From 2af4da0da8b80f59c6588c87db83a68f5793af6e Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 12 Mar 2024 10:15:10 +0100 Subject: [PATCH 001/508] More context menu 7: cleanup (#5456) ### What NOTE: review commit by commit (first commit is pure refactoring). Final PR in the series. This PR: - split `actions.rs` into many sub-files - fix capitalisation in some menu item - split the release check list in small checks Full series: - https://github.com/rerun-io/rerun/pull/5392 - https://github.com/rerun-io/rerun/pull/5397 - https://github.com/rerun-io/rerun/pull/5407 - https://github.com/rerun-io/rerun/pull/5411 - https://github.com/rerun-io/rerun/pull/5422 - https://github.com/rerun-io/rerun/pull/5433 - https://github.com/rerun-io/rerun/pull/5456 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5456/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5456/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5456/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5456) - [Docs preview](https://rerun.io/preview/a36360f586494f6648fdc4bbb9d806ab12911358/docs) - [Examples preview](https://rerun.io/preview/a36360f586494f6648fdc4bbb9d806ab12911358/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../re_viewport/src/context_menu/actions.rs | 665 ------------------ .../src/context_menu/actions/add_container.rs | 35 + .../actions/add_entities_to_new_space_view.rs | 175 +++++ .../context_menu/actions/add_space_view.rs | 36 + .../context_menu/actions/clone_space_view.rs | 29 + .../actions/collapse_expand_all.rs | 122 ++++ .../src/context_menu/actions/mod.rs | 8 + .../actions/move_contents_to_new_container.rs | 69 ++ .../src/context_menu/actions/remove.rs | 58 ++ .../src/context_menu/actions/show_hide.rs | 156 ++++ crates/re_viewport/src/context_menu/mod.rs | 13 +- .../release_checklist/check_context_menu.py | 106 --- ...heck_context_menu_invalid_sub_container.py | 55 ++ .../check_context_menu_multi_selection.py | 101 +++ .../check_context_menu_single_selection.py | 111 +++ ...xt_menu_single_selection_blueprint_tree.py | 96 +++ 16 files changed, 1060 insertions(+), 775 deletions(-) delete mode 100644 crates/re_viewport/src/context_menu/actions.rs create mode 100644 crates/re_viewport/src/context_menu/actions/add_container.rs create mode 100644 crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs create mode 100644 crates/re_viewport/src/context_menu/actions/add_space_view.rs create mode 100644 crates/re_viewport/src/context_menu/actions/clone_space_view.rs create mode 100644 crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs create mode 100644 crates/re_viewport/src/context_menu/actions/mod.rs create mode 100644 crates/re_viewport/src/context_menu/actions/move_contents_to_new_container.rs create mode 100644 crates/re_viewport/src/context_menu/actions/remove.rs create mode 100644 crates/re_viewport/src/context_menu/actions/show_hide.rs delete mode 100644 tests/python/release_checklist/check_context_menu.py create mode 100644 tests/python/release_checklist/check_context_menu_invalid_sub_container.py create mode 100644 tests/python/release_checklist/check_context_menu_multi_selection.py create mode 100644 tests/python/release_checklist/check_context_menu_single_selection.py create mode 100644 tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py diff --git a/crates/re_viewport/src/context_menu/actions.rs b/crates/re_viewport/src/context_menu/actions.rs deleted file mode 100644 index 3da382af3641..000000000000 --- a/crates/re_viewport/src/context_menu/actions.rs +++ /dev/null @@ -1,665 +0,0 @@ -use egui::{Response, Ui}; -use itertools::Itertools; -use nohash_hasher::IntSet; - -use re_entity_db::InstancePath; -use re_log_types::{EntityPath, EntityPathFilter, EntityPathRule, RuleEffect}; -use re_space_view::{determine_visualizable_entities, SpaceViewBlueprint}; -use re_viewer_context::{CollapseScope, ContainerId, Item, SpaceViewClassIdentifier, SpaceViewId}; - -use super::{ContextMenuAction, ContextMenuContext}; -use crate::Contents; - -pub(super) struct ShowAction; - -impl ContextMenuAction for ShowAction { - fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { - ctx.selection.iter().any(|(item, _)| match item { - Item::SpaceView(space_view_id) => !ctx - .viewport_blueprint - .is_contents_visible(&Contents::SpaceView(*space_view_id)), - Item::Container(container_id) => { - !ctx.viewport_blueprint - .is_contents_visible(&Contents::Container(*container_id)) - && ctx.viewport_blueprint.root_container != Some(*container_id) - } - Item::DataResult(space_view_id, instance_path) => { - data_result_visible(ctx, space_view_id, instance_path).is_some_and(|vis| !vis) - } - _ => false, - }) - } - - fn label(&self, ctx: &ContextMenuContext<'_>) -> String { - if ctx.selection.len() > 1 { - "Show All".to_owned() - } else { - "Show".to_owned() - } - } - - fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { - ctx.viewport_blueprint.set_content_visibility( - ctx.viewer_context, - &Contents::Container(*container_id), - true, - ); - } - - fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { - ctx.viewport_blueprint.set_content_visibility( - ctx.viewer_context, - &Contents::SpaceView(*space_view_id), - true, - ); - } - - fn process_data_result( - &self, - ctx: &ContextMenuContext<'_>, - space_view_id: &SpaceViewId, - instance_path: &InstancePath, - ) { - set_data_result_visible(ctx, space_view_id, instance_path, true); - } -} - -pub(super) struct HideAction; - -impl ContextMenuAction for HideAction { - fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { - ctx.selection.iter().any(|(item, _)| match item { - Item::SpaceView(space_view_id) => ctx - .viewport_blueprint - .is_contents_visible(&Contents::SpaceView(*space_view_id)), - Item::Container(container_id) => { - ctx.viewport_blueprint - .is_contents_visible(&Contents::Container(*container_id)) - && ctx.viewport_blueprint.root_container != Some(*container_id) - } - Item::DataResult(space_view_id, instance_path) => { - data_result_visible(ctx, space_view_id, instance_path).unwrap_or(false) - } - _ => false, - }) - } - - fn label(&self, ctx: &ContextMenuContext<'_>) -> String { - if ctx.selection.len() > 1 { - "Hide All".to_owned() - } else { - "Hide".to_owned() - } - } - - fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { - ctx.viewport_blueprint.set_content_visibility( - ctx.viewer_context, - &Contents::Container(*container_id), - false, - ); - } - - fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { - ctx.viewport_blueprint.set_content_visibility( - ctx.viewer_context, - &Contents::SpaceView(*space_view_id), - false, - ); - } - - fn process_data_result( - &self, - ctx: &ContextMenuContext<'_>, - space_view_id: &SpaceViewId, - instance_path: &InstancePath, - ) { - set_data_result_visible(ctx, space_view_id, instance_path, false); - } -} - -fn data_result_visible( - ctx: &ContextMenuContext<'_>, - space_view_id: &SpaceViewId, - instance_path: &InstancePath, -) -> Option { - instance_path - .is_splat() - .then(|| { - let query_result = ctx.viewer_context.lookup_query_result(*space_view_id); - query_result - .tree - .lookup_result_by_path(&instance_path.entity_path) - .map(|data_result| { - data_result - .recursive_properties() - .map_or(true, |prop| prop.visible) - }) - }) - .flatten() -} - -fn set_data_result_visible( - ctx: &ContextMenuContext<'_>, - space_view_id: &SpaceViewId, - instance_path: &InstancePath, - visible: bool, -) { - let query_result = ctx.viewer_context.lookup_query_result(*space_view_id); - if let Some(data_result) = query_result - .tree - .lookup_result_by_path(&instance_path.entity_path) - { - let mut recursive_properties = data_result - .recursive_properties() - .cloned() - .unwrap_or_default(); - recursive_properties.visible = visible; - - data_result.save_recursive_override(ctx.viewer_context, Some(recursive_properties)); - } -} - -// --- - -/// Remove a container, space view, or data result. -pub(super) struct RemoveAction; - -impl ContextMenuAction for RemoveAction { - fn supports_multi_selection(&self, _ctx: &ContextMenuContext<'_>) -> bool { - true - } - - fn supports_item(&self, ctx: &ContextMenuContext<'_>, item: &Item) -> bool { - match item { - Item::SpaceView(_) => true, - Item::Container(container_id) => { - ctx.viewport_blueprint.root_container != Some(*container_id) - } - Item::DataResult(_, instance_path) => instance_path.is_splat(), - _ => false, - } - } - - fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { - "Remove".to_owned() - } - - fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { - ctx.viewport_blueprint - .mark_user_interaction(ctx.viewer_context); - ctx.viewport_blueprint - .remove_contents(Contents::Container(*container_id)); - } - - fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { - ctx.viewport_blueprint - .mark_user_interaction(ctx.viewer_context); - ctx.viewport_blueprint - .remove_contents(Contents::SpaceView(*space_view_id)); - } - - fn process_data_result( - &self, - ctx: &ContextMenuContext<'_>, - space_view_id: &SpaceViewId, - instance_path: &InstancePath, - ) { - if let Some(space_view) = ctx.viewport_blueprint.space_view(space_view_id) { - space_view.contents.add_entity_exclusion( - ctx.viewer_context, - EntityPathRule::including_subtree(instance_path.entity_path.clone()), - ); - } - } -} - -// --- - -/// Clone a single space view -pub(super) struct CloneSpaceViewAction; - -impl ContextMenuAction for CloneSpaceViewAction { - fn supports_item(&self, _ctx: &ContextMenuContext<'_>, item: &Item) -> bool { - matches!(item, Item::SpaceView(_)) - } - - fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { - "Clone".to_owned() - } - - fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { - if let Some(new_space_view_id) = ctx - .viewport_blueprint - .duplicate_space_view(space_view_id, ctx.viewer_context) - { - ctx.viewer_context - .selection_state() - .set_selection(Item::SpaceView(new_space_view_id)); - ctx.viewport_blueprint - .mark_user_interaction(ctx.viewer_context); - } - } -} - -// --- - -/// Add a container of a specific type -pub(super) struct AddContainerAction(pub egui_tiles::ContainerKind); - -impl ContextMenuAction for AddContainerAction { - fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { - if let Some(Item::Container(container_id)) = ctx.selection.single_item() { - if let Some(container) = ctx.viewport_blueprint.container(container_id) { - // same-kind linear containers cannot be nested - (container.container_kind != egui_tiles::ContainerKind::Vertical - && container.container_kind != egui_tiles::ContainerKind::Horizontal) - || container.container_kind != self.0 - } else { - // unknown container - false - } - } else { - false - } - } - - fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { - format!("{:?}", self.0) - } - - fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { - ctx.viewport_blueprint - .add_container(self.0, Some(*container_id)); - ctx.viewport_blueprint - .mark_user_interaction(ctx.viewer_context); - } -} - -// --- - -/// Add a space view of the specific class -pub(super) struct AddSpaceViewAction(pub SpaceViewClassIdentifier); - -impl ContextMenuAction for AddSpaceViewAction { - fn supports_item(&self, _ctx: &ContextMenuContext<'_>, item: &Item) -> bool { - matches!(item, Item::Container(_)) - } - - fn label(&self, ctx: &ContextMenuContext<'_>) -> String { - ctx.viewer_context - .space_view_class_registry - .get_class_or_log_error(&self.0) - .display_name() - .to_owned() - } - - fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { - let space_view = - SpaceViewBlueprint::new(self.0, &EntityPath::root(), EntityPathFilter::default()); - - ctx.viewport_blueprint.add_space_views( - std::iter::once(space_view), - ctx.viewer_context, - Some(*container_id), - None, - ); - ctx.viewport_blueprint - .mark_user_interaction(ctx.viewer_context); - } -} - -// --- - -/// Move the selected contents to a newly created container of the given kind -pub(super) struct MoveContentsToNewContainerAction(pub egui_tiles::ContainerKind); - -impl ContextMenuAction for MoveContentsToNewContainerAction { - fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { - if let Some((parent_container, _)) = ctx.clicked_item_enclosing_container_and_position() { - if (parent_container.container_kind == egui_tiles::ContainerKind::Vertical - || parent_container.container_kind == egui_tiles::ContainerKind::Horizontal) - && parent_container.container_kind == self.0 - { - return false; - } - } - - ctx.selection.iter().all(|(item, _)| match item { - Item::SpaceView(_) => true, - Item::Container(container_id) => { - ctx.viewport_blueprint.root_container != Some(*container_id) - } - _ => false, - }) - } - - fn supports_multi_selection(&self, _ctx: &ContextMenuContext<'_>) -> bool { - true - } - - fn supports_item(&self, ctx: &ContextMenuContext<'_>, item: &Item) -> bool { - match item { - Item::SpaceView(_) => true, - Item::Container(container_id) => { - ctx.viewport_blueprint.root_container != Some(*container_id) - } - _ => false, - } - } - - fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { - format!("{:?}", self.0) - } - - fn process_selection(&self, ctx: &ContextMenuContext<'_>) { - if let Some(root_container_id) = ctx.viewport_blueprint.root_container { - let (target_container_id, target_position) = ctx - .clicked_item_enclosing_container_id_and_position() - .unwrap_or((root_container_id, 0)); - - let contents = ctx - .selection - .iter() - .filter_map(|(item, _)| item.try_into().ok()) - .collect(); - - ctx.viewport_blueprint.move_contents_to_new_container( - contents, - self.0, - target_container_id, - target_position, - ); - - ctx.viewport_blueprint - .mark_user_interaction(ctx.viewer_context); - } - } -} - -// --- - -/// Create a new space view containing the selected entities. -/// -/// The space view is created next to the clicked item's parent view (if a data result was clicked). -pub(super) struct AddEntitiesToNewSpaceViewAction; - -impl ContextMenuAction for AddEntitiesToNewSpaceViewAction { - fn supports_multi_selection(&self, _ctx: &ContextMenuContext<'_>) -> bool { - true - } - - fn supports_item(&self, _ctx: &ContextMenuContext<'_>, item: &Item) -> bool { - matches!(item, Item::DataResult(_, _) | Item::InstancePath(_)) - } - - fn ui(&self, ctx: &ContextMenuContext<'_>, ui: &mut Ui) -> Response { - let space_view_class_registry = ctx.viewer_context.space_view_class_registry; - - let recommended_space_view_classes = recommended_space_views_for_selection(ctx); - let other_space_view_classes: IntSet<_> = space_view_class_registry - .iter_registry() - .map(|entry| entry.class.identifier()) - .collect::>() - .difference(&recommended_space_view_classes) - .cloned() - .collect(); - - ui.menu_button("Add to new space view", |ui| { - let buttons_for_space_view_classes = - |ui: &mut egui::Ui, space_view_classes: &IntSet| { - for (identifier, display_name) in space_view_classes - .iter() - .map(|identifier| { - ( - identifier, - space_view_class_registry - .get_class_or_log_error(identifier) - .display_name(), - ) - }) - .sorted_by_key(|(_, display_name)| display_name.to_owned()) - { - if ui.button(display_name).clicked() { - create_space_view_for_selected_entities(ctx, *identifier); - ui.close_menu(); - } - } - }; - - ui.label(egui::WidgetText::from("Recommended:").italics()); - if recommended_space_view_classes.is_empty() { - ui.label("None"); - } else { - buttons_for_space_view_classes(ui, &recommended_space_view_classes); - } - - if !other_space_view_classes.is_empty() { - ui.label(egui::WidgetText::from("Others:").italics()); - buttons_for_space_view_classes(ui, &other_space_view_classes); - } - }) - .response - } -} - -/// Builds a list of compatible space views for the provided selection. -fn recommended_space_views_for_selection( - ctx: &ContextMenuContext<'_>, -) -> IntSet { - re_tracing::profile_function!(); - - let entities_of_interest = ctx - .selection - .iter() - .filter_map(|(item, _)| item.entity_path().cloned()) - .collect::>(); - - let mut output: IntSet = IntSet::default(); - - let space_view_class_registry = ctx.viewer_context.space_view_class_registry; - let entity_db = ctx.viewer_context.entity_db; - let applicable_entities_per_visualizer = - space_view_class_registry.applicable_entities_for_visualizer_systems(entity_db.store_id()); - - for entry in space_view_class_registry.iter_registry() { - let Some(suggested_root) = entry - .class - .recommended_root_for_entities(&entities_of_interest, entity_db) - else { - continue; - }; - - let visualizable_entities = determine_visualizable_entities( - &applicable_entities_per_visualizer, - entity_db, - &space_view_class_registry.new_visualizer_collection(entry.class.identifier()), - &*entry.class, - &suggested_root, - ); - - // We consider a space view class to be recommended if all selected entities are - // "visualizable" with it. By "visualizable" we mean that either the entity itself, or any - // of its sub-entities, are visualizable. - - let covered = entities_of_interest.iter().all(|entity| { - visualizable_entities.0.iter().any(|(_, entities)| { - entities - .0 - .iter() - .any(|visualizable_entity| visualizable_entity.starts_with(entity)) - }) - }); - - if covered { - output.insert(entry.class.identifier()); - } - } - - output -} - -/// Creates a space view of the given class, with root set as origin, and a filter set to include all -/// selected entities. Then, the selection is set to the new space view. -fn create_space_view_for_selected_entities( - ctx: &ContextMenuContext<'_>, - identifier: SpaceViewClassIdentifier, -) { - let entities_of_interest = ctx - .selection - .iter() - .filter_map(|(item, _)| item.entity_path().cloned()) - .collect::>(); - - let origin = ctx - .viewer_context - .space_view_class_registry - .get_class_or_log_error(&identifier) - .recommended_root_for_entities(&entities_of_interest, ctx.viewer_context.entity_db) - .unwrap_or_else(EntityPath::root); - - let mut filter = EntityPathFilter::default(); - - for path in entities_of_interest { - filter.add_rule(RuleEffect::Include, EntityPathRule::including_subtree(path)); - } - - let target_container_id = ctx - .clicked_item_enclosing_container_id_and_position() - .map(|(id, _)| id); - - let space_view = SpaceViewBlueprint::new(identifier, &origin, filter); - - let new_space_view = ctx.viewport_blueprint.add_space_views( - std::iter::once(space_view), - ctx.viewer_context, - target_container_id, - None, - ); - if let Some(space_view_id) = new_space_view.first() { - ctx.viewer_context - .selection_state() - .set_selection(Item::SpaceView(*space_view_id)); - } - ctx.viewport_blueprint - .mark_user_interaction(ctx.viewer_context); -} - -// --- - -/// Collapse or expand all items in the selection. -// TODO(ab): the current implementation makes strong assumptions of which CollapseScope to use based -// on the item type. This is brittle and will not scale if/when we add more trees to the UI. When -// that happens, we will have to pass the scope to `context_menu_ui_for_item` and use it here. -pub(super) enum CollapseExpandAllAction { - CollapseAll, - ExpandAll, -} - -impl ContextMenuAction for CollapseExpandAllAction { - fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { - // let's allow this action if at least one item supports it - ctx.selection - .iter() - .any(|(item, _)| self.supports_item(ctx, item)) - } - - fn supports_item(&self, ctx: &ContextMenuContext<'_>, item: &Item) -> bool { - // TODO(ab): in an ideal world, we'd check the fully expended/collapsed state of the item to - // avoid showing a command that wouldn't have an effect but that's lots of added complexity. - match item { - Item::StoreId(_) | Item::ComponentPath(_) => false, - Item::SpaceView(_) | Item::Container(_) | Item::InstancePath(_) => true, - //TODO(ab): for DataResult, walk the data result tree instead! - Item::DataResult(_, instance_path) => ctx - .viewer_context - .entity_db - .tree() - .subtree(&instance_path.entity_path) - .is_some_and(|subtree| !subtree.is_leaf()), - } - } - - fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { - match self { - CollapseExpandAllAction::CollapseAll => "Collapse all".to_owned(), - CollapseExpandAllAction::ExpandAll => "Expand all".to_owned(), - } - } - - fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { - ctx.viewport_blueprint - .visit_contents_in_container(container_id, &mut |contents| match contents { - Contents::Container(container_id) => CollapseScope::BlueprintTree - .container(*container_id) - .set_open(&ctx.egui_context, self.open()), - Contents::SpaceView(space_view_id) => self.process_space_view(ctx, space_view_id), - }); - } - - fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { - CollapseScope::BlueprintTree - .space_view(*space_view_id) - .set_open(&ctx.egui_context, self.open()); - - let query_result = ctx.viewer_context.lookup_query_result(*space_view_id); - let result_tree = &query_result.tree; - if let Some(root_node) = result_tree.root_node() { - self.process_data_result( - ctx, - space_view_id, - &InstancePath::entity_splat(root_node.data_result.entity_path.clone()), - ); - } - } - - fn process_data_result( - &self, - ctx: &ContextMenuContext<'_>, - space_view_id: &SpaceViewId, - instance_path: &InstancePath, - ) { - //TODO(ab): here we should in principle walk the DataResult tree instead of the entity tree - // but the current API isn't super ergonomic. - let Some(subtree) = ctx - .viewer_context - .entity_db - .tree() - .subtree(&instance_path.entity_path) - else { - return; - }; - - subtree.visit_children_recursively(&mut |entity_path, _| { - CollapseScope::BlueprintTree - .data_result(*space_view_id, entity_path.clone()) - .set_open(&ctx.egui_context, self.open()); - }); - } - - fn process_instance_path(&self, ctx: &ContextMenuContext<'_>, instance_path: &InstancePath) { - let Some(subtree) = ctx - .viewer_context - .entity_db - .tree() - .subtree(&instance_path.entity_path) - else { - return; - }; - - subtree.visit_children_recursively(&mut |entity_path, _| { - CollapseScope::StreamsTree - .entity(entity_path.clone()) - .set_open(&ctx.egui_context, self.open()); - }); - } -} - -impl CollapseExpandAllAction { - fn open(&self) -> bool { - match self { - CollapseExpandAllAction::CollapseAll => false, - CollapseExpandAllAction::ExpandAll => true, - } - } -} diff --git a/crates/re_viewport/src/context_menu/actions/add_container.rs b/crates/re_viewport/src/context_menu/actions/add_container.rs new file mode 100644 index 000000000000..ea594fe4fa14 --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/add_container.rs @@ -0,0 +1,35 @@ +use re_viewer_context::{ContainerId, Item}; + +use crate::context_menu::{ContextMenuAction, ContextMenuContext}; + +/// Add a container of a specific type +pub(crate) struct AddContainerAction(pub egui_tiles::ContainerKind); + +impl ContextMenuAction for AddContainerAction { + fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { + if let Some(Item::Container(container_id)) = ctx.selection.single_item() { + if let Some(container) = ctx.viewport_blueprint.container(container_id) { + // same-kind linear containers cannot be nested + (container.container_kind != egui_tiles::ContainerKind::Vertical + && container.container_kind != egui_tiles::ContainerKind::Horizontal) + || container.container_kind != self.0 + } else { + // unknown container + false + } + } else { + false + } + } + + fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { + format!("{:?}", self.0) + } + + fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { + ctx.viewport_blueprint + .add_container(self.0, Some(*container_id)); + ctx.viewport_blueprint + .mark_user_interaction(ctx.viewer_context); + } +} diff --git a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs new file mode 100644 index 000000000000..3dd49a8b3e7f --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs @@ -0,0 +1,175 @@ +use egui::{Response, Ui}; +use itertools::Itertools; +use nohash_hasher::IntSet; + +use re_log_types::{EntityPath, EntityPathFilter, EntityPathRule, RuleEffect}; +use re_space_view::{determine_visualizable_entities, SpaceViewBlueprint}; +use re_viewer_context::{Item, SpaceViewClassIdentifier}; + +use crate::context_menu::{ContextMenuAction, ContextMenuContext}; + +/// Create a new space view containing the selected entities. +/// +/// The space view is created next to the clicked item's parent view (if a data result was clicked). +pub(crate) struct AddEntitiesToNewSpaceViewAction; + +impl ContextMenuAction for AddEntitiesToNewSpaceViewAction { + fn supports_multi_selection(&self, _ctx: &ContextMenuContext<'_>) -> bool { + true + } + + fn supports_item(&self, _ctx: &ContextMenuContext<'_>, item: &Item) -> bool { + matches!(item, Item::DataResult(_, _) | Item::InstancePath(_)) + } + + fn ui(&self, ctx: &ContextMenuContext<'_>, ui: &mut Ui) -> Response { + let space_view_class_registry = ctx.viewer_context.space_view_class_registry; + + let recommended_space_view_classes = recommended_space_views_for_selection(ctx); + let other_space_view_classes: IntSet<_> = space_view_class_registry + .iter_registry() + .map(|entry| entry.class.identifier()) + .collect::>() + .difference(&recommended_space_view_classes) + .cloned() + .collect(); + + ui.menu_button("Add to new Space View", |ui| { + let buttons_for_space_view_classes = + |ui: &mut egui::Ui, space_view_classes: &IntSet| { + for (identifier, display_name) in space_view_classes + .iter() + .map(|identifier| { + ( + identifier, + space_view_class_registry + .get_class_or_log_error(identifier) + .display_name(), + ) + }) + .sorted_by_key(|(_, display_name)| display_name.to_owned()) + { + if ui.button(display_name).clicked() { + create_space_view_for_selected_entities(ctx, *identifier); + ui.close_menu(); + } + } + }; + + ui.label(egui::WidgetText::from("Recommended:").italics()); + if recommended_space_view_classes.is_empty() { + ui.label("None"); + } else { + buttons_for_space_view_classes(ui, &recommended_space_view_classes); + } + + if !other_space_view_classes.is_empty() { + ui.label(egui::WidgetText::from("Others:").italics()); + buttons_for_space_view_classes(ui, &other_space_view_classes); + } + }) + .response + } +} + +/// Builds a list of compatible space views for the provided selection. +fn recommended_space_views_for_selection( + ctx: &ContextMenuContext<'_>, +) -> IntSet { + re_tracing::profile_function!(); + + let entities_of_interest = ctx + .selection + .iter() + .filter_map(|(item, _)| item.entity_path().cloned()) + .collect::>(); + + let mut output: IntSet = IntSet::default(); + + let space_view_class_registry = ctx.viewer_context.space_view_class_registry; + let entity_db = ctx.viewer_context.entity_db; + let applicable_entities_per_visualizer = + space_view_class_registry.applicable_entities_for_visualizer_systems(entity_db.store_id()); + + for entry in space_view_class_registry.iter_registry() { + let Some(suggested_root) = entry + .class + .recommended_root_for_entities(&entities_of_interest, entity_db) + else { + continue; + }; + + let visualizable_entities = determine_visualizable_entities( + &applicable_entities_per_visualizer, + entity_db, + &space_view_class_registry.new_visualizer_collection(entry.class.identifier()), + &*entry.class, + &suggested_root, + ); + + // We consider a space view class to be recommended if all selected entities are + // "visualizable" with it. By "visualizable" we mean that either the entity itself, or any + // of its sub-entities, are visualizable. + + let covered = entities_of_interest.iter().all(|entity| { + visualizable_entities.0.iter().any(|(_, entities)| { + entities + .0 + .iter() + .any(|visualizable_entity| visualizable_entity.starts_with(entity)) + }) + }); + + if covered { + output.insert(entry.class.identifier()); + } + } + + output +} + +/// Creates a space view of the given class, with root set as origin, and a filter set to include all +/// selected entities. Then, the selection is set to the new space view. +fn create_space_view_for_selected_entities( + ctx: &ContextMenuContext<'_>, + identifier: SpaceViewClassIdentifier, +) { + let entities_of_interest = ctx + .selection + .iter() + .filter_map(|(item, _)| item.entity_path().cloned()) + .collect::>(); + + let origin = ctx + .viewer_context + .space_view_class_registry + .get_class_or_log_error(&identifier) + .recommended_root_for_entities(&entities_of_interest, ctx.viewer_context.entity_db) + .unwrap_or_else(EntityPath::root); + + let mut filter = EntityPathFilter::default(); + + for path in entities_of_interest { + filter.add_rule(RuleEffect::Include, EntityPathRule::including_subtree(path)); + } + + let target_container_id = ctx + .clicked_item_enclosing_container_id_and_position() + .map(|(id, _)| id); + + let space_view = SpaceViewBlueprint::new(identifier, &origin, filter); + + let new_space_view = ctx.viewport_blueprint.add_space_views( + std::iter::once(space_view), + ctx.viewer_context, + target_container_id, + None, + ); + if let Some(space_view_id) = new_space_view.first() { + ctx.viewer_context + .selection_state() + .set_selection(Item::SpaceView(*space_view_id)); + } + ctx.viewport_blueprint + .mark_user_interaction(ctx.viewer_context); +} diff --git a/crates/re_viewport/src/context_menu/actions/add_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_space_view.rs new file mode 100644 index 000000000000..03e548967420 --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/add_space_view.rs @@ -0,0 +1,36 @@ +use re_log_types::{EntityPath, EntityPathFilter}; +use re_space_view::SpaceViewBlueprint; +use re_viewer_context::{ContainerId, Item, SpaceViewClassIdentifier}; + +use crate::context_menu::{ContextMenuAction, ContextMenuContext}; + +/// Add a space view of the specific class +pub(crate) struct AddSpaceViewAction(pub SpaceViewClassIdentifier); + +impl ContextMenuAction for AddSpaceViewAction { + fn supports_item(&self, _ctx: &ContextMenuContext<'_>, item: &Item) -> bool { + matches!(item, Item::Container(_)) + } + + fn label(&self, ctx: &ContextMenuContext<'_>) -> String { + ctx.viewer_context + .space_view_class_registry + .get_class_or_log_error(&self.0) + .display_name() + .to_owned() + } + + fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { + let space_view = + SpaceViewBlueprint::new(self.0, &EntityPath::root(), EntityPathFilter::default()); + + ctx.viewport_blueprint.add_space_views( + std::iter::once(space_view), + ctx.viewer_context, + Some(*container_id), + None, + ); + ctx.viewport_blueprint + .mark_user_interaction(ctx.viewer_context); + } +} diff --git a/crates/re_viewport/src/context_menu/actions/clone_space_view.rs b/crates/re_viewport/src/context_menu/actions/clone_space_view.rs new file mode 100644 index 000000000000..d625d8e32787 --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/clone_space_view.rs @@ -0,0 +1,29 @@ +use re_viewer_context::{Item, SpaceViewId}; + +use crate::context_menu::{ContextMenuAction, ContextMenuContext}; + +/// Clone a single space view +pub(crate) struct CloneSpaceViewAction; + +impl ContextMenuAction for CloneSpaceViewAction { + fn supports_item(&self, _ctx: &ContextMenuContext<'_>, item: &Item) -> bool { + matches!(item, Item::SpaceView(_)) + } + + fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { + "Clone".to_owned() + } + + fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { + if let Some(new_space_view_id) = ctx + .viewport_blueprint + .duplicate_space_view(space_view_id, ctx.viewer_context) + { + ctx.viewer_context + .selection_state() + .set_selection(Item::SpaceView(new_space_view_id)); + ctx.viewport_blueprint + .mark_user_interaction(ctx.viewer_context); + } + } +} diff --git a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs new file mode 100644 index 000000000000..bcc1624043e4 --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs @@ -0,0 +1,122 @@ +use re_entity_db::InstancePath; +use re_viewer_context::{CollapseScope, ContainerId, Item, SpaceViewId}; + +use crate::context_menu::{ContextMenuAction, ContextMenuContext}; +use crate::Contents; + +/// Collapse or expand all items in the selection. +// TODO(ab): the current implementation makes strong assumptions of which CollapseScope to use based +// on the item type. This is brittle and will not scale if/when we add more trees to the UI. When +// that happens, we will have to pass the scope to `context_menu_ui_for_item` and use it here. +pub(crate) enum CollapseExpandAllAction { + CollapseAll, + ExpandAll, +} + +impl ContextMenuAction for CollapseExpandAllAction { + fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { + // let's allow this action if at least one item supports it + ctx.selection + .iter() + .any(|(item, _)| self.supports_item(ctx, item)) + } + + fn supports_item(&self, ctx: &ContextMenuContext<'_>, item: &Item) -> bool { + // TODO(ab): in an ideal world, we'd check the fully expended/collapsed state of the item to + // avoid showing a command that wouldn't have an effect but that's lots of added complexity. + match item { + Item::StoreId(_) | Item::ComponentPath(_) => false, + Item::SpaceView(_) | Item::Container(_) | Item::InstancePath(_) => true, + //TODO(ab): for DataResult, walk the data result tree instead! + Item::DataResult(_, instance_path) => ctx + .viewer_context + .entity_db + .tree() + .subtree(&instance_path.entity_path) + .is_some_and(|subtree| !subtree.is_leaf()), + } + } + + fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { + match self { + CollapseExpandAllAction::CollapseAll => "Collapse all".to_owned(), + CollapseExpandAllAction::ExpandAll => "Expand all".to_owned(), + } + } + + fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { + ctx.viewport_blueprint + .visit_contents_in_container(container_id, &mut |contents| match contents { + Contents::Container(container_id) => CollapseScope::BlueprintTree + .container(*container_id) + .set_open(&ctx.egui_context, self.open()), + Contents::SpaceView(space_view_id) => self.process_space_view(ctx, space_view_id), + }); + } + + fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { + CollapseScope::BlueprintTree + .space_view(*space_view_id) + .set_open(&ctx.egui_context, self.open()); + + let query_result = ctx.viewer_context.lookup_query_result(*space_view_id); + let result_tree = &query_result.tree; + if let Some(root_node) = result_tree.root_node() { + self.process_data_result( + ctx, + space_view_id, + &InstancePath::entity_splat(root_node.data_result.entity_path.clone()), + ); + } + } + + fn process_data_result( + &self, + ctx: &ContextMenuContext<'_>, + space_view_id: &SpaceViewId, + instance_path: &InstancePath, + ) { + //TODO(ab): here we should in principle walk the DataResult tree instead of the entity tree + // but the current API isn't super ergonomic. + let Some(subtree) = ctx + .viewer_context + .entity_db + .tree() + .subtree(&instance_path.entity_path) + else { + return; + }; + + subtree.visit_children_recursively(&mut |entity_path, _| { + CollapseScope::BlueprintTree + .data_result(*space_view_id, entity_path.clone()) + .set_open(&ctx.egui_context, self.open()); + }); + } + + fn process_instance_path(&self, ctx: &ContextMenuContext<'_>, instance_path: &InstancePath) { + let Some(subtree) = ctx + .viewer_context + .entity_db + .tree() + .subtree(&instance_path.entity_path) + else { + return; + }; + + subtree.visit_children_recursively(&mut |entity_path, _| { + CollapseScope::StreamsTree + .entity(entity_path.clone()) + .set_open(&ctx.egui_context, self.open()); + }); + } +} + +impl CollapseExpandAllAction { + fn open(&self) -> bool { + match self { + CollapseExpandAllAction::CollapseAll => false, + CollapseExpandAllAction::ExpandAll => true, + } + } +} diff --git a/crates/re_viewport/src/context_menu/actions/mod.rs b/crates/re_viewport/src/context_menu/actions/mod.rs new file mode 100644 index 000000000000..f438c2e3698f --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/mod.rs @@ -0,0 +1,8 @@ +pub(super) mod add_container; +pub(super) mod add_entities_to_new_space_view; +pub(super) mod add_space_view; +pub(super) mod clone_space_view; +pub(super) mod collapse_expand_all; +pub(super) mod move_contents_to_new_container; +pub(super) mod remove; +pub(super) mod show_hide; diff --git a/crates/re_viewport/src/context_menu/actions/move_contents_to_new_container.rs b/crates/re_viewport/src/context_menu/actions/move_contents_to_new_container.rs new file mode 100644 index 000000000000..ab2596575f17 --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/move_contents_to_new_container.rs @@ -0,0 +1,69 @@ +use re_viewer_context::Item; + +use crate::context_menu::{ContextMenuAction, ContextMenuContext}; + +/// Move the selected contents to a newly created container of the given kind +pub(crate) struct MoveContentsToNewContainerAction(pub egui_tiles::ContainerKind); + +impl ContextMenuAction for MoveContentsToNewContainerAction { + fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { + if let Some((parent_container, _)) = ctx.clicked_item_enclosing_container_and_position() { + if (parent_container.container_kind == egui_tiles::ContainerKind::Vertical + || parent_container.container_kind == egui_tiles::ContainerKind::Horizontal) + && parent_container.container_kind == self.0 + { + return false; + } + } + + ctx.selection.iter().all(|(item, _)| match item { + Item::SpaceView(_) => true, + Item::Container(container_id) => { + ctx.viewport_blueprint.root_container != Some(*container_id) + } + _ => false, + }) + } + + fn supports_multi_selection(&self, _ctx: &ContextMenuContext<'_>) -> bool { + true + } + + fn supports_item(&self, ctx: &ContextMenuContext<'_>, item: &Item) -> bool { + match item { + Item::SpaceView(_) => true, + Item::Container(container_id) => { + ctx.viewport_blueprint.root_container != Some(*container_id) + } + _ => false, + } + } + + fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { + format!("{:?}", self.0) + } + + fn process_selection(&self, ctx: &ContextMenuContext<'_>) { + if let Some(root_container_id) = ctx.viewport_blueprint.root_container { + let (target_container_id, target_position) = ctx + .clicked_item_enclosing_container_id_and_position() + .unwrap_or((root_container_id, 0)); + + let contents = ctx + .selection + .iter() + .filter_map(|(item, _)| item.try_into().ok()) + .collect(); + + ctx.viewport_blueprint.move_contents_to_new_container( + contents, + self.0, + target_container_id, + target_position, + ); + + ctx.viewport_blueprint + .mark_user_interaction(ctx.viewer_context); + } + } +} diff --git a/crates/re_viewport/src/context_menu/actions/remove.rs b/crates/re_viewport/src/context_menu/actions/remove.rs new file mode 100644 index 000000000000..ff7ef6e1ce20 --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/remove.rs @@ -0,0 +1,58 @@ +use re_entity_db::InstancePath; +use re_log_types::EntityPathRule; +use re_viewer_context::{ContainerId, Item, SpaceViewId}; + +use crate::context_menu::{ContextMenuAction, ContextMenuContext}; +use crate::Contents; + +/// Remove a container, space view, or data result. +pub(crate) struct RemoveAction; + +impl ContextMenuAction for RemoveAction { + fn supports_multi_selection(&self, _ctx: &ContextMenuContext<'_>) -> bool { + true + } + + fn supports_item(&self, ctx: &ContextMenuContext<'_>, item: &Item) -> bool { + match item { + Item::SpaceView(_) => true, + Item::Container(container_id) => { + ctx.viewport_blueprint.root_container != Some(*container_id) + } + Item::DataResult(_, instance_path) => instance_path.is_splat(), + _ => false, + } + } + + fn label(&self, _ctx: &ContextMenuContext<'_>) -> String { + "Remove".to_owned() + } + + fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { + ctx.viewport_blueprint + .mark_user_interaction(ctx.viewer_context); + ctx.viewport_blueprint + .remove_contents(Contents::Container(*container_id)); + } + + fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { + ctx.viewport_blueprint + .mark_user_interaction(ctx.viewer_context); + ctx.viewport_blueprint + .remove_contents(Contents::SpaceView(*space_view_id)); + } + + fn process_data_result( + &self, + ctx: &ContextMenuContext<'_>, + space_view_id: &SpaceViewId, + instance_path: &InstancePath, + ) { + if let Some(space_view) = ctx.viewport_blueprint.space_view(space_view_id) { + space_view.contents.add_entity_exclusion( + ctx.viewer_context, + EntityPathRule::including_subtree(instance_path.entity_path.clone()), + ); + } + } +} diff --git a/crates/re_viewport/src/context_menu/actions/show_hide.rs b/crates/re_viewport/src/context_menu/actions/show_hide.rs new file mode 100644 index 000000000000..f3319805ab55 --- /dev/null +++ b/crates/re_viewport/src/context_menu/actions/show_hide.rs @@ -0,0 +1,156 @@ +use re_entity_db::InstancePath; +use re_viewer_context::{ContainerId, Item, SpaceViewId}; + +use crate::context_menu::{ContextMenuAction, ContextMenuContext}; +use crate::Contents; + +pub(crate) struct ShowAction; + +// TODO(ab): deduplicate these action on the model of CollapseExpandAllAction +impl ContextMenuAction for ShowAction { + fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { + ctx.selection.iter().any(|(item, _)| match item { + Item::SpaceView(space_view_id) => !ctx + .viewport_blueprint + .is_contents_visible(&Contents::SpaceView(*space_view_id)), + Item::Container(container_id) => { + !ctx.viewport_blueprint + .is_contents_visible(&Contents::Container(*container_id)) + && ctx.viewport_blueprint.root_container != Some(*container_id) + } + Item::DataResult(space_view_id, instance_path) => { + data_result_visible(ctx, space_view_id, instance_path).is_some_and(|vis| !vis) + } + _ => false, + }) + } + + fn label(&self, ctx: &ContextMenuContext<'_>) -> String { + if ctx.selection.len() > 1 { + "Show All".to_owned() + } else { + "Show".to_owned() + } + } + + fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { + ctx.viewport_blueprint.set_content_visibility( + ctx.viewer_context, + &Contents::Container(*container_id), + true, + ); + } + + fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { + ctx.viewport_blueprint.set_content_visibility( + ctx.viewer_context, + &Contents::SpaceView(*space_view_id), + true, + ); + } + + fn process_data_result( + &self, + ctx: &ContextMenuContext<'_>, + space_view_id: &SpaceViewId, + instance_path: &InstancePath, + ) { + set_data_result_visible(ctx, space_view_id, instance_path, true); + } +} + +pub(crate) struct HideAction; + +impl ContextMenuAction for HideAction { + fn supports_selection(&self, ctx: &ContextMenuContext<'_>) -> bool { + ctx.selection.iter().any(|(item, _)| match item { + Item::SpaceView(space_view_id) => ctx + .viewport_blueprint + .is_contents_visible(&Contents::SpaceView(*space_view_id)), + Item::Container(container_id) => { + ctx.viewport_blueprint + .is_contents_visible(&Contents::Container(*container_id)) + && ctx.viewport_blueprint.root_container != Some(*container_id) + } + Item::DataResult(space_view_id, instance_path) => { + data_result_visible(ctx, space_view_id, instance_path).unwrap_or(false) + } + _ => false, + }) + } + + fn label(&self, ctx: &ContextMenuContext<'_>) -> String { + if ctx.selection.len() > 1 { + "Hide All".to_owned() + } else { + "Hide".to_owned() + } + } + + fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { + ctx.viewport_blueprint.set_content_visibility( + ctx.viewer_context, + &Contents::Container(*container_id), + false, + ); + } + + fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { + ctx.viewport_blueprint.set_content_visibility( + ctx.viewer_context, + &Contents::SpaceView(*space_view_id), + false, + ); + } + + fn process_data_result( + &self, + ctx: &ContextMenuContext<'_>, + space_view_id: &SpaceViewId, + instance_path: &InstancePath, + ) { + set_data_result_visible(ctx, space_view_id, instance_path, false); + } +} + +fn data_result_visible( + ctx: &ContextMenuContext<'_>, + space_view_id: &SpaceViewId, + instance_path: &InstancePath, +) -> Option { + instance_path + .is_splat() + .then(|| { + let query_result = ctx.viewer_context.lookup_query_result(*space_view_id); + query_result + .tree + .lookup_result_by_path(&instance_path.entity_path) + .map(|data_result| { + data_result + .recursive_properties() + .map_or(true, |prop| prop.visible) + }) + }) + .flatten() +} + +fn set_data_result_visible( + ctx: &ContextMenuContext<'_>, + space_view_id: &SpaceViewId, + instance_path: &InstancePath, + visible: bool, +) { + let query_result = ctx.viewer_context.lookup_query_result(*space_view_id); + if let Some(data_result) = query_result + .tree + .lookup_result_by_path(&instance_path.entity_path) + { + let mut recursive_properties = data_result + .recursive_properties() + .cloned() + .unwrap_or_default(); + recursive_properties.visible = visible; + + data_result.save_recursive_override(ctx.viewer_context, Some(recursive_properties)); + } +} diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index b0ce3d8f4baf..f9835dd874ac 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -10,9 +10,14 @@ mod actions; mod sub_menu; use actions::{ - AddContainerAction, AddEntitiesToNewSpaceViewAction, AddSpaceViewAction, CloneSpaceViewAction, - CollapseExpandAllAction, HideAction, MoveContentsToNewContainerAction, RemoveAction, - ShowAction, + add_container::AddContainerAction, + add_entities_to_new_space_view::AddEntitiesToNewSpaceViewAction, + add_space_view::AddSpaceViewAction, + clone_space_view::CloneSpaceViewAction, + collapse_expand_all::CollapseExpandAllAction, + move_contents_to_new_container::MoveContentsToNewContainerAction, + remove::RemoveAction, + show_hide::{HideAction, ShowAction}, }; use sub_menu::SubMenu; @@ -133,7 +138,7 @@ fn action_list( }), ], vec![Box::new(SubMenu { - label: "Move to new container".to_owned(), + label: "Move to new Container".to_owned(), actions: vec![ Box::new(MoveContentsToNewContainerAction( egui_tiles::ContainerKind::Tabs, diff --git a/tests/python/release_checklist/check_context_menu.py b/tests/python/release_checklist/check_context_menu.py deleted file mode 100644 index fe31b9263448..000000000000 --- a/tests/python/release_checklist/check_context_menu.py +++ /dev/null @@ -1,106 +0,0 @@ -from __future__ import annotations - -import os -from argparse import Namespace -from uuid import uuid4 - -import rerun as rr - -README = """ -# Context Menu - -### Single-selection checks - -* Reset the blueprint. -* Right-click on any space view and check for context menu content: - - Hide (or Show, depending on visibility) - - Remove - - Clone - - Move to new container -* Check all work as expected. -* Right-click on a space view's tab title widget and check: - - It should show the same actions are above. - - It should set the selection to that space view, regardless of the previous selection state. -* Right-click on the top-level container ("Viewport") and check for context menu content: - - Add Container - - Add Space View -* Add a container via the context menu, check the container appears at then end of the list. -* Right-click on the container and check for context menu content: - - Hide (or Show, depending on visibility) - - Remove - - Add Container - - Add Space View - - Move to new container -* Right-click on a data result and check for the context menu content: - - Hide (or Show, depending on visibility) - - Remove -* Select a container and, in the Selection Panel, right click on either space view or container children: - - The context menu action should be the same as before. - - The selection state is not affected by the right-click. - - -### Selection behavior - -* Select a space view. -* Right-click on _another_ space view: the selection should switch to the newly-clicked space view. -* Select multiple space views. -* Right-click on one of the selected space view: the selection should remain the same and the context menu should appear. -* With multiple space views selected, right click on another space view that isn't yet selected. The selection should switch to the newly-clicked space view. - - -### Multi-selection checks - -* Select multiple space views, right-click, and check for context menu content: - - Hide All (if any are visible) - - Show All (if any are hidden) - - Remove - - Move to new container -* Same as above, but with only containers selected. -* Same as above, but with both space views and containers selected. -* Same as above, but with the viewport selected as well, and check for context menu content. These should not affect the Viewport. - - Hide All (if any are visible) - - Show All (if any are hidden) -* Select a mix of containers, space views, and data results, and check for context menu content: - - Hide All (if any are visible) - - Show All (if any are hidden) - - Remove - -### Invalid sub-container kind - -* Single-select a horizontal container, check that it disallow adding a horizontal container inside it. -* Same for a vertical container. -* Single select a space view inside a horizontal container, check that it disallow moving to a new horizontal container. -* Same for a space view inside a vertical container. -""" - - -def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) - - -def log_some_space_views() -> None: - rr.set_time_sequence("frame_nr", 0) - - rr.log("boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3)) - rr.log("boxes2d", rr.Boxes2D(centers=[[0, 0], [1.3, 0.5], [3, 2]], half_sizes=[0.5, 1] * 3)) - rr.log("text_logs", rr.TextLog("Hello, world!", level=rr.TextLogLevel.INFO)) - rr.log("points2d", rr.Points2D([[0, 0], [1, 1], [3, 2]], labels=["a", "b", "c"])) - rr.log("points2d/bbx", rr.Boxes2D(centers=[1, 1], half_sizes=[3, 3])) - - -def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) - - log_readme() - log_some_space_views() - - -if __name__ == "__main__": - import argparse - - parser = argparse.ArgumentParser(description="Interactive release checklist") - rr.script_add_args(parser) - args = parser.parse_args() - run(args) diff --git a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py new file mode 100644 index 000000000000..62b76362976c --- /dev/null +++ b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py @@ -0,0 +1,55 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr + +README = """ +# Context Menu - Invalid sub-container kind + +## Preparation + +TODO(ab): automate this with blueprints + +- Reset the blueprint +- Add a Horizontal container and a Vertical container in the viewport, and move one space view into each. + + +## Checks + +* Single-select a horizontal container, check that it disallow adding a horizontal container inside it. +* Same for a vertical container. +* Single select a space view inside a horizontal container, check that it disallow moving to a new horizontal container. +* Same for a space view inside a vertical container. +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def log_some_space_views() -> None: + rr.set_time_sequence("frame_nr", 0) + + rr.log("boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3)) + rr.log("boxes2d", rr.Boxes2D(centers=[[0, 0], [1.3, 0.5], [3, 2]], half_sizes=[0.5, 1] * 3)) + + +def run(args: Namespace) -> None: + # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but + # I'm not gonna rely on it anyway. + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + log_readme() + log_some_space_views() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) diff --git a/tests/python/release_checklist/check_context_menu_multi_selection.py b/tests/python/release_checklist/check_context_menu_multi_selection.py new file mode 100644 index 000000000000..030d83bfbe5f --- /dev/null +++ b/tests/python/release_checklist/check_context_menu_multi_selection.py @@ -0,0 +1,101 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr + +README = """ +# Context Menu - Multi-selection + + +## Preparation + +TODO(ab): automate this with blueprints + +- Reset the blueprint +- Add a Horizontal container in the viewport and move both the 2D and 3D space view into it + + +## Checks + +For each of the multi-selection below, check the context menu content as per the following table. + + +```plaintext +ITEMS CONTEXT MENU CONTENT + + +2x Space views Hide all + Remove + Expand all + Collapse all + Move to new Container + + ++ Horizontal container Hide all + Remove + Expand all + Collapse all + Move to new Container + + ++ Viewport Hide all + Expand all + Collapse all + + + --deselect all-- + + +Space view + 'box2d' data result Hide all + Remove + Expand all + Collapse all + + + --deselect all-- + + +'box2d' data result Hide all ++ 'box3d' entity (streams tree) Expand all + Collapse all + Add to new Space View + + ++ some component Hide all + Expand all + Collapse all + +``` +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def log_some_space_views() -> None: + rr.set_time_sequence("frame_nr", 0) + + rr.log("boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3)) + rr.log("boxes2d", rr.Boxes2D(centers=[[0, 0], [1.3, 0.5], [3, 2]], half_sizes=[0.5, 1] * 3)) + + +def run(args: Namespace) -> None: + # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but + # I'm not gonna rely on it anyway. + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + log_readme() + log_some_space_views() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) diff --git a/tests/python/release_checklist/check_context_menu_single_selection.py b/tests/python/release_checklist/check_context_menu_single_selection.py new file mode 100644 index 000000000000..04a7b53437fb --- /dev/null +++ b/tests/python/release_checklist/check_context_menu_single_selection.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr + +README = """ +# Context Menu - Single Selection + +## Preparation + +TODO(ab): automate this with blueprints + +- Reset the blueprint +- Add a Horizontal container in the viewport and move the 3D space view into it +- Right-click on the viewport and "Expand All" + + +## Streams tree + +- Right-click on various _unselected_ items, and check that: + - It becomes selected as the context menu appears. + - The context menu content is as per the following table. + + +```plaintext +ITEM CONTEXT MENU CONTENT + + +'group/' entity Expand all + Collapse all + Add to new Space View + + +Component + +``` + +## Tile Title UI + +- Multi-select the 3D space view and the Horizontal container in the Blueprint tree. +- Right-click on the 3D space view tab title: + - The selection is set to the space view _only_. + - The context menu content is as per the following table. + + +```plaintext +ITEM CONTEXT MENU CONTENT + + +space view (tab title) Hide (or Show, depending on visibility)d + Remove + Expand all + Collapse all + Clone + Move to new Container + +``` + + +## Container Selection Panel child list + +- Select the Horizontal container. +- In the selection panel, right-click on the 3D space view, and check that: + - The selection remains unchanged. + - The context menu content is as per the following table. + +```plaintext +ITEM CONTEXT MENU CONTENT + + +space view (child list) Hide (or Show, depending on visibility) + Remove + Expand all + Collapse all + Clone + Move to new Container + +``` + +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def log_some_space_views() -> None: + rr.set_time_sequence("frame_nr", 0) + + rr.log("group/boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3)) + + +def run(args: Namespace) -> None: + # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but + # I'm not gonna rely on it anyway. + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + log_readme() + log_some_space_views() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) diff --git a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py new file mode 100644 index 000000000000..b92577a3a334 --- /dev/null +++ b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py @@ -0,0 +1,96 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr + +README = """ +# Context Menu - Single Selection in the Blueprint tree + +## Preparation + +TODO(ab): automate this with blueprints + +- Reset the blueprint +- Add a Horizontal container in the viewport and move the 3D space view into it +- Right-click on the viewport and "Expand All" + + +## Checks + +- Right-click on various _unselected_ items, and check that: + - It becomes selected as the context menu appears. + - The context menu content is as per the following table. + + +```plaintext +ITEM CONTEXT MENU CONTENT + + +Viewport Expand all + Collapse all + Add Container + Add Space View + + +Container Hide (or Show, depending on visibility) + Remove + Expand all + Collapse all + Add Container + Add Space View + Move to new Container + + +Space View Hide (or Show, depending on visibility) + Remove + Expand all + Collapse all + Clone + Move to new Container + + +'group' Data Result Hide (or Show, depending on visibility) + Remove + Expand all + Collapse all + Add to new Space View + + +'boxes3d' Data Result Hide (or Show, depending on visibility) + Remove + Add to new Space View + +``` + +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def log_some_space_views() -> None: + rr.set_time_sequence("frame_nr", 0) + + rr.log("group/boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3)) + + +def run(args: Namespace) -> None: + # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but + # I'm not gonna rely on it anyway. + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + log_readme() + log_some_space_views() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) From 124305ccaef5df38d10ae492092ee9716a7945ff Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 12 Mar 2024 10:19:00 +0100 Subject: [PATCH 002/508] Add `incremental_logging` example (#5462) Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. Turns out the first thing I immediately wanted was clamping-edge semantics :smiling_face_with_tear: ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5462/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5462/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5462/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5462) - [Docs preview](https://rerun.io/preview/28ff483ad15c8d29334984ae730b0cd2d1677131/docs) - [Examples preview](https://rerun.io/preview/28ff483ad15c8d29334984ae730b0cd2d1677131/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 11 ++++ examples/cpp/CMakeLists.txt | 2 + .../cpp/incremental_logging/CMakeLists.txt | 27 ++++++++ examples/cpp/incremental_logging/README.md | 27 ++++++++ examples/cpp/incremental_logging/main.cpp | 38 +++++++++++ examples/python/incremental_logging/README.md | 25 +++++++ examples/python/incremental_logging/main.py | 36 ++++++++++ .../incremental_logging/requirements.txt | 2 + examples/python/requirements.txt | 1 + examples/rust/incremental_logging/Cargo.toml | 15 +++++ examples/rust/incremental_logging/README.md | 24 +++++++ examples/rust/incremental_logging/src/main.rs | 66 +++++++++++++++++++ 12 files changed, 274 insertions(+) create mode 100644 examples/cpp/incremental_logging/CMakeLists.txt create mode 100644 examples/cpp/incremental_logging/README.md create mode 100644 examples/cpp/incremental_logging/main.cpp create mode 100644 examples/python/incremental_logging/README.md create mode 100755 examples/python/incremental_logging/main.py create mode 100644 examples/python/incremental_logging/requirements.txt create mode 100644 examples/rust/incremental_logging/Cargo.toml create mode 100644 examples/rust/incremental_logging/README.md create mode 100644 examples/rust/incremental_logging/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index e10343637ee7..70d3ed4c4acb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2617,6 +2617,17 @@ dependencies = [ "tiff", ] +[[package]] +name = "incremental_logging" +version = "0.15.0-alpha.2" +dependencies = [ + "anyhow", + "clap", + "glam", + "rand", + "rerun", +] + [[package]] name = "indent" version = "0.1.1" diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt index 1bc4433b52b0..f4827c8fb3d4 100644 --- a/examples/cpp/CMakeLists.txt +++ b/examples/cpp/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(clock) add_subdirectory(custom_collection_adapter) add_subdirectory(dna) add_subdirectory(external_data_loader) +add_subdirectory(incremental_logging) add_subdirectory(log_file) add_subdirectory(minimal) add_subdirectory(shared_recording) @@ -13,6 +14,7 @@ add_custom_target(examples) add_dependencies(examples example_clock) add_dependencies(examples example_custom_collection_adapter) add_dependencies(examples example_dna) +add_dependencies(examples example_incremental_logging) add_dependencies(examples example_log_file) add_dependencies(examples example_minimal) add_dependencies(examples example_shared_recording) diff --git a/examples/cpp/incremental_logging/CMakeLists.txt b/examples/cpp/incremental_logging/CMakeLists.txt new file mode 100644 index 000000000000..fc9ac1b03a01 --- /dev/null +++ b/examples/cpp/incremental_logging/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.16...3.27) + +# If you use the example outside of the Rerun SDK you need to specify +# where the rerun_c build is to be found by setting the `RERUN_CPP_URL` variable. +# This can be done by passing `-DRERUN_CPP_URL=` to cmake. +if(DEFINED RERUN_REPOSITORY) + add_executable(example_incremental_logging main.cpp) + rerun_strict_warning_settings(example_incremental_logging) +else() + project(example_incremental_logging LANGUAGES CXX) + + add_executable(example_incremental_logging main.cpp) + + # Set the path to the rerun_c build. + set(RERUN_CPP_URL "https://github.com/rerun-io/rerun/releases/latest/download/rerun_cpp_sdk.zip" CACHE STRING "URL to the rerun_cpp zip.") + + # Download the rerun_sdk + include(FetchContent) + FetchContent_Declare(rerun_sdk URL ${RERUN_CPP_URL}) + FetchContent_MakeAvailable(rerun_sdk) + + # Rerun requires at least C++17, but it should be compatible with newer versions. + set_property(TARGET example_incremental_logging PROPERTY CXX_STANDARD 17) +endif() + +# Link against rerun_sdk. +target_link_libraries(example_incremental_logging PRIVATE rerun_sdk) diff --git a/examples/cpp/incremental_logging/README.md b/examples/cpp/incremental_logging/README.md new file mode 100644 index 000000000000..9e21b511b8a7 --- /dev/null +++ b/examples/cpp/incremental_logging/README.md @@ -0,0 +1,27 @@ + + + + + + + + + + + +Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. + + +To build it from a checkout of the repository (requires a Rust toolchain): +```bash +cmake . +cmake --build . --target example_incremental_logging +./examples/cpp/incremental/example_incremental_logging +``` diff --git a/examples/cpp/incremental_logging/main.cpp b/examples/cpp/incremental_logging/main.cpp new file mode 100644 index 000000000000..07645bed173f --- /dev/null +++ b/examples/cpp/incremental_logging/main.cpp @@ -0,0 +1,38 @@ +// Showcase how to incrementally log data belonging to the same archetype, and re-use some or all +// of it across frames. + +#include + +#include +#include + +int main() { + const auto rec = rerun::RecordingStream("rerun_example_incremental_logging"); + rec.spawn().exit_on_failure(); + + // TODO(#5264): just log one once clamp-to-edge semantics land. + std::vector colors(10, rerun::Color(255, 0, 0)); + std::vector radii(10, rerun::Radius(0.1f)); + + // Only log colors and radii once. + rec.set_time_sequence("frame_nr", 0); + rec.log("points", colors, radii); + // Logging timelessly with `RecordingStream::log_timeless` would also work. + // rec.log_timeless("points", colors, radii); + + std::default_random_engine gen; + std::uniform_real_distribution dist_pos(-5.0f, 5.0f); + + // Then log only the points themselves each frame. + // + // They will automatically re-use the colors and radii logged at the beginning. + for (int i = 0; i < 10; ++i) { + rec.set_time_sequence("frame_nr", i); + + std::vector points(10); + std::generate(points.begin(), points.end(), [&] { + return rerun::Position3D(dist_pos(gen), dist_pos(gen), dist_pos(gen)); + }); + rec.log("points", rerun::Points3D(points)); + } +} diff --git a/examples/python/incremental_logging/README.md b/examples/python/incremental_logging/README.md new file mode 100644 index 000000000000..0f0de9cfd8f9 --- /dev/null +++ b/examples/python/incremental_logging/README.md @@ -0,0 +1,25 @@ + + + + + + + + + + + +Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. + + +To build it from a checkout of the repository (requires a Rust toolchain): +```bash +python examples/python/incremental_logging/main.py +``` diff --git a/examples/python/incremental_logging/main.py b/examples/python/incremental_logging/main.py new file mode 100755 index 000000000000..d253aa9ca344 --- /dev/null +++ b/examples/python/incremental_logging/main.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +"""Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames.""" +from __future__ import annotations + +import argparse + +import numpy as np +import rerun as rr +from numpy.random import default_rng + +parser = argparse.ArgumentParser(description="Showcases how to incrementally log data belonging to the same archetype.") +rr.script_add_args(parser) +args = parser.parse_args() + +rr.script_setup(args, "rerun_example_incremental_logging") + +# TODO(#5264): just log one once clamp-to-edge semantics land. +colors = rr.components.ColorBatch(np.repeat(0xFF0000FF, 10)) +radii = rr.components.RadiusBatch(np.repeat(0.1, 10)) + +# Only log colors and radii once. +rr.set_time_sequence("frame_nr", 0) +rr.log_components("points", [colors, radii]) +# Logging timelessly would also work. +# rr.log_components("points", [colors, radii], timeless=True) + +rng = default_rng(12345) + +# Then log only the points themselves each frame. +# +# They will automatically re-use the colors and radii logged at the beginning. +for i in range(10): + rr.set_time_sequence("frame_nr", i) + rr.log("points", rr.Points3D(rng.uniform(-5, 5, size=[10, 3]))) + +rr.script_teardown(args) diff --git a/examples/python/incremental_logging/requirements.txt b/examples/python/incremental_logging/requirements.txt new file mode 100644 index 000000000000..fa4ff5da669a --- /dev/null +++ b/examples/python/incremental_logging/requirements.txt @@ -0,0 +1,2 @@ +numpy +rerun-sdk diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt index 55659d6d6160..e96506de5b14 100644 --- a/examples/python/requirements.txt +++ b/examples/python/requirements.txt @@ -11,6 +11,7 @@ -r face_tracking/requirements.txt -r gesture_detection/requirements.txt -r human_pose_tracking/requirements.txt +-r incremental_logging/requirements.txt -r lidar/requirements.txt -r live_camera_edge_detection/requirements.txt -r live_depth_sensor/requirements.txt diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml new file mode 100644 index 000000000000..34635f1109ae --- /dev/null +++ b/examples/rust/incremental_logging/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "incremental_logging" +version = "0.15.0-alpha.2" +edition = "2021" +rust-version = "1.74" +license = "MIT OR Apache-2.0" +publish = false + +[dependencies] +rerun = { path = "../../../crates/rerun", features = ["web_viewer", "clap"] } + +anyhow = "1.0" +clap = { version = "4.0", features = ["derive"] } +glam = "0.22" +rand = "0.8" diff --git a/examples/rust/incremental_logging/README.md b/examples/rust/incremental_logging/README.md new file mode 100644 index 000000000000..ec79ff2115a6 --- /dev/null +++ b/examples/rust/incremental_logging/README.md @@ -0,0 +1,24 @@ + + + + + + + + + + + +Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. + + +```bash +cargo run --release +``` diff --git a/examples/rust/incremental_logging/src/main.rs b/examples/rust/incremental_logging/src/main.rs new file mode 100644 index 000000000000..3a310cf63a00 --- /dev/null +++ b/examples/rust/incremental_logging/src/main.rs @@ -0,0 +1,66 @@ +//! Showcase how to incrementally log data belonging to the same archetype, and re-use some or all +//! of it across frames. +//! +//! Usage: +//! ``` +//! cargo run -p incremental -- --help +//! ``` + +use rand::{distributions::Uniform, Rng as _}; +use rerun::external::re_log; + +#[derive(Debug, clap::Parser)] +#[clap(author, version, about)] +struct Args { + #[command(flatten)] + rerun: rerun::clap::RerunArgs, +} + +fn main() -> anyhow::Result<()> { + re_log::setup_logging(); + + use clap::Parser as _; + let args = Args::parse(); + + let (rec, _serve_guard) = args.rerun.init("rerun_example_incremental_logging")?; + run(&rec) +} + +fn run(rec: &rerun::RecordingStream) -> anyhow::Result<()> { + // TODO(#5264): just log one once clamp-to-edge semantics land. + let colors = [rerun::Color::from_rgb(255, 0, 0); 10]; + let radii = [rerun::Radius(0.1); 10]; + + // Only log colors and radii once. + rec.set_time_sequence("frame_nr", 0); + rec.log_component_batches( + "points", + false, /* timeless */ + [&colors as &dyn rerun::ComponentBatch, &radii], + )?; + // Logging timelessly would also work. + // rec.log_component_batches( + // "points", + // true, /* timeless */ + // [&colors as &dyn rerun::ComponentBatch, &radii], + // )?; + + let mut rng = rand::thread_rng(); + let dist = Uniform::new(-5., 5.); + + // Then log only the points themselves each frame. + // + // They will automatically re-use the colors and radii logged at the beginning. + for i in 0..10 { + rec.set_time_sequence("frame_nr", i); + + rec.log( + "points", + &rerun::Points3D::new( + (0..10).map(|_| (rng.sample(dist), rng.sample(dist), rng.sample(dist))), + ), + )?; + } + + Ok(()) +} From 7a6efffbbf9b6e4af4dc55d75cbc125eebfab50c Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 12 Mar 2024 11:31:19 +0100 Subject: [PATCH 003/508] Configurable background color for 3D Space Views (#5443) ### What * Fixes #754 Originally made a sort of tint/alpha color for the existing gradient, but after some feedback I got I changed it around to be a dropdown of 3 different modes: dark gradient, bright gradient, solid color (with the picker) The blend version was quite confusing and admittedly not all that useful :) https://github.com/rerun-io/rerun/assets/1220815/2ed21cba-3abe-46f1-9ce3-317f41e576d4 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5443/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5443/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5443/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5443) - [Docs preview](https://rerun.io/preview/5088b46141a6c8823ebe8cd51e112b49c47a165d/docs) - [Examples preview](https://rerun.io/preview/5088b46141a6c8823ebe8cd51e112b49c47a165d/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/editors.rs | 8 +- crates/re_renderer/shader/generic_skybox.wgsl | 27 ++- .../src/renderer/generic_skybox.rs | 82 +++++++- crates/re_renderer/src/renderer/mod.rs | 2 +- crates/re_renderer_examples/depth_cloud.rs | 4 +- crates/re_renderer_examples/multiview.rs | 2 +- crates/re_renderer_examples/outlines.rs | 5 +- crates/re_renderer_examples/picking.rs | 7 +- .../src/space_view_2d.rs | 10 +- .../src/space_view_3d.rs | 143 +++++++++++++- crates/re_space_view_spatial/src/ui.rs | 161 ++++----------- crates/re_space_view_spatial/src/ui_3d.rs | 73 ++++++- .../re_types/definitions/rerun/blueprint.fbs | 2 + .../blueprint/archetypes/background_3d.fbs | 29 +++ .../components/background_3d_kind.fbs | 24 +++ .../src/blueprint/archetypes/.gitattributes | 1 + .../src/blueprint/archetypes/background3d.rs | 185 ++++++++++++++++++ .../blueprint/archetypes/background3d_ext.rs | 17 ++ .../re_types/src/blueprint/archetypes/mod.rs | 3 + .../src/blueprint/components/.gitattributes | 1 + .../blueprint/components/background3d_kind.rs | 167 ++++++++++++++++ .../re_types/src/blueprint/components/mod.rs | 2 + crates/re_types/src/components/color_ext.rs | 4 + crates/re_types/src/datatypes/rgba32_ext.rs | 9 + .../src/blueprint/validation_gen/mod.rs | 2 + rerun_cpp/src/rerun/blueprint/archetypes.hpp | 1 + .../rerun/blueprint/archetypes/.gitattributes | 2 + .../blueprint/archetypes/background3d.cpp | 38 ++++ .../blueprint/archetypes/background3d.hpp | 74 +++++++ rerun_cpp/src/rerun/blueprint/components.hpp | 1 + .../rerun/blueprint/components/.gitattributes | 2 + .../components/background3d_kind.cpp | 66 +++++++ .../components/background3d_kind.hpp | 55 ++++++ .../rerun/blueprint/archetypes/.gitattributes | 1 + .../rerun/blueprint/archetypes/__init__.py | 2 + .../blueprint/archetypes/background3d.py | 81 ++++++++ .../rerun/blueprint/components/.gitattributes | 1 + .../rerun/blueprint/components/__init__.py | 12 ++ .../blueprint/components/background3d_kind.py | 103 ++++++++++ 39 files changed, 1250 insertions(+), 159 deletions(-) create mode 100644 crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs create mode 100644 crates/re_types/src/blueprint/archetypes/background3d.rs create mode 100644 crates/re_types/src/blueprint/archetypes/background3d_ext.rs create mode 100644 crates/re_types/src/blueprint/components/background3d_kind.rs create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/background3d.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index 78b70a56d124..62b603e3c516 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -31,8 +31,7 @@ fn edit_color_ui( .ok() .unwrap_or_else(|| default_color(ctx, query, store, entity_path)); - let [r, g, b, a] = current_color.to_array(); - let current_color = egui::Color32::from_rgba_unmultiplied(r, g, b, a); + let current_color = current_color.into(); let mut edit_color = current_color; egui::color_picker::color_edit_button_srgba( @@ -42,10 +41,7 @@ fn edit_color_ui( ); if edit_color != current_color { - let [r, g, b, a] = edit_color.to_array(); - let new_color = Color::from_unmultiplied_rgba(r, g, b, a); - - ctx.save_blueprint_component(override_path, &new_color); + ctx.save_blueprint_component(override_path, &Color::from(edit_color)); } } diff --git a/crates/re_renderer/shader/generic_skybox.wgsl b/crates/re_renderer/shader/generic_skybox.wgsl index 65d9252cb419..9aa59482d0af 100644 --- a/crates/re_renderer/shader/generic_skybox.wgsl +++ b/crates/re_renderer/shader/generic_skybox.wgsl @@ -4,6 +4,18 @@ #import <./utils/camera.wgsl> #import <./screen_triangle_vertex.wgsl> +struct UniformBuffer { + // See `GenericSkyboxType` in `generic_skybox.rs` + background_type: u32, + _padding: vec3f, +} + +const GRADIENT_DARK: u32 = 0u; +const GRADIENT_BRGHT: u32 = 1u; + +@group(1) @binding(0) +var uniforms: UniformBuffer; + fn skybox_dark_srgb(dir: vec3f) -> vec3f { let rgb = dir * 0.5 + vec3f(0.5); return vec3f(0.05) + 0.20 * rgb; @@ -11,7 +23,7 @@ fn skybox_dark_srgb(dir: vec3f) -> vec3f { fn skybox_light_srgb(dir: vec3f) -> vec3f { let rgb = dir * 0.5 + vec3f(0.5); - return vec3f(0.85) + 0.15 * rgb; + return vec3f(0.7) + 0.20 * rgb; } // ----------------------------------------------- @@ -39,15 +51,20 @@ fn dither_interleaved(rgb: vec3f, levels: f32, frag_coord: vec4) -> vec3f { @fragment fn main(in: FragmentInput, @builtin(position) frag_coord: vec4) -> @location(0) vec4f { let camera_dir = camera_ray_direction_from_screenuv(in.texcoord); - // Messing with direction a bit so it looks like in our old three-d based renderer (for easier comparison) - let rgb = skybox_dark_srgb(camera_dir); // TODO(andreas): Allow switching to skybox_light + + var rgb: vec3f; + if uniforms.background_type == GRADIENT_DARK { + rgb = skybox_dark_srgb(camera_dir); + } else { + rgb = skybox_light_srgb(camera_dir); + } // Apply dithering in gamma space. // TODO(andreas): Once we switch to HDR outputs, this can be removed. // As of writing, the render target itself is (s)RGB8, so we need to dither while we still have maximum precision. - let rgb_dithered = dither_interleaved(rgb, 256.0, frag_coord); + var rgb_gamma_dithered = dither_interleaved(rgb, 256.0, frag_coord); - return vec4f(linear_from_srgb(rgb_dithered), 1.0); + return vec4f(linear_from_srgb(rgb_gamma_dithered), 1.0); //return vec4f(linear_from_srgb(rgb), 1.0); // Without dithering //return vec4f(camera_dir, 1.0); } diff --git a/crates/re_renderer/src/renderer/generic_skybox.rs b/crates/re_renderer/src/renderer/generic_skybox.rs index 5b278e79aaa3..7c8e1ad6176e 100644 --- a/crates/re_renderer/src/renderer/generic_skybox.rs +++ b/crates/re_renderer/src/renderer/generic_skybox.rs @@ -1,11 +1,13 @@ use smallvec::smallvec; use crate::{ + allocator::create_and_fill_uniform_buffer, draw_phases::DrawPhase, include_shader_module, renderer::screen_triangle_vertex_shader, view_builder::ViewBuilder, wgpu_resources::{ + BindGroupDesc, BindGroupLayoutDesc, GpuBindGroup, GpuBindGroupLayoutHandle, GpuRenderPipelineHandle, GpuRenderPipelinePoolAccessor, PipelineLayoutDesc, RenderPipelineDesc, }, @@ -13,25 +15,68 @@ use crate::{ use super::{DrawData, DrawError, RenderContext, Renderer}; +/// The type of generic skybox to render. +/// +/// If you want a solid background color, don't add the skybox at all and instead set a clear color. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +pub enum GenericSkyboxType { + #[default] + GradientDark = 0, + GradientBright = 1, +} + +mod gpu_data { + use crate::wgpu_buffer_types; + + #[repr(C, align(256))] + #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] + pub struct UniformBuffer { + pub background_type: wgpu_buffer_types::U32RowPadded, + pub _end_padding: [wgpu_buffer_types::PaddingRow; 16 - 1], + } +} + /// Renders a generated skybox from a color gradient /// /// Is not actually a skybox, but a fullscreen effect. /// Should be rendered *last* to reduce amount of overdraw! pub struct GenericSkybox { render_pipeline: GpuRenderPipelineHandle, + bind_group_layout: GpuBindGroupLayoutHandle, } #[derive(Clone)] -pub struct GenericSkyboxDrawData {} +pub struct GenericSkyboxDrawData { + bind_group: GpuBindGroup, +} impl DrawData for GenericSkyboxDrawData { type Renderer = GenericSkybox; } impl GenericSkyboxDrawData { - pub fn new(ctx: &RenderContext) -> Self { - let _ = ctx.renderer::(); // TODO(andreas): This line ensures that the renderer exists. Currently this needs to be done ahead of time, but should be fully automatic! - GenericSkyboxDrawData {} + pub fn new(ctx: &RenderContext, typ: GenericSkyboxType) -> Self { + let skybox_renderer = ctx.renderer::(); + + let uniform_buffer = gpu_data::UniformBuffer { + background_type: (typ as u32).into(), + _end_padding: Default::default(), + }; + + let uniform_buffer_binding = + create_and_fill_uniform_buffer(ctx, "skybox uniform buffer".into(), uniform_buffer); + + let bind_group = ctx.gpu_resources.bind_groups.alloc( + &ctx.device, + &ctx.gpu_resources, + &BindGroupDesc { + label: "GenericSkyboxDrawData::bind_group".into(), + entries: smallvec![uniform_buffer_binding,], + layout: skybox_renderer.bind_group_layout, + }, + ); + + GenericSkyboxDrawData { bind_group } } } @@ -41,6 +86,25 @@ impl Renderer for GenericSkybox { fn create_renderer(ctx: &RenderContext) -> Self { re_tracing::profile_function!(); + let bind_group_layout = ctx.gpu_resources.bind_group_layouts.get_or_create( + &ctx.device, + &(BindGroupLayoutDesc { + label: "GenericSkybox::bind_group_layout".into(), + entries: vec![wgpu::BindGroupLayoutEntry { + binding: 0, + visibility: wgpu::ShaderStages::FRAGMENT, + ty: wgpu::BindingType::Buffer { + ty: wgpu::BufferBindingType::Uniform, + has_dynamic_offset: false, + min_binding_size: (std::mem::size_of::() as u64) + .try_into() + .ok(), + }, + count: None, + }], + }), + ); + let vertex_handle = screen_triangle_vertex_shader(ctx); let render_pipeline = ctx.gpu_resources.render_pipelines.get_or_create( ctx, @@ -50,7 +114,7 @@ impl Renderer for GenericSkybox { ctx, &PipelineLayoutDesc { label: "GenericSkybox::render_pipeline".into(), - entries: vec![ctx.global_bindings.layout], + entries: vec![ctx.global_bindings.layout, bind_group_layout], }, ), @@ -76,7 +140,10 @@ impl Renderer for GenericSkybox { multisample: ViewBuilder::MAIN_TARGET_DEFAULT_MSAA_STATE, }, ); - GenericSkybox { render_pipeline } + GenericSkybox { + render_pipeline, + bind_group_layout, + } } fn draw<'a>( @@ -84,13 +151,14 @@ impl Renderer for GenericSkybox { render_pipelines: &'a GpuRenderPipelinePoolAccessor<'a>, _phase: DrawPhase, pass: &mut wgpu::RenderPass<'a>, - _draw_data: &GenericSkyboxDrawData, + draw_data: &'a Self::RendererDrawData, ) -> Result<(), DrawError> { re_tracing::profile_function!(); let pipeline = render_pipelines.get(self.render_pipeline)?; pass.set_pipeline(pipeline); + pass.set_bind_group(1, &draw_data.bind_group, &[]); pass.draw(0..3, 0..1); Ok(()) diff --git a/crates/re_renderer/src/renderer/mod.rs b/crates/re_renderer/src/renderer/mod.rs index f67a832dc08c..ccca81217c8a 100644 --- a/crates/re_renderer/src/renderer/mod.rs +++ b/crates/re_renderer/src/renderer/mod.rs @@ -1,5 +1,5 @@ mod generic_skybox; -pub use generic_skybox::GenericSkyboxDrawData; +pub use generic_skybox::{GenericSkyboxDrawData, GenericSkyboxType}; mod lines; pub use lines::{LineBatchInfo, LineDrawData, LineDrawDataError, LineStripFlags}; diff --git a/crates/re_renderer_examples/depth_cloud.rs b/crates/re_renderer_examples/depth_cloud.rs index 270826113bf0..da160f24b8d1 100644 --- a/crates/re_renderer_examples/depth_cloud.rs +++ b/crates/re_renderer_examples/depth_cloud.rs @@ -128,7 +128,7 @@ impl RenderDepthClouds { ); let command_buffer = view_builder - .queue_draw(GenericSkyboxDrawData::new(re_ctx)) + .queue_draw(GenericSkyboxDrawData::new(re_ctx, Default::default())) .queue_draw(point_cloud_draw_data) .queue_draw(frame_draw_data) .queue_draw(image_draw_data) @@ -208,7 +208,7 @@ impl RenderDepthClouds { ); let command_buffer = view_builder - .queue_draw(GenericSkyboxDrawData::new(re_ctx)) + .queue_draw(GenericSkyboxDrawData::new(re_ctx, Default::default())) .queue_draw(depth_cloud_draw_data) .queue_draw(frame_draw_data) .queue_draw(image_draw_data) diff --git a/crates/re_renderer_examples/multiview.rs b/crates/re_renderer_examples/multiview.rs index a8b7129dc9fb..f6d14dd07e09 100644 --- a/crates/re_renderer_examples/multiview.rs +++ b/crates/re_renderer_examples/multiview.rs @@ -324,7 +324,7 @@ impl Example for Multiview { IsoTransform::look_at_rh(self.camera_position, Vec3::ZERO, Vec3::Y).unwrap(); let triangle = TestTriangleDrawData::new(re_ctx); - let skybox = GenericSkyboxDrawData::new(re_ctx); + let skybox = GenericSkyboxDrawData::new(re_ctx, Default::default()); let lines = build_lines(re_ctx, seconds_since_startup); let mut builder = PointCloudBuilder::new(re_ctx); diff --git a/crates/re_renderer_examples/outlines.rs b/crates/re_renderer_examples/outlines.rs index 5317878317ab..37a606ea7b16 100644 --- a/crates/re_renderer_examples/outlines.rs +++ b/crates/re_renderer_examples/outlines.rs @@ -120,7 +120,10 @@ impl framework::Example for Outlines { }) .collect_vec(); - view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx)); + view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new( + re_ctx, + Default::default(), + )); view_builder .queue_draw(re_renderer::renderer::MeshDrawData::new(re_ctx, &instances).unwrap()); diff --git a/crates/re_renderer_examples/picking.rs b/crates/re_renderer_examples/picking.rs index 20d2f940fbf0..2f9b157f8739 100644 --- a/crates/re_renderer_examples/picking.rs +++ b/crates/re_renderer_examples/picking.rs @@ -190,12 +190,13 @@ impl framework::Example for Picking { }) .collect_vec(); - view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx)); + view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new( + re_ctx, + Default::default(), + )); view_builder .queue_draw(re_renderer::renderer::MeshDrawData::new(re_ctx, &instances).unwrap()); - view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new(re_ctx)); - let command_buffer = view_builder .draw(re_ctx, re_renderer::Rgba::TRANSPARENT) .unwrap(); diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index 6c2bb125a3be..cc75ce856db8 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -222,11 +222,17 @@ impl SpaceViewClass for SpatialSpaceView2D { ctx: &re_viewer_context::ViewerContext<'_>, ui: &mut egui::Ui, state: &mut Self::State, - space_origin: &EntityPath, + _space_origin: &EntityPath, _space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, ) { - state.selection_ui(ctx, ui, space_origin, SpatialSpaceViewKind::TwoD); + ctx.re_ui + .selection_grid(ui, "spatial_settings_ui") + .show(ui, |ui| { + state.default_size_ui(ctx, ui); + state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::TwoD); + ui.end_row(); + }); } fn ui( diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index f10a5f729e88..53fd96366127 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -2,7 +2,12 @@ use itertools::Itertools; use nohash_hasher::IntSet; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, EntityPathFilter}; -use re_types::{components::ViewCoordinates, Loggable}; +use re_space_view::query_space_view_sub_archetype; +use re_types::{ + blueprint::{archetypes::Background3D, components::Background3DKind}, + components::ViewCoordinates, + Loggable, +}; use re_viewer_context::{ PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, @@ -15,7 +20,7 @@ use crate::{ default_visualized_entities_for_visualizer_kind, update_object_property_heuristics, }, spatial_topology::{HeuristicHints, SpatialTopology, SubSpaceConnectionFlags}, - ui::SpatialSpaceViewState, + ui::{format_vector, SpatialSpaceViewState}, view_kind::SpatialSpaceViewKind, visualizers::register_3d_spatial_visualizers, }; @@ -261,10 +266,77 @@ impl SpaceViewClass for SpatialSpaceView3D { ui: &mut egui::Ui, state: &mut Self::State, space_origin: &EntityPath, - _space_view_id: SpaceViewId, + space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, ) { - state.selection_ui(ctx, ui, space_origin, SpatialSpaceViewKind::ThreeD); + let scene_view_coordinates = ctx + .entity_db + .store() + .query_latest_component::(space_origin, &ctx.current_query()) + .map(|c| c.value); + + ctx.re_ui + .selection_grid(ui, "spatial_settings_ui") + .show(ui, |ui| { + state.default_size_ui(ctx, ui); + + ctx.re_ui + .grid_left_hand_label(ui, "Camera") + .on_hover_text("The virtual camera which controls what is shown on screen"); + ui.vertical(|ui| { + state.view_eye_ui(ctx.re_ui, ui, scene_view_coordinates); + }); + ui.end_row(); + + ctx.re_ui + .grid_left_hand_label(ui, "Coordinates") + .on_hover_text("The world coordinate system used for this view"); + ui.vertical(|ui| { + let up_description = + if let Some(scene_up) = scene_view_coordinates.and_then(|vc| vc.up()) { + format!("Scene up is {scene_up}") + } else { + "Scene up is unspecified".to_owned() + }; + ui.label(up_description).on_hover_ui(|ui| { + re_ui::markdown_ui( + ui, + egui::Id::new("view_coordinates_tooltip"), + "Set with `rerun.ViewCoordinates`.", + ); + }); + + if let Some(eye) = &state.state_3d.view_eye { + if let Some(eye_up) = eye.eye_up() { + ui.label(format!( + "Current camera-eye up-axis is {}", + format_vector(eye_up) + )); + } + } + + ctx.re_ui + .checkbox(ui, &mut state.state_3d.show_axes, "Show origin axes") + .on_hover_text("Show X-Y-Z axes"); + ctx.re_ui + .checkbox(ui, &mut state.state_3d.show_bbox, "Show bounding box") + .on_hover_text("Show the current scene bounding box"); + ctx.re_ui + .checkbox( + ui, + &mut state.state_3d.show_accumulated_bbox, + "Show accumulated bounding box", + ) + .on_hover_text("Show bounding box accumulated over all rendered frames"); + }); + ui.end_row(); + + background_ui(ctx, space_view_id, ui); + ui.end_row(); + + state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::ThreeD); + ui.end_row(); + }); } fn ui( @@ -288,3 +360,66 @@ impl SpaceViewClass for SpatialSpaceView3D { crate::ui_3d::view_3d(ctx, ui, state, query, system_output) } } + +fn background_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mut egui::Ui) { + let blueprint_db = ctx.store_context.blueprint; + let blueprint_query = ctx.blueprint_query; + let (archetype, blueprint_path) = + query_space_view_sub_archetype(space_view_id, blueprint_db, blueprint_query); + + let Background3D { color, mut kind } = archetype.unwrap_or_default(); + + ctx.re_ui.grid_left_hand_label(ui, "Background"); + + ui.vertical(|ui| { + let kind_before = kind; + egui::ComboBox::from_id_source("background") + .selected_text(background_color_text(kind)) + .show_ui(ui, |ui| { + ui.selectable_value( + &mut kind, + Background3DKind::GradientDark, + background_color_text(Background3DKind::GradientDark), + ); + ui.selectable_value( + &mut kind, + Background3DKind::GradientBright, + background_color_text(Background3DKind::GradientBright), + ); + ui.selectable_value( + &mut kind, + Background3DKind::SolidColor, + background_color_text(Background3DKind::SolidColor), + ); + }); + if kind_before != kind { + ctx.save_blueprint_component(&blueprint_path, &kind); + } + + if kind == Background3DKind::SolidColor { + let current_color = color.unwrap_or(Background3D::DEFAULT_COLOR).into(); + let mut edit_color = current_color; + egui::color_picker::color_edit_button_srgba( + ui, + &mut edit_color, + egui::color_picker::Alpha::Opaque, + ); + if edit_color != current_color { + ctx.save_blueprint_component( + &blueprint_path, + &re_types::components::Color::from(edit_color), + ); + } + } + }); + + ui.end_row(); +} + +fn background_color_text(kind: Background3DKind) -> &'static str { + match kind { + Background3DKind::GradientDark => "Dark Gradient", + Background3DKind::GradientBright => "Bright Gradient", + Background3DKind::SolidColor => "Solid Color", + } +} diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 8ff74ac562c4..d4e992dab371 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -3,7 +3,6 @@ use macaw::BoundingBox; use re_data_ui::{image_meaning_for_entity, item_ui, DataUi}; use re_data_ui::{show_zoomed_image_region, show_zoomed_image_region_area_outline}; -use re_entity_db::EntityPath; use re_format::format_f32; use re_renderer::OutlineConfig; use re_space_view::ScreenshotMode; @@ -88,136 +87,62 @@ impl SpatialSpaceViewState { config } - pub fn selection_ui( + pub fn bounding_box_ui( &mut self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - space_origin: &EntityPath, spatial_kind: SpatialSpaceViewKind, ) { - let re_ui = ctx.re_ui; - - let scene_view_coordinates = ctx - .entity_db - .store() - .query_latest_component::(space_origin, &ctx.current_query()) - .map(|c| c.value); - ctx.re_ui - .selection_grid(ui, "spatial_settings_ui") - .show(ui, |ui| { - let auto_size_world = auto_size_world_heuristic( - &self.bounding_boxes.accumulated, - self.scene_num_primitives, - ); - - ctx.re_ui.grid_left_hand_label(ui, "Default size"); - ui.vertical(|ui| { - ui.horizontal(|ui| { - ui.push_id("points", |ui| { - size_ui( - ui, - 2.0, - auto_size_world, - &mut self.auto_size_config.point_radius, - ); - }); - ui.label("Point radius") - .on_hover_text("Point radius used whenever not explicitly specified"); - }); - ui.horizontal(|ui| { - ui.push_id("lines", |ui| { - size_ui( - ui, - 1.5, - auto_size_world, - &mut self.auto_size_config.line_radius, - ); - ui.label("Line radius").on_hover_text( - "Line radius used whenever not explicitly specified", - ); - }); - }); - }); - ui.end_row(); - - ctx.re_ui - .grid_left_hand_label(ui, "Camera") - .on_hover_text("The virtual camera which controls what is shown on screen"); - ui.vertical(|ui| { - if spatial_kind == SpatialSpaceViewKind::ThreeD { - self.view_eye_ui(re_ui, ui, scene_view_coordinates); - } - }); - ui.end_row(); - - if spatial_kind == SpatialSpaceViewKind::ThreeD { - ctx.re_ui - .grid_left_hand_label(ui, "Coordinates") - .on_hover_text("The world coordinate system used for this view"); - ui.vertical(|ui| { - let up_description = - if let Some(scene_up) = scene_view_coordinates.and_then(|vc| vc.up()) { - format!("Scene up is {scene_up}") - } else { - "Scene up is unspecified".to_owned() - }; - ui.label(up_description).on_hover_ui(|ui| { - re_ui::markdown_ui( - ui, - egui::Id::new("view_coordinates_tooltip"), - "Set with `rerun.ViewCoordinates`.", - ); - }); - - if let Some(eye) = &self.state_3d.view_eye { - if let Some(eye_up) = eye.eye_up() { - ui.label(format!( - "Current camera-eye up-axis is {}", - format_vector(eye_up) - )); - } - } + .grid_left_hand_label(ui, "Bounding box") + .on_hover_text("The bounding box encompassing all Entities in the view right now"); + ui.vertical(|ui| { + ui.style_mut().wrap = Some(false); + let BoundingBox { min, max } = self.bounding_boxes.current; + ui.label(format!("x [{} - {}]", format_f32(min.x), format_f32(max.x),)); + ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); + if spatial_kind == SpatialSpaceViewKind::ThreeD { + ui.label(format!("z [{} - {}]", format_f32(min.z), format_f32(max.z),)); + } + }); + } - re_ui - .checkbox(ui, &mut self.state_3d.show_axes, "Show origin axes") - .on_hover_text("Show X-Y-Z axes"); - re_ui - .checkbox(ui, &mut self.state_3d.show_bbox, "Show bounding box") - .on_hover_text("Show the current scene bounding box"); - re_ui - .checkbox( - ui, - &mut self.state_3d.show_accumulated_bbox, - "Show accumulated bounding box", - ) - .on_hover_text( - "Show bounding box accumulated over all rendered frames", - ); - }); - ui.end_row(); - } + pub fn default_size_ui(&mut self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { + let auto_size_world = + auto_size_world_heuristic(&self.bounding_boxes.accumulated, self.scene_num_primitives); - ctx.re_ui - .grid_left_hand_label(ui, "Bounding box") - .on_hover_text( - "The bounding box encompassing all Entities in the view right now", + ctx.re_ui.grid_left_hand_label(ui, "Default size"); + ui.vertical(|ui| { + ui.horizontal(|ui| { + ui.push_id("points", |ui| { + size_ui( + ui, + 2.0, + auto_size_world, + &mut self.auto_size_config.point_radius, ); - ui.vertical(|ui| { - ui.style_mut().wrap = Some(false); - let BoundingBox { min, max } = self.bounding_boxes.current; - ui.label(format!("x [{} - {}]", format_f32(min.x), format_f32(max.x),)); - ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); - if spatial_kind == SpatialSpaceViewKind::ThreeD { - ui.label(format!("z [{} - {}]", format_f32(min.z), format_f32(max.z),)); - } }); - ui.end_row(); + ui.label("Point radius") + .on_hover_text("Point radius used whenever not explicitly specified"); }); + ui.horizontal(|ui| { + ui.push_id("lines", |ui| { + size_ui( + ui, + 1.5, + auto_size_world, + &mut self.auto_size_config.line_radius, + ); + ui.label("Line radius") + .on_hover_text("Line radius used whenever not explicitly specified"); + }); + }); + }); + ui.end_row(); } // Say the name out loud. It is fun! - fn view_eye_ui( + pub fn view_eye_ui( &mut self, re_ui: &re_ui::ReUi, ui: &mut egui::Ui, @@ -816,7 +741,7 @@ fn hit_ui(ui: &mut egui::Ui, hit: &crate::picking::PickingRayHit) { } } -fn format_vector(v: glam::Vec3) -> String { +pub fn format_vector(v: glam::Vec3) -> String { use glam::Vec3; if v == Vec3::X { diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 6ae09b5ad81d..2aa7a9cec49f 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -6,11 +6,14 @@ use web_time::Instant; use re_log_types::EntityPath; use re_renderer::{ view_builder::{Projection, TargetConfiguration, ViewBuilder}, - LineDrawableBuilder, Size, + LineDrawableBuilder, QueueableDrawData, Size, }; -use re_space_view::controls::{ - RuntimeModifiers, DRAG_PAN3D_BUTTON, RESET_VIEW_BUTTON_TEXT, ROLL_MOUSE, ROLL_MOUSE_ALT, - ROLL_MOUSE_MODIFIER, ROTATE3D_BUTTON, SPEED_UP_3D_MODIFIER, TRACKED_OBJECT_RESTORE_KEY, +use re_space_view::{ + controls::{ + RuntimeModifiers, DRAG_PAN3D_BUTTON, RESET_VIEW_BUTTON_TEXT, ROLL_MOUSE, ROLL_MOUSE_ALT, + ROLL_MOUSE_MODIFIER, ROTATE3D_BUTTON, SPEED_UP_3D_MODIFIER, TRACKED_OBJECT_RESTORE_KEY, + }, + query_space_view_sub_archetype_or_default, }; use re_types::{components::ViewCoordinates, view_coordinates::SignedAxis3}; use re_viewer_context::{ @@ -663,14 +666,15 @@ pub fn view_3d( // Commit ui induced lines. view_builder.queue_draw(line_builder.into_draw_data()?); - // Composite viewbuilder into egui. - view_builder.queue_draw(re_renderer::renderer::GenericSkyboxDrawData::new( - ctx.render_ctx, - )); + let (background_drawable, clear_color) = configure_background(ctx, query); + if let Some(background_drawable) = background_drawable { + view_builder.queue_draw(background_drawable); + } + ui.painter().add(gpu_bridge::new_renderer_callback( view_builder, rect, - re_renderer::Rgba::TRANSPARENT, + clear_color, )); // Add egui driven labels on top of re_renderer content. @@ -680,6 +684,57 @@ pub fn view_3d( Ok(()) } +fn configure_background( + ctx: &ViewerContext<'_>, + query: &ViewQuery<'_>, +) -> (Option, re_renderer::Rgba) { + use re_renderer::renderer; + use re_types::blueprint::{archetypes::Background3D, components::Background3DKind}; + + let blueprint_db = ctx.store_context.blueprint; + let blueprint_query = ctx.blueprint_query; + let ( + Background3D { + kind, + color: solid_color, + }, + _, + ) = query_space_view_sub_archetype_or_default::( + query.space_view_id, + blueprint_db, + blueprint_query, + ); + + match kind { + Background3DKind::GradientDark => ( + Some( + renderer::GenericSkyboxDrawData::new( + ctx.render_ctx, + renderer::GenericSkyboxType::GradientDark, + ) + .into(), + ), + re_renderer::Rgba::TRANSPARENT, // All zero is slightly faster to clear usually. + ), + + Background3DKind::GradientBright => ( + Some( + renderer::GenericSkyboxDrawData::new( + ctx.render_ctx, + renderer::GenericSkyboxType::GradientBright, + ) + .into(), + ), + re_renderer::Rgba::TRANSPARENT, // All zero is slightly faster to clear usually. + ), + + Background3DKind::SolidColor => ( + None, + solid_color.unwrap_or(Background3D::DEFAULT_COLOR).into(), + ), + } +} + /// Show center of orbit camera when interacting with camera (it's quite helpful). fn show_orbit_eye_center( egui_ctx: &egui::Context, diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index d4613676c074..0cf284a99838 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -1,6 +1,7 @@ include "./blueprint/components/active_tab.fbs"; include "./blueprint/components/auto_layout.fbs"; include "./blueprint/components/auto_space_views.fbs"; +include "./blueprint/components/background_3d_kind.fbs"; include "./blueprint/components/column_share.fbs"; include "./blueprint/components/container_kind.fbs"; include "./blueprint/components/corner_2d.fbs"; @@ -19,6 +20,7 @@ include "./blueprint/components/space_view_origin.fbs"; include "./blueprint/components/viewer_recommendation_hash.fbs"; include "./blueprint/components/visible.fbs"; +include "./blueprint/archetypes/background_3d.fbs"; include "./blueprint/archetypes/container_blueprint.fbs"; include "./blueprint/archetypes/space_view_blueprint.fbs"; include "./blueprint/archetypes/space_view_contents.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs new file mode 100644 index 000000000000..6f50b47a5b30 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs @@ -0,0 +1,29 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.archetypes; + + +// --- + +/// Configuration for the background of the 3D space view. +table Background3D ( + "attr.rerun.scope": "blueprint", + "attr.docs.unreleased" +) { + // --- Required --- + + /// The type of the background. Defaults to DirectionalGradient + kind: rerun.blueprint.components.Background3DKind ("attr.rerun.component_required", order: 1000); + + // --- Optional --- + + /// Color used for Background3DKind.SolidColor. + /// + /// Defaults to White. + color: rerun.components.Color ("attr.rerun.component_optional", nullable, order: 2000); +} diff --git a/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs b/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs new file mode 100644 index 000000000000..092a71bf0b5c --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs @@ -0,0 +1,24 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.components; + + +/// The type of the background in 3D Space Views. +enum Background3DKind: byte ( + "attr.rerun.scope": "blueprint", + "attr.docs.unreleased" +) { + /// Gradient depending on the direction of the view, dark theme. + GradientDark (default), + + /// Gradient depending on the direction of the view, bright theme. + GradientBright, + + /// Simple uniform color. + SolidColor, +} diff --git a/crates/re_types/src/blueprint/archetypes/.gitattributes b/crates/re_types/src/blueprint/archetypes/.gitattributes index 37ee5616526f..4095717515a0 100644 --- a/crates/re_types/src/blueprint/archetypes/.gitattributes +++ b/crates/re_types/src/blueprint/archetypes/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +background3d.rs linguist-generated=true mod.rs linguist-generated=true plot_legend.rs linguist-generated=true scalar_axis.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/archetypes/background3d.rs b/crates/re_types/src/blueprint/archetypes/background3d.rs new file mode 100644 index 000000000000..45778c7c55fc --- /dev/null +++ b/crates/re_types/src/blueprint/archetypes/background3d.rs @@ -0,0 +1,185 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Configuration for the background of the 3D space view. +#[derive(Clone, Debug)] +pub struct Background3D { + /// The type of the background. Defaults to DirectionalGradient + pub kind: crate::blueprint::components::Background3DKind, + + /// Color used for Background3DKind.SolidColor. + /// + /// Defaults to White. + pub color: Option, +} + +impl ::re_types_core::SizeBytes for Background3D { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.kind.heap_size_bytes() + self.color.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + && >::is_pod() + } +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.Background3DKind".into()]); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.Background3DIndicator".into()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.components.Color".into(), + "rerun.components.InstanceKey".into(), + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.Background3DKind".into(), + "rerun.blueprint.components.Background3DIndicator".into(), + "rerun.components.Color".into(), + "rerun.components.InstanceKey".into(), + ] + }); + +impl Background3D { + pub const NUM_COMPONENTS: usize = 4usize; +} + +/// Indicator component for the [`Background3D`] [`::re_types_core::Archetype`] +pub type Background3DIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for Background3D { + type Indicator = Background3DIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.Background3D".into() + } + + #[inline] + fn indicator() -> MaybeOwnedComponentBatch<'static> { + static INDICATOR: Background3DIndicator = Background3DIndicator::DEFAULT; + MaybeOwnedComponentBatch::Ref(&INDICATOR) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let kind = { + let array = arrays_by_name + .get("rerun.blueprint.components.Background3DKind") + .ok_or_else(DeserializationError::missing_data) + .with_context("rerun.blueprint.archetypes.Background3D#kind")?; + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.Background3D#kind")? + .into_iter() + .next() + .flatten() + .ok_or_else(DeserializationError::missing_data) + .with_context("rerun.blueprint.archetypes.Background3D#kind")? + }; + let color = if let Some(array) = arrays_by_name.get("rerun.components.Color") { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.Background3D#color")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { kind, color }) + } +} + +impl ::re_types_core::AsComponents for Background3D { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + Some((&self.kind as &dyn ComponentBatch).into()), + self.color + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch).into()), + ] + .into_iter() + .flatten() + .collect() + } + + #[inline] + fn num_instances(&self) -> usize { + 1 + } +} + +impl Background3D { + pub fn new(kind: impl Into) -> Self { + Self { + kind: kind.into(), + color: None, + } + } + + #[inline] + pub fn with_color(mut self, color: impl Into) -> Self { + self.color = Some(color.into()); + self + } +} diff --git a/crates/re_types/src/blueprint/archetypes/background3d_ext.rs b/crates/re_types/src/blueprint/archetypes/background3d_ext.rs new file mode 100644 index 000000000000..14daf0283ed1 --- /dev/null +++ b/crates/re_types/src/blueprint/archetypes/background3d_ext.rs @@ -0,0 +1,17 @@ +use crate::{blueprint::components::Background3DKind, components::Color}; + +use super::Background3D; + +impl Background3D { + pub const DEFAULT_COLOR: Color = Color::WHITE; +} + +impl Default for Background3D { + #[inline] + fn default() -> Self { + Self { + kind: Background3DKind::default(), + color: Some(Background3D::DEFAULT_COLOR), + } + } +} diff --git a/crates/re_types/src/blueprint/archetypes/mod.rs b/crates/re_types/src/blueprint/archetypes/mod.rs index 2c27bb1c6cea..2b251ddec081 100644 --- a/crates/re_types/src/blueprint/archetypes/mod.rs +++ b/crates/re_types/src/blueprint/archetypes/mod.rs @@ -1,10 +1,13 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +mod background3d; +mod background3d_ext; mod plot_legend; mod scalar_axis; mod space_view_blueprint; mod space_view_contents; +pub use self::background3d::Background3D; pub use self::plot_legend::PlotLegend; pub use self::scalar_axis::ScalarAxis; pub use self::space_view_blueprint::SpaceViewBlueprint; diff --git a/crates/re_types/src/blueprint/components/.gitattributes b/crates/re_types/src/blueprint/components/.gitattributes index 1c53f8775af7..ced2ceabb002 100644 --- a/crates/re_types/src/blueprint/components/.gitattributes +++ b/crates/re_types/src/blueprint/components/.gitattributes @@ -2,6 +2,7 @@ .gitattributes linguist-generated=true active_tab.rs linguist-generated=true +background3d_kind.rs linguist-generated=true column_share.rs linguist-generated=true corner2d.rs linguist-generated=true included_content.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/components/background3d_kind.rs b/crates/re_types/src/blueprint/components/background3d_kind.rs new file mode 100644 index 000000000000..f2bae7c2de6f --- /dev/null +++ b/crates/re_types/src/blueprint/components/background3d_kind.rs @@ -0,0 +1,167 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: The type of the background in 3D Space Views. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +pub enum Background3DKind { + /// Gradient depending on the direction of the view, dark theme. + #[default] + GradientDark = 1, + + /// Gradient depending on the direction of the view, bright theme. + GradientBright = 2, + + /// Simple uniform color. + SolidColor = 3, +} + +impl Background3DKind { + /// All the different enum variants. + pub const ALL: [Self; 3] = [Self::GradientDark, Self::GradientBright, Self::SolidColor]; +} + +impl ::re_types_core::SizeBytes for Background3DKind { + #[inline] + fn heap_size_bytes(&self) -> u64 { + 0 + } + + #[inline] + fn is_pod() -> bool { + true + } +} + +impl std::fmt::Display for Background3DKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::GradientDark => write!(f, "GradientDark"), + Self::GradientBright => write!(f, "GradientBright"), + Self::SolidColor => write!(f, "SolidColor"), + } + } +} + +::re_types_core::macros::impl_into_cow!(Background3DKind); + +impl ::re_types_core::Loggable for Background3DKind { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.components.Background3DKind".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Union( + std::sync::Arc::new(vec![ + Field::new("_null_markers", DataType::Null, true), + Field::new("GradientDark", DataType::Null, true), + Field::new("GradientBright", DataType::Null, true), + Field::new("SolidColor", DataType::Null, true), + ]), + Some(std::sync::Arc::new(vec![0i32, 1i32, 2i32, 3i32])), + UnionMode::Sparse, + ) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let data: Vec<_> = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + datum + }) + .collect(); + let num_variants = 3usize; + let types = data + .iter() + .map(|a| match a.as_deref() { + None => 0, + Some(value) => *value as i8, + }) + .collect(); + let fields: Vec<_> = + std::iter::repeat(NullArray::new(DataType::Null, data.len()).boxed()) + .take(1 + num_variants) + .collect(); + UnionArray::new( + ::arrow_datatype(), + types, + fields, + None, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok({ + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.blueprint.components.Background3DKind")?; + let arrow_data_types = arrow_data.types(); + arrow_data_types + .iter() + .map(|typ| match typ { + 0 => Ok(None), + 1 => Ok(Some(Background3DKind::GradientDark)), + 2 => Ok(Some(Background3DKind::GradientBright)), + 3 => Ok(Some(Background3DKind::SolidColor)), + _ => Err(DeserializationError::missing_union_arm( + Self::arrow_datatype(), + "", + *typ as _, + )), + }) + .collect::>>() + .with_context("rerun.blueprint.components.Background3DKind")? + }) + } +} diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index f29b4819a347..f9472feaf086 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -1,6 +1,7 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs mod active_tab; +mod background3d_kind; mod column_share; mod corner2d; mod corner2d_ext; @@ -14,6 +15,7 @@ mod viewer_recommendation_hash; mod visible; pub use self::active_tab::ActiveTab; +pub use self::background3d_kind::Background3DKind; pub use self::column_share::ColumnShare; pub use self::corner2d::Corner2D; pub use self::included_content::IncludedContent; diff --git a/crates/re_types/src/components/color_ext.rs b/crates/re_types/src/components/color_ext.rs index 1df6c6b5c25f..0f7e52c0410c 100644 --- a/crates/re_types/src/components/color_ext.rs +++ b/crates/re_types/src/components/color_ext.rs @@ -1,6 +1,10 @@ use super::Color; impl Color { + pub const BLACK: Self = Self(crate::datatypes::Rgba32::BLACK); + pub const WHITE: Self = Self(crate::datatypes::Rgba32::WHITE); + pub const TRANSPARENT: Self = Self(crate::datatypes::Rgba32::TRANSPARENT); + #[inline] pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { Self::from([r, g, b, 255]) diff --git a/crates/re_types/src/datatypes/rgba32_ext.rs b/crates/re_types/src/datatypes/rgba32_ext.rs index da1594148e85..674e850475ae 100644 --- a/crates/re_types/src/datatypes/rgba32_ext.rs +++ b/crates/re_types/src/datatypes/rgba32_ext.rs @@ -1,7 +1,9 @@ use super::Rgba32; impl Rgba32 { + pub const BLACK: Self = Self::from_rgb(0, 0, 0); pub const WHITE: Self = Self::from_rgb(255, 255, 255); + pub const TRANSPARENT: Self = Self::from_unmultiplied_rgba(0, 0, 0, 0); #[inline] pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self { @@ -88,3 +90,10 @@ impl From for Rgba32 { val.to_srgba_unmultiplied().into() } } + +#[cfg(feature = "ecolor")] +impl From for Rgba32 { + fn from(val: ecolor::Color32) -> Self { + val.to_srgba_unmultiplied().into() + } +} diff --git a/crates/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/re_viewer/src/blueprint/validation_gen/mod.rs index cc7e7cb98c24..b933e95e29c0 100644 --- a/crates/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/re_viewer/src/blueprint/validation_gen/mod.rs @@ -4,6 +4,7 @@ pub use crate::blueprint::components::PanelView; pub use re_entity_db::blueprint::components::EntityPropertiesComponent; use re_entity_db::EntityDb; pub use re_types::blueprint::components::ActiveTab; +pub use re_types::blueprint::components::Background3DKind; pub use re_types::blueprint::components::ColumnShare; pub use re_types::blueprint::components::Corner2D; pub use re_types::blueprint::components::IncludedContent; @@ -29,6 +30,7 @@ pub fn is_valid_blueprint(blueprint: &EntityDb) -> bool { validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) + && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index 3b653492a605..238fc9ef64cd 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -2,6 +2,7 @@ #pragma once +#include "blueprint/archetypes/background3d.hpp" #include "blueprint/archetypes/container_blueprint.hpp" #include "blueprint/archetypes/plot_legend.hpp" #include "blueprint/archetypes/scalar_axis.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index 343a9685d084..6862e81c32db 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -1,6 +1,8 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +background3d.cpp linguist-generated=true +background3d.hpp linguist-generated=true container_blueprint.cpp linguist-generated=true container_blueprint.hpp linguist-generated=true plot_legend.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background3d.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/background3d.cpp new file mode 100644 index 000000000000..989797dbe049 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background3d.cpp @@ -0,0 +1,38 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs". + +#include "background3d.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const blueprint::archetypes::Background3D& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(3); + + { + auto result = DataCell::from_loggable(archetype.kind); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.color.has_value()) { + auto result = DataCell::from_loggable(archetype.color.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = Background3D::IndicatorComponent(); + auto result = DataCell::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp new file mode 100644 index 000000000000..e1e97d9b85dd --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp @@ -0,0 +1,74 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs". + +#pragma once + +#include "../../blueprint/components/background3d_kind.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../components/color.hpp" +#include "../../data_cell.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Configuration for the background of the 3D space view. + struct Background3D { + /// The type of the background. Defaults to DirectionalGradient + rerun::blueprint::components::Background3DKind kind; + + /// Color used for Background3DKind.SolidColor. + /// + /// Defaults to White. + std::optional color; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.Background3DIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + Background3D() = default; + Background3D(Background3D&& other) = default; + + explicit Background3D(rerun::blueprint::components::Background3DKind _kind) + : kind(std::move(_kind)) {} + + /// Color used for Background3DKind.SolidColor. + /// + /// Defaults to White. + Background3D with_color(rerun::components::Color _color) && { + color = std::move(_color); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// Returns the number of primary instances of this archetype. + size_t num_instances() const { + return 1; + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::Background3D& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index 8fe7b4745f1a..5971ebeec9fc 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -5,6 +5,7 @@ #include "blueprint/components/active_tab.hpp" #include "blueprint/components/auto_layout.hpp" #include "blueprint/components/auto_space_views.hpp" +#include "blueprint/components/background3d_kind.hpp" #include "blueprint/components/column_share.hpp" #include "blueprint/components/container_kind.hpp" #include "blueprint/components/corner2d.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index aebedc0c9630..1890d3618645 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -7,6 +7,8 @@ auto_layout.cpp linguist-generated=true auto_layout.hpp linguist-generated=true auto_space_views.cpp linguist-generated=true auto_space_views.hpp linguist-generated=true +background3d_kind.cpp linguist-generated=true +background3d_kind.hpp linguist-generated=true column_share.cpp linguist-generated=true column_share.hpp linguist-generated=true container_kind.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp new file mode 100644 index 000000000000..465e5963c081 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp @@ -0,0 +1,66 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs". + +#include "background3d_kind.hpp" + +#include +#include + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = arrow::sparse_union({ + arrow::field("_null_markers", arrow::null(), true, nullptr), + arrow::field("GradientDark", arrow::null(), false), + arrow::field("GradientBright", arrow::null(), false), + arrow::field("SolidColor", arrow::null(), false), + }); + return datatype; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::SparseUnionBuilder* builder, const blueprint::components::Background3DKind* elements, + size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + ARROW_RETURN_NOT_OK(builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + const auto variant = elements[elem_idx]; + ARROW_RETURN_NOT_OK(builder->Append(static_cast(variant))); + } + + return Error::ok(); + } + + Result> + Loggable::to_arrow( + const blueprint::components::Background3DKind* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK( + Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + ) + ); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp new file mode 100644 index 000000000000..41c1235f6537 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp @@ -0,0 +1,55 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs". + +#pragma once + +#include "../../result.hpp" + +#include +#include + +namespace arrow { + class Array; + class DataType; + class SparseUnionBuilder; +} // namespace arrow + +namespace rerun::blueprint::components { + /// **Component**: The type of the background in 3D Space Views. + enum class Background3DKind : uint8_t { + + /// Gradient depending on the direction of the view, dark theme. + GradientDark = 1, + + /// Gradient depending on the direction of the view, bright theme. + GradientBright = 2, + + /// Simple uniform color. + SolidColor = 3, + }; +} // namespace rerun::blueprint::components + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.Background3DKind"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::SparseUnionBuilder* builder, + const blueprint::components::Background3DKind* elements, size_t num_elements + ); + + /// Serializes an array of `rerun::blueprint:: components::Background3DKind` into an arrow array. + static Result> to_arrow( + const blueprint::components::Background3DKind* instances, size_t num_instances + ); + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index be9c8652636c..4d0dbb01bc00 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -2,6 +2,7 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true +background3d.py linguist-generated=true container_blueprint.py linguist-generated=true plot_legend.py linguist-generated=true scalar_axis.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py index 412a529a9b53..854c4a7398c2 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .background3d import Background3D from .container_blueprint import ContainerBlueprint from .plot_legend import PlotLegend from .scalar_axis import ScalarAxis @@ -10,6 +11,7 @@ from .viewport_blueprint import ViewportBlueprint __all__ = [ + "Background3D", "ContainerBlueprint", "PlotLegend", "ScalarAxis", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py new file mode 100644 index 000000000000..056c5c413973 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py @@ -0,0 +1,81 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs". + +# You can extend this class by creating a "Background3DExt" class in "background3d_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ... import components, datatypes +from ..._baseclasses import Archetype +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + +__all__ = ["Background3D"] + + +@define(str=False, repr=False, init=False) +class Background3D(Archetype): + """**Archetype**: Configuration for the background of the 3D space view.""" + + def __init__( + self: Any, kind: blueprint_components.Background3DKindLike, *, color: datatypes.Rgba32Like | None = None + ): + """ + Create a new instance of the Background3D archetype. + + Parameters + ---------- + kind: + The type of the background. Defaults to DirectionalGradient + color: + Color used for Background3DKind.SolidColor. + + Defaults to White. + + """ + + # You can define your own __init__ function as a member of Background3DExt in background3d_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(kind=kind, color=color) + return + self.__attrs_clear__() + + 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] + ) + + @classmethod + def _clear(cls) -> Background3D: + """Produce an empty Background3D, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + kind: blueprint_components.Background3DKindBatch = field( + metadata={"component": "required"}, + converter=blueprint_components.Background3DKindBatch._required, # type: ignore[misc] + ) + # The type of the background. Defaults to DirectionalGradient + # + # (Docstring intentionally commented out to hide this field from the docs) + + color: components.ColorBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=components.ColorBatch._optional, # type: ignore[misc] + ) + # Color used for Background3DKind.SolidColor. + # + # Defaults to White. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index 7b5b77705d5a..ed71ab812d53 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -5,6 +5,7 @@ __init__.py linguist-generated=true active_tab.py linguist-generated=true auto_layout.py linguist-generated=true auto_space_views.py linguist-generated=true +background3d_kind.py linguist-generated=true column_share.py linguist-generated=true container_kind.py linguist-generated=true corner2d.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index f0eda9f5563b..5ba044b04cbc 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -11,6 +11,13 @@ AutoSpaceViewsLike, AutoSpaceViewsType, ) +from .background3d_kind import ( + Background3DKind, + Background3DKindArrayLike, + Background3DKindBatch, + Background3DKindLike, + Background3DKindType, +) from .column_share import ColumnShare, ColumnShareArrayLike, ColumnShareBatch, ColumnShareLike, ColumnShareType from .container_kind import ( ContainerKind, @@ -65,6 +72,11 @@ "AutoSpaceViewsBatch", "AutoSpaceViewsLike", "AutoSpaceViewsType", + "Background3DKind", + "Background3DKindArrayLike", + "Background3DKindBatch", + "Background3DKindLike", + "Background3DKindType", "ColumnShare", "ColumnShareArrayLike", "ColumnShareBatch", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py b/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py new file mode 100644 index 000000000000..89cb07f3035a --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py @@ -0,0 +1,103 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs". + +# You can extend this class by creating a "Background3DKindExt" class in "background3d_kind_ext.py". + +from __future__ import annotations + +from typing import Sequence, Union + +import pyarrow as pa + +from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin + +__all__ = [ + "Background3DKind", + "Background3DKindArrayLike", + "Background3DKindBatch", + "Background3DKindLike", + "Background3DKindType", +] + + +from enum import Enum + + +class Background3DKind(Enum): + """**Component**: The type of the background in 3D Space Views.""" + + GradientDark = 1 + """Gradient depending on the direction of the view, dark theme.""" + + GradientBright = 2 + """Gradient depending on the direction of the view, bright theme.""" + + SolidColor = 3 + """Simple uniform color.""" + + +Background3DKindLike = Union[Background3DKind, str] +Background3DKindArrayLike = Union[Background3DKindLike, Sequence[Background3DKindLike]] + + +class Background3DKindType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.components.Background3DKind" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("GradientDark", pa.null(), nullable=True, metadata={}), + pa.field("GradientBright", pa.null(), nullable=True, metadata={}), + pa.field("SolidColor", pa.null(), nullable=True, metadata={}), + ] + ), + self._TYPE_NAME, + ) + + +class Background3DKindBatch(BaseBatch[Background3DKindArrayLike], ComponentBatchMixin): + _ARROW_TYPE = Background3DKindType() + + @staticmethod + def _native_to_pa_array(data: Background3DKindArrayLike, data_type: pa.DataType) -> pa.Array: + if isinstance(data, (Background3DKind, int, str)): + data = [data] + + types: list[int] = [] + + for value in data: + if value is None: + types.append(0) + elif isinstance(value, Background3DKind): + types.append(value.value) # Actual enum value + elif isinstance(value, int): + types.append(value) # By number + elif isinstance(value, str): + if hasattr(Background3DKind, value): + types.append(Background3DKind[value].value) # fast path + elif value.lower() == "gradientdark": + types.append(Background3DKind.GradientDark.value) + elif value.lower() == "gradientbright": + types.append(Background3DKind.GradientBright.value) + elif value.lower() == "solidcolor": + types.append(Background3DKind.SolidColor.value) + else: + raise ValueError(f"Unknown Background3DKind kind: {value}") + else: + raise ValueError(f"Unknown Background3DKind kind: {value}") + + buffers = [ + None, + pa.array(types, type=pa.int8()).buffers()[1], + ] + children = (1 + 3) * [pa.nulls(len(data))] + + return pa.UnionArray.from_buffers( + type=data_type, + length=len(data), + buffers=buffers, + children=children, + ) From 149a07c7cbe298b465b8a30aed8888ed0323f8fa Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 12 Mar 2024 12:47:33 +0100 Subject: [PATCH 004/508] Fix typos that were on the typo ignore list (#5472) ### What ... how did that happen. Thanks to @ErichDonGubler for pointing out ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5472/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5472/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5472/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5472) - [Docs preview](https://rerun.io/preview/75a4c2c9c033e6910ef2f964f6dca2f5497c8391/docs) - [Examples preview](https://rerun.io/preview/75a4c2c9c033e6910ef2f964f6dca2f5497c8391/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- design/blueprint_store.md | 2 +- docs/cspell.json | 2 -- examples/python/depth_guided_stable_diffusion/README.md | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/design/blueprint_store.md b/design/blueprint_store.md index f81b90845986..e01698bd5c66 100644 --- a/design/blueprint_store.md +++ b/design/blueprint_store.md @@ -137,7 +137,7 @@ As a further simplification, the Blueprint will allow for the direct inclusion o the data-logging APIs entirely for simple use-cases that don't require temporal information. This will be accomplished by allowing `rrb.Data` objects to be constructed from any Rerun-loggable object. -Data that is a *query* from the recording store references an entity path used seprately by the logging APIs: +Data that is a *query* from the recording store references an entity path used separately by the logging APIs: ```python # Log Data for t in range(100): diff --git a/docs/cspell.json b/docs/cspell.json index 48fb691bc72b..d2ece19505a0 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -313,10 +313,8 @@ "sccache", "SCCACHE", "scipy", - "screeshot", "scrollwheel", "segs", - "seprately", "serde", "serialisation", "serialised", diff --git a/examples/python/depth_guided_stable_diffusion/README.md b/examples/python/depth_guided_stable_diffusion/README.md index a8de8c85ae13..815b8c36ea4d 100644 --- a/examples/python/depth_guided_stable_diffusion/README.md +++ b/examples/python/depth_guided_stable_diffusion/README.md @@ -12,7 +12,7 @@ channel = "nightly" - Depth-guided stable diffusion screeshot + Depth-guided stable diffusion screenshot A more elaborate example running Depth Guided Stable Diffusion 2.0. From 593cfd9c6adce9fdc2fae8faab3a7830730b7176 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 12 Mar 2024 13:10:26 +0100 Subject: [PATCH 005/508] Fix size comparison (red CI) (#5474) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5474/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5474/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5474/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5474) - [Docs preview](https://rerun.io/preview/1f43b69488e8e24931db53dbd1abbf78aaa2b731/docs) - [Examples preview](https://rerun.io/preview/1f43b69488e8e24931db53dbd1abbf78aaa2b731/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- scripts/ci/compare.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/ci/compare.py b/scripts/ci/compare.py index fb1508f0575a..24a6dabca2ee 100755 --- a/scripts/ci/compare.py +++ b/scripts/ci/compare.py @@ -116,7 +116,11 @@ def compare( unit = get_unit(min(previous_bytes, current_bytes)) div = get_divisor(unit) - change_pct = ((current - previous) / previous) * 100 + if previous == 0: + change_pct = 100 + else: + change_pct = 100 * (current - previous) / previous + if abs(change_pct) >= threshold_pct: if unit in DIVISORS: change = f"{change_pct:+.2f}%" From b35505edcdc6e9d838784be25c9f7bc564eeacb1 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 12 Mar 2024 12:07:59 -0400 Subject: [PATCH 006/508] Add google colab notebook update to the release instructions (#5478) ### What These haven't been updated since 0.10 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5478/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5478/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5478/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5478) - [Docs preview](https://rerun.io/preview/58c1c2383b8e37b9e3907ed937feb2809d4d6025/docs) - [Examples preview](https://rerun.io/preview/58c1c2383b8e37b9e3907ed937feb2809d4d6025/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fb0594535cee..3404cf7663e0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -191,6 +191,7 @@ jobs: - [ ] Populate the release with the changelog and a nice header video/picture, check `Set as latest release`, then click `Publish release`. - [ ] Make sure the [conda feedstock PR](https://github.com/conda-forge/rerun-sdk-feedstock/pulls) gets merged. This will be created by the `regro-cf-autotick-bot` once the GitHub release is created. + - [ ] Update the [google colab notebooks](https://drive.google.com/drive/folders/0AC0q24MFKh3fUk9PVA) to install this version and re-execute the notebook. - [ ] Tests - [ ] Windows From 5b1a66652329a7f23c35c61bd5ca84c7ff36be36 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 12 Mar 2024 17:50:39 +0100 Subject: [PATCH 007/508] More typo fixes (#5475) * Follow-up to https://github.com/rerun-io/rerun/pull/5472 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5475/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5475/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5475/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5475) - [Docs preview](https://rerun.io/preview/882fd399a1e5f9799ff67c59b7a9536814b2f022/docs) - [Examples preview](https://rerun.io/preview/882fd399a1e5f9799ff67c59b7a9536814b2f022/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .typos.toml | 7 +++++++ CHANGELOG.md | 4 ++-- crates/re_data_store/tests/correctness.rs | 2 +- crates/re_renderer/src/view_builder.rs | 2 +- crates/re_types_builder/src/codegen/python/mod.rs | 2 +- .../re_viewer/data/quick_start_guides/how_does_it_work.md | 2 +- design/batching.md | 2 +- docs/cspell.json | 6 ------ rerun_py/ARCHITECTURE.md | 8 ++++---- rerun_py/tests/unit/test_transform3d.py | 2 +- tests/cpp/roundtrips/image/main.cpp | 2 +- 11 files changed, 20 insertions(+), 19 deletions(-) diff --git a/.typos.toml b/.typos.toml index e2a6b84e7fc6..6622c0ed9e3c 100644 --- a/.typos.toml +++ b/.typos.toml @@ -100,6 +100,7 @@ prologue = "prolog" rancour = "rancor" realise = "realize" recognise = "recognize" +recognised = "recognized" rigour = "rigor" rumour = "rumor" sabre = "saber" @@ -109,8 +110,14 @@ savour = "savor" sceptical = "skeptical" sceptre = "scepter" sepulchre = "sepulcher" +serialisation = "serialization" +serialise = "serialize" +serialised = "serialized" skilful = "skillful" sombre = "somber" +specialisation = "specialization" +specialise = "specialize" +specialised = "specialized" splendour = "splendor" standardise = "standardize" sulphur = "sulfur" diff --git a/CHANGELOG.md b/CHANGELOG.md index 4650607b0df9..ae98ba2eb52b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1670,7 +1670,7 @@ We now host an experimental and unpolished web-viewer at - Stop using infinities in wgsl shaders [#1594](https://github.com/rerun-io/rerun/pull/1594) - Workaround for alpha to coverage state leaking on (Web)GL renderer [#1596](https://github.com/rerun-io/rerun/pull/1596) - Use a patched `wasm-bindgen-cli` with fix for 2GiB bug [#1605](https://github.com/rerun-io/rerun/pull/1605) -- Misc: make example in `log_pinhole` runable [#1609](https://github.com/rerun-io/rerun/pull/1609) (thanks [@Sjouks](https://github.com/Sjouks)!) +- Misc: make example in `log_pinhole` runnable [#1609](https://github.com/rerun-io/rerun/pull/1609) (thanks [@Sjouks](https://github.com/Sjouks)!) - Early-out on zero-sized space-views to prevent crashes [#1623](https://github.com/rerun-io/rerun/pull/1623) - Print our own callstack on panics [#1622](https://github.com/rerun-io/rerun/pull/1622) - Handle ctrl+c to gracefully shutdown the server(s) [#1613](https://github.com/rerun-io/rerun/pull/1613) @@ -1698,7 +1698,7 @@ We now host an experimental and unpolished web-viewer at - Add re_arrow_store profile scopes [#1546](https://github.com/rerun-io/rerun/pull/1546) - datastore: early exit missing components at table level [#1554](https://github.com/rerun-io/rerun/pull/1554) - datastore: track bucket count in store stats & mem panel [#1555](https://github.com/rerun-io/rerun/pull/1555) -- LogDb: dont split on index bucket size [#1558](https://github.com/rerun-io/rerun/pull/1558) +- LogDb: don't split on index bucket size [#1558](https://github.com/rerun-io/rerun/pull/1558) - Introduce a simpler cache dedicated to just decode JPEGs [#1550](https://github.com/rerun-io/rerun/pull/1550) - Implement outlines for points 2d/3d/depth & use them for select & hover in Viewer [#1568](https://github.com/rerun-io/rerun/pull/1568) - Simplify ImageCache [#1551](https://github.com/rerun-io/rerun/pull/1551) diff --git a/crates/re_data_store/tests/correctness.rs b/crates/re_data_store/tests/correctness.rs index a52519d179fc..d1297f9cc565 100644 --- a/crates/re_data_store/tests/correctness.rs +++ b/crates/re_data_store/tests/correctness.rs @@ -356,7 +356,7 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { // bunch of non-existing components { - let components = &["they".into(), "dont".into(), "exist".into()]; + let components = &["does".into(), "not".into(), "exist".into()]; let (_, _, cells) = store .latest_at( &LatestAtQuery::new(timeline_frame_nr, frame40), diff --git a/crates/re_renderer/src/view_builder.rs b/crates/re_renderer/src/view_builder.rs index 59a9358cd24f..92464abd3ac7 100644 --- a/crates/re_renderer/src/view_builder.rs +++ b/crates/re_renderer/src/view_builder.rs @@ -222,7 +222,7 @@ impl ViewBuilder { /// Depth format used for the main target of the view builder. /// - /// [`wgpu::TextureFormat::Depth24Plus`] would be preferable for performance, see [Nvidia's Vulkan dos and dont's](https://developer.nvidia.com/blog/vulkan-dos-donts/). + /// [`wgpu::TextureFormat::Depth24Plus`] would be preferable for performance, see [Nvidia's Vulkan dos and don'ts](https://developer.nvidia.com/blog/vulkan-dos-donts/). /// However, the problem with being "24Plus" is that we no longer know what format we'll actually get, which is a problem e.g. for vertex shader determined depth offsets. /// (This is a real concern - for example on Metal we always get a floating point target with this!) /// [`wgpu::TextureFormat::Depth32Float`] on the other hand is widely supported and has the best possible precision (with reverse infinite z projection which we're already using). diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index 63a4bfe90285..d15afd942e12 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -1292,7 +1292,7 @@ fn quote_array_method_from_obj( return format!("# __array__ can be found in {}", ext_class.file_name); } - // exclude archetypes, objects which dont have a single field, and anything that isn't an numpy + // exclude archetypes, objects which don't have a single field, and anything that isn't an numpy // array or scalar numbers if obj.kind == ObjectKind::Archetype || obj.fields.len() != 1 diff --git a/crates/re_viewer/data/quick_start_guides/how_does_it_work.md b/crates/re_viewer/data/quick_start_guides/how_does_it_work.md index d63c61efe45f..c3c51d3ce830 100644 --- a/crates/re_viewer/data/quick_start_guides/how_does_it_work.md +++ b/crates/re_viewer/data/quick_start_guides/how_does_it_work.md @@ -2,7 +2,7 @@ Rerun's goal is to make handling and visualizing multimodal data streams easy and performant. -Rerun is made of two main building blocks: the SDK and the Viewer. The data provided by the user code is serialised by the SDK and transferred (via a log file, a TCP socket, a WebSocket, etc.) to the Viewer process for visualization. You can learn more about Rerun's operating modes [here](https://www.rerun.io/docs/reference/sdk-operating-modes). +Rerun is made of two main building blocks: the SDK and the Viewer. The data provided by the user code is serialized by the SDK and transferred (via a log file, a TCP socket, a WebSocket, etc.) to the Viewer process for visualization. You can learn more about Rerun's operating modes [here](https://www.rerun.io/docs/reference/sdk-operating-modes). In the example above, the SDK connects via a TCP socket to the viewer. diff --git a/design/batching.md b/design/batching.md index baafd8293a46..973460a5cb64 100644 --- a/design/batching.md +++ b/design/batching.md @@ -850,7 +850,7 @@ Update the store implementation to remove component tables, remove the `get` API Add the required logic/thread/timers/whatever-else in the SDKs to accumulate data and just send it all as many `LogMsg`s (i.e. no batching yet). 1. Implement full-on batching -End-to-end: transport, storage, the whele shebang. +End-to-end: transport, storage, the whole shebang. 1. Sort the batch before sending (`(event_id, entity_path)`) Keep that in its own PR to keep track of the benchmarks. diff --git a/docs/cspell.json b/docs/cspell.json index d2ece19505a0..1816892358b9 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -93,7 +93,6 @@ "docstrings", "Doersch", "Dollár", - "dont", "downsampled", "downscaled", "downscaling", @@ -281,7 +280,6 @@ "realsense", "Rebatch", "rebatching", - "recognised", "rects", "refcount", "refcounted", @@ -302,7 +300,6 @@ "roundtrips", "roym", "rsplit", - "runable", "rustc", "rustdoc", "rustflags", @@ -316,8 +313,6 @@ "scrollwheel", "segs", "serde", - "serialisation", - "serialised", "Shaohui", "Shap", "Shariq", @@ -397,7 +392,6 @@ "werror", "wgpu", "wgsl", - "whele", "WINIT", "Wofk", "Wonka", diff --git a/rerun_py/ARCHITECTURE.md b/rerun_py/ARCHITECTURE.md index db417b7c8431..4d14b5733765 100644 --- a/rerun_py/ARCHITECTURE.md +++ b/rerun_py/ARCHITECTURE.md @@ -59,17 +59,17 @@ The archetype native objects are the primary user-facing API of the Rerun SDK. #### Components -Component's key role is to provide the serialisation of user data into their read-to-log, serialised Arrow array form. As such, a component's Arrow extension array object, and it's `from_similar()` method, play a key role. By convention, components must be structs with one, and exactly one, field. +Component's key role is to provide the serialization of user data into their read-to-log, serialized Arrow array form. As such, a component's Arrow extension array object, and it's `from_similar()` method, play a key role. By convention, components must be structs with one, and exactly one, field. The code generator distinguishes between delegating and non-delegating components Delegating components use a datatype as field type, and their Arrow extension array object delegate its implementation to the corresponding datatype's. As a result, their implementation is very minimal, and forgoes native objects and typing aliases. `Point2D` is an example of delegating component (it delegates to the `Point2D` datatype). -Non-delegating components use a native type as field type, such as a `float` or `int` instead of relying on a separate datatypes. As a result, their implementation much resembles that of datatypes as they must handle data serialisation in addition to their semantic role. In particular, a native object and typing aliases are generated. +Non-delegating components use a native type as field type, such as a `float` or `int` instead of relying on a separate datatypes. As a result, their implementation much resembles that of datatypes as they must handle data serialization in addition to their semantic role. In particular, a native object and typing aliases are generated. #### Datatypes -Datatypes primary concern is modelling well-defined data structures, including a nice user-facing construction API and support for Arrow serialisation. All the object types described in the previous section are thus generated for components. +Datatypes primary concern is modelling well-defined data structures, including a nice user-facing construction API and support for Arrow serialization. All the object types described in the previous section are thus generated for components. Contrary to archetypes and components, datatypes occasionally represent complex data structures, such as `Transform3D`, made of nested structs and unions. The latter, lacking an obvious counterpart in Python, calls for a specific treatment (see below for details). @@ -150,7 +150,7 @@ TODO(ab): Implementing a Pythonic API for a component or datatype sometime require a subtle interplay between various hand-coded overrides and auto-generated methods. The `Color` component is a good illustration: - The `ColorExt.rgba__field_converter_override()` converter flexibly normalizes user input into a `int` RGBA storage. -- The auto-generated `__int__()` method facilitates the conversion of a `Color` instance into a `int`, which is recognised by Numpy array creation functions. +- The auto-generated `__int__()` method facilitates the conversion of a `Color` instance into a `int`, which is recognized by Numpy array creation functions. - The `ColorExt.native_to_pa_array()` exploits these capabilities of the `Color` native object to simplify its implementation (even though, in most cases, the user code will skip using actual `Color` instances). ### Converter must be functions diff --git a/rerun_py/tests/unit/test_transform3d.py b/rerun_py/tests/unit/test_transform3d.py index 9d998ffa49cf..c775c71991ba 100644 --- a/rerun_py/tests/unit/test_transform3d.py +++ b/rerun_py/tests/unit/test_transform3d.py @@ -163,7 +163,7 @@ def test_translation_and_mat3x3_from_parent() -> None: assert not TranslationAndMat3x3(from_parent=False).from_parent -# SERIALISATION TESTS +# SERIALIZATION TESTS # This should cover all acceptable input to the Transform3D archetype diff --git a/tests/cpp/roundtrips/image/main.cpp b/tests/cpp/roundtrips/image/main.cpp index fa8dfaefce5a..dba320811e78 100644 --- a/tests/cpp/roundtrips/image/main.cpp +++ b/tests/cpp/roundtrips/image/main.cpp @@ -5,7 +5,7 @@ #include uint32_t as_uint(float f) { - // Dont do `*reinterpret_cast(&x)` since it breaks strict aliasing rules. + // Don't do `*reinterpret_cast(&x)` since it breaks strict aliasing rules. uint32_t n; memcpy(&n, &f, sizeof(float)); return n; From 1d6274a1b26984568f43d74e0c3a785d5e662b11 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 12 Mar 2024 17:50:49 +0100 Subject: [PATCH 008/508] Use uppercase for "2D" and "3D" (#5476) For consistency, and because it looks much better ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5476/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5476/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5476/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5476) - [Docs preview](https://rerun.io/preview/aec5ee45f90e545612a824d42b4502d8d50e7e8b/docs) - [Examples preview](https://rerun.io/preview/aec5ee45f90e545612a824d42b4502d8d50e7e8b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- CHANGELOG.md | 14 +++++----- .../src/path/entity_path_filter.rs | 4 +-- .../src/allocator/cpu_write_gpu_read_belt.rs | 4 +-- crates/re_renderer/src/depth_offset.rs | 2 +- crates/re_renderer/src/renderer/rectangles.rs | 2 +- .../src/resource_managers/texture_manager.rs | 2 +- crates/re_renderer_examples/2d.rs | 4 +-- crates/re_renderer_examples/Cargo.toml | 4 +-- .../src/space_view_2d.rs | 2 +- .../src/space_view_3d.rs | 4 +-- .../src/spatial_topology.rs | 8 +++--- crates/re_types_builder/src/lib.rs | 4 +-- .../src/components/instance_key_ext.rs | 4 +-- design/blueprint_store.md | 2 +- docs/code-examples/all/line_strip2d_batch.cpp | 2 +- docs/code-examples/all/line_strip2d_batch.py | 2 +- docs/code-examples/all/line_strip2d_batch.rs | 2 +- docs/code-examples/all/line_strip3d_batch.cpp | 2 +- docs/code-examples/all/line_strip3d_batch.py | 2 +- docs/code-examples/all/line_strip3d_batch.rs | 2 +- docs/content/concepts/annotation-context.md | 2 +- docs/content/concepts/entity-path.md | 2 +- .../getting-started/viewer-walkthrough.md | 10 +++---- docs/content/reference/types.md | 2 +- examples/cpp/dna/README.md | 2 +- examples/cpp/incremental_logging/README.md | 2 +- examples/python/arkit_scenes/main.py | 10 +++---- examples/python/dna/README.md | 2 +- examples/python/face_tracking/README.md | 2 +- examples/python/incremental_logging/README.md | 2 +- examples/python/nv12/README.md | 2 +- .../open_photogrammetry_format/README.md | 2 +- examples/python/plots/README.md | 2 +- examples/python/shape_pointe/README.md | 2 +- examples/rust/dna/README.md | 2 +- examples/rust/incremental_logging/README.md | 2 +- .../rerun/datatypes/rotation3d_ext.py | 2 +- .../rerun/datatypes/transform3d_ext.py | 2 +- scripts/lint.py | 8 ++++++ tests/cpp/roundtrips/line_strips2d/main.cpp | 2 +- tests/cpp/roundtrips/points2d/main.cpp | 2 +- .../check_heuristics_mixed_2d_and_3d.py | 12 ++++---- .../check_hover_select_reset.py | 4 +-- .../check_parallelism_caching_reentrancy.py | 28 +++++++++---------- tests/python/roundtrips/line_strips2d/main.py | 2 +- tests/python/roundtrips/points2d/main.py | 2 +- tests/python/test_api/main.py | 2 +- .../rust/roundtrips/line_strips2d/src/main.rs | 2 +- tests/rust/roundtrips/points2d/src/main.rs | 2 +- 49 files changed, 99 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae98ba2eb52b..23faef07585b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -367,7 +367,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Plot legend visibility and position control (part 3): legend UI added for both timeseries and bar charts space views [#4365](https://github.com/rerun-io/rerun/pull/4365) - Improve component data table UI in the selection panel [#4370](https://github.com/rerun-io/rerun/pull/4370) - Add optional color component to BarChart archetype [#4372](https://github.com/rerun-io/rerun/pull/4372) -- Resolve unexpected view-partitioning by only bucket images when creating a new 2d view [#4361](https://github.com/rerun-io/rerun/pull/4361) +- Resolve unexpected view-partitioning by only bucket images when creating a new 2D view [#4361](https://github.com/rerun-io/rerun/pull/4361) - Restore `egui_plot` auto-bounds state after dragging the time cursor in timeseries space views [#4270](https://github.com/rerun-io/rerun/pull/4270) - Make Space View containers selectable and editable [#4403](https://github.com/rerun-io/rerun/pull/4403) - Improve selection and hover behavior of viewport's tabs [#4424](https://github.com/rerun-io/rerun/pull/4424) @@ -807,7 +807,7 @@ Other highlights: - Improve styling of demo header [#3022](https://github.com/rerun-io/rerun/pull/3022) - Implement "Open file" dialog on Web [#3068](https://github.com/rerun-io/rerun/pull/3068) - Show Welcome Screen after closing recording even with `--skip-welcome-screen` [#3035](https://github.com/rerun-io/rerun/pull/3035) -- Fix the 3d space view's tooltip help text [#3132](https://github.com/rerun-io/rerun/pull/3132) +- Fix the 3D space view's tooltip help text [#3132](https://github.com/rerun-io/rerun/pull/3132) - Use `ListItem` in blueprint tree UI [#3118](https://github.com/rerun-io/rerun/pull/3118) - Use `ListItem` in Stream Tree UI [#3153](https://github.com/rerun-io/rerun/pull/3153) - Limit the size of component tooltips with `UiVerbosity::Reduced` [#3171](https://github.com/rerun-io/rerun/pull/3171) @@ -1080,7 +1080,7 @@ for use-cases like real-time video feeds. [#2220](https://github.com/rerun-io/re - Move StoreHub out of the Viewer during Update [#2330](https://github.com/rerun-io/rerun/pull/2330) - Expand CommandSender to support SystemCommand [#2344](https://github.com/rerun-io/rerun/pull/2344) - Use `camino` crate for UTF8 paths in `re_types_builder` [#2637](https://github.com/rerun-io/rerun/pull/2637) -- Separate 2d & 3d spaceview classes, removal of `ViewCategory`, `SpaceViewClass` driven spawn heuristics [#2716](https://github.com/rerun-io/rerun/pull/2716) +- Separate 2D & 3D spaceview classes, removal of `ViewCategory`, `SpaceViewClass` driven spawn heuristics [#2716](https://github.com/rerun-io/rerun/pull/2716) - Move object property heuristics to heuristics.rs [#2764](https://github.com/rerun-io/rerun/pull/2764) #### 📦 Dependencies @@ -1290,7 +1290,7 @@ here's a smaller release packed with useful improvements 🎉 #### 🌁 Viewer Improvements - Support projecting 3D entities in 2D views [#2008](https://github.com/rerun-io/rerun/pull/2008) - Set Rerun viewer native app icon using eframe [#1976](https://github.com/rerun-io/rerun/pull/1976) -- Use `alt` key again for rolling camera in 3d views [#2066](https://github.com/rerun-io/rerun/pull/2066) +- Use `alt` key again for rolling camera in 3D views [#2066](https://github.com/rerun-io/rerun/pull/2066) - Show tensors shaped [H, W, 1, 1] as images (and more!) [#2075](https://github.com/rerun-io/rerun/pull/2075) - Show meshes and images with `rerun foo.obj bar.png` [#2060](https://github.com/rerun-io/rerun/pull/2060) - Don't persist blueprints for unknown apps [#2165](https://github.com/rerun-io/rerun/pull/2165) @@ -1682,7 +1682,7 @@ We now host an experimental and unpolished web-viewer at - Fix crash when trying to listen on a taken TCP port [#1650](https://github.com/rerun-io/rerun/pull/1650) - Don't show 2D labels in 3D space views. [#1641](https://github.com/rerun-io/rerun/pull/1641) - Fix Z fighting with improved depth offset math [#1661](https://github.com/rerun-io/rerun/pull/1661) -- Whether a spatial view is 2d or 3d is now reevaluated over time unless picked explicitly [#1660](https://github.com/rerun-io/rerun/pull/1660) +- Whether a spatial view is 2D or 3D is now reevaluated over time unless picked explicitly [#1660](https://github.com/rerun-io/rerun/pull/1660) - Update wgpu to v0.15.3, fixing meshes on Windows Chrome [#1682](https://github.com/rerun-io/rerun/pull/1682) - Fix a bug in the image hover code, causing the wrong RGBA values to be printed [#1690](https://github.com/rerun-io/rerun/pull/1690) - Fix a bug that caused points to be render too large [#1690](https://github.com/rerun-io/rerun/pull/1690) @@ -1700,7 +1700,7 @@ We now host an experimental and unpolished web-viewer at - datastore: track bucket count in store stats & mem panel [#1555](https://github.com/rerun-io/rerun/pull/1555) - LogDb: don't split on index bucket size [#1558](https://github.com/rerun-io/rerun/pull/1558) - Introduce a simpler cache dedicated to just decode JPEGs [#1550](https://github.com/rerun-io/rerun/pull/1550) -- Implement outlines for points 2d/3d/depth & use them for select & hover in Viewer [#1568](https://github.com/rerun-io/rerun/pull/1568) +- Implement outlines for points 2D/3D/depth & use them for select & hover in Viewer [#1568](https://github.com/rerun-io/rerun/pull/1568) - Simplify ImageCache [#1551](https://github.com/rerun-io/rerun/pull/1551) - New time panel density graph [#1557](https://github.com/rerun-io/rerun/pull/1557) - Refactor the Arrow Mesh3D type to use zero-copy Buffers [#1691](https://github.com/rerun-io/rerun/pull/1691) @@ -1855,7 +1855,7 @@ Meanwhile, we did a bunch of improvements to our manual. If you had trouble runn * Python SDK: Add strict mode [#1477](https://github.com/rerun-io/rerun/pull/1477) * OS independent Zoom factor & serialization thereof [#1448](https://github.com/rerun-io/rerun/pull/1448) * Labels for 3D objects have now a color can now be selected & hovered [#1438](https://github.com/rerun-io/rerun/pull/1438) -* Add 2d support for linestrips [#1430](https://github.com/rerun-io/rerun/pull/1430) +* Add 2D support for linestrips [#1430](https://github.com/rerun-io/rerun/pull/1430) * Add signal handler on *nix with troubleshooting and stacktrace [#1340](https://github.com/rerun-io/rerun/pull/1340) * Point users to our troubleshooting page on panic [#1338](https://github.com/rerun-io/rerun/pull/1338) diff --git a/crates/re_log_types/src/path/entity_path_filter.rs b/crates/re_log_types/src/path/entity_path_filter.rs index 557999d0184a..b555d45023a3 100644 --- a/crates/re_log_types/src/path/entity_path_filter.rs +++ b/crates/re_log_types/src/path/entity_path_filter.rs @@ -496,8 +496,8 @@ mod tests { ); for (path, expected) in [ - ("/2d", false), - ("/2d/image", false), + ("/2D", false), + ("/2D/image", false), ("/world", true), ("/world/car", true), ("/world/car/driver", true), diff --git a/crates/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs b/crates/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs index 851fafca16e3..800b2433c4f0 100644 --- a/crates/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs +++ b/crates/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs @@ -235,7 +235,7 @@ where self.unwritten_element_range.end } - /// Copies all so far written data to the first layer of a 2d texture. + /// Copies all so far written data to the first layer of a 2D texture. /// /// Assumes that the buffer consists of as-tightly-packed-as-possible rows of data. /// (taking into account required padding as specified by [`wgpu::COPY_BYTES_PER_ROW_ALIGNMENT`]) @@ -259,7 +259,7 @@ where ) } - /// Copies all so far written data to a rectangle on a single 2d texture layer. + /// Copies all so far written data to a rectangle on a single 2D texture layer. /// /// Assumes that the buffer consists of as-tightly-packed-as-possible rows of data. /// (taking into account required padding as specified by [`wgpu::COPY_BYTES_PER_ROW_ALIGNMENT`]) diff --git a/crates/re_renderer/src/depth_offset.rs b/crates/re_renderer/src/depth_offset.rs index b08ff1e51c19..36e43fca75a8 100644 --- a/crates/re_renderer/src/depth_offset.rs +++ b/crates/re_renderer/src/depth_offset.rs @@ -1,4 +1,4 @@ -/// Depth offset used to resolve z-fighting between 2d primitives. +/// Depth offset used to resolve z-fighting between 2D primitives. /// /// Zero means no offset. /// Higher values push an object towards the viewer, lower away from the viewer. diff --git a/crates/re_renderer/src/renderer/rectangles.rs b/crates/re_renderer/src/renderer/rectangles.rs index d174c5e70cbe..71ad0d80df33 100644 --- a/crates/re_renderer/src/renderer/rectangles.rs +++ b/crates/re_renderer/src/renderer/rectangles.rs @@ -1,4 +1,4 @@ -//! Renderer that makes it easy to draw textured 2d rectangles with transparency +//! Renderer that makes it easy to draw textured 2D rectangles with transparency //! //! Transparency: (TODO(andreas):) //! We're not performing any sorting on transparency yet, so the transparent rectangles pretty much diff --git a/crates/re_renderer/src/resource_managers/texture_manager.rs b/crates/re_renderer/src/resource_managers/texture_manager.rs index ffe1c1939e44..f4323cf58121 100644 --- a/crates/re_renderer/src/resource_managers/texture_manager.rs +++ b/crates/re_renderer/src/resource_managers/texture_manager.rs @@ -75,7 +75,7 @@ impl std::borrow::Borrow for GpuTexture2D { } } -/// Data required to create a texture 2d resource. +/// Data required to create a texture 2D resource. /// /// It is *not* stored along side the resulting texture resource! pub struct Texture2DCreationDesc<'a> { diff --git a/crates/re_renderer_examples/2d.rs b/crates/re_renderer_examples/2d.rs index 46442291f772..a1753b4953cd 100644 --- a/crates/re_renderer_examples/2d.rs +++ b/crates/re_renderer_examples/2d.rs @@ -288,7 +288,7 @@ impl framework::Example for Render2D { .unwrap(); vec![ - // 2d view to the left + // 2D view to the left { let mut view_builder = ViewBuilder::new( re_ctx, @@ -318,7 +318,7 @@ impl framework::Example for Render2D { target_location: splits[0].target_location, } }, - // and 3d view of the same scene to the right + // and 3D view of the same scene to the right { let seconds_since_startup = time.seconds_since_startup(); let camera_rotation_center = screen_size.extend(0.0) * 0.5; diff --git a/crates/re_renderer_examples/Cargo.toml b/crates/re_renderer_examples/Cargo.toml index a60148706844..b591fd196a03 100644 --- a/crates/re_renderer_examples/Cargo.toml +++ b/crates/re_renderer_examples/Cargo.toml @@ -10,8 +10,8 @@ publish = false [features] [[bin]] -name = "2d" -path = "2d.rs" +name = "2d" # NOLINT +path = "2d.rs" # NOLINT [[bin]] name = "depth_cloud" diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index cc75ce856db8..cc391390afbf 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -181,7 +181,7 @@ impl SpaceViewClass for SpatialSpaceView2D { return Vec::new(); } - // Collect just the 2d-relevant entities in this subspace + // Collect just the 2D-relevant entities in this subspace let relevant_entities: IntSet = subspace .entities .iter() diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 53fd96366127..cc389d6ca7fd 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -138,7 +138,7 @@ impl SpaceViewClass for SpatialSpaceView3D { }; } - // All entities in the 3d space are visualizable + everything under pinholes. + // All entities in the 3D space are visualizable + everything under pinholes. let mut entities_in_main_3d_space = primary_space.entities.clone(); let mut entities_under_pinholes = IntSet::::default(); @@ -154,7 +154,7 @@ impl SpaceViewClass for SpatialSpaceView3D { .contains(SubSpaceConnectionFlags::Pinhole) { // Note that for this the connection to the parent is allowed to contain the disconnected flag. - // Entities _at_ pinholes are a special case: we display both 3d and 2d visualizers for them. + // Entities _at_ pinholes are a special case: we display both 3D and 2D visualizers for them. entities_in_main_3d_space.insert(child_space.origin.clone()); entities_under_pinholes.extend(child_space.entities.iter().cloned()); } diff --git a/crates/re_space_view_spatial/src/spatial_topology.rs b/crates/re_space_view_spatial/src/spatial_topology.rs index 2e16990c5270..01bcdb11dcc3 100644 --- a/crates/re_space_view_spatial/src/spatial_topology.rs +++ b/crates/re_space_view_spatial/src/spatial_topology.rs @@ -57,7 +57,7 @@ pub struct SubSpace { /// Note that we this is merely here to speed up queries. /// Instead, we could check if an entity is equal to or a descendent of the /// origin and not equal or descendent of any child space. - /// The problem with that is that it's common for a 3d space to have many 2d spaces as children, + /// The problem with that is that it's common for a 3D space to have many 2D spaces as children, /// which would make this an expensive query. pub entities: IntSet, @@ -91,7 +91,7 @@ pub struct SubSpace { } impl SubSpace { - /// Whether 3d content in this subspace can be displayed. + /// Whether 3D content in this subspace can be displayed. #[inline] pub fn supports_3d_content(&self) -> bool { // Note that we currently do *not* walk up the tree of spaces to check for pinholes. @@ -106,11 +106,11 @@ impl SubSpace { .contains(SubSpaceConnectionFlags::Pinhole) } - /// Whether 2d content in this subspace can be displayed. + /// Whether 2D content in this subspace can be displayed. #[inline] #[allow(clippy::unused_self)] pub fn supports_2d_content(&self) -> bool { - // There's currently no way to prevent a subspace from displaying 2d content. + // There's currently no way to prevent a subspace from displaying 2D content. true } } diff --git a/crates/re_types_builder/src/lib.rs b/crates/re_types_builder/src/lib.rs index d5c8b2283271..0c9f573eabaf 100644 --- a/crates/re_types_builder/src/lib.rs +++ b/crates/re_types_builder/src/lib.rs @@ -692,8 +692,8 @@ pub(crate) fn to_pascal_case(s: &str) -> String { *last = last .replace("uvec", "UVec") .replace("uint", "UInt") - .replace("2d", "2D") - .replace("3d", "3D") + .replace("2d", "2D") // NOLINT + .replace("3d", "3D") // NOLINT .replace("4d", "4D"); *last = rerun_snake.convert(&last); } diff --git a/crates/re_types_core/src/components/instance_key_ext.rs b/crates/re_types_core/src/components/instance_key_ext.rs index 744c5f092e87..7ff7d5085e69 100644 --- a/crates/re_types_core/src/components/instance_key_ext.rs +++ b/crates/re_types_core/src/components/instance_key_ext.rs @@ -36,12 +36,12 @@ impl InstanceKey { self.is_specific().then_some(self) } - /// Creates a new [`InstanceKey`] that identifies a 2d coordinate. + /// Creates a new [`InstanceKey`] that identifies a 2D coordinate. pub fn from_2d_image_coordinate([x, y]: [u32; 2], image_width: u64) -> Self { Self((x as u64) + (y as u64) * image_width) } - /// Retrieves 2d image coordinates (x, y) encoded in an instance key + /// Retrieves 2D image coordinates (x, y) encoded in an instance key pub fn to_2d_image_coordinate(self, image_width: u64) -> [u32; 2] { [(self.0 % image_width) as u32, (self.0 / image_width) as u32] } diff --git a/design/blueprint_store.md b/design/blueprint_store.md index e01698bd5c66..9dc81037d867 100644 --- a/design/blueprint_store.md +++ b/design/blueprint_store.md @@ -247,7 +247,7 @@ The ui components are quite specific for the type of blueprint. Here are a few e * `sizes`: individual sizes of the children * Space view * `children` (data blueprints) - * `category` ("3d", "text", …) + * `category` ("3D", "text", …) * Data group * `children` * Data diff --git a/docs/code-examples/all/line_strip2d_batch.cpp b/docs/code-examples/all/line_strip2d_batch.cpp index 46b4d5bfffb7..91508627b7a6 100644 --- a/docs/code-examples/all/line_strip2d_batch.cpp +++ b/docs/code-examples/all/line_strip2d_batch.cpp @@ -1,4 +1,4 @@ -// Log a batch of 2d line strips. +// Log a batch of 2D line strips. #include diff --git a/docs/code-examples/all/line_strip2d_batch.py b/docs/code-examples/all/line_strip2d_batch.py index f38cc4febfe8..7ff5ab60377f 100644 --- a/docs/code-examples/all/line_strip2d_batch.py +++ b/docs/code-examples/all/line_strip2d_batch.py @@ -1,4 +1,4 @@ -"""Log a batch of 2d line strips.""" +"""Log a batch of 2D line strips.""" import rerun as rr rr.init("rerun_example_line_strip2d_batch", spawn=True) diff --git a/docs/code-examples/all/line_strip2d_batch.rs b/docs/code-examples/all/line_strip2d_batch.rs index 15f255f5cb6d..d44120ae1473 100644 --- a/docs/code-examples/all/line_strip2d_batch.rs +++ b/docs/code-examples/all/line_strip2d_batch.rs @@ -1,4 +1,4 @@ -//! Log a batch of 2d line strips. +//! Log a batch of 2D line strips. fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_line_strip2d_batch").spawn()?; diff --git a/docs/code-examples/all/line_strip3d_batch.cpp b/docs/code-examples/all/line_strip3d_batch.cpp index 1580779b0699..4ed68ef544d5 100644 --- a/docs/code-examples/all/line_strip3d_batch.cpp +++ b/docs/code-examples/all/line_strip3d_batch.cpp @@ -1,4 +1,4 @@ -// Log a batch of 3d line strips. +// Log a batch of 3D line strips. #include diff --git a/docs/code-examples/all/line_strip3d_batch.py b/docs/code-examples/all/line_strip3d_batch.py index b04dff6e6f32..94c96024f82c 100644 --- a/docs/code-examples/all/line_strip3d_batch.py +++ b/docs/code-examples/all/line_strip3d_batch.py @@ -1,4 +1,4 @@ -"""Log a batch of 3d line strips.""" +"""Log a batch of 3D line strips.""" import rerun as rr rr.init("rerun_example_line_strip3d_batch", spawn=True) diff --git a/docs/code-examples/all/line_strip3d_batch.rs b/docs/code-examples/all/line_strip3d_batch.rs index 1bea34022589..42ea0620ef69 100644 --- a/docs/code-examples/all/line_strip3d_batch.rs +++ b/docs/code-examples/all/line_strip3d_batch.rs @@ -1,4 +1,4 @@ -//! Log a batch of 2d line strips. +//! Log a batch of 2D line strips. fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_line_strip3d_batch").spawn()?; diff --git a/docs/content/concepts/annotation-context.md b/docs/content/concepts/annotation-context.md index d8fbac655538..15d93033642c 100644 --- a/docs/content/concepts/annotation-context.md +++ b/docs/content/concepts/annotation-context.md @@ -39,7 +39,7 @@ Just as with labels and colors this allows you to use the same connection inform Keypoints are currently only applicable to 2D and 3D points. - keypoint shown on a 3d skeleton + keypoint shown on a 3D skeleton diff --git a/docs/content/concepts/entity-path.md b/docs/content/concepts/entity-path.md index df08c29a61f9..143aba39d8df 100644 --- a/docs/content/concepts/entity-path.md +++ b/docs/content/concepts/entity-path.md @@ -45,7 +45,7 @@ Any other character should be escaped, including symbols (`\:`, `\$`, …) and w You can an arbitrary unicode code point into an entity path using `\u{262E}`. -So for instance, `world/3d/My\ Image.jpg/detection` is a valid path (note the escaped space!). +So for instance, `world/3D/My\ Image.jpg/detection` is a valid path (note the escaped space!). ⚠️ NOTE: even though entity paths are somewhat analogous to file paths, they are NOT the same. `..` does not mean "parent folder", and you are NOT intended to pass a file path as an entity path (especially not on Windows, which use `\` as a path separator). diff --git a/docs/content/getting-started/viewer-walkthrough.md b/docs/content/getting-started/viewer-walkthrough.md index 324e2dc5e22c..e88b569eb059 100644 --- a/docs/content/getting-started/viewer-walkthrough.md +++ b/docs/content/getting-started/viewer-walkthrough.md @@ -121,9 +121,9 @@ Feel free to move the views around until you are happy with the layout. The space views are where you can see the data that was actually logged. This scene has streams of data for 6 different primitives, also known as [entities](../concepts/entity-component.md): * [images](../reference/types/archetypes/image.md) that were captured from a camera. -* [2d keypoints](../reference/types/archetypes/points2d.md) that were detected and tracked in those images. +* [2D keypoints](../reference/types/archetypes/points2d.md) that were detected and tracked in those images. * a [pinhole](../reference/types/archetypes/pinhole.md) camera model that describes the relationship between 2D and 3D space. -* [3d points](../reference/types/archetypes/points3d.md) that were computed by the COLMAP slam pipeline. +* [3D points](../reference/types/archetypes/points3d.md) that were computed by the COLMAP slam pipeline. * A sequence of [transforms](../reference/types/archetypes/transform3d.md) describing the 3D location of the camera in space. * A [scalar](../reference/types/archetypes/time_series_scalar.md) error metric that was computed by the algorithm for each frame. @@ -152,7 +152,7 @@ corresponding ray projected into the `/ (Spatial)` view. See the section on [Spaces and Transforms](../concepts/spaces-and-transforms.md) for more information on how this linking works. ### Rotate, zoom, and pan -Clicking and dragging the contents of any view will move it. You can rotate 3d views, or pan 2d views and plots. You can +Clicking and dragging the contents of any view will move it. You can rotate 3D views, or pan 2D views and plots. You can also zoom using ctrl+scrollwheel or pinch gestures on a trackpad. Most views can be restored to their default state by double-clicking somewhere in the view. Every view has a "?" icon in the upper right hand corner. You can always mouse over this icon to find out more information about the specific view. @@ -235,7 +235,7 @@ section. Try toggling "visible" on and off and you will see that the points disappear and reappear. Next, click the control labeled "visible history" and drag it to the right to increase the value. As you drag farther you will see more points show up in the view. This is making historical points, from farther back in time visible within the time point of this -view. Because the points are logged in stationary 3d space, aggregating them here gives us a more complete view of the +view. Because the points are logged in stationary 3D space, aggregating them here gives us a more complete view of the car. Leave the visible history with a value of 50. @@ -289,7 +289,7 @@ right corner. Note that even with the timeline collapsed you still have access t ### Reusing what you've learned Finally, use what we covered in the previous section to change the contents of this view. Select the new `camera` view, -then choose "Add/remove entities." Remove the 2d "keypoints" and add in the 3d "points." Note that these points do not +then choose "Add/remove entities." Remove the 2D "keypoints" and add in the 3D "points." Note that these points do not have visible history turned on -- that's because the blueprint is part of the view and not part of the entity. Select the points within this view by clicking on them in the blueprint or the view itself, and then give them visible history as well. When you are done, your view should look like this: diff --git a/docs/content/reference/types.md b/docs/content/reference/types.md index 8dffeadc4e90..b2057e0c9da5 100644 --- a/docs/content/reference/types.md +++ b/docs/content/reference/types.md @@ -12,7 +12,7 @@ For more information on the relationship between **archetypes** and **components on [Entities and Components](../concepts/entity-component.md). ## Spatial **Archetypes** -The spatial archetypes represent 2d and 3d spatial data. These types have some notion of a coordinate system and +The spatial archetypes represent 2D and 3D spatial data. These types have some notion of a coordinate system and generally support spatial transformations. These types can be visualized by 2D and 3D space views. To visualize a 2D entity in a 3D space view it must be under a pinhole transformation. diff --git a/examples/cpp/dna/README.md b/examples/cpp/dna/README.md index 99fcffb5672b..d7d7f44c8efd 100644 --- a/examples/cpp/dna/README.md +++ b/examples/cpp/dna/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/incremental_logging/README.md b/examples/python/incremental_logging/README.md index 0f0de9cfd8f9..0b6e7ef0b668 100644 --- a/examples/python/incremental_logging/README.md +++ b/examples/python/incremental_logging/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/open_photogrammetry_format/README.md b/examples/python/open_photogrammetry_format/README.md index c45dde7387bb..953fce825834 100644 --- a/examples/python/open_photogrammetry_format/README.md +++ b/examples/python/open_photogrammetry_format/README.md @@ -1,6 +1,6 @@ -OpenAI has released two models for text-to-3d generation: Point-E and Shape-E. Both of these methods are fast and interesting but still low fidelity for now. +OpenAI has released two models for text-to-3D generation: Point-E and Shape-E. Both of these methods are fast and interesting but still low fidelity for now. https://vimeo.com/865974160?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=10000:6545 diff --git a/examples/rust/dna/README.md b/examples/rust/dna/README.md index 2c251a2474bc..27ff4016de24 100644 --- a/examples/rust/dna/README.md +++ b/examples/rust/dna/README.md @@ -1,6 +1,6 @@ - [Examples preview](https://rerun.io/preview/9a4aff23ac532eb7bf08cf6aa6cf3d9ce6d8bfd9/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_sdk/src/recording_stream.rs | 20 +- .../archetypes/viewport_blueprint.fbs | 5 +- .../archetypes/viewport_blueprint.rs | 62 +-- crates/re_viewport/src/viewport_blueprint.rs | 7 +- crates/rerun_c/src/lib.rs | 2 +- examples/python/blueprint/main.py | 5 +- .../archetypes/viewport_blueprint.cpp | 4 +- .../archetypes/viewport_blueprint.hpp | 14 +- rerun_py/rerun_sdk/rerun/__init__.py | 23 +- rerun_py/rerun_sdk/rerun/_log.py | 3 + .../rerun_sdk/rerun/blueprint/__init__.py | 15 +- rerun_py/rerun_sdk/rerun/blueprint/api.py | 386 ++++++++++++++++++ .../archetypes/viewport_blueprint.py | 9 +- rerun_py/rerun_sdk/rerun/sinks.py | 30 +- rerun_py/src/python_bridge.rs | 18 +- .../tests/unit/test_viewport_blueprint.py | 2 +- tests/python/blueprint/main.py | 40 ++ 17 files changed, 560 insertions(+), 85 deletions(-) create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/api.py create mode 100644 tests/python/blueprint/main.py diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs index 62f80b81c9f9..c0b1a0cf1cf9 100644 --- a/crates/re_sdk/src/recording_stream.rs +++ b/crates/re_sdk/src/recording_stream.rs @@ -1522,7 +1522,11 @@ impl RecordingStream { /// terms of data durability and ordering. /// See [`Self::set_sink`] for more information. pub fn connect(&self) { - self.connect_opts(crate::default_server_addr(), crate::default_flush_timeout()); + self.connect_opts( + crate::default_server_addr(), + crate::default_flush_timeout(), + None, + ); } /// Swaps the underlying sink for a [`crate::log_sink::TcpSink`] sink pre-configured to use @@ -1539,13 +1543,23 @@ impl RecordingStream { &self, addr: std::net::SocketAddr, flush_timeout: Option, + blueprint: Option>, ) { if forced_sink_path().is_some() { re_log::debug!("Ignored setting new TcpSink since _RERUN_FORCE_SINK is set"); return; } - self.set_sink(Box::new(crate::log_sink::TcpSink::new(addr, flush_timeout))); + let sink = crate::log_sink::TcpSink::new(addr, flush_timeout); + + // If a blueprint was provided, send it first. + if let Some(blueprint) = blueprint { + for msg in blueprint { + sink.send(msg); + } + } + + self.set_sink(Box::new(sink)); } /// Spawns a new Rerun Viewer process from an executable available in PATH, then swaps the @@ -1598,7 +1612,7 @@ impl RecordingStream { spawn(opts)?; - self.connect_opts(opts.connect_addr(), flush_timeout); + self.connect_opts(opts.connect_addr(), flush_timeout, None); Ok(()) } diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs index 8a00279674e7..b87721d45262 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs @@ -15,10 +15,9 @@ table ViewportBlueprint ( ) { // --- Required --- - /// All of the space-views that belong to the viewport. - space_views: [rerun.blueprint.components.IncludedSpaceView] ("attr.rerun.component_required", order: 1000); - // --- Optional --- + /// All of the space-views that belong to the viewport. + space_views: [rerun.blueprint.components.IncludedSpaceView] ("attr.rerun.component_optional", nullable, order: 1000); /// The layout of the space-views root_container: rerun.blueprint.components.RootContainer ("attr.rerun.component_optional", nullable, order: 2500); diff --git a/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs b/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs index b902fbe52da0..1773aae2afe9 100644 --- a/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs +++ b/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; #[derive(Clone, Debug, Default)] pub struct ViewportBlueprint { /// All of the space-views that belong to the viewport. - pub space_views: Vec, + pub space_views: Option>, /// The layout of the space-views pub root_container: Option, @@ -69,7 +69,7 @@ impl ::re_types_core::SizeBytes for ViewportBlueprint { #[inline] fn is_pod() -> bool { - >::is_pod() + >>::is_pod() && >::is_pod() && >::is_pod() && >::is_pod() @@ -78,17 +78,18 @@ impl ::re_types_core::SizeBytes for ViewportBlueprint { } } -static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.IncludedSpaceView".into()]); +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.ViewportBlueprintIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.AutoLayout".into(), "rerun.blueprint.components.AutoSpaceViews".into(), + "rerun.blueprint.components.IncludedSpaceView".into(), "rerun.blueprint.components.RootContainer".into(), "rerun.blueprint.components.SpaceViewMaximized".into(), "rerun.blueprint.components.ViewerRecommendationHash".into(), @@ -99,10 +100,10 @@ static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = once_cell::sync::Lazy::new(|| { [ - "rerun.blueprint.components.IncludedSpaceView".into(), "rerun.blueprint.components.ViewportBlueprintIndicator".into(), "rerun.blueprint.components.AutoLayout".into(), "rerun.blueprint.components.AutoSpaceViews".into(), + "rerun.blueprint.components.IncludedSpaceView".into(), "rerun.blueprint.components.RootContainer".into(), "rerun.blueprint.components.SpaceViewMaximized".into(), "rerun.blueprint.components.ViewerRecommendationHash".into(), @@ -161,17 +162,19 @@ impl ::re_types_core::Archetype for ViewportBlueprint { .into_iter() .map(|(name, array)| (name.full_name(), array)) .collect(); - let space_views = { - let array = arrays_by_name - .get("rerun.blueprint.components.IncludedSpaceView") - .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.blueprint.archetypes.ViewportBlueprint#space_views")?; - ::from_arrow_opt(&**array) - .with_context("rerun.blueprint.archetypes.ViewportBlueprint#space_views")? - .into_iter() - .map(|v| v.ok_or_else(DeserializationError::missing_data)) - .collect::>>() - .with_context("rerun.blueprint.archetypes.ViewportBlueprint#space_views")? + let space_views = if let Some(array) = + arrays_by_name.get("rerun.blueprint.components.IncludedSpaceView") + { + Some({ + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.ViewportBlueprint#space_views")? + .into_iter() + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .collect::>>() + .with_context("rerun.blueprint.archetypes.ViewportBlueprint#space_views")? + }) + } else { + None }; let root_container = if let Some(array) = arrays_by_name.get("rerun.blueprint.components.RootContainer") { @@ -249,7 +252,9 @@ impl ::re_types_core::AsComponents for ViewportBlueprint { use ::re_types_core::Archetype as _; [ Some(Self::indicator()), - Some((&self.space_views as &dyn ComponentBatch).into()), + self.space_views + .as_ref() + .map(|comp_batch| (comp_batch as &dyn ComponentBatch).into()), self.root_container .as_ref() .map(|comp| (comp as &dyn ComponentBatch).into()), @@ -273,18 +278,14 @@ impl ::re_types_core::AsComponents for ViewportBlueprint { #[inline] fn num_instances(&self) -> usize { - self.space_views.len() + 0 } } impl ViewportBlueprint { - pub fn new( - space_views: impl IntoIterator< - Item = impl Into, - >, - ) -> Self { + pub fn new() -> Self { Self { - space_views: space_views.into_iter().map(Into::into).collect(), + space_views: None, root_container: None, maximized: None, auto_layout: None, @@ -293,6 +294,17 @@ impl ViewportBlueprint { } } + #[inline] + pub fn with_space_views( + mut self, + space_views: impl IntoIterator< + Item = impl Into, + >, + ) -> Self { + self.space_views = Some(space_views.into_iter().map(Into::into).collect()); + self + } + #[inline] pub fn with_root_container( mut self, diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 428a7979a90b..439f913b4caa 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -98,8 +98,11 @@ impl ViewportBlueprint { } }; - let space_view_ids: Vec = - space_views.into_iter().map(|id| id.0.into()).collect(); + let space_view_ids: Vec = space_views + .unwrap_or(vec![]) + .iter() + .map(|id| id.0.into()) + .collect(); let space_views: BTreeMap = space_view_ids .into_iter() diff --git a/crates/rerun_c/src/lib.rs b/crates/rerun_c/src/lib.rs index e814a9dd530c..9f04baba1cad 100644 --- a/crates/rerun_c/src/lib.rs +++ b/crates/rerun_c/src/lib.rs @@ -408,7 +408,7 @@ fn rr_recording_stream_connect_impl( } else { None }; - stream.connect_opts(tcp_addr, flush_timeout); + stream.connect_opts(tcp_addr, flush_timeout, None); Ok(()) } diff --git a/examples/python/blueprint/main.py b/examples/python/blueprint/main.py index 006bc2a3a88b..2a8bc427949b 100755 --- a/examples/python/blueprint/main.py +++ b/examples/python/blueprint/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Example of using the blueprint APIs to configure Rerun.""" +# TODO(jleibs): Update this example to use the new APIs from __future__ import annotations import argparse @@ -26,15 +27,11 @@ def main() -> None: rr.init( "Blueprint demo", init_logging=False, - exp_init_blueprint=not args.skip_blueprint, - exp_add_to_app_default_blueprint=args.no_append_default, spawn=True, ) else: rr.init( "Blueprint demo", - exp_init_blueprint=not args.skip_blueprint, - exp_add_to_app_default_blueprint=args.no_append_default, spawn=True, ) diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp index e4f142f58638..82770516049d 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp @@ -16,8 +16,8 @@ namespace rerun { std::vector cells; cells.reserve(7); - { - auto result = DataCell::from_loggable(archetype.space_views); + if (archetype.space_views.has_value()) { + auto result = DataCell::from_loggable(archetype.space_views.value()); RR_RETURN_NOT_OK(result.error); cells.push_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp index 31458d45b3f4..fff310ce9a58 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp @@ -24,7 +24,7 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: The top-level description of the Viewport. struct ViewportBlueprint { /// All of the space-views that belong to the viewport. - Collection space_views; + std::optional> space_views; /// The layout of the space-views std::optional root_container; @@ -65,10 +65,14 @@ namespace rerun::blueprint::archetypes { ViewportBlueprint() = default; ViewportBlueprint(ViewportBlueprint&& other) = default; - explicit ViewportBlueprint( + /// All of the space-views that belong to the viewport. + ViewportBlueprint with_space_views( Collection _space_views - ) - : space_views(std::move(_space_views)) {} + ) && { + space_views = std::move(_space_views); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } /// The layout of the space-views ViewportBlueprint with_root_container( @@ -128,7 +132,7 @@ namespace rerun::blueprint::archetypes { /// Returns the number of primary instances of this archetype. size_t num_instances() const { - return space_views.size(); + return 0; } }; diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 16087f9ff5dc..5cd47eb194f4 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -142,6 +142,7 @@ ViewCoordinates, ) from .archetypes.boxes2d_ext import Box2DFormat +from .blueprint.api import BlueprintLike from .components import ( Material, MediaType, @@ -230,6 +231,7 @@ def _init_recording_stream() -> None: set_time_nanos, disable_timeline, reset_time, + log, ] + [fn for name, fn in getmembers(sys.modules[__name__], isfunction) if name.startswith("log_")] ) @@ -247,8 +249,7 @@ def init( init_logging: bool = True, default_enabled: bool = True, strict: bool = False, - exp_init_blueprint: bool = False, - exp_add_to_app_default_blueprint: bool = True, + blueprint: BlueprintLike | None = None, ) -> None: """ Initialize the Rerun SDK with a user-chosen application id (name). @@ -316,10 +317,8 @@ def init( strict If `True`, an exceptions is raised on use error (wrong parameter types, etc.). If `False`, errors are logged as warnings instead. - exp_init_blueprint - (Experimental) Should we initialize the blueprint for this application? - exp_add_to_app_default_blueprint - (Experimental) Should the blueprint append to the existing app-default blueprint instead of creating a new one. + blueprint + A blueprint to use for this application. If not provided, a new one will be created. """ @@ -346,21 +345,11 @@ def init( spawn=False, default_enabled=default_enabled, ) - if exp_init_blueprint: - experimental.new_blueprint( - application_id=application_id, - blueprint_id=recording_id, - make_default=True, - make_thread_default=False, - spawn=False, - add_to_app_default_blueprint=exp_add_to_app_default_blueprint, - default_enabled=default_enabled, - ) if spawn: from rerun.sinks import spawn as _spawn - _spawn() + _spawn(blueprint=blueprint) # TODO(#3793): defaulting recording_id to authkey should be opt-in diff --git a/rerun_py/rerun_sdk/rerun/_log.py b/rerun_py/rerun_sdk/rerun/_log.py index 216977848cf3..30a182364a4f 100644 --- a/rerun_py/rerun_sdk/rerun/_log.py +++ b/rerun_py/rerun_sdk/rerun/_log.py @@ -218,6 +218,9 @@ def log_components( if None, use the global default from `rerun.strict_mode()` """ + # Convert to a native recording + recording = RecordingStream.to_native(recording) + instanced: dict[str, pa.Array] = {} splats: dict[str, pa.Array] = {} diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index d9bd07a140a0..ba7be91efa09 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -1,5 +1,18 @@ from __future__ import annotations -__all__ = ["archetypes", "datatypes", "components"] +__all__ = [ + "archetypes", + "BlueprintLike", + "components", + "datatypes", + "Grid", + "Horizontal", + "Spatial2D", + "Spatial3D", + "Tabs", + "Vertical", + "Viewport", +] from . import archetypes, components, datatypes +from .api import BlueprintLike, Grid, Horizontal, Spatial2D, Spatial3D, Tabs, Vertical, Viewport diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py new file mode 100644 index 000000000000..cf85e5dbb2b1 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -0,0 +1,386 @@ +from __future__ import annotations + +import itertools +import uuid +from typing import Iterable, Optional, Sequence, Union + +import rerun_bindings as bindings + +from ..datatypes import EntityPathLike, Utf8Like +from ..recording import MemoryRecording +from ..recording_stream import RecordingStream +from .archetypes import ( + ContainerBlueprint, + SpaceViewBlueprint, + SpaceViewContents, + ViewportBlueprint, +) +from .components import ColumnShareArrayLike, RowShareArrayLike +from .components.container_kind import ContainerKind, ContainerKindLike + +SpaceViewContentsLike = Union[str, Sequence[str], Utf8Like, SpaceViewContents] + + +class SpaceView: + """ + Base class for all space view types. + + Consider using one of the subclasses instead of this class directly: + - [Spatial3D][] for 3D space views + - [Spatial2D][] for 2D space views + + This is an ergonomic helper on top of [rerun.blueprint.archetypes.SpaceViewBlueprint][]. + """ + + def __init__( + self, + class_identifier: Utf8Like, + origin: EntityPathLike, + contents: SpaceViewContentsLike, + ): + """ + Construct a blueprint for a new space view. + + Parameters + ---------- + class_identifier + The class of the space view to add. This must correspond to a known space view class. + Prefer to use one of the subclasses of `SpaceView` which will populate this for you. + origin + The `EntityPath` to use as the origin of this space view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the space view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + + """ + self.id = uuid.uuid4() + self.class_identifier = class_identifier + self.origin = origin + self.contents = contents + + def blueprint_path(self) -> str: + """ + The blueprint path where this space view will be logged. + + Note that although this is an `EntityPath`, is scoped to the blueprint tree and + not a part of the regular data hierarchy. + """ + return f"space_view/{self.id}" + + def _log_to_stream(self, stream: RecordingStream) -> None: + """Internal method to convert to an archetype and log to the stream.""" + # Handle the cases for SpaceViewContentsLike + # TODO(#5483): Move this into a QueryExpressionExt class. + # This is a little bit tricky since QueryExpression is a delegating component for Utf8, + # and delegating components make extending things in this way a bit more complicated. + if isinstance(self.contents, str): + # str + contents = SpaceViewContents(query=self.contents) + elif isinstance(self.contents, Sequence) and len(self.contents) > 0 and isinstance(self.contents[0], str): + # list[str] + contents = SpaceViewContents(query="\n".join(self.contents)) + elif isinstance(self.contents, SpaceViewContents): + # SpaceViewContents + contents = self.contents + else: + # Anything else we let SpaceViewContents handle + contents = SpaceViewContents(query=self.contents) # type: ignore[arg-type] + + stream.log(self.blueprint_path() + "/SpaceViewContents", contents) # type: ignore[attr-defined] + + arch = SpaceViewBlueprint( + class_identifier=self.class_identifier, + space_origin=self.origin, + ) + + stream.log(self.blueprint_path(), arch, recording=stream) # type: ignore[attr-defined] + + def _iter_space_views(self) -> Iterable[bytes]: + """Internal method to iterate over all of the space views in the blueprint.""" + # TODO(jleibs): This goes away when we get rid of `space_views` from the viewport and just use + # the entity-path lookup instead. + return [self.id.bytes] + + +class Spatial3D(SpaceView): + """A Spatial 3D space view.""" + + def __init__(self, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**"): + """ + Construct a blueprint for a new 3D space view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this space view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the space view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + + """ + super().__init__("3D", origin, contents) + + +class Spatial2D(SpaceView): + """A Spatial 2D space view.""" + + def __init__(self, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**"): + """ + Construct a blueprint for a new 2D space view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this space view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the space view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + + """ + super().__init__("2D", origin, contents) + + +class Container: + """ + Base class for all container types. + + Consider using one of the subclasses instead of this class directly: + - [Horizontal][] for horizontal containers + - [Vertical][] for vertical containers + - [Grid][] for grid containers + - [Tabs][] for tab containers + + This is an ergonomic helper on top of [rerun.blueprint.archetypes.ContainerBlueprint][]. + """ + + def __init__( + self, + *contents: Container | SpaceView, + kind: ContainerKindLike, + column_shares: Optional[ColumnShareArrayLike] = None, + row_shares: Optional[RowShareArrayLike] = None, + grid_columns: Optional[int] = None, + ): + """ + Construct a new container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + kind + The kind of the container. This must correspond to a known container kind. + Prefer to use one of the subclasses of `Container` which will populate this for you. + column_shares + The layout shares of the columns in the container. The share is used to determine what fraction of the total width each + column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. + This is only applicable to `Horizontal` or `Grid` containers. + row_shares + The layout shares of the rows in the container. The share is used to determine what fraction of the total height each + row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. + This is only applicable to `Vertical` or `Grid` containers. + grid_columns + The number of columns in the grid. This is only applicable to `Grid` containers. + + """ + self.id = uuid.uuid4() + self.kind = kind + self.contents = contents + self.column_shares = column_shares + self.row_shares = row_shares + self.grid_columns = grid_columns + + def blueprint_path(self) -> str: + """ + The blueprint path where this space view will be logged. + + Note that although this is an `EntityPath`, is scoped to the blueprint tree and + not a part of the regular data hierarchy. + """ + return f"container/{self.id}" + + def _log_to_stream(self, stream: RecordingStream) -> None: + """Internal method to convert to an archetype and log to the stream.""" + for sub in self.contents: + sub._log_to_stream(stream) + + arch = ContainerBlueprint( + container_kind=self.kind, + contents=[sub.blueprint_path() for sub in self.contents], + col_shares=self.column_shares, + row_shares=self.row_shares, + visible=True, + grid_columns=self.grid_columns, + ) + + stream.log(self.blueprint_path(), arch) # type: ignore[attr-defined] + + def _iter_space_views(self) -> Iterable[bytes]: + """Internal method to iterate over all of the space views in the blueprint.""" + # TODO(jleibs): This goes away when we get rid of `space_views` from the viewport and just use + # the entity-path lookup instead. + return itertools.chain.from_iterable(sub._iter_space_views() for sub in self.contents) + + +class Horizontal(Container): + """A horizontal container.""" + + def __init__(self, *contents: Container | SpaceView, column_shares: Optional[ColumnShareArrayLike] = None): + """ + Construct a new horizontal container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + column_shares + The layout shares of the columns in the container. The share is used to determine what fraction of the total width each + column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. + + """ + super().__init__(*contents, kind=ContainerKind.Horizontal, column_shares=column_shares) + + +class Vertical(Container): + """A vertical container.""" + + def __init__(self, *contents: Container | SpaceView, row_shares: Optional[RowShareArrayLike] = None): + """ + Construct a new vertical container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + row_shares + The layout shares of the rows in the container. The share is used to determine what fraction of the total height each + row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. + + """ + super().__init__(*contents, kind=ContainerKind.Vertical, row_shares=row_shares) + + +class Grid(Container): + """A grid container.""" + + def __init__( + self, + *contents: Container | SpaceView, + column_shares: Optional[ColumnShareArrayLike] = None, + row_shares: Optional[RowShareArrayLike] = None, + grid_columns: Optional[int] = None, + ): + """ + Construct a new grid container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + column_shares + The layout shares of the columns in the container. The share is used to determine what fraction of the total width each + column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. + row_shares + The layout shares of the rows in the container. The share is used to determine what fraction of the total height each + row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. + grid_columns + The number of columns in the grid. + + """ + super().__init__( + *contents, + kind=ContainerKind.Grid, + column_shares=column_shares, + row_shares=row_shares, + grid_columns=grid_columns, + ) + + +class Tabs(Container): + """A tab container.""" + + def __init__(self, *contents: Container | SpaceView): + """ + Construct a new tab container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + + """ + super().__init__(*contents, kind=ContainerKind.Tabs) + + +class Viewport: + """ + The top-level description of the Viewport. + + This is an ergonomic helper on top of [rerun.blueprint.archetypes.ViewportBlueprint][]. + """ + + def __init__(self, root_container: Container): + """ + Construct a new viewport. + + Parameters + ---------- + root_container: + The container that sits at the top of the viewport hierarchy. The only content visible + in this viewport must be contained within this container. + + """ + self.root_container = root_container + + def blueprint_path(self) -> str: + """ + The blueprint path where this space view will be logged. + + Note that although this is an `EntityPath`, is scoped to the blueprint tree and + not a part of the regular data hierarchy. + """ + return "viewport" + + def _log_to_stream(self, stream: RecordingStream) -> None: + """Internal method to convert to an archetype and log to the stream.""" + self.root_container._log_to_stream(stream) + + arch = ViewportBlueprint( + space_views=list(self.root_container._iter_space_views()), + root_container=self.root_container.id.bytes, + auto_layout=False, + auto_space_views=False, + ) + + stream.log(self.blueprint_path(), arch) # type: ignore[attr-defined] + + +BlueprintLike = Union[Viewport, Container, SpaceView] + + +def create_in_memory_blueprint(*, application_id: str, blueprint: BlueprintLike) -> MemoryRecording: + """Internal rerun helper to convert a `BlueprintLike` into a stream that can be sent to the viewer.""" + + # Add trivial wrappers as necessary + if isinstance(blueprint, SpaceView): + blueprint = Viewport(Grid(blueprint)) + elif isinstance(blueprint, Container): + blueprint = Viewport(blueprint) + + blueprint_stream = RecordingStream( + bindings.new_blueprint( + application_id=application_id, + ) + ) + + # TODO(jleibs): This should use a monotonic seq + blueprint_stream.set_time_seconds("blueprint", 1) # type: ignore[attr-defined] + + blueprint._log_to_stream(blueprint_stream) + + return blueprint_stream.memory_recording() # type: ignore[attr-defined, no-any-return] 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 fcace42edb95..5e8a72a7b33b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py @@ -23,8 +23,8 @@ class ViewportBlueprint(Archetype): def __init__( self: Any, - space_views: datatypes.UuidArrayLike, *, + space_views: datatypes.UuidArrayLike | None = None, root_container: datatypes.UuidLike | None = None, maximized: datatypes.UuidLike | None = None, auto_layout: blueprint_components.AutoLayoutLike | None = None, @@ -94,9 +94,10 @@ def _clear(cls) -> ViewportBlueprint: inst.__attrs_clear__() return inst - space_views: blueprint_components.IncludedSpaceViewBatch = field( - metadata={"component": "required"}, - converter=blueprint_components.IncludedSpaceViewBatch._required, # type: ignore[misc] + space_views: blueprint_components.IncludedSpaceViewBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.IncludedSpaceViewBatch._optional, # type: ignore[misc] ) # All of the space-views that belong to the viewport. # diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index 5820591386f0..0f0f7d4f22e1 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -6,14 +6,19 @@ import rerun_bindings as bindings # type: ignore[attr-defined] +from rerun.blueprint.api import BlueprintLike, create_in_memory_blueprint from rerun.recording import MemoryRecording -from rerun.recording_stream import RecordingStream +from rerun.recording_stream import RecordingStream, get_application_id # --- Sinks --- def connect( - addr: str | None = None, *, flush_timeout_sec: float | None = 2.0, recording: RecordingStream | None = None + addr: str | None = None, + *, + flush_timeout_sec: float | None = 2.0, + blueprint: BlueprintLike | None = None, + recording: RecordingStream | None = None, ) -> None: """ Connect to a remote Rerun Viewer on the given ip:port. @@ -30,14 +35,28 @@ def connect( The minimum time the SDK will wait during a flush before potentially dropping data if progress is not being made. Passing `None` indicates no timeout, and can cause a call to `flush` to block indefinitely. + blueprint: Optional[BlueprintLike] + An optional blueprint to configure the UI. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. """ + application_id = get_application_id(recording=recording) recording = RecordingStream.to_native(recording) - bindings.connect(addr=addr, flush_timeout_sec=flush_timeout_sec, recording=recording) + + if application_id is None: + raise ValueError( + "No application id found. You must call rerun.init before connecting to a viewer, or provide a recording." + ) + + # If a blueprint is provided, we need to create a blueprint storage object + blueprint_storage = None + if blueprint is not None: + blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + + bindings.connect(addr=addr, flush_timeout_sec=flush_timeout_sec, blueprint=blueprint_storage, recording=recording) _connect = connect # we need this because Python scoping is horrible @@ -204,6 +223,7 @@ def spawn( port: int = 9876, connect: bool = True, memory_limit: str = "75%", + blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None, ) -> None: """ @@ -228,6 +248,8 @@ def spawn( Specifies the [`rerun.RecordingStream`][] to use if `connect = True`. If left unspecified, defaults to the current active data recording, if there is one. See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. + blueprint: Optional[BlueprintLike] + An optional blueprint to configure the UI. """ @@ -286,4 +308,4 @@ def spawn( sleep(0.1) if connect: - _connect(f"127.0.0.1:{port}", recording=recording) + _connect(f"127.0.0.1:{port}", recording=recording, blueprint=blueprint) diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index 537acb11222b..c0acbd5796b1 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -535,10 +535,11 @@ fn is_enabled(recording: Option<&PyRecordingStream>) -> bool { } #[pyfunction] -#[pyo3(signature = (addr = None, flush_timeout_sec=rerun::default_flush_timeout().unwrap().as_secs_f32(), recording = None))] +#[pyo3(signature = (addr = None, flush_timeout_sec=rerun::default_flush_timeout().unwrap().as_secs_f32(), blueprint = None, recording = None))] fn connect( addr: Option, flush_timeout_sec: Option, + blueprint: Option<&PyMemorySinkStorage>, recording: Option<&PyRecordingStream>, py: Python<'_>, ) -> PyResult<()> { @@ -553,18 +554,9 @@ fn connect( // The call to connect may internally flush. // Release the GIL in case any flushing behavior needs to cleanup a python object. py.allow_threads(|| { - if let Some(recording) = recording { - // If the user passed in a recording, use it - recording.connect_opts(addr, flush_timeout); - } else { - // Otherwise, connect both global defaults - if let Some(recording) = get_data_recording(None) { - recording.connect_opts(addr, flush_timeout); - }; - if let Some(blueprint) = get_blueprint_recording(None) { - blueprint.connect_opts(addr, flush_timeout); - }; - } + if let Some(recording) = get_data_recording(recording) { + recording.connect_opts(addr, flush_timeout, blueprint.map(|b| b.inner.take())); + }; flush_garbage_queue(); }); diff --git a/rerun_py/tests/unit/test_viewport_blueprint.py b/rerun_py/tests/unit/test_viewport_blueprint.py index 153ef1ea467a..0f6ab7ee67c2 100644 --- a/rerun_py/tests/unit/test_viewport_blueprint.py +++ b/rerun_py/tests/unit/test_viewport_blueprint.py @@ -75,7 +75,7 @@ def test_viewport_blueprint() -> None: ")", ) arch = ViewportBlueprint( - space_views, + space_views=space_views, root_container=root_container, maximized=maximized, auto_layout=auto_layout, diff --git a/tests/python/blueprint/main.py b/tests/python/blueprint/main.py new file mode 100644 index 000000000000..4b042b9e9fdf --- /dev/null +++ b/tests/python/blueprint/main.py @@ -0,0 +1,40 @@ +from __future__ import annotations + +import rerun as rr +from numpy.random import default_rng +from rerun.blueprint import Grid, Horizontal, Spatial2D, Spatial3D, Tabs, Vertical + +if __name__ == "__main__": + blueprint = Vertical( + Spatial3D(origin="/test1"), + Horizontal( + Tabs( + Spatial3D(origin="/test1"), + Spatial2D(origin="/test2"), + ), + Grid( + Spatial3D(origin="/test1"), + Spatial2D(origin="/test2"), + Spatial3D(origin="/test1"), + Spatial2D(origin="/test2"), + grid_columns=3, + column_shares=[1, 1, 1], + ), + column_shares=[1, 2], + ), + row_shares=[2, 1], + ) + + rr.init( + "rerun_example_blueprint_test", + spawn=True, + blueprint=blueprint, + ) + + rng = default_rng(12345) + positions = rng.uniform(-5, 5, size=[10, 3]) + colors = rng.uniform(0, 255, size=[10, 3]) + radii = rng.uniform(0, 1, size=[10]) + + rr.log("test1", rr.Points3D(positions, colors=colors, radii=radii)) + rr.log("test2", rr.Points2D(positions[:, :2], colors=colors, radii=radii)) From 66bd58bc51eaa22e4f4cfb73068ea04ad5a0e9ac Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 13 Mar 2024 08:51:23 +0100 Subject: [PATCH 010/508] Update to egui master (#5486) ### What * Closes #5352 * Closes #5368 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5486/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5486/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5486/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5486) - [Docs preview](https://rerun.io/preview/fe51c08c917b25609140f44c5c475b1818a53beb/docs) - [Examples preview](https://rerun.io/preview/fe51c08c917b25609140f44c5c475b1818a53beb/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 70d3ed4c4acb..bc7d36d39c56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1567,7 +1567,7 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "bytemuck", "serde", @@ -1576,7 +1576,7 @@ dependencies = [ [[package]] name = "eframe" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "bytemuck", "cocoa", @@ -1611,7 +1611,7 @@ dependencies = [ [[package]] name = "egui" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "accesskit", "ahash", @@ -1627,7 +1627,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "bytemuck", "document-features", @@ -1645,7 +1645,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "accesskit_winit", "arboard", @@ -1674,7 +1674,7 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "egui", "ehttp", @@ -1689,7 +1689,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "bytemuck", "egui", @@ -1706,7 +1706,7 @@ dependencies = [ [[package]] name = "egui_plot" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "egui", ] @@ -1748,7 +1748,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "bytemuck", "serde", @@ -1849,7 +1849,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=a1d5145c16aba4d0b11668d496735d07520d0339#a1d5145c16aba4d0b11668d496735d07520d0339" +source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" dependencies = [ "ab_glyph", "ahash", diff --git a/Cargo.toml b/Cargo.toml index 3791985ab52e..cddfa2d1b9ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -283,13 +283,13 @@ debug = true # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "a1d5145c16aba4d0b11668d496735d07520d0339" } # egui master 2024-03-06 -eframe = { git = "https://github.com/emilk/egui.git", rev = "a1d5145c16aba4d0b11668d496735d07520d0339" } # egui master 2024-03-06 -egui = { git = "https://github.com/emilk/egui.git", rev = "a1d5145c16aba4d0b11668d496735d07520d0339" } # egui master 2024-03-06 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "a1d5145c16aba4d0b11668d496735d07520d0339" } # egui master 2024-03-06 -egui_plot = { git = "https://github.com/emilk/egui.git", rev = "a1d5145c16aba4d0b11668d496735d07520d0339" } # egui master 2024-03-06 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "a1d5145c16aba4d0b11668d496735d07520d0339" } # egui master 2024-03-06 -emath = { git = "https://github.com/emilk/egui.git", rev = "a1d5145c16aba4d0b11668d496735d07520d0339" } # egui master 2024-03-06 +ecolor = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 +eframe = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 +egui = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 +egui_extras = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 +egui_plot = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 +egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 +emath = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } From 67e628ba10952c814ca4acbd13f66a12b97495ce Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 13 Mar 2024 09:33:29 +0100 Subject: [PATCH 011/508] Implement recursive component overrides (#5481) ### What * First bits of #5463 10% impl 90% test code! (unfortunately a fair portion of that is boilerplate) Additionally, also takes into account "root property overrides": visual time range on space view is right now implemented via a special hook that passes root `EntityProperties` in. We need/want the same for component overrides and that's exactly what's happening here as well. Unfortunately, that part isn't covered by unit testing, but it's fairly straight forward so I'm not too worried. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5481/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5481/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5481/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5481) - [Docs preview](https://rerun.io/preview/2ae6d25785a5275e2fc721691cd3850e4096a9f4/docs) - [Examples preview](https://rerun.io/preview/2ae6d25785a5275e2fc721691cd3850e4096a9f4/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view/src/data_query.rs | 7 + crates/re_space_view/src/space_view.rs | 295 +++++++++++++++++- .../re_space_view/src/space_view_contents.rs | 105 ++++--- .../src/space_view/view_query.rs | 2 +- 4 files changed, 361 insertions(+), 48 deletions(-) diff --git a/crates/re_space_view/src/data_query.rs b/crates/re_space_view/src/data_query.rs index 68f3d1c02f73..ea9771817509 100644 --- a/crates/re_space_view/src/data_query.rs +++ b/crates/re_space_view/src/data_query.rs @@ -1,10 +1,17 @@ +use ahash::HashMap; + use re_entity_db::{external::re_data_store::LatestAtQuery, EntityProperties, EntityPropertyMap}; +use re_log_types::{EntityPath, StoreKind}; +use re_types::ComponentName; use re_viewer_context::{DataQueryResult, PerVisualizer, StoreContext, VisualizableEntities}; pub struct EntityOverrideContext { pub root: EntityProperties, pub individual: EntityPropertyMap, pub recursive: EntityPropertyMap, + + /// Base component overrides that are inherited by all entities. + pub root_component_overrides: HashMap, } /// Trait for resolving properties needed by most implementations of [`DataQuery`] diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 0b69c09a4cc7..c7473d84842c 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -450,12 +450,16 @@ impl SpaceViewBlueprint { mod tests { use crate::data_query::{DataQuery, PropertyResolver}; use re_entity_db::EntityDb; - use re_log_types::{DataCell, DataRow, EntityPathFilter, RowId, StoreId, TimePoint}; - use re_types::archetypes::Points3D; + use re_log_types::{ + example_components::{MyColor, MyLabel, MyPoint}, + DataCell, DataRow, EntityPathFilter, RowId, StoreId, StoreKind, TimePoint, + }; + use re_types::{archetypes::Points3D, ComponentBatch, ComponentName, Loggable as _}; use re_viewer_context::{ blueprint_timeline, IndicatedEntities, PerVisualizer, SpaceViewClassRegistry, StoreContext, VisualizableEntities, }; + use std::collections::HashMap; use super::*; @@ -474,7 +478,7 @@ mod tests { } #[test] - fn test_overrides() { + fn test_entity_properties() { let space_view_class_registry = SpaceViewClassRegistry::default(); let mut recording = EntityDb::new(StoreId::random(re_log_types::StoreKind::Recording)); let mut blueprint = EntityDb::new(StoreId::random(re_log_types::StoreKind::Blueprint)); @@ -758,4 +762,289 @@ mod tests { ); } } + + #[test] + fn test_component_overrides() { + let space_view_class_registry = SpaceViewClassRegistry::default(); + let mut recording = EntityDb::new(StoreId::random(re_log_types::StoreKind::Recording)); + let mut visualizable_entities_per_visualizer = + PerVisualizer::::default(); + + // Set up a store DB with some entities. + { + let entity_paths: Vec = + ["parent", "parent/skipped/grandchild", "parent/child"] + .into_iter() + .map(Into::into) + .collect(); + for entity_path in &entity_paths { + let row = DataRow::from_component_batches( + RowId::new(), + TimePoint::timeless(), + entity_path.clone(), + [&[MyPoint::new(1.0, 2.0)] as _], + ) + .unwrap(); + recording.add_data_row(row).unwrap(); + } + + // All of them are visualizable with some arbitrary visualizer. + visualizable_entities_per_visualizer + .0 + .entry("Points3D".into()) + .or_insert_with(|| VisualizableEntities(entity_paths.into_iter().collect())); + } + + // Basic blueprint - a single space view that queries everything. + let space_view = SpaceViewBlueprint::new( + "3D".into(), + &EntityPath::root(), + EntityPathFilter::parse_forgiving("+ /**"), + ); + let individual_override_root = space_view + .contents + .blueprint_entity_path + .join(&DataResult::INDIVIDUAL_OVERRIDES_PREFIX.into()); + let recursive_override_root = space_view + .contents + .blueprint_entity_path + .join(&DataResult::RECURSIVE_OVERRIDES_PREFIX.into()); + + // Things needed to resolve properties: + let auto_properties = EntityPropertyMap::default(); + let indicated_entities_per_visualizer = PerVisualizer::::default(); // Don't care about indicated entities. + let resolver = space_view.contents.build_resolver( + &space_view_class_registry, + &space_view, + &auto_properties, + &visualizable_entities_per_visualizer, + &indicated_entities_per_visualizer, + ); + + struct Scenario { + recursive_overrides: Vec<(EntityPath, Box)>, + individual_overrides: Vec<(EntityPath, Box)>, + expected_overrides: HashMap>, + } + + let scenarios: Vec = vec![ + // No overrides. + Scenario { + recursive_overrides: Vec::new(), + individual_overrides: Vec::new(), + expected_overrides: HashMap::default(), + }, + // Recursive override at parent entity. + Scenario { + recursive_overrides: vec![( + "parent".into(), + Box::new(MyLabel("parent_override".to_owned())), + )], + individual_overrides: Vec::new(), + expected_overrides: HashMap::from([ + ( + "parent".into(), + HashMap::from([( + MyLabel::name(), + recursive_override_root.join(&"parent".into()), + )]), + ), + ( + "parent/skipped".into(), + HashMap::from([( + MyLabel::name(), + recursive_override_root.join(&"parent".into()), + )]), + ), + ( + "parent/skipped/grandchild".into(), + HashMap::from([( + MyLabel::name(), + recursive_override_root.join(&"parent".into()), + )]), + ), + ( + "parent/child".into(), + HashMap::from([( + MyLabel::name(), + recursive_override_root.join(&"parent".into()), + )]), + ), + ]), + }, + // Set a single individual. + Scenario { + recursive_overrides: Vec::new(), + individual_overrides: vec![( + "parent".into(), + Box::new(MyLabel("parent_individual".to_owned())), + )], + expected_overrides: HashMap::from([( + "parent".into(), + HashMap::from([( + MyLabel::name(), + individual_override_root.join(&"parent".into()), + )]), + )]), + }, + // Recursive override, partially shadowed by individual. + Scenario { + recursive_overrides: vec![ + ( + "parent/skipped".into(), + Box::new(MyLabel("parent_individual".to_owned())), + ), + ( + "parent/skipped".into(), + Box::new(MyColor::from_rgb(0, 1, 2)), + ), + ], + individual_overrides: vec![( + "parent/skipped/grandchild".into(), + Box::new(MyColor::from_rgb(1, 2, 3)), + )], + expected_overrides: HashMap::from([ + ( + "parent/skipped".into(), + HashMap::from([ + ( + MyLabel::name(), + recursive_override_root.join(&"parent/skipped".into()), + ), + ( + MyColor::name(), + recursive_override_root.join(&"parent/skipped".into()), + ), + ]), + ), + ( + "parent/skipped/grandchild".into(), + HashMap::from([ + ( + MyLabel::name(), + recursive_override_root.join(&"parent/skipped".into()), + ), + ( + MyColor::name(), + individual_override_root.join(&"parent/skipped/grandchild".into()), + ), + ]), + ), + ]), + }, + // Recursive override, partially shadowed by another recursive override. + Scenario { + recursive_overrides: vec![ + ( + "parent/skipped".into(), + Box::new(MyLabel("parent_individual".to_owned())), + ), + ( + "parent/skipped".into(), + Box::new(MyColor::from_rgb(0, 1, 2)), + ), + ( + "parent/skipped/grandchild".into(), + Box::new(MyColor::from_rgb(3, 2, 1)), + ), + ], + individual_overrides: Vec::new(), + expected_overrides: HashMap::from([ + ( + "parent/skipped".into(), + HashMap::from([ + ( + MyLabel::name(), + recursive_override_root.join(&"parent/skipped".into()), + ), + ( + MyColor::name(), + recursive_override_root.join(&"parent/skipped".into()), + ), + ]), + ), + ( + "parent/skipped/grandchild".into(), + HashMap::from([ + ( + MyLabel::name(), + recursive_override_root.join(&"parent/skipped".into()), + ), + ( + MyColor::name(), + recursive_override_root.join(&"parent/skipped/grandchild".into()), + ), + ]), + ), + ]), + }, + ]; + + for ( + i, + Scenario { + recursive_overrides, + individual_overrides, + expected_overrides, + }, + ) in scenarios.into_iter().enumerate() + { + let mut blueprint = EntityDb::new(StoreId::random(re_log_types::StoreKind::Blueprint)); + let mut add_to_blueprint = |path: &EntityPath, batch: &dyn ComponentBatch| { + let row = DataRow::from_component_batches( + RowId::new(), + TimePoint::timeless(), + path.clone(), + std::iter::once(batch), + ) + .unwrap(); + blueprint.add_data_row(row).unwrap(); + }; + + // log individual and override components as instructed. + for (entity_path, batch) in recursive_overrides { + add_to_blueprint(&recursive_override_root.join(&entity_path), batch.as_ref()); + } + for (entity_path, batch) in individual_overrides { + add_to_blueprint(&individual_override_root.join(&entity_path), batch.as_ref()); + } + + // Set up a store query and update the overrides. + let ctx = StoreContext { + blueprint: &blueprint, + recording: Some(&recording), + all_recordings: vec![], + }; + let mut query_result = space_view + .contents + .execute_query(&ctx, &visualizable_entities_per_visualizer); + let blueprint_query = LatestAtQuery::latest(blueprint_timeline()); + resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); + + // Extract component overrides for testing. + let mut visited: HashMap> = + HashMap::default(); + query_result.tree.visit(&mut |node| { + let result = &node.data_result; + if let Some(property_overrides) = &result.property_overrides { + if !property_overrides.component_overrides.is_empty() { + visited.insert( + result.entity_path.clone(), + property_overrides + .component_overrides + .iter() + .map(|(component_name, (store_kind, path))| { + assert_eq!(store_kind, &StoreKind::Blueprint); + (*component_name, path.clone()) + }) + .collect(), + ); + } + } + true + }); + + assert_eq!(visited, expected_overrides, "Scenario {i}"); + } + } } diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 7254883e89ff..033a1e3982c0 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -336,11 +336,11 @@ impl DataQueryPropertyResolver<'_> { // TODO(#4194): We always start the override context with the root_data_result from // the space-view. This isn't totally generic once we add container overrides, but it's a start. - let mut root: EntityProperties = self + let (mut root_entity_properties, root_component_overrides) = self .space_view .root_data_result(ctx, query) .property_overrides - .map(|p| p.accumulated_properties.clone()) + .map(|p| (p.accumulated_properties, p.component_overrides)) .unwrap_or_default(); for prefix in &self.default_stack { @@ -349,7 +349,7 @@ impl DataQueryPropertyResolver<'_> { .store() .query_latest_component::(prefix, query) { - root = root.with_child(&overrides.value.0); + root_entity_properties = root_entity_properties.with_child(&overrides.value.0); } } @@ -357,7 +357,7 @@ impl DataQueryPropertyResolver<'_> { // if we were to support incrementally inheriting overrides from parent // contexts such as the `SpaceView` or `Container`. EntityOverrideContext { - root, + root: root_entity_properties, individual: self.resolve_entity_overrides_for_path( ctx, query, @@ -368,6 +368,7 @@ impl DataQueryPropertyResolver<'_> { query, &self.recursive_override_root, ), + root_component_overrides, } } @@ -407,6 +408,7 @@ impl DataQueryPropertyResolver<'_> { /// /// This will accumulate the recursive properties at each step down the tree, and then merge /// with individual overrides on each step. + #[allow(clippy::too_many_arguments)] // This will be a lot simpler and smaller once `EntityProperties` are gone! fn update_overrides_recursive( &self, ctx: &StoreContext<'_>, @@ -414,9 +416,10 @@ impl DataQueryPropertyResolver<'_> { query_result: &mut DataQueryResult, override_context: &EntityOverrideContext, accumulated: &EntityProperties, + recursive_property_overrides: &HashMap, handle: DataResultHandle, ) { - if let Some((child_handles, accumulated)) = + if let Some((child_handles, accumulated, recursive_property_overrides)) = query_result.tree.lookup_node_mut(handle).map(|node| { let recursive_properties = override_context .recursive @@ -473,13 +476,37 @@ impl DataQueryPropertyResolver<'_> { } } - let mut component_overrides: HashMap = - Default::default(); + // First, gather recursive overrides. Previous recursive overrides are the base for the next. + // We assume that most of the time there's no new recursive overrides, so clone the map lazily. + let mut recursive_property_overrides = + std::borrow::Cow::Borrowed(recursive_property_overrides); + if let Some(recursive_override_subtree) = + ctx.blueprint.tree().subtree(&recursive_override_path) + { + for component in recursive_override_subtree.entity.components.keys() { + if let Some(component_data) = ctx + .blueprint + .store() + .latest_at(query, &recursive_override_path, *component, &[*component]) + .and_then(|(_, _, cells)| cells[0].clone()) + { + if !component_data.is_empty() { + recursive_property_overrides.to_mut().insert( + *component, + (StoreKind::Blueprint, recursive_override_path.clone()), + ); + } + } + } + } - if let Some(override_subtree) = + // Then, gather individual overrides - these may override the recursive ones again, + // but recursive overrides are still inherited to children. + let mut component_overrides = (*recursive_property_overrides).clone(); + if let Some(individual_override_subtree) = ctx.blueprint.tree().subtree(&individual_override_path) { - for component in override_subtree.entity.components.keys() { + for component in individual_override_subtree.entity.components.keys() { if let Some(component_data) = ctx .blueprint .store() @@ -505,7 +532,11 @@ impl DataQueryPropertyResolver<'_> { individual_override_path, }); - (node.children.clone(), accumulated_recursive_properties) + ( + node.children.clone(), + accumulated_recursive_properties, + recursive_property_overrides, + ) }) { for child in child_handles { @@ -515,6 +546,7 @@ impl DataQueryPropertyResolver<'_> { query_result, override_context, &accumulated, + &recursive_property_overrides, child, ); } @@ -540,13 +572,13 @@ impl<'a> PropertyResolver for DataQueryPropertyResolver<'a> { query_result, &entity_overrides, &entity_overrides.root, + &entity_overrides.root_component_overrides, root, ); } } } -#[cfg(feature = "testing")] #[cfg(test)] mod tests { use re_entity_db::EntityDb; @@ -611,9 +643,8 @@ mod tests { filter: "+ /**", outputs: vec![ "/**", - "/parent/**", "/parent", - "/parent/skipped/**", // Not an exact match and not found in tree + "/parent/skipped", "/parent/skipped/child1", // Only child 1 has visualizers ], }, @@ -621,8 +652,8 @@ mod tests { filter: "+ parent/skipped/**", outputs: vec![ "/**", - "/parent/**", // Only included because is a prefix - "/parent/skipped/**", // Not an exact match and not found in tree + "/parent/**", // Only included because is a prefix + "/parent/skipped", "/parent/skipped/child1", // Only child 1 has visualizers ], }, @@ -631,7 +662,6 @@ mod tests { + parent/skipped/child2", outputs: vec![ "/**", // Trivial intermediate group -- could be collapsed - "/parent/**", "/parent", "/parent/skipped/**", // Trivial intermediate group -- could be collapsed "/parent/skipped/child2", @@ -643,9 +673,7 @@ mod tests { + parent/**", outputs: vec![ "/**", - "/parent/**", "/parent", - "/parent/skipped/**", "/parent/skipped", // Included because an exact match "/parent/skipped/child1", // Included because an exact match "/parent/skipped/child2", @@ -658,8 +686,7 @@ mod tests { - parent", outputs: vec![ "/**", - "/parent/**", // Parent leaf has been excluded - "/parent/skipped/**", + "/parent/**", // Parent leaf has been excluded "/parent/skipped", // Included because an exact match "/parent/skipped/child1", // Included because an exact match "/parent/skipped/child2", @@ -676,9 +703,8 @@ mod tests { - parent/skipped/child1", outputs: vec![ "/**", - "/parent/**", "/parent", - "/parent/skipped/**", + "/parent/skipped", "/parent/skipped/child2", // No child1 since skipped. ], }, @@ -692,36 +718,27 @@ mod tests { ]; for (i, Scenario { filter, outputs }) in scenarios.into_iter().enumerate() { - let query = SpaceViewContents { - id: DataQueryId::random(), - space_view_class_identifier: "3D".into(), - entity_path_filter: EntityPathFilter::parse_forgiving(filter), - }; - - let indicated_entities_per_visualizer = PerVisualizer::( - visualizable_entities_for_visualizer_systems - .iter() - .map(|(id, entities)| { - (*id, IndicatedEntities(entities.0.iter().cloned().collect())) - }) - .collect(), - ); - let query_result = query.execute_query( - &ctx, - &visualizable_entities_for_visualizer_systems, - &indicated_entities_per_visualizer, + let contents = SpaceViewContents::new( + SpaceViewId::random(), + "3D".into(), + EntityPathFilter::parse_forgiving(filter), ); + let query_result = + contents.execute_query(&ctx, &visualizable_entities_for_visualizer_systems); + let mut visited = vec![]; - query_result.tree.visit(&mut |handle| { - let result = query_result.tree.lookup_result(handle).unwrap(); - if result.is_group && result.entity_path == EntityPath::root() { + query_result.tree.visit(&mut |node| { + let result = &node.data_result; + if result.entity_path == EntityPath::root() { visited.push("/**".to_owned()); - } else if result.is_group { + } else if result.tree_prefix_only { visited.push(format!("{}/**", result.entity_path)); + assert!(result.visualizers.is_empty()); } else { visited.push(result.entity_path.to_string()); } + true }); assert_eq!(visited, outputs, "Scenario {i}, filter: {filter}"); diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 2caf37a065e8..07d09d3da24f 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -33,7 +33,7 @@ pub struct PropertyOverrides { // TODO(jleibs): Consider something like `tinymap` for this. pub component_overrides: HashMap, - /// `EntityPath` in the Blueprint store where updated overrides should be written back\ + /// `EntityPath` in the Blueprint store where updated overrides should be written back /// for properties that apply recursively. pub recursive_override_path: EntityPath, From 929741bd9601bcb8a519d2dbc2320026f75fb343 Mon Sep 17 00:00:00 2001 From: Andreas Naoum <49308613+andreasnaoum@users.noreply.github.com> Date: Wed, 13 Mar 2024 09:37:48 +0100 Subject: [PATCH 012/508] Update Human Pose Tracking Readme file (#5359) --- examples/python/human_pose_tracking/README.md | 137 +++++++++++++++++- examples/python/human_pose_tracking/main.py | 6 +- 2 files changed, 137 insertions(+), 6 deletions(-) diff --git a/examples/python/human_pose_tracking/README.md b/examples/python/human_pose_tracking/README.md index 5b596f817474..7d6705cf5fc4 100644 --- a/examples/python/human_pose_tracking/README.md +++ b/examples/python/human_pose_tracking/README.md @@ -7,7 +7,6 @@ thumbnail_dimensions = [480, 272] channel = "main" --> - @@ -16,9 +15,141 @@ channel = "main" -Use the [MediaPipe](https://google.github.io/mediapipe/) Pose solution to detect and track a human pose in video. +Use the [MediaPipe Pose Landmark Detection](https://developers.google.com/mediapipe/solutions/vision/pose_landmarker) solution to detect and track a human pose in video. + + + +## Used Rerun Types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) + +## Background +The [MediaPipe Pose Landmark Detection](https://developers.google.com/mediapipe/solutions/vision/pose_landmarker) solution detects and tracks human pose landmarks and produces segmentation masks for humans. The solution targets real-time inference on video streams. In this example we use Rerun to visualize the output of the Mediapipe solution over time to make it easy to analyze the behavior. + + +# Logging and Visualizing with Rerun +The visualizations in this example were created with the following Rerun code. + +## Timelines + +For each processed video frame, all data sent to Rerun is associated with the two [`timelines`](https://www.rerun.io/docs/concepts/timelines) `time` and `frame_idx`. + +```python +rr.set_time_seconds("time", bgr_frame.time) +rr.set_time_sequence("frame_idx", bgr_frame.idx) +``` + +## Video +The input video is logged as a sequence of +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) objects to the 'Video' entity. +```python +rr.log( + "video/rgb", + rr.Image(rgb).compress(jpeg_quality=75) +) +``` + +## Segmentation Mask + +The segmentation result is logged through a combination of two archetypes. The segmentation +image itself is logged as an +[`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) and +contains the id for each pixel. The color is determined by the +[`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is +logged with `timeless=True` as it should apply to the whole sequence. + +### Label Mapping + +```python +rr.log( + "video/mask", + rr.AnnotationContext( + [ + rr.AnnotationInfo(id=0, label="Background"), + rr.AnnotationInfo(id=1, label="Person", color=(0, 0, 0)), + ] + ), + timeless=True, + ) +``` + +### Segmentation Image + +```python +rr.log( + "video/mask", + rr.SegmentationImage(segmentation_mask.astype(np.uint8)) +) +``` + +## Body Pose Points +Logging the body pose landmarks involves specifying connections between the points, extracting pose landmark points and logging them to the Rerun SDK. +The 2D points are visualized over the image/video for a better understanding and visualization of the body pose. The 3D points allows the creation of a 3D model of the body posture for a more comprehensive representation of the human pose. + + +The 2D and 3D points are logged through a combination of two archetypes. First, a timeless +[`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description) is logged, that contains the information which maps keypoint ids to labels and how to connect +the keypoints. +Defining these connections automatically renders lines between them. Mediapipe provides the `POSE_CONNECTIONS` variable which contains the list of `(from, to)` landmark indices that define the connections. Second, the actual keypoint positions are logged in 2D +and 3D as [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d) and +[`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetypes, respectively. + +### Label Mapping and Keypoint Connections + +```python +rr.log( + "/", + rr.AnnotationContext( + rr.ClassDescription( + info=rr.AnnotationInfo(id=1, label="Person"), + keypoint_annotations=[rr.AnnotationInfo(id=lm.value, label=lm.name) for lm in mp_pose.PoseLandmark], + keypoint_connections=mp_pose.POSE_CONNECTIONS, + ) + ), + timeless=True, +) +``` + +### 2D Points + +```python +rr.log( + "video/pose/points", + rr.Points2D(landmark_positions_2d, class_ids=1, keypoint_ids=mp_pose.PoseLandmark) +) +``` + +### 3D Points + +```python +rr.log( + "person/pose/points", + rr.Points3D(landmark_positions_3d, class_ids=1, keypoint_ids=mp_pose.PoseLandmark), +) +``` + +# Run the Code + +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` + +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/human_pose_tracking/requirements.txt -python examples/python/human_pose_tracking/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/human_pose_tracking/main.py # run the example +``` + +If you wish to customize it for various videos, adjust the maximum frames, or explore additional features, use the CLI with the `--help` option for guidance: + +```bash +python examples/python/human_pose_tracking/main.py --help ``` diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py index 60e712b03bf3..2884f99a3d45 100755 --- a/examples/python/human_pose_tracking/main.py +++ b/examples/python/human_pose_tracking/main.py @@ -69,7 +69,7 @@ def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) - "/", rr.AnnotationContext( rr.ClassDescription( - info=rr.AnnotationInfo(id=0, label="Person"), + info=rr.AnnotationInfo(id=1, label="Person"), keypoint_annotations=[rr.AnnotationInfo(id=lm.value, label=lm.name) for lm in mp_pose.PoseLandmark], keypoint_connections=mp_pose.POSE_CONNECTIONS, ) @@ -105,14 +105,14 @@ def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) - if landmark_positions_2d is not None: rr.log( "video/pose/points", - rr.Points2D(landmark_positions_2d, class_ids=0, keypoint_ids=mp_pose.PoseLandmark), + rr.Points2D(landmark_positions_2d, class_ids=1, keypoint_ids=mp_pose.PoseLandmark), ) landmark_positions_3d = read_landmark_positions_3d(results) if landmark_positions_3d is not None: rr.log( "person/pose/points", - rr.Points3D(landmark_positions_3d, class_ids=0, keypoint_ids=mp_pose.PoseLandmark), + rr.Points3D(landmark_positions_3d, class_ids=1, keypoint_ids=mp_pose.PoseLandmark), ) segmentation_mask = results.segmentation_mask From b9f14618c2d4b9578623dfbfa305e76fee25a88c Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 13 Mar 2024 10:18:38 +0100 Subject: [PATCH 013/508] Remove DynSpaceViewClass indirection (#5471) ### What Originally we had `SpaceViewClass` as the non-object-safe wrapper of `DynSpaceViewClass` to allow a bunch of generic type parameters while having object safety preserved in `DynSpaceViewClass` (== being able to store it in a `Box`, passing it around as `&dyn DynSpaceViewClass`). Over time however we removed more and more strong types from `SpaceViewClass`, leaving only the `SpaceViewClassState`. At the same time we kept adding methods that don't use the state type, making the overhead of maintaining the `DynSpaceViewClass`->`SpaceViewClass` traits a burden. In spirit this PR removes `SpaceViewClass` and renames `DynSpaceViewClass` to `SpaceViewClass` rather than the other way round. Plus some inevitable cascading & ensuing cleanups ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5471/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5471/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5471/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5471) - [Docs preview](https://rerun.io/preview/4abffa5edd0dd13cc2d682e357372c5b225d264b/docs) - [Examples preview](https://rerun.io/preview/4abffa5edd0dd13cc2d682e357372c5b225d264b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view/src/space_view.rs | 16 +- crates/re_space_view/src/visualizable.rs | 6 +- .../src/space_view_class.rs | 27 +- .../src/space_view_class.rs | 32 +- .../src/space_view_2d.rs | 45 ++- .../src/space_view_3d.rs | 39 +- .../src/visualizers/entity_iterator.rs | 4 +- .../src/visualizers/images.rs | 12 +- .../src/space_view_class.rs | 31 +- .../src/space_view_class.rs | 28 +- .../src/space_view_class.rs | 30 +- .../src/space_view_class.rs | 34 +- crates/re_viewer/src/app.rs | 8 +- crates/re_viewer/src/ui/selection_panel.rs | 26 +- crates/re_viewer/src/ui/visible_history.rs | 6 +- crates/re_viewer_context/src/lib.rs | 17 +- .../src/space_view/dyn_space_view_class.rs | 211 ----------- .../re_viewer_context/src/space_view/mod.rs | 13 +- .../src/space_view/space_view_class.rs | 333 +++++++----------- .../space_view_class_placeholder.rs | 32 +- .../space_view/space_view_class_registry.rs | 22 +- .../src/add_space_view_or_container_modal.rs | 6 +- .../actions/add_entities_to_new_space_view.rs | 6 +- crates/re_viewport/src/context_menu/mod.rs | 2 +- .../src/space_view_entity_picker.rs | 2 +- .../re_viewport/src/space_view_heuristics.rs | 3 +- crates/re_viewport/src/system_execution.rs | 5 +- crates/re_viewport/src/viewport_blueprint.rs | 2 +- .../src/color_coordinates_space_view.rs | 34 +- 29 files changed, 416 insertions(+), 616 deletions(-) delete mode 100644 crates/re_viewer_context/src/space_view/dyn_space_view_class.rs diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index c7473d84842c..03c226f78414 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -14,8 +14,8 @@ use re_types::{ use re_types_core::archetypes::Clear; use re_types_core::Archetype as _; use re_viewer_context::{ - blueprint_timepoint_for_writes, DataResult, DynSpaceViewClass, PerSystemEntities, - PropertyOverrides, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, + blueprint_timepoint_for_writes, DataResult, PerSystemEntities, PropertyOverrides, + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, }; @@ -337,7 +337,7 @@ impl SpaceViewBlueprint { pub fn class<'a>( &self, space_view_class_registry: &'a re_viewer_context::SpaceViewClassRegistry, - ) -> &'a dyn DynSpaceViewClass { + ) -> &'a dyn SpaceViewClass { space_view_class_registry.get_class_or_log_error(&self.class_identifier) } @@ -391,7 +391,15 @@ impl SpaceViewBlueprint { .unwrap_or_default(); ui.scope(|ui| { - class.ui(ctx, ui, view_state, &props, query, system_output); + class + .ui(ctx, ui, view_state, &props, query, system_output) + .unwrap_or_else(|err| { + re_log::error!( + "Error in Space View UI (class: {}, display name: {}): {err}", + self.class_identifier, + class.display_name(), + ); + }); }); } diff --git a/crates/re_space_view/src/visualizable.rs b/crates/re_space_view/src/visualizable.rs index 8368eca7509e..a5a5704279cd 100644 --- a/crates/re_space_view/src/visualizable.rs +++ b/crates/re_space_view/src/visualizable.rs @@ -1,8 +1,6 @@ use re_entity_db::EntityDb; use re_log_types::EntityPath; -use re_viewer_context::{ - ApplicableEntities, DynSpaceViewClass, PerVisualizer, VisualizableEntities, -}; +use re_viewer_context::{ApplicableEntities, PerVisualizer, SpaceViewClass, VisualizableEntities}; /// Determines the set of visible entities for a given space view. // TODO(andreas): This should be part of the SpaceView's (non-blueprint) state. @@ -11,7 +9,7 @@ pub fn determine_visualizable_entities( applicable_entities_per_visualizer: &PerVisualizer, entity_db: &EntityDb, visualizers: &re_viewer_context::VisualizerCollection, - class: &dyn DynSpaceViewClass, + class: &dyn SpaceViewClass, space_origin: &EntityPath, ) -> PerVisualizer { re_tracing::profile_function!(); diff --git a/crates/re_space_view_bar_chart/src/space_view_class.rs b/crates/re_space_view_bar_chart/src/space_view_class.rs index 821e3a609671..4f9f848182db 100644 --- a/crates/re_space_view_bar_chart/src/space_view_class.rs +++ b/crates/re_space_view_bar_chart/src/space_view_class.rs @@ -4,8 +4,8 @@ use re_log_types::EntityPath; use re_space_view::{controls, suggest_space_view_for_each_entity}; use re_types::datatypes::TensorBuffer; use re_viewer_context::{ - auto_color, SpaceViewClass, SpaceViewClassRegistryError, SpaceViewId, - SpaceViewSystemExecutionError, ViewQuery, ViewerContext, + auto_color, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, + SpaceViewState, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, }; use super::visualizer_system::BarChartVisualizerSystem; @@ -14,15 +14,22 @@ use super::visualizer_system::BarChartVisualizerSystem; pub struct BarChartSpaceView; impl SpaceViewClass for BarChartSpaceView { - type State = (); + fn identifier() -> SpaceViewClassIdentifier { + "Bar Chart".into() + } - const IDENTIFIER: &'static str = "Bar Chart"; - const DISPLAY_NAME: &'static str = "Bar Chart"; + fn display_name(&self) -> &'static str { + "Bar Chart" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_HISTOGRAM } + fn new_state(&self) -> Box { + Box::<()>::default() + } + fn help_text(&self, re_ui: &re_ui::ReUi) -> egui::WidgetText { let mut layout = re_ui::LayoutJobBuilder::new(re_ui); @@ -55,7 +62,7 @@ impl SpaceViewClass for BarChartSpaceView { system_registry.register_visualizer::() } - fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { + fn preferred_tile_aspect_ratio(&self, _state: &dyn SpaceViewState) -> Option { None } @@ -75,11 +82,11 @@ impl SpaceViewClass for BarChartSpaceView { &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - _state: &mut Self::State, + _state: &mut dyn SpaceViewState, _space_origin: &EntityPath, _space_view_id: SpaceViewId, root_entity_properties: &mut EntityProperties, - ) { + ) -> Result<(), SpaceViewSystemExecutionError> { ctx.re_ui .selection_grid(ui, "bar_chart_selection_ui") .show(ui, |ui| { @@ -128,13 +135,15 @@ impl SpaceViewClass for BarChartSpaceView { }); ui.end_row(); }); + + Ok(()) } fn ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - _state: &mut Self::State, + _state: &mut dyn SpaceViewState, root_entity_properties: &EntityProperties, query: &ViewQuery<'_>, system_output: re_viewer_context::SystemExecutionOutput, diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index ddb7df26d0ce..99e1c0b75fb3 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -8,8 +8,8 @@ use re_entity_db::{EntityProperties, InstancePath}; use re_log_types::{EntityPath, Timeline}; use re_query::get_component_with_instances; use re_viewer_context::{ - SpaceViewClass, SpaceViewClassRegistryError, SpaceViewId, SpaceViewSystemExecutionError, - SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewState, + SpaceViewSystemExecutionError, SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, }; use crate::visualizer_system::EmptySystem; @@ -18,10 +18,13 @@ use crate::visualizer_system::EmptySystem; pub struct DataframeSpaceView; impl SpaceViewClass for DataframeSpaceView { - type State = (); + fn identifier() -> SpaceViewClassIdentifier { + "Dataframe".into() + } - const IDENTIFIER: &'static str = "Dataframe"; - const DISPLAY_NAME: &'static str = "Dataframe"; + fn display_name(&self) -> &'static str { + "Dataframe" + } fn icon(&self) -> &'static re_ui::Icon { //TODO(ab): fix that icon @@ -44,7 +47,11 @@ impl SpaceViewClass for DataframeSpaceView { system_registry.register_visualizer::() } - fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { + fn new_state(&self) -> Box { + Box::<()>::default() + } + + fn preferred_tile_aspect_ratio(&self, _state: &dyn SpaceViewState) -> Option { None } @@ -60,22 +67,11 @@ impl SpaceViewClass for DataframeSpaceView { Default::default() } - fn selection_ui( - &self, - _ctx: &ViewerContext<'_>, - _ui: &mut egui::Ui, - _state: &mut Self::State, - _space_origin: &EntityPath, - _space_view_id: SpaceViewId, - _root_entity_properties: &mut EntityProperties, - ) { - } - fn ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - _state: &mut Self::State, + _state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, query: &ViewQuery<'_>, _system_output: SystemExecutionOutput, diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index cc391390afbf..5287d841bbcf 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -8,8 +8,9 @@ use re_types::{ Archetype, ComponentName, }; use re_viewer_context::{ - PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassRegistryError, - SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, + PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, + SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, + SpaceViewStateExt as _, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, VisualizableFilterContext, }; @@ -42,10 +43,13 @@ impl VisualizableFilterContext for VisualizableFilterContext2D { pub struct SpatialSpaceView2D; impl SpaceViewClass for SpatialSpaceView2D { - type State = SpatialSpaceViewState; + fn identifier() -> SpaceViewClassIdentifier { + "2D".into() + } - const IDENTIFIER: &'static str = "2D"; - const DISPLAY_NAME: &'static str = "2D"; + fn display_name(&self) -> &'static str { + "2D" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_2D @@ -68,9 +72,18 @@ impl SpaceViewClass for SpatialSpaceView2D { Ok(()) } - fn preferred_tile_aspect_ratio(&self, state: &Self::State) -> Option { - let size = state.bounding_boxes.accumulated.size(); - Some(size.x / size.y) + fn new_state(&self) -> Box { + Box::::default() + } + + fn preferred_tile_aspect_ratio(&self, state: &dyn SpaceViewState) -> Option { + state + .downcast_ref::() + .ok() + .map(|state| { + let size = state.bounding_boxes.accumulated.size(); + size.x / size.y + }) } fn layout_priority(&self) -> re_viewer_context::SpaceViewClassLayoutPriority { @@ -136,10 +149,13 @@ impl SpaceViewClass for SpatialSpaceView2D { fn on_frame_start( &self, ctx: &ViewerContext<'_>, - state: &Self::State, + state: &mut dyn SpaceViewState, ent_paths: &PerSystemEntities, entity_properties: &mut re_entity_db::EntityPropertyMap, ) { + let Ok(state) = state.downcast_mut::() else { + return; + }; update_object_property_heuristics( ctx, ent_paths, @@ -157,7 +173,7 @@ impl SpaceViewClass for SpatialSpaceView2D { let indicated_entities = default_visualized_entities_for_visualizer_kind( ctx, - self.identifier(), + Self::identifier(), SpatialSpaceViewKind::TwoD, ); @@ -221,11 +237,12 @@ impl SpaceViewClass for SpatialSpaceView2D { &self, ctx: &re_viewer_context::ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _space_origin: &EntityPath, _space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, - ) { + ) -> Result<(), SpaceViewSystemExecutionError> { + let state = state.downcast_mut::()?; ctx.re_ui .selection_grid(ui, "spatial_settings_ui") .show(ui, |ui| { @@ -233,19 +250,21 @@ impl SpaceViewClass for SpatialSpaceView2D { state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::TwoD); ui.end_row(); }); + Ok(()) } fn ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, query: &ViewQuery<'_>, system_output: re_viewer_context::SystemExecutionOutput, ) -> Result<(), SpaceViewSystemExecutionError> { re_tracing::profile_function!(); + let state = state.downcast_mut::()?; state.bounding_boxes.update(&system_output.view_systems); state.scene_num_primitives = system_output .context_systems diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index cc389d6ca7fd..91ca48b5d86d 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -9,8 +9,9 @@ use re_types::{ Loggable, }; use re_viewer_context::{ - PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassRegistryError, - SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, + PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, + SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, + SpaceViewStateExt as _, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, VisualizableFilterContext, }; @@ -42,10 +43,13 @@ impl VisualizableFilterContext for VisualizableFilterContext3D { pub struct SpatialSpaceView3D; impl SpaceViewClass for SpatialSpaceView3D { - type State = SpatialSpaceViewState; + fn identifier() -> SpaceViewClassIdentifier { + "3D".into() + } - const IDENTIFIER: &'static str = "3D"; - const DISPLAY_NAME: &'static str = "3D"; + fn display_name(&self) -> &'static str { + "3D" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_3D @@ -55,6 +59,10 @@ impl SpaceViewClass for SpatialSpaceView3D { super::ui_3d::help_text(re_ui) } + fn new_state(&self) -> Box { + Box::::default() + } + fn on_register( &self, system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, @@ -68,7 +76,7 @@ impl SpaceViewClass for SpatialSpaceView3D { Ok(()) } - fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { + fn preferred_tile_aspect_ratio(&self, _state: &dyn SpaceViewState) -> Option { None } @@ -177,7 +185,7 @@ impl SpaceViewClass for SpatialSpaceView3D { let mut indicated_entities = default_visualized_entities_for_visualizer_kind( ctx, - self.identifier(), + Self::identifier(), SpatialSpaceViewKind::ThreeD, ); @@ -247,10 +255,13 @@ impl SpaceViewClass for SpatialSpaceView3D { fn on_frame_start( &self, ctx: &ViewerContext<'_>, - state: &Self::State, + state: &mut dyn SpaceViewState, ent_paths: &PerSystemEntities, entity_properties: &mut re_entity_db::EntityPropertyMap, ) { + let Ok(state) = state.downcast_mut::() else { + return; + }; update_object_property_heuristics( ctx, ent_paths, @@ -264,11 +275,13 @@ impl SpaceViewClass for SpatialSpaceView3D { &self, ctx: &re_viewer_context::ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, space_origin: &EntityPath, space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, - ) { + ) -> Result<(), SpaceViewSystemExecutionError> { + let state = state.downcast_mut::()?; + let scene_view_coordinates = ctx .entity_db .store() @@ -337,19 +350,23 @@ impl SpaceViewClass for SpatialSpaceView3D { state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::ThreeD); ui.end_row(); }); + + Ok(()) } fn ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, query: &ViewQuery<'_>, system_output: re_viewer_context::SystemExecutionOutput, ) -> Result<(), SpaceViewSystemExecutionError> { re_tracing::profile_function!(); + let state = state.downcast_mut::()?; + state.bounding_boxes.update(&system_output.view_systems); state.scene_num_primitives = system_output .context_systems diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index a48423a61b87..4f407245832b 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -45,7 +45,7 @@ where for data_result in query.iter_visible_data_results(System::identifier()) { // The transform that considers pinholes only makes sense if this is a 3D space-view let world_from_entity = - if view_ctx.space_view_class_identifier() == SpatialSpaceView3D.identifier() { + if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() { transforms.reference_from_entity(&data_result.entity_path) } else { transforms.reference_from_entity_ignoring_pinhole( @@ -153,7 +153,7 @@ macro_rules! impl_process_archetype { for data_result in query.iter_visible_data_results(S::identifier()) { // The transform that considers pinholes only makes sense if this is a 3D space-view - let world_from_entity = if view_ctx.space_view_class_identifier() == SpatialSpaceView3D.identifier() { + let world_from_entity = if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() { transforms.reference_from_entity(&data_result.entity_path) } else { transforms.reference_from_entity_ignoring_pinhole( diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index d4d31e107747..e08e822a82ae 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -214,7 +214,7 @@ impl ImageVisualizer { // Parent pinhole should only be relevant to 3D views let parent_pinhole_path = - if ent_context.space_view_class_identifier == SpatialSpaceView3D.identifier() { + if ent_context.space_view_class_identifier == SpatialSpaceView3D::identifier() { transforms.parent_pinhole(ent_path) } else { None @@ -280,7 +280,7 @@ impl ImageVisualizer { // relationship where the image plane grows the bounds which in // turn influence the size of the image plane. // See: https://github.com/rerun-io/rerun/issues/3728 - if ent_context.space_view_class_identifier == SpatialSpaceView2D.identifier() + if ent_context.space_view_class_identifier == SpatialSpaceView2D::identifier() || !ent_props.pinhole_image_plane_distance.is_auto() { self.data.add_bounding_box( @@ -330,7 +330,7 @@ impl ImageVisualizer { // Parent pinhole should only be relevant to 3D views let parent_pinhole_path = - if ent_context.space_view_class_identifier == SpatialSpaceView3D.identifier() { + if ent_context.space_view_class_identifier == SpatialSpaceView3D::identifier() { transforms.parent_pinhole(ent_path) } else { None @@ -418,7 +418,7 @@ impl ImageVisualizer { // relationship where the image plane grows the bounds which in // turn influence the size of the image plane. // See: https://github.com/rerun-io/rerun/issues/3728 - if ent_context.space_view_class_identifier == SpatialSpaceView2D.identifier() + if ent_context.space_view_class_identifier == SpatialSpaceView2D::identifier() || !ent_props.pinhole_image_plane_distance.is_auto() { self.data.add_bounding_box( @@ -456,7 +456,7 @@ impl ImageVisualizer { // Parent pinhole should only be relevant to 3D views let parent_pinhole_path = - if ent_context.space_view_class_identifier == SpatialSpaceView3D.identifier() { + if ent_context.space_view_class_identifier == SpatialSpaceView3D::identifier() { transforms.parent_pinhole(ent_path) } else { None @@ -521,7 +521,7 @@ impl ImageVisualizer { // relationship where the image plane grows the bounds which in // turn influence the size of the image plane. // See: https://github.com/rerun-io/rerun/issues/3728 - if ent_context.space_view_class_identifier == SpatialSpaceView2D.identifier() + if ent_context.space_view_class_identifier == SpatialSpaceView2D::identifier() || !ent_props.pinhole_image_plane_distance.is_auto() { self.data.add_bounding_box( diff --git a/crates/re_space_view_tensor/src/space_view_class.rs b/crates/re_space_view_tensor/src/space_view_class.rs index e4c6df538ce4..ddf038787c30 100644 --- a/crates/re_space_view_tensor/src/space_view_class.rs +++ b/crates/re_space_view_tensor/src/space_view_class.rs @@ -14,9 +14,10 @@ use re_types::{ tensor_data::{DecodedTensor, TensorDataMeaning}, }; use re_viewer_context::{ - gpu_bridge, gpu_bridge::colormap_dropdown_button_ui, SpaceViewClass, - SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, SpaceViewSystemExecutionError, - TensorStatsCache, ViewQuery, ViewerContext, + gpu_bridge::{self, colormap_dropdown_button_ui}, + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, + SpaceViewState, SpaceViewStateExt as _, SpaceViewSystemExecutionError, TensorStatsCache, + ViewQuery, ViewerContext, }; use crate::{tensor_dimension_mapper::dimension_mapping_ui, visualizer_system::TensorSystem}; @@ -135,10 +136,13 @@ impl PerTensorState { } impl SpaceViewClass for TensorSpaceView { - type State = ViewTensorState; + fn identifier() -> SpaceViewClassIdentifier { + "Tensor".into() + } - const IDENTIFIER: &'static str = "Tensor"; - const DISPLAY_NAME: &'static str = "Tensor"; + fn display_name(&self) -> &'static str { + "Tensor" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_TENSOR @@ -155,7 +159,7 @@ impl SpaceViewClass for TensorSpaceView { system_registry.register_visualizer::() } - fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { + fn preferred_tile_aspect_ratio(&self, _state: &dyn SpaceViewState) -> Option { None } @@ -163,20 +167,26 @@ impl SpaceViewClass for TensorSpaceView { re_viewer_context::SpaceViewClassLayoutPriority::Medium } + fn new_state(&self) -> Box { + Box::::default() + } + fn selection_ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _space_origin: &EntityPath, _space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, - ) { + ) -> Result<(), SpaceViewSystemExecutionError> { + let state = state.downcast_mut::()?; if let Some(selected_tensor) = &state.selected_tensor { if let Some(state_tensor) = state.state_tensors.get_mut(selected_tensor) { state_tensor.ui(ctx, ui); } } + Ok(()) } fn spawn_heuristics( @@ -192,12 +202,13 @@ impl SpaceViewClass for TensorSpaceView { &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, _query: &ViewQuery<'_>, system_output: re_viewer_context::SystemExecutionOutput, ) -> Result<(), SpaceViewSystemExecutionError> { re_tracing::profile_function!(); + let state = state.downcast_mut::()?; let tensors = &system_output.view_systems.get::()?.tensors; diff --git a/crates/re_space_view_text_document/src/space_view_class.rs b/crates/re_space_view_text_document/src/space_view_class.rs index a1e2147e54a1..5154de039c99 100644 --- a/crates/re_space_view_text_document/src/space_view_class.rs +++ b/crates/re_space_view_text_document/src/space_view_class.rs @@ -2,9 +2,11 @@ use egui::Label; use re_space_view::suggest_space_view_for_each_entity; use re_viewer_context::external::re_entity_db::EntityProperties; +use re_viewer_context::SpaceViewClassIdentifier; use re_viewer_context::{ external::re_log_types::EntityPath, SpaceViewClass, SpaceViewClassRegistryError, SpaceViewId, - SpaceViewState, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, + SpaceViewState, SpaceViewStateExt as _, SpaceViewSystemExecutionError, ViewQuery, + ViewerContext, }; use crate::visualizer_system::{TextDocumentEntry, TextDocumentSystem}; @@ -45,10 +47,13 @@ impl SpaceViewState for TextDocumentSpaceViewState { pub struct TextDocumentSpaceView; impl SpaceViewClass for TextDocumentSpaceView { - type State = TextDocumentSpaceViewState; + fn identifier() -> SpaceViewClassIdentifier { + "Text Document".into() + } - const IDENTIFIER: &'static str = "Text Document"; - const DISPLAY_NAME: &'static str = "Text Document"; + fn display_name(&self) -> &'static str { + "Text Document" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_TEXT @@ -65,6 +70,10 @@ impl SpaceViewClass for TextDocumentSpaceView { system_registry.register_visualizer::() } + fn new_state(&self) -> Box { + Box::::default() + } + fn layout_priority(&self) -> re_viewer_context::SpaceViewClassLayoutPriority { re_viewer_context::SpaceViewClassLayoutPriority::Low } @@ -73,11 +82,13 @@ impl SpaceViewClass for TextDocumentSpaceView { &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _space_origin: &EntityPath, _space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, - ) { + ) -> Result<(), SpaceViewSystemExecutionError> { + let state = state.downcast_mut::()?; + ctx.re_ui.selection_grid(ui, "text_config").show(ui, |ui| { ctx.re_ui.grid_left_hand_label(ui, "Text style"); ui.vertical(|ui| { @@ -89,6 +100,8 @@ impl SpaceViewClass for TextDocumentSpaceView { }); ui.end_row(); }); + + Ok(()) } fn spawn_heuristics( @@ -104,11 +117,12 @@ impl SpaceViewClass for TextDocumentSpaceView { &self, _ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, _query: &ViewQuery<'_>, system_output: re_viewer_context::SystemExecutionOutput, ) -> Result<(), SpaceViewSystemExecutionError> { + let state = state.downcast_mut::()?; let text_document = system_output.view_systems.get::()?; egui::Frame { diff --git a/crates/re_space_view_text_log/src/space_view_class.rs b/crates/re_space_view_text_log/src/space_view_class.rs index 40ed53674ffc..57758d354d70 100644 --- a/crates/re_space_view_text_log/src/space_view_class.rs +++ b/crates/re_space_view_text_log/src/space_view_class.rs @@ -6,8 +6,8 @@ use re_log_types::{EntityPath, EntityPathFilter, TimePoint, Timeline}; use re_types::components::TextLogLevel; use re_viewer_context::{ level_to_rich_text, IdentifiedViewSystem as _, RecommendedSpaceView, SpaceViewClass, - SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, - SpaceViewSystemExecutionError, ViewQuery, ViewerContext, + SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, + SpaceViewState, SpaceViewStateExt, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, }; use super::visualizer_system::{Entry, TextLogSystem}; @@ -40,10 +40,13 @@ impl SpaceViewState for TextSpaceViewState { pub struct TextSpaceView; impl SpaceViewClass for TextSpaceView { - type State = TextSpaceViewState; + fn identifier() -> SpaceViewClassIdentifier { + "TextLog".into() + } - const IDENTIFIER: &'static str = "TextLog"; - const DISPLAY_NAME: &'static str = "Text Log"; + fn display_name(&self) -> &'static str { + "Text Log" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_LOG @@ -60,7 +63,11 @@ impl SpaceViewClass for TextSpaceView { system_registry.register_visualizer::() } - fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { + fn new_state(&self) -> Box { + Box::::default() + } + + fn preferred_tile_aspect_ratio(&self, _state: &dyn SpaceViewState) -> Option { Some(2.0) // Make text logs wide } @@ -96,11 +103,12 @@ impl SpaceViewClass for TextSpaceView { &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _space_origin: &EntityPath, _space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, - ) { + ) -> Result<(), SpaceViewSystemExecutionError> { + let state = state.downcast_mut::()?; let ViewTextFilters { col_timelines, col_entity_path, @@ -138,18 +146,22 @@ impl SpaceViewClass for TextSpaceView { }); ui.end_row(); }); + + Ok(()) } fn ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, _query: &ViewQuery<'_>, system_output: re_viewer_context::SystemExecutionOutput, ) -> Result<(), SpaceViewSystemExecutionError> { re_tracing::profile_function!(); + + let state = state.downcast_mut::()?; let text = system_output.view_systems.get::()?; // TODO(andreas): Should filter text entries in the part-system instead. diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index a69a7265d371..bd45d955f9ae 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -13,9 +13,10 @@ use re_viewer_context::external::re_entity_db::{ }; use re_viewer_context::{ IdentifiedViewSystem, IndicatedEntities, PerVisualizer, RecommendedSpaceView, - SmallVisualizerSet, SpaceViewClass, SpaceViewClassRegistryError, SpaceViewId, - SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewSystemExecutionError, SystemExecutionOutput, - ViewQuery, ViewSystemIdentifier, ViewerContext, VisualizableEntities, + SmallVisualizerSet, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, + SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt as _, + SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, ViewSystemIdentifier, + ViewerContext, VisualizableEntities, }; use crate::legacy_visualizer_system::LegacyTimeSeriesSystem; @@ -75,10 +76,13 @@ pub struct TimeSeriesSpaceView; const DEFAULT_LEGEND_CORNER: egui_plot::Corner = egui_plot::Corner::RightBottom; impl SpaceViewClass for TimeSeriesSpaceView { - type State = TimeSeriesSpaceViewState; + fn identifier() -> SpaceViewClassIdentifier { + "Time Series".into() + } - const IDENTIFIER: &'static str = "Time Series"; - const DISPLAY_NAME: &'static str = "Time Series"; + fn display_name(&self) -> &'static str { + "Time Series" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_TIMESERIES @@ -123,7 +127,11 @@ impl SpaceViewClass for TimeSeriesSpaceView { Ok(()) } - fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { + fn new_state(&self) -> Box { + Box::::default() + } + + fn preferred_tile_aspect_ratio(&self, _state: &dyn SpaceViewState) -> Option { None } @@ -135,11 +143,13 @@ impl SpaceViewClass for TimeSeriesSpaceView { &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _space_origin: &EntityPath, space_view_id: SpaceViewId, root_entity_properties: &mut EntityProperties, - ) { + ) -> Result<(), SpaceViewSystemExecutionError> { + let state = state.downcast_mut::()?; + ctx.re_ui .selection_grid(ui, "time_series_selection_ui_aggregation") .show(ui, |ui| { @@ -169,6 +179,8 @@ It can greatly improve performance (and readability) in such situations as it pr legend_ui(ctx, space_view_id, ui); axis_ui(ctx, space_view_id, ui, state); + + Ok(()) } fn spawn_heuristics(&self, ctx: &ViewerContext<'_>) -> SpaceViewSpawnHeuristics { @@ -288,13 +300,15 @@ It can greatly improve performance (and readability) in such situations as it pr &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, query: &ViewQuery<'_>, system_output: SystemExecutionOutput, ) -> Result<(), SpaceViewSystemExecutionError> { re_tracing::profile_function!(); + let state = state.downcast_mut::()?; + let blueprint_db = ctx.store_context.blueprint; let blueprint_query = ctx.blueprint_query; diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 579bfb160bac..43f47b8c1021 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -5,9 +5,9 @@ use re_renderer::WgpuResourcePoolStatistics; use re_smart_channel::{ReceiveSet, SmartChannelSource}; use re_ui::{toasts, UICommand, UICommandSender}; use re_viewer_context::{ - command_channel, AppOptions, CommandReceiver, CommandSender, ComponentUiRegistry, - DynSpaceViewClass, PlayState, SpaceViewClassRegistry, SpaceViewClassRegistryError, - StoreContext, SystemCommand, SystemCommandSender, + command_channel, AppOptions, CommandReceiver, CommandSender, ComponentUiRegistry, PlayState, + SpaceViewClass, SpaceViewClassRegistry, SpaceViewClassRegistryError, StoreContext, + SystemCommand, SystemCommandSender, }; use crate::{ @@ -298,7 +298,7 @@ impl App { } /// Adds a new space view class to the viewer. - pub fn add_space_view_class( + pub fn add_space_view_class( &mut self, ) -> Result<(), SpaceViewClassRegistryError> { self.space_view_class_registry.add_class::() diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 0caec1cb5c0a..ac19c50af1c8 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -157,7 +157,7 @@ impl SelectionPanel { // TODO(jleibs): Overrides still require special handling inside the visualizers. // For now, only show the override section for TimeSeries until support is implemented // generically. - if space_view.class_identifier() == TimeSeriesSpaceView::IDENTIFIER + if *space_view.class_identifier() == TimeSeriesSpaceView::identifier() || ctx.app_options.experimental_visualizer_selection { ctx.re_ui @@ -863,16 +863,22 @@ fn blueprint_ui_for_space_view( &root_data_result.accumulated_properties().visible_history, ); - space_view - .class(ctx.space_view_class_registry) - .selection_ui( - ctx, - ui, - space_view_state.space_view_state.as_mut(), - &space_view.space_origin, - space_view.id, - &mut props, + let space_view_class = space_view.class(ctx.space_view_class_registry); + + if let Err(err) = space_view_class.selection_ui( + ctx, + ui, + space_view_state.space_view_state.as_mut(), + &space_view.space_origin, + space_view.id, + &mut props, + ) { + re_log::error!( + "Error in Space View selection UI (class: {}, display name: {}): {err}", + space_view.class_identifier(), + space_view_class.display_name(), ); + } root_data_result.save_individual_override(Some(props), ctx); } diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index 2b072ed9b3a0..7bcb9137c0c2 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -16,9 +16,9 @@ static VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS: once_cell::sync::Lazy< HashSet, > = once_cell::sync::Lazy::new(|| { [ - SpatialSpaceView3D::IDENTIFIER, - SpatialSpaceView2D::IDENTIFIER, - TimeSeriesSpaceView::IDENTIFIER, + SpatialSpaceView3D::identifier(), + SpatialSpaceView2D::identifier(), + TimeSeriesSpaceView::identifier(), ] .map(Into::into) .into() diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 4cf402e7c7e9..868c5d2fa7e6 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -45,15 +45,14 @@ pub use selection_state::{ Selection, SelectionHighlight, }; pub use space_view::{ - DataResult, DynSpaceViewClass, IdentifiedViewSystem, PerSystemDataResults, PerSystemEntities, - PropertyOverrides, RecommendedSpaceView, SmallVisualizerSet, SpaceViewClass, - SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, SpaceViewClassRegistry, - SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, - SpaceViewOutlineMasks, SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewSystemExecutionError, - SpaceViewSystemRegistrator, SystemExecutionOutput, ViewContextCollection, ViewContextSystem, - ViewQuery, ViewSystemIdentifier, VisualizableFilterContext, - VisualizerAdditionalApplicabilityFilter, VisualizerCollection, VisualizerQueryInfo, - VisualizerSystem, + DataResult, IdentifiedViewSystem, PerSystemDataResults, PerSystemEntities, PropertyOverrides, + RecommendedSpaceView, SmallVisualizerSet, SpaceViewClass, SpaceViewClassIdentifier, + SpaceViewClassLayoutPriority, SpaceViewClassRegistry, SpaceViewClassRegistryError, + SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewSpawnHeuristics, + SpaceViewState, SpaceViewStateExt, SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, + SystemExecutionOutput, ViewContextCollection, ViewContextSystem, ViewQuery, + ViewSystemIdentifier, VisualizableFilterContext, VisualizerAdditionalApplicabilityFilter, + VisualizerCollection, VisualizerQueryInfo, VisualizerSystem, }; pub use store_context::StoreContext; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; diff --git a/crates/re_viewer_context/src/space_view/dyn_space_view_class.rs b/crates/re_viewer_context/src/space_view/dyn_space_view_class.rs deleted file mode 100644 index e2acbfd61dfb..000000000000 --- a/crates/re_viewer_context/src/space_view/dyn_space_view_class.rs +++ /dev/null @@ -1,211 +0,0 @@ -use nohash_hasher::IntSet; -use re_entity_db::{EntityProperties, EntityPropertyMap}; -use re_log_types::EntityPath; -use re_types::ComponentName; - -use crate::{ - IndicatedEntities, PerSystemEntities, PerVisualizer, SmallVisualizerSet, - SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewSystemRegistrator, - SystemExecutionOutput, ViewQuery, ViewerContext, VisualizableEntities, -}; - -re_string_interner::declare_new_type!( - /// The unique name of a space view type. - #[derive(serde::Deserialize, serde::Serialize)] - pub struct SpaceViewClassIdentifier; -); - -impl SpaceViewClassIdentifier { - pub fn invalid() -> Self { - Self::from("invalid") - } -} - -#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Ord, Eq)] -pub enum SpaceViewClassLayoutPriority { - /// This space view can share space with others - /// - /// Used for boring things like text and plots. - Low, - - #[default] - Medium, - - /// Give this space view lots of space. - /// Used for spatial views (2D/3D). - High, -} - -/// Context object returned by [`crate::SpaceViewClass::visualizable_filter_context`]. -pub trait VisualizableFilterContext { - fn as_any(&self) -> &dyn std::any::Any; -} - -impl VisualizableFilterContext for () { - fn as_any(&self) -> &dyn std::any::Any { - self - } -} - -/// Defines a class of space view without any concrete types making it suitable for storage and interfacing. -/// -/// Implemented by [`crate::SpaceViewClass`]. -/// -/// Each Space View in the viewer's viewport has a single class assigned immutable at its creation time. -/// The class defines all aspects of its behavior. -/// It determines which entities are queried, how they are rendered, and how the user can interact with them. -/// -/// TODO(andreas): Consider formulating a space view instance context object that is passed to all -/// methods that operate on concrete space views as opposed to be about general information on the class. -pub trait DynSpaceViewClass: Send + Sync { - /// Identifier of this space view class. - /// - /// Used for identification. Must be unique within a viewer session. - fn identifier(&self) -> SpaceViewClassIdentifier; - - /// Identifier string of this space view class. - /// - /// This is similar to [`Self::identifier`] but it can be used without an actual instance of the - /// class. - fn identifier_str() -> &'static str - where - Self: Sized; - - /// User-facing name of this space view class. - /// - /// Used for UI display. - fn display_name(&self) -> &'static str; - - /// Icon used to identify this space view class. - fn icon(&self) -> &'static re_ui::Icon; - - /// Help text describing how to interact with this space view in the ui. - fn help_text(&self, re_ui: &re_ui::ReUi) -> egui::WidgetText; - - /// Called once upon registration of the class - /// - /// This can be used to register all built-in [`crate::ViewContextSystem`] and [`crate::VisualizerSystem`]. - fn on_register( - &self, - system_registry: &mut SpaceViewSystemRegistrator<'_>, - ) -> Result<(), SpaceViewClassRegistryError>; - - /// Called once for every new space view instance of this class. - /// - /// The state is *not* persisted across viewer sessions, only shared frame-to-frame. - fn new_state(&self) -> Box; - - /// Optional archetype of the Space View's blueprint properties. - /// - /// Blueprint components that only apply to the space view itself, not to the entities it displays. - fn blueprint_archetype(&self) -> Option>; - - /// Preferred aspect ratio for the ui tiles of this space view. - fn preferred_tile_aspect_ratio(&self, state: &dyn SpaceViewState) -> Option; - - /// Controls how likely this space view will get a large tile in the ui. - fn layout_priority(&self) -> SpaceViewClassLayoutPriority; - - /// Determines a suitable origin given the provided set of entities. - /// - /// This function only considers the transform topology, disregarding the actual visualizability - /// of the entities (for this, use [`Self::visualizable_filter_context`]). - fn recommended_root_for_entities( - &self, - _entities: &IntSet, - _entity_db: &re_entity_db::EntityDb, - ) -> Option; - - /// Create context object that is passed to all of this classes visualizers - /// to determine whether they can be visualized - /// - /// See [`crate::VisualizerSystem::filter_visualizable_entities`]. - fn visualizable_filter_context( - &self, - space_origin: &EntityPath, - entity_db: &re_entity_db::EntityDb, - ) -> Box; - - /// Choose the default visualizers to enable for this entity. - /// - /// Helpful for customizing fallback behavior for types that are insufficient - /// to determine indicated on their own. - /// - /// Will only be called for entities where the selected visualizers have not - /// been overridden by the blueprint. - /// - /// This interface provides a default implementation which will return all visualizers - /// which are both visualizable and indicated for the given entity. - fn choose_default_visualizers( - &self, - entity_path: &EntityPath, - visualizable_entities_per_visualizer: &PerVisualizer, - indicated_entities_per_visualizer: &PerVisualizer, - ) -> SmallVisualizerSet; - - /// Determines which space views should be spawned by default for this class. - fn spawn_heuristics(&self, ctx: &ViewerContext<'_>) -> SpaceViewSpawnHeuristics; - - /// Executed for all active space views on frame start (before any ui is drawn), - /// can be use for heuristic & state updates before populating the scene. - /// - /// Is only allowed to access archetypes defined by [`Self::blueprint_archetype`] - /// Passed entity properties are individual properties without propagated values. - fn on_frame_start( - &self, - ctx: &ViewerContext<'_>, - state: &mut dyn SpaceViewState, - ent_paths: &PerSystemEntities, - entity_properties: &mut EntityPropertyMap, - ); - - /// Ui shown when the user selects a space view of this class. - /// - /// TODO(andreas): Should this be instead implemented via a registered `data_ui` of all blueprint relevant types? - fn selection_ui( - &self, - ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - state: &mut dyn SpaceViewState, - space_origin: &EntityPath, - space_view_id: SpaceViewId, - root_entity_properties: &mut EntityProperties, - ); - - /// Draws the ui for this space view type and handles ui events. - /// - /// The state passed in was previously created by [`Self::new_state`] and is kept frame-to-frame. - fn ui( - &self, - ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - state: &mut dyn SpaceViewState, - root_entity_properties: &EntityProperties, - query: &ViewQuery<'_>, - system_output: SystemExecutionOutput, - ); -} - -/// Unserialized frame to frame state of a space view. -/// -/// For any state that should be persisted, use the Blueprint! -/// This state is used for transient state, such as animation or uncommitted ui state like dragging a camera. -/// (on mouse release, the camera would be committed to the blueprint). -pub trait SpaceViewState: std::any::Any { - /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. - fn as_any(&self) -> &dyn std::any::Any; - - /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. - fn as_any_mut(&mut self) -> &mut dyn std::any::Any; -} - -/// Implementation of an empty space view state. -impl SpaceViewState for () { - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } -} diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 70298a3ee512..f5d557acd190 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -4,7 +4,6 @@ //! Does not implement any concrete space view. // TODO(andreas): Can we move some of these to the `re_space_view` crate? -mod dyn_space_view_class; mod highlights; mod named_system; mod space_view_class; @@ -17,13 +16,12 @@ mod view_query; mod visualizer_entity_subscriber; mod visualizer_system; -pub use dyn_space_view_class::{ - DynSpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, SpaceViewState, - VisualizableFilterContext, -}; pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; pub use named_system::{IdentifiedViewSystem, PerSystemEntities, ViewSystemIdentifier}; -pub use space_view_class::SpaceViewClass; +pub use space_view_class::{ + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, SpaceViewState, + SpaceViewStateExt, VisualizableFilterContext, +}; pub use space_view_class_registry::{ SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewSystemRegistrator, }; @@ -57,6 +55,9 @@ pub enum SpaceViewSystemExecutionError { #[error(transparent)] GpuTransferError(#[from] re_renderer::CpuWriteGpuReadError), + + #[error("Failed to downcast Space View's to the {0}.")] + StateCastError(&'static str), } // Convenience conversions for some re_renderer error types since these are so frequent. diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index 0f54e567be09..3aac62c4c441 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -1,47 +1,74 @@ use nohash_hasher::IntSet; - -use re_entity_db::{EntityDb, EntityProperties, EntityPropertyMap}; +use re_entity_db::{EntityProperties, EntityPropertyMap}; use re_log_types::EntityPath; use re_types::ComponentName; use crate::{ - DynSpaceViewClass, IndicatedEntities, PerSystemEntities, PerVisualizer, SmallVisualizerSet, - SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, - SpaceViewState, SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, - SystemExecutionOutput, ViewQuery, ViewerContext, VisualizableEntities, - VisualizableFilterContext, + IndicatedEntities, PerSystemEntities, PerVisualizer, SmallVisualizerSet, + SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, + SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, + ViewerContext, VisualizableEntities, }; -/// Defines a class of space view. -/// -/// Each Space View in the viewer's viewport has a single class assigned immutable at its creation time. -/// The class defines all aspects of its behavior. -/// It determines which entities are queried, how they are rendered, and how the user can interact with them. -pub trait SpaceViewClass: std::marker::Sized + Send + Sync { - /// State of a space view. - type State: SpaceViewState + Default + 'static; +re_string_interner::declare_new_type!( + /// The unique name of a space view type. + #[derive(serde::Deserialize, serde::Serialize)] + pub struct SpaceViewClassIdentifier; +); + +impl SpaceViewClassIdentifier { + pub fn invalid() -> Self { + Self::from("invalid") + } +} - /// Name for this space view class. +#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Ord, Eq)] +pub enum SpaceViewClassLayoutPriority { + /// This space view can share space with others /// - /// Used as identifier. - const IDENTIFIER: &'static str; + /// Used for boring things like text and plots. + Low, - /// User-facing name for this space view class - const DISPLAY_NAME: &'static str; + #[default] + Medium, - /// Name of this space view class. - /// - /// Used for identification. Must be unique within a viewer session. - fn identifier(&self) -> SpaceViewClassIdentifier { - Self::IDENTIFIER.into() + /// Give this space view lots of space. + /// Used for spatial views (2D/3D). + High, +} + +/// Context object returned by [`crate::SpaceViewClass::visualizable_filter_context`]. +pub trait VisualizableFilterContext { + fn as_any(&self) -> &dyn std::any::Any; +} + +impl VisualizableFilterContext for () { + fn as_any(&self) -> &dyn std::any::Any { + self } +} - /// User-facing name for this space view class. +/// Defines a class of space view without any concrete types making it suitable for storage and interfacing. +/// +/// Each Space View in the viewer's viewport has a single class assigned immutable at its creation time. +/// The class defines all aspects of its behavior. +/// It determines which entities are queried, how they are rendered, and how the user can interact with them. +/// +/// TODO(andreas): Consider formulating a space view instance context object that is passed to all +/// methods that operate on concrete space views as opposed to be about general information on the class. +pub trait SpaceViewClass: Send + Sync { + /// Identifier string of this space view class. + /// + /// This is similar to [`Self::identifier`] but it can be used without an actual instance of the + /// class. + fn identifier() -> SpaceViewClassIdentifier + where + Self: Sized; + + /// User-facing name of this space view class. /// /// Used for UI display. - fn display_name(&self) -> &'static str { - Self::DISPLAY_NAME - } + fn display_name(&self) -> &'static str; /// Icon used to identify this space view class. fn icon(&self) -> &'static re_ui::Icon { @@ -59,13 +86,25 @@ pub trait SpaceViewClass: std::marker::Sized + Send + Sync { system_registry: &mut SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError>; + /// Called once for every new space view instance of this class. + /// + /// The state is *not* persisted across viewer sessions, only shared frame-to-frame. + fn new_state(&self) -> Box; + + /// Optional archetype of the Space View's blueprint properties. + /// + /// Blueprint components that only apply to the space view itself, not to the entities it displays. + fn blueprint_archetype(&self) -> Option> { + None + } + /// Preferred aspect ratio for the ui tiles of this space view. - fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { + fn preferred_tile_aspect_ratio(&self, _state: &dyn SpaceViewState) -> Option { None } /// Controls how likely this space view will get a large tile in the ui. - fn layout_priority(&self) -> crate::SpaceViewClassLayoutPriority; + fn layout_priority(&self) -> SpaceViewClassLayoutPriority; /// Determines a suitable origin given the provided set of entities. /// @@ -80,7 +119,7 @@ pub trait SpaceViewClass: std::marker::Sized + Send + Sync { } /// Create context object that is passed to all of this classes visualizers - /// to determine whether they can be visualized. + /// to determine whether they can be visualized /// /// See [`crate::VisualizerSystem::filter_visualizable_entities`]. fn visualizable_filter_context( @@ -135,13 +174,6 @@ pub trait SpaceViewClass: std::marker::Sized + Send + Sync { /// Determines which space views should be spawned by default for this class. fn spawn_heuristics(&self, ctx: &ViewerContext<'_>) -> SpaceViewSpawnHeuristics; - /// Optional archetype of the Space View's blueprint properties. - /// - /// Blueprint components that only apply to the space view itself, not to the entities it displays. - fn blueprint_archetype(&self) -> Option> { - None - } - /// Executed for all active space views on frame start (before any ui is drawn), /// can be use for heuristic & state updates before populating the scene. /// @@ -150,24 +182,24 @@ pub trait SpaceViewClass: std::marker::Sized + Send + Sync { fn on_frame_start( &self, _ctx: &ViewerContext<'_>, - _state: &Self::State, + _state: &mut dyn SpaceViewState, _ent_paths: &PerSystemEntities, - _entity_properties: &mut re_entity_db::EntityPropertyMap, + _entity_properties: &mut EntityPropertyMap, ) { } /// Ui shown when the user selects a space view of this class. - /// - /// TODO(andreas): Should this be instead implemented via a registered `data_ui` of all blueprint relevant types? fn selection_ui( &self, - ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - state: &mut Self::State, - space_origin: &EntityPath, - space_view_id: SpaceViewId, - root_entity_properties: &mut EntityProperties, - ); + _ctx: &ViewerContext<'_>, + _ui: &mut egui::Ui, + _state: &mut dyn SpaceViewState, + _space_origin: &EntityPath, + _space_view_id: SpaceViewId, + _root_entity_properties: &mut EntityProperties, + ) -> Result<(), SpaceViewSystemExecutionError> { + Ok(()) + } /// Draws the ui for this space view class and handles ui events. /// @@ -180,184 +212,55 @@ pub trait SpaceViewClass: std::marker::Sized + Send + Sync { &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, root_entity_properties: &EntityProperties, query: &ViewQuery<'_>, system_output: SystemExecutionOutput, ) -> Result<(), SpaceViewSystemExecutionError>; } -impl DynSpaceViewClass for T { - #[inline] - fn identifier(&self) -> SpaceViewClassIdentifier { - self.identifier() - } - - #[inline] - fn identifier_str() -> &'static str { - Self::IDENTIFIER - } - - #[inline] - fn display_name(&self) -> &'static str { - self.display_name() - } - - #[inline] - fn icon(&self) -> &'static re_ui::Icon { - self.icon() - } - - #[inline] - fn help_text(&self, re_ui: &re_ui::ReUi) -> egui::WidgetText { - self.help_text(re_ui) - } - - #[inline] - fn new_state(&self) -> Box { - Box::::default() - } - - fn on_register( - &self, - system_registry: &mut SpaceViewSystemRegistrator<'_>, - ) -> Result<(), SpaceViewClassRegistryError> { - self.on_register(system_registry) - } - - fn preferred_tile_aspect_ratio(&self, state: &dyn SpaceViewState) -> Option { - typed_state_wrapper(state, |state| self.preferred_tile_aspect_ratio(state)) - } - - #[inline] - fn layout_priority(&self) -> crate::SpaceViewClassLayoutPriority { - self.layout_priority() - } - - #[inline] - fn recommended_root_for_entities( - &self, - entities: &IntSet, - entity_db: &EntityDb, - ) -> Option { - self.recommended_root_for_entities(entities, entity_db) - } - - #[inline] - fn visualizable_filter_context( - &self, - space_origin: &EntityPath, - entity_db: &re_entity_db::EntityDb, - ) -> Box { - self.visualizable_filter_context(space_origin, entity_db) - } - - #[inline] - fn choose_default_visualizers( - &self, - entity_path: &EntityPath, - visualizable_entities_per_visualizer: &PerVisualizer, - indicated_entities_per_visualizer: &PerVisualizer, - ) -> SmallVisualizerSet { - self.choose_default_visualizers( - entity_path, - visualizable_entities_per_visualizer, - indicated_entities_per_visualizer, - ) - } - - #[inline] - fn spawn_heuristics(&self, ctx: &ViewerContext<'_>) -> SpaceViewSpawnHeuristics { - self.spawn_heuristics(ctx) - } - - #[inline] - fn blueprint_archetype(&self) -> Option> { - self.blueprint_archetype() - } - - fn on_frame_start( - &self, - ctx: &ViewerContext<'_>, - state: &mut dyn SpaceViewState, - ent_paths: &PerSystemEntities, - entity_properties: &mut EntityPropertyMap, - ) { - typed_state_wrapper_mut(state, |state| { - self.on_frame_start(ctx, state, ent_paths, entity_properties); - }); - } +/// Unserialized frame to frame state of a space view. +/// +/// For any state that should be persisted, use the Blueprint! +/// This state is used for transient state, such as animation or uncommitted ui state like dragging a camera. +/// (on mouse release, the camera would be committed to the blueprint). +pub trait SpaceViewState: std::any::Any { + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. + fn as_any(&self) -> &dyn std::any::Any; + + /// Converts itself to a reference of [`std::any::Any`], which enables downcasting to concrete types. + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; +} - #[inline] - fn selection_ui( - &self, - ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - state: &mut dyn SpaceViewState, - space_origin: &EntityPath, - space_view_id: SpaceViewId, - root_entity_properties: &mut EntityProperties, - ) { - typed_state_wrapper_mut(state, |state| { - self.selection_ui( - ctx, - ui, - state, - space_origin, - space_view_id, - root_entity_properties, - ); - }); +/// Implementation of an empty space view state. +impl SpaceViewState for () { + fn as_any(&self) -> &dyn std::any::Any { + self } - #[allow(clippy::for_kv_map)] - fn ui( - &self, - ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - state: &mut dyn SpaceViewState, - root_entity_properties: &EntityProperties, - query: &ViewQuery<'_>, - system_output: SystemExecutionOutput, - ) { - re_tracing::profile_function!(); - - typed_state_wrapper_mut(state, |state| { - if let Err(err) = self.ui(ctx, ui, state, root_entity_properties, query, system_output) - { - // TODO(andreas): Draw an error message on top of the space view ui instead of logging. - re_log::error_once!("Error drawing ui for space view: {err}"); - } - }); + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self } } -fn typed_state_wrapper_mut R>( - state: &mut dyn SpaceViewState, - fun: F, -) -> R { - if let Some(state) = state.as_any_mut().downcast_mut() { - fun(state) - } else { - re_log::error_once!( - "Unexpected space view state type. Expected {}", - std::any::type_name::() - ); - R::default() +pub trait SpaceViewStateExt: SpaceViewState { + /// Downcasts this state to a reference of a concrete type. + fn downcast_ref(&self) -> Result<&T, SpaceViewSystemExecutionError> { + self.as_any() + .downcast_ref() + .ok_or(SpaceViewSystemExecutionError::StateCastError( + std::any::type_name::(), + )) } -} -fn typed_state_wrapper R>( - state: &dyn SpaceViewState, - fun: F, -) -> R { - if let Some(state) = state.as_any().downcast_ref() { - fun(state) - } else { - re_log::error_once!( - "Unexpected space view state type. Expected {}", - std::any::type_name::() - ); - R::default() + /// Downcasts this state to a mutable reference of a concrete type. + fn downcast_mut(&mut self) -> Result<&mut T, SpaceViewSystemExecutionError> { + self.as_any_mut() + .downcast_mut() + .ok_or(SpaceViewSystemExecutionError::StateCastError( + std::any::type_name::(), + )) } } + +impl SpaceViewStateExt for dyn SpaceViewState {} diff --git a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs index a742f8f8f64b..3ad5ac0a8563 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs @@ -1,7 +1,7 @@ use crate::{ - SpaceViewClass, SpaceViewClassRegistryError, SpaceViewSpawnHeuristics, - SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, - ViewerContext, + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, + SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewSystemExecutionError, + SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, ViewerContext, }; use re_entity_db::EntityProperties; @@ -10,10 +10,13 @@ use re_entity_db::EntityProperties; pub struct SpaceViewClassPlaceholder; impl SpaceViewClass for SpaceViewClassPlaceholder { - type State = (); + fn identifier() -> SpaceViewClassIdentifier { + "Unknown Space View Class".into() + } - const IDENTIFIER: &'static str = "Unknown Space View Class"; - const DISPLAY_NAME: &'static str = "Unknown Space View Class"; + fn display_name(&self) -> &'static str { + "Unknown Space View Class" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_UNKNOWN @@ -30,6 +33,10 @@ impl SpaceViewClass for SpaceViewClassPlaceholder { Ok(()) } + fn new_state(&self) -> Box { + Box::<()>::default() + } + fn layout_priority(&self) -> crate::SpaceViewClassLayoutPriority { crate::SpaceViewClassLayoutPriority::Low } @@ -40,22 +47,11 @@ impl SpaceViewClass for SpaceViewClassPlaceholder { } } - fn selection_ui( - &self, - _ctx: &ViewerContext<'_>, - _ui: &mut egui::Ui, - _state: &mut (), - _space_origin: &re_log_types::EntityPath, - _space_view_id: crate::SpaceViewId, - _root_entity_properties: &mut EntityProperties, - ) { - } - fn ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - _state: &mut Self::State, + _state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, _query: &ViewQuery<'_>, _system_output: SystemExecutionOutput, diff --git a/crates/re_viewer_context/src/space_view/space_view_class_registry.rs b/crates/re_viewer_context/src/space_view/space_view_class_registry.rs index 61dccee7f9a3..722b87851bf7 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_registry.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_registry.rs @@ -2,7 +2,7 @@ use ahash::{HashMap, HashSet}; use re_data_store::DataStore; use crate::{ - ApplicableEntities, DynSpaceViewClass, IdentifiedViewSystem, IndicatedEntities, PerVisualizer, + ApplicableEntities, IdentifiedViewSystem, IndicatedEntities, PerVisualizer, SpaceViewClass, SpaceViewClassIdentifier, ViewContextCollection, ViewContextSystem, ViewSystemIdentifier, VisualizerCollection, VisualizerSystem, }; @@ -123,7 +123,8 @@ impl SpaceViewSystemRegistrator<'_> { /// Space view class entry in [`SpaceViewClassRegistry`]. pub struct SpaceViewClassRegistryEntry { - pub class: Box, + pub class: Box, + pub identifier: SpaceViewClassIdentifier, pub context_system_ids: HashSet, pub visualizer_system_ids: HashSet, } @@ -133,6 +134,7 @@ impl Default for SpaceViewClassRegistryEntry { fn default() -> Self { Self { class: Box::::default(), + identifier: SpaceViewClassPlaceholder::identifier(), context_system_ids: Default::default(), visualizer_system_ids: Default::default(), } @@ -176,14 +178,14 @@ impl SpaceViewClassRegistry { /// Adds a new space view class. /// /// Fails if a space view class with the same name was already registered. - pub fn add_class( + pub fn add_class( &mut self, ) -> Result<(), SpaceViewClassRegistryError> { let class = Box::::default(); let mut registrator = SpaceViewSystemRegistrator { registry: self, - identifier: class.identifier(), + identifier: T::identifier(), context_systems: Default::default(), visualizers: Default::default(), }; @@ -203,6 +205,7 @@ impl SpaceViewClassRegistry { identifier, SpaceViewClassRegistryEntry { class, + identifier, context_system_ids: context_systems, visualizer_system_ids: visualizers, }, @@ -218,10 +221,10 @@ impl SpaceViewClassRegistry { } /// Removes a space view class from the registry. - pub fn remove_class( + pub fn remove_class( &mut self, ) -> Result<(), SpaceViewClassRegistryError> { - let identifier: SpaceViewClassIdentifier = T::identifier_str().into(); + let identifier = T::identifier(); if self.space_view_classes.remove(&identifier).is_none() { return Err(SpaceViewClassRegistryError::UnknownClassIdentifier( identifier, @@ -242,7 +245,7 @@ impl SpaceViewClassRegistry { } /// Queries a Space View type by class name, returning `None` if it is not registered. - fn get_class(&self, name: &SpaceViewClassIdentifier) -> Option<&dyn DynSpaceViewClass> { + fn get_class(&self, name: &SpaceViewClassIdentifier) -> Option<&dyn SpaceViewClass> { self.space_view_classes .get(name) .map(|boxed| boxed.class.as_ref()) @@ -260,10 +263,7 @@ impl SpaceViewClassRegistry { } /// Queries a Space View type by class name and logs if it fails, returning a placeholder class. - pub fn get_class_or_log_error( - &self, - name: &SpaceViewClassIdentifier, - ) -> &dyn DynSpaceViewClass { + pub fn get_class_or_log_error(&self, name: &SpaceViewClassIdentifier) -> &dyn SpaceViewClass { if let Some(result) = self.get_class(name) { result } else { diff --git a/crates/re_viewport/src/add_space_view_or_container_modal.rs b/crates/re_viewport/src/add_space_view_or_container_modal.rs index c24abc119f42..c47135041530 100644 --- a/crates/re_viewport/src/add_space_view_or_container_modal.rs +++ b/crates/re_viewport/src/add_space_view_or_container_modal.rs @@ -113,11 +113,7 @@ fn modal_ui( .iter_registry() .sorted_by_key(|entry| entry.class.display_name()) .map(|entry| { - SpaceViewBlueprint::new( - entry.class.identifier(), - &EntityPath::root(), - Default::default(), - ) + SpaceViewBlueprint::new(entry.identifier, &EntityPath::root(), Default::default()) }) { let icon = space_view.class(ctx.space_view_class_registry).icon(); diff --git a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs index 3dd49a8b3e7f..9d3d386f68e7 100644 --- a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs +++ b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs @@ -28,7 +28,7 @@ impl ContextMenuAction for AddEntitiesToNewSpaceViewAction { let recommended_space_view_classes = recommended_space_views_for_selection(ctx); let other_space_view_classes: IntSet<_> = space_view_class_registry .iter_registry() - .map(|entry| entry.class.identifier()) + .map(|entry| entry.identifier) .collect::>() .difference(&recommended_space_view_classes) .cloned() @@ -102,7 +102,7 @@ fn recommended_space_views_for_selection( let visualizable_entities = determine_visualizable_entities( &applicable_entities_per_visualizer, entity_db, - &space_view_class_registry.new_visualizer_collection(entry.class.identifier()), + &space_view_class_registry.new_visualizer_collection(entry.identifier), &*entry.class, &suggested_root, ); @@ -121,7 +121,7 @@ fn recommended_space_views_for_selection( }); if covered { - output.insert(entry.class.identifier()); + output.insert(entry.identifier); } } diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index f9835dd874ac..08e3f29179c6 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -131,7 +131,7 @@ fn action_list( .iter_registry() .sorted_by_key(|entry| entry.class.display_name()) .map(|entry| { - Box::new(AddSpaceViewAction(entry.class.identifier())) + Box::new(AddSpaceViewAction(entry.identifier)) as Box }) .collect(), diff --git a/crates/re_viewport/src/space_view_entity_picker.rs b/crates/re_viewport/src/space_view_entity_picker.rs index 06781f456be4..644aaaa38463 100644 --- a/crates/re_viewport/src/space_view_entity_picker.rs +++ b/crates/re_viewport/src/space_view_entity_picker.rs @@ -324,7 +324,7 @@ fn create_entity_add_info( ctx.applicable_entities_per_visualizer, ctx.entity_db, &ctx.space_view_class_registry - .new_visualizer_collection(class.identifier()), + .new_visualizer_collection(*space_view.class_identifier()), class, &space_view.space_origin, ); diff --git a/crates/re_viewport/src/space_view_heuristics.rs b/crates/re_viewport/src/space_view_heuristics.rs index fc9e8607ba4b..592c0109b7e5 100644 --- a/crates/re_viewport/src/space_view_heuristics.rs +++ b/crates/re_viewport/src/space_view_heuristics.rs @@ -12,14 +12,13 @@ pub fn default_created_space_views(ctx: &ViewerContext<'_>) -> Vec( ) -> (ViewQuery<'a>, SystemExecutionOutput) { re_tracing::profile_function!(space_view.class_identifier().as_str()); - let class = space_view.class(ctx.space_view_class_registry); - let query_result = ctx.lookup_query_result(space_view.id); let mut per_system_data_results = PerSystemDataResults::default(); @@ -130,7 +128,8 @@ pub fn execute_systems_for_space_view<'a>( highlights, }; - let system_output = create_and_run_space_view_systems(ctx, class.identifier(), &query); + let system_output = + create_and_run_space_view_systems(ctx, *space_view.class_identifier(), &query); (query, system_output) } diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 439f913b4caa..626da984b4e8 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -290,7 +290,7 @@ impl ViewportBlueprint { re_tracing::profile_function!(); for entry in ctx.space_view_class_registry.iter_registry() { - let class_id = entry.class.identifier(); + let class_id = entry.identifier; let SpaceViewSpawnHeuristics { mut recommended_space_views, } = entry.class.spawn_heuristics(ctx); diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index 6397568e9322..4d44316603a2 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -6,9 +6,10 @@ use re_viewer::external::{ re_ui, re_viewer_context::{ HoverHighlight, IdentifiedViewSystem as _, Item, RecommendedSpaceView, SelectionHighlight, - SpaceViewClass, SpaceViewClassLayoutPriority, SpaceViewClassRegistryError, SpaceViewId, - SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewSystemExecutionError, - SpaceViewSystemRegistrator, SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, + SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, + SpaceViewStateExt as _, SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, + SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, }, }; @@ -66,10 +67,14 @@ pub struct ColorCoordinatesSpaceView; impl SpaceViewClass for ColorCoordinatesSpaceView { // State type as described above. - type State = ColorCoordinatesSpaceViewState; - const IDENTIFIER: &'static str = "Color Coordinates"; - const DISPLAY_NAME: &'static str = "Color Coordinates"; + fn identifier() -> SpaceViewClassIdentifier { + "Color Coordinates".into() + } + + fn display_name(&self) -> &'static str { + "Color Coordinates" + } fn icon(&self) -> &'static re_ui::Icon { &re_ui::icons::SPACE_VIEW_GENERIC @@ -87,7 +92,11 @@ impl SpaceViewClass for ColorCoordinatesSpaceView { system_registry.register_visualizer::() } - fn preferred_tile_aspect_ratio(&self, _state: &Self::State) -> Option { + fn new_state(&self) -> Box { + Box::::default() + } + + fn preferred_tile_aspect_ratio(&self, _state: &dyn SpaceViewState) -> Option { // Prefer a square tile if possible. Some(1.0) } @@ -121,11 +130,13 @@ impl SpaceViewClass for ColorCoordinatesSpaceView { &self, _ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _space_origin: &EntityPath, _space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, - ) { + ) -> Result<(), SpaceViewSystemExecutionError> { + let state = state.downcast_mut::()?; + ui.horizontal(|ui| { ui.label("Coordinates mode"); egui::ComboBox::from_id_source("color_coordinates_mode") @@ -139,6 +150,8 @@ impl SpaceViewClass for ColorCoordinatesSpaceView { } }); }); + + Ok(()) } /// The contents of the Space View window and all interaction within it. @@ -148,12 +161,13 @@ impl SpaceViewClass for ColorCoordinatesSpaceView { &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - state: &mut Self::State, + state: &mut dyn SpaceViewState, _root_entity_properties: &EntityProperties, query: &ViewQuery<'_>, system_output: SystemExecutionOutput, ) -> Result<(), SpaceViewSystemExecutionError> { let colors = system_output.view_systems.get::()?; + let state = state.downcast_mut::()?; egui::Frame::default().show(ui, |ui| { let color_at = match state.mode { From 4292f477930883556793cc1a1c325388af5df2ca Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 13 Mar 2024 10:56:32 +0100 Subject: [PATCH 014/508] Incremental logging example improvements + removed from manifest (#5487) This example ended up in the manifest by mistake. ![image](https://github.com/rerun-io/rerun/assets/2910679/0d7fc5a6-58b0-407e-9ec8- --- examples/cpp/incremental_logging/README.md | 1 - examples/cpp/incremental_logging/main.cpp | 39 +++++++++++++++++++ examples/python/incremental_logging/README.md | 1 - examples/python/incremental_logging/main.py | 32 +++++++++++++++ examples/rust/incremental_logging/README.md | 1 - examples/rust/incremental_logging/src/main.rs | 34 ++++++++++++++++ 6 files changed, 105 insertions(+), 3 deletions(-) diff --git a/examples/cpp/incremental_logging/README.md b/examples/cpp/incremental_logging/README.md index 4446300b069c..8903c7e83aad 100644 --- a/examples/cpp/incremental_logging/README.md +++ b/examples/cpp/incremental_logging/README.md @@ -4,7 +4,6 @@ tags = ["3D", "api-example"] description = "Showcases how to incrementally log data belonging to the same archetype." thumbnail = "https://static.rerun.io/incremental_logging/b7a2bd889b09c3840f56dc31bd6d677934ab3126/480w.png" thumbnail_dimensions = [480, 285] -channel = "main" --> diff --git a/examples/cpp/incremental_logging/main.cpp b/examples/cpp/incremental_logging/main.cpp index 07645bed173f..ddd33d96e528 100644 --- a/examples/cpp/incremental_logging/main.cpp +++ b/examples/cpp/incremental_logging/main.cpp @@ -6,10 +6,49 @@ #include #include +static const char* README = R"( +# Incremental Logging + +This example showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. + +It was logged with the following code: +```cpp +std::vector colors(10, rerun::Color(255, 0, 0)); +std::vector radii(10, rerun::Radius(0.1f)); + +// Only log colors and radii once. +rec.set_time_sequence("frame_nr", 0); +rec.log("points", colors, radii); + +std::default_random_engine gen; +std::uniform_real_distribution dist_pos(-5.0f, 5.0f); + +// Then log only the points themselves each frame. +// +// They will automatically re-use the colors and radii logged at the beginning. +for (int i = 0; i < 10; ++i) { + rec.set_time_sequence("frame_nr", i); + + std::vector points(10); + std::generate(points.begin(), points.end(), [&] { + return rerun::Position3D(dist_pos(gen), dist_pos(gen), dist_pos(gen)); + }); + rec.log("points", rerun::Points3D(points)); +} +``` + +Move the time cursor around, and notice how the colors and radii from frame 0 are still picked up by later frames, while the points themselves keep changing every frame. +)"; + int main() { const auto rec = rerun::RecordingStream("rerun_example_incremental_logging"); rec.spawn().exit_on_failure(); + rec.log_timeless( + "readme", + rerun::TextDocument(README).with_media_type(rerun::components::MediaType::markdown()) + ); + // TODO(#5264): just log one once clamp-to-edge semantics land. std::vector colors(10, rerun::Color(255, 0, 0)); std::vector radii(10, rerun::Radius(0.1f)); diff --git a/examples/python/incremental_logging/README.md b/examples/python/incremental_logging/README.md index 0b6e7ef0b668..09ac14766431 100644 --- a/examples/python/incremental_logging/README.md +++ b/examples/python/incremental_logging/README.md @@ -4,7 +4,6 @@ tags = ["3D", "api-example"] description = "Showcases how to incrementally log data belonging to the same archetype." thumbnail = "https://static.rerun.io/incremental_logging/b7a2bd889b09c3840f56dc31bd6d677934ab3126/480w.png" thumbnail_dimensions = [480, 301] -channel = "main" --> diff --git a/examples/python/incremental_logging/main.py b/examples/python/incremental_logging/main.py index d253aa9ca344..933d24b76750 100755 --- a/examples/python/incremental_logging/main.py +++ b/examples/python/incremental_logging/main.py @@ -12,8 +12,40 @@ rr.script_add_args(parser) args = parser.parse_args() + +README = """\ +# Incremental Logging + +This example showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. + +It was logged with the following code: +```python +colors = rr.components.ColorBatch(np.repeat(0xFF0000FF, 10)) +radii = rr.components.RadiusBatch(np.repeat(0.1, 10)) + +# Only log colors and radii once. +rr.set_time_sequence("frame_nr", 0) +rr.log_components("points", [colors, radii]) + +rng = default_rng(12345) + +# Then log only the points themselves each frame. +# +# They will automatically re-use the colors and radii logged at the beginning. +for i in range(10): + rr.set_time_sequence("frame_nr", i) + rr.log("points", rr.Points3D(rng.uniform(-5, 5, size=[10, 3]))) +``` + +Move the time cursor around, and notice how the colors and radii from frame 0 are still picked up by later frames, while the points themselves keep changing every frame. +""" + +# --- + rr.script_setup(args, "rerun_example_incremental_logging") +rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + # TODO(#5264): just log one once clamp-to-edge semantics land. colors = rr.components.ColorBatch(np.repeat(0xFF0000FF, 10)) radii = rr.components.RadiusBatch(np.repeat(0.1, 10)) diff --git a/examples/rust/incremental_logging/README.md b/examples/rust/incremental_logging/README.md index 171212c08f5f..a71984bdf504 100644 --- a/examples/rust/incremental_logging/README.md +++ b/examples/rust/incremental_logging/README.md @@ -4,7 +4,6 @@ tags = ["3D", "api-example"] description = "Showcases how to incrementally log data belonging to the same archetype." thumbnail = "https://static.rerun.io/incremental_logging/b7a2bd889b09c3840f56dc31bd6d677934ab3126/480w.png" thumbnail_dimensions = [480, 285] -channel = "main" --> diff --git a/examples/rust/incremental_logging/src/main.rs b/examples/rust/incremental_logging/src/main.rs index 3a310cf63a00..68cc926ee197 100644 --- a/examples/rust/incremental_logging/src/main.rs +++ b/examples/rust/incremental_logging/src/main.rs @@ -26,7 +26,41 @@ fn main() -> anyhow::Result<()> { run(&rec) } +const README: &str = r#" +# Incremental Logging + +This example showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. + +It was logged with the following code: +```rust +let colors = [rerun::Color::from_rgb(255, 0, 0); 10]; +let radii = [rerun::Radius(0.1); 10]; + +// Only log colors and radii once. +rec.set_time_sequence("frame_nr", 0); +rec.log_component_batches("points", false, /* timeless */ [&colors as &dyn rerun::ComponentBatch, &radii])?; + +let mut rng = rand::thread_rng(); +let dist = Uniform::new(-5., 5.); + +// Then log only the points themselves each frame. +// +// They will automatically re-use the colors and radii logged at the beginning. +for i in 0..10 { + rec.set_time_sequence("frame_nr", i); + rec.log("points", &rerun::Points3D::new((0..10).map(|_| (rng.sample(dist), rng.sample(dist), rng.sample(dist)))))?; +} +``` + +Move the time cursor around, and notice how the colors and radii from frame 0 are still picked up by later frames, while the points themselves keep changing every frame. +"#; + fn run(rec: &rerun::RecordingStream) -> anyhow::Result<()> { + rec.log_timeless( + "readme", + &rerun::TextDocument::new(README).with_media_type(rerun::MediaType::MARKDOWN), + )?; + // TODO(#5264): just log one once clamp-to-edge semantics land. let colors = [rerun::Color::from_rgb(255, 0, 0); 10]; let radii = [rerun::Radius(0.1); 10]; From a16b61a376faee12223f85097f5908d03af1cbc3 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 13 Mar 2024 11:30:00 +0100 Subject: [PATCH 015/508] Save recordings from web viewer (#5488) ### What You can now save recordings from the web viewer. The UI is admittedly pretty ugly (we use [rfd](https://github.com/PolyMeilex/rfd)), but it works. ### Checklist * [x] I have read and agree to [Contributor Guide](https://githubcom/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5488/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5488/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5488/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5488) - [Docs preview](https://rerun.io/preview/ebf6bf5a428eeabe6b61d1bfe9a5f2c578775bcd/docs) - [Examples preview](https://rerun.io/preview/ebf6bf5a428eeabe6b61d1bfe9a5f2c578775bcd/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Clement Rey --- crates/re_data_store/src/store_read.rs | 1 + crates/re_entity_db/src/entity_db.rs | 43 ++++++++++++- crates/re_log_encoding/src/encoder.rs | 18 +++--- crates/re_log_encoding/src/lib.rs | 3 - crates/re_ui/examples/re_ui_example.rs | 4 +- crates/re_ui/src/command.rs | 21 +++---- crates/re_viewer/src/app.rs | 86 +++++++++++++++++++++----- crates/re_viewer/src/saving.rs | 64 +++---------------- crates/re_viewer/src/store_hub.rs | 12 ++-- crates/re_viewer/src/ui/rerun_menu.rs | 21 +++---- scripts/ci/compare.py | 4 +- 11 files changed, 160 insertions(+), 117 deletions(-) diff --git a/crates/re_data_store/src/store_read.rs b/crates/re_data_store/src/store_read.rs index 5c36a08c28f7..516fe472c03c 100644 --- a/crates/re_data_store/src/store_read.rs +++ b/crates/re_data_store/src/store_read.rs @@ -397,6 +397,7 @@ impl DataStore { /// Sort all unsorted indices in the store. pub fn sort_indices_if_needed(&self) { + re_tracing::profile_function!(); for index in self.tables.values() { index.sort_indices_if_needed(); } diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 817c62c747b1..adb947d05d18 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -8,8 +8,9 @@ use re_data_store::{ DataStore, DataStoreConfig, GarbageCollectionOptions, StoreEvent, StoreSubscriber, }; use re_log_types::{ - ApplicationId, DataCell, DataRow, DataTable, EntityPath, EntityPathHash, LogMsg, RowId, - SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, Timeline, + ApplicationId, DataCell, DataRow, DataTable, DataTableResult, EntityPath, EntityPathHash, + LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, TimeRange, TimeRangeF, + Timeline, }; use re_types_core::{components::InstanceKey, Archetype, Loggable}; @@ -510,6 +511,44 @@ impl EntityDb { self.store_info() .map(|info| (info.application_id.0.as_str(), info.started)) } + + /// Export the contents of the current database to a sequence of messages. + /// + /// If `time_selection` is specified, then only data for that specific timeline over that + /// specific time range will be accounted for. + pub fn to_messages( + &self, + time_selection: Option<(Timeline, TimeRangeF)>, + ) -> DataTableResult> { + re_tracing::profile_function!(); + + self.store().sort_indices_if_needed(); + + let set_store_info_msg = self + .store_info_msg() + .map(|msg| LogMsg::SetStoreInfo(msg.clone())); + + let time_filter = time_selection.map(|(timeline, range)| { + ( + timeline, + TimeRange::new(range.min.floor(), range.max.ceil()), + ) + }); + + let data_messages = self.store().to_data_tables(time_filter).map(|table| { + table + .to_arrow_msg() + .map(|msg| LogMsg::ArrowMsg(self.store_id().clone(), msg)) + }); + + let messages: Result, _> = set_store_info_msg + .map(re_log_types::DataTableResult::Ok) + .into_iter() + .chain(data_messages) + .collect(); + + messages + } } // ---------------------------------------------------------------------------- diff --git a/crates/re_log_encoding/src/encoder.rs b/crates/re_log_encoding/src/encoder.rs index 4ae637bb228a..fa00f120493d 100644 --- a/crates/re_log_encoding/src/encoder.rs +++ b/crates/re_log_encoding/src/encoder.rs @@ -75,6 +75,8 @@ impl Encoder { } pub fn append(&mut self, message: &LogMsg) -> Result<(), EncodeError> { + re_tracing::profile_function!(); + self.uncompressed.clear(); rmp_serde::encode::write_named(&mut self.uncompressed, message)?; @@ -119,6 +121,7 @@ pub fn encode<'a>( messages: impl Iterator, write: &mut impl std::io::Write, ) -> Result<(), EncodeError> { + re_tracing::profile_function!(); let mut encoder = Encoder::new(options, write)?; for message in messages { encoder.append(message)?; @@ -126,14 +129,15 @@ pub fn encode<'a>( Ok(()) } -pub fn encode_owned( +pub fn encode_as_bytes<'a>( options: EncodingOptions, - messages: impl Iterator, - write: impl std::io::Write, -) -> Result<(), EncodeError> { - let mut encoder = Encoder::new(options, write)?; + messages: impl Iterator, +) -> Result, EncodeError> { + re_tracing::profile_function!(); + let mut bytes: Vec = vec![]; + let mut encoder = Encoder::new(options, &mut bytes)?; for message in messages { - encoder.append(&message)?; + encoder.append(message)?; } - Ok(()) + Ok(bytes) } diff --git a/crates/re_log_encoding/src/lib.rs b/crates/re_log_encoding/src/lib.rs index a0ae722b66c0..f57e82c32899 100644 --- a/crates/re_log_encoding/src/lib.rs +++ b/crates/re_log_encoding/src/lib.rs @@ -3,7 +3,6 @@ #[cfg(feature = "decoder")] pub mod decoder; #[cfg(feature = "encoder")] -#[cfg(not(target_arch = "wasm32"))] // we do no yet support encoding LogMsgs in the browser pub mod encoder; #[cfg(feature = "encoder")] @@ -121,7 +120,6 @@ impl FileHeader { pub const SIZE: usize = 12; #[cfg(feature = "encoder")] - #[cfg(not(target_arch = "wasm32"))] // we do no yet support encoding LogMsgs in the browser pub fn encode(&self, write: &mut impl std::io::Write) -> Result<(), encoder::EncodeError> { write .write_all(&self.magic) @@ -165,7 +163,6 @@ impl MessageHeader { pub const SIZE: usize = 8; #[cfg(feature = "encoder")] - #[cfg(not(target_arch = "wasm32"))] // we do no yet support encoding LogMsgs in the browser pub fn encode(&self, write: &mut impl std::io::Write) -> Result<(), encoder::EncodeError> { write .write_all(&self.compressed_len.to_le_bytes()) diff --git a/crates/re_ui/examples/re_ui_example.rs b/crates/re_ui/examples/re_ui_example.rs index eeb0e3c1ec81..0075c5babb3d 100644 --- a/crates/re_ui/examples/re_ui_example.rs +++ b/crates/re_ui/examples/re_ui_example.rs @@ -541,8 +541,8 @@ impl ExampleApp { } fn file_menu(ui: &mut egui::Ui, command_sender: &CommandSender) { - UICommand::Save.menu_button_ui(ui, command_sender); - UICommand::SaveSelection.menu_button_ui(ui, command_sender); + UICommand::SaveRecording.menu_button_ui(ui, command_sender); + UICommand::SaveRecordingSelection.menu_button_ui(ui, command_sender); UICommand::Open.menu_button_ui(ui, command_sender); UICommand::Quit.menu_button_ui(ui, command_sender); } diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs index 22fe42c951c0..8792d29f6850 100644 --- a/crates/re_ui/src/command.rs +++ b/crates/re_ui/src/command.rs @@ -14,10 +14,8 @@ pub trait UICommandSender { pub enum UICommand { // Listed in the order they show up in the command palette by default! Open, - #[cfg(not(target_arch = "wasm32"))] - Save, - #[cfg(not(target_arch = "wasm32"))] - SaveSelection, + SaveRecording, + SaveRecordingSelection, CloseCurrentRecording, #[cfg(not(target_arch = "wasm32"))] Quit, @@ -95,12 +93,10 @@ impl UICommand { pub fn text_and_tooltip(self) -> (&'static str, &'static str) { match self { - #[cfg(not(target_arch = "wasm32"))] - Self::Save => ("Save…", "Save all data to a Rerun data file (.rrd)"), + Self::SaveRecording => ("Save recording…", "Save all data to a Rerun data file (.rrd)"), - #[cfg(not(target_arch = "wasm32"))] - Self::SaveSelection => ( - "Save loop selection…", + Self::SaveRecordingSelection => ( + "Save recording (current time selection only)…", "Save data for the current loop selection to a Rerun data file (.rrd)", ), @@ -238,7 +234,6 @@ impl UICommand { KeyboardShortcut::new(Modifiers::COMMAND, key) } - #[cfg(not(target_arch = "wasm32"))] fn cmd_alt(key: Key) -> KeyboardShortcut { KeyboardShortcut::new(Modifiers::COMMAND.plus(Modifiers::ALT), key) } @@ -248,10 +243,8 @@ impl UICommand { } match self { - #[cfg(not(target_arch = "wasm32"))] - Self::Save => Some(cmd(Key::S)), - #[cfg(not(target_arch = "wasm32"))] - Self::SaveSelection => Some(cmd_alt(Key::S)), + Self::SaveRecording => Some(cmd(Key::S)), + Self::SaveRecordingSelection => Some(cmd_alt(Key::S)), Self::Open => Some(cmd(Key::O)), Self::CloseCurrentRecording => None, diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 43f47b8c1021..3f9cc3b737df 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -442,18 +442,17 @@ impl App { cmd: UICommand, ) { match cmd { - #[cfg(not(target_arch = "wasm32"))] - UICommand::Save => { + UICommand::SaveRecording => { save(self, store_context, None); } - #[cfg(not(target_arch = "wasm32"))] - UICommand::SaveSelection => { + UICommand::SaveRecordingSelection => { save( self, store_context, self.state.loop_selection(store_context), ); } + #[cfg(not(target_arch = "wasm32"))] UICommand::Open => { for file_path in open_file_dialog_native() { @@ -1501,13 +1500,13 @@ async fn async_open_rrd_dialog() -> Vec { file_contents } -#[cfg(not(target_arch = "wasm32"))] +#[allow(clippy::needless_pass_by_ref_mut)] fn save( - app: &mut App, + #[allow(unused_variables)] app: &mut App, // only used on native store_context: Option<&StoreContext<'_>>, loop_selection: Option<(re_entity_db::Timeline, re_log_types::TimeRangeF)>, ) { - use crate::saving::save_database_to_file; + re_tracing::profile_function!(); let Some(entity_db) = store_context.as_ref().and_then(|view| view.recording) else { // NOTE: Can only happen if saving through the command palette. @@ -1515,27 +1514,82 @@ fn save( return; }; + let file_name = "data.rrd"; + let title = if loop_selection.is_some() { "Save loop selection" } else { "Save" }; - if let Some(path) = rfd::FileDialog::new() - .set_file_name("data.rrd") - .set_title(title) - .save_file() + // Web + #[cfg(target_arch = "wasm32")] { - let f = match save_database_to_file(entity_db, path, loop_selection) { - Ok(f) => f, + let messages = match entity_db.to_messages(loop_selection) { + Ok(messages) => messages, Err(err) => { re_log::error!("File saving failed: {err}"); return; } }; - if let Err(err) = app.background_tasks.spawn_file_saver(f) { - // NOTE: Can only happen if saving through the command palette. - re_log::error!("File saving failed: {err}"); + + wasm_bindgen_futures::spawn_local(async move { + if let Err(err) = async_save_dialog(file_name, title, &messages).await { + re_log::error!("File saving failed: {err}"); + } + }); + } + + // Native + #[cfg(not(target_arch = "wasm32"))] + { + let path = { + re_tracing::profile_scope!("file_dialog"); + rfd::FileDialog::new() + .set_file_name(file_name) + .set_title(title) + .save_file() + }; + if let Some(path) = path { + let messages = match entity_db.to_messages(loop_selection) { + Ok(messages) => messages, + Err(err) => { + re_log::error!("File saving failed: {err}"); + return; + } + }; + if let Err(err) = app + .background_tasks + .spawn_file_saver(move || crate::saving::encode_to_file(&path, messages.iter())) + { + // NOTE: Can only happen if saving through the command palette. + re_log::error!("File saving failed: {err}"); + } } } } + +#[cfg(target_arch = "wasm32")] +async fn async_save_dialog( + file_name: &str, + title: &str, + messages: &[LogMsg], +) -> anyhow::Result<()> { + use anyhow::Context as _; + + let file_handle = rfd::AsyncFileDialog::new() + .set_file_name(file_name) + .set_title(title) + .save_file() + .await; + + let Some(file_handle) = file_handle else { + return Ok(()); // aborted + }; + + let bytes = re_log_encoding::encoder::encode_as_bytes( + re_log_encoding::EncodingOptions::COMPRESSED, + messages.iter(), + )?; + file_handle.write(&bytes).await.context("Failed to save") +} diff --git a/crates/re_viewer/src/saving.rs b/crates/re_viewer/src/saving.rs index c78e759e388f..0e9d6aeb3c80 100644 --- a/crates/re_viewer/src/saving.rs +++ b/crates/re_viewer/src/saving.rs @@ -1,6 +1,3 @@ -#[cfg(not(target_arch = "wasm32"))] -use re_entity_db::EntityDb; - #[cfg(not(target_arch = "wasm32"))] use re_log_types::ApplicationId; @@ -65,60 +62,17 @@ pub fn default_blueprint_path(app_id: &ApplicationId) -> anyhow::Result, -) -> anyhow::Result anyhow::Result> { - use re_data_store::TimeRange; - +pub fn encode_to_file<'a>( + path: &std::path::Path, + messages: impl Iterator, +) -> anyhow::Result<()> { re_tracing::profile_function!(); - - entity_db.store().sort_indices_if_needed(); - - let set_store_info_msg = entity_db - .store_info_msg() - .map(|msg| LogMsg::SetStoreInfo(msg.clone())); - - let time_filter = time_selection.map(|(timeline, range)| { - ( - timeline, - TimeRange::new(range.min.floor(), range.max.ceil()), - ) - }); - let data_msgs: Result, _> = entity_db - .store() - .to_data_tables(time_filter) - .map(|table| { - table - .to_arrow_msg() - .map(|msg| LogMsg::ArrowMsg(entity_db.store_id().clone(), msg)) - }) - .collect(); - use anyhow::Context as _; - use re_log_types::LogMsg; - let data_msgs = data_msgs.with_context(|| "Failed to export to data tables")?; - - let msgs = std::iter::once(set_store_info_msg) - .flatten() // option - .chain(data_msgs); - - Ok(move || { - re_tracing::profile_scope!("save_to_file"); - use anyhow::Context as _; - let file = std::fs::File::create(path.as_path()) - .with_context(|| format!("Failed to create file at {path:?}"))?; + let mut file = std::fs::File::create(path) + .with_context(|| format!("Failed to create file at {path:?}"))?; - let encoding_options = re_log_encoding::EncodingOptions::COMPRESSED; - re_log_encoding::encoder::encode_owned(encoding_options, msgs, file) - .map(|_| path) - .context("Message encode") - }) + let encoding_options = re_log_encoding::EncodingOptions::COMPRESSED; + re_log_encoding::encoder::encode(encoding_options, messages, &mut file) + .context("Message encode") } diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer/src/store_hub.rs index ca263ed8293c..296fca370624 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer/src/store_hub.rs @@ -10,10 +10,7 @@ use re_query_cache::CachesStats; use re_viewer_context::{AppOptions, StoreContext}; #[cfg(not(target_arch = "wasm32"))] -use crate::{ - loading::load_blueprint_file, - saving::{default_blueprint_path, save_database_to_file}, -}; +use crate::{loading::load_blueprint_file, saving::default_blueprint_path}; /// Interface for accessing all blueprints and recordings /// @@ -342,10 +339,13 @@ impl StoreHub { { let blueprint_path = default_blueprint_path(app_id)?; re_log::debug_once!("Saving blueprint for {app_id} to {blueprint_path:?}"); + + let messages = blueprint.to_messages(None)?; + // TODO(jleibs): Should we push this into a background thread? Blueprints should generally // be small & fast to save, but maybe not once we start adding big pieces of user data? - let file_saver = save_database_to_file(blueprint, blueprint_path, None)?; - file_saver()?; + crate::saving::encode_to_file(&blueprint_path, messages.iter())?; + self.blueprint_last_save .insert(blueprint_id.clone(), blueprint.generation()); } diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index 32c8fb867e93..4591bb970bd3 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -38,14 +38,14 @@ impl App { UICommand::Open.menu_button_ui(ui, &self.command_sender); - #[cfg(not(target_arch = "wasm32"))] - { - self.save_buttons_ui(ui, _store_context); + self.save_buttons_ui(ui, _store_context); - UICommand::CloseCurrentRecording.menu_button_ui(ui, &self.command_sender); + UICommand::CloseCurrentRecording.menu_button_ui(ui, &self.command_sender); - ui.add_space(SPACING); + ui.add_space(SPACING); + #[cfg(not(target_arch = "wasm32"))] + { // On the web the browser controls the zoom let zoom_factor = ui.ctx().zoom_factor(); ui.weak(format!("Current zoom: {:.0}%", zoom_factor * 100.0)) @@ -160,15 +160,13 @@ impl App { } } - // TODO(emilk): support saving data on web - #[cfg(not(target_arch = "wasm32"))] fn save_buttons_ui(&mut self, ui: &mut egui::Ui, store_view: Option<&StoreContext<'_>>) { use re_ui::UICommandSender; let file_save_in_progress = self.background_tasks.is_file_save_in_progress(); - let save_button = UICommand::Save.menu_button(ui.ctx()); - let save_selection_button = UICommand::SaveSelection.menu_button(ui.ctx()); + let save_button = UICommand::SaveRecording.menu_button(ui.ctx()); + let save_selection_button = UICommand::SaveRecordingSelection.menu_button(ui.ctx()); if file_save_in_progress { ui.add_enabled_ui(false, |ui| { @@ -192,7 +190,7 @@ impl App { .clicked() { ui.close_menu(); - self.command_sender.send_ui(UICommand::Save); + self.command_sender.send_ui(UICommand::SaveRecording); } // We need to know the loop selection _before_ we can even display the @@ -209,7 +207,8 @@ impl App { .clicked() { ui.close_menu(); - self.command_sender.send_ui(UICommand::SaveSelection); + self.command_sender + .send_ui(UICommand::SaveRecordingSelection); } }); } diff --git a/scripts/ci/compare.py b/scripts/ci/compare.py index 24a6dabca2ee..282bdffc80b0 100755 --- a/scripts/ci/compare.py +++ b/scripts/ci/compare.py @@ -116,7 +116,9 @@ def compare( unit = get_unit(min(previous_bytes, current_bytes)) div = get_divisor(unit) - if previous == 0: + if previous == current: + change_pct = 0 # e.g. both are zero + elif previous == 0: change_pct = 100 else: change_pct = 100 * (current - previous) / previous From 25bb0f6ae933833e36315b2fbfd732f637db1a65 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 13 Mar 2024 12:00:19 +0100 Subject: [PATCH 016/508] Automatically expand and scroll the blueprint tree when focusing on an item (#5482) ### What Double-clicking on an item, e.g. in a space views, focuses on that item. When that happens, the blueprint tree UI will uncollapse and scroll as needed to bring said item to view. When that item is an entity (e.g. double-clicked in the streams view), then all occurrences of that entity are uncollapsed, and the view scrolls to the first one. https://github.com/rerun-io/rerun/assets/49431240/93b54fb6-ad52-4880-babd-d1001732c4db ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5482/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5482/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5482/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5482) - [Docs preview](https://rerun.io/preview/ce5c582ffbe0844840846373a467a6907fb7b895/docs) - [Examples preview](https://rerun.io/preview/ce5c582ffbe0844840846373a467a6907fb7b895/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 1 + crates/re_viewport/Cargo.toml | 1 + .../actions/collapse_expand_all.rs | 2 +- crates/re_viewport/src/viewport.rs | 7 + crates/re_viewport/src/viewport_blueprint.rs | 37 ++++- .../re_viewport/src/viewport_blueprint_ui.rs | 141 +++++++++++++++++- tests/python/release_checklist/check_focus.py | 57 +++++++ 7 files changed, 234 insertions(+), 12 deletions(-) create mode 100644 tests/python/release_checklist/check_focus.py diff --git a/Cargo.lock b/Cargo.lock index bc7d36d39c56..2d6be4d67224 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5155,6 +5155,7 @@ dependencies = [ "re_ui", "re_viewer_context", "rmp-serde", + "smallvec", ] [[package]] diff --git a/crates/re_viewport/Cargo.toml b/crates/re_viewport/Cargo.toml index a43d9e6a5787..b10509c45c57 100644 --- a/crates/re_viewport/Cargo.toml +++ b/crates/re_viewport/Cargo.toml @@ -49,3 +49,4 @@ nohash-hasher.workspace = true once_cell.workspace = true rayon.workspace = true rmp-serde.workspace = true +smallvec.workspace = true diff --git a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs index bcc1624043e4..74d9878fd02f 100644 --- a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs +++ b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs @@ -46,7 +46,7 @@ impl ContextMenuAction for CollapseExpandAllAction { fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { ctx.viewport_blueprint - .visit_contents_in_container(container_id, &mut |contents| match contents { + .visit_contents_in_container(container_id, &mut |contents, _| match contents { Contents::Container(container_id) => CollapseScope::BlueprintTree .container(*container_id) .set_open(&ctx.egui_context, self.open()), diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index 473395323298..8285bccc8897 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -48,6 +48,13 @@ pub struct ViewportState { /// /// See [`ViewportState::is_candidate_drop_parent_container`] for details. candidate_drop_parent_container_id: Option, + + /// The item that should be focused on in the blueprint tree. + /// + /// Set at each frame by [`Viewport::tree_ui`]. This is similar to + /// [`ViewerContext::focused_item`] but account for how specifically the blueprint tree should + /// handle the focused item. + pub(crate) blueprint_tree_scroll_to_item: Option, } static DEFAULT_PROPS: Lazy = Lazy::::new(Default::default); diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 626da984b4e8..96a5248ed000 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -3,8 +3,9 @@ use std::sync::atomic::{AtomicBool, Ordering}; use ahash::HashMap; use egui_tiles::{SimplificationOptions, TileId}; - use nohash_hasher::IntSet; +use smallvec::SmallVec; + use re_data_store::LatestAtQuery; use re_entity_db::EntityPath; use re_log_types::hash::Hash64; @@ -442,26 +443,50 @@ impl ViewportBlueprint { ) } + /// Walk the entire [`Contents`] tree, starting from the root container. + /// + /// See [`Self::visit_contents_in_container`] for details. + pub fn visit_contents(&self, visitor: &mut impl FnMut(&Contents, &SmallVec<[ContainerId; 4]>)) { + if let Some(root_container) = self.root_container { + self.visit_contents_in_container(&root_container, visitor); + } + } + /// Walk the subtree defined by the provided container id and call `visitor` for each /// [`Contents`]. /// - /// Note: `visitor` is first called for the container passed in argument. + /// Note: + /// - `visitor` is first called for the container passed in argument + /// - `visitor`'s second argument contains the hierarchy leading to the visited contents, from + /// (and including) the container passed in argument pub fn visit_contents_in_container( &self, container_id: &ContainerId, - visitor: &mut impl FnMut(&Contents), + visitor: &mut impl FnMut(&Contents, &SmallVec<[ContainerId; 4]>), + ) { + let mut hierarchy = SmallVec::new(); + self.visit_contents_in_container_impl(container_id, &mut hierarchy, visitor); + } + + fn visit_contents_in_container_impl( + &self, + container_id: &ContainerId, + hierarchy: &mut SmallVec<[ContainerId; 4]>, + visitor: &mut impl FnMut(&Contents, &SmallVec<[ContainerId; 4]>), ) { - visitor(&Contents::Container(*container_id)); + visitor(&Contents::Container(*container_id), hierarchy); if let Some(container) = self.container(container_id) { + hierarchy.push(*container_id); for contents in &container.contents { - visitor(contents); + visitor(contents, hierarchy); match contents { Contents::Container(container_id) => { - self.visit_contents_in_container(container_id, visitor); + self.visit_contents_in_container_impl(container_id, hierarchy, visitor); } Contents::SpaceView(_) => {} } } + hierarchy.pop(); } } diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index b606f0882d65..293eb6863ee4 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -1,6 +1,7 @@ use egui::{Response, Ui}; use itertools::Itertools; use re_data_ui::item_ui::guess_instance_path_icon; +use smallvec::SmallVec; use re_entity_db::InstancePath; use re_log_types::EntityPath; @@ -54,7 +55,7 @@ impl<'a> DataResultNodeOrPath<'a> { impl Viewport<'_, '_> { /// Show the blueprint panel tree view. - pub fn tree_ui(&self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { + pub fn tree_ui(&mut self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { re_tracing::profile_function!(); egui::ScrollArea::both() @@ -62,6 +63,8 @@ impl Viewport<'_, '_> { .auto_shrink([true, false]) .show(ui, |ui| { ctx.re_ui.panel_content(ui, |_, ui| { + self.state.blueprint_tree_scroll_to_item = self.handle_focused_item(ctx, ui); + self.root_container_tree_ui(ctx, ui); let empty_space_response = @@ -81,6 +84,131 @@ impl Viewport<'_, '_> { }); } + /// Expend all required items and compute which item we should scroll to. + fn handle_focused_item(&self, ctx: &ViewerContext<'_>, ui: &egui::Ui) -> Option { + let focused_item = ctx.focused_item.as_ref()?; + match focused_item { + Item::Container(container_id) => { + self.expand_all_contents_until(ui.ctx(), &Contents::Container(*container_id)); + Some(focused_item.clone()) + } + Item::SpaceView(space_view_id) => { + self.expand_all_contents_until(ui.ctx(), &Contents::SpaceView(*space_view_id)); + ctx.focused_item.clone() + } + Item::DataResult(space_view_id, instance_path) => { + self.expand_all_contents_until(ui.ctx(), &Contents::SpaceView(*space_view_id)); + self.expand_all_data_results_until( + ctx, + ui.ctx(), + space_view_id, + &instance_path.entity_path, + ); + + ctx.focused_item.clone() + } + Item::InstancePath(instance_path) => { + let space_view_ids = + self.list_space_views_with_entity(ctx, &instance_path.entity_path); + + // focus on the first matching data result + let res = space_view_ids + .first() + .map(|id| Item::DataResult(*id, instance_path.clone())); + + for space_view_id in space_view_ids { + self.expand_all_contents_until(ui.ctx(), &Contents::SpaceView(space_view_id)); + self.expand_all_data_results_until( + ctx, + ui.ctx(), + &space_view_id, + &instance_path.entity_path, + ); + } + + res + } + + Item::StoreId(_) | Item::ComponentPath(_) => None, + } + } + + /// Expand all containers until reaching the provided content. + fn expand_all_contents_until(&self, egui_ctx: &egui::Context, focused_contents: &Contents) { + //TODO(ab): this could look nicer if `Contents` was declared in re_view_context :) + let expend_contents = |contents: &Contents| match contents { + Contents::Container(container_id) => CollapseScope::BlueprintTree + .container(*container_id) + .set_open(egui_ctx, true), + Contents::SpaceView(space_view_id) => CollapseScope::BlueprintTree + .space_view(*space_view_id) + .set_open(egui_ctx, true), + }; + + self.blueprint.visit_contents(&mut |contents, hierarchy| { + if contents == focused_contents { + expend_contents(contents); + for parent in hierarchy { + expend_contents(&Contents::Container(*parent)); + } + } + }); + } + + /// List all space views that have the provided entity as data result. + #[inline] + fn list_space_views_with_entity( + &self, + ctx: &ViewerContext<'_>, + entity_path: &EntityPath, + ) -> SmallVec<[SpaceViewId; 4]> { + let mut space_view_ids = SmallVec::new(); + self.blueprint.visit_contents(&mut |contents, _| { + if let Contents::SpaceView(space_view_id) = contents { + let result_tree = &ctx.lookup_query_result(*space_view_id).tree; + if result_tree.lookup_node_by_path(entity_path).is_some() { + space_view_ids.push(*space_view_id); + } + } + }); + space_view_ids + } + + /// Expand data results of the provided space view all the way to the provided entity. + #[allow(clippy::unused_self)] + fn expand_all_data_results_until( + &self, + ctx: &ViewerContext<'_>, + egui_ctx: &egui::Context, + space_view_id: &SpaceViewId, + entity_path: &EntityPath, + ) { + let result_tree = &ctx.lookup_query_result(*space_view_id).tree; + if result_tree.lookup_node_by_path(entity_path).is_some() { + if let Some(root_node) = result_tree.root_node() { + EntityPath::incremental_walk(Some(&root_node.data_result.entity_path), entity_path) + .chain(std::iter::once(root_node.data_result.entity_path.clone())) + .for_each(|entity_path| { + CollapseScope::BlueprintTree + .data_result(*space_view_id, entity_path) + .set_open(egui_ctx, true); + }); + } + } + } + + /// Check if the provided item should be scrolled to. + fn scroll_to_me_if_needed(&self, ui: &egui::Ui, item: &Item, response: &egui::Response) { + if Some(item) == self.state.blueprint_tree_scroll_to_item.as_ref() { + // Scroll only if the entity isn't already visible. This is important because that's what + // happens when double-clicking an entity _in the blueprint tree_. In such case, it would be + // annoying to induce a scroll motion. + if !ui.clip_rect().contains_rect(response.rect) { + response.scroll_to_me(Some(egui::Align::Center)); + } + } + } + /// If a group or spaceview has a total of this number of elements, show its subtree by default? fn default_open_for_data_result(group: &DataResultNode) -> bool { let num_children = group.children.len(); @@ -145,6 +273,7 @@ impl Viewport<'_, '_> { &item_response, SelectionUpdateBehavior::UseSelection, ); + self.scroll_to_me_if_needed(ui, &item, &item_response); ctx.select_hovered_on_click(&item_response, item); self.handle_root_container_drag_and_drop_interaction( @@ -218,6 +347,7 @@ impl Viewport<'_, '_> { &response, SelectionUpdateBehavior::UseSelection, ); + self.scroll_to_me_if_needed(ui, &item, &response); ctx.select_hovered_on_click(&response, item); self.blueprint @@ -304,7 +434,7 @@ impl Viewport<'_, '_> { ); // Show 'projections' if there's any items that weren't part of the tree under origin but are directly included. - // The later is important since `+ image/camera/**` necessarily has `image` and `image/camera` in the data result tree. + // The latter is important since `+ image/camera/**` necessarily has `image` and `image/camera` in the data result tree. let mut projections = Vec::new(); result_tree.visit(&mut |node| { if node @@ -312,7 +442,7 @@ impl Viewport<'_, '_> { .entity_path .starts_with(&space_view.space_origin) { - false // If its under the origin, we're not interested, stop recursing. + false // If it's under the origin, we're not interested, stop recursing. } else if node.data_result.tree_prefix_only { true // Keep recursing until we find a projection. } else { @@ -351,6 +481,7 @@ impl Viewport<'_, '_> { &response, SelectionUpdateBehavior::UseSelection, ); + self.scroll_to_me_if_needed(ui, &item, &response); ctx.select_hovered_on_click(&response, item); let content = Contents::SpaceView(*space_view_id); @@ -474,8 +605,7 @@ impl Viewport<'_, '_> { let response = list_item .show_collapsing( ui, - CollapseScope::BlueprintTree - .data_result(space_view.id, node.data_result.entity_path.clone()), + CollapseScope::BlueprintTree.data_result(space_view.id, entity_path.clone()), default_open, |_, ui| { for child in node.children.iter().sorted_by_key(|c| { @@ -526,6 +656,7 @@ impl Viewport<'_, '_> { &response, SelectionUpdateBehavior::UseSelection, ); + self.scroll_to_me_if_needed(ui, &item, &response); ctx.select_hovered_on_click(&response, item); } diff --git a/tests/python/release_checklist/check_focus.py b/tests/python/release_checklist/check_focus.py new file mode 100644 index 000000000000..f2d1bf5a34cd --- /dev/null +++ b/tests/python/release_checklist/check_focus.py @@ -0,0 +1,57 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr + +README = """ +# Focus checks + +## Preparation + +TODO(ab): automate this with blueprints +TODO(ab): add lots of stuff via blueprint to make the tree more crowded and check scrolling + +- Reset the blueprint +- Clone the 3D space view such as to have 2 of them. + +## Checks + +- Collapse all in the blueprint tree. +- Double-click on the box in the first space view, check corresponding space view expands. +- Collapse all in the blueprint tree. +- Double-click on the leaf "boxes3d" entity in the streams view, check both space views expand. +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def log_some_space_views() -> None: + rr.set_time_sequence("frame_nr", 0) + + rr.log( + "/objects/boxes/boxes3d", + rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3), + ) + + +def run(args: Namespace) -> None: + # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but + # I'm not gonna rely on it anyway. + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + log_readme() + log_some_space_views() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) From 6896c2ed22806a3fcfd5d51b89a8324e92b12020 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 13 Mar 2024 13:25:20 +0100 Subject: [PATCH 017/508] Update egui to improve logic for when a submenu gets closed (#5493) ### What * Closes https://github.com/rerun-io/rerun/issues/5412 * egui fix in https://github.com/emilk/egui/pull/4166 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5493/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5493/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5493/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5493) - [Docs preview](https://rerun.io/preview/bbd4a18fcca0b2dfc2b04f14e584fda8ac9a953d/docs) - [Examples preview](https://rerun.io/preview/bbd4a18fcca0b2dfc2b04f14e584fda8ac9a953d/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d6be4d67224..92ed816d8fdc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1567,7 +1567,7 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "bytemuck", "serde", @@ -1576,7 +1576,7 @@ dependencies = [ [[package]] name = "eframe" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "bytemuck", "cocoa", @@ -1611,7 +1611,7 @@ dependencies = [ [[package]] name = "egui" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "accesskit", "ahash", @@ -1627,7 +1627,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "bytemuck", "document-features", @@ -1645,7 +1645,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "accesskit_winit", "arboard", @@ -1674,7 +1674,7 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "egui", "ehttp", @@ -1689,7 +1689,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "bytemuck", "egui", @@ -1706,7 +1706,7 @@ dependencies = [ [[package]] name = "egui_plot" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "egui", ] @@ -1748,7 +1748,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "bytemuck", "serde", @@ -1849,7 +1849,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=f0190320333c8a8f5f5520833d754ada1ce0f529#f0190320333c8a8f5f5520833d754ada1ce0f529" +source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" dependencies = [ "ab_glyph", "ahash", diff --git a/Cargo.toml b/Cargo.toml index cddfa2d1b9ad..855e85452a46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -283,13 +283,13 @@ debug = true # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 -eframe = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 -egui = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 -egui_plot = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 -emath = { git = "https://github.com/emilk/egui.git", rev = "f0190320333c8a8f5f5520833d754ada1ce0f529" } # egui master 2024-03-13 +ecolor = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 +eframe = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 +egui = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 +egui_extras = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 +egui_plot = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 +egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 +emath = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } From e4f1fc95395454bfa0beae07e98de6f1deac298f Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 13 Mar 2024 13:52:05 +0100 Subject: [PATCH 018/508] Save blueprint to file (#5491) ### What * Part of https://github.com/rerun-io/rerun/issues/5294 This adds a command for saving the currently active `.blueprint` file to disk. ![image](https://github.com/rerun-io/rerun/assets/1148717/706006f1-e440-4402-a73d-b78e4c24a936) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5491/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5491/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5491/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5491) - [Docs preview](https://rerun.io/preview/95bfd02278a9a97ec511e87d320ef27d47d479d2/docs) - [Examples preview](https://rerun.io/preview/95bfd02278a9a97ec511e87d320ef27d47d479d2/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view/src/space_view.rs | 7 ++ .../re_space_view/src/space_view_contents.rs | 1 + crates/re_ui/src/command.rs | 4 ++ crates/re_viewer/src/app.rs | 64 +++++++++++++++---- crates/re_viewer/src/background_tasks.rs | 5 +- crates/re_viewer/src/saving.rs | 6 +- crates/re_viewer/src/store_hub.rs | 45 ++++++------- crates/re_viewer/src/ui/rerun_menu.rs | 8 ++- crates/re_viewer_context/src/store_context.rs | 2 + 9 files changed, 93 insertions(+), 49 deletions(-) diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 03c226f78414..c30be095628e 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -553,6 +553,7 @@ mod tests { // No overrides set. Everybody has default values. { let ctx = StoreContext { + app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, recording: Some(&recording), all_recordings: vec![], @@ -595,6 +596,7 @@ mod tests { // Parent is not visible, but children are { let ctx = StoreContext { + app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, recording: Some(&recording), all_recordings: vec![], @@ -643,6 +645,7 @@ mod tests { // Nobody is visible { let ctx = StoreContext { + app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, recording: Some(&recording), all_recordings: vec![], @@ -673,6 +676,7 @@ mod tests { { let root = space_view.root_data_result( &StoreContext { + app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, recording: Some(&recording), all_recordings: vec![], @@ -693,6 +697,7 @@ mod tests { // Everyone has visible history { let ctx = StoreContext { + app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, recording: Some(&recording), all_recordings: vec![], @@ -734,6 +739,7 @@ mod tests { // Child2 has its own visible history { let ctx = StoreContext { + app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, recording: Some(&recording), all_recordings: vec![], @@ -1019,6 +1025,7 @@ mod tests { // Set up a store query and update the overrides. let ctx = StoreContext { + app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, recording: Some(&recording), all_recordings: vec![], diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 033a1e3982c0..773a59e71517 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -628,6 +628,7 @@ mod tests { }); let ctx = StoreContext { + app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, recording: Some(&recording), all_recordings: vec![], diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs index 8792d29f6850..3db65c6ca9de 100644 --- a/crates/re_ui/src/command.rs +++ b/crates/re_ui/src/command.rs @@ -16,6 +16,7 @@ pub enum UICommand { Open, SaveRecording, SaveRecordingSelection, + SaveBlueprint, CloseCurrentRecording, #[cfg(not(target_arch = "wasm32"))] Quit, @@ -100,6 +101,8 @@ impl UICommand { "Save data for the current loop selection to a Rerun data file (.rrd)", ), + Self::SaveBlueprint => ("Save blueprint…", "Save the current viewer setup as a Rerun blueprint file (.blueprint)"), + Self::Open => ("Open…", "Open any supported files (.rrd, images, meshes, …)"), Self::CloseCurrentRecording => ( @@ -245,6 +248,7 @@ impl UICommand { match self { Self::SaveRecording => Some(cmd(Key::S)), Self::SaveRecordingSelection => Some(cmd_alt(Key::S)), + Self::SaveBlueprint => None, Self::Open => Some(cmd(Key::O)), Self::CloseCurrentRecording => None, diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 3f9cc3b737df..a4b90289bf5f 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -443,16 +443,20 @@ impl App { ) { match cmd { UICommand::SaveRecording => { - save(self, store_context, None); + save_recording(self, store_context, None); } UICommand::SaveRecordingSelection => { - save( + save_recording( self, store_context, self.state.loop_selection(store_context), ); } + UICommand::SaveBlueprint => { + save_blueprint(self, store_context); + } + #[cfg(not(target_arch = "wasm32"))] UICommand::Open => { for file_path in open_file_dialog_native() { @@ -1500,17 +1504,14 @@ async fn async_open_rrd_dialog() -> Vec { file_contents } -#[allow(clippy::needless_pass_by_ref_mut)] -fn save( - #[allow(unused_variables)] app: &mut App, // only used on native +fn save_recording( + app: &mut App, store_context: Option<&StoreContext<'_>>, loop_selection: Option<(re_entity_db::Timeline, re_log_types::TimeRangeF)>, ) { - re_tracing::profile_function!(); - let Some(entity_db) = store_context.as_ref().and_then(|view| view.recording) else { // NOTE: Can only happen if saving through the command palette. - re_log::error!("No data to save!"); + re_log::error!("No recording data to save"); return; }; @@ -1519,9 +1520,44 @@ fn save( let title = if loop_selection.is_some() { "Save loop selection" } else { - "Save" + "Save recording" + }; + + save_entity_db( + app, + file_name.to_owned(), + title.to_owned(), + entity_db, + loop_selection, + ); +} + +fn save_blueprint(app: &mut App, store_context: Option<&StoreContext<'_>>) { + let Some(store_context) = store_context else { + re_log::error!("No blueprint to save"); + return; }; + let entity_db = store_context.blueprint; + + let file_name = format!( + "{}.blueprint", + crate::saving::sanitize_app_id(&store_context.app_id) + ); + let title = "Save blueprint"; + save_entity_db(app, file_name, title.to_owned(), entity_db, None); +} + +#[allow(clippy::needless_pass_by_ref_mut)] // `app` is only used on native +fn save_entity_db( + #[allow(unused_variables)] app: &mut App, // only used on native + file_name: String, + title: String, + entity_db: &EntityDb, + loop_selection: Option<(re_log_types::Timeline, re_log_types::TimeRangeF)>, +) { + re_tracing::profile_function!(); + // Web #[cfg(target_arch = "wasm32")] { @@ -1534,7 +1570,7 @@ fn save( }; wasm_bindgen_futures::spawn_local(async move { - if let Err(err) = async_save_dialog(file_name, title, &messages).await { + if let Err(err) = async_save_dialog(&file_name, &title, &messages).await { re_log::error!("File saving failed: {err}"); } }); @@ -1558,10 +1594,10 @@ fn save( return; } }; - if let Err(err) = app - .background_tasks - .spawn_file_saver(move || crate::saving::encode_to_file(&path, messages.iter())) - { + if let Err(err) = app.background_tasks.spawn_file_saver(move || { + crate::saving::encode_to_file(&path, messages.iter())?; + Ok(path) + }) { // NOTE: Can only happen if saving through the command palette. re_log::error!("File saving failed: {err}"); } diff --git a/crates/re_viewer/src/background_tasks.rs b/crates/re_viewer/src/background_tasks.rs index bee0fcf524cf..223aade7b8e2 100644 --- a/crates/re_viewer/src/background_tasks.rs +++ b/crates/re_viewer/src/background_tasks.rs @@ -44,10 +44,9 @@ impl BackgroundTasks { } #[cfg(not(target_arch = "wasm32"))] - pub fn spawn_file_saver(&mut self, f: F) -> anyhow::Result<()> + pub fn spawn_file_saver(&mut self, f: F) -> anyhow::Result<()> where - F: FnOnce() -> T + Send + 'static, - T: Send + 'static, + F: FnOnce() -> anyhow::Result + Send + 'static, { self.spawn_threaded_promise(FILE_SAVER_PROMISE, f) } diff --git a/crates/re_viewer/src/saving.rs b/crates/re_viewer/src/saving.rs index 0e9d6aeb3c80..9788934e2127 100644 --- a/crates/re_viewer/src/saving.rs +++ b/crates/re_viewer/src/saving.rs @@ -1,10 +1,8 @@ -#[cfg(not(target_arch = "wasm32"))] use re_log_types::ApplicationId; -#[cfg(not(target_arch = "wasm32"))] /// Convert to lowercase and replace any character that is not a fairly common /// filename character with '-' -fn sanitize_app_id(app_id: &ApplicationId) -> String { +pub fn sanitize_app_id(app_id: &ApplicationId) -> String { let output = app_id.0.to_lowercase(); output.replace( |c: char| !matches!(c, '0'..='9' | 'a'..='z' | '.' | '_' | '+' | '(' | ')' | '[' | ']'), @@ -12,10 +10,10 @@ fn sanitize_app_id(app_id: &ApplicationId) -> String { ) } -#[cfg(not(target_arch = "wasm32"))] /// Determine the default path for a blueprint based on its `ApplicationId` /// This path should be deterministic and unique. // TODO(#2579): Implement equivalent for web +#[cfg(not(target_arch = "wasm32"))] pub fn default_blueprint_path(app_id: &ApplicationId) -> anyhow::Result { use anyhow::Context; diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer/src/store_hub.rs index 296fca370624..41ff28ecdfd3 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer/src/store_hub.rs @@ -90,33 +90,28 @@ impl StoreHub { /// matching [`ApplicationId`]. pub fn read_context(&mut self) -> Option> { // If we have an app-id, then use it to look up the blueprint. - let blueprint_id = self.selected_application_id.as_ref().map(|app_id| { - self.blueprint_by_app_id - .entry(app_id.clone()) - .or_insert_with(|| StoreId::from_string(StoreKind::Blueprint, app_id.clone().0)) - }); + let app_id = self.selected_application_id.clone()?; + + let blueprint_id = self + .blueprint_by_app_id + .entry(app_id.clone()) + .or_insert_with(|| StoreId::from_string(StoreKind::Blueprint, app_id.clone().0)); - // As long as we have a blueprint-id, create the blueprint. - blueprint_id + // Get or create the blueprint: + self.store_bundle.blueprint_entry(blueprint_id); + let blueprint = self.store_bundle.blueprint(blueprint_id)?; + + let recording = self + .selected_rec_id .as_ref() - .map(|id| self.store_bundle.blueprint_entry(id)); - - // If we have a blueprint, we can return the `StoreContext`. In most - // cases it should have already existed or been created above. - blueprint_id - .and_then(|id| self.store_bundle.blueprint(id)) - .map(|blueprint| { - let recording = self - .selected_rec_id - .as_ref() - .and_then(|id| self.store_bundle.recording(id)); - - StoreContext { - blueprint, - recording, - all_recordings: self.store_bundle.recordings().collect_vec(), - } - }) + .and_then(|id| self.store_bundle.recording(id)); + + Some(StoreContext { + app_id, + blueprint, + recording, + all_recordings: self.store_bundle.recordings().collect_vec(), + }) } /// Keeps track if a recording was ever activated. diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index 4591bb970bd3..08698f451cfd 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -40,6 +40,8 @@ impl App { self.save_buttons_ui(ui, _store_context); + UICommand::SaveBlueprint.menu_button_ui(ui, &self.command_sender); + UICommand::CloseCurrentRecording.menu_button_ui(ui, &self.command_sender); ui.add_space(SPACING); @@ -165,13 +167,13 @@ impl App { let file_save_in_progress = self.background_tasks.is_file_save_in_progress(); - let save_button = UICommand::SaveRecording.menu_button(ui.ctx()); + let save_recording_button = UICommand::SaveRecording.menu_button(ui.ctx()); let save_selection_button = UICommand::SaveRecordingSelection.menu_button(ui.ctx()); if file_save_in_progress { ui.add_enabled_ui(false, |ui| { ui.horizontal(|ui| { - ui.add(save_button); + ui.add(save_recording_button); ui.spinner(); }); ui.horizontal(|ui| { @@ -185,7 +187,7 @@ impl App { .map_or(false, |recording| !recording.is_empty()); ui.add_enabled_ui(entity_db_is_nonempty, |ui| { if ui - .add(save_button) + .add(save_recording_button) .on_hover_text("Save all data to a Rerun data file (.rrd)") .clicked() { diff --git a/crates/re_viewer_context/src/store_context.rs b/crates/re_viewer_context/src/store_context.rs index 505015300f90..c0756192ec0d 100644 --- a/crates/re_viewer_context/src/store_context.rs +++ b/crates/re_viewer_context/src/store_context.rs @@ -1,7 +1,9 @@ use re_entity_db::EntityDb; +use re_log_types::ApplicationId; /// The current Blueprint and Recording being displayed by the viewer pub struct StoreContext<'a> { + pub app_id: ApplicationId, pub blueprint: &'a EntityDb, pub recording: Option<&'a EntityDb>, pub all_recordings: Vec<&'a EntityDb>, From 05d2b987579b4410b1f86294de577aa206c32021 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Wed, 13 Mar 2024 16:03:58 -0400 Subject: [PATCH 019/508] Include blueprint APIs for controlling panel expanded state (#5484) ### What These replace the old python_bridge APIs. Also plumb through some missing components: - Viewport.auto_space_view - Viewport.auto_layout - SpaceView.display_name Updated the old python blueprint example now that the bridge APIs are gone. Example code: ```python blueprint = Blueprint( Viewport( Grid( Spatial2D(name="Rect 0", origin="/", contents=["image", "rect/0"]), Spatial2D(name="Rect 1", origin="/", contents=["image", "rect/1"]), ), auto_space_views=args.auto_space_views, ), BlueprintPanel(expanded=False), SelectionPanel(expanded=False), TimePanel(expanded=False), ) ``` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5484/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5484/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5484/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5484) - [Docs preview](https://rerun.io/preview/f90df2a1f85ae651fa084f28d1fce9f8c10e9754/docs) - [Examples preview](https://rerun.io/preview/f90df2a1f85ae651fa084f28d1fce9f8c10e9754/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../re_types/definitions/rerun/blueprint.fbs | 3 +- .../blueprint/archetypes/panel_blueprint.fbs | 21 ++ .../blueprint/components/panel_expanded.fbs | 20 ++ .../rerun/blueprint/components/panel_view.fbs | 21 -- .../re_types/definitions/rerun/datatypes.fbs | 1 + .../definitions/rerun/datatypes/bool.fbs | 23 ++ .../src/blueprint/components/.gitattributes | 1 + .../re_types/src/blueprint/components/mod.rs | 2 + .../blueprint/components/panel_expanded.rs | 150 +++++++++++ crates/re_types/src/datatypes/.gitattributes | 1 + .../src/datatypes/bool.rs} | 37 ++- crates/re_types/src/datatypes/mod.rs | 2 + .../src/codegen/rust/serializer.rs | 53 ++-- crates/re_viewer/src/app_blueprint.rs | 42 ++- .../src/blueprint/components/.gitattributes | 5 - .../re_viewer/src/blueprint/components/mod.rs | 6 - .../blueprint/components/panel_view_ext.rs | 9 - crates/re_viewer/src/blueprint/mod.rs | 1 - .../src/blueprint/validation_gen/mod.rs | 4 +- .../src/blueprint/archetypes/.gitattributes | 1 + .../src/blueprint/archetypes/mod.rs | 2 + .../blueprint/archetypes/panel_blueprint.rs | 165 ++++++++++++ docs/content/reference/types/datatypes.md | 1 + .../reference/types/datatypes/.gitattributes | 1 + .../content/reference/types/datatypes/bool.md | 16 ++ examples/python/blueprint/main.py | 58 ++-- rerun_cpp/src/rerun/blueprint/archetypes.hpp | 1 + .../rerun/blueprint/archetypes/.gitattributes | 2 + .../blueprint/archetypes/panel_blueprint.cpp | 33 +++ .../blueprint/archetypes/panel_blueprint.hpp | 63 +++++ rerun_cpp/src/rerun/blueprint/components.hpp | 2 +- .../rerun/blueprint/components/.gitattributes | 4 +- .../blueprint/components/panel_expanded.cpp | 57 ++++ .../{panel_view.hpp => panel_expanded.hpp} | 41 +-- rerun_cpp/src/rerun/datatypes.hpp | 1 + rerun_cpp/src/rerun/datatypes/.gitattributes | 2 + .../panel_view.cpp => datatypes/bool.cpp} | 24 +- rerun_cpp/src/rerun/datatypes/bool.hpp | 56 ++++ .../rerun_sdk/rerun/blueprint/__init__.py | 19 +- rerun_py/rerun_sdk/rerun/blueprint/api.py | 252 ++++++++++++++++-- .../rerun/blueprint/archetypes/.gitattributes | 1 + .../rerun/blueprint/archetypes/__init__.py | 2 + .../blueprint/archetypes/panel_blueprint.py | 64 +++++ .../rerun/blueprint/components/.gitattributes | 2 +- .../rerun/blueprint/components/__init__.py | 10 +- .../blueprint/components/panel_expanded.py | 28 ++ .../rerun/blueprint/components/panel_view.py | 57 ---- .../rerun_sdk/rerun/datatypes/.gitattributes | 1 + .../rerun_sdk/rerun/datatypes/__init__.py | 6 + rerun_py/rerun_sdk/rerun/datatypes/bool.py | 58 ++++ .../rerun_sdk/rerun/datatypes/bool_ext.py | 18 ++ .../rerun_sdk/rerun/experimental/__init__.py | 9 +- .../rerun_sdk/rerun/experimental/blueprint.py | 172 ------------ rerun_py/src/python_bridge.rs | 133 +-------- tests/python/blueprint/main.py | 40 +-- 55 files changed, 1218 insertions(+), 586 deletions(-) create mode 100644 crates/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs delete mode 100644 crates/re_types/definitions/rerun/blueprint/components/panel_view.fbs create mode 100644 crates/re_types/definitions/rerun/datatypes/bool.fbs create mode 100644 crates/re_types/src/blueprint/components/panel_expanded.rs rename crates/{re_viewer/src/blueprint/components/panel_view.rs => re_types/src/datatypes/bool.rs} (79%) delete mode 100644 crates/re_viewer/src/blueprint/components/.gitattributes delete mode 100644 crates/re_viewer/src/blueprint/components/mod.rs delete mode 100644 crates/re_viewer/src/blueprint/components/panel_view_ext.rs create mode 100644 crates/re_viewport/src/blueprint/archetypes/panel_blueprint.rs create mode 100644 docs/content/reference/types/datatypes/bool.md create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/components/panel_expanded.cpp rename rerun_cpp/src/rerun/blueprint/components/{panel_view.hpp => panel_expanded.hpp} (54%) rename rerun_cpp/src/rerun/{blueprint/components/panel_view.cpp => datatypes/bool.cpp} (60%) create mode 100644 rerun_cpp/src/rerun/datatypes/bool.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/panel_expanded.py delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/panel_view.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/bool.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/bool_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/experimental/blueprint.py diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index 0cf284a99838..1d629523d648 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -10,7 +10,7 @@ include "./blueprint/components/grid_columns.fbs"; include "./blueprint/components/included_content.fbs"; include "./blueprint/components/included_space_view.fbs"; include "./blueprint/components/lock_range_during_zoom.fbs"; -include "./blueprint/components/panel_view.fbs"; +include "./blueprint/components/panel_expanded.fbs"; include "./blueprint/components/query_expression.fbs"; include "./blueprint/components/root_container.fbs"; include "./blueprint/components/row_share.fbs"; @@ -22,6 +22,7 @@ include "./blueprint/components/visible.fbs"; include "./blueprint/archetypes/background_3d.fbs"; include "./blueprint/archetypes/container_blueprint.fbs"; +include "./blueprint/archetypes/panel_blueprint.fbs"; include "./blueprint/archetypes/space_view_blueprint.fbs"; include "./blueprint/archetypes/space_view_contents.fbs"; include "./blueprint/archetypes/viewport_blueprint.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs new file mode 100644 index 000000000000..ba481becc977 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs @@ -0,0 +1,21 @@ +include "fbs/attributes.fbs"; +include "rust/attributes.fbs"; + +namespace rerun.blueprint.archetypes; + +// --- + +/// Shared state for the 3 collapsible panels. +table PanelBlueprint ( + "attr.rerun.scope": "blueprint", + "attr.rust.derive": "Default", + "attr.rust.override_crate": "re_viewport" +) { + // --- Required --- + + // --- Optional --- + /// Whether or not the panel is expanded. + expanded: rerun.blueprint.components.PanelExpanded ("attr.rerun.component_optional", nullable, order: 1000); + + // TODO(jleibs): Add a float to track how expanded the panel is. +} diff --git a/crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs b/crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs new file mode 100644 index 000000000000..a6479b76c512 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs @@ -0,0 +1,20 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.components; + +// --- + +/// Whether an application panel is expanded or not. +struct PanelExpanded ( + "attr.rerun.scope": "blueprint", + "attr.rust.derive": "Copy, Default, PartialEq, Eq, PartialOrd, Ord", + "attr.rust.repr": "transparent", + "attr.rust.tuple_struct" +) { + expanded: rerun.datatypes.Bool (order: 100); +} diff --git a/crates/re_types/definitions/rerun/blueprint/components/panel_view.fbs b/crates/re_types/definitions/rerun/blueprint/components/panel_view.fbs deleted file mode 100644 index f6b5e7a65315..000000000000 --- a/crates/re_types/definitions/rerun/blueprint/components/panel_view.fbs +++ /dev/null @@ -1,21 +0,0 @@ -include "arrow/attributes.fbs"; -include "python/attributes.fbs"; -include "rust/attributes.fbs"; - -include "rerun/datatypes.fbs"; -include "rerun/attributes.fbs"; - -namespace rerun.blueprint.components; - -// --- - -/// The state of the panels. -/// -/// Unstable. Used for the ongoing blueprint experimentations. -struct PanelView ( - "attr.rerun.scope": "blueprint", - "attr.rust.derive": "Copy", - "attr.rust.override_crate": "re_viewer" -) { - is_expanded: bool (order: 100); -} diff --git a/crates/re_types/definitions/rerun/datatypes.fbs b/crates/re_types/definitions/rerun/datatypes.fbs index 9c70e334df00..3b8adb39a597 100644 --- a/crates/re_types/definitions/rerun/datatypes.fbs +++ b/crates/re_types/definitions/rerun/datatypes.fbs @@ -1,5 +1,6 @@ include "./datatypes/angle.fbs"; include "./datatypes/annotation_info.fbs"; +include "./datatypes/bool.fbs"; include "./datatypes/class_description.fbs"; include "./datatypes/class_description_map_elem.fbs"; include "./datatypes/class_id.fbs"; diff --git a/crates/re_types/definitions/rerun/datatypes/bool.fbs b/crates/re_types/definitions/rerun/datatypes/bool.fbs new file mode 100644 index 000000000000..6a0b7fc811c1 --- /dev/null +++ b/crates/re_types/definitions/rerun/datatypes/bool.fbs @@ -0,0 +1,23 @@ +include "arrow/attributes.fbs"; +include "docs/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.datatypes; + +// --- + +/// A single boolean. +struct Bool ( + "attr.arrow.transparent", + "attr.python.aliases": "bool", + "attr.rust.derive": "Copy, Default, PartialEq, Eq, PartialOrd, Ord", + "attr.rust.repr": "transparent", + "attr.rust.tuple_struct", + "attr.docs.unreleased" +) { + value: bool (order: 100); +} diff --git a/crates/re_types/src/blueprint/components/.gitattributes b/crates/re_types/src/blueprint/components/.gitattributes index ced2ceabb002..9f8d0a8dd3bf 100644 --- a/crates/re_types/src/blueprint/components/.gitattributes +++ b/crates/re_types/src/blueprint/components/.gitattributes @@ -8,6 +8,7 @@ corner2d.rs linguist-generated=true included_content.rs linguist-generated=true lock_range_during_zoom.rs linguist-generated=true mod.rs linguist-generated=true +panel_expanded.rs linguist-generated=true query_expression.rs linguist-generated=true row_share.rs linguist-generated=true space_view_class.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index f9472feaf086..554e1ae416dc 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -7,6 +7,7 @@ mod corner2d; mod corner2d_ext; mod included_content; mod lock_range_during_zoom; +mod panel_expanded; mod query_expression; mod row_share; mod space_view_class; @@ -20,6 +21,7 @@ pub use self::column_share::ColumnShare; pub use self::corner2d::Corner2D; pub use self::included_content::IncludedContent; pub use self::lock_range_during_zoom::LockRangeDuringZoom; +pub use self::panel_expanded::PanelExpanded; pub use self::query_expression::QueryExpression; pub use self::row_share::RowShare; pub use self::space_view_class::SpaceViewClass; diff --git a/crates/re_types/src/blueprint/components/panel_expanded.rs b/crates/re_types/src/blueprint/components/panel_expanded.rs new file mode 100644 index 000000000000..50ca10cbe67b --- /dev/null +++ b/crates/re_types/src/blueprint/components/panel_expanded.rs @@ -0,0 +1,150 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: Whether an application panel is expanded or not. +#[derive(Clone, Debug, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] +#[repr(transparent)] +pub struct PanelExpanded(pub crate::datatypes::Bool); + +impl ::re_types_core::SizeBytes for PanelExpanded { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for PanelExpanded { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for PanelExpanded { + #[inline] + fn borrow(&self) -> &crate::datatypes::Bool { + &self.0 + } +} + +impl std::ops::Deref for PanelExpanded { + type Target = crate::datatypes::Bool; + + #[inline] + fn deref(&self) -> &crate::datatypes::Bool { + &self.0 + } +} + +::re_types_core::macros::impl_into_cow!(PanelExpanded); + +impl ::re_types_core::Loggable for PanelExpanded { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.components.PanelExpanded".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Boolean + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data0): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + let datum = datum.map(|datum| { + let Self(data0) = datum.into_owned(); + data0 + }); + (datum.is_some(), datum) + }) + .unzip(); + let data0_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + BooleanArray::new( + Self::arrow_datatype(), + data0 + .into_iter() + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::Bool(data0) = datum; + data0 + }) + .unwrap_or_default() + }) + .collect(), + data0_bitmap, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok(arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.blueprint.components.PanelExpanded#expanded")? + .into_iter() + .map(|res_or_opt| res_or_opt.map(|v| crate::datatypes::Bool(v))) + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.blueprint.components.PanelExpanded#expanded") + .with_context("rerun.blueprint.components.PanelExpanded")?) + } +} diff --git a/crates/re_types/src/datatypes/.gitattributes b/crates/re_types/src/datatypes/.gitattributes index ecf405502f49..fe920bd960dc 100644 --- a/crates/re_types/src/datatypes/.gitattributes +++ b/crates/re_types/src/datatypes/.gitattributes @@ -3,6 +3,7 @@ .gitattributes linguist-generated=true angle.rs linguist-generated=true annotation_info.rs linguist-generated=true +bool.rs linguist-generated=true class_description.rs linguist-generated=true class_description_map_elem.rs linguist-generated=true class_id.rs linguist-generated=true diff --git a/crates/re_viewer/src/blueprint/components/panel_view.rs b/crates/re_types/src/datatypes/bool.rs similarity index 79% rename from crates/re_viewer/src/blueprint/components/panel_view.rs rename to crates/re_types/src/datatypes/bool.rs index c401d1a7e4cd..55e7ab767f51 100644 --- a/crates/re_viewer/src/blueprint/components/panel_view.rs +++ b/crates/re_types/src/datatypes/bool.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/panel_view.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/bool.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -21,13 +21,12 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Component**: The state of the panels. -/// -/// Unstable. Used for the ongoing blueprint experimentations. -#[derive(Clone, Debug, Copy)] -pub struct PanelView(pub bool); +/// **Datatype**: A single boolean. +#[derive(Clone, Debug, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] +#[repr(transparent)] +pub struct Bool(pub bool); -impl ::re_types_core::SizeBytes for PanelView { +impl ::re_types_core::SizeBytes for Bool { #[inline] fn heap_size_bytes(&self) -> u64 { self.0.heap_size_bytes() @@ -39,28 +38,28 @@ impl ::re_types_core::SizeBytes for PanelView { } } -impl From for PanelView { +impl From for Bool { #[inline] - fn from(is_expanded: bool) -> Self { - Self(is_expanded) + fn from(value: bool) -> Self { + Self(value) } } -impl From for bool { +impl From for bool { #[inline] - fn from(value: PanelView) -> Self { + fn from(value: Bool) -> Self { value.0 } } -::re_types_core::macros::impl_into_cow!(PanelView); +::re_types_core::macros::impl_into_cow!(Bool); -impl ::re_types_core::Loggable for PanelView { - type Name = ::re_types_core::ComponentName; +impl ::re_types_core::Loggable for Bool { + type Name = ::re_types_core::DatatypeName; #[inline] fn name() -> Self::Name { - "rerun.blueprint.components.PanelView".into() + "rerun.datatypes.Bool".into() } #[allow(clippy::wildcard_imports)] @@ -121,12 +120,12 @@ impl ::re_types_core::Loggable for PanelView { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.components.PanelView#is_expanded")? + .with_context("rerun.datatypes.Bool#value")? .into_iter() .map(|v| v.ok_or_else(DeserializationError::missing_data)) .map(|res| res.map(|v| Some(Self(v)))) .collect::>>>() - .with_context("rerun.blueprint.components.PanelView#is_expanded") - .with_context("rerun.blueprint.components.PanelView")?) + .with_context("rerun.datatypes.Bool#value") + .with_context("rerun.datatypes.Bool")?) } } diff --git a/crates/re_types/src/datatypes/mod.rs b/crates/re_types/src/datatypes/mod.rs index f400fc5b8f38..cc7296e88223 100644 --- a/crates/re_types/src/datatypes/mod.rs +++ b/crates/re_types/src/datatypes/mod.rs @@ -4,6 +4,7 @@ mod angle; mod angle_ext; mod annotation_info; mod annotation_info_ext; +mod bool; mod class_description; mod class_description_ext; mod class_description_map_elem; @@ -61,6 +62,7 @@ mod vec4d_ext; pub use self::angle::Angle; pub use self::annotation_info::AnnotationInfo; +pub use self::bool::Bool; pub use self::class_description::ClassDescription; pub use self::class_description_map_elem::ClassDescriptionMapElem; pub use self::class_id::ClassId; diff --git a/crates/re_types_builder/src/codegen/rust/serializer.rs b/crates/re_types_builder/src/codegen/rust/serializer.rs index f9e17d304c4e..60cfef561a4b 100644 --- a/crates/re_types_builder/src/codegen/rust/serializer.rs +++ b/crates/re_types_builder/src/codegen/rust/serializer.rs @@ -411,7 +411,8 @@ fn quote_arrow_field_serializer( let inner_is_arrow_transparent = inner_obj.map_or(false, |obj| obj.datatype.is_none()); match datatype.to_logical_type() { - DataType::Int8 + DataType::Boolean + | DataType::Int8 | DataType::Int16 | DataType::Int32 | DataType::Int64 @@ -458,35 +459,35 @@ fn quote_arrow_field_serializer( } }; - match inner_repr { - // A primitive that's an inner element of a list will already have been mapped - // to a buffer type. - InnerRepr::ArrowBuffer => quote! { - PrimitiveArray::new( - #quoted_datatype, - #data_src, - #bitmap_src, - ).boxed() - }, - InnerRepr::NativeIterable => quote! { - PrimitiveArray::new( + if datatype.to_logical_type() == &DataType::Boolean { + quote! { + BooleanArray::new( #quoted_datatype, + // NOTE: We need values for all slots, regardless of what the bitmap says, + // hence `unwrap_or_default`. #data_src.into_iter() #quoted_transparent_mapping .collect(), #bitmap_src, ).boxed() - }, - } - } - - DataType::Boolean => { - quote! { - BooleanArray::new( - #quoted_datatype, - // NOTE: We need values for all slots, regardless of what the bitmap says, - // hence `unwrap_or_default`. - #data_src.into_iter().map(|v| v.unwrap_or_default()).collect(), - #bitmap_src, - ).boxed() + } + } else { + match inner_repr { + // A primitive that's an inner element of a list will already have been mapped + // to a buffer type. + InnerRepr::ArrowBuffer => quote! { + PrimitiveArray::new( + #quoted_datatype, + #data_src, + #bitmap_src, + ).boxed() + }, + InnerRepr::NativeIterable => quote! { + PrimitiveArray::new( + #quoted_datatype, + #data_src.into_iter() #quoted_transparent_mapping .collect(), + #bitmap_src, + ).boxed() + }, + } } } diff --git a/crates/re_viewer/src/app_blueprint.rs b/crates/re_viewer/src/app_blueprint.rs index 8c5f8297dc12..395bcad6acbb 100644 --- a/crates/re_viewer/src/app_blueprint.rs +++ b/crates/re_viewer/src/app_blueprint.rs @@ -1,11 +1,15 @@ -use crate::blueprint::components::PanelView; use re_data_store::LatestAtQuery; use re_entity_db::EntityDb; use re_log_types::{DataRow, EntityPath, RowId, TimePoint}; +use re_types::blueprint::components::PanelExpanded; use re_viewer_context::{ blueprint_timepoint_for_writes, CommandSender, StoreContext, SystemCommand, SystemCommandSender, }; +pub const BLUEPRINT_PANEL_PATH: &str = "blueprint_panel"; +pub const SELECTION_PANEL_PATH: &str = "selection_panel"; +pub const TIME_PANEL_PATH: &str = "time_panel"; + /// Blueprint for top-level application pub struct AppBlueprint<'a> { blueprint_db: Option<&'a EntityDb>, @@ -33,18 +37,16 @@ impl<'a> AppBlueprint<'a> { if let Some(blueprint_db) = blueprint_db { if let Some(expanded) = - load_panel_state(&PanelView::BLUEPRINT_VIEW_PATH.into(), blueprint_db, query) + load_panel_state(&BLUEPRINT_PANEL_PATH.into(), blueprint_db, query) { ret.blueprint_panel_expanded = expanded; } if let Some(expanded) = - load_panel_state(&PanelView::SELECTION_VIEW_PATH.into(), blueprint_db, query) + load_panel_state(&SELECTION_PANEL_PATH.into(), blueprint_db, query) { ret.selection_panel_expanded = expanded; } - if let Some(expanded) = - load_panel_state(&PanelView::TIMELINE_VIEW_PATH.into(), blueprint_db, query) - { + if let Some(expanded) = load_panel_state(&TIME_PANEL_PATH.into(), blueprint_db, query) { ret.time_panel_expanded = expanded; } } @@ -55,47 +57,43 @@ impl<'a> AppBlueprint<'a> { pub fn toggle_blueprint_panel(&self, command_sender: &CommandSender) { let blueprint_panel_expanded = !self.blueprint_panel_expanded; self.send_panel_expanded( - PanelView::BLUEPRINT_VIEW_PATH, + BLUEPRINT_PANEL_PATH, blueprint_panel_expanded, command_sender, ); if self.is_narrow_screen && self.blueprint_panel_expanded { - self.send_panel_expanded(PanelView::SELECTION_VIEW_PATH, false, command_sender); + self.send_panel_expanded(SELECTION_PANEL_PATH, false, command_sender); } } pub fn toggle_selection_panel(&self, command_sender: &CommandSender) { let selection_panel_expanded = !self.selection_panel_expanded; self.send_panel_expanded( - PanelView::SELECTION_VIEW_PATH, + SELECTION_PANEL_PATH, selection_panel_expanded, command_sender, ); if self.is_narrow_screen && self.blueprint_panel_expanded { - self.send_panel_expanded(PanelView::BLUEPRINT_VIEW_PATH, false, command_sender); + self.send_panel_expanded(BLUEPRINT_PANEL_PATH, false, command_sender); } } pub fn toggle_time_panel(&self, command_sender: &CommandSender) { - self.send_panel_expanded( - PanelView::TIMELINE_VIEW_PATH, - !self.time_panel_expanded, - command_sender, - ); + self.send_panel_expanded(TIME_PANEL_PATH, !self.time_panel_expanded, command_sender); } } pub fn setup_welcome_screen_blueprint(welcome_screen_blueprint: &mut EntityDb) { for (panel_name, is_expanded) in [ - (PanelView::BLUEPRINT_VIEW_PATH, true), - (PanelView::SELECTION_VIEW_PATH, false), - (PanelView::TIMELINE_VIEW_PATH, false), + (BLUEPRINT_PANEL_PATH, true), + (SELECTION_PANEL_PATH, false), + (TIME_PANEL_PATH, false), ] { let entity_path = EntityPath::from(panel_name); // TODO(jleibs): Seq instead of timeless? let timepoint = TimePoint::timeless(); - let component = PanelView(is_expanded); + let component = PanelExpanded(is_expanded.into()); let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, [component]) .unwrap(); // Can only fail if we have the wrong number of instances for the component, and we don't @@ -118,7 +116,7 @@ impl<'a> AppBlueprint<'a> { let timepoint = blueprint_timepoint_for_writes(); - let component = PanelView(is_expanded); + let component = PanelExpanded(is_expanded.into()); let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, [component]) @@ -140,6 +138,6 @@ fn load_panel_state( re_tracing::profile_function!(); blueprint_db .store() - .query_latest_component_quiet::(path, query) - .map(|p| p.0) + .query_latest_component_quiet::(path, query) + .map(|p| p.0 .0) } diff --git a/crates/re_viewer/src/blueprint/components/.gitattributes b/crates/re_viewer/src/blueprint/components/.gitattributes deleted file mode 100644 index 45c858ca5099..000000000000 --- a/crates/re_viewer/src/blueprint/components/.gitattributes +++ /dev/null @@ -1,5 +0,0 @@ -# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs - -.gitattributes linguist-generated=true -mod.rs linguist-generated=true -panel_view.rs linguist-generated=true diff --git a/crates/re_viewer/src/blueprint/components/mod.rs b/crates/re_viewer/src/blueprint/components/mod.rs deleted file mode 100644 index 709b135a99b6..000000000000 --- a/crates/re_viewer/src/blueprint/components/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs - -mod panel_view; -mod panel_view_ext; - -pub use self::panel_view::PanelView; diff --git a/crates/re_viewer/src/blueprint/components/panel_view_ext.rs b/crates/re_viewer/src/blueprint/components/panel_view_ext.rs deleted file mode 100644 index 7b0aa64ea5e1..000000000000 --- a/crates/re_viewer/src/blueprint/components/panel_view_ext.rs +++ /dev/null @@ -1,9 +0,0 @@ -use super::PanelView; - -impl PanelView { - // TODO(jleibs): Would be nice if this could be a const EntityPath but making - // the hash const is a bit of a pain. - pub const BLUEPRINT_VIEW_PATH: &'static str = "blueprint_view"; - pub const SELECTION_VIEW_PATH: &'static str = "selection_view"; - pub const TIMELINE_VIEW_PATH: &'static str = "timeline_view"; -} diff --git a/crates/re_viewer/src/blueprint/mod.rs b/crates/re_viewer/src/blueprint/mod.rs index 485b113ad4e0..542d93ba57ec 100644 --- a/crates/re_viewer/src/blueprint/mod.rs +++ b/crates/re_viewer/src/blueprint/mod.rs @@ -1,4 +1,3 @@ -pub mod components; #[cfg(not(target_arch = "wasm32"))] pub mod validation; #[cfg(not(target_arch = "wasm32"))] diff --git a/crates/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/re_viewer/src/blueprint/validation_gen/mod.rs index b933e95e29c0..e33d2eb05e11 100644 --- a/crates/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/re_viewer/src/blueprint/validation_gen/mod.rs @@ -1,6 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/blueprint_validation.rs use super::validation::validate_component; -pub use crate::blueprint::components::PanelView; pub use re_entity_db::blueprint::components::EntityPropertiesComponent; use re_entity_db::EntityDb; pub use re_types::blueprint::components::ActiveTab; @@ -9,6 +8,7 @@ pub use re_types::blueprint::components::ColumnShare; pub use re_types::blueprint::components::Corner2D; pub use re_types::blueprint::components::IncludedContent; pub use re_types::blueprint::components::LockRangeDuringZoom; +pub use re_types::blueprint::components::PanelExpanded; pub use re_types::blueprint::components::QueryExpression; pub use re_types::blueprint::components::RowShare; pub use re_types::blueprint::components::SpaceViewClass; @@ -39,7 +39,7 @@ pub fn is_valid_blueprint(blueprint: &EntityDb) -> bool { && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) - && validate_component::(blueprint) + && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) diff --git a/crates/re_viewport/src/blueprint/archetypes/.gitattributes b/crates/re_viewport/src/blueprint/archetypes/.gitattributes index af8b16152051..0c2be0e6ac46 100644 --- a/crates/re_viewport/src/blueprint/archetypes/.gitattributes +++ b/crates/re_viewport/src/blueprint/archetypes/.gitattributes @@ -3,4 +3,5 @@ .gitattributes linguist-generated=true container_blueprint.rs linguist-generated=true mod.rs linguist-generated=true +panel_blueprint.rs linguist-generated=true viewport_blueprint.rs linguist-generated=true diff --git a/crates/re_viewport/src/blueprint/archetypes/mod.rs b/crates/re_viewport/src/blueprint/archetypes/mod.rs index fe094e103313..ce5986f78d2b 100644 --- a/crates/re_viewport/src/blueprint/archetypes/mod.rs +++ b/crates/re_viewport/src/blueprint/archetypes/mod.rs @@ -1,7 +1,9 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs mod container_blueprint; +mod panel_blueprint; mod viewport_blueprint; pub use self::container_blueprint::ContainerBlueprint; +pub use self::panel_blueprint::PanelBlueprint; pub use self::viewport_blueprint::ViewportBlueprint; diff --git a/crates/re_viewport/src/blueprint/archetypes/panel_blueprint.rs b/crates/re_viewport/src/blueprint/archetypes/panel_blueprint.rs new file mode 100644 index 000000000000..0e74f1fc1bab --- /dev/null +++ b/crates/re_viewport/src/blueprint/archetypes/panel_blueprint.rs @@ -0,0 +1,165 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Shared state for the 3 collapsible panels. +#[derive(Clone, Debug, Default)] +pub struct PanelBlueprint { + /// Whether or not the panel is expanded. + pub expanded: Option, +} + +impl ::re_types_core::SizeBytes for PanelBlueprint { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.expanded.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + } +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.PanelBlueprintIndicator".into()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.PanelExpanded".into(), + "rerun.components.InstanceKey".into(), + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.PanelBlueprintIndicator".into(), + "rerun.blueprint.components.PanelExpanded".into(), + "rerun.components.InstanceKey".into(), + ] + }); + +impl PanelBlueprint { + pub const NUM_COMPONENTS: usize = 3usize; +} + +/// Indicator component for the [`PanelBlueprint`] [`::re_types_core::Archetype`] +pub type PanelBlueprintIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for PanelBlueprint { + type Indicator = PanelBlueprintIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.PanelBlueprint".into() + } + + #[inline] + fn indicator() -> MaybeOwnedComponentBatch<'static> { + static INDICATOR: PanelBlueprintIndicator = PanelBlueprintIndicator::DEFAULT; + MaybeOwnedComponentBatch::Ref(&INDICATOR) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let expanded = + if let Some(array) = arrays_by_name.get("rerun.blueprint.components.PanelExpanded") { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.PanelBlueprint#expanded")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { expanded }) + } +} + +impl ::re_types_core::AsComponents for PanelBlueprint { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + self.expanded + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch).into()), + ] + .into_iter() + .flatten() + .collect() + } + + #[inline] + fn num_instances(&self) -> usize { + 0 + } +} + +impl PanelBlueprint { + pub fn new() -> Self { + Self { expanded: None } + } + + #[inline] + pub fn with_expanded( + mut self, + expanded: impl Into, + ) -> Self { + self.expanded = Some(expanded.into()); + self + } +} diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index 9bc0c16c5b21..57ab7ca7b854 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -9,6 +9,7 @@ Data types are the lowest layer of the data model hierarchy * [`Angle`](datatypes/angle.md) * [`AnnotationInfo`](datatypes/annotation_info.md) +* [`Bool`](datatypes/bool.md) * [`ClassDescription`](datatypes/class_description.md) * [`ClassDescriptionMapElem`](datatypes/class_description_map_elem.md) * [`ClassId`](datatypes/class_id.md) diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index c9c2f3a81adc..6e766a712369 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -3,6 +3,7 @@ .gitattributes linguist-generated=true angle.md linguist-generated=true annotation_info.md linguist-generated=true +bool.md linguist-generated=true class_description.md linguist-generated=true class_description_map_elem.md linguist-generated=true class_id.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/bool.md b/docs/content/reference/types/datatypes/bool.md new file mode 100644 index 000000000000..3326327cc2ae --- /dev/null +++ b/docs/content/reference/types/datatypes/bool.md @@ -0,0 +1,16 @@ +--- +title: "Bool" +--- + +A single boolean. + +## Fields + +* value: `bool` + +## Links + * 🌊 [C++ API docs for `Bool`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Bool.html?speculative-link) + * 🐍 [Python API docs for `Bool`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.Bool) + * 🦀 [Rust API docs for `Bool`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Bool.html?speculative-link) + + diff --git a/examples/python/blueprint/main.py b/examples/python/blueprint/main.py index 2a8bc427949b..51fd984dd1a1 100755 --- a/examples/python/blueprint/main.py +++ b/examples/python/blueprint/main.py @@ -1,57 +1,51 @@ #!/usr/bin/env python3 """Example of using the blueprint APIs to configure Rerun.""" -# TODO(jleibs): Update this example to use the new APIs from __future__ import annotations import argparse import numpy as np import rerun as rr # pip install rerun-sdk -import rerun.experimental as rr_exp +from rerun.blueprint.api import Blueprint, BlueprintPanel, Grid, SelectionPanel, Spatial2D, TimePanel, Viewport def main() -> None: parser = argparse.ArgumentParser(description="Different options for how we might use blueprint") - parser.add_argument("--blueprint-only", action="store_true", help="Only send the blueprint") parser.add_argument("--skip-blueprint", action="store_true", help="Don't send the blueprint") - parser.add_argument( - "--no-append-default", action="store_false", help="Append to the default blueprint instead of replacing it" - ) parser.add_argument("--auto-space-views", action="store_true", help="Automatically add space views") args = parser.parse_args() - if args.blueprint_only: - # If only using blueprint, it's important to specify init_logging=False - rr.init( - "Blueprint demo", - init_logging=False, - spawn=True, - ) + if args.skip_blueprint: + blueprint = None else: - rr.init( - "Blueprint demo", - spawn=True, + # Create a blueprint which includes 2 additional views each only showing 1 of the two + # rectangles. + # + # If auto_space_views is True, the blueprint will automatically add one of the heuristic + # space views, which will include the image and both rectangles. + blueprint = Blueprint( + Viewport( + Grid( + Spatial2D(name="Rect 0", origin="/", contents=["image", "rect/0"]), + Spatial2D(name="Rect 1", origin="/", contents=["image", "rect/1"]), + ), + auto_space_views=args.auto_space_views, + ), + BlueprintPanel(expanded=False), + SelectionPanel(expanded=False), + TimePanel(expanded=False), ) - if not args.blueprint_only: - img = np.zeros([128, 128, 3], dtype="uint8") - for i in range(8): - img[(i * 16) + 4 : (i * 16) + 12, :] = (0, 0, 200) - rr.log("image", rr.Image(img)) - rr.log("rect/0", rr.Boxes2D(mins=[16, 16], sizes=[64, 64], labels="Rect0", colors=(255, 0, 0))) - rr.log("rect/1", rr.Boxes2D(mins=[48, 48], sizes=[64, 64], labels="Rect1", colors=(0, 255, 0))) - - if not args.skip_blueprint: - if args.auto_space_views: - rr_exp.set_auto_space_views(True) + rr.init("rerun_example_blueprint", spawn=True, blueprint=blueprint) - rr_exp.set_panels(all_expanded=False) - - rr_exp.add_space_view( - name="overlaid", space_view_class="2D", origin="/", entity_paths=["image", "rect/0", "rect/1"] - ) + img = np.zeros([128, 128, 3], dtype="uint8") + for i in range(8): + img[(i * 16) + 4 : (i * 16) + 12, :] = (0, 0, 200) + rr.log("image", rr.Image(img)) + rr.log("rect/0", rr.Boxes2D(mins=[16, 16], sizes=[64, 64], labels="Rect0", colors=(255, 0, 0))) + rr.log("rect/1", rr.Boxes2D(mins=[48, 48], sizes=[64, 64], labels="Rect1", colors=(0, 255, 0))) if __name__ == "__main__": diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index 238fc9ef64cd..ef60a3d1b936 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -4,6 +4,7 @@ #include "blueprint/archetypes/background3d.hpp" #include "blueprint/archetypes/container_blueprint.hpp" +#include "blueprint/archetypes/panel_blueprint.hpp" #include "blueprint/archetypes/plot_legend.hpp" #include "blueprint/archetypes/scalar_axis.hpp" #include "blueprint/archetypes/space_view_blueprint.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index 6862e81c32db..358568f59312 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -5,6 +5,8 @@ background3d.cpp linguist-generated=true background3d.hpp linguist-generated=true container_blueprint.cpp linguist-generated=true container_blueprint.hpp linguist-generated=true +panel_blueprint.cpp linguist-generated=true +panel_blueprint.hpp linguist-generated=true plot_legend.cpp linguist-generated=true plot_legend.hpp linguist-generated=true scalar_axis.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp new file mode 100644 index 000000000000..a42069149ffb --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.cpp @@ -0,0 +1,33 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs". + +#include "panel_blueprint.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const blueprint::archetypes::PanelBlueprint& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(2); + + if (archetype.expanded.has_value()) { + auto result = DataCell::from_loggable(archetype.expanded.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = PanelBlueprint::IndicatorComponent(); + auto result = DataCell::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp new file mode 100644 index 000000000000..7a903fa0d7a6 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp @@ -0,0 +1,63 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs". + +#pragma once + +#include "../../blueprint/components/panel_expanded.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../data_cell.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Shared state for the 3 collapsible panels. + struct PanelBlueprint { + /// Whether or not the panel is expanded. + std::optional expanded; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.PanelBlueprintIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + PanelBlueprint() = default; + PanelBlueprint(PanelBlueprint&& other) = default; + + /// Whether or not the panel is expanded. + PanelBlueprint with_expanded(rerun::blueprint::components::PanelExpanded _expanded) && { + expanded = std::move(_expanded); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// Returns the number of primary instances of this archetype. + size_t num_instances() const { + return 0; + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::PanelBlueprint& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index 5971ebeec9fc..fc45185e5696 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -14,7 +14,7 @@ #include "blueprint/components/included_content.hpp" #include "blueprint/components/included_space_view.hpp" #include "blueprint/components/lock_range_during_zoom.hpp" -#include "blueprint/components/panel_view.hpp" +#include "blueprint/components/panel_expanded.hpp" #include "blueprint/components/query_expression.hpp" #include "blueprint/components/root_container.hpp" #include "blueprint/components/row_share.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index 1890d3618645..a77b30d84754 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -25,8 +25,8 @@ included_space_view.cpp linguist-generated=true included_space_view.hpp linguist-generated=true lock_range_during_zoom.cpp linguist-generated=true lock_range_during_zoom.hpp linguist-generated=true -panel_view.cpp linguist-generated=true -panel_view.hpp linguist-generated=true +panel_expanded.cpp linguist-generated=true +panel_expanded.hpp linguist-generated=true query_expression.cpp linguist-generated=true query_expression.hpp linguist-generated=true root_container.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/panel_expanded.cpp b/rerun_cpp/src/rerun/blueprint/components/panel_expanded.cpp new file mode 100644 index 000000000000..de51eb1f8191 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/panel_expanded.cpp @@ -0,0 +1,57 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs". + +#include "panel_expanded.hpp" + +#include "../../datatypes/bool.hpp" + +#include +#include + +namespace rerun::blueprint::components {} + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = Loggable::arrow_datatype(); + return datatype; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::BooleanBuilder* builder, const blueprint::components::PanelExpanded* elements, + size_t num_elements + ) { + static_assert( + sizeof(rerun::datatypes::Bool) == sizeof(blueprint::components::PanelExpanded) + ); + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + builder, + reinterpret_cast(elements), + num_elements + )); + + return Error::ok(); + } + + Result> Loggable::to_arrow( + const blueprint::components::PanelExpanded* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK( + Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + ) + ); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/panel_view.hpp b/rerun_cpp/src/rerun/blueprint/components/panel_expanded.hpp similarity index 54% rename from rerun_cpp/src/rerun/blueprint/components/panel_view.hpp rename to rerun_cpp/src/rerun/blueprint/components/panel_expanded.hpp index b81ea8ea6af0..aa5f694cdd1d 100644 --- a/rerun_cpp/src/rerun/blueprint/components/panel_view.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/panel_expanded.hpp @@ -1,8 +1,9 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/panel_view.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs". #pragma once +#include "../../datatypes/bool.hpp" #include "../../result.hpp" #include @@ -15,21 +16,31 @@ namespace arrow { } // namespace arrow namespace rerun::blueprint::components { - /// **Component**: The state of the panels. - /// - /// Unstable. Used for the ongoing blueprint experimentations. - struct PanelView { - bool is_expanded; + /// **Component**: Whether an application panel is expanded or not. + struct PanelExpanded { + rerun::datatypes::Bool expanded; public: - PanelView() = default; + PanelExpanded() = default; - PanelView(bool is_expanded_) : is_expanded(is_expanded_) {} + PanelExpanded(rerun::datatypes::Bool expanded_) : expanded(expanded_) {} - PanelView& operator=(bool is_expanded_) { - is_expanded = is_expanded_; + PanelExpanded& operator=(rerun::datatypes::Bool expanded_) { + expanded = expanded_; return *this; } + + PanelExpanded(bool value_) : expanded(value_) {} + + PanelExpanded& operator=(bool value_) { + expanded = value_; + return *this; + } + + /// Cast to the underlying Bool datatype + operator rerun::datatypes::Bool() const { + return expanded; + } }; } // namespace rerun::blueprint::components @@ -39,21 +50,21 @@ namespace rerun { /// \private template <> - struct Loggable { - static constexpr const char Name[] = "rerun.blueprint.components.PanelView"; + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.PanelExpanded"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( - arrow::BooleanBuilder* builder, const blueprint::components::PanelView* elements, + arrow::BooleanBuilder* builder, const blueprint::components::PanelExpanded* elements, size_t num_elements ); - /// Serializes an array of `rerun::blueprint:: components::PanelView` into an arrow array. + /// Serializes an array of `rerun::blueprint:: components::PanelExpanded` into an arrow array. static Result> to_arrow( - const blueprint::components::PanelView* instances, size_t num_instances + const blueprint::components::PanelExpanded* instances, size_t num_instances ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 60d458ef8f9a..7f33e559abe9 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -4,6 +4,7 @@ #include "datatypes/angle.hpp" #include "datatypes/annotation_info.hpp" +#include "datatypes/bool.hpp" #include "datatypes/class_description.hpp" #include "datatypes/class_description_map_elem.hpp" #include "datatypes/class_id.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 3fe8d752c348..5c61073231da 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -5,6 +5,8 @@ angle.cpp linguist-generated=true angle.hpp linguist-generated=true annotation_info.cpp linguist-generated=true annotation_info.hpp linguist-generated=true +bool.cpp linguist-generated=true +bool.hpp linguist-generated=true class_description.cpp linguist-generated=true class_description.hpp linguist-generated=true class_description_map_elem.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/panel_view.cpp b/rerun_cpp/src/rerun/datatypes/bool.cpp similarity index 60% rename from rerun_cpp/src/rerun/blueprint/components/panel_view.cpp rename to rerun_cpp/src/rerun/datatypes/bool.cpp index 1446f72fe809..b01282f23e30 100644 --- a/rerun_cpp/src/rerun/blueprint/components/panel_view.cpp +++ b/rerun_cpp/src/rerun/datatypes/bool.cpp @@ -1,23 +1,21 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/panel_view.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/bool.fbs". -#include "panel_view.hpp" +#include "bool.hpp" #include #include -namespace rerun::blueprint::components {} +namespace rerun::datatypes {} namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { + const std::shared_ptr& Loggable::arrow_datatype() { static const auto datatype = arrow::boolean(); return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::BooleanBuilder* builder, const blueprint::components::PanelView* elements, - size_t num_elements + rerun::Error Loggable::fill_arrow_array_builder( + arrow::BooleanBuilder* builder, const datatypes::Bool* elements, size_t num_elements ) { if (builder == nullptr) { return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); @@ -29,17 +27,17 @@ namespace rerun { ); } - static_assert(sizeof(*elements) == sizeof(elements->is_expanded)); + static_assert(sizeof(*elements) == sizeof(elements->value)); ARROW_RETURN_NOT_OK(builder->AppendValues( - reinterpret_cast(&elements->is_expanded), + reinterpret_cast(&elements->value), static_cast(num_elements) )); return Error::ok(); } - Result> Loggable::to_arrow( - const blueprint::components::PanelView* instances, size_t num_instances + Result> Loggable::to_arrow( + const datatypes::Bool* instances, size_t num_instances ) { // TODO(andreas): Allow configuring the memory pool. arrow::MemoryPool* pool = arrow::default_memory_pool(); @@ -47,7 +45,7 @@ namespace rerun { ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( static_cast(builder.get()), instances, num_instances diff --git a/rerun_cpp/src/rerun/datatypes/bool.hpp b/rerun_cpp/src/rerun/datatypes/bool.hpp new file mode 100644 index 000000000000..00aeb20814e1 --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/bool.hpp @@ -0,0 +1,56 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/datatypes/bool.fbs". + +#pragma once + +#include "../result.hpp" + +#include +#include + +namespace arrow { + class Array; + class BooleanBuilder; + class DataType; +} // namespace arrow + +namespace rerun::datatypes { + /// **Datatype**: A single boolean. + struct Bool { + bool value; + + public: + Bool() = default; + + Bool(bool value_) : value(value_) {} + + Bool& operator=(bool value_) { + value = value_; + return *this; + } + }; +} // namespace rerun::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.Bool"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::BooleanBuilder* builder, const datatypes::Bool* elements, size_t num_elements + ); + + /// Serializes an array of `rerun::datatypes::Bool` into an arrow array. + static Result> to_arrow( + const datatypes::Bool* instances, size_t num_instances + ); + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index ba7be91efa09..6a5d18c1059d 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -2,17 +2,34 @@ __all__ = [ "archetypes", + "Blueprint", "BlueprintLike", + "BlueprintPanel", "components", "datatypes", "Grid", "Horizontal", + "SelectionPanel", "Spatial2D", "Spatial3D", "Tabs", + "TimePanel", "Vertical", "Viewport", ] from . import archetypes, components, datatypes -from .api import BlueprintLike, Grid, Horizontal, Spatial2D, Spatial3D, Tabs, Vertical, Viewport +from .api import ( + Blueprint, + BlueprintLike, + BlueprintPanel, + Grid, + Horizontal, + SelectionPanel, + Spatial2D, + Spatial3D, + Tabs, + TimePanel, + Vertical, + Viewport, +) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index cf85e5dbb2b1..5b76a5ed9621 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -9,12 +9,7 @@ from ..datatypes import EntityPathLike, Utf8Like from ..recording import MemoryRecording from ..recording_stream import RecordingStream -from .archetypes import ( - ContainerBlueprint, - SpaceViewBlueprint, - SpaceViewContents, - ViewportBlueprint, -) +from .archetypes import ContainerBlueprint, PanelBlueprint, SpaceViewBlueprint, SpaceViewContents, ViewportBlueprint from .components import ColumnShareArrayLike, RowShareArrayLike from .components.container_kind import ContainerKind, ContainerKindLike @@ -34,15 +29,19 @@ class SpaceView: def __init__( self, + *, class_identifier: Utf8Like, origin: EntityPathLike, contents: SpaceViewContentsLike, + name: Utf8Like | None, ): """ Construct a blueprint for a new space view. Parameters ---------- + name + The name of the space view. class_identifier The class of the space view to add. This must correspond to a known space view class. Prefer to use one of the subclasses of `SpaceView` which will populate this for you. @@ -56,6 +55,7 @@ def __init__( """ self.id = uuid.uuid4() self.class_identifier = class_identifier + self.name = name self.origin = origin self.contents = contents @@ -68,6 +68,14 @@ def blueprint_path(self) -> str: """ return f"space_view/{self.id}" + def to_viewport(self) -> Viewport: + """Convert this space view to a viewport.""" + return Viewport(Grid(self)) + + def to_blueprint(self) -> Blueprint: + """Convert this space view to a full blueprint.""" + return Blueprint(self.to_viewport()) + def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" # Handle the cases for SpaceViewContentsLike @@ -91,6 +99,7 @@ def _log_to_stream(self, stream: RecordingStream) -> None: arch = SpaceViewBlueprint( class_identifier=self.class_identifier, + display_name=self.name, space_origin=self.origin, ) @@ -106,7 +115,9 @@ def _iter_space_views(self) -> Iterable[bytes]: class Spatial3D(SpaceView): """A Spatial 3D space view.""" - def __init__(self, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**"): + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): """ Construct a blueprint for a new 3D space view. @@ -119,15 +130,19 @@ def __init__(self, origin: EntityPathLike = "/", contents: SpaceViewContentsLike The contents of the space view. Most commonly specified as a query expression. The individual sub-expressions must either be newline separate, or provided as a list of strings. See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the space view. """ - super().__init__("3D", origin, contents) + super().__init__(class_identifier="3D", origin=origin, contents=contents, name=name) class Spatial2D(SpaceView): """A Spatial 2D space view.""" - def __init__(self, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**"): + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): """ Construct a blueprint for a new 2D space view. @@ -140,9 +155,11 @@ def __init__(self, origin: EntityPathLike = "/", contents: SpaceViewContentsLike The contents of the space view. Most commonly specified as a query expression. The individual sub-expressions must either be newline separate, or provided as a list of strings. See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the space view. """ - super().__init__("2D", origin, contents) + super().__init__(class_identifier="2D", origin=origin, contents=contents, name=name) class Container: @@ -204,6 +221,14 @@ def blueprint_path(self) -> str: """ return f"container/{self.id}" + def to_viewport(self) -> Viewport: + """Convert this container to a viewport.""" + return Viewport(self) + + def to_blueprint(self) -> Blueprint: + """Convert this container to a full blueprint.""" + return Blueprint(self.to_viewport()) + def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" for sub in self.contents: @@ -324,7 +349,9 @@ class Viewport: This is an ergonomic helper on top of [rerun.blueprint.archetypes.ViewportBlueprint][]. """ - def __init__(self, root_container: Container): + def __init__( + self, root_container: Container, *, auto_layout: bool | None = None, auto_space_views: bool | None = None + ): """ Construct a new viewport. @@ -333,9 +360,17 @@ def __init__(self, root_container: Container): root_container: The container that sits at the top of the viewport hierarchy. The only content visible in this viewport must be contained within this container. + auto_layout: + Whether to automatically layout the viewport. If `True`, the container layout will be + reset whenever a new space view is added to the viewport. Defaults to `False`. + auto_space_views: + Whether to automatically add space views to the viewport. If `True`, the viewport will + automatically add space views based on content in the data store. Defaults to `False`. """ self.root_container = root_container + self.auto_layout = auto_layout + self.auto_space_views = auto_space_views def blueprint_path(self) -> str: """ @@ -346,6 +381,14 @@ def blueprint_path(self) -> str: """ return "viewport" + def to_viewport(self) -> Viewport: + """Conform with the `ViewportLike` interface.""" + return self + + def to_blueprint(self) -> Blueprint: + """Convert this viewport to a full blueprint.""" + return Blueprint(self) + def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" self.root_container._log_to_stream(stream) @@ -353,24 +396,195 @@ def _log_to_stream(self, stream: RecordingStream) -> None: arch = ViewportBlueprint( space_views=list(self.root_container._iter_space_views()), root_container=self.root_container.id.bytes, - auto_layout=False, - auto_space_views=False, + auto_layout=self.auto_layout, + auto_space_views=self.auto_space_views, + ) + + stream.log(self.blueprint_path(), arch) # type: ignore[attr-defined] + + +class Panel: + """ + Base class for the panel types. + + Consider using one of the subclasses instead of this class directly: + - [BlueprintPanel][] + - [SelectionPanel][] + - [TimePanel][] + + This is an ergonomic helper on top of [rerun.blueprint.archetypes.PanelBlueprint][]. + """ + + def __init__(self, *, blueprint_path: str, expanded: bool | None = None): + """ + Construct a new panel. + + Parameters + ---------- + blueprint_path: + The blueprint path of the panel. + expanded: + Whether the panel is expanded or not. + + """ + self._blueprint_path = blueprint_path + self.expanded = expanded + + def blueprint_path(self) -> str: + """ + The blueprint path where this space view will be logged. + + Note that although this is an `EntityPath`, is scoped to the blueprint tree and + not a part of the regular data hierarchy. + """ + return self._blueprint_path + + def _log_to_stream(self, stream: RecordingStream) -> None: + """Internal method to convert to an archetype and log to the stream.""" + arch = PanelBlueprint( + expanded=self.expanded, ) stream.log(self.blueprint_path(), arch) # type: ignore[attr-defined] -BlueprintLike = Union[Viewport, Container, SpaceView] +class BlueprintPanel(Panel): + """The state of the blueprint panel.""" + + def __init__(self, *, expanded: bool | None = None): + """ + Construct a new blueprint panel. + + Parameters + ---------- + expanded: + Whether the panel is expanded or not. + + """ + super().__init__(blueprint_path="blueprint_panel", expanded=expanded) + + +class SelectionPanel(Panel): + """The state of the selection panel.""" + + def __init__(self, *, expanded: bool | None = None): + """ + Construct a new selection panel. + + Parameters + ---------- + expanded: + Whether the panel is expanded or not. + + """ + super().__init__(blueprint_path="selection_panel", expanded=expanded) + + +class TimePanel(Panel): + """The state of the time panel.""" + + def __init__(self, *, expanded: bool | None = None): + """ + Construct a new time panel. + + Parameters + ---------- + expanded: + Whether the panel is expanded or not. + + """ + super().__init__(blueprint_path="time_panel", expanded=expanded) + + +ViewportLike = Union[Viewport, Container, SpaceView] +""" +A type that can be converted to a viewport. + +These types all implement a `to_viewport()` method that wraps them in the necessary +helper classes. +""" + +BlueprintPart = Union[ViewportLike, BlueprintPanel, SelectionPanel, TimePanel] +""" +The types that make up a blueprint. +""" + + +class Blueprint: + """The top-level description of the viewer blueprint.""" + + def __init__( + self, + *parts: BlueprintPart, + ): + """ + Construct a new blueprint from the given parts. + + Each [BlueprintPart][] can be one of the following: + - [Viewport][] + - [BlueprintPanel][] + - [SelectionPanel][] + - [TimePanel][] + + It is an error to provide more than one of any type of part. + + Parameters + ---------- + *parts: + The parts of the blueprint. + + """ + + for part in parts: + if isinstance(part, (Viewport, Container, SpaceView)): + if hasattr(self, "viewport"): + raise ValueError("Only one viewport can be provided") + self.viewport = part.to_viewport() + elif isinstance(part, BlueprintPanel): + if hasattr(self, "blueprint_panel"): + raise ValueError("Only one blueprint panel can be provided") + self.blueprint_panel = part + elif isinstance(part, SelectionPanel): + if hasattr(self, "selection_panel"): + raise ValueError("Only one selection panel can be provided") + self.selection_panel = part + elif isinstance(part, TimePanel): + if hasattr(self, "time_panel"): + raise ValueError("Only one time panel can be provided") + self.time_panel = part + else: + raise ValueError(f"Unknown part type: {part}") + + def to_blueprint(self) -> Blueprint: + """Conform with the `BlueprintLike` interface.""" + return self + + def _log_to_stream(self, stream: RecordingStream) -> None: + """Internal method to convert to an archetype and log to the stream.""" + self.viewport._log_to_stream(stream) + if hasattr(self, "blueprint_panel"): + self.blueprint_panel._log_to_stream(stream) + if hasattr(self, "selection_panel"): + self.selection_panel._log_to_stream(stream) + if hasattr(self, "time_panel"): + self.time_panel._log_to_stream(stream) + + +BlueprintLike = Union[Blueprint, Viewport, Container, SpaceView] + +""" +A type that can be converted to a blueprint. + +These types all implement a `to_blueprint()` method that wraps them in the necessary +helper classes. +""" def create_in_memory_blueprint(*, application_id: str, blueprint: BlueprintLike) -> MemoryRecording: """Internal rerun helper to convert a `BlueprintLike` into a stream that can be sent to the viewer.""" - # Add trivial wrappers as necessary - if isinstance(blueprint, SpaceView): - blueprint = Viewport(Grid(blueprint)) - elif isinstance(blueprint, Container): - blueprint = Viewport(blueprint) + # Convert the BlueprintLike to a full blueprint + blueprint = blueprint.to_blueprint() blueprint_stream = RecordingStream( bindings.new_blueprint( diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index 4d0dbb01bc00..135b24010d97 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -4,6 +4,7 @@ __init__.py linguist-generated=true background3d.py linguist-generated=true container_blueprint.py linguist-generated=true +panel_blueprint.py linguist-generated=true plot_legend.py linguist-generated=true scalar_axis.py linguist-generated=true space_view_blueprint.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py index 854c4a7398c2..982c77a4ec65 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -4,6 +4,7 @@ from .background3d import Background3D from .container_blueprint import ContainerBlueprint +from .panel_blueprint import PanelBlueprint from .plot_legend import PlotLegend from .scalar_axis import ScalarAxis from .space_view_blueprint import SpaceViewBlueprint @@ -13,6 +14,7 @@ __all__ = [ "Background3D", "ContainerBlueprint", + "PanelBlueprint", "PlotLegend", "ScalarAxis", "SpaceViewBlueprint", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py new file mode 100644 index 000000000000..946cc72a78e7 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/panel_blueprint.py @@ -0,0 +1,64 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/archetypes/panel_blueprint.fbs". + +# You can extend this class by creating a "PanelBlueprintExt" class in "panel_blueprint_ext.py". + +from __future__ import annotations + +from typing import Any + +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 + +__all__ = ["PanelBlueprint"] + + +@define(str=False, repr=False, init=False) +class PanelBlueprint(Archetype): + """**Archetype**: Shared state for the 3 collapsible panels.""" + + def __init__(self: Any, *, expanded: datatypes.BoolLike | None = None): + """ + Create a new instance of the PanelBlueprint archetype. + + Parameters + ---------- + expanded: + Whether or not the panel is expanded. + + """ + + # You can define your own __init__ function as a member of PanelBlueprintExt in panel_blueprint_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(expanded=expanded) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + expanded=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> PanelBlueprint: + """Produce an empty PanelBlueprint, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + expanded: blueprint_components.PanelExpandedBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.PanelExpandedBatch._optional, # type: ignore[misc] + ) + # Whether or not the panel is expanded. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index ed71ab812d53..2ad52015791a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -14,7 +14,7 @@ grid_columns.py linguist-generated=true included_content.py linguist-generated=true included_space_view.py linguist-generated=true lock_range_during_zoom.py linguist-generated=true -panel_view.py linguist-generated=true +panel_expanded.py linguist-generated=true query_expression.py linguist-generated=true root_container.py linguist-generated=true row_share.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index 5ba044b04cbc..94f3b1e26008 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -44,7 +44,7 @@ LockRangeDuringZoomLike, LockRangeDuringZoomType, ) -from .panel_view import PanelView, PanelViewArrayLike, PanelViewBatch, PanelViewLike, PanelViewType +from .panel_expanded import PanelExpanded, PanelExpandedBatch, PanelExpandedType from .query_expression import QueryExpression, QueryExpressionBatch, QueryExpressionType from .root_container import RootContainer, RootContainerBatch, RootContainerType from .row_share import RowShare, RowShareArrayLike, RowShareBatch, RowShareLike, RowShareType @@ -113,11 +113,9 @@ "LockRangeDuringZoomBatch", "LockRangeDuringZoomLike", "LockRangeDuringZoomType", - "PanelView", - "PanelViewArrayLike", - "PanelViewBatch", - "PanelViewLike", - "PanelViewType", + "PanelExpanded", + "PanelExpandedBatch", + "PanelExpandedType", "QueryExpression", "QueryExpressionBatch", "QueryExpressionType", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/panel_expanded.py b/rerun_py/rerun_sdk/rerun/blueprint/components/panel_expanded.py new file mode 100644 index 000000000000..0f4a1abf5bf6 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/panel_expanded.py @@ -0,0 +1,28 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs". + +# You can extend this class by creating a "PanelExpandedExt" class in "panel_expanded_ext.py". + +from __future__ import annotations + +from ... import datatypes +from ..._baseclasses import ComponentBatchMixin + +__all__ = ["PanelExpanded", "PanelExpandedBatch", "PanelExpandedType"] + + +class PanelExpanded(datatypes.Bool): + """**Component**: Whether an application panel is expanded or not.""" + + # You can define your own __init__ function as a member of PanelExpandedExt in panel_expanded_ext.py + + # Note: there are no fields here because PanelExpanded delegates to datatypes.Bool + pass + + +class PanelExpandedType(datatypes.BoolType): + _TYPE_NAME: str = "rerun.blueprint.components.PanelExpanded" + + +class PanelExpandedBatch(datatypes.BoolBatch, ComponentBatchMixin): + _ARROW_TYPE = PanelExpandedType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/panel_view.py b/rerun_py/rerun_sdk/rerun/blueprint/components/panel_view.py deleted file mode 100644 index 6db8186d5dfb..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/panel_view.py +++ /dev/null @@ -1,57 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/blueprint/components/panel_view.fbs". - -# You can extend this class by creating a "PanelViewExt" class in "panel_view_ext.py". - -from __future__ import annotations - -from typing import Any, Sequence, Union - -import pyarrow as pa -from attrs import define, field - -from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin - -__all__ = ["PanelView", "PanelViewArrayLike", "PanelViewBatch", "PanelViewLike", "PanelViewType"] - - -@define(init=False) -class PanelView: - """ - **Component**: The state of the panels. - - Unstable. Used for the ongoing blueprint experimentations. - """ - - def __init__(self: Any, is_expanded: PanelViewLike): - """Create a new instance of the PanelView component.""" - - # You can define your own __init__ function as a member of PanelViewExt in panel_view_ext.py - self.__attrs_init__(is_expanded=is_expanded) - - def __bool__(self) -> bool: - return self.is_expanded - - is_expanded: bool = field(converter=bool) - - -PanelViewLike = PanelView -PanelViewArrayLike = Union[ - PanelView, - Sequence[PanelViewLike], -] - - -class PanelViewType(BaseExtensionType): - _TYPE_NAME: str = "rerun.blueprint.components.PanelView" - - def __init__(self) -> None: - pa.ExtensionType.__init__(self, pa.bool_(), self._TYPE_NAME) - - -class PanelViewBatch(BaseBatch[PanelViewArrayLike], ComponentBatchMixin): - _ARROW_TYPE = PanelViewType() - - @staticmethod - def _native_to_pa_array(data: PanelViewArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in panel_view_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index 4cbc75d706ad..02728bf929d2 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -4,6 +4,7 @@ __init__.py linguist-generated=true angle.py linguist-generated=true annotation_info.py linguist-generated=true +bool.py linguist-generated=true class_description.py linguist-generated=true class_description_map_elem.py linguist-generated=true class_id.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index 3b16797e8d15..36fcb289aa61 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -10,6 +10,7 @@ AnnotationInfoLike, AnnotationInfoType, ) +from .bool import Bool, BoolArrayLike, BoolBatch, BoolLike, BoolType from .class_description import ( ClassDescription, ClassDescriptionArrayLike, @@ -96,6 +97,11 @@ "AnnotationInfoBatch", "AnnotationInfoLike", "AnnotationInfoType", + "Bool", + "BoolArrayLike", + "BoolBatch", + "BoolLike", + "BoolType", "ClassDescription", "ClassDescriptionArrayLike", "ClassDescriptionBatch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/bool.py b/rerun_py/rerun_sdk/rerun/datatypes/bool.py new file mode 100644 index 000000000000..cefabcb36551 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/bool.py @@ -0,0 +1,58 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/datatypes/bool.fbs". + +# You can extend this class by creating a "BoolExt" class in "bool_ext.py". + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Sequence, Union + +import pyarrow as pa +from attrs import define, field + +from .._baseclasses import BaseBatch, BaseExtensionType +from .bool_ext import BoolExt + +__all__ = ["Bool", "BoolArrayLike", "BoolBatch", "BoolLike", "BoolType"] + + +@define(init=False) +class Bool(BoolExt): + """**Datatype**: A single boolean.""" + + def __init__(self: Any, value: BoolLike): + """Create a new instance of the Bool datatype.""" + + # You can define your own __init__ function as a member of BoolExt in bool_ext.py + self.__attrs_init__(value=value) + + def __bool__(self) -> bool: + return self.value + + value: bool = field(converter=bool) + + +if TYPE_CHECKING: + BoolLike = Union[Bool, bool] +else: + BoolLike = Any + +BoolArrayLike = Union[ + Bool, + Sequence[BoolLike], +] + + +class BoolType(BaseExtensionType): + _TYPE_NAME: str = "rerun.datatypes.Bool" + + def __init__(self) -> None: + pa.ExtensionType.__init__(self, pa.bool_(), self._TYPE_NAME) + + +class BoolBatch(BaseBatch[BoolArrayLike]): + _ARROW_TYPE = BoolType() + + @staticmethod + def _native_to_pa_array(data: BoolArrayLike, data_type: pa.DataType) -> pa.Array: + return BoolExt.native_to_pa_array_override(data, data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/bool_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/bool_ext.py new file mode 100644 index 000000000000..da47a8526287 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/bool_ext.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import numpy as np +import pyarrow as pa + +if TYPE_CHECKING: + from . import BoolArrayLike + + +class BoolExt: + """Extension for [Bool][rerun.datatypes.Bool].""" + + @staticmethod + def native_to_pa_array_override(data: BoolArrayLike, data_type: pa.DataType) -> pa.Array: + array = np.asarray(data, dtype=np.bool_).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/experimental/__init__.py b/rerun_py/rerun_sdk/rerun/experimental/__init__.py index b979d1888e52..485bcf3c66a0 100644 --- a/rerun_py/rerun_sdk/rerun/experimental/__init__.py +++ b/rerun_py/rerun_sdk/rerun/experimental/__init__.py @@ -6,11 +6,4 @@ """ from __future__ import annotations -from .blueprint import add_space_view, new_blueprint, set_auto_space_views, set_panels - -__all__ = [ - "add_space_view", - "new_blueprint", - "set_auto_space_views", - "set_panels", -] +# __all__ = [] diff --git a/rerun_py/rerun_sdk/rerun/experimental/blueprint.py b/rerun_py/rerun_sdk/rerun/experimental/blueprint.py deleted file mode 100644 index 4d12480edbbd..000000000000 --- a/rerun_py/rerun_sdk/rerun/experimental/blueprint.py +++ /dev/null @@ -1,172 +0,0 @@ -# TODO(jleibs): docstrings -from __future__ import annotations - -import rerun_bindings as bindings # type: ignore[attr-defined] - -from rerun.recording_stream import RecordingStream - - -def new_blueprint( - application_id: str, - *, - blueprint_id: str | None = None, - make_default: bool = False, - make_thread_default: bool = False, - spawn: bool = False, - add_to_app_default_blueprint: bool = False, - default_enabled: bool = True, -) -> RecordingStream: - """ - Creates a new blueprint with a user-chosen application id (name) to configure the appearance of Rerun. - - If you only need a single global blueprint, [`rerun.init`][] might be simpler. - - Parameters - ---------- - application_id : str - Your Rerun recordings will be categorized by this application id, so - try to pick a unique one for each application that uses the Rerun SDK. - - For example, if you have one application doing object detection - and another doing camera calibration, you could have - `rerun.init("object_detector")` and `rerun.init("calibrator")`. - blueprint_id : Optional[str] - Set the blueprint ID that this process is logging to, as a UUIDv4. - - The default blueprint_id is based on `multiprocessing.current_process().authkey` - which means that all processes spawned with `multiprocessing` - will have the same default blueprint_id. - - If you are not using `multiprocessing` and still want several different Python - processes to log to the same Rerun instance (and be part of the same blueprint), - you will need to manually assign them all the same blueprint_id. - Any random UUIDv4 will work, or copy the blueprint_id for the parent process. - make_default : bool - If true (_not_ the default), the newly initialized blueprint will replace the current - active one (if any) in the global scope. - make_thread_default : bool - If true (_not_ the default), the newly initialized blueprint will replace the current - active one (if any) in the thread-local scope. - spawn : bool - Spawn a Rerun Viewer and stream logging data to it. - Short for calling `spawn` separately. - If you don't call this, log events will be buffered indefinitely until - you call either `connect`, `show`, or `save` - add_to_app_default_blueprint - Should the blueprint append to the existing app-default blueprint instead of creating a new one. - default_enabled - Should Rerun logging be on by default? - Can overridden with the RERUN env-var, e.g. `RERUN=on` or `RERUN=off`. - - Returns - ------- - RecordingStream - A handle to the [`rerun.RecordingStream`][]. Use it to log data to Rerun. - - """ - - blueprint_id = application_id if add_to_app_default_blueprint else blueprint_id - - blueprint = RecordingStream( - bindings.new_blueprint( - application_id=application_id, - blueprint_id=blueprint_id, - make_default=make_default, - make_thread_default=make_thread_default, - default_enabled=default_enabled, - ) - ) - - if spawn: - from rerun.sinks import spawn as _spawn - - _spawn(recording=blueprint) - - return blueprint - - -def add_space_view( - *, - origin: str, - space_view_class: str, - name: str | None, - entity_paths: list[str] | None, - blueprint: RecordingStream | None = None, -) -> None: - """ - Add a new space view to the blueprint. - - Parameters - ---------- - origin : str - The EntityPath to use as the origin of this space view. All other entities will be transformed - to be displayed relative to this origin. - space_view_class: str - The class of the space view to add. - name : Optional[str] - The name of the space view to show in the UI. Will default to the origin if not provided. - entity_paths : Optional[List[str]] - The entities to be shown in the space view. If not provided, this will default to [origin] - blueprint : Optional[RecordingStream] - The blueprint to add the space view to. If None, the default global blueprint is used. - - """ - if name is None: - name = origin - if entity_paths is None: - entity_paths = [origin] - blueprint = RecordingStream.to_native(blueprint) - bindings.add_space_view(name, space_view_class, origin, entity_paths, blueprint) - - -def set_panels( - *, - all_expanded: bool | None = None, - blueprint_view_expanded: bool | None = None, - selection_view_expanded: bool | None = None, - timeline_view_expanded: bool | None = None, - blueprint: RecordingStream | None = None, -) -> None: - """ - Change the visibility of the view panels. - - Parameters - ---------- - all_expanded : Optional[bool] - Expand or collapse all panels. - blueprint_view_expanded : Optional[bool] - Expand or collapse the blueprint view panel. - selection_view_expanded : Optional[bool] - Expand or collapse the selection view panel. - timeline_view_expanded : Optional[bool] - Expand or collapse the timeline view panel. - blueprint : Optional[RecordingStream] - The blueprint to add the space view to. If None, the default global blueprint is used. - - """ - blueprint = RecordingStream.to_native(blueprint) - bindings.set_panels( - blueprint_view_expanded=blueprint_view_expanded or all_expanded, - selection_view_expanded=selection_view_expanded or all_expanded, - timeline_view_expanded=timeline_view_expanded or all_expanded, - blueprint=blueprint, - ) - - -def set_auto_space_views( - enabled: bool, - blueprint: RecordingStream | None = None, -) -> None: - """ - Change whether or not the blueprint automatically adds space views for all entities. - - Parameters - ---------- - enabled : Optional[bool] - Whether or not to automatically add space views for all entities. - blueprint : Optional[RecordingStream] - The blueprint to add the space view to. If None, the default global blueprint is used. - - """ - blueprint = RecordingStream.to_native(blueprint) - bindings.set_auto_space_views(enabled, blueprint) diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index c0acbd5796b1..856c74b188db 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -12,12 +12,10 @@ use pyo3::{ types::{PyBytes, PyDict}, }; -use re_viewport::VIEWPORT_PATH; - -use re_log_types::{DataRow, EntityPathPart, StoreKind}; +use re_log_types::{EntityPathPart, StoreKind}; use rerun::{ - log::RowId, sink::MemorySinkStorage, time::TimePoint, EntityPath, RecordingStream, - RecordingStreamBuilder, StoreId, + sink::MemorySinkStorage, time::TimePoint, EntityPath, RecordingStream, RecordingStreamBuilder, + StoreId, }; #[cfg(feature = "web_viewer")] @@ -190,11 +188,6 @@ fn rerun_bindings(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(escape_entity_path_part, m)?)?; m.add_function(wrap_pyfunction!(new_entity_path, m)?)?; - // blueprint - m.add_function(wrap_pyfunction!(set_panels, m)?)?; - m.add_function(wrap_pyfunction!(add_space_view, m)?)?; - m.add_function(wrap_pyfunction!(set_auto_space_views, m)?)?; - Ok(()) } @@ -800,126 +793,6 @@ fn reset_time(recording: Option<&PyRecordingStream>) { // --- Log special --- -#[pyfunction] -fn set_panels( - blueprint_view_expanded: Option, - selection_view_expanded: Option, - timeline_view_expanded: Option, - blueprint: Option<&PyRecordingStream>, -) { - // TODO(jleibs): This should go away as part of https://github.com/rerun-io/rerun/issues/2089 - use re_viewer::blueprint::components::PanelView; - - if let Some(expanded) = blueprint_view_expanded { - set_panel(PanelView::BLUEPRINT_VIEW_PATH, expanded, blueprint); - } - if let Some(expanded) = selection_view_expanded { - set_panel(PanelView::SELECTION_VIEW_PATH, expanded, blueprint); - } - if let Some(expanded) = timeline_view_expanded { - set_panel(PanelView::TIMELINE_VIEW_PATH, expanded, blueprint); - } -} - -fn set_panel(entity_path: &str, is_expanded: bool, blueprint: Option<&PyRecordingStream>) { - let Some(blueprint) = get_blueprint_recording(blueprint) else { - return; - }; - - // TODO(jleibs): This should go away as part of https://github.com/rerun-io/rerun/issues/2089 - use re_viewer::blueprint::components::PanelView; - - // TODO(jleibs): Validation this is a valid blueprint path? - let entity_path = EntityPath::parse_forgiving(entity_path); - - let panel_state = PanelView(is_expanded); - - let row = DataRow::from_cells1( - RowId::new(), - entity_path, - TimePoint::default(), - 1, - [panel_state].as_slice(), - ) - .unwrap(); // Can only fail if we have the wrong number of instances for the component, and we don't - - // TODO(jleibs) timeless? Something else? - let timeless = true; - blueprint.record_row(row, !timeless); -} - -#[pyfunction] -fn add_space_view( - _name: &str, - _space_view_class: &str, - _origin: &str, - _entity_paths: Vec<&str>, - _blueprint: Option<&PyRecordingStream>, -) -> PyResult<()> { - Err(PyRuntimeError::new_err( - "add_space_view is broken until blueprint refactoring is complete: https://github.com/rerun-io/rerun/issues/4167", - )) - - /* - let Some(blueprint) = get_blueprint_recording(blueprint) else { - return; - }; - - let entity_paths = entity_paths.into_iter().map(|s| s.into()).collect_vec(); - let mut space_view = - SpaceViewBlueprint::new(space_view_class.into(), &origin.into(), entity_paths.iter()); - - // Choose the space-view id deterministically from the name; this means the user - // can run the application multiple times and get sane behavior. - space_view.id = SpaceViewId::hashed_from_str(name); - - space_view.display_name = name.into(); - space_view.entities_determined_by_user = true; - - let entity_path = space_view.entity_path(); - - let space_view = SpaceViewComponent { space_view }; - - let row = DataRow::from_cells1( - RowId::new(), - entity_path, - TimePoint::default(), - 1, - [space_view].as_slice(), - ) - .unwrap(); - - // TODO(jleibs) timeless? Something else? - let timeless = true; - blueprint.record_row(row, !timeless); - */ -} - -#[pyfunction] -fn set_auto_space_views(enabled: bool, blueprint: Option<&PyRecordingStream>) { - let Some(blueprint) = get_blueprint_recording(blueprint) else { - return; - }; - - // TODO(jleibs): This should go away as part of https://github.com/rerun-io/rerun/issues/2089 - use re_viewport::blueprint::components::AutoSpaceViews; - - let enable_auto_space = AutoSpaceViews(enabled); - - let row = DataRow::from_cells1( - RowId::new(), - VIEWPORT_PATH, - TimePoint::default(), - 1, - [enable_auto_space].as_slice(), - ) - .unwrap(); - - // TODO(jleibs) timeless? Something else? - let timeless = true; - blueprint.record_row(row, !timeless); -} - #[pyfunction] #[pyo3(signature = ( entity_path, diff --git a/tests/python/blueprint/main.py b/tests/python/blueprint/main.py index 4b042b9e9fdf..3d431a2678f5 100644 --- a/tests/python/blueprint/main.py +++ b/tests/python/blueprint/main.py @@ -2,27 +2,33 @@ import rerun as rr from numpy.random import default_rng -from rerun.blueprint import Grid, Horizontal, Spatial2D, Spatial3D, Tabs, Vertical +from rerun.blueprint import Blueprint, Grid, Horizontal, Spatial2D, Spatial3D, Tabs, Vertical, Viewport +from rerun.blueprint.api import TimePanel if __name__ == "__main__": - blueprint = Vertical( - Spatial3D(origin="/test1"), - Horizontal( - Tabs( + blueprint = Blueprint( + Viewport( + Vertical( Spatial3D(origin="/test1"), - Spatial2D(origin="/test2"), - ), - Grid( - Spatial3D(origin="/test1"), - Spatial2D(origin="/test2"), - Spatial3D(origin="/test1"), - Spatial2D(origin="/test2"), - grid_columns=3, - column_shares=[1, 1, 1], - ), - column_shares=[1, 2], + Horizontal( + Tabs( + Spatial3D(origin="/test1"), + Spatial2D(origin="/test2"), + ), + Grid( + Spatial3D(origin="/test1"), + Spatial2D(origin="/test2"), + Spatial3D(origin="/test1"), + Spatial2D(origin="/test2"), + grid_columns=3, + column_shares=[1, 1, 1], + ), + column_shares=[1, 2], + ), + row_shares=[2, 1], + ) ), - row_shares=[2, 1], + TimePanel(expanded=False), ) rr.init( From 1a2b9e3f90fe6f592112cacb061841eb0f85bb8c Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Wed, 13 Mar 2024 17:20:31 -0400 Subject: [PATCH 020/508] Allow rerun_py to be built without the viewer (#5485) ### What - Builds on top of: https://github.com/rerun-io/rerun/pull/5484 - Resolves: https://github.com/rerun-io/rerun/issues/2089 - Specifically the part about the bridge dep on re_viewer. The rest of the decoupling has already been done. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5485/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5485/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5485/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5485) - [Docs preview](https://rerun.io/preview/5189590ca4dc0282a6b1c814200db8434ab7004e/docs) - [Examples preview](https://rerun.io/preview/5189590ca4dc0282a6b1c814200db8434ab7004e/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 2 -- rerun_py/Cargo.toml | 4 ---- 2 files changed, 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92ed816d8fdc..dec4be2dc83a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5354,8 +5354,6 @@ dependencies = [ "re_log", "re_log_types", "re_memory", - "re_viewer", - "re_viewport", "re_web_viewer_server", "re_ws_comms", "rerun", diff --git a/rerun_py/Cargo.toml b/rerun_py/Cargo.toml index 1ce40ec94ed9..3394a559bbe1 100644 --- a/rerun_py/Cargo.toml +++ b/rerun_py/Cargo.toml @@ -51,10 +51,6 @@ rerun = { workspace = true, features = [ re_web_viewer_server = { workspace = true, optional = true } re_ws_comms = { workspace = true, optional = true } -# TODO(jleibs): Dependency on re_viewer and re_viewport should go away as part of https://github.com/rerun-io/rerun/issues/2089 -re_viewer.workspace = true -re_viewport.workspace = true - arrow2 = { workspace = true, features = ["io_ipc", "io_print"] } crossbeam.workspace = true document-features.workspace = true From 21e06fcc3cd8e8c0a08758b15d6c16c4864afc9c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 14 Mar 2024 10:07:04 +0100 Subject: [PATCH 021/508] Add new design guidelines for title casing etc (#5501) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5501/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5501/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5501/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5501) - [Docs preview](https://rerun.io/preview/920c7ce37479eb3a0c12a9f155e8a0a388c508af/docs) - [Examples preview](https://rerun.io/preview/920c7ce37479eb3a0c12a9f155e8a0a388c508af/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- DESIGN.md | 32 +++++++++++++++++++ crates/re_data_ui/src/component.rs | 2 +- crates/re_ui/src/command.rs | 22 ++++++------- crates/re_viewer/src/ui/rerun_menu.rs | 2 +- crates/re_viewer/src/ui/visible_history.rs | 18 +++++------ .../src/ui/welcome_screen/welcome_section.rs | 6 ++-- crates/re_viewport/src/context_menu/mod.rs | 4 +-- .../release_checklist/check_plot_overrides.py | 4 +-- 8 files changed, 61 insertions(+), 29 deletions(-) create mode 100644 DESIGN.md diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 000000000000..a6d1a7def756 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,32 @@ +# Design guidelines +Guidelines for UI design, covering GUI, CLI, documentation, log messages, etc + +## Text +#### Sentences +Short, single-sentence text do NOT end in a period. + +Multi-sentence text ALWAYS ends in a period. + +#### Casing +We prefer normal casing, and avoid Title Casing. + +We only use Title Casing for company and product names (Rerun, Rerun Viewer, Discord, …), but NOT for concepts like “container”, “space view”, etc. + +#### Examples +Good: `log("File saved")` + +Bad: `log("file saved.")` + +### Buttons + +When a button action requires more input after pressing, suffix it with `…`. + +Good: `Save recording…` (leads to a save-dialog) + +## GUI labels + +We do not use a colon suffix for labels in front of a value. + +Good: `Color 🔴` + +Bad: `Color: 🔴` diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index b4a2353d1e10..b329896c64fc 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -106,7 +106,7 @@ impl DataUi for EntityComponentWithInstances { .header(re_ui::ReUi::table_header_height(), |mut header| { re_ui::ReUi::setup_table_header(&mut header); header.col(|ui| { - ui.label("Instance Key"); + ui.label("Instance key"); }); header.col(|ui| { ui.label(self.component_name().short_name()); diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs index 3db65c6ca9de..3e95bbb9f54c 100644 --- a/crates/re_ui/src/command.rs +++ b/crates/re_ui/src/command.rs @@ -97,7 +97,7 @@ impl UICommand { Self::SaveRecording => ("Save recording…", "Save all data to a Rerun data file (.rrd)"), Self::SaveRecordingSelection => ( - "Save recording (current time selection only)…", + "Save current time selection…", "Save data for the current loop selection to a Rerun data file (.rrd)", ), @@ -128,22 +128,22 @@ impl UICommand { ), Self::ToggleMemoryPanel => ( - "Toggle Memory Panel", + "Toggle memory panel", "View and track current RAM usage inside Rerun Viewer", ), - Self::ToggleBlueprintPanel => ("Toggle Blueprint Panel", "Toggle the left panel"), - Self::ToggleSelectionPanel => ("Toggle Selection Panel", "Toggle the right panel"), - Self::ToggleTimePanel => ("Toggle Time Panel", "Toggle the bottom panel"), + Self::ToggleBlueprintPanel => ("Toggle blueprint panel", "Toggle the left panel"), + Self::ToggleSelectionPanel => ("Toggle selection panel", "Toggle the right panel"), + Self::ToggleTimePanel => ("Toggle time panel", "Toggle the bottom panel"), #[cfg(debug_assertions)] Self::ToggleBlueprintInspectionPanel => ( - "Toggle Blueprint Inspection Panel", + "Toggle blueprint inspection panel", "Inspect the timeline of the internal blueprint data.", ), #[cfg(debug_assertions)] Self::ToggleEguiDebugPanel => ( - "Toggle Egui Options/Debug Panel", + "Toggle egui debug panel", "View and change global egui style settings", ), @@ -154,18 +154,18 @@ impl UICommand { "Toggle between windowed and fullscreen viewer", ), #[cfg(not(target_arch = "wasm32"))] - Self::ZoomIn => ("Zoom In", "Increases the UI zoom level"), + Self::ZoomIn => ("Zoom in", "Increases the UI zoom level"), #[cfg(not(target_arch = "wasm32"))] - Self::ZoomOut => ("Zoom Out", "Decreases the UI zoom level"), + Self::ZoomOut => ("Zoom out", "Decreases the UI zoom level"), #[cfg(not(target_arch = "wasm32"))] Self::ZoomReset => ( - "Reset Zoom", + "Reset zoom", "Resets the UI zoom level to the operating system's default value", ), Self::SelectionPrevious => ("Previous selection", "Go to previous selection"), Self::SelectionNext => ("Next selection", "Go to next selection"), - Self::ToggleCommandPalette => ("Command Palette…", "Toggle the Command Palette"), + Self::ToggleCommandPalette => ("Command palette…", "Toggle the Command Palette"), Self::PlaybackTogglePlayPause => { ("Toggle play/pause", "Either play or pause the time") diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index 08698f451cfd..b9288b6d22dd 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -26,7 +26,7 @@ impl App { .max_height(desired_icon_height); ui.menu_image_button(image, |ui| { - ui.set_min_width(220.0); + ui.set_min_width(240.0); ui.menu_button("About", |ui| self.about_rerun_ui(frame, ui)); diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index 7bcb9137c0c2..831f2f4fd4ee 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -24,7 +24,7 @@ static VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS: once_cell::sync::Lazy< .into() }); -/// Entities containing one of these components support the Visible History feature. +/// Entities containing one of these components support the visible history feature. static VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES: once_cell::sync::Lazy> = once_cell::sync::Lazy::new(|| { [ @@ -92,24 +92,24 @@ pub fn visible_history_ui( let mut interacting_with_controls = false; - let collapsing_response = re_ui.collapsing_header(ui, "Visible Time Range", false, |ui| { + let collapsing_response = re_ui.collapsing_header(ui, "Visible time range", false, |ui| { ui.horizontal(|ui| { re_ui .radio_value(ui, &mut visible_history_prop.enabled, false, "Default") .on_hover_text(if is_space_view { - "Default Visible Time Range settings for this kind of Space View" + "Default visible time range settings for this kind of Space View" } else { - "Visible Time Range settings inherited from parent Group(s) or enclosing \ + "Visible time range settings inherited from parent Group(s) or enclosing \ Space View" }); re_ui .radio_value(ui, &mut visible_history_prop.enabled, true, "Override") .on_hover_text(if is_space_view { - "Set Visible Time Range settings for the contents of this Space View" + "Set visible time range settings for the contents of this Space View" } else if entity_path.is_some() { - "Set Visible Time Range settings for this entity" + "Set visible time range settings for this entity" } else { - "Set Visible Time Range settings for he contents of this Group" + "Set visible time range settings for he contents of this Group" }); }); @@ -263,12 +263,12 @@ pub fn visible_history_ui( } } - let markdown = format!("# Visible Time Range\n + let markdown = format!("# Visible time range\n This feature controls the time range used to display data in the Space View. The settings are inherited from parent Group(s) or enclosing Space View if not overridden. -Visible Time Range properties are stored separately for each _type_ of timelines. They may differ depending on \ +Visible time range properties are stored separately for each _type_ of timelines. They may differ depending on \ whether the current timeline is temporal or a sequence. The current settings apply to all _{}_ timelines. Notes that the data current as of the time range starting time is included.", diff --git a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs index 7749088fc23b..c7176b96d845 100644 --- a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs @@ -138,7 +138,7 @@ fn onboarding_content_ui(ui: &mut Ui, command_sender: &CommandSender, accepts_co Visualize synchronized data from multiple processes, locally or over a network.", image: &re_ui::icons::WELCOME_SCREEN_LIVE_DATA, add_buttons: Box::new(move |ui, command_sender| { - if large_text_button(ui, "Quick Start").clicked() { + if large_text_button(ui, "Quick start").clicked() { let entries = if accepts_connections { QUICK_START_ENTRIES_CONNECT } else { @@ -169,7 +169,7 @@ fn onboarding_content_ui(ui: &mut Ui, command_sender: &CommandSender, accepts_co interactively in the viewer or (coming soon) directly from code in the SDK.", image: &re_ui::icons::WELCOME_SCREEN_CONFIGURE, add_buttons: Box::new(|ui, _| { - url_large_text_button(ui, "Learn about Views", SPACE_VIEWS_HELP); + url_large_text_button(ui, "Learn about views", SPACE_VIEWS_HELP); }), }, ]; @@ -306,7 +306,7 @@ fn open_quick_start( } let store_info = StoreInfo { - application_id: "Quick Start".into(), + application_id: "Quick start".into(), store_id: StoreId::random(StoreKind::Recording), is_official_example: true, started: Time::now(), diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index 08e3f29179c6..dfaab61cbe15 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -116,7 +116,7 @@ fn action_list( vec![Box::new(CloneSpaceViewAction)], vec![ Box::new(SubMenu { - label: "Add Container".to_owned(), + label: "Add container".to_owned(), actions: vec![ Box::new(AddContainerAction(egui_tiles::ContainerKind::Tabs)), Box::new(AddContainerAction(egui_tiles::ContainerKind::Horizontal)), @@ -138,7 +138,7 @@ fn action_list( }), ], vec![Box::new(SubMenu { - label: "Move to new Container".to_owned(), + label: "Move to new container".to_owned(), actions: vec![ Box::new(MoveContentsToNewContainerAction( egui_tiles::ContainerKind::Tabs, diff --git a/tests/python/release_checklist/check_plot_overrides.py b/tests/python/release_checklist/check_plot_overrides.py index a540b8f879e3..b2b1af4595d1 100644 --- a/tests/python/release_checklist/check_plot_overrides.py +++ b/tests/python/release_checklist/check_plot_overrides.py @@ -11,13 +11,13 @@ This checks whether one can override all properties in a plot. -### Component Overrides +### Component overrides * Select `plots/cos`. * Override all of its properties with arbitrary values. * Remove all these overrides. -### Visible Time Range Overrides +### Visible time range overrides * Select the `plots` space view and confirm it shows: * "Default" selected * Showing data between frames -∞ and +∞ (included). From 3209c7aa5a5c2755a9303429e47d749723210f9d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 14 Mar 2024 10:10:26 +0100 Subject: [PATCH 022/508] Add `-g` option to `re_build_web_viewer` to keep debug symbols (#5500) This enables in-browser profiling of the web viewer, as well as better callstack. Usage: `cargo r -p re_build_web_viewer -- --release -g` | | .wasm | zipped | | ------------- | ------------- | ------------- | | `--release` | 19.2 MB | 6.3 MB | | `--release -g` | 20.7 MB | 6.6 MB | ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5500/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5500/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5500/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5500) - [Docs preview](https://rerun.io/preview/806fb1cc339b0efe732650e49d447fabdd38d821/docs) - [Examples preview](https://rerun.io/preview/806fb1cc339b0efe732650e49d447fabdd38d821/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_build_web_viewer/src/lib.rs | 17 ++++++++++++++--- crates/re_build_web_viewer/src/main.rs | 11 ++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/crates/re_build_web_viewer/src/lib.rs b/crates/re_build_web_viewer/src/lib.rs index b2771a51d8fb..589e728b7b8e 100644 --- a/crates/re_build_web_viewer/src/lib.rs +++ b/crates/re_build_web_viewer/src/lib.rs @@ -50,7 +50,15 @@ pub enum Target { } /// Build `re_viewer` as Wasm, generate .js bindings for it, and place it all into the `build_dir` folder. -pub fn build(profile: Profile, target: Target, build_dir: &Utf8Path) -> anyhow::Result<()> { +/// +/// If `debug_symbols` is set, debug symbols are kept even in release builds, +/// allowing for better callstacks on panics, as well as in-browser profiling of the wasm. +pub fn build( + profile: Profile, + debug_symbols: bool, + target: Target, + build_dir: &Utf8Path, +) -> anyhow::Result<()> { std::env::set_current_dir(workspace_root())?; eprintln!("Building web viewer wasm…"); @@ -167,8 +175,11 @@ pub fn build(profile: Profile, target: Target, build_dir: &Utf8Path) -> anyhow:: // to get wasm-opt: apt/brew/dnf install binaryen let mut cmd = std::process::Command::new("wasm-opt"); - // TODO(emilk): add `-g` to keep debug symbols; useful for profiling release builds in the in-browser profiler. - cmd.args([wasm_path.as_str(), "-O2", "--output", wasm_path.as_str()]); + let mut args = vec![wasm_path.as_str(), "-O2", "--output", wasm_path.as_str()]; + if debug_symbols { + args.push("-g"); + } + cmd.args(args); eprintln!("{root_dir}> {cmd:?}"); let output = cmd diff --git a/crates/re_build_web_viewer/src/main.rs b/crates/re_build_web_viewer/src/main.rs index cce54fad6dd1..f734d4097ef4 100644 --- a/crates/re_build_web_viewer/src/main.rs +++ b/crates/re_build_web_viewer/src/main.rs @@ -4,6 +4,7 @@ use std::process::ExitCode; struct Opts { profile: Option, + debug_symbols: bool, target: Target, build_dir: Utf8PathBuf, } @@ -12,6 +13,7 @@ impl Default for Opts { fn default() -> Self { Self { profile: None, + debug_symbols: false, target: Target::Browser, build_dir: default_build_dir(), } @@ -42,6 +44,9 @@ fn main() -> ExitCode { ); opts.profile = Some(Profile::Release); } + "-g" => { + opts.debug_symbols = true; + } "-o" | "--out" => match args.next() { Some(value) if !value.starts_with('-') => { opts.build_dir = Utf8PathBuf::from(value); @@ -63,7 +68,9 @@ fn main() -> ExitCode { return ExitCode::FAILURE; }; - if let Err(err) = re_build_web_viewer::build(release, opts.target, &opts.build_dir) { + if let Err(err) = + re_build_web_viewer::build(release, opts.debug_symbols, opts.target, &opts.build_dir) + { eprintln!("Failed to build web viewer: {}", re_error::format(err)); ExitCode::FAILURE } else { @@ -79,6 +86,8 @@ fn print_help() { --debug: Build a debug binary --release: Compile for release, and run wasm-opt. NOTE: --release also removes debug symbols which are otherwise useful for in-browser profiling. + -g: Keep debug symbols, even in release builds. + This gives better callstacks on panics, and also allows for in-browser profiling of the Wasm. -o, --out: Set the output directory. This is a path relative to the cargo workspace root. " ); From 8e24b568abaafede46ccd4082537c33e6e68364d Mon Sep 17 00:00:00 2001 From: murgeljm Date: Thu, 14 Mar 2024 10:13:59 +0100 Subject: [PATCH 023/508] Add unix epoch as timezone option (#5450) * Closes #4866 ### What Added a unix epoch timestamp display option, as mentioned in issue [4866](https://github.com/rerun-io/rerun/issues/4866) Screenshot 2024-03-10 at 23 25 16-min Not quite sure how compact time display should be handled: ```diff /// Useful when showing dates/times on a timeline /// and you want it compact. /// /// Shows dates when zoomed out, shows times when zoomed in, /// shows relative millisecond when really zoomed in. pub fn format_time_compact(&self, time_zone_for_timestamps: TimeZone) -> String { ... if let Some(datetime) = self.to_datetime() { let is_whole_minute = ns % 60_000_000_000 == 0; let time_format = if self.is_exactly_midnight() { "[year]-[month]-[day]" } else if is_whole_minute { "[hour]:[minute]" } else { - "[hour]:[minute]:[second]" + Self::get_time_prefix(&time_zone_for_timestamps) }; let parsed_format = time::format_description::parse(time_format).unwrap(); return Self::time_string(datetime, &parsed_format, time_zone_for_timestamps); } ... } ``` Should the `[hour]:[minute]` be changed as well when unix timestamp is chosen? ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5450/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5450/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5450/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5450) - [Docs preview](https://rerun.io/preview/7e0f542930b6d1279c55190e3f375f0dcf2b2603/docs) - [Examples preview](https://rerun.io/preview/7e0f542930b6d1279c55190e3f375f0dcf2b2603/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: mm Co-authored-by: Emil Ernerfeldt --- crates/re_log_types/src/time.rs | 39 ++++++++++++++++++++++----- crates/re_viewer/src/ui/rerun_menu.rs | 10 +++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/re_log_types/src/time.rs b/crates/re_log_types/src/time.rs index caebf376b84b..c7fb28719cf8 100644 --- a/crates/re_log_types/src/time.rs +++ b/crates/re_log_types/src/time.rs @@ -6,6 +6,9 @@ use time::{format_description::FormatItem, OffsetDateTime, UtcOffset}; pub enum TimeZone { Local, Utc, + + /// Seconds since unix epoch + UnixEpoch, } /// A date-time represented as nanoseconds since unix epoch @@ -91,6 +94,7 @@ impl Time { TimeZone::Utc => { format!("{}Z", datetime.format(&parsed_format).unwrap()) } + TimeZone::UnixEpoch => datetime.format(&parsed_format).unwrap(), } } @@ -101,19 +105,23 @@ impl Time { if let Some(datetime) = self.to_datetime() { let is_whole_second = nanos_since_epoch % 1_000_000_000 == 0; let is_whole_millisecond = nanos_since_epoch % 1_000_000 == 0; + let prefix = match time_zone_for_timestamps { + TimeZone::UnixEpoch => "[unix_timestamp]", + TimeZone::Utc | TimeZone::Local => "[hour]:[minute]:[second]", + }; let time_format = if is_whole_second { - "[hour]:[minute]:[second]" + prefix.to_owned() } else if is_whole_millisecond { - "[hour]:[minute]:[second].[subsecond digits:3]" + format!("{prefix}.[subsecond digits:3]") } else { - "[hour]:[minute]:[second].[subsecond digits:6]" + format!("{prefix}.[subsecond digits:6]") }; let date_is_today = datetime.date() == OffsetDateTime::now_utc().date(); let date_format = format!("[year]-[month]-[day] {time_format}"); let parsed_format = if date_is_today { - time::format_description::parse(time_format).unwrap() + time::format_description::parse(&time_format).unwrap() } else { time::format_description::parse(&date_format).unwrap() }; @@ -147,9 +155,15 @@ impl Time { let time_format = if self.is_exactly_midnight() { "[year]-[month]-[day]" } else if is_whole_minute { - "[hour]:[minute]" + match time_zone_for_timestamps { + TimeZone::UnixEpoch => "[unix_timestamp]", + TimeZone::Utc | TimeZone::Local => "[hour]:[minute]", + } } else { - "[hour]:[minute]:[second]" + match time_zone_for_timestamps { + TimeZone::UnixEpoch => "[unix_timestamp]", + TimeZone::Utc | TimeZone::Local => "[hour]:[minute]:[second]", + } }; let parsed_format = time::format_description::parse(time_format).unwrap(); @@ -302,6 +316,19 @@ mod tests { &Time::from_us_since_epoch(69_900).format(TimeZone::Local), "+0.070s" ); + + assert_eq!( + &Time::from_us_since_epoch(42_000_000).format(TimeZone::UnixEpoch), + "+42s" + ); + assert_eq!( + &Time::from_us_since_epoch(69_000).format(TimeZone::UnixEpoch), + "+0.069s" + ); + assert_eq!( + &Time::from_us_since_epoch(69_900).format(TimeZone::UnixEpoch), + "+0.070s" + ); } #[test] diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index b9288b6d22dd..aa0a945b6e57 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -319,12 +319,22 @@ fn options_menu_ui( ui.horizontal(|ui| { ui.label("Timezone:"); + }); + ui.horizontal(|ui| { re_ui .radio_value(ui, &mut app_options.time_zone, TimeZone::Utc, "UTC") .on_hover_text("Display timestamps in UTC"); re_ui .radio_value(ui, &mut app_options.time_zone, TimeZone::Local, "Local") .on_hover_text("Display timestamps in the local timezone"); + re_ui + .radio_value( + ui, + &mut app_options.time_zone, + TimeZone::UnixEpoch, + "Unix Epoch", + ) + .on_hover_text("Display timestamps in seconds since unix epoch"); }); { From 103093497693443a4b2336442703e64f342d8380 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 14 Mar 2024 10:35:08 +0100 Subject: [PATCH 024/508] Build C++ SDK for Linux ARM64 (#5489) ### What * Part of #4136 Had to use a buildjet runner because some of our `rerun_c` dependencies (`ring` foremost) had trouble cross compiling after all. Artifact I built from CI by emulating push-to-main ci: https://build.rerun.io/commit/04b1eb6/rerun_cpp_sdk.zip Not properly tested, but evidently has arm64 linux static library in it. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5489/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5489/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5489/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5489) - [Docs preview](https://rerun.io/preview/20c26b4682d0d874dddbaab26102b8a061a885a3/docs) - [Examples preview](https://rerun.io/preview/20c26b4682d0d874dddbaab26102b8a061a885a3/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/on_push_main.yml | 53 +++++++++++-------- .../reusable_build_and_upload_rerun_c.yml | 26 +++++---- rerun_cpp/CMakeLists.txt | 13 +++-- rerun_cpp/cmake_setup_in_detail.md | 1 + scripts/ci/bundle_and_upload_rerun_cpp.py | 11 ++-- 5 files changed, 67 insertions(+), 37 deletions(-) diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 2f54ad3221e6..101cfaa4935c 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -114,40 +114,49 @@ jobs: # ----------------------------------------------------------------------------------- # Build rerun_c library binaries: - build-rerun_c-and-upload-linux: + build-rerun_c-and-upload-linux-arm64: + needs: [checks] + name: "Linux-Arm64: Build & Upload rerun_c" + uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml + with: + CONCURRENCY: push-linux-arm64-${{ github.ref_name }} + PLATFORM: linux-arm64 + secrets: inherit + + build-rerun_c-and-upload-linux-x64: needs: [checks] name: "Linux-x64: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-linux-${{ github.ref_name }} - PLATFORM: linux + CONCURRENCY: push-linux-x64-${{ github.ref_name }} + PLATFORM: linux-x64 secrets: inherit - build-rerun_c-and-upload-macos-intel: + build-rerun_c-and-upload-macos-x64: needs: [checks] name: "Mac-Intel: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-macos-intel-${{ github.ref_name }} - PLATFORM: macos-intel + CONCURRENCY: push-macos-x64-${{ github.ref_name }} + PLATFORM: macos-x64 secrets: inherit - build-rerun_c-and-upload-macos-arm: + build-rerun_c-and-upload-macos-arm64: needs: [checks] - name: "Mac-Arm: Build & Upload rerun_c" + name: "Mac-Arm64: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-macos-arm-${{ github.ref_name }} - PLATFORM: macos-arm + CONCURRENCY: push-macos-arm64-${{ github.ref_name }} + PLATFORM: macos-arm64 secrets: inherit - build-rerun_c-and-upload-windows: + build-rerun_c-and-upload-windows-x64: needs: [checks] name: "Windows-x64: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-windows-${{ github.ref_name }} - PLATFORM: windows + CONCURRENCY: push-windows-x64-${{ github.ref_name }} + PLATFORM: windows-x64 secrets: inherit # ----------------------------------------------------------------------------------- @@ -273,10 +282,11 @@ jobs: name: "Bundle and upload rerun_cpp_sdk.zip" needs: [ - build-rerun_c-and-upload-linux, - build-rerun_c-and-upload-macos-intel, - build-rerun_c-and-upload-macos-arm, - build-rerun_c-and-upload-windows, + build-rerun_c-and-upload-linux-x64, + build-rerun_c-and-upload-linux-arm64, + build-rerun_c-and-upload-macos-x64, + build-rerun_c-and-upload-macos-arm64, + build-rerun_c-and-upload-windows-x64, ] uses: ./.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml secrets: inherit @@ -290,10 +300,11 @@ jobs: [ upload-web, generate-pip-index, - build-rerun_c-and-upload-linux, - build-rerun_c-and-upload-macos-intel, - build-rerun_c-and-upload-macos-arm, - build-rerun_c-and-upload-windows, + build-rerun_c-and-upload-linux-x64, + build-rerun_c-and-upload-linux-arm64, + build-rerun_c-and-upload-macos-x64, + build-rerun_c-and-upload-macos-arm64, + build-rerun_c-and-upload-windows-x64, build-rerun-cli-and-upload-linux, build-rerun-cli-and-upload-macos-intel, build-rerun-cli-and-upload-macos-arm, diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml index 019fbeb56687..28bed0855d01 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_c.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml @@ -21,16 +21,18 @@ on: workflow_dispatch: inputs: ADHOC_NAME: - required: true + required: false type: string description: "Name of the adhoc build, used for upload directory" + default: "" PLATFORM: type: choice options: - - linux - - windows - - macos-arm - - macos-intel + - linux-arm64 + - linux-x64 + - windows-x64 + - macos-arm64 + - macos-x64 description: "Platform to build for" required: true CONCURRENCY: @@ -70,25 +72,31 @@ jobs: shell: bash run: | case "${{ inputs.PLATFORM }}" in - linux) + linux-arm64) + runner="buildjet-8vcpu-ubuntu-2204-arm" + target="aarch64-unknown-linux-gnu" + container="null" + lib_name="librerun_c.a" + ;; + linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" container="{'image': 'rerunio/ci_docker:0.11.0'}" lib_name="librerun_c.a" ;; - windows) + windows-x64) runner="windows-latest-8-cores" target="x86_64-pc-windows-msvc" container="null" lib_name="rerun_c.lib" ;; - macos-arm) + macos-arm64) runner="macos-latest" # Small runners, because building rerun_c is fast target="aarch64-apple-darwin" container="null" lib_name="librerun_c.a" ;; - macos-intel) + macos-x64) runner="macos-latest" # Small runners, because building rerun_c is fast target="x86_64-apple-darwin" container="null" diff --git a/rerun_cpp/CMakeLists.txt b/rerun_cpp/CMakeLists.txt index 4aceacc7e7b5..9d6fb8d0e285 100644 --- a/rerun_cpp/CMakeLists.txt +++ b/rerun_cpp/CMakeLists.txt @@ -51,14 +51,19 @@ if(NOT TARGET rerun_c) if(APPLE) if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") set(RERUN_C_LIB_DEFAULT ${RERUN_C_DEFAULT_LIB_DIR}/librerun_c__macos_x64.a) - elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64") + elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") set(RERUN_C_LIB_DEFAULT ${RERUN_C_DEFAULT_LIB_DIR}/librerun_c__macos_arm64.a) else() message(WARNING "Unknown architecture ${CMAKE_SYSTEM_PROCESSOR}, can't find rerun_c library.") endif() elseif(UNIX) # if(LINUX) # CMake 3.25 - # TODO(andreas): Arm support. - set(RERUN_C_LIB_DEFAULT ${RERUN_C_DEFAULT_LIB_DIR}/librerun_c__linux_x64.a) + if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + set(RERUN_C_LIB_DEFAULT ${RERUN_C_DEFAULT_LIB_DIR}/librerun_c__linux_x64.a) + elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") + set(RERUN_C_LIB_DEFAULT ${RERUN_C_DEFAULT_LIB_DIR}/librerun_c__linux_arm64.a) + else() + message(WARNING "Unknown architecture ${CMAKE_SYSTEM_PROCESSOR}, can't find rerun_c library.") + endif() elseif(WIN32) # TODO(andreas): Arm support. set(RERUN_C_LIB_DEFAULT ${RERUN_C_DEFAULT_LIB_DIR}/rerun_c__win_x64.lib) @@ -127,8 +132,10 @@ install(TARGETS rerun_sdk install(DIRECTORY "${RERUN_CPP_SOURCE_DIR}/" TYPE INCLUDE FILES_MATCHING PATTERN "*.hpp") option(RERUN_INSTALL_RERUN_C "Install rerun_c file." ON) + # if rerun_sdk is a static library it is compulsory to install rerun_c get_target_property(rerun_sdk_TYPE rerun_sdk TYPE) + if(rerun_sdk_TYPE STREQUAL "STATIC_LIBRARY" AND NOT RERUN_INSTALL_RERUN_C) message(FATAL_ERROR "It is not possible to disable RERUN_INSTALL_RERUN_C option if rerun_sdk is compiled as static library.") endif() diff --git a/rerun_cpp/cmake_setup_in_detail.md b/rerun_cpp/cmake_setup_in_detail.md index f20c463aaa90..741dd645b3c1 100644 --- a/rerun_cpp/cmake_setup_in_detail.md +++ b/rerun_cpp/cmake_setup_in_detail.md @@ -34,6 +34,7 @@ Pre-built libraries can be downloaded from [the release pages](https://github.co If you want to match the behavior of `rerun_cpp_sdk.zip`, these libraries should be placed in the folder `rerun_cpp/lib`, renamed as: - Linux, x64: `librerun_c__linux_x64.a` + - Linux, Arm64: `librerun_c__linux_arm64.a` - Windows, x64: `rerun_c__win_x64.lib` - Mac, Intel: `librerun_c__macos_x64.a` - Mac, Apple Silicon: `librerun_c__macos_arm64.a` diff --git a/scripts/ci/bundle_and_upload_rerun_cpp.py b/scripts/ci/bundle_and_upload_rerun_cpp.py index a5731d906019..92819cff86da 100644 --- a/scripts/ci/bundle_and_upload_rerun_cpp.py +++ b/scripts/ci/bundle_and_upload_rerun_cpp.py @@ -34,15 +34,18 @@ def download_rerun_c(target_dir: str, git_hash: str, platform_filter: str = None # See reusable_build_and_upload_rerun_c.yml for available libraries. # See rerun_cpp_sdk/CMakeLists.txt for library names. for src, dst in [ - ("linux/librerun_c.a", "librerun_c__linux_x64.a"), - ("macos-arm/librerun_c.a", "librerun_c__macos_arm64.a"), - ("macos-intel/librerun_c.a", "librerun_c__macos_x64.a"), - ("windows/rerun_c.lib", "rerun_c__win_x64.lib"), + ("linux-arm64/librerun_c.a", "librerun_c__linux_arm64.a"), + ("linux-x64/librerun_c.a", "librerun_c__linux_x64.a"), + ("macos-arm64/librerun_c.a", "librerun_c__macos_arm64.a"), + ("macos-x64/librerun_c.a", "librerun_c__macos_x64.a"), + ("windows-x64/rerun_c.lib", "rerun_c__win_x64.lib"), ]: if platform_filter is not None and src.startswith(platform_filter) is False: continue blob = bucket.get_blob(f"commit/{git_hash}/rerun_c/{src}") + if blob is None: + raise RuntimeError(f"Blob not found: commit/{git_hash}/rerun_c/{src}") with open(f"{target_dir}/{dst}", "wb") as f: logging.info(f"Copying {blob.path} to {target_dir}/{dst}") blob.download_to_file(f) From fad5244ea04e3fc947d1d06fc2d91c131058a245 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:45:56 +0100 Subject: [PATCH 025/508] Add some common artefact directories to `.prettierignore` (#5504) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What ☝🏻 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5504/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5504/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5504/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5504) - [Docs preview](https://rerun.io/preview/db14a2752fdfd217c4e035ccd8e4ba758b7872f2/docs) - [Examples preview](https://rerun.io/preview/db14a2752fdfd217c4e035ccd8e4ba758b7872f2/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .prettierignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.prettierignore b/.prettierignore index 3778b915682d..0f5da258e2e1 100644 --- a/.prettierignore +++ b/.prettierignore @@ -8,3 +8,10 @@ web_viewer/re_viewer.js crates/re_web_viewer_server/web_viewer/re_viewer.js .pixi +/.nox +/build +/compare_screenshot +**/target +**/target_ra +**/target_wasm +**/venv* From d77e0255c7d96658089e21c824288f7dd6bcb581 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 14 Mar 2024 11:16:25 -0400 Subject: [PATCH 026/508] Add the remaining space views and name them consistently (#5498) ### What Just lots of boiler plate with some name changes. Also split the apy.py file into a few sub-modules because it was getting large. All SpaceViews now end in View. - Spatial2DView - Spatial3DView - BarChartView - TensorView - TextDocumentView - TextLogView - TimeSeriesView Testing it out on the plots example: ![image](https://github.com/rerun-io/rerun/assets/3312232/97890949-de50-464e-b640-014f151177b5) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5498/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5498/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5498/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5498) - [Docs preview](https://rerun.io/preview/bcbce7510db61092c96237a2668518ba564f0227/docs) - [Examples preview](https://rerun.io/preview/bcbce7510db61092c96237a2668518ba564f0227/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/blueprint/main.py | 6 +- .../rerun_sdk/rerun/blueprint/__init__.py | 25 ++- rerun_py/rerun_sdk/rerun/blueprint/api.py | 144 +------------- .../rerun_sdk/rerun/blueprint/containers.py | 97 ++++++++++ .../rerun_sdk/rerun/blueprint/space_views.py | 179 ++++++++++++++++++ tests/python/blueprint/main.py | 27 ++- 6 files changed, 317 insertions(+), 161 deletions(-) create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/containers.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/space_views.py diff --git a/examples/python/blueprint/main.py b/examples/python/blueprint/main.py index 51fd984dd1a1..401cc955fdfa 100755 --- a/examples/python/blueprint/main.py +++ b/examples/python/blueprint/main.py @@ -6,7 +6,7 @@ import numpy as np import rerun as rr # pip install rerun-sdk -from rerun.blueprint.api import Blueprint, BlueprintPanel, Grid, SelectionPanel, Spatial2D, TimePanel, Viewport +from rerun.blueprint import Blueprint, BlueprintPanel, Grid, SelectionPanel, Spatial2DView, TimePanel, Viewport def main() -> None: @@ -28,8 +28,8 @@ def main() -> None: blueprint = Blueprint( Viewport( Grid( - Spatial2D(name="Rect 0", origin="/", contents=["image", "rect/0"]), - Spatial2D(name="Rect 1", origin="/", contents=["image", "rect/1"]), + Spatial2DView(name="Rect 0", origin="/", contents=["image", "rect/0"]), + Spatial2DView(name="Rect 1", origin="/", contents=["image", "rect/1"]), ), auto_space_views=args.auto_space_views, ), diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 6a5d18c1059d..84a4b7063359 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -2,6 +2,7 @@ __all__ = [ "archetypes", + "BarChartView", "Blueprint", "BlueprintLike", "BlueprintPanel", @@ -10,10 +11,14 @@ "Grid", "Horizontal", "SelectionPanel", - "Spatial2D", - "Spatial3D", + "Spatial2DView", + "Spatial3DView", "Tabs", + "TensorView", + "TextDocumentView", + "TextLogView", "TimePanel", + "TimeSeriesView", "Vertical", "Viewport", ] @@ -23,13 +28,17 @@ Blueprint, BlueprintLike, BlueprintPanel, - Grid, - Horizontal, SelectionPanel, - Spatial2D, - Spatial3D, - Tabs, TimePanel, - Vertical, Viewport, ) +from .containers import Grid, Horizontal, Vertical +from .space_views import ( + BarChartView, + Spatial2DView, + Spatial3DView, + TensorView, + TextDocumentView, + TextLogView, + TimeSeriesView, +) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 5b76a5ed9621..6bea25e2a582 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -11,7 +11,7 @@ from ..recording_stream import RecordingStream from .archetypes import ContainerBlueprint, PanelBlueprint, SpaceViewBlueprint, SpaceViewContents, ViewportBlueprint from .components import ColumnShareArrayLike, RowShareArrayLike -from .components.container_kind import ContainerKind, ContainerKindLike +from .components.container_kind import ContainerKindLike SpaceViewContentsLike = Union[str, Sequence[str], Utf8Like, SpaceViewContents] @@ -70,6 +70,8 @@ def blueprint_path(self) -> str: def to_viewport(self) -> Viewport: """Convert this space view to a viewport.""" + from .containers import Grid + return Viewport(Grid(self)) def to_blueprint(self) -> Blueprint: @@ -112,56 +114,6 @@ def _iter_space_views(self) -> Iterable[bytes]: return [self.id.bytes] -class Spatial3D(SpaceView): - """A Spatial 3D space view.""" - - def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None - ): - """ - Construct a blueprint for a new 3D space view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this space view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. - name - The name of the space view. - - """ - super().__init__(class_identifier="3D", origin=origin, contents=contents, name=name) - - -class Spatial2D(SpaceView): - """A Spatial 2D space view.""" - - def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None - ): - """ - Construct a blueprint for a new 2D space view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this space view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. - name - The name of the space view. - - """ - super().__init__(class_identifier="2D", origin=origin, contents=contents, name=name) - - class Container: """ Base class for all container types. @@ -252,96 +204,6 @@ def _iter_space_views(self) -> Iterable[bytes]: return itertools.chain.from_iterable(sub._iter_space_views() for sub in self.contents) -class Horizontal(Container): - """A horizontal container.""" - - def __init__(self, *contents: Container | SpaceView, column_shares: Optional[ColumnShareArrayLike] = None): - """ - Construct a new horizontal container. - - Parameters - ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. - column_shares - The layout shares of the columns in the container. The share is used to determine what fraction of the total width each - column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. - - """ - super().__init__(*contents, kind=ContainerKind.Horizontal, column_shares=column_shares) - - -class Vertical(Container): - """A vertical container.""" - - def __init__(self, *contents: Container | SpaceView, row_shares: Optional[RowShareArrayLike] = None): - """ - Construct a new vertical container. - - Parameters - ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. - row_shares - The layout shares of the rows in the container. The share is used to determine what fraction of the total height each - row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. - - """ - super().__init__(*contents, kind=ContainerKind.Vertical, row_shares=row_shares) - - -class Grid(Container): - """A grid container.""" - - def __init__( - self, - *contents: Container | SpaceView, - column_shares: Optional[ColumnShareArrayLike] = None, - row_shares: Optional[RowShareArrayLike] = None, - grid_columns: Optional[int] = None, - ): - """ - Construct a new grid container. - - Parameters - ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. - column_shares - The layout shares of the columns in the container. The share is used to determine what fraction of the total width each - column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. - row_shares - The layout shares of the rows in the container. The share is used to determine what fraction of the total height each - row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. - grid_columns - The number of columns in the grid. - - """ - super().__init__( - *contents, - kind=ContainerKind.Grid, - column_shares=column_shares, - row_shares=row_shares, - grid_columns=grid_columns, - ) - - -class Tabs(Container): - """A tab container.""" - - def __init__(self, *contents: Container | SpaceView): - """ - Construct a new tab container. - - Parameters - ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. - - """ - super().__init__(*contents, kind=ContainerKind.Tabs) - - class Viewport: """ The top-level description of the Viewport. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/containers.py b/rerun_py/rerun_sdk/rerun/blueprint/containers.py new file mode 100644 index 000000000000..db47f5a1fdba --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/containers.py @@ -0,0 +1,97 @@ +from __future__ import annotations + +from typing import Optional + +from .api import Container, SpaceView +from .components import ColumnShareArrayLike, RowShareArrayLike +from .components.container_kind import ContainerKind + + +class Horizontal(Container): + """A horizontal container.""" + + def __init__(self, *contents: Container | SpaceView, column_shares: Optional[ColumnShareArrayLike] = None): + """ + Construct a new horizontal container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + column_shares + The layout shares of the columns in the container. The share is used to determine what fraction of the total width each + column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. + + """ + super().__init__(*contents, kind=ContainerKind.Horizontal, column_shares=column_shares) + + +class Vertical(Container): + """A vertical container.""" + + def __init__(self, *contents: Container | SpaceView, row_shares: Optional[RowShareArrayLike] = None): + """ + Construct a new vertical container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + row_shares + The layout shares of the rows in the container. The share is used to determine what fraction of the total height each + row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. + + """ + super().__init__(*contents, kind=ContainerKind.Vertical, row_shares=row_shares) + + +class Grid(Container): + """A grid container.""" + + def __init__( + self, + *contents: Container | SpaceView, + column_shares: Optional[ColumnShareArrayLike] = None, + row_shares: Optional[RowShareArrayLike] = None, + grid_columns: Optional[int] = None, + ): + """ + Construct a new grid container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + column_shares + The layout shares of the columns in the container. The share is used to determine what fraction of the total width each + column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. + row_shares + The layout shares of the rows in the container. The share is used to determine what fraction of the total height each + row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. + grid_columns + The number of columns in the grid. + + """ + super().__init__( + *contents, + kind=ContainerKind.Grid, + column_shares=column_shares, + row_shares=row_shares, + grid_columns=grid_columns, + ) + + +class Tabs(Container): + """A tab container.""" + + def __init__(self, *contents: Container | SpaceView): + """ + Construct a new tab container. + + Parameters + ---------- + *contents: + All positional arguments are the contents of the container, which may be either other containers or space views. + + """ + super().__init__(*contents, kind=ContainerKind.Tabs) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py new file mode 100644 index 000000000000..80df3a462adf --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py @@ -0,0 +1,179 @@ +from __future__ import annotations + +from ..datatypes import EntityPathLike, Utf8Like +from .api import SpaceView, SpaceViewContentsLike + + +class BarChartView(SpaceView): + """A bar chart view.""" + + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): + """ + Construct a blueprint for a new bar chart view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the view. + + """ + super().__init__(class_identifier="Bar Chart", origin=origin, contents=contents, name=name) + + +class Spatial2DView(SpaceView): + """A Spatial 2D view.""" + + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): + """ + Construct a blueprint for a new spatial 2D view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the view. + + """ + super().__init__(class_identifier="2D", origin=origin, contents=contents, name=name) + + +class Spatial3DView(SpaceView): + """A Spatial 3D view.""" + + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): + """ + Construct a blueprint for a new spatial 3D view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the view. + + """ + super().__init__(class_identifier="3D", origin=origin, contents=contents, name=name) + + +class TensorView(SpaceView): + """A tensor view.""" + + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): + """ + Construct a blueprint for a new tensor view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the view. + + """ + super().__init__(class_identifier="Tensor", origin=origin, contents=contents, name=name) + + +class TextDocumentView(SpaceView): + """A text document view.""" + + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): + """ + Construct a blueprint for a new text document view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the view. + + """ + super().__init__(class_identifier="Text Document", origin=origin, contents=contents, name=name) + + +class TextLogView(SpaceView): + """A text log view.""" + + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): + """ + Construct a blueprint for a new text log view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the view. + + """ + super().__init__(class_identifier="TextLog", origin=origin, contents=contents, name=name) + + +class TimeSeriesView(SpaceView): + """A time series view.""" + + def __init__( + self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + ): + """ + Construct a blueprint for a new time series view. + + Parameters + ---------- + origin + The `EntityPath` to use as the origin of this view. All other entities will be transformed + to be displayed relative to this origin. + contents + The contents of the view. Most commonly specified as a query expression. The individual + sub-expressions must either be newline separate, or provided as a list of strings. + See: [rerun.blueprint.components.QueryExpression][]. + name + The name of the view. + + """ + super().__init__(class_identifier="Time Series", origin=origin, contents=contents, name=name) diff --git a/tests/python/blueprint/main.py b/tests/python/blueprint/main.py index 3d431a2678f5..73723bea1d9c 100644 --- a/tests/python/blueprint/main.py +++ b/tests/python/blueprint/main.py @@ -2,24 +2,33 @@ import rerun as rr from numpy.random import default_rng -from rerun.blueprint import Blueprint, Grid, Horizontal, Spatial2D, Spatial3D, Tabs, Vertical, Viewport -from rerun.blueprint.api import TimePanel +from rerun.blueprint import ( + Blueprint, + Grid, + Horizontal, + Spatial2DView, + Spatial3DView, + Tabs, + TimePanel, + Vertical, + Viewport, +) if __name__ == "__main__": blueprint = Blueprint( Viewport( Vertical( - Spatial3D(origin="/test1"), + Spatial3DView(origin="/test1"), Horizontal( Tabs( - Spatial3D(origin="/test1"), - Spatial2D(origin="/test2"), + Spatial3DView(origin="/test1"), + Spatial2DView(origin="/test2"), ), Grid( - Spatial3D(origin="/test1"), - Spatial2D(origin="/test2"), - Spatial3D(origin="/test1"), - Spatial2D(origin="/test2"), + Spatial3DView(origin="/test1"), + Spatial2DView(origin="/test2"), + Spatial3DView(origin="/test1"), + Spatial2DView(origin="/test2"), grid_columns=3, column_shares=[1, 1, 1], ), From 045923a9f30fdcca909674ffca1f780b5a553ece Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 14 Mar 2024 16:33:00 +0100 Subject: [PATCH 027/508] Rename `.blueprint` extension to `.rbl` (#5506) ### What Three letters is common. You can read it as "Rerun Blueprint Layout" or maybe "Rerun BLuprint". Can be pronounced as "rebel" ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5506/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5506/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5506/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5506) - [Docs preview](https://rerun.io/preview/d8af706a0b2ee89c43bfd2ccbc2de9779b9b5e14/docs) - [Examples preview](https://rerun.io/preview/d8af706a0b2ee89c43bfd2ccbc2de9779b9b5e14/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_log_encoding/src/decoder/mod.rs | 2 +- crates/re_ui/src/command.rs | 2 +- crates/re_viewer/src/app.rs | 2 +- crates/re_viewer/src/saving.rs | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/re_log_encoding/src/decoder/mod.rs b/crates/re_log_encoding/src/decoder/mod.rs index 48eb1f42fb44..fc278988e430 100644 --- a/crates/re_log_encoding/src/decoder/mod.rs +++ b/crates/re_log_encoding/src/decoder/mod.rs @@ -22,7 +22,7 @@ pub enum VersionPolicy { /// Return [`DecodeError::IncompatibleRerunVersion`] if the versions aren't compatible. /// - /// We usually use this for tests, and for loading `.blueprint` files. + /// We usually use this for tests, and for loading `.rbl` blueprint files. Error, } diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs index 3e95bbb9f54c..918d875442b1 100644 --- a/crates/re_ui/src/command.rs +++ b/crates/re_ui/src/command.rs @@ -101,7 +101,7 @@ impl UICommand { "Save data for the current loop selection to a Rerun data file (.rrd)", ), - Self::SaveBlueprint => ("Save blueprint…", "Save the current viewer setup as a Rerun blueprint file (.blueprint)"), + Self::SaveBlueprint => ("Save blueprint…", "Save the current viewer setup as a Rerun blueprint file (.rbl)"), Self::Open => ("Open…", "Open any supported files (.rrd, images, meshes, …)"), diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index a4b90289bf5f..1faf301ecbff 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -1541,7 +1541,7 @@ fn save_blueprint(app: &mut App, store_context: Option<&StoreContext<'_>>) { let entity_db = store_context.blueprint; let file_name = format!( - "{}.blueprint", + "{}.rbl", crate::saving::sanitize_app_id(&store_context.app_id) ); let title = "Save blueprint"; diff --git a/crates/re_viewer/src/saving.rs b/crates/re_viewer/src/saving.rs index 9788934e2127..1cd59e2dfeb4 100644 --- a/crates/re_viewer/src/saving.rs +++ b/crates/re_viewer/src/saving.rs @@ -37,7 +37,7 @@ pub fn default_blueprint_path(app_id: &ApplicationId) -> anyhow::Result MAX_PATH { anyhow::bail!( @@ -56,7 +56,7 @@ pub fn default_blueprint_path(app_id: &ApplicationId) -> anyhow::Result Date: Thu, 14 Mar 2024 11:41:56 -0400 Subject: [PATCH 028/508] Add support for active_tab (#5499) ### What Referring to an object created in the same constructor is somewhat awkward. Forcing users to create the object out-of-line so they can assign it to a variable and then refer to it is just a pain. Specifying a name or index seems like a convenient middle ground. Example ```python Tabs( BarChartView(name="Bar Chart", origin="/bar_chart", contents=["/bar_chart/**"]), TimeSeriesView(name="Curves", origin="/curves", contents=["/curves/**"]), TimeSeriesView(name="Trig", origin="/trig", contents=["/trig/**"]), TimeSeriesView(name="Classification", origin="/classification", contents=["/classification/**"]), active_tab="Curves", ), ``` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5499/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5499/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5499/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5499) - [Docs preview](https://rerun.io/preview/4c45a10b77cb3dd4794ca2d2ac8267e3d9230606/docs) - [Examples preview](https://rerun.io/preview/4c45a10b77cb3dd4794ca2d2ac8267e3d9230606/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- rerun_py/rerun_sdk/rerun/blueprint/api.py | 14 +++++++++++++- rerun_py/rerun_sdk/rerun/blueprint/containers.py | 6 ++++-- rerun_py/rerun_sdk/rerun/script_helpers.py | 7 +++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 6bea25e2a582..ae031e3ded94 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -134,6 +134,7 @@ def __init__( column_shares: Optional[ColumnShareArrayLike] = None, row_shares: Optional[RowShareArrayLike] = None, grid_columns: Optional[int] = None, + active_tab: Optional[int | str] = None, ): """ Construct a new container. @@ -155,6 +156,8 @@ def __init__( This is only applicable to `Vertical` or `Grid` containers. grid_columns The number of columns in the grid. This is only applicable to `Grid` containers. + active_tab + The active tab in the container. This is only applicable to `Tabs` containers. """ self.id = uuid.uuid4() @@ -163,6 +166,7 @@ def __init__( self.column_shares = column_shares self.row_shares = row_shares self.grid_columns = grid_columns + self.active_tab = active_tab def blueprint_path(self) -> str: """ @@ -183,8 +187,15 @@ def to_blueprint(self) -> Blueprint: def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" - for sub in self.contents: + active_tab_path = None + + for i, sub in enumerate(self.contents): sub._log_to_stream(stream) + if i == self.active_tab or (isinstance(sub, SpaceView) and sub.name == self.active_tab): + active_tab_path = sub.blueprint_path() + + if self.active_tab is not None and active_tab_path is None: + raise ValueError(f"Active tab '{self.active_tab}' not found in the container contents.") arch = ContainerBlueprint( container_kind=self.kind, @@ -193,6 +204,7 @@ def _log_to_stream(self, stream: RecordingStream) -> None: row_shares=self.row_shares, visible=True, grid_columns=self.grid_columns, + active_tab=active_tab_path, ) stream.log(self.blueprint_path(), arch) # type: ignore[attr-defined] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/containers.py b/rerun_py/rerun_sdk/rerun/blueprint/containers.py index db47f5a1fdba..243201151c37 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/containers.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/containers.py @@ -84,7 +84,7 @@ def __init__( class Tabs(Container): """A tab container.""" - def __init__(self, *contents: Container | SpaceView): + def __init__(self, *contents: Container | SpaceView, active_tab: Optional[int | str] = None): """ Construct a new tab container. @@ -92,6 +92,8 @@ def __init__(self, *contents: Container | SpaceView): ---------- *contents: All positional arguments are the contents of the container, which may be either other containers or space views. + active_tab: + The index or name of the active tab. """ - super().__init__(*contents, kind=ContainerKind.Tabs) + super().__init__(*contents, kind=ContainerKind.Tabs, active_tab=active_tab) diff --git a/rerun_py/rerun_sdk/rerun/script_helpers.py b/rerun_py/rerun_sdk/rerun/script_helpers.py index d4542a7e9362..86d48e01338d 100644 --- a/rerun_py/rerun_sdk/rerun/script_helpers.py +++ b/rerun_py/rerun_sdk/rerun/script_helpers.py @@ -65,6 +65,7 @@ def script_setup( args: Namespace, application_id: str, recording_id: str | UUID | None = None, + blueprint: rr.blueprint.Blueprint | None = None, ) -> RecordingStream: """ Run common Rerun script setup actions. Connect to the viewer if necessary. @@ -86,6 +87,8 @@ def script_setup( processes to log to the same Rerun instance (and be part of the same recording), you will need to manually assign them all the same recording_id. Any random UUIDv4 will work, or copy the recording id for the parent process. + blueprint : Optional[rr.blueprint.Blueprint] + An optional blueprint to use for the viewer. """ rr.init( @@ -106,11 +109,11 @@ def script_setup( # Send logging data to separate `rerun` process. # You can omit the argument to connect to the default address, # which is `127.0.0.1:9876`. - rec.connect(args.addr) # type: ignore[attr-defined] + rec.connect(args.addr, blueprint=blueprint) # type: ignore[attr-defined] elif args.save is not None: rec.save(args.save) # type: ignore[attr-defined] elif not args.headless: - rec.spawn() # type: ignore[attr-defined] + rec.spawn(blueprint=blueprint) # type: ignore[attr-defined] return rec From 56bb2eaee98741f1a58306323a31d1d114c9b5e4 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:32:19 +0100 Subject: [PATCH 029/508] Build CLI for Linux ARM64 (#5503) ### What Add support for building a Linux ARM64 version of the CLI in our build system. - Follow-up to https://github.com/rerun-io/rerun/pull/5489 - Part of #4136 This PR introduces ugly work-around to be cleaned when our pixi deps support linux-aarch64: - https://github.com/rerun-io/rerun/issues/5507 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5503/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5503/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5503/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5503) - [Docs preview](https://rerun.io/preview/65c8082ad0c5482bad9167e8620490494f80637e/docs) - [Examples preview](https://rerun.io/preview/65c8082ad0c5482bad9167e8620490494f80637e/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Andreas Reich --- .github/workflows/on_push_main.yml | 46 +++++++++++-------- .../reusable_build_and_upload_rerun_c.yml | 1 + .../reusable_build_and_upload_rerun_cli.yml | 39 ++++++++++++---- scripts/ci/sync_release_assets.py | 24 ++++++---- 4 files changed, 74 insertions(+), 36 deletions(-) diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 101cfaa4935c..9e29139a2863 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -162,40 +162,49 @@ jobs: # ----------------------------------------------------------------------------------- # Build rerun-cli (rerun binaries): - build-rerun-cli-and-upload-linux: + build-rerun-cli-and-upload-linux-arm64: + needs: [checks] + name: "Linux-arm64: Build & Upload rerun-cli" + uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + with: + CONCURRENCY: push-linux-arm64-${{ github.ref_name }} + PLATFORM: linux-arm64 + secrets: inherit + + build-rerun-cli-and-upload-linux-x64: needs: [checks] name: "Linux-x64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-linux-${{ github.ref_name }} - PLATFORM: linux + CONCURRENCY: push-linux-x64-${{ github.ref_name }} + PLATFORM: linux-x64 secrets: inherit - build-rerun-cli-and-upload-macos-intel: + build-rerun-cli-and-upload-macos-x64: needs: [checks] - name: "Mac-Intel: Build & Upload rerun-cli" + name: "Mac-x64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-macos-intel-${{ github.ref_name }} - PLATFORM: macos-intel + CONCURRENCY: push-macos-x64-${{ github.ref_name }} + PLATFORM: macos-x64 secrets: inherit - build-rerun-cli-and-upload-macos-arm: + build-rerun-cli-and-upload-macos-arm64: needs: [checks] - name: "Mac-Arm: Build & Upload rerun-cli" + name: "Mac-arm64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-macos-arm-${{ github.ref_name }} - PLATFORM: macos-arm + CONCURRENCY: push-macos-arm64-${{ github.ref_name }} + PLATFORM: macos-arm64 secrets: inherit - build-rerun-cli-and-upload-windows: + build-rerun-cli-and-upload-windows-x64: needs: [checks] name: "Windows-x64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-windows-${{ github.ref_name }} - PLATFORM: windows + CONCURRENCY: push-windows-x64-${{ github.ref_name }} + PLATFORM: windows-x64 secrets: inherit # ----------------------------------------------------------------------------------- @@ -305,10 +314,11 @@ jobs: build-rerun_c-and-upload-macos-x64, build-rerun_c-and-upload-macos-arm64, build-rerun_c-and-upload-windows-x64, - build-rerun-cli-and-upload-linux, - build-rerun-cli-and-upload-macos-intel, - build-rerun-cli-and-upload-macos-arm, - build-rerun-cli-and-upload-windows, + build-rerun-cli-and-upload-linux-x64, + build-rerun-cli-and-upload-linux-arm64, + build-rerun-cli-and-upload-macos-x64, + build-rerun-cli-and-upload-macos-arm64, + build-rerun-cli-and-upload-windows-x64, bundle-and-upload-rerun_cpp, ] runs-on: "ubuntu-latest" diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml index 28bed0855d01..ffb07202f703 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_c.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml @@ -39,6 +39,7 @@ on: required: false type: string default: "adhoc" + description: "Concurrency group to use" concurrency: group: ${{ inputs.CONCURRENCY }}-build-rerun_c diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index 3df8a86aeb93..3c73ab51c177 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -21,22 +21,25 @@ on: workflow_dispatch: inputs: ADHOC_NAME: - required: true + required: false type: string + default: "" description: "Name of the adhoc build, used for upload directory" PLATFORM: type: choice options: - - linux - - windows - - macos-arm - - macos-intel + - linux-arm64 + - linux-x64 + - windows-x64 + - macos-arm64 + - macos-x64 description: "Platform to build for" required: true CONCURRENCY: required: false type: string default: "adhoc" + description: "Concurrency group to use" concurrency: group: ${{ inputs.CONCURRENCY }}-build-rerun-cli @@ -71,25 +74,31 @@ jobs: shell: bash run: | case "${{ inputs.PLATFORM }}" in - linux) + linux-arm64) + runner="buildjet-8vcpu-ubuntu-2204-arm" + target="aarch64-unknown-linux-gnu" + container="null" + bin_name="rerun" + ;; + linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" container="{'image': 'rerunio/ci_docker:0.11.0'}" bin_name="rerun" ;; - windows) + windows-x64) runner="windows-latest-8-cores" target="x86_64-pc-windows-msvc" container="null" bin_name="rerun.exe" ;; - macos-arm) + macos-arm64) runner="macos-latest-large" # See https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/ target="aarch64-apple-darwin" container="null" bin_name="rerun" ;; - macos-intel) + macos-x64) runner="macos-latest-large" # See https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/ target="x86_64-apple-darwin" container="null" @@ -138,16 +147,26 @@ jobs: targets: ${{ needs.set-config.outputs.TARGET }} - uses: prefix-dev/setup-pixi@v0.4.1 + if: ${{ inputs.PLATFORM != 'linux-arm64' }} # TODO(#5507): see below with: pixi-version: v0.13.0 - name: Build web-viewer (release) + if: ${{ inputs.PLATFORM != 'linux-arm64' }} # TODO(#5507): see below shell: bash run: | pixi run cargo run --locked -p re_build_web_viewer -- --release + # TODO(#5507): supress this workaround when pixi dependencies are available on linux-arm64 + - name: Build web-viewer (release, Linux ARM64) + if: ${{ inputs.PLATFORM == 'linux-arm64' }} + shell: bash + run: | + sudo apt-get install binaryen + cargo run --locked -p re_build_web_viewer -- --release + # This does not run in the pixi environment, doing so - # causes it to select the wrong compiler on macos-arm + # causes it to select the wrong compiler on macos-arm64 - name: Build rerun-cli shell: bash env: diff --git a/scripts/ci/sync_release_assets.py b/scripts/ci/sync_release_assets.py index 7cb7dc8cf1f2..d75f262a5d4f 100644 --- a/scripts/ci/sync_release_assets.py +++ b/scripts/ci/sync_release_assets.py @@ -96,19 +96,23 @@ def fetch_binary_assets( rerun_c_blobs = [ ( f"rerun_c-{tag}-x86_64-pc-windows-msvc.lib", - f"commit/{commit_short}/rerun_c/windows/rerun_c.lib", + f"commit/{commit_short}/rerun_c/windows-x64/rerun_c.lib", ), ( f"librerun_c-{tag}-x86_64-unknown-linux-gnu.a", - f"commit/{commit_short}/rerun_c/linux/librerun_c.a", + f"commit/{commit_short}/rerun_c/linux-x64/librerun_c.a", + ), + ( + f"librerun_c-{tag}-aarch64-unknown-linux-gnu.a", + f"commit/{commit_short}/rerun_c/linux-arm64/librerun_c.a", ), ( f"librerun_c-{tag}-aarch64-apple-darwin.a", - f"commit/{commit_short}/rerun_c/macos-arm/librerun_c.a", + f"commit/{commit_short}/rerun_c/macos-arm64/librerun_c.a", ), ( f"librerun_c-{tag}-x86_64-apple-darwin.a", - f"commit/{commit_short}/rerun_c/macos-intel/librerun_c.a", + f"commit/{commit_short}/rerun_c/macos-x64/librerun_c.a", ), ] for name, blob_url in rerun_c_blobs: @@ -139,19 +143,23 @@ def fetch_binary_assets( rerun_cli_blobs = [ ( f"rerun-cli-{tag}-x86_64-pc-windows-msvc.exe", - f"commit/{commit_short}/rerun-cli/windows/rerun.exe", + f"commit/{commit_short}/rerun-cli/windows-x64/rerun.exe", ), ( f"rerun-cli-{tag}-x86_64-unknown-linux-gnu", - f"commit/{commit_short}/rerun-cli/linux/rerun", + f"commit/{commit_short}/rerun-cli/linux-x64/rerun", + ), + ( + f"rerun-cli-{tag}-aarch64-unknown-linux-gnu", + f"commit/{commit_short}/rerun-cli/linux-arm64/rerun", ), ( f"rerun-cli-{tag}-aarch64-apple-darwin", - f"commit/{commit_short}/rerun-cli/macos-arm/rerun", + f"commit/{commit_short}/rerun-cli/macos-arm64/rerun", ), ( f"rerun-cli-{tag}-x86_64-apple-darwin", - f"commit/{commit_short}/rerun-cli/macos-intel/rerun", + f"commit/{commit_short}/rerun-cli/macos-x64/rerun", ), ] for name, blob_url in rerun_cli_blobs: From ded377098c0d8c84ee0afcae2b8739df5f40f508 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 14 Mar 2024 15:02:35 -0400 Subject: [PATCH 030/508] Add missing Tabs import to blueprint/__init__.py (#5515) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- rerun_py/rerun_sdk/rerun/blueprint/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 84a4b7063359..0924e508e31a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -32,7 +32,7 @@ TimePanel, Viewport, ) -from .containers import Grid, Horizontal, Vertical +from .containers import Grid, Horizontal, Tabs, Vertical from .space_views import ( BarChartView, Spatial2DView, From 8fad2caac682a100cd03b7febe415b7191f69db0 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 15 Mar 2024 08:40:35 +0100 Subject: [PATCH 031/508] Use blueprint in arkit_scenes demo, leveraging the viewer's ability to re-project 3D->2D (#5510) ### What * Part of #3412 Removes a lot of code from the arkit demo and makes it look a little bit nicer (beyond the 2d reprojections looking broken before!): * two tabs for 2D, one with depth one with rgb * named space views ![image](https://github.com/rerun-io/rerun/assets/1220815/eb7616da-ed6f-45bc-93ca-9453fdf5be17) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5510/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5510/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5510/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5510) - [Docs preview](https://rerun.io/preview/f2544987580d94f0d912eeaa224a98d46745f2a4/docs) - [Examples preview](https://rerun.io/preview/f2544987580d94f0d912eeaa224a98d46745f2a4/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/arkit_scenes/main.py | 233 +++--------------- pixi.toml | 3 +- .../rerun_sdk/rerun/blueprint/.gitattributes | 11 - rerun_py/rerun_sdk/rerun/script_helpers.py | 4 +- .../tests/unit/test_container_blueprint.py | 4 +- 5 files changed, 47 insertions(+), 208 deletions(-) delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/.gitattributes diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py index 6d166b30ed5d..8f0b0046591e 100755 --- a/examples/python/arkit_scenes/main.py +++ b/examples/python/arkit_scenes/main.py @@ -8,10 +8,9 @@ from typing import Any, Tuple import cv2 -import matplotlib.pyplot as plt import numpy as np -import numpy.typing as npt import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rbl import trimesh from download_dataset import AVAILABLE_RECORDINGS, ensure_recording_available from scipy.spatial.transform import Rotation as R @@ -84,6 +83,9 @@ bounding box is logged as a separate entity to the common [world/annotations](recording://world/annotations) parent. """.strip() +lowres_posed_entity_path = "world/camera_lowres" +highres_entity_path = "world/camera_highres" + def load_json(js_path: Path) -> dict[str, Any]: with open(js_path) as f: @@ -91,29 +93,18 @@ def load_json(js_path: Path) -> dict[str, Any]: return json_data -def log_annotated_bboxes(annotation: dict[str, Any]) -> tuple[npt.NDArray[np.float64], list[str], list[Color]]: +def log_annotated_bboxes(annotation: dict[str, Any]) -> None: """ Logs annotated oriented bounding boxes to Rerun. - We currently calculate and return the 3D bounding boxes keypoints, labels, and colors for each object to log them in - each camera frame TODO(#3412): once resolved this can be removed. - annotation json file | |-- label: object name of bounding box | |-- axesLengths[x, y, z]: size of the origin bounding-box before transforming | |-- centroid[]: the translation matrix (1,3) of bounding-box | |-- normalizedAxes[]: the rotation matrix (3,3) of bounding-box """ - bbox_list = [] - bbox_labels = [] - num_objects = len(annotation["data"]) - # Generate a color per object that can be reused across both 3D obb and their 2D projections - # TODO(#3412, #1728): once resolved this can be removed - color_positions = np.linspace(0, 1, num_objects) - colormap = plt.colormaps["viridis"] - colors = [colormap(pos) for pos in color_positions] - - for i, label_info in enumerate(annotation["data"]): + + for label_info in annotation["data"]: uid = label_info["uid"] label = label_info["label"] @@ -130,184 +121,25 @@ def log_annotated_bboxes(annotation: dict[str, Any]) -> tuple[npt.NDArray[np.flo centers=centroid, rotations=rr.Quaternion(xyzw=rot.as_quat()), labels=label, - colors=colors[i], ), timeless=True, ) - box3d = compute_box_3d(half_size, centroid, rotation) - bbox_list.append(box3d) - bbox_labels.append(label) - bboxes_3d = np.array(bbox_list) - return bboxes_3d, bbox_labels, colors - - -def compute_box_3d( - half_size: npt.NDArray[np.float64], transform: npt.NDArray[np.float64], rotation: npt.NDArray[np.float64] -) -> npt.NDArray[np.float64]: - """ - Given obb compute 3D keypoints of the box. - - TODO(#3412): once resolved this can be removed - """ - length, height, width = half_size.tolist() - center = np.reshape(transform, (-1, 3)) - center = center.reshape(3) - x_corners = [length, length, -length, -length, length, length, -length, -length] - y_corners = [height, -height, -height, height, height, -height, -height, height] - z_corners = [width, width, width, width, -width, -width, -width, -width] - corners_3d = np.dot(np.transpose(rotation), np.vstack([x_corners, y_corners, z_corners])) - - corners_3d[0, :] += center[0] - corners_3d[1, :] += center[1] - corners_3d[2, :] += center[2] - bbox3d_raw = np.transpose(corners_3d) - return bbox3d_raw - - -def log_line_segments(entity_path: str, bboxes_2d_filtered: npt.NDArray[np.float64], color: Color, label: str) -> None: - """ - Generates line segments for each object's bounding box in 2D. - - Box corner order that we return is of the format below: - 6 -------- 7 - /| /| - 5 -------- 4 . - | | | | - . 2 -------- 3 - |/ |/ - 1 -------- 0 - - TODO(#3412): once resolved this can be removed - - :param bboxes_2d_filtered: - A numpy array of shape (8, 2), representing the filtered 2D keypoints of the 3D bounding boxes. - :return: A numpy array of shape (24, 2), representing the line segments for each object's bounding boxes. - Even and odd indices represent the start and end points of each line segment respectively. - """ - - # Calculate the centroid of the 2D keypoints - valid_points = bboxes_2d_filtered[~np.isnan(bboxes_2d_filtered).any(axis=1)] - - # log centroid and add label so that object label is visible in the 2D view - if valid_points.size > 0: - centroid = valid_points.mean(axis=0) - rr.log(f"{entity_path}/centroid", rr.Points2D(centroid, colors=color, labels=label)) - else: - pass - - segments = [ - # bottom of bbox - [bboxes_2d_filtered[0], bboxes_2d_filtered[1]], - [bboxes_2d_filtered[1], bboxes_2d_filtered[2]], - [bboxes_2d_filtered[2], bboxes_2d_filtered[3]], - [bboxes_2d_filtered[3], bboxes_2d_filtered[0]], - # top of bbox - [bboxes_2d_filtered[4], bboxes_2d_filtered[5]], - [bboxes_2d_filtered[5], bboxes_2d_filtered[6]], - [bboxes_2d_filtered[6], bboxes_2d_filtered[7]], - [bboxes_2d_filtered[7], bboxes_2d_filtered[4]], - # sides of bbox - [bboxes_2d_filtered[0], bboxes_2d_filtered[4]], - [bboxes_2d_filtered[1], bboxes_2d_filtered[5]], - [bboxes_2d_filtered[2], bboxes_2d_filtered[6]], - [bboxes_2d_filtered[3], bboxes_2d_filtered[7]], - ] - - rr.log(entity_path, rr.LineStrips2D(segments, colors=color)) - - -def project_3d_bboxes_to_2d_keypoints( - bboxes_3d: npt.NDArray[np.float64], - camera_from_world: rr.TranslationRotationScale3D, - intrinsic: npt.NDArray[np.float64], - img_width: int, - img_height: int, -) -> npt.NDArray[np.float64]: - """ - Returns 2D keypoints of the 3D bounding box in the camera view. - - TODO(#3412): once resolved this can be removed - Args: - bboxes_3d: (nObjects, 8, 3) containing the 3D bounding box keypoints in world frame. - camera_from_world: Tuple containing the camera translation and rotation_quaternion in world frame. - intrinsic: (3,3) containing the camera intrinsic matrix. - img_width: Width of the image. - img_height: Height of the image. - - Returns - ------- - bboxes_2d_filtered: - A numpy array of shape (nObjects, 8, 2), representing the 2D keypoints of the 3D bounding boxes. That - are within the image frame. - - """ - - translation, rotation_q = camera_from_world.translation, camera_from_world.rotation - # We know we stored the rotation as a quaternion, so extract it again. - # TODO(#3467): This shouldn't directly access rotation.inner - rotation = R.from_quat(rotation_q.inner) # type: ignore[union-attr] - - # Transform 3D keypoints from world to camera frame - world_to_camera_rotation = rotation.as_matrix() - world_to_camera_translation = np.array(translation).reshape(3, 1) - # Tile translation to match bounding box shape, (nObjects, 1, 3) - world_to_camera_translation_tiled = np.tile(world_to_camera_translation.T, (bboxes_3d.shape[0], 1, 1)) - # Transform 3D bounding box keypoints from world to camera frame to filter out points behind the camera - camera_points = ( - np.einsum("ij,afj->afi", world_to_camera_rotation, bboxes_3d[..., :3]) + world_to_camera_translation_tiled - ) - # Check if the points are in front of the camera - depth_mask = camera_points[..., 2] > 0 - # convert to transformation matrix shape of (3, 4) - world_to_camera = np.hstack([world_to_camera_rotation, world_to_camera_translation]) - transformation_matrix = intrinsic @ world_to_camera - # add batch dimension to match bounding box shape, (nObjects, 3, 4) - transformation_matrix = np.tile(transformation_matrix, (bboxes_3d.shape[0], 1, 1)) - # bboxes_3d: [nObjects, 8, 3] -> [nObjects, 8, 4] to allow for batch projection - bboxes_3d = np.concatenate([bboxes_3d, np.ones((bboxes_3d.shape[0], bboxes_3d.shape[1], 1))], axis=-1) - # Apply depth mask to filter out points behind the camera - bboxes_3d[~depth_mask] = np.nan - # batch projection of points using einsum - bboxes_2d = np.einsum("vab,fnb->vfna", transformation_matrix, bboxes_3d) - bboxes_2d = bboxes_2d[..., :2] / bboxes_2d[..., 2:] - # nViews irrelevant, squeeze out - bboxes_2d = bboxes_2d[0] - - # Filter out keypoints that are not within the frame - mask_x = (bboxes_2d[:, :, 0] >= 0) & (bboxes_2d[:, :, 0] < img_width) - mask_y = (bboxes_2d[:, :, 1] >= 0) & (bboxes_2d[:, :, 1] < img_height) - mask = mask_x & mask_y - bboxes_2d_filtered = np.where(mask[..., np.newaxis], bboxes_2d, np.nan) - - return bboxes_2d_filtered - def log_camera( intri_path: Path, frame_id: str, poses_from_traj: dict[str, rr.TranslationRotationScale3D], entity_id: str, - bboxes: npt.NDArray[np.float64], - bbox_labels: list[str], - colors: list[Color], ) -> None: """Logs camera transform and 3D bounding boxes in the image frame.""" w, h, fx, fy, cx, cy = np.loadtxt(intri_path) intrinsic = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]]) camera_from_world = poses_from_traj[frame_id] - # TODO(#3412): once resolved this can be removed - # Project 3D bounding boxes into 2D image - bboxes_2d = project_3d_bboxes_to_2d_keypoints(bboxes, camera_from_world, intrinsic, img_width=w, img_height=h) - # clear previous centroid labels rr.log(f"{entity_id}/bbox-2D-segments", rr.Clear(recursive=True)) - # Log line segments for each bounding box in the image - for i, (label, bbox_2d) in enumerate(zip(bbox_labels, bboxes_2d)): - log_line_segments(f"{entity_id}/bbox-2D-segments/{label}", bbox_2d.reshape(-1, 2), colors[i], label) - # pathlib makes it easy to get the parent, but log methods requires a string rr.log(entity_id, rr.Transform3D(transform=camera_from_world)) rr.log(entity_id, rr.Pinhole(image_from_camera=intrinsic, resolution=[w, h])) @@ -430,10 +262,7 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: # load the obb annotations and log them in the world frame bbox_annotations_path = recording_path / f"{recording_path.stem}_3dod_annotation.json" annotation = load_json(bbox_annotations_path) - bboxes_3d, bbox_labels, colors_list = log_annotated_bboxes(annotation) - - lowres_posed_entity_id = "world/camera_lowres" - highres_entity_id = "world/camera_highres" + log_annotated_bboxes(annotation) print("Processing frames…") for frame_timestamp in tqdm(lowres_frame_ids): @@ -453,14 +282,11 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: lowres_intri_path, frame_timestamp, camera_from_world_dict, - lowres_posed_entity_id, - bboxes_3d, - bbox_labels, - colors_list, + lowres_posed_entity_path, ) - rr.log(f"{lowres_posed_entity_id}/rgb", rr.Image(rgb).compress(jpeg_quality=95)) - rr.log(f"{lowres_posed_entity_id}/depth", rr.DepthImage(depth, meter=1000)) + rr.log(f"{lowres_posed_entity_path}/rgb", rr.Image(rgb).compress(jpeg_quality=95)) + rr.log(f"{lowres_posed_entity_path}/depth", rr.DepthImage(depth, meter=1000)) # log the high res camera if high_res_exists: @@ -472,10 +298,7 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: highres_intri_path, closest_lowres_frame_id, camera_from_world_dict, - highres_entity_id, - bboxes_3d, - bbox_labels, - colors_list, + highres_entity_path, ) # load the highres image and depth if they exist @@ -484,8 +307,8 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: highres_rgb = cv2.cvtColor(highres_bgr, cv2.COLOR_BGR2RGB) - rr.log(f"{highres_entity_id}/rgb", rr.Image(highres_rgb).compress(jpeg_quality=75)) - rr.log(f"{highres_entity_id}/depth", rr.DepthImage(highres_depth, meter=1000)) + rr.log(f"{highres_entity_path}/rgb", rr.Image(highres_rgb).compress(jpeg_quality=75)) + rr.log(f"{highres_entity_path}/depth", rr.DepthImage(highres_depth, meter=1000)) def main() -> None: @@ -505,7 +328,33 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_arkit_scenes") + primary_camera_entity = highres_entity_path if args.include_highres else lowres_posed_entity_path + + rr.script_setup( + args, + "rerun_example_arkit_scenes", + blueprint=rbl.Horizontal( + rbl.Spatial3DView(name="3D"), + rbl.Vertical( + rbl.Tabs( + # Note that we re-project the annotations into the 2D views: + # For this to work, the origin of the 2D views has to be a pinhole camera, + # this way the viewer knows how to project the 3D annotations into the 2D views. + rbl.Spatial2DView( + name="RGB", + origin=primary_camera_entity, + contents=[f"{primary_camera_entity}/rgb", "/world/annotations/**"], + ), + rbl.Spatial2DView( + name="Depth", + origin=primary_camera_entity, + contents=[f"{primary_camera_entity}/depth", "/world/annotations/**"], + ), + ), + rbl.TextDocumentView(name="Readme"), + ), + ), + ) recording_path = ensure_recording_available(args.video_id, args.include_highres) log_arkit(recording_path, args.include_highres) diff --git a/pixi.toml b/pixi.toml index 27a4b5a6773a..b24f5bf5c0ac 100644 --- a/pixi.toml +++ b/pixi.toml @@ -77,13 +77,14 @@ lint-rs-all = "cargo fmt --check" lint-py-fmt-check = "ruff format --check --config rerun_py/pyproject.toml" lint-py-blackdoc = "blackdoc --check" lint-py-mypy = "mypy --install-types --non-interactive --no-warn-unused-ignore" -lint-py-ruff = "ruff check --config rerun_py/pyproject.toml" +lint-py-ruff = "ruff format --check --config rerun_py/pyproject.toml" lint-taplo = "taplo fmt --check --diff" lint-typos = "typos" misc-fmt = "prettier --write '**/*.{yml,yaml,js,css,html}'" misc-fmt-check = "prettier --check '**/*.{yml,yaml,js,css,html}'" toml-fmt = "taplo fmt" +ruff-fmt = "ruff format --config rerun_py/pyproject.toml ." ruff-fix = "ruff --fix --config rerun_py/pyproject.toml ." py-build = "maturin develop --manifest-path rerun_py/Cargo.toml --extras=tests" diff --git a/rerun_py/rerun_sdk/rerun/blueprint/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/.gitattributes deleted file mode 100644 index 988541d69fd9..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/.gitattributes +++ /dev/null @@ -1,11 +0,0 @@ -# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs - -.gitattributes linguist-generated=true -__init__.py linguist-generated=true -auto_space_views.py linguist-generated=true -entity_properties_component.py linguist-generated=true -panel_view.py linguist-generated=true -query_expressions.py linguist-generated=true -space_view_component.py linguist-generated=true -space_view_maximized.py linguist-generated=true -viewport_layout.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/script_helpers.py b/rerun_py/rerun_sdk/rerun/script_helpers.py index 86d48e01338d..666ac742a392 100644 --- a/rerun_py/rerun_sdk/rerun/script_helpers.py +++ b/rerun_py/rerun_sdk/rerun/script_helpers.py @@ -65,7 +65,7 @@ def script_setup( args: Namespace, application_id: str, recording_id: str | UUID | None = None, - blueprint: rr.blueprint.Blueprint | None = None, + blueprint: rr.blueprint.BlueprintLike | None = None, ) -> RecordingStream: """ Run common Rerun script setup actions. Connect to the viewer if necessary. @@ -87,7 +87,7 @@ def script_setup( processes to log to the same Rerun instance (and be part of the same recording), you will need to manually assign them all the same recording_id. Any random UUIDv4 will work, or copy the recording id for the parent process. - blueprint : Optional[rr.blueprint.Blueprint] + blueprint : Optional[rr.blueprint.BlueprintLike] An optional blueprint to use for the viewer. """ diff --git a/rerun_py/tests/unit/test_container_blueprint.py b/rerun_py/tests/unit/test_container_blueprint.py index ad5739c67799..a16c762bc13a 100644 --- a/rerun_py/tests/unit/test_container_blueprint.py +++ b/rerun_py/tests/unit/test_container_blueprint.py @@ -1,7 +1,7 @@ from __future__ import annotations import itertools -from typing import Optional, cast +from typing import Any, Optional, Sequence, cast from rerun.blueprint.archetypes.container_blueprint import ContainerBlueprint from rerun.blueprint.components.active_tab import ActiveTab, ActiveTabBatch @@ -30,7 +30,7 @@ def test_container_blueprint() -> None: "my container", ] - contents_arrays = [ + contents_arrays: Sequence[Any] = [ None, [], ["space_view/1234", "container/5678"], From 33c53da38c7a6c220a6bb5e17d97bcb51b040c19 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Fri, 15 Mar 2024 09:33:40 +0100 Subject: [PATCH 032/508] Add `workflow_dispatch` to reusable_build_and_upload_wheels.yml (#5522) ### What I need that to test https://github.com/rerun-io/rerun/pull/5511 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../reusable_build_and_upload_wheels.yml | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 78f54e6a3438..137e39c9895c 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -22,6 +22,41 @@ on: type: string default: "" + workflow_dispatch: + inputs: + PLATFORM: + type: choice + options: + - linux-arm64 + - linux-x64 + - windows-x64 + - macos-arm64 + - macos-x64 + description: "Platform to build for" + required: true + MODE: + type: choice + required: false + options: + - pypi + - pr + description: "The build mode (`pypi` includes the web viewer, `pr` does not)" + CONCURRENCY: + required: false + type: string + default: "adhoc" + description: "Concurrency group to use" + WHEEL_ARTIFACT_NAME: + required: false + type: string + default: "" + description: "If set, will be saved under that name in the workflow artifacts" + RELEASE_COMMIT: + required: false + type: string + default: "" + description: "Release commit" + concurrency: group: ${{ inputs.CONCURRENCY }}-build-wheels cancel-in-progress: true From a79520e2b3cb5b3f6a1b39aacb414320d5005c0e Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 15 Mar 2024 10:24:20 +0100 Subject: [PATCH 033/508] Support loading `.bpl` blueprint files (#5513) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What * Part of https://github.com/rerun-io/rerun/issues/5294 This implements loading of blueprint files (.rbl) on native and on web, using either drag-and-drop of the `Open…` command. One shortcoming of the approach in this PR is documented here: * https://github.com/rerun-io/rerun/issues/5514 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5513/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5513/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5513/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5513) - [Docs preview](https://rerun.io/preview/9b3e7d9aed9113d340516caed9d87897c8ae8abb/docs) - [Examples preview](https://rerun.io/preview/9b3e7d9aed9113d340516caed9d87897c8ae8abb/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/data_loader/loader_rrd.rs | 6 +- crates/re_data_source/src/data_source.rs | 18 +++ crates/re_data_source/src/lib.rs | 13 +- crates/re_data_source/src/load_file.rs | 4 +- crates/re_entity_db/src/entity_db.rs | 9 +- crates/re_log_types/src/lib.rs | 11 ++ crates/re_viewer/src/app.rs | 140 +++++++++++------- crates/re_viewer/src/app_state.rs | 2 +- crates/re_viewer/src/store_hub.rs | 49 ++++-- crates/re_viewport/src/container.rs | 1 + 10 files changed, 172 insertions(+), 81 deletions(-) diff --git a/crates/re_data_source/src/data_loader/loader_rrd.rs b/crates/re_data_source/src/data_loader/loader_rrd.rs index 78b90bc10d66..a6f89c7dce3f 100644 --- a/crates/re_data_source/src/data_loader/loader_rrd.rs +++ b/crates/re_data_source/src/data_loader/loader_rrd.rs @@ -24,7 +24,8 @@ impl crate::DataLoader for RrdLoader { re_tracing::profile_function!(filepath.display().to_string()); let extension = crate::extension(&filepath); - if extension != "rrd" { + if !matches!(extension.as_str(), "rbl" | "rrd") { + // NOTE: blueprints and recordings has the same file format return Err(crate::DataLoaderError::Incompatible(filepath.clone())); } @@ -66,7 +67,8 @@ impl crate::DataLoader for RrdLoader { re_tracing::profile_function!(filepath.display().to_string()); let extension = crate::extension(&filepath); - if extension != "rrd" { + if !matches!(extension.as_str(), "rbl" | "rrd") { + // NOTE: blueprints and recordings has the same file format return Err(crate::DataLoaderError::Incompatible(filepath)); } diff --git a/crates/re_data_source/src/data_source.rs b/crates/re_data_source/src/data_source.rs index b8a334119ec1..d2728bde1f42 100644 --- a/crates/re_data_source/src/data_source.rs +++ b/crates/re_data_source/src/data_source.rs @@ -108,6 +108,24 @@ impl DataSource { } } + pub fn file_name(&self) -> Option { + match self { + DataSource::RrdHttpUrl(url) => url.split('/').last().map(|r| r.to_owned()), + #[cfg(not(target_arch = "wasm32"))] + DataSource::FilePath(_, path) => { + path.file_name().map(|s| s.to_string_lossy().to_string()) + } + DataSource::FileContents(_, file_contents) => Some(file_contents.name.clone()), + DataSource::WebSocketAddr(_) => None, + #[cfg(not(target_arch = "wasm32"))] + DataSource::Stdin => None, + } + } + + pub fn is_blueprint(&self) -> Option { + self.file_name().map(|name| name.ends_with(".rbl")) + } + /// Stream the data from the given data source. /// /// Will do minimal checks (e.g. that the file exists), for synchronous errors, diff --git a/crates/re_data_source/src/lib.rs b/crates/re_data_source/src/lib.rs index cfa37dab6875..0caba04b91ff 100644 --- a/crates/re_data_source/src/lib.rs +++ b/crates/re_data_source/src/lib.rs @@ -38,12 +38,21 @@ pub use self::load_file::load_from_path; /// This is what you get when loading a file on Web, or when using drag-n-drop. // // TODO(#4554): drag-n-drop streaming support -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct FileContents { pub name: String, pub bytes: std::sync::Arc<[u8]>, } +impl std::fmt::Debug for FileContents { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("FileContents") + .field("name", &self.name) + .field("bytes", &format_args!("{} bytes", self.bytes.len())) + .finish() + } +} + // …given that all feature flags are turned on for the `image` crate. pub const SUPPORTED_IMAGE_EXTENSIONS: &[&str] = &[ "avif", "bmp", "dds", "exr", "farbfeld", "ff", "gif", "hdr", "ico", "jpeg", "jpg", "pam", @@ -55,7 +64,7 @@ pub const SUPPORTED_MESH_EXTENSIONS: &[&str] = &["glb", "gltf", "obj", "stl"]; // TODO(#4532): `.ply` data loader should support 2D point cloud & meshes pub const SUPPORTED_POINT_CLOUD_EXTENSIONS: &[&str] = &["ply"]; -pub const SUPPORTED_RERUN_EXTENSIONS: &[&str] = &["rrd"]; +pub const SUPPORTED_RERUN_EXTENSIONS: &[&str] = &["rbl", "rrd"]; // TODO(#4555): Add catch-all builtin `DataLoader` for text files pub const SUPPORTED_TEXT_EXTENSIONS: &[&str] = &["txt", "md"]; diff --git a/crates/re_data_source/src/load_file.rs b/crates/re_data_source/src/load_file.rs index b49572d8a344..158ec9028365 100644 --- a/crates/re_data_source/src/load_file.rs +++ b/crates/re_data_source/src/load_file.rs @@ -34,7 +34,7 @@ pub fn load_from_path( re_log::info!("Loading {path:?}…"); - let data = load(settings, path, None)?; + let rx = load(settings, path, None)?; // TODO(cmc): should we always unconditionally set store info though? // If we reach this point, then at least one compatible `DataLoader` has been found. @@ -45,7 +45,7 @@ pub fn load_from_path( } } - send(&settings.store_id, data, tx); + send(&settings.store_id, rx, tx); Ok(()) } diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index adb947d05d18..f27a2e5d38bf 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -82,9 +82,6 @@ fn insert_row_with_retries( /// /// NOTE: all mutation is to be done via public functions! pub struct EntityDb { - /// The [`StoreId`] for this log. - store_id: StoreId, - /// Set by whomever created this [`EntityDb`]. pub data_source: Option, @@ -126,7 +123,6 @@ impl EntityDb { ); let query_caches = re_query_cache::Caches::new(&data_store); Self { - store_id: store_id.clone(), data_source: None, set_store_info: None, last_modified_at: web_time::Instant::now(), @@ -193,11 +189,11 @@ impl EntityDb { } pub fn store_kind(&self) -> StoreKind { - self.store_id.kind + self.store_id().kind } pub fn store_id(&self) -> &StoreId { - &self.store_id + self.data_store.id() } pub fn timelines(&self) -> impl ExactSizeIterator { @@ -486,7 +482,6 @@ impl EntityDb { re_tracing::profile_function!(); let Self { - store_id: _, data_source: _, set_store_info: _, last_modified_at: _, diff --git a/crates/re_log_types/src/lib.rs b/crates/re_log_types/src/lib.rs index 0bc8f6a350b5..b1950ce26fea 100644 --- a/crates/re_log_types/src/lib.rs +++ b/crates/re_log_types/src/lib.rs @@ -227,6 +227,17 @@ impl LogMsg { Self::ArrowMsg(store_id, _) => store_id, } } + + pub fn set_store_id(&mut self, new_store_id: StoreId) { + match self { + LogMsg::SetStoreInfo(store_info) => { + store_info.info.store_id = new_store_id; + } + LogMsg::ArrowMsg(msg_store_id, _) => { + *msg_store_id = new_store_id; + } + } + } } impl_into_enum!(SetStoreInfo, LogMsg, SetStoreInfo); diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 1faf301ecbff..7f96af6d2380 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -1,3 +1,5 @@ +use itertools::Itertools as _; + use re_data_source::{DataSource, FileContents}; use re_entity_db::entity_db::EntityDb; use re_log_types::{FileSource, LogMsg, StoreKind}; @@ -366,7 +368,7 @@ impl App { SystemCommand::LoadStoreDb(entity_db) => { let store_id = entity_db.store_id().clone(); - store_hub.insert_recording(entity_db); + store_hub.insert_entity_db(entity_db); store_hub.set_recording_id(store_id); } @@ -443,18 +445,24 @@ impl App { ) { match cmd { UICommand::SaveRecording => { - save_recording(self, store_context, None); + if let Err(err) = save_recording(self, store_context, None) { + re_log::error!("Failed to save recording: {err}"); + } } UICommand::SaveRecordingSelection => { - save_recording( + if let Err(err) = save_recording( self, store_context, self.state.loop_selection(store_context), - ); + ) { + re_log::error!("Failed to save recording: {err}"); + } } UICommand::SaveBlueprint => { - save_blueprint(self, store_context); + if let Err(err) = save_blueprint(self, store_context) { + re_log::error!("Failed to save blueprint: {err}"); + } } #[cfg(not(target_arch = "wasm32"))] @@ -934,7 +942,39 @@ impl App { if let Some(err) = err { re_log::warn!("Data source {} has left unexpectedly: {err}", msg.source); } else { - re_log::debug!("Data source {} has left", msg.source); + re_log::debug!("Data source {} has finished", msg.source); + + // This could be the signal that we finished loading a blueprint. + // In that case, we want to make it the default. + // We wait with activaing blueprints until they are fully loaded, + // so that we don't run heuristics on half-loaded blueprints. + + let blueprints = store_hub + .entity_dbs_from_channel_source(&channel_source) + .filter_map(|entity_db| { + if let Some(store_info) = entity_db.store_info() { + match store_info.store_id.kind { + StoreKind::Recording => { + // Recordings become active as soon as we start streaming them. + } + StoreKind::Blueprint => { + return Some(store_info.clone()); + } + } + } + None + }) + .collect_vec(); + + for re_log_types::StoreInfo { + store_id, + application_id, + .. + } in blueprints + { + re_log::debug!("Activating newly loaded blueprint"); + store_hub.set_blueprint_for_app_id(store_id, application_id); + } } continue; } @@ -942,6 +982,11 @@ impl App { let store_id = msg.store_id(); + if store_hub.is_active_blueprint(store_id) { + // TODO(#5514): handle loading of active blueprints. + re_log::warn_once!("Loading a blueprint {store_id} that is active. See https://github.com/rerun-io/rerun/issues/5514 for details."); + } + let entity_db = store_hub.entity_db_mut(store_id); if entity_db.data_source.is_none() { @@ -952,8 +997,8 @@ impl App { re_log::error_once!("Failed to add incoming msg: {err}"); }; - // Set the recording-id after potentially creating the store in the - // hub. This ordering is important because the `StoreHub` internally + // Set the recording-id after potentially creating the store in the hub. + // This ordering is important because the `StoreHub` internally // updates the app-id when changing the recording. if let LogMsg::SetStoreInfo(msg) = &msg { match msg.info.store_id.kind { @@ -961,19 +1006,18 @@ impl App { re_log::debug!("Opening a new recording: {:?}", msg.info); store_hub.set_recording_id(store_id.clone()); } - StoreKind::Blueprint => { - re_log::debug!("Opening a new blueprint: {:?}", msg.info); - store_hub.set_blueprint_for_app_id( - store_id.clone(), - msg.info.application_id.clone(), - ); + // We wait with activaing blueprints until they are fully loaded, + // so that we don't run heuristics on half-loaded blueprints. + // TODO(#5297): heed special "end-of-blueprint" message to activate blueprint. + // Otherwise on a mixed connection (SDK sending both blueprint and recording) + // the blueprint won't be activated until the whole _recording_ has finished loading. } } } // Do analytics after ingesting the new message, - // because thats when the `entity_db.store_info` is set, + // because that's when the `entity_db.store_info` is set, // which we use in the analytics call. let entity_db = store_hub.entity_db_mut(store_id); let is_new_store = matches!(&msg, LogMsg::SetStoreInfo(_msg)); @@ -1508,11 +1552,10 @@ fn save_recording( app: &mut App, store_context: Option<&StoreContext<'_>>, loop_selection: Option<(re_entity_db::Timeline, re_log_types::TimeRangeF)>, -) { +) -> anyhow::Result<()> { let Some(entity_db) = store_context.as_ref().and_then(|view| view.recording) else { // NOTE: Can only happen if saving through the command palette. - re_log::error!("No recording data to save"); - return; + anyhow::bail!("No recording data to save"); }; let file_name = "data.rrd"; @@ -1523,29 +1566,36 @@ fn save_recording( "Save recording" }; - save_entity_db( - app, - file_name.to_owned(), - title.to_owned(), - entity_db, - loop_selection, - ); + save_entity_db(app, file_name.to_owned(), title.to_owned(), || { + entity_db.to_messages(loop_selection) + }) } -fn save_blueprint(app: &mut App, store_context: Option<&StoreContext<'_>>) { +fn save_blueprint(app: &mut App, store_context: Option<&StoreContext<'_>>) -> anyhow::Result<()> { let Some(store_context) = store_context else { - re_log::error!("No blueprint to save"); - return; + anyhow::bail!("No blueprint to save"); }; - let entity_db = store_context.blueprint; + re_tracing::profile_function!(); + + // We change the recording id to a new random one, + // otherwise when saving and loading a blueprint file, we can end up + // in a situation where the store_id we're loading is the same as the currently active one, + // which mean they will merge in a strange way. + // This is also related to https://github.com/rerun-io/rerun/issues/5295 + let new_store_id = re_log_types::StoreId::random(StoreKind::Blueprint); + let mut messages = store_context.blueprint.to_messages(None)?; + for message in &mut messages { + message.set_store_id(new_store_id.clone()); + } let file_name = format!( "{}.rbl", crate::saving::sanitize_app_id(&store_context.app_id) ); let title = "Save blueprint"; - save_entity_db(app, file_name, title.to_owned(), entity_db, None); + + save_entity_db(app, file_name, title.to_owned(), || Ok(messages)) } #[allow(clippy::needless_pass_by_ref_mut)] // `app` is only used on native @@ -1553,21 +1603,14 @@ fn save_entity_db( #[allow(unused_variables)] app: &mut App, // only used on native file_name: String, title: String, - entity_db: &EntityDb, - loop_selection: Option<(re_log_types::Timeline, re_log_types::TimeRangeF)>, -) { + to_log_messages: impl FnOnce() -> re_log_types::DataTableResult>, +) -> anyhow::Result<()> { re_tracing::profile_function!(); // Web #[cfg(target_arch = "wasm32")] { - let messages = match entity_db.to_messages(loop_selection) { - Ok(messages) => messages, - Err(err) => { - re_log::error!("File saving failed: {err}"); - return; - } - }; + let messages = to_log_messages()?; wasm_bindgen_futures::spawn_local(async move { if let Err(err) = async_save_dialog(&file_name, &title, &messages).await { @@ -1587,22 +1630,15 @@ fn save_entity_db( .save_file() }; if let Some(path) = path { - let messages = match entity_db.to_messages(loop_selection) { - Ok(messages) => messages, - Err(err) => { - re_log::error!("File saving failed: {err}"); - return; - } - }; - if let Err(err) = app.background_tasks.spawn_file_saver(move || { + let messages = to_log_messages()?; + app.background_tasks.spawn_file_saver(move || { crate::saving::encode_to_file(&path, messages.iter())?; Ok(path) - }) { - // NOTE: Can only happen if saving through the command palette. - re_log::error!("File saving failed: {err}"); - } + })?; } } + + Ok(()) } #[cfg(target_arch = "wasm32")] diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index fc94eb3d1cad..4678373d7049 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -431,7 +431,7 @@ impl AppState { re_tracing::profile_function!(); self.recording_configs - .retain(|store_id, _| store_hub.contains_recording(store_id)); + .retain(|store_id, _| store_hub.contains_store(store_id)); } /// Returns the blueprint query that should be used for generating the current diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer/src/store_hub.rs index 41ff28ecdfd3..93c558fbf02c 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer/src/store_hub.rs @@ -173,14 +173,22 @@ impl StoreHub { /// Change which blueprint is active for a given [`ApplicationId`] #[inline] pub fn set_blueprint_for_app_id(&mut self, blueprint_id: StoreId, app_id: ApplicationId) { - re_log::debug!("Switching blueprint for {app_id:?} to {blueprint_id:?}"); + re_log::debug!("Switching blueprint for {app_id} to {blueprint_id}"); self.blueprint_by_app_id.insert(app_id, blueprint_id); } + /// Is the given blueprint id the active blueprint for any app id? + pub fn is_active_blueprint(&self, blueprint_id: &StoreId) -> bool { + self.blueprint_by_app_id + .values() + .any(|id| id == blueprint_id) + } + /// Clear the current blueprint pub fn clear_current_blueprint(&mut self) { if let Some(app_id) = &self.selected_application_id { if let Some(blueprint_id) = self.blueprint_by_app_id.remove(app_id) { + re_log::debug!("Clearing blueprint for {app_id}: {blueprint_id}"); self.store_bundle.remove(&blueprint_id); } } @@ -193,12 +201,12 @@ impl StoreHub { } } - /// Insert a new recording into the [`StoreHub`]. + /// Insert a new recording or blueprint into the [`StoreHub`]. /// /// Note that the recording is not automatically made active. Use [`StoreHub::set_recording_id`] /// if needed. - pub fn insert_recording(&mut self, entity_db: EntityDb) { - self.store_bundle.insert_recording(entity_db); + pub fn insert_entity_db(&mut self, entity_db: EntityDb) { + self.store_bundle.insert_entity_db(entity_db); } /// Mutable access to a [`EntityDb`] by id @@ -271,9 +279,19 @@ impl StoreHub { .and_then(|id| self.store_bundle.recording(id)) } - /// Check whether the [`StoreHub`] contains the referenced recording - pub fn contains_recording(&self, id: &StoreId) -> bool { - self.store_bundle.contains_recording(id) + /// Check whether the [`StoreHub`] contains the referenced store (recording or blueprint). + pub fn contains_store(&self, id: &StoreId) -> bool { + self.store_bundle.contains_store(id) + } + + pub fn entity_dbs_from_channel_source<'a>( + &'a self, + source: &'a re_smart_channel::SmartChannelSource, + ) -> impl Iterator + 'a { + self.store_bundle + .entity_dbs + .values() + .filter(move |db| db.data_source.as_ref() == Some(source)) } /// Remove any recordings with a network source pointing at this `uri`. @@ -382,7 +400,7 @@ impl StoreHub { // We found the blueprint we were looking for; make it active. // borrow-checker won't let us just call `self.set_blueprint_for_app_id` re_log::debug!( - "Switching blueprint for {app_id:?} to {:?}", + "Switching blueprint for {app_id} to {} loaded from {blueprint_path:?}", store.store_id(), ); self.blueprint_by_app_id @@ -490,9 +508,10 @@ impl StoreBundle { /// Returns either a recording or blueprint [`EntityDb`]. /// One is created if it doesn't already exist. pub fn entity_db_entry(&mut self, id: &StoreId) -> &mut EntityDb { - self.entity_dbs - .entry(id.clone()) - .or_insert_with(|| EntityDb::new(id.clone())) + self.entity_dbs.entry(id.clone()).or_insert_with(|| { + re_log::debug!("Creating new store: {id}"); + EntityDb::new(id.clone()) + }) } /// All loaded [`EntityDb`], both recordings and blueprints, in arbitrary order. @@ -554,8 +573,7 @@ impl StoreBundle { // -- - pub fn contains_recording(&self, id: &StoreId) -> bool { - debug_assert_eq!(id.kind, StoreKind::Recording); + pub fn contains_store(&self, id: &StoreId) -> bool { self.entity_dbs.contains_key(id) } @@ -577,8 +595,7 @@ impl StoreBundle { .or_insert_with(|| EntityDb::new(id.clone())) } - pub fn insert_recording(&mut self, entity_db: EntityDb) { - debug_assert_eq!(entity_db.store_kind(), StoreKind::Recording); + pub fn insert_entity_db(&mut self, entity_db: EntityDb) { self.entity_dbs .insert(entity_db.store_id().clone(), entity_db); } @@ -629,6 +646,8 @@ impl StoreBundle { let mut blueprint_db = EntityDb::new(id.clone()); + re_log::debug!("Creating a new blueprint {id}"); + blueprint_db.set_store_info(re_log_types::SetStoreInfo { row_id: re_log_types::RowId::new(), info: re_log_types::StoreInfo { diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index c463575479bd..dff9e5dd92d3 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -1,5 +1,6 @@ use ahash::HashMap; use egui_tiles::TileId; + use re_data_store::LatestAtQuery; use re_entity_db::EntityDb; use re_log::ResultExt; From c8d6edf59bd496b523a5dbf9506d11c6951743a6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 15 Mar 2024 10:33:29 +0100 Subject: [PATCH 034/508] Allow hiding/showing entity subtrees under shown/hidden parent tree (#5508) ### What * Fixes #5464 * using the design we agreed upon that doesn't use tristate buttons in the blueprint panel * Next step on #5463 * Fixes #5396 * Fixes #3194 The title describes the main effect this has on what Rerun can do compared to the previous release. But the real star of the show is that visible is now a component, not part of `EntityProperties`. @ reviewer: Please take your time and explore the behavior both on blueprint panel and selection panel, there's a surprising amount of nuance in here. For instance there's extra logic for allowing you to go back to a clean slate with ui interactions - for instance hiding & unhiding an item that doesn't receive any parent overrides will remove the visibility override completely as the default value for visibility is 'true'. You can now hide/show under a shown/hidden parent tree: https://github.com/rerun-io/rerun/assets/1220815/f412cac5-2db6-43d0-9b02-d2269cb60824 We're able to keep track of where an override comes from, this is exposed in the selection panels' tooltip: ![image](https://github.com/rerun-io/rerun/assets/1220815/ef7794ac-07c8-4930-ba92-11a45f91f6fe) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5508/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5508/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5508/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5508) - [Docs preview](https://rerun.io/preview/a09f77a2233fd101a4c5a94703f7726a920a18c6/docs) - [Examples preview](https://rerun.io/preview/a09f77a2233fd101a4c5a94703f7726a920a18c6/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_entity_db/src/entity_properties.rs | 8 +- crates/re_space_view/src/data_query.rs | 9 +- crates/re_space_view/src/space_view.rs | 36 +-- .../re_space_view/src/space_view_contents.rs | 22 +- .../src/visualizer_system.rs | 2 +- .../src/space_view_class.rs | 2 +- .../src/contexts/depth_offsets.rs | 2 +- .../src/visualizers/cameras.rs | 2 +- .../src/visualizers/entity_iterator.rs | 6 +- .../src/visualizers/transform3d_arrows.rs | 2 +- .../src/visualizer_system.rs | 2 +- .../src/visualizer_system.rs | 2 +- .../src/visualizer_system.rs | 2 +- .../src/legacy_visualizer_system.rs | 19 +- .../src/line_visualizer_system.rs | 14 +- .../src/overrides.rs | 28 +-- .../src/point_visualizer_system.rs | 16 +- .../rerun/blueprint/components/visible.fbs | 2 +- .../re_types/src/blueprint/components/mod.rs | 1 + .../src/blueprint/components/visible.rs | 2 +- .../src/blueprint/components/visible_ext.rs | 7 + crates/re_ui/src/lib.rs | 17 +- crates/re_viewer/src/ui/override_ui.rs | 29 +-- crates/re_viewer/src/ui/selection_panel.rs | 53 ++++- .../src/blueprint_helpers.rs | 13 +- crates/re_viewer_context/src/lib.rs | 17 +- .../re_viewer_context/src/space_view/mod.rs | 3 +- .../src/space_view/view_query.rs | 219 ++++++++++++++---- .../src/context_menu/actions/show_hide.rs | 31 ++- .../re_viewport/src/viewport_blueprint_ui.rs | 37 ++- .../color_coordinates_visualizer_system.rs | 2 +- 31 files changed, 388 insertions(+), 219 deletions(-) create mode 100644 crates/re_types/src/blueprint/components/visible_ext.rs diff --git a/crates/re_entity_db/src/entity_properties.rs b/crates/re_entity_db/src/entity_properties.rs index 4e7e0d1e2d38..02f6e29325a1 100644 --- a/crates/re_entity_db/src/entity_properties.rs +++ b/crates/re_entity_db/src/entity_properties.rs @@ -94,7 +94,6 @@ impl FromIterator<(EntityPath, EntityProperties)> for EntityPropertyMap { #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct EntityProperties { - pub visible: bool, pub visible_history: re_query::ExtraQueryHistory, pub interactive: bool, @@ -144,7 +143,6 @@ pub struct EntityProperties { impl Default for EntityProperties { fn default() -> Self { Self { - visible: true, visible_history: re_query::ExtraQueryHistory::default(), interactive: true, color_mapper: EditableAutoValue::default(), @@ -166,7 +164,6 @@ impl EntityProperties { /// Multiply/and these together. pub fn with_child(&self, child: &Self) -> Self { Self { - visible: self.visible && child.visible, visible_history: self.visible_history.with_child(&child.visible_history), interactive: self.interactive && child.interactive, @@ -211,7 +208,6 @@ impl EntityProperties { /// loaded from the Blueprint store where the Auto values are not up-to-date. pub fn merge_with(&self, other: &Self) -> Self { Self { - visible: other.visible, visible_history: self.visible_history.with_child(&other.visible_history), interactive: other.interactive, @@ -250,7 +246,6 @@ impl EntityProperties { /// Determine whether this `EntityProperty` has user-edits relative to another `EntityProperty` pub fn has_edits(&self, other: &Self) -> bool { let Self { - visible, visible_history, interactive, color_mapper, @@ -265,8 +260,7 @@ impl EntityProperties { time_series_aggregator, } = self; - visible != &other.visible - || visible_history != &other.visible_history + visible_history != &other.visible_history || interactive != &other.interactive || color_mapper.has_edits(&other.color_mapper) || pinhole_image_plane_distance.has_edits(&other.pinhole_image_plane_distance) diff --git a/crates/re_space_view/src/data_query.rs b/crates/re_space_view/src/data_query.rs index ea9771817509..7cf3fcb141fd 100644 --- a/crates/re_space_view/src/data_query.rs +++ b/crates/re_space_view/src/data_query.rs @@ -1,9 +1,10 @@ -use ahash::HashMap; +use nohash_hasher::IntMap; use re_entity_db::{external::re_data_store::LatestAtQuery, EntityProperties, EntityPropertyMap}; -use re_log_types::{EntityPath, StoreKind}; use re_types::ComponentName; -use re_viewer_context::{DataQueryResult, PerVisualizer, StoreContext, VisualizableEntities}; +use re_viewer_context::{ + DataQueryResult, OverridePath, PerVisualizer, StoreContext, VisualizableEntities, +}; pub struct EntityOverrideContext { pub root: EntityProperties, @@ -11,7 +12,7 @@ pub struct EntityOverrideContext { pub recursive: EntityPropertyMap, /// Base component overrides that are inherited by all entities. - pub root_component_overrides: HashMap, + pub root_component_overrides: IntMap, } /// Trait for resolving properties needed by most implementations of [`DataQuery`] diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index c30be095628e..821f62597b96 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -446,7 +446,7 @@ impl SpaceViewBlueprint { accumulated_properties, individual_properties, recursive_properties: Default::default(), - component_overrides: Default::default(), + resolved_component_overrides: Default::default(), recursive_override_path: entity_path.clone(), individual_override_path: entity_path, }), @@ -464,8 +464,8 @@ mod tests { }; use re_types::{archetypes::Points3D, ComponentBatch, ComponentName, Loggable as _}; use re_viewer_context::{ - blueprint_timeline, IndicatedEntities, PerVisualizer, SpaceViewClassRegistry, StoreContext, - VisualizableEntities, + blueprint_timeline, IndicatedEntities, OverridePath, PerVisualizer, SpaceViewClassRegistry, + StoreContext, VisualizableEntities, }; use std::collections::HashMap; @@ -582,9 +582,9 @@ mod tests { ); } - // Now, override visibility on parent individually. + // Now, override interactive on parent individually. let mut overrides = parent.individual_properties().cloned().unwrap_or_default(); - overrides.visible = false; + overrides.interactive = false; save_override( overrides, @@ -593,7 +593,7 @@ mod tests { ); } - // Parent is not visible, but children are + // Parent is not interactive, but children are { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), @@ -622,18 +622,18 @@ mod tests { .lookup_result_by_path(&EntityPath::from("parent/skip/child2")) .unwrap(); - assert!(!parent.accumulated_properties().visible); + assert!(!parent.accumulated_properties().interactive); for result in [child1, child2] { - assert!(result.accumulated_properties().visible); + assert!(result.accumulated_properties().interactive); } - // Override visibility on parent recursively. + // Override interactivity on parent recursively. let mut overrides = parent_group .individual_properties() .cloned() .unwrap_or_default(); - overrides.visible = false; + overrides.interactive = false; save_override( overrides, @@ -642,7 +642,7 @@ mod tests { ); } - // Nobody is visible + // Nobody is interactive { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), @@ -668,11 +668,11 @@ mod tests { .unwrap(); for result in [parent, child1, child2] { - assert!(!result.accumulated_properties().visible); + assert!(!result.accumulated_properties().interactive); } } - // Override visible range on root + // Override interactive range on root { let root = space_view.root_data_result( &StoreContext { @@ -694,7 +694,7 @@ mod tests { ); } - // Everyone has visible history + // Everyone has interactive history { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), @@ -736,7 +736,7 @@ mod tests { ); } - // Child2 has its own visible history + // Child2 has its own interactive history { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), @@ -1042,13 +1042,13 @@ mod tests { query_result.tree.visit(&mut |node| { let result = &node.data_result; if let Some(property_overrides) = &result.property_overrides { - if !property_overrides.component_overrides.is_empty() { + if !property_overrides.resolved_component_overrides.is_empty() { visited.insert( result.entity_path.clone(), property_overrides - .component_overrides + .resolved_component_overrides .iter() - .map(|(component_name, (store_kind, path))| { + .map(|(component_name, OverridePath { store_kind, path })| { assert_eq!(store_kind, &StoreKind::Blueprint); (*component_name, path.clone()) }) diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 773a59e71517..c999d337e276 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -1,4 +1,4 @@ -use ahash::HashMap; +use nohash_hasher::IntMap; use slotmap::SlotMap; use smallvec::SmallVec; @@ -6,7 +6,7 @@ use re_entity_db::{ external::re_data_store::LatestAtQuery, EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, }; -use re_log_types::{path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule, StoreKind}; +use re_log_types::{path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule}; use re_types::{ blueprint::{archetypes as blueprint_archetypes, components::QueryExpression}, Archetype as _, @@ -14,8 +14,8 @@ use re_types::{ use re_types_core::{components::VisualizerOverrides, ComponentName}; use re_viewer_context::{ DataQueryResult, DataResult, DataResultHandle, DataResultNode, DataResultTree, - IndicatedEntities, PerVisualizer, PropertyOverrides, SpaceViewClassIdentifier, SpaceViewId, - StoreContext, ViewerContext, VisualizableEntities, + IndicatedEntities, OverridePath, PerVisualizer, PropertyOverrides, SpaceViewClassIdentifier, + SpaceViewId, StoreContext, ViewerContext, VisualizableEntities, }; use crate::{ @@ -340,7 +340,7 @@ impl DataQueryPropertyResolver<'_> { .space_view .root_data_result(ctx, query) .property_overrides - .map(|p| (p.accumulated_properties, p.component_overrides)) + .map(|p| (p.accumulated_properties, p.resolved_component_overrides)) .unwrap_or_default(); for prefix in &self.default_stack { @@ -416,7 +416,7 @@ impl DataQueryPropertyResolver<'_> { query_result: &mut DataQueryResult, override_context: &EntityOverrideContext, accumulated: &EntityProperties, - recursive_property_overrides: &HashMap, + recursive_property_overrides: &IntMap, handle: DataResultHandle, ) { if let Some((child_handles, accumulated, recursive_property_overrides)) = @@ -493,7 +493,7 @@ impl DataQueryPropertyResolver<'_> { if !component_data.is_empty() { recursive_property_overrides.to_mut().insert( *component, - (StoreKind::Blueprint, recursive_override_path.clone()), + OverridePath::blueprint_path(recursive_override_path.clone()), ); } } @@ -502,7 +502,7 @@ impl DataQueryPropertyResolver<'_> { // Then, gather individual overrides - these may override the recursive ones again, // but recursive overrides are still inherited to children. - let mut component_overrides = (*recursive_property_overrides).clone(); + let mut resolved_component_overrides = (*recursive_property_overrides).clone(); if let Some(individual_override_subtree) = ctx.blueprint.tree().subtree(&individual_override_path) { @@ -514,9 +514,9 @@ impl DataQueryPropertyResolver<'_> { .and_then(|(_, _, cells)| cells[0].clone()) { if !component_data.is_empty() { - component_overrides.insert( + resolved_component_overrides.insert( *component, - (StoreKind::Blueprint, individual_override_path.clone()), + OverridePath::blueprint_path(individual_override_path.clone()), ); } } @@ -527,7 +527,7 @@ impl DataQueryPropertyResolver<'_> { accumulated_properties, individual_properties: individual_properties.cloned(), recursive_properties: recursive_properties.cloned(), - component_overrides, + resolved_component_overrides, recursive_override_path, individual_override_path, }); diff --git a/crates/re_space_view_bar_chart/src/visualizer_system.rs b/crates/re_space_view_bar_chart/src/visualizer_system.rs index 834a29dd3c9e..ef93f0024656 100644 --- a/crates/re_space_view_bar_chart/src/visualizer_system.rs +++ b/crates/re_space_view_bar_chart/src/visualizer_system.rs @@ -50,7 +50,7 @@ impl VisualizerSystem for BarChartVisualizerSystem { let store = ctx.entity_db.store(); - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let query = LatestAtQuery::new(query.timeline, query.latest_at); let tensor = store.query_latest_component::( &data_result.entity_path, diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index 99e1c0b75fb3..82454150c679 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -81,7 +81,7 @@ impl SpaceViewClass for DataframeSpaceView { // These are the entity paths whose content we must display. let sorted_entity_paths: BTreeSet<_> = query .iter_all_data_results() - .filter(|data_result| data_result.accumulated_properties().visible) + .filter(|data_result| data_result.is_visible(ctx)) .map(|data_result| &data_result.entity_path) .cloned() .collect(); diff --git a/crates/re_space_view_spatial/src/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/contexts/depth_offsets.rs index b70714c07252..736192b302dd 100644 --- a/crates/re_space_view_spatial/src/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/contexts/depth_offsets.rs @@ -48,7 +48,7 @@ impl ViewContextSystem for EntityDepthOffsets { // Use a BTreeSet for entity hashes to get a stable order. let mut entities_per_draw_order = BTreeMap::>::new(); - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { if let Some(draw_order) = store .query_latest_component::(&data_result.entity_path, &ctx.current_query()) { diff --git a/crates/re_space_view_spatial/src/visualizers/cameras.rs b/crates/re_space_view_spatial/src/visualizers/cameras.rs index 002ab4949852..f9e79bc524b9 100644 --- a/crates/re_space_view_spatial/src/visualizers/cameras.rs +++ b/crates/re_space_view_spatial/src/visualizers/cameras.rs @@ -213,7 +213,7 @@ impl VisualizerSystem for CamerasVisualizer { let mut line_builder = re_renderer::LineDrawableBuilder::new(ctx.render_ctx); line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES); - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let time_query = re_data_store::LatestAtQuery::new(query.timeline, query.latest_at); if let Some(pinhole) = query_pinhole(store, &time_query, &data_result.entity_path) { diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 4f407245832b..986c40c7db18 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -42,7 +42,7 @@ where let annotations = view_ctx.get::()?; let counter = view_ctx.get::()?; - for data_result in query.iter_visible_data_results(System::identifier()) { + for data_result in query.iter_visible_data_results(ctx, System::identifier()) { // The transform that considers pinholes only makes sense if this is a 3D space-view let world_from_entity = if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() { @@ -151,7 +151,7 @@ macro_rules! impl_process_archetype { let annotations = view_ctx.get::()?; let counter = view_ctx.get::()?; - for data_result in query.iter_visible_data_results(S::identifier()) { + for data_result in query.iter_visible_data_results(ctx, S::identifier()) { // The transform that considers pinholes only makes sense if this is a 3D space-view let world_from_entity = if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() { transforms.reference_from_entity(&data_result.entity_path) @@ -256,7 +256,7 @@ pub fn count_instances_in_archetype_views< let mut num_instances = 0; - for data_result in query.iter_visible_data_results(System::identifier()) { + for data_result in query.iter_visible_data_results(ctx, System::identifier()) { match query_archetype_with_history::( ctx.entity_db.store(), &query.timeline, diff --git a/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs b/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs index be5bc096f315..bcb11e63061c 100644 --- a/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs +++ b/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs @@ -61,7 +61,7 @@ impl VisualizerSystem for Transform3DArrowsVisualizer { let mut line_builder = re_renderer::LineDrawableBuilder::new(ctx.render_ctx); line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES); - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { if !*data_result.accumulated_properties().transform_3d_visible { continue; } diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index e690df2e84d1..55559fc1797b 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -48,7 +48,7 @@ impl VisualizerSystem for TensorSystem { re_tracing::profile_function!(); let store = ctx.entity_db.store(); - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let timeline_query = LatestAtQuery::new(query.timeline, query.latest_at); if let Some(tensor) = store diff --git a/crates/re_space_view_text_document/src/visualizer_system.rs b/crates/re_space_view_text_document/src/visualizer_system.rs index f121ff40fcab..b0f55e9cf04f 100644 --- a/crates/re_space_view_text_document/src/visualizer_system.rs +++ b/crates/re_space_view_text_document/src/visualizer_system.rs @@ -44,7 +44,7 @@ impl VisualizerSystem for TextDocumentSystem { let timeline_query = LatestAtQuery::new(query.timeline, query.latest_at); - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { // TODO(#3320): this match can go away once the issue is resolved match query_archetype::( store, diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index 42fe24acf1ee..192d051668f6 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -53,7 +53,7 @@ impl VisualizerSystem for TextLogSystem { let query_caches = ctx.entity_db.query_caches(); let store = ctx.entity_db.store(); - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { re_tracing::profile_scope!("primary", &data_result.entity_path.to_string()); // We want everything, for all times: diff --git a/crates/re_space_view_time_series/src/legacy_visualizer_system.rs b/crates/re_space_view_time_series/src/legacy_visualizer_system.rs index 4d4b6d65b85a..6d71a991ed03 100644 --- a/crates/re_space_view_time_series/src/legacy_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/legacy_visualizer_system.rs @@ -10,7 +10,7 @@ use re_viewer_context::{ }; use crate::{ - overrides::{initial_override_color, lookup_override}, + overrides::initial_override_color, util::{determine_plot_bounds_and_time_per_pixel, determine_time_range, points_to_series}, PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind, ScatterAttrs, }; @@ -57,7 +57,7 @@ impl VisualizerSystem for LegacyTimeSeriesSystem { ctx, &query.latest_at_query(), query - .iter_visible_data_results(Self::identifier()) + .iter_visible_data_results(ctx, Self::identifier()) .map(|data| &data.entity_path), ); @@ -102,7 +102,7 @@ impl LegacyTimeSeriesSystem { let (plot_bounds, time_per_pixel) = determine_plot_bounds_and_time_per_pixel(ctx, query); // TODO(cmc): this should be thread-pooled in case there are a gazillon series in the same plot… - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let annotations = self.annotation_map.find(&data_result.entity_path); let annotation_info = annotations .resolved_class_description(None) @@ -111,11 +111,14 @@ impl LegacyTimeSeriesSystem { const DEFAULT_RADIUS: f32 = 0.75; - let override_color = lookup_override::(data_result, ctx).map(|c| c.to_array()); - let override_label = lookup_override::(data_result, ctx).map(|t| t.0); - let override_scattered = - lookup_override::(data_result, ctx).map(|s| s.0); - let override_radius = lookup_override::(data_result, ctx).map(|r| r.0); + let override_color = data_result + .lookup_override::(ctx) + .map(|c| c.to_array()); + let override_label = data_result.lookup_override::(ctx).map(|t| t.0); + let override_scattered = data_result + .lookup_override::(ctx) + .map(|s| s.0); + let override_radius = data_result.lookup_override::(ctx).map(|r| r.0); // All the default values for a `PlotPoint`, accounting for both overrides and default // values. diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 92b1dba52471..5672f84770f5 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -15,7 +15,7 @@ use crate::overrides::initial_override_color; use crate::util::{ determine_plot_bounds_and_time_per_pixel, determine_time_range, points_to_series, }; -use crate::{overrides::lookup_override, PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind}; +use crate::{PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind}; /// The system for rendering [`SeriesLine`] archetypes. #[derive(Default, Debug)] @@ -56,7 +56,7 @@ impl VisualizerSystem for SeriesLineSystem { ctx, &query.latest_at_query(), query - .iter_visible_data_results(Self::identifier()) + .iter_visible_data_results(ctx, Self::identifier()) .map(|data| &data.entity_path), ); @@ -98,7 +98,7 @@ impl SeriesLineSystem { let (plot_bounds, time_per_pixel) = determine_plot_bounds_and_time_per_pixel(ctx, query); - let data_results = query.iter_visible_data_results(Self::identifier()); + let data_results = query.iter_visible_data_results(ctx, Self::identifier()); let parallel_loading = false; // TODO(emilk): enable parallel loading when it is faster, because right now it is often slower. if parallel_loading { @@ -162,9 +162,11 @@ fn load_series( .resolved_class_description(None) .annotation_info(); let default_color = DefaultColor::EntityPath(&data_result.entity_path); - let override_color = lookup_override::(data_result, ctx).map(|c| c.to_array()); - let override_series_name = lookup_override::(data_result, ctx).map(|t| t.0); - let override_stroke_width = lookup_override::(data_result, ctx).map(|r| r.0); + let override_color = data_result + .lookup_override::(ctx) + .map(|c| c.to_array()); + let override_series_name = data_result.lookup_override::(ctx).map(|t| t.0); + let override_stroke_width = data_result.lookup_override::(ctx).map(|r| r.0); // All the default values for a `PlotPoint`, accounting for both overrides and default // values. diff --git a/crates/re_space_view_time_series/src/overrides.rs b/crates/re_space_view_time_series/src/overrides.rs index 397d764915f5..d2f0afc9e8fd 100644 --- a/crates/re_space_view_time_series/src/overrides.rs +++ b/crates/re_space_view_time_series/src/overrides.rs @@ -1,28 +1,6 @@ -use re_log_types::{EntityPath, StoreKind}; -use re_types::{components::Color, Component}; -use re_viewer_context::{DefaultColor, ResolvedAnnotationInfo, ViewerContext}; - -pub fn lookup_override( - data_result: &re_viewer_context::DataResult, - ctx: &ViewerContext<'_>, -) -> Option { - data_result - .property_overrides - .as_ref() - .and_then(|p| p.component_overrides.get(&C::name())) - .and_then(|(store_kind, path)| match store_kind { - StoreKind::Blueprint => ctx - .store_context - .blueprint - .store() - .query_latest_component::(path, ctx.blueprint_query), - StoreKind::Recording => ctx - .entity_db - .store() - .query_latest_component::(path, &ctx.current_query()), - }) - .map(|c| c.value) -} +use re_log_types::EntityPath; +use re_types::components::Color; +use re_viewer_context::{DefaultColor, ResolvedAnnotationInfo}; pub fn initial_override_color(entity_path: &EntityPath) -> Color { let default_color = DefaultColor::EntityPath(entity_path); diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 90ee4ce60e9d..f0b612798773 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -16,7 +16,7 @@ use crate::util::{ determine_plot_bounds_and_time_per_pixel, determine_time_range, points_to_series, }; use crate::ScatterAttrs; -use crate::{overrides::lookup_override, PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind}; +use crate::{PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind}; /// The system for rendering [`SeriesPoint`] archetypes. #[derive(Default, Debug)] @@ -60,7 +60,7 @@ impl VisualizerSystem for SeriesPointSystem { ctx, &query.latest_at_query(), query - .iter_visible_data_results(Self::identifier()) + .iter_visible_data_results(ctx, Self::identifier()) .map(|data| &data.entity_path), ); @@ -106,17 +106,19 @@ impl SeriesPointSystem { let (plot_bounds, time_per_pixel) = determine_plot_bounds_and_time_per_pixel(ctx, query); // TODO(cmc): this should be thread-pooled in case there are a gazillon series in the same plot… - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let annotations = self.annotation_map.find(&data_result.entity_path); let annotation_info = annotations .resolved_class_description(None) .annotation_info(); let default_color = DefaultColor::EntityPath(&data_result.entity_path); - let override_color = lookup_override::(data_result, ctx).map(|c| c.to_array()); - let override_series_name = lookup_override::(data_result, ctx).map(|t| t.0); - let override_marker_size = lookup_override::(data_result, ctx).map(|r| r.0); - let override_marker = lookup_override::(data_result, ctx); + let override_color = data_result + .lookup_override::(ctx) + .map(|c| c.to_array()); + let override_series_name = data_result.lookup_override::(ctx).map(|t| t.0); + let override_marker_size = data_result.lookup_override::(ctx).map(|r| r.0); + let override_marker = data_result.lookup_override::(ctx); // All the default values for a `PlotPoint`, accounting for both overrides and default // values. diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible.fbs index 992d11f53f6b..ee11f7651d5d 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/visible.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/visible.fbs @@ -14,7 +14,7 @@ struct Visible ( "attr.arrow.transparent", "attr.rerun.scope": "blueprint", "attr.python.aliases": "bool", - "attr.rust.derive": "Copy, Default, PartialEq, Eq, PartialOrd, Ord", + "attr.rust.derive": "Copy, PartialEq, Eq, PartialOrd, Ord", "attr.rust.repr": "transparent", "attr.rust.tuple_struct" ) { diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index 554e1ae416dc..0b873668d40b 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -14,6 +14,7 @@ mod space_view_class; mod space_view_origin; mod viewer_recommendation_hash; mod visible; +mod visible_ext; pub use self::active_tab::ActiveTab; pub use self::background3d_kind::Background3DKind; diff --git a/crates/re_types/src/blueprint/components/visible.rs b/crates/re_types/src/blueprint/components/visible.rs index 7c671219a95e..20887b57cb2a 100644 --- a/crates/re_types/src/blueprint/components/visible.rs +++ b/crates/re_types/src/blueprint/components/visible.rs @@ -22,7 +22,7 @@ use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Whether the container, space view, entity or instance is currently visible. -#[derive(Clone, Debug, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct Visible(pub bool); diff --git a/crates/re_types/src/blueprint/components/visible_ext.rs b/crates/re_types/src/blueprint/components/visible_ext.rs new file mode 100644 index 000000000000..777ab528f2c0 --- /dev/null +++ b/crates/re_types/src/blueprint/components/visible_ext.rs @@ -0,0 +1,7 @@ +use super::Visible; + +impl Default for Visible { + fn default() -> Self { + Self(true) + } +} diff --git a/crates/re_ui/src/lib.rs b/crates/re_ui/src/lib.rs index 55b8d179050f..18cd4abf257d 100644 --- a/crates/re_ui/src/lib.rs +++ b/crates/re_ui/src/lib.rs @@ -65,7 +65,7 @@ pub enum LabelStyle { use crate::list_item::ListItem; use egui::emath::{Rangef, Rot2}; use egui::epaint::util::FloatOrd; -use egui::{pos2, Align2, CollapsingResponse, Color32, Mesh, NumExt, Rect, Shape, Vec2}; +use egui::{pos2, Align2, CollapsingResponse, Color32, Mesh, NumExt, Rect, Shape, Vec2, Widget}; #[derive(Clone)] pub struct ReUi { @@ -431,6 +431,17 @@ impl ReUi { ui: &mut egui::Ui, selected: &mut bool, text: impl Into, + ) -> egui::Response { + self.checkbox_indeterminate(ui, selected, text, false) + } + + #[allow(clippy::unused_self)] + pub fn checkbox_indeterminate( + &self, + ui: &mut egui::Ui, + selected: &mut bool, + text: impl Into, + indeterminate: bool, ) -> egui::Response { ui.scope(|ui| { ui.visuals_mut().widgets.hovered.expansion = 0.0; @@ -438,7 +449,9 @@ impl ReUi { ui.visuals_mut().widgets.open.expansion = 0.0; // NOLINT - ui.checkbox(selected, text) + egui::Checkbox::new(selected, text) + .indeterminate(indeterminate) + .ui(ui) }) .inner } diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index 3b3f2b711035..ff055faf55b4 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -13,8 +13,8 @@ use re_types_core::{ ComponentName, }; use re_viewer_context::{ - blueprint_timepoint_for_writes, DataResult, SystemCommand, SystemCommandSender as _, - UiVerbosity, ViewSystemIdentifier, ViewerContext, + blueprint_timepoint_for_writes, DataResult, OverridePath, SystemCommand, + SystemCommandSender as _, UiVerbosity, ViewSystemIdentifier, ViewerContext, }; pub fn override_ui( @@ -48,7 +48,7 @@ pub fn override_ui( let active_overrides: BTreeSet = data_result .property_overrides .as_ref() - .map(|props| props.component_overrides.keys().cloned().collect()) + .map(|props| props.resolved_component_overrides.keys().cloned().collect()) .unwrap_or_default(); let view_systems = ctx @@ -95,7 +95,7 @@ pub fn override_ui( }; let components: Vec<_> = overrides - .component_overrides + .resolved_component_overrides .into_iter() .sorted_by_key(|(c, _)| *c) .filter(|(c, _)| component_to_vis.contains_key(c) && is_component_visible_in_ui(c)) @@ -111,7 +111,7 @@ pub fn override_ui( re_ui::ReUi::setup_table_body(&mut body); let row_height = re_ui::ReUi::table_line_height(); body.rows(row_height, components.len(), |mut row| { - if let Some((component_name, (store_kind, entity_path))) = + if let Some((component_name, OverridePath { store_kind, path })) = components.get(row.index()) { // Remove button @@ -124,7 +124,6 @@ pub fn override_ui( // Note: need to use the blueprint store since the data might // not exist in the recording store. ctx.save_empty_blueprint_component_name( - ctx.store_context.blueprint.store(), &overrides.individual_override_path, *component_name, ); @@ -143,19 +142,11 @@ pub fn override_ui( StoreKind::Blueprint => { let store = ctx.store_context.blueprint.store(); let query = ctx.blueprint_query; - get_component_with_instances( - store, - query, - entity_path, - *component_name, - ) + get_component_with_instances(store, query, path, *component_name) + } + StoreKind::Recording => { + get_component_with_instances(store, &query, path, *component_name) } - StoreKind::Recording => get_component_with_instances( - store, - &query, - entity_path, - *component_name, - ), }; if let Some((_, _, component_data)) = component_data { @@ -165,7 +156,7 @@ pub fn override_ui( UiVerbosity::Small, &query, store, - entity_path, + path, &overrides.individual_override_path, &component_data, instance_key, diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index ac19c50af1c8..8151e04222bd 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -17,8 +17,8 @@ use re_types::{ use re_ui::list_item::ListItem; use re_ui::{ReUi, SyntaxHighlighting as _}; use re_viewer_context::{ - gpu_bridge::colormap_dropdown_button_ui, ContainerId, HoverHighlight, Item, SpaceViewClass, - SpaceViewClassIdentifier, SpaceViewId, UiVerbosity, ViewerContext, + gpu_bridge::colormap_dropdown_button_ui, ContainerId, DataQueryResult, HoverHighlight, Item, + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, UiVerbosity, ViewerContext, }; use re_viewport::{ context_menu_ui_for_item, icon_for_container_kind, space_view_name_style, Contents, @@ -911,8 +911,9 @@ fn blueprint_ui_for_data_result( entity_props_ui( ctx, ui, + ctx.lookup_query_result(*space_view_id), &space_view_class, - Some(entity_path), + entity_path, &mut props, data_result.accumulated_properties(), ); @@ -1068,13 +1069,45 @@ The last rule matching `/world/house` is `+ /world/**`, so it is included. fn entity_props_ui( ctx: &ViewerContext<'_>, ui: &mut egui::Ui, + query_result: &DataQueryResult, space_view_class: &SpaceViewClassIdentifier, - entity_path: Option<&EntityPath>, + entity_path: &EntityPath, entity_props: &mut EntityProperties, resolved_entity_props: &EntityProperties, ) { + use re_types::blueprint::components::Visible; + use re_types::Loggable as _; + let re_ui = ctx.re_ui; - re_ui.checkbox(ui, &mut entity_props.visible, "Visible"); + let Some(data_result) = query_result.tree.lookup_result_by_path(entity_path) else { + return; + }; + + { + let visible_before = data_result.lookup_override_or_default::(ctx); + let mut visible = visible_before; + + let override_source = + data_result.component_override_source(&query_result.tree, &Visible::name()); + let is_inherited = + override_source.is_some() && override_source.as_ref() != Some(entity_path); + + ui.horizontal(|ui| { + re_ui.checkbox(ui, &mut visible.0, "Visible"); + if is_inherited { + ui.label("(inherited)"); + } + }); + + if visible_before != visible { + data_result.save_recursive_override_or_clear_if_redundant( + ctx, + &query_result.tree, + &visible, + ); + } + } + re_ui .checkbox(ui, &mut entity_props.interactive, "Interactive") .on_hover_text("If disabled, the entity will not react to any mouse interaction"); @@ -1084,7 +1117,7 @@ fn entity_props_ui( ui, space_view_class, false, - entity_path, + Some(entity_path), &mut entity_props.visible_history, &resolved_entity_props.visible_history, ); @@ -1094,11 +1127,9 @@ fn entity_props_ui( .show(ui, |ui| { // TODO(wumpf): It would be nice to only show pinhole & depth properties in the context of a 3D view. // if *view_state.state_spatial.nav_mode.get() == SpatialNavigationMode::ThreeD { - if let Some(entity_path) = entity_path { - pinhole_props_ui(ctx, ui, entity_path, entity_props); - depth_props_ui(ctx, ui, entity_path, entity_props); - transform3d_visualization_ui(ctx, ui, entity_path, entity_props); - } + pinhole_props_ui(ctx, ui, entity_path, entity_props); + depth_props_ui(ctx, ui, entity_path, entity_props); + transform3d_visualization_ui(ctx, ui, entity_path, entity_props); }); } diff --git a/crates/re_viewer_context/src/blueprint_helpers.rs b/crates/re_viewer_context/src/blueprint_helpers.rs index 4af906b6bad1..a23caa52f9d4 100644 --- a/crates/re_viewer_context/src/blueprint_helpers.rs +++ b/crates/re_viewer_context/src/blueprint_helpers.rs @@ -59,6 +59,13 @@ impl ViewerContext<'_> { let num_instances = components.num_instances() as u32; let timepoint = blueprint_timepoint_for_writes(); + re_log::trace!( + "Writing {} components of type {:?} to {:?}", + num_instances, + components.name(), + entity_path + ); + let data_row_result = if num_instances == 1 { let mut splat_cell: DataCell = [InstanceKey::SPLAT].into(); splat_cell.compute_size_bytes(); @@ -105,11 +112,11 @@ impl ViewerContext<'_> { /// Helper to save a component to the blueprint store. pub fn save_empty_blueprint_component_name( &self, - store: &re_data_store::DataStore, entity_path: &EntityPath, component_name: ComponentName, ) { - let Some(datatype) = store.lookup_datatype(&component_name) else { + let blueprint = &self.store_context.blueprint; + let Some(datatype) = blueprint.store().lookup_datatype(&component_name) else { re_log::error_once!( "Tried to clear a component with unknown type: {}", component_name @@ -130,7 +137,7 @@ impl ViewerContext<'_> { Ok(row) => self .command_sender .send_system(SystemCommand::UpdateBlueprint( - self.store_context.blueprint.store_id().clone(), + blueprint.store_id().clone(), vec![row], )), Err(err) => { diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 868c5d2fa7e6..a4f40d6ea3f7 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -45,14 +45,15 @@ pub use selection_state::{ Selection, SelectionHighlight, }; pub use space_view::{ - DataResult, IdentifiedViewSystem, PerSystemDataResults, PerSystemEntities, PropertyOverrides, - RecommendedSpaceView, SmallVisualizerSet, SpaceViewClass, SpaceViewClassIdentifier, - SpaceViewClassLayoutPriority, SpaceViewClassRegistry, SpaceViewClassRegistryError, - SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewSpawnHeuristics, - SpaceViewState, SpaceViewStateExt, SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, - SystemExecutionOutput, ViewContextCollection, ViewContextSystem, ViewQuery, - ViewSystemIdentifier, VisualizableFilterContext, VisualizerAdditionalApplicabilityFilter, - VisualizerCollection, VisualizerQueryInfo, VisualizerSystem, + DataResult, IdentifiedViewSystem, OverridePath, PerSystemDataResults, PerSystemEntities, + PropertyOverrides, RecommendedSpaceView, SmallVisualizerSet, SpaceViewClass, + SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, SpaceViewClassRegistry, + SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, + SpaceViewOutlineMasks, SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt, + SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, SystemExecutionOutput, + ViewContextCollection, ViewContextSystem, ViewQuery, ViewSystemIdentifier, + VisualizableFilterContext, VisualizerAdditionalApplicabilityFilter, VisualizerCollection, + VisualizerQueryInfo, VisualizerSystem, }; pub use store_context::StoreContext; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index f5d557acd190..df6bc0a3cff1 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -29,7 +29,8 @@ pub use spawn_heuristics::{RecommendedSpaceView, SpaceViewSpawnHeuristics}; pub use system_execution_output::SystemExecutionOutput; pub use view_context_system::{ViewContextCollection, ViewContextSystem}; pub use view_query::{ - DataResult, PerSystemDataResults, PropertyOverrides, SmallVisualizerSet, ViewQuery, + DataResult, OverridePath, PerSystemDataResults, PropertyOverrides, SmallVisualizerSet, + ViewQuery, }; pub use visualizer_entity_subscriber::VisualizerAdditionalApplicabilityFilter; pub use visualizer_system::{VisualizerCollection, VisualizerQueryInfo, VisualizerSystem}; diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 07d09d3da24f..9847cc516536 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -1,19 +1,37 @@ use std::collections::BTreeMap; -use ahash::HashMap; use itertools::Itertools; +use nohash_hasher::IntMap; use once_cell::sync::Lazy; + use re_data_store::LatestAtQuery; use re_entity_db::{EntityPath, EntityProperties, EntityPropertiesComponent, TimeInt, Timeline}; -use re_log_types::{DataCell, DataRow, RowId, StoreKind}; -use re_types::{ComponentName, Loggable}; +use re_log_types::StoreKind; +use re_types::ComponentName; use smallvec::SmallVec; use crate::{ - blueprint_timepoint_for_writes, SpaceViewHighlights, SpaceViewId, SystemCommand, - SystemCommandSender as _, ViewSystemIdentifier, ViewerContext, + DataResultTree, SpaceViewHighlights, SpaceViewId, ViewSystemIdentifier, ViewerContext, }; +/// Path to a specific entity in a specific store used for overrides. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct OverridePath { + // NOTE: StoreKind is easier to work with than a `StoreId`` or full `DataStore` but + // might still be ambiguous when we have multiple stores active at a time. + pub store_kind: StoreKind, + pub path: EntityPath, +} + +impl OverridePath { + pub fn blueprint_path(path: EntityPath) -> Self { + Self { + store_kind: StoreKind::Blueprint, + path, + } + } +} + #[derive(Clone, Debug, PartialEq)] pub struct PropertyOverrides { /// The accumulated properties (including any hierarchical flattening) to apply. @@ -28,10 +46,14 @@ pub struct PropertyOverrides { pub recursive_properties: Option, /// An alternative store and entity path to use for the specified component. - // NOTE: StoreKind is easier to work with than a `StoreId`` or full `DataStore` but - // might still be ambiguous when we have multiple stores active at a time. + /// + /// These are resolved overrides, i.e. the result of recursive override propagation + individual overrides. // TODO(jleibs): Consider something like `tinymap` for this. - pub component_overrides: HashMap, + // TODO(andreas): Should be a `Cow` to not do as many clones. + // TODO(andreas): Track recursive vs resolved (== individual + recursive) overrides. + // Recursive here meaning inherited + own recursive, i.e. not just what's on the path. + // What is logged on *this* entity can be inferred from walking up the tree. + pub resolved_component_overrides: IntMap, /// `EntityPath` in the Blueprint store where updated overrides should be written back /// for properties that apply recursively. @@ -91,6 +113,64 @@ impl DataResult { .map(|p| &p.individual_override_path) } + /// Saves a recursive override OR clears both (!) individual & recursive overrides if the override is due to a parent recursive override or a default value. + // TODO(andreas): Does not take individual overrides into account yet. + // TODO(andreas): This should have a unit test, but the delayed override write makes it hard to test. + pub fn save_recursive_override_or_clear_if_redundant( + &self, + ctx: &ViewerContext<'_>, + data_result_tree: &DataResultTree, + desired_override: &C, + ) { + re_tracing::profile_function!(); + + // TODO(jleibs): Make it impossible for this to happen with different type structure + // This should never happen unless we're doing something with a partially processed + // query. + let (Some(recursive_override_path), Some(individual_override_path)) = ( + self.recursive_override_path(), + self.individual_override_path(), + ) else { + re_log::warn!( + "Tried to save override for {:?} but it has no override path", + self.entity_path + ); + return; + }; + + if let Some(current_resolved_override) = self.lookup_override::(ctx) { + // Do nothing if the resolved override is already the same as the new override. + if ¤t_resolved_override == desired_override { + return; + } + + // TODO(andreas): Assumes this is a recursive override + let parent_recursive_override = self + .entity_path + .parent() + .and_then(|parent_path| data_result_tree.lookup_result_by_path(&parent_path)) + .and_then(|data_result| data_result.lookup_override::(ctx)); + + // If the parent has a recursive override that is the same as the new override, + // clear both individual and recursive override at the current path. + // (at least one of them has to be set, otherwise the current resolved override would be the same as the desired override) + // + // Another case for clearing + if parent_recursive_override.as_ref() == Some(desired_override) + || (parent_recursive_override.is_none() && desired_override == &C::default()) + { + // TODO(andreas): It might be that only either of these two are necessary, in that case we shouldn't clear both. + ctx.save_empty_blueprint_component::(recursive_override_path); + ctx.save_empty_blueprint_component::(individual_override_path); + } else { + ctx.save_blueprint_component(recursive_override_path, desired_override); + } + } else { + // No override at all so far, simply set it. + ctx.save_blueprint_component(recursive_override_path, desired_override); + } + } + /// Write the [`EntityProperties`] for this result back to the Blueprint store on the recursive override. /// /// Setting `new_recursive_props` to `None` will always clear the override. @@ -145,44 +225,20 @@ impl DataResult { return; }; - let cell = match new_individual_props { + match new_individual_props { None => { - re_log::debug!("Clearing {:?}", override_path); - - Some(DataCell::from_arrow_empty( - EntityPropertiesComponent::name(), - EntityPropertiesComponent::arrow_datatype(), - )) + ctx.save_empty_blueprint_component::(override_path); } Some(props) => { // A value of `None` in the data store means "use the default value", so if // the properties are `None`, we only must save if `props` is different // from the default. if props.has_edits(properties.unwrap_or(&DEFAULT_PROPS)) { - re_log::debug!("Overriding {:?} with {:?}", override_path, props); - let component = EntityPropertiesComponent(props); - - Some(DataCell::from([component])) - } else { - None + ctx.save_blueprint_component(override_path, &component); } } }; - - if let Some(cell) = cell { - let timepoint = blueprint_timepoint_for_writes(); - - let row = - DataRow::from_cells1_sized(RowId::new(), override_path.clone(), timepoint, 1, cell) - .unwrap(); - - ctx.command_sender - .send_system(SystemCommand::UpdateBlueprint( - ctx.store_context.blueprint.store_id().clone(), - vec![row], - )); - } } #[inline] @@ -214,6 +270,87 @@ impl DataResult { .as_ref() .and_then(|p| p.individual_properties.as_ref()) } + + pub fn lookup_override(&self, ctx: &ViewerContext<'_>) -> Option { + self.property_overrides + .as_ref() + .and_then(|p| p.resolved_component_overrides.get(&C::name())) + .and_then(|OverridePath { store_kind, path }| match store_kind { + StoreKind::Blueprint => ctx + .store_context + .blueprint + .store() + .query_latest_component::(path, ctx.blueprint_query), + StoreKind::Recording => ctx + .entity_db + .store() + .query_latest_component::(path, &ctx.current_query()), + }) + .map(|c| c.value) + } + + #[inline] + pub fn lookup_override_or_default( + &self, + ctx: &ViewerContext<'_>, + ) -> C { + self.lookup_override(ctx).unwrap_or_default() + } + + /// Returns from which entity path an override originates from. + /// + /// Returns None if there was no override at all. + /// Note that if this returns the current path, the override might be either an individual or recursive override. + #[inline] + pub fn component_override_source( + &self, + result_tree: &DataResultTree, + component_name: &ComponentName, + ) -> Option { + re_tracing::profile_function!(); + + // If we don't have a resolved override, clearly nothing overrode this. + let active_override = self + .property_overrides + .as_ref() + .and_then(|p| p.resolved_component_overrides.get(component_name))?; + + // Walk up the tree to find the highest ancestor which has a matching override. + // This must be the ancestor we inherited the override from. Note that `active_override` + // is a `(StoreKind, EntityPath)`, not a value. + let mut override_source = self.entity_path.clone(); + while let Some(parent_path) = override_source.parent() { + if result_tree + .lookup_result_by_path(&parent_path) + .and_then(|data_result| data_result.property_overrides.as_ref()) + .map_or(true, |property_overrides| { + // TODO(andreas): Assumes all overrides are recursive which is not true, + // This should access `recursive_component_overrides` instead. + property_overrides + .resolved_component_overrides + .get(component_name) + != Some(active_override) + }) + { + break; + } + + override_source = parent_path; + } + + Some(override_source) + } + + /// Shorthand for checking for visibility on data overrides. + /// + /// Note that this won't check if the data store has visibility logged. + // TODO(andreas): Should this be possible? + // TODO(andreas): Should the result be cached, this might be a very common operation? + #[inline] + pub fn is_visible(&self, ctx: &ViewerContext<'_>) -> bool { + self.lookup_override_or_default::(ctx) + .0 + } } pub type PerSystemDataResults<'a> = BTreeMap>; @@ -244,17 +381,21 @@ pub struct ViewQuery<'s> { impl<'s> ViewQuery<'s> { /// Iter over all of the currently visible [`DataResult`]s for a given `ViewSystem` - pub fn iter_visible_data_results( - &self, + pub fn iter_visible_data_results<'a>( + &'a self, + ctx: &'a ViewerContext<'a>, system: ViewSystemIdentifier, - ) -> impl Iterator { + ) -> impl Iterator + where + 's: 'a, + { self.per_system_data_results.get(&system).map_or( itertools::Either::Left(std::iter::empty()), |results| { itertools::Either::Right( results .iter() - .filter(|result| result.accumulated_properties().visible) + .filter(|result| result.is_visible(ctx)) .copied(), ) }, diff --git a/crates/re_viewport/src/context_menu/actions/show_hide.rs b/crates/re_viewport/src/context_menu/actions/show_hide.rs index f3319805ab55..b4488c42eb32 100644 --- a/crates/re_viewport/src/context_menu/actions/show_hide.rs +++ b/crates/re_viewport/src/context_menu/actions/show_hide.rs @@ -125,11 +125,7 @@ fn data_result_visible( query_result .tree .lookup_result_by_path(&instance_path.entity_path) - .map(|data_result| { - data_result - .recursive_properties() - .map_or(true, |prop| prop.visible) - }) + .map(|data_result| data_result.is_visible(ctx.viewer_context)) }) .flatten() } @@ -140,17 +136,18 @@ fn set_data_result_visible( instance_path: &InstancePath, visible: bool, ) { - let query_result = ctx.viewer_context.lookup_query_result(*space_view_id); - if let Some(data_result) = query_result - .tree - .lookup_result_by_path(&instance_path.entity_path) - { - let mut recursive_properties = data_result - .recursive_properties() - .cloned() - .unwrap_or_default(); - recursive_properties.visible = visible; - - data_result.save_recursive_override(ctx.viewer_context, Some(recursive_properties)); + if let Some(query_result) = ctx.viewer_context.query_results.get(space_view_id) { + if let Some(data_result) = query_result + .tree + .lookup_result_by_path(&instance_path.entity_path) + { + data_result.save_recursive_override_or_clear_if_redundant( + ctx.viewer_context, + &query_result.tree, + &re_types::blueprint::components::Visible(visible), + ); + } + } else { + re_log::error!("No query available for space view {:?}", space_view_id); } } diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 293eb6863ee4..588fefd8c047 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -7,6 +7,7 @@ use re_entity_db::InstancePath; use re_log_types::EntityPath; use re_log_types::EntityPathRule; use re_space_view::{SpaceViewBlueprint, SpaceViewName}; +use re_types::blueprint::components::Visible; use re_ui::{drag_and_drop::DropTarget, list_item::ListItem, ReUi}; use re_viewer_context::{CollapseScope, DataResultTree}; use re_viewer_context::{ @@ -539,12 +540,7 @@ impl Viewport<'_, '_> { let is_item_hovered = ctx.selection_state().highlight_for_ui_element(&item) == HoverHighlight::Hovered; - let visible = - data_result_node.map_or(false, |n| n.data_result.accumulated_properties().visible); - let mut recursive_properties = data_result_node - .and_then(|n| n.data_result.recursive_properties()) - .cloned() - .unwrap_or_default(); + let visible = data_result_node.map_or(false, |n| n.data_result.is_visible(ctx)); let item_label = if entity_path.is_root() { "/ (root)".to_owned() @@ -573,12 +569,20 @@ impl Viewport<'_, '_> { .subdued(subdued) .force_hovered(is_item_hovered) .with_buttons(|re_ui: &_, ui: &mut egui::Ui| { - let vis_response = visibility_button_ui( - re_ui, - ui, - space_view_visible, - &mut recursive_properties.visible, - ); + let mut visible_after = visible; + let vis_response = + visibility_button_ui(re_ui, ui, space_view_visible, &mut visible_after); + if visible_after != visible { + if let Some(data_result_node) = data_result_node { + data_result_node + .data_result + .save_recursive_override_or_clear_if_redundant( + ctx, + &query_result.tree, + &Visible(visible_after), + ); + } + } let response = remove_button_ui( re_ui, @@ -602,7 +606,7 @@ impl Viewport<'_, '_> { let default_open = entity_path.starts_with(&space_view.space_origin) && Self::default_open_for_data_result(node); - let response = list_item + list_item .show_collapsing( ui, CollapseScope::BlueprintTree.data_result(space_view.id, entity_path.clone()), @@ -634,12 +638,7 @@ impl Viewport<'_, '_> { } }, ) - .item_response; - - node.data_result - .save_recursive_override(ctx, Some(recursive_properties)); - - response + .item_response } else { list_item.show(ui) }; diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index 690af975e98a..4d072495bf04 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -54,7 +54,7 @@ impl VisualizerSystem for InstanceColorSystem { _view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { // For each entity in the space view that should be displayed with the `InstanceColorSystem`… - for data_result in query.iter_visible_data_results(Self::identifier()) { + for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { // …gather all colors and their instance ids. if let Ok(arch_view) = query_archetype::( ctx.entity_db.store(), From 458862b792297fce037301d013d9f44a6eebc6cf Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 15 Mar 2024 07:59:06 -0400 Subject: [PATCH 035/508] Convert the SpaceViewArchetype to use QueryExpression as a batch (#5516) ### What Working with lists of query expressions is generally much more ergonomic than wrangling newline separated strings in the blueprint APIs. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5516/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5516/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5516/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5516) - [Docs preview](https://rerun.io/preview/8adae8bec4acb3de40258d08819073ec5e6b82fa/docs) - [Examples preview](https://rerun.io/preview/8adae8bec4acb3de40258d08819073ec5e6b82fa/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/path/entity_path_filter.rs | 34 +++++++--- .../re_space_view/src/space_view_contents.rs | 13 +++- .../archetypes/space_view_contents.fbs | 36 ++++++++++- .../blueprint/components/query_expression.fbs | 31 ++------- .../archetypes/space_view_contents.rs | 64 +++++++++++++++---- .../blueprint/components/query_expression.rs | 31 ++------- .../archetypes/space_view_contents.hpp | 38 ++++++++++- .../blueprint/components/query_expression.hpp | 31 ++------- rerun_py/rerun_sdk/rerun/blueprint/api.py | 22 ++----- .../archetypes/space_view_contents.py | 40 +++++++++++- .../blueprint/components/query_expression.py | 31 ++------- .../tests/unit/test_space_view_contents.py | 18 ++++-- 12 files changed, 227 insertions(+), 162 deletions(-) diff --git a/crates/re_log_types/src/path/entity_path_filter.rs b/crates/re_log_types/src/path/entity_path_filter.rs index b555d45023a3..7bd5fe36918d 100644 --- a/crates/re_log_types/src/path/entity_path_filter.rs +++ b/crates/re_log_types/src/path/entity_path_filter.rs @@ -1,5 +1,7 @@ use std::collections::BTreeMap; +use itertools::Itertools as _; + use crate::EntityPath; /// A way to filter a set of `EntityPath`s. @@ -101,10 +103,22 @@ impl EntityPathFilter { /// /// Conflicting rules are resolved by the last rule. pub fn parse_forgiving(rules: &str) -> Self { + Self::from_query_expressions(rules.split('\n')) + } + + /// Build a filter from a list of query expressions. + /// + /// Each item in the iterator should be a query expression. + /// + /// The first character should be `+` or `-`. If missing, `+` is assumed. + /// The rest of the expression is trimmed and treated as an entity path. + /// + /// Conflicting rules are resolved by the last rule. + pub fn from_query_expressions<'a>(rules: impl IntoIterator) -> Self { let mut filter = Self::default(); for line in rules - .split('\n') + .into_iter() .map(|line| line.trim()) .filter(|line| !line.is_empty()) { @@ -140,9 +154,9 @@ impl EntityPathFilter { self.rules.insert(rule, effect); } - pub fn formatted(&self) -> String { - let mut s = String::new(); - for (rule, effect) in &self.rules { + pub fn iter_expressions(&self) -> impl Iterator + '_ { + self.rules.iter().map(|(rule, effect)| { + let mut s = String::new(); s.push_str(match effect { RuleEffect::Include => "+ ", RuleEffect::Exclude => "- ", @@ -156,12 +170,12 @@ impl EntityPathFilter { s.push_str("/**"); } } - s.push('\n'); - } - if s.ends_with('\n') { - s.pop(); - } - s + s + }) + } + + pub fn formatted(&self) -> String { + self.iter_expressions().join("\n") } /// Find the most specific matching rule and return its effect. diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index c999d337e276..f885865edfa3 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -112,7 +112,9 @@ impl SpaceViewContents { Default::default() }); - let entity_path_filter = EntityPathFilter::parse_forgiving(query.0.as_str()); + let query = query.iter().map(|qe| qe.0.as_str()); + + let entity_path_filter = EntityPathFilter::from_query_expressions(query); Self { blueprint_entity_path, @@ -130,7 +132,9 @@ impl SpaceViewContents { pub fn save_to_blueprint_store(&self, ctx: &ViewerContext<'_>) { ctx.save_blueprint_archetype( self.blueprint_entity_path.clone(), - &blueprint_archetypes::SpaceViewContents::new(self.entity_path_filter.formatted()), + &blueprint_archetypes::SpaceViewContents::new( + self.entity_path_filter.iter_expressions(), + ), ); } @@ -145,7 +149,10 @@ impl SpaceViewContents { ctx.save_blueprint_component( &self.blueprint_entity_path, - &QueryExpression(new_entity_path_filter.formatted().into()), + &new_entity_path_filter + .iter_expressions() + .map(|s| QueryExpression(s.into())) + .collect::>(), ); } diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/space_view_contents.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/space_view_contents.fbs index e8da863a7cfb..95250bf0558b 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/space_view_contents.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/space_view_contents.fbs @@ -8,14 +8,48 @@ namespace rerun.blueprint.archetypes; // --- /// The contents of a `SpaceView`. +/// +/// The contents are found by combining a collection of `QueryExpression`s. +/// +/// ```diff +/// + /world/** # add everything… +/// - /world/roads/** # …but remove all roads… +/// + /world/roads/main # …but show main road +/// ``` +/// +/// If there is multiple matching rules, the most specific rule wins. +/// If there are multiple rules of the same specificity, the last one wins. +/// If no rules match, the path is excluded. +/// +/// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively +/// (`/world/**` matches both `/world` and `/world/car/driver`). +/// Other uses of `*` are not (yet) supported. +/// +/// Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive. +/// This means the last matching rule is also the most specific one. For instance: +/// ```diff +/// + /world/** +/// - /world +/// - /world/car/** +/// + /world/car/driver +/// ``` +/// +/// The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. +/// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. +/// The last rule matching `/world` is `- /world`, so it is excluded. +/// The last rule matching `/world/house` is `+ /world/**`, so it is included. +/// +/// Unstable. Used for the ongoing blueprint experimentations. table SpaceViewContents ( "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default" ) { // --- Required --- + // --- Optional --- + /// The `QueryExpression` that populates the contents for the `SpaceView`. /// /// They determine which entities are part of the spaceview. - query: rerun.blueprint.components.QueryExpression ("attr.rerun.component_required", order: 1000); + query: [rerun.blueprint.components.QueryExpression] ("attr.rerun.component_optional", order: 1000); } diff --git a/crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs b/crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs index 01d98798b5f8..12efe195ed8c 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs @@ -8,40 +8,17 @@ include "rerun/attributes.fbs"; namespace rerun.blueprint.components; // --- -/// A way to filter a set of `EntityPath`s. +/// An individual `QueryExpression` used to filter a set of `EntityPath`s. /// -/// This implements as simple set of include/exclude rules: +/// Each expression is either an inclusion or an exclusion expression. +/// Inclusions start with an optional `+` and exclusions must start with a `-`. /// -/// ```diff -/// + /world/** # add everything… -/// - /world/roads/** # …but remove all roads… -/// + /world/roads/main # …but show main road -/// ``` -/// -/// If there is multiple matching rules, the most specific rule wins. -/// If there are multiple rules of the same specificity, the last one wins. -/// If no rules match, the path is excluded. +/// Multiple expressions are combined together as part of `SpaceViewContents`. /// /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. /// -/// Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive. -/// This means the last matching rule is also the most specific one. -/// For instance: -/// -/// ```diff -/// + /world/** -/// - /world -/// - /world/car/** -/// + /world/car/driver -/// ``` -/// -/// The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. -/// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. -/// The last rule matching `/world` is `- /world`, so it is excluded. -/// The last rule matching `/world/house` is `+ /world/**`, so it is included. -/// /// Unstable. Used for the ongoing blueprint experimentations. table QueryExpression ( "attr.rerun.scope": "blueprint", diff --git a/crates/re_types/src/blueprint/archetypes/space_view_contents.rs b/crates/re_types/src/blueprint/archetypes/space_view_contents.rs index 45a696c086cb..d2bae9513ae3 100644 --- a/crates/re_types/src/blueprint/archetypes/space_view_contents.rs +++ b/crates/re_types/src/blueprint/archetypes/space_view_contents.rs @@ -22,12 +22,44 @@ use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: The contents of a `SpaceView`. +/// +/// The contents are found by combining a collection of `QueryExpression`s. +/// +/// ```diff +/// + /world/** # add everything… +/// - /world/roads/** # …but remove all roads… +/// + /world/roads/main # …but show main road +/// ``` +/// +/// If there is multiple matching rules, the most specific rule wins. +/// If there are multiple rules of the same specificity, the last one wins. +/// If no rules match, the path is excluded. +/// +/// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively +/// (`/world/**` matches both `/world` and `/world/car/driver`). +/// Other uses of `*` are not (yet) supported. +/// +/// Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive. +/// This means the last matching rule is also the most specific one. For instance: +/// ```diff +/// + /world/** +/// - /world +/// - /world/car/** +/// + /world/car/driver +/// ``` +/// +/// The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. +/// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. +/// The last rule matching `/world` is `- /world`, so it is excluded. +/// The last rule matching `/world/house` is `+ /world/**`, so it is included. +/// +/// Unstable. Used for the ongoing blueprint experimentations. #[derive(Clone, Debug, Default)] pub struct SpaceViewContents { /// The `QueryExpression` that populates the contents for the `SpaceView`. /// /// They determine which entities are part of the spaceview. - pub query: crate::blueprint::components::QueryExpression, + pub query: Vec, } impl ::re_types_core::SizeBytes for SpaceViewContents { @@ -38,24 +70,29 @@ impl ::re_types_core::SizeBytes for SpaceViewContents { #[inline] fn is_pod() -> bool { - ::is_pod() + >::is_pod() } } -static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.QueryExpression".into()]); +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.SpaceViewContentsIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.QueryExpression".into(), + "rerun.components.InstanceKey".into(), + ] + }); static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ - "rerun.blueprint.components.QueryExpression".into(), "rerun.blueprint.components.SpaceViewContentsIndicator".into(), + "rerun.blueprint.components.QueryExpression".into(), "rerun.components.InstanceKey".into(), ] }); @@ -119,9 +156,8 @@ impl ::re_types_core::Archetype for SpaceViewContents { ::from_arrow_opt(&**array) .with_context("rerun.blueprint.archetypes.SpaceViewContents#query")? .into_iter() - .next() - .flatten() - .ok_or_else(DeserializationError::missing_data) + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .collect::>>() .with_context("rerun.blueprint.archetypes.SpaceViewContents#query")? }; Ok(Self { query }) @@ -143,14 +179,16 @@ impl ::re_types_core::AsComponents for SpaceViewContents { #[inline] fn num_instances(&self) -> usize { - 1 + 0 } } impl SpaceViewContents { - pub fn new(query: impl Into) -> Self { + pub fn new( + query: impl IntoIterator>, + ) -> Self { Self { - query: query.into(), + query: query.into_iter().map(Into::into).collect(), } } } diff --git a/crates/re_types/src/blueprint/components/query_expression.rs b/crates/re_types/src/blueprint/components/query_expression.rs index 98c0961e7200..fb0dddbec79c 100644 --- a/crates/re_types/src/blueprint/components/query_expression.rs +++ b/crates/re_types/src/blueprint/components/query_expression.rs @@ -21,40 +21,17 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Component**: A way to filter a set of `EntityPath`s. +/// **Component**: An individual `QueryExpression` used to filter a set of `EntityPath`s. /// -/// This implements as simple set of include/exclude rules: +/// Each expression is either an inclusion or an exclusion expression. +/// Inclusions start with an optional `+` and exclusions must start with a `-`. /// -/// ```diff -/// + /world/** # add everything… -/// - /world/roads/** # …but remove all roads… -/// + /world/roads/main # …but show main road -/// ``` -/// -/// If there is multiple matching rules, the most specific rule wins. -/// If there are multiple rules of the same specificity, the last one wins. -/// If no rules match, the path is excluded. +/// Multiple expressions are combined together as part of `SpaceViewContents`. /// /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. /// -/// Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive. -/// This means the last matching rule is also the most specific one. -/// For instance: -/// -/// ```diff -/// + /world/** -/// - /world -/// - /world/car/** -/// + /world/car/driver -/// ``` -/// -/// The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. -/// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. -/// The last rule matching `/world` is `- /world`, so it is excluded. -/// The last rule matching `/world/house` is `+ /world/**`, so it is included. -/// /// Unstable. Used for the ongoing blueprint experimentations. #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp index 3a7eeb186f0c..53ffc874c3d6 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp @@ -15,11 +15,43 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: The contents of a `SpaceView`. + /// + /// The contents are found by combining a collection of `QueryExpression`s. + /// + /// ```diff + /// + /world/** # add everything… + /// - /world/roads/** # …but remove all roads… + /// + /world/roads/main # …but show main road + /// ``` + /// + /// If there is multiple matching rules, the most specific rule wins. + /// If there are multiple rules of the same specificity, the last one wins. + /// If no rules match, the path is excluded. + /// + /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively + /// (`/world/**` matches both `/world` and `/world/car/driver`). + /// Other uses of `*` are not (yet) supported. + /// + /// Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive. + /// This means the last matching rule is also the most specific one. For instance: + /// ```diff + /// + /world/** + /// - /world + /// - /world/car/** + /// + /world/car/driver + /// ``` + /// + /// The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. + /// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. + /// The last rule matching `/world` is `- /world`, so it is excluded. + /// The last rule matching `/world/house` is `+ /world/**`, so it is included. + /// + /// Unstable. Used for the ongoing blueprint experimentations. struct SpaceViewContents { /// The `QueryExpression` that populates the contents for the `SpaceView`. /// /// They determine which entities are part of the spaceview. - rerun::blueprint::components::QueryExpression query; + Collection query; public: static constexpr const char IndicatorComponentName[] = @@ -32,12 +64,12 @@ namespace rerun::blueprint::archetypes { SpaceViewContents() = default; SpaceViewContents(SpaceViewContents&& other) = default; - explicit SpaceViewContents(rerun::blueprint::components::QueryExpression _query) + explicit SpaceViewContents(Collection _query) : query(std::move(_query)) {} /// Returns the number of primary instances of this archetype. size_t num_instances() const { - return 1; + return query.size(); } }; diff --git a/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp b/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp index cf4b3e3a8277..2ed83df16a81 100644 --- a/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp @@ -18,40 +18,17 @@ namespace arrow { } // namespace arrow namespace rerun::blueprint::components { - /// **Component**: A way to filter a set of `EntityPath`s. + /// **Component**: An individual `QueryExpression` used to filter a set of `EntityPath`s. /// - /// This implements as simple set of include/exclude rules: + /// Each expression is either an inclusion or an exclusion expression. + /// Inclusions start with an optional `+` and exclusions must start with a `-`. /// - /// ```diff - /// + /world/** # add everything… - /// - /world/roads/** # …but remove all roads… - /// + /world/roads/main # …but show main road - /// ``` - /// - /// If there is multiple matching rules, the most specific rule wins. - /// If there are multiple rules of the same specificity, the last one wins. - /// If no rules match, the path is excluded. + /// Multiple expressions are combined together as part of `SpaceViewContents`. /// /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. /// - /// Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive. - /// This means the last matching rule is also the most specific one. - /// For instance: - /// - /// ```diff - /// + /world/** - /// - /world - /// - /world/car/** - /// + /world/car/driver - /// ``` - /// - /// The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. - /// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. - /// The last rule matching `/world` is `- /world`, so it is excluded. - /// The last rule matching `/world/house` is `+ /world/**`, so it is included. - /// /// Unstable. Used for the ongoing blueprint experimentations. struct QueryExpression { rerun::datatypes::Utf8 filter; diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index ae031e3ded94..3b5696df18b6 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -2,18 +2,18 @@ import itertools import uuid -from typing import Iterable, Optional, Sequence, Union +from typing import Iterable, Optional, Union import rerun_bindings as bindings -from ..datatypes import EntityPathLike, Utf8Like +from ..datatypes import EntityPathLike, Utf8ArrayLike, Utf8Like from ..recording import MemoryRecording from ..recording_stream import RecordingStream from .archetypes import ContainerBlueprint, PanelBlueprint, SpaceViewBlueprint, SpaceViewContents, ViewportBlueprint from .components import ColumnShareArrayLike, RowShareArrayLike from .components.container_kind import ContainerKindLike -SpaceViewContentsLike = Union[str, Sequence[str], Utf8Like, SpaceViewContents] +SpaceViewContentsLike = Union[Utf8ArrayLike, SpaceViewContents] class SpaceView: @@ -80,21 +80,11 @@ def to_blueprint(self) -> Blueprint: def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" - # Handle the cases for SpaceViewContentsLike - # TODO(#5483): Move this into a QueryExpressionExt class. - # This is a little bit tricky since QueryExpression is a delegating component for Utf8, - # and delegating components make extending things in this way a bit more complicated. - if isinstance(self.contents, str): - # str - contents = SpaceViewContents(query=self.contents) - elif isinstance(self.contents, Sequence) and len(self.contents) > 0 and isinstance(self.contents[0], str): - # list[str] - contents = SpaceViewContents(query="\n".join(self.contents)) - elif isinstance(self.contents, SpaceViewContents): - # SpaceViewContents + if isinstance(self.contents, SpaceViewContents): + # If contents is already a SpaceViewContents, we can just use it directly contents = self.contents else: - # Anything else we let SpaceViewContents handle + # Otherwise we delegate to the SpaceViewContents constructor contents = SpaceViewContents(query=self.contents) # type: ignore[arg-type] stream.log(self.blueprint_path() + "/SpaceViewContents", contents) # type: ignore[attr-defined] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/space_view_contents.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/space_view_contents.py index 3f38a598acbe..dd1ee215cc54 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/space_view_contents.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/space_view_contents.py @@ -19,9 +19,43 @@ @define(str=False, repr=False, init=False) class SpaceViewContents(Archetype): - """**Archetype**: The contents of a `SpaceView`.""" - - def __init__(self: Any, query: datatypes.Utf8Like): + """ + **Archetype**: The contents of a `SpaceView`. + + The contents are found by combining a collection of `QueryExpression`s. + + ```diff + + /world/** # add everything… + - /world/roads/** # …but remove all roads… + + /world/roads/main # …but show main road + ``` + + If there is multiple matching rules, the most specific rule wins. + If there are multiple rules of the same specificity, the last one wins. + If no rules match, the path is excluded. + + The `/**` suffix matches the whole subtree, i.e. self and any child, recursively + (`/world/**` matches both `/world` and `/world/car/driver`). + Other uses of `*` are not (yet) supported. + + Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive. + This means the last matching rule is also the most specific one. For instance: + ```diff + + /world/** + - /world + - /world/car/** + + /world/car/driver + ``` + + The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. + The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. + The last rule matching `/world` is `- /world`, so it is excluded. + The last rule matching `/world/house` is `+ /world/**`, so it is included. + + Unstable. Used for the ongoing blueprint experimentations. + """ + + def __init__(self: Any, query: datatypes.Utf8ArrayLike): """ Create a new instance of the SpaceViewContents archetype. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/query_expression.py b/rerun_py/rerun_sdk/rerun/blueprint/components/query_expression.py index 063e11ffbff8..ab9a59cfd592 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/query_expression.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/query_expression.py @@ -13,40 +13,17 @@ class QueryExpression(datatypes.Utf8): """ - **Component**: A way to filter a set of `EntityPath`s. + **Component**: An individual `QueryExpression` used to filter a set of `EntityPath`s. - This implements as simple set of include/exclude rules: + Each expression is either an inclusion or an exclusion expression. + Inclusions start with an optional `+` and exclusions must start with a `-`. - ```diff - + /world/** # add everything… - - /world/roads/** # …but remove all roads… - + /world/roads/main # …but show main road - ``` - - If there is multiple matching rules, the most specific rule wins. - If there are multiple rules of the same specificity, the last one wins. - If no rules match, the path is excluded. + Multiple expressions are combined together as part of `SpaceViewContents`. The `/**` suffix matches the whole subtree, i.e. self and any child, recursively (`/world/**` matches both `/world` and `/world/car/driver`). Other uses of `*` are not (yet) supported. - Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive. - This means the last matching rule is also the most specific one. - For instance: - - ```diff - + /world/** - - /world - - /world/car/** - + /world/car/driver - ``` - - The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included. - The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. - The last rule matching `/world` is `- /world`, so it is excluded. - The last rule matching `/world/house` is `+ /world/**`, so it is included. - Unstable. Used for the ongoing blueprint experimentations. """ diff --git a/rerun_py/tests/unit/test_space_view_contents.py b/rerun_py/tests/unit/test_space_view_contents.py index 36ead02d1e83..4ed50b269959 100644 --- a/rerun_py/tests/unit/test_space_view_contents.py +++ b/rerun_py/tests/unit/test_space_view_contents.py @@ -5,11 +5,20 @@ from rerun.blueprint.archetypes.space_view_contents import SpaceViewContents from rerun.blueprint.components.query_expression import QueryExpression, QueryExpressionBatch -from rerun.datatypes.utf8 import Utf8Like +from rerun.datatypes.utf8 import Utf8ArrayLike def test_space_view_contents() -> None: - query_array = ["+ /**\n- /robot", QueryExpression("+ /**\n- /robot")] + query_array = [ + [ + "+ /**", + "- /robot", + ], + [ + QueryExpression("+ /**"), + QueryExpression("- /robot"), + ], + ] all_arrays = itertools.zip_longest( query_array, @@ -19,7 +28,7 @@ def test_space_view_contents() -> None: # query = query if query is not None else query_array[-1] # mypy can't track types properly through itertools zip so re-cast - query = cast(Utf8Like, query) + query = cast(Utf8ArrayLike, query) print( "rr.SpaceViewContents(\n", @@ -29,7 +38,6 @@ def test_space_view_contents() -> None: arch = SpaceViewContents( query, ) - print(f"{arch}\n") # 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.query == QueryExpressionBatch("+ /**\n- /robot") + assert arch.query == QueryExpressionBatch(["+ /**", "- /robot"]) From 1509aae72e1d30f974355624bd0433754cffe7b9 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 15 Mar 2024 10:24:35 -0400 Subject: [PATCH 036/508] Fix the names of the links in types.md (#5526) ### What Some names that never got updated. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5526/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5526/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5526/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5526) - [Docs preview](https://rerun.io/preview/926bf84385cac680b0d98a59977a0e1676fb3513/docs) - [Examples preview](https://rerun.io/preview/926bf84385cac680b0d98a59977a0e1676fb3513/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/content/reference/types.md | 57 +++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/docs/content/reference/types.md b/docs/content/reference/types.md index b2057e0c9da5..d6286a445256 100644 --- a/docs/content/reference/types.md +++ b/docs/content/reference/types.md @@ -12,49 +12,52 @@ For more information on the relationship between **archetypes** and **components on [Entities and Components](../concepts/entity-component.md). ## Spatial **Archetypes** + The spatial archetypes represent 2D and 3D spatial data. These types have some notion of a coordinate system and generally support spatial transformations. These types can be visualized by 2D and 3D space views. To visualize a 2D entity in a 3D space view it must be under a pinhole transformation. To visualize a 3D entity in a 2D space view, the 2D's origin must be at a pinhole transform and all 3D objects are above it. -* [Arrow3D](types/archetypes/arrows3d.md) -* [Asset](types/archetypes/asset3d.md) -* [Box2D](types/archetypes/boxes2d.md) -* [Box3D](types/archetypes/boxes3d.md) -* [LineStrip2D](types/archetypes/line_strips2d.md) -* [LineStrip3D](types/archetypes/line_strips3d.md) -* [Mesh](types/archetypes/mesh3d.md) -* [Point2D](types/archetypes/points2d.md) -* [Point3D](types/archetypes/points3d.md) +- [Arrows3D](types/archetypes/arrows3d.md) +- [Asset3D](types/archetypes/asset3d.md) +- [Boxes2D](types/archetypes/boxes2d.md) +- [Boxes3D](types/archetypes/boxes3d.md) +- [LineStrips2D](types/archetypes/line_strips2d.md) +- [LineStrips3D](types/archetypes/line_strips3d.md) +- [Mesh3D](types/archetypes/mesh3d.md) +- [Points2D](types/archetypes/points2d.md) +- [Points3D](types/archetypes/points3d.md) ### Spatial transformations -* [Transform3D](types/archetypes/transform3d.md) -* [Pinhole](types/archetypes/pinhole.md) -* [DisconnectedSpace](types/archetypes/disconnected_space.md): disconnect an entity path from its parent. - +- [Transform3D](types/archetypes/transform3d.md) +- [Pinhole](types/archetypes/pinhole.md) +- [DisconnectedSpace](types/archetypes/disconnected_space.md): disconnect an entity path from its parent. ## Image & Tensor **Archetypes** + Image and tensor archetypes all build on top of a common tensor component. The tensor component is a multi-dimensional generic container for arrays of data. Images are restricted to tensors of rank 2 or rank 3; these can be viewed in the `Spatial` space view. Generic tensors of greater rank can only be viewed in the specialized `Tensor` space view. -* [Image](types/archetypes/image.md) -* [DepthImage](types/archetypes/depth_image.md) -* [SegmentationImage](types/archetypes/segmentation_image.md) -* [Tensor](types/archetypes/tensor.md) + +- [Image](types/archetypes/image.md) +- [DepthImage](types/archetypes/depth_image.md) +- [SegmentationImage](types/archetypes/segmentation_image.md) +- [Tensor](types/archetypes/tensor.md) ## Time Series **Archetypes** -* [Scalar](types/archetypes/scalar.md): a single scalar / metric value. -* [SeriesPoint](types/archetypes/series_point.md): define the style properties for a point series in a chart. -* [SeriesLine](types/archetypes/series_line.md): define the style properties for a line series in a chart. -* [TimeSeriesScalar (deprecated)](types/archetypes/time_series_scalar.md): a single scalar / metric value as well as styling options. Can be viewed in the `TimeSeries` space view. + +- [Scalar](types/archetypes/scalar.md): a single scalar / metric value. +- [SeriesPoint](types/archetypes/series_point.md): define the style properties for a point series in a chart. +- [SeriesLine](types/archetypes/series_line.md): define the style properties for a line series in a chart. +- [TimeSeriesScalar (deprecated)](types/archetypes/time_series_scalar.md): a single scalar / metric value as well as styling options. Can be viewed in the `TimeSeries` space view. ## Other **Archetypes** -* [AnnotationContext](types/archetypes/annotation_context.md): not viewed directly, but provides classes, labels, and connectivity information for other entities. -* [BarChart](types/archetypes/bar_chart.md): data displayed in a `BarChart` space view. -* [Clear](types/archetypes/clear.md): clear all components of an entity. -* [TextDocument](types/archetypes/text_document.md): text displayed in a `TextDocument` space view. -* [TextLog](types/archetypes/text_log.md): a log entry in a `TextLog` space view. -* [ViewCoordinates](types/archetypes/view_coordinates.md): determines how we interpret the coordinate system of an entity/space. +- [AnnotationContext](types/archetypes/annotation_context.md): not viewed directly, but provides classes, labels, and connectivity information for other entities. +- [BarChart](types/archetypes/bar_chart.md): data displayed in a `BarChart` space view. +- [Clear](types/archetypes/clear.md): clear all components of an entity. +- [TextDocument](types/archetypes/text_document.md): text displayed in a `TextDocument` space view. +- [TextLog](types/archetypes/text_log.md): a log entry in a `TextLog` space view. +- [ViewCoordinates](types/archetypes/view_coordinates.md): determines how we interpret the coordinate system of an entity/space. From ce407eb3480fb19a84d956fa283e1eb650831b1f Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 15 Mar 2024 10:49:40 -0400 Subject: [PATCH 037/508] Introduce basic support for $origin substitution in EntityPathFilter (#5517) ### What - Initial implementation of: https://github.com/rerun-io/rerun/issues/5288 - Builds on top of: https://github.com/rerun-io/rerun/pull/5516 This is a very dumb first stab at doing variable substitution. - Rather than parse the string to extract potential `$vars` it uses the input environment and blindly tries to substitute all the vars it knows about (currently only `origin`). - The biggest downside of this is we get no feedback when a variable fails to substitute. - There's just enough future complexity handling edge-cases (e.g. mismatched `{`, variable-termination, nested substitutions, etc.) that it might be worth pulling in a proper utility library, though I don't know if there's an obvious rust ecosystem choice here. Working through this uncovered some complexities regarding what we store in different parts of the blueprint. For example, if we do the full substitution immediately when construction the EntityPathFilter, then we can't use that Filter to re-create the query with the variable substitutions. Additionally, we need to know about these substitutions all the way back when evaluating whether we want to keep RecommendedSpaceViews because we need the substitutions applied to do the overlap-checking. I suspect the direction we might want to go in is to split EntityPathFilter into a non-substituted representation, from which we can create a version that executes the substitutions, but I'm not yet sure what the storage should look like. For example, do we just create full `EntityPath`s that contain EntityPathParts with "$origin" in them and then run the substitution on the EntityPath? ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5517/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5517/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5517/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5517) - [Docs preview](https://rerun.io/preview/82c517d5786790176b78fdfbff4a5e261a25f7f0/docs) - [Examples preview](https://rerun.io/preview/82c517d5786790176b78fdfbff4a5e261a25f7f0/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/path/entity_path_filter.rs | 137 +++++++++++++++--- crates/re_log_types/src/path/mod.rs | 2 +- crates/re_space_view/src/heuristics.rs | 6 +- crates/re_space_view/src/space_view.rs | 48 +++--- .../re_space_view/src/space_view_contents.rs | 11 +- .../src/space_view_2d.rs | 14 +- .../src/space_view_3d.rs | 15 +- .../src/space_view_class.rs | 7 +- .../src/space_view_class.rs | 12 +- crates/re_viewer/src/ui/selection_panel.rs | 2 +- .../src/space_view/spawn_heuristics.rs | 32 +++- .../src/add_space_view_or_container_modal.rs | 7 +- .../actions/add_entities_to_new_space_view.rs | 19 ++- .../context_menu/actions/add_space_view.rs | 6 +- .../re_viewport/src/space_view_heuristics.rs | 8 +- crates/re_viewport/src/viewport_blueprint.rs | 6 +- examples/python/plots/main.py | 20 ++- .../src/color_coordinates_space_view.rs | 7 +- .../rerun_sdk/rerun/blueprint/space_views.py | 42 +++++- 19 files changed, 266 insertions(+), 135 deletions(-) diff --git a/crates/re_log_types/src/path/entity_path_filter.rs b/crates/re_log_types/src/path/entity_path_filter.rs index 7bd5fe36918d..779e0a9fadc5 100644 --- a/crates/re_log_types/src/path/entity_path_filter.rs +++ b/crates/re_log_types/src/path/entity_path_filter.rs @@ -1,9 +1,21 @@ use std::collections::BTreeMap; +use ahash::HashMap; use itertools::Itertools as _; use crate::EntityPath; +/// A set of substitutions for entity paths. +#[derive(Default)] +pub struct EntityPathSubs(pub HashMap); + +impl EntityPathSubs { + /// Create a new set of substitutions from a single origin. + pub fn new_with_origin(origin: &EntityPath) -> Self { + Self(std::iter::once(("origin".to_owned(), origin.to_string())).collect()) + } +} + /// A way to filter a set of `EntityPath`s. /// /// This implements as simple set of include/exclude rules: @@ -54,14 +66,26 @@ impl std::fmt::Debug for EntityPathFilter { } } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug)] pub struct EntityPathRule { + // We need to store the raw expression to be able to round-trip the filter + // when it contains substitutions. + pub raw_expression: String, + pub path: EntityPath, /// If true, ALSO include children and grandchildren of this path (recursive rule). pub include_subtree: bool, } +impl PartialEq for EntityPathRule { + fn eq(&self, other: &Self) -> bool { + self.raw_expression == other.raw_expression + } +} + +impl Eq for EntityPathRule {} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RuleEffect { Include, @@ -102,8 +126,8 @@ impl EntityPathFilter { /// The rest of the line is trimmed and treated as an entity path. /// /// Conflicting rules are resolved by the last rule. - pub fn parse_forgiving(rules: &str) -> Self { - Self::from_query_expressions(rules.split('\n')) + pub fn parse_forgiving(rules: &str, subst_env: &EntityPathSubs) -> Self { + Self::from_query_expressions(rules.split('\n'), subst_env) } /// Build a filter from a list of query expressions. @@ -114,7 +138,10 @@ impl EntityPathFilter { /// The rest of the expression is trimmed and treated as an entity path. /// /// Conflicting rules are resolved by the last rule. - pub fn from_query_expressions<'a>(rules: impl IntoIterator) -> Self { + pub fn from_query_expressions<'a>( + rules: impl IntoIterator, + subst_env: &EntityPathSubs, + ) -> Self { let mut filter = Self::default(); for line in rules @@ -128,7 +155,7 @@ impl EntityPathFilter { _ => (RuleEffect::Include, line), }; - let rule = EntityPathRule::parse_forgiving(path_pattern); + let rule = EntityPathRule::parse_forgiving(path_pattern, subst_env); filter.add_rule(effect, rule); } @@ -161,15 +188,7 @@ impl EntityPathFilter { RuleEffect::Include => "+ ", RuleEffect::Exclude => "- ", }); - if rule.path.is_root() && rule.include_subtree { - // needs special casing, otherwise we end up with `//**` - s.push_str("/**"); - } else { - s.push_str(&rule.path.to_string()); - if rule.include_subtree { - s.push_str("/**"); - } - } + s.push_str(&rule.raw_expression); s }) } @@ -360,6 +379,7 @@ impl EntityPathRule { #[inline] pub fn exact(path: EntityPath) -> Self { Self { + raw_expression: path.to_string(), path, include_subtree: false, } @@ -369,26 +389,40 @@ impl EntityPathRule { #[inline] pub fn including_subtree(path: EntityPath) -> Self { Self { + raw_expression: format!("{path}/**",), path, include_subtree: true, } } - pub fn parse_forgiving(expression: &str) -> Self { - let expression = expression.trim(); + pub fn parse_forgiving(expression: &str, subst_env: &EntityPathSubs) -> Self { + let raw_expression = expression.trim().to_owned(); + + // TODO(#5528): This is a very naive implementation of variable substitution. + // unclear if we want to do this here, push this down into `EntityPath::parse`, + // or even supported deferred evaluation on the `EntityPath` itself. + let mut expression_sub = raw_expression.clone(); + for (key, value) in &subst_env.0 { + expression_sub = expression_sub.replace(format!("${key}").as_str(), value); + expression_sub = expression_sub.replace(format!("${{{key}}}").as_str(), value); + } + if expression == "/**" { Self { + raw_expression, path: EntityPath::root(), include_subtree: true, } - } else if let Some(path) = expression.strip_suffix("/**") { + } else if let Some(path) = expression_sub.strip_suffix("/**") { Self { + raw_expression, path: EntityPath::parse_forgiving(path), include_subtree: true, } } else { Self { - path: EntityPath::parse_forgiving(expression), + raw_expression, + path: EntityPath::parse_forgiving(&expression_sub), include_subtree: false, } } @@ -421,10 +455,12 @@ impl std::cmp::PartialOrd for EntityPathRule { #[cfg(test)] mod tests { - use crate::{EntityPath, EntityPathFilter, EntityPathRule, RuleEffect}; + use crate::{EntityPath, EntityPathFilter, EntityPathRule, EntityPathSubs, RuleEffect}; #[test] fn test_rule_order() { + let subst_env = Default::default(); + use std::cmp::Ordering; fn check_total_order(rules: &[EntityPathRule]) { @@ -459,12 +495,14 @@ mod tests { "/world/car/driver", "/x/y/z", ]; - let rules = rules.map(EntityPathRule::parse_forgiving); + let rules = rules.map(|rule| EntityPathRule::parse_forgiving(rule, &subst_env)); check_total_order(&rules); } #[test] fn test_entity_path_filter() { + let subst_env = Default::default(); + let filter = EntityPathFilter::parse_forgiving( r#" + /world/** @@ -472,6 +510,7 @@ mod tests { - /world/car/** + /world/car/driver "#, + &subst_env, ); for (path, expected_effect) in [ @@ -491,13 +530,59 @@ mod tests { } assert_eq!( - EntityPathFilter::parse_forgiving("/**").formatted(), + EntityPathFilter::parse_forgiving("/**", &subst_env).formatted(), + "+ /**" + ); + } + + #[test] + fn test_entity_path_filter_subs() { + // Make sure we use a string longer than `$origin` here. + // We can't do in-place substitution. + let subst_env = EntityPathSubs::new_with_origin(&EntityPath::from("/annoyingly/long/path")); + + let filter = EntityPathFilter::parse_forgiving( + r#" + + $origin/** + - $origin + - $origin/car/** + + $origin/car/driver + "#, + &subst_env, + ); + + for (path, expected_effect) in [ + ("/unworldly", None), + ("/annoyingly/long/path", Some(RuleEffect::Exclude)), + ("/annoyingly/long/path/house", Some(RuleEffect::Include)), + ("/annoyingly/long/path/car", Some(RuleEffect::Exclude)), + ("/annoyingly/long/path/car/hood", Some(RuleEffect::Exclude)), + ( + "/annoyingly/long/path/car/driver", + Some(RuleEffect::Include), + ), + ( + "/annoyingly/long/path/car/driver/head", + Some(RuleEffect::Exclude), + ), + ] { + assert_eq!( + filter.most_specific_match(&EntityPath::from(path)), + expected_effect, + "path: {path:?}", + ); + } + + assert_eq!( + EntityPathFilter::parse_forgiving("/**", &subst_env).formatted(), "+ /**" ); } #[test] fn test_entity_path_filter_subtree() { + let subst_env = Default::default(); + let filter = EntityPathFilter::parse_forgiving( r#" + /world/** @@ -507,6 +592,7 @@ mod tests { - /world/city - /world/houses/** "#, + &subst_env, ); for (path, expected) in [ @@ -533,6 +619,8 @@ mod tests { #[test] fn test_is_superset_of() { + let subst_env = Default::default(); + struct TestCase { filter: &'static str, contains: Vec<&'static str>, @@ -594,9 +682,9 @@ mod tests { ]; for case in &cases { - let filter = EntityPathFilter::parse_forgiving(case.filter); + let filter = EntityPathFilter::parse_forgiving(case.filter, &subst_env); for contains in &case.contains { - let contains_filter = EntityPathFilter::parse_forgiving(contains); + let contains_filter = EntityPathFilter::parse_forgiving(contains, &subst_env); assert!( filter.is_superset_of(&contains_filter), "Expected {:?} to fully contain {:?}, but it didn't", @@ -605,7 +693,8 @@ mod tests { ); } for not_contains in &case.not_contains { - let not_contains_filter = EntityPathFilter::parse_forgiving(not_contains); + let not_contains_filter = + EntityPathFilter::parse_forgiving(not_contains, &subst_env); assert!( !filter.is_superset_of(¬_contains_filter), "Expected {:?} to NOT fully contain {:?}, but it did", diff --git a/crates/re_log_types/src/path/mod.rs b/crates/re_log_types/src/path/mod.rs index 0ba2fe95aa98..fa394a720003 100644 --- a/crates/re_log_types/src/path/mod.rs +++ b/crates/re_log_types/src/path/mod.rs @@ -14,7 +14,7 @@ mod parse_path; pub use component_path::ComponentPath; pub use data_path::DataPath; pub use entity_path::{EntityPath, EntityPathHash}; -pub use entity_path_filter::{EntityPathFilter, EntityPathRule, RuleEffect}; +pub use entity_path_filter::{EntityPathFilter, EntityPathRule, EntityPathSubs, RuleEffect}; pub use entity_path_part::EntityPathPart; pub use parse_path::PathParseError; diff --git a/crates/re_space_view/src/heuristics.rs b/crates/re_space_view/src/heuristics.rs index cce353e33a97..264ccfb51d84 100644 --- a/crates/re_space_view/src/heuristics.rs +++ b/crates/re_space_view/src/heuristics.rs @@ -1,4 +1,3 @@ -use re_log_types::EntityPathFilter; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, RecommendedSpaceView, SpaceViewClass, SpaceViewSpawnHeuristics, ViewerContext, VisualizerSystem, @@ -44,10 +43,7 @@ where { None } else { - Some(RecommendedSpaceView { - root: entity.clone(), - query_filter: EntityPathFilter::single_entity_filter(entity), - }) + Some(RecommendedSpaceView::new_single_entity(entity.clone())) } }) .collect(); diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 821f62597b96..18d39498c7c8 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -4,7 +4,7 @@ use re_entity_db::{EntityDb, EntityPath, EntityProperties, VisibleHistory}; use re_entity_db::{EntityPropertiesComponent, EntityPropertyMap}; use crate::SpaceViewContents; -use re_log_types::{DataRow, EntityPathFilter, RowId}; +use re_log_types::{DataRow, EntityPathSubs, RowId}; use re_query::query_archetype; use re_types::blueprint::archetypes as blueprint_archetypes; use re_types::{ @@ -15,8 +15,9 @@ use re_types_core::archetypes::Clear; use re_types_core::Archetype as _; use re_viewer_context::{ blueprint_timepoint_for_writes, DataResult, PerSystemEntities, PropertyOverrides, - SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, - SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, + RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, + StoreContext, SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, + ViewerContext, }; // ---------------------------------------------------------------------------- @@ -80,8 +81,7 @@ impl SpaceViewBlueprint { /// must call [`Self::save_to_blueprint_store`]. pub fn new( space_view_class: SpaceViewClassIdentifier, - space_path: &EntityPath, - content: EntityPathFilter, + recommended: RecommendedSpaceView, ) -> Self { let id = SpaceViewId::random(); @@ -89,8 +89,8 @@ impl SpaceViewBlueprint { display_name: None, class_identifier: space_view_class, id, - space_origin: space_path.clone(), - contents: SpaceViewContents::new(id, space_view_class, content), + space_origin: recommended.origin, + contents: SpaceViewContents::new(id, space_view_class, recommended.query_filter), visible: true, pending_writes: Default::default(), } @@ -165,8 +165,15 @@ impl SpaceViewBlueprint { let class_identifier: SpaceViewClassIdentifier = class_identifier.0.as_str().into(); let display_name = display_name.map(|v| v.0.to_string()); - let content = - SpaceViewContents::from_db_or_default(id, blueprint_db, query, class_identifier); + let space_env = EntityPathSubs::new_with_origin(&space_origin); + + let content = SpaceViewContents::from_db_or_default( + id, + blueprint_db, + query, + class_identifier, + &space_env, + ); let visible = visible.map_or(true, |v| v.0); Some(Self { @@ -460,7 +467,7 @@ mod tests { use re_entity_db::EntityDb; use re_log_types::{ example_components::{MyColor, MyLabel, MyPoint}, - DataCell, DataRow, EntityPathFilter, RowId, StoreId, StoreKind, TimePoint, + DataCell, DataRow, RowId, StoreId, StoreKind, TimePoint, }; use re_types::{archetypes::Points3D, ComponentBatch, ComponentName, Loggable as _}; use re_viewer_context::{ @@ -503,18 +510,13 @@ mod tests { recording.add_data_row(row).ok(); } - let space_view = SpaceViewBlueprint::new( - "3D".into(), - &EntityPath::root(), - EntityPathFilter::parse_forgiving( - r" - + parent - + parent/skip/child1 - + parent/skip/child2 - ", - ), + let recommended = RecommendedSpaceView::new( + EntityPath::root(), + ["+ parent", "+ parent/skip/child1", "+ parent/skip/child2"], ); + let space_view = SpaceViewBlueprint::new("3D".into(), recommended); + let auto_properties = Default::default(); let mut visualizable_entities = PerVisualizer::::default(); @@ -810,11 +812,7 @@ mod tests { } // Basic blueprint - a single space view that queries everything. - let space_view = SpaceViewBlueprint::new( - "3D".into(), - &EntityPath::root(), - EntityPathFilter::parse_forgiving("+ /**"), - ); + let space_view = SpaceViewBlueprint::new("3D".into(), RecommendedSpaceView::root()); let individual_override_root = space_view .contents .blueprint_entity_path diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index f885865edfa3..ab75c2ea9922 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -6,7 +6,9 @@ use re_entity_db::{ external::re_data_store::LatestAtQuery, EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, }; -use re_log_types::{path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule}; +use re_log_types::{ + path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule, EntityPathSubs, +}; use re_types::{ blueprint::{archetypes as blueprint_archetypes, components::QueryExpression}, Archetype as _, @@ -97,6 +99,7 @@ impl SpaceViewContents { blueprint_db: &EntityDb, query: &LatestAtQuery, space_view_class_identifier: SpaceViewClassIdentifier, + space_env: &EntityPathSubs, ) -> Self { let (contents, blueprint_entity_path) = query_space_view_sub_archetype::< blueprint_archetypes::SpaceViewContents, @@ -114,7 +117,7 @@ impl SpaceViewContents { let query = query.iter().map(|qe| qe.0.as_str()); - let entity_path_filter = EntityPathFilter::from_query_expressions(query); + let entity_path_filter = EntityPathFilter::from_query_expressions(query, space_env); Self { blueprint_entity_path, @@ -596,6 +599,8 @@ mod tests { #[test] fn test_query_results() { + let space_env = Default::default(); + let mut recording = EntityDb::new(StoreId::random(re_log_types::StoreKind::Recording)); let blueprint = EntityDb::new(StoreId::random(re_log_types::StoreKind::Blueprint)); @@ -729,7 +734,7 @@ mod tests { let contents = SpaceViewContents::new( SpaceViewId::random(), "3D".into(), - EntityPathFilter::parse_forgiving(filter), + EntityPathFilter::parse_forgiving(filter, &space_env), ); let query_result = diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index 5287d841bbcf..3141b66c504c 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -2,7 +2,7 @@ use ahash::HashSet; use nohash_hasher::{IntMap, IntSet}; use re_entity_db::{EntityDb, EntityProperties, EntityTree}; -use re_log_types::{EntityPath, EntityPathFilter}; +use re_log_types::EntityPath; use re_types::{ archetypes::{DepthImage, Image}, Archetype, ComponentName, @@ -387,10 +387,9 @@ fn recommended_space_views_with_image_splits( // If the root also had a visualizable entity, give it its own space. // TODO(jleibs): Maybe merge this entity into each child if entities.contains(recommended_root) { - recommended.push(RecommendedSpaceView { - root: recommended_root.clone(), - query_filter: EntityPathFilter::single_entity_filter(recommended_root), - }); + recommended.push(RecommendedSpaceView::new_single_entity( + recommended_root.clone(), + )); } // And then recurse into the children @@ -413,9 +412,6 @@ fn recommended_space_views_with_image_splits( } } else { // Otherwise we can use the space as it is - recommended.push(RecommendedSpaceView { - root: recommended_root.clone(), - query_filter: EntityPathFilter::subtree_entity_filter(recommended_root), - }); + recommended.push(RecommendedSpaceView::new_subtree(recommended_root.clone())); } } diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 91ca48b5d86d..19287fd40a20 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use nohash_hasher::IntSet; use re_entity_db::{EntityDb, EntityProperties}; -use re_log_types::{EntityPath, EntityPathFilter}; +use re_log_types::EntityPath; use re_space_view::query_space_view_sub_archetype; use re_types::{ blueprint::{archetypes::Background3D, components::Background3DKind}, @@ -220,7 +220,7 @@ impl SpaceViewClass for SpatialSpaceView3D { // // An exception to this rule is not to create a view there if this is already _also_ a subspace root. // (e.g. this also has a camera or a `disconnect` logged there) - let mut roots = subspace + let mut origins = subspace .heuristic_hints .iter() .filter(|(path, hint)| { @@ -232,18 +232,15 @@ impl SpaceViewClass for SpatialSpaceView3D { // If there's no view coordinates or there are still some entities not covered, // create a view at the subspace origin. - if !roots.iter().contains(&subspace.origin) + if !origins.iter().contains(&subspace.origin) && indicated_entities .intersection(&subspace.entities) - .any(|e| roots.iter().all(|root| !e.starts_with(root))) + .any(|e| origins.iter().all(|origin| !e.starts_with(origin))) { - roots.push(subspace.origin.clone()); + origins.push(subspace.origin.clone()); } - Some(roots.into_iter().map(|root| RecommendedSpaceView { - query_filter: EntityPathFilter::subtree_entity_filter(&root), - root, - })) + Some(origins.into_iter().map(RecommendedSpaceView::new_subtree)) } }) .flatten() diff --git a/crates/re_space_view_text_log/src/space_view_class.rs b/crates/re_space_view_text_log/src/space_view_class.rs index 57758d354d70..c4da833d154e 100644 --- a/crates/re_space_view_text_log/src/space_view_class.rs +++ b/crates/re_space_view_text_log/src/space_view_class.rs @@ -2,7 +2,7 @@ use re_entity_db::EntityProperties; use std::collections::BTreeMap; use re_data_ui::item_ui; -use re_log_types::{EntityPath, EntityPathFilter, TimePoint, Timeline}; +use re_log_types::{EntityPath, TimePoint, Timeline}; use re_types::components::TextLogLevel; use re_viewer_context::{ level_to_rich_text, IdentifiedViewSystem as _, RecommendedSpaceView, SpaceViewClass, @@ -91,10 +91,7 @@ impl SpaceViewClass for TextSpaceView { SpaceViewSpawnHeuristics::default() } else { SpaceViewSpawnHeuristics { - recommended_space_views: vec![RecommendedSpaceView { - root: EntityPath::root(), - query_filter: EntityPathFilter::subtree_entity_filter(&EntityPath::root()), - }], + recommended_space_views: vec![RecommendedSpaceView::root()], } } } diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index bd45d955f9ae..1b76b4a2f2fc 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -4,7 +4,7 @@ use egui_plot::{Legend, Line, Plot, PlotPoint, Points}; use re_data_store::TimeType; use re_format::next_grid_tick_magnitude_ns; -use re_log_types::{EntityPath, EntityPathFilter, TimeZone}; +use re_log_types::{EntityPath, TimeZone}; use re_space_view::{controls, query_space_view_sub_archetype_or_default}; use re_types::blueprint::components::Corner2D; use re_types::components::Range1D; @@ -223,10 +223,7 @@ It can greatly improve performance (and readability) in such situations as it pr .any(|(_, subtree)| indicated_entities.contains(&subtree.path)) { return SpaceViewSpawnHeuristics { - recommended_space_views: vec![RecommendedSpaceView { - root: EntityPath::root(), - query_filter: EntityPathFilter::subtree_entity_filter(&EntityPath::root()), - }], + recommended_space_views: vec![RecommendedSpaceView::root()], }; } @@ -242,10 +239,7 @@ It can greatly improve performance (and readability) in such situations as it pr .into_iter() .map(|path_part| { let entity = EntityPath::new(vec![path_part.clone()]); - RecommendedSpaceView { - query_filter: EntityPathFilter::subtree_entity_filter(&entity), - root: entity, - } + RecommendedSpaceView::new_subtree(entity) }) .collect(); diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 8151e04222bd..7368804694ba 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -1058,7 +1058,7 @@ The last rule matching `/world/house` is `+ /world/**`, so it is included. } // Apply the edit. - let new_filter = EntityPathFilter::parse_forgiving(&filter_string); + let new_filter = EntityPathFilter::parse_forgiving(&filter_string, &Default::default()); if &new_filter == filter { None // no change } else { diff --git a/crates/re_viewer_context/src/space_view/spawn_heuristics.rs b/crates/re_viewer_context/src/space_view/spawn_heuristics.rs index 628987c1603f..6d5e3302d0ea 100644 --- a/crates/re_viewer_context/src/space_view/spawn_heuristics.rs +++ b/crates/re_viewer_context/src/space_view/spawn_heuristics.rs @@ -1,9 +1,9 @@ -use re_log_types::{EntityPath, EntityPathFilter}; +use re_log_types::{EntityPath, EntityPathFilter, EntityPathSubs}; /// Properties of a space view that as recommended to be spawned by default via space view spawn heuristics. -#[derive(Hash, Debug)] +#[derive(Hash, Debug, Clone)] pub struct RecommendedSpaceView { - pub root: EntityPath, + pub origin: EntityPath, pub query_filter: EntityPathFilter, } @@ -17,3 +17,29 @@ pub struct SpaceViewSpawnHeuristics { /// The recommended space views to spawn pub recommended_space_views: Vec, } + +impl RecommendedSpaceView { + #[inline] + pub fn new<'a>(origin: EntityPath, expressions: impl IntoIterator) -> Self { + let space_env = EntityPathSubs::new_with_origin(&origin); + Self { + origin, + query_filter: EntityPathFilter::from_query_expressions(expressions, &space_env), + } + } + + #[inline] + pub fn new_subtree(origin: EntityPath) -> Self { + Self::new(origin, std::iter::once("$origin/**")) + } + + #[inline] + pub fn new_single_entity(origin: EntityPath) -> Self { + Self::new(origin, std::iter::once("$origin")) + } + + #[inline] + pub fn root() -> Self { + Self::new_subtree(EntityPath::root()) + } +} diff --git a/crates/re_viewport/src/add_space_view_or_container_modal.rs b/crates/re_viewport/src/add_space_view_or_container_modal.rs index c47135041530..cfda7c7f900d 100644 --- a/crates/re_viewport/src/add_space_view_or_container_modal.rs +++ b/crates/re_viewport/src/add_space_view_or_container_modal.rs @@ -4,10 +4,9 @@ use itertools::Itertools; use crate::container::blueprint_id_to_tile_id; use crate::{icon_for_container_kind, ViewportBlueprint}; -use re_log_types::EntityPath; use re_space_view::SpaceViewBlueprint; use re_ui::ReUi; -use re_viewer_context::{ContainerId, ViewerContext}; +use re_viewer_context::{ContainerId, RecommendedSpaceView, ViewerContext}; #[derive(Default)] pub struct AddSpaceViewOrContainerModal { @@ -112,9 +111,7 @@ fn modal_ui( .space_view_class_registry .iter_registry() .sorted_by_key(|entry| entry.class.display_name()) - .map(|entry| { - SpaceViewBlueprint::new(entry.identifier, &EntityPath::root(), Default::default()) - }) + .map(|entry| SpaceViewBlueprint::new(entry.identifier, RecommendedSpaceView::root())) { let icon = space_view.class(ctx.space_view_class_registry).icon(); let title = space_view diff --git a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs index 9d3d386f68e7..0378902a6296 100644 --- a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs +++ b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs @@ -4,7 +4,7 @@ use nohash_hasher::IntSet; use re_log_types::{EntityPath, EntityPathFilter, EntityPathRule, RuleEffect}; use re_space_view::{determine_visualizable_entities, SpaceViewBlueprint}; -use re_viewer_context::{Item, SpaceViewClassIdentifier}; +use re_viewer_context::{Item, RecommendedSpaceView, SpaceViewClassIdentifier}; use crate::context_menu::{ContextMenuAction, ContextMenuContext}; @@ -149,15 +149,22 @@ fn create_space_view_for_selected_entities( let mut filter = EntityPathFilter::default(); - for path in entities_of_interest { - filter.add_rule(RuleEffect::Include, EntityPathRule::including_subtree(path)); - } - let target_container_id = ctx .clicked_item_enclosing_container_id_and_position() .map(|(id, _)| id); - let space_view = SpaceViewBlueprint::new(identifier, &origin, filter); + // Note that these entity paths will always be absolute, rather than + // relative to the origin. This makes sense since if you create a view and + // then change the origin you likely wanted those entities to still be there. + for path in entities_of_interest { + filter.add_rule(RuleEffect::Include, EntityPathRule::including_subtree(path)); + } + let recommended = RecommendedSpaceView { + origin, + query_filter: filter, + }; + + let space_view = SpaceViewBlueprint::new(identifier, recommended); let new_space_view = ctx.viewport_blueprint.add_space_views( std::iter::once(space_view), diff --git a/crates/re_viewport/src/context_menu/actions/add_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_space_view.rs index 03e548967420..51b8da5ff5c1 100644 --- a/crates/re_viewport/src/context_menu/actions/add_space_view.rs +++ b/crates/re_viewport/src/context_menu/actions/add_space_view.rs @@ -1,6 +1,5 @@ -use re_log_types::{EntityPath, EntityPathFilter}; use re_space_view::SpaceViewBlueprint; -use re_viewer_context::{ContainerId, Item, SpaceViewClassIdentifier}; +use re_viewer_context::{ContainerId, Item, RecommendedSpaceView, SpaceViewClassIdentifier}; use crate::context_menu::{ContextMenuAction, ContextMenuContext}; @@ -21,8 +20,7 @@ impl ContextMenuAction for AddSpaceViewAction { } fn process_container(&self, ctx: &ContextMenuContext<'_>, container_id: &ContainerId) { - let space_view = - SpaceViewBlueprint::new(self.0, &EntityPath::root(), EntityPathFilter::default()); + let space_view = SpaceViewBlueprint::new(self.0, RecommendedSpaceView::root()); ctx.viewport_blueprint.add_space_views( std::iter::once(space_view), diff --git a/crates/re_viewport/src/space_view_heuristics.rs b/crates/re_viewport/src/space_view_heuristics.rs index 592c0109b7e5..c6f74bf3c0a6 100644 --- a/crates/re_viewport/src/space_view_heuristics.rs +++ b/crates/re_viewport/src/space_view_heuristics.rs @@ -16,13 +16,7 @@ pub fn default_created_space_views(ctx: &ViewerContext<'_>) -> Vec None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_plot") + blueprint = rrb.Blueprint( + rrb.Horizontal( + rrb.Grid( + rrb.BarChartView(name="Bar Chart", origin="/bar_chart"), + rrb.TimeSeriesView(name="Curves", origin="/curves"), + rrb.TimeSeriesView(name="Trig", origin="/trig"), + rrb.TimeSeriesView(name="Classification", origin="/classification"), + ), + rrb.TextDocumentView(name="Description", origin="/description"), + column_shares=[2, 1], + ), + rrb.SelectionPanel(expanded=False), + rrb.TimePanel(expanded=False), + ) + + rr.script_setup(args, "rerun_example_plot", blueprint=blueprint) rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) log_bar_chart() diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index 4d44316603a2..c1151493a22c 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -2,7 +2,7 @@ use re_viewer::external::{ egui, re_data_ui::{item_ui, DataUi}, re_entity_db::{EntityProperties, InstancePath}, - re_log_types::{EntityPath, EntityPathFilter}, + re_log_types::EntityPath, re_ui, re_viewer_context::{ HoverHighlight, IdentifiedViewSystem as _, Item, RecommendedSpaceView, SelectionHighlight, @@ -115,10 +115,7 @@ impl SpaceViewClass for ColorCoordinatesSpaceView { SpaceViewSpawnHeuristics::default() } else { SpaceViewSpawnHeuristics { - recommended_space_views: vec![RecommendedSpaceView { - root: EntityPath::root(), - query_filter: EntityPathFilter::subtree_entity_filter(&EntityPath::root()), - }], + recommended_space_views: vec![RecommendedSpaceView::root()], } } } diff --git a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py index 80df3a462adf..c9d127d5947b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py @@ -8,7 +8,11 @@ class BarChartView(SpaceView): """A bar chart view.""" def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, ): """ Construct a blueprint for a new bar chart view. @@ -33,7 +37,11 @@ class Spatial2DView(SpaceView): """A Spatial 2D view.""" def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, ): """ Construct a blueprint for a new spatial 2D view. @@ -58,7 +66,11 @@ class Spatial3DView(SpaceView): """A Spatial 3D view.""" def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, ): """ Construct a blueprint for a new spatial 3D view. @@ -83,7 +95,11 @@ class TensorView(SpaceView): """A tensor view.""" def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, ): """ Construct a blueprint for a new tensor view. @@ -108,7 +124,11 @@ class TextDocumentView(SpaceView): """A text document view.""" def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, ): """ Construct a blueprint for a new text document view. @@ -133,7 +153,11 @@ class TextLogView(SpaceView): """A text log view.""" def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, ): """ Construct a blueprint for a new text log view. @@ -158,7 +182,11 @@ class TimeSeriesView(SpaceView): """A time series view.""" def __init__( - self, *, origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "/**", name: Utf8Like | None = None + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, ): """ Construct a blueprint for a new time series view. From dab0322e98e570d5d673109e1922da8895109e9e Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 15 Mar 2024 12:30:20 -0400 Subject: [PATCH 038/508] Switch the blueprint timeline from seconds to sequence (#5539) ### What - Resolves: https://github.com/rerun-io/rerun/issues/5222 Confirmed working in blueprint inspector: ![image](https://github.com/rerun-io/rerun/assets/3312232/0f0a1a73-5f89-4f3d-859a-4263ba7f3ed8) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5539/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5539/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5539/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5539) - [Docs preview](https://rerun.io/preview/53c919201d689b77aac31aa8a226f0422262ea66/docs) - [Examples preview](https://rerun.io/preview/53c919201d689b77aac31aa8a226f0422262ea66/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view/src/space_view.rs | 14 ++++---- crates/re_viewer/src/app_blueprint.rs | 14 ++++---- crates/re_viewer/src/ui/override_ui.rs | 6 ++-- .../src/blueprint_helpers.rs | 33 +++++++++++++------ crates/re_viewer_context/src/lib.rs | 2 +- crates/re_viewport/src/container.rs | 6 ++-- crates/re_viewport/src/viewport_blueprint.rs | 2 +- rerun_py/rerun_sdk/rerun/blueprint/api.py | 3 +- 8 files changed, 45 insertions(+), 35 deletions(-) diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 18d39498c7c8..02804b85b60b 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -14,10 +14,9 @@ use re_types::{ use re_types_core::archetypes::Clear; use re_types_core::Archetype as _; use re_viewer_context::{ - blueprint_timepoint_for_writes, DataResult, PerSystemEntities, PropertyOverrides, - RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, - StoreContext, SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, - ViewerContext, + DataResult, PerSystemEntities, PropertyOverrides, RecommendedSpaceView, SpaceViewClass, + SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, SystemCommand, + SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, }; // ---------------------------------------------------------------------------- @@ -194,7 +193,7 @@ impl SpaceViewBlueprint { /// Otherwise, incremental calls to `set_` functions will write just the necessary component /// update directly to the store. pub fn save_to_blueprint_store(&self, ctx: &ViewerContext<'_>) { - let timepoint = blueprint_timepoint_for_writes(); + let timepoint = ctx.store_context.blueprint_timepoint_for_writes(); let Self { id, @@ -237,8 +236,9 @@ impl SpaceViewBlueprint { /// Creates a new [`SpaceViewBlueprint`] with the same contents, but a different [`SpaceViewId`] /// /// Also duplicates all the queries in the space view. - pub fn duplicate(&self, blueprint: &EntityDb, query: &LatestAtQuery) -> Self { + pub fn duplicate(&self, store_context: &StoreContext<'_>, query: &LatestAtQuery) -> Self { let mut pending_writes = Vec::new(); + let blueprint = store_context.blueprint; let current_path = self.entity_path(); let new_id = SpaceViewId::random(); @@ -256,7 +256,7 @@ impl SpaceViewBlueprint { if let Ok(row) = DataRow::from_cells( RowId::new(), - blueprint_timepoint_for_writes(), + store_context.blueprint_timepoint_for_writes(), sub_path, 1, info.components diff --git a/crates/re_viewer/src/app_blueprint.rs b/crates/re_viewer/src/app_blueprint.rs index 395bcad6acbb..949532cbd46d 100644 --- a/crates/re_viewer/src/app_blueprint.rs +++ b/crates/re_viewer/src/app_blueprint.rs @@ -2,9 +2,7 @@ use re_data_store::LatestAtQuery; use re_entity_db::EntityDb; use re_log_types::{DataRow, EntityPath, RowId, TimePoint}; use re_types::blueprint::components::PanelExpanded; -use re_viewer_context::{ - blueprint_timepoint_for_writes, CommandSender, StoreContext, SystemCommand, SystemCommandSender, -}; +use re_viewer_context::{CommandSender, StoreContext, SystemCommand, SystemCommandSender}; pub const BLUEPRINT_PANEL_PATH: &str = "blueprint_panel"; pub const SELECTION_PANEL_PATH: &str = "selection_panel"; @@ -12,7 +10,7 @@ pub const TIME_PANEL_PATH: &str = "time_panel"; /// Blueprint for top-level application pub struct AppBlueprint<'a> { - blueprint_db: Option<&'a EntityDb>, + store_ctx: Option<&'a StoreContext<'a>>, is_narrow_screen: bool, pub blueprint_panel_expanded: bool, pub selection_panel_expanded: bool, @@ -28,7 +26,7 @@ impl<'a> AppBlueprint<'a> { let blueprint_db = store_ctx.map(|ctx| ctx.blueprint); let screen_size = egui_ctx.screen_rect().size(); let mut ret = Self { - blueprint_db, + store_ctx, is_narrow_screen: screen_size.x < 600.0, blueprint_panel_expanded: screen_size.x > 750.0, selection_panel_expanded: screen_size.x > 1000.0, @@ -111,10 +109,10 @@ impl<'a> AppBlueprint<'a> { is_expanded: bool, command_sender: &CommandSender, ) { - if let Some(blueprint_db) = self.blueprint_db { + if let Some(store_ctx) = self.store_ctx { let entity_path = EntityPath::from(panel_name); - let timepoint = blueprint_timepoint_for_writes(); + let timepoint = store_ctx.blueprint_timepoint_for_writes(); let component = PanelExpanded(is_expanded.into()); @@ -123,7 +121,7 @@ impl<'a> AppBlueprint<'a> { .unwrap(); // Can only fail if we have the wrong number of instances for the component, and we don't command_sender.send_system(SystemCommand::UpdateBlueprint( - blueprint_db.store_id().clone(), + store_ctx.blueprint.store_id().clone(), vec![row], )); } diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index ff055faf55b4..41c110c9d858 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -13,8 +13,8 @@ use re_types_core::{ ComponentName, }; use re_viewer_context::{ - blueprint_timepoint_for_writes, DataResult, OverridePath, SystemCommand, - SystemCommandSender as _, UiVerbosity, ViewSystemIdentifier, ViewerContext, + DataResult, OverridePath, SystemCommand, SystemCommandSender as _, UiVerbosity, + ViewSystemIdentifier, ViewerContext, }; pub fn override_ui( @@ -267,7 +267,7 @@ pub fn add_new_override( match DataRow::from_cells( RowId::new(), - blueprint_timepoint_for_writes(), + ctx.store_context.blueprint_timepoint_for_writes(), override_path.clone(), 1, [splat_cell, initial_data], diff --git a/crates/re_viewer_context/src/blueprint_helpers.rs b/crates/re_viewer_context/src/blueprint_helpers.rs index a23caa52f9d4..e818b0e0ae95 100644 --- a/crates/re_viewer_context/src/blueprint_helpers.rs +++ b/crates/re_viewer_context/src/blueprint_helpers.rs @@ -1,22 +1,35 @@ -use re_log_types::{DataCell, DataRow, EntityPath, RowId, Time, TimePoint, Timeline}; +use re_log_types::{DataCell, DataRow, EntityPath, RowId, TimePoint, Timeline}; use re_types::{components::InstanceKey, AsComponents, ComponentBatch, ComponentName}; -use crate::{SystemCommand, SystemCommandSender as _, ViewerContext}; +use crate::{StoreContext, SystemCommand, SystemCommandSender as _, ViewerContext}; #[inline] pub fn blueprint_timeline() -> Timeline { - Timeline::new_temporal("blueprint") + Timeline::new_sequence("blueprint") } -/// The timepoint to use when writing an update to the blueprint. -#[inline] -pub fn blueprint_timepoint_for_writes() -> TimePoint { - TimePoint::from([(blueprint_timeline(), Time::now().into())]) +impl StoreContext<'_> { + /// The timepoint to use when writing an update to the blueprint. + #[inline] + pub fn blueprint_timepoint_for_writes(&self) -> TimePoint { + let timeline = blueprint_timeline(); + + let mut max_time = self + .blueprint + .times_per_timeline() + .get(&timeline) + .and_then(|times| times.last_key_value()) + .map_or(0.into(), |(time, _)| *time); + + max_time += 1.into(); + + TimePoint::from([(timeline, max_time)]) + } } impl ViewerContext<'_> { pub fn save_blueprint_archetype(&self, entity_path: EntityPath, components: &dyn AsComponents) { - let timepoint = blueprint_timepoint_for_writes(); + let timepoint = self.store_context.blueprint_timepoint_for_writes(); let data_row = match DataRow::from_archetype(RowId::new(), timepoint.clone(), entity_path, components) @@ -57,7 +70,7 @@ impl ViewerContext<'_> { data_cell.compute_size_bytes(); let num_instances = components.num_instances() as u32; - let timepoint = blueprint_timepoint_for_writes(); + let timepoint = self.store_context.blueprint_timepoint_for_writes(); re_log::trace!( "Writing {} components of type {:?} to {:?}", @@ -124,7 +137,7 @@ impl ViewerContext<'_> { return; }; - let timepoint = blueprint_timepoint_for_writes(); + let timepoint = self.store_context.blueprint_timepoint_for_writes(); let cell = DataCell::from_arrow_empty(component_name, datatype.clone()); match DataRow::from_cells1( diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index a4f40d6ea3f7..44d4b95371ec 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -29,7 +29,7 @@ pub use annotations::{ AnnotationMap, Annotations, ResolvedAnnotationInfo, ResolvedAnnotationInfos, }; pub use app_options::AppOptions; -pub use blueprint_helpers::{blueprint_timeline, blueprint_timepoint_for_writes}; +pub use blueprint_helpers::blueprint_timeline; pub use blueprint_id::{BlueprintId, BlueprintIdRegistry, ContainerId, SpaceViewId}; pub use caches::{Cache, Caches}; pub use collapsed_id::{CollapseItem, CollapseScope, CollapsedId}; diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index dff9e5dd92d3..7e5d3f2d287c 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -9,8 +9,8 @@ use re_query::query_archetype; use re_types::blueprint::components::Visible; use re_types_core::archetypes::Clear; use re_viewer_context::{ - blueprint_timepoint_for_writes, BlueprintId, BlueprintIdRegistry, ContainerId, Item, - SpaceViewId, SystemCommand, SystemCommandSender as _, ViewerContext, + BlueprintId, BlueprintIdRegistry, ContainerId, Item, SpaceViewId, SystemCommand, + SystemCommandSender as _, ViewerContext, }; use crate::blueprint::components::GridColumns; @@ -218,7 +218,7 @@ impl ContainerBlueprint { /// Otherwise, incremental calls to `set_` functions will write just the necessary component /// update directly to the store. pub fn save_to_blueprint_store(&self, ctx: &ViewerContext<'_>) { - let timepoint = blueprint_timepoint_for_writes(); + let timepoint = ctx.store_context.blueprint_timepoint_for_writes(); let Self { id, diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index fdcfa3ec2320..fda7eccd491b 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -237,7 +237,7 @@ impl ViewportBlueprint { ) -> Option { let space_view = self.space_view(space_view_id)?; - let new_space_view = space_view.duplicate(ctx.store_context.blueprint, ctx.blueprint_query); + let new_space_view = space_view.duplicate(ctx.store_context, ctx.blueprint_query); let new_space_view_id = new_space_view.id; let parent_and_pos = diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 3b5696df18b6..b106feb23f3d 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -456,8 +456,7 @@ def create_in_memory_blueprint(*, application_id: str, blueprint: BlueprintLike) ) ) - # TODO(jleibs): This should use a monotonic seq - blueprint_stream.set_time_seconds("blueprint", 1) # type: ignore[attr-defined] + blueprint_stream.set_time_sequence("blueprint", 0) # type: ignore[attr-defined] blueprint._log_to_stream(blueprint_stream) From 4982c01087fd3af57e6d141b979a8c4cff61a772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Sun, 17 Mar 2024 19:48:36 +0100 Subject: [PATCH 039/508] Docs inline viewer infrastructure (#5438) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Snippets™️ (formerly known as "code examples" or "doc examples") are now built on CI together with Examples™️, and uploaded to the same place. Also includes some changes to example screenshots (adding `data-inline-viewer` attributes), and updating the egui rev to fix a bug - Blocked by https://github.com/emilk/egui/pull/4169 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5438/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5438/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5438/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5438) - [Docs preview](https://rerun.io/preview/27f898acc6efda581ce2a4f540f73dc68ef50578/docs) - [Examples preview](https://rerun.io/preview/27f898acc6efda581ce2a4f540f73dc68ef50578/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/actions/deploy-vercel/action.yml | 4 + .github/actions/deploy-vercel/index.mjs | 26 ++- .github/workflows/contrib_rerun_py.yml | 4 +- .github/workflows/reusable_build_examples.yml | 6 + .github/workflows/reusable_deploy_docs.yml | 1 + .github/workflows/reusable_test_wheels.yml | 4 +- CMakeLists.txt | 2 +- Cargo.lock | 44 ++--- Cargo.toml | 16 +- crates/re_build_examples/src/lib.rs | 37 ++++ crates/re_build_examples/src/main.rs | 2 + crates/re_build_examples/src/rrd.rs | 41 +--- crates/re_build_examples/src/snippets.rs | 182 ++++++++++++++++++ crates/re_types/src/lib.rs | 2 +- .../src/bin/build_re_types.rs | 4 +- crates/re_types_builder/src/codegen/common.rs | 8 +- .../re_types_builder/src/codegen/cpp/mod.rs | 4 +- .../re_types_builder/src/codegen/docs/mod.rs | 2 +- .../src/codegen/python/mod.rs | 6 +- .../re_types_builder/src/codegen/rust/api.rs | 4 +- crates/re_types_builder/src/lib.rs | 9 +- .../quick_start_connect.cpp | 2 +- .../quick_start_guides/quick_start_connect.py | 2 +- .../quick_start_guides/quick_start_connect.rs | 2 +- .../quick_start_guides/quick_start_spawn.cpp | 18 +- .../quick_start_guides/quick_start_spawn.py | 2 +- .../quick_start_guides/quick_start_spawn.rs | 2 +- .../src/ui/welcome_screen/welcome_section.rs | 24 +-- docs/README.md | 41 ++-- docs/code-examples/src/lib.rs | 5 - docs/code-examples/src/main.rs | 6 - docs/content/concepts/annotation-context.md | 2 +- docs/content/concepts/entity-component.md | 6 +- docs/content/concepts/timelines.md | 2 +- docs/content/howto/extend/custom-data.md | 2 +- docs/content/howto/open-any-file.md | 2 +- docs/content/howto/shared-recordings.md | 2 +- docs/content/howto/using-native-loggers.md | 2 +- .../reference/migration/migration-0-9.md | 2 +- .../content/reference/sdk-logging-controls.md | 2 +- .../types/archetypes/annotation_context.md | 6 +- .../reference/types/archetypes/arrows2d.md | 2 +- .../reference/types/archetypes/arrows3d.md | 2 +- .../reference/types/archetypes/asset3d.md | 4 +- .../reference/types/archetypes/bar_chart.md | 2 +- .../reference/types/archetypes/boxes2d.md | 2 +- .../reference/types/archetypes/boxes3d.md | 4 +- .../reference/types/archetypes/clear.md | 4 +- .../reference/types/archetypes/depth_image.md | 4 +- .../types/archetypes/disconnected_space.md | 2 +- .../reference/types/archetypes/image.md | 2 +- .../types/archetypes/line_strips2d.md | 6 +- .../types/archetypes/line_strips3d.md | 6 +- .../reference/types/archetypes/mesh3d.md | 4 +- .../reference/types/archetypes/pinhole.md | 4 +- .../reference/types/archetypes/points2d.md | 4 +- .../reference/types/archetypes/points3d.md | 4 +- .../reference/types/archetypes/scalar.md | 4 +- .../types/archetypes/segmentation_image.md | 2 +- .../reference/types/archetypes/series_line.md | 2 +- .../types/archetypes/series_point.md | 2 +- .../reference/types/archetypes/tensor.md | 2 +- .../types/archetypes/text_document.md | 2 +- .../reference/types/archetypes/text_log.md | 2 +- .../types/archetypes/time_series_scalar.md | 4 +- .../reference/types/archetypes/transform3d.md | 2 +- .../types/archetypes/view_coordinates.md | 2 +- .../CMakeLists.txt | 4 +- docs/{code-examples => snippets}/Cargo.toml | 2 +- docs/{code-examples => snippets}/README.md | 12 +- .../all/annotation-context/example.py | 0 .../all/annotation-context/example.rs | 0 .../all/annotation_context_connections.cpp | 0 .../all/annotation_context_connections.py | 0 .../all/annotation_context_connections.rs | 0 .../all/annotation_context_rects.cpp | 0 .../all/annotation_context_rects.py | 0 .../all/annotation_context_rects.rs | 0 .../all/annotation_context_segmentation.cpp | 0 .../all/annotation_context_segmentation.py | 0 .../all/annotation_context_segmentation.rs | 0 .../all/any_values.py | 0 .../all/arrow2d_simple.cpp | 0 .../all/arrow2d_simple.py | 0 .../all/arrow2d_simple.rs | 0 .../all/arrow3d_simple.cpp | 0 .../all/arrow3d_simple.py | 0 .../all/arrow3d_simple.rs | 0 .../all/asset3d_out_of_tree.cpp | 0 .../all/asset3d_out_of_tree.py | 0 .../all/asset3d_out_of_tree.rs | 0 .../all/asset3d_simple.cpp | 0 .../all/asset3d_simple.py | 0 .../all/asset3d_simple.rs | 0 .../all/bar_chart.cpp | 0 .../all/bar_chart.py | 0 .../all/bar_chart.rs | 0 .../all/box2d_simple.cpp | 0 .../all/box2d_simple.py | 0 .../all/box2d_simple.rs | 0 .../all/box3d_batch.cpp | 0 .../all/box3d_batch.py | 0 .../all/box3d_batch.rs | 0 .../all/box3d_simple.cpp | 0 .../all/box3d_simple.py | 0 .../all/box3d_simple.rs | 0 .../all/clear_recursive.cpp | 0 .../all/clear_recursive.py | 0 .../all/clear_recursive.rs | 0 .../all/clear_simple.cpp | 0 .../all/clear_simple.py | 0 .../all/clear_simple.rs | 0 .../all/custom-recording-id/example.cpp | 0 .../all/custom-recording-id/example.py | 0 .../all/custom-recording-id/example.rs | 0 .../all/custom_data.cpp | 0 .../all/custom_data.py | 0 .../all/custom_data.rs | 0 .../all/default-off-session/example.py | 0 .../all/default-off-session/example.rs | 0 .../all/depth_image_3d.cpp | 0 .../all/depth_image_3d.py | 0 .../all/depth_image_3d.rs | 0 .../all/depth_image_simple.cpp | 0 .../all/depth_image_simple.py | 0 .../all/depth_image_simple.rs | 0 .../all/disconnected_space.cpp | 0 .../all/disconnected_space.py | 0 .../all/disconnected_space.rs | 0 .../all/entity_path.cpp | 0 .../all/entity_path.py | 0 .../all/entity_path.rs | 0 .../all/extra_values.py | 0 .../all/image_advanced.py | 0 .../all/image_simple.cpp | 0 .../all/image_simple.py | 0 .../all/image_simple.rs | 0 .../all/line_segments2d_simple.cpp | 0 .../all/line_segments2d_simple.py | 0 .../all/line_segments2d_simple.rs | 0 .../all/line_segments3d_simple.cpp | 0 .../all/line_segments3d_simple.py | 0 .../all/line_segments3d_simple.rs | 0 .../all/line_strip2d_batch.cpp | 0 .../all/line_strip2d_batch.py | 0 .../all/line_strip2d_batch.rs | 0 .../all/line_strip2d_simple.cpp | 0 .../all/line_strip2d_simple.py | 0 .../all/line_strip2d_simple.rs | 0 .../all/line_strip3d_batch.cpp | 0 .../all/line_strip3d_batch.py | 0 .../all/line_strip3d_batch.rs | 0 .../all/line_strip3d_simple.cpp | 0 .../all/line_strip3d_simple.py | 0 .../all/line_strip3d_simple.rs | 0 .../all/log-file/example.cpp | 0 .../all/log-file/example.py | 0 .../all/log-file/example.rs | 0 .../all/log_line.py | 0 .../all/log_line.rs | 0 .../all/manual_indicator.cpp | 0 .../all/manual_indicator.py | 0 .../all/manual_indicator.rs | 0 .../all/mesh3d_indexed.cpp | 0 .../all/mesh3d_indexed.py | 0 .../all/mesh3d_indexed.rs | 0 .../all/mesh3d_partial_updates.cpp | 0 .../all/mesh3d_partial_updates.py | 0 .../all/mesh3d_partial_updates.rs | 0 .../all/mesh3d_simple.cpp | 0 .../all/mesh3d_simple.py | 0 .../all/mesh3d_simple.rs | 0 .../all/pinhole_perspective.cpp | 0 .../all/pinhole_perspective.py | 0 .../all/pinhole_perspective.rs | 0 .../all/pinhole_simple.cpp | 0 .../all/pinhole_simple.py | 0 .../all/pinhole_simple.rs | 0 .../all/point2d_random.cpp | 0 .../all/point2d_random.py | 0 .../all/point2d_random.rs | 0 .../all/point2d_simple.cpp | 0 .../all/point2d_simple.py | 0 .../all/point2d_simple.rs | 0 .../all/point3d_random.cpp | 0 .../all/point3d_random.py | 0 .../all/point3d_random.rs | 0 .../all/point3d_simple.cpp | 0 .../all/point3d_simple.py | 0 .../all/point3d_simple.rs | 0 .../all/quick_start_connect.cpp | 0 .../all/quick_start_connect.py | 0 .../all/quick_start_connect.rs | 0 .../all/quick_start_spawn.cpp | 0 .../all/quick_start_spawn.py | 0 .../all/quick_start_spawn.rs | 0 .../all/scalar_multiple_plots.cpp | 0 .../all/scalar_multiple_plots.py | 0 .../all/scalar_multiple_plots.rs | 0 .../all/scalar_simple.cpp | 0 .../all/scalar_simple.py | 0 .../all/scalar_simple.rs | 0 .../all/segmentation_image_simple.cpp | 0 .../all/segmentation_image_simple.py | 0 .../all/segmentation_image_simple.rs | 0 .../all/series_line_style.cpp | 0 .../all/series_line_style.py | 0 .../all/series_line_style.rs | 0 .../all/series_point_style.cpp | 0 .../all/series_point_style.py | 0 .../all/series_point_style.rs | 0 .../all/tensor_simple.cpp | 0 .../all/tensor_simple.py | 0 .../all/tensor_simple.rs | 0 .../all/text_document.cpp | 0 .../all/text_document.py | 0 .../all/text_document.rs | 0 .../all/text_log.cpp | 0 .../all/text_log.py | 0 .../all/text_log.rs | 0 .../all/text_log_integration.cpp | 0 .../all/text_log_integration.py | 0 .../all/text_log_integration.rs | 0 .../all/timelines_example.cpp | 0 .../all/timelines_example.py | 0 .../all/timelines_example.rs | 0 .../all/transform3d_simple.cpp | 0 .../all/transform3d_simple.py | 0 .../all/transform3d_simple.rs | 0 .../all/view_coordinates_simple.cpp | 0 .../all/view_coordinates_simple.py | 0 .../all/view_coordinates_simple.rs | 0 docs/{code-examples => snippets}/build.rs | 2 +- .../compare_snippet_output.py} | 85 +++----- docs/snippets/snippets.toml | 90 +++++++++ .../src/examples/.gitignore | 0 docs/snippets/src/lib.rs | 5 + docs/snippets/src/main.rs | 6 + examples/python/arkit_scenes/README.md | 2 +- .../depth_guided_stable_diffusion/README.md | 2 +- .../python/detect_and_track_objects/README.md | 2 +- examples/python/dicom_mri/README.md | 2 +- examples/python/dna/README.md | 3 +- examples/python/human_pose_tracking/README.md | 2 +- examples/python/incremental_logging/README.md | 2 +- examples/python/nuscenes/README.md | 2 +- .../open_photogrammetry_format/README.md | 2 +- examples/python/plots/README.md | 2 +- examples/python/raw_mesh/README.md | 2 +- examples/python/rgbd/README.md | 2 +- .../python/segment_anything_model/README.md | 2 +- .../python/structure_from_motion/README.md | 2 +- justfile | 8 +- noxfile.py | 2 +- pixi.toml | 2 +- rerun_py/pyproject.toml | 6 +- .../build_screenshot_compare.py | 41 ++-- 257 files changed, 589 insertions(+), 325 deletions(-) create mode 100644 crates/re_build_examples/src/snippets.rs mode change 100644 => 120000 crates/re_viewer/data/quick_start_guides/quick_start_spawn.cpp delete mode 100644 docs/code-examples/src/lib.rs delete mode 100644 docs/code-examples/src/main.rs rename docs/{code-examples => snippets}/CMakeLists.txt (91%) rename docs/{code-examples => snippets}/Cargo.toml (94%) rename docs/{code-examples => snippets}/README.md (62%) rename docs/{code-examples => snippets}/all/annotation-context/example.py (100%) rename docs/{code-examples => snippets}/all/annotation-context/example.rs (100%) rename docs/{code-examples => snippets}/all/annotation_context_connections.cpp (100%) rename docs/{code-examples => snippets}/all/annotation_context_connections.py (100%) rename docs/{code-examples => snippets}/all/annotation_context_connections.rs (100%) rename docs/{code-examples => snippets}/all/annotation_context_rects.cpp (100%) rename docs/{code-examples => snippets}/all/annotation_context_rects.py (100%) rename docs/{code-examples => snippets}/all/annotation_context_rects.rs (100%) rename docs/{code-examples => snippets}/all/annotation_context_segmentation.cpp (100%) rename docs/{code-examples => snippets}/all/annotation_context_segmentation.py (100%) rename docs/{code-examples => snippets}/all/annotation_context_segmentation.rs (100%) rename docs/{code-examples => snippets}/all/any_values.py (100%) rename docs/{code-examples => snippets}/all/arrow2d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/arrow2d_simple.py (100%) rename docs/{code-examples => snippets}/all/arrow2d_simple.rs (100%) rename docs/{code-examples => snippets}/all/arrow3d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/arrow3d_simple.py (100%) rename docs/{code-examples => snippets}/all/arrow3d_simple.rs (100%) rename docs/{code-examples => snippets}/all/asset3d_out_of_tree.cpp (100%) rename docs/{code-examples => snippets}/all/asset3d_out_of_tree.py (100%) rename docs/{code-examples => snippets}/all/asset3d_out_of_tree.rs (100%) rename docs/{code-examples => snippets}/all/asset3d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/asset3d_simple.py (100%) rename docs/{code-examples => snippets}/all/asset3d_simple.rs (100%) rename docs/{code-examples => snippets}/all/bar_chart.cpp (100%) rename docs/{code-examples => snippets}/all/bar_chart.py (100%) rename docs/{code-examples => snippets}/all/bar_chart.rs (100%) rename docs/{code-examples => snippets}/all/box2d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/box2d_simple.py (100%) rename docs/{code-examples => snippets}/all/box2d_simple.rs (100%) rename docs/{code-examples => snippets}/all/box3d_batch.cpp (100%) rename docs/{code-examples => snippets}/all/box3d_batch.py (100%) rename docs/{code-examples => snippets}/all/box3d_batch.rs (100%) rename docs/{code-examples => snippets}/all/box3d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/box3d_simple.py (100%) rename docs/{code-examples => snippets}/all/box3d_simple.rs (100%) rename docs/{code-examples => snippets}/all/clear_recursive.cpp (100%) rename docs/{code-examples => snippets}/all/clear_recursive.py (100%) rename docs/{code-examples => snippets}/all/clear_recursive.rs (100%) rename docs/{code-examples => snippets}/all/clear_simple.cpp (100%) rename docs/{code-examples => snippets}/all/clear_simple.py (100%) rename docs/{code-examples => snippets}/all/clear_simple.rs (100%) rename docs/{code-examples => snippets}/all/custom-recording-id/example.cpp (100%) rename docs/{code-examples => snippets}/all/custom-recording-id/example.py (100%) rename docs/{code-examples => snippets}/all/custom-recording-id/example.rs (100%) rename docs/{code-examples => snippets}/all/custom_data.cpp (100%) rename docs/{code-examples => snippets}/all/custom_data.py (100%) rename docs/{code-examples => snippets}/all/custom_data.rs (100%) rename docs/{code-examples => snippets}/all/default-off-session/example.py (100%) rename docs/{code-examples => snippets}/all/default-off-session/example.rs (100%) rename docs/{code-examples => snippets}/all/depth_image_3d.cpp (100%) rename docs/{code-examples => snippets}/all/depth_image_3d.py (100%) rename docs/{code-examples => snippets}/all/depth_image_3d.rs (100%) rename docs/{code-examples => snippets}/all/depth_image_simple.cpp (100%) rename docs/{code-examples => snippets}/all/depth_image_simple.py (100%) rename docs/{code-examples => snippets}/all/depth_image_simple.rs (100%) rename docs/{code-examples => snippets}/all/disconnected_space.cpp (100%) rename docs/{code-examples => snippets}/all/disconnected_space.py (100%) rename docs/{code-examples => snippets}/all/disconnected_space.rs (100%) rename docs/{code-examples => snippets}/all/entity_path.cpp (100%) rename docs/{code-examples => snippets}/all/entity_path.py (100%) rename docs/{code-examples => snippets}/all/entity_path.rs (100%) rename docs/{code-examples => snippets}/all/extra_values.py (100%) rename docs/{code-examples => snippets}/all/image_advanced.py (100%) rename docs/{code-examples => snippets}/all/image_simple.cpp (100%) rename docs/{code-examples => snippets}/all/image_simple.py (100%) rename docs/{code-examples => snippets}/all/image_simple.rs (100%) rename docs/{code-examples => snippets}/all/line_segments2d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/line_segments2d_simple.py (100%) rename docs/{code-examples => snippets}/all/line_segments2d_simple.rs (100%) rename docs/{code-examples => snippets}/all/line_segments3d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/line_segments3d_simple.py (100%) rename docs/{code-examples => snippets}/all/line_segments3d_simple.rs (100%) rename docs/{code-examples => snippets}/all/line_strip2d_batch.cpp (100%) rename docs/{code-examples => snippets}/all/line_strip2d_batch.py (100%) rename docs/{code-examples => snippets}/all/line_strip2d_batch.rs (100%) rename docs/{code-examples => snippets}/all/line_strip2d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/line_strip2d_simple.py (100%) rename docs/{code-examples => snippets}/all/line_strip2d_simple.rs (100%) rename docs/{code-examples => snippets}/all/line_strip3d_batch.cpp (100%) rename docs/{code-examples => snippets}/all/line_strip3d_batch.py (100%) rename docs/{code-examples => snippets}/all/line_strip3d_batch.rs (100%) rename docs/{code-examples => snippets}/all/line_strip3d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/line_strip3d_simple.py (100%) rename docs/{code-examples => snippets}/all/line_strip3d_simple.rs (100%) rename docs/{code-examples => snippets}/all/log-file/example.cpp (100%) rename docs/{code-examples => snippets}/all/log-file/example.py (100%) rename docs/{code-examples => snippets}/all/log-file/example.rs (100%) rename docs/{code-examples => snippets}/all/log_line.py (100%) rename docs/{code-examples => snippets}/all/log_line.rs (100%) rename docs/{code-examples => snippets}/all/manual_indicator.cpp (100%) rename docs/{code-examples => snippets}/all/manual_indicator.py (100%) rename docs/{code-examples => snippets}/all/manual_indicator.rs (100%) rename docs/{code-examples => snippets}/all/mesh3d_indexed.cpp (100%) rename docs/{code-examples => snippets}/all/mesh3d_indexed.py (100%) rename docs/{code-examples => snippets}/all/mesh3d_indexed.rs (100%) rename docs/{code-examples => snippets}/all/mesh3d_partial_updates.cpp (100%) rename docs/{code-examples => snippets}/all/mesh3d_partial_updates.py (100%) rename docs/{code-examples => snippets}/all/mesh3d_partial_updates.rs (100%) rename docs/{code-examples => snippets}/all/mesh3d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/mesh3d_simple.py (100%) rename docs/{code-examples => snippets}/all/mesh3d_simple.rs (100%) rename docs/{code-examples => snippets}/all/pinhole_perspective.cpp (100%) rename docs/{code-examples => snippets}/all/pinhole_perspective.py (100%) rename docs/{code-examples => snippets}/all/pinhole_perspective.rs (100%) rename docs/{code-examples => snippets}/all/pinhole_simple.cpp (100%) rename docs/{code-examples => snippets}/all/pinhole_simple.py (100%) rename docs/{code-examples => snippets}/all/pinhole_simple.rs (100%) rename docs/{code-examples => snippets}/all/point2d_random.cpp (100%) rename docs/{code-examples => snippets}/all/point2d_random.py (100%) rename docs/{code-examples => snippets}/all/point2d_random.rs (100%) rename docs/{code-examples => snippets}/all/point2d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/point2d_simple.py (100%) rename docs/{code-examples => snippets}/all/point2d_simple.rs (100%) rename docs/{code-examples => snippets}/all/point3d_random.cpp (100%) rename docs/{code-examples => snippets}/all/point3d_random.py (100%) rename docs/{code-examples => snippets}/all/point3d_random.rs (100%) rename docs/{code-examples => snippets}/all/point3d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/point3d_simple.py (100%) rename docs/{code-examples => snippets}/all/point3d_simple.rs (100%) rename docs/{code-examples => snippets}/all/quick_start_connect.cpp (100%) rename docs/{code-examples => snippets}/all/quick_start_connect.py (100%) rename docs/{code-examples => snippets}/all/quick_start_connect.rs (100%) rename docs/{code-examples => snippets}/all/quick_start_spawn.cpp (100%) rename docs/{code-examples => snippets}/all/quick_start_spawn.py (100%) rename docs/{code-examples => snippets}/all/quick_start_spawn.rs (100%) rename docs/{code-examples => snippets}/all/scalar_multiple_plots.cpp (100%) rename docs/{code-examples => snippets}/all/scalar_multiple_plots.py (100%) rename docs/{code-examples => snippets}/all/scalar_multiple_plots.rs (100%) rename docs/{code-examples => snippets}/all/scalar_simple.cpp (100%) rename docs/{code-examples => snippets}/all/scalar_simple.py (100%) rename docs/{code-examples => snippets}/all/scalar_simple.rs (100%) rename docs/{code-examples => snippets}/all/segmentation_image_simple.cpp (100%) rename docs/{code-examples => snippets}/all/segmentation_image_simple.py (100%) rename docs/{code-examples => snippets}/all/segmentation_image_simple.rs (100%) rename docs/{code-examples => snippets}/all/series_line_style.cpp (100%) rename docs/{code-examples => snippets}/all/series_line_style.py (100%) rename docs/{code-examples => snippets}/all/series_line_style.rs (100%) rename docs/{code-examples => snippets}/all/series_point_style.cpp (100%) rename docs/{code-examples => snippets}/all/series_point_style.py (100%) rename docs/{code-examples => snippets}/all/series_point_style.rs (100%) rename docs/{code-examples => snippets}/all/tensor_simple.cpp (100%) rename docs/{code-examples => snippets}/all/tensor_simple.py (100%) rename docs/{code-examples => snippets}/all/tensor_simple.rs (100%) rename docs/{code-examples => snippets}/all/text_document.cpp (100%) rename docs/{code-examples => snippets}/all/text_document.py (100%) rename docs/{code-examples => snippets}/all/text_document.rs (100%) rename docs/{code-examples => snippets}/all/text_log.cpp (100%) rename docs/{code-examples => snippets}/all/text_log.py (100%) rename docs/{code-examples => snippets}/all/text_log.rs (100%) rename docs/{code-examples => snippets}/all/text_log_integration.cpp (100%) rename docs/{code-examples => snippets}/all/text_log_integration.py (100%) rename docs/{code-examples => snippets}/all/text_log_integration.rs (100%) rename docs/{code-examples => snippets}/all/timelines_example.cpp (100%) rename docs/{code-examples => snippets}/all/timelines_example.py (100%) rename docs/{code-examples => snippets}/all/timelines_example.rs (100%) rename docs/{code-examples => snippets}/all/transform3d_simple.cpp (100%) rename docs/{code-examples => snippets}/all/transform3d_simple.py (100%) rename docs/{code-examples => snippets}/all/transform3d_simple.rs (100%) rename docs/{code-examples => snippets}/all/view_coordinates_simple.cpp (100%) rename docs/{code-examples => snippets}/all/view_coordinates_simple.py (100%) rename docs/{code-examples => snippets}/all/view_coordinates_simple.rs (100%) rename docs/{code-examples => snippets}/build.rs (98%) rename docs/{code-examples/compare_code_example_output.py => snippets/compare_snippet_output.py} (67%) create mode 100644 docs/snippets/snippets.toml rename docs/{code-examples => snippets}/src/examples/.gitignore (100%) create mode 100644 docs/snippets/src/lib.rs create mode 100644 docs/snippets/src/main.rs diff --git a/.github/actions/deploy-vercel/action.yml b/.github/actions/deploy-vercel/action.yml index c1e7d29bc86b..9f2d084a0d2c 100644 --- a/.github/actions/deploy-vercel/action.yml +++ b/.github/actions/deploy-vercel/action.yml @@ -22,6 +22,10 @@ inputs: description: "Release commit to update the deployment to" type: string required: true + release_version: + description: "Which release version to update the deployment to" + type: string + required: true runs: using: "node20" diff --git a/.github/actions/deploy-vercel/index.mjs b/.github/actions/deploy-vercel/index.mjs index 825a88ae8f1d..43b8bbb0fe85 100644 --- a/.github/actions/deploy-vercel/index.mjs +++ b/.github/actions/deploy-vercel/index.mjs @@ -8,6 +8,7 @@ const token = getRequiredInput("vercel_token"); const teamName = getRequiredInput("vercel_team_name"); const projectName = getRequiredInput("vercel_project_name"); const releaseCommit = getRequiredInput("release_commit"); +const releaseVersion = getRequiredInput("release_version"); const client = new Client(token); @@ -25,21 +26,38 @@ assert(project, `failed to get project "${projectName}"`); info`Fetching latest production deployment`; const productionDeployments = await client.deployments(team.id, project.id); const latestProductionDeployment = productionDeployments[0]; -assert(latestProductionDeployment, `failed to get latest production deployment`); +assert( + latestProductionDeployment, + `failed to get latest production deployment`, +); +const environment = await client.envs(team.id, project.id); const RELEASE_COMMIT_KEY = "RELEASE_COMMIT"; +const RELEASE_VERSION_KEY = "RELEASE_VERSION"; info`Fetching "${RELEASE_COMMIT_KEY}" env var`; -const environment = await client.envs(team.id, project.id); -const releaseCommitEnv = environment.find((env) => env.key === RELEASE_COMMIT_KEY); +const releaseCommitEnv = environment.find( + (env) => env.key === RELEASE_COMMIT_KEY, +); assert(releaseCommitEnv, `failed to get "${RELEASE_COMMIT_KEY}" env var`); +info`Fetching "${RELEASE_VERSION_KEY}" env var`; +const releaseVersionEnv = environment.find( + (env) => env.key === RELEASE_VERSION_KEY, +); +assert(releaseVersionEnv, `failed to get "${RELEASE_VERSION_KEY}" env var`); + info`Setting "${RELEASE_COMMIT_KEY}" env to "${releaseCommit}"`; await client.setEnv(team.id, project.id, releaseCommitEnv.id, { key: RELEASE_COMMIT_KEY, value: releaseCommit, }); +info`Setting "${RELEASE_VERSION_KEY}" env to "${releaseVersion}"`; +await client.setEnv(team.id, project.id, releaseVersionEnv.id, { + key: RELEASE_VERSION_KEY, + value: releaseVersion, +}); + info`Triggering redeploy`; await client.redeploy(team.id, latestProductionDeployment.uid, "landing"); - diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index bc1a458ddb04..f0b7b1517c68 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -112,13 +112,13 @@ jobs: run: | RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build - - name: Run docs/code-examples/compare_code_example_output.py + - name: Run docs/snippets/compare_snippet_output.py shell: bash # --release so we can inherit from some of the artifacts that maturin has just built before # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… # --no-py-build because rerun-sdk is already built and installed run: | - RUST_LOG=debug docs/code-examples/compare_code_example_output.py --release --target x86_64-unknown-linux-gnu --no-py-build + RUST_LOG=debug docs/snippets/compare_snippet_output.py --release --target x86_64-unknown-linux-gnu --no-py-build - name: Cache RRD dataset id: dataset diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 768c648c103b..2aa2df31bdd6 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -93,6 +93,12 @@ jobs: --channel ${{ inputs.CHANNEL }} \ example_data + - name: Build snippets + shell: bash + run: | + pixi run build-examples snippets \ + example_data/snippets + - name: Upload assets uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index 1bafd93a59bc..7536ec162887 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -261,3 +261,4 @@ jobs: vercel_team_name: ${{ vars.VERCEL_TEAM_NAME }} vercel_project_name: ${{ vars.VERCEL_PROJECT_NAME }} release_commit: ${{ inputs.RELEASE_COMMIT }} + release_version: ${{ inputs.RELEASE_VERSION }} diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 552609dab0ce..33228b2d1d94 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -195,11 +195,11 @@ jobs: run: | RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build - - name: Run docs/code-examples/compare_code_example_output.py + - name: Run docs/snippets/compare_snippet_output.py if: ${{ inputs.PLATFORM != 'windows' }} shell: bash # --release so we can inherit from some of the artifacts that maturin has just built before # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… # --no-py-build because rerun-sdk is already built and installed run: | - RUST_LOG=debug docs/code-examples/compare_code_example_output.py --release --target x86_64-unknown-linux-gnu --no-py-build + RUST_LOG=debug docs/snippets/compare_snippet_output.py --release --target x86_64-unknown-linux-gnu --no-py-build diff --git a/CMakeLists.txt b/CMakeLists.txt index fc2b6f6a93ef..c9918f250cdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,4 +157,4 @@ add_subdirectory(crates/rerun_c) # The Rerun C SDK library, must be included bef add_subdirectory(rerun_cpp) # The Rerun C++ SDK library. add_subdirectory(examples/cpp) add_subdirectory(tests/cpp) -add_subdirectory(docs/code-examples) +add_subdirectory(docs/snippets) diff --git a/Cargo.lock b/Cargo.lock index dec4be2dc83a..f112875bcd7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1094,18 +1094,6 @@ dependencies = [ "objc", ] -[[package]] -name = "code_examples" -version = "0.15.0-alpha.2" -dependencies = [ - "itertools 0.12.0", - "ndarray", - "rand", - "re_build_tools", - "rerun", - "rust-format", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1567,7 +1555,7 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "bytemuck", "serde", @@ -1576,7 +1564,7 @@ dependencies = [ [[package]] name = "eframe" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "bytemuck", "cocoa", @@ -1611,7 +1599,7 @@ dependencies = [ [[package]] name = "egui" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "accesskit", "ahash", @@ -1627,7 +1615,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "bytemuck", "document-features", @@ -1645,7 +1633,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "accesskit_winit", "arboard", @@ -1674,7 +1662,7 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "egui", "ehttp", @@ -1689,7 +1677,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "bytemuck", "egui", @@ -1706,7 +1694,7 @@ dependencies = [ [[package]] name = "egui_plot" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "egui", ] @@ -1748,7 +1736,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "bytemuck", "serde", @@ -1849,7 +1837,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0afbefc884cc6d8ada9c60461b1b7c89415270b1#0afbefc884cc6d8ada9c60461b1b7c89415270b1" +source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" dependencies = [ "ab_glyph", "ahash", @@ -6046,6 +6034,18 @@ dependencies = [ "serde", ] +[[package]] +name = "snippets" +version = "0.15.0-alpha.2" +dependencies = [ + "itertools 0.12.0", + "ndarray", + "rand", + "re_build_tools", + "rerun", + "rust-format", +] + [[package]] name = "socket2" version = "0.4.9" diff --git a/Cargo.toml b/Cargo.toml index 855e85452a46..d1c981ffb0a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ resolver = "2" members = [ "crates/*", - "docs/code-examples", + "docs/snippets", "examples/rust/*", "rerun_py", "run_wasm", @@ -283,13 +283,13 @@ debug = true # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 -eframe = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 -egui = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 -egui_plot = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 -emath = { git = "https://github.com/emilk/egui.git", rev = "0afbefc884cc6d8ada9c60461b1b7c89415270b1" } # egui master 2024-03-13 +ecolor = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 +eframe = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 +egui = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 +egui_extras = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 +egui_plot = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 +egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 +emath = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } diff --git a/crates/re_build_examples/src/lib.rs b/crates/re_build_examples/src/lib.rs index 854e650bccbf..5f3784bdbdb6 100644 --- a/crates/re_build_examples/src/lib.rs +++ b/crates/re_build_examples/src/lib.rs @@ -3,5 +3,42 @@ pub mod example; pub mod manifest; pub mod rrd; +pub mod snippets; + +use std::io::stdout; +use std::io::IsTerminal; +use std::process::Command; +use std::process::Output; +use std::time::Duration; pub use example::{Channel, Example}; +use indicatif::MultiProgress; +use indicatif::ProgressBar; + +fn wait_for_output( + mut cmd: Command, + name: &str, + progress: &MultiProgress, +) -> anyhow::Result { + let progress = progress.add(ProgressBar::new_spinner().with_message(name.to_owned())); + progress.enable_steady_tick(Duration::from_millis(100)); + + let output = cmd.output()?; + + let elapsed = progress.elapsed().as_secs_f64(); + let tick = if output.status.success() { + "✔" + } else { + "✘" + }; + let message = format!("{tick} {name} ({elapsed:.3}s)"); + + if stdout().is_terminal() { + progress.set_message(message); + progress.finish(); + } else { + println!("{message}"); + } + + Ok(output) +} diff --git a/crates/re_build_examples/src/main.rs b/crates/re_build_examples/src/main.rs index 01e75eb618ec..b4adb0725684 100644 --- a/crates/re_build_examples/src/main.rs +++ b/crates/re_build_examples/src/main.rs @@ -21,6 +21,7 @@ fn main() -> anyhow::Result<()> { match args.cmd { Cmd::Rrd(cmd) => cmd.run(), Cmd::Manifest(cmd) => cmd.run(), + Cmd::Snippets(cmd) => cmd.run(), } } @@ -36,4 +37,5 @@ struct Args { enum Cmd { Rrd(rrd::Rrd), Manifest(manifest::Manifest), + Snippets(snippets::Snippets), } diff --git a/crates/re_build_examples/src/rrd.rs b/crates/re_build_examples/src/rrd.rs index d1b6f74c9cd1..fba6886ec4d4 100644 --- a/crates/re_build_examples/src/rrd.rs +++ b/crates/re_build_examples/src/rrd.rs @@ -1,16 +1,12 @@ +use crate::wait_for_output; use crate::{Channel, Example}; use indicatif::MultiProgress; -use indicatif::ProgressBar; use rayon::prelude::IntoParallelIterator; use rayon::prelude::ParallelIterator; use std::fs::create_dir_all; -use std::io::stdout; -use std::io::IsTerminal; use std::path::Path; use std::path::PathBuf; use std::process::Command; -use std::process::Output; -use std::time::Duration; /// Collect examples in the repository and run them to produce `.rrd` files. #[derive(argh::FromArgs)] @@ -75,12 +71,7 @@ impl Rrd { } } -trait Build { - /// Returns the path to the resulting `.rrd` file. - fn build(self, progress: &MultiProgress, output_dir: &Path) -> anyhow::Result; -} - -impl Build for Example { +impl Example { fn build(self, progress: &MultiProgress, output_dir: &Path) -> anyhow::Result { let rrd_path = output_dir.join(&self.name).with_extension("rrd"); @@ -118,31 +109,3 @@ impl Build for Example { } } } - -fn wait_for_output( - mut cmd: Command, - name: &str, - progress: &MultiProgress, -) -> anyhow::Result { - let progress = progress.add(ProgressBar::new_spinner().with_message(name.to_owned())); - progress.enable_steady_tick(Duration::from_millis(100)); - - let output = cmd.output()?; - - let elapsed = progress.elapsed().as_secs_f64(); - let tick = if output.status.success() { - "✔" - } else { - "✘" - }; - let message = format!("{tick} {name} ({elapsed:.3}s)"); - - if stdout().is_terminal() { - progress.set_message(message); - progress.finish(); - } else { - println!("{message}"); - } - - Ok(output) -} diff --git a/crates/re_build_examples/src/snippets.rs b/crates/re_build_examples/src/snippets.rs new file mode 100644 index 000000000000..ecbd9e568327 --- /dev/null +++ b/crates/re_build_examples/src/snippets.rs @@ -0,0 +1,182 @@ +use std::collections::HashMap; +use std::ffi::OsStr; +use std::fs::create_dir_all; +use std::fs::read_dir; +use std::fs::read_to_string; +use std::path::Path; +use std::path::PathBuf; +use std::process::Command; + +use indicatif::MultiProgress; +use rayon::prelude::IntoParallelIterator; +use rayon::prelude::ParallelIterator; + +use crate::wait_for_output; + +/// Collect code snippets from `docs/snippets` in the repository and run them to produce `.rrd` files. +#[derive(argh::FromArgs)] +#[argh(subcommand, name = "snippets")] +pub struct Snippets { + #[argh(positional, description = "directory to output `rrd` files into")] + output_dir: PathBuf, +} + +impl Snippets { + pub fn run(self) -> anyhow::Result<()> { + create_dir_all(&self.output_dir)?; + + let snippets_dir = re_build_tools::cargo_metadata()? + .workspace_root + .join("docs/snippets"); + + println!("Reading config…"); + let config = read_to_string(snippets_dir.join("snippets.toml"))?; + let config: Config = toml::from_str(&config)?; + + println!("Collecting snippets…"); + let mut snippets = vec![]; + for snippet in read_dir(snippets_dir.join("all"))? { + let snippet = snippet?; + let meta = snippet.metadata()?; + let path = snippet.path(); + let name = path.file_stem().and_then(OsStr::to_str).unwrap().to_owned(); + + if meta.is_dir() { + println!( + "Skipping {}: directories are implicitly opt-out", + path.display() + ); + continue; + } + + // We only run python examples, because: + // - Each snippet should already be available in each language + // - Python is the easiest to run + if !path.extension().is_some_and(|p| p == "py") { + println!("Skipping {}: not a python example", path.display()); + continue; + } + + if config.opt_out.run.contains_key(&name) { + println!( + "Skipping {}: explicit opt-out in `snippets.toml`", + path.display() + ); + continue; + } + + println!("Adding {}", path.display()); + let extra_args: Vec = config + .extra_args + .get(&name) + .cloned() + .unwrap_or_default() + .into_iter() + .map(|value| value.replace("$config_dir", snippets_dir.as_str())) + .collect(); + snippets.push(Snippet { + extra_args, + name, + path, + }); + } + + println!("Running {} snippets…", snippets.len()); + let progress = MultiProgress::new(); + let results: Vec> = snippets + .into_par_iter() + .map(|example| example.build(&progress, &self.output_dir)) + .collect(); + + let mut failed = false; + for result in results { + match result { + Ok(rrd_path) => { + if let Ok(metadata) = std::fs::metadata(&rrd_path) { + println!( + "Output: {} ({})", + rrd_path.display(), + re_format::format_bytes(metadata.len() as _) + ); + } else { + eprintln!("Missing rrd at {}", rrd_path.display()); + failed = true; + } + } + Err(err) => { + eprintln!("{err}"); + failed = true; + } + } + } + if failed { + anyhow::bail!("Failed to run some examples"); + } + + Ok(()) + } +} + +#[derive(Debug)] +struct Snippet { + path: PathBuf, + name: String, + extra_args: Vec, +} + +impl Snippet { + fn build(self, progress: &MultiProgress, output_dir: &Path) -> anyhow::Result { + let rrd_path = output_dir.join(&self.name).with_extension("rrd"); + + let mut cmd = Command::new("python3"); + cmd.arg(&self.path); + cmd.args(&self.extra_args); + + let final_args = cmd + .get_args() + .map(|arg| arg.to_string_lossy().to_string()) + .collect::>(); + + cmd.envs([ + ("RERUN_FLUSH_NUM_ROWS", "0"), + ("RERUN_STRICT", "1"), + ("RERUN_PANIC_ON_WARN", "1"), + ( + "_RERUN_TEST_FORCE_SAVE", + rrd_path.to_string_lossy().as_ref(), + ), + ]); + + let output = wait_for_output(cmd, &self.name, progress)?; + + if output.status.success() { + Ok(rrd_path) + } else { + anyhow::bail!( + "Failed to run `python3 {}`: \ + \nstdout: \ + \n{} \ + \nstderr: \ + \n{}", + final_args.join(" "), + String::from_utf8(output.stdout)?, + String::from_utf8(output.stderr)?, + ); + } + } +} + +/// See `docs/snippets/snippets.toml` for more info +#[derive(serde::Deserialize)] +struct Config { + opt_out: OptOut, + + /// example name -> args + extra_args: HashMap>, +} + +#[derive(serde::Deserialize)] +struct OptOut { + /// example name -> languages + run: HashMap>, +} diff --git a/crates/re_types/src/lib.rs b/crates/re_types/src/lib.rs index c78ed6f89a2e..a826d99724e0 100644 --- a/crates/re_types/src/lib.rs +++ b/crates/re_types/src/lib.rs @@ -100,7 +100,7 @@ //! //! ### Examples //! -//! You can add an example to `docs/code-examples/all`, and then include its source code in +//! You can add an example to `docs/snippets/all`, and then include its source code in //! the docs using the `\example` tag. The example will also be included in the list of //! examples for type's generated docs. //! diff --git a/crates/re_types_builder/src/bin/build_re_types.rs b/crates/re_types_builder/src/bin/build_re_types.rs index a32175d30aab..0cb5e2ef9f87 100644 --- a/crates/re_types_builder/src/bin/build_re_types.rs +++ b/crates/re_types_builder/src/bin/build_re_types.rs @@ -13,7 +13,7 @@ use camino::Utf8Path; const RE_TYPES_SOURCE_HASH_PATH: &str = "crates/re_types/source_hash.txt"; const DEFINITIONS_DIR_PATH: &str = "crates/re_types/definitions"; const ENTRYPOINT_PATH: &str = "crates/re_types/definitions/rerun/archetypes.fbs"; -const DOC_EXAMPLES_DIR_PATH: &str = "docs/code-examples/all"; +const SNIPPETS_DIR_PATH: &str = "docs/snippets/all"; const CPP_OUTPUT_DIR_PATH: &str = "rerun_cpp"; const PYTHON_OUTPUT_DIR_PATH: &str = "rerun_py/rerun_sdk/rerun"; const PYTHON_TESTING_OUTPUT_DIR_PATH: &str = "rerun_py/tests/test_types"; @@ -84,7 +84,7 @@ fn main() { let new_hash = compute_re_types_hash(&SourceLocations { definitions_dir: DEFINITIONS_DIR_PATH, - doc_examples_dir: DOC_EXAMPLES_DIR_PATH, + snippets_dir: SNIPPETS_DIR_PATH, python_output_dir: PYTHON_OUTPUT_DIR_PATH, cpp_output_dir: CPP_OUTPUT_DIR_PATH, }); diff --git a/crates/re_types_builder/src/codegen/common.rs b/crates/re_types_builder/src/codegen/common.rs index 8ed35fed7089..19118a4d0734 100644 --- a/crates/re_types_builder/src/codegen/common.rs +++ b/crates/re_types_builder/src/codegen/common.rs @@ -45,7 +45,7 @@ pub fn get_documentation(docs: &Docs, tags: &[&str]) -> Vec { pub struct ExampleInfo<'a> { /// The snake_case name of the example. /// - /// Used with `code-example:`, `std::fs::read_to_string`, etc. + /// Used with `snippet:`, `std::fs::read_to_string`, etc. pub name: &'a str, /// The human-readable name of the example. @@ -242,7 +242,7 @@ pub struct Example<'a> { pub lines: Vec, } -pub fn collect_examples_for_api_docs<'a>( +pub fn collect_snippets_for_api_docs<'a>( docs: &'a Docs, extension: &str, required: bool, @@ -250,7 +250,7 @@ pub fn collect_examples_for_api_docs<'a>( let mut out = Vec::new(); if let Some(examples) = docs.tagged_docs.get("example") { - let base_path = crate::rerun_workspace_path().join("docs/code-examples/all"); + let base_path = crate::rerun_workspace_path().join("docs/snippets/all"); for base @ ExampleInfo { name, @@ -267,7 +267,7 @@ pub fn collect_examples_for_api_docs<'a>( Ok(content) => content, Err(_) if !required => continue, Err(err) => { - return Err(err).with_context(|| format!("couldn't open code example {path:?}")) + return Err(err).with_context(|| format!("couldn't open snippet {path:?}")) } }; let mut content = content diff --git a/crates/re_types_builder/src/codegen/cpp/mod.rs b/crates/re_types_builder/src/codegen/cpp/mod.rs index 5ba80026e1a6..4201060ce9cc 100644 --- a/crates/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/re_types_builder/src/codegen/cpp/mod.rs @@ -12,7 +12,7 @@ use quote::{format_ident, quote}; use rayon::prelude::*; use crate::{ - codegen::{autogen_warning, common::collect_examples_for_api_docs}, + codegen::{autogen_warning, common::collect_snippets_for_api_docs}, format_path, objects::ObjectClass, ArrowRegistry, Docs, ElementType, GeneratedFiles, Object, ObjectField, ObjectKind, Objects, @@ -2199,7 +2199,7 @@ fn lines_from_docs(docs: &Docs) -> Vec { let mut lines = crate::codegen::get_documentation(docs, &["cpp", "c++"]); let required = true; - let examples = collect_examples_for_api_docs(docs, "cpp", required).unwrap_or_default(); + let examples = collect_snippets_for_api_docs(docs, "cpp", required).unwrap_or_default(); if !examples.is_empty() { lines.push(String::new()); let section_title = if examples.len() == 1 { diff --git a/crates/re_types_builder/src/codegen/docs/mod.rs b/crates/re_types_builder/src/codegen/docs/mod.rs index d130f828335c..d695c838031c 100644 --- a/crates/re_types_builder/src/codegen/docs/mod.rs +++ b/crates/re_types_builder/src/codegen/docs/mod.rs @@ -454,7 +454,7 @@ fn write_example_list(o: &mut String, examples: &[ExampleInfo<'_>]) { let title = title.unwrap_or(name); putln!(o, "### {title}"); putln!(o); - putln!(o, "code-example: {name}"); + putln!(o, "snippet: {name}"); if let Some(image_url) = image { putln!(o); for line in image_url.image_stack() { diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index d15afd942e12..41769667124e 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -10,7 +10,7 @@ use unindent::unindent; use crate::{ codegen::{ autogen_warning, - common::{collect_examples_for_api_docs, Example}, + common::{collect_snippets_for_api_docs, Example}, StringExt as _, }, format_path, @@ -1156,7 +1156,7 @@ fn quote_obj_docs(obj: &Object) -> String { fn lines_from_docs(docs: &Docs) -> Vec { let mut lines = crate::codegen::get_documentation(docs, &["py", "python"]); - let examples = collect_examples_for_api_docs(docs, "py", true).unwrap(); + let examples = collect_snippets_for_api_docs(docs, "py", true).unwrap(); if !examples.is_empty() { lines.push(String::new()); let (section_title, divider) = if examples.len() == 1 { @@ -1212,7 +1212,7 @@ fn quote_doc_from_fields(objects: &Objects, fields: &Vec) -> String } } - let examples = collect_examples_for_api_docs(&field.docs, "py", true).unwrap(); + let examples = collect_snippets_for_api_docs(&field.docs, "py", true).unwrap(); if !examples.is_empty() { content.push(String::new()); // blank line between docs and examples quote_examples(examples, &mut lines); diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index 19ff35b6ee31..61d9f4b5fe8b 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -9,7 +9,7 @@ use quote::{format_ident, quote}; use crate::{ codegen::{ autogen_warning, - common::{collect_examples_for_api_docs, ExampleInfo}, + common::{collect_snippets_for_api_docs, ExampleInfo}, rust::{ arrow::ArrowDataTypeTokenizer, deserializer::{ @@ -716,7 +716,7 @@ fn quote_obj_docs(reporter: &Reporter, obj: &Object) -> TokenStream { fn doc_as_lines(reporter: &Reporter, virtpath: &str, fqname: &str, docs: &Docs) -> Vec { let mut lines = crate::codegen::get_documentation(docs, &["rs", "rust"]); - let examples = collect_examples_for_api_docs(docs, "rs", true) + let examples = collect_snippets_for_api_docs(docs, "rs", true) .map_err(|err| reporter.error(virtpath, fqname, err)) .unwrap_or_default(); diff --git a/crates/re_types_builder/src/lib.rs b/crates/re_types_builder/src/lib.rs index 0c9f573eabaf..17d6b1615fb7 100644 --- a/crates/re_types_builder/src/lib.rs +++ b/crates/re_types_builder/src/lib.rs @@ -328,7 +328,7 @@ pub fn compute_re_types_builder_hash() -> String { pub struct SourceLocations<'a> { pub definitions_dir: &'a str, - pub doc_examples_dir: &'a str, + pub snippets_dir: &'a str, pub python_output_dir: &'a str, pub cpp_output_dir: &'a str, } @@ -341,8 +341,7 @@ pub fn compute_re_types_hash(locations: &SourceLocations<'_>) -> String { // code generator itself! let re_types_builder_hash = compute_re_types_builder_hash(); let definitions_hash = compute_dir_hash(locations.definitions_dir, Some(&["fbs"])); - let doc_examples_hash = - compute_dir_hash(locations.doc_examples_dir, Some(&["rs", "py", "cpp"])); + let snippets_hash = compute_dir_hash(locations.snippets_dir, Some(&["rs", "py", "cpp"])); let python_extensions_hash = compute_dir_filtered_hash(locations.python_output_dir, |path| { path.to_str().unwrap().ends_with("_ext.py") }); @@ -353,14 +352,14 @@ pub fn compute_re_types_hash(locations: &SourceLocations<'_>) -> String { let new_hash = compute_strings_hash(&[ &re_types_builder_hash, &definitions_hash, - &doc_examples_hash, + &snippets_hash, &python_extensions_hash, &cpp_extensions_hash, ]); re_log::debug!("re_types_builder_hash: {re_types_builder_hash:?}"); re_log::debug!("definitions_hash: {definitions_hash:?}"); - re_log::debug!("doc_examples_hash: {doc_examples_hash:?}"); + re_log::debug!("snippets_hash: {snippets_hash:?}"); re_log::debug!("python_extensions_hash: {python_extensions_hash:?}"); re_log::debug!("cpp_extensions_hash: {cpp_extensions_hash:?}"); re_log::debug!("new_hash: {new_hash:?}"); diff --git a/crates/re_viewer/data/quick_start_guides/quick_start_connect.cpp b/crates/re_viewer/data/quick_start_guides/quick_start_connect.cpp index 6e50ed1f948e..3c5c90aea114 120000 --- a/crates/re_viewer/data/quick_start_guides/quick_start_connect.cpp +++ b/crates/re_viewer/data/quick_start_guides/quick_start_connect.cpp @@ -1 +1 @@ -../../../../docs/code-examples/all/quick_start_connect.cpp \ No newline at end of file +../../../../docs/snippets/all/quick_start_connect.cpp \ No newline at end of file diff --git a/crates/re_viewer/data/quick_start_guides/quick_start_connect.py b/crates/re_viewer/data/quick_start_guides/quick_start_connect.py index f319284a41ce..f0ecdce5c83b 120000 --- a/crates/re_viewer/data/quick_start_guides/quick_start_connect.py +++ b/crates/re_viewer/data/quick_start_guides/quick_start_connect.py @@ -1 +1 @@ -../../../../docs/code-examples/all/quick_start_connect.py \ No newline at end of file +../../../../docs/snippets/all/quick_start_connect.py \ No newline at end of file diff --git a/crates/re_viewer/data/quick_start_guides/quick_start_connect.rs b/crates/re_viewer/data/quick_start_guides/quick_start_connect.rs index f6e9d25d3ac9..9f4151700f0e 120000 --- a/crates/re_viewer/data/quick_start_guides/quick_start_connect.rs +++ b/crates/re_viewer/data/quick_start_guides/quick_start_connect.rs @@ -1 +1 @@ -../../../../docs/code-examples/all/quick_start_connect.rs \ No newline at end of file +../../../../docs/snippets/all/quick_start_connect.rs \ No newline at end of file diff --git a/crates/re_viewer/data/quick_start_guides/quick_start_spawn.cpp b/crates/re_viewer/data/quick_start_guides/quick_start_spawn.cpp deleted file mode 100644 index f0efac3d862f..000000000000 --- a/crates/re_viewer/data/quick_start_guides/quick_start_spawn.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -using namespace rerun::demo; - -int main() { - // Create a new `RecordingStream` which sends data over TCP to the viewer process. - const auto rec = rerun::RecordingStream("rerun_example_demo"); - rec.spawn().exit_on_failure(); - - // Create some data using the `grid` utility function. - std::vector points = grid3d(-10.f, 10.f, 10); - std::vector colors = grid3d(0, 255, 10); - - // Log the "my_points" entity with our data, using the `Points3D` archetype. - rec.log("my_points", rerun::Points3D(points).with_colors(colors).with_radii({0.5f})); -} diff --git a/crates/re_viewer/data/quick_start_guides/quick_start_spawn.cpp b/crates/re_viewer/data/quick_start_guides/quick_start_spawn.cpp new file mode 120000 index 000000000000..e0f604450ea1 --- /dev/null +++ b/crates/re_viewer/data/quick_start_guides/quick_start_spawn.cpp @@ -0,0 +1 @@ +../../../../docs/snippets/all/quick_start_spawn.cpp \ No newline at end of file diff --git a/crates/re_viewer/data/quick_start_guides/quick_start_spawn.py b/crates/re_viewer/data/quick_start_guides/quick_start_spawn.py index f6eb369d0a16..b182333cc341 120000 --- a/crates/re_viewer/data/quick_start_guides/quick_start_spawn.py +++ b/crates/re_viewer/data/quick_start_guides/quick_start_spawn.py @@ -1 +1 @@ -../../../../docs/code-examples/all/quick_start_spawn.py \ No newline at end of file +../../../../docs/snippets/all/quick_start_spawn.py \ No newline at end of file diff --git a/crates/re_viewer/data/quick_start_guides/quick_start_spawn.rs b/crates/re_viewer/data/quick_start_guides/quick_start_spawn.rs index 36e9929496ed..09f65ff09b03 120000 --- a/crates/re_viewer/data/quick_start_guides/quick_start_spawn.rs +++ b/crates/re_viewer/data/quick_start_guides/quick_start_spawn.rs @@ -1 +1 @@ -../../../../docs/code-examples/all/quick_start_spawn.rs \ No newline at end of file +../../../../docs/snippets/all/quick_start_spawn.rs \ No newline at end of file diff --git a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs index c7176b96d845..56bbc564a6af 100644 --- a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs @@ -23,17 +23,17 @@ const RUST_SPAWN_MARKDOWN: &str = include_str!("../../../data/quick_start_guides const HOW_DOES_IT_WORK_MARKDOWN: &str = include_str!("../../../data/quick_start_guides/how_does_it_work.md"); -const CPP_CONNECT_CODE_EXAMPLE: &str = +const CPP_CONNECT_SNIPPET: &str = include_str!("../../../data/quick_start_guides/quick_start_connect.cpp"); -const CPP_SPAWN_CODE_EXAMPLE: &str = +const CPP_SPAWN_SNIPPET: &str = include_str!("../../../data/quick_start_guides/quick_start_spawn.cpp"); -const PYTHON_CONNECT_CODE_EXAMPLE: &str = +const PYTHON_CONNECT_SNIPPET: &str = include_str!("../../../data/quick_start_guides/quick_start_connect.py"); -const PYTHON_SPAWN_CODE_EXAMPLE: &str = +const PYTHON_SPAWN_SNIPPET: &str = include_str!("../../../data/quick_start_guides/quick_start_spawn.py"); -const RUST_CONNECT_CODE_EXAMPLE: &str = +const RUST_CONNECT_SNIPPET: &str = include_str!("../../../data/quick_start_guides/quick_start_connect.rs"); -const RUST_SPAWN_CODE_EXAMPLE: &str = +const RUST_SPAWN_SNIPPET: &str = include_str!("../../../data/quick_start_guides/quick_start_spawn.rs"); struct Placeholder<'a> { @@ -48,27 +48,27 @@ const PLACEHOLDERS: &[Placeholder<'_>] = &[ }, Placeholder { key: "EXAMPLE_CODE_CPP_CONNECT", - value: CPP_CONNECT_CODE_EXAMPLE, + value: CPP_CONNECT_SNIPPET, }, Placeholder { key: "EXAMPLE_CODE_CPP_SPAWN", - value: CPP_SPAWN_CODE_EXAMPLE, + value: CPP_SPAWN_SNIPPET, }, Placeholder { key: "EXAMPLE_CODE_PYTHON_CONNECT", - value: PYTHON_CONNECT_CODE_EXAMPLE, + value: PYTHON_CONNECT_SNIPPET, }, Placeholder { key: "EXAMPLE_CODE_PYTHON_SPAWN", - value: PYTHON_SPAWN_CODE_EXAMPLE, + value: PYTHON_SPAWN_SNIPPET, }, Placeholder { key: "EXAMPLE_CODE_RUST_CONNECT", - value: RUST_CONNECT_CODE_EXAMPLE, + value: RUST_CONNECT_SNIPPET, }, Placeholder { key: "EXAMPLE_CODE_RUST_SPAWN", - value: RUST_SPAWN_CODE_EXAMPLE, + value: RUST_SPAWN_SNIPPET, }, ]; diff --git a/docs/README.md b/docs/README.md index e12be7f6f3fd..046f27b98d65 100644 --- a/docs/README.md +++ b/docs/README.md @@ -12,18 +12,7 @@ until the next time we roll out a site-update. We will generally to do this at l The site documentation lives in Markdown files inside [`/content`](./content). -The entry point to the documentation is [`/content/index.md`](./content/index.md) - -Code examples can be rendered in multiple languages by placing them in `code-examples/all`, like so: - -``` -/docs - /code-examples - /all - /my-example - /example.py - /example.rs -``` +The entry point to the documentation is [`/content/index.md`](./content/index.md). ## Special syntax @@ -38,9 +27,31 @@ order: 6 ``` -### Code Examples +### Snippets + +Snippets are small, self-contained code examples. + +To ensure all the code blocks in our documentation contain valid code, we give each one a name, and move it into `snippets/all`: +``` +/docs + /snippets + /all + /my-example + /example.py +``` + +Each snippet can and should be written in all our supported languages: +``` +/docs + /snippets + /all + /my-example + /example.cpp + /example.py + /example.rs +``` -Code-examples can be referenced in Markdown using this syntax: +Once the snippet is in `snippet/all`, it may be referenced in a documentation Markdown file using this syntax: ``` -code-example: my-example +snippet: my-example ``` diff --git a/docs/code-examples/src/lib.rs b/docs/code-examples/src/lib.rs deleted file mode 100644 index e9cf2fdc39f4..000000000000 --- a/docs/code-examples/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Code examples that we show in documentation. - -mod examples; - -pub use examples::run; diff --git a/docs/code-examples/src/main.rs b/docs/code-examples/src/main.rs deleted file mode 100644 index 9d76de6ccb01..000000000000 --- a/docs/code-examples/src/main.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! Code examples that we show in documentation. - -pub fn main() { - // Call into the generated code. - code_examples::run(); -} diff --git a/docs/content/concepts/annotation-context.md b/docs/content/concepts/annotation-context.md index 15d93033642c..06d983d1dda9 100644 --- a/docs/content/concepts/annotation-context.md +++ b/docs/content/concepts/annotation-context.md @@ -56,7 +56,7 @@ Annotation contexts are logged with: * Python: 🐍[`rr.AnnotationContext`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.AnnotationContext) * Rust: 🦀[`rerun::AnnotationContext`](https://docs.rs/rerun/latest/rerun/archetypes/struct.AnnotationContext.html#) -code-example: annotation-context +snippet: annotation-context ## Affected Entities diff --git a/docs/content/concepts/entity-component.md b/docs/content/concepts/entity-component.md index 39ea923160d7..a03c2103fb9b 100644 --- a/docs/content/concepts/entity-component.md +++ b/docs/content/concepts/entity-component.md @@ -52,15 +52,15 @@ own set of components, bypassing archetypes altogether. In Python, the [rr.AnyValues](https://ref.rerun.io/docs/python/stable/common/custom_data/#rerun.AnyValues) helper object can be used to add custom component(s) to an archetype: -code-example: extra_values +snippet: extra_values It can also be used log an entirely custom set of components: -code-example: any_values +snippet: any_values For more complex use-cases, custom objects implementing the `rr.AsComponents` protocol can be used. For Rust, the `rerun::AsComponents` trait must be implemented: -code-example: custom_data +snippet: custom_data ### Empty Entities diff --git a/docs/content/concepts/timelines.md b/docs/content/concepts/timelines.md index 82a94ac6d95f..7237c1d408be 100644 --- a/docs/content/concepts/timelines.md +++ b/docs/content/concepts/timelines.md @@ -10,7 +10,7 @@ By default, each log is added to the `log_time` timeline, with a timestamp assig You can use the _set time_ functions (Python reference: [set_time_sequence](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_sequence), [set_time_seconds](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_seconds), [set_time_nanos](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_nanos)) to associate logs with other timestamps on other timelines. For example: -code-example: timelines_example +snippet: timelines_example This will add the logged points to the timelines `log_time`, `frame_idx`, and `sensor_time`. You can then choose which timeline you want to organize your data along in the expanded timeline view in the bottom of the Rerun Viewer. diff --git a/docs/content/howto/extend/custom-data.md b/docs/content/howto/extend/custom-data.md index 9b2342ca43bb..564bfef1854d 100644 --- a/docs/content/howto/extend/custom-data.md +++ b/docs/content/howto/extend/custom-data.md @@ -40,7 +40,7 @@ You can also define and log your own custom archetypes and components completely In this example we extend the Rerun Points3D archetype with custom confidence and indicator components. -code-example: custom_data +snippet: custom_data diff --git a/docs/content/howto/open-any-file.md b/docs/content/howto/open-any-file.md index 380bb427d1ce..b1cb45618dfa 100644 --- a/docs/content/howto/open-any-file.md +++ b/docs/content/howto/open-any-file.md @@ -29,7 +29,7 @@ To log the contents of a file from the SDK you can use the `log_file_from_path` Note: when calling these APIs from the SDK, the data will be loaded by the process running the SDK, not the Viewer! -code-example: log-file +snippet: log-file ## Adding support for arbitrary filetypes diff --git a/docs/content/howto/shared-recordings.md b/docs/content/howto/shared-recordings.md index 70f4be2f72c4..582f3caaabdf 100644 --- a/docs/content/howto/shared-recordings.md +++ b/docs/content/howto/shared-recordings.md @@ -12,7 +12,7 @@ All that matter is that they share the same Recording ID. By default, Rerun generates a random Recording ID everytime you start a new logging session, but you can override that behavior, e.g.: -code-example: custom-recording-id +snippet: custom-recording-id It's up to you to decide where each recording ends up: - all processes could stream their share of the data in real-time to a Rerun Viewer, diff --git a/docs/content/howto/using-native-loggers.md b/docs/content/howto/using-native-loggers.md index 133ef25c3251..3dcd8b919038 100644 --- a/docs/content/howto/using-native-loggers.md +++ b/docs/content/howto/using-native-loggers.md @@ -8,7 +8,7 @@ The Rerun SDK implements the native logging interfaces of its supported host lan The details of how to achieve that vary language by language, see the snippets below. -code-example: text_log_integration +snippet: text_log_integration diff --git a/docs/content/reference/migration/migration-0-9.md b/docs/content/reference/migration/migration-0-9.md index 290c64e36f94..3b18d7a4e1d2 100644 --- a/docs/content/reference/migration/migration-0-9.md +++ b/docs/content/reference/migration/migration-0-9.md @@ -16,7 +16,7 @@ API has been replaced by one (or more) new Archetypes. You can find more informa In practice, the changes are mostly demonstrated in the following example: -code-example: log_line +snippet: log_line Note that for any Archetype that supports batching the object names are now plural. For example, points are now logged with the `Points3D` archetype. Even if you are logging a single point, under the hood it is always implemented as a diff --git a/docs/content/reference/sdk-logging-controls.md b/docs/content/reference/sdk-logging-controls.md index 3421823bb301..99d5e5efc03b 100644 --- a/docs/content/reference/sdk-logging-controls.md +++ b/docs/content/reference/sdk-logging-controls.md @@ -24,7 +24,7 @@ The `RERUN` environment variable is read once during SDK initialization. The acc The "default-on" behavior can also be changed to a "default-off" behavior: -code-example: default-off-session +snippet: default-off-session ## Dynamically turn logging on/off diff --git a/docs/content/reference/types/archetypes/annotation_context.md b/docs/content/reference/types/archetypes/annotation_context.md index cb033f0749c0..3dff9cc93a10 100644 --- a/docs/content/reference/types/archetypes/annotation_context.md +++ b/docs/content/reference/types/archetypes/annotation_context.md @@ -23,7 +23,7 @@ path. ### Rectangles -code-example: annotation_context_rects +snippet: annotation_context_rects
@@ -37,7 +37,7 @@ code-example: annotation_context_rects ### Segmentation -code-example: annotation_context_segmentation +snippet: annotation_context_segmentation
@@ -51,7 +51,7 @@ code-example: annotation_context_segmentation ### Connections -code-example: annotation_context_connections +snippet: annotation_context_connections
diff --git a/docs/content/reference/types/archetypes/arrows2d.md b/docs/content/reference/types/archetypes/arrows2d.md index de57d50d492a..b0231ca8b43f 100644 --- a/docs/content/reference/types/archetypes/arrows2d.md +++ b/docs/content/reference/types/archetypes/arrows2d.md @@ -21,7 +21,7 @@ title: "Arrows2D" ### Simple batch of 2D Arrows -code-example: arrow2d_simple +snippet: arrow2d_simple
diff --git a/docs/content/reference/types/archetypes/arrows3d.md b/docs/content/reference/types/archetypes/arrows3d.md index 4c4d3f7a6edf..3699afc0fbb7 100644 --- a/docs/content/reference/types/archetypes/arrows3d.md +++ b/docs/content/reference/types/archetypes/arrows3d.md @@ -21,7 +21,7 @@ title: "Arrows3D" ### Simple batch of 3D Arrows -code-example: arrow3d_simple +snippet: arrow3d_simple
diff --git a/docs/content/reference/types/archetypes/asset3d.md b/docs/content/reference/types/archetypes/asset3d.md index e133d0ee2279..75e5f4188533 100644 --- a/docs/content/reference/types/archetypes/asset3d.md +++ b/docs/content/reference/types/archetypes/asset3d.md @@ -21,7 +21,7 @@ A prepacked 3D asset (`.gltf`, `.glb`, `.obj`, `.stl`, etc.). ### Simple 3D asset -code-example: asset3d_simple +snippet: asset3d_simple
@@ -35,5 +35,5 @@ code-example: asset3d_simple ### 3D asset with out-of-tree transform -code-example: asset3d_out_of_tree +snippet: asset3d_out_of_tree diff --git a/docs/content/reference/types/archetypes/bar_chart.md b/docs/content/reference/types/archetypes/bar_chart.md index fa8c13e47149..5a37a466ff3f 100644 --- a/docs/content/reference/types/archetypes/bar_chart.md +++ b/docs/content/reference/types/archetypes/bar_chart.md @@ -21,7 +21,7 @@ The x values will be the indices of the array, and the bar heights will be the p ### Simple bar chart -code-example: bar_chart +snippet: bar_chart
diff --git a/docs/content/reference/types/archetypes/boxes2d.md b/docs/content/reference/types/archetypes/boxes2d.md index 2c7ec33ef287..5da8ad3f9434 100644 --- a/docs/content/reference/types/archetypes/boxes2d.md +++ b/docs/content/reference/types/archetypes/boxes2d.md @@ -21,7 +21,7 @@ title: "Boxes2D" ### Simple 2D boxes -code-example: box2d_simple +snippet: box2d_simple
diff --git a/docs/content/reference/types/archetypes/boxes3d.md b/docs/content/reference/types/archetypes/boxes3d.md index 74d984ac87c9..741c5c4c7b66 100644 --- a/docs/content/reference/types/archetypes/boxes3d.md +++ b/docs/content/reference/types/archetypes/boxes3d.md @@ -21,7 +21,7 @@ title: "Boxes3D" ### Simple 3D boxes -code-example: box3d_simple +snippet: box3d_simple
@@ -35,7 +35,7 @@ code-example: box3d_simple ### Batch of 3D boxes -code-example: box3d_batch +snippet: box3d_batch
diff --git a/docs/content/reference/types/archetypes/clear.md b/docs/content/reference/types/archetypes/clear.md index 4fb3f64715dc..ef0787e47d1b 100644 --- a/docs/content/reference/types/archetypes/clear.md +++ b/docs/content/reference/types/archetypes/clear.md @@ -27,7 +27,7 @@ data (i.e. discontinuous lines). ### Flat -code-example: clear_simple +snippet: clear_simple
@@ -41,5 +41,5 @@ code-example: clear_simple ### Recursive -code-example: clear_recursive +snippet: clear_recursive diff --git a/docs/content/reference/types/archetypes/depth_image.md b/docs/content/reference/types/archetypes/depth_image.md index 945ec6532ed6..8017e1e822ee 100644 --- a/docs/content/reference/types/archetypes/depth_image.md +++ b/docs/content/reference/types/archetypes/depth_image.md @@ -22,7 +22,7 @@ Each pixel corresponds to a depth value in units specified by `meter`. ### Simple example -code-example: depth_image_simple +snippet: depth_image_simple
@@ -36,7 +36,7 @@ code-example: depth_image_simple ### Depth to 3D example -code-example: depth_image_3d +snippet: depth_image_3d
diff --git a/docs/content/reference/types/archetypes/disconnected_space.md b/docs/content/reference/types/archetypes/disconnected_space.md index 3e446c0e674b..a53a280c0a49 100644 --- a/docs/content/reference/types/archetypes/disconnected_space.md +++ b/docs/content/reference/types/archetypes/disconnected_space.md @@ -22,7 +22,7 @@ This is useful for specifying that a subgraph is independent of the rest of the ### Disconnected Space -code-example: disconnected_space +snippet: disconnected_space
diff --git a/docs/content/reference/types/archetypes/image.md b/docs/content/reference/types/archetypes/image.md index 2ce162be3af0..8e323397c58a 100644 --- a/docs/content/reference/types/archetypes/image.md +++ b/docs/content/reference/types/archetypes/image.md @@ -27,7 +27,7 @@ Leading and trailing unit-dimensions are ignored, so that ### image_simple -code-example: image_simple +snippet: image_simple
diff --git a/docs/content/reference/types/archetypes/line_strips2d.md b/docs/content/reference/types/archetypes/line_strips2d.md index af824655a864..faefdf1201c2 100644 --- a/docs/content/reference/types/archetypes/line_strips2d.md +++ b/docs/content/reference/types/archetypes/line_strips2d.md @@ -21,7 +21,7 @@ title: "LineStrips2D" ### line_strip2d_simple -code-example: line_strip2d_simple +snippet: line_strip2d_simple
@@ -35,7 +35,7 @@ code-example: line_strip2d_simple ### line_segments2d_simple -code-example: line_segments2d_simple +snippet: line_segments2d_simple
@@ -49,7 +49,7 @@ code-example: line_segments2d_simple ### line_strip2d_batch -code-example: line_strip2d_batch +snippet: line_strip2d_batch
diff --git a/docs/content/reference/types/archetypes/line_strips3d.md b/docs/content/reference/types/archetypes/line_strips3d.md index 0614898946d6..a2e8d1dbebaa 100644 --- a/docs/content/reference/types/archetypes/line_strips3d.md +++ b/docs/content/reference/types/archetypes/line_strips3d.md @@ -21,7 +21,7 @@ title: "LineStrips3D" ### Simple example -code-example: line_strip3d_simple +snippet: line_strip3d_simple
@@ -35,7 +35,7 @@ code-example: line_strip3d_simple ### Many individual segments -code-example: line_segments3d_simple +snippet: line_segments3d_simple
@@ -49,7 +49,7 @@ code-example: line_segments3d_simple ### Many strips -code-example: line_strip3d_batch +snippet: line_strip3d_batch
diff --git a/docs/content/reference/types/archetypes/mesh3d.md b/docs/content/reference/types/archetypes/mesh3d.md index 0dd58af4f9e7..4d3c0443a236 100644 --- a/docs/content/reference/types/archetypes/mesh3d.md +++ b/docs/content/reference/types/archetypes/mesh3d.md @@ -21,7 +21,7 @@ A 3D triangle mesh as specified by its per-mesh and per-vertex properties. ### Simple indexed 3D mesh -code-example: mesh3d_indexed +snippet: mesh3d_indexed
@@ -35,7 +35,7 @@ code-example: mesh3d_indexed ### 3D mesh with partial updates -code-example: mesh3d_partial_updates +snippet: mesh3d_partial_updates
diff --git a/docs/content/reference/types/archetypes/pinhole.md b/docs/content/reference/types/archetypes/pinhole.md index f7d0e2b0fdf5..9c124df7762e 100644 --- a/docs/content/reference/types/archetypes/pinhole.md +++ b/docs/content/reference/types/archetypes/pinhole.md @@ -21,7 +21,7 @@ Camera perspective projection (a.k.a. intrinsics). ### Simple Pinhole Camera -code-example: pinhole_simple +snippet: pinhole_simple
@@ -35,7 +35,7 @@ code-example: pinhole_simple ### Perspective Pinhole Camera -code-example: pinhole_perspective +snippet: pinhole_perspective
diff --git a/docs/content/reference/types/archetypes/points2d.md b/docs/content/reference/types/archetypes/points2d.md index 136de1aa2dc1..032d67924eab 100644 --- a/docs/content/reference/types/archetypes/points2d.md +++ b/docs/content/reference/types/archetypes/points2d.md @@ -21,7 +21,7 @@ A 2D point cloud with positions and optional colors, radii, labels, etc. ### Simple 2D points -code-example: point2d_simple +snippet: point2d_simple
@@ -35,7 +35,7 @@ code-example: point2d_simple ### Randomly distributed 2D points with varying color and radius -code-example: point2d_random +snippet: point2d_random
diff --git a/docs/content/reference/types/archetypes/points3d.md b/docs/content/reference/types/archetypes/points3d.md index f084417090cd..e5717824498e 100644 --- a/docs/content/reference/types/archetypes/points3d.md +++ b/docs/content/reference/types/archetypes/points3d.md @@ -21,7 +21,7 @@ A 3D point cloud with positions and optional colors, radii, labels, etc. ### Simple 3D points -code-example: point3d_simple +snippet: point3d_simple
@@ -35,7 +35,7 @@ code-example: point3d_simple ### Randomly distributed 3D points with varying color and radius -code-example: point3d_random +snippet: point3d_random
diff --git a/docs/content/reference/types/archetypes/scalar.md b/docs/content/reference/types/archetypes/scalar.md index 0faef1724e79..246d1f88e8eb 100644 --- a/docs/content/reference/types/archetypes/scalar.md +++ b/docs/content/reference/types/archetypes/scalar.md @@ -25,7 +25,7 @@ the plot-specific archetypes through the blueprint. ### Simple line plot -code-example: scalar_simple +snippet: scalar_simple
@@ -39,7 +39,7 @@ code-example: scalar_simple ### Multiple time series plots -code-example: scalar_multiple_plots +snippet: scalar_multiple_plots
diff --git a/docs/content/reference/types/archetypes/segmentation_image.md b/docs/content/reference/types/archetypes/segmentation_image.md index f093fcb8d15d..39c943f9d5b2 100644 --- a/docs/content/reference/types/archetypes/segmentation_image.md +++ b/docs/content/reference/types/archetypes/segmentation_image.md @@ -28,7 +28,7 @@ Leading and trailing unit-dimensions are ignored, so that ### Simple segmentation image -code-example: segmentation_image_simple +snippet: segmentation_image_simple
diff --git a/docs/content/reference/types/archetypes/series_line.md b/docs/content/reference/types/archetypes/series_line.md index ad4aef8bd2ec..940acd5bca52 100644 --- a/docs/content/reference/types/archetypes/series_line.md +++ b/docs/content/reference/types/archetypes/series_line.md @@ -21,7 +21,7 @@ the `Scalar` archetype. ### Series Line -code-example: series_line_style +snippet: series_line_style
diff --git a/docs/content/reference/types/archetypes/series_point.md b/docs/content/reference/types/archetypes/series_point.md index 6e77a30f87d4..6e3761c346eb 100644 --- a/docs/content/reference/types/archetypes/series_point.md +++ b/docs/content/reference/types/archetypes/series_point.md @@ -21,7 +21,7 @@ the `Scalar` archetype. ### Series Point -code-example: series_point_style +snippet: series_point_style
diff --git a/docs/content/reference/types/archetypes/tensor.md b/docs/content/reference/types/archetypes/tensor.md index ab2a7a436978..a11008eb9fb9 100644 --- a/docs/content/reference/types/archetypes/tensor.md +++ b/docs/content/reference/types/archetypes/tensor.md @@ -17,7 +17,7 @@ A generic n-dimensional Tensor. ### Simple Tensor -code-example: tensor_simple +snippet: tensor_simple
diff --git a/docs/content/reference/types/archetypes/text_document.md b/docs/content/reference/types/archetypes/text_document.md index 80d53aebc46f..a52953b8e34c 100644 --- a/docs/content/reference/types/archetypes/text_document.md +++ b/docs/content/reference/types/archetypes/text_document.md @@ -21,7 +21,7 @@ Supports raw text and markdown. ### Markdown text document -code-example: text_document +snippet: text_document
diff --git a/docs/content/reference/types/archetypes/text_log.md b/docs/content/reference/types/archetypes/text_log.md index be884751fe2d..f3d2506631d9 100644 --- a/docs/content/reference/types/archetypes/text_log.md +++ b/docs/content/reference/types/archetypes/text_log.md @@ -21,7 +21,7 @@ A log entry in a text log, comprised of a text body and its log level. ### text_log_integration -code-example: text_log_integration +snippet: text_log_integration
diff --git a/docs/content/reference/types/archetypes/time_series_scalar.md b/docs/content/reference/types/archetypes/time_series_scalar.md index a25e3a40b550..982a179e99a7 100644 --- a/docs/content/reference/types/archetypes/time_series_scalar.md +++ b/docs/content/reference/types/archetypes/time_series_scalar.md @@ -30,7 +30,7 @@ This archetype is in the process of being deprecated. Prefer usage of ### Simple line plot -code-example: scalar_simple +snippet: scalar_simple
@@ -44,7 +44,7 @@ code-example: scalar_simple ### Multiple time series plots -code-example: scalar_multiple_plots +snippet: scalar_multiple_plots
diff --git a/docs/content/reference/types/archetypes/transform3d.md b/docs/content/reference/types/archetypes/transform3d.md index d94e480c015d..188dfe9c1241 100644 --- a/docs/content/reference/types/archetypes/transform3d.md +++ b/docs/content/reference/types/archetypes/transform3d.md @@ -17,7 +17,7 @@ A 3D transform. ### Variety of 3D transforms -code-example: transform3d_simple +snippet: transform3d_simple
diff --git a/docs/content/reference/types/archetypes/view_coordinates.md b/docs/content/reference/types/archetypes/view_coordinates.md index c456f7652f1e..3277a337ab43 100644 --- a/docs/content/reference/types/archetypes/view_coordinates.md +++ b/docs/content/reference/types/archetypes/view_coordinates.md @@ -24,7 +24,7 @@ down, and the Z axis points forward. ### View coordinates for adjusting the eye camera -code-example: view_coordinates_simple +snippet: view_coordinates_simple
diff --git a/docs/code-examples/CMakeLists.txt b/docs/snippets/CMakeLists.txt similarity index 91% rename from docs/code-examples/CMakeLists.txt rename to docs/snippets/CMakeLists.txt index fc91f67ec1b0..d7dde4a3eaa6 100644 --- a/docs/code-examples/CMakeLists.txt +++ b/docs/snippets/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB sources_list true ${CMAKE_CURRENT_SOURCE_DIR}/all/*.cpp) # TODO(ab): incomplete code, need hideable stubs, see https://github.com/rerun-io/landing/issues/515 list(REMOVE_ITEM sources_list ${CMAKE_CURRENT_SOURCE_DIR}/all/timelines_example.cpp) -add_custom_target(doc_examples) +add_custom_target(snippets) foreach(SOURCE_PATH ${sources_list}) get_filename_component(SOURCE_NAME ${SOURCE_PATH} NAME_WLE) @@ -22,7 +22,7 @@ foreach(SOURCE_PATH ${sources_list}) rerun_strict_warning_settings(${EXAMPLE_TARGET}) target_link_libraries(${EXAMPLE_TARGET} PRIVATE rerun_sdk) - add_dependencies(doc_examples ${EXAMPLE_TARGET}) + add_dependencies(snippets ${EXAMPLE_TARGET}) endforeach() # `text_log_integration` uses `loguru` as the example text logging library. diff --git a/docs/code-examples/Cargo.toml b/docs/snippets/Cargo.toml similarity index 94% rename from docs/code-examples/Cargo.toml rename to docs/snippets/Cargo.toml index a5b4bab365a5..f69cb77e0f25 100644 --- a/docs/code-examples/Cargo.toml +++ b/docs/snippets/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "code_examples" +name = "snippets" version.workspace = true edition.workspace = true rust-version.workspace = true diff --git a/docs/code-examples/README.md b/docs/snippets/README.md similarity index 62% rename from docs/code-examples/README.md rename to docs/snippets/README.md index 708032925555..510d504a6962 100644 --- a/docs/code-examples/README.md +++ b/docs/snippets/README.md @@ -9,22 +9,22 @@ Most of these examples are automatically used as docstrings for the `Archetype` You can run each example individually using the following: - **C++**: - - `pixi run cpp-build-doc-examples` to compile all examples - - `./build/docs/code-examples/all/` to run, e.g. `./build/docs/code-examples/all/point3d_random` + - `pixi run cpp-build-snippets` to compile all examples + - `./build/docs/snippets/all/` to run, e.g. `./build/docs/snippets/all/point3d_random` - **Python**: `python .py`, e.g. `python point3d_random.py`. -- **Rust**: `cargo run -p code_examples -- [args]`, e.g. `cargo run -p code_examples -- point3d_random`. +- **Rust**: `cargo run -p snippets -- [args]`, e.g. `cargo run -p snippets -- point3d_random`. ## Comparison test -The script `compare_code_example_output.py` execute the same logging commands from all 3 SDKs, save the results to distinct rrd files, and finally compare these rrd files. +The script `compare_snippet_output.py` execute the same logging commands from all 3 SDKs, save the results to distinct rrd files, and finally compare these rrd files. These tests are then automatically run by the CI, which will loudly complain if the resulting rrd files don't match. These tests check that A) all of our SDKs yield the exact same data when used the same way and B) act as regression tests, relying on the fact that it is extremely unlikely that all supported languages break in the exact same way at the exact same time. ### Usage -To run the comparison tests, check out `./docs/code-examples/compare_code_example_output.py --help`. -`./docs/code-examples/compare_code_example_output.py` is a valid invocation that will build all 3 SDKs and run all tests for all of them. +To run the comparison tests, check out `./docs/snippets/compare_snippet_output.py --help`. +`./docs/snippets/compare_snippet_output.py` is a valid invocation that will build all 3 SDKs and run all tests for all of them. ### Implementing new tests diff --git a/docs/code-examples/all/annotation-context/example.py b/docs/snippets/all/annotation-context/example.py similarity index 100% rename from docs/code-examples/all/annotation-context/example.py rename to docs/snippets/all/annotation-context/example.py diff --git a/docs/code-examples/all/annotation-context/example.rs b/docs/snippets/all/annotation-context/example.rs similarity index 100% rename from docs/code-examples/all/annotation-context/example.rs rename to docs/snippets/all/annotation-context/example.rs diff --git a/docs/code-examples/all/annotation_context_connections.cpp b/docs/snippets/all/annotation_context_connections.cpp similarity index 100% rename from docs/code-examples/all/annotation_context_connections.cpp rename to docs/snippets/all/annotation_context_connections.cpp diff --git a/docs/code-examples/all/annotation_context_connections.py b/docs/snippets/all/annotation_context_connections.py similarity index 100% rename from docs/code-examples/all/annotation_context_connections.py rename to docs/snippets/all/annotation_context_connections.py diff --git a/docs/code-examples/all/annotation_context_connections.rs b/docs/snippets/all/annotation_context_connections.rs similarity index 100% rename from docs/code-examples/all/annotation_context_connections.rs rename to docs/snippets/all/annotation_context_connections.rs diff --git a/docs/code-examples/all/annotation_context_rects.cpp b/docs/snippets/all/annotation_context_rects.cpp similarity index 100% rename from docs/code-examples/all/annotation_context_rects.cpp rename to docs/snippets/all/annotation_context_rects.cpp diff --git a/docs/code-examples/all/annotation_context_rects.py b/docs/snippets/all/annotation_context_rects.py similarity index 100% rename from docs/code-examples/all/annotation_context_rects.py rename to docs/snippets/all/annotation_context_rects.py diff --git a/docs/code-examples/all/annotation_context_rects.rs b/docs/snippets/all/annotation_context_rects.rs similarity index 100% rename from docs/code-examples/all/annotation_context_rects.rs rename to docs/snippets/all/annotation_context_rects.rs diff --git a/docs/code-examples/all/annotation_context_segmentation.cpp b/docs/snippets/all/annotation_context_segmentation.cpp similarity index 100% rename from docs/code-examples/all/annotation_context_segmentation.cpp rename to docs/snippets/all/annotation_context_segmentation.cpp diff --git a/docs/code-examples/all/annotation_context_segmentation.py b/docs/snippets/all/annotation_context_segmentation.py similarity index 100% rename from docs/code-examples/all/annotation_context_segmentation.py rename to docs/snippets/all/annotation_context_segmentation.py diff --git a/docs/code-examples/all/annotation_context_segmentation.rs b/docs/snippets/all/annotation_context_segmentation.rs similarity index 100% rename from docs/code-examples/all/annotation_context_segmentation.rs rename to docs/snippets/all/annotation_context_segmentation.rs diff --git a/docs/code-examples/all/any_values.py b/docs/snippets/all/any_values.py similarity index 100% rename from docs/code-examples/all/any_values.py rename to docs/snippets/all/any_values.py diff --git a/docs/code-examples/all/arrow2d_simple.cpp b/docs/snippets/all/arrow2d_simple.cpp similarity index 100% rename from docs/code-examples/all/arrow2d_simple.cpp rename to docs/snippets/all/arrow2d_simple.cpp diff --git a/docs/code-examples/all/arrow2d_simple.py b/docs/snippets/all/arrow2d_simple.py similarity index 100% rename from docs/code-examples/all/arrow2d_simple.py rename to docs/snippets/all/arrow2d_simple.py diff --git a/docs/code-examples/all/arrow2d_simple.rs b/docs/snippets/all/arrow2d_simple.rs similarity index 100% rename from docs/code-examples/all/arrow2d_simple.rs rename to docs/snippets/all/arrow2d_simple.rs diff --git a/docs/code-examples/all/arrow3d_simple.cpp b/docs/snippets/all/arrow3d_simple.cpp similarity index 100% rename from docs/code-examples/all/arrow3d_simple.cpp rename to docs/snippets/all/arrow3d_simple.cpp diff --git a/docs/code-examples/all/arrow3d_simple.py b/docs/snippets/all/arrow3d_simple.py similarity index 100% rename from docs/code-examples/all/arrow3d_simple.py rename to docs/snippets/all/arrow3d_simple.py diff --git a/docs/code-examples/all/arrow3d_simple.rs b/docs/snippets/all/arrow3d_simple.rs similarity index 100% rename from docs/code-examples/all/arrow3d_simple.rs rename to docs/snippets/all/arrow3d_simple.rs diff --git a/docs/code-examples/all/asset3d_out_of_tree.cpp b/docs/snippets/all/asset3d_out_of_tree.cpp similarity index 100% rename from docs/code-examples/all/asset3d_out_of_tree.cpp rename to docs/snippets/all/asset3d_out_of_tree.cpp diff --git a/docs/code-examples/all/asset3d_out_of_tree.py b/docs/snippets/all/asset3d_out_of_tree.py similarity index 100% rename from docs/code-examples/all/asset3d_out_of_tree.py rename to docs/snippets/all/asset3d_out_of_tree.py diff --git a/docs/code-examples/all/asset3d_out_of_tree.rs b/docs/snippets/all/asset3d_out_of_tree.rs similarity index 100% rename from docs/code-examples/all/asset3d_out_of_tree.rs rename to docs/snippets/all/asset3d_out_of_tree.rs diff --git a/docs/code-examples/all/asset3d_simple.cpp b/docs/snippets/all/asset3d_simple.cpp similarity index 100% rename from docs/code-examples/all/asset3d_simple.cpp rename to docs/snippets/all/asset3d_simple.cpp diff --git a/docs/code-examples/all/asset3d_simple.py b/docs/snippets/all/asset3d_simple.py similarity index 100% rename from docs/code-examples/all/asset3d_simple.py rename to docs/snippets/all/asset3d_simple.py diff --git a/docs/code-examples/all/asset3d_simple.rs b/docs/snippets/all/asset3d_simple.rs similarity index 100% rename from docs/code-examples/all/asset3d_simple.rs rename to docs/snippets/all/asset3d_simple.rs diff --git a/docs/code-examples/all/bar_chart.cpp b/docs/snippets/all/bar_chart.cpp similarity index 100% rename from docs/code-examples/all/bar_chart.cpp rename to docs/snippets/all/bar_chart.cpp diff --git a/docs/code-examples/all/bar_chart.py b/docs/snippets/all/bar_chart.py similarity index 100% rename from docs/code-examples/all/bar_chart.py rename to docs/snippets/all/bar_chart.py diff --git a/docs/code-examples/all/bar_chart.rs b/docs/snippets/all/bar_chart.rs similarity index 100% rename from docs/code-examples/all/bar_chart.rs rename to docs/snippets/all/bar_chart.rs diff --git a/docs/code-examples/all/box2d_simple.cpp b/docs/snippets/all/box2d_simple.cpp similarity index 100% rename from docs/code-examples/all/box2d_simple.cpp rename to docs/snippets/all/box2d_simple.cpp diff --git a/docs/code-examples/all/box2d_simple.py b/docs/snippets/all/box2d_simple.py similarity index 100% rename from docs/code-examples/all/box2d_simple.py rename to docs/snippets/all/box2d_simple.py diff --git a/docs/code-examples/all/box2d_simple.rs b/docs/snippets/all/box2d_simple.rs similarity index 100% rename from docs/code-examples/all/box2d_simple.rs rename to docs/snippets/all/box2d_simple.rs diff --git a/docs/code-examples/all/box3d_batch.cpp b/docs/snippets/all/box3d_batch.cpp similarity index 100% rename from docs/code-examples/all/box3d_batch.cpp rename to docs/snippets/all/box3d_batch.cpp diff --git a/docs/code-examples/all/box3d_batch.py b/docs/snippets/all/box3d_batch.py similarity index 100% rename from docs/code-examples/all/box3d_batch.py rename to docs/snippets/all/box3d_batch.py diff --git a/docs/code-examples/all/box3d_batch.rs b/docs/snippets/all/box3d_batch.rs similarity index 100% rename from docs/code-examples/all/box3d_batch.rs rename to docs/snippets/all/box3d_batch.rs diff --git a/docs/code-examples/all/box3d_simple.cpp b/docs/snippets/all/box3d_simple.cpp similarity index 100% rename from docs/code-examples/all/box3d_simple.cpp rename to docs/snippets/all/box3d_simple.cpp diff --git a/docs/code-examples/all/box3d_simple.py b/docs/snippets/all/box3d_simple.py similarity index 100% rename from docs/code-examples/all/box3d_simple.py rename to docs/snippets/all/box3d_simple.py diff --git a/docs/code-examples/all/box3d_simple.rs b/docs/snippets/all/box3d_simple.rs similarity index 100% rename from docs/code-examples/all/box3d_simple.rs rename to docs/snippets/all/box3d_simple.rs diff --git a/docs/code-examples/all/clear_recursive.cpp b/docs/snippets/all/clear_recursive.cpp similarity index 100% rename from docs/code-examples/all/clear_recursive.cpp rename to docs/snippets/all/clear_recursive.cpp diff --git a/docs/code-examples/all/clear_recursive.py b/docs/snippets/all/clear_recursive.py similarity index 100% rename from docs/code-examples/all/clear_recursive.py rename to docs/snippets/all/clear_recursive.py diff --git a/docs/code-examples/all/clear_recursive.rs b/docs/snippets/all/clear_recursive.rs similarity index 100% rename from docs/code-examples/all/clear_recursive.rs rename to docs/snippets/all/clear_recursive.rs diff --git a/docs/code-examples/all/clear_simple.cpp b/docs/snippets/all/clear_simple.cpp similarity index 100% rename from docs/code-examples/all/clear_simple.cpp rename to docs/snippets/all/clear_simple.cpp diff --git a/docs/code-examples/all/clear_simple.py b/docs/snippets/all/clear_simple.py similarity index 100% rename from docs/code-examples/all/clear_simple.py rename to docs/snippets/all/clear_simple.py diff --git a/docs/code-examples/all/clear_simple.rs b/docs/snippets/all/clear_simple.rs similarity index 100% rename from docs/code-examples/all/clear_simple.rs rename to docs/snippets/all/clear_simple.rs diff --git a/docs/code-examples/all/custom-recording-id/example.cpp b/docs/snippets/all/custom-recording-id/example.cpp similarity index 100% rename from docs/code-examples/all/custom-recording-id/example.cpp rename to docs/snippets/all/custom-recording-id/example.cpp diff --git a/docs/code-examples/all/custom-recording-id/example.py b/docs/snippets/all/custom-recording-id/example.py similarity index 100% rename from docs/code-examples/all/custom-recording-id/example.py rename to docs/snippets/all/custom-recording-id/example.py diff --git a/docs/code-examples/all/custom-recording-id/example.rs b/docs/snippets/all/custom-recording-id/example.rs similarity index 100% rename from docs/code-examples/all/custom-recording-id/example.rs rename to docs/snippets/all/custom-recording-id/example.rs diff --git a/docs/code-examples/all/custom_data.cpp b/docs/snippets/all/custom_data.cpp similarity index 100% rename from docs/code-examples/all/custom_data.cpp rename to docs/snippets/all/custom_data.cpp diff --git a/docs/code-examples/all/custom_data.py b/docs/snippets/all/custom_data.py similarity index 100% rename from docs/code-examples/all/custom_data.py rename to docs/snippets/all/custom_data.py diff --git a/docs/code-examples/all/custom_data.rs b/docs/snippets/all/custom_data.rs similarity index 100% rename from docs/code-examples/all/custom_data.rs rename to docs/snippets/all/custom_data.rs diff --git a/docs/code-examples/all/default-off-session/example.py b/docs/snippets/all/default-off-session/example.py similarity index 100% rename from docs/code-examples/all/default-off-session/example.py rename to docs/snippets/all/default-off-session/example.py diff --git a/docs/code-examples/all/default-off-session/example.rs b/docs/snippets/all/default-off-session/example.rs similarity index 100% rename from docs/code-examples/all/default-off-session/example.rs rename to docs/snippets/all/default-off-session/example.rs diff --git a/docs/code-examples/all/depth_image_3d.cpp b/docs/snippets/all/depth_image_3d.cpp similarity index 100% rename from docs/code-examples/all/depth_image_3d.cpp rename to docs/snippets/all/depth_image_3d.cpp diff --git a/docs/code-examples/all/depth_image_3d.py b/docs/snippets/all/depth_image_3d.py similarity index 100% rename from docs/code-examples/all/depth_image_3d.py rename to docs/snippets/all/depth_image_3d.py diff --git a/docs/code-examples/all/depth_image_3d.rs b/docs/snippets/all/depth_image_3d.rs similarity index 100% rename from docs/code-examples/all/depth_image_3d.rs rename to docs/snippets/all/depth_image_3d.rs diff --git a/docs/code-examples/all/depth_image_simple.cpp b/docs/snippets/all/depth_image_simple.cpp similarity index 100% rename from docs/code-examples/all/depth_image_simple.cpp rename to docs/snippets/all/depth_image_simple.cpp diff --git a/docs/code-examples/all/depth_image_simple.py b/docs/snippets/all/depth_image_simple.py similarity index 100% rename from docs/code-examples/all/depth_image_simple.py rename to docs/snippets/all/depth_image_simple.py diff --git a/docs/code-examples/all/depth_image_simple.rs b/docs/snippets/all/depth_image_simple.rs similarity index 100% rename from docs/code-examples/all/depth_image_simple.rs rename to docs/snippets/all/depth_image_simple.rs diff --git a/docs/code-examples/all/disconnected_space.cpp b/docs/snippets/all/disconnected_space.cpp similarity index 100% rename from docs/code-examples/all/disconnected_space.cpp rename to docs/snippets/all/disconnected_space.cpp diff --git a/docs/code-examples/all/disconnected_space.py b/docs/snippets/all/disconnected_space.py similarity index 100% rename from docs/code-examples/all/disconnected_space.py rename to docs/snippets/all/disconnected_space.py diff --git a/docs/code-examples/all/disconnected_space.rs b/docs/snippets/all/disconnected_space.rs similarity index 100% rename from docs/code-examples/all/disconnected_space.rs rename to docs/snippets/all/disconnected_space.rs diff --git a/docs/code-examples/all/entity_path.cpp b/docs/snippets/all/entity_path.cpp similarity index 100% rename from docs/code-examples/all/entity_path.cpp rename to docs/snippets/all/entity_path.cpp diff --git a/docs/code-examples/all/entity_path.py b/docs/snippets/all/entity_path.py similarity index 100% rename from docs/code-examples/all/entity_path.py rename to docs/snippets/all/entity_path.py diff --git a/docs/code-examples/all/entity_path.rs b/docs/snippets/all/entity_path.rs similarity index 100% rename from docs/code-examples/all/entity_path.rs rename to docs/snippets/all/entity_path.rs diff --git a/docs/code-examples/all/extra_values.py b/docs/snippets/all/extra_values.py similarity index 100% rename from docs/code-examples/all/extra_values.py rename to docs/snippets/all/extra_values.py diff --git a/docs/code-examples/all/image_advanced.py b/docs/snippets/all/image_advanced.py similarity index 100% rename from docs/code-examples/all/image_advanced.py rename to docs/snippets/all/image_advanced.py diff --git a/docs/code-examples/all/image_simple.cpp b/docs/snippets/all/image_simple.cpp similarity index 100% rename from docs/code-examples/all/image_simple.cpp rename to docs/snippets/all/image_simple.cpp diff --git a/docs/code-examples/all/image_simple.py b/docs/snippets/all/image_simple.py similarity index 100% rename from docs/code-examples/all/image_simple.py rename to docs/snippets/all/image_simple.py diff --git a/docs/code-examples/all/image_simple.rs b/docs/snippets/all/image_simple.rs similarity index 100% rename from docs/code-examples/all/image_simple.rs rename to docs/snippets/all/image_simple.rs diff --git a/docs/code-examples/all/line_segments2d_simple.cpp b/docs/snippets/all/line_segments2d_simple.cpp similarity index 100% rename from docs/code-examples/all/line_segments2d_simple.cpp rename to docs/snippets/all/line_segments2d_simple.cpp diff --git a/docs/code-examples/all/line_segments2d_simple.py b/docs/snippets/all/line_segments2d_simple.py similarity index 100% rename from docs/code-examples/all/line_segments2d_simple.py rename to docs/snippets/all/line_segments2d_simple.py diff --git a/docs/code-examples/all/line_segments2d_simple.rs b/docs/snippets/all/line_segments2d_simple.rs similarity index 100% rename from docs/code-examples/all/line_segments2d_simple.rs rename to docs/snippets/all/line_segments2d_simple.rs diff --git a/docs/code-examples/all/line_segments3d_simple.cpp b/docs/snippets/all/line_segments3d_simple.cpp similarity index 100% rename from docs/code-examples/all/line_segments3d_simple.cpp rename to docs/snippets/all/line_segments3d_simple.cpp diff --git a/docs/code-examples/all/line_segments3d_simple.py b/docs/snippets/all/line_segments3d_simple.py similarity index 100% rename from docs/code-examples/all/line_segments3d_simple.py rename to docs/snippets/all/line_segments3d_simple.py diff --git a/docs/code-examples/all/line_segments3d_simple.rs b/docs/snippets/all/line_segments3d_simple.rs similarity index 100% rename from docs/code-examples/all/line_segments3d_simple.rs rename to docs/snippets/all/line_segments3d_simple.rs diff --git a/docs/code-examples/all/line_strip2d_batch.cpp b/docs/snippets/all/line_strip2d_batch.cpp similarity index 100% rename from docs/code-examples/all/line_strip2d_batch.cpp rename to docs/snippets/all/line_strip2d_batch.cpp diff --git a/docs/code-examples/all/line_strip2d_batch.py b/docs/snippets/all/line_strip2d_batch.py similarity index 100% rename from docs/code-examples/all/line_strip2d_batch.py rename to docs/snippets/all/line_strip2d_batch.py diff --git a/docs/code-examples/all/line_strip2d_batch.rs b/docs/snippets/all/line_strip2d_batch.rs similarity index 100% rename from docs/code-examples/all/line_strip2d_batch.rs rename to docs/snippets/all/line_strip2d_batch.rs diff --git a/docs/code-examples/all/line_strip2d_simple.cpp b/docs/snippets/all/line_strip2d_simple.cpp similarity index 100% rename from docs/code-examples/all/line_strip2d_simple.cpp rename to docs/snippets/all/line_strip2d_simple.cpp diff --git a/docs/code-examples/all/line_strip2d_simple.py b/docs/snippets/all/line_strip2d_simple.py similarity index 100% rename from docs/code-examples/all/line_strip2d_simple.py rename to docs/snippets/all/line_strip2d_simple.py diff --git a/docs/code-examples/all/line_strip2d_simple.rs b/docs/snippets/all/line_strip2d_simple.rs similarity index 100% rename from docs/code-examples/all/line_strip2d_simple.rs rename to docs/snippets/all/line_strip2d_simple.rs diff --git a/docs/code-examples/all/line_strip3d_batch.cpp b/docs/snippets/all/line_strip3d_batch.cpp similarity index 100% rename from docs/code-examples/all/line_strip3d_batch.cpp rename to docs/snippets/all/line_strip3d_batch.cpp diff --git a/docs/code-examples/all/line_strip3d_batch.py b/docs/snippets/all/line_strip3d_batch.py similarity index 100% rename from docs/code-examples/all/line_strip3d_batch.py rename to docs/snippets/all/line_strip3d_batch.py diff --git a/docs/code-examples/all/line_strip3d_batch.rs b/docs/snippets/all/line_strip3d_batch.rs similarity index 100% rename from docs/code-examples/all/line_strip3d_batch.rs rename to docs/snippets/all/line_strip3d_batch.rs diff --git a/docs/code-examples/all/line_strip3d_simple.cpp b/docs/snippets/all/line_strip3d_simple.cpp similarity index 100% rename from docs/code-examples/all/line_strip3d_simple.cpp rename to docs/snippets/all/line_strip3d_simple.cpp diff --git a/docs/code-examples/all/line_strip3d_simple.py b/docs/snippets/all/line_strip3d_simple.py similarity index 100% rename from docs/code-examples/all/line_strip3d_simple.py rename to docs/snippets/all/line_strip3d_simple.py diff --git a/docs/code-examples/all/line_strip3d_simple.rs b/docs/snippets/all/line_strip3d_simple.rs similarity index 100% rename from docs/code-examples/all/line_strip3d_simple.rs rename to docs/snippets/all/line_strip3d_simple.rs diff --git a/docs/code-examples/all/log-file/example.cpp b/docs/snippets/all/log-file/example.cpp similarity index 100% rename from docs/code-examples/all/log-file/example.cpp rename to docs/snippets/all/log-file/example.cpp diff --git a/docs/code-examples/all/log-file/example.py b/docs/snippets/all/log-file/example.py similarity index 100% rename from docs/code-examples/all/log-file/example.py rename to docs/snippets/all/log-file/example.py diff --git a/docs/code-examples/all/log-file/example.rs b/docs/snippets/all/log-file/example.rs similarity index 100% rename from docs/code-examples/all/log-file/example.rs rename to docs/snippets/all/log-file/example.rs diff --git a/docs/code-examples/all/log_line.py b/docs/snippets/all/log_line.py similarity index 100% rename from docs/code-examples/all/log_line.py rename to docs/snippets/all/log_line.py diff --git a/docs/code-examples/all/log_line.rs b/docs/snippets/all/log_line.rs similarity index 100% rename from docs/code-examples/all/log_line.rs rename to docs/snippets/all/log_line.rs diff --git a/docs/code-examples/all/manual_indicator.cpp b/docs/snippets/all/manual_indicator.cpp similarity index 100% rename from docs/code-examples/all/manual_indicator.cpp rename to docs/snippets/all/manual_indicator.cpp diff --git a/docs/code-examples/all/manual_indicator.py b/docs/snippets/all/manual_indicator.py similarity index 100% rename from docs/code-examples/all/manual_indicator.py rename to docs/snippets/all/manual_indicator.py diff --git a/docs/code-examples/all/manual_indicator.rs b/docs/snippets/all/manual_indicator.rs similarity index 100% rename from docs/code-examples/all/manual_indicator.rs rename to docs/snippets/all/manual_indicator.rs diff --git a/docs/code-examples/all/mesh3d_indexed.cpp b/docs/snippets/all/mesh3d_indexed.cpp similarity index 100% rename from docs/code-examples/all/mesh3d_indexed.cpp rename to docs/snippets/all/mesh3d_indexed.cpp diff --git a/docs/code-examples/all/mesh3d_indexed.py b/docs/snippets/all/mesh3d_indexed.py similarity index 100% rename from docs/code-examples/all/mesh3d_indexed.py rename to docs/snippets/all/mesh3d_indexed.py diff --git a/docs/code-examples/all/mesh3d_indexed.rs b/docs/snippets/all/mesh3d_indexed.rs similarity index 100% rename from docs/code-examples/all/mesh3d_indexed.rs rename to docs/snippets/all/mesh3d_indexed.rs diff --git a/docs/code-examples/all/mesh3d_partial_updates.cpp b/docs/snippets/all/mesh3d_partial_updates.cpp similarity index 100% rename from docs/code-examples/all/mesh3d_partial_updates.cpp rename to docs/snippets/all/mesh3d_partial_updates.cpp diff --git a/docs/code-examples/all/mesh3d_partial_updates.py b/docs/snippets/all/mesh3d_partial_updates.py similarity index 100% rename from docs/code-examples/all/mesh3d_partial_updates.py rename to docs/snippets/all/mesh3d_partial_updates.py diff --git a/docs/code-examples/all/mesh3d_partial_updates.rs b/docs/snippets/all/mesh3d_partial_updates.rs similarity index 100% rename from docs/code-examples/all/mesh3d_partial_updates.rs rename to docs/snippets/all/mesh3d_partial_updates.rs diff --git a/docs/code-examples/all/mesh3d_simple.cpp b/docs/snippets/all/mesh3d_simple.cpp similarity index 100% rename from docs/code-examples/all/mesh3d_simple.cpp rename to docs/snippets/all/mesh3d_simple.cpp diff --git a/docs/code-examples/all/mesh3d_simple.py b/docs/snippets/all/mesh3d_simple.py similarity index 100% rename from docs/code-examples/all/mesh3d_simple.py rename to docs/snippets/all/mesh3d_simple.py diff --git a/docs/code-examples/all/mesh3d_simple.rs b/docs/snippets/all/mesh3d_simple.rs similarity index 100% rename from docs/code-examples/all/mesh3d_simple.rs rename to docs/snippets/all/mesh3d_simple.rs diff --git a/docs/code-examples/all/pinhole_perspective.cpp b/docs/snippets/all/pinhole_perspective.cpp similarity index 100% rename from docs/code-examples/all/pinhole_perspective.cpp rename to docs/snippets/all/pinhole_perspective.cpp diff --git a/docs/code-examples/all/pinhole_perspective.py b/docs/snippets/all/pinhole_perspective.py similarity index 100% rename from docs/code-examples/all/pinhole_perspective.py rename to docs/snippets/all/pinhole_perspective.py diff --git a/docs/code-examples/all/pinhole_perspective.rs b/docs/snippets/all/pinhole_perspective.rs similarity index 100% rename from docs/code-examples/all/pinhole_perspective.rs rename to docs/snippets/all/pinhole_perspective.rs diff --git a/docs/code-examples/all/pinhole_simple.cpp b/docs/snippets/all/pinhole_simple.cpp similarity index 100% rename from docs/code-examples/all/pinhole_simple.cpp rename to docs/snippets/all/pinhole_simple.cpp diff --git a/docs/code-examples/all/pinhole_simple.py b/docs/snippets/all/pinhole_simple.py similarity index 100% rename from docs/code-examples/all/pinhole_simple.py rename to docs/snippets/all/pinhole_simple.py diff --git a/docs/code-examples/all/pinhole_simple.rs b/docs/snippets/all/pinhole_simple.rs similarity index 100% rename from docs/code-examples/all/pinhole_simple.rs rename to docs/snippets/all/pinhole_simple.rs diff --git a/docs/code-examples/all/point2d_random.cpp b/docs/snippets/all/point2d_random.cpp similarity index 100% rename from docs/code-examples/all/point2d_random.cpp rename to docs/snippets/all/point2d_random.cpp diff --git a/docs/code-examples/all/point2d_random.py b/docs/snippets/all/point2d_random.py similarity index 100% rename from docs/code-examples/all/point2d_random.py rename to docs/snippets/all/point2d_random.py diff --git a/docs/code-examples/all/point2d_random.rs b/docs/snippets/all/point2d_random.rs similarity index 100% rename from docs/code-examples/all/point2d_random.rs rename to docs/snippets/all/point2d_random.rs diff --git a/docs/code-examples/all/point2d_simple.cpp b/docs/snippets/all/point2d_simple.cpp similarity index 100% rename from docs/code-examples/all/point2d_simple.cpp rename to docs/snippets/all/point2d_simple.cpp diff --git a/docs/code-examples/all/point2d_simple.py b/docs/snippets/all/point2d_simple.py similarity index 100% rename from docs/code-examples/all/point2d_simple.py rename to docs/snippets/all/point2d_simple.py diff --git a/docs/code-examples/all/point2d_simple.rs b/docs/snippets/all/point2d_simple.rs similarity index 100% rename from docs/code-examples/all/point2d_simple.rs rename to docs/snippets/all/point2d_simple.rs diff --git a/docs/code-examples/all/point3d_random.cpp b/docs/snippets/all/point3d_random.cpp similarity index 100% rename from docs/code-examples/all/point3d_random.cpp rename to docs/snippets/all/point3d_random.cpp diff --git a/docs/code-examples/all/point3d_random.py b/docs/snippets/all/point3d_random.py similarity index 100% rename from docs/code-examples/all/point3d_random.py rename to docs/snippets/all/point3d_random.py diff --git a/docs/code-examples/all/point3d_random.rs b/docs/snippets/all/point3d_random.rs similarity index 100% rename from docs/code-examples/all/point3d_random.rs rename to docs/snippets/all/point3d_random.rs diff --git a/docs/code-examples/all/point3d_simple.cpp b/docs/snippets/all/point3d_simple.cpp similarity index 100% rename from docs/code-examples/all/point3d_simple.cpp rename to docs/snippets/all/point3d_simple.cpp diff --git a/docs/code-examples/all/point3d_simple.py b/docs/snippets/all/point3d_simple.py similarity index 100% rename from docs/code-examples/all/point3d_simple.py rename to docs/snippets/all/point3d_simple.py diff --git a/docs/code-examples/all/point3d_simple.rs b/docs/snippets/all/point3d_simple.rs similarity index 100% rename from docs/code-examples/all/point3d_simple.rs rename to docs/snippets/all/point3d_simple.rs diff --git a/docs/code-examples/all/quick_start_connect.cpp b/docs/snippets/all/quick_start_connect.cpp similarity index 100% rename from docs/code-examples/all/quick_start_connect.cpp rename to docs/snippets/all/quick_start_connect.cpp diff --git a/docs/code-examples/all/quick_start_connect.py b/docs/snippets/all/quick_start_connect.py similarity index 100% rename from docs/code-examples/all/quick_start_connect.py rename to docs/snippets/all/quick_start_connect.py diff --git a/docs/code-examples/all/quick_start_connect.rs b/docs/snippets/all/quick_start_connect.rs similarity index 100% rename from docs/code-examples/all/quick_start_connect.rs rename to docs/snippets/all/quick_start_connect.rs diff --git a/docs/code-examples/all/quick_start_spawn.cpp b/docs/snippets/all/quick_start_spawn.cpp similarity index 100% rename from docs/code-examples/all/quick_start_spawn.cpp rename to docs/snippets/all/quick_start_spawn.cpp diff --git a/docs/code-examples/all/quick_start_spawn.py b/docs/snippets/all/quick_start_spawn.py similarity index 100% rename from docs/code-examples/all/quick_start_spawn.py rename to docs/snippets/all/quick_start_spawn.py diff --git a/docs/code-examples/all/quick_start_spawn.rs b/docs/snippets/all/quick_start_spawn.rs similarity index 100% rename from docs/code-examples/all/quick_start_spawn.rs rename to docs/snippets/all/quick_start_spawn.rs diff --git a/docs/code-examples/all/scalar_multiple_plots.cpp b/docs/snippets/all/scalar_multiple_plots.cpp similarity index 100% rename from docs/code-examples/all/scalar_multiple_plots.cpp rename to docs/snippets/all/scalar_multiple_plots.cpp diff --git a/docs/code-examples/all/scalar_multiple_plots.py b/docs/snippets/all/scalar_multiple_plots.py similarity index 100% rename from docs/code-examples/all/scalar_multiple_plots.py rename to docs/snippets/all/scalar_multiple_plots.py diff --git a/docs/code-examples/all/scalar_multiple_plots.rs b/docs/snippets/all/scalar_multiple_plots.rs similarity index 100% rename from docs/code-examples/all/scalar_multiple_plots.rs rename to docs/snippets/all/scalar_multiple_plots.rs diff --git a/docs/code-examples/all/scalar_simple.cpp b/docs/snippets/all/scalar_simple.cpp similarity index 100% rename from docs/code-examples/all/scalar_simple.cpp rename to docs/snippets/all/scalar_simple.cpp diff --git a/docs/code-examples/all/scalar_simple.py b/docs/snippets/all/scalar_simple.py similarity index 100% rename from docs/code-examples/all/scalar_simple.py rename to docs/snippets/all/scalar_simple.py diff --git a/docs/code-examples/all/scalar_simple.rs b/docs/snippets/all/scalar_simple.rs similarity index 100% rename from docs/code-examples/all/scalar_simple.rs rename to docs/snippets/all/scalar_simple.rs diff --git a/docs/code-examples/all/segmentation_image_simple.cpp b/docs/snippets/all/segmentation_image_simple.cpp similarity index 100% rename from docs/code-examples/all/segmentation_image_simple.cpp rename to docs/snippets/all/segmentation_image_simple.cpp diff --git a/docs/code-examples/all/segmentation_image_simple.py b/docs/snippets/all/segmentation_image_simple.py similarity index 100% rename from docs/code-examples/all/segmentation_image_simple.py rename to docs/snippets/all/segmentation_image_simple.py diff --git a/docs/code-examples/all/segmentation_image_simple.rs b/docs/snippets/all/segmentation_image_simple.rs similarity index 100% rename from docs/code-examples/all/segmentation_image_simple.rs rename to docs/snippets/all/segmentation_image_simple.rs diff --git a/docs/code-examples/all/series_line_style.cpp b/docs/snippets/all/series_line_style.cpp similarity index 100% rename from docs/code-examples/all/series_line_style.cpp rename to docs/snippets/all/series_line_style.cpp diff --git a/docs/code-examples/all/series_line_style.py b/docs/snippets/all/series_line_style.py similarity index 100% rename from docs/code-examples/all/series_line_style.py rename to docs/snippets/all/series_line_style.py diff --git a/docs/code-examples/all/series_line_style.rs b/docs/snippets/all/series_line_style.rs similarity index 100% rename from docs/code-examples/all/series_line_style.rs rename to docs/snippets/all/series_line_style.rs diff --git a/docs/code-examples/all/series_point_style.cpp b/docs/snippets/all/series_point_style.cpp similarity index 100% rename from docs/code-examples/all/series_point_style.cpp rename to docs/snippets/all/series_point_style.cpp diff --git a/docs/code-examples/all/series_point_style.py b/docs/snippets/all/series_point_style.py similarity index 100% rename from docs/code-examples/all/series_point_style.py rename to docs/snippets/all/series_point_style.py diff --git a/docs/code-examples/all/series_point_style.rs b/docs/snippets/all/series_point_style.rs similarity index 100% rename from docs/code-examples/all/series_point_style.rs rename to docs/snippets/all/series_point_style.rs diff --git a/docs/code-examples/all/tensor_simple.cpp b/docs/snippets/all/tensor_simple.cpp similarity index 100% rename from docs/code-examples/all/tensor_simple.cpp rename to docs/snippets/all/tensor_simple.cpp diff --git a/docs/code-examples/all/tensor_simple.py b/docs/snippets/all/tensor_simple.py similarity index 100% rename from docs/code-examples/all/tensor_simple.py rename to docs/snippets/all/tensor_simple.py diff --git a/docs/code-examples/all/tensor_simple.rs b/docs/snippets/all/tensor_simple.rs similarity index 100% rename from docs/code-examples/all/tensor_simple.rs rename to docs/snippets/all/tensor_simple.rs diff --git a/docs/code-examples/all/text_document.cpp b/docs/snippets/all/text_document.cpp similarity index 100% rename from docs/code-examples/all/text_document.cpp rename to docs/snippets/all/text_document.cpp diff --git a/docs/code-examples/all/text_document.py b/docs/snippets/all/text_document.py similarity index 100% rename from docs/code-examples/all/text_document.py rename to docs/snippets/all/text_document.py diff --git a/docs/code-examples/all/text_document.rs b/docs/snippets/all/text_document.rs similarity index 100% rename from docs/code-examples/all/text_document.rs rename to docs/snippets/all/text_document.rs diff --git a/docs/code-examples/all/text_log.cpp b/docs/snippets/all/text_log.cpp similarity index 100% rename from docs/code-examples/all/text_log.cpp rename to docs/snippets/all/text_log.cpp diff --git a/docs/code-examples/all/text_log.py b/docs/snippets/all/text_log.py similarity index 100% rename from docs/code-examples/all/text_log.py rename to docs/snippets/all/text_log.py diff --git a/docs/code-examples/all/text_log.rs b/docs/snippets/all/text_log.rs similarity index 100% rename from docs/code-examples/all/text_log.rs rename to docs/snippets/all/text_log.rs diff --git a/docs/code-examples/all/text_log_integration.cpp b/docs/snippets/all/text_log_integration.cpp similarity index 100% rename from docs/code-examples/all/text_log_integration.cpp rename to docs/snippets/all/text_log_integration.cpp diff --git a/docs/code-examples/all/text_log_integration.py b/docs/snippets/all/text_log_integration.py similarity index 100% rename from docs/code-examples/all/text_log_integration.py rename to docs/snippets/all/text_log_integration.py diff --git a/docs/code-examples/all/text_log_integration.rs b/docs/snippets/all/text_log_integration.rs similarity index 100% rename from docs/code-examples/all/text_log_integration.rs rename to docs/snippets/all/text_log_integration.rs diff --git a/docs/code-examples/all/timelines_example.cpp b/docs/snippets/all/timelines_example.cpp similarity index 100% rename from docs/code-examples/all/timelines_example.cpp rename to docs/snippets/all/timelines_example.cpp diff --git a/docs/code-examples/all/timelines_example.py b/docs/snippets/all/timelines_example.py similarity index 100% rename from docs/code-examples/all/timelines_example.py rename to docs/snippets/all/timelines_example.py diff --git a/docs/code-examples/all/timelines_example.rs b/docs/snippets/all/timelines_example.rs similarity index 100% rename from docs/code-examples/all/timelines_example.rs rename to docs/snippets/all/timelines_example.rs diff --git a/docs/code-examples/all/transform3d_simple.cpp b/docs/snippets/all/transform3d_simple.cpp similarity index 100% rename from docs/code-examples/all/transform3d_simple.cpp rename to docs/snippets/all/transform3d_simple.cpp diff --git a/docs/code-examples/all/transform3d_simple.py b/docs/snippets/all/transform3d_simple.py similarity index 100% rename from docs/code-examples/all/transform3d_simple.py rename to docs/snippets/all/transform3d_simple.py diff --git a/docs/code-examples/all/transform3d_simple.rs b/docs/snippets/all/transform3d_simple.rs similarity index 100% rename from docs/code-examples/all/transform3d_simple.rs rename to docs/snippets/all/transform3d_simple.rs diff --git a/docs/code-examples/all/view_coordinates_simple.cpp b/docs/snippets/all/view_coordinates_simple.cpp similarity index 100% rename from docs/code-examples/all/view_coordinates_simple.cpp rename to docs/snippets/all/view_coordinates_simple.cpp diff --git a/docs/code-examples/all/view_coordinates_simple.py b/docs/snippets/all/view_coordinates_simple.py similarity index 100% rename from docs/code-examples/all/view_coordinates_simple.py rename to docs/snippets/all/view_coordinates_simple.py diff --git a/docs/code-examples/all/view_coordinates_simple.rs b/docs/snippets/all/view_coordinates_simple.rs similarity index 100% rename from docs/code-examples/all/view_coordinates_simple.rs rename to docs/snippets/all/view_coordinates_simple.rs diff --git a/docs/code-examples/build.rs b/docs/snippets/build.rs similarity index 98% rename from docs/code-examples/build.rs rename to docs/snippets/build.rs index 485dd44e612d..ca96022f5515 100644 --- a/docs/code-examples/build.rs +++ b/docs/snippets/build.rs @@ -1,4 +1,4 @@ -//! Finds all the `*.rs` files in `docs/code-examples/all`, +//! Finds all the `*.rs` files in `docs/snippets/all`, //! copies them to `src/examples` (with slight modifications), and generate a `examples/mod.rs` for them. //! //! The reason we combine all the examples into a single binary diff --git a/docs/code-examples/compare_code_example_output.py b/docs/snippets/compare_snippet_output.py similarity index 67% rename from docs/code-examples/compare_code_example_output.py rename to docs/snippets/compare_snippet_output.py index fb0372a736f7..87636afe74a8 100755 --- a/docs/code-examples/compare_code_example_output.py +++ b/docs/snippets/compare_snippet_output.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -"""Runs all our code-examples, for all our languages, and compares the .rrd they output.""" +"""Runs all our snippets, for all our languages, and compares the .rrd they output.""" from __future__ import annotations @@ -11,54 +11,27 @@ import time from os import listdir from os.path import isfile, join +from pathlib import Path + +import tomlkit sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../../scripts/") from roundtrip_utils import roundtrip_env, run, run_comparison # noqa -# fmt: off - -# These entries won't run at all. -# -# You should only ever use this if the test isn't implemented and cannot yet be implemented -# for one or more specific SDKs. -opt_out_run = { - "any_values": ["cpp", "rust"], # Not yet implemented - "extra_values": ["cpp", "rust"], # Missing examples - "image_advanced": ["cpp", "rust"], # Missing examples - "log_line": ["cpp", "rust", "py"], # Not a complete example -- just a single log line - "timelines_example": ["py", "cpp", "rust"], # TODO(ab): incomplete code, need hideable stubs, see https://github.com/rerun-io/landing/issues/515 - - # This is this script, it's not an example. - "roundtrips": ["cpp", "py", "rust"], -} - -# These entries will run but their results won't be compared to the baseline. -# -# You should only ever use this if the test cannot yet be implemented in a way that yields the right -# data, but you still want to check whether the test runs properly and outputs _something_. -opt_out_compare = { - "arrow3d_simple": ["cpp", "py", "rust"], # TODO(#3206): examples use different RNGs - "asset3d_out_of_tree": ["cpp", "py", "rust"], # float issues since calculation is done slightly differently (also, Python uses doubles) - "mesh3d_partial_updates": ["cpp", "py", "rust"], # float precision issues - "pinhole_simple": ["cpp", "py", "rust"], # TODO(#3206): examples use different RNGs - "point2d_random": ["cpp", "py", "rust"], # TODO(#3206): examples use different RNGs - "point3d_random": ["cpp", "py", "rust"], # TODO(#3206): examples use different RNGs - "quick_start_connect": ["cpp", "py", "rust"], # These example don't have exactly the same implementation. - "quick_start_spawn": ["cpp", "py", "rust"], # These example don't have exactly the same implementation. - "scalar_multiple_plots": ["cpp"], # trigonometric functions have slightly different outcomes - "tensor_simple": ["cpp", "py", "rust"], # TODO(#3206): examples use different RNGs - "text_log_integration": ["cpp", "py", "rust"], # The entity path will differ because the Rust code is part of a library - "series_point_style": ["cpp", "py", "rust"], # TODO(#5116): trigonometric functions have slightly different outcomes - "series_line_style": ["cpp", "py", "rust"], # TODO(#5116):trigonometric functions have slightly different outcomes +config_path = Path(__file__).parent / "snippets.toml" +config = tomlkit.loads(config_path.read_text()) +OPT_OUT_RUN = config["opt_out"]["run"] +OPT_OUT_COMPARE = config["opt_out"]["compare"] +EXTRA_ARGS = { + name: [arg.replace("$config_dir", str(Path(__file__).parent.absolute())) for arg in args] + for name, args in config["extra_args"].items() } -extra_args = { +EXTRA_ARGS = { "asset3d_simple": [f"{os.path.dirname(__file__)}/../assets/cube.glb"], "asset3d_out_of_tree": [f"{os.path.dirname(__file__)}/../assets/cube.glb"], } -# fmt: on - def main() -> None: parser = argparse.ArgumentParser(description="Run end-to-end cross-language roundtrip tests for all API examples") @@ -108,7 +81,7 @@ def main() -> None: print("----------------------------------------------------------") print("Build rerun_c & rerun_cpp…") start_time = time.time() - run(["pixi", "run", "cpp-build-doc-examples"]) + run(["pixi", "run", "cpp-build-snippets"]) elapsed = time.time() - start_time print(f"rerun-sdk for C++ built in {elapsed:.1f} seconds") print("") @@ -139,7 +112,7 @@ def main() -> None: if not args.no_cpp_build: print(f"Running {len(examples)} C++ examples…") for example in examples: - example_opt_out_entirely = opt_out_run.get(example, []) + example_opt_out_entirely = OPT_OUT_RUN.get(example, []) if "cpp" in example_opt_out_entirely: continue run_example(example, "cpp", args) @@ -148,7 +121,7 @@ def main() -> None: with multiprocessing.Pool() as pool: jobs = [] for example in examples: - example_opt_out_entirely = opt_out_run.get(example, []) + example_opt_out_entirely = OPT_OUT_RUN.get(example, []) for language in active_languages: if language in example_opt_out_entirely or language == "cpp": # cpp already processed in series. continue @@ -166,15 +139,15 @@ def main() -> None: print("----------------------------------------------------------") print(f"Comparing example '{example}'…") - example_opt_out_entirely = opt_out_run.get(example, []) - example_opt_out_compare = opt_out_compare.get(example, []) + example_opt_out_entirely = OPT_OUT_RUN.get(example, []) + example_opt_out_compare = OPT_OUT_COMPARE.get(example, []) if "rust" in example_opt_out_entirely: continue # No baseline to compare against - cpp_output_path = f"docs/code-examples/all/{example}_cpp.rrd" - python_output_path = f"docs/code-examples/all/{example}_py.rrd" - rust_output_path = f"docs/code-examples/all/{example}_rust.rrd" + cpp_output_path = f"docs/snippets/all/{example}_cpp.rrd" + python_output_path = f"docs/snippets/all/{example}_py.rrd" + rust_output_path = f"docs/snippets/all/{example}_rust.rrd" if "cpp" in active_languages and "cpp" not in example_opt_out_entirely and "cpp" not in example_opt_out_compare: run_comparison(cpp_output_path, rust_output_path, args.full_dump) @@ -202,15 +175,15 @@ def run_example(example: str, language: str, args: argparse.Namespace) -> None: def run_roundtrip_python(example: str) -> str: - main_path = f"docs/code-examples/all/{example}.py" - output_path = f"docs/code-examples/all/{example}_py.rrd" + main_path = f"docs/snippets/all/{example}.py" + output_path = f"docs/snippets/all/{example}_py.rrd" # sys.executable: the absolute path of the executable binary for the Python interpreter python_executable = sys.executable if python_executable is None: python_executable = "python3" - cmd = [python_executable, main_path] + (extra_args.get(example) or []) + cmd = [python_executable, main_path] + (EXTRA_ARGS.get(example) or []) env = roundtrip_env(save_path=output_path) run(cmd, env=env, timeout=30) @@ -219,9 +192,9 @@ def run_roundtrip_python(example: str) -> str: def run_roundtrip_rust(example: str, release: bool, target: str | None, target_dir: str | None) -> str: - output_path = f"docs/code-examples/all/{example}_rust.rrd" + output_path = f"docs/snippets/all/{example}_rust.rrd" - cmd = ["cargo", "run", "--quiet", "-p", "code_examples"] + cmd = ["cargo", "run", "--quiet", "-p", "snippets"] if target is not None: cmd += ["--target", target] @@ -234,8 +207,8 @@ def run_roundtrip_rust(example: str, release: bool, target: str | None, target_d cmd += ["--", example] - if extra_args.get(example): - cmd += extra_args[example] + if EXTRA_ARGS.get(example): + cmd += EXTRA_ARGS[example] env = roundtrip_env(save_path=output_path) run(cmd, env=env, timeout=12000) @@ -244,9 +217,9 @@ def run_roundtrip_rust(example: str, release: bool, target: str | None, target_d def run_roundtrip_cpp(example: str, release: bool) -> str: - output_path = f"docs/code-examples/all/{example}_cpp.rrd" + output_path = f"docs/snippets/all/{example}_cpp.rrd" - cmd = [f"./build/debug/docs/code-examples/{example}"] + (extra_args.get(example) or []) + cmd = [f"./build/debug/docs/snippets/{example}"] + (EXTRA_ARGS.get(example) or []) env = roundtrip_env(save_path=output_path) run(cmd, env=env, timeout=12000) diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml new file mode 100644 index 000000000000..7f918fa81cf6 --- /dev/null +++ b/docs/snippets/snippets.toml @@ -0,0 +1,90 @@ +# This file is read in `compare_snippet_output.py` and the `snippets` command in `re_build_examples`. + +# These entries won't run at all. +# +# You should only ever use this if the test isn't implemented and cannot yet be implemented +# for one or more specific SDKs. +[opt_out.run] +any_values = ["cpp", "rust"] # Not yet implemented +extra_values = ["cpp", "rust"] # Missing examples +image_advanced = ["cpp", "rust"] # Missing examples +log_line = [ # Not a complete example -- just a single log line + "cpp", + "rust", + "py", +] +timelines_example = [ # TODO(ab): incomplete code, need hideable stubs, see https://github.com/rerun-io/landing/issues/515 + "py", + "cpp", + "rust", +] + +# This is this script, it's not an example. +roundtrips = ["cpp", "py", "rust"] + + +# These entries will run but their results won't be compared to the baseline. +# +# You should only ever use this if the test cannot yet be implemented in a way that yields the right +# data, but you still want to check whether the test runs properly and outputs _something_. +[opt_out.compare] +arrow3d_simple = [ # TODO(#3206): examples use different RNGs + "cpp", + "py", + "rust", +] +asset3d_out_of_tree = [ # float issues since calculation is done slightly differently (also, Python uses doubles) + "cpp", + "py", + "rust", +] +mesh3d_partial_updates = ["cpp", "py", "rust"] # float precision issues +pinhole_simple = [ # TODO(#3206): examples use different RNGs + "cpp", + "py", + "rust", +] +point2d_random = [ # TODO(#3206): examples use different RNGs + "cpp", + "py", + "rust", +] +point3d_random = [ # TODO(#3206): examples use different RNGs + "cpp", + "py", + "rust", +] +quick_start_connect = [ # These example don't have exactly the same implementation. + "cpp", + "py", + "rust", +] +quick_start_spawn = [ # These example don't have exactly the same implementation. + "cpp", + "py", + "rust", +] +scalar_multiple_plots = [ # trigonometric functions have slightly different outcomes + "cpp", +] +tensor_simple = ["cpp", "py", "rust"] # TODO(#3206): examples use different RNGs +text_log_integration = [ # The entity path will differ because the Rust code is part of a library + "cpp", + "py", + "rust", +] +series_point_style = [ # TODO(#5116): trigonometric functions have slightly different outcomes + "cpp", + "py", + "rust", +] +series_line_style = [ # TODO(#5116):trigonometric functions have slightly different outcomes + "cpp", + "py", + "rust", +] + +# `$config_dir` will be replaced with the absolute path of `docs/snippets`. +[extra_args] +asset3d_simple = ["$config_dir/assets/cube.glb"] +asset3d_out_of_tree = ["$config_dir/assets/cube.glb"] diff --git a/docs/code-examples/src/examples/.gitignore b/docs/snippets/src/examples/.gitignore similarity index 100% rename from docs/code-examples/src/examples/.gitignore rename to docs/snippets/src/examples/.gitignore diff --git a/docs/snippets/src/lib.rs b/docs/snippets/src/lib.rs new file mode 100644 index 000000000000..0caa1b4e110d --- /dev/null +++ b/docs/snippets/src/lib.rs @@ -0,0 +1,5 @@ +//! Snippets that we show in documentation. + +mod examples; + +pub use examples::run; diff --git a/docs/snippets/src/main.rs b/docs/snippets/src/main.rs new file mode 100644 index 000000000000..14149bea60a3 --- /dev/null +++ b/docs/snippets/src/main.rs @@ -0,0 +1,6 @@ +//! Snippets that we show in documentation. + +pub fn main() { + // Call into the generated code. + snippets::run(); +} diff --git a/examples/python/arkit_scenes/README.md b/examples/python/arkit_scenes/README.md index 22d158b98227..b4bbf5038515 100644 --- a/examples/python/arkit_scenes/README.md +++ b/examples/python/arkit_scenes/README.md @@ -8,7 +8,7 @@ channel = "main" --> - + diff --git a/examples/python/depth_guided_stable_diffusion/README.md b/examples/python/depth_guided_stable_diffusion/README.md index 815b8c36ea4d..eeae6dfaf07f 100644 --- a/examples/python/depth_guided_stable_diffusion/README.md +++ b/examples/python/depth_guided_stable_diffusion/README.md @@ -7,7 +7,7 @@ channel = "nightly" --> - + diff --git a/examples/python/detect_and_track_objects/README.md b/examples/python/detect_and_track_objects/README.md index 6a175696e3ce..b721c6d84f20 100644 --- a/examples/python/detect_and_track_objects/README.md +++ b/examples/python/detect_and_track_objects/README.md @@ -8,7 +8,7 @@ channel = "release" --> - + diff --git a/examples/python/dicom_mri/README.md b/examples/python/dicom_mri/README.md index f91da8201fa1..0cbd8d9b510b 100644 --- a/examples/python/dicom_mri/README.md +++ b/examples/python/dicom_mri/README.md @@ -8,7 +8,7 @@ channel = "main" --> - + diff --git a/examples/python/dna/README.md b/examples/python/dna/README.md index 6c93c016bef2..0539c8463edd 100644 --- a/examples/python/dna/README.md +++ b/examples/python/dna/README.md @@ -7,8 +7,7 @@ thumbnail_dimensions = [480, 285] channel = "main" --> - - + diff --git a/examples/python/human_pose_tracking/README.md b/examples/python/human_pose_tracking/README.md index 7d6705cf5fc4..09d41b873476 100644 --- a/examples/python/human_pose_tracking/README.md +++ b/examples/python/human_pose_tracking/README.md @@ -7,7 +7,7 @@ thumbnail_dimensions = [480, 272] channel = "main" --> - + diff --git a/examples/python/incremental_logging/README.md b/examples/python/incremental_logging/README.md index 09ac14766431..96f8bae946c5 100644 --- a/examples/python/incremental_logging/README.md +++ b/examples/python/incremental_logging/README.md @@ -7,7 +7,7 @@ thumbnail_dimensions = [480, 301] --> - + diff --git a/examples/python/nuscenes/README.md b/examples/python/nuscenes/README.md index 1ba1dbff0959..e383da597eb1 100644 --- a/examples/python/nuscenes/README.md +++ b/examples/python/nuscenes/README.md @@ -8,7 +8,7 @@ channel = "release" build_args = ["--seconds=5"] --> - + diff --git a/examples/python/open_photogrammetry_format/README.md b/examples/python/open_photogrammetry_format/README.md index 953fce825834..98d5dc4799b1 100644 --- a/examples/python/open_photogrammetry_format/README.md +++ b/examples/python/open_photogrammetry_format/README.md @@ -8,7 +8,7 @@ channel = "release" build_args = ["--jpeg-quality=50"] --> - + diff --git a/examples/python/plots/README.md b/examples/python/plots/README.md index c2be11144c3a..2db5f09adf8c 100644 --- a/examples/python/plots/README.md +++ b/examples/python/plots/README.md @@ -8,7 +8,7 @@ channel = "main" --> - + diff --git a/examples/python/raw_mesh/README.md b/examples/python/raw_mesh/README.md index aebb1b32b709..b42f6ebd9b67 100644 --- a/examples/python/raw_mesh/README.md +++ b/examples/python/raw_mesh/README.md @@ -7,7 +7,7 @@ thumbnail_dimensions = [480, 296] channel = "release" --> - + diff --git a/examples/python/rgbd/README.md b/examples/python/rgbd/README.md index e6d9d6e83508..7cdcd283c91b 100644 --- a/examples/python/rgbd/README.md +++ b/examples/python/rgbd/README.md @@ -8,7 +8,7 @@ channel = "release" build_args = ["--frames=300"] --> - + diff --git a/examples/python/segment_anything_model/README.md b/examples/python/segment_anything_model/README.md index 0b926e155dfa..e0a8ef776694 100644 --- a/examples/python/segment_anything_model/README.md +++ b/examples/python/segment_anything_model/README.md @@ -8,7 +8,7 @@ channel = "release" --> - + diff --git a/examples/python/structure_from_motion/README.md b/examples/python/structure_from_motion/README.md index f94d45189412..ea26881ef83b 100644 --- a/examples/python/structure_from_motion/README.md +++ b/examples/python/structure_from_motion/README.md @@ -9,7 +9,7 @@ build_args = ["--dataset=colmap_fiat", "--resize=800x600"] --> - + diff --git a/justfile b/justfile index 2eebc65976d8..d69e6d958176 100644 --- a/justfile +++ b/justfile @@ -46,9 +46,9 @@ cpp-build: cpp-build-examples: pixi run cpp-build-examples -# Build all our C++ api doc examples. -cpp-build-doc-examples: - pixi run cpp-build-doc-examples +# Build all our C++ snippets. +cpp-build-snippets: + pixi run cpp-build-snippets # Run our C++ tests cpp-test: @@ -118,7 +118,7 @@ py-format: # NOTE: we need both `ruff check --fix` and `ruff format` in that order: https://twitter.com/charliermarsh/status/1717229721954799727 ruff check --fix --config rerun_py/pyproject.toml {{py_folders}} ruff format --config rerun_py/pyproject.toml {{py_folders}} - blackdoc {{py_folders}} # Format code examples in docstring. Hopefully `ruff` can do this soon: https://github.com/astral-sh/ruff/issues/7146 + blackdoc {{py_folders}} # Format snippets in docstring. Hopefully `ruff` can do this soon: https://github.com/astral-sh/ruff/issues/7146 # Check that all the requirements.txt files for all the examples are correct py-requirements: diff --git a/noxfile.py b/noxfile.py index ca52b8948568..2bfc7935a701 100644 --- a/noxfile.py +++ b/noxfile.py @@ -68,6 +68,6 @@ def roundtrips(session: nox.Session) -> None: extra_args.extend(session.posargs) session.run("python", "tests/roundtrips.py", "--no-py-build", *extra_args) - session.run("python", "docs/code-examples/compare_code_example_output.py", "--no-py-build", *extra_args) + session.run("python", "docs/snippets/compare_snippet_output.py", "--no-py-build", *extra_args) roundtrip_cpp_built = True diff --git a/pixi.toml b/pixi.toml index b24f5bf5c0ac..50e264179e07 100644 --- a/pixi.toml +++ b/pixi.toml @@ -126,7 +126,7 @@ cpp-build-roundtrips = { cmd = "cmake --build build/debug --config Debug --targe cpp-build-examples = { cmd = "cmake --build build/debug --config Debug --target examples", depends_on = [ "cpp-prepare", ] } -cpp-build-doc-examples = { cmd = "cmake --build build/debug --config Debug --target doc_examples", depends_on = [ +cpp-build-snippets = { cmd = "cmake --build build/debug --config Debug --target snippets", depends_on = [ "cpp-prepare", ] } cpp-build-log-benchmark = { cmd = "cmake --build build/release --config Release --target log_benchmark", depends_on = [ diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index 82efd7e03f73..4c9126eb6ffb 100644 --- a/rerun_py/pyproject.toml +++ b/rerun_py/pyproject.toml @@ -53,10 +53,10 @@ extend-exclude = [ "target/", # Intentionally uses ''' instead of """ so we can embed it in a docstring in the Python API docs. - "docs/code-examples/all/text_document.py", + "docs/snippets/all/text_document.py", # TODO(#4047): incomplete example snippet - "docs/code-examples/all/timelines_example.py", + "docs/snippets/all/timelines_example.py", # generated "examples/python/objectron/proto/objectron/proto.py", @@ -108,7 +108,7 @@ lint.select = [ ] [tool.ruff.lint.per-file-ignores] -"docs/code-examples/all/*" = [ +"docs/snippets/all/*" = [ # Missing required import: `from __future__ import annotations` "I002", ] diff --git a/scripts/screenshot_compare/build_screenshot_compare.py b/scripts/screenshot_compare/build_screenshot_compare.py index c62bd3016c46..38e334f7e03f 100755 --- a/scripts/screenshot_compare/build_screenshot_compare.py +++ b/scripts/screenshot_compare/build_screenshot_compare.py @@ -7,7 +7,7 @@ them side-by-side. It pulls from the following sources: - The screenshots listed in .fbs files (crates/re_types/definitions/rerun/**/*.fbs), - and the corresponding code examples in the docs (docs/code-examples/*.rs) + and the corresponding snippets in the docs (docs/snippets/*.rs) - The `app.rerun.io` examples, as built by the `re_build_examples` script. The comparisons are generated in the `compare_screenshot` directory. Use the `--serve` @@ -43,7 +43,7 @@ INDEX_TEMPLATE = Template((TEMPLATE_DIR / "index.html").read_text()) EXAMPLE_TEMPLATE = Template((TEMPLATE_DIR / "example.html").read_text()) RERUN_DIR = SCRIPT_DIR_PATH.parent.parent -CODE_EXAMPLE_DIR = RERUN_DIR / "docs" / "code-examples" +SNIPPETS_DIR = RERUN_DIR / "docs" / "snippets" def measure_thumbnail(url: str) -> Any: @@ -95,13 +95,13 @@ def build_python_sdk() -> None: # ==================================================================================================== -# CODE EXAMPLES +# SNIPPETS # -# We scrape FBS for screenshot URL and generate the corresponding code examples RRD with roundtrips.py +# We scrape FBS for screenshot URL and generate the corresponding snippets RRD with roundtrips.py # ==================================================================================================== -def extract_code_example_urls_from_fbs() -> dict[str, str]: +def extract_snippet_urls_from_fbs() -> dict[str, str]: fbs_path = SCRIPT_DIR_PATH.parent.parent / "crates" / "re_types" / "definitions" / "rerun" urls = {} @@ -120,27 +120,27 @@ def extract_code_example_urls_from_fbs() -> dict[str, str]: return urls -CODE_EXAMPLE_URLS = extract_code_example_urls_from_fbs() +SNIPPET_URLS = extract_snippet_urls_from_fbs() -def build_code_examples() -> None: +def build_snippets() -> None: cmd = [ - str(CODE_EXAMPLE_DIR / "roundtrips.py"), + str(SNIPPETS_DIR / "roundtrips.py"), "--no-py", "--no-cpp", "--no-py-build", "--no-cpp-build", ] - for name in CODE_EXAMPLE_URLS.keys(): + for name in SNIPPET_URLS.keys(): run(cmd + [name], cwd=RERUN_DIR) -def collect_code_examples() -> Iterable[Example]: - for name in sorted(CODE_EXAMPLE_URLS.keys()): - rrd = CODE_EXAMPLE_DIR / f"{name}_rust.rrd" +def collect_snippets() -> Iterable[Example]: + for name in sorted(SNIPPET_URLS.keys()): + rrd = SNIPPETS_DIR / f"{name}_rust.rrd" assert rrd.exists(), f"Missing {rrd} for {name}" - yield Example(name=name, title=name, rrd=rrd, screenshot_url=CODE_EXAMPLE_URLS[name]) + yield Example(name=name, title=name, rrd=rrd, screenshot_url=SNIPPET_URLS[name]) # ==================================================================================================== @@ -150,7 +150,7 @@ def collect_code_examples() -> Iterable[Example]: # ==================================================================================================== -def build_demo_examples() -> None: +def build_examples() -> None: # fmt: off cmd = [ "cargo", "run", "--locked", @@ -168,7 +168,7 @@ def build_demo_examples() -> None: # fmt: on -def collect_demo_examples() -> Iterable[Example]: +def collect_examples() -> Iterable[Example]: example_dir = RERUN_DIR / "example_data" assert example_dir.exists(), "Examples have not been built yet." @@ -187,11 +187,6 @@ def collect_demo_examples() -> Iterable[Example]: ) -def collect_examples() -> Iterable[Example]: - yield from collect_code_examples() - yield from collect_demo_examples() - - def render_index(examples: list[Example]) -> None: BASE_PATH.mkdir(exist_ok=True) @@ -262,10 +257,10 @@ def main() -> None: build_python_sdk() if not args.skip_example_build: - build_code_examples() - build_demo_examples() + build_snippets() + build_examples() - examples = list(collect_examples()) + examples = list(collect_snippets()) + list(collect_examples()) assert len(examples) > 0, "No examples found" render_index(examples) From 83491b272f92777e350d0ce8ec564bebb05ecdd1 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 18 Mar 2024 09:42:28 +0100 Subject: [PATCH 040/508] Support loading multiple recordings and/or blueprints in web-viewer (#5548) ### What * Closes https://github.com/rerun-io/rerun/issues/5294 This adds support for passing multiple .rrd and/or .rbl files to the web-viewer by repeating the `url` query parameter. ### TODO * [x] Test this ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5548/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5548/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5548/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5548) - [Docs preview](https://rerun.io/preview/62af0e20b1216c2dfc66806d8470966259606981/docs) - [Examples preview](https://rerun.io/preview/62af0e20b1216c2dfc66806d8470966259606981/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 20 ++++---- Cargo.toml | 14 +++--- crates/re_data_source/src/data_source.rs | 7 ++- crates/re_viewer/src/app.rs | 1 + crates/re_viewer/src/web.rs | 59 +++++++++++++----------- 5 files changed, 56 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f112875bcd7e..4f315aca96a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1555,7 +1555,7 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "bytemuck", "serde", @@ -1564,7 +1564,7 @@ dependencies = [ [[package]] name = "eframe" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "bytemuck", "cocoa", @@ -1599,7 +1599,7 @@ dependencies = [ [[package]] name = "egui" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "accesskit", "ahash", @@ -1615,7 +1615,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "bytemuck", "document-features", @@ -1633,7 +1633,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "accesskit_winit", "arboard", @@ -1662,7 +1662,7 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "egui", "ehttp", @@ -1677,7 +1677,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "bytemuck", "egui", @@ -1694,7 +1694,7 @@ dependencies = [ [[package]] name = "egui_plot" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "egui", ] @@ -1736,7 +1736,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "bytemuck", "serde", @@ -1837,7 +1837,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb#bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" +source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" dependencies = [ "ab_glyph", "ahash", diff --git a/Cargo.toml b/Cargo.toml index d1c981ffb0a6..2a4110640321 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -283,13 +283,13 @@ debug = true # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 -eframe = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 -egui = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 -egui_plot = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 -emath = { git = "https://github.com/emilk/egui.git", rev = "bf7ffb982a6e8c0a40d0871c38bccacef9ee8efb" } # egui master 2024-03-15 +ecolor = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 +eframe = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 +egui = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 +egui_extras = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 +egui_plot = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 +egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 +emath = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } diff --git a/crates/re_data_source/src/data_source.rs b/crates/re_data_source/src/data_source.rs index d2728bde1f42..c842fd894b43 100644 --- a/crates/re_data_source/src/data_source.rs +++ b/crates/re_data_source/src/data_source.rs @@ -10,6 +10,8 @@ use anyhow::Context as _; #[derive(Debug, Clone)] pub enum DataSource { /// A remote RRD file, served over http. + /// + /// Could be either an `.rrd` recording or a `.rbl` blueprint. RrdHttpUrl(String), /// A path to a local file. @@ -86,7 +88,7 @@ impl DataSource { DataSource::FilePath(file_source, path) } else if uri.starts_with("http://") || uri.starts_with("https://") - || (uri.starts_with("www.") && uri.ends_with(".rrd")) + || (uri.starts_with("www.") && (uri.ends_with(".rrd") || uri.ends_with(".rbl"))) { DataSource::RrdHttpUrl(uri) } else if uri.starts_with("ws://") || uri.starts_with("wss://") { @@ -95,7 +97,7 @@ impl DataSource { // Now we are into heuristics territory: } else if looks_like_a_file_path(&uri) { DataSource::FilePath(file_source, path) - } else if uri.ends_with(".rrd") { + } else if uri.ends_with(".rrd") || uri.ends_with(".rbl") { DataSource::RrdHttpUrl(uri) } else { // If this is sometyhing like `foo.com` we can't know what it is until we connect to it. @@ -234,6 +236,7 @@ fn test_data_source_from_uri() { "https://foo.zip", "example.zip/foo.rrd", "www.foo.zip/foo.rrd", + "www.foo.zip/blueprint.rbl", ]; let ws = ["ws://foo.zip", "wss://foo.zip", "127.0.0.1"]; diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 7f96af6d2380..15a4983bd69f 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -263,6 +263,7 @@ impl App { } pub fn set_examples_manifest_url(&mut self, url: String) { + re_log::info!("Using manifest_url={url:?}"); self.state .set_examples_manifest_url(&self.re_ui.egui_ctx, url); } diff --git a/crates/re_viewer/src/web.rs b/crates/re_viewer/src/web.rs index 85b76d7a5db0..3fade48b17d9 100644 --- a/crates/re_viewer/src/web.rs +++ b/crates/re_viewer/src/web.rs @@ -133,22 +133,21 @@ fn create_app( let query_map = &cc.integration_info.web_info.location.query_map; - let manifest_url = match &manifest_url { - Some(url) => Some(url.as_str()), - None => query_map.get("manifest_url").map(String::as_str), - }; - if let Some(url) = manifest_url { - app.set_examples_manifest_url(url.into()); - re_log::info!("Using manifest_url={url:?}"); + if let Some(manifest_url) = manifest_url { + app.set_examples_manifest_url(manifest_url.into()); + } else { + for url in query_map.get("manifest_url").into_iter().flatten() { + app.set_examples_manifest_url(url.clone()); + } } - let url = match &url { - Some(url) => Some(url.as_str()), - None => query_map.get("url").map(String::as_str), - }; if let Some(url) = url { - let rx = url_to_receiver(url, egui_ctx.clone()); - app.add_receiver(rx); + app.add_receiver(url_to_receiver(url, egui_ctx)); + } else { + // NOTE: we support passing in multiple urls to multiple different recorording, blueprints, etc + for url in query_map.get("url").into_iter().flatten() { + app.add_receiver(url_to_receiver(url, egui_ctx.clone())); + } } app @@ -223,6 +222,8 @@ pub fn set_email(email: String) { enum EndpointCategory { /// Could be a local path (`/foo.rrd`) or a remote url (`http://foo.com/bar.rrd`). + /// + /// Could be a link to either an `.rrd` recording or a `.rbl` blueprint. HttpRrd(String), /// A remote Rerun server. @@ -233,7 +234,7 @@ enum EndpointCategory { } fn categorize_uri(uri: &str) -> EndpointCategory { - if uri.starts_with("http") || uri.ends_with(".rrd") { + if uri.starts_with("http") || uri.ends_with(".rrd") || uri.ends_with(".rbl") { EndpointCategory::HttpRrd(uri.into()) } else if uri.starts_with("ws:") || uri.starts_with("wss:") { EndpointCategory::WebSocket(uri.into()) @@ -261,21 +262,27 @@ fn get_persist_state(info: &eframe::IntegrationInfo) -> bool { fn get_query_bool(info: &eframe::IntegrationInfo, key: &str, default: bool) -> bool { let default_int = default as i32; - match info - .web_info - .location - .query_map - .get(key) - .map(String::as_str) - { - Some("0") => false, - Some("1") => true, - Some(other) => { + + if let Some(values) = info.web_info.location.query_map.get(key) { + if values.len() == 1 { + match values[0].as_str() { + "0" => false, + "1" => true, + other => { + re_log::warn!( + "Unexpected value for '{key}' query: {other:?}. Expected either '0' or '1'. Defaulting to '{default_int}'." + ); + default + } + } + } else { re_log::warn!( - "Unexpected value for '{key}' query: {other:?}. Expected either '0' or '1'. Defaulting to '{default_int}'." + "Found {} values for '{key}' query. Expected one or none. Defaulting to '{default_int}'.", + values.len() ); default } - _ => default, + } else { + default } } From 61b5e9e2aa7661749124a832cc691f3f6880e511 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 18 Mar 2024 09:42:36 +0100 Subject: [PATCH 041/508] Activate blueprint as soon as it has finished transmitting (#5529) ### What * Closes https://github.com/rerun-io/rerun/issues/5297 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5529/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5529/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5529/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5529) - [Docs preview](https://rerun.io/preview/d2d0b7e00a7ad3c8ef5ced1744605977f302760c/docs) - [Examples preview](https://rerun.io/preview/d2d0b7e00a7ad3c8ef5ced1744605977f302760c/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/log_msg.rs | 3 ++ crates/re_entity_db/src/entity_db.rs | 4 ++ crates/re_log_types/src/lib.rs | 11 +++++- crates/re_sdk/src/recording_stream.rs | 27 ++++++++++---- crates/re_sdk_comms/src/server.rs | 2 +- crates/re_viewer/src/app.rs | 53 ++++++++++++++++++++------- crates/rerun/src/run.rs | 5 +++ 7 files changed, 80 insertions(+), 25 deletions(-) diff --git a/crates/re_data_ui/src/log_msg.rs b/crates/re_data_ui/src/log_msg.rs index 19643fd0f9e0..9abc4f29a76c 100644 --- a/crates/re_data_ui/src/log_msg.rs +++ b/crates/re_data_ui/src/log_msg.rs @@ -16,6 +16,9 @@ impl DataUi for LogMsg { match self { LogMsg::SetStoreInfo(msg) => msg.data_ui(ctx, ui, verbosity, query, store), LogMsg::ArrowMsg(_, msg) => msg.data_ui(ctx, ui, verbosity, query, store), + LogMsg::ActivateStore(store_id) => { + ui.label(format!("ActivateStore({store_id})")); + } } } } diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index f27a2e5d38bf..b2f60470fbcd 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -273,6 +273,10 @@ impl EntityDb { let table = DataTable::from_arrow_msg(arrow_msg)?; self.add_data_table(table)?; } + + LogMsg::ActivateStore(_) => { + // Not for us to handle + } } Ok(()) diff --git a/crates/re_log_types/src/lib.rs b/crates/re_log_types/src/lib.rs index b1950ce26fea..0606d24f6cbf 100644 --- a/crates/re_log_types/src/lib.rs +++ b/crates/re_log_types/src/lib.rs @@ -218,13 +218,20 @@ pub enum LogMsg { /// Log an entity using an [`ArrowMsg`]. ArrowMsg(StoreId, ArrowMsg), + + /// Send after all messages in a blueprint to signal that the blueprint is complete. + /// + /// This is so that the viewer can wait with activating the blueprint until it is + /// fully transmitted. Showing a half-transmitted blueprint can cause confusion, + /// and also lead to problems with space-view heuristics. + ActivateStore(StoreId), } impl LogMsg { pub fn store_id(&self) -> &StoreId { match self { Self::SetStoreInfo(msg) => &msg.info.store_id, - Self::ArrowMsg(store_id, _) => store_id, + Self::ArrowMsg(store_id, _) | Self::ActivateStore(store_id) => store_id, } } @@ -233,7 +240,7 @@ impl LogMsg { LogMsg::SetStoreInfo(store_info) => { store_info.info.store_id = new_store_id; } - LogMsg::ArrowMsg(msg_store_id, _) => { + LogMsg::ArrowMsg(msg_store_id, _) | LogMsg::ActivateStore(msg_store_id) => { *msg_store_id = new_store_id; } } diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs index c0b1a0cf1cf9..35f0ff073e46 100644 --- a/crates/re_sdk/src/recording_stream.rs +++ b/crates/re_sdk/src/recording_stream.rs @@ -1554,9 +1554,20 @@ impl RecordingStream { // If a blueprint was provided, send it first. if let Some(blueprint) = blueprint { + let mut store_id = None; for msg in blueprint { + if store_id.is_none() { + store_id = Some(msg.store_id().clone()); + } sink.send(msg); } + if let Some(store_id) = store_id { + // Let the viewer know that the blueprint has been fully received, + // and that it can now be activated. + // We don't want to activate half-loaded blueprints, because that can be confusing, + // and can also lead to problems with space-view heuristics. + sink.send(LogMsg::ActivateStore(store_id)); + } } self.set_sink(Box::new(sink)); @@ -2048,7 +2059,7 @@ mod tests { assert!(msg.row_id != RowId::ZERO); similar_asserts::assert_eq!(store_info, msg.info); } - LogMsg::ArrowMsg { .. } => panic!("expected SetStoreInfo"), + _ => panic!("expected SetStoreInfo"), } // Second message should be a set_store_info resulting from the later sink swap from @@ -2059,7 +2070,7 @@ mod tests { assert!(msg.row_id != RowId::ZERO); similar_asserts::assert_eq!(store_info, msg.info); } - LogMsg::ArrowMsg { .. } => panic!("expected SetStoreInfo"), + _ => panic!("expected SetStoreInfo"), } // Third message is the batched table itself, which was sent as a result of the implicit @@ -2076,7 +2087,7 @@ mod tests { similar_asserts::assert_eq!(table, got); } - LogMsg::SetStoreInfo { .. } => panic!("expected ArrowMsg"), + _ => panic!("expected ArrowMsg"), } // That's all. @@ -2115,7 +2126,7 @@ mod tests { assert!(msg.row_id != RowId::ZERO); similar_asserts::assert_eq!(store_info, msg.info); } - LogMsg::ArrowMsg { .. } => panic!("expected SetStoreInfo"), + _ => panic!("expected SetStoreInfo"), } // Second message should be a set_store_info resulting from the later sink swap from @@ -2126,7 +2137,7 @@ mod tests { assert!(msg.row_id != RowId::ZERO); similar_asserts::assert_eq!(store_info, msg.info); } - LogMsg::ArrowMsg { .. } => panic!("expected SetStoreInfo"), + _ => panic!("expected SetStoreInfo"), } let mut rows = { @@ -2150,7 +2161,7 @@ mod tests { similar_asserts::assert_eq!(expected, got); } - LogMsg::SetStoreInfo { .. } => panic!("expected ArrowMsg"), + _ => panic!("expected ArrowMsg"), } }; @@ -2195,7 +2206,7 @@ mod tests { assert!(msg.row_id != RowId::ZERO); similar_asserts::assert_eq!(store_info, msg.info); } - LogMsg::ArrowMsg { .. } => panic!("expected SetStoreInfo"), + _ => panic!("expected SetStoreInfo"), } // MemorySinkStorage transparently handles flushing during `take()`! @@ -2213,7 +2224,7 @@ mod tests { similar_asserts::assert_eq!(table, got); } - LogMsg::SetStoreInfo { .. } => panic!("expected ArrowMsg"), + _ => panic!("expected ArrowMsg"), } // That's all. diff --git a/crates/re_sdk_comms/src/server.rs b/crates/re_sdk_comms/src/server.rs index 7254f782a024..f74033f6c9dc 100644 --- a/crates/re_sdk_comms/src/server.rs +++ b/crates/re_sdk_comms/src/server.rs @@ -249,7 +249,7 @@ impl CongestionManager { #[allow(clippy::match_same_arms)] match msg { // we don't want to drop any of these - LogMsg::SetStoreInfo(_) => true, + LogMsg::SetStoreInfo(_) | LogMsg::ActivateStore(_) => true, LogMsg::ArrowMsg(_, arrow_msg) => self.should_send_time_point(&arrow_msg.timepoint_max), } diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 15a4983bd69f..df008fb327a5 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -949,6 +949,7 @@ impl App { // In that case, we want to make it the default. // We wait with activaing blueprints until they are fully loaded, // so that we don't run heuristics on half-loaded blueprints. + // This is a fallback in case `LogMsg::ActivateStore` isn't sent (for whatever reason). let blueprints = store_hub .entity_dbs_from_channel_source(&channel_source) @@ -998,21 +999,45 @@ impl App { re_log::error_once!("Failed to add incoming msg: {err}"); }; - // Set the recording-id after potentially creating the store in the hub. - // This ordering is important because the `StoreHub` internally - // updates the app-id when changing the recording. - if let LogMsg::SetStoreInfo(msg) = &msg { - match msg.info.store_id.kind { - StoreKind::Recording => { - re_log::debug!("Opening a new recording: {:?}", msg.info); - store_hub.set_recording_id(store_id.clone()); + match &msg { + LogMsg::SetStoreInfo(_) => { + // Set the recording-id after potentially creating the store in the hub. + // This ordering is important because the `StoreHub` internally + // updates the app-id when changing the recording. + match store_id.kind { + StoreKind::Recording => { + re_log::debug!("Opening a new recording: {store_id}"); + store_hub.set_recording_id(store_id.clone()); + } + StoreKind::Blueprint => { + // We wait with activaing blueprints until they are fully loaded, + // so that we don't run heuristics on half-loaded blueprints. + // TODO(#5297): heed special "end-of-blueprint" message to activate blueprint. + // Otherwise on a mixed connection (SDK sending both blueprint and recording) + // the blueprint won't be activated until the whole _recording_ has finished loading. + } } - StoreKind::Blueprint => { - // We wait with activaing blueprints until they are fully loaded, - // so that we don't run heuristics on half-loaded blueprints. - // TODO(#5297): heed special "end-of-blueprint" message to activate blueprint. - // Otherwise on a mixed connection (SDK sending both blueprint and recording) - // the blueprint won't be activated until the whole _recording_ has finished loading. + } + + LogMsg::ArrowMsg(_, _) => { + // Andled by EntityDb::add + } + + LogMsg::ActivateStore(store_id) => { + match store_id.kind { + StoreKind::Recording => { + re_log::debug!("Opening a new recording: {store_id}"); + store_hub.set_recording_id(store_id.clone()); + } + StoreKind::Blueprint => { + re_log::debug!("Activating newly loaded blueprint"); + if let Some(info) = entity_db.store_info() { + let app_id = info.application_id.clone(); + store_hub.set_blueprint_for_app_id(store_id.clone(), app_id); + } else { + re_log::warn!("Got ActivateStore message without first receiving a SetStoreInfo"); + } + } } } } diff --git a/crates/rerun/src/run.rs b/crates/rerun/src/run.rs index c571bd2b4b1c..9437471ab927 100644 --- a/crates/rerun/src/run.rs +++ b/crates/rerun/src/run.rs @@ -532,6 +532,7 @@ impl PrintCommand { let SetStoreInfo { row_id: _, info } = msg; println!("{info:#?}"); } + LogMsg::ArrowMsg(_row_id, arrow_msg) => { let mut table = DataTable::from_arrow_msg(&arrow_msg).context("Decode arrow message")?; @@ -557,6 +558,10 @@ impl PrintCommand { ); } } + + LogMsg::ActivateStore(store_id) => { + println!("ActivateStore({store_id})"); + } } } Ok(()) From 7fc4299017b92150f8b6cdb3933b43fa16330038 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 18 Mar 2024 10:28:16 +0100 Subject: [PATCH 042/508] Make arrow null fields nullable in C++ (#5551) * Closes #5459 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5551/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5551/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5551/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5551) - [Docs preview](https://rerun.io/preview/4fdba96c770a32dad1a69dbbfad20c5b0a73abf8/docs) - [Examples preview](https://rerun.io/preview/4fdba96c770a32dad1a69dbbfad20c5b0a73abf8/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../re_types_builder/src/codegen/cpp/mod.rs | 6 +++--- crates/re_types_builder/src/objects.rs | 6 +++--- .../components/background3d_kind.cpp | 6 +++--- .../blueprint/components/container_kind.cpp | 8 ++++---- .../rerun/blueprint/components/corner2d.cpp | 8 ++++---- .../src/rerun/components/marker_shape.cpp | 20 +++++++++---------- .../tests/generated/components/enum_test.cpp | 12 +++++------ 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/crates/re_types_builder/src/codegen/cpp/mod.rs b/crates/re_types_builder/src/codegen/cpp/mod.rs index 4201060ce9cc..0ff49abf78c1 100644 --- a/crates/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/re_types_builder/src/codegen/cpp/mod.rs @@ -2345,7 +2345,7 @@ fn quote_arrow_field_type( ) -> TokenStream { let name = &field.name; let datatype = quote_arrow_data_type(&field.typ, objects, includes, false); - let is_nullable = field.is_nullable; + let is_nullable = field.is_nullable || field.typ == Type::Unit; // null type is always nullable quote! { arrow::field(#name, #datatype, #is_nullable) @@ -2359,9 +2359,9 @@ fn quote_arrow_elem_type( ) -> TokenStream { let typ: Type = elem_type.clone().into(); let datatype = quote_arrow_data_type(&typ, objects, includes, false); - + let is_nullable = typ == Type::Unit; // null type must be nullable quote! { - arrow::field("item", #datatype, false) + arrow::field("item", #datatype, #is_nullable) } } diff --git a/crates/re_types_builder/src/objects.rs b/crates/re_types_builder/src/objects.rs index 5efea2bf04da..e332fb9e89ca 100644 --- a/crates/re_types_builder/src/objects.rs +++ b/crates/re_types_builder/src/objects.rs @@ -798,7 +798,7 @@ impl ObjectField { let typ = Type::from_raw_type(&virtpath, enums, objs, field.type_(), &attrs); let order = attrs.get::(&fqname, crate::ATTR_ORDER); - let is_nullable = attrs.has(crate::ATTR_NULLABLE); + let is_nullable = attrs.has(crate::ATTR_NULLABLE) || typ == Type::Unit; // null type is always nullable let is_deprecated = field.deprecated(); Self { @@ -852,8 +852,8 @@ impl ObjectField { &attrs, ); - let is_nullable = attrs.has(crate::ATTR_NULLABLE); - // TODO(cmc): not sure about this, but fbs unions are a bit weird that way + let is_nullable = attrs.has(crate::ATTR_NULLABLE) || typ == Type::Unit; // null type is always nullable + let is_deprecated = false; if attrs.has(crate::ATTR_ORDER) { diff --git a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp index 465e5963c081..7a99c3460f99 100644 --- a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp @@ -11,9 +11,9 @@ namespace rerun { Loggable::arrow_datatype() { static const auto datatype = arrow::sparse_union({ arrow::field("_null_markers", arrow::null(), true, nullptr), - arrow::field("GradientDark", arrow::null(), false), - arrow::field("GradientBright", arrow::null(), false), - arrow::field("SolidColor", arrow::null(), false), + arrow::field("GradientDark", arrow::null(), true), + arrow::field("GradientBright", arrow::null(), true), + arrow::field("SolidColor", arrow::null(), true), }); return datatype; } diff --git a/rerun_cpp/src/rerun/blueprint/components/container_kind.cpp b/rerun_cpp/src/rerun/blueprint/components/container_kind.cpp index 84651d071328..dec91deb4b2e 100644 --- a/rerun_cpp/src/rerun/blueprint/components/container_kind.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/container_kind.cpp @@ -11,10 +11,10 @@ namespace rerun { Loggable::arrow_datatype() { static const auto datatype = arrow::sparse_union({ arrow::field("_null_markers", arrow::null(), true, nullptr), - arrow::field("Tabs", arrow::null(), false), - arrow::field("Horizontal", arrow::null(), false), - arrow::field("Vertical", arrow::null(), false), - arrow::field("Grid", arrow::null(), false), + arrow::field("Tabs", arrow::null(), true), + arrow::field("Horizontal", arrow::null(), true), + arrow::field("Vertical", arrow::null(), true), + arrow::field("Grid", arrow::null(), true), }); return datatype; } diff --git a/rerun_cpp/src/rerun/blueprint/components/corner2d.cpp b/rerun_cpp/src/rerun/blueprint/components/corner2d.cpp index 20390a943227..abc6f3e33d6e 100644 --- a/rerun_cpp/src/rerun/blueprint/components/corner2d.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/corner2d.cpp @@ -11,10 +11,10 @@ namespace rerun { Loggable::arrow_datatype() { static const auto datatype = arrow::sparse_union({ arrow::field("_null_markers", arrow::null(), true, nullptr), - arrow::field("LeftTop", arrow::null(), false), - arrow::field("RightTop", arrow::null(), false), - arrow::field("LeftBottom", arrow::null(), false), - arrow::field("RightBottom", arrow::null(), false), + arrow::field("LeftTop", arrow::null(), true), + arrow::field("RightTop", arrow::null(), true), + arrow::field("LeftBottom", arrow::null(), true), + arrow::field("RightBottom", arrow::null(), true), }); return datatype; } diff --git a/rerun_cpp/src/rerun/components/marker_shape.cpp b/rerun_cpp/src/rerun/components/marker_shape.cpp index d105942e2021..0c94783c9748 100644 --- a/rerun_cpp/src/rerun/components/marker_shape.cpp +++ b/rerun_cpp/src/rerun/components/marker_shape.cpp @@ -10,16 +10,16 @@ namespace rerun { const std::shared_ptr& Loggable::arrow_datatype() { static const auto datatype = arrow::sparse_union({ arrow::field("_null_markers", arrow::null(), true, nullptr), - arrow::field("Circle", arrow::null(), false), - arrow::field("Diamond", arrow::null(), false), - arrow::field("Square", arrow::null(), false), - arrow::field("Cross", arrow::null(), false), - arrow::field("Plus", arrow::null(), false), - arrow::field("Up", arrow::null(), false), - arrow::field("Down", arrow::null(), false), - arrow::field("Left", arrow::null(), false), - arrow::field("Right", arrow::null(), false), - arrow::field("Asterisk", arrow::null(), false), + arrow::field("Circle", arrow::null(), true), + arrow::field("Diamond", arrow::null(), true), + arrow::field("Square", arrow::null(), true), + arrow::field("Cross", arrow::null(), true), + arrow::field("Plus", arrow::null(), true), + arrow::field("Up", arrow::null(), true), + arrow::field("Down", arrow::null(), true), + arrow::field("Left", arrow::null(), true), + arrow::field("Right", arrow::null(), true), + arrow::field("Asterisk", arrow::null(), true), }); return datatype; } diff --git a/rerun_cpp/tests/generated/components/enum_test.cpp b/rerun_cpp/tests/generated/components/enum_test.cpp index 4a6dba776640..6e49ee6a4d35 100644 --- a/rerun_cpp/tests/generated/components/enum_test.cpp +++ b/rerun_cpp/tests/generated/components/enum_test.cpp @@ -10,12 +10,12 @@ namespace rerun { const std::shared_ptr& Loggable::arrow_datatype() { static const auto datatype = arrow::sparse_union({ arrow::field("_null_markers", arrow::null(), true, nullptr), - arrow::field("Up", arrow::null(), false), - arrow::field("Down", arrow::null(), false), - arrow::field("Right", arrow::null(), false), - arrow::field("Left", arrow::null(), false), - arrow::field("Forward", arrow::null(), false), - arrow::field("Back", arrow::null(), false), + arrow::field("Up", arrow::null(), true), + arrow::field("Down", arrow::null(), true), + arrow::field("Right", arrow::null(), true), + arrow::field("Left", arrow::null(), true), + arrow::field("Forward", arrow::null(), true), + arrow::field("Back", arrow::null(), true), }); return datatype; } From 3bf45c4dbe8e6f0a5a0725d5e2d424aeccf04cba Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 18 Mar 2024 10:42:28 +0100 Subject: [PATCH 043/508] Fewer cpp files: Inline forward serialization of transparent components to their respective datatypes (#5544) ### What * don't generate `fill_arrow_array_builder_method` if it's not needed * inline fully transparent components whose serialization is implemented by a datatypes (that's most of them!) -> removes lots of cpp files, thus cutting down compile times and amount of code @ reviewer: all the interesting changes are `crates/re_types_builder/src/codegen/cpp/mod.rs`, everything else is just an example ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5544/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5544/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5544/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5544) - [Docs preview](https://rerun.io/preview/fd6c99047b0a4b6c32a022073eb646e4fffbcd68/docs) - [Examples preview](https://rerun.io/preview/fd6c99047b0a4b6c32a022073eb646e4fffbcd68/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../re_types_builder/src/codegen/cpp/mod.rs | 237 ++++++++++++------ .../rerun/blueprint/components/.gitattributes | 10 - .../rerun/blueprint/components/active_tab.cpp | 55 ---- .../rerun/blueprint/components/active_tab.hpp | 23 +- .../blueprint/components/auto_layout.cpp | 40 +-- .../blueprint/components/auto_layout.hpp | 10 +- .../blueprint/components/auto_space_views.cpp | 44 ++-- .../blueprint/components/auto_space_views.hpp | 10 +- .../components/background3d_kind.cpp | 46 ++-- .../components/background3d_kind.hpp | 10 +- .../blueprint/components/column_share.cpp | 40 +-- .../blueprint/components/column_share.hpp | 10 +- .../blueprint/components/container_kind.cpp | 44 ++-- .../blueprint/components/container_kind.hpp | 10 +- .../rerun/blueprint/components/corner2d.cpp | 40 +-- .../rerun/blueprint/components/corner2d.hpp | 10 +- .../entity_properties_component.cpp | 44 ++-- .../entity_properties_component.hpp | 10 +- .../blueprint/components/grid_columns.cpp | 40 +-- .../blueprint/components/grid_columns.hpp | 10 +- .../blueprint/components/included_content.cpp | 58 ----- .../blueprint/components/included_content.hpp | 28 +-- .../components/included_space_view.cpp | 58 ----- .../components/included_space_view.hpp | 28 +-- .../components/lock_range_during_zoom.cpp | 46 ++-- .../components/lock_range_during_zoom.hpp | 10 +- .../blueprint/components/panel_expanded.cpp | 57 ----- .../blueprint/components/panel_expanded.hpp | 23 +- .../blueprint/components/query_expression.cpp | 58 ----- .../blueprint/components/query_expression.hpp | 23 +- .../blueprint/components/root_container.cpp | 57 ----- .../blueprint/components/root_container.hpp | 23 +- .../rerun/blueprint/components/row_share.cpp | 40 +-- .../rerun/blueprint/components/row_share.hpp | 10 +- .../blueprint/components/space_view_class.cpp | 57 ----- .../blueprint/components/space_view_class.hpp | 23 +- .../components/space_view_maximized.cpp | 58 ----- .../components/space_view_maximized.hpp | 28 +-- .../components/space_view_origin.cpp | 58 ----- .../components/space_view_origin.hpp | 28 +-- .../components/viewer_recommendation_hash.cpp | 60 ----- .../components/viewer_recommendation_hash.hpp | 30 +-- .../rerun/blueprint/components/visible.cpp | 40 +-- .../rerun/blueprint/components/visible.hpp | 10 +- rerun_cpp/src/rerun/components/.gitattributes | 22 -- .../rerun/components/annotation_context.cpp | 40 +-- .../rerun/components/annotation_context.hpp | 10 +- rerun_cpp/src/rerun/components/blob.cpp | 40 +-- rerun_cpp/src/rerun/components/blob.hpp | 10 +- rerun_cpp/src/rerun/components/class_id.cpp | 51 ---- rerun_cpp/src/rerun/components/class_id.hpp | 27 +- .../rerun/components/clear_is_recursive.cpp | 40 +-- .../rerun/components/clear_is_recursive.hpp | 10 +- rerun_cpp/src/rerun/components/color.cpp | 51 ---- rerun_cpp/src/rerun/components/color.hpp | 27 +- .../src/rerun/components/depth_meter.cpp | 40 +-- .../src/rerun/components/depth_meter.hpp | 10 +- .../rerun/components/disconnected_space.cpp | 40 +-- .../rerun/components/disconnected_space.hpp | 10 +- rerun_cpp/src/rerun/components/draw_order.cpp | 40 +-- rerun_cpp/src/rerun/components/draw_order.hpp | 10 +- .../src/rerun/components/half_sizes2d.cpp | 52 ---- .../src/rerun/components/half_sizes2d.hpp | 23 +- .../src/rerun/components/half_sizes3d.cpp | 52 ---- .../src/rerun/components/half_sizes3d.hpp | 23 +- .../src/rerun/components/instance_key.cpp | 40 +-- .../src/rerun/components/instance_key.hpp | 10 +- .../src/rerun/components/keypoint_id.cpp | 51 ---- .../src/rerun/components/keypoint_id.hpp | 28 +-- .../src/rerun/components/line_strip2d.cpp | 40 +-- .../src/rerun/components/line_strip2d.hpp | 10 +- .../src/rerun/components/line_strip3d.cpp | 40 +-- .../src/rerun/components/line_strip3d.hpp | 10 +- .../src/rerun/components/marker_shape.cpp | 40 +-- .../src/rerun/components/marker_shape.hpp | 10 +- .../src/rerun/components/marker_size.cpp | 40 +-- .../src/rerun/components/marker_size.hpp | 10 +- rerun_cpp/src/rerun/components/material.cpp | 51 ---- rerun_cpp/src/rerun/components/material.hpp | 25 +- rerun_cpp/src/rerun/components/media_type.cpp | 51 ---- rerun_cpp/src/rerun/components/media_type.hpp | 23 +- .../src/rerun/components/mesh_properties.cpp | 54 ---- .../src/rerun/components/mesh_properties.hpp | 26 +- rerun_cpp/src/rerun/components/name.cpp | 51 ---- rerun_cpp/src/rerun/components/name.hpp | 22 +- .../components/out_of_tree_transform3d.cpp | 55 ---- .../components/out_of_tree_transform3d.hpp | 28 +-- .../rerun/components/pinhole_projection.cpp | 53 ---- .../rerun/components/pinhole_projection.hpp | 26 +- rerun_cpp/src/rerun/components/position2d.cpp | 52 ---- rerun_cpp/src/rerun/components/position2d.hpp | 23 +- rerun_cpp/src/rerun/components/position3d.cpp | 52 ---- rerun_cpp/src/rerun/components/position3d.hpp | 23 +- rerun_cpp/src/rerun/components/radius.cpp | 40 +-- rerun_cpp/src/rerun/components/radius.hpp | 10 +- rerun_cpp/src/rerun/components/range1d.cpp | 40 +-- rerun_cpp/src/rerun/components/range1d.hpp | 10 +- rerun_cpp/src/rerun/components/resolution.cpp | 52 ---- rerun_cpp/src/rerun/components/resolution.hpp | 26 +- rerun_cpp/src/rerun/components/rotation3d.cpp | 52 ---- rerun_cpp/src/rerun/components/rotation3d.hpp | 26 +- rerun_cpp/src/rerun/components/scalar.cpp | 40 +-- rerun_cpp/src/rerun/components/scalar.hpp | 10 +- .../rerun/components/scalar_scattering.cpp | 40 +-- .../rerun/components/scalar_scattering.hpp | 10 +- .../src/rerun/components/stroke_width.cpp | 40 +-- .../src/rerun/components/stroke_width.hpp | 10 +- .../src/rerun/components/tensor_data.cpp | 51 ---- .../src/rerun/components/tensor_data.hpp | 26 +- rerun_cpp/src/rerun/components/texcoord2d.cpp | 52 ---- rerun_cpp/src/rerun/components/texcoord2d.hpp | 23 +- rerun_cpp/src/rerun/components/text.cpp | 51 ---- rerun_cpp/src/rerun/components/text.hpp | 22 +- .../src/rerun/components/text_log_level.cpp | 51 ---- .../src/rerun/components/text_log_level.hpp | 23 +- .../src/rerun/components/transform3d.cpp | 52 ---- .../src/rerun/components/transform3d.hpp | 26 +- rerun_cpp/src/rerun/components/vector2d.cpp | 52 ---- rerun_cpp/src/rerun/components/vector2d.hpp | 23 +- rerun_cpp/src/rerun/components/vector3d.cpp | 52 ---- rerun_cpp/src/rerun/components/vector3d.hpp | 23 +- .../src/rerun/components/view_coordinates.cpp | 40 +-- .../src/rerun/components/view_coordinates.hpp | 10 +- .../rerun/components/visualizer_overrides.cpp | 40 +-- .../rerun/components/visualizer_overrides.hpp | 10 +- rerun_cpp/src/rerun/datatypes/angle.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/angle.hpp | 10 +- .../src/rerun/datatypes/annotation_info.cpp | 40 +-- .../src/rerun/datatypes/annotation_info.hpp | 10 +- rerun_cpp/src/rerun/datatypes/bool.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/bool.hpp | 10 +- .../src/rerun/datatypes/class_description.cpp | 40 +-- .../src/rerun/datatypes/class_description.hpp | 10 +- .../datatypes/class_description_map_elem.cpp | 40 +-- .../datatypes/class_description_map_elem.hpp | 10 +- rerun_cpp/src/rerun/datatypes/class_id.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/class_id.hpp | 10 +- rerun_cpp/src/rerun/datatypes/entity_path.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/entity_path.hpp | 10 +- rerun_cpp/src/rerun/datatypes/float32.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/float32.hpp | 10 +- rerun_cpp/src/rerun/datatypes/keypoint_id.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/keypoint_id.hpp | 10 +- .../src/rerun/datatypes/keypoint_pair.cpp | 40 +-- .../src/rerun/datatypes/keypoint_pair.hpp | 10 +- rerun_cpp/src/rerun/datatypes/mat3x3.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/mat3x3.hpp | 10 +- rerun_cpp/src/rerun/datatypes/mat4x4.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/mat4x4.hpp | 10 +- rerun_cpp/src/rerun/datatypes/material.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/material.hpp | 10 +- .../src/rerun/datatypes/mesh_properties.cpp | 40 +-- .../src/rerun/datatypes/mesh_properties.hpp | 10 +- rerun_cpp/src/rerun/datatypes/quaternion.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/quaternion.hpp | 10 +- rerun_cpp/src/rerun/datatypes/rgba32.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/rgba32.hpp | 10 +- rerun_cpp/src/rerun/datatypes/rotation3d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/rotation3d.hpp | 10 +- .../rerun/datatypes/rotation_axis_angle.cpp | 40 +-- .../rerun/datatypes/rotation_axis_angle.hpp | 10 +- rerun_cpp/src/rerun/datatypes/scale3d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/scale3d.hpp | 10 +- .../src/rerun/datatypes/tensor_buffer.cpp | 40 +-- .../src/rerun/datatypes/tensor_buffer.hpp | 10 +- rerun_cpp/src/rerun/datatypes/tensor_data.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/tensor_data.hpp | 10 +- .../src/rerun/datatypes/tensor_dimension.cpp | 40 +-- .../src/rerun/datatypes/tensor_dimension.hpp | 10 +- rerun_cpp/src/rerun/datatypes/transform3d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/transform3d.hpp | 10 +- .../datatypes/translation_and_mat3x3.cpp | 40 +-- .../datatypes/translation_and_mat3x3.hpp | 10 +- .../translation_rotation_scale3d.cpp | 44 ++-- .../translation_rotation_scale3d.hpp | 10 +- rerun_cpp/src/rerun/datatypes/uint32.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/uint32.hpp | 10 +- rerun_cpp/src/rerun/datatypes/uint64.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/uint64.hpp | 10 +- rerun_cpp/src/rerun/datatypes/utf8.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/utf8.hpp | 10 +- rerun_cpp/src/rerun/datatypes/uuid.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/uuid.hpp | 10 +- rerun_cpp/src/rerun/datatypes/uvec2d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/uvec2d.hpp | 10 +- rerun_cpp/src/rerun/datatypes/uvec3d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/uvec3d.hpp | 10 +- rerun_cpp/src/rerun/datatypes/uvec4d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/uvec4d.hpp | 10 +- rerun_cpp/src/rerun/datatypes/vec2d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/vec2d.hpp | 10 +- rerun_cpp/src/rerun/datatypes/vec3d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/vec3d.hpp | 10 +- rerun_cpp/src/rerun/datatypes/vec4d.cpp | 40 +-- rerun_cpp/src/rerun/datatypes/vec4d.hpp | 10 +- .../tests/generated/components/.gitattributes | 7 - .../generated/components/affix_fuzzer1.cpp | 51 ---- .../generated/components/affix_fuzzer1.hpp | 26 +- .../generated/components/affix_fuzzer10.cpp | 40 +-- .../generated/components/affix_fuzzer10.hpp | 10 +- .../generated/components/affix_fuzzer11.cpp | 40 +-- .../generated/components/affix_fuzzer11.hpp | 10 +- .../generated/components/affix_fuzzer12.cpp | 40 +-- .../generated/components/affix_fuzzer12.hpp | 10 +- .../generated/components/affix_fuzzer13.cpp | 40 +-- .../generated/components/affix_fuzzer13.hpp | 10 +- .../generated/components/affix_fuzzer14.cpp | 52 ---- .../generated/components/affix_fuzzer14.hpp | 26 +- .../generated/components/affix_fuzzer15.cpp | 34 +-- .../generated/components/affix_fuzzer15.hpp | 10 +- .../generated/components/affix_fuzzer16.cpp | 40 +-- .../generated/components/affix_fuzzer16.hpp | 10 +- .../generated/components/affix_fuzzer17.cpp | 40 +-- .../generated/components/affix_fuzzer17.hpp | 10 +- .../generated/components/affix_fuzzer18.cpp | 40 +-- .../generated/components/affix_fuzzer18.hpp | 10 +- .../generated/components/affix_fuzzer19.cpp | 52 ---- .../generated/components/affix_fuzzer19.hpp | 26 +- .../generated/components/affix_fuzzer2.cpp | 51 ---- .../generated/components/affix_fuzzer2.hpp | 26 +- .../generated/components/affix_fuzzer20.cpp | 52 ---- .../generated/components/affix_fuzzer20.hpp | 26 +- .../generated/components/affix_fuzzer21.cpp | 52 ---- .../generated/components/affix_fuzzer21.hpp | 26 +- .../generated/components/affix_fuzzer22.cpp | 34 +-- .../generated/components/affix_fuzzer22.hpp | 10 +- .../generated/components/affix_fuzzer3.cpp | 51 ---- .../generated/components/affix_fuzzer3.hpp | 26 +- .../generated/components/affix_fuzzer4.cpp | 32 +-- .../generated/components/affix_fuzzer4.hpp | 10 +- .../generated/components/affix_fuzzer5.cpp | 32 +-- .../generated/components/affix_fuzzer5.hpp | 10 +- .../generated/components/affix_fuzzer6.cpp | 32 +-- .../generated/components/affix_fuzzer6.hpp | 10 +- .../generated/components/affix_fuzzer7.cpp | 40 +-- .../generated/components/affix_fuzzer7.hpp | 10 +- .../generated/components/affix_fuzzer8.cpp | 40 +-- .../generated/components/affix_fuzzer8.hpp | 10 +- .../generated/components/affix_fuzzer9.cpp | 40 +-- .../generated/components/affix_fuzzer9.hpp | 10 +- .../tests/generated/components/enum_test.cpp | 40 +-- .../tests/generated/components/enum_test.hpp | 10 +- .../generated/datatypes/affix_fuzzer1.cpp | 40 +-- .../generated/datatypes/affix_fuzzer1.hpp | 10 +- .../generated/datatypes/affix_fuzzer2.cpp | 40 +-- .../generated/datatypes/affix_fuzzer2.hpp | 10 +- .../generated/datatypes/affix_fuzzer20.cpp | 40 +-- .../generated/datatypes/affix_fuzzer20.hpp | 10 +- .../generated/datatypes/affix_fuzzer21.cpp | 40 +-- .../generated/datatypes/affix_fuzzer21.hpp | 10 +- .../generated/datatypes/affix_fuzzer22.cpp | 40 +-- .../generated/datatypes/affix_fuzzer22.hpp | 10 +- .../generated/datatypes/affix_fuzzer3.cpp | 40 +-- .../generated/datatypes/affix_fuzzer3.hpp | 10 +- .../generated/datatypes/affix_fuzzer4.cpp | 40 +-- .../generated/datatypes/affix_fuzzer4.hpp | 10 +- .../generated/datatypes/affix_fuzzer5.cpp | 40 +-- .../generated/datatypes/affix_fuzzer5.hpp | 10 +- .../generated/datatypes/flattened_scalar.cpp | 40 +-- .../generated/datatypes/flattened_scalar.hpp | 10 +- .../datatypes/primitive_component.cpp | 40 +-- .../datatypes/primitive_component.hpp | 10 +- .../generated/datatypes/string_component.cpp | 40 +-- .../generated/datatypes/string_component.hpp | 10 +- 264 files changed, 2779 insertions(+), 5098 deletions(-) delete mode 100644 rerun_cpp/src/rerun/blueprint/components/active_tab.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/included_content.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/included_space_view.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/panel_expanded.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/query_expression.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/root_container.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/space_view_class.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/space_view_maximized.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/space_view_origin.cpp delete mode 100644 rerun_cpp/src/rerun/blueprint/components/viewer_recommendation_hash.cpp delete mode 100644 rerun_cpp/src/rerun/components/class_id.cpp delete mode 100644 rerun_cpp/src/rerun/components/color.cpp delete mode 100644 rerun_cpp/src/rerun/components/half_sizes2d.cpp delete mode 100644 rerun_cpp/src/rerun/components/half_sizes3d.cpp delete mode 100644 rerun_cpp/src/rerun/components/keypoint_id.cpp delete mode 100644 rerun_cpp/src/rerun/components/material.cpp delete mode 100644 rerun_cpp/src/rerun/components/media_type.cpp delete mode 100644 rerun_cpp/src/rerun/components/mesh_properties.cpp delete mode 100644 rerun_cpp/src/rerun/components/name.cpp delete mode 100644 rerun_cpp/src/rerun/components/out_of_tree_transform3d.cpp delete mode 100644 rerun_cpp/src/rerun/components/pinhole_projection.cpp delete mode 100644 rerun_cpp/src/rerun/components/position2d.cpp delete mode 100644 rerun_cpp/src/rerun/components/position3d.cpp delete mode 100644 rerun_cpp/src/rerun/components/resolution.cpp delete mode 100644 rerun_cpp/src/rerun/components/rotation3d.cpp delete mode 100644 rerun_cpp/src/rerun/components/tensor_data.cpp delete mode 100644 rerun_cpp/src/rerun/components/texcoord2d.cpp delete mode 100644 rerun_cpp/src/rerun/components/text.cpp delete mode 100644 rerun_cpp/src/rerun/components/text_log_level.cpp delete mode 100644 rerun_cpp/src/rerun/components/transform3d.cpp delete mode 100644 rerun_cpp/src/rerun/components/vector2d.cpp delete mode 100644 rerun_cpp/src/rerun/components/vector3d.cpp delete mode 100644 rerun_cpp/tests/generated/components/affix_fuzzer1.cpp delete mode 100644 rerun_cpp/tests/generated/components/affix_fuzzer14.cpp delete mode 100644 rerun_cpp/tests/generated/components/affix_fuzzer19.cpp delete mode 100644 rerun_cpp/tests/generated/components/affix_fuzzer2.cpp delete mode 100644 rerun_cpp/tests/generated/components/affix_fuzzer20.cpp delete mode 100644 rerun_cpp/tests/generated/components/affix_fuzzer21.cpp delete mode 100644 rerun_cpp/tests/generated/components/affix_fuzzer3.cpp diff --git a/crates/re_types_builder/src/codegen/cpp/mod.rs b/crates/re_types_builder/src/codegen/cpp/mod.rs index 0ff49abf78c1..697546ab5146 100644 --- a/crates/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/re_types_builder/src/codegen/cpp/mod.rs @@ -241,7 +241,11 @@ fn generate_object_files( let (hpp, cpp) = generate_hpp_cpp(objects, obj, hpp_includes, &hpp_type_extensions)?; - for (extension, tokens) in [("hpp", hpp), ("cpp", cpp)] { + for (extension, tokens) in [("hpp", Some(hpp)), ("cpp", cpp)] { + let Some(tokens) = tokens else { + continue; + }; + let mut contents = string_from_token_stream(&tokens, obj.relative_filepath()); if let Some(hpp_extension_string) = &hpp_extension_string { contents = contents.replace( @@ -348,7 +352,7 @@ fn generate_hpp_cpp( obj: &Object, hpp_includes: Includes, hpp_type_extensions: &TokenStream, -) -> Result<(TokenStream, TokenStream)> { +) -> Result<(TokenStream, Option)> { let QuotedObject { hpp, cpp } = QuotedObject::new(objects, obj, hpp_includes, hpp_type_extensions)?; let snake_case_name = obj.snake_case_name(); @@ -360,10 +364,12 @@ fn generate_hpp_cpp( #pragma_once #hpp }; - let cpp = quote! { - #hash include #header_file_name #NEWLINE_TOKEN #NEWLINE_TOKEN - #cpp - }; + let cpp = cpp.map(|cpp| { + quote! { + #hash include #header_file_name #NEWLINE_TOKEN #NEWLINE_TOKEN + #cpp + } + }); Ok((hpp, cpp)) } @@ -377,7 +383,7 @@ fn pragma_once() -> TokenStream { struct QuotedObject { hpp: TokenStream, - cpp: TokenStream, + cpp: Option, } impl QuotedObject { @@ -637,7 +643,10 @@ impl QuotedObject { #deprecation_ignore_end }; - Self { hpp, cpp } + Self { + hpp, + cpp: Some(cpp), + } } fn from_struct( @@ -714,9 +723,6 @@ impl QuotedObject { } let methods_hpp = methods.iter().map(|m| m.to_hpp_tokens()); - let methods_cpp = methods - .iter() - .map(|m| m.to_cpp_tokens("e!(#type_ident))); let (hpp_loggable, cpp_loggable) = quote_loggable_hpp_and_cpp( obj, @@ -748,14 +754,23 @@ impl QuotedObject { #hpp_loggable }; - let cpp = quote! { - #cpp_includes - namespace rerun::#quoted_namespace { - #(#methods_cpp)* - } + let cpp = if cpp_loggable.is_some() || methods.iter().any(|m| !m.inline) { + let methods_cpp = methods + .iter() + .map(|m| m.to_cpp_tokens("e!(#type_ident))); - #cpp_loggable + Some(quote! { + #cpp_includes + + namespace rerun::#quoted_namespace { + #(#methods_cpp)* + } + + #cpp_loggable + }) + } else { + None }; Self { hpp, cpp } @@ -1157,7 +1172,10 @@ impl QuotedObject { #cpp_loggable }; - Self { hpp, cpp } + Self { + hpp, + cpp: Some(cpp), + } } // C-style enum @@ -1229,7 +1247,10 @@ impl QuotedObject { #cpp_loggable }; - Self { hpp, cpp } + Self { + hpp, + cpp: Some(cpp), + } } } @@ -1323,6 +1344,16 @@ fn add_copy_assignment_and_constructor( methods } +/// If the type forwards to another rerun defined type, returns the fully qualified name of that type. +fn transparent_forwarded_fqname(obj: &Object) -> Option<&str> { + if obj.is_arrow_transparent() && obj.fields.len() == 1 && !obj.fields[0].is_nullable { + if let Type::Object(fqname) = &obj.fields[0].typ { + return Some(fqname); + } + } + None +} + fn arrow_data_type_method( obj: &Object, objects: &Objects, @@ -1331,15 +1362,35 @@ fn arrow_data_type_method( hpp_declarations: &mut ForwardDecls, ) -> Method { hpp_includes.insert_system("memory"); // std::shared_ptr - cpp_includes.insert_system("arrow/type_fwd.h"); - hpp_declarations.insert("arrow", ForwardDecl::Class(format_ident!("DataType"))); - let quoted_datatype = quote_arrow_data_type( - &Type::Object(obj.fqname.clone()), - objects, - cpp_includes, - true, - ); + let (inline, definition_body) = + if let Some(forwarded_fqname) = transparent_forwarded_fqname(obj) { + let forwarded_type = quote_fqname_as_type_path(hpp_includes, forwarded_fqname); + ( + true, + quote! { + return Loggable<#forwarded_type>::arrow_datatype(); + }, + ) + } else { + cpp_includes.insert_system("arrow/type_fwd.h"); + hpp_declarations.insert("arrow", ForwardDecl::Class(format_ident!("DataType"))); + + let quoted_datatype = quote_arrow_data_type( + &Type::Object(obj.fqname.clone()), + objects, + cpp_includes, + true, + ); + + ( + false, + quote! { + static const auto datatype = #quoted_datatype; + return datatype; + }, + ) + }; Method { docs: "Returns the arrow data type this type corresponds to.".into(), @@ -1348,11 +1399,8 @@ fn arrow_data_type_method( return_type: quote! { const std::shared_ptr& }, name_and_parameters: quote! { arrow_datatype() }, }, - definition_body: quote! { - static const auto datatype = #quoted_datatype; - return datatype; - }, - inline: false, + definition_body, + inline, } } @@ -1405,17 +1453,10 @@ fn to_arrow_method( declarations: &mut ForwardDecls, ) -> Method { hpp_includes.insert_system("memory"); // std::shared_ptr - hpp_includes.insert_rerun("result.hpp"); - declarations.insert("arrow", ForwardDecl::Class(format_ident!("Array"))); - - let todo_pool = quote_comment("TODO(andreas): Allow configuring the memory pool."); - - // Only need this in the cpp file where we don't need to forward declare the arrow builder type. - let arrow_builder_type = - arrow_array_builder_type_object(obj, objects, &mut ForwardDecls::default()); let type_ident = obj.ident(); let namespace_ident = obj.namespace_ident(); + let quoted_namespace = if let Some(scope) = obj.scope() { let scope = format_ident!("{}", scope); quote! { #scope::#namespace_ident} @@ -1423,6 +1464,52 @@ fn to_arrow_method( quote! {#namespace_ident} }; + let (inline, definition_body) = if let Some(forwarded_fqname) = + transparent_forwarded_fqname(obj) + { + let forwarded_type = quote_fqname_as_type_path(hpp_includes, forwarded_fqname); + let field_name = format_ident!("{}", obj.fields[0].snake_case_name()); + + ( + true, + quote! { + return Loggable<#forwarded_type>::to_arrow(&instances->#field_name, num_instances); + }, + ) + } else { + hpp_includes.insert_rerun("result.hpp"); + declarations.insert("arrow", ForwardDecl::Class(format_ident!("Array"))); + + let todo_pool = quote_comment("TODO(andreas): Allow configuring the memory pool."); + + // Only need this in the cpp file where we don't need to forward declare the arrow builder type. + let arrow_builder_type = + arrow_array_builder_type_object(obj, objects, &mut ForwardDecls::default()); + + ( + false, + quote! { + #NEWLINE_TOKEN + #todo_pool + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + #NEWLINE_TOKEN + #NEWLINE_TOKEN + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable<#quoted_namespace::#type_ident>::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + }, + ) + }; + Method { docs: format!( "Serializes an array of `rerun::{quoted_namespace}::{type_ident}` into an arrow array." @@ -1435,26 +1522,8 @@ fn to_arrow_method( to_arrow(const #quoted_namespace::#type_ident* instances, size_t num_instances) }, }, - definition_body: quote! { - #NEWLINE_TOKEN - #todo_pool - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - #NEWLINE_TOKEN - #NEWLINE_TOKEN - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable<#quoted_namespace::#type_ident>::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - }, - inline: false, + definition_body, + inline, } } @@ -2371,7 +2440,7 @@ fn quote_loggable_hpp_and_cpp( hpp_includes: &mut Includes, cpp_includes: &mut Includes, hpp_declarations: &mut ForwardDecls, -) -> (TokenStream, TokenStream) { +) -> (TokenStream, Option) { assert!(obj.kind != ObjectKind::Archetype); let namespace_ident = obj.namespace_ident(); @@ -2385,14 +2454,38 @@ fn quote_loggable_hpp_and_cpp( }; let fqname = &obj.fqname; + let loggable_type_name = quote! { Loggable<#quoted_namespace::#type_ident> }; - let methods = vec![ + let mut methods = vec![ arrow_data_type_method(obj, objects, hpp_includes, cpp_includes, hpp_declarations), - fill_arrow_array_builder_method(obj, cpp_includes, hpp_declarations, objects), to_arrow_method(obj, objects, hpp_includes, hpp_declarations), ]; - let loggable_type_name = quote! { Loggable<#quoted_namespace::#type_ident> }; + let predeclarations_and_static_assertions = if let Some(forwarded_fqname) = + transparent_forwarded_fqname(obj) + { + // We only actually need `to_arrow`, everything else is just nice to have. + + let forwarded_type = quote_fqname_as_type_path(hpp_includes, forwarded_fqname); + + // Don't to pre-declare `Loggable` if we're forwarding to another type - it's already known in this case. + quote! { static_assert(sizeof(#forwarded_type) == sizeof(#quoted_namespace::#type_ident)); } + } else { + // `fill_arrow_array_builder_method` is used as a utility to implement `to_arrow`. + // We only need it if we're not forwarding to another type. + methods.push(fill_arrow_array_builder_method( + obj, + cpp_includes, + hpp_declarations, + objects, + )); + + quote! { + // Instead of including loggable.hpp, simply re-declare the template since it's trivial + template + struct Loggable; + } + }; let methods_hpp = methods.iter().map(|m| m.to_hpp_tokens()); let methods_cpp = methods.iter().map(|m| m.to_cpp_tokens(&loggable_type_name)); @@ -2400,9 +2493,7 @@ fn quote_loggable_hpp_and_cpp( let hpp = quote! { namespace rerun { - // Instead of including loggable.hpp, simply re-declare the template since it's trivial - template - struct Loggable; + #predeclarations_and_static_assertions #hide_from_docs_comment template<> @@ -2415,10 +2506,14 @@ fn quote_loggable_hpp_and_cpp( } }; - let cpp = quote! { - namespace rerun { - #(#methods_cpp)* - } + let cpp = if methods.iter().any(|m| !m.inline) { + Some(quote! { + namespace rerun { + #(#methods_cpp)* + } + }) + } else { + None }; (hpp, cpp) diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index a77b30d84754..c013fc7cd820 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -1,7 +1,6 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -active_tab.cpp linguist-generated=true active_tab.hpp linguist-generated=true auto_layout.cpp linguist-generated=true auto_layout.hpp linguist-generated=true @@ -19,27 +18,18 @@ entity_properties_component.cpp linguist-generated=true entity_properties_component.hpp linguist-generated=true grid_columns.cpp linguist-generated=true grid_columns.hpp linguist-generated=true -included_content.cpp linguist-generated=true included_content.hpp linguist-generated=true -included_space_view.cpp linguist-generated=true included_space_view.hpp linguist-generated=true lock_range_during_zoom.cpp linguist-generated=true lock_range_during_zoom.hpp linguist-generated=true -panel_expanded.cpp linguist-generated=true panel_expanded.hpp linguist-generated=true -query_expression.cpp linguist-generated=true query_expression.hpp linguist-generated=true -root_container.cpp linguist-generated=true root_container.hpp linguist-generated=true row_share.cpp linguist-generated=true row_share.hpp linguist-generated=true -space_view_class.cpp linguist-generated=true space_view_class.hpp linguist-generated=true -space_view_maximized.cpp linguist-generated=true space_view_maximized.hpp linguist-generated=true -space_view_origin.cpp linguist-generated=true space_view_origin.hpp linguist-generated=true -viewer_recommendation_hash.cpp linguist-generated=true viewer_recommendation_hash.hpp linguist-generated=true visible.cpp linguist-generated=true visible.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/active_tab.cpp b/rerun_cpp/src/rerun/blueprint/components/active_tab.cpp deleted file mode 100644 index 2598fc7be74b..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/active_tab.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/active_tab.fbs". - -#include "active_tab.hpp" - -#include "../../datatypes/entity_path.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::ActiveTab* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::EntityPath) == sizeof(blueprint::components::ActiveTab) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const blueprint::components::ActiveTab* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/active_tab.hpp b/rerun_cpp/src/rerun/blueprint/components/active_tab.hpp index a93295153a0d..545dbb4dee7c 100644 --- a/rerun_cpp/src/rerun/blueprint/components/active_tab.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/active_tab.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: The active tab in a tabbed container. struct ActiveTab { @@ -50,8 +44,7 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::EntityPath) == sizeof(blueprint::components::ActiveTab)); /// \private template <> @@ -59,17 +52,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.ActiveTab"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::ActiveTab* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::ActiveTab` into an arrow array. static Result> to_arrow( const blueprint::components::ActiveTab* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->tab, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/auto_layout.cpp b/rerun_cpp/src/rerun/blueprint/components/auto_layout.cpp index 0394e3ad9259..c211bd24ac10 100644 --- a/rerun_cpp/src/rerun/blueprint/components/auto_layout.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/auto_layout.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const blueprint::components::AutoLayout* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::BooleanBuilder* builder, const blueprint::components::AutoLayout* elements, size_t num_elements @@ -37,24 +57,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const blueprint::components::AutoLayout* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/auto_layout.hpp b/rerun_cpp/src/rerun/blueprint/components/auto_layout.hpp index de68d0c26711..5d9536882109 100644 --- a/rerun_cpp/src/rerun/blueprint/components/auto_layout.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/auto_layout.hpp @@ -45,15 +45,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::AutoLayout` into an arrow array. + static Result> to_arrow( + const blueprint::components::AutoLayout* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::BooleanBuilder* builder, const blueprint::components::AutoLayout* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::AutoLayout` into an arrow array. - static Result> to_arrow( - const blueprint::components::AutoLayout* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/auto_space_views.cpp b/rerun_cpp/src/rerun/blueprint/components/auto_space_views.cpp index 2acadde9fc13..4c5dee19ad18 100644 --- a/rerun_cpp/src/rerun/blueprint/components/auto_space_views.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/auto_space_views.cpp @@ -15,6 +15,28 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const blueprint::components::AutoSpaceViews* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK( + Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + ) + ); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::BooleanBuilder* builder, const blueprint::components::AutoSpaceViews* elements, size_t num_elements @@ -37,26 +59,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const blueprint::components::AutoSpaceViews* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/auto_space_views.hpp b/rerun_cpp/src/rerun/blueprint/components/auto_space_views.hpp index 3ea401ebb02c..c4e520a722f9 100644 --- a/rerun_cpp/src/rerun/blueprint/components/auto_space_views.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/auto_space_views.hpp @@ -45,15 +45,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::AutoSpaceViews` into an arrow array. + static Result> to_arrow( + const blueprint::components::AutoSpaceViews* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::BooleanBuilder* builder, const blueprint::components::AutoSpaceViews* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::AutoSpaceViews` into an arrow array. - static Result> to_arrow( - const blueprint::components::AutoSpaceViews* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp index 7a99c3460f99..7d6c7e969104 100644 --- a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp @@ -18,29 +18,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::SparseUnionBuilder* builder, const blueprint::components::Background3DKind* elements, - size_t num_elements - ) { - if (builder == nullptr) { - return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); - } - if (elements == nullptr) { - return rerun::Error( - ErrorCode::UnexpectedNullArgument, - "Cannot serialize null pointer to arrow array." - ); - } - - ARROW_RETURN_NOT_OK(builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - const auto variant = elements[elem_idx]; - ARROW_RETURN_NOT_OK(builder->Append(static_cast(variant))); - } - - return Error::ok(); - } - Result> Loggable::to_arrow( const blueprint::components::Background3DKind* instances, size_t num_instances @@ -63,4 +40,27 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::SparseUnionBuilder* builder, const blueprint::components::Background3DKind* elements, + size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + ARROW_RETURN_NOT_OK(builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + const auto variant = elements[elem_idx]; + ARROW_RETURN_NOT_OK(builder->Append(static_cast(variant))); + } + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp index 41c1235f6537..17af1c8a3ea2 100644 --- a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp @@ -41,15 +41,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::Background3DKind` into an arrow array. + static Result> to_arrow( + const blueprint::components::Background3DKind* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const blueprint::components::Background3DKind* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::Background3DKind` into an arrow array. - static Result> to_arrow( - const blueprint::components::Background3DKind* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/column_share.cpp b/rerun_cpp/src/rerun/blueprint/components/column_share.cpp index 3cb9767d36b0..65287e8e8115 100644 --- a/rerun_cpp/src/rerun/blueprint/components/column_share.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/column_share.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const blueprint::components::ColumnShare* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const blueprint::components::ColumnShare* elements, size_t num_elements @@ -36,24 +56,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const blueprint::components::ColumnShare* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/column_share.hpp b/rerun_cpp/src/rerun/blueprint/components/column_share.hpp index e49e3bfaa020..a3fdf109717e 100644 --- a/rerun_cpp/src/rerun/blueprint/components/column_share.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/column_share.hpp @@ -49,15 +49,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::ColumnShare` into an arrow array. + static Result> to_arrow( + const blueprint::components::ColumnShare* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FloatBuilder* builder, const blueprint::components::ColumnShare* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::ColumnShare` into an arrow array. - static Result> to_arrow( - const blueprint::components::ColumnShare* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/container_kind.cpp b/rerun_cpp/src/rerun/blueprint/components/container_kind.cpp index dec91deb4b2e..ef9d182851fa 100644 --- a/rerun_cpp/src/rerun/blueprint/components/container_kind.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/container_kind.cpp @@ -19,6 +19,28 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const blueprint::components::ContainerKind* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK( + Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + ) + ); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const blueprint::components::ContainerKind* elements, size_t num_elements @@ -41,26 +63,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const blueprint::components::ContainerKind* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/container_kind.hpp b/rerun_cpp/src/rerun/blueprint/components/container_kind.hpp index e8c94d219a3e..467e24b7eb00 100644 --- a/rerun_cpp/src/rerun/blueprint/components/container_kind.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/container_kind.hpp @@ -40,15 +40,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::ContainerKind` into an arrow array. + static Result> to_arrow( + const blueprint::components::ContainerKind* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const blueprint::components::ContainerKind* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::ContainerKind` into an arrow array. - static Result> to_arrow( - const blueprint::components::ContainerKind* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/corner2d.cpp b/rerun_cpp/src/rerun/blueprint/components/corner2d.cpp index abc6f3e33d6e..0ae2cc542621 100644 --- a/rerun_cpp/src/rerun/blueprint/components/corner2d.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/corner2d.cpp @@ -19,6 +19,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const blueprint::components::Corner2D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const blueprint::components::Corner2D* elements, size_t num_elements @@ -41,24 +61,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const blueprint::components::Corner2D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/corner2d.hpp b/rerun_cpp/src/rerun/blueprint/components/corner2d.hpp index dc5ad66be1ed..2f7559b458f4 100644 --- a/rerun_cpp/src/rerun/blueprint/components/corner2d.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/corner2d.hpp @@ -40,15 +40,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::Corner2D` into an arrow array. + static Result> to_arrow( + const blueprint::components::Corner2D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const blueprint::components::Corner2D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::Corner2D` into an arrow array. - static Result> to_arrow( - const blueprint::components::Corner2D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.cpp b/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.cpp index dd83bf101300..a427b42010cf 100644 --- a/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.cpp @@ -15,6 +15,28 @@ namespace rerun { return datatype; } + Result> + Loggable::to_arrow( + const blueprint::components::EntityPropertiesComponent* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable:: + fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, @@ -46,26 +68,4 @@ namespace rerun { return Error::ok(); } - - Result> - Loggable::to_arrow( - const blueprint::components::EntityPropertiesComponent* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable:: - fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.hpp b/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.hpp index 66c58b6dbdb8..bf2af30ef06f 100644 --- a/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.hpp @@ -47,15 +47,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::EntityPropertiesComponent` into an arrow array. + static Result> to_arrow( + const blueprint::components::EntityPropertiesComponent* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const blueprint::components::EntityPropertiesComponent* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::EntityPropertiesComponent` into an arrow array. - static Result> to_arrow( - const blueprint::components::EntityPropertiesComponent* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/grid_columns.cpp b/rerun_cpp/src/rerun/blueprint/components/grid_columns.cpp index b3f8a8c07a72..0162fc86dbb4 100644 --- a/rerun_cpp/src/rerun/blueprint/components/grid_columns.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/grid_columns.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const blueprint::components::GridColumns* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::UInt32Builder* builder, const blueprint::components::GridColumns* elements, size_t num_elements @@ -36,24 +56,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const blueprint::components::GridColumns* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/grid_columns.hpp b/rerun_cpp/src/rerun/blueprint/components/grid_columns.hpp index 6ec32f4508c3..ac0e56eb5d71 100644 --- a/rerun_cpp/src/rerun/blueprint/components/grid_columns.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/grid_columns.hpp @@ -49,15 +49,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::GridColumns` into an arrow array. + static Result> to_arrow( + const blueprint::components::GridColumns* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::UInt32Builder* builder, const blueprint::components::GridColumns* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::GridColumns` into an arrow array. - static Result> to_arrow( - const blueprint::components::GridColumns* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/included_content.cpp b/rerun_cpp/src/rerun/blueprint/components/included_content.cpp deleted file mode 100644 index 6dde7e9a1399..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/included_content.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/included_content.fbs". - -#include "included_content.hpp" - -#include "../../datatypes/entity_path.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::IncludedContent* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::EntityPath) == sizeof(blueprint::components::IncludedContent) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> - Loggable::to_arrow( - const blueprint::components::IncludedContent* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/included_content.hpp b/rerun_cpp/src/rerun/blueprint/components/included_content.hpp index aaf1e2e7b5eb..20c143348e04 100644 --- a/rerun_cpp/src/rerun/blueprint/components/included_content.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/included_content.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: All the contents in the container. struct IncludedContent { @@ -51,8 +45,9 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert( + sizeof(rerun::datatypes::EntityPath) == sizeof(blueprint::components::IncludedContent) + ); /// \private template <> @@ -60,17 +55,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.IncludedContent"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::IncludedContent* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::IncludedContent` into an arrow array. static Result> to_arrow( const blueprint::components::IncludedContent* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->contents, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/included_space_view.cpp b/rerun_cpp/src/rerun/blueprint/components/included_space_view.cpp deleted file mode 100644 index 5b36afd60486..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/included_space_view.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/included_space_view.fbs". - -#include "included_space_view.hpp" - -#include "../../datatypes/uuid.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, - const blueprint::components::IncludedSpaceView* elements, size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::Uuid) == sizeof(blueprint::components::IncludedSpaceView) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> - Loggable::to_arrow( - const blueprint::components::IncludedSpaceView* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/included_space_view.hpp b/rerun_cpp/src/rerun/blueprint/components/included_space_view.hpp index 401f17fe69a0..b55cd76bc089 100644 --- a/rerun_cpp/src/rerun/blueprint/components/included_space_view.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/included_space_view.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: The id of a `SpaceView`. /// @@ -48,8 +42,9 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert( + sizeof(rerun::datatypes::Uuid) == sizeof(blueprint::components::IncludedSpaceView) + ); /// \private template <> @@ -57,17 +52,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.IncludedSpaceView"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, - const blueprint::components::IncludedSpaceView* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::IncludedSpaceView` into an arrow array. static Result> to_arrow( const blueprint::components::IncludedSpaceView* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->space_view_id, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.cpp b/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.cpp index 83d7029f2a11..f44feac14b8e 100644 --- a/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.cpp @@ -15,29 +15,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::BooleanBuilder* builder, const blueprint::components::LockRangeDuringZoom* elements, - size_t num_elements - ) { - if (builder == nullptr) { - return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); - } - if (elements == nullptr) { - return rerun::Error( - ErrorCode::UnexpectedNullArgument, - "Cannot serialize null pointer to arrow array." - ); - } - - static_assert(sizeof(*elements) == sizeof(elements->lock_range)); - ARROW_RETURN_NOT_OK(builder->AppendValues( - reinterpret_cast(&elements->lock_range), - static_cast(num_elements) - )); - - return Error::ok(); - } - Result> Loggable::to_arrow( const blueprint::components::LockRangeDuringZoom* instances, size_t num_instances @@ -60,4 +37,27 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::BooleanBuilder* builder, const blueprint::components::LockRangeDuringZoom* elements, + size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + static_assert(sizeof(*elements) == sizeof(elements->lock_range)); + ARROW_RETURN_NOT_OK(builder->AppendValues( + reinterpret_cast(&elements->lock_range), + static_cast(num_elements) + )); + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.hpp b/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.hpp index 42b598553f23..820ea6487f27 100644 --- a/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.hpp @@ -45,15 +45,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::LockRangeDuringZoom` into an arrow array. + static Result> to_arrow( + const blueprint::components::LockRangeDuringZoom* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::BooleanBuilder* builder, const blueprint::components::LockRangeDuringZoom* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::LockRangeDuringZoom` into an arrow array. - static Result> to_arrow( - const blueprint::components::LockRangeDuringZoom* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/panel_expanded.cpp b/rerun_cpp/src/rerun/blueprint/components/panel_expanded.cpp deleted file mode 100644 index de51eb1f8191..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/panel_expanded.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/panel_expanded.fbs". - -#include "panel_expanded.hpp" - -#include "../../datatypes/bool.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::BooleanBuilder* builder, const blueprint::components::PanelExpanded* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::Bool) == sizeof(blueprint::components::PanelExpanded) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const blueprint::components::PanelExpanded* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/panel_expanded.hpp b/rerun_cpp/src/rerun/blueprint/components/panel_expanded.hpp index aa5f694cdd1d..f3c9b4387f3f 100644 --- a/rerun_cpp/src/rerun/blueprint/components/panel_expanded.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/panel_expanded.hpp @@ -9,12 +9,6 @@ #include #include -namespace arrow { - class Array; - class BooleanBuilder; - class DataType; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: Whether an application panel is expanded or not. struct PanelExpanded { @@ -45,8 +39,7 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Bool) == sizeof(blueprint::components::PanelExpanded)); /// \private template <> @@ -54,17 +47,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.PanelExpanded"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::BooleanBuilder* builder, const blueprint::components::PanelExpanded* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::PanelExpanded` into an arrow array. static Result> to_arrow( const blueprint::components::PanelExpanded* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->expanded, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/query_expression.cpp b/rerun_cpp/src/rerun/blueprint/components/query_expression.cpp deleted file mode 100644 index 34ef4f9c584d..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/query_expression.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs". - -#include "query_expression.hpp" - -#include "../../datatypes/utf8.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::QueryExpression* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::Utf8) == sizeof(blueprint::components::QueryExpression) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> - Loggable::to_arrow( - const blueprint::components::QueryExpression* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp b/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp index 2ed83df16a81..5d9042ab6dcd 100644 --- a/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: An individual `QueryExpression` used to filter a set of `EntityPath`s. /// @@ -58,8 +52,7 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(blueprint::components::QueryExpression)); /// \private template <> @@ -67,17 +60,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.QueryExpression"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::QueryExpression* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::QueryExpression` into an arrow array. static Result> to_arrow( const blueprint::components::QueryExpression* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->filter, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/root_container.cpp b/rerun_cpp/src/rerun/blueprint/components/root_container.cpp deleted file mode 100644 index b65f5a5a0bbc..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/root_container.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/root_container.fbs". - -#include "root_container.hpp" - -#include "../../datatypes/uuid.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const blueprint::components::RootContainer* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::Uuid) == sizeof(blueprint::components::RootContainer) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const blueprint::components::RootContainer* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/root_container.hpp b/rerun_cpp/src/rerun/blueprint/components/root_container.hpp index 737f64a5329b..4cd35245c149 100644 --- a/rerun_cpp/src/rerun/blueprint/components/root_container.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/root_container.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: The container that sits at the root of a viewport. struct RootContainer { @@ -47,8 +41,7 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Uuid) == sizeof(blueprint::components::RootContainer)); /// \private template <> @@ -56,17 +49,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.RootContainer"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, - const blueprint::components::RootContainer* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::RootContainer` into an arrow array. static Result> to_arrow( const blueprint::components::RootContainer* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->id, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/row_share.cpp b/rerun_cpp/src/rerun/blueprint/components/row_share.cpp index ba736265da07..da42c70284f9 100644 --- a/rerun_cpp/src/rerun/blueprint/components/row_share.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/row_share.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const blueprint::components::RowShare* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const blueprint::components::RowShare* elements, size_t num_elements @@ -36,24 +56,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const blueprint::components::RowShare* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/row_share.hpp b/rerun_cpp/src/rerun/blueprint/components/row_share.hpp index bdc840d932a1..4a9e53724f76 100644 --- a/rerun_cpp/src/rerun/blueprint/components/row_share.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/row_share.hpp @@ -49,15 +49,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::RowShare` into an arrow array. + static Result> to_arrow( + const blueprint::components::RowShare* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FloatBuilder* builder, const blueprint::components::RowShare* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::RowShare` into an arrow array. - static Result> to_arrow( - const blueprint::components::RowShare* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/space_view_class.cpp b/rerun_cpp/src/rerun/blueprint/components/space_view_class.cpp deleted file mode 100644 index 2badc811cb5c..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/space_view_class.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/space_view_class.fbs". - -#include "space_view_class.hpp" - -#include "../../datatypes/utf8.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::SpaceViewClass* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::Utf8) == sizeof(blueprint::components::SpaceViewClass) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const blueprint::components::SpaceViewClass* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/space_view_class.hpp b/rerun_cpp/src/rerun/blueprint/components/space_view_class.hpp index 428aa26db77c..5f7ed62a5da7 100644 --- a/rerun_cpp/src/rerun/blueprint/components/space_view_class.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/space_view_class.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: The class of a `SpaceView`. struct SpaceViewClass { @@ -47,8 +41,7 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(blueprint::components::SpaceViewClass)); /// \private template <> @@ -56,17 +49,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.SpaceViewClass"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::SpaceViewClass* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::SpaceViewClass` into an arrow array. static Result> to_arrow( const blueprint::components::SpaceViewClass* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->value, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.cpp b/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.cpp deleted file mode 100644 index 245206f2539c..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/space_view_maximized.fbs". - -#include "space_view_maximized.hpp" - -#include "../../datatypes/uuid.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, - const blueprint::components::SpaceViewMaximized* elements, size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::Uuid) == sizeof(blueprint::components::SpaceViewMaximized) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> - Loggable::to_arrow( - const blueprint::components::SpaceViewMaximized* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.hpp b/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.hpp index f3d5579b4a94..525a1323b604 100644 --- a/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: Whether a space view is maximized. /// @@ -48,8 +42,9 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert( + sizeof(rerun::datatypes::Uuid) == sizeof(blueprint::components::SpaceViewMaximized) + ); /// \private template <> @@ -57,17 +52,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.SpaceViewMaximized"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, - const blueprint::components::SpaceViewMaximized* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::SpaceViewMaximized` into an arrow array. static Result> to_arrow( const blueprint::components::SpaceViewMaximized* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->space_view_id, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/space_view_origin.cpp b/rerun_cpp/src/rerun/blueprint/components/space_view_origin.cpp deleted file mode 100644 index 6dd4fab09f27..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/space_view_origin.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/space_view_origin.fbs". - -#include "space_view_origin.hpp" - -#include "../../datatypes/entity_path.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::SpaceViewOrigin* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::EntityPath) == sizeof(blueprint::components::SpaceViewOrigin) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> - Loggable::to_arrow( - const blueprint::components::SpaceViewOrigin* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/space_view_origin.hpp b/rerun_cpp/src/rerun/blueprint/components/space_view_origin.hpp index b2c819486292..6bbb9459b379 100644 --- a/rerun_cpp/src/rerun/blueprint/components/space_view_origin.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/space_view_origin.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: The origin of a `SpaceView`. struct SpaceViewOrigin { @@ -47,8 +41,9 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert( + sizeof(rerun::datatypes::EntityPath) == sizeof(blueprint::components::SpaceViewOrigin) + ); /// \private template <> @@ -56,17 +51,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.SpaceViewOrigin"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const blueprint::components::SpaceViewOrigin* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::SpaceViewOrigin` into an arrow array. static Result> to_arrow( const blueprint::components::SpaceViewOrigin* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->value, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/viewer_recommendation_hash.cpp b/rerun_cpp/src/rerun/blueprint/components/viewer_recommendation_hash.cpp deleted file mode 100644 index b92576dc9b6a..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/viewer_recommendation_hash.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/viewer_recommendation_hash.fbs". - -#include "viewer_recommendation_hash.hpp" - -#include "../../datatypes/uint64.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error - Loggable::fill_arrow_array_builder( - arrow::UInt64Builder* builder, - const blueprint::components::ViewerRecommendationHash* elements, size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::UInt64) == - sizeof(blueprint::components::ViewerRecommendationHash) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> - Loggable::to_arrow( - const blueprint::components::ViewerRecommendationHash* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/viewer_recommendation_hash.hpp b/rerun_cpp/src/rerun/blueprint/components/viewer_recommendation_hash.hpp index c342c6285abe..b18d76ce8d15 100644 --- a/rerun_cpp/src/rerun/blueprint/components/viewer_recommendation_hash.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/viewer_recommendation_hash.hpp @@ -9,17 +9,6 @@ #include #include -namespace arrow { - /// \private - template - class NumericBuilder; - - class Array; - class DataType; - class UInt64Type; - using UInt64Builder = NumericBuilder; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: Hash of a viewer recommendation. /// @@ -52,8 +41,9 @@ namespace rerun::blueprint::components { } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert( + sizeof(rerun::datatypes::UInt64) == sizeof(blueprint::components::ViewerRecommendationHash) + ); /// \private template <> @@ -61,17 +51,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.ViewerRecommendationHash"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt64Builder* builder, - const blueprint::components::ViewerRecommendationHash* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::ViewerRecommendationHash` into an arrow array. static Result> to_arrow( const blueprint::components::ViewerRecommendationHash* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->value, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/visible.cpp b/rerun_cpp/src/rerun/blueprint/components/visible.cpp index 32a6f4af43fb..808af8c61bc5 100644 --- a/rerun_cpp/src/rerun/blueprint/components/visible.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/visible.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const blueprint::components::Visible* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::BooleanBuilder* builder, const blueprint::components::Visible* elements, size_t num_elements @@ -37,24 +57,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const blueprint::components::Visible* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/visible.hpp b/rerun_cpp/src/rerun/blueprint/components/visible.hpp index f980d8a0666a..510a46cacf34 100644 --- a/rerun_cpp/src/rerun/blueprint/components/visible.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/visible.hpp @@ -43,15 +43,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::blueprint:: components::Visible` into an arrow array. + static Result> to_arrow( + const blueprint::components::Visible* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::BooleanBuilder* builder, const blueprint::components::Visible* elements, size_t num_elements ); - - /// Serializes an array of `rerun::blueprint:: components::Visible` into an arrow array. - static Result> to_arrow( - const blueprint::components::Visible* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/.gitattributes b/rerun_cpp/src/rerun/components/.gitattributes index aa8ff1fc3a6a..c6655108354f 100644 --- a/rerun_cpp/src/rerun/components/.gitattributes +++ b/rerun_cpp/src/rerun/components/.gitattributes @@ -5,11 +5,9 @@ annotation_context.cpp linguist-generated=true annotation_context.hpp linguist-generated=true blob.cpp linguist-generated=true blob.hpp linguist-generated=true -class_id.cpp linguist-generated=true class_id.hpp linguist-generated=true clear_is_recursive.cpp linguist-generated=true clear_is_recursive.hpp linguist-generated=true -color.cpp linguist-generated=true color.hpp linguist-generated=true depth_meter.cpp linguist-generated=true depth_meter.hpp linguist-generated=true @@ -17,13 +15,10 @@ disconnected_space.cpp linguist-generated=true disconnected_space.hpp linguist-generated=true draw_order.cpp linguist-generated=true draw_order.hpp linguist-generated=true -half_sizes2d.cpp linguist-generated=true half_sizes2d.hpp linguist-generated=true -half_sizes3d.cpp linguist-generated=true half_sizes3d.hpp linguist-generated=true instance_key.cpp linguist-generated=true instance_key.hpp linguist-generated=true -keypoint_id.cpp linguist-generated=true keypoint_id.hpp linguist-generated=true line_strip2d.cpp linguist-generated=true line_strip2d.hpp linguist-generated=true @@ -33,29 +28,19 @@ marker_shape.cpp linguist-generated=true marker_shape.hpp linguist-generated=true marker_size.cpp linguist-generated=true marker_size.hpp linguist-generated=true -material.cpp linguist-generated=true material.hpp linguist-generated=true -media_type.cpp linguist-generated=true media_type.hpp linguist-generated=true -mesh_properties.cpp linguist-generated=true mesh_properties.hpp linguist-generated=true -name.cpp linguist-generated=true name.hpp linguist-generated=true -out_of_tree_transform3d.cpp linguist-generated=true out_of_tree_transform3d.hpp linguist-generated=true -pinhole_projection.cpp linguist-generated=true pinhole_projection.hpp linguist-generated=true -position2d.cpp linguist-generated=true position2d.hpp linguist-generated=true -position3d.cpp linguist-generated=true position3d.hpp linguist-generated=true radius.cpp linguist-generated=true radius.hpp linguist-generated=true range1d.cpp linguist-generated=true range1d.hpp linguist-generated=true -resolution.cpp linguist-generated=true resolution.hpp linguist-generated=true -rotation3d.cpp linguist-generated=true rotation3d.hpp linguist-generated=true scalar.cpp linguist-generated=true scalar.hpp linguist-generated=true @@ -63,19 +48,12 @@ scalar_scattering.cpp linguist-generated=true scalar_scattering.hpp linguist-generated=true stroke_width.cpp linguist-generated=true stroke_width.hpp linguist-generated=true -tensor_data.cpp linguist-generated=true tensor_data.hpp linguist-generated=true -texcoord2d.cpp linguist-generated=true texcoord2d.hpp linguist-generated=true -text.cpp linguist-generated=true text.hpp linguist-generated=true -text_log_level.cpp linguist-generated=true text_log_level.hpp linguist-generated=true -transform3d.cpp linguist-generated=true transform3d.hpp linguist-generated=true -vector2d.cpp linguist-generated=true vector2d.hpp linguist-generated=true -vector3d.cpp linguist-generated=true vector3d.hpp linguist-generated=true view_coordinates.cpp linguist-generated=true view_coordinates.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/annotation_context.cpp b/rerun_cpp/src/rerun/components/annotation_context.cpp index a8c018c50d65..435a547ca46a 100644 --- a/rerun_cpp/src/rerun/components/annotation_context.cpp +++ b/rerun_cpp/src/rerun/components/annotation_context.cpp @@ -21,6 +21,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AnnotationContext* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AnnotationContext* elements, size_t num_elements @@ -55,24 +75,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AnnotationContext* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/annotation_context.hpp b/rerun_cpp/src/rerun/components/annotation_context.hpp index aab641675dd4..841066ea72eb 100644 --- a/rerun_cpp/src/rerun/components/annotation_context.hpp +++ b/rerun_cpp/src/rerun/components/annotation_context.hpp @@ -84,15 +84,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AnnotationContext` into an arrow array. + static Result> to_arrow( + const components::AnnotationContext* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AnnotationContext* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AnnotationContext` into an arrow array. - static Result> to_arrow( - const components::AnnotationContext* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/blob.cpp b/rerun_cpp/src/rerun/components/blob.cpp index 34c97610fa51..50be1471dba0 100644 --- a/rerun_cpp/src/rerun/components/blob.cpp +++ b/rerun_cpp/src/rerun/components/blob.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::Blob* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::Blob* elements, size_t num_elements ) { @@ -43,24 +63,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::Blob* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/blob.hpp b/rerun_cpp/src/rerun/components/blob.hpp index 0db18fa147a9..8b94d9dfb989 100644 --- a/rerun_cpp/src/rerun/components/blob.hpp +++ b/rerun_cpp/src/rerun/components/blob.hpp @@ -45,14 +45,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::ListBuilder* builder, const components::Blob* elements, size_t num_elements - ); - /// Serializes an array of `rerun::components::Blob` into an arrow array. static Result> to_arrow( const components::Blob* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::ListBuilder* builder, const components::Blob* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/class_id.cpp b/rerun_cpp/src/rerun/components/class_id.cpp deleted file mode 100644 index 8aedab263c8d..000000000000 --- a/rerun_cpp/src/rerun/components/class_id.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/class_id.fbs". - -#include "class_id.hpp" - -#include "../datatypes/class_id.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::UInt16Builder* builder, const components::ClassId* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::ClassId) == sizeof(components::ClassId)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::ClassId* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/class_id.hpp b/rerun_cpp/src/rerun/components/class_id.hpp index 033488e4f982..3da93fb40e95 100644 --- a/rerun_cpp/src/rerun/components/class_id.hpp +++ b/rerun_cpp/src/rerun/components/class_id.hpp @@ -9,17 +9,6 @@ #include #include -namespace arrow { - /// \private - template - class NumericBuilder; - - class Array; - class DataType; - class UInt16Type; - using UInt16Builder = NumericBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A 16-bit ID representing a type of semantic class. struct ClassId { @@ -50,8 +39,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::ClassId) == sizeof(components::ClassId)); /// \private template <> @@ -59,16 +47,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.ClassId"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt16Builder* builder, const components::ClassId* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::ClassId` into an arrow array. static Result> to_arrow( const components::ClassId* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->id, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/clear_is_recursive.cpp b/rerun_cpp/src/rerun/components/clear_is_recursive.cpp index 4eb6614791c8..ad36c3bafa59 100644 --- a/rerun_cpp/src/rerun/components/clear_is_recursive.cpp +++ b/rerun_cpp/src/rerun/components/clear_is_recursive.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::ClearIsRecursive* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::BooleanBuilder* builder, const components::ClearIsRecursive* elements, size_t num_elements @@ -37,24 +57,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::ClearIsRecursive* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/clear_is_recursive.hpp b/rerun_cpp/src/rerun/components/clear_is_recursive.hpp index 58c96eb05502..7862eac2cd2c 100644 --- a/rerun_cpp/src/rerun/components/clear_is_recursive.hpp +++ b/rerun_cpp/src/rerun/components/clear_is_recursive.hpp @@ -44,15 +44,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::ClearIsRecursive` into an arrow array. + static Result> to_arrow( + const components::ClearIsRecursive* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::BooleanBuilder* builder, const components::ClearIsRecursive* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::ClearIsRecursive` into an arrow array. - static Result> to_arrow( - const components::ClearIsRecursive* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/color.cpp b/rerun_cpp/src/rerun/components/color.cpp deleted file mode 100644 index 4a336d839698..000000000000 --- a/rerun_cpp/src/rerun/components/color.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/color.fbs". - -#include "color.hpp" - -#include "../datatypes/rgba32.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::UInt32Builder* builder, const components::Color* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Rgba32) == sizeof(components::Color)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Color* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/color.hpp b/rerun_cpp/src/rerun/components/color.hpp index 5b823032ca9c..3478072deff6 100644 --- a/rerun_cpp/src/rerun/components/color.hpp +++ b/rerun_cpp/src/rerun/components/color.hpp @@ -9,17 +9,6 @@ #include #include -namespace arrow { - /// \private - template - class NumericBuilder; - - class Array; - class DataType; - class UInt32Type; - using UInt32Builder = NumericBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha. /// @@ -75,8 +64,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Rgba32) == sizeof(components::Color)); /// \private template <> @@ -84,16 +72,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Color"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt32Builder* builder, const components::Color* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Color` into an arrow array. static Result> to_arrow( const components::Color* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->rgba, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/depth_meter.cpp b/rerun_cpp/src/rerun/components/depth_meter.cpp index 71e6b78599e1..8d1ff567c255 100644 --- a/rerun_cpp/src/rerun/components/depth_meter.cpp +++ b/rerun_cpp/src/rerun/components/depth_meter.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::DepthMeter* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::DepthMeter* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::DepthMeter* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/depth_meter.hpp b/rerun_cpp/src/rerun/components/depth_meter.hpp index cb3a53eaf449..016b633e0991 100644 --- a/rerun_cpp/src/rerun/components/depth_meter.hpp +++ b/rerun_cpp/src/rerun/components/depth_meter.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::DepthMeter` into an arrow array. + static Result> to_arrow( + const components::DepthMeter* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::DepthMeter* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::DepthMeter` into an arrow array. - static Result> to_arrow( - const components::DepthMeter* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/disconnected_space.cpp b/rerun_cpp/src/rerun/components/disconnected_space.cpp index 11c762d21514..cc879960f41a 100644 --- a/rerun_cpp/src/rerun/components/disconnected_space.cpp +++ b/rerun_cpp/src/rerun/components/disconnected_space.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::DisconnectedSpace* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::BooleanBuilder* builder, const components::DisconnectedSpace* elements, size_t num_elements @@ -37,24 +57,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::DisconnectedSpace* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/disconnected_space.hpp b/rerun_cpp/src/rerun/components/disconnected_space.hpp index f2ffb2a87295..d6201da79e89 100644 --- a/rerun_cpp/src/rerun/components/disconnected_space.hpp +++ b/rerun_cpp/src/rerun/components/disconnected_space.hpp @@ -49,15 +49,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::DisconnectedSpace` into an arrow array. + static Result> to_arrow( + const components::DisconnectedSpace* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::BooleanBuilder* builder, const components::DisconnectedSpace* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::DisconnectedSpace` into an arrow array. - static Result> to_arrow( - const components::DisconnectedSpace* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/draw_order.cpp b/rerun_cpp/src/rerun/components/draw_order.cpp index 714fcf7f8b76..7001c1ea4e7b 100644 --- a/rerun_cpp/src/rerun/components/draw_order.cpp +++ b/rerun_cpp/src/rerun/components/draw_order.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::DrawOrder* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::DrawOrder* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::DrawOrder* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/draw_order.hpp b/rerun_cpp/src/rerun/components/draw_order.hpp index 0f2ad957b8fb..a5c07fed17d9 100644 --- a/rerun_cpp/src/rerun/components/draw_order.hpp +++ b/rerun_cpp/src/rerun/components/draw_order.hpp @@ -54,14 +54,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FloatBuilder* builder, const components::DrawOrder* elements, size_t num_elements - ); - /// Serializes an array of `rerun::components::DrawOrder` into an arrow array. static Result> to_arrow( const components::DrawOrder* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::FloatBuilder* builder, const components::DrawOrder* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/half_sizes2d.cpp b/rerun_cpp/src/rerun/components/half_sizes2d.cpp deleted file mode 100644 index 0263a1942048..000000000000 --- a/rerun_cpp/src/rerun/components/half_sizes2d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/half_sizes2d.fbs". - -#include "half_sizes2d.hpp" - -#include "../datatypes/vec2d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::HalfSizes2D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::HalfSizes2D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::HalfSizes2D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/half_sizes2d.hpp b/rerun_cpp/src/rerun/components/half_sizes2d.hpp index a25fe228f376..e74e8f4d4bb0 100644 --- a/rerun_cpp/src/rerun/components/half_sizes2d.hpp +++ b/rerun_cpp/src/rerun/components/half_sizes2d.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: Half-sizes (extents) of a 2D box along its local axis, starting at its local origin/center. /// @@ -63,8 +57,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::HalfSizes2D)); /// \private template <> @@ -72,17 +65,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.HalfSizes2D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::HalfSizes2D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::HalfSizes2D` into an arrow array. static Result> to_arrow( const components::HalfSizes2D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->xy, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/half_sizes3d.cpp b/rerun_cpp/src/rerun/components/half_sizes3d.cpp deleted file mode 100644 index 01c1c5c8c125..000000000000 --- a/rerun_cpp/src/rerun/components/half_sizes3d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/half_sizes3d.fbs". - -#include "half_sizes3d.hpp" - -#include "../datatypes/vec3d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::HalfSizes3D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Vec3D) == sizeof(components::HalfSizes3D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::HalfSizes3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/half_sizes3d.hpp b/rerun_cpp/src/rerun/components/half_sizes3d.hpp index 0a5742dbe574..255c5ee61a80 100644 --- a/rerun_cpp/src/rerun/components/half_sizes3d.hpp +++ b/rerun_cpp/src/rerun/components/half_sizes3d.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: Half-sizes (extents) of a 3D box along its local axis, starting at its local origin/center. /// @@ -67,8 +61,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Vec3D) == sizeof(components::HalfSizes3D)); /// \private template <> @@ -76,17 +69,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.HalfSizes3D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::HalfSizes3D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::HalfSizes3D` into an arrow array. static Result> to_arrow( const components::HalfSizes3D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->xyz, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/instance_key.cpp b/rerun_cpp/src/rerun/components/instance_key.cpp index 96c5514efd5b..c912980cce2b 100644 --- a/rerun_cpp/src/rerun/components/instance_key.cpp +++ b/rerun_cpp/src/rerun/components/instance_key.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::InstanceKey* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::UInt64Builder* builder, const components::InstanceKey* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::InstanceKey* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/instance_key.hpp b/rerun_cpp/src/rerun/components/instance_key.hpp index ab3d8d6c2c72..c3d92a4bcf82 100644 --- a/rerun_cpp/src/rerun/components/instance_key.hpp +++ b/rerun_cpp/src/rerun/components/instance_key.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::InstanceKey` into an arrow array. + static Result> to_arrow( + const components::InstanceKey* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::UInt64Builder* builder, const components::InstanceKey* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::InstanceKey` into an arrow array. - static Result> to_arrow( - const components::InstanceKey* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/keypoint_id.cpp b/rerun_cpp/src/rerun/components/keypoint_id.cpp deleted file mode 100644 index b4c0b8706cf7..000000000000 --- a/rerun_cpp/src/rerun/components/keypoint_id.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/keypoint_id.fbs". - -#include "keypoint_id.hpp" - -#include "../datatypes/keypoint_id.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::UInt16Builder* builder, const components::KeypointId* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::KeypointId) == sizeof(components::KeypointId)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::KeypointId* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/keypoint_id.hpp b/rerun_cpp/src/rerun/components/keypoint_id.hpp index 644f3a456839..7a2f7d5c17ac 100644 --- a/rerun_cpp/src/rerun/components/keypoint_id.hpp +++ b/rerun_cpp/src/rerun/components/keypoint_id.hpp @@ -9,17 +9,6 @@ #include #include -namespace arrow { - /// \private - template - class NumericBuilder; - - class Array; - class DataType; - class UInt16Type; - using UInt16Builder = NumericBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A 16-bit ID representing a type of semantic keypoint within a class. struct KeypointId { @@ -50,8 +39,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::KeypointId) == sizeof(components::KeypointId)); /// \private template <> @@ -59,17 +47,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.KeypointId"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt16Builder* builder, const components::KeypointId* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::KeypointId` into an arrow array. static Result> to_arrow( const components::KeypointId* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->id, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/line_strip2d.cpp b/rerun_cpp/src/rerun/components/line_strip2d.cpp index 43873719f4c5..12c48e0cf59e 100644 --- a/rerun_cpp/src/rerun/components/line_strip2d.cpp +++ b/rerun_cpp/src/rerun/components/line_strip2d.cpp @@ -18,6 +18,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::LineStrip2D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::LineStrip2D* elements, size_t num_elements ) { @@ -49,24 +69,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::LineStrip2D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/line_strip2d.hpp b/rerun_cpp/src/rerun/components/line_strip2d.hpp index 96fab3837bae..7b6b482d7d4f 100644 --- a/rerun_cpp/src/rerun/components/line_strip2d.hpp +++ b/rerun_cpp/src/rerun/components/line_strip2d.hpp @@ -58,15 +58,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::LineStrip2D` into an arrow array. + static Result> to_arrow( + const components::LineStrip2D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::LineStrip2D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::LineStrip2D` into an arrow array. - static Result> to_arrow( - const components::LineStrip2D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/line_strip3d.cpp b/rerun_cpp/src/rerun/components/line_strip3d.cpp index 4940300a67c4..394acde9668e 100644 --- a/rerun_cpp/src/rerun/components/line_strip3d.cpp +++ b/rerun_cpp/src/rerun/components/line_strip3d.cpp @@ -18,6 +18,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::LineStrip3D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::LineStrip3D* elements, size_t num_elements ) { @@ -49,24 +69,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::LineStrip3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/line_strip3d.hpp b/rerun_cpp/src/rerun/components/line_strip3d.hpp index 19d073ddf816..0cce36238f7d 100644 --- a/rerun_cpp/src/rerun/components/line_strip3d.hpp +++ b/rerun_cpp/src/rerun/components/line_strip3d.hpp @@ -58,15 +58,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::LineStrip3D` into an arrow array. + static Result> to_arrow( + const components::LineStrip3D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::LineStrip3D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::LineStrip3D` into an arrow array. - static Result> to_arrow( - const components::LineStrip3D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/marker_shape.cpp b/rerun_cpp/src/rerun/components/marker_shape.cpp index 0c94783c9748..c8f38822498a 100644 --- a/rerun_cpp/src/rerun/components/marker_shape.cpp +++ b/rerun_cpp/src/rerun/components/marker_shape.cpp @@ -24,6 +24,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::MarkerShape* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const components::MarkerShape* elements, size_t num_elements @@ -46,24 +66,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::MarkerShape* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/marker_shape.hpp b/rerun_cpp/src/rerun/components/marker_shape.hpp index 8d09bd1e5fe5..d1508f483dcb 100644 --- a/rerun_cpp/src/rerun/components/marker_shape.hpp +++ b/rerun_cpp/src/rerun/components/marker_shape.hpp @@ -52,15 +52,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::MarkerShape` into an arrow array. + static Result> to_arrow( + const components::MarkerShape* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const components::MarkerShape* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::MarkerShape` into an arrow array. - static Result> to_arrow( - const components::MarkerShape* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/marker_size.cpp b/rerun_cpp/src/rerun/components/marker_size.cpp index 608d0914cdf8..4f2811b47bfd 100644 --- a/rerun_cpp/src/rerun/components/marker_size.cpp +++ b/rerun_cpp/src/rerun/components/marker_size.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::MarkerSize* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::MarkerSize* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::MarkerSize* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/marker_size.hpp b/rerun_cpp/src/rerun/components/marker_size.hpp index 7f78a40fbda2..178245496809 100644 --- a/rerun_cpp/src/rerun/components/marker_size.hpp +++ b/rerun_cpp/src/rerun/components/marker_size.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::MarkerSize` into an arrow array. + static Result> to_arrow( + const components::MarkerSize* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::MarkerSize* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::MarkerSize` into an arrow array. - static Result> to_arrow( - const components::MarkerSize* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/material.cpp b/rerun_cpp/src/rerun/components/material.cpp deleted file mode 100644 index e7dccda5d31c..000000000000 --- a/rerun_cpp/src/rerun/components/material.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/material.fbs". - -#include "material.hpp" - -#include "../datatypes/material.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::Material* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Material) == sizeof(components::Material)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Material* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/material.hpp b/rerun_cpp/src/rerun/components/material.hpp index dfe861f11724..1549193f0f3c 100644 --- a/rerun_cpp/src/rerun/components/material.hpp +++ b/rerun_cpp/src/rerun/components/material.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: Material properties of a mesh. struct Material { @@ -55,8 +49,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Material) == sizeof(components::Material)); /// \private template <> @@ -64,16 +57,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Material"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::Material* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Material` into an arrow array. static Result> to_arrow( const components::Material* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->material, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/media_type.cpp b/rerun_cpp/src/rerun/components/media_type.cpp deleted file mode 100644 index fddc1f4e1be9..000000000000 --- a/rerun_cpp/src/rerun/components/media_type.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/media_type.fbs". - -#include "media_type.hpp" - -#include "../datatypes/utf8.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const components::MediaType* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(components::MediaType)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::MediaType* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/media_type.hpp b/rerun_cpp/src/rerun/components/media_type.hpp index cb613d9d066a..51c63d5f1d27 100644 --- a/rerun_cpp/src/rerun/components/media_type.hpp +++ b/rerun_cpp/src/rerun/components/media_type.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A standardized media type (RFC2046, formerly known as MIME types), encoded as a utf8 string. /// @@ -100,8 +94,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(components::MediaType)); /// \private template <> @@ -109,17 +102,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.MediaType"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const components::MediaType* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::MediaType` into an arrow array. static Result> to_arrow( const components::MediaType* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->value, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/mesh_properties.cpp b/rerun_cpp/src/rerun/components/mesh_properties.cpp deleted file mode 100644 index d31591039ff0..000000000000 --- a/rerun_cpp/src/rerun/components/mesh_properties.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/mesh_properties.fbs". - -#include "mesh_properties.hpp" - -#include "../datatypes/mesh_properties.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::MeshProperties* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::MeshProperties) == sizeof(components::MeshProperties) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::MeshProperties* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/mesh_properties.hpp b/rerun_cpp/src/rerun/components/mesh_properties.hpp index 98a8e5070b76..c40a9f7ea734 100644 --- a/rerun_cpp/src/rerun/components/mesh_properties.hpp +++ b/rerun_cpp/src/rerun/components/mesh_properties.hpp @@ -12,12 +12,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: Optional triangle indices for a mesh. struct MeshProperties { @@ -56,8 +50,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::MeshProperties) == sizeof(components::MeshProperties)); /// \private template <> @@ -65,17 +58,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.MeshProperties"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::MeshProperties* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::MeshProperties` into an arrow array. static Result> to_arrow( const components::MeshProperties* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->props, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/name.cpp b/rerun_cpp/src/rerun/components/name.cpp deleted file mode 100644 index 7f8aa817f2e6..000000000000 --- a/rerun_cpp/src/rerun/components/name.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/name.fbs". - -#include "name.hpp" - -#include "../datatypes/utf8.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const components::Name* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(components::Name)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Name* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/name.hpp b/rerun_cpp/src/rerun/components/name.hpp index de9c3312eca4..fca48489ca70 100644 --- a/rerun_cpp/src/rerun/components/name.hpp +++ b/rerun_cpp/src/rerun/components/name.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A display name, typically for an entity or a item like a plot series. struct Name { @@ -57,8 +51,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(components::Name)); /// \private template <> @@ -66,16 +59,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Name"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const components::Name* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Name` into an arrow array. static Result> to_arrow( const components::Name* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->value, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/out_of_tree_transform3d.cpp b/rerun_cpp/src/rerun/components/out_of_tree_transform3d.cpp deleted file mode 100644 index aa69bf473822..000000000000 --- a/rerun_cpp/src/rerun/components/out_of_tree_transform3d.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/out_of_tree_transform3d.fbs". - -#include "out_of_tree_transform3d.hpp" - -#include "../datatypes/transform3d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::OutOfTreeTransform3D* elements, - size_t num_elements - ) { - static_assert( - sizeof(rerun::datatypes::Transform3D) == sizeof(components::OutOfTreeTransform3D) - ); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::OutOfTreeTransform3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/out_of_tree_transform3d.hpp b/rerun_cpp/src/rerun/components/out_of_tree_transform3d.hpp index 00e8f7e57cc7..d84c7f59a386 100644 --- a/rerun_cpp/src/rerun/components/out_of_tree_transform3d.hpp +++ b/rerun_cpp/src/rerun/components/out_of_tree_transform3d.hpp @@ -9,12 +9,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class DenseUnionBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: An out-of-tree affine transform between two 3D spaces, represented in a given direction. /// @@ -41,8 +35,9 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert( + sizeof(rerun::datatypes::Transform3D) == sizeof(components::OutOfTreeTransform3D) + ); /// \private template <> @@ -50,17 +45,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.OutOfTreeTransform3D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::OutOfTreeTransform3D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::OutOfTreeTransform3D` into an arrow array. static Result> to_arrow( const components::OutOfTreeTransform3D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->repr, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/pinhole_projection.cpp b/rerun_cpp/src/rerun/components/pinhole_projection.cpp deleted file mode 100644 index 8acae569a288..000000000000 --- a/rerun_cpp/src/rerun/components/pinhole_projection.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/pinhole_projection.fbs". - -#include "pinhole_projection.hpp" - -#include "../datatypes/mat3x3.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype( - ) { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::PinholeProjection* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Mat3x3) == sizeof(components::PinholeProjection)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::PinholeProjection* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/pinhole_projection.hpp b/rerun_cpp/src/rerun/components/pinhole_projection.hpp index 37f20bf011c7..ae1c5a7722ae 100644 --- a/rerun_cpp/src/rerun/components/pinhole_projection.hpp +++ b/rerun_cpp/src/rerun/components/pinhole_projection.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: Camera projection, from image coordinates to view coordinates. /// @@ -65,8 +59,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Mat3x3) == sizeof(components::PinholeProjection)); /// \private template <> @@ -74,17 +67,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.PinholeProjection"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::PinholeProjection* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::PinholeProjection` into an arrow array. static Result> to_arrow( const components::PinholeProjection* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->image_from_camera, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/position2d.cpp b/rerun_cpp/src/rerun/components/position2d.cpp deleted file mode 100644 index 82e70c1c1ae2..000000000000 --- a/rerun_cpp/src/rerun/components/position2d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/position2d.fbs". - -#include "position2d.hpp" - -#include "../datatypes/vec2d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Position2D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::Position2D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Position2D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/position2d.hpp b/rerun_cpp/src/rerun/components/position2d.hpp index db6b3746b0d9..03cb29195604 100644 --- a/rerun_cpp/src/rerun/components/position2d.hpp +++ b/rerun_cpp/src/rerun/components/position2d.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A position in 2D space. struct Position2D { @@ -60,8 +54,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::Position2D)); /// \private template <> @@ -69,17 +62,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Position2D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Position2D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Position2D` into an arrow array. static Result> to_arrow( const components::Position2D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->xy, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/position3d.cpp b/rerun_cpp/src/rerun/components/position3d.cpp deleted file mode 100644 index 56f30ac7920c..000000000000 --- a/rerun_cpp/src/rerun/components/position3d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/position3d.fbs". - -#include "position3d.hpp" - -#include "../datatypes/vec3d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Position3D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Vec3D) == sizeof(components::Position3D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Position3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/position3d.hpp b/rerun_cpp/src/rerun/components/position3d.hpp index bfb5b75fef45..65b818afd79a 100644 --- a/rerun_cpp/src/rerun/components/position3d.hpp +++ b/rerun_cpp/src/rerun/components/position3d.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A position in 3D space. struct Position3D { @@ -64,8 +58,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Vec3D) == sizeof(components::Position3D)); /// \private template <> @@ -73,17 +66,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Position3D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Position3D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Position3D` into an arrow array. static Result> to_arrow( const components::Position3D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->xyz, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/radius.cpp b/rerun_cpp/src/rerun/components/radius.cpp index 3a1e8f2b3c44..dfa23ce443b5 100644 --- a/rerun_cpp/src/rerun/components/radius.cpp +++ b/rerun_cpp/src/rerun/components/radius.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::Radius* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::Radius* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::Radius* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/radius.hpp b/rerun_cpp/src/rerun/components/radius.hpp index e95ada701c2f..2de85bfdad94 100644 --- a/rerun_cpp/src/rerun/components/radius.hpp +++ b/rerun_cpp/src/rerun/components/radius.hpp @@ -48,14 +48,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FloatBuilder* builder, const components::Radius* elements, size_t num_elements - ); - /// Serializes an array of `rerun::components::Radius` into an arrow array. static Result> to_arrow( const components::Radius* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::FloatBuilder* builder, const components::Radius* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/range1d.cpp b/rerun_cpp/src/rerun/components/range1d.cpp index 6f35a2a82715..01bb5228f1fa 100644 --- a/rerun_cpp/src/rerun/components/range1d.cpp +++ b/rerun_cpp/src/rerun/components/range1d.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::Range1D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const components::Range1D* elements, size_t num_elements @@ -41,24 +61,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::Range1D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/range1d.hpp b/rerun_cpp/src/rerun/components/range1d.hpp index 17279a212530..874fafbf18e4 100644 --- a/rerun_cpp/src/rerun/components/range1d.hpp +++ b/rerun_cpp/src/rerun/components/range1d.hpp @@ -44,15 +44,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::Range1D` into an arrow array. + static Result> to_arrow( + const components::Range1D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const components::Range1D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::Range1D` into an arrow array. - static Result> to_arrow( - const components::Range1D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/resolution.cpp b/rerun_cpp/src/rerun/components/resolution.cpp deleted file mode 100644 index db08075008a8..000000000000 --- a/rerun_cpp/src/rerun/components/resolution.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/resolution.fbs". - -#include "resolution.hpp" - -#include "../datatypes/vec2d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Resolution* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::Resolution)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Resolution* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/resolution.hpp b/rerun_cpp/src/rerun/components/resolution.hpp index 97415d075f5a..609e20117d4f 100644 --- a/rerun_cpp/src/rerun/components/resolution.hpp +++ b/rerun_cpp/src/rerun/components/resolution.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: Pixel resolution width & height, e.g. of a camera sensor. /// @@ -60,8 +54,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::Resolution)); /// \private template <> @@ -69,17 +62,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Resolution"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Resolution* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Resolution` into an arrow array. static Result> to_arrow( const components::Resolution* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->resolution, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/rotation3d.cpp b/rerun_cpp/src/rerun/components/rotation3d.cpp deleted file mode 100644 index d451df9adead..000000000000 --- a/rerun_cpp/src/rerun/components/rotation3d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/rotation3d.fbs". - -#include "rotation3d.hpp" - -#include "../datatypes/rotation3d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::Rotation3D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Rotation3D) == sizeof(components::Rotation3D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Rotation3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/rotation3d.hpp b/rerun_cpp/src/rerun/components/rotation3d.hpp index 24fd8fd79ef7..ada3dab95177 100644 --- a/rerun_cpp/src/rerun/components/rotation3d.hpp +++ b/rerun_cpp/src/rerun/components/rotation3d.hpp @@ -9,12 +9,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class DenseUnionBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A 3D rotation, represented either by a quaternion or a rotation around axis. struct Rotation3D { @@ -50,8 +44,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Rotation3D) == sizeof(components::Rotation3D)); /// \private template <> @@ -59,17 +52,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Rotation3D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::Rotation3D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Rotation3D` into an arrow array. static Result> to_arrow( const components::Rotation3D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->repr, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/scalar.cpp b/rerun_cpp/src/rerun/components/scalar.cpp index 58ba72656271..a1caa04a506b 100644 --- a/rerun_cpp/src/rerun/components/scalar.cpp +++ b/rerun_cpp/src/rerun/components/scalar.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::Scalar* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::DoubleBuilder* builder, const components::Scalar* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::Scalar* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/scalar.hpp b/rerun_cpp/src/rerun/components/scalar.hpp index 7037bd2de538..a0c628d64125 100644 --- a/rerun_cpp/src/rerun/components/scalar.hpp +++ b/rerun_cpp/src/rerun/components/scalar.hpp @@ -50,14 +50,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::DoubleBuilder* builder, const components::Scalar* elements, size_t num_elements - ); - /// Serializes an array of `rerun::components::Scalar` into an arrow array. static Result> to_arrow( const components::Scalar* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::DoubleBuilder* builder, const components::Scalar* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/scalar_scattering.cpp b/rerun_cpp/src/rerun/components/scalar_scattering.cpp index 1114744b5fef..757732c059d8 100644 --- a/rerun_cpp/src/rerun/components/scalar_scattering.cpp +++ b/rerun_cpp/src/rerun/components/scalar_scattering.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::ScalarScattering* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::BooleanBuilder* builder, const components::ScalarScattering* elements, size_t num_elements @@ -37,24 +57,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::ScalarScattering* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/scalar_scattering.hpp b/rerun_cpp/src/rerun/components/scalar_scattering.hpp index 4b459530d9a9..8125a85a7dfe 100644 --- a/rerun_cpp/src/rerun/components/scalar_scattering.hpp +++ b/rerun_cpp/src/rerun/components/scalar_scattering.hpp @@ -43,15 +43,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::ScalarScattering` into an arrow array. + static Result> to_arrow( + const components::ScalarScattering* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::BooleanBuilder* builder, const components::ScalarScattering* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::ScalarScattering` into an arrow array. - static Result> to_arrow( - const components::ScalarScattering* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/stroke_width.cpp b/rerun_cpp/src/rerun/components/stroke_width.cpp index 842a1cf077b8..6925f383d2e9 100644 --- a/rerun_cpp/src/rerun/components/stroke_width.cpp +++ b/rerun_cpp/src/rerun/components/stroke_width.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::StrokeWidth* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::StrokeWidth* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::StrokeWidth* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/stroke_width.hpp b/rerun_cpp/src/rerun/components/stroke_width.hpp index a0576fba9f34..960d2c136607 100644 --- a/rerun_cpp/src/rerun/components/stroke_width.hpp +++ b/rerun_cpp/src/rerun/components/stroke_width.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::StrokeWidth` into an arrow array. + static Result> to_arrow( + const components::StrokeWidth* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::StrokeWidth* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::StrokeWidth` into an arrow array. - static Result> to_arrow( - const components::StrokeWidth* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/tensor_data.cpp b/rerun_cpp/src/rerun/components/tensor_data.cpp deleted file mode 100644 index 01dfe22bd1d0..000000000000 --- a/rerun_cpp/src/rerun/components/tensor_data.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/tensor_data.fbs". - -#include "tensor_data.hpp" - -#include "../datatypes/tensor_data.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::TensorData* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::TensorData) == sizeof(components::TensorData)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::TensorData* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/tensor_data.hpp b/rerun_cpp/src/rerun/components/tensor_data.hpp index 6fe507f4b1d7..b3f5a5e75cbc 100644 --- a/rerun_cpp/src/rerun/components/tensor_data.hpp +++ b/rerun_cpp/src/rerun/components/tensor_data.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A multi-dimensional `Tensor` of data. /// @@ -73,8 +67,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::TensorData) == sizeof(components::TensorData)); /// \private template <> @@ -82,17 +75,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.TensorData"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::TensorData* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::TensorData` into an arrow array. static Result> to_arrow( const components::TensorData* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->data, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/texcoord2d.cpp b/rerun_cpp/src/rerun/components/texcoord2d.cpp deleted file mode 100644 index b462646d8168..000000000000 --- a/rerun_cpp/src/rerun/components/texcoord2d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/texcoord2d.fbs". - -#include "texcoord2d.hpp" - -#include "../datatypes/vec2d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Texcoord2D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::Texcoord2D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Texcoord2D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/texcoord2d.hpp b/rerun_cpp/src/rerun/components/texcoord2d.hpp index 34101cec6967..ecc635e43ee0 100644 --- a/rerun_cpp/src/rerun/components/texcoord2d.hpp +++ b/rerun_cpp/src/rerun/components/texcoord2d.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A 2D texture UV coordinate. /// @@ -75,8 +69,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::Texcoord2D)); /// \private template <> @@ -84,17 +77,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Texcoord2D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Texcoord2D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Texcoord2D` into an arrow array. static Result> to_arrow( const components::Texcoord2D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->uv, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/text.cpp b/rerun_cpp/src/rerun/components/text.cpp deleted file mode 100644 index 8214878892ee..000000000000 --- a/rerun_cpp/src/rerun/components/text.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/text.fbs". - -#include "text.hpp" - -#include "../datatypes/utf8.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const components::Text* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(components::Text)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Text* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/text.hpp b/rerun_cpp/src/rerun/components/text.hpp index baa00d127a70..c788f61b55b4 100644 --- a/rerun_cpp/src/rerun/components/text.hpp +++ b/rerun_cpp/src/rerun/components/text.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A string of text, e.g. for labels and text documents. struct Text { @@ -57,8 +51,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(components::Text)); /// \private template <> @@ -66,16 +59,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Text"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const components::Text* elements, size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Text` into an arrow array. static Result> to_arrow( const components::Text* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->value, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/text_log_level.cpp b/rerun_cpp/src/rerun/components/text_log_level.cpp deleted file mode 100644 index 428a9150887b..000000000000 --- a/rerun_cpp/src/rerun/components/text_log_level.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/text_log_level.fbs". - -#include "text_log_level.hpp" - -#include "../datatypes/utf8.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StringBuilder* builder, const components::TextLogLevel* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(components::TextLogLevel)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::TextLogLevel* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/text_log_level.hpp b/rerun_cpp/src/rerun/components/text_log_level.hpp index 4f29060f3812..d26158b72ef4 100644 --- a/rerun_cpp/src/rerun/components/text_log_level.hpp +++ b/rerun_cpp/src/rerun/components/text_log_level.hpp @@ -11,12 +11,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StringBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: The severity level of a text log message. /// @@ -83,8 +77,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Utf8) == sizeof(components::TextLogLevel)); /// \private template <> @@ -92,17 +85,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.TextLogLevel"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const components::TextLogLevel* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::TextLogLevel` into an arrow array. static Result> to_arrow( const components::TextLogLevel* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->value, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/transform3d.cpp b/rerun_cpp/src/rerun/components/transform3d.cpp deleted file mode 100644 index 2bcd61bf69fc..000000000000 --- a/rerun_cpp/src/rerun/components/transform3d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/transform3d.fbs". - -#include "transform3d.hpp" - -#include "../datatypes/transform3d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::Transform3D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Transform3D) == sizeof(components::Transform3D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Transform3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/transform3d.hpp b/rerun_cpp/src/rerun/components/transform3d.hpp index 3d29d6f59ea0..cbe1121ce920 100644 --- a/rerun_cpp/src/rerun/components/transform3d.hpp +++ b/rerun_cpp/src/rerun/components/transform3d.hpp @@ -9,12 +9,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class DenseUnionBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: An affine transform between two 3D spaces, represented in a given direction. struct Transform3D { @@ -39,8 +33,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Transform3D) == sizeof(components::Transform3D)); /// \private template <> @@ -48,17 +41,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Transform3D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::Transform3D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Transform3D` into an arrow array. static Result> to_arrow( const components::Transform3D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->repr, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/vector2d.cpp b/rerun_cpp/src/rerun/components/vector2d.cpp deleted file mode 100644 index 5a5c0210317c..000000000000 --- a/rerun_cpp/src/rerun/components/vector2d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/vector2d.fbs". - -#include "vector2d.hpp" - -#include "../datatypes/vec2d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Vector2D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::Vector2D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Vector2D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/vector2d.hpp b/rerun_cpp/src/rerun/components/vector2d.hpp index fadc46f62d15..65bc9aeffd7e 100644 --- a/rerun_cpp/src/rerun/components/vector2d.hpp +++ b/rerun_cpp/src/rerun/components/vector2d.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A vector in 2D space. struct Vector2D { @@ -63,8 +57,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Vec2D) == sizeof(components::Vector2D)); /// \private template <> @@ -72,17 +65,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Vector2D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Vector2D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Vector2D` into an arrow array. static Result> to_arrow( const components::Vector2D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->vector, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/vector3d.cpp b/rerun_cpp/src/rerun/components/vector3d.cpp deleted file mode 100644 index 422d60a133db..000000000000 --- a/rerun_cpp/src/rerun/components/vector3d.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/vector3d.fbs". - -#include "vector3d.hpp" - -#include "../datatypes/vec3d.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Vector3D* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::Vec3D) == sizeof(components::Vector3D)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::Vector3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/vector3d.hpp b/rerun_cpp/src/rerun/components/vector3d.hpp index 3e30e05c9f37..96c55af07c86 100644 --- a/rerun_cpp/src/rerun/components/vector3d.hpp +++ b/rerun_cpp/src/rerun/components/vector3d.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A vector in 3D space. struct Vector3D { @@ -67,8 +61,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Vec3D) == sizeof(components::Vector3D)); /// \private template <> @@ -76,17 +69,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Vector3D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Vector3D* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Vector3D` into an arrow array. static Result> to_arrow( const components::Vector3D* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow(&instances->vector, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/view_coordinates.cpp b/rerun_cpp/src/rerun/components/view_coordinates.cpp index b587dba4d725..78db36544098 100644 --- a/rerun_cpp/src/rerun/components/view_coordinates.cpp +++ b/rerun_cpp/src/rerun/components/view_coordinates.cpp @@ -16,6 +16,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::ViewCoordinates* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const components::ViewCoordinates* elements, size_t num_elements @@ -42,24 +62,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::ViewCoordinates* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/view_coordinates.hpp b/rerun_cpp/src/rerun/components/view_coordinates.hpp index 0fe2b86191e7..f06fa7d28db4 100644 --- a/rerun_cpp/src/rerun/components/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/components/view_coordinates.hpp @@ -144,15 +144,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::ViewCoordinates` into an arrow array. + static Result> to_arrow( + const components::ViewCoordinates* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const components::ViewCoordinates* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::ViewCoordinates` into an arrow array. - static Result> to_arrow( - const components::ViewCoordinates* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/visualizer_overrides.cpp b/rerun_cpp/src/rerun/components/visualizer_overrides.cpp index f8f1181e523c..758042b5dd24 100644 --- a/rerun_cpp/src/rerun/components/visualizer_overrides.cpp +++ b/rerun_cpp/src/rerun/components/visualizer_overrides.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::VisualizerOverrides* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::VisualizerOverrides* elements, size_t num_elements @@ -43,24 +63,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::VisualizerOverrides* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/visualizer_overrides.hpp b/rerun_cpp/src/rerun/components/visualizer_overrides.hpp index 9e06a1d3d9c8..c38ebca1600b 100644 --- a/rerun_cpp/src/rerun/components/visualizer_overrides.hpp +++ b/rerun_cpp/src/rerun/components/visualizer_overrides.hpp @@ -46,15 +46,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::VisualizerOverrides` into an arrow array. + static Result> to_arrow( + const components::VisualizerOverrides* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::VisualizerOverrides* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::VisualizerOverrides` into an arrow array. - static Result> to_arrow( - const components::VisualizerOverrides* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/angle.cpp b/rerun_cpp/src/rerun/datatypes/angle.cpp index cf54c6868a26..1f7d22dff114 100644 --- a/rerun_cpp/src/rerun/datatypes/angle.cpp +++ b/rerun_cpp/src/rerun/datatypes/angle.cpp @@ -18,6 +18,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Angle* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::Angle* elements, size_t num_elements ) { @@ -64,24 +84,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Angle* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/angle.hpp b/rerun_cpp/src/rerun/datatypes/angle.hpp index c8a67fb1b386..8a907dd04158 100644 --- a/rerun_cpp/src/rerun/datatypes/angle.hpp +++ b/rerun_cpp/src/rerun/datatypes/angle.hpp @@ -142,14 +142,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const datatypes::Angle* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::Angle` into an arrow array. static Result> to_arrow( const datatypes::Angle* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::DenseUnionBuilder* builder, const datatypes::Angle* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/annotation_info.cpp b/rerun_cpp/src/rerun/datatypes/annotation_info.cpp index 289f4be1894e..2d6c14064de0 100644 --- a/rerun_cpp/src/rerun/datatypes/annotation_info.cpp +++ b/rerun_cpp/src/rerun/datatypes/annotation_info.cpp @@ -21,6 +21,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AnnotationInfo* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AnnotationInfo* elements, size_t num_elements @@ -78,24 +98,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AnnotationInfo* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/annotation_info.hpp b/rerun_cpp/src/rerun/datatypes/annotation_info.hpp index b05e28c22352..719196731ec7 100644 --- a/rerun_cpp/src/rerun/datatypes/annotation_info.hpp +++ b/rerun_cpp/src/rerun/datatypes/annotation_info.hpp @@ -61,15 +61,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AnnotationInfo` into an arrow array. + static Result> to_arrow( + const datatypes::AnnotationInfo* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AnnotationInfo* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AnnotationInfo` into an arrow array. - static Result> to_arrow( - const datatypes::AnnotationInfo* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/bool.cpp b/rerun_cpp/src/rerun/datatypes/bool.cpp index b01282f23e30..5c8622cfa362 100644 --- a/rerun_cpp/src/rerun/datatypes/bool.cpp +++ b/rerun_cpp/src/rerun/datatypes/bool.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Bool* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::BooleanBuilder* builder, const datatypes::Bool* elements, size_t num_elements ) { @@ -35,24 +55,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Bool* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/bool.hpp b/rerun_cpp/src/rerun/datatypes/bool.hpp index 00aeb20814e1..5b192ee0eeb6 100644 --- a/rerun_cpp/src/rerun/datatypes/bool.hpp +++ b/rerun_cpp/src/rerun/datatypes/bool.hpp @@ -43,14 +43,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::BooleanBuilder* builder, const datatypes::Bool* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::Bool` into an arrow array. static Result> to_arrow( const datatypes::Bool* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::BooleanBuilder* builder, const datatypes::Bool* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/class_description.cpp b/rerun_cpp/src/rerun/datatypes/class_description.cpp index a7bc14380117..52fbaa797864 100644 --- a/rerun_cpp/src/rerun/datatypes/class_description.cpp +++ b/rerun_cpp/src/rerun/datatypes/class_description.cpp @@ -42,6 +42,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::ClassDescription* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::ClassDescription* elements, size_t num_elements @@ -113,24 +133,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::ClassDescription* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/class_description.hpp b/rerun_cpp/src/rerun/datatypes/class_description.hpp index ceb111e926be..8d6db97d2666 100644 --- a/rerun_cpp/src/rerun/datatypes/class_description.hpp +++ b/rerun_cpp/src/rerun/datatypes/class_description.hpp @@ -77,15 +77,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::ClassDescription` into an arrow array. + static Result> to_arrow( + const datatypes::ClassDescription* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::ClassDescription* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::ClassDescription` into an arrow array. - static Result> to_arrow( - const datatypes::ClassDescription* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/class_description_map_elem.cpp b/rerun_cpp/src/rerun/datatypes/class_description_map_elem.cpp index e79bbdd5976f..a4d43ba5c3fc 100644 --- a/rerun_cpp/src/rerun/datatypes/class_description_map_elem.cpp +++ b/rerun_cpp/src/rerun/datatypes/class_description_map_elem.cpp @@ -25,6 +25,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::ClassDescriptionMapElem* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::ClassDescriptionMapElem* elements, size_t num_elements @@ -67,24 +87,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::ClassDescriptionMapElem* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/class_description_map_elem.hpp b/rerun_cpp/src/rerun/datatypes/class_description_map_elem.hpp index 2906bdd6f9ff..ff57a039a30a 100644 --- a/rerun_cpp/src/rerun/datatypes/class_description_map_elem.hpp +++ b/rerun_cpp/src/rerun/datatypes/class_description_map_elem.hpp @@ -51,15 +51,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::ClassDescriptionMapElem` into an arrow array. + static Result> to_arrow( + const datatypes::ClassDescriptionMapElem* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::ClassDescriptionMapElem* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::ClassDescriptionMapElem` into an arrow array. - static Result> to_arrow( - const datatypes::ClassDescriptionMapElem* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/class_id.cpp b/rerun_cpp/src/rerun/datatypes/class_id.cpp index 0ce034b1d7f8..571ef1b016d2 100644 --- a/rerun_cpp/src/rerun/datatypes/class_id.cpp +++ b/rerun_cpp/src/rerun/datatypes/class_id.cpp @@ -14,26 +14,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::UInt16Builder* builder, const datatypes::ClassId* elements, size_t num_elements - ) { - if (builder == nullptr) { - return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); - } - if (elements == nullptr) { - return rerun::Error( - ErrorCode::UnexpectedNullArgument, - "Cannot serialize null pointer to arrow array." - ); - } - - static_assert(sizeof(*elements) == sizeof(elements->id)); - ARROW_RETURN_NOT_OK(builder->AppendValues(&elements->id, static_cast(num_elements)) - ); - - return Error::ok(); - } - Result> Loggable::to_arrow( const datatypes::ClassId* instances, size_t num_instances ) { @@ -53,4 +33,24 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::UInt16Builder* builder, const datatypes::ClassId* elements, size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + static_assert(sizeof(*elements) == sizeof(elements->id)); + ARROW_RETURN_NOT_OK(builder->AppendValues(&elements->id, static_cast(num_elements)) + ); + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/class_id.hpp b/rerun_cpp/src/rerun/datatypes/class_id.hpp index dc97a0b13c37..99a79a9c12eb 100644 --- a/rerun_cpp/src/rerun/datatypes/class_id.hpp +++ b/rerun_cpp/src/rerun/datatypes/class_id.hpp @@ -48,14 +48,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt16Builder* builder, const datatypes::ClassId* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::ClassId` into an arrow array. static Result> to_arrow( const datatypes::ClassId* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::UInt16Builder* builder, const datatypes::ClassId* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/entity_path.cpp b/rerun_cpp/src/rerun/datatypes/entity_path.cpp index 3e909dc9d7b4..b8e6f1afd3d7 100644 --- a/rerun_cpp/src/rerun/datatypes/entity_path.cpp +++ b/rerun_cpp/src/rerun/datatypes/entity_path.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::EntityPath* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StringBuilder* builder, const datatypes::EntityPath* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::EntityPath* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/entity_path.hpp b/rerun_cpp/src/rerun/datatypes/entity_path.hpp index c459109f2fb1..05e9f35e74dd 100644 --- a/rerun_cpp/src/rerun/datatypes/entity_path.hpp +++ b/rerun_cpp/src/rerun/datatypes/entity_path.hpp @@ -45,15 +45,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::EntityPath` into an arrow array. + static Result> to_arrow( + const datatypes::EntityPath* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StringBuilder* builder, const datatypes::EntityPath* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::EntityPath` into an arrow array. - static Result> to_arrow( - const datatypes::EntityPath* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/float32.cpp b/rerun_cpp/src/rerun/datatypes/float32.cpp index cff26a171c7e..2fc5d21152bc 100644 --- a/rerun_cpp/src/rerun/datatypes/float32.cpp +++ b/rerun_cpp/src/rerun/datatypes/float32.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Float32* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const datatypes::Float32* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Float32* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/float32.hpp b/rerun_cpp/src/rerun/datatypes/float32.hpp index 78023580e5ec..53a94384c861 100644 --- a/rerun_cpp/src/rerun/datatypes/float32.hpp +++ b/rerun_cpp/src/rerun/datatypes/float32.hpp @@ -48,14 +48,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FloatBuilder* builder, const datatypes::Float32* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::Float32` into an arrow array. static Result> to_arrow( const datatypes::Float32* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::FloatBuilder* builder, const datatypes::Float32* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/keypoint_id.cpp b/rerun_cpp/src/rerun/datatypes/keypoint_id.cpp index d332124953d2..e514969d844d 100644 --- a/rerun_cpp/src/rerun/datatypes/keypoint_id.cpp +++ b/rerun_cpp/src/rerun/datatypes/keypoint_id.cpp @@ -14,26 +14,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::UInt16Builder* builder, const datatypes::KeypointId* elements, size_t num_elements - ) { - if (builder == nullptr) { - return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); - } - if (elements == nullptr) { - return rerun::Error( - ErrorCode::UnexpectedNullArgument, - "Cannot serialize null pointer to arrow array." - ); - } - - static_assert(sizeof(*elements) == sizeof(elements->id)); - ARROW_RETURN_NOT_OK(builder->AppendValues(&elements->id, static_cast(num_elements)) - ); - - return Error::ok(); - } - Result> Loggable::to_arrow( const datatypes::KeypointId* instances, size_t num_instances ) { @@ -53,4 +33,24 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::UInt16Builder* builder, const datatypes::KeypointId* elements, size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + static_assert(sizeof(*elements) == sizeof(elements->id)); + ARROW_RETURN_NOT_OK(builder->AppendValues(&elements->id, static_cast(num_elements)) + ); + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/keypoint_id.hpp b/rerun_cpp/src/rerun/datatypes/keypoint_id.hpp index 54ec16f8225a..7d4f0fa2fd67 100644 --- a/rerun_cpp/src/rerun/datatypes/keypoint_id.hpp +++ b/rerun_cpp/src/rerun/datatypes/keypoint_id.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::KeypointId` into an arrow array. + static Result> to_arrow( + const datatypes::KeypointId* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::UInt16Builder* builder, const datatypes::KeypointId* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::KeypointId` into an arrow array. - static Result> to_arrow( - const datatypes::KeypointId* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/keypoint_pair.cpp b/rerun_cpp/src/rerun/datatypes/keypoint_pair.cpp index a482280e58a6..a88803daf9b9 100644 --- a/rerun_cpp/src/rerun/datatypes/keypoint_pair.cpp +++ b/rerun_cpp/src/rerun/datatypes/keypoint_pair.cpp @@ -27,6 +27,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::KeypointPair* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::KeypointPair* elements, size_t num_elements ) { @@ -66,24 +86,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::KeypointPair* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/keypoint_pair.hpp b/rerun_cpp/src/rerun/datatypes/keypoint_pair.hpp index 9c22323ccf77..25d68451eaea 100644 --- a/rerun_cpp/src/rerun/datatypes/keypoint_pair.hpp +++ b/rerun_cpp/src/rerun/datatypes/keypoint_pair.hpp @@ -50,15 +50,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::KeypointPair` into an arrow array. + static Result> to_arrow( + const datatypes::KeypointPair* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::KeypointPair* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::KeypointPair` into an arrow array. - static Result> to_arrow( - const datatypes::KeypointPair* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/mat3x3.cpp b/rerun_cpp/src/rerun/datatypes/mat3x3.cpp index 021b75e17225..cf3198d77471 100644 --- a/rerun_cpp/src/rerun/datatypes/mat3x3.cpp +++ b/rerun_cpp/src/rerun/datatypes/mat3x3.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Mat3x3* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Mat3x3* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Mat3x3* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/mat3x3.hpp b/rerun_cpp/src/rerun/datatypes/mat3x3.hpp index 20b27d2c2656..6ba35081b6b6 100644 --- a/rerun_cpp/src/rerun/datatypes/mat3x3.hpp +++ b/rerun_cpp/src/rerun/datatypes/mat3x3.hpp @@ -88,15 +88,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Mat3x3` into an arrow array. + static Result> to_arrow( + const datatypes::Mat3x3* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Mat3x3* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Mat3x3` into an arrow array. - static Result> to_arrow( - const datatypes::Mat3x3* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/mat4x4.cpp b/rerun_cpp/src/rerun/datatypes/mat4x4.cpp index f8af413c7cc8..2073fc3fe341 100644 --- a/rerun_cpp/src/rerun/datatypes/mat4x4.cpp +++ b/rerun_cpp/src/rerun/datatypes/mat4x4.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Mat4x4* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Mat4x4* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Mat4x4* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/mat4x4.hpp b/rerun_cpp/src/rerun/datatypes/mat4x4.hpp index 39bb1cc5f29b..4c5da8272c68 100644 --- a/rerun_cpp/src/rerun/datatypes/mat4x4.hpp +++ b/rerun_cpp/src/rerun/datatypes/mat4x4.hpp @@ -103,15 +103,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Mat4x4` into an arrow array. + static Result> to_arrow( + const datatypes::Mat4x4* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Mat4x4* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Mat4x4` into an arrow array. - static Result> to_arrow( - const datatypes::Mat4x4* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/material.cpp b/rerun_cpp/src/rerun/datatypes/material.cpp index 9512650af0c8..a15929d97704 100644 --- a/rerun_cpp/src/rerun/datatypes/material.cpp +++ b/rerun_cpp/src/rerun/datatypes/material.cpp @@ -22,6 +22,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Material* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::Material* elements, size_t num_elements ) { @@ -55,24 +75,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Material* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/material.hpp b/rerun_cpp/src/rerun/datatypes/material.hpp index efd12166804e..e5cea5ef3377 100644 --- a/rerun_cpp/src/rerun/datatypes/material.hpp +++ b/rerun_cpp/src/rerun/datatypes/material.hpp @@ -54,14 +54,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const datatypes::Material* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::Material` into an arrow array. static Result> to_arrow( const datatypes::Material* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::StructBuilder* builder, const datatypes::Material* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/mesh_properties.cpp b/rerun_cpp/src/rerun/datatypes/mesh_properties.cpp index 5782e0b3e70e..680705aabe3e 100644 --- a/rerun_cpp/src/rerun/datatypes/mesh_properties.cpp +++ b/rerun_cpp/src/rerun/datatypes/mesh_properties.cpp @@ -20,6 +20,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::MeshProperties* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::MeshProperties* elements, size_t num_elements @@ -58,24 +78,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::MeshProperties* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/mesh_properties.hpp b/rerun_cpp/src/rerun/datatypes/mesh_properties.hpp index bb51d2b66cd9..2ef25850a818 100644 --- a/rerun_cpp/src/rerun/datatypes/mesh_properties.hpp +++ b/rerun_cpp/src/rerun/datatypes/mesh_properties.hpp @@ -50,15 +50,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::MeshProperties` into an arrow array. + static Result> to_arrow( + const datatypes::MeshProperties* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::MeshProperties* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::MeshProperties` into an arrow array. - static Result> to_arrow( - const datatypes::MeshProperties* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/quaternion.cpp b/rerun_cpp/src/rerun/datatypes/quaternion.cpp index 836c091c704d..ec89930612a7 100644 --- a/rerun_cpp/src/rerun/datatypes/quaternion.cpp +++ b/rerun_cpp/src/rerun/datatypes/quaternion.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Quaternion* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Quaternion* elements, size_t num_elements @@ -41,24 +61,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Quaternion* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/quaternion.hpp b/rerun_cpp/src/rerun/datatypes/quaternion.hpp index 683400158ca2..a23032eec45b 100644 --- a/rerun_cpp/src/rerun/datatypes/quaternion.hpp +++ b/rerun_cpp/src/rerun/datatypes/quaternion.hpp @@ -93,15 +93,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Quaternion` into an arrow array. + static Result> to_arrow( + const datatypes::Quaternion* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Quaternion* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Quaternion` into an arrow array. - static Result> to_arrow( - const datatypes::Quaternion* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/rgba32.cpp b/rerun_cpp/src/rerun/datatypes/rgba32.cpp index cae995bc5637..0103ec7bff78 100644 --- a/rerun_cpp/src/rerun/datatypes/rgba32.cpp +++ b/rerun_cpp/src/rerun/datatypes/rgba32.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Rgba32* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::UInt32Builder* builder, const datatypes::Rgba32* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Rgba32* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/rgba32.hpp b/rerun_cpp/src/rerun/datatypes/rgba32.hpp index 0f7c0621c86b..9094866a7f50 100644 --- a/rerun_cpp/src/rerun/datatypes/rgba32.hpp +++ b/rerun_cpp/src/rerun/datatypes/rgba32.hpp @@ -80,14 +80,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt32Builder* builder, const datatypes::Rgba32* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::Rgba32` into an arrow array. static Result> to_arrow( const datatypes::Rgba32* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::UInt32Builder* builder, const datatypes::Rgba32* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/rotation3d.cpp b/rerun_cpp/src/rerun/datatypes/rotation3d.cpp index 925c4f285ca1..eb5710f3e8be 100644 --- a/rerun_cpp/src/rerun/datatypes/rotation3d.cpp +++ b/rerun_cpp/src/rerun/datatypes/rotation3d.cpp @@ -29,6 +29,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Rotation3D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::Rotation3D* elements, size_t num_elements @@ -84,24 +104,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Rotation3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/rotation3d.hpp b/rerun_cpp/src/rerun/datatypes/rotation3d.hpp index de2d1daf6af1..ca22e66a0e05 100644 --- a/rerun_cpp/src/rerun/datatypes/rotation3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/rotation3d.hpp @@ -163,15 +163,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Rotation3D` into an arrow array. + static Result> to_arrow( + const datatypes::Rotation3D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::Rotation3D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Rotation3D` into an arrow array. - static Result> to_arrow( - const datatypes::Rotation3D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/rotation_axis_angle.cpp b/rerun_cpp/src/rerun/datatypes/rotation_axis_angle.cpp index ed0772ff0627..3de614e63a5b 100644 --- a/rerun_cpp/src/rerun/datatypes/rotation_axis_angle.cpp +++ b/rerun_cpp/src/rerun/datatypes/rotation_axis_angle.cpp @@ -21,6 +21,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::RotationAxisAngle* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::RotationAxisAngle* elements, size_t num_elements @@ -62,24 +82,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::RotationAxisAngle* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/rotation_axis_angle.hpp b/rerun_cpp/src/rerun/datatypes/rotation_axis_angle.hpp index 106f5c65515c..3a7236f9a1d6 100644 --- a/rerun_cpp/src/rerun/datatypes/rotation_axis_angle.hpp +++ b/rerun_cpp/src/rerun/datatypes/rotation_axis_angle.hpp @@ -51,15 +51,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::RotationAxisAngle` into an arrow array. + static Result> to_arrow( + const datatypes::RotationAxisAngle* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::RotationAxisAngle* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::RotationAxisAngle` into an arrow array. - static Result> to_arrow( - const datatypes::RotationAxisAngle* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/scale3d.cpp b/rerun_cpp/src/rerun/datatypes/scale3d.cpp index 3f6affba3e49..c058ede21d0c 100644 --- a/rerun_cpp/src/rerun/datatypes/scale3d.cpp +++ b/rerun_cpp/src/rerun/datatypes/scale3d.cpp @@ -20,6 +20,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Scale3D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::Scale3D* elements, size_t num_elements ) { @@ -68,24 +88,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Scale3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/scale3d.hpp b/rerun_cpp/src/rerun/datatypes/scale3d.hpp index c91b8c658c7a..0eef794b0328 100644 --- a/rerun_cpp/src/rerun/datatypes/scale3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/scale3d.hpp @@ -157,15 +157,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Scale3D` into an arrow array. + static Result> to_arrow( + const datatypes::Scale3D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::Scale3D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Scale3D` into an arrow array. - static Result> to_arrow( - const datatypes::Scale3D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/tensor_buffer.cpp b/rerun_cpp/src/rerun/datatypes/tensor_buffer.cpp index 01e8afa174d1..4c67308ed438 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_buffer.cpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_buffer.cpp @@ -30,6 +30,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::TensorBuffer* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::TensorBuffer* elements, size_t num_elements @@ -218,24 +238,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::TensorBuffer* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/tensor_buffer.hpp b/rerun_cpp/src/rerun/datatypes/tensor_buffer.hpp index 5ab09be65e90..9d73a88eac21 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_buffer.hpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_buffer.hpp @@ -584,15 +584,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::TensorBuffer` into an arrow array. + static Result> to_arrow( + const datatypes::TensorBuffer* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::TensorBuffer* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::TensorBuffer` into an arrow array. - static Result> to_arrow( - const datatypes::TensorBuffer* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/tensor_data.cpp b/rerun_cpp/src/rerun/datatypes/tensor_data.cpp index 71b592957914..77446b8c2fed 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_data.cpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_data.cpp @@ -32,6 +32,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::TensorData* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::TensorData* elements, size_t num_elements ) { @@ -80,24 +100,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::TensorData* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/tensor_data.hpp b/rerun_cpp/src/rerun/datatypes/tensor_data.hpp index 560853cf8d3a..ec8c20e75b52 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_data.hpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_data.hpp @@ -80,15 +80,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::TensorData` into an arrow array. + static Result> to_arrow( + const datatypes::TensorData* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::TensorData* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::TensorData` into an arrow array. - static Result> to_arrow( - const datatypes::TensorData* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/tensor_dimension.cpp b/rerun_cpp/src/rerun/datatypes/tensor_dimension.cpp index 6958f78c49e3..357ced695a2e 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_dimension.cpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_dimension.cpp @@ -17,6 +17,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::TensorDimension* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::TensorDimension* elements, size_t num_elements @@ -54,24 +74,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::TensorDimension* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/tensor_dimension.hpp b/rerun_cpp/src/rerun/datatypes/tensor_dimension.hpp index 5d0866ca3549..027fabcbe952 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_dimension.hpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_dimension.hpp @@ -51,15 +51,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::TensorDimension` into an arrow array. + static Result> to_arrow( + const datatypes::TensorDimension* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::TensorDimension* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::TensorDimension` into an arrow array. - static Result> to_arrow( - const datatypes::TensorDimension* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/transform3d.cpp b/rerun_cpp/src/rerun/datatypes/transform3d.cpp index ee5059d76f73..e3e4bd7edcac 100644 --- a/rerun_cpp/src/rerun/datatypes/transform3d.cpp +++ b/rerun_cpp/src/rerun/datatypes/transform3d.cpp @@ -29,6 +29,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Transform3D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::Transform3D* elements, size_t num_elements @@ -85,24 +105,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Transform3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/transform3d.hpp b/rerun_cpp/src/rerun/datatypes/transform3d.hpp index 893972ed86b7..d55fa89e42bd 100644 --- a/rerun_cpp/src/rerun/datatypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/transform3d.hpp @@ -159,15 +159,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Transform3D` into an arrow array. + static Result> to_arrow( + const datatypes::Transform3D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::Transform3D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Transform3D` into an arrow array. - static Result> to_arrow( - const datatypes::Transform3D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.cpp b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.cpp index abcbafe65587..f11058df7356 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.cpp +++ b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.cpp @@ -22,6 +22,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::TranslationAndMat3x3* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::TranslationAndMat3x3* elements, size_t num_elements @@ -81,24 +101,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::TranslationAndMat3x3* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp index ac308985a501..bd535dfe2d0e 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp +++ b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp @@ -85,15 +85,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::TranslationAndMat3x3` into an arrow array. + static Result> to_arrow( + const datatypes::TranslationAndMat3x3* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::TranslationAndMat3x3* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::TranslationAndMat3x3` into an arrow array. - static Result> to_arrow( - const datatypes::TranslationAndMat3x3* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.cpp b/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.cpp index 01ffa5ab0238..9cb528ee4ad9 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.cpp +++ b/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.cpp @@ -28,6 +28,28 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::TranslationRotationScale3D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK( + Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + ) + ); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::TranslationRotationScale3D* elements, size_t num_elements @@ -104,26 +126,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::TranslationRotationScale3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.hpp b/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.hpp index 8d0d670db401..ef36c3c31c9c 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.hpp @@ -210,15 +210,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::TranslationRotationScale3D` into an arrow array. + static Result> to_arrow( + const datatypes::TranslationRotationScale3D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::TranslationRotationScale3D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::TranslationRotationScale3D` into an arrow array. - static Result> to_arrow( - const datatypes::TranslationRotationScale3D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uint32.cpp b/rerun_cpp/src/rerun/datatypes/uint32.cpp index 880bbaa8a28b..dc8cb0ab8dad 100644 --- a/rerun_cpp/src/rerun/datatypes/uint32.cpp +++ b/rerun_cpp/src/rerun/datatypes/uint32.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::UInt32* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::UInt32Builder* builder, const datatypes::UInt32* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::UInt32* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uint32.hpp b/rerun_cpp/src/rerun/datatypes/uint32.hpp index cd64724dcbe3..015b8ffd4ba4 100644 --- a/rerun_cpp/src/rerun/datatypes/uint32.hpp +++ b/rerun_cpp/src/rerun/datatypes/uint32.hpp @@ -48,14 +48,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt32Builder* builder, const datatypes::UInt32* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::UInt32` into an arrow array. static Result> to_arrow( const datatypes::UInt32* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::UInt32Builder* builder, const datatypes::UInt32* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uint64.cpp b/rerun_cpp/src/rerun/datatypes/uint64.cpp index 4aa873041cae..1d7c7eed2507 100644 --- a/rerun_cpp/src/rerun/datatypes/uint64.cpp +++ b/rerun_cpp/src/rerun/datatypes/uint64.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::UInt64* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::UInt64Builder* builder, const datatypes::UInt64* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::UInt64* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uint64.hpp b/rerun_cpp/src/rerun/datatypes/uint64.hpp index 9886a239d1a6..1326cd612474 100644 --- a/rerun_cpp/src/rerun/datatypes/uint64.hpp +++ b/rerun_cpp/src/rerun/datatypes/uint64.hpp @@ -48,14 +48,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt64Builder* builder, const datatypes::UInt64* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::UInt64` into an arrow array. static Result> to_arrow( const datatypes::UInt64* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::UInt64Builder* builder, const datatypes::UInt64* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/utf8.cpp b/rerun_cpp/src/rerun/datatypes/utf8.cpp index f3da93e4560f..72b5c71f2e99 100644 --- a/rerun_cpp/src/rerun/datatypes/utf8.cpp +++ b/rerun_cpp/src/rerun/datatypes/utf8.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Utf8* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StringBuilder* builder, const datatypes::Utf8* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Utf8* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/utf8.hpp b/rerun_cpp/src/rerun/datatypes/utf8.hpp index 14e3a41e89ea..130e63bdce8f 100644 --- a/rerun_cpp/src/rerun/datatypes/utf8.hpp +++ b/rerun_cpp/src/rerun/datatypes/utf8.hpp @@ -55,14 +55,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StringBuilder* builder, const datatypes::Utf8* elements, size_t num_elements - ); - /// Serializes an array of `rerun::datatypes::Utf8` into an arrow array. static Result> to_arrow( const datatypes::Utf8* instances, size_t num_instances ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::StringBuilder* builder, const datatypes::Utf8* elements, size_t num_elements + ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uuid.cpp b/rerun_cpp/src/rerun/datatypes/uuid.cpp index 5814dad69ae9..e7fcde504d84 100644 --- a/rerun_cpp/src/rerun/datatypes/uuid.cpp +++ b/rerun_cpp/src/rerun/datatypes/uuid.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Uuid* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Uuid* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Uuid* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uuid.hpp b/rerun_cpp/src/rerun/datatypes/uuid.hpp index 0bbe56de8396..30328284ded6 100644 --- a/rerun_cpp/src/rerun/datatypes/uuid.hpp +++ b/rerun_cpp/src/rerun/datatypes/uuid.hpp @@ -44,15 +44,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Uuid` into an arrow array. + static Result> to_arrow( + const datatypes::Uuid* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Uuid* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Uuid` into an arrow array. - static Result> to_arrow( - const datatypes::Uuid* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uvec2d.cpp b/rerun_cpp/src/rerun/datatypes/uvec2d.cpp index 1f342126f60f..09b50101c574 100644 --- a/rerun_cpp/src/rerun/datatypes/uvec2d.cpp +++ b/rerun_cpp/src/rerun/datatypes/uvec2d.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::UVec2D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::UVec2D* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::UVec2D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uvec2d.hpp b/rerun_cpp/src/rerun/datatypes/uvec2d.hpp index 50b800ff0d70..b1805d7c17bb 100644 --- a/rerun_cpp/src/rerun/datatypes/uvec2d.hpp +++ b/rerun_cpp/src/rerun/datatypes/uvec2d.hpp @@ -44,15 +44,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::UVec2D` into an arrow array. + static Result> to_arrow( + const datatypes::UVec2D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::UVec2D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::UVec2D` into an arrow array. - static Result> to_arrow( - const datatypes::UVec2D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uvec3d.cpp b/rerun_cpp/src/rerun/datatypes/uvec3d.cpp index 1e7466bc67ff..5415cbe5eb75 100644 --- a/rerun_cpp/src/rerun/datatypes/uvec3d.cpp +++ b/rerun_cpp/src/rerun/datatypes/uvec3d.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::UVec3D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::UVec3D* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::UVec3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uvec3d.hpp b/rerun_cpp/src/rerun/datatypes/uvec3d.hpp index 83a4f7651326..0ca22e82f87d 100644 --- a/rerun_cpp/src/rerun/datatypes/uvec3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/uvec3d.hpp @@ -44,15 +44,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::UVec3D` into an arrow array. + static Result> to_arrow( + const datatypes::UVec3D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::UVec3D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::UVec3D` into an arrow array. - static Result> to_arrow( - const datatypes::UVec3D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uvec4d.cpp b/rerun_cpp/src/rerun/datatypes/uvec4d.cpp index 23a2427838e4..b589acff0eb3 100644 --- a/rerun_cpp/src/rerun/datatypes/uvec4d.cpp +++ b/rerun_cpp/src/rerun/datatypes/uvec4d.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::UVec4D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::UVec4D* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::UVec4D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/uvec4d.hpp b/rerun_cpp/src/rerun/datatypes/uvec4d.hpp index aea1a45b8362..8869e44e86a9 100644 --- a/rerun_cpp/src/rerun/datatypes/uvec4d.hpp +++ b/rerun_cpp/src/rerun/datatypes/uvec4d.hpp @@ -44,15 +44,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::UVec4D` into an arrow array. + static Result> to_arrow( + const datatypes::UVec4D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::UVec4D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::UVec4D` into an arrow array. - static Result> to_arrow( - const datatypes::UVec4D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/vec2d.cpp b/rerun_cpp/src/rerun/datatypes/vec2d.cpp index dc5782703263..fcbf2cd825ba 100644 --- a/rerun_cpp/src/rerun/datatypes/vec2d.cpp +++ b/rerun_cpp/src/rerun/datatypes/vec2d.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Vec2D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Vec2D* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Vec2D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/vec2d.hpp b/rerun_cpp/src/rerun/datatypes/vec2d.hpp index bf8778aea650..69345a538783 100644 --- a/rerun_cpp/src/rerun/datatypes/vec2d.hpp +++ b/rerun_cpp/src/rerun/datatypes/vec2d.hpp @@ -61,15 +61,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Vec2D` into an arrow array. + static Result> to_arrow( + const datatypes::Vec2D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Vec2D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Vec2D` into an arrow array. - static Result> to_arrow( - const datatypes::Vec2D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/vec3d.cpp b/rerun_cpp/src/rerun/datatypes/vec3d.cpp index 3a6c0805f2ca..e3cce4021973 100644 --- a/rerun_cpp/src/rerun/datatypes/vec3d.cpp +++ b/rerun_cpp/src/rerun/datatypes/vec3d.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Vec3D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Vec3D* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Vec3D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/vec3d.hpp b/rerun_cpp/src/rerun/datatypes/vec3d.hpp index 90c6164042c8..e97e579393d2 100644 --- a/rerun_cpp/src/rerun/datatypes/vec3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/vec3d.hpp @@ -65,15 +65,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Vec3D` into an arrow array. + static Result> to_arrow( + const datatypes::Vec3D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Vec3D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Vec3D` into an arrow array. - static Result> to_arrow( - const datatypes::Vec3D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/vec4d.cpp b/rerun_cpp/src/rerun/datatypes/vec4d.cpp index 6d1f78219358..935cf311fb77 100644 --- a/rerun_cpp/src/rerun/datatypes/vec4d.cpp +++ b/rerun_cpp/src/rerun/datatypes/vec4d.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::Vec4D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Vec4D* elements, size_t num_elements ) { @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::Vec4D* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/vec4d.hpp b/rerun_cpp/src/rerun/datatypes/vec4d.hpp index ac1ec0a70ef8..51df14bb518e 100644 --- a/rerun_cpp/src/rerun/datatypes/vec4d.hpp +++ b/rerun_cpp/src/rerun/datatypes/vec4d.hpp @@ -69,15 +69,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::Vec4D` into an arrow array. + static Result> to_arrow( + const datatypes::Vec4D* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FixedSizeListBuilder* builder, const datatypes::Vec4D* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::Vec4D` into an arrow array. - static Result> to_arrow( - const datatypes::Vec4D* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/.gitattributes b/rerun_cpp/tests/generated/components/.gitattributes index 57f71720efaf..ce1387003057 100644 --- a/rerun_cpp/tests/generated/components/.gitattributes +++ b/rerun_cpp/tests/generated/components/.gitattributes @@ -1,7 +1,6 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -affix_fuzzer1.cpp linguist-generated=true affix_fuzzer1.hpp linguist-generated=true affix_fuzzer10.cpp linguist-generated=true affix_fuzzer10.hpp linguist-generated=true @@ -11,7 +10,6 @@ affix_fuzzer12.cpp linguist-generated=true affix_fuzzer12.hpp linguist-generated=true affix_fuzzer13.cpp linguist-generated=true affix_fuzzer13.hpp linguist-generated=true -affix_fuzzer14.cpp linguist-generated=true affix_fuzzer14.hpp linguist-generated=true affix_fuzzer15.cpp linguist-generated=true affix_fuzzer15.hpp linguist-generated=true @@ -21,17 +19,12 @@ affix_fuzzer17.cpp linguist-generated=true affix_fuzzer17.hpp linguist-generated=true affix_fuzzer18.cpp linguist-generated=true affix_fuzzer18.hpp linguist-generated=true -affix_fuzzer19.cpp linguist-generated=true affix_fuzzer19.hpp linguist-generated=true -affix_fuzzer2.cpp linguist-generated=true affix_fuzzer2.hpp linguist-generated=true -affix_fuzzer20.cpp linguist-generated=true affix_fuzzer20.hpp linguist-generated=true -affix_fuzzer21.cpp linguist-generated=true affix_fuzzer21.hpp linguist-generated=true affix_fuzzer22.cpp linguist-generated=true affix_fuzzer22.hpp linguist-generated=true -affix_fuzzer3.cpp linguist-generated=true affix_fuzzer3.hpp linguist-generated=true affix_fuzzer4.cpp linguist-generated=true affix_fuzzer4.hpp linguist-generated=true diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer1.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer1.cpp deleted file mode 100644 index 560cf159a674..000000000000 --- a/rerun_cpp/tests/generated/components/affix_fuzzer1.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/testing/components/fuzzy.fbs". - -#include "affix_fuzzer1.hpp" - -#include "../datatypes/affix_fuzzer1.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer1* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::AffixFuzzer1) == sizeof(components::AffixFuzzer1)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::AffixFuzzer1* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer1.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer1.hpp index 49709bed41d5..e8b79b21ee18 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer1.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer1.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { struct AffixFuzzer1 { rerun::datatypes::AffixFuzzer1 single_required; @@ -39,8 +33,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::AffixFuzzer1) == sizeof(components::AffixFuzzer1)); /// \private template <> @@ -48,17 +41,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.testing.components.AffixFuzzer1"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer1* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::AffixFuzzer1` into an arrow array. static Result> to_arrow( const components::AffixFuzzer1* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->single_required, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer10.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer10.cpp index 802721af27a6..f29c4a983ea5 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer10.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer10.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer10* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StringBuilder* builder, const components::AffixFuzzer10* elements, size_t num_elements @@ -40,24 +60,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer10* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer10.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer10.hpp index be6eb3e5e3b3..4ac4b9646e58 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer10.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer10.hpp @@ -45,15 +45,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer10` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer10* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StringBuilder* builder, const components::AffixFuzzer10* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer10` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer10* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer11.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer11.cpp index 2b6e72ef7303..dc44a5f59ee0 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer11.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer11.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer11* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer11* elements, size_t num_elements ) { @@ -47,24 +67,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer11* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer11.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer11.hpp index 5f97c75bf997..6e0c12d2e35d 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer11.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer11.hpp @@ -45,15 +45,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer11` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer11* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer11* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer11` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer11* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer12.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer12.cpp index 99583da21d37..d59f0da2fece 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer12.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer12.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer12* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer12* elements, size_t num_elements ) { @@ -42,24 +62,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer12* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer12.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer12.hpp index b6c871e41238..67eb0b0f9f51 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer12.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer12.hpp @@ -45,15 +45,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer12` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer12* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer12* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer12` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer12* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer13.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer13.cpp index af289b73fa32..704ebab1b261 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer13.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer13.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer13* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer13* elements, size_t num_elements ) { @@ -47,24 +67,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer13* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer13.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer13.hpp index d660a53c00c0..fd0b77e38ea8 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer13.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer13.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer13` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer13* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer13* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer13` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer13* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer14.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer14.cpp deleted file mode 100644 index c63ce249ffe0..000000000000 --- a/rerun_cpp/tests/generated/components/affix_fuzzer14.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/testing/components/fuzzy.fbs". - -#include "affix_fuzzer14.hpp" - -#include "../datatypes/affix_fuzzer3.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::AffixFuzzer14* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::AffixFuzzer3) == sizeof(components::AffixFuzzer14)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::AffixFuzzer14* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer14.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer14.hpp index edc82924979d..84e1629d6858 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer14.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer14.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class DenseUnionBuilder; -} // namespace arrow - namespace rerun::components { struct AffixFuzzer14 { rerun::datatypes::AffixFuzzer3 single_required_union; @@ -39,8 +33,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::AffixFuzzer3) == sizeof(components::AffixFuzzer14)); /// \private template <> @@ -48,17 +41,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.testing.components.AffixFuzzer14"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::AffixFuzzer14* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::AffixFuzzer14` into an arrow array. static Result> to_arrow( const components::AffixFuzzer14* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->single_required_union, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer15.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer15.cpp index 8721eb6510c9..c57b88ac7cb4 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer15.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer15.cpp @@ -16,23 +16,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::DenseUnionBuilder* builder, const components::AffixFuzzer15* elements, - size_t num_elements - ) { - (void)builder; - (void)elements; - (void)num_elements; - if (true) { - return rerun::Error( - ErrorCode::NotImplemented, - "TODO(andreas) Handle nullable extensions" - ); - } - - return Error::ok(); - } - Result> Loggable::to_arrow( const components::AffixFuzzer15* instances, size_t num_instances ) { @@ -52,4 +35,21 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::DenseUnionBuilder* builder, const components::AffixFuzzer15* elements, + size_t num_elements + ) { + (void)builder; + (void)elements; + (void)num_elements; + if (true) { + return rerun::Error( + ErrorCode::NotImplemented, + "TODO(andreas) Handle nullable extensions" + ); + } + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer15.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer15.hpp index e20cba371a1e..bef43ae34b0a 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer15.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer15.hpp @@ -53,15 +53,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer15` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer15* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const components::AffixFuzzer15* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer15` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer15* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer16.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer16.cpp index 9517cec76869..170a12c38a12 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer16.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer16.cpp @@ -18,6 +18,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer16* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer16* elements, size_t num_elements ) { @@ -49,24 +69,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer16* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer16.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer16.hpp index 5febd65b9473..083568bce67c 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer16.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer16.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer16` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer16* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer16* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer16` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer16* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer17.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer17.cpp index c7ace54e8822..5fec0dfa3f5d 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer17.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer17.cpp @@ -18,6 +18,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer17* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer17* elements, size_t num_elements ) { @@ -55,24 +75,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer17* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer17.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer17.hpp index aafce9c411b7..5343a93e97ef 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer17.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer17.hpp @@ -51,15 +51,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer17` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer17* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer17* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer17` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer17* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer18.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer18.cpp index 29d9405d7e13..efc00931c9fd 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer18.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer18.cpp @@ -18,6 +18,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer18* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer18* elements, size_t num_elements ) { @@ -55,24 +75,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer18* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer18.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer18.hpp index 62654f1286fb..cc5e948a644f 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer18.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer18.hpp @@ -51,15 +51,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer18` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer18* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer18* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer18` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer18* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer19.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer19.cpp deleted file mode 100644 index a1d137975059..000000000000 --- a/rerun_cpp/tests/generated/components/affix_fuzzer19.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/testing/components/fuzzy.fbs". - -#include "affix_fuzzer19.hpp" - -#include "../datatypes/affix_fuzzer5.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer19* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::AffixFuzzer5) == sizeof(components::AffixFuzzer19)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::AffixFuzzer19* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer19.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer19.hpp index 93d25280593b..7ca8ec015866 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer19.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer19.hpp @@ -12,12 +12,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { struct AffixFuzzer19 { rerun::datatypes::AffixFuzzer5 just_a_table_nothing_shady; @@ -51,8 +45,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::AffixFuzzer5) == sizeof(components::AffixFuzzer19)); /// \private template <> @@ -60,17 +53,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.testing.components.AffixFuzzer19"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer19* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::AffixFuzzer19` into an arrow array. static Result> to_arrow( const components::AffixFuzzer19* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->just_a_table_nothing_shady, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer2.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer2.cpp deleted file mode 100644 index 0322452b2343..000000000000 --- a/rerun_cpp/tests/generated/components/affix_fuzzer2.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/testing/components/fuzzy.fbs". - -#include "affix_fuzzer2.hpp" - -#include "../datatypes/affix_fuzzer1.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer2* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::AffixFuzzer1) == sizeof(components::AffixFuzzer2)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::AffixFuzzer2* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer2.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer2.hpp index 11d843acd322..8e77e3ee7dd6 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer2.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer2.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { struct AffixFuzzer2 { rerun::datatypes::AffixFuzzer1 single_required; @@ -39,8 +33,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::AffixFuzzer1) == sizeof(components::AffixFuzzer2)); /// \private template <> @@ -48,17 +41,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.testing.components.AffixFuzzer2"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer2* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::AffixFuzzer2` into an arrow array. static Result> to_arrow( const components::AffixFuzzer2* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->single_required, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer20.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer20.cpp deleted file mode 100644 index a4d7fc2d1dd6..000000000000 --- a/rerun_cpp/tests/generated/components/affix_fuzzer20.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/testing/components/fuzzy.fbs". - -#include "affix_fuzzer20.hpp" - -#include "../datatypes/affix_fuzzer20.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer20* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::AffixFuzzer20) == sizeof(components::AffixFuzzer20)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::AffixFuzzer20* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer20.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer20.hpp index 11819e4b8a11..9f234f684382 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer20.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer20.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { struct AffixFuzzer20 { rerun::datatypes::AffixFuzzer20 nested_transparent; @@ -39,8 +33,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::AffixFuzzer20) == sizeof(components::AffixFuzzer20)); /// \private template <> @@ -48,17 +41,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.testing.components.AffixFuzzer20"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer20* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::AffixFuzzer20` into an arrow array. static Result> to_arrow( const components::AffixFuzzer20* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->nested_transparent, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer21.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer21.cpp deleted file mode 100644 index 59080ae202ab..000000000000 --- a/rerun_cpp/tests/generated/components/affix_fuzzer21.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/testing/components/fuzzy.fbs". - -#include "affix_fuzzer21.hpp" - -#include "../datatypes/affix_fuzzer21.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer21* elements, - size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::AffixFuzzer21) == sizeof(components::AffixFuzzer21)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::AffixFuzzer21* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer21.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer21.hpp index 0f003d9edb58..1c156173723b 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer21.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer21.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { struct AffixFuzzer21 { rerun::datatypes::AffixFuzzer21 nested_halves; @@ -39,8 +33,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::AffixFuzzer21) == sizeof(components::AffixFuzzer21)); /// \private template <> @@ -48,17 +41,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.testing.components.AffixFuzzer21"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer21* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::AffixFuzzer21` into an arrow array. static Result> to_arrow( const components::AffixFuzzer21* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->nested_halves, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer22.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer22.cpp index 262f30ff2771..14639eb55526 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer22.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer22.cpp @@ -16,23 +16,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer22* elements, - size_t num_elements - ) { - (void)builder; - (void)elements; - (void)num_elements; - if (true) { - return rerun::Error( - ErrorCode::NotImplemented, - "TODO(andreas) Handle nullable extensions" - ); - } - - return Error::ok(); - } - Result> Loggable::to_arrow( const components::AffixFuzzer22* instances, size_t num_instances ) { @@ -52,4 +35,21 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const components::AffixFuzzer22* elements, + size_t num_elements + ) { + (void)builder; + (void)elements; + (void)num_elements; + if (true) { + return rerun::Error( + ErrorCode::NotImplemented, + "TODO(andreas) Handle nullable extensions" + ); + } + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer22.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer22.hpp index 752e4b9ff016..a88fa3e25e28 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer22.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer22.hpp @@ -61,15 +61,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer22` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer22* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const components::AffixFuzzer22* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer22` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer22* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer3.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer3.cpp deleted file mode 100644 index 2a0cf09e81ad..000000000000 --- a/rerun_cpp/tests/generated/components/affix_fuzzer3.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/testing/components/fuzzy.fbs". - -#include "affix_fuzzer3.hpp" - -#include "../datatypes/affix_fuzzer1.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = Loggable::arrow_datatype(); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer3* elements, size_t num_elements - ) { - static_assert(sizeof(rerun::datatypes::AffixFuzzer1) == sizeof(components::AffixFuzzer3)); - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - builder, - reinterpret_cast(elements), - num_elements - )); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const components::AffixFuzzer3* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer3.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer3.hpp index ae2cf4b6ab6a..4729969aaf00 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer3.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer3.hpp @@ -10,12 +10,6 @@ #include #include -namespace arrow { - class Array; - class DataType; - class StructBuilder; -} // namespace arrow - namespace rerun::components { struct AffixFuzzer3 { rerun::datatypes::AffixFuzzer1 single_required; @@ -39,8 +33,7 @@ namespace rerun::components { } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::AffixFuzzer1) == sizeof(components::AffixFuzzer3)); /// \private template <> @@ -48,17 +41,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.testing.components.AffixFuzzer3"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer3* elements, - size_t num_elements - ); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::AffixFuzzer3` into an arrow array. static Result> to_arrow( const components::AffixFuzzer3* instances, size_t num_instances - ); + ) { + return Loggable::to_arrow( + &instances->single_required, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer4.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer4.cpp index 7c442a4c385c..74d54523c0a0 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer4.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer4.cpp @@ -16,22 +16,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer4* elements, size_t num_elements - ) { - (void)builder; - (void)elements; - (void)num_elements; - if (true) { - return rerun::Error( - ErrorCode::NotImplemented, - "TODO(andreas) Handle nullable extensions" - ); - } - - return Error::ok(); - } - Result> Loggable::to_arrow( const components::AffixFuzzer4* instances, size_t num_instances ) { @@ -51,4 +35,20 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const components::AffixFuzzer4* elements, size_t num_elements + ) { + (void)builder; + (void)elements; + (void)num_elements; + if (true) { + return rerun::Error( + ErrorCode::NotImplemented, + "TODO(andreas) Handle nullable extensions" + ); + } + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer4.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer4.hpp index ed30b1c556ca..f2275c5ecc19 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer4.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer4.hpp @@ -51,15 +51,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer4` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer4* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const components::AffixFuzzer4* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer4` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer4* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer5.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer5.cpp index d36b5485a404..d7a8bd739a4c 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer5.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer5.cpp @@ -16,22 +16,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer5* elements, size_t num_elements - ) { - (void)builder; - (void)elements; - (void)num_elements; - if (true) { - return rerun::Error( - ErrorCode::NotImplemented, - "TODO(andreas) Handle nullable extensions" - ); - } - - return Error::ok(); - } - Result> Loggable::to_arrow( const components::AffixFuzzer5* instances, size_t num_instances ) { @@ -51,4 +35,20 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const components::AffixFuzzer5* elements, size_t num_elements + ) { + (void)builder; + (void)elements; + (void)num_elements; + if (true) { + return rerun::Error( + ErrorCode::NotImplemented, + "TODO(andreas) Handle nullable extensions" + ); + } + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer5.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer5.hpp index a79a6cbb8346..a361c2533852 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer5.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer5.hpp @@ -51,15 +51,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer5` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer5* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const components::AffixFuzzer5* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer5` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer5* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer6.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer6.cpp index 3b986cdf7cbc..6032468ba14a 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer6.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer6.cpp @@ -16,22 +16,6 @@ namespace rerun { return datatype; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const components::AffixFuzzer6* elements, size_t num_elements - ) { - (void)builder; - (void)elements; - (void)num_elements; - if (true) { - return rerun::Error( - ErrorCode::NotImplemented, - "TODO(andreas) Handle nullable extensions" - ); - } - - return Error::ok(); - } - Result> Loggable::to_arrow( const components::AffixFuzzer6* instances, size_t num_instances ) { @@ -51,4 +35,20 @@ namespace rerun { ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const components::AffixFuzzer6* elements, size_t num_elements + ) { + (void)builder; + (void)elements; + (void)num_elements; + if (true) { + return rerun::Error( + ErrorCode::NotImplemented, + "TODO(andreas) Handle nullable extensions" + ); + } + + return Error::ok(); + } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer6.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer6.hpp index 7ab19340eb6a..88fc39e9d1e0 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer6.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer6.hpp @@ -51,15 +51,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer6` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer6* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const components::AffixFuzzer6* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer6` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer6* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer7.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer7.cpp index 03314c7cbf70..036f8f0df314 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer7.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer7.cpp @@ -18,6 +18,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer7* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer7* elements, size_t num_elements ) { @@ -55,24 +75,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer7* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer7.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer7.hpp index 84a735a0851e..60211aa0236b 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer7.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer7.hpp @@ -50,15 +50,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer7` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer7* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::ListBuilder* builder, const components::AffixFuzzer7* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer7` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer7* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer8.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer8.cpp index 704c1ccc40bd..d5f582915fa7 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer8.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer8.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer8* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::AffixFuzzer8* elements, size_t num_elements ) { @@ -39,24 +59,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer8* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer8.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer8.hpp index 47e4ed0c6e78..b9e48f54cf29 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer8.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer8.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer8` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer8* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FloatBuilder* builder, const components::AffixFuzzer8* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer8` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer8* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer9.cpp b/rerun_cpp/tests/generated/components/affix_fuzzer9.cpp index bc47e005af4a..b38865650fd6 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer9.cpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer9.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::AffixFuzzer9* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StringBuilder* builder, const components::AffixFuzzer9* elements, size_t num_elements ) { @@ -34,24 +54,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::AffixFuzzer9* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/affix_fuzzer9.hpp b/rerun_cpp/tests/generated/components/affix_fuzzer9.hpp index ffef331faa8c..1f0000c56671 100644 --- a/rerun_cpp/tests/generated/components/affix_fuzzer9.hpp +++ b/rerun_cpp/tests/generated/components/affix_fuzzer9.hpp @@ -44,15 +44,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::AffixFuzzer9` into an arrow array. + static Result> to_arrow( + const components::AffixFuzzer9* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StringBuilder* builder, const components::AffixFuzzer9* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::AffixFuzzer9` into an arrow array. - static Result> to_arrow( - const components::AffixFuzzer9* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/enum_test.cpp b/rerun_cpp/tests/generated/components/enum_test.cpp index 6e49ee6a4d35..21d298a88f98 100644 --- a/rerun_cpp/tests/generated/components/enum_test.cpp +++ b/rerun_cpp/tests/generated/components/enum_test.cpp @@ -20,6 +20,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const components::EnumTest* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const components::EnumTest* elements, size_t num_elements @@ -42,24 +62,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const components::EnumTest* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/components/enum_test.hpp b/rerun_cpp/tests/generated/components/enum_test.hpp index efe3e5db4827..88b8e46d41a0 100644 --- a/rerun_cpp/tests/generated/components/enum_test.hpp +++ b/rerun_cpp/tests/generated/components/enum_test.hpp @@ -49,15 +49,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::components::EnumTest` into an arrow array. + static Result> to_arrow( + const components::EnumTest* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, const components::EnumTest* elements, size_t num_elements ); - - /// Serializes an array of `rerun::components::EnumTest` into an arrow array. - static Result> to_arrow( - const components::EnumTest* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer1.cpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer1.cpp index d3f6acdd3a0d..427721e1da88 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer1.cpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer1.cpp @@ -42,6 +42,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AffixFuzzer1* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer1* elements, size_t num_elements ) { @@ -184,24 +204,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AffixFuzzer1* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer1.hpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer1.hpp index 2b9258b54703..cd13b39ecc42 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer1.hpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer1.hpp @@ -55,15 +55,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AffixFuzzer1` into an arrow array. + static Result> to_arrow( + const datatypes::AffixFuzzer1* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer1* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AffixFuzzer1` into an arrow array. - static Result> to_arrow( - const datatypes::AffixFuzzer1* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer2.cpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer2.cpp index 1d07c46e2aab..53624e07c005 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer2.cpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer2.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AffixFuzzer2* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::FloatBuilder* builder, const datatypes::AffixFuzzer2* elements, size_t num_elements ) { @@ -39,24 +59,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AffixFuzzer2* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer2.hpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer2.hpp index 5a569fd419c0..bc2659ff6536 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer2.hpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer2.hpp @@ -48,15 +48,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AffixFuzzer2` into an arrow array. + static Result> to_arrow( + const datatypes::AffixFuzzer2* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::FloatBuilder* builder, const datatypes::AffixFuzzer2* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AffixFuzzer2` into an arrow array. - static Result> to_arrow( - const datatypes::AffixFuzzer2* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer20.cpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer20.cpp index 1612e23d47c2..423d3cd9da2b 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer20.cpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer20.cpp @@ -24,6 +24,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AffixFuzzer20* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer20* elements, size_t num_elements ) { @@ -67,24 +87,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AffixFuzzer20* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer20.hpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer20.hpp index 87ab4122d26e..d74c987c3e54 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer20.hpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer20.hpp @@ -39,15 +39,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AffixFuzzer20` into an arrow array. + static Result> to_arrow( + const datatypes::AffixFuzzer20* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer20* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AffixFuzzer20` into an arrow array. - static Result> to_arrow( - const datatypes::AffixFuzzer20* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer21.cpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer21.cpp index b2adc03028ec..e064544b3425 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer21.cpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer21.cpp @@ -21,6 +21,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AffixFuzzer21* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer21* elements, size_t num_elements ) { @@ -64,24 +84,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AffixFuzzer21* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer21.hpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer21.hpp index b836c07e0cb3..533040bfd1fe 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer21.hpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer21.hpp @@ -38,15 +38,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AffixFuzzer21` into an arrow array. + static Result> to_arrow( + const datatypes::AffixFuzzer21* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer21* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AffixFuzzer21` into an arrow array. - static Result> to_arrow( - const datatypes::AffixFuzzer21* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer22.cpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer22.cpp index 22db4f2b1ecb..fea3b46609ba 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer22.cpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer22.cpp @@ -20,6 +20,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AffixFuzzer22* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer22* elements, size_t num_elements ) { @@ -50,24 +70,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AffixFuzzer22* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer22.hpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer22.hpp index d90ab9e3abaa..d43c819bed92 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer22.hpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer22.hpp @@ -43,15 +43,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AffixFuzzer22` into an arrow array. + static Result> to_arrow( + const datatypes::AffixFuzzer22* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer22* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AffixFuzzer22` into an arrow array. - static Result> to_arrow( - const datatypes::AffixFuzzer22* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer3.cpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer3.cpp index 90344d710ab6..a0387ac838b8 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer3.cpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer3.cpp @@ -34,6 +34,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AffixFuzzer3* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::AffixFuzzer3* elements, size_t num_elements @@ -102,24 +122,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AffixFuzzer3* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer3.hpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer3.hpp index 1e5446762d3d..ab0fd0e499fe 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer3.hpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer3.hpp @@ -218,15 +218,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AffixFuzzer3` into an arrow array. + static Result> to_arrow( + const datatypes::AffixFuzzer3* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::AffixFuzzer3* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AffixFuzzer3` into an arrow array. - static Result> to_arrow( - const datatypes::AffixFuzzer3* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer4.cpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer4.cpp index d464eb45d4de..32677fa7fc1a 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer4.cpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer4.cpp @@ -41,6 +41,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AffixFuzzer4* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::AffixFuzzer4* elements, size_t num_elements @@ -103,24 +123,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AffixFuzzer4* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer4.hpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer4.hpp index a3f7d2dcaac3..8f029e6ea2c2 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer4.hpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer4.hpp @@ -208,15 +208,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AffixFuzzer4` into an arrow array. + static Result> to_arrow( + const datatypes::AffixFuzzer4* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::DenseUnionBuilder* builder, const datatypes::AffixFuzzer4* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AffixFuzzer4` into an arrow array. - static Result> to_arrow( - const datatypes::AffixFuzzer4* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer5.cpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer5.cpp index b81ed3261a50..c3302d22215f 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer5.cpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer5.cpp @@ -22,6 +22,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::AffixFuzzer5* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer5* elements, size_t num_elements ) { @@ -57,24 +77,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::AffixFuzzer5* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/affix_fuzzer5.hpp b/rerun_cpp/tests/generated/datatypes/affix_fuzzer5.hpp index fc6ea5b4445a..d240b3b35a56 100644 --- a/rerun_cpp/tests/generated/datatypes/affix_fuzzer5.hpp +++ b/rerun_cpp/tests/generated/datatypes/affix_fuzzer5.hpp @@ -47,15 +47,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::AffixFuzzer5` into an arrow array. + static Result> to_arrow( + const datatypes::AffixFuzzer5* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::AffixFuzzer5* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::AffixFuzzer5` into an arrow array. - static Result> to_arrow( - const datatypes::AffixFuzzer5* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/flattened_scalar.cpp b/rerun_cpp/tests/generated/datatypes/flattened_scalar.cpp index 4d5c8dc245c9..09cfad272c3c 100644 --- a/rerun_cpp/tests/generated/datatypes/flattened_scalar.cpp +++ b/rerun_cpp/tests/generated/datatypes/flattened_scalar.cpp @@ -16,6 +16,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::FlattenedScalar* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::FlattenedScalar* elements, size_t num_elements @@ -41,24 +61,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::FlattenedScalar* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/flattened_scalar.hpp b/rerun_cpp/tests/generated/datatypes/flattened_scalar.hpp index 4a6ee8fc1938..bd7ceed85db2 100644 --- a/rerun_cpp/tests/generated/datatypes/flattened_scalar.hpp +++ b/rerun_cpp/tests/generated/datatypes/flattened_scalar.hpp @@ -41,15 +41,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::FlattenedScalar` into an arrow array. + static Result> to_arrow( + const datatypes::FlattenedScalar* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StructBuilder* builder, const datatypes::FlattenedScalar* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::FlattenedScalar` into an arrow array. - static Result> to_arrow( - const datatypes::FlattenedScalar* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/primitive_component.cpp b/rerun_cpp/tests/generated/datatypes/primitive_component.cpp index afa72757c5a6..18384a342742 100644 --- a/rerun_cpp/tests/generated/datatypes/primitive_component.cpp +++ b/rerun_cpp/tests/generated/datatypes/primitive_component.cpp @@ -15,6 +15,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::PrimitiveComponent* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::UInt32Builder* builder, const datatypes::PrimitiveComponent* elements, size_t num_elements @@ -36,24 +56,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::PrimitiveComponent* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/primitive_component.hpp b/rerun_cpp/tests/generated/datatypes/primitive_component.hpp index 050f573c9c40..2960b4b08f02 100644 --- a/rerun_cpp/tests/generated/datatypes/primitive_component.hpp +++ b/rerun_cpp/tests/generated/datatypes/primitive_component.hpp @@ -46,15 +46,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::PrimitiveComponent` into an arrow array. + static Result> to_arrow( + const datatypes::PrimitiveComponent* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::UInt32Builder* builder, const datatypes::PrimitiveComponent* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::PrimitiveComponent` into an arrow array. - static Result> to_arrow( - const datatypes::PrimitiveComponent* instances, size_t num_instances - ); }; } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/string_component.cpp b/rerun_cpp/tests/generated/datatypes/string_component.cpp index c0fbb28ac950..f57d85be7e6c 100644 --- a/rerun_cpp/tests/generated/datatypes/string_component.cpp +++ b/rerun_cpp/tests/generated/datatypes/string_component.cpp @@ -14,6 +14,26 @@ namespace rerun { return datatype; } + Result> Loggable::to_arrow( + const datatypes::StringComponent* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + rerun::Error Loggable::fill_arrow_array_builder( arrow::StringBuilder* builder, const datatypes::StringComponent* elements, size_t num_elements @@ -35,24 +55,4 @@ namespace rerun { return Error::ok(); } - - Result> Loggable::to_arrow( - const datatypes::StringComponent* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } } // namespace rerun diff --git a/rerun_cpp/tests/generated/datatypes/string_component.hpp b/rerun_cpp/tests/generated/datatypes/string_component.hpp index 981e7e4843ed..8f9caa6ef4b7 100644 --- a/rerun_cpp/tests/generated/datatypes/string_component.hpp +++ b/rerun_cpp/tests/generated/datatypes/string_component.hpp @@ -43,15 +43,15 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); + /// Serializes an array of `rerun::datatypes::StringComponent` into an arrow array. + static Result> to_arrow( + const datatypes::StringComponent* instances, size_t num_instances + ); + /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::StringBuilder* builder, const datatypes::StringComponent* elements, size_t num_elements ); - - /// Serializes an array of `rerun::datatypes::StringComponent` into an arrow array. - static Result> to_arrow( - const datatypes::StringComponent* instances, size_t num_instances - ); }; } // namespace rerun From 39797ff9e23c88baabcb869bc8b66f88fedcc205 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Mon, 18 Mar 2024 10:47:36 +0100 Subject: [PATCH 044/508] Fix RERUN_C_BUILD_ARTIFACT path value if CARGO_BUILD_TARGET env variable is set (#5547) ### What When building the conda-forge package for the C++ bindings for rerun-sdk, I encountered a failure of the following type (see https://github.com/conda-forge/staged-recipes/pull/25648#issuecomment-2000481352): ~~~ [307/532] Linking CXX shared library rerun_cpp/librerun_sdk.so FAILED: rerun_cpp/librerun_sdk.so : && $BUILD_PREFIX/bin/x86_64-conda-linux-gnu-c++ -fPIC -fvisibility-inlines-hidden -fmessage-length=0 -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem $PREFIX/include -fdebug-prefix-map=$SRC_DIR=/usr/local/src/conda/librerun-sdk-0.14.1 -fdebug-prefix-map=$PREFIX=/usr/local/src/conda-prefix -O3 -DNDEBUG -Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,--allow-shlib-undefined -Wl,-rpath,$PREFIX/lib -Wl,-rpath-link,$PREFIX/lib -L$PREFIX/lib -shared -Wl,-soname,librerun_sdk.so -o rerun_cpp/librerun_sdk.so rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/annotation_context.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/arrows2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/arrows2d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/arrows3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/arrows3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/asset3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/asset3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/bar_chart.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/bar_chart_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/boxes2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/boxes2d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/boxes3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/boxes3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/clear.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/clear_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/depth_image.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/depth_image_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/disconnected_space.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/image.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/image_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/line_strips2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/line_strips3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/mesh3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/pinhole.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/pinhole_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/points2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/points3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/scalar.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/segmentation_image.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/segmentation_image_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/series_line.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/series_point.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/tensor.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/tensor_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/text_document.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/text_log.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/time_series_scalar.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/transform3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/transform3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/view_coordinates.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/archetypes/view_coordinates_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/archetypes/container_blueprint.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/archetypes/plot_legend.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/archetypes/scalar_axis.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/archetypes/space_view_blueprint.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/archetypes/viewport_blueprint.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/active_tab.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/auto_layout.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/auto_space_views.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/column_shares.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/container_kind.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/corner2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/entities_determined_by_user.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/entity_properties_component.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/grid_columns.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/included_contents.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/included_queries.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/included_space_views.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/lock_range_during_zoom.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/panel_view.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/query_expressions.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/root_container.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/row_shares.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/space_view_class.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/space_view_maximized.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/space_view_origin.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/viewport_layout.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/components/visible.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/blueprint/datatypes/legend.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/component_type.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/annotation_context.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/annotation_context_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/blob.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/class_id.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/clear_is_recursive.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/color.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/color_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/depth_meter.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/disconnected_space.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/draw_order.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/half_sizes2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/half_sizes2d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/half_sizes3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/half_sizes3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/instance_key.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/keypoint_id.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/line_strip2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/line_strip3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/marker_shape.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/marker_shape_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/marker_size.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/material.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/material_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/media_type.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/media_type_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/mesh_properties.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/mesh_properties_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/name.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/name_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/out_of_tree_transform3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/pinhole_projection.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/pinhole_projection_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/position2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/position2d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/position3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/position3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/radius.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/range1d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/resolution.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/resolution_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/rotation3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/rotation3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/scalar.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/scalar_scattering.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/stroke_width.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/tensor_data.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/tensor_data_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/texcoord2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/texcoord2d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/text.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/text_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/text_log_level.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/text_log_level_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/transform3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/vector2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/vector2d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/vector3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/vector3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/view_coordinates.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/view_coordinates_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/components/visualizer_overrides.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/config.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/data_cell.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/angle.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/annotation_info.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/annotation_info_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/class_description.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/class_description_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/class_description_map_elem.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/class_description_map_elem_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/class_id.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/entity_path.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/float32.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/keypoint_id.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/keypoint_pair.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/keypoint_pair_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/mat3x3.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/mat3x3_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/mat4x4.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/mat4x4_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/material.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/mesh_properties.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/quaternion.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/quaternion_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/rgba32.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/rgba32_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/rotation3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/rotation3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/rotation_axis_angle.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/rotation_axis_angle_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/scale3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/tensor_buffer.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/tensor_buffer_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/tensor_data.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/tensor_data_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/tensor_dimension.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/tensor_dimension_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/transform3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/translation_and_mat3x3.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/translation_and_mat3x3_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/translation_rotation_scale3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/translation_rotation_scale3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/uint32.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/utf8.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/utf8_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/uuid.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/uvec2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/uvec3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/uvec4d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/vec2d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/vec2d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/vec3d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/vec3d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/vec4d.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/datatypes/vec4d_ext.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/demo_utils.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/entity_path.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/error.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/indicator_component.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/recording_stream.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/sdk_info.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/spawn.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/spawn_options.cpp.o rerun_cpp/CMakeFiles/rerun_sdk.dir/src/rerun/string_utils.cpp.o $SRC_DIR/crates/rerun_c/../../target/release/librerun_c.a $PREFIX/lib/libarrow.so.1200.1.0 -lm -ldl -pthread && : $BUILD_PREFIX/bin/../lib/gcc/x86_64-conda-linux-gnu/12.3.0/../../../../x86_64-conda-linux-gnu/bin/ld: cannot find $SRC_DIR/crates/rerun_c/../../target/release/librerun_c.a: No such file or directory collect2: error: ld returned 1 exit status ~~~ It turned out that this was due to some rust activation script in conda-forge, that defined the `CARGO_BUILD_TARGET` env variable, and that apparently changed the location of the `librerun_c.a` library generated by cargo. To handle this, I modified the CMake code as reported in this PR. If the `CARGO_BUILD_TARGET` env variable is not defined, `$ENV{CARGO_BUILD_TARGET}` evalutes to an empty string, and the behaviour is exactly the same that you have before this PR. I am not sure if it make sense to have this patch upstream, but I guess even to just ask that it was more efficient to open a PR rather than to open an issue to ask if it could make sense to open a PR. If you think it is better no to have this change upstream, feel free to close the PR, we can just keep the patch locally in https://github.com/conda-forge/librerun-sdk-feedstock/blob/main/recipe/fixrerun_c_location.patch . ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5547/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5547/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5547/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5547) - [Docs preview](https://rerun.io/preview/3af4793c662b313c1cc14062566eca05e4e34dda/docs) - [Examples preview](https://rerun.io/preview/3af4793c662b313c1cc14062566eca05e4e34dda/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/rerun_c/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/rerun_c/CMakeLists.txt b/crates/rerun_c/CMakeLists.txt index 5c030a692d5f..1f8f0deacf00 100644 --- a/crates/rerun_c/CMakeLists.txt +++ b/crates/rerun_c/CMakeLists.txt @@ -2,11 +2,11 @@ # Determine Rust's librerun path. if(APPLE) - set(RERUN_C_BUILD_ARTIFACT ${CMAKE_CURRENT_SOURCE_DIR}/../../target/release/librerun_c.a) + set(RERUN_C_BUILD_ARTIFACT ${CMAKE_CURRENT_SOURCE_DIR}/../../target/$ENV{CARGO_BUILD_TARGET}/release/librerun_c.a) elseif(UNIX) # if(LINUX) # CMake 3.25 - set(RERUN_C_BUILD_ARTIFACT ${CMAKE_CURRENT_SOURCE_DIR}/../../target/release/librerun_c.a) + set(RERUN_C_BUILD_ARTIFACT ${CMAKE_CURRENT_SOURCE_DIR}/../../target/$ENV{CARGO_BUILD_TARGET}/release/librerun_c.a) elseif(WIN32) - set(RERUN_C_BUILD_ARTIFACT ${CMAKE_CURRENT_SOURCE_DIR}/../../target/release/rerun_c.lib) + set(RERUN_C_BUILD_ARTIFACT ${CMAKE_CURRENT_SOURCE_DIR}/../../target/$ENV{CARGO_BUILD_TARGET}/release/rerun_c.lib) else() message(FATAL_ERROR "Unsupported platform.") endif() From 253b7205b287f4af2401bfb60e5779adfc125f94 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 18 Mar 2024 11:00:27 +0100 Subject: [PATCH 045/508] Remove what's left of setup_dev.sh & setup.sh (#5552) ### What Almost everything has been taken over by `pixi` by now and these outdated / partially broken scripts keep confusing new-comers to the repo, so at this point they're clearly doing more bad than good. * Fixes #5545 * Fixes #4170 * There's still some stuff that should be moved to pixi but that's better covered by #3717 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5552/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5552/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5552/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5552) - [Docs preview](https://rerun.io/preview/8da4ef3b503b5459274c73ea40bc0926b61dbae9/docs) - [Examples preview](https://rerun.io/preview/8da4ef3b503b5459274c73ea40bc0926b61dbae9/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt --- BUILD.md | 14 ++++++----- ci_docker/Dockerfile | 1 - scripts/setup.sh | 60 -------------------------------------------- scripts/setup_dev.sh | 40 ----------------------------- 4 files changed, 8 insertions(+), 107 deletions(-) delete mode 100755 scripts/setup.sh delete mode 100755 scripts/setup_dev.sh diff --git a/BUILD.md b/BUILD.md index 533f464f7a1a..e9a11cbabc69 100644 --- a/BUILD.md +++ b/BUILD.md @@ -23,12 +23,6 @@ cd rerun Now install the `pixi` package manager: -Finally, run the following script to install the dependencies and CLI tools needed for Rerun's build environment: - -```sh -./scripts/setup_dev.sh -``` - Make sure `cargo --version` prints `1.74.0` once you are done. If you are using an Apple-silicon Mac (M1, M2), make sure `rustc -vV` outputs `host: aarch64-apple-darwin`. If not, this should fix it: @@ -37,6 +31,14 @@ If you are using an Apple-silicon Mac (M1, M2), make sure `rustc -vV` outputs `h rustup set default-host aarch64-apple-darwin && rustup install 1.74.0 ``` +Additionally, we use [cargo-cranky](https://github.com/ericseppanen/cargo-cranky) for defining which Clippy lints are active and [cargo-deny](https://github.com/EmbarkStudios/cargo-deny) for linting crate versions. +You don't need to install these for building, but it's highly recommended when contributing changes to +Rust code. +```sh +cargo install cargo-cranky +cargo install --locked cargo-deny +``` + ## Building and running the viewer Use this command for building and running the viewer: diff --git a/ci_docker/Dockerfile b/ci_docker/Dockerfile index 68d94fc8fb96..e5e4acfab46f 100644 --- a/ci_docker/Dockerfile +++ b/ci_docker/Dockerfile @@ -6,7 +6,6 @@ LABEL version="0.11.0" LABEL description="Docker image used for the CI of https://github.com/rerun-io/rerun" # Install the ubuntu package dependencies -# This mirrors scripts/setup.sh ENV DEBIAN_FRONTEND=noninteractive RUN set -eux; \ apt-get update; \ diff --git a/scripts/setup.sh b/scripts/setup.sh deleted file mode 100755 index c70b90de0823..000000000000 --- a/scripts/setup.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env bash -# Setup required to build rerun. -# This file is largly mirrored in ci_docker/Dockerfile. - -set -eu -script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -cd "$script_path/.." -set -x - -# eframe dependencies needed on run on Linux and Fedora Rawhide: -if [ -x "$(command -v apt-get)" ]; then - sudo apt-get -y install \ - libatk-bridge2.0 \ - libfontconfig1-dev \ - libfreetype6-dev \ - libglib2.0-dev \ - libgtk-3-dev \ - libssl-dev \ - libxcb-render0-dev \ - libxcb-shape0-dev \ - libxcb-xfixes0-dev \ - libxkbcommon-dev \ - patchelf -elif [ -x "$(command -v dnf)" ]; then - sudo dnf install \ - clang \ - clang-devel \ - clang-tools-extra \ - libxcb-devel \ - libxkbcommon-devel \ - openssl-devel \ - pkg-config -fi - -# C++ SDK requires `cmake` and `apache-arrow` -# Note that this may look different for different package managers. -# If you have issues installing arrow, check https://arrow.apache.org/install/ -packagesNeeded='cmake apache-arrow' -if [ -x "$(command -v brew)" ]; then brew install $packagesNeeded -elif [ -x "$(command -v port)" ]; then sudo port install $packagesNeeded -elif [ -x "$(command -v apt-get)" ]; then - sudo apt-get install -y -V ca-certificates lsb-release wget - wget https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb - sudo apt-get install -y -V ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb - sudo apt-get update - sudo apt-get -y install 'cmake libarrow-dev' -elif [ -x "$(command -v dnf)" ]; then sudo dnf install $packagesNeeded -elif [ -x "$(command -v zypper)" ]; then sudo zypper install $packagesNeeded -elif [ -x "$(command -v apk)" ]; then sudo apk add --no-cache $packagesNeeded -elif [ -x "$(command -v winget)" ]; then sudo winget add --no-cache $packagesNeeded -elif [ -x "$(command -v pacman)" ]; then sudo pacman -S 'cmake arrow' -else - echo "FAILED TO INSTALL PACKAGE: Package manager not found. You must manually install: $packagesNeeded">&2; - exit 1 -fi - -# Needed to compile and check the code: -rustup install 1.74.0 - -echo "setup.sh completed!" diff --git a/scripts/setup_dev.sh b/scripts/setup_dev.sh deleted file mode 100755 index 85163008b7f2..000000000000 --- a/scripts/setup_dev.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -# Run all the setup required to work as a developer in the rerun repository. - -set -eu -script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -cd "$script_path/.." -set -x - -./scripts/setup.sh - -# Install -curl -fsSL https://pixi.sh/install.sh | bash - -cargo install cargo-cranky # Uses lints defined in Cranky.toml. See https://github.com/ericseppanen/cargo-cranky -cargo install --locked cargo-deny # https://github.com/EmbarkStudios/cargo-deny -cargo install just # https://github.com/casey/just - a command runner - - -packagesNeeded='pngcrush pipx clang-format flatbuffers' -if [ -x "$(command -v brew)" ]; then brew install $packagesNeeded -elif [ -x "$(command -v port)" ]; then sudo port install $packagesNeeded -elif [ -x "$(command -v apt-get)" ]; then sudo apt-get -y install $packagesNeeded -elif [ -x "$(command -v dnf)" ]; then sudo dnf install $packagesNeeded -elif [ -x "$(command -v zypper)" ]; then sudo zypper install $packagesNeeded -elif [ -x "$(command -v apk)" ]; then sudo apk add --no-cache $packagesNeeded -elif [ -x "$(command -v winget)" ]; then sudo winget add --no-cache $packagesNeeded -elif [ -x "$(command -v pacman)" ]; then sudo pacman -S $packagesNeeded -else - echo "FAILED TO INSTALL PACKAGE: Package manager not found. You must manually install: $packagesNeeded">&2; - exit 1 -fi - -# ensure pipx is on the path -pipx ensurepath - -# install nox for python testing automation -# https://nox.thea.codes/en/stable/ -pipx install nox - -echo "setup_dev.sh completed!" From 300d82a5bab15f2fad5d338fc69e49952ef7e26b Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:20:55 +0100 Subject: [PATCH 046/508] Automatically expand and scroll the streams tree when focusing on an item (#5494) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What - Follow up to #5482 - Fixes #5232 This PR adds support for expanding and scrolling to the focus item in the Streams view. It also adds expanding/scrolling the Blueprint tree when focusing on a component. - Blocked on https://github.com/emilk/egui/pull/4174 TODO: - [x] update egui commit once ☝🏻 is merged https://github.com/rerun-io/rerun/assets/49431240/55c2959f-bb9b-4f67-b20b-06ba82175d71 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5494/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5494/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5494/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5494) - [Docs preview](https://rerun.io/preview/e879778c92dd2e50eb05bc6fdefee9ac79b93872/docs) - [Examples preview](https://rerun.io/preview/e879778c92dd2e50eb05bc6fdefee9ac79b93872/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_time_panel/src/lib.rs | 21 ++++++++++++++++++ .../re_viewport/src/viewport_blueprint_ui.rs | 22 +++++++++++++++---- tests/python/release_checklist/check_focus.py | 6 +++-- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/crates/re_time_panel/src/lib.rs b/crates/re_time_panel/src/lib.rs index 9521a2f911a0..64a4ffd9d262 100644 --- a/crates/re_time_panel/src/lib.rs +++ b/crates/re_time_panel/src/lib.rs @@ -584,6 +584,18 @@ impl TimePanel { clip_rect.max.x = tree_max_y; ui.set_clip_rect(clip_rect); + // expand if children is focused + let focused_entity_path = ctx + .focused_item + .as_ref() + .and_then(|item| item.entity_path()); + + if focused_entity_path.is_some_and(|entity_path| entity_path.is_descendant_of(&tree.path)) { + CollapseScope::StreamsTree + .entity(tree.path.clone()) + .set_open(ui.ctx(), true); + } + let re_ui::list_item::ShowCollapsingResponse { item_response: response, body_response, @@ -625,6 +637,15 @@ impl TimePanel { ); }); + if Some(&tree.path) == focused_entity_path { + // Scroll only if the entity isn't already visible. This is important because that's what + // happens when double-clicking an entity _in the blueprint tree_. In such case, it would be + // annoying to induce a scroll motion. + if !ui.clip_rect().contains_rect(response.rect) { + response.scroll_to_me(Some(egui::Align::Center)); + } + } + context_menu_ui_for_item( ctx, viewport_blueprint, diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 588fefd8c047..382e62c8880e 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -64,7 +64,10 @@ impl Viewport<'_, '_> { .auto_shrink([true, false]) .show(ui, |ui| { ctx.re_ui.panel_content(ui, |_, ui| { - self.state.blueprint_tree_scroll_to_item = self.handle_focused_item(ctx, ui); + self.state.blueprint_tree_scroll_to_item = ctx + .focused_item + .as_ref() + .and_then(|item| self.handle_focused_item(ctx, ui, item)); self.root_container_tree_ui(ctx, ui); @@ -86,8 +89,12 @@ impl Viewport<'_, '_> { } /// Expend all required items and compute which item we should scroll to. - fn handle_focused_item(&self, ctx: &ViewerContext<'_>, ui: &egui::Ui) -> Option { - let focused_item = ctx.focused_item.as_ref()?; + fn handle_focused_item( + &self, + ctx: &ViewerContext<'_>, + ui: &egui::Ui, + focused_item: &Item, + ) -> Option { match focused_item { Item::Container(container_id) => { self.expand_all_contents_until(ui.ctx(), &Contents::Container(*container_id)); @@ -129,8 +136,15 @@ impl Viewport<'_, '_> { res } + Item::ComponentPath(component_path) => self.handle_focused_item( + ctx, + ui, + &Item::InstancePath(InstancePath::entity_splat( + component_path.entity_path.clone(), + )), + ), - Item::StoreId(_) | Item::ComponentPath(_) => None, + Item::StoreId(_) => None, } } diff --git a/tests/python/release_checklist/check_focus.py b/tests/python/release_checklist/check_focus.py index f2d1bf5a34cd..2f4a711e957e 100644 --- a/tests/python/release_checklist/check_focus.py +++ b/tests/python/release_checklist/check_focus.py @@ -19,8 +19,10 @@ ## Checks -- Collapse all in the blueprint tree. -- Double-click on the box in the first space view, check corresponding space view expands. +- Collapse all in the blueprint tree and the streams view +- Double-click on the box in the first space view + - check corresponding space view expands and scrolls + - check the streams view expands and scrolls - Collapse all in the blueprint tree. - Double-click on the leaf "boxes3d" entity in the streams view, check both space views expand. """ From 1a7951037691f479d5a27b7fa0516a76f7f67f24 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 18 Mar 2024 11:50:47 +0100 Subject: [PATCH 047/508] Visible Range as a component override / fix non-inheriting visual range regression (#5538) ### What * next step on #5463 Fixes the "Visual Range does not inherit" regression we got when removing groups. Does this by moving the visual time range out of `EntityProperties`. I kept all the previous data structures and convert from and to avoid even deeper changes than already necessary. This PR explicitly aims at getting 0.14 time range behavior back, the ui is expected to behave exactly as it did before. ![image](https://github.com/rerun-io/rerun/assets/1220815/1ac1223c-3bc4-44d9-bf08-1ab2cd394fbe) (much same) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5538/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5538/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5538/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5538) - [Docs preview](https://rerun.io/preview/477bfed3dd24a6cf61a5867e309ed41d9ea7eab8/docs) - [Examples preview](https://rerun.io/preview/477bfed3dd24a6cf61a5867e309ed41d9ea7eab8/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_entity_db/src/entity_properties.rs | 8 +- .../re_log_types/src/time_point/time_int.rs | 7 + crates/re_query/src/util.rs | 17 - crates/re_space_view/src/lib.rs | 5 + crates/re_space_view/src/space_view.rs | 178 +++------ crates/re_space_view/src/visual_time_range.rs | 114 ++++++ .../src/visualizers/entity_iterator.rs | 13 +- .../src/legacy_visualizer_system.rs | 1 + .../src/line_visualizer_system.rs | 1 + .../src/point_visualizer_system.rs | 1 + crates/re_space_view_time_series/src/util.rs | 32 +- .../re_types/definitions/rerun/blueprint.fbs | 3 + .../components/visible_time_range.fbs | 20 ++ .../datatypes/visible_time_range.fbs | 58 +++ .../re_types/definitions/rerun/datatypes.fbs | 5 +- .../definitions/rerun/datatypes/time_int.fbs | 19 + .../src/blueprint/components/.gitattributes | 1 + .../re_types/src/blueprint/components/mod.rs | 3 + .../components/visible_time_range.rs | 153 ++++++++ .../components/visible_time_range_ext.rs | 6 + .../src/blueprint/datatypes/.gitattributes | 4 +- .../re_types/src/blueprint/datatypes/mod.rs | 10 +- .../blueprint/datatypes/visible_time_range.rs | 340 ++++++++++++++++++ ...gend.rs => visible_time_range_boundary.rs} | 194 +++++----- .../visible_time_range_boundary_ext.rs | 47 +++ .../visible_time_range_boundary_kind.rs | 166 +++++++++ .../datatypes/visible_time_range_ext.rs | 17 + .../src/codegen/python/mod.rs | 2 +- .../src/datatypes/.gitattributes | 1 + crates/re_types_core/src/datatypes/mod.rs | 3 + .../re_types_core/src/datatypes/time_int.rs | 131 +++++++ .../src/datatypes/time_int_ext.rs | 6 + .../src/blueprint/validation_gen/mod.rs | 2 + crates/re_viewer/src/ui/selection_panel.rs | 51 +-- crates/re_viewer/src/ui/visible_history.rs | 155 ++++---- .../src/space_view/view_query.rs | 52 ++- docs/content/reference/types/datatypes.md | 1 + .../reference/types/datatypes/.gitattributes | 1 + .../reference/types/datatypes/time_int.md | 16 + rerun_cpp/src/rerun/blueprint/.gitattributes | 1 + rerun_cpp/src/rerun/blueprint/components.hpp | 1 + .../rerun/blueprint/components/.gitattributes | 1 + .../components/visible_time_range.hpp | 60 ++++ rerun_cpp/src/rerun/blueprint/datatypes.hpp | 7 + .../rerun/blueprint/datatypes/.gitattributes | 8 +- .../src/rerun/blueprint/datatypes/legend.cpp | 78 ---- .../datatypes/visible_time_range.cpp | 124 +++++++ .../datatypes/visible_time_range.hpp | 61 ++++ .../datatypes/visible_time_range_boundary.cpp | 91 +++++ ...nd.hpp => visible_time_range_boundary.hpp} | 45 ++- .../visible_time_range_boundary_kind.cpp | 67 ++++ .../visible_time_range_boundary_kind.hpp | 57 +++ rerun_cpp/src/rerun/datatypes.hpp | 1 + rerun_cpp/src/rerun/datatypes/.gitattributes | 2 + rerun_cpp/src/rerun/datatypes/time_int.cpp | 57 +++ rerun_cpp/src/rerun/datatypes/time_int.hpp | 61 ++++ .../rerun/blueprint/components/.gitattributes | 1 + .../rerun/blueprint/components/__init__.py | 4 + .../components/visible_time_range.py | 28 ++ .../rerun/blueprint/datatypes/.gitattributes | 4 +- .../rerun/blueprint/datatypes/__init__.py | 42 ++- .../rerun/blueprint/datatypes/legend.py | 92 ----- .../blueprint/datatypes/visible_time_range.py | 194 ++++++++++ .../datatypes/visible_time_range_boundary.py | 104 ++++++ .../visible_time_range_boundary_kind.py | 105 ++++++ .../rerun_sdk/rerun/datatypes/.gitattributes | 1 + .../rerun_sdk/rerun/datatypes/__init__.py | 6 + .../rerun_sdk/rerun/datatypes/time_int.py | 59 +++ 68 files changed, 2616 insertions(+), 590 deletions(-) create mode 100644 crates/re_space_view/src/visual_time_range.rs create mode 100644 crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs create mode 100644 crates/re_types/definitions/rerun/datatypes/time_int.fbs create mode 100644 crates/re_types/src/blueprint/components/visible_time_range.rs create mode 100644 crates/re_types/src/blueprint/components/visible_time_range_ext.rs create mode 100644 crates/re_types/src/blueprint/datatypes/visible_time_range.rs rename crates/re_types/src/blueprint/datatypes/{legend.rs => visible_time_range_boundary.rs} (53%) create mode 100644 crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs create mode 100644 crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs create mode 100644 crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs create mode 100644 crates/re_types_core/src/datatypes/time_int.rs create mode 100644 crates/re_types_core/src/datatypes/time_int_ext.rs create mode 100644 docs/content/reference/types/datatypes/time_int.md create mode 100644 rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes.hpp delete mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/legend.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp rename rerun_cpp/src/rerun/blueprint/datatypes/{legend.hpp => visible_time_range_boundary.hpp} (55%) create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp create mode 100644 rerun_cpp/src/rerun/datatypes/time_int.cpp create mode 100644 rerun_cpp/src/rerun/datatypes/time_int.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/legend.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/time_int.py diff --git a/crates/re_entity_db/src/entity_properties.rs b/crates/re_entity_db/src/entity_properties.rs index 02f6e29325a1..fb50dc0d39bc 100644 --- a/crates/re_entity_db/src/entity_properties.rs +++ b/crates/re_entity_db/src/entity_properties.rs @@ -94,7 +94,6 @@ impl FromIterator<(EntityPath, EntityProperties)> for EntityPropertyMap { #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct EntityProperties { - pub visible_history: re_query::ExtraQueryHistory, pub interactive: bool, /// What kind of color mapping should be applied (none, map, texture, transfer..)? @@ -143,7 +142,6 @@ pub struct EntityProperties { impl Default for EntityProperties { fn default() -> Self { Self { - visible_history: re_query::ExtraQueryHistory::default(), interactive: true, color_mapper: EditableAutoValue::default(), pinhole_image_plane_distance: EditableAutoValue::Auto(1.0), @@ -164,7 +162,6 @@ impl EntityProperties { /// Multiply/and these together. pub fn with_child(&self, child: &Self) -> Self { Self { - visible_history: self.visible_history.with_child(&child.visible_history), interactive: self.interactive && child.interactive, color_mapper: self.color_mapper.or(&child.color_mapper).clone(), @@ -208,7 +205,6 @@ impl EntityProperties { /// loaded from the Blueprint store where the Auto values are not up-to-date. pub fn merge_with(&self, other: &Self) -> Self { Self { - visible_history: self.visible_history.with_child(&other.visible_history), interactive: other.interactive, color_mapper: other.color_mapper.or(&self.color_mapper).clone(), @@ -246,7 +242,6 @@ impl EntityProperties { /// Determine whether this `EntityProperty` has user-edits relative to another `EntityProperty` pub fn has_edits(&self, other: &Self) -> bool { let Self { - visible_history, interactive, color_mapper, pinhole_image_plane_distance, @@ -260,8 +255,7 @@ impl EntityProperties { time_series_aggregator, } = self; - visible_history != &other.visible_history - || interactive != &other.interactive + interactive != &other.interactive || color_mapper.has_edits(&other.color_mapper) || pinhole_image_plane_distance.has_edits(&other.pinhole_image_plane_distance) || backproject_depth.has_edits(&other.backproject_depth) diff --git a/crates/re_log_types/src/time_point/time_int.rs b/crates/re_log_types/src/time_point/time_int.rs index fa633336323a..de13e0d624df 100644 --- a/crates/re_log_types/src/time_point/time_int.rs +++ b/crates/re_log_types/src/time_point/time_int.rs @@ -113,6 +113,13 @@ impl From for Duration { } } +impl From for re_types_core::datatypes::TimeInt { + #[inline] + fn from(int: TimeInt) -> Self { + Self(int.as_i64()) + } +} + impl std::ops::Neg for TimeInt { type Output = Self; diff --git a/crates/re_query/src/util.rs b/crates/re_query/src/util.rs index d1c72298bdf9..11cfe034e48f 100644 --- a/crates/re_query/src/util.rs +++ b/crates/re_query/src/util.rs @@ -11,7 +11,6 @@ use crate::{query_archetype, range::range_archetype, ArchetypeView}; /// For [`VisibleHistoryBoundary::RelativeToTimeCursor`] and [`VisibleHistoryBoundary::Absolute`], /// the value are either nanos or frames, depending on the type of timeline. #[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum VisibleHistoryBoundary { /// Boundary is a value relative to the time cursor RelativeToTimeCursor(i64), @@ -36,7 +35,6 @@ impl Default for VisibleHistoryBoundary { /// Visible history bounds. #[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct VisibleHistory { /// Low time boundary. pub from: VisibleHistoryBoundary, @@ -99,8 +97,6 @@ impl VisibleHistory { /// When showing an entity in the history view, add this much history to it. #[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(default))] pub struct ExtraQueryHistory { /// Is the feature enabled? pub enabled: bool, @@ -112,19 +108,6 @@ pub struct ExtraQueryHistory { pub sequences: VisibleHistory, } -impl ExtraQueryHistory { - /// Multiply/and these together. - pub fn with_child(&self, child: &Self) -> Self { - if child.enabled { - *child - } else if self.enabled { - *self - } else { - Self::default() - } - } -} - // --- pub fn query_archetype_with_history<'a, A: Archetype + 'a, const N: usize>( diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index dea050e7ca05..fc879706ef7d 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -9,6 +9,7 @@ mod screenshot; mod space_view; mod space_view_contents; mod sub_archetypes; // TODO(andreas): better name before `sub_archetype` sticks around? +mod visual_time_range; mod visualizable; pub use data_query::{DataQuery, EntityOverrideContext, PropertyResolver}; @@ -20,6 +21,10 @@ pub use sub_archetypes::{ entity_path_for_space_view_sub_archetype, query_space_view_sub_archetype, query_space_view_sub_archetype_or_default, }; +pub use visual_time_range::{ + default_time_range, query_visual_history, time_range_boundary_to_visible_history_boundary, + visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, +}; pub use visualizable::determine_visualizable_entities; // ----------- diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 02804b85b60b..4b8dc2214af7 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,9 +1,9 @@ use itertools::{FoldWhile, Itertools}; -use re_data_store::LatestAtQuery; -use re_entity_db::{EntityDb, EntityPath, EntityProperties, VisibleHistory}; -use re_entity_db::{EntityPropertiesComponent, EntityPropertyMap}; +use nohash_hasher::IntMap; use crate::SpaceViewContents; +use re_data_store::LatestAtQuery; +use re_entity_db::{EntityDb, EntityPath, EntityPropertiesComponent, EntityPropertyMap}; use re_log_types::{DataRow, EntityPathSubs, RowId}; use re_query::query_archetype; use re_types::blueprint::archetypes as blueprint_archetypes; @@ -14,9 +14,9 @@ use re_types::{ use re_types_core::archetypes::Clear; use re_types_core::Archetype as _; use re_viewer_context::{ - DataResult, PerSystemEntities, PropertyOverrides, RecommendedSpaceView, SpaceViewClass, - SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, SystemCommand, - SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, + DataResult, OverridePath, PerSystemEntities, PropertyOverrides, RecommendedSpaceView, + SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, + SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, }; // ---------------------------------------------------------------------------- @@ -416,46 +416,56 @@ impl SpaceViewBlueprint { } pub fn root_data_result(&self, ctx: &StoreContext<'_>, query: &LatestAtQuery) -> DataResult { - let entity_path = self.entity_path(); - - let is_time_series = self.class_identifier == "Time Series"; + let base_override_root = self.entity_path(); + let individual_override_path = + base_override_root.join(&DataResult::INDIVIDUAL_OVERRIDES_PREFIX.into()); + let recursive_override_path = + base_override_root.join(&DataResult::RECURSIVE_OVERRIDES_PREFIX.into()); - let mut individual_properties = ctx + let individual_properties = ctx .blueprint .store() - .query_latest_component_quiet::(&self.entity_path(), query) + .query_latest_component_quiet::( + &individual_override_path, + query, + ) .map(|result| result.value.0); + let accumulated_properties = individual_properties.clone().unwrap_or_default(); - // TODO(#4194): this should come from delegation to the space-view-class - if individual_properties.is_none() && is_time_series { - let mut time_series_defaults = EntityProperties::default(); - time_series_defaults.visible_history.nanos = VisibleHistory::ALL; - time_series_defaults.visible_history.sequences = VisibleHistory::ALL; - individual_properties = Some(time_series_defaults); - } - - let mut accumulated_properties = individual_properties.clone().unwrap_or_default(); - - if is_time_series { - // TODO(#4194): enabled == false means use defaults - if !accumulated_properties.visible_history.enabled { - accumulated_properties.visible_history.enabled = true; - accumulated_properties.visible_history.nanos = VisibleHistory::ALL; - accumulated_properties.visible_history.sequences = VisibleHistory::ALL; + // Gather recursive component overrides. + // Ignore individual overrides on SpaceView root. + let mut recursive_component_overrides = IntMap::default(); + if let Some(recursive_override_subtree) = + ctx.blueprint.tree().subtree(&recursive_override_path) + { + for component in recursive_override_subtree.entity.components.keys() { + if let Some(component_data) = ctx + .blueprint + .store() + .latest_at(query, &recursive_override_path, *component, &[*component]) + .and_then(|(_, _, cells)| cells[0].clone()) + { + if !component_data.is_empty() { + recursive_component_overrides.insert( + *component, + OverridePath::blueprint_path(recursive_override_path.clone()), + ); + } + } } } DataResult { - entity_path: entity_path.clone(), + entity_path: base_override_root, visualizers: Default::default(), tree_prefix_only: false, property_overrides: Some(PropertyOverrides { accumulated_properties, individual_properties, recursive_properties: Default::default(), - resolved_component_overrides: Default::default(), - recursive_override_path: entity_path.clone(), - individual_override_path: entity_path, + resolved_component_overrides: recursive_component_overrides, + recursive_override_path, + individual_override_path, }), } } @@ -464,7 +474,7 @@ impl SpaceViewBlueprint { #[cfg(test)] mod tests { use crate::data_query::{DataQuery, PropertyResolver}; - use re_entity_db::EntityDb; + use re_entity_db::{EntityDb, EntityProperties, EntityPropertiesComponent}; use re_log_types::{ example_components::{MyColor, MyLabel, MyPoint}, DataCell, DataRow, RowId, StoreId, StoreKind, TimePoint, @@ -673,110 +683,6 @@ mod tests { assert!(!result.accumulated_properties().interactive); } } - - // Override interactive range on root - { - let root = space_view.root_data_result( - &StoreContext { - app_id: re_log_types::ApplicationId::unknown(), - blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], - }, - &blueprint_query, - ); - let mut overrides = root.individual_properties().cloned().unwrap_or_default(); - overrides.visible_history.enabled = true; - overrides.visible_history.nanos = VisibleHistory::ALL; - - save_override( - overrides, - root.recursive_override_path().unwrap(), - &mut blueprint, - ); - } - - // Everyone has interactive history - { - let ctx = StoreContext { - app_id: re_log_types::ApplicationId::unknown(), - blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], - }; - let mut query_result = contents.execute_query(&ctx, &visualizable_entities); - resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); - - let parent = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent")) - .unwrap(); - let child1 = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent/skip/child1")) - .unwrap(); - let child2 = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent/skip/child2")) - .unwrap(); - - for result in [parent, child1, child2] { - assert!(result.accumulated_properties().visible_history.enabled); - assert_eq!( - result.accumulated_properties().visible_history.nanos, - VisibleHistory::ALL - ); - } - - let mut overrides = child2.individual_properties().cloned().unwrap_or_default(); - overrides.visible_history.enabled = true; - - save_override( - overrides, - child2.individual_override_path().unwrap(), - &mut blueprint, - ); - } - - // Child2 has its own interactive history - { - let ctx = StoreContext { - app_id: re_log_types::ApplicationId::unknown(), - blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], - }; - - let mut query_result = contents.execute_query(&ctx, &visualizable_entities); - resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); - - let parent = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent")) - .unwrap(); - let child1 = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent/skip/child1")) - .unwrap(); - let child2 = query_result - .tree - .lookup_result_by_path(&EntityPath::from("parent/skip/child2")) - .unwrap(); - - for result in [parent, child1] { - assert!(result.accumulated_properties().visible_history.enabled); - assert_eq!( - result.accumulated_properties().visible_history.nanos, - VisibleHistory::ALL - ); - } - - assert!(child2.accumulated_properties().visible_history.enabled); - assert_eq!( - child2.accumulated_properties().visible_history.nanos, - VisibleHistory::OFF - ); - } } #[test] diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs new file mode 100644 index 000000000000..b07261f7b4f9 --- /dev/null +++ b/crates/re_space_view/src/visual_time_range.rs @@ -0,0 +1,114 @@ +//! For the most part this module bridges older visual history types to the newer +//! visual range types that are defined in the `re_types` crate. +//! +//! Historically there was a special `EntityProperty` bag that was used to store the visual history. +//! Now, visual history makes use of the component override system (components stored at special paths in the blueprint store). +//! +//! The intent is to eventually remove the old types, but this bridge here is there in order +//! to reduce the amount of changes in code that is likely to be refactored soon anyways. + +use re_log_types::TimeRange; +use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +use re_types::blueprint::{ + components::VisibleTimeRange, + datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, +}; +use re_viewer_context::{SpaceViewClassIdentifier, ViewerContext}; + +pub fn time_range_boundary_to_visible_history_boundary( + boundary: &VisibleTimeRangeBoundary, +) -> VisibleHistoryBoundary { + match boundary.kind { + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => { + VisibleHistoryBoundary::RelativeToTimeCursor(boundary.time.0) + } + VisibleTimeRangeBoundaryKind::Absolute => VisibleHistoryBoundary::Absolute(boundary.time.0), + VisibleTimeRangeBoundaryKind::Infinite => VisibleHistoryBoundary::Infinite, + } +} + +pub fn visible_history_boundary_to_time_range_boundary( + boundary: &VisibleHistoryBoundary, +) -> VisibleTimeRangeBoundary { + match boundary { + VisibleHistoryBoundary::RelativeToTimeCursor(v) => VisibleTimeRangeBoundary { + kind: VisibleTimeRangeBoundaryKind::RelativeToTimeCursor, + time: (*v).into(), + }, + VisibleHistoryBoundary::Absolute(v) => VisibleTimeRangeBoundary { + kind: VisibleTimeRangeBoundaryKind::Absolute, + time: (*v).into(), + }, + VisibleHistoryBoundary::Infinite => VisibleTimeRangeBoundary { + kind: VisibleTimeRangeBoundaryKind::Infinite, + time: 0.into(), + }, + } +} + +pub fn visible_time_range_to_time_range( + range: &VisibleTimeRange, + time_type: re_log_types::TimeType, + cursor: re_log_types::TimeInt, +) -> re_log_types::TimeRange { + let cursor = cursor.as_i64().into(); + + let mut min = match time_type { + re_log_types::TimeType::Sequence => range.0.from_sequence.start_boundary_time(cursor).0, + re_log_types::TimeType::Time => range.0.from_time.start_boundary_time(cursor).0, + }; + let mut max = match time_type { + re_log_types::TimeType::Sequence => range.0.to_sequence.end_boundary_time(cursor).0, + re_log_types::TimeType::Time => range.0.to_time.end_boundary_time(cursor).0, + }; + + if min > max { + std::mem::swap(&mut min, &mut max); + } + + TimeRange::new(min.into(), max.into()) +} + +pub fn query_visual_history( + ctx: &ViewerContext<'_>, + data_result: &re_viewer_context::DataResult, +) -> ExtraQueryHistory { + let visual_time_range_component = + data_result.lookup_override::(ctx); + if let Some(visual_time_range_component) = visual_time_range_component { + ExtraQueryHistory { + enabled: true, + nanos: VisibleHistory { + from: time_range_boundary_to_visible_history_boundary( + &visual_time_range_component.0.from_time, + ), + to: time_range_boundary_to_visible_history_boundary( + &visual_time_range_component.0.to_time, + ), + }, + sequences: VisibleHistory { + from: time_range_boundary_to_visible_history_boundary( + &visual_time_range_component.0.from_sequence, + ), + to: time_range_boundary_to_visible_history_boundary( + &visual_time_range_component.0.to_sequence, + ), + }, + } + } else { + ExtraQueryHistory { + enabled: false, + nanos: VisibleHistory::default(), + sequences: VisibleHistory::default(), + } + } +} + +// TODO(#4194): this should come from delegation to the space-view-class +pub fn default_time_range(class_identifier: SpaceViewClassIdentifier) -> VisibleTimeRange { + if class_identifier == "Time Series" { + VisibleTimeRange::EVERYTHING.clone() + } else { + VisibleTimeRange::EMPTY.clone() + } +} diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 986c40c7db18..8b37590166dc 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,6 +2,7 @@ use re_entity_db::EntityProperties; use re_log_types::{EntityPath, RowId, TimeInt}; use re_query::{query_archetype_with_history, ArchetypeView, QueryError}; use re_renderer::DepthOffset; +use re_space_view::query_visual_history; use re_types::{components::InstanceKey, Archetype, Component}; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewClass, SpaceViewSystemExecutionError, ViewContextCollection, @@ -71,11 +72,13 @@ where space_view_class_identifier: view_ctx.space_view_class_identifier(), }; + let extra_history = query_visual_history(ctx, data_result); + match query_archetype_with_history::( ctx.entity_db.store(), &query.timeline, &query.latest_at, - &data_result.accumulated_properties().visible_history, + &extra_history, &data_result.entity_path, ) .and_then(|arch_views| { @@ -179,11 +182,13 @@ macro_rules! impl_process_archetype { space_view_class_identifier: view_ctx.space_view_class_identifier(), }; + let extra_history = query_visual_history(ctx, data_result); + match ctx.entity_db.query_caches().[]::( ctx.entity_db.store(), &query.timeline, &query.latest_at, - &data_result.accumulated_properties().visible_history, + &extra_history, &data_result.entity_path, |(t, keys, $($pov,)+ $($comp,)*)| { counter @@ -257,11 +262,13 @@ pub fn count_instances_in_archetype_views< let mut num_instances = 0; for data_result in query.iter_visible_data_results(ctx, System::identifier()) { + let extra_history = query_visual_history(ctx, data_result); + match query_archetype_with_history::( ctx.entity_db.store(), &query.timeline, &query.latest_at, - &data_result.accumulated_properties().visible_history, + &extra_history, &data_result.entity_path, ) .map(|arch_views| { diff --git a/crates/re_space_view_time_series/src/legacy_visualizer_system.rs b/crates/re_space_view_time_series/src/legacy_visualizer_system.rs index 6d71a991ed03..bd9753f1d33c 100644 --- a/crates/re_space_view_time_series/src/legacy_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/legacy_visualizer_system.rs @@ -140,6 +140,7 @@ impl LegacyTimeSeriesSystem { let mut points = Vec::new(); let time_range = determine_time_range( + ctx, query, data_result, plot_bounds, diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 5672f84770f5..4668bb409c53 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -184,6 +184,7 @@ fn load_series( let mut points = Vec::new(); let time_range = determine_time_range( + ctx, query, data_result, plot_bounds, diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index f0b612798773..58a7d5423639 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -138,6 +138,7 @@ impl SeriesPointSystem { let mut points = Vec::new(); let time_range = determine_time_range( + ctx, query, data_result, plot_bounds, diff --git a/crates/re_space_view_time_series/src/util.rs b/crates/re_space_view_time_series/src/util.rs index d58faaeb51ee..b703b7d20ae7 100644 --- a/crates/re_space_view_time_series/src/util.rs +++ b/crates/re_space_view_time_series/src/util.rs @@ -1,10 +1,13 @@ use re_log_types::{EntityPath, TimeInt, TimeRange}; +use re_space_view::{default_time_range, visible_time_range_to_time_range}; use re_types::datatypes::Utf8; -use re_viewer_context::{external::re_entity_db::TimeSeriesAggregator, ViewQuery, ViewerContext}; +use re_viewer_context::{ + external::re_entity_db::TimeSeriesAggregator, SpaceViewClass, ViewQuery, ViewerContext, +}; use crate::{ aggregation::{AverageAggregator, MinMaxAggregator}, - PlotPoint, PlotSeries, PlotSeriesKind, ScatterAttrs, + PlotPoint, PlotSeries, PlotSeriesKind, ScatterAttrs, TimeSeriesSpaceView, }; /// Find the plot bounds and the per-ui-point delta from egui. @@ -28,26 +31,21 @@ pub fn determine_plot_bounds_and_time_per_pixel( } pub fn determine_time_range( + ctx: &ViewerContext<'_>, query: &ViewQuery<'_>, data_result: &re_viewer_context::DataResult, plot_bounds: Option, enable_query_clamping: bool, ) -> TimeRange { - let visible_history = match query.timeline.typ() { - re_log_types::TimeType::Time => data_result.accumulated_properties().visible_history.nanos, - re_log_types::TimeType::Sequence => { - data_result - .accumulated_properties() - .visible_history - .sequences - } - }; - - let mut time_range = if data_result.accumulated_properties().visible_history.enabled { - visible_history.time_range(query.latest_at) - } else { - TimeRange::new(TimeInt::MIN, TimeInt::MAX) - }; + let visible_time_range_override = data_result + .lookup_override::(ctx) + .unwrap_or(default_time_range(TimeSeriesSpaceView::identifier())); + + let mut time_range = visible_time_range_to_time_range( + &visible_time_range_override, + query.timeline.typ(), + query.latest_at, + ); // TODO(cmc): We would love to reduce the query to match the actual plot bounds, but because // the plot widget handles zoom after we provide it with data for the current frame, diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index 1d629523d648..c7056192eca7 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -1,3 +1,5 @@ +include "./blueprint/datatypes/visible_time_range.fbs"; + include "./blueprint/components/active_tab.fbs"; include "./blueprint/components/auto_layout.fbs"; include "./blueprint/components/auto_space_views.fbs"; @@ -18,6 +20,7 @@ include "./blueprint/components/space_view_class.fbs"; include "./blueprint/components/space_view_maximized.fbs"; include "./blueprint/components/space_view_origin.fbs"; include "./blueprint/components/viewer_recommendation_hash.fbs"; +include "./blueprint/components/visible_time_range.fbs"; include "./blueprint/components/visible.fbs"; include "./blueprint/archetypes/background_3d.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs new file mode 100644 index 000000000000..7e71f15c0d08 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs @@ -0,0 +1,20 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.components; + +// --- + +/// The range of values that will be included in a Space View query. +table VisibleTimeRange ( + "attr.arrow.transparent", + "attr.rerun.scope": "blueprint", + "attr.rust.repr": "transparent", + "attr.rust.derive": "PartialEq, Eq" +) { + value: rerun.blueprint.datatypes.VisibleTimeRange (order: 100); +} diff --git a/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs b/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs new file mode 100644 index 000000000000..584a6f42366e --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs @@ -0,0 +1,58 @@ + +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/attributes.fbs"; + +include "../../datatypes/time_int.fbs"; + +namespace rerun.blueprint.datatypes; + +/// Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. +enum VisibleTimeRangeBoundaryKind: byte ( + "attr.rerun.scope": "blueprint", + "attr.docs.unreleased" +) { + /// Boundary is a value relative to the time cursor. + RelativeToTimeCursor, + + /// Boundary is an absolute value. + Absolute, + + /// The boundary extends to infinity. + Infinite, +} + +/// Type of boundary for visible history. +struct VisibleTimeRangeBoundary ( + "attr.rerun.scope": "blueprint", + "attr.docs.unreleased" +) { + /// Type of the boundary. + kind: rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind (order: 100); + + /// Value of the boundary (ignored for `Infinite` type). + time: rerun.datatypes.TimeInt (order: 200); +} + +/// Visible time range bounds. +struct VisibleTimeRange ( + "attr.rerun.scope": "blueprint", + "attr.rust.derive": "PartialEq, Eq", + "attr.docs.unreleased" +) { + // TODO(andreas): Split this up into two separate components. + + /// Low time boundary for sequence timeline. + from_sequence: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 100); + + /// High time boundary for sequence timeline. + to_sequence: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 200); + + /// Low time boundary for time timeline. + from_time: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 300); + + /// High time boundary for time timeline. + to_time: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 400); +} diff --git a/crates/re_types/definitions/rerun/datatypes.fbs b/crates/re_types/definitions/rerun/datatypes.fbs index 3b8adb39a597..74d5fc31fea0 100644 --- a/crates/re_types/definitions/rerun/datatypes.fbs +++ b/crates/re_types/definitions/rerun/datatypes.fbs @@ -1,8 +1,8 @@ include "./datatypes/angle.fbs"; include "./datatypes/annotation_info.fbs"; include "./datatypes/bool.fbs"; -include "./datatypes/class_description.fbs"; include "./datatypes/class_description_map_elem.fbs"; +include "./datatypes/class_description.fbs"; include "./datatypes/class_id.fbs"; include "./datatypes/entity_path.fbs"; include "./datatypes/float32.fbs"; @@ -14,12 +14,13 @@ include "./datatypes/material.fbs"; include "./datatypes/mesh_properties.fbs"; include "./datatypes/quaternion.fbs"; include "./datatypes/rgba32.fbs"; -include "./datatypes/rotation3d.fbs"; include "./datatypes/rotation_axis_angle.fbs"; +include "./datatypes/rotation3d.fbs"; include "./datatypes/scale3d.fbs"; include "./datatypes/tensor_buffer.fbs"; include "./datatypes/tensor_data.fbs"; include "./datatypes/tensor_dimension.fbs"; +include "./datatypes/time_int.fbs"; include "./datatypes/transform3d.fbs"; include "./datatypes/translation_and_mat3x3.fbs"; include "./datatypes/translation_rotation_scale3d.fbs"; diff --git a/crates/re_types/definitions/rerun/datatypes/time_int.fbs b/crates/re_types/definitions/rerun/datatypes/time_int.fbs new file mode 100644 index 000000000000..dfecb256d70b --- /dev/null +++ b/crates/re_types/definitions/rerun/datatypes/time_int.fbs @@ -0,0 +1,19 @@ + +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/attributes.fbs"; + +namespace rerun.datatypes; + +/// A 64-bit number describing either nanoseconds OR sequence numbers. +struct TimeInt ( + "attr.docs.unreleased", + "attr.arrow.transparent", + "attr.rust.derive": "Copy, PartialEq, Eq, PartialOrd, Ord", + "attr.rust.tuple_struct", + "attr.rust.override_crate": "re_types_core" +) { + value: long (order: 100); +} diff --git a/crates/re_types/src/blueprint/components/.gitattributes b/crates/re_types/src/blueprint/components/.gitattributes index 9f8d0a8dd3bf..02afa95257cd 100644 --- a/crates/re_types/src/blueprint/components/.gitattributes +++ b/crates/re_types/src/blueprint/components/.gitattributes @@ -15,3 +15,4 @@ space_view_class.rs linguist-generated=true space_view_origin.rs linguist-generated=true viewer_recommendation_hash.rs linguist-generated=true visible.rs linguist-generated=true +visible_time_range.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index 0b873668d40b..d3670e91167c 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -15,6 +15,8 @@ mod space_view_origin; mod viewer_recommendation_hash; mod visible; mod visible_ext; +mod visible_time_range; +mod visible_time_range_ext; pub use self::active_tab::ActiveTab; pub use self::background3d_kind::Background3DKind; @@ -29,3 +31,4 @@ pub use self::space_view_class::SpaceViewClass; pub use self::space_view_origin::SpaceViewOrigin; pub use self::viewer_recommendation_hash::ViewerRecommendationHash; pub use self::visible::Visible; +pub use self::visible_time_range::VisibleTimeRange; diff --git a/crates/re_types/src/blueprint/components/visible_time_range.rs b/crates/re_types/src/blueprint/components/visible_time_range.rs new file mode 100644 index 000000000000..053681357c0c --- /dev/null +++ b/crates/re_types/src/blueprint/components/visible_time_range.rs @@ -0,0 +1,153 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: The range of values that will be included in a Space View query. +#[derive(Clone, Debug, PartialEq, Eq)] +#[repr(transparent)] +pub struct VisibleTimeRange(pub crate::blueprint::datatypes::VisibleTimeRange); + +impl ::re_types_core::SizeBytes for VisibleTimeRange { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for VisibleTimeRange { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for VisibleTimeRange { + #[inline] + fn borrow(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + &self.0 + } +} + +impl std::ops::Deref for VisibleTimeRange { + type Target = crate::blueprint::datatypes::VisibleTimeRange; + + #[inline] + fn deref(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + &self.0 + } +} + +::re_types_core::macros::impl_into_cow!(VisibleTimeRange); + +impl ::re_types_core::Loggable for VisibleTimeRange { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.components.VisibleTimeRange".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new( + "from_sequence", + ::arrow_datatype(), + false, + ), + Field::new( + "to_sequence", + ::arrow_datatype(), + false, + ), + Field::new( + "from_time", + ::arrow_datatype(), + false, + ), + Field::new( + "to_time", + ::arrow_datatype(), + false, + ), + ])) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data0): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + let datum = datum.map(|datum| { + let Self(data0) = datum.into_owned(); + data0 + }); + (datum.is_some(), datum) + }) + .unzip(); + let data0_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = data0_bitmap; + crate::blueprint::datatypes::VisibleTimeRange::to_arrow_opt(data0)? + } + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok( + crate::blueprint::datatypes::VisibleTimeRange::from_arrow_opt(arrow_data) + .with_context("rerun.blueprint.components.VisibleTimeRange#value")? + .into_iter() + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.blueprint.components.VisibleTimeRange#value") + .with_context("rerun.blueprint.components.VisibleTimeRange")?, + ) + } +} diff --git a/crates/re_types/src/blueprint/components/visible_time_range_ext.rs b/crates/re_types/src/blueprint/components/visible_time_range_ext.rs new file mode 100644 index 000000000000..051f3d145a13 --- /dev/null +++ b/crates/re_types/src/blueprint/components/visible_time_range_ext.rs @@ -0,0 +1,6 @@ +use super::VisibleTimeRange; + +impl VisibleTimeRange { + pub const EMPTY: Self = Self(crate::blueprint::datatypes::VisibleTimeRange::EMPTY); + pub const EVERYTHING: Self = Self(crate::blueprint::datatypes::VisibleTimeRange::EVERYTHING); +} diff --git a/crates/re_types/src/blueprint/datatypes/.gitattributes b/crates/re_types/src/blueprint/datatypes/.gitattributes index f8cc2be56035..788b8f6860a3 100644 --- a/crates/re_types/src/blueprint/datatypes/.gitattributes +++ b/crates/re_types/src/blueprint/datatypes/.gitattributes @@ -1,5 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -legend.rs linguist-generated=true mod.rs linguist-generated=true +visible_time_range.rs linguist-generated=true +visible_time_range_boundary.rs linguist-generated=true +visible_time_range_boundary_kind.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/datatypes/mod.rs b/crates/re_types/src/blueprint/datatypes/mod.rs index af61829b13e1..c843412e734b 100644 --- a/crates/re_types/src/blueprint/datatypes/mod.rs +++ b/crates/re_types/src/blueprint/datatypes/mod.rs @@ -1,5 +1,11 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -mod legend; +mod visible_time_range; +mod visible_time_range_boundary; +mod visible_time_range_boundary_ext; +mod visible_time_range_boundary_kind; +mod visible_time_range_ext; -pub use self::legend::Legend; +pub use self::visible_time_range::VisibleTimeRange; +pub use self::visible_time_range_boundary::VisibleTimeRangeBoundary; +pub use self::visible_time_range_boundary_kind::VisibleTimeRangeBoundaryKind; diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range.rs new file mode 100644 index 000000000000..bc1bd84fef03 --- /dev/null +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range.rs @@ -0,0 +1,340 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Datatype**: Visible time range bounds. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct VisibleTimeRange { + /// Low time boundary for sequence timeline. + pub from_sequence: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + + /// High time boundary for sequence timeline. + pub to_sequence: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + + /// Low time boundary for time timeline. + pub from_time: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + + /// High time boundary for time timeline. + pub to_time: crate::blueprint::datatypes::VisibleTimeRangeBoundary, +} + +impl ::re_types_core::SizeBytes for VisibleTimeRange { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.from_sequence.heap_size_bytes() + + self.to_sequence.heap_size_bytes() + + self.from_time.heap_size_bytes() + + self.to_time.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + && ::is_pod() + && ::is_pod() + && ::is_pod() + } +} + +::re_types_core::macros::impl_into_cow!(VisibleTimeRange); + +impl ::re_types_core::Loggable for VisibleTimeRange { + type Name = ::re_types_core::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.datatypes.VisibleTimeRange".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new( + "from_sequence", + ::arrow_datatype(), + false, + ), + Field::new( + "to_sequence", + ::arrow_datatype(), + false, + ), + Field::new( + "from_time", + ::arrow_datatype(), + false, + ), + Field::new( + "to_time", + ::arrow_datatype(), + false, + ), + ])) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + (datum.is_some(), datum) + }) + .unzip(); + let bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + StructArray::new( + ::arrow_datatype(), + vec![ + { + let (somes, from_sequence): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { from_sequence, .. } = &**datum; + from_sequence.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let from_sequence_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = from_sequence_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( + from_sequence, + )? + } + }, + { + let (somes, to_sequence): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { to_sequence, .. } = &**datum; + to_sequence.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let to_sequence_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = to_sequence_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( + to_sequence, + )? + } + }, + { + let (somes, from_time): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { from_time, .. } = &**datum; + from_time.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let from_time_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = from_time_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( + from_time, + )? + } + }, + { + let (somes, to_time): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { to_time, .. } = &**datum; + to_time.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let to_time_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = to_time_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( + to_time, + )? + } + }, + ], + bitmap, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok({ + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let (arrow_data_fields, arrow_data_arrays) = + (arrow_data.fields(), arrow_data.values()); + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data_fields + .iter() + .map(|field| field.name.as_str()) + .zip(arrow_data_arrays) + .collect(); + let from_sequence = { + if !arrays_by_name.contains_key("from_sequence") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "from_sequence", + )) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + } + let arrow_data = &**arrays_by_name["from_sequence"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#from_sequence")? + .into_iter() + }; + let to_sequence = { + if !arrays_by_name.contains_key("to_sequence") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "to_sequence", + )) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + } + let arrow_data = &**arrays_by_name["to_sequence"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#to_sequence")? + .into_iter() + }; + let from_time = { + if !arrays_by_name.contains_key("from_time") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "from_time", + )) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + } + let arrow_data = &**arrays_by_name["from_time"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#from_time")? + .into_iter() + }; + let to_time = { + if !arrays_by_name.contains_key("to_time") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "to_time", + )) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + } + let arrow_data = &**arrays_by_name["to_time"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#to_time")? + .into_iter() + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + ::itertools::izip!(from_sequence, to_sequence, from_time, to_time), + arrow_data.validity(), + ) + .map(|opt| { + opt.map(|(from_sequence, to_sequence, from_time, to_time)| { + Ok(Self { + from_sequence: from_sequence + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRange#from_sequence", + )?, + to_sequence: to_sequence + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRange#to_sequence", + )?, + from_time: from_time + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRange#from_time", + )?, + to_time: to_time + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRange#to_time", + )?, + }) + }) + .transpose() + }) + .collect::>>() + .with_context("rerun.blueprint.datatypes.VisibleTimeRange")? + } + }) + } +} diff --git a/crates/re_types/src/blueprint/datatypes/legend.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs similarity index 53% rename from crates/re_types/src/blueprint/datatypes/legend.rs rename to crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs index a75e3bc464e4..2307d5fcf906 100644 --- a/crates/re_types/src/blueprint/datatypes/legend.rs +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/legend.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -21,42 +21,37 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Datatype**: Configuration for the legend of a plot. -#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub struct Legend { - /// Whether or not the legend should be displayed. - pub visible: bool, +/// **Datatype**: Type of boundary for visible history. +#[derive(Clone, Debug)] +pub struct VisibleTimeRangeBoundary { + /// Type of the boundary. + pub kind: crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind, - /// Where should the legend be located. - /// - /// Allowed values: - /// - LeftTop = 1, - /// - RightTop = 2, - /// - LeftBottom = 3, - /// - RightBottom = 4 - pub location: Option, + /// Value of the boundary (ignored for `Infinite` type). + pub time: crate::datatypes::TimeInt, } -impl ::re_types_core::SizeBytes for Legend { +impl ::re_types_core::SizeBytes for VisibleTimeRangeBoundary { #[inline] fn heap_size_bytes(&self) -> u64 { - self.visible.heap_size_bytes() + self.location.heap_size_bytes() + self.kind.heap_size_bytes() + self.time.heap_size_bytes() } #[inline] fn is_pod() -> bool { - ::is_pod() && >::is_pod() + ::is_pod() + && ::is_pod() } } -::re_types_core::macros::impl_into_cow!(Legend); +::re_types_core::macros::impl_into_cow!(VisibleTimeRangeBoundary); -impl ::re_types_core::Loggable for Legend { +impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { type Name = ::re_types_core::DatatypeName; #[inline] fn name() -> Self::Name { - "rerun.blueprint.datatypes.Legend".into() + "rerun.blueprint.datatypes.VisibleTimeRangeBoundary".into() } #[allow(clippy::wildcard_imports)] @@ -64,18 +59,12 @@ impl ::re_types_core::Loggable for Legend { fn arrow_datatype() -> arrow2::datatypes::DataType { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ - Field { - name: "visible".to_owned(), - data_type: DataType::Boolean, - is_nullable: false, - metadata: [].into(), - }, - Field { - name: "location".to_owned(), - data_type: DataType::UInt8, - is_nullable: true, - metadata: [].into(), - }, + Field::new( + "kind", + ::arrow_datatype(), + false, + ), + Field::new("time", ::arrow_datatype(), false), ])) } @@ -101,55 +90,58 @@ impl ::re_types_core::Loggable for Legend { any_nones.then(|| somes.into()) }; StructArray::new( - ::arrow_datatype(), + ::arrow_datatype(), vec![ { - let (somes, visible): (Vec<_>, Vec<_>) = data + let (somes, kind): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum.as_ref().map(|datum| { - let Self { visible, .. } = &**datum; - visible.clone() + let Self { kind, .. } = &**datum; + kind.clone() }); (datum.is_some(), datum) }) .unzip(); - let visible_bitmap: Option = { + let kind_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; - BooleanArray::new( - DataType::Boolean, - visible.into_iter().map(|v| v.unwrap_or_default()).collect(), - visible_bitmap, - ) - .boxed() + { + _ = kind_bitmap; + crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind::to_arrow_opt( + kind, + )? + } }, { - let (somes, location): (Vec<_>, Vec<_>) = data + let (somes, time): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { - let datum = datum - .as_ref() - .map(|datum| { - let Self { location, .. } = &**datum; - location.clone() - }) - .flatten(); + let datum = datum.as_ref().map(|datum| { + let Self { time, .. } = &**datum; + time.clone() + }); (datum.is_some(), datum) }) .unzip(); - let location_bitmap: Option = { + let time_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; PrimitiveArray::new( - DataType::UInt8, - location - .into_iter() - .map(|v| v.unwrap_or_default()) + DataType::Int64, + time.into_iter() + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::TimeInt(data0) = datum; + data0 + }) + .unwrap_or_default() + }) .collect(), - location_bitmap, + time_bitmap, ) .boxed() }, @@ -174,25 +166,11 @@ impl ::re_types_core::Loggable for Legend { .as_any() .downcast_ref::() .ok_or_else(|| { - DeserializationError::datatype_mismatch( - DataType::Struct(std::sync::Arc::new(vec![ - Field { - name: "visible".to_owned(), - data_type: DataType::Boolean, - is_nullable: false, - metadata: [].into(), - }, - Field { - name: "location".to_owned(), - data_type: DataType::UInt8, - is_nullable: true, - metadata: [].into(), - }, - ])), - arrow_data.data_type().clone(), - ) + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.datatypes.Legend")?; + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary")?; if arrow_data.is_empty() { Vec::new() } else { @@ -203,66 +181,66 @@ impl ::re_types_core::Loggable for Legend { .map(|field| field.name.as_str()) .zip(arrow_data_arrays) .collect(); - let visible = { - if !arrays_by_name.contains_key("visible") { + let kind = { + if !arrays_by_name.contains_key("kind") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "visible", + "kind", )) - .with_context("rerun.blueprint.datatypes.Legend"); + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary"); } - let arrow_data = &**arrays_by_name["visible"]; - arrow_data - .as_any() - .downcast_ref::() - .ok_or_else(|| { - DeserializationError::datatype_mismatch( - DataType::Boolean, - arrow_data.data_type().clone(), - ) - }) - .with_context("rerun.blueprint.datatypes.Legend#visible")? - .into_iter() + let arrow_data = &**arrays_by_name["kind"]; + crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind::from_arrow_opt( + arrow_data, + ) + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary#kind")? + .into_iter() }; - let location = { - if !arrays_by_name.contains_key("location") { + let time = { + if !arrays_by_name.contains_key("time") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "location", + "time", )) - .with_context("rerun.blueprint.datatypes.Legend"); + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary"); } - let arrow_data = &**arrays_by_name["location"]; + let arrow_data = &**arrays_by_name["time"]; arrow_data .as_any() - .downcast_ref::() + .downcast_ref::() .ok_or_else(|| { - DeserializationError::datatype_mismatch( - DataType::UInt8, - arrow_data.data_type().clone(), - ) + let expected = DataType::Int64; + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.datatypes.Legend#location")? + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary#time")? .into_iter() .map(|opt| opt.copied()) + .map(|res_or_opt| res_or_opt.map(|v| crate::datatypes::TimeInt(v))) }; arrow2::bitmap::utils::ZipValidity::new_with_validity( - ::itertools::izip!(visible, location), + ::itertools::izip!(kind, time), arrow_data.validity(), ) .map(|opt| { - opt.map(|(visible, location)| { + opt.map(|(kind, time)| { Ok(Self { - visible: visible + kind: kind + .ok_or_else(DeserializationError::missing_data) + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRangeBoundary#kind", + )?, + time: time .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.blueprint.datatypes.Legend#visible")?, - location, + .with_context( + "rerun.blueprint.datatypes.VisibleTimeRangeBoundary#time", + )?, }) }) .transpose() }) .collect::>>() - .with_context("rerun.blueprint.datatypes.Legend")? + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary")? } }) } diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs new file mode 100644 index 000000000000..a93c32dce2be --- /dev/null +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs @@ -0,0 +1,47 @@ +use super::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}; +use re_types_core::datatypes::TimeInt; + +impl VisibleTimeRangeBoundary { + pub const AT_CURSOR: Self = Self { + kind: VisibleTimeRangeBoundaryKind::RelativeToTimeCursor, + time: TimeInt(0), + }; + + pub const INFINITE: Self = Self { + kind: VisibleTimeRangeBoundaryKind::Infinite, + time: TimeInt(0), + }; + + /// Returns the time assuming this boundary is a start boundary. + pub fn start_boundary_time(&self, cursor: TimeInt) -> TimeInt { + match self.kind { + VisibleTimeRangeBoundaryKind::Absolute => self.time, + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => TimeInt(cursor.0 + self.time.0), + VisibleTimeRangeBoundaryKind::Infinite => TimeInt::MIN, + } + } + + /// Returns the correct time assuming this boundary is an end boundary. + pub fn end_boundary_time(&self, cursor: TimeInt) -> TimeInt { + match self.kind { + VisibleTimeRangeBoundaryKind::Absolute => self.time, + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => TimeInt(cursor.0 + self.time.0), + VisibleTimeRangeBoundaryKind::Infinite => TimeInt::MAX, + } + } +} + +impl PartialEq for VisibleTimeRangeBoundary { + fn eq(&self, other: &Self) -> bool { + match self.kind { + VisibleTimeRangeBoundaryKind::Absolute + | VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => { + other.kind == self.kind && other.time == self.time + } + // Ignore the time value for infinite boundaries. + VisibleTimeRangeBoundaryKind::Infinite => other.kind == self.kind, + } + } +} + +impl Eq for VisibleTimeRangeBoundary {} diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs new file mode 100644 index 000000000000..46b3d8f37750 --- /dev/null +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs @@ -0,0 +1,166 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Datatype**: Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum VisibleTimeRangeBoundaryKind { + /// Boundary is a value relative to the time cursor. + RelativeToTimeCursor = 1, + + /// Boundary is an absolute value. + Absolute = 2, + + /// The boundary extends to infinity. + Infinite = 3, +} + +impl VisibleTimeRangeBoundaryKind { + /// All the different enum variants. + pub const ALL: [Self; 3] = [Self::RelativeToTimeCursor, Self::Absolute, Self::Infinite]; +} + +impl ::re_types_core::SizeBytes for VisibleTimeRangeBoundaryKind { + #[inline] + fn heap_size_bytes(&self) -> u64 { + 0 + } + + #[inline] + fn is_pod() -> bool { + true + } +} + +impl std::fmt::Display for VisibleTimeRangeBoundaryKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::RelativeToTimeCursor => write!(f, "RelativeToTimeCursor"), + Self::Absolute => write!(f, "Absolute"), + Self::Infinite => write!(f, "Infinite"), + } + } +} + +::re_types_core::macros::impl_into_cow!(VisibleTimeRangeBoundaryKind); + +impl ::re_types_core::Loggable for VisibleTimeRangeBoundaryKind { + type Name = ::re_types_core::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Union( + std::sync::Arc::new(vec![ + Field::new("_null_markers", DataType::Null, true), + Field::new("RelativeToTimeCursor", DataType::Null, true), + Field::new("Absolute", DataType::Null, true), + Field::new("Infinite", DataType::Null, true), + ]), + Some(std::sync::Arc::new(vec![0i32, 1i32, 2i32, 3i32])), + UnionMode::Sparse, + ) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let data: Vec<_> = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + datum + }) + .collect(); + let num_variants = 3usize; + let types = data + .iter() + .map(|a| match a.as_deref() { + None => 0, + Some(value) => *value as i8, + }) + .collect(); + let fields: Vec<_> = + std::iter::repeat(NullArray::new(DataType::Null, data.len()).boxed()) + .take(1 + num_variants) + .collect(); + UnionArray::new( + ::arrow_datatype(), + types, + fields, + None, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok({ + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind")?; + let arrow_data_types = arrow_data.types(); + arrow_data_types + .iter() + .map(|typ| match typ { + 0 => Ok(None), + 1 => Ok(Some(VisibleTimeRangeBoundaryKind::RelativeToTimeCursor)), + 2 => Ok(Some(VisibleTimeRangeBoundaryKind::Absolute)), + 3 => Ok(Some(VisibleTimeRangeBoundaryKind::Infinite)), + _ => Err(DeserializationError::missing_union_arm( + Self::arrow_datatype(), + "", + *typ as _, + )), + }) + .collect::>>() + .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind")? + }) + } +} diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs new file mode 100644 index 000000000000..d558b143e343 --- /dev/null +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs @@ -0,0 +1,17 @@ +use super::{VisibleTimeRange, VisibleTimeRangeBoundary}; + +impl VisibleTimeRange { + pub const EMPTY: Self = Self { + from_sequence: VisibleTimeRangeBoundary::AT_CURSOR, + to_sequence: VisibleTimeRangeBoundary::AT_CURSOR, + from_time: VisibleTimeRangeBoundary::AT_CURSOR, + to_time: VisibleTimeRangeBoundary::AT_CURSOR, + }; + + pub const EVERYTHING: Self = Self { + from_sequence: VisibleTimeRangeBoundary::INFINITE, + to_sequence: VisibleTimeRangeBoundary::INFINITE, + from_time: VisibleTimeRangeBoundary::INFINITE, + to_time: VisibleTimeRangeBoundary::INFINITE, + }; +} diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index 41769667124e..d9dd3d71402a 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -587,7 +587,7 @@ fn code_for_struct( if obj.is_delegating_component() { let delegate = obj.delegate_datatype(objects).unwrap(); let scope = match delegate.scope() { - Some(scope) => format!("{scope}."), + Some(scope) => format!("{scope}_"), None => String::new(), }; superclasses.push(format!( diff --git a/crates/re_types_core/src/datatypes/.gitattributes b/crates/re_types_core/src/datatypes/.gitattributes index 5d1c22973176..8d8025b30391 100644 --- a/crates/re_types_core/src/datatypes/.gitattributes +++ b/crates/re_types_core/src/datatypes/.gitattributes @@ -4,6 +4,7 @@ entity_path.rs linguist-generated=true float32.rs linguist-generated=true mod.rs linguist-generated=true +time_int.rs linguist-generated=true uint32.rs linguist-generated=true uint64.rs linguist-generated=true utf8.rs linguist-generated=true diff --git a/crates/re_types_core/src/datatypes/mod.rs b/crates/re_types_core/src/datatypes/mod.rs index dd64cf5f950c..b3afd8508146 100644 --- a/crates/re_types_core/src/datatypes/mod.rs +++ b/crates/re_types_core/src/datatypes/mod.rs @@ -2,6 +2,8 @@ mod entity_path; mod float32; +mod time_int; +mod time_int_ext; mod uint32; mod uint64; mod utf8; @@ -9,6 +11,7 @@ mod utf8_ext; pub use self::entity_path::EntityPath; pub use self::float32::Float32; +pub use self::time_int::TimeInt; pub use self::uint32::UInt32; pub use self::uint64::UInt64; pub use self::utf8::Utf8; diff --git a/crates/re_types_core/src/datatypes/time_int.rs b/crates/re_types_core/src/datatypes/time_int.rs new file mode 100644 index 000000000000..1f488806ca0d --- /dev/null +++ b/crates/re_types_core/src/datatypes/time_int.rs @@ -0,0 +1,131 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/datatypes/time_int.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use crate::external::arrow2; +use crate::ComponentName; +use crate::SerializationResult; +use crate::{ComponentBatch, MaybeOwnedComponentBatch}; +use crate::{DeserializationError, DeserializationResult}; + +/// **Datatype**: A 64-bit number describing either nanoseconds OR sequence numbers. +#[derive(Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct TimeInt(pub i64); + +impl crate::SizeBytes for TimeInt { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl From for TimeInt { + #[inline] + fn from(value: i64) -> Self { + Self(value) + } +} + +impl From for i64 { + #[inline] + fn from(value: TimeInt) -> Self { + value.0 + } +} + +crate::macros::impl_into_cow!(TimeInt); + +impl crate::Loggable for TimeInt { + type Name = crate::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.datatypes.TimeInt".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Int64 + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use crate::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data0): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + let datum = datum.map(|datum| { + let Self(data0) = datum.into_owned(); + data0 + }); + (datum.is_some(), datum) + }) + .unzip(); + let data0_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + PrimitiveArray::new( + Self::arrow_datatype(), + data0.into_iter().map(|v| v.unwrap_or_default()).collect(), + data0_bitmap, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use crate::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok(arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.TimeInt#value")? + .into_iter() + .map(|opt| opt.copied()) + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.datatypes.TimeInt#value") + .with_context("rerun.datatypes.TimeInt")?) + } +} diff --git a/crates/re_types_core/src/datatypes/time_int_ext.rs b/crates/re_types_core/src/datatypes/time_int_ext.rs new file mode 100644 index 000000000000..511f0efc2676 --- /dev/null +++ b/crates/re_types_core/src/datatypes/time_int_ext.rs @@ -0,0 +1,6 @@ +use super::TimeInt; + +impl TimeInt { + pub const MIN: Self = Self(i64::MIN); + pub const MAX: Self = Self(i64::MAX); +} diff --git a/crates/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/re_viewer/src/blueprint/validation_gen/mod.rs index e33d2eb05e11..032557e39f0a 100644 --- a/crates/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/re_viewer/src/blueprint/validation_gen/mod.rs @@ -15,6 +15,7 @@ pub use re_types::blueprint::components::SpaceViewClass; pub use re_types::blueprint::components::SpaceViewOrigin; pub use re_types::blueprint::components::ViewerRecommendationHash; pub use re_types::blueprint::components::Visible; +pub use re_types::blueprint::components::VisibleTimeRange; pub use re_viewport::blueprint::components::AutoLayout; pub use re_viewport::blueprint::components::AutoSpaceViews; pub use re_viewport::blueprint::components::ContainerKind; @@ -48,4 +49,5 @@ pub fn is_valid_blueprint(blueprint: &EntityDb) -> bool { && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) + && validate_component::(blueprint) } diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 7368804694ba..9dd09ffad9e8 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -26,9 +26,9 @@ use re_viewport::{ }; use crate::ui::override_ui::override_ui; -use crate::ui::{override_ui::override_visualizer_ui, visible_history::visible_history_ui}; +use crate::ui::override_ui::override_visualizer_ui; -use super::selection_history_ui::SelectionHistoryUi; +use super::{selection_history_ui::SelectionHistoryUi, visible_history::visual_time_range_ui}; // --- @@ -837,34 +837,42 @@ fn blueprint_ui_for_space_view( ui.add_space(ui.spacing().item_spacing.y / 2.0); if let Some(space_view) = viewport.blueprint.space_view(space_view_id) { - let space_view_class = *space_view.class_identifier(); + let class_identifier = *space_view.class_identifier(); let space_view_state = viewport.state.space_view_state_mut( ctx.space_view_class_registry, space_view.id, - space_view.class_identifier(), + &class_identifier, ); // Space View don't inherit properties. let root_data_result = space_view.root_data_result(ctx.store_context, ctx.blueprint_query); - let mut props = root_data_result - .individual_properties() - .cloned() - .unwrap_or_default(); + let query_result = ctx.lookup_query_result(space_view.id); + let Some(data_result) = query_result + .tree + .root_handle() + .and_then(|root| query_result.tree.lookup_result(root)) + else { + re_log::error!("Could not find root data result for Space View {space_view_id:?}"); + return; + }; - visible_history_ui( + visual_time_range_ui( ctx, ui, - &space_view_class, + &query_result.tree, + data_result, + class_identifier, true, - None, - &mut props.visible_history, - &root_data_result.accumulated_properties().visible_history, ); - let space_view_class = space_view.class(ctx.space_view_class_registry); + let mut props = root_data_result + .individual_properties() + .cloned() + .unwrap_or_default(); + let space_view_class = space_view.class(ctx.space_view_class_registry); if let Err(err) = space_view_class.selection_ui( ctx, ui, @@ -880,7 +888,7 @@ fn blueprint_ui_for_space_view( ); } - root_data_result.save_individual_override(Some(props), ctx); + root_data_result.save_individual_override_properties(ctx, Some(props)); } } @@ -915,9 +923,8 @@ fn blueprint_ui_for_data_result( &space_view_class, entity_path, &mut props, - data_result.accumulated_properties(), ); - data_result.save_individual_override(Some(props), ctx); + data_result.save_individual_override_properties(ctx, Some(props)); } } } @@ -1073,7 +1080,6 @@ fn entity_props_ui( space_view_class: &SpaceViewClassIdentifier, entity_path: &EntityPath, entity_props: &mut EntityProperties, - resolved_entity_props: &EntityProperties, ) { use re_types::blueprint::components::Visible; use re_types::Loggable as _; @@ -1112,14 +1118,13 @@ fn entity_props_ui( .checkbox(ui, &mut entity_props.interactive, "Interactive") .on_hover_text("If disabled, the entity will not react to any mouse interaction"); - visible_history_ui( + visual_time_range_ui( ctx, ui, - space_view_class, + &query_result.tree, + data_result, + *space_view_class, false, - Some(entity_path), - &mut entity_props.visible_history, - &resolved_entity_props.visible_history, ); egui::Grid::new("entity_properties") diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index 831f2f4fd4ee..f223f3eca65d 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -3,11 +3,16 @@ use std::ops::RangeInclusive; use egui::{NumExt as _, Response, Ui}; -use re_entity_db::{ExtraQueryHistory, TimeHistogram, VisibleHistory, VisibleHistoryBoundary}; +use re_entity_db::{TimeHistogram, VisibleHistory, VisibleHistoryBoundary}; use re_log_types::{EntityPath, TimeType, TimeZone}; +use re_space_view::{ + default_time_range, time_range_boundary_to_visible_history_boundary, + visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, +}; use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D}; use re_space_view_time_series::TimeSeriesSpaceView; -use re_types_core::ComponentName; +use re_types::blueprint::components::VisibleTimeRange; +use re_types_core::{ComponentName, Loggable as _}; use re_ui::{markdown_ui, ReUi}; use re_viewer_context::{SpaceViewClass, SpaceViewClassIdentifier, TimeControl, ViewerContext}; @@ -44,45 +49,37 @@ static VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES: once_cell::sync::Lazy bool { + VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS.contains(&space_view_class) +} + +fn entity_with_visible_history( ctx: &ViewerContext<'_>, time_ctrl: &TimeControl, - space_view_class: &SpaceViewClassIdentifier, - entity_path: Option<&EntityPath>, + entity_path: &EntityPath, ) -> bool { - if !VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS.contains(space_view_class) { - return false; - } - - if let Some(entity_path) = entity_path { - let store = ctx.entity_db.store(); - let component_names = store.all_components(time_ctrl.timeline(), entity_path); - if let Some(component_names) = component_names { - if !component_names - .iter() - .any(|name| VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES.contains(name)) - { - return false; - } - } else { - return false; - } - } - - true + let store = ctx.entity_db.store(); + let component_names = store.all_components(time_ctrl.timeline(), entity_path); + component_names + .iter() + .flatten() + .any(|name| VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES.contains(name)) } -pub fn visible_history_ui( +pub fn visual_time_range_ui( ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - space_view_class: &SpaceViewClassIdentifier, + ui: &mut Ui, + data_result_tree: &re_viewer_context::DataResultTree, + data_result: &re_viewer_context::DataResult, + space_view_class: SpaceViewClassIdentifier, is_space_view: bool, - entity_path: Option<&EntityPath>, - visible_history_prop: &mut ExtraQueryHistory, - resolved_visible_history_prop: &ExtraQueryHistory, ) { let time_ctrl = ctx.rec_cfg.time_ctrl.read().clone(); - if !has_visible_history(ctx, &time_ctrl, space_view_class, entity_path) { + + if is_space_view && !space_view_with_visible_history(space_view_class) { + return; + } + if !is_space_view && !entity_with_visible_history(ctx, &time_ctrl, &data_result.entity_path) { return; } @@ -92,24 +89,33 @@ pub fn visible_history_ui( let mut interacting_with_controls = false; + let mut resolved_range = data_result + .lookup_override::(ctx) + .unwrap_or(default_time_range(space_view_class)); + let mut has_individual_range = data_result + .component_override_source(data_result_tree, &VisibleTimeRange::name()) + .as_ref() + == Some(&data_result.entity_path); + let collapsing_response = re_ui.collapsing_header(ui, "Visible time range", false, |ui| { + let has_individual_range_before = has_individual_range; + let resolved_range_before = resolved_range.clone(); + ui.horizontal(|ui| { re_ui - .radio_value(ui, &mut visible_history_prop.enabled, false, "Default") + .radio_value(ui, &mut has_individual_range, false, "Default") .on_hover_text(if is_space_view { "Default visible time range settings for this kind of Space View" } else { - "Visible time range settings inherited from parent Group(s) or enclosing \ + "Visible time range settings inherited from parent Entity or enclosing \ Space View" }); re_ui - .radio_value(ui, &mut visible_history_prop.enabled, true, "Override") + .radio_value(ui, &mut has_individual_range, true, "Override") .on_hover_text(if is_space_view { "Set visible time range settings for the contents of this Space View" - } else if entity_path.is_some() { - "Set visible time range settings for this entity" } else { - "Set visible time range settings for he contents of this Group" + "Set visible time range settings for this entity" }); }); @@ -125,22 +131,29 @@ pub fn visible_history_ui( .unwrap_or_default() .at_least(*timeline_spec.range.start()); // accounts for timeless time (TimeInt::BEGINNING) - let (resolved_visible_history, visible_history) = match time_type { + // pick right from/to depending on the timeline type. + let (from, to) = match time_type { TimeType::Time => ( - &resolved_visible_history_prop.nanos, - &mut visible_history_prop.nanos, + &mut resolved_range.0.from_time, + &mut resolved_range.0.to_time, ), TimeType::Sequence => ( - &resolved_visible_history_prop.sequences, - &mut visible_history_prop.sequences, + &mut resolved_range.0.from_sequence, + &mut resolved_range.0.to_sequence, ), }; - if visible_history_prop.enabled { - let current_low_boundary = visible_history + // Convert to legacy visual history type. + let mut visible_history = VisibleHistory { + from: time_range_boundary_to_visible_history_boundary(from), + to: time_range_boundary_to_visible_history_boundary(to), + }; + + if has_individual_range { + let current_from = visible_history .range_start_from_cursor(current_time.into()) .as_i64(); - let current_high_boundary = visible_history + let current_to = visible_history .range_end_from_cursor(current_time.into()) .as_i64(); @@ -156,7 +169,7 @@ pub fn visible_history_ui( current_time, &timeline_spec, true, - current_high_boundary, + current_to, ) }) .inner; @@ -173,23 +186,23 @@ pub fn visible_history_ui( current_time, &timeline_spec, false, - current_low_boundary, + current_from, ) }) .inner; ui.end_row(); }); - current_range_ui(ctx, ui, current_time, time_type, visible_history); + current_range_ui(ctx, ui, current_time, time_type, &visible_history); } else { // Show the resolved visible range as labels (user can't edit them): - if resolved_visible_history.from == VisibleHistoryBoundary::Infinite - && resolved_visible_history.to == VisibleHistoryBoundary::Infinite + if visible_history.from == VisibleHistoryBoundary::Infinite + && visible_history.to == VisibleHistoryBoundary::Infinite { ui.label("Entire timeline"); - } else if resolved_visible_history.from == VisibleHistoryBoundary::AT_CURSOR - && resolved_visible_history.to == VisibleHistoryBoundary::AT_CURSOR + } else if visible_history.from == VisibleHistoryBoundary::AT_CURSOR + && visible_history.to == VisibleHistoryBoundary::AT_CURSOR { let current_time = time_type.format(current_time.into(), ctx.app_options.time_zone); match time_type { @@ -206,7 +219,7 @@ pub fn visible_history_ui( resolved_visible_history_boundary_ui( ctx, ui, - &resolved_visible_history.from, + &visible_history.from, time_type, true, ); @@ -216,14 +229,31 @@ pub fn visible_history_ui( resolved_visible_history_boundary_ui( ctx, ui, - &resolved_visible_history.to, + &visible_history.to, time_type, false, ); ui.end_row(); }); - current_range_ui(ctx, ui, current_time, time_type, resolved_visible_history); + current_range_ui(ctx, ui, current_time, time_type, &visible_history); + } + } + + // Convert back from visual history type. + *from = visible_history_boundary_to_time_range_boundary(&visible_history.from); + *to = visible_history_boundary_to_time_range_boundary(&visible_history.to); + + // Save to blueprint store if anything has changed. + if has_individual_range != has_individual_range_before + || resolved_range != resolved_range_before + { + if has_individual_range { + re_log::debug!("override!"); + data_result.save_recursive_override(ctx, &resolved_range); + } else { + re_log::debug!("clear!"); + data_result.clear_recursive_override::(ctx); } } }); @@ -251,22 +281,15 @@ pub fn visible_history_ui( if should_display_visible_history { if let Some(current_time) = time_ctrl.time_int() { - let visible_history = match (visible_history_prop.enabled, time_type) { - (true, TimeType::Sequence) => visible_history_prop.sequences, - (true, TimeType::Time) => visible_history_prop.nanos, - (false, TimeType::Sequence) => resolved_visible_history_prop.sequences, - (false, TimeType::Time) => resolved_visible_history_prop.nanos, - }; - - ctx.rec_cfg.time_ctrl.write().highlighted_range = - Some(visible_history.time_range(current_time)); + let range = visible_time_range_to_time_range(&resolved_range, time_type, current_time); + ctx.rec_cfg.time_ctrl.write().highlighted_range = Some(range); } } let markdown = format!("# Visible time range\n This feature controls the time range used to display data in the Space View. -The settings are inherited from parent Group(s) or enclosing Space View if not overridden. +The settings are inherited from the parent Entity or enclosing Space View if not overridden. Visible time range properties are stored separately for each _type_ of timelines. They may differ depending on \ whether the current timeline is temporal or a sequence. The current settings apply to all _{}_ timelines. diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 9847cc516536..24a2ebcd15ad 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -171,17 +171,57 @@ impl DataResult { } } + /// Saves a recursive override, does not take into current or default values. + /// + /// Ignores individual overrides and current value. + pub fn save_recursive_override( + &self, + ctx: &ViewerContext<'_>, + desired_override: &C, + ) { + re_tracing::profile_function!(); + + // TODO(jleibs): Make it impossible for this to happen with different type structure + // This should never happen unless we're doing something with a partially processed + // query. + let Some(recursive_override_path) = self.recursive_override_path() else { + re_log::warn!( + "Tried to save override for {:?} but it has no override path", + self.entity_path + ); + return; + }; + + ctx.save_blueprint_component(recursive_override_path, desired_override); + } + + /// Clears the recursive override for a given component + pub fn clear_recursive_override(&self, ctx: &ViewerContext<'_>) { + // TODO(jleibs): Make it impossible for this to happen with different type structure + // This should never happen unless we're doing something with a partially processed + // query. + let Some(recursive_override_path) = self.recursive_override_path() else { + re_log::warn!( + "Tried to save override for {:?} but it has no override path", + self.entity_path + ); + return; + }; + + ctx.save_empty_blueprint_component::(recursive_override_path); + } + /// Write the [`EntityProperties`] for this result back to the Blueprint store on the recursive override. /// /// Setting `new_recursive_props` to `None` will always clear the override. /// Otherwise, writes only if the recursive properties aren't already the same value. /// (does *not* take into account what the accumulated properties are which are a combination of recursive and individual overwrites) - pub fn save_recursive_override( + pub fn save_recursive_override_properties( &self, ctx: &ViewerContext<'_>, new_recursive_props: Option, ) { - self.save_override_internal( + self.save_override_properties_internal( ctx, new_recursive_props, self.recursive_override_path(), @@ -194,12 +234,12 @@ impl DataResult { /// Setting `new_individual_props` to `None` will always clear the override. /// Otherwise, writes only if the individual properties aren't already the same value. /// (does *not* take into account what the accumulated properties are which are a combination of recursive and individual overwrites) - pub fn save_individual_override( + pub fn save_individual_override_properties( &self, - new_individual_props: Option, ctx: &ViewerContext<'_>, + new_individual_props: Option, ) { - self.save_override_internal( + self.save_override_properties_internal( ctx, new_individual_props, self.individual_override_path(), @@ -207,7 +247,7 @@ impl DataResult { ); } - fn save_override_internal( + fn save_override_properties_internal( &self, ctx: &ViewerContext<'_>, new_individual_props: Option, diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index 57ab7ca7b854..95daf97ca8f7 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -29,6 +29,7 @@ Data types are the lowest layer of the data model hierarchy * [`TensorBuffer`](datatypes/tensor_buffer.md) * [`TensorData`](datatypes/tensor_data.md) * [`TensorDimension`](datatypes/tensor_dimension.md) +* [`TimeInt`](datatypes/time_int.md) * [`Transform3D`](datatypes/transform3d.md) * [`TranslationAndMat3x3`](datatypes/translation_and_mat3x3.md) * [`TranslationRotationScale3D`](datatypes/translation_rotation_scale3d.md) diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index 6e766a712369..1ef35ab8e55a 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -23,6 +23,7 @@ scale3d.md linguist-generated=true tensor_buffer.md linguist-generated=true tensor_data.md linguist-generated=true tensor_dimension.md linguist-generated=true +time_int.md linguist-generated=true transform3d.md linguist-generated=true translation_and_mat3x3.md linguist-generated=true translation_rotation_scale3d.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/time_int.md b/docs/content/reference/types/datatypes/time_int.md new file mode 100644 index 000000000000..de6030538958 --- /dev/null +++ b/docs/content/reference/types/datatypes/time_int.md @@ -0,0 +1,16 @@ +--- +title: "TimeInt" +--- + +A 64-bit number describing either nanoseconds OR sequence numbers. + +## Fields + +* value: `i64` + +## Links + * 🌊 [C++ API docs for `TimeInt`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TimeInt.html?speculative-link) + * 🐍 [Python API docs for `TimeInt`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.TimeInt) + * 🦀 [Rust API docs for `TimeInt`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TimeInt.html?speculative-link) + + diff --git a/rerun_cpp/src/rerun/blueprint/.gitattributes b/rerun_cpp/src/rerun/blueprint/.gitattributes index 0661cd67c5ea..435e1f8fe40d 100644 --- a/rerun_cpp/src/rerun/blueprint/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/.gitattributes @@ -3,3 +3,4 @@ .gitattributes linguist-generated=true archetypes.hpp linguist-generated=true components.hpp linguist-generated=true +datatypes.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index fc45185e5696..715845efe9dd 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -23,3 +23,4 @@ #include "blueprint/components/space_view_origin.hpp" #include "blueprint/components/viewer_recommendation_hash.hpp" #include "blueprint/components/visible.hpp" +#include "blueprint/components/visible_time_range.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index c013fc7cd820..7b4380fbe687 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -33,3 +33,4 @@ space_view_origin.hpp linguist-generated=true viewer_recommendation_hash.hpp linguist-generated=true visible.cpp linguist-generated=true visible.hpp linguist-generated=true +visible_time_range.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp b/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp new file mode 100644 index 000000000000..f55840689b09 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp @@ -0,0 +1,60 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs". + +#pragma once + +#include "../../blueprint/datatypes/visible_time_range.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: The range of values that will be included in a Space View query. + struct VisibleTimeRange { + rerun::blueprint::datatypes::VisibleTimeRange value; + + public: + VisibleTimeRange() = default; + + VisibleTimeRange(rerun::blueprint::datatypes::VisibleTimeRange value_) : value(value_) {} + + VisibleTimeRange& operator=(rerun::blueprint::datatypes::VisibleTimeRange value_) { + value = value_; + return *this; + } + + /// Cast to the underlying VisibleTimeRange datatype + operator rerun::blueprint::datatypes::VisibleTimeRange() const { + return value; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert( + sizeof(rerun::blueprint::datatypes::VisibleTimeRange) == + sizeof(blueprint::components::VisibleTimeRange) + ); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.VisibleTimeRange"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::blueprint:: components::VisibleTimeRange` into an arrow array. + static Result> to_arrow( + const blueprint::components::VisibleTimeRange* instances, size_t num_instances + ) { + return Loggable::to_arrow( + &instances->value, + num_instances + ); + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes.hpp b/rerun_cpp/src/rerun/blueprint/datatypes.hpp new file mode 100644 index 000000000000..361e00061d0e --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes.hpp @@ -0,0 +1,7 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs + +#pragma once + +#include "blueprint/datatypes/visible_time_range.hpp" +#include "blueprint/datatypes/visible_time_range_boundary.hpp" +#include "blueprint/datatypes/visible_time_range_boundary_kind.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes index da03d4b96e87..06328369afaa 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes @@ -1,5 +1,9 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -legend.cpp linguist-generated=true -legend.hpp linguist-generated=true +visible_time_range.cpp linguist-generated=true +visible_time_range.hpp linguist-generated=true +visible_time_range_boundary.cpp linguist-generated=true +visible_time_range_boundary.hpp linguist-generated=true +visible_time_range_boundary_kind.cpp linguist-generated=true +visible_time_range_boundary_kind.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/legend.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/legend.cpp deleted file mode 100644 index 948dd620e8bc..000000000000 --- a/rerun_cpp/src/rerun/blueprint/datatypes/legend.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/legend.fbs". - -#include "legend.hpp" - -#include -#include - -namespace rerun::blueprint::datatypes {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype( - ) { - static const auto datatype = arrow::struct_({ - arrow::field("visible", arrow::boolean(), false), - arrow::field("location", arrow::uint8(), true), - }); - return datatype; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const blueprint::datatypes::Legend* elements, - size_t num_elements - ) { - if (builder == nullptr) { - return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); - } - if (elements == nullptr) { - return rerun::Error( - ErrorCode::UnexpectedNullArgument, - "Cannot serialize null pointer to arrow array." - ); - } - - { - auto field_builder = static_cast(builder->field_builder(0)); - ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - ARROW_RETURN_NOT_OK(field_builder->Append(elements[elem_idx].visible)); - } - } - { - auto field_builder = static_cast(builder->field_builder(1)); - ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - const auto& element = elements[elem_idx]; - if (element.location.has_value()) { - ARROW_RETURN_NOT_OK(field_builder->Append(element.location.value())); - } else { - ARROW_RETURN_NOT_OK(field_builder->AppendNull()); - } - } - } - ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); - - return Error::ok(); - } - - Result> Loggable::to_arrow( - const blueprint::datatypes::Legend* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp new file mode 100644 index 000000000000..36f9e1bdaa5b --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp @@ -0,0 +1,124 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +#include "visible_time_range.hpp" + +#include "visible_time_range_boundary.hpp" + +#include +#include + +namespace rerun::blueprint::datatypes {} + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = arrow::struct_({ + arrow::field( + "from_sequence", + Loggable::arrow_datatype(), + false + ), + arrow::field( + "to_sequence", + Loggable::arrow_datatype(), + false + ), + arrow::field( + "from_time", + Loggable::arrow_datatype(), + false + ), + arrow::field( + "to_time", + Loggable::arrow_datatype(), + false + ), + }); + return datatype; + } + + Result> + Loggable::to_arrow( + const blueprint::datatypes::VisibleTimeRange* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK( + Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + ) + ); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const blueprint::datatypes::VisibleTimeRange* elements, + size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + { + auto field_builder = static_cast(builder->field_builder(0)); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK(Loggable:: + fill_arrow_array_builder( + field_builder, + &elements[elem_idx].from_sequence, + 1 + )); + } + } + { + auto field_builder = static_cast(builder->field_builder(1)); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK( + Loggable:: + fill_arrow_array_builder(field_builder, &elements[elem_idx].to_sequence, 1) + ); + } + } + { + auto field_builder = static_cast(builder->field_builder(2)); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK( + Loggable:: + fill_arrow_array_builder(field_builder, &elements[elem_idx].from_time, 1) + ); + } + } + { + auto field_builder = static_cast(builder->field_builder(3)); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK( + Loggable:: + fill_arrow_array_builder(field_builder, &elements[elem_idx].to_time, 1) + ); + } + } + ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp new file mode 100644 index 000000000000..6a0dc250edf7 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp @@ -0,0 +1,61 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +#pragma once + +#include "../../result.hpp" +#include "visible_time_range_boundary.hpp" + +#include +#include + +namespace arrow { + class Array; + class DataType; + class StructBuilder; +} // namespace arrow + +namespace rerun::blueprint::datatypes { + /// **Datatype**: Visible time range bounds. + struct VisibleTimeRange { + /// Low time boundary for sequence timeline. + rerun::blueprint::datatypes::VisibleTimeRangeBoundary from_sequence; + + /// High time boundary for sequence timeline. + rerun::blueprint::datatypes::VisibleTimeRangeBoundary to_sequence; + + /// Low time boundary for time timeline. + rerun::blueprint::datatypes::VisibleTimeRangeBoundary from_time; + + /// High time boundary for time timeline. + rerun::blueprint::datatypes::VisibleTimeRangeBoundary to_time; + + public: + VisibleTimeRange() = default; + }; +} // namespace rerun::blueprint::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.datatypes.VisibleTimeRange"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRange` into an arrow array. + static Result> to_arrow( + const blueprint::datatypes::VisibleTimeRange* instances, size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::StructBuilder* builder, const blueprint::datatypes::VisibleTimeRange* elements, + size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp new file mode 100644 index 000000000000..6e4820a69c1f --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp @@ -0,0 +1,91 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +#include "visible_time_range_boundary.hpp" + +#include "../../datatypes/time_int.hpp" +#include "visible_time_range_boundary_kind.hpp" + +#include +#include + +namespace rerun::blueprint::datatypes {} + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = arrow::struct_({ + arrow::field( + "kind", + Loggable::arrow_datatype( + ), + false + ), + arrow::field("time", Loggable::arrow_datatype(), false), + }); + return datatype; + } + + Result> + Loggable::to_arrow( + const blueprint::datatypes::VisibleTimeRangeBoundary* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK( + Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + ) + ); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, + const blueprint::datatypes::VisibleTimeRangeBoundary* elements, size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + { + auto field_builder = static_cast(builder->field_builder(0)); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK( + Loggable:: + fill_arrow_array_builder(field_builder, &elements[elem_idx].kind, 1) + ); + } + } + { + auto field_builder = static_cast(builder->field_builder(1)); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + field_builder, + &elements[elem_idx].time, + 1 + )); + } + } + ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/legend.hpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp similarity index 55% rename from rerun_cpp/src/rerun/blueprint/datatypes/legend.hpp rename to rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp index b8efd53df620..317bf804ec91 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/legend.hpp +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp @@ -1,13 +1,14 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/legend.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". #pragma once +#include "../../datatypes/time_int.hpp" #include "../../result.hpp" +#include "visible_time_range_boundary_kind.hpp" #include #include -#include namespace arrow { class Array; @@ -16,22 +17,16 @@ namespace arrow { } // namespace arrow namespace rerun::blueprint::datatypes { - /// **Datatype**: Configuration for the legend of a plot. - struct Legend { - /// Whether or not the legend should be displayed. - bool visible; - - /// Where should the legend be located. - /// - /// Allowed values: - /// - LeftTop = 1, - /// - RightTop = 2, - /// - LeftBottom = 3, - /// - RightBottom = 4 - std::optional location; + /// **Datatype**: Type of boundary for visible history. + struct VisibleTimeRangeBoundary { + /// Type of the boundary. + rerun::blueprint::datatypes::VisibleTimeRangeBoundaryKind kind; + + /// Value of the boundary (ignored for `Infinite` type). + rerun::datatypes::TimeInt time; public: - Legend() = default; + VisibleTimeRangeBoundary() = default; }; } // namespace rerun::blueprint::datatypes @@ -41,21 +36,21 @@ namespace rerun { /// \private template <> - struct Loggable { - static constexpr const char Name[] = "rerun.blueprint.datatypes.Legend"; + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.datatypes.VisibleTimeRangeBoundary"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const blueprint::datatypes::Legend* elements, - size_t num_elements + /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRangeBoundary` into an arrow array. + static Result> to_arrow( + const blueprint::datatypes::VisibleTimeRangeBoundary* instances, size_t num_instances ); - /// Serializes an array of `rerun::blueprint:: datatypes::Legend` into an arrow array. - static Result> to_arrow( - const blueprint::datatypes::Legend* instances, size_t num_instances + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::StructBuilder* builder, + const blueprint::datatypes::VisibleTimeRangeBoundary* elements, size_t num_elements ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp new file mode 100644 index 000000000000..08a67a5061bf --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp @@ -0,0 +1,67 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +#include "visible_time_range_boundary_kind.hpp" + +#include +#include + +namespace rerun { + const std::shared_ptr& + Loggable::arrow_datatype() { + static const auto datatype = arrow::sparse_union({ + arrow::field("_null_markers", arrow::null(), true, nullptr), + arrow::field("RelativeToTimeCursor", arrow::null(), true), + arrow::field("Absolute", arrow::null(), true), + arrow::field("Infinite", arrow::null(), true), + }); + return datatype; + } + + Result> + Loggable::to_arrow( + const blueprint::datatypes::VisibleTimeRangeBoundaryKind* instances, + size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable:: + fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + + rerun::Error + Loggable::fill_arrow_array_builder( + arrow::SparseUnionBuilder* builder, + const blueprint::datatypes::VisibleTimeRangeBoundaryKind* elements, size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + ARROW_RETURN_NOT_OK(builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + const auto variant = elements[elem_idx]; + ARROW_RETURN_NOT_OK(builder->Append(static_cast(variant))); + } + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp new file mode 100644 index 000000000000..59025d01da86 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp @@ -0,0 +1,57 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +#pragma once + +#include "../../result.hpp" + +#include +#include + +namespace arrow { + class Array; + class DataType; + class SparseUnionBuilder; +} // namespace arrow + +namespace rerun::blueprint::datatypes { + /// **Datatype**: Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. + enum class VisibleTimeRangeBoundaryKind : uint8_t { + + /// Boundary is a value relative to the time cursor. + RelativeToTimeCursor = 1, + + /// Boundary is an absolute value. + Absolute = 2, + + /// The boundary extends to infinity. + Infinite = 3, + }; +} // namespace rerun::blueprint::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = + "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRangeBoundaryKind` into an arrow array. + static Result> to_arrow( + const blueprint::datatypes::VisibleTimeRangeBoundaryKind* instances, + size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::SparseUnionBuilder* builder, + const blueprint::datatypes::VisibleTimeRangeBoundaryKind* elements, size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 7f33e559abe9..81c850bdde6f 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -24,6 +24,7 @@ #include "datatypes/tensor_buffer.hpp" #include "datatypes/tensor_data.hpp" #include "datatypes/tensor_dimension.hpp" +#include "datatypes/time_int.hpp" #include "datatypes/transform3d.hpp" #include "datatypes/translation_and_mat3x3.hpp" #include "datatypes/translation_rotation_scale3d.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 5c61073231da..83fde1441f4b 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -45,6 +45,8 @@ tensor_data.cpp linguist-generated=true tensor_data.hpp linguist-generated=true tensor_dimension.cpp linguist-generated=true tensor_dimension.hpp linguist-generated=true +time_int.cpp linguist-generated=true +time_int.hpp linguist-generated=true transform3d.cpp linguist-generated=true transform3d.hpp linguist-generated=true translation_and_mat3x3.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/datatypes/time_int.cpp b/rerun_cpp/src/rerun/datatypes/time_int.cpp new file mode 100644 index 000000000000..7b368b716fcd --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/time_int.cpp @@ -0,0 +1,57 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/datatypes/time_int.fbs". + +#include "time_int.hpp" + +#include +#include + +namespace rerun::datatypes {} + +namespace rerun { + const std::shared_ptr& Loggable::arrow_datatype() { + static const auto datatype = arrow::int64(); + return datatype; + } + + Result> Loggable::to_arrow( + const datatypes::TimeInt* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::Int64Builder* builder, const datatypes::TimeInt* elements, size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + static_assert(sizeof(*elements) == sizeof(elements->value)); + ARROW_RETURN_NOT_OK( + builder->AppendValues(&elements->value, static_cast(num_elements)) + ); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/time_int.hpp b/rerun_cpp/src/rerun/datatypes/time_int.hpp new file mode 100644 index 000000000000..75b090690811 --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/time_int.hpp @@ -0,0 +1,61 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/datatypes/time_int.fbs". + +#pragma once + +#include "../result.hpp" + +#include +#include + +namespace arrow { + /// \private + template + class NumericBuilder; + + class Array; + class DataType; + class Int64Type; + using Int64Builder = NumericBuilder; +} // namespace arrow + +namespace rerun::datatypes { + /// **Datatype**: A 64-bit number describing either nanoseconds OR sequence numbers. + struct TimeInt { + int64_t value; + + public: + TimeInt() = default; + + TimeInt(int64_t value_) : value(value_) {} + + TimeInt& operator=(int64_t value_) { + value = value_; + return *this; + } + }; +} // namespace rerun::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.TimeInt"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::datatypes::TimeInt` into an arrow array. + static Result> to_arrow( + const datatypes::TimeInt* instances, size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::Int64Builder* builder, const datatypes::TimeInt* elements, size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index 2ad52015791a..a8e9e72f9c7e 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -23,3 +23,4 @@ space_view_maximized.py linguist-generated=true space_view_origin.py linguist-generated=true viewer_recommendation_hash.py linguist-generated=true visible.py linguist-generated=true +visible_time_range.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index 94f3b1e26008..1dbd8f8d98c3 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -57,6 +57,7 @@ ViewerRecommendationHashType, ) from .visible import Visible, VisibleArrayLike, VisibleBatch, VisibleLike, VisibleType +from .visible_time_range import VisibleTimeRange, VisibleTimeRangeBatch, VisibleTimeRangeType __all__ = [ "ActiveTab", @@ -143,5 +144,8 @@ "VisibleArrayLike", "VisibleBatch", "VisibleLike", + "VisibleTimeRange", + "VisibleTimeRangeBatch", + "VisibleTimeRangeType", "VisibleType", ] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py new file mode 100644 index 000000000000..7ffed4d09f56 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py @@ -0,0 +1,28 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeExt" class in "visible_time_range_ext.py". + +from __future__ import annotations + +from ..._baseclasses import ComponentBatchMixin +from ...blueprint import datatypes as blueprint_datatypes + +__all__ = ["VisibleTimeRange", "VisibleTimeRangeBatch", "VisibleTimeRangeType"] + + +class VisibleTimeRange(blueprint_datatypes.VisibleTimeRange): + """**Component**: The range of values that will be included in a Space View query.""" + + # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py + + # Note: there are no fields here because VisibleTimeRange delegates to datatypes.VisibleTimeRange + pass + + +class VisibleTimeRangeType(blueprint_datatypes.VisibleTimeRangeType): + _TYPE_NAME: str = "rerun.blueprint.components.VisibleTimeRange" + + +class VisibleTimeRangeBatch(blueprint_datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): + _ARROW_TYPE = VisibleTimeRangeType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes index d7d100d86518..5f25eb77dacd 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes @@ -2,4 +2,6 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true -legend.py linguist-generated=true +visible_time_range.py linguist-generated=true +visible_time_range_boundary.py linguist-generated=true +visible_time_range_boundary_kind.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py index e18ca0758275..cfcebd2abc65 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py @@ -1,7 +1,43 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python.rs +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs from __future__ import annotations -from .legend import Legend, LegendArrayLike, LegendBatch, LegendLike, LegendType +from .visible_time_range import ( + VisibleTimeRange, + VisibleTimeRangeArrayLike, + VisibleTimeRangeBatch, + VisibleTimeRangeLike, + VisibleTimeRangeType, +) +from .visible_time_range_boundary import ( + VisibleTimeRangeBoundary, + VisibleTimeRangeBoundaryArrayLike, + VisibleTimeRangeBoundaryBatch, + VisibleTimeRangeBoundaryLike, + VisibleTimeRangeBoundaryType, +) +from .visible_time_range_boundary_kind import ( + VisibleTimeRangeBoundaryKind, + VisibleTimeRangeBoundaryKindArrayLike, + VisibleTimeRangeBoundaryKindBatch, + VisibleTimeRangeBoundaryKindLike, + VisibleTimeRangeBoundaryKindType, +) -__all__ = ["Legend", "LegendArrayLike", "LegendBatch", "LegendLike", "LegendType"] +__all__ = [ + "VisibleTimeRange", + "VisibleTimeRangeArrayLike", + "VisibleTimeRangeBatch", + "VisibleTimeRangeBoundary", + "VisibleTimeRangeBoundaryArrayLike", + "VisibleTimeRangeBoundaryBatch", + "VisibleTimeRangeBoundaryKind", + "VisibleTimeRangeBoundaryKindArrayLike", + "VisibleTimeRangeBoundaryKindBatch", + "VisibleTimeRangeBoundaryKindLike", + "VisibleTimeRangeBoundaryKindType", + "VisibleTimeRangeBoundaryLike", + "VisibleTimeRangeBoundaryType", + "VisibleTimeRangeLike", + "VisibleTimeRangeType", +] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/legend.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/legend.py deleted file mode 100644 index 3c462c99938f..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/legend.py +++ /dev/null @@ -1,92 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python.rs -# Based on "crates/re_types/definitions/rerun/blueprint/datatypes/legend.fbs". - -# You can extend this class by creating a "LegendExt" class in "legend_ext.py". - -from __future__ import annotations - -from typing import Any, Sequence, Union - -import pyarrow as pa -from attrs import define, field - -from ..._baseclasses import BaseBatch, BaseExtensionType -from ..._converters import ( - int_or_none, -) - -__all__ = ["Legend", "LegendArrayLike", "LegendBatch", "LegendLike", "LegendType"] - - -@define(init=False) -class Legend: - """**Datatype**: Configuration for the legend of a plot.""" - - def __init__(self: Any, visible: bool, location: int | None = None): - """ - Create a new instance of the Legend datatype. - - Parameters - ---------- - visible: - Whether or not the legend should be displayed. - location: - Where should the legend be located. - - Allowed values: - - LeftTop = 1, - - RightTop = 2, - - LeftBottom = 3, - - RightBottom = 4 - - """ - - # You can define your own __init__ function as a member of LegendExt in legend_ext.py - self.__attrs_init__(visible=visible, location=location) - - visible: bool = field(converter=bool) - # Whether or not the legend should be displayed. - # - # (Docstring intentionally commented out to hide this field from the docs) - - location: int | None = field(default=None, converter=int_or_none) - # Where should the legend be located. - # - # Allowed values: - # - LeftTop = 1, - # - RightTop = 2, - # - LeftBottom = 3, - # - RightBottom = 4 - # - # (Docstring intentionally commented out to hide this field from the docs) - - -LegendLike = Legend -LegendArrayLike = Union[ - Legend, - Sequence[LegendLike], -] - - -class LegendType(BaseExtensionType): - _TYPE_NAME: str = "rerun.blueprint.datatypes.Legend" - - def __init__(self) -> None: - pa.ExtensionType.__init__( - self, - pa.struct( - [ - pa.field("visible", pa.bool_(), nullable=False, metadata={}), - pa.field("location", pa.uint8(), nullable=True, metadata={}), - ] - ), - self._TYPE_NAME, - ) - - -class LegendBatch(BaseBatch[LegendArrayLike]): - _ARROW_TYPE = LegendType() - - @staticmethod - def _native_to_pa_array(data: LegendArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in legend_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py new file mode 100644 index 000000000000..735c720b7a47 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py @@ -0,0 +1,194 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeExt" class in "visible_time_range_ext.py". + +from __future__ import annotations + +from typing import Any, Sequence, Union + +import pyarrow as pa +from attrs import define, field + +from ..._baseclasses import BaseBatch, BaseExtensionType +from ...blueprint import datatypes as blueprint_datatypes + +__all__ = [ + "VisibleTimeRange", + "VisibleTimeRangeArrayLike", + "VisibleTimeRangeBatch", + "VisibleTimeRangeLike", + "VisibleTimeRangeType", +] + + +@define(init=False) +class VisibleTimeRange: + """**Datatype**: Visible time range bounds.""" + + def __init__( + self: Any, + from_sequence: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + to_sequence: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + from_time: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + to_time: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + ): + """ + Create a new instance of the VisibleTimeRange datatype. + + Parameters + ---------- + from_sequence: + Low time boundary for sequence timeline. + to_sequence: + High time boundary for sequence timeline. + from_time: + Low time boundary for time timeline. + to_time: + High time boundary for time timeline. + + """ + + # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py + self.__attrs_init__(from_sequence=from_sequence, to_sequence=to_sequence, from_time=from_time, to_time=to_time) + + from_sequence: blueprint_datatypes.VisibleTimeRangeBoundary = field() + # Low time boundary for sequence timeline. + # + # (Docstring intentionally commented out to hide this field from the docs) + + to_sequence: blueprint_datatypes.VisibleTimeRangeBoundary = field() + # High time boundary for sequence timeline. + # + # (Docstring intentionally commented out to hide this field from the docs) + + from_time: blueprint_datatypes.VisibleTimeRangeBoundary = field() + # Low time boundary for time timeline. + # + # (Docstring intentionally commented out to hide this field from the docs) + + to_time: blueprint_datatypes.VisibleTimeRangeBoundary = field() + # High time boundary for time timeline. + # + # (Docstring intentionally commented out to hide this field from the docs) + + +VisibleTimeRangeLike = VisibleTimeRange +VisibleTimeRangeArrayLike = Union[ + VisibleTimeRange, + Sequence[VisibleTimeRangeLike], +] + + +class VisibleTimeRangeType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRange" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.struct( + [ + pa.field( + "from_sequence", + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field( + "to_sequence", + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field( + "from_time", + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field( + "to_time", + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + ] + ), + self._TYPE_NAME, + ) + + +class VisibleTimeRangeBatch(BaseBatch[VisibleTimeRangeArrayLike]): + _ARROW_TYPE = VisibleTimeRangeType() + + @staticmethod + def _native_to_pa_array(data: VisibleTimeRangeArrayLike, data_type: pa.DataType) -> pa.Array: + raise NotImplementedError # You need to implement native_to_pa_array_override in visible_time_range_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py new file mode 100644 index 000000000000..7d94422c9c4e --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py @@ -0,0 +1,104 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeBoundaryExt" class in "visible_time_range_boundary_ext.py". + +from __future__ import annotations + +from typing import Any, Sequence, Union + +import pyarrow as pa +from attrs import define, field + +from ... import datatypes +from ..._baseclasses import BaseBatch, BaseExtensionType +from ...blueprint import datatypes as blueprint_datatypes + +__all__ = [ + "VisibleTimeRangeBoundary", + "VisibleTimeRangeBoundaryArrayLike", + "VisibleTimeRangeBoundaryBatch", + "VisibleTimeRangeBoundaryLike", + "VisibleTimeRangeBoundaryType", +] + + +def _visible_time_range_boundary__time__special_field_converter_override(x: datatypes.TimeIntLike) -> datatypes.TimeInt: + if isinstance(x, datatypes.TimeInt): + return x + else: + return datatypes.TimeInt(x) + + +@define(init=False) +class VisibleTimeRangeBoundary: + """**Datatype**: Type of boundary for visible history.""" + + def __init__(self: Any, kind: blueprint_datatypes.VisibleTimeRangeBoundaryKindLike, time: datatypes.TimeIntLike): + """ + Create a new instance of the VisibleTimeRangeBoundary datatype. + + Parameters + ---------- + kind: + Type of the boundary. + time: + Value of the boundary (ignored for `Infinite` type). + + """ + + # You can define your own __init__ function as a member of VisibleTimeRangeBoundaryExt in visible_time_range_boundary_ext.py + self.__attrs_init__(kind=kind, time=time) + + kind: blueprint_datatypes.VisibleTimeRangeBoundaryKind = field() + # Type of the boundary. + # + # (Docstring intentionally commented out to hide this field from the docs) + + time: datatypes.TimeInt = field(converter=_visible_time_range_boundary__time__special_field_converter_override) + # Value of the boundary (ignored for `Infinite` type). + # + # (Docstring intentionally commented out to hide this field from the docs) + + +VisibleTimeRangeBoundaryLike = VisibleTimeRangeBoundary +VisibleTimeRangeBoundaryArrayLike = Union[ + VisibleTimeRangeBoundary, + Sequence[VisibleTimeRangeBoundaryLike], +] + + +class VisibleTimeRangeBoundaryType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRangeBoundary" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.struct( + [ + pa.field( + "kind", + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + nullable=False, + metadata={}, + ), + pa.field("time", pa.int64(), nullable=False, metadata={}), + ] + ), + self._TYPE_NAME, + ) + + +class VisibleTimeRangeBoundaryBatch(BaseBatch[VisibleTimeRangeBoundaryArrayLike]): + _ARROW_TYPE = VisibleTimeRangeBoundaryType() + + @staticmethod + def _native_to_pa_array(data: VisibleTimeRangeBoundaryArrayLike, data_type: pa.DataType) -> pa.Array: + raise NotImplementedError # You need to implement native_to_pa_array_override in visible_time_range_boundary_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py new file mode 100644 index 000000000000..e179602b070d --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py @@ -0,0 +1,105 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeBoundaryKindExt" class in "visible_time_range_boundary_kind_ext.py". + +from __future__ import annotations + +from typing import Sequence, Union + +import pyarrow as pa + +from ..._baseclasses import BaseBatch, BaseExtensionType + +__all__ = [ + "VisibleTimeRangeBoundaryKind", + "VisibleTimeRangeBoundaryKindArrayLike", + "VisibleTimeRangeBoundaryKindBatch", + "VisibleTimeRangeBoundaryKindLike", + "VisibleTimeRangeBoundaryKindType", +] + + +from enum import Enum + + +class VisibleTimeRangeBoundaryKind(Enum): + """**Datatype**: Kind of boundary for visible history, see `VisibleTimeRangeBoundary`.""" + + RelativeToTimeCursor = 1 + """Boundary is a value relative to the time cursor.""" + + Absolute = 2 + """Boundary is an absolute value.""" + + Infinite = 3 + """The boundary extends to infinity.""" + + +VisibleTimeRangeBoundaryKindLike = Union[VisibleTimeRangeBoundaryKind, str] +VisibleTimeRangeBoundaryKindArrayLike = Union[ + VisibleTimeRangeBoundaryKindLike, Sequence[VisibleTimeRangeBoundaryKindLike] +] + + +class VisibleTimeRangeBoundaryKindType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.sparse_union( + [ + pa.field("_null_markers", pa.null(), nullable=True, metadata={}), + pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), + pa.field("Absolute", pa.null(), nullable=True, metadata={}), + pa.field("Infinite", pa.null(), nullable=True, metadata={}), + ] + ), + self._TYPE_NAME, + ) + + +class VisibleTimeRangeBoundaryKindBatch(BaseBatch[VisibleTimeRangeBoundaryKindArrayLike]): + _ARROW_TYPE = VisibleTimeRangeBoundaryKindType() + + @staticmethod + def _native_to_pa_array(data: VisibleTimeRangeBoundaryKindArrayLike, data_type: pa.DataType) -> pa.Array: + if isinstance(data, (VisibleTimeRangeBoundaryKind, int, str)): + data = [data] + + types: list[int] = [] + + for value in data: + if value is None: + types.append(0) + elif isinstance(value, VisibleTimeRangeBoundaryKind): + types.append(value.value) # Actual enum value + elif isinstance(value, int): + types.append(value) # By number + elif isinstance(value, str): + if hasattr(VisibleTimeRangeBoundaryKind, value): + types.append(VisibleTimeRangeBoundaryKind[value].value) # fast path + elif value.lower() == "relativetotimecursor": + types.append(VisibleTimeRangeBoundaryKind.RelativeToTimeCursor.value) + elif value.lower() == "absolute": + types.append(VisibleTimeRangeBoundaryKind.Absolute.value) + elif value.lower() == "infinite": + types.append(VisibleTimeRangeBoundaryKind.Infinite.value) + else: + raise ValueError(f"Unknown VisibleTimeRangeBoundaryKind kind: {value}") + else: + raise ValueError(f"Unknown VisibleTimeRangeBoundaryKind kind: {value}") + + buffers = [ + None, + pa.array(types, type=pa.int8()).buffers()[1], + ] + children = (1 + 3) * [pa.nulls(len(data))] + + return pa.UnionArray.from_buffers( + type=data_type, + length=len(data), + buffers=buffers, + children=children, + ) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index 02728bf929d2..74fd88d4d968 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -24,6 +24,7 @@ scale3d.py linguist-generated=true tensor_buffer.py linguist-generated=true tensor_data.py linguist-generated=true tensor_dimension.py linguist-generated=true +time_int.py linguist-generated=true transform3d.py linguist-generated=true translation_and_mat3x3.py linguist-generated=true translation_rotation_scale3d.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index 36fcb289aa61..31fb9e4f05e4 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -60,6 +60,7 @@ TensorDimensionLike, TensorDimensionType, ) +from .time_int import TimeInt, TimeIntArrayLike, TimeIntBatch, TimeIntLike, TimeIntType from .transform3d import Transform3D, Transform3DArrayLike, Transform3DBatch, Transform3DLike, Transform3DType from .translation_and_mat3x3 import ( TranslationAndMat3x3, @@ -197,6 +198,11 @@ "TensorDimensionBatch", "TensorDimensionLike", "TensorDimensionType", + "TimeInt", + "TimeIntArrayLike", + "TimeIntBatch", + "TimeIntLike", + "TimeIntType", "Transform3D", "Transform3DArrayLike", "Transform3DBatch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/time_int.py b/rerun_py/rerun_sdk/rerun/datatypes/time_int.py new file mode 100644 index 000000000000..56b224544a7c --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/time_int.py @@ -0,0 +1,59 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/datatypes/time_int.fbs". + +# You can extend this class by creating a "TimeIntExt" class in "time_int_ext.py". + +from __future__ import annotations + +from typing import Any, Sequence, Union + +import numpy as np +import numpy.typing as npt +import pyarrow as pa +from attrs import define, field + +from .._baseclasses import BaseBatch, BaseExtensionType + +__all__ = ["TimeInt", "TimeIntArrayLike", "TimeIntBatch", "TimeIntLike", "TimeIntType"] + + +@define(init=False) +class TimeInt: + """**Datatype**: A 64-bit number describing either nanoseconds OR sequence numbers.""" + + def __init__(self: Any, value: TimeIntLike): + """Create a new instance of the TimeInt datatype.""" + + # You can define your own __init__ function as a member of TimeIntExt in time_int_ext.py + self.__attrs_init__(value=value) + + value: int = field(converter=int) + + def __array__(self, dtype: npt.DTypeLike = None) -> npt.NDArray[Any]: + # You can define your own __array__ function as a member of TimeIntExt in time_int_ext.py + return np.asarray(self.value, dtype=dtype) + + def __int__(self) -> int: + return int(self.value) + + +TimeIntLike = TimeInt +TimeIntArrayLike = Union[ + TimeInt, + Sequence[TimeIntLike], +] + + +class TimeIntType(BaseExtensionType): + _TYPE_NAME: str = "rerun.datatypes.TimeInt" + + def __init__(self) -> None: + pa.ExtensionType.__init__(self, pa.int64(), self._TYPE_NAME) + + +class TimeIntBatch(BaseBatch[TimeIntArrayLike]): + _ARROW_TYPE = TimeIntType() + + @staticmethod + def _native_to_pa_array(data: TimeIntArrayLike, data_type: pa.DataType) -> pa.Array: + raise NotImplementedError # You need to implement native_to_pa_array_override in time_int_ext.py From c8ab078b31409549a0708867c07e9d9afb7dcf9c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 18 Mar 2024 12:21:55 +0100 Subject: [PATCH 048/508] Hide entity icons in paths (#5550) ### What * Closes https://github.com/rerun-io/rerun/issues/5524 Before: image After: image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5550/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5550/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5550/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5550) - [Docs preview](https://rerun.io/preview/93e90e8c6e8e8df6093eabdf129d7061dab0d1a8/docs) - [Examples preview](https://rerun.io/preview/93e90e8c6e8e8df6093eabdf129d7061dab0d1a8/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/item_ui.rs | 90 ++++++++++++++++------ crates/re_viewer/src/ui/selection_panel.rs | 51 ++++++------ 2 files changed, 92 insertions(+), 49 deletions(-) diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 9cca518e2ec0..261c1bb61af5 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -3,7 +3,6 @@ //! TODO(andreas): This is not a `data_ui`, can this go somewhere else, shouldn't be in `re_data_ui`. use re_entity_db::{EntityTree, InstancePath}; -use re_log_types::external::re_types_core::components::InstanceKey; use re_log_types::{ComponentPath, EntityPath, TimeInt, Timeline}; use re_ui::SyntaxHighlighting; use re_viewer_context::{HoverHighlight, Item, SpaceViewId, UiVerbosity, ViewerContext}; @@ -62,22 +61,29 @@ pub fn entity_path_parts_buttons( space_view_id: Option, entity_path: &EntityPath, ) -> egui::Response { + let with_icon = false; // too much noise with icons in a path + ui.horizontal(|ui| { - ui.spacing_mut().item_spacing.x = 4.0; + ui.spacing_mut().item_spacing.x = 2.0; + + // Show one single icon up-front instead: + let instance_path = InstancePath::entity_splat(entity_path.clone()); + ui.add(instance_path_icon(&query.timeline, store, &instance_path).as_image()); let mut accumulated = Vec::new(); for part in entity_path.iter() { accumulated.push(part.clone()); ui.strong("/"); - entity_path_button_to( + instance_path_button_to_ex( ctx, query, store, ui, space_view_id, - &accumulated.clone().into(), + &InstancePath::entity_splat(accumulated.clone().into()), part.syntax_highlighted(ui.style()), + with_icon, ); } }) @@ -134,17 +140,19 @@ pub fn instance_path_icon( store: &re_data_store::DataStore, instance_path: &InstancePath, ) -> &'static re_ui::icons::Icon { - if instance_path.instance_key != InstanceKey::SPLAT { - return &re_ui::icons::ENTITY; - } - - if store - .all_components(timeline, &instance_path.entity_path) - .is_some() - { - &re_ui::icons::ENTITY + if instance_path.is_splat() { + // It is an entity path + if store + .all_components(timeline, &instance_path.entity_path) + .is_some() + { + &re_ui::icons::ENTITY + } else { + &re_ui::icons::ENTITY_EMPTY + } } else { - &re_ui::icons::ENTITY_EMPTY + // An instance path + &re_ui::icons::ENTITY } } @@ -190,6 +198,30 @@ pub fn instance_path_button_to( space_view_id: Option, instance_path: &InstancePath, text: impl Into, +) -> egui::Response { + instance_path_button_to_ex( + ctx, + query, + store, + ui, + space_view_id, + instance_path, + text, + true, + ) +} + +/// Show an instance id and make it selectable. +#[allow(clippy::too_many_arguments)] +fn instance_path_button_to_ex( + ctx: &ViewerContext<'_>, + query: &re_data_store::LatestAtQuery, + store: &re_data_store::DataStore, + ui: &mut egui::Ui, + space_view_id: Option, + instance_path: &InstancePath, + text: impl Into, + with_icon: bool, ) -> egui::Response { let item = if let Some(space_view_id) = space_view_id { Item::DataResult(space_view_id, instance_path.clone()) @@ -197,18 +229,21 @@ pub fn instance_path_button_to( Item::InstancePath(instance_path.clone()) }; - let response = ctx - .re_ui - .selectable_label_with_icon( + let response = if with_icon { + ctx.re_ui.selectable_label_with_icon( ui, instance_path_icon(&query.timeline, store, instance_path), text, ctx.selection().contains_item(&item), re_ui::LabelStyle::Normal, ) - .on_hover_ui(|ui| { - instance_hover_card_ui(ui, ctx, query, store, instance_path); - }); + } else { + ui.selectable_label(ctx.selection().contains_item(&item), text) + }; + + let response = response.on_hover_ui(|ui| { + instance_hover_card_ui(ui, ctx, query, store, instance_path); + }); cursor_interact_with_selectable(ctx, response, item) } @@ -222,28 +257,34 @@ pub fn instance_path_parts_buttons( space_view_id: Option, instance_path: &InstancePath, ) -> egui::Response { + let with_icon = false; // too much noise with icons in a path + ui.horizontal(|ui| { - ui.spacing_mut().item_spacing.x = 4.0; + ui.spacing_mut().item_spacing.x = 2.0; + + // Show one single icon up-front instead: + ui.add(instance_path_icon(&query.timeline, store, instance_path).as_image()); let mut accumulated = Vec::new(); for part in instance_path.entity_path.iter() { accumulated.push(part.clone()); ui.strong("/"); - entity_path_button_to( + instance_path_button_to_ex( ctx, query, store, ui, space_view_id, - &accumulated.clone().into(), + &InstancePath::entity_splat(accumulated.clone().into()), part.syntax_highlighted(ui.style()), + with_icon, ); } if !instance_path.instance_key.is_splat() { ui.strong("/"); - instance_path_button_to( + instance_path_button_to_ex( ctx, query, store, @@ -251,6 +292,7 @@ pub fn instance_path_parts_buttons( space_view_id, instance_path, instance_path.instance_key.syntax_highlighted(ui.style()), + with_icon, ); } }) diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 9dd09ffad9e8..84136ab00b68 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -316,6 +316,7 @@ fn what_is_selected_ui( item_title_ui(ctx.re_ui, ui, &title, Some(&re_ui::icons::STORE), &id_str); } + Item::Container(container_id) => { if let Some(container_blueprint) = viewport.container(container_id) { item_title_ui( @@ -329,6 +330,7 @@ fn what_is_selected_ui( ); } } + Item::ComponentPath(re_log_types::ComponentPath { entity_path, component_name, @@ -354,6 +356,7 @@ fn what_is_selected_ui( list_existing_data_blueprints(ui, ctx, &entity_path.clone().into(), viewport); } + Item::SpaceView(space_view_id) => { if let Some(space_view) = viewport.space_view(space_view_id) { let space_view_class = space_view.class(ctx.space_view_class_registry); @@ -381,20 +384,10 @@ fn what_is_selected_ui( .on_hover_text(hover_text); } } - Item::InstancePath(instance_path) => { - let is_instance = !instance_path.instance_key.is_splat(); + Item::InstancePath(instance_path) => { let typ = item.kind(); - - let (query, store) = - guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); - let name = instance_path.syntax_highlighted(ui.style()); - let parent = if is_instance { - Some(instance_path.entity_path.clone()) - } else { - instance_path.entity_path.parent() - }; item_title_ui( ctx.re_ui, @@ -404,10 +397,18 @@ fn what_is_selected_ui( &format!("{typ} '{instance_path}'"), ); + let is_instance = !instance_path.instance_key.is_splat(); + let parent = if is_instance { + Some(instance_path.entity_path.clone()) + } else { + instance_path.entity_path.parent() + }; if let Some(parent) = parent { if !parent.is_root() { + let (query, store) = + guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); ui.horizontal(|ui| { - ui.label("path"); + ui.label("Parent"); item_ui::entity_path_parts_buttons(ctx, &query, store, ui, None, &parent); }); } @@ -417,21 +418,10 @@ fn what_is_selected_ui( } Item::DataResult(space_view_id, instance_path) => { - let is_instance = !instance_path.instance_key.is_splat(); - - let typ = item.kind(); - - let (query, store) = - guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); - let name = instance_path.syntax_highlighted(ui.style()); - let parent = if is_instance { - Some(instance_path.entity_path.clone()) - } else { - instance_path.entity_path.parent() - }; if let Some(space_view) = viewport.space_view(space_view_id) { + let typ = item.kind(); item_title_ui( ctx.re_ui, ui, @@ -443,10 +433,21 @@ fn what_is_selected_ui( ), ); + let is_instance = !instance_path.instance_key.is_splat(); + let parent = if is_instance { + Some(instance_path.entity_path.clone()) + } else { + instance_path.entity_path.parent() + }; if let Some(parent) = parent { if !parent.is_root() { ui.horizontal(|ui| { - ui.label("path"); + let (query, store) = guess_query_and_store_for_selected_entity( + ctx, + &instance_path.entity_path, + ); + + ui.label("Parent"); item_ui::entity_path_parts_buttons( ctx, &query, From be1fbcc8d778481a1fd9a90f78fd38c34e24df02 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Mon, 18 Mar 2024 14:22:49 +0100 Subject: [PATCH 049/508] Build wheels for Linux ARM64 (#5511) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What Build linux-aarch64 wheels (with manylinux_2_31) and fixes the C and CLI builds to bring the min required glibc version to 2.31. **Note**: cursory inspection indicates that the _actual_ min glibc version 2.29. However, we don't formally test that. The only test is done by `maturin` on our wheels, against the `manylinux_2_31` standard. Amongst other things, this PR: - updates our ci docker image to be compatible with aarch64 (#5543 – thanks @jleibs) - remove all instances of double GCS authentication (our setup-rust action auth to GCS, so an explicit auth isn't necessary, _and_ would break cleanup in linux-arm/cli build workflow—why there only is unclear) - use it for all linux-aarch64 builds - fixes `pixi.toml` for linux-aarch64 compatibility - bumps pixi to 0.16.1 everywhere in the ci - adds a manual trigger for building wheels - (mostly) unifies the target naming scheme #### Related - Follow-up to: - #5489 - #5503 - Closes #4136 - Fixes #5507 #### Further work - ~~support lower glibc version: https://github.com/rerun-io/rerun/issues/5512~~ - test more wheels: https://github.com/rerun-io/rerun/issues/5525 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5511/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5511/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5511/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5511) - [Docs preview](https://rerun.io/preview/c029b411730d035b9babdba3f9721dbe2905196b/docs) - [Examples preview](https://rerun.io/preview/c029b411730d035b9babdba3f9721dbe2905196b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Jeremy Leibs --- .github/workflows/auto_release_crates.yml | 2 +- .github/workflows/contrib_checks.yml | 16 +- .github/workflows/contrib_rerun_py.yml | 4 +- .github/workflows/nightly.yml | 6 +- .github/workflows/on_pull_request.yml | 14 +- .github/workflows/on_push_main.yml | 106 +- .github/workflows/release.yml | 4 +- .github/workflows/reusable_bench.yml | 2 +- .../reusable_build_and_upload_rerun_c.yml | 15 +- .../reusable_build_and_upload_rerun_cli.yml | 32 +- .../reusable_build_and_upload_wheels.yml | 31 +- .github/workflows/reusable_build_examples.yml | 2 +- .github/workflows/reusable_build_js.yml | 4 +- .github/workflows/reusable_build_web.yml | 6 +- .../reusable_bundle_and_upload_rerun_cpp.yml | 2 +- .github/workflows/reusable_checks.yml | 6 +- .github/workflows/reusable_checks_cpp.yml | 2 +- .github/workflows/reusable_checks_rust.yml | 34 +- .github/workflows/reusable_deploy_docs.yml | 4 +- .github/workflows/reusable_publish_js.yml | 2 +- .github/workflows/reusable_publish_web.yml | 2 +- .github/workflows/reusable_publish_wheels.yml | 87 +- .github/workflows/reusable_release_crates.yml | 2 +- .github/workflows/reusable_run_notebook.yml | 4 +- .github/workflows/reusable_test_wheels.yml | 24 +- ci_docker/Dockerfile | 20 +- ci_docker/publish.sh | 19 +- pixi.lock | 7552 +++++++++++++++-- pixi.toml | 37 +- 29 files changed, 6974 insertions(+), 1067 deletions(-) diff --git a/.github/workflows/auto_release_crates.yml b/.github/workflows/auto_release_crates.yml index 0e73b9c6bc30..a1b7d814ff89 100644 --- a/.github/workflows/auto_release_crates.yml +++ b/.github/workflows/auto_release_crates.yml @@ -22,7 +22,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Install dependencies shell: bash diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 46cf95ca72d0..74d6d97b8594 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -86,7 +86,7 @@ jobs: name: Check if running codegen would produce any changes runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: # Note: We explicitly don't override `ref` here. We need to see if changes would be made # in a context where we have merged with main. Otherwise we might miss changes such as one @@ -101,7 +101,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Codegen check shell: bash @@ -112,7 +112,7 @@ jobs: name: Rust lints (fmt, check, cranky, tests, doc) runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 @@ -183,7 +183,7 @@ jobs: name: Check Rust web build (wasm32 + wasm-bindgen) runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 @@ -212,7 +212,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - run: pixi run lint-taplo shell: bash @@ -268,7 +268,7 @@ jobs: name: Cargo Deny runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 @@ -294,13 +294,13 @@ jobs: name: C++ tests runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 # TODO(emilk): make this work somehow. Right now this just results in # > Compiler: GNU 12.3.0 (/__w/rerun/rerun/.pixi/env/bin/x86_64-conda-linux-gnu-c++) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index f0b7b1517c68..e0f0d65224c1 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -36,13 +36,13 @@ jobs: name: Build Wheels runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 # These should already be in the docker container, but run for good measure. A no-op install # should be fast, and this way things don't break if we add new packages without rebuilding diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 22c1365da432..5e25573628e2 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -53,8 +53,8 @@ jobs: uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: CONCURRENCY: nightly-linux - PLATFORM: linux - WHEEL_ARTIFACT_NAME: linux-wheel + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: linux-x64-wheel MODE: "pr" secrets: inherit @@ -65,7 +65,7 @@ jobs: with: CONCURRENCY: nightly CHANNEL: nightly - WHEEL_ARTIFACT_NAME: linux-wheel + WHEEL_ARTIFACT_NAME: linux-x64-wheel secrets: inherit upload-examples: diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 652f69707afe..451fd6a47f43 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -76,6 +76,8 @@ jobs: FULL: "true" secrets: inherit + # Build and test a single wheel to limit CI cost. We use linux-x64 because it's fast. linux-arm64 would also be a good + # choice, but reusable_test_wheels.yml is broken for that target (https://github.com/rerun-io/rerun/issues/5525) min-wheel-build: name: "Minimum Wheel Build" if: github.event.pull_request.head.repo.owner.login == 'rerun-io' @@ -83,8 +85,8 @@ jobs: with: CONCURRENCY: pr-${{ github.event.pull_request.number }} MODE: "pr" - PLATFORM: linux - WHEEL_ARTIFACT_NAME: "linux-wheel-fast" + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" secrets: inherit min-wheel-test: @@ -94,8 +96,8 @@ jobs: uses: ./.github/workflows/reusable_test_wheels.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} - PLATFORM: linux - WHEEL_ARTIFACT_NAME: "linux-wheel-fast" + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" secrets: inherit build-js: @@ -133,7 +135,7 @@ jobs: with: CONCURRENCY: pr-${{ github.event.pull_request.number }} CHANNEL: main - WHEEL_ARTIFACT_NAME: linux-wheel-fast + WHEEL_ARTIFACT_NAME: linux-x64-wheel-fast secrets: inherit track-sizes: @@ -163,7 +165,7 @@ jobs: uses: ./.github/workflows/reusable_run_notebook.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} - WHEEL_ARTIFACT_NAME: linux-wheel-fast + WHEEL_ARTIFACT_NAME: linux-x64-wheel-fast secrets: inherit save-pr-summary: diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 9e29139a2863..da7500ae4568 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -209,78 +209,90 @@ jobs: # ----------------------------------------------------------------------------------- - build-wheel-linux: + build-wheel-linux-arm64: needs: [checks] - name: "Linux: Build & Upload Wheels" + name: "Linux-arm64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: push-linux-${{ github.ref_name }} - PLATFORM: linux - WHEEL_ARTIFACT_NAME: linux-wheel + CONCURRENCY: push-linux-arm64-${{ github.ref_name }} + PLATFORM: linux-arm64 + WHEEL_ARTIFACT_NAME: linux-arm64-wheel + MODE: "pypi" + secrets: inherit + + build-wheel-linux-x64: + needs: [checks] + name: "Linux-x64: Build & Upload Wheels" + uses: ./.github/workflows/reusable_build_and_upload_wheels.yml + with: + CONCURRENCY: push-linux-x64-${{ github.ref_name }} + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: linux-x64-wheel MODE: "pypi" secrets: inherit - build-wheel-windows: + build-wheel-windows-x64: needs: [checks] - name: "Windows: Build & Upload Wheels" + name: "Windows-x64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: push-windows-${{ github.ref_name }} - PLATFORM: windows - WHEEL_ARTIFACT_NAME: windows-wheel + CONCURRENCY: push-windows-x64-${{ github.ref_name }} + PLATFORM: windows-x64 + WHEEL_ARTIFACT_NAME: windows-x64-wheel MODE: "pypi" secrets: inherit - build-wheel-macos-arm: + build-wheel-macos-arm64: needs: [checks] - name: "Macos-Arm: Build & Upload Wheels" + name: "Macos-arm64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: push-macos-arm-${{ github.ref_name }} - PLATFORM: macos-arm - WHEEL_ARTIFACT_NAME: macos-arm-wheel + CONCURRENCY: push-macos-arm64-${{ github.ref_name }} + PLATFORM: macos-arm64 + WHEEL_ARTIFACT_NAME: macos-arm64-wheel MODE: "pypi" secrets: inherit - build-wheel-macos-intel: + build-wheel-macos-x64: needs: [checks] - name: "Macos-Intel: Build & Upload Wheels" + name: "Macos-x64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: push-macos-intel-${{ github.ref_name }} - PLATFORM: macos-intel - WHEEL_ARTIFACT_NAME: "macos-intel-wheel" + CONCURRENCY: push-macos-x64-${{ github.ref_name }} + PLATFORM: macos-x64 + WHEEL_ARTIFACT_NAME: "macos-x64-wheel" MODE: "pypi" secrets: inherit - test-wheel-linux: - needs: [checks, build-wheel-linux] - name: "Linux: Test Wheels" + test-wheel-linux-x64: + needs: [checks, build-wheel-linux-x64] + name: "Linux-x64: Test Wheels" uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: push-linux-${{ github.ref_name }} - PLATFORM: linux - WHEEL_ARTIFACT_NAME: linux-wheel + CONCURRENCY: push-linux-x64-${{ github.ref_name }} + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: linux-x64-wheel secrets: inherit - test-wheel-windows: - needs: [checks, build-wheel-windows] - name: "Windows: Test Wheels" + test-wheel-windows-x64: + needs: [checks, build-wheel-windows-x64] + name: "Windows-x64: Test Wheels" uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: push-windows-${{ github.ref_name }} - PLATFORM: windows - WHEEL_ARTIFACT_NAME: windows-wheel + CONCURRENCY: push-windows-x64-${{ github.ref_name }} + PLATFORM: windows-x64 + WHEEL_ARTIFACT_NAME: windows-x64-wheel secrets: inherit generate-pip-index: name: "Generate Pip Index" needs: [ - build-wheel-linux, - build-wheel-windows, - build-wheel-macos-arm, - build-wheel-macos-intel, + build-wheel-linux-arm64, + build-wheel-linux-x64, + build-wheel-macos-arm64, + build-wheel-macos-x64, + build-wheel-windows-x64, ] uses: ./.github/workflows/reusable_pip_index.yml with: @@ -291,10 +303,10 @@ jobs: name: "Bundle and upload rerun_cpp_sdk.zip" needs: [ - build-rerun_c-and-upload-linux-x64, build-rerun_c-and-upload-linux-arm64, - build-rerun_c-and-upload-macos-x64, + build-rerun_c-and-upload-linux-x64, build-rerun_c-and-upload-macos-arm64, + build-rerun_c-and-upload-macos-x64, build-rerun_c-and-upload-windows-x64, ] uses: ./.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml @@ -307,19 +319,19 @@ jobs: cancel-in-progress: true needs: [ - upload-web, - generate-pip-index, - build-rerun_c-and-upload-linux-x64, - build-rerun_c-and-upload-linux-arm64, - build-rerun_c-and-upload-macos-x64, - build-rerun_c-and-upload-macos-arm64, - build-rerun_c-and-upload-windows-x64, - build-rerun-cli-and-upload-linux-x64, build-rerun-cli-and-upload-linux-arm64, - build-rerun-cli-and-upload-macos-x64, + build-rerun-cli-and-upload-linux-x64, build-rerun-cli-and-upload-macos-arm64, + build-rerun-cli-and-upload-macos-x64, build-rerun-cli-and-upload-windows-x64, + build-rerun_c-and-upload-linux-arm64, + build-rerun_c-and-upload-linux-x64, + build-rerun_c-and-upload-macos-arm64, + build-rerun_c-and-upload-macos-x64, + build-rerun_c-and-upload-windows-x64, bundle-and-upload-rerun_cpp, + generate-pip-index, + upload-web, ] runs-on: "ubuntu-latest" steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3404cf7663e0..c75eeddc2c1f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Update crate versions id: versioning @@ -391,7 +391,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Install dependencies shell: bash diff --git a/.github/workflows/reusable_bench.yml b/.github/workflows/reusable_bench.yml index ccfb154c880d..7c6885a4c65b 100644 --- a/.github/workflows/reusable_bench.yml +++ b/.github/workflows/reusable_bench.yml @@ -52,7 +52,7 @@ jobs: runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml index ffb07202f703..04b2403ddd7e 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_c.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml @@ -76,13 +76,13 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="null" + container="{'image': 'rerunio/ci_docker:0.12.0'}" lib_name="librerun_c.a" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.11.0'}" + container="{'image': 'rerunio/ci_docker:0.12.0'}" lib_name="librerun_c.a" ;; windows-x64) @@ -112,9 +112,12 @@ jobs: rs-build-rerun_c: name: Build rerun_c (${{ needs.set-config.outputs.RUNNER }}) + needs: [set-config] + runs-on: ${{ needs.set-config.outputs.RUNNER }} container: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + steps: - name: Show context shell: bash @@ -133,7 +136,7 @@ jobs: with: ref: ${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.ref) || '') }} - - name: Set up Rust + - name: Set up Rust and Authenticate to GCS uses: ./.github/actions/setup-rust with: cache_key: "build-${{ inputs.PLATFORM }}" @@ -148,12 +151,6 @@ jobs: command: build args: --locked -p rerun_c --release --target ${{ needs.set-config.outputs.TARGET }} - - id: "auth" - uses: google-github-actions/auth@v1 - with: - workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - name: Get sha id: get-sha shell: bash diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index 3c73ab51c177..056670dd6eef 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -75,15 +75,15 @@ jobs: run: | case "${{ inputs.PLATFORM }}" in linux-arm64) - runner="buildjet-8vcpu-ubuntu-2204-arm" - target="aarch64-unknown-linux-gnu" - container="null" - bin_name="rerun" - ;; + runner="buildjet-8vcpu-ubuntu-2204-arm" + target="aarch64-unknown-linux-gnu" + container="{'image': 'rerunio/ci_docker:0.12.0'}" + bin_name="rerun" + ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.11.0'}" + container="{'image': 'rerunio/ci_docker:0.12.0'}" bin_name="rerun" ;; windows-x64) @@ -137,7 +137,7 @@ jobs: with: ref: ${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.ref) || '') }} - - name: Set up Rust + - name: Set up Rust and Authenticate to GCS uses: ./.github/actions/setup-rust with: cache_key: "build-${{ inputs.PLATFORM }}" @@ -147,24 +147,14 @@ jobs: targets: ${{ needs.set-config.outputs.TARGET }} - uses: prefix-dev/setup-pixi@v0.4.1 - if: ${{ inputs.PLATFORM != 'linux-arm64' }} # TODO(#5507): see below with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Build web-viewer (release) - if: ${{ inputs.PLATFORM != 'linux-arm64' }} # TODO(#5507): see below shell: bash run: | pixi run cargo run --locked -p re_build_web_viewer -- --release - # TODO(#5507): supress this workaround when pixi dependencies are available on linux-arm64 - - name: Build web-viewer (release, Linux ARM64) - if: ${{ inputs.PLATFORM == 'linux-arm64' }} - shell: bash - run: | - sudo apt-get install binaryen - cargo run --locked -p re_build_web_viewer -- --release - # This does not run in the pixi environment, doing so # causes it to select the wrong compiler on macos-arm64 - name: Build rerun-cli @@ -181,12 +171,6 @@ jobs: --release \ --target ${{ needs.set-config.outputs.TARGET }} - - id: "auth" - uses: google-github-actions/auth@v1 - with: - workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - name: Get sha id: get-sha shell: bash diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 137e39c9895c..f5dee2423b65 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -86,42 +86,54 @@ jobs: set-config: name: Set Config (${{ inputs.PLATFORM }}) - runs-on: ubuntu-latest-16-cores + runs-on: ubuntu-latest outputs: RUNNER: ${{ steps.set-config.outputs.runner }} TARGET: ${{ steps.set-config.outputs.target }} CONTAINER: ${{ steps.set-config.outputs.container }} + COMPAT: ${{ steps.set-config.outputs.compat }} steps: - name: Set runner and target based on platform id: set-config shell: bash run: | case "${{ inputs.PLATFORM }}" in - linux) + linux-arm64) + runner="buildjet-8vcpu-ubuntu-2204-arm" + target="aarch64-unknown-linux-gnu" + container="{'image': 'rerunio/ci_docker:0.12.0'}" + compat="manylinux_2_31" + ;; + linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.11.0'}" + compat="manylinux_2_31" + container="{'image': 'rerunio/ci_docker:0.12.0'}" ;; - windows) + windows-x64) runner="windows-latest-8-cores" target="x86_64-pc-windows-msvc" container="null" + compat="manylinux_2_31" ;; - macos-arm) + macos-arm64) runner="macos-latest-large" # See https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/ target="aarch64-apple-darwin" container="null" + compat="manylinux_2_31" ;; - macos-intel) + macos-x64) runner="macos-latest-large" # See https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/ target="x86_64-apple-darwin" container="null" + compat="manylinux_2_31" ;; *) echo "Invalid platform" && exit 1 ;; esac echo "runner=$runner" >> "$GITHUB_OUTPUT" echo "target=$target" >> "$GITHUB_OUTPUT" echo "container=$container" >> "$GITHUB_OUTPUT" + echo "compat=$compat" >> "$GITHUB_OUTPUT" # --------------------------------------------------------------------------- @@ -151,7 +163,7 @@ jobs: with: ref: ${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.ref) || '') }} - - name: Set up Rust + - name: Set up Rust and Authenticate to GCS uses: ./.github/actions/setup-rust with: cache_key: "build-${{ inputs.PLATFORM }}" @@ -159,10 +171,11 @@ jobs: save_cache: false workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} + targets: ${{ needs.set-config.outputs.TARGET }} - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Install dependencies shell: bash @@ -185,7 +198,7 @@ jobs: --mode ${{ inputs.MODE }} \ --target ${{ needs.set-config.outputs.TARGET }} \ --dir commit/${{ steps.get-sha.outputs.sha }}/wheels \ - --compat manylinux_2_31 + --compat ${{ needs.set-config.outputs.COMPAT }} - name: Save wheel artifact if: ${{ inputs.WHEEL_ARTIFACT_NAME != '' }} diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 2aa2df31bdd6..108dde0ed807 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -50,7 +50,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Download Wheel uses: actions/download-artifact@v3 diff --git a/.github/workflows/reusable_build_js.yml b/.github/workflows/reusable_build_js.yml index 2ccad2fb1f84..b64f2e356a5b 100644 --- a/.github/workflows/reusable_build_js.yml +++ b/.github/workflows/reusable_build_js.yml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 @@ -55,7 +55,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.3.0 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Install dependencies shell: bash diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 85363ba2c934..622561dd96c7 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 @@ -55,7 +55,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Build web-viewer (release) shell: bash @@ -63,7 +63,7 @@ jobs: if [ ${{ inputs.CHANNEL }} = "nightly" ]; then export DEFAULT_EXAMPLES_MANIFEST_URL="https://app.rerun.io/version/nightly/examples_manifest.json" fi - cargo run --locked -p re_build_web_viewer -- --release + pixi run cargo run --locked -p re_build_web_viewer -- --release # We build a single manifest pointing to the `commit` # All the `pr`, `main`, release tag, etc. variants will always just point to the resolved commit diff --git a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml index 2eb69d79e16e..33df3acec442 100644 --- a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml +++ b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest # Need container for arrow dependency. container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - name: Checkout repository diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index e0681fcca58f..823dc755da7c 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -102,7 +102,7 @@ jobs: name: Check if running codegen would produce any changes runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 env: RUSTC_WRAPPER: "sccache" steps: @@ -127,7 +127,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Codegen check shell: bash @@ -208,7 +208,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: prettier --check run: pixi run misc-fmt-check diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index ab01d5279e1e..d98471e91e36 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -73,7 +73,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Set up Rust uses: ./.github/actions/setup-rust diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 42a2fcc4b1ae..3b4ce9353576 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -39,7 +39,7 @@ jobs: name: Rust lints (fmt, check, cranky, tests, doc) runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 env: RUSTC_WRAPPER: "sccache" steps: @@ -55,13 +55,16 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} + - uses: prefix-dev/setup-pixi@v0.4.1 + with: + pixi-version: v0.16.1 + # We need to build the web viewer for `rust_checks.py` to succeed. + # We build in release so that we can reuse the results for actual publishing, if necessary - name: Build web-viewer (release) - uses: actions-rs/cargo@v1 - with: - command: run - # We build in release so that we can reuse the results for actual publishing, if necessary - args: --locked -p re_build_web_viewer -- --release + shell: bash + run: | + pixi run cargo run --locked -p re_build_web_viewer -- --release - name: Rust checks & tests if: ${{ !inputs.ALL_CHECKS }} @@ -77,7 +80,7 @@ jobs: name: Check Rust web build (wasm32 + wasm-bindgen) runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 env: RUSTC_WRAPPER: "sccache" steps: @@ -103,12 +106,15 @@ jobs: command: check args: --locked --target wasm32-unknown-unknown --target-dir target_wasm -p re_renderer --examples - - name: Build web-viewer (release) - uses: actions-rs/cargo@v1 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - command: run - # We build in release so that we can reuse the results for actual publishing, if necessary - args: --locked -p re_build_web_viewer -- --release + pixi-version: v0.16.1 + + # We build in release so that we can reuse the results for actual publishing, if necessary + - name: Build web-viewer (release) + shell: bash + run: | + pixi run cargo run --locked -p re_build_web_viewer -- --release # --------------------------------------------------------------------------- @@ -122,7 +128,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Taplo check shell: bash @@ -135,7 +141,7 @@ jobs: name: Cargo Deny runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index 7536ec162887..1f251647c174 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -116,7 +116,7 @@ jobs: needs: [py-deploy-docs] runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - name: Show context shell: bash @@ -206,7 +206,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Doxygen C++ docs shell: bash diff --git a/.github/workflows/reusable_publish_js.yml b/.github/workflows/reusable_publish_js.yml index a9005fe12f1b..711f5c923225 100644 --- a/.github/workflows/reusable_publish_js.yml +++ b/.github/workflows/reusable_publish_js.yml @@ -63,7 +63,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.3.0 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Publish packages env: diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index 24a9f76b5f56..1d0ed09555fc 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -74,7 +74,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 # built by `reusable_build_and_publish_wheels` - name: Download Wheel diff --git a/.github/workflows/reusable_publish_wheels.yml b/.github/workflows/reusable_publish_wheels.yml index b3c7f4427c05..9f6512426bae 100644 --- a/.github/workflows/reusable_publish_wheels.yml +++ b/.github/workflows/reusable_publish_wheels.yml @@ -15,10 +15,6 @@ on: description: "Release Version Number (Must match Cargo.toml)" type: string required: true - linux-wheel-name: - description: "Name of the wheel built for linux" - type: string - required: true release-commit: description: "Which commit to build+publish" type: string @@ -44,81 +40,100 @@ jobs: ## Build - build-linux: - name: "Linux: Build Wheels" + build-linux-x64: + name: "Linux-x64: Build Wheels" + needs: [get-commit-sha] + uses: ./.github/workflows/reusable_build_and_upload_wheels.yml + with: + CONCURRENCY: wheels-build-linux-x64-${{ inputs.concurrency }} + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: linux-x64-wheel + RELEASE_COMMIT: ${{ inputs.release-commit }} + MODE: "pypi" + secrets: inherit + + build-linux-arm64: + name: "Linux-arm64: Build Wheels" needs: [get-commit-sha] uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: wheels-build-linux-${{ inputs.concurrency }} - PLATFORM: linux - WHEEL_ARTIFACT_NAME: ${{ inputs.linux-wheel-name }} + CONCURRENCY: wheels-build-linux-arm64-${{ inputs.concurrency }} + PLATFORM: linux-arm64 + WHEEL_ARTIFACT_NAME: linux-arm64-wheel RELEASE_COMMIT: ${{ inputs.release-commit }} MODE: "pypi" secrets: inherit - build-windows: - name: "Windows: Build Wheels" + build-windows-x64: + name: "Windows-x64: Build Wheels" needs: [get-commit-sha] uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: wheels-build-windows-${{ inputs.concurrency }} - PLATFORM: windows - WHEEL_ARTIFACT_NAME: windows-wheel + CONCURRENCY: wheels-build-windows-x64-${{ inputs.concurrency }} + PLATFORM: windows-x64 + WHEEL_ARTIFACT_NAME: windows-x64-wheel RELEASE_COMMIT: ${{ inputs.release-commit }} MODE: "pypi" secrets: inherit - build-macos-arm: - name: "Macos-Arm: Build Wheels" + build-macos-arm64: + name: "Macos-arm64: Build Wheels" needs: [get-commit-sha] uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: wheels-build-macos-arm-${{ inputs.concurrency }} - PLATFORM: macos-arm - WHEEL_ARTIFACT_NAME: macos-arm-wheel + CONCURRENCY: wheels-build-macos-arm64-${{ inputs.concurrency }} + PLATFORM: macos-arm64 + WHEEL_ARTIFACT_NAME: macos-arm64-wheel RELEASE_COMMIT: ${{ inputs.release-commit }} MODE: "pypi" secrets: inherit - build-macos-intel: - name: "Macos-Intel: Build Wheels" + build-macos-x64: + name: "Macos-x64: Build Wheels" needs: [get-commit-sha] uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: wheels-build-macos-intel-${{ inputs.concurrency }} - PLATFORM: macos-intel - WHEEL_ARTIFACT_NAME: "macos-intel-wheel" + CONCURRENCY: wheels-build-macos-x64-${{ inputs.concurrency }} + PLATFORM: macos-x64 + WHEEL_ARTIFACT_NAME: "macos-x64-wheel" RELEASE_COMMIT: ${{ inputs.release-commit }} MODE: "pypi" secrets: inherit ## Test - test-windows: - name: "Windows: Test Wheels" - needs: [build-windows] + test-windows-x64: + name: "Windows-x64: Test Wheels" + needs: [build-windows-x64] uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: wheels-test-windows-${{ inputs.concurrency }} - PLATFORM: windows - WHEEL_ARTIFACT_NAME: windows-wheel + CONCURRENCY: wheels-test-windows-x64-${{ inputs.concurrency }} + PLATFORM: windows-x64 + WHEEL_ARTIFACT_NAME: windows-x64-wheel RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit test-linux: - name: "Linux: Test Wheels" - needs: [build-linux] + name: "Linux-x64: Test Wheels" + needs: [build-linux-x64] uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: wheels-test-linux-${{ inputs.concurrency }} - PLATFORM: linux - WHEEL_ARTIFACT_NAME: ${{ inputs.linux-wheel-name }} + CONCURRENCY: wheels-test-linux-x64-${{ inputs.concurrency }} + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: linux-x64-wheel RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit generate-wheel-index: name: "Generate Pip Index" - needs: [build-linux, build-windows, build-macos-arm, build-macos-intel] + needs: + [ + build-linux-x64, + build-linux-arm64, + build-windows-x64, + build-macos-arm64, + build-macos-x64, + ] uses: ./.github/workflows/reusable_pip_index.yml with: CONCURRENCY: generate-wheel-index-${{ inputs.concurrency }} diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml index 47ce2c75ace6..92646766fd95 100644 --- a/.github/workflows/reusable_release_crates.yml +++ b/.github/workflows/reusable_release_crates.yml @@ -26,7 +26,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 - name: Build web-viewer (release) shell: bash diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml index 5cabcb26e96f..b741ad6750e2 100644 --- a/.github/workflows/reusable_run_notebook.yml +++ b/.github/workflows/reusable_run_notebook.yml @@ -1,4 +1,4 @@ -name: Reusable Buld and Upload Notebook +name: Reusable Build and Upload Notebook on: workflow_call: @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.11.0 + image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 33228b2d1d94..8c1cc08b4292 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -56,24 +56,30 @@ jobs: - name: Set runner and target based on platform id: set-config shell: bash + # TODO(#5525): at least this target is broken, maybe others — we currently only use linux-x64 and windows-x64 run: | case "${{ inputs.PLATFORM }}" in - linux) + linux-arm64) + runner="buildjet-8vcpu-ubuntu-2204-arm" + target="aarch64-unknown-linux-gnu" + container="{'image': 'rerunio/ci_docker:0.12.0'}" + ;; + linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.11.0'}" + container="{'image': 'rerunio/ci_docker:0.12.0'}" ;; - windows) + windows-x64) runner="windows-latest-8-cores" target="x86_64-pc-windows-msvc" container="null" ;; - macos-arm) + macos-arm64) runner="macos-latest-large" # See https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/ target="aarch64-apple-darwin" container="null" ;; - macos-intel) + macos-x64) runner="macos-latest-large" # See https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/ target="x86_64-apple-darwin" container="null" @@ -123,12 +129,12 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.13.0 + pixi-version: v0.16.1 # The pip-cache setup logic doesn't work in the ubuntu docker container # That's probably fine since we bake these deps into the container already - name: Setup python - if: ${{ inputs.PLATFORM != 'linux' }} + if: ${{ inputs.PLATFORM != 'linux-x64' }} uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} @@ -187,7 +193,7 @@ jobs: run: RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed - name: Run tests/roundtrips.py - if: ${{ inputs.PLATFORM != 'windows' }} + if: ${{ inputs.PLATFORM != 'windows-x64' }} shell: bash # --release so we can inherit from some of the artifacts that maturin has just built before # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… @@ -196,7 +202,7 @@ jobs: RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build - name: Run docs/snippets/compare_snippet_output.py - if: ${{ inputs.PLATFORM != 'windows' }} + if: ${{ inputs.PLATFORM != 'windows-x64' }} shell: bash # --release so we can inherit from some of the artifacts that maturin has just built before # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… diff --git a/ci_docker/Dockerfile b/ci_docker/Dockerfile index e5e4acfab46f..300ba04c48bf 100644 --- a/ci_docker/Dockerfile +++ b/ci_docker/Dockerfile @@ -2,11 +2,13 @@ FROM ubuntu:20.04 LABEL maintainer="opensource@rerun.io" # Remember to update the version in publish.sh # TODO(jleibs) use this version in the publish.sh script and below in the CACHE_KEY -LABEL version="0.11.0" +LABEL version="0.12.0" LABEL description="Docker image used for the CI of https://github.com/rerun-io/rerun" # Install the ubuntu package dependencies ENV DEBIAN_FRONTEND=noninteractive +ARG TARGETARCH + RUN set -eux; \ apt-get update; \ apt-get install -y ca-certificates lsb-release wget; \ @@ -57,8 +59,10 @@ RUN git clone --depth 1 --branch v23.5.9 https://github.com/google/flatbuffers.g make install && \ cd .. && rm -rf flatbuffers + # We need a more modern patchelf than ships on ubuntu-20.04 -RUN curl --fail -L https://github.com/NixOS/patchelf/releases/download/0.17.2/patchelf-0.17.2-x86_64.tar.gz | tar -xz ./bin/patchelf +RUN arch=$(if [ "$TARGETARCH" = "arm64" ]; then echo "aarch64"; else echo "x86_64"; fi) && \ + curl --fail -L https://github.com/NixOS/patchelf/releases/download/0.17.2/patchelf-0.17.2-${arch}.tar.gz | tar -xz ./bin/patchelf # TODO(andreas): Update cargo-deny below when updating rust version to 1.70.0 or above! ENV RUSTUP_HOME=/usr/local/rustup \ @@ -69,9 +73,10 @@ ENV RUSTUP_HOME=/usr/local/rustup \ # Install Rust # Borrowed from: https://github.com/rust-lang/docker-rust/blob/a8a2a9d/1.71.0/bookworm/Dockerfile -RUN set -eux; \ - rustArch='x86_64-unknown-linux-gnu'; \ - rustupSha256='0b2f6c8f85a3d02fde2efc0ced4657869d73fccfce59defb4e8d29233116e6db'; \ +RUN arch=$(if [ "$TARGETARCH" = "arm64" ]; then echo "aarch64"; else echo "x86_64"; fi) && \ + set -eux; \ + rustArch="${arch}-unknown-linux-gnu"; \ + rustupSha256=$(if [ "$TARGETARCH" = "arm64" ]; then echo "673e336c81c65e6b16dcdede33f4cc9ed0f08bde1dbe7a935f113605292dc800"; else echo "0b2f6c8f85a3d02fde2efc0ced4657869d73fccfce59defb4e8d29233116e6db"; fi); \ url="https://static.rust-lang.org/rustup/archive/${RUSTUP_VERSION}/${rustArch}/rustup-init"; \ wget "$url"; \ echo "${rustupSha256} *rustup-init" | sha256sum -c -; \ @@ -102,11 +107,8 @@ RUN pip install -r requirements-build.txt ADD rerun_py/requirements-lint.txt requirements-lint.txt RUN pip install -r requirements-lint.txt -# Note: We need a more modern binaryen than ships on ubuntu-20.4, so we pull it from github -RUN curl --fail -L https://github.com/WebAssembly/binaryen/releases/download/version_112/binaryen-version_112-x86_64-linux.tar.gz | tar xzk --strip-components 1 - # Increment this to invalidate cache -ENV CACHE_KEY=rerun_docker_v0.10.0 +ENV CACHE_KEY=rerun_docker_v0.12.0 # See: https://github.com/actions/runner-images/issues/6775#issuecomment-1410270956 RUN git config --system --add safe.directory '*' diff --git a/ci_docker/publish.sh b/ci_docker/publish.sh index 047dd990b15c..31d3d9b57d10 100755 --- a/ci_docker/publish.sh +++ b/ci_docker/publish.sh @@ -1,24 +1,11 @@ #!/usr/bin/env bash set -eux -VERSION=0.11.0 # Bump on each new version. Remember to update the version in the Dockerfile too. +VERSION=0.12.0 # Bump on each new version. Remember to update the version in the Dockerfile too. # The build needs to run from top of repo to access the requirements.txt cd `git rev-parse --show-toplevel` -# Pull :latest so we have the correct cache -docker pull rerunio/ci_docker - # Build the image -docker build -t ci_docker -f ci_docker/Dockerfile . -# This is necessary to build on mac, but is doing something weird with the Cache -# TODO(jleibs): Make this all work portably with caching -# docker buildx build --platform=linux/amd64 -t ci_docker -f ci_docker/Dockerfile . - -# Tag latest and version -docker tag ci_docker rerunio/ci_docker -docker tag ci_docker rerunio/ci_docker:$VERSION - -# Push the images back up -docker push rerunio/ci_docker -docker push rerunio/ci_docker:$VERSION +# buildx wants to do all of this in one step +docker buildx build --pull --platform linux/arm64,linux/amd64 -t rerunio/ci_docker -t rerunio/ci_docker:$VERSION --push -f ci_docker/Dockerfile . diff --git a/pixi.lock b/pixi.lock index 4b1d18ea4341..de4e93572c55 100644 --- a/pixi.lock +++ b/pixi.lock @@ -7,6 +7,7 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.16-h79b3bcb_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.10-hb29e0c7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.13-hd590300_0.conda @@ -20,11 +21,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.18-hecc5fa9_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.2-h19f5d62_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-h5606698_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-116-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.40-hdd6e379_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-hf600244_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.40-hbdbef99_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.26.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.6.0-hd590300_0.conda @@ -34,21 +36,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_hb11cfb5_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/colorlog-4.8.0-py311h38be061_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.6.0-h00ab1b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-23.5.26-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-12.3.0-h8d2909c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-12.3.0-he2b93b0_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-12.3.0-h76fc315_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-12.3.0-h8d2909c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-12.3.0-he2b93b0_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-12.3.0-h8a814eb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/just-1.22.1-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_16.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda @@ -74,6 +84,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h8bca6fd_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_5.conda @@ -97,6 +108,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-12.3.0-h0f45ef3_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.1-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h8bca6fd_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.19.0-hb90f79a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.8.0-h166bdaf_0.tar.bz2 @@ -106,120 +118,212 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.5-h232c23b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.4.0-py311h63ff55d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_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/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-h59595ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.18.2-hb753e55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.2-h00e871a_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-50.0-hd3aeb46_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.5-h06160fa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.8.1-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.18.1-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h75e419f_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.8-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_16.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h8bca6fd_105.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h8bca6fd_105.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_16.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.18.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h75e419f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - osx-64: - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.13-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-compression-0.2.18-h00d1b86_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-event-stream-0.4.2-h128c7ac_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-http-0.8.1-he0aa6e1_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-io-0.14.5-h2bbb85f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-mqtt-0.10.2-hf974719_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-s3-0.5.2-h170583c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-sdkutils-0.1.15-h00d1b86_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-checksums-0.1.18-h00d1b86_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.2-h07bb24a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/black-24.2.0-py311hec3470c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-16.0.6-ha38d28d_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.8-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/just-1.24.0-h1d8f897_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20240116.1-cxx17_h2f0025b_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-14.0.2-h25df049_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-acero-14.0.2-h2f0025b_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-dataset-14.0.2-h2f0025b_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-14.0.2-h2f4a9e5_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-sql-14.0.2-hc81a7a7_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-gandiva-14.0.2-h3a2b1eb_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-substrait-14.0.2-hd45466a_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.9.0-21_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-21_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp16-16.0.6-default_hb368394_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-18.1.1-default_hf9b4efe_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcrc32c-1.1.2-h01db608_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.5.0-h4e8248e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-13.2.0-hf8544c7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-ng-13.2.0-he9431aa_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-13.2.0-h582850c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-13.2.0-hf8544c7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-2.22.0-hd739bbb_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-storage-2.22.0-hdb39181_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgrpc-1.62.1-h98a9317_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.17-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.9.0-21_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm15-15.0.7-hb4f23b0_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm16-16.0.6-h0b931ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm18-18.1.1-hbfe100b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.58.0-hb0e430d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnl-3.9.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.26-pthreads_h5a5ec62_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libparquet-14.0.2-hb18b541_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-4.25.3-h648ac29_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libre2-11-2023.09.01-h9d008c2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.0-h492db2e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-13.2.0-h9a76618_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libthrift-0.19.0-h043aeee_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libutf8proc-2.8.0-h4e544f5_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.38.1-hb4cce97_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.46.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.5-h3091e33_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.9.4-hd600fc2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.4.0-py311h06e5ef9_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4-h0425590_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-h75d905f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.2.2-py311he69e3a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.25.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.16-h79cb451_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.10-h7beb4c2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.13-h10d778d_0.conda @@ -233,8 +337,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.18-hf5538d0_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.2-h56a5195_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h4da54b2_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-116-he965462_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.26.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.6.0-h282daa2_0.conda @@ -251,15 +356,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-16.0.6-h6d92fbe_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-16.0.6-hb91bd55_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/colorlog-4.8.0-py311h6eed73b_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-16.0.6-ha38d28d_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-16.0.6-ha38d28d_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.6.0-h7728843_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-23.5.26-he965462_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/just-1.22.1-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-609-ha02d983_16.conda @@ -312,75 +425,60 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.6-hb6ac08f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-16.0.6-hbedff68_3.conda - 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-2.1.5-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.4.0-py311h24bb903_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/meilisearch-1.5.1-hc85fda4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4-h93d8f39_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.18.2-h2713218_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h3758fe2_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.18.1-h11a7dfb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-16.0.6-h3808999_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.8-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.18.1-h11a7dfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.16-h51b92d1_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.10-hf888d4c_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.13-h93a5062_0.conda @@ -394,8 +492,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.18-hf888d4c_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.2-h06549c9_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h73c0887_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-116-h13dd4ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.26.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.6.0-h6aa9301_0.conda @@ -412,15 +511,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-16.0.6-default_h4cf2255_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-16.0.6-hcd7bac0_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-16.0.6-h54d7cd3_9.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/colorlog-4.8.0-py311h267d04e_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-16.0.6-h3808999_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-16.0.6-h3808999_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.6.0-h2ffa867_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-23.5.26-h13dd4ca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.22.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-609-h634c8be_16.conda @@ -473,74 +580,60 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-17.0.6-hcd81f8e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-16.0.6-haab561b_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.4.0-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/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h463b476_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.18.2-h7ed3092_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h798d188_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.18.1-h5ef7bb8_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - win-64: - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.8-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.18.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.25.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.13-hcfcfb64_0.conda @@ -554,17 +647,25 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-hd481e46_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-116-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/colorlog-4.8.0-py311h1ea47a8_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.0.0-h57928b3_49841.conda - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.22.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda @@ -609,38 +710,62 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.4.0-py311h9a9e57f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/meilisearch-1.5.1-h8b8d39b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.0.0-h66d3029_49657.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.8.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.11.0-h91493d7_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.18.1-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.37.32822-h0123c8e_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vswhere-3.1.4-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl default: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -648,6 +773,7 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.10-h0100c56_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.9-h5d48c4d_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.10-hd590300_0.conda @@ -661,21 +787,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.17-h7f92143_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.0-h3b5eec7_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.210-hac0d6e5_8.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-116-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h7f98852_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.24.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.7.22-hbcca054_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_hb11cfb5_4.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/colorlog-4.8.0-py311h38be061_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-23.5.26-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.6.0-h6f12383_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/just-1.15.0-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda @@ -731,117 +865,212 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.11.5-h232c23b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.4.0-py311h63ff55d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/meilisearch-1.5.1-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-hcb278e6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.18.2-hb753e55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.2-h4b38347_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-28.9-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.06.02-h2873b5e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.1-h06160fa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.8.1-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-h2797004_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.2-pyhd8ed1ab_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.24.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - osx-64: - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.13-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-compression-0.2.18-h00d1b86_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-event-stream-0.4.2-h128c7ac_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-http-0.8.1-he0aa6e1_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-io-0.14.5-h2bbb85f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-mqtt-0.10.2-hf974719_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-s3-0.5.2-h170583c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-sdkutils-0.1.15-h00d1b86_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-checksums-0.1.18-h00d1b86_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.2-h07bb24a_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/black-24.2.0-py311hec3470c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.2-pyhd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/just-1.24.0-h1d8f897_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20240116.1-cxx17_h2f0025b_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-14.0.2-h25df049_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-acero-14.0.2-h2f0025b_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-dataset-14.0.2-h2f0025b_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-14.0.2-h2f4a9e5_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-sql-14.0.2-hc81a7a7_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-gandiva-14.0.2-h3a2b1eb_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-substrait-14.0.2-hd45466a_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.9.0-21_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-21_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp16-16.0.6-default_hb368394_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-18.1.1-default_hf9b4efe_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcrc32c-1.1.2-h01db608_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.5.0-h4e8248e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-13.2.0-hf8544c7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-ng-13.2.0-he9431aa_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-13.2.0-h582850c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-13.2.0-hf8544c7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-2.22.0-hd739bbb_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-storage-2.22.0-hdb39181_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgrpc-1.62.1-h98a9317_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.17-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.9.0-21_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm15-15.0.7-hb4f23b0_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm16-16.0.6-h0b931ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm18-18.1.1-hbfe100b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.58.0-hb0e430d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnl-3.9.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.26-pthreads_h5a5ec62_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libparquet-14.0.2-hb18b541_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-4.25.3-h648ac29_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libre2-11-2023.09.01-h9d008c2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.0-h492db2e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-13.2.0-h9a76618_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libthrift-0.19.0-h043aeee_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libutf8proc-2.8.0-h4e544f5_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.38.1-hb4cce97_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.46.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.5-h3091e33_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.9.4-hd600fc2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.4.0-py311h06e5ef9_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4-h0425590_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-h75d905f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.2.2-py311he69e3a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.24.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.10-h5ed86db_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.9-had988b7_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.10-h10d778d_0.conda @@ -855,21 +1084,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.17-hb45f1eb_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.0-h88f2ebf_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.210-heeba50e_8.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-116-he965462_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h0d85af4_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.24.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2023.7.22-h8857fd0_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/colorlog-4.8.0-py311h6eed73b_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-23.5.26-he965462_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.6.0-h8ac2a54_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/just-1.15.0-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20230802.1-cxx17_h048a20a_0.conda @@ -918,73 +1155,59 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.2-hff08bdf_0.conda - 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-2.1.5-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.4.0-py311h24bb903_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/meilisearch-1.5.1-hc85fda4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4-hf0c8a7f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.18.2-h2713218_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h9ab30d4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.06.02-hd34609a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hef22860_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.16.20-h63b85fc_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.2-pyhd8ed1ab_1.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hef22860_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.16.20-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.24.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.10-h8e8137d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.9-hb1772db_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.10-h93a5062_0.conda @@ -998,21 +1221,29 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.17-hb1772db_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.0-hcc526ff_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.210-ha042220_8.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-116-h13dd4ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h3422bc3_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.24.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2023.7.22-hf0a4a13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/colorlog-4.8.0-py311h267d04e_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-23.5.26-h13dd4ca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.6.0-h6da1cb0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.15.0-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20230802.1-cxx17_h13dd4ca_0.conda @@ -1061,133 +1292,692 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-17.0.2-h1c12783_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.4.0-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/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h7ea286d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.18.2-h7ed3092_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h7c018df_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.06.02-h6135d0a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hb31c410_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.16.20-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl win-64: - - conda: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.13-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-hd481e46_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-h0f06f08_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-hdb5aac5_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.5-h08270f9_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.2-hfea8755_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.2-h4b2095a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-hd481e46_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-hd481e46_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h8ffe710_4.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2023.7.22-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.7-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.2-pyhd8ed1ab_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2023.2.0-h57928b3_50496.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.15.0-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-hd01637b_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h63175ca_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h63175ca_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-hca4e5ea_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h1ef3bed_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-h6d0e577_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-hf368baa_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-18_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlicommon-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlidec-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlienc-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-18_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libclang13-17.0.6-default_h85b4d89_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.5.0-hd5e4a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.5.0-h63175ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.21.0-h2b62511_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.21.0-hb581fae_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.61.1-h864d0f4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.9.3-default_haede6df_1009.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.17-h8ffe710_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-18_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h7ec3a38_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.2-h503648d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libre2-11-2023.09.01-hf8d8778_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.1-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libthrift-0.19.0-ha2b3283_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libutf8proc-2.8.0-h82a8f57_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.44.2-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.5-hc3477c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.4-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libgfortran-5.3.0-6.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-5.3.0-7.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.4.0-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2022.1.0-h6a75c08_874.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311ha68e1ae_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/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/ninja-1.11.1-h91493d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.10.0-h91493d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.16.20-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.24.6-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h64f974e_17.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.36.32532-hdcecf7f_17.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.36.32532-h05e6639_17.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.13-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-hd481e46_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-h0f06f08_4.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-hdb5aac5_5.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.5-h08270f9_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.2-hfea8755_4.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.2-h4b2095a_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-hd481e46_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-hd481e46_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-116-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + taplo: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.16-haed3651_8.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.10-ha9bf9b1_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.14-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.2.18-h4466546_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.4.2-he635cd5_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.8.1-hbfc29b2_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.14.6-h9e7f0e3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.10.3-hffff1cc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.5.2-h4893938_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.1.15-h4466546_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.18-h4466546_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.3-h137ae52_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-he0cb598_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.27.0-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.7-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/just-1.24.0-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20240116.1-cxx17_h59595ed_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-h6bfc85a_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-14.0.2-h59595ed_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-14.0.2-h59595ed_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-14.0.2-hc6145d9_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-sql-14.0.2-h757c851_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hb016d2e_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-14.0.2-h757c851_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-21_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-21_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp16-16.0.6-default_h127d8a8_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-18.1.1-default_h5d6823c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.5.0-hca28451_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.22.0-h9be4e54_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.22.0-hc7a4891_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.62.1-h15f2491_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-21_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm15-15.0.7-hb3ce162_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm16-16.0.6-hb3ce162_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.1-h2448989_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnl-3.9.0-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.26-pthreads_h413a1c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-14.0.2-h352af49_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.25.3-h08a7969_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libre2-11-2023.09.01-h5a48ba9_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.19.0-hb90f79a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.8.0-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.46.0-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.5-h232c23b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.4.0-py311h63ff55d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_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/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-h59595ed_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.19.0-hb753e55_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.0.0-h1e5e2c1_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-50.0-hd3aeb46_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.6-h06160fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.8.1-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.19.0-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h11edf95_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.16-h9d28af5_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.10-hf9de6f9_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.14-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.18-h905ab21_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.2-h30f2259_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.1-hce3b3da_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.6-hf76ed93_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.3-ha335edc_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.5.2-h6f42f56_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.15-h905ab21_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.18-h905ab21_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.3-hf5b2fc6_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h232afc9_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.27.0-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.7-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/just-1.24.0-h11a7dfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20240116.1-cxx17_hc1bcbd7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-he79e29d_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-h000cb23_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-h000cb23_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-h2382776_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-h7e3fe20_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-ha5acb15_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-h7e3fe20_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-21_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-21_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp16-16.0.6-default_h7151d67_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-18.1.1-default_h0edc4dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.5.0-h726d00d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-16.0.6-hd57cbcb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-5.0.0-13_2_0_h97931a8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-13.2.0-h2873a65_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.22.0-h651e89d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.22.0-ha67e85c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.1-h384b2fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-21_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm15-15.0.7-hbedff68_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm16-16.0.6-hbedff68_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.1-hbcf5fad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.26-openmp_hfef2a42_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h381d950_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-h4e4d658_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2023.09.01-h81f5012_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.19.0-h064b379_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.8.0-hb7f2c08_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.47.0-h67532ce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.5-hc0ae0f7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.6-hb6ac08f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.4.0-py311h24bb903_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4-h93d8f39_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.19.0-h119ffd7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.0-h6c6cd50_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.19.0-h11a7dfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.16-h0d2f7a6_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.10-h677d54c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.14-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.2.18-h677d54c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.4.2-h59ac3ca_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.8.1-hfe5d766_7.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.14.6-h9ac2cdb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.10.3-hb8a1441_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.5.2-h4398043_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.1.15-h677d54c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.18-h677d54c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.3-h0de420c_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h2fb64bc_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.27.0-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.7-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.24.0-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20240116.1-cxx17_hebf3989_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h5233fb5_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-14.0.2-h13dd4ca_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-14.0.2-h13dd4ca_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-14.0.2-h95ca633_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-sql-14.0.2-hdc5392b_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-gandiva-14.0.2-hfef958d_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-14.0.2-hef52601_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-21_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-21_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp16-16.0.6-default_he012953_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-18.1.1-default_h83d0a53_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.5.0-h2d989ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-16.0.6-h4653b0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-13_2_0_hd922786_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-13.2.0-hf226fd6_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.22.0-hbebe991_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-2.22.0-h8a76758_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.62.1-h9c18a4f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-21_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm15-15.0.7-h2621b3d_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm16-16.0.6-haab561b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.1-h30cc82d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.26-openmp_h6c19121_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-14.0.2-hf6ce1d5_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-4.25.3-hbfab5d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2023.09.01-h7b2c953_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.19.0-h026a170_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.8.0-h1a8c8d9_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.47.0-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.5-h0d0cfa8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-17.0.6-hcd81f8e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.4.0-py311h71175c2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h463b476_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.19.0-h5f47a4d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.0.0-h3d3088e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.19.0-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-h7613915_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hf6fcf4e_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.14-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-hf6fcf4e_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-h3df98b0_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-h4e3df0f_7.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.6-hf0b8b6f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.3-h96fac68_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.2-h08df315_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-hf6fcf4e_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-hf6fcf4e_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.3-h6047f0a_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h558341a_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h8ffe710_4.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2023.7.22-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/colorlog-4.8.0-py311h1ea47a8_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2023.2.0-h57928b3_50496.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.15.0-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.7-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.0.0-h57928b3_49841.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.24.0-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-hd01637b_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h63175ca_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h63175ca_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-hca4e5ea_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h1ef3bed_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-h6d0e577_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-hf368baa_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-18_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h2a83f13_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h63175ca_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h63175ca_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-h02312f3_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h55b4db4_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-hcb01e45_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-h89268de_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-21_win64_mkl.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlicommon-1.1.0-hcfcfb64_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlidec-1.1.0-hcfcfb64_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlienc-1.1.0-hcfcfb64_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-18_win64_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libclang13-17.0.6-default_h85b4d89_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-21_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libclang13-18.1.1-default_hf64faad_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.5.0-hd5e4a3a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.5.0-h63175ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.21.0-h2b62511_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.21.0-hb581fae_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.61.1-h864d0f4_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.22.0-h9cad5c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.22.0-hb581fae_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.62.1-h5273850_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.9.3-default_haede6df_1009.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.17-h8ffe710_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-18_win64_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h7ec3a38_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.2-h503648d_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.17-hcfcfb64_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-21_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h7ec3a38_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.3-h503648d_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libre2-11-2023.09.01-hf8d8778_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.1-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libthrift-0.19.0-ha2b3283_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libutf8proc-2.8.0-h82a8f57_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.44.2-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.5-hc3477c8_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.4-hcfcfb64_0.conda @@ -1196,36 +1986,61 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.4.0-py311h9a9e57f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/meilisearch-1.5.1-h8b8d39b_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2022.1.0-h6a75c08_874.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.0.0-h66d3029_49657.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.19.0-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/orc-2.0.0-heb0c069_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_13_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.8.1-h7f3b576_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.10.0-h91493d7_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.16.20-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.11.0-h91493d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.19.0-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h64f974e_17.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.36.32532-hdcecf7f_17.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.36.32532-h05e6639_17.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl packages: - kind: conda name: _libgcc_mutex @@ -1257,24 +2072,34 @@ packages: size: 23621 timestamp: 1650670423406 - kind: conda - name: argcomplete - version: 1.12.3 - build: pyhd8ed1ab_2 - build_number: 2 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/argcomplete-1.12.3-pyhd8ed1ab_2.tar.bz2 - sha256: 2abb116f5bdc62d5e83c9dd15e5fc30c2a9571f728ccc012fad03350ed1d581e - md5: b8152341fc3fc9880c6e1b9d188974e5 + name: _openmp_mutex + version: '4.5' + build: 2_gnu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + sha256: 3702bef2f0a4d38bd8288bbe54aace623602a1343c2cfbefd3fa188e015bebf0 + md5: 6168d71addc746e8f2b8d57dfd2edcea depends: - - importlib_metadata >=0.23,<5 - - python >=3.5 - arch: x86_64 - platform: win - license: Apache-2.0 - license_family: Apache - size: 35310 - timestamp: 1619128850100 + - libgomp >=7.5.0 + constrains: + - openmp_impl 9999 + license: BSD-3-Clause + license_family: BSD + size: 23712 + timestamp: 1650670790230 +- kind: pypi + name: argcomplete + version: 3.2.3 + url: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + sha256: c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + requires_dist: + - coverage ; extra == 'test' + - pexpect ; extra == 'test' + - wheel ; extra == 'test' + - ruff ; extra == 'test' + - mypy ; extra == 'test' + requires_python: '>=3.8' - kind: conda name: attrs version: 23.1.0 @@ -1291,6 +2116,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/attrs size: 55022 timestamp: 1683424195402 - kind: conda @@ -1306,6 +2133,8 @@ packages: - python >=3.7 license: MIT license_family: MIT + purls: + - pkg:pypi/attrs size: 54582 timestamp: 1704011393776 - kind: conda @@ -1372,6 +2201,25 @@ packages: license_family: Apache size: 89155 timestamp: 1704306064106 +- kind: conda + name: aws-c-auth + version: 0.7.16 + build: h0d2f7a6_8 + build_number: 8 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.16-h0d2f7a6_8.conda + sha256: 82006dd3067f4d09fd8cee0ea9c4836b6ac0c02db68acd001ff5c7b8669522b5 + md5: a37cb159ebfb3d3adc1a351c98c1027f + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 89205 + timestamp: 1710282202281 - kind: conda name: aws-c-auth version: 0.7.16 @@ -1391,6 +2239,28 @@ packages: license_family: Apache size: 89495 timestamp: 1708633374785 +- kind: conda + name: aws-c-auth + version: 0.7.16 + build: h7613915_8 + build_number: 8 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-h7613915_8.conda + sha256: 9ac4ebfc14faa7377a0df29ebf562d55e04a99d6d72f8ce8bb6a661e4753cde3 + md5: 61c802b7e9c8d6215116c01ce7d582d9 + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 99468 + timestamp: 1710282357839 - kind: conda name: aws-c-auth version: 0.7.16 @@ -1430,6 +2300,65 @@ packages: license_family: Apache size: 90856 timestamp: 1708633418805 +- kind: conda + name: aws-c-auth + version: 0.7.16 + build: h9d28af5_8 + build_number: 8 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.16-h9d28af5_8.conda + sha256: f75a39577b61fc649e3a8c926b91218ebad6ea78beb2f2b16f90d3ae9493c1c4 + md5: 0b451cddce1ea8f9247b386ba3285edc + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 90270 + timestamp: 1710282294532 +- kind: conda + name: aws-c-auth + version: 0.7.16 + build: haed3651_8 + build_number: 8 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.16-haed3651_8.conda + sha256: 75a540b313e5dc212fc0a6057f8a5bee2dda443f17a5a076bd3ea4d7195d483e + md5: ce96c083829ab2727c942243ac93ffe0 + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 103298 + timestamp: 1710281865011 +- kind: conda + name: aws-c-auth + version: 0.7.16 + build: hcac9c52_6 + build_number: 6 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda + sha256: 183846836b1a6fa73ae852137eb1916f3d0f2a9d9569e6b1e5f8720f1ef60eb6 + md5: d2b70bb402aac5cfbfc269d43057fa4d + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 107769 + timestamp: 1708633088332 - kind: conda name: aws-c-auth version: 0.7.16 @@ -1505,6 +2434,21 @@ packages: license_family: Apache size: 39662 timestamp: 1701212885323 +- kind: conda + name: aws-c-cal + version: 0.6.10 + build: h677d54c_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.10-h677d54c_2.conda + sha256: d4f0fa97a3f6f5a090b0c9ed078fedf6b50f19a406d272f8e4b2b214f074323e + md5: a501703d122cdf7cf38c1bbc8c16f981 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 38986 + timestamp: 1709815581194 - kind: conda name: aws-c-cal version: 0.6.10 @@ -1520,6 +2464,40 @@ packages: license_family: Apache size: 45497 timestamp: 1708003974070 +- kind: conda + name: aws-c-cal + version: 0.6.10 + build: h967b9ec_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda + sha256: b92492ab587792933673ac9c2a35f863d23131f57185f8882d39e91cb68163d7 + md5: 70047d857a1c7dfe144be45bf13b94cb + depends: + - aws-c-common >=0.9.13,<0.9.14.0a0 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 48505 + timestamp: 1708003694470 +- kind: conda + name: aws-c-cal + version: 0.6.10 + build: ha9bf9b1_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.10-ha9bf9b1_2.conda + sha256: e45d9f1eb862f566bdea3d3229dfc74f31e647a72198fe04aab58ccc03a30a37 + md5: ce2471034f5459a39636aacc292c96b6 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 55421 + timestamp: 1709815095625 - kind: conda name: aws-c-cal version: 0.6.10 @@ -1555,6 +2533,24 @@ packages: license_family: Apache size: 55726 timestamp: 1708004211846 +- kind: conda + name: aws-c-cal + version: 0.6.10 + build: hf6fcf4e_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hf6fcf4e_2.conda + sha256: 800b25ee5590f3ddd9186e225c756b9e5d00d3ecce8c2de5d9343af85213d883 + md5: 7490ede93a75acc3589a2e43f77c79e9 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 55818 + timestamp: 1709815582485 - kind: conda name: aws-c-cal version: 0.6.10 @@ -1570,6 +2566,21 @@ packages: license_family: Apache size: 39206 timestamp: 1708003965707 +- kind: conda + name: aws-c-cal + version: 0.6.10 + build: hf9de6f9_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.10-hf9de6f9_2.conda + sha256: cb9b20aeec4cd037117fd0bfe2ae5a0a5f6a08a71f941be0f163bb27c87b98ea + md5: 393dbe9973160cb09cb3594c9246e260 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 45249 + timestamp: 1709815427644 - kind: conda name: aws-c-common version: 0.9.10 @@ -1626,6 +2637,20 @@ packages: license_family: Apache size: 208489 timestamp: 1707964779175 +- kind: conda + name: aws-c-common + version: 0.9.13 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.13-h31becfc_0.conda + sha256: 68a7dc87d1c7fefe07f6745acc9c7fffe5d53e1c8cc6b446f97bc3a257df4c7b + md5: 0f2a8f03a8eb0543a400494f444ebcfd + depends: + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 232361 + timestamp: 1707964647676 - kind: conda name: aws-c-common version: 0.9.13 @@ -1659,15 +2684,69 @@ packages: version: 0.9.13 build: hd590300_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.13-hd590300_0.conda - sha256: b113ee0822ff47ae7db10f75802aa0cde60cdada82d5d07e57c36daba146035f - md5: 0ba89522712d993987e6d0fae108c721 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.13-hd590300_0.conda + sha256: b113ee0822ff47ae7db10f75802aa0cde60cdada82d5d07e57c36daba146035f + md5: 0ba89522712d993987e6d0fae108c721 + depends: + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 225560 + timestamp: 1707964559211 +- kind: conda + name: aws-c-common + version: 0.9.14 + build: h10d778d_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.14-h10d778d_0.conda + sha256: 1d207a8aee42700763e6a7801c69721ccc06ce75e62e0e5d8fc6df0197c0a88b + md5: c620ac518f3086eaf4f105f64908a57c + license: Apache-2.0 + license_family: Apache + size: 208228 + timestamp: 1709669491258 +- kind: conda + name: aws-c-common + version: 0.9.14 + build: h93a5062_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.14-h93a5062_0.conda + sha256: c58aea968814459ef485c1f1aeb889423b0fa808b7c1216d96d5282ff2e796ab + md5: 028bc18a1ef8bb1a4e4d6ec94e9b50da + license: Apache-2.0 + license_family: Apache + size: 203827 + timestamp: 1709669473014 +- kind: conda + name: aws-c-common + version: 0.9.14 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.14-hcfcfb64_0.conda + sha256: 46f4dced6c9d553d65e6f721d51ef43e6a343487a3073299c03a073161d7637f + md5: 169998d49ac3c4800187bfc546e1d165 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 222375 + timestamp: 1709669884758 +- kind: conda + name: aws-c-common + version: 0.9.14 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.14-hd590300_0.conda + sha256: c71dd835b1d8c7097c8d152a65680f119a203b73a6a62c5aac414bafe5e997ad + md5: d44fe0d9a6971a4fb245be0055775d9d depends: - libgcc-ng >=12 license: Apache-2.0 license_family: Apache - size: 225560 - timestamp: 1707964559211 + size: 225655 + timestamp: 1709669368566 - kind: conda name: aws-c-compression version: 0.2.17 @@ -1720,6 +2799,68 @@ packages: license_family: Apache size: 18129 timestamp: 1701212675008 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: h00d1b86_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-compression-0.2.18-h00d1b86_1.conda + sha256: f328392d70583dcb5ee49c95059fe086bafaae0d65c38bb9ec0b98ec6fb6a8fd + md5: 16f4516d03cbc0aba2bdda73db85ca37 + depends: + - aws-c-common >=0.9.13,<0.9.14.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 19873 + timestamp: 1708003535938 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: h4466546_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.2.18-h4466546_2.conda + sha256: 7fcc6a924691f9de65c82fd559cb1cb2ebd121c42da544a9a43623d69a284e23 + md5: b0d9153fc7cfa8dc36b8703e1a59f5f3 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 19072 + timestamp: 1709815144275 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: h677d54c_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.2.18-h677d54c_2.conda + sha256: bbc73d8ec3d760d528f15edad66835d1fe63a035f254e760235e745cf360de20 + md5: 71e953c1c0fac25dd5d65d63d47389d8 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 17911 + timestamp: 1709815495665 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: h905ab21_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.18-h905ab21_2.conda + sha256: 021cee135f0d9b58fbc8d212618cd9bd6bd0012da41a6469edf010b2853dd3ef + md5: ffd7cfb55b1aa4e3eef477583b1ad87d + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 17930 + timestamp: 1709815482244 - kind: conda name: aws-c-compression version: 0.2.18 @@ -1769,6 +2910,24 @@ packages: license_family: Apache size: 18067 timestamp: 1708003629797 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: hf6fcf4e_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-hf6fcf4e_2.conda + sha256: ecb5ab2353c4499311fe17c82210955a498526c9563861777b3b0cd6dcc5cfea + md5: 6efdf7af73d7043a00394a2f1b039650 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 22366 + timestamp: 1709815905155 - kind: conda name: aws-c-compression version: 0.2.18 @@ -1862,6 +3021,25 @@ packages: license_family: Apache size: 54585 timestamp: 1708602875487 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: h128c7ac_4 + build_number: 4 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-event-stream-0.4.2-h128c7ac_4.conda + sha256: 7e75f646a79e5eff69e9a73d859cdc94ae76a9a9d72f519ebef8314dfe331993 + md5: ff4fb2adfeee5bb13494feac3bc91b6b + depends: + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 55186 + timestamp: 1708602558232 - kind: conda name: aws-c-event-stream version: 0.4.2 @@ -1880,6 +3058,62 @@ packages: license_family: Apache size: 46870 timestamp: 1708602815747 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: h30f2259_6 + build_number: 6 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.2-h30f2259_6.conda + sha256: 65ea5552f7a87783b75a3ecf6e4acd2aee5357c4275a9932d732ee516acab0a9 + md5: 0923a8e81839b0b2d9787d85d635b196 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 46261 + timestamp: 1710264045535 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: h3df98b0_6 + build_number: 6 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-h3df98b0_6.conda + sha256: 823a4665b3d38a4078b34b6f891bd388400942a3bcbad55b4c6223c559b15de6 + md5: 80ca7e9993f6b0141ae5425a69771a9a + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 54211 + timestamp: 1710264185867 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: h59ac3ca_6 + build_number: 6 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.4.2-h59ac3ca_6.conda + sha256: 86db342fd921f17a50cf7648b45566b2449ac1408a94c2e6cae132b876f1c17c + md5: 7278d0ef10644f95a2dd619b9917e8a2 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 47119 + timestamp: 1710264020154 - kind: conda name: aws-c-event-stream version: 0.4.2 @@ -1898,6 +3132,25 @@ packages: license_family: Apache size: 46676 timestamp: 1708602620909 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: he635cd5_6 + build_number: 6 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.4.2-he635cd5_6.conda + sha256: 38a30beabafc1dd86c0264b6746315a1010e541a1b3ed7f97e1702873e5eaa51 + md5: 58fc78e523e35a08423c913751a51fde + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 53665 + timestamp: 1710263650074 - kind: conda name: aws-c-event-stream version: 0.4.2 @@ -1993,6 +3246,27 @@ packages: license_family: Apache size: 163076 timestamp: 1708602693889 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: h4e3df0f_7 + build_number: 7 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-h4e3df0f_7.conda + sha256: 651bdcbe53630bf9665b76c18a6cb21a7b53fe347b03d88c1cb99ed0281c267e + md5: 08ba30d73686a5129f4209c25b31252a + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 180557 + timestamp: 1710264351681 - kind: conda name: aws-c-http version: 0.8.1 @@ -2012,6 +3286,43 @@ packages: license_family: Apache size: 195024 timestamp: 1708602547845 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: hbfc29b2_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.8.1-hbfc29b2_7.conda + sha256: 0dc5b73aa31cef3faeeb902a11f12e1244ac241f995d73e4f4e3e0c01622f7a1 + md5: 8476ec099649e9a6de52f7f4d916cd2a + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 194307 + timestamp: 1710263686092 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: hce3b3da_7 + build_number: 7 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.1-hce3b3da_7.conda + sha256: a3e6bfd71bbc4119da1e79f2bce6094f045112c230b3fd5cc9e6ccd36aba3156 + md5: d287122dfb77c5fa0147fdf368c86d54 + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + license: Apache-2.0 + license_family: Apache + size: 162710 + timestamp: 1710263951106 - kind: conda name: aws-c-http version: 0.8.1 @@ -2033,6 +3344,25 @@ packages: license_family: Apache size: 180105 timestamp: 1708603146126 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: he0aa6e1_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-http-0.8.1-he0aa6e1_5.conda + sha256: 40f254d4012a60733bc5428414bd72787d2198b8238a0d0dc799a0e666f3d788 + md5: 1397fefc62656680d66570c23d875198 + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 188613 + timestamp: 1708602656753 - kind: conda name: aws-c-http version: 0.8.1 @@ -2051,6 +3381,24 @@ packages: license_family: Apache size: 151481 timestamp: 1708602772972 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: hfe5d766_7 + build_number: 7 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.8.1-hfe5d766_7.conda + sha256: 0a454c1280e87b4bfd3ab1d70498c5f60c62139ddcd06d1a68c39dcd81e05e75 + md5: 4096407e9d908ef9a292980f93034fcd + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + license: Apache-2.0 + license_family: Apache + size: 151329 + timestamp: 1710264327114 - kind: conda name: aws-c-io version: 0.13.36 @@ -2126,6 +3474,24 @@ packages: license_family: Apache size: 159778 timestamp: 1708688290150 +- kind: conda + name: aws-c-io + version: 0.14.5 + build: h2bbb85f_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-io-0.14.5-h2bbb85f_1.conda + sha256: a6d25f44ec1b64387ede38fd8b066d7e3eedc77a4e9bb95197ec8a77fa02b236 + md5: 40573930eba2a6f2f19c16635457962f + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.13,<0.9.14.0a0 + - libgcc-ng >=12 + - s2n >=1.4.5,<1.4.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 160898 + timestamp: 1708687797361 - kind: conda name: aws-c-io version: 0.14.5 @@ -2176,6 +3542,70 @@ packages: license_family: Apache size: 136989 timestamp: 1708687976415 +- kind: conda + name: aws-c-io + version: 0.14.6 + build: h9ac2cdb_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.14.6-h9ac2cdb_0.conda + sha256: 1dcae62df79786292e841275994c9ded564eb49d7200284c09f7d61326a06c1b + md5: b0c80a8220ddc90196e3b76d856dc6b0 + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 136547 + timestamp: 1710222457819 +- kind: conda + name: aws-c-io + version: 0.14.6 + build: h9e7f0e3_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.14.6-h9e7f0e3_0.conda + sha256: bb9e7bee234532f7905faf4abc15e3a1be1d8f683b8a0d5863761daad18a7cac + md5: 3fef14ef6e79ea0da149cebb1d0635bf + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - s2n >=1.4.6,<1.4.7.0a0 + license: Apache-2.0 + license_family: Apache + size: 157726 + timestamp: 1710222250665 +- kind: conda + name: aws-c-io + version: 0.14.6 + build: hf0b8b6f_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.6-hf0b8b6f_0.conda + sha256: ab046e34dcaa533d75f8f4892c63ec503812a69fa6e8d23bfbdb0d74926cdc40 + md5: aee3f042f60da448ab622b0a149d6ec2 + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 160412 + timestamp: 1710222753707 +- kind: conda + name: aws-c-io + version: 0.14.6 + build: hf76ed93_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.6-hf76ed93_0.conda + sha256: 824eb1fcf69f67c4fee4e05fd401dba6d5c55f9e37e3cb9904b8b81909e3c3be + md5: 586e11f2969f1f2a61104c5cec8a7957 + depends: + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 137968 + timestamp: 1710222523409 - kind: conda name: aws-c-mqtt version: 0.10.0 @@ -2286,6 +3716,24 @@ packages: license_family: Apache size: 164421 timestamp: 1708620822368 +- kind: conda + name: aws-c-mqtt + version: 0.10.2 + build: hf974719_4 + build_number: 4 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-mqtt-0.10.2-hf974719_4.conda + sha256: 8f24dc8fa19429c4599159ae9a68f2e90418e3471adb273fab112cd122cba0af + md5: 9addf6456c59c94686fe2dfdd9f8c43d + depends: + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 146210 + timestamp: 1708620468353 - kind: conda name: aws-c-mqtt version: 0.10.2 @@ -2306,6 +3754,78 @@ packages: license_family: Apache size: 157819 timestamp: 1708621381498 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: h96fac68_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.3-h96fac68_2.conda + sha256: 70b62dcf6314a9e1f514fe6f838eb02dfc4a28f4d17723768211a60c28c3429b + md5: 463c0be9e1fb416192174156f58bb2af + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 157436 + timestamp: 1710283031953 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: ha335edc_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.3-ha335edc_2.conda + sha256: 99304e5095193b937745d0ce6812d0333186a31c41a51b1e4297ddcd962824eb + md5: c8bacb9a988fd8fb6b560a966c4979a8 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + license: Apache-2.0 + license_family: Apache + size: 139008 + timestamp: 1710282888188 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: hb8a1441_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.10.3-hb8a1441_2.conda + sha256: 344ba23eb2cd45105a09d775dd7449e17304b3930d5ff08fbc1426f0f8030b08 + md5: 26421a2d8a329048bb1a5673ce620de5 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + license: Apache-2.0 + license_family: Apache + size: 117955 + timestamp: 1710282576148 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: hffff1cc_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.10.3-hffff1cc_2.conda + sha256: 6b2de4a0e6e907310127b1025a0030d023e1051da48ea5821dcc6db094d69ab7 + md5: 14ad8defb307e1edb293c3fc9da8648f + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 163172 + timestamp: 1710282530222 - kind: conda name: aws-c-s3 version: 0.4.7 @@ -2372,8 +3892,31 @@ packages: platform: osx license: Apache-2.0 license_family: Apache - size: 90455 - timestamp: 1704321754265 + size: 90455 + timestamp: 1704321754265 +- kind: conda + name: aws-c-s3 + version: 0.5.2 + build: h08df315_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.2-h08df315_2.conda + sha256: 2f7af939a87176de471bac1a1c6cc7336c714a64c495f1a5d967e0cfa7bb0e07 + md5: 0a7a232878640624469d3ca4923d146b + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 101487 + timestamp: 1710296653111 - kind: conda name: aws-c-s3 version: 0.5.2 @@ -2393,6 +3936,69 @@ packages: license_family: Apache size: 90732 timestamp: 1709172899774 +- kind: conda + name: aws-c-s3 + version: 0.5.2 + build: h170583c_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-s3-0.5.2-h170583c_0.conda + sha256: a1ff6af6f8c03eb4f4d738a2bab006ad7c46580bef9613b2f53b0d98c47b1192 + md5: b8c6ea0b0244487e9cc579393c1dbf70 + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 109725 + timestamp: 1709172552237 +- kind: conda + name: aws-c-s3 + version: 0.5.2 + build: h4398043_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.5.2-h4398043_2.conda + sha256: 27e90ada0ae6895159a49bc4ed7172b2757cd8fc63e0189dd8cce5d057c6ee06 + md5: 5ddebd5447f4baba6215b1bafcf605dc + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + license: Apache-2.0 + license_family: Apache + size: 90478 + timestamp: 1710296516337 +- kind: conda + name: aws-c-s3 + version: 0.5.2 + build: h4893938_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.5.2-h4893938_2.conda + sha256: 312d67b236c9c6003f92f682c55ff344721f79d50d9a4bcdea44f2144f637642 + md5: 7e24759a8b8ead67ce687f3c31ffd12f + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 105455 + timestamp: 1710296220268 - kind: conda name: aws-c-s3 version: 0.5.2 @@ -2436,6 +4042,26 @@ packages: license_family: Apache size: 101468 timestamp: 1709173131467 +- kind: conda + name: aws-c-s3 + version: 0.5.2 + build: h6f42f56_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.5.2-h6f42f56_2.conda + sha256: 950a37ab27ec0145a4c92a3524b8862a4f5affec08049dda7b9ab83403969fd6 + md5: 9f5dc9ef044d3c13b0959d04a2005753 + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + license: Apache-2.0 + license_family: Apache + size: 91371 + timestamp: 1710296654896 - kind: conda name: aws-c-s3 version: 0.5.2 @@ -2504,6 +4130,68 @@ packages: license_family: Apache size: 47467 timestamp: 1701999663058 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: h00d1b86_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-sdkutils-0.1.15-h00d1b86_1.conda + sha256: e2ec786734acca3a7449f27aee7052f93e627a76459c3718a4d9236b0e813dad + md5: 222e0288b02a00e62232dde9ff479146 + depends: + - aws-c-common >=0.9.13,<0.9.14.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 57857 + timestamp: 1708014280193 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: h4466546_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.1.15-h4466546_2.conda + sha256: 349a05cf5fbcb3f6f358fc05098b210aa7da4ec3ab6d4719c79bb93b50a629f8 + md5: 258194cedccd33fd8a7b95a8aa105015 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 55383 + timestamp: 1709830510021 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: h677d54c_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.1.15-h677d54c_2.conda + sha256: 02649707625df0c8908fd807f5d599b5f60b90d7b4e0e71953ff10b9aa0f010c + md5: a68e269534f50d5a94107b9b9b6be747 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 48880 + timestamp: 1709830883787 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: h905ab21_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.15-h905ab21_2.conda + sha256: 77f58ac3aec0cd987f80e202a8197e123beb13b9b25b0137dd921c7a6ddc86ac + md5: bb1523b7de7ac6f112b1992cfcfb250b + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 50028 + timestamp: 1709830709542 - kind: conda name: aws-c-sdkutils version: 0.1.15 @@ -2553,6 +4241,24 @@ packages: license_family: Apache size: 50255 timestamp: 1708014587926 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: hf6fcf4e_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-hf6fcf4e_2.conda + sha256: 03f361182431688732e7173f0d71e5778e0616e68d9ebf994d3ecb70483468a0 + md5: 87fb9f67d4c936a704d6a23a748fad77 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 54282 + timestamp: 1709830762581 - kind: conda name: aws-c-sdkutils version: 0.1.15 @@ -2620,6 +4326,68 @@ packages: license_family: Apache size: 48848 timestamp: 1701246965518 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: h00d1b86_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-checksums-0.1.18-h00d1b86_1.conda + sha256: abe3046db1238044d236c01512d41ca743812510bc39da9d0d2b9726520e82df + md5: c4824ce78b16799e1f93e7f9b0f56b5e + depends: + - aws-c-common >=0.9.13,<0.9.14.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 50114 + timestamp: 1708017850698 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: h4466546_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.18-h4466546_2.conda + sha256: 9080f064f572ac1747d32b4dff30452ff44ef2df399e6ec7bf9730da1eb99bba + md5: 8a04fc5a5ecaba31f66904b47dcc7797 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 49940 + timestamp: 1709826415680 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: h677d54c_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.18-h677d54c_2.conda + sha256: 3a7cc8824a23a39478e479865df20d88c12a954895fb9c8a91152cc76976183a + md5: 21b73ab89b82b17ae50d635ce675fea6 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 48836 + timestamp: 1709826804838 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: h905ab21_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.18-h905ab21_2.conda + sha256: 5760728e7320a01519bcbbae8dcd31b86e819f66c58f641b86b27ce592e5fff3 + md5: f17e778398011e88d45edf58f24c18ae + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + license: Apache-2.0 + license_family: Apache + size: 48733 + timestamp: 1709826868797 - kind: conda name: aws-checksums version: 0.1.18 @@ -2669,6 +4437,24 @@ packages: license_family: Apache size: 48808 timestamp: 1708017957232 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: hf6fcf4e_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-hf6fcf4e_2.conda + sha256: 1a67c0ee80cb2d18bd7cfc9ec1aae2ad78d51adc7ac9442ec70e370bbcef24de + md5: ffa6601a628ccc6ec5eddb0def2db1d2 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 52016 + timestamp: 1709827173669 - kind: conda name: aws-checksums version: 0.1.18 @@ -2787,6 +4573,31 @@ packages: license_family: Apache size: 216464 timestamp: 1709208473555 +- kind: conda + name: aws-crt-cpp + version: 0.26.2 + build: h07bb24a_7 + build_number: 7 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.2-h07bb24a_7.conda + sha256: 08b125c53613c7363bba10b90543fe9744b5b5412cf01c635b795a5e586c0ff4 + md5: bfd628a5808085446ae16cbdfb0b934b + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - aws-c-mqtt >=0.10.2,<0.10.3.0a0 + - aws-c-s3 >=0.5.2,<0.5.3.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 260420 + timestamp: 1709208294949 - kind: conda name: aws-crt-cpp version: 0.26.2 @@ -2802,66 +4613,165 @@ packages: - aws-c-common >=0.9.13,<0.9.14.0a0 - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.5,<0.14.6.0a0 - - aws-c-mqtt >=0.10.2,<0.10.3.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - aws-c-mqtt >=0.10.2,<0.10.3.0a0 + - aws-c-s3 >=0.5.2,<0.5.3.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 333814 + timestamp: 1709208341782 +- kind: conda + name: aws-crt-cpp + version: 0.26.2 + build: h56a5195_7 + build_number: 7 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.2-h56a5195_7.conda + sha256: 3899ccca939b94adde813be207181cfae00d1211efa68613d4ba1828c9a39f0a + md5: 62ae597a0641cbcbf68a06beec4ac313 + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - aws-c-mqtt >=0.10.2,<0.10.3.0a0 + - aws-c-s3 >=0.5.2,<0.5.3.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 280702 + timestamp: 1709208918309 +- kind: conda + name: aws-crt-cpp + version: 0.26.2 + build: h8492d2a_7 + build_number: 7 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda + sha256: 99bd606407c723da49ce9e831d2764849d44b48d9d7bfd8b36db20edda301ded + md5: 444af8c6a4c76298b6322807c25df166 + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.5,<0.14.6.0a0 + - aws-c-mqtt >=0.10.2,<0.10.3.0a0 + - aws-c-s3 >=0.5.2,<0.5.3.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 242812 + timestamp: 1709208518468 +- kind: conda + name: aws-crt-cpp + version: 0.26.3 + build: h0de420c_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.3-h0de420c_2.conda + sha256: 578ffab0c981ea227d5a9d70b32af5bcba58c632d0f8b38d4eb1ed88cc05eaaa + md5: e6d964373064af06199c6e4dff9f174e + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 + - aws-c-s3 >=0.5.2,<0.5.3.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 218109 + timestamp: 1710309757551 +- kind: conda + name: aws-crt-cpp + version: 0.26.3 + build: h137ae52_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.3-h137ae52_2.conda + sha256: 596b6d63352b7ae189842dc86510d53438f88d1e2c1d56779eeebc130beef2b6 + md5: 21c8acfdfa31ab5582897dda7c9c8a75 + depends: + - aws-c-auth >=0.7.16,<0.7.17.0a0 + - aws-c-cal >=0.6.10,<0.6.11.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 - aws-c-s3 >=0.5.2,<0.5.3.0a0 - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - libgcc-ng >=12 - libstdcxx-ng >=12 license: Apache-2.0 license_family: Apache - size: 333814 - timestamp: 1709208341782 + size: 333634 + timestamp: 1710309442818 - kind: conda name: aws-crt-cpp - version: 0.26.2 - build: h56a5195_7 - build_number: 7 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.2-h56a5195_7.conda - sha256: 3899ccca939b94adde813be207181cfae00d1211efa68613d4ba1828c9a39f0a - md5: 62ae597a0641cbcbf68a06beec4ac313 + version: 0.26.3 + build: h6047f0a_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.3-h6047f0a_2.conda + sha256: 1cb3c3f8d0b19dad52eaa64758629f47aea88591cf3bc354fcb87c0923dc9e73 + md5: 5c8a2ba1c7a6477b10d0bcd33ee1202f depends: - aws-c-auth >=0.7.16,<0.7.17.0a0 - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.5,<0.14.6.0a0 - - aws-c-mqtt >=0.10.2,<0.10.3.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 - aws-c-s3 >=0.5.2,<0.5.3.0a0 - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - - libcxx >=16 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 license: Apache-2.0 license_family: Apache - size: 280702 - timestamp: 1709208918309 + size: 242851 + timestamp: 1710309795536 - kind: conda name: aws-crt-cpp - version: 0.26.2 - build: h8492d2a_7 - build_number: 7 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda - sha256: 99bd606407c723da49ce9e831d2764849d44b48d9d7bfd8b36db20edda301ded - md5: 444af8c6a4c76298b6322807c25df166 + version: 0.26.3 + build: hf5b2fc6_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.3-hf5b2fc6_2.conda + sha256: d4ec9488f2052276b4b119e62b2b08df52deec3e38dc7c57311f51413046de8b + md5: bcea6861674e784e2eb2f1de4f3bac35 depends: - aws-c-auth >=0.7.16,<0.7.17.0a0 - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-common >=0.9.14,<0.9.15.0a0 - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.5,<0.14.6.0a0 - - aws-c-mqtt >=0.10.2,<0.10.3.0a0 + - aws-c-io >=0.14.6,<0.14.7.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 - aws-c-s3 >=0.5.2,<0.5.3.0a0 - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - libcxx >=16 license: Apache-2.0 license_family: Apache - size: 242812 - timestamp: 1709208518468 + size: 280273 + timestamp: 1710309758427 - kind: conda name: aws-sdk-cpp version: 1.11.210 @@ -2935,6 +4845,50 @@ packages: license_family: Apache size: 3267017 timestamp: 1704353210503 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: h232afc9_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h232afc9_3.conda + sha256: d83b5e4728d61f996115251fbb1670b79c6b5c0a02f2f1f458b80a6b06b08eb1 + md5: f707d57fee350a6b47726b2996f8e4e1 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.3,<0.26.4.0a0 + - libcurl >=8.5.0,<9.0a0 + - libcxx >=16 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 3367065 + timestamp: 1710323636919 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: h2fb64bc_3 + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h2fb64bc_3.conda + sha256: 5ad2be70779844380b8b8567814ed3966ef2efd9c48cc258975cec7f072c9753 + md5: e11e8d3c0ca63039e4b8101a5063fa30 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.3,<0.26.4.0a0 + - libcurl >=8.5.0,<9.0a0 + - libcxx >=16 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 3423557 + timestamp: 1710323443841 - kind: conda name: aws-sdk-cpp version: 1.11.267 @@ -2957,6 +4911,28 @@ packages: license_family: Apache size: 3375381 timestamp: 1708527712169 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: h558341a_3 + build_number: 3 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h558341a_3.conda + sha256: 886817ef6b059f715ab3d93025d5306c5046688fdbdade21f6fb3ce33e053561 + md5: 42633be391d0a113f39356a37ce7ea40 + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.3,<0.26.4.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 3409008 + timestamp: 1710323920901 - kind: conda name: aws-sdk-cpp version: 1.11.267 @@ -3024,65 +5000,125 @@ packages: license_family: Apache size: 3413748 timestamp: 1708528552370 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: he0cb598_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-he0cb598_3.conda + sha256: 55bf5d47ba2591507abb9b2120905cdb0b1834b2867f03c6cff4bb88f7ec7c58 + md5: ca4aebdc89bb9b08b3b6dd68ae09080d + depends: + - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.3,<0.26.4.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 3636564 + timestamp: 1710322529863 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: hfce6cab_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda + sha256: 735f6c624215c384ad89729debf176620299e2923f8981d7e2acbb44cda6c52d + md5: 0d759609cfe4bd61b7a90f2d29185d84 + depends: + - aws-c-common >=0.9.13,<0.9.14.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.2,<0.26.3.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 3409636 + timestamp: 1708527387032 - kind: conda name: binaryen - version: '116' - build: h13dd4ca_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-116-h13dd4ca_0.conda - sha256: 80aba7f9d8f311ba103e6a4806231a404b0f39f130be5af07ea9574cd42afebf - md5: e4aad775b4f2c3b336b8e2eea63eaff2 + version: '117' + build: h2f0025b_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda + sha256: 3820ab878d1a20792271a37440da1d304b36e26effff6f302592d5098cefa496 + md5: 69f34782ba69df988531f13d6bcc4385 depends: - - libcxx >=15.0.7 + - libgcc-ng >=12 + - libstdcxx-ng >=12 license: Apache-2.0 - license_family: APACHE - size: 3505018 - timestamp: 1694723361260 + size: 5372762 + timestamp: 1710444374732 - kind: conda name: binaryen - version: '116' + version: '117' build: h59595ed_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/binaryen-116-h59595ed_0.conda - sha256: 84704b46b2bfde6d35fdd479bfe2769a6ef4c899677618ce1d6f8c926657cbf8 - md5: 52dff2370624a2be1e323c41e3882ed4 + url: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda + sha256: f6d7f876c514d2d138fd8b06e485b042598cf3dcda40a8a346252bb7e1adf8d7 + md5: 58aea5eaef8cb663104654734d432ba3 depends: - libgcc-ng >=12 - libstdcxx-ng >=12 license: Apache-2.0 license_family: APACHE - size: 5215096 - timestamp: 1694722302360 + size: 5783056 + timestamp: 1709092512197 - kind: conda name: binaryen - version: '116' + version: '117' build: h63175ca_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/binaryen-116-h63175ca_0.conda - sha256: 531c4be009192cfb1b53ef1724fc3c670d16f629c20a77b5664b90f3c4d048c9 - md5: eee203f471868cf9c078ddfae586f221 + url: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda + sha256: 2cc0e433360f7c4a5ce8e2b5f8960cfba8675b6b3232830da7e6f8403c6b4186 + md5: b0028cf00bb7d8f3fd8075de8165b1a8 depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: Apache-2.0 license_family: APACHE - size: 36575639 - timestamp: 1694723421705 + size: 40046563 + timestamp: 1709093094826 - kind: conda name: binaryen - version: '116' - build: he965462_0 + version: '117' + build: h73e2aa4_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/binaryen-116-he965462_0.conda - sha256: ccdf062ca035f8087619c454d3a676dd1598626ee753799cdf8cba1e497bebbd - md5: 8c5fcc736f62d68f1807f87b3f36708b + url: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda + sha256: f1dae7bbbdae9ee2f4b3479b51578fc67e77d54c5c235a5e5c7c1c58b2fff13e + md5: 029b1d804ba237f99163740225d53abc depends: - - libcxx >=15.0.7 + - libcxx >=16 license: Apache-2.0 license_family: APACHE - size: 3440338 - timestamp: 1694723081095 + size: 3797571 + timestamp: 1709093347983 +- kind: conda + name: binaryen + version: '117' + build: hebf3989_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda + sha256: 9f4696ff6bf7a43261e549c1142dc24f45905fff68a6c0a1ebbdd0a84acd9056 + md5: 26d849f5539e7e20d8b7465a3616a622 + depends: + - libcxx >=16 + license: Apache-2.0 + license_family: APACHE + size: 3466426 + timestamp: 1709092708128 - kind: conda name: binutils version: '2.40' @@ -3209,6 +5245,49 @@ packages: license_family: MIT size: 386618 timestamp: 1708248490085 +- kind: conda + name: black + version: 24.2.0 + build: py311hec3470c_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/black-24.2.0-py311hec3470c_0.conda + sha256: 44600ae70a8fca4ea1fda9c86818e2a5a58c23b3b03a27b1de9079f5f022c193 + md5: 5f1d486090d858df5fd90f2137b27e53 + depends: + - click >=8.0.0 + - mypy_extensions >=0.4.3 + - packaging >=22.0 + - pathspec >=0.9 + - platformdirs >=2 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + size: 386639 + timestamp: 1708248423560 +- kind: conda + name: blackdoc + version: 0.3.8 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + sha256: ec7b75c0f88db3e8c8b506ec48fa4fa210b0c1d09b0969df726a68b5563d151d + md5: c03749cb0d5874fd5b9c1620a3d230c4 + depends: + - black + - importlib-metadata + - more-itertools + - python >=3.7 + - rich + - tomli + license: MIT + license_family: MIT + purls: + - pkg:pypi/blackdoc + size: 30092 + timestamp: 1667565048643 - kind: conda name: blackdoc version: 0.3.8 @@ -3229,6 +5308,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/blackdoc size: 30092 timestamp: 1667565048643 - kind: conda @@ -3259,6 +5340,21 @@ packages: license_family: BSD size: 127885 timestamp: 1699280178474 +- kind: conda + name: bzip2 + version: 1.0.8 + build: h31becfc_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda + sha256: b9f170990625cb1eeefaca02e091dc009a64264b077166d8ed7aeb7a09e923b0 + md5: a64e35f01e0b7a2a152eca87d33b9c87 + depends: + - libgcc-ng >=12 + license: bzip2-1.0.6 + license_family: BSD + size: 189668 + timestamp: 1699280060686 - kind: conda name: bzip2 version: 1.0.8 @@ -3436,6 +5532,44 @@ packages: license_family: MIT size: 162725 timestamp: 1706299899438 +- kind: conda + name: c-ares + version: 1.27.0 + build: h10d778d_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.27.0-h10d778d_0.conda + sha256: a53e14c071dcce756ce80673f2a90a1c6dff695a26bc9f5e54d56b55e76ee3dc + md5: 713dd57081dfe8535eb961b45ed26a0c + license: MIT + license_family: MIT + size: 148568 + timestamp: 1708685147963 +- kind: conda + name: c-ares + version: 1.27.0 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda + sha256: 4152e674377179b35d59ddd9218411477a206ecff5f5939dfc963f997cf3b8b8 + md5: f03f76a77d690f2d31ce12e7b4e12ae4 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 170421 + timestamp: 1708684764494 +- kind: conda + name: c-ares + version: 1.27.0 + build: h93a5062_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.27.0-h93a5062_0.conda + sha256: a168e53ee462980cd78b324e055afdd00080ded378ca974969a0917eb4ae1ccb + md5: d3579ba506791b1f8f8a16cfc2885326 + license: MIT + license_family: MIT + size: 145697 + timestamp: 1708685057216 - kind: conda name: c-ares version: 1.27.0 @@ -3452,6 +5586,20 @@ packages: license_family: MIT size: 153934 timestamp: 1708685329364 +- kind: conda + name: c-ares + version: 1.27.0 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.27.0-hd590300_0.conda + sha256: 2a5866b19d28cb963fab291a62ff1c884291b9d6f59de14643e52f103e255749 + md5: f6afff0e9ee08d2f1b897881a4f38cdb + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 163578 + timestamp: 1708684786032 - kind: conda name: c-compiler version: 1.6.0 @@ -3584,6 +5732,17 @@ packages: license: ISC size: 155432 timestamp: 1706843687645 +- kind: conda + name: ca-certificates + version: 2024.2.2 + build: hcefe29a_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + sha256: 0f6b34d835e26e5fa97cca4985dc46f0aba551a3a23f07c6f13cca2542b8c642 + md5: 57c226edb90c4e973b9b7503537dd339 + license: ISC + size: 155738 + timestamp: 1706845723412 - kind: conda name: ca-certificates version: 2024.2.2 @@ -3805,6 +5964,25 @@ packages: license_family: Apache size: 692537 timestamp: 1706894104516 +- kind: conda + name: clang-format + version: 16.0.6 + build: default_h127d8a8_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_5.conda + sha256: 8ae23380654712d8e8440871419cd8409903c3e2fd7c051978f2923e662a9c92 + md5: 1fe9ee2e961ecae22f5a0413b34f9f5d + depends: + - clang-format-16 16.0.6 default_h127d8a8_5 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 21690 + timestamp: 1709765119029 - kind: conda name: clang-format version: 16.0.6 @@ -3859,6 +6037,25 @@ packages: license_family: Apache size: 21613 timestamp: 1704262844623 +- kind: conda + name: clang-format + version: 16.0.6 + build: default_hb368394_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda + sha256: e56e743bc4db5e85cebc479479c8ac6fd8be73effb3d40071f027b5ead77be8a + md5: 566748cfa5d501ed00b28612daa0bae7 + depends: + - clang-format-16 16.0.6 default_hb368394_5 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 21892 + timestamp: 1706896136958 - kind: conda name: clang-format version: 16.0.6 @@ -3877,6 +6074,24 @@ packages: license_family: Apache size: 21914 timestamp: 1706894694897 +- kind: conda + name: clang-format-16 + version: 16.0.6 + build: default_h127d8a8_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_5.conda + sha256: 9843007a8ffd53008240aec77b74068733daf5a00c60480d0978d05146511522 + md5: 72cd7fd253434f1c6c6ee0af962ee700 + depends: + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 61980 + timestamp: 1709765062005 - kind: conda name: clang-format-16 version: 16.0.6 @@ -3912,6 +6127,24 @@ packages: license_family: Apache size: 61766 timestamp: 1704262713061 +- kind: conda + name: clang-format-16 + version: 16.0.6 + build: default_hb368394_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda + sha256: 9c7bb588c975f100298736a0d4582a4b860071bb31ca195c2bdeaa1644681510 + md5: fb61b4171f7357ed8a6e38be8782628f + depends: + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 63067 + timestamp: 1706896079312 - kind: conda name: clang-format-16 version: 16.0.6 @@ -3927,8 +6160,34 @@ packages: - libllvm16 >=16.0.6,<16.1.0a0 license: Apache-2.0 WITH LLVM-exception license_family: Apache - size: 56848 - timestamp: 1706894594045 + size: 56848 + timestamp: 1706894594045 +- kind: conda + name: clang-tools + version: 16.0.6 + build: default_h127d8a8_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_5.conda + sha256: 4b1c26e1058995181efcbd31b9d952241f9c561aad79ca6b7261ec7dc4796bd7 + md5: a85978ea2f9ea8b3a0c0b5ccea48a42e + depends: + - clang-format 16.0.6 default_h127d8a8_5 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libclang13 >=16.0.6 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + constrains: + - clangdev 16.0.6 + - clang 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 26812015 + timestamp: 1709765163586 - kind: conda name: clang-tools version: 16.0.6 @@ -4008,6 +6267,32 @@ packages: license_family: Apache size: 26681224 timestamp: 1704262959552 +- kind: conda + name: clang-tools + version: 16.0.6 + build: default_hb368394_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda + sha256: e7fa9cf87f0cfda820c177247dd184ecd139751d43219dc864c665b02f4944a7 + md5: 7e2843f2ab82c0d7f31d07b4eafd105f + depends: + - clang-format 16.0.6 default_hb368394_5 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libclang13 >=16.0.6 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + constrains: + - clangdev 16.0.6 + - clang 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 26926170 + timestamp: 1706896230135 - kind: conda name: clang-tools version: 16.0.6 @@ -4199,6 +6484,24 @@ packages: license_family: BSD size: 19330 timestamp: 1706832814124 +- kind: conda + name: click + version: 8.1.7 + build: unix_pyh707e725_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + sha256: f0016cbab6ac4138a429e28dbcb904a90305b34b3fe41a9b89d697c90401caec + md5: f3ad426304898027fc619827ff428eca + depends: + - __unix + - python >=3.8 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/click + size: 84437 + timestamp: 1692311973840 - kind: conda name: click version: 8.1.7 @@ -4215,8 +6518,29 @@ packages: platform: osx license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/click size: 84437 timestamp: 1692311973840 +- kind: conda + name: click + version: 8.1.7 + build: win_pyh7428d3b_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda + sha256: 90236b113b9a20041736e80b80ee965167f9aac0468315c55e2bad902d673fb0 + md5: 3549ecbceb6cd77b91a105511b7d0786 + depends: + - __win + - colorama + - python >=3.8 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/click + size: 85051 + timestamp: 1692312207348 - kind: conda name: click version: 8.1.7 @@ -4234,6 +6558,8 @@ packages: platform: win license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/click size: 85051 timestamp: 1692312207348 - kind: conda @@ -4283,6 +6609,30 @@ packages: license_family: BSD size: 18494905 timestamp: 1695269729661 +- kind: conda + name: cmake + version: 3.27.6 + build: hef020d8_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda + sha256: 099e3d6deac7fc29251552f87b59ee7299582caf291a20de71107327a4aded57 + md5: e20b2e0185007a671ebbb72f4353d70b + depends: + - bzip2 >=1.0.8,<2.0a0 + - libcurl >=8.3.0,<9.0a0 + - libexpat >=2.5.0,<3.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libuv >=1.46.0,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ncurses >=6.4,<7.0a0 + - rhash >=1.4.4,<2.0a0 + - xz >=5.2.6,<6.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: BSD-3-Clause + license_family: BSD + size: 17776308 + timestamp: 1695269663260 - kind: conda name: cmake version: 3.27.6 @@ -4332,85 +6682,51 @@ packages: name: colorama version: 0.4.6 build: pyhd8ed1ab_0 - subdir: win-64 + subdir: noarch noarch: python url: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 sha256: 2c1b2e9755ce3102bca8d69e8f26e4f087ece73f50418186aee7c74bef8e1698 md5: 3faab06a954c2a04039983f2c4a50d99 depends: - python >=3.7 - arch: x86_64 - platform: win license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/colorama size: 25170 timestamp: 1666700778190 - kind: conda - name: colorlog - version: 4.8.0 - build: py311h1ea47a8_3 - build_number: 3 + name: colorama + version: 0.4.6 + build: pyhd8ed1ab_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/colorlog-4.8.0-py311h1ea47a8_3.conda - sha256: 3b317933f05df326e327faafcf1fd1be643df36f1aa479aab54f2a85062307f0 - md5: 9881fe3cbeed11cd8138a28c4c9d1f94 - depends: - - colorama - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 20460 - timestamp: 1697027322301 -- kind: conda - name: colorlog - version: 4.8.0 - build: py311h267d04e_3 - build_number: 3 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/colorlog-4.8.0-py311h267d04e_3.conda - sha256: 86dcaba5a3cd40e9752aa08221c45997a434cf2917d0b32eea56d788522a514a - md5: e4b2335855768eade29813b85342c990 - depends: - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 20239 - timestamp: 1697027319606 -- kind: conda - name: colorlog - version: 4.8.0 - build: py311h38be061_3 - build_number: 3 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/colorlog-4.8.0-py311h38be061_3.conda - sha256: bb52f32dfd32fe73691eebcbb336103db8167c26134c56123b26dc9808a684fa - md5: 09b2eea88d971b3986ac2cb47c9ea99f + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + sha256: 2c1b2e9755ce3102bca8d69e8f26e4f087ece73f50418186aee7c74bef8e1698 + md5: 3faab06a954c2a04039983f2c4a50d99 depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 19834 - timestamp: 1697026997816 -- kind: conda + - python >=3.7 + arch: x86_64 + platform: win + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/colorama + size: 25170 + timestamp: 1666700778190 +- kind: pypi name: colorlog - version: 4.8.0 - build: py311h6eed73b_3 - build_number: 3 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/colorlog-4.8.0-py311h6eed73b_3.conda - sha256: b929b2da9e782b6a2f7b559e32e443293c3ecdf628918fc685db928b5570460f - md5: cd35ca12286652e78d1d4c457b6e5a98 - depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 20046 - timestamp: 1697027212659 + version: 6.8.2 + url: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + sha256: 4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + requires_dist: + - colorama ; sys_platform == 'win32' + - black ; extra == 'development' + - flake8 ; extra == 'development' + - mypy ; extra == 'development' + - pytest ; extra == 'development' + - types-colorama ; extra == 'development' + requires_python: '>=3.6' - kind: conda name: compiler-rt version: 16.0.6 @@ -4526,38 +6842,11 @@ packages: license: BSD size: 6415 timestamp: 1701504710176 -- kind: conda - name: distlib - version: 0.3.7 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.7-pyhd8ed1ab_0.conda - sha256: 13c887cb4a29e1e853a118cfc0e42b72a7e1d1c50c66c0974885d37f0db30619 - md5: 12d8aae6994f342618443a8f05c652a0 - depends: - - python 2.7|>=3.6 - arch: x86_64 - platform: win - license: Apache-2.0 - license_family: APACHE - size: 273692 - timestamp: 1689598624555 -- kind: conda +- kind: pypi name: distlib version: 0.3.8 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.8-pyhd8ed1ab_0.conda - sha256: 3ff11acdd5cc2f80227682966916e878e45ced94f59c402efb94911a5774e84e - md5: db16c66b759a64dc5183d69cc3745a52 - depends: - - python 2.7|>=3.6 - license: Apache-2.0 - license_family: APACHE - size: 274915 - timestamp: 1702383349284 + url: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + sha256: 034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - kind: conda name: doxygen version: 1.9.7 @@ -4591,6 +6880,23 @@ packages: license_family: GPL size: 6179024 timestamp: 1687332729384 +- kind: conda + name: doxygen + version: 1.9.7 + build: h7b6a552_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda + sha256: cb4e2a628da54bf13d2decd9bbe982c611c216eb82b5ab826da59397492babd8 + md5: f619530bed063f8498eb2e15de71cf32 + depends: + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libstdcxx-ng >=12 + license: GPL-2.0-only + license_family: GPL + size: 5785379 + timestamp: 1687332318274 - kind: conda name: doxygen version: 1.9.7 @@ -4640,6 +6946,8 @@ packages: platform: win license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/exceptiongroup size: 19262 timestamp: 1692026296517 - kind: conda @@ -4655,24 +6963,28 @@ packages: depends: - python >=3.7 license: MIT and PSF-2.0 + purls: + - pkg:pypi/exceptiongroup size: 20551 timestamp: 1704921321122 -- kind: conda +- kind: pypi name: filelock version: 3.13.1 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/filelock-3.13.1-pyhd8ed1ab_0.conda - sha256: 4d742d91412d1f163e5399d2b50c5d479694ebcd309127abb549ca3977f89d2b - md5: 0c1729b74a8152fde6a38ba0a2ab9f45 - depends: - - python >=3.7 - arch: x86_64 - platform: win - license: Unlicense - size: 15605 - timestamp: 1698715139726 + url: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl + sha256: 57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c + requires_dist: + - furo >=2023.9.10 ; extra == 'docs' + - sphinx-autodoc-typehints !=1.23.4, >=1.24 ; extra == 'docs' + - sphinx >=7.2.6 ; extra == 'docs' + - covdefaults >=2.3 ; extra == 'testing' + - coverage >=7.3.2 ; extra == 'testing' + - diff-cover >=8 ; extra == 'testing' + - pytest-cov >=4.1 ; extra == 'testing' + - pytest-mock >=3.12 ; extra == 'testing' + - pytest-timeout >=2.2 ; extra == 'testing' + - pytest >=7.4.3 ; extra == 'testing' + - typing-extensions >=4.8 ; python_version < '3.11' and extra == 'typing' + requires_python: '>=3.8' - kind: conda name: flatbuffers version: 23.5.26 @@ -4736,6 +7048,80 @@ packages: license_family: APACHE size: 1303407 timestamp: 1685304046679 +- kind: conda + name: flatbuffers + version: 24.3.7 + build: h2f0025b_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda + sha256: 4284097708db3645f85dd0a9bbacfdd43d50ed1ad6cde0ebebfa24dac2518b83 + md5: 418752006d8190594749f21530c27fb5 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 1298784 + timestamp: 1710058440028 +- kind: conda + name: flatbuffers + version: 24.3.7 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.7-h59595ed_0.conda + sha256: 30b53ebe46e902ea80479406d8d849f6d552d1f3ea4ee0eef6048a7a2201d93e + md5: e72ffaf09c193f6bebbb0054079ab7d1 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 1453620 + timestamp: 1710058292298 +- kind: conda + name: flatbuffers + version: 24.3.7 + build: h63175ca_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.7-h63175ca_0.conda + sha256: 40613c4386464f2a1fa8ccebf1a38fede56669b8cdb6e4b0307e427720805232 + md5: 030adc8125b572439459ea9f063cf3de + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 1727810 + timestamp: 1710058620131 +- kind: conda + name: flatbuffers + version: 24.3.7 + build: h73e2aa4_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.7-h73e2aa4_0.conda + sha256: e4d0e09f5f27825fc8ccb42cc4ebb20951b364a303aa4e95fc996afbac78bf79 + md5: 4bca4cc7c9864063a92b08fb6975b802 + depends: + - libcxx >=16 + license: Apache-2.0 + license_family: APACHE + size: 1336422 + timestamp: 1710058653949 +- kind: conda + name: flatbuffers + version: 24.3.7 + build: hebf3989_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.7-hebf3989_0.conda + sha256: accfeff694d2b95a4a0ec6cd2ae5206028ce63a72583523e74bbb9d8e5b9ab53 + md5: 51f4a8e083d8caf54e945a9cf858a966 + depends: + - libcxx >=16 + license: Apache-2.0 + license_family: APACHE + size: 1278204 + timestamp: 1710058972127 - kind: conda name: gcc version: 12.3.0 @@ -4789,6 +7175,22 @@ packages: license_family: BSD size: 30351 timestamp: 1694604476800 +- kind: conda + name: gflags + version: 2.2.2 + build: h54f1f3f_1004 + build_number: 1004 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 + sha256: c72f18b94048df5525d8ae73a9efb8d830048b70328d63738d91d3ea54e55b91 + md5: f286d3464cc8d467c92e4f17990c98c1 + depends: + - libgcc-ng >=7.5.0 + - libstdcxx-ng >=7.5.0 + license: BSD-3-Clause + license_family: BSD + size: 124596 + timestamp: 1599590718502 - kind: conda name: gflags version: 2.2.2 @@ -4835,6 +7237,24 @@ packages: license_family: BSD size: 116549 timestamp: 1594303828933 +- kind: conda + name: gitdb + version: 4.0.11 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + sha256: 52ab2798be31b8f509eeec458712f447ced4f96ecb672c6c9a42778f47e07b1b + md5: 623b19f616f2ca0c261441067e18ae40 + depends: + - python >=3.7 + - smmap >=3.0.1,<6 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/gitdb + size: 52872 + timestamp: 1697791718749 - kind: conda name: gitdb version: 4.0.11 @@ -4851,6 +7271,8 @@ packages: platform: win license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/gitdb size: 52872 timestamp: 1697791718749 - kind: conda @@ -4868,6 +7290,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/gitignore-parser size: 11371 timestamp: 1696511979480 - kind: conda @@ -4883,6 +7307,8 @@ packages: - python >=3.7 license: MIT license_family: MIT + purls: + - pkg:pypi/gitignore-parser size: 11460 timestamp: 1705776957779 - kind: conda @@ -4902,6 +7328,8 @@ packages: platform: win license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/gitpython size: 147305 timestamp: 1697650463508 - kind: conda @@ -4919,8 +7347,29 @@ packages: - typing_extensions >=3.7.4.3 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/gitpython size: 150528 timestamp: 1704911329345 +- kind: conda + name: gitpython + version: 3.1.42 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + sha256: a11e1cf4404157467d0f51906d1db80bcb8bfe4bb3d3eba703b28e981ea7e308 + md5: 6bc8e496351bafd761c0922c3ebd989a + depends: + - gitdb >=4.0.1,<5 + - python >=3.7 + - typing_extensions >=3.7.4.3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/gitpython + size: 149604 + timestamp: 1708069389374 - kind: conda name: glog version: 0.6.0 @@ -4981,8 +7430,24 @@ packages: - libcxx >=16 license: BSD-3-Clause license_family: BSD - size: 115506 - timestamp: 1708261022187 + size: 115506 + timestamp: 1708261022187 +- kind: conda + name: glog + version: 0.7.0 + build: ha63034d_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda + sha256: 5b03faf3e29d277f03db2609399408182a2ee1af10986eed5a334e0d98f4e526 + md5: 70e70f34821c33530baeefd3ad1229bd + depends: + - gflags >=2.2.2,<2.3.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: BSD-3-Clause + license_family: BSD + size: 147076 + timestamp: 1708260860922 - kind: conda name: glog version: 0.7.0 @@ -5080,6 +7545,21 @@ packages: license_family: MIT size: 12089150 timestamp: 1692900650789 +- kind: conda + name: icu + version: '73.2' + build: h787c7f5_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + sha256: aedb9c911ede5596c87e1abd763ed940fab680d71fdb953bce8e4094119d47b3 + md5: 9d3c29d71f28452a2e843aff8cbe09d2 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: MIT + license_family: MIT + size: 12237094 + timestamp: 1692900632394 - kind: conda name: icu version: '73.2' @@ -5123,22 +7603,38 @@ packages: size: 25527 timestamp: 1676330831614 - kind: conda - name: importlib_metadata - version: 4.13.0 - build: hd8ed1ab_0 - subdir: win-64 - noarch: generic - url: https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.13.0-hd8ed1ab_0.conda - sha256: 3721a25eddddf46e562cfe04aa36c7c6417ae7056cd0c9d0a42d0349ce3bbcc8 - md5: eb09e30f586f5d8f8e8b784824be7017 + name: importlib-metadata + version: 7.0.2 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda + sha256: 9a26136d2cc81ccac209d6ae24281ceba3365fe34e34b2c45570f2a96e9d9c1b + md5: b050a4bb0e90ebd6e7fa4093d6346867 depends: - - importlib-metadata >=4.13.0,<4.13.1.0a0 - arch: x86_64 - platform: win + - python >=3.8 + - zipp >=0.5 license: Apache-2.0 license_family: APACHE - size: 9145 - timestamp: 1676330837094 + size: 26900 + timestamp: 1709821273570 +- kind: conda + name: iniconfig + version: 2.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + sha256: 38740c939b668b36a50ef455b077e8015b8c9cf89860d421b3fff86048f49666 + md5: f800d2da156d08e289b14e87e43c1ae5 + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/iniconfig + size: 11101 + timestamp: 1673103208955 - kind: conda name: iniconfig version: 2.0.0 @@ -5154,6 +7650,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/iniconfig size: 11101 timestamp: 1673103208955 - kind: conda @@ -5184,41 +7682,6 @@ packages: license_family: Proprietary size: 2325424 timestamp: 1706182537883 -- kind: conda - name: jinja2 - version: 3.1.2 - build: pyhd8ed1ab_1 - build_number: 1 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.2-pyhd8ed1ab_1.tar.bz2 - sha256: b045faba7130ab263db6a8fdc96b1a3de5fcf85c4a607c5f11a49e76851500b5 - md5: c8490ed5c70966d232fdd389d0dbed37 - depends: - - markupsafe >=2.0 - - python >=3.7 - arch: x86_64 - platform: win - license: BSD-3-Clause - license_family: BSD - size: 101443 - timestamp: 1654302514195 -- kind: conda - name: jinja2 - version: 3.1.3 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - sha256: fd517b7dd3a61eca34f8a6f9f92f306397149cae1204fce72ac3d227107dafdc - md5: e7d8df6509ba635247ff9aea31134262 - depends: - - markupsafe >=2.0 - - python >=3.7 - license: BSD-3-Clause - license_family: BSD - size: 111589 - timestamp: 1704967140287 - kind: conda name: just version: 1.15.0 @@ -5325,6 +7788,72 @@ packages: license: CC0-1.0 size: 1178083 timestamp: 1704893025811 +- kind: conda + name: just + version: 1.24.0 + build: h11a7dfb_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/just-1.24.0-h11a7dfb_0.conda + sha256: 802572940bc1208d135637b9859517d4262d156d956a98c96ca5502240da7d7d + md5: 5ac25104279a5589381ade8bd8e56552 + constrains: + - __osx >=10.12 + license: CC0-1.0 + size: 1113461 + timestamp: 1708241218651 +- kind: conda + name: just + version: 1.24.0 + build: h1d8f897_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/just-1.24.0-h1d8f897_0.conda + sha256: 581e83c4f9aa9663244b767e49a857374019d71f589567611be2870a95a05f52 + md5: 0a0e604e2ff4c1a207f5a2fbc2df154c + depends: + - libgcc-ng >=12 + license: CC0-1.0 + size: 1104293 + timestamp: 1708246328468 +- kind: conda + name: just + version: 1.24.0 + build: h5ef7bb8_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.24.0-h5ef7bb8_0.conda + sha256: 8a887ad3b46cb7df6e6f28301bf498a1d546a191b4e856f5ec68b51508534efd + md5: cd1e84db2e7aafc373279d6ac9746e20 + constrains: + - __osx >=11.0 + license: CC0-1.0 + size: 1033268 + timestamp: 1708241219422 +- kind: conda + name: just + version: 1.24.0 + build: h7f3b576_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/just-1.24.0-h7f3b576_0.conda + sha256: 00ef2294055adaf43115f0929172e8cd6cecec3ec03fa73d0fd10d6c34ed4aa2 + md5: 969f459714747b46af1159ee41dabd6d + depends: + - m2w64-gcc-libs + - m2w64-gcc-libs-core + license: CC0-1.0 + size: 1166282 + timestamp: 1708241728702 +- kind: conda + name: just + version: 1.24.0 + build: he8a937b_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/just-1.24.0-he8a937b_0.conda + sha256: 6d230b47d7548158e92d54580abdb2c1c767c986dc3d72431db7025570bf82cd + md5: 1de85b6ac80b52ce66fab344945cf2c3 + depends: + - libgcc-ng >=12 + license: CC0-1.0 + size: 1203601 + timestamp: 1708240909235 - kind: conda name: kernel-headers_linux-64 version: 2.6.32 @@ -5354,6 +7883,19 @@ packages: license: LGPL-2.1-or-later size: 117831 timestamp: 1646151697040 +- kind: conda + name: keyutils + version: 1.6.1 + build: h4e544f5_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 + sha256: 6d4233d97a9b38acbb26e1268bcf8c10a8e79c2aed7e5a385ec3769967e3e65b + md5: 1f24853e59c68892452ef94ddd8afd4b + depends: + - libgcc-ng >=10.3.0 + license: LGPL-2.1-or-later + size: 112327 + timestamp: 1646166857935 - kind: conda name: krb5 version: 1.21.2 @@ -5407,6 +7949,25 @@ packages: license_family: MIT size: 1183568 timestamp: 1692098004387 +- kind: conda + name: krb5 + version: 1.21.2 + build: hc419048_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda + sha256: c3f24ead49fb7d7c29fae491bec3f090f63d77a46954eadbc4463f137e2b42cd + md5: 55b51af37bf6fdcfe06f140e62e8c8db + depends: + - keyutils >=1.6.1,<2.0a0 + - libedit >=3.1.20191231,<3.2.0a0 + - libedit >=3.1.20191231,<4.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - openssl >=3.1.2,<4.0a0 + license: MIT + license_family: MIT + size: 1473397 + timestamp: 1692097651347 - kind: conda name: krb5 version: 1.21.2 @@ -5522,6 +8083,20 @@ packages: license_family: GPL size: 704696 timestamp: 1674833944779 +- kind: conda + name: ld_impl_linux-aarch64 + version: '2.40' + build: h2d8c526_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda + sha256: 1ba06e8645094b340b4aee23603a6abb1b0383788180e65f3de34e655c5f577c + md5: 16246d69e945d0b1969a6099e7c5d457 + constrains: + - binutils_impl_linux-aarch64 2.40 + license: GPL-3.0-only + license_family: GPL + size: 738776 + timestamp: 1674833843183 - kind: conda name: libabseil version: '20230802.1' @@ -5575,6 +8150,25 @@ packages: license_family: Apache size: 1263396 timestamp: 1695063868515 +- kind: conda + name: libabseil + version: '20240116.1' + build: cxx17_h2f0025b_2 + build_number: 2 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20240116.1-cxx17_h2f0025b_2.conda + sha256: bf8d5c1ee76960840d6a0e8eac4fd4111712a4745fffb1e6f9466feb3f11c1c6 + md5: 85dff948e5ec41a2eba9eb8fb001d01e + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + constrains: + - abseil-cpp =20240116.1 + - libabseil-static =20240116.1=cxx17* + license: Apache-2.0 + license_family: Apache + size: 1286200 + timestamp: 1709159884574 - kind: conda name: libabseil version: '20240116.1' @@ -5688,6 +8282,85 @@ packages: license_family: APACHE size: 15778237 timestamp: 1706610772424 +- kind: conda + name: libarrow + version: 14.0.2 + build: h25df049_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-14.0.2-h25df049_12_cpu.conda + sha256: 6a722025c1815e97356a480444a948a895eba8a529e06a946775218dffca5c96 + md5: d7a52d1add3c83e733238ba1b5169b37 + depends: + - aws-crt-cpp >=0.26.2,<0.26.3.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.0,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libgcc-ng >=12 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - orc >=2.0.0,<2.0.1.0a0 + - re2 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - apache-arrow-proc =*=cpu + - parquet-cpp <0.0a0 + - arrow-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + size: 7385058 + timestamp: 1710292910535 +- kind: conda + name: libarrow + version: 14.0.2 + build: h2a83f13_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h2a83f13_13_cpu.conda + sha256: 1e20499fa3ec9e4abb03ec91fa5422019868b36dcf2ae3d123e1b5785a9c7424 + md5: 3c1e5bd6b032045ee42bb09302f1c01f + depends: + - aws-crt-cpp >=0.26.3,<0.26.4.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - openssl >=3.2.1,<4.0a0 + - orc >=2.0.0,<2.0.1.0a0 + - re2 + - snappy >=1.1.10,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - parquet-cpp <0.0a0 + - arrow-cpp <0.0a0 + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 4907643 + timestamp: 1710345937957 - kind: conda name: libarrow version: 14.0.2 @@ -5706,10 +8379,84 @@ packages: - libabseil >=20240116.1,<20240117.0a0 - libbrotlidec >=1.1.0,<1.2.0a0 - libbrotlienc >=1.1.0,<1.2.0a0 - - libcxx >=14 + - libcxx >=14 + - libgoogle-cloud >=2.21.0,<2.22.0a0 + - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 + - libre2-11 >=2023.6.2,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - orc >=1.9.2,<1.9.3.0a0 + - re2 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - apache-arrow-proc =*=cpu + - arrow-cpp <0.0a0 + - parquet-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + size: 5316906 + timestamp: 1708691094438 +- kind: conda + name: libarrow + version: 14.0.2 + build: h4ce3932_3_cpu + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h4ce3932_3_cpu.conda + sha256: bfc40fc098db7715245c0aa5809ae2b8489a44e2619b63c1f75a2f9fedbc90ff + md5: 65d8be032e978630f715376237e12d95 + depends: + - aws-crt-cpp >=0.26.0,<0.26.1.0a0 + - aws-sdk-cpp >=1.11.210,<1.11.211.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.6.0,<0.7.0a0 + - libabseil * cxx17* + - libabseil >=20230802.1,<20230803.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libcxx >=14 + - libgoogle-cloud >=2.12.0,<2.13.0a0 + - libre2-11 >=2023.6.2,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - orc >=1.9.2,<1.9.3.0a0 + - re2 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - arrow-cpp <0.0a0 + - parquet-cpp <0.0a0 + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 14649507 + timestamp: 1706610614109 +- kind: conda + name: libarrow + version: 14.0.2 + build: h5001e6d_10_cpu + build_number: 10 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-h5001e6d_10_cpu.conda + sha256: 2e6340ba6cf72a4e38e8cfe1fd58bede4ffeb48955430b7bab0c69583233c81c + md5: ccba2f34c1345ad610734bd20f2aade7 + depends: + - aws-crt-cpp >=0.26.2,<0.26.3.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.0,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libgcc-ng >=12 - libgoogle-cloud >=2.21.0,<2.22.0a0 - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 - libre2-11 >=2023.6.2,<2024.0a0 + - libstdcxx-ng >=12 - libutf8proc >=2.8.0,<3.0a0 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 @@ -5718,60 +8465,61 @@ packages: - snappy >=1.1.10,<2.0a0 - zstd >=1.5.5,<1.6.0a0 constrains: - - apache-arrow-proc =*=cpu - arrow-cpp <0.0a0 + - apache-arrow-proc =*=cpu - parquet-cpp <0.0a0 license: Apache-2.0 license_family: APACHE - size: 5316906 - timestamp: 1708691094438 + size: 8080771 + timestamp: 1708689749260 - kind: conda name: libarrow version: 14.0.2 - build: h4ce3932_3_cpu - build_number: 3 + build: h5233fb5_13_cpu + build_number: 13 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h4ce3932_3_cpu.conda - sha256: bfc40fc098db7715245c0aa5809ae2b8489a44e2619b63c1f75a2f9fedbc90ff - md5: 65d8be032e978630f715376237e12d95 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h5233fb5_13_cpu.conda + sha256: b2fdb38eac0220e2588548c13e1b599e567c147450e19011cb661786085c64f0 + md5: 5964f068ac691eb417ecc6173e3ec288 depends: - - aws-crt-cpp >=0.26.0,<0.26.1.0a0 - - aws-sdk-cpp >=1.11.210,<1.11.211.0a0 + - aws-crt-cpp >=0.26.3,<0.26.4.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 - bzip2 >=1.0.8,<2.0a0 - - glog >=0.6.0,<0.7.0a0 + - glog >=0.7.0,<0.8.0a0 - libabseil * cxx17* - - libabseil >=20230802.1,<20230803.0a0 + - libabseil >=20240116.1,<20240117.0a0 - libbrotlidec >=1.1.0,<1.2.0a0 - libbrotlienc >=1.1.0,<1.2.0a0 - libcxx >=14 - - libgoogle-cloud >=2.12.0,<2.13.0a0 - - libre2-11 >=2023.6.2,<2024.0a0 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 - libutf8proc >=2.8.0,<3.0a0 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - - orc >=1.9.2,<1.9.3.0a0 + - orc >=2.0.0,<2.0.1.0a0 - re2 - snappy >=1.1.10,<2.0a0 - zstd >=1.5.5,<1.6.0a0 constrains: - - arrow-cpp <0.0a0 - parquet-cpp <0.0a0 - apache-arrow-proc =*=cpu + - arrow-cpp <0.0a0 license: Apache-2.0 license_family: APACHE - size: 14649507 - timestamp: 1706610614109 + size: 5325718 + timestamp: 1710345870461 - kind: conda name: libarrow version: 14.0.2 - build: h5001e6d_10_cpu - build_number: 10 + build: h6bfc85a_13_cpu + build_number: 13 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-h5001e6d_10_cpu.conda - sha256: 2e6340ba6cf72a4e38e8cfe1fd58bede4ffeb48955430b7bab0c69583233c81c - md5: ccba2f34c1345ad610734bd20f2aade7 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-h6bfc85a_13_cpu.conda + sha256: f62f6a0a50b94f55c4ee90288b599c17980f1c0b7d18ae9533c42fc18437fc8f + md5: 0b97d14e02c9a6c3a259f9cd88335c9f depends: - - aws-crt-cpp >=0.26.2,<0.26.3.0a0 + - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 - bzip2 >=1.0.8,<2.0a0 - glog >=0.7.0,<0.8.0a0 @@ -5780,25 +8528,25 @@ packages: - libbrotlidec >=1.1.0,<1.2.0a0 - libbrotlienc >=1.1.0,<1.2.0a0 - libgcc-ng >=12 - - libgoogle-cloud >=2.21.0,<2.22.0a0 - - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 - - libre2-11 >=2023.6.2,<2024.0a0 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 - libstdcxx-ng >=12 - libutf8proc >=2.8.0,<3.0a0 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - - orc >=1.9.2,<1.9.3.0a0 + - orc >=2.0.0,<2.0.1.0a0 - re2 - snappy >=1.1.10,<2.0a0 - zstd >=1.5.5,<1.6.0a0 constrains: - - arrow-cpp <0.0a0 - apache-arrow-proc =*=cpu - parquet-cpp <0.0a0 + - arrow-cpp <0.0a0 license: Apache-2.0 license_family: APACHE - size: 8080771 - timestamp: 1708689749260 + size: 8070162 + timestamp: 1710345363045 - kind: conda name: libarrow version: 14.0.2 @@ -5915,6 +8663,44 @@ packages: license_family: APACHE size: 5696868 timestamp: 1708690271784 +- kind: conda + name: libarrow + version: 14.0.2 + build: he79e29d_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-he79e29d_13_cpu.conda + sha256: 613a144ad341462f08e7be43a028441501c810dc59023cbe12e3e56e27ad1c92 + md5: 02fa4f5f3f8287b5914f8ee7cff7487b + depends: + - __osx >=10.13 + - aws-crt-cpp >=0.26.3,<0.26.4.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.0,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libcxx >=14 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - orc >=2.0.0,<2.0.1.0a0 + - re2 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - arrow-cpp <0.0a0 + - apache-arrow-proc =*=cpu + - parquet-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + size: 5718166 + timestamp: 1710346534084 - kind: conda name: libarrow-acero version: 14.0.2 @@ -5931,6 +8717,22 @@ packages: license_family: APACHE size: 512509 timestamp: 1708690347206 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: h000cb23_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-h000cb23_13_cpu.conda + sha256: bd071a96a8b4da5cf7fe88d586c5ecc77cff17a80dc5bb46873c73d29c70f788 + md5: f8a9bb4d1aef7853c734c829456efcff + depends: + - libarrow 14.0.2 he79e29d_13_cpu + - libcxx >=14 + license: Apache-2.0 + license_family: APACHE + size: 512740 + timestamp: 1710346674065 - kind: conda name: libarrow-acero version: 14.0.2 @@ -5963,6 +8765,22 @@ packages: license_family: APACHE size: 494852 timestamp: 1708691198827 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: h13dd4ca_13_cpu + build_number: 13 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-14.0.2-h13dd4ca_13_cpu.conda + sha256: c43bf0f7c5fda78df3830656ad600b061fe3a3d1a2596f95e1d152fa9d36c936 + md5: c9f53116aac6f41597e004e42f479591 + depends: + - libarrow 14.0.2 h5233fb5_13_cpu + - libcxx >=14 + license: Apache-2.0 + license_family: APACHE + size: 495434 + timestamp: 1710345986422 - kind: conda name: libarrow-acero version: 14.0.2 @@ -5979,6 +8797,23 @@ packages: license_family: APACHE size: 495117 timestamp: 1706610742772 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: h2f0025b_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-acero-14.0.2-h2f0025b_12_cpu.conda + sha256: d70bc3ef9fcf1fba63cf0b127512569ff22202306391d93c30f3d5ec4f557996 + md5: 6cf8a6e338e394fe0dd30e59988f8981 + depends: + - libarrow 14.0.2 h25df049_12_cpu + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 542198 + timestamp: 1710292954892 - kind: conda name: libarrow-acero version: 14.0.2 @@ -5996,6 +8831,23 @@ packages: license_family: APACHE size: 577227 timestamp: 1708689800054 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: h59595ed_13_cpu + build_number: 13 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-14.0.2-h59595ed_13_cpu.conda + sha256: 16cadd969ffd3d68a0821c7d9af4fb7772ad2f54187852b09026677a1c203410 + md5: 28e25c6db46fc5542c858cf701909d84 + depends: + - libarrow 14.0.2 h6bfc85a_13_cpu + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 577795 + timestamp: 1710345426232 - kind: conda name: libarrow-acero version: 14.0.2 @@ -6031,6 +8883,24 @@ packages: license_family: APACHE size: 430548 timestamp: 1708690137226 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: h63175ca_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h63175ca_13_cpu.conda + sha256: 8ee3b272ebdadbf4e41f4ea4d1b36db62555870378f8be941f83220bf3cd3b2e + md5: 389ccdec73910798474ab1517d5a5747 + depends: + - libarrow 14.0.2 h2a83f13_13_cpu + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 431459 + timestamp: 1710346036673 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -6049,6 +8919,24 @@ packages: license_family: APACHE size: 511903 timestamp: 1708690574393 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: h000cb23_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-h000cb23_13_cpu.conda + sha256: 0f013a4a208723516f0049585994dc2363c120cf11c18849c4b3b01bc4986f40 + md5: d6db4c70e3a1fc9ac0a48c9165e2e820 + depends: + - libarrow 14.0.2 he79e29d_13_cpu + - libarrow-acero 14.0.2 h000cb23_13_cpu + - libcxx >=14 + - libparquet 14.0.2 h381d950_13_cpu + license: Apache-2.0 + license_family: APACHE + size: 512999 + timestamp: 1710347067673 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -6085,6 +8973,24 @@ packages: license_family: APACHE size: 526964 timestamp: 1708691531170 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: h13dd4ca_13_cpu + build_number: 13 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-14.0.2-h13dd4ca_13_cpu.conda + sha256: a0833d1bc74cb554ab5da8b01f65c77525190b295da1d77071adc778ebfb1072 + md5: 90c1416a2538df8b3343716cfec2c4f8 + depends: + - libarrow 14.0.2 h5233fb5_13_cpu + - libarrow-acero 14.0.2 h13dd4ca_13_cpu + - libcxx >=14 + - libparquet 14.0.2 hf6ce1d5_13_cpu + license: Apache-2.0 + license_family: APACHE + size: 527932 + timestamp: 1710346391216 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -6103,6 +9009,25 @@ packages: license_family: APACHE size: 526945 timestamp: 1706611070744 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: h2f0025b_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-dataset-14.0.2-h2f0025b_12_cpu.conda + sha256: 65a33363cb7e4936bc1c75f2f115ea4dd32498c283baa5c1ea1a321cfa17d10b + md5: d46471dbf3c19b687d324a297a72debd + depends: + - libarrow 14.0.2 h25df049_12_cpu + - libarrow-acero 14.0.2 h2f0025b_12_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 hb18b541_12_cpu + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 551283 + timestamp: 1710293072163 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -6122,6 +9047,25 @@ packages: license_family: APACHE size: 580942 timestamp: 1708689918 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: h59595ed_13_cpu + build_number: 13 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-14.0.2-h59595ed_13_cpu.conda + sha256: eae222df321ea3408a3b28ea85cb40504e86975cd6f258d37912f6ce6d0b9ad1 + md5: 5266653f8b74e0ba57401be532055410 + depends: + - libarrow 14.0.2 h6bfc85a_13_cpu + - libarrow-acero 14.0.2 h59595ed_13_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 h352af49_13_cpu + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 581399 + timestamp: 1710345583152 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -6161,6 +9105,48 @@ packages: license_family: APACHE size: 429115 timestamp: 1708690422907 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: h63175ca_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h63175ca_13_cpu.conda + sha256: 50ba7bff4899da18c8791071cbc733496eccc65d6948b2faac6a5f2e0a98e9b7 + md5: daeb4b650d02b601783ea6799f9afd6c + depends: + - libarrow 14.0.2 h2a83f13_13_cpu + - libarrow-acero 14.0.2 h63175ca_13_cpu + - libparquet 14.0.2 h7ec3a38_13_cpu + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 429023 + timestamp: 1710346405791 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: h02312f3_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-h02312f3_13_cpu.conda + sha256: 9a64a061f5d42e7c021f9e65066957cd1650f6a97cf3897363111b52f464021f + md5: f51f43c16adcee3ed9a1e151c1aeb92e + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h2a83f13_13_cpu + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 286961 + timestamp: 1710346136713 - kind: conda name: libarrow-flight version: 14.0.2 @@ -6183,6 +9169,49 @@ packages: license_family: APACHE size: 501085 timestamp: 1706609649937 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: h2382776_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-h2382776_13_cpu.conda + sha256: bbd32e1906eb567d95d41b72d64f993d88761dc2b2760fe508854baab7802966 + md5: 3bf6df6c793a2ea01f3e0612c741b372 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 he79e29d_13_cpu + - libcxx >=14 + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 322715 + timestamp: 1710346774669 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: h2f4a9e5_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-14.0.2-h2f4a9e5_12_cpu.conda + sha256: bbea5d23c616b6b36a6cbf04a617657553628d08a0844a2279ebdce1c749a69d + md5: e98e22bae314c018497b409170001620 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h25df049_12_cpu + - libgcc-ng >=12 + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + - ucx >=1.15.0,<1.16.0a0 + license: Apache-2.0 + license_family: APACHE + size: 474817 + timestamp: 1710292993611 - kind: conda name: libarrow-flight version: 14.0.2 @@ -6204,6 +9233,26 @@ packages: license_family: APACHE size: 321632 timestamp: 1708690401993 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: h95ca633_13_cpu + build_number: 13 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-14.0.2-h95ca633_13_cpu.conda + sha256: c44b819b5efb283c01aa43c805de17266cb407256c4e86427bb64b6cfd392e42 + md5: 392cd88b061dbc1c4366871e65a68ed9 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h5233fb5_13_cpu + - libcxx >=14 + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 333172 + timestamp: 1710346111062 - kind: conda name: libarrow-flight version: 14.0.2 @@ -6245,6 +9294,28 @@ packages: license_family: APACHE size: 332020 timestamp: 1706610826254 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: hc6145d9_13_cpu + build_number: 13 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-14.0.2-hc6145d9_13_cpu.conda + sha256: 5bb091f548f124d9aa0f1a2bb070be2f3713dabd7995e7b82c61427cf7b1f9a5 + md5: be1e8c18e141e9fb3358f1225c583d0d + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h6bfc85a_13_cpu + - libgcc-ng >=12 + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + - ucx >=1.15.0,<1.16.0a0 + license: Apache-2.0 + license_family: APACHE + size: 503693 + timestamp: 1710345464269 - kind: conda name: libarrow-flight version: 14.0.2 @@ -6385,6 +9456,26 @@ packages: license_family: APACHE size: 154009 timestamp: 1708690633124 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: h55b4db4_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h55b4db4_13_cpu.conda + sha256: 4ba5130101c323580e9f8ae86ab9a7389aa1a27a62c1d793e89cc99d24ff84c2 + md5: 8c27d39e7147c7ee420bcbdf12b83200 + depends: + - libarrow 14.0.2 h2a83f13_13_cpu + - libarrow-flight 14.0.2 h02312f3_13_cpu + - libprotobuf >=4.25.3,<4.25.4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 235314 + timestamp: 1710346485995 - kind: conda name: libarrow-flight-sql version: 14.0.2 @@ -6422,6 +9513,44 @@ packages: license_family: APACHE size: 195809 timestamp: 1706609745191 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: h757c851_13_cpu + build_number: 13 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-sql-14.0.2-h757c851_13_cpu.conda + sha256: 669a52f7240ab55fa51b89c805acb91c89975db6081347aff14ea8363c9f2b34 + md5: 690b85e4586d37c997a090d42e20295a + depends: + - libarrow 14.0.2 h6bfc85a_13_cpu + - libarrow-flight 14.0.2 hc6145d9_13_cpu + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 195497 + timestamp: 1710345622444 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: h7e3fe20_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-h7e3fe20_13_cpu.conda + sha256: 90bd62adf53cd99da17365ab73f53b90df0af79b6861a9e21051b1a0b811174e + md5: 4c5fea48489a40db78b2fcbfe262900f + depends: + - __osx >=10.13 + - libarrow 14.0.2 he79e29d_13_cpu + - libarrow-flight 14.0.2 h2382776_13_cpu + - libcxx >=14 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 155420 + timestamp: 1710347160360 - kind: conda name: libarrow-flight-sql version: 14.0.2 @@ -6441,6 +9570,43 @@ packages: license_family: APACHE size: 153818 timestamp: 1706611190988 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: hc81a7a7_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-sql-14.0.2-hc81a7a7_12_cpu.conda + sha256: 0145909d1aee5df3c1b25b483f4f62f7e9081c568e74069b4e18a67ba69ade9e + md5: c2cbaeac8289e227203bc770aa987086 + depends: + - libarrow 14.0.2 h25df049_12_cpu + - libarrow-flight 14.0.2 h2f4a9e5_12_cpu + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 182885 + timestamp: 1710293099163 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: hdc5392b_13_cpu + build_number: 13 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-sql-14.0.2-hdc5392b_13_cpu.conda + sha256: a74ba3c1ed45cc6b89b66b5dd465d6a1210bc75481d79b80028034f404a7968a + md5: d98a1133d4bba9a05325954e662f5295 + depends: + - libarrow 14.0.2 h5233fb5_13_cpu + - libarrow-flight 14.0.2 h95ca633_13_cpu + - libcxx >=14 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 163324 + timestamp: 1710346482468 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -6462,6 +9628,30 @@ packages: license_family: APACHE size: 698984 timestamp: 1706611013722 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: h3a2b1eb_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-gandiva-14.0.2-h3a2b1eb_12_cpu.conda + sha256: cc4399d0e141dbc024d7e523bb96526548dbfc3b6ad418265012fe164a3da88a + md5: edfc287a18bae624cccb0e3078137d7d + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h25df049_12_cpu + - libgcc-ng >=12 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + size: 855698 + timestamp: 1710293021684 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -6534,6 +9724,30 @@ packages: license_family: APACHE size: 10170570 timestamp: 1708690279861 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: ha5acb15_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-ha5acb15_13_cpu.conda + sha256: 6d06c71df682907daf6a37deac2fac394388b8e3947b5171ba6fa280e45b1ebc + md5: e864ce81130c6fbae77fd7ffb768b41d + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 he79e29d_13_cpu + - libcxx >=14 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + size: 700321 + timestamp: 1710346874742 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -6556,6 +9770,55 @@ packages: license_family: APACHE size: 895232 timestamp: 1706609674431 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: hb016d2e_13_cpu + build_number: 13 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hb016d2e_13_cpu.conda + sha256: a82694957ba8209fa9eb7f5e26c4ad71a936fe3c963c133368c60da078267566 + md5: 677a678f1794a6a6c4efff894a5a92cb + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h6bfc85a_13_cpu + - libgcc-ng >=12 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + size: 894432 + timestamp: 1710345503892 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: hcb01e45_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-hcb01e45_13_cpu.conda + sha256: 0d5764893b016216fada279215d7ac77d7791f1e724cb3d977538720e1ab3158 + md5: b01782c5a1e218bc257bb0a15fabd8b5 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h2a83f13_13_cpu + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 10177269 + timestamp: 1710346223297 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -6601,6 +9864,29 @@ packages: license_family: APACHE size: 688245 timestamp: 1706610908126 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: hfef958d_13_cpu + build_number: 13 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-gandiva-14.0.2-hfef958d_13_cpu.conda + sha256: 692521ca74dc6ce6de168a5ae1d1c11136b0541af5e2aab388deeb3c35e61a59 + md5: 28e850b27dd93367bb783d0d16d55afc + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h5233fb5_13_cpu + - libcxx >=14 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + size: 688483 + timestamp: 1710346205367 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -6680,6 +9966,46 @@ packages: license_family: APACHE size: 509163 timestamp: 1706609767216 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: h757c851_13_cpu + build_number: 13 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-14.0.2-h757c851_13_cpu.conda + sha256: e4e15042a93bc3a6e4e0717a2802c6859a5a9cafdcc8f49957f0948a249b2816 + md5: 15c79e6f7b9686ebff4d687a33a52a76 + depends: + - libarrow 14.0.2 h6bfc85a_13_cpu + - libarrow-acero 14.0.2 h59595ed_13_cpu + - libarrow-dataset 14.0.2 h59595ed_13_cpu + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 518209 + timestamp: 1710345660675 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: h7e3fe20_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-h7e3fe20_13_cpu.conda + sha256: 4e27d6f673e8ef27d62d5c5a8bd00a8ae2b93d65c0b90373f2a5917479d6e68d + md5: c50111280b8d2f2c176d949e5c7ddfd1 + depends: + - __osx >=10.13 + - libarrow 14.0.2 he79e29d_13_cpu + - libarrow-acero 14.0.2 h000cb23_13_cpu + - libarrow-dataset 14.0.2 h000cb23_13_cpu + - libcxx >=14 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 454371 + timestamp: 1710347255673 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -6699,6 +10025,29 @@ packages: license_family: APACHE size: 472877 timestamp: 1706611234135 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: h89268de_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-h89268de_13_cpu.conda + sha256: 816be5f4ac5ed5b35fcc3966b39314acbf9aef31e50162656b53d103560f002c + md5: c3599d0881c8f26df0900993f40f7c10 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h2a83f13_13_cpu + - libarrow-acero 14.0.2 h63175ca_13_cpu + - libarrow-dataset 14.0.2 h63175ca_13_cpu + - libprotobuf >=4.25.3,<4.25.4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 361120 + timestamp: 1710346569221 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -6719,6 +10068,45 @@ packages: license_family: APACHE size: 452971 timestamp: 1706611246525 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: hd45466a_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-substrait-14.0.2-hd45466a_12_cpu.conda + sha256: 0ba6e17e61be79349ab6fe1de1c3984e8b88b3553056dffc251f49f3211a4762 + md5: c891077d81b44b532462b3f565e0de86 + depends: + - libarrow 14.0.2 h25df049_12_cpu + - libarrow-acero 14.0.2 h2f0025b_12_cpu + - libarrow-dataset 14.0.2 h2f0025b_12_cpu + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 503549 + timestamp: 1710293136119 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: hef52601_13_cpu + build_number: 13 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-14.0.2-hef52601_13_cpu.conda + sha256: 3a9302c70f68e7b1fd433b5b0176b8317fb85ea840155c520ae012c619c5785c + md5: d5ac1ee4616a6caa87ba3f84b47e3de1 + depends: + - libarrow 14.0.2 h5233fb5_13_cpu + - libarrow-acero 14.0.2 h13dd4ca_13_cpu + - libarrow-dataset 14.0.2 h13dd4ca_13_cpu + - libcxx >=14 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 473073 + timestamp: 1710346607250 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -6851,6 +10239,27 @@ packages: license_family: BSD size: 14691 timestamp: 1705979549006 +- kind: conda + name: libblas + version: 3.9.0 + build: 21_linuxaarch64_openblas + build_number: 21 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.9.0-21_linuxaarch64_openblas.conda + sha256: 5d1dcfc2ef54ce415ffabc8e2d94d10f8a24e10096193da24b0b62dbfe35bf32 + md5: 7358230781e5d6e76e6adacf5201bcdf + depends: + - libopenblas >=0.3.26,<0.3.27.0a0 + - libopenblas >=0.3.26,<1.0a0 + constrains: + - liblapacke 3.9.0 21_linuxaarch64_openblas + - liblapack 3.9.0 21_linuxaarch64_openblas + - blas * openblas + - libcblas 3.9.0 21_linuxaarch64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14650 + timestamp: 1705979384501 - kind: conda name: libblas version: 3.9.0 @@ -6926,6 +10335,21 @@ packages: license_family: MIT size: 67476 timestamp: 1695990207321 +- kind: conda + name: libbrotlicommon + version: 1.1.0 + build: h31becfc_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.1.0-h31becfc_1.conda + sha256: 1c3d4ea61e862eb5f1968915f6f5917ea61db9921aec30b14785775c87234060 + md5: 1b219fd801eddb7a94df5bd001053ad9 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 69237 + timestamp: 1695990107496 - kind: conda name: libbrotlicommon version: 1.1.0 @@ -6986,6 +10410,22 @@ packages: license_family: MIT size: 30327 timestamp: 1695990232422 +- kind: conda + name: libbrotlidec + version: 1.1.0 + build: h31becfc_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.1.0-h31becfc_1.conda + sha256: 1d2558efbb727f9065dd94d5f906aa68252153f80e571456d3695fa102e8a352 + md5: 8db7cff89510bec0b863a0a8ee6a7bce + depends: + - libbrotlicommon 1.1.0 h31becfc_1 + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 31926 + timestamp: 1695990123189 - kind: conda name: libbrotlidec version: 1.1.0 @@ -7050,6 +10490,22 @@ packages: license_family: MIT size: 299092 timestamp: 1695990259225 +- kind: conda + name: libbrotlienc + version: 1.1.0 + build: h31becfc_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.1.0-h31becfc_1.conda + sha256: 271fd8ef9181ad19246bf8b4273c99b9608c6eedecb6b11cd925211b8f1c6217 + md5: ad3d3a826b5848d99936e4466ebbaa26 + depends: + - libbrotlicommon 1.1.0 h31becfc_1 + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 290542 + timestamp: 1695990138784 - kind: conda name: libbrotlienc version: 1.1.0 @@ -7202,6 +10658,25 @@ packages: license_family: BSD size: 14614 timestamp: 1705979564122 +- kind: conda + name: libcblas + version: 3.9.0 + build: 21_linuxaarch64_openblas + build_number: 21 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-21_linuxaarch64_openblas.conda + sha256: 86224669232944141f46b41d0ba18192c7f5af9cc3133fa89694f42701fe89fd + md5: 7eb9aa7a90f067f8dbfede586cdc55cd + depends: + - libblas 3.9.0 21_linuxaarch64_openblas + constrains: + - liblapacke 3.9.0 21_linuxaarch64_openblas + - liblapack 3.9.0 21_linuxaarch64_openblas + - blas * openblas + license: BSD-3-Clause + license_family: BSD + size: 14575 + timestamp: 1705979392590 - kind: conda name: libcblas version: 3.9.0 @@ -7259,6 +10734,23 @@ packages: license_family: BSD size: 5017024 timestamp: 1705980469944 +- kind: conda + name: libclang-cpp16 + version: 16.0.6 + build: default_h127d8a8_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp16-16.0.6-default_h127d8a8_5.conda + sha256: 8d034d92a7f7a9841796297bc18c2d8d8133583a6f3b661bfb1ca88ba01a076b + md5: 9fed40c47995a15eca939c4562d879bf + depends: + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 17942793 + timestamp: 1709764754399 - kind: conda name: libclang-cpp16 version: 16.0.6 @@ -7292,6 +10784,23 @@ packages: license_family: Apache size: 17942324 timestamp: 1704262063346 +- kind: conda + name: libclang-cpp16 + version: 16.0.6 + build: default_hb368394_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp16-16.0.6-default_hb368394_5.conda + sha256: fb1fd911d494f23abd889a95b9ea603de261badcd5120df2eda7f12f36d0707c + md5: 0b273d3ae3793c79728ed914c4a2aac5 + depends: + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 17600643 + timestamp: 1706895662107 - kind: conda name: libclang-cpp16 version: 16.0.6 @@ -7422,6 +10931,101 @@ packages: license_family: Apache size: 7164068 timestamp: 1704280614681 +- kind: conda + name: libclang13 + version: 18.1.1 + build: default_h0edc4dd_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libclang13-18.1.1-default_h0edc4dd_0.conda + sha256: 6706f35efe4f45bd50c56854e93715eb59bb948feb098aabd23923d5bbd409a7 + md5: badbda562ead0bcae661586067298002 + depends: + - libcxx >=16.0.6 + - libllvm18 >=18.1.1,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 8055181 + timestamp: 1710477023799 +- kind: conda + name: libclang13 + version: 18.1.1 + build: default_h5d6823c_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libclang13-18.1.1-default_h5d6823c_0.conda + sha256: eab9467b8e7bef6152af4ac2a167abab76f5453396f62755605cfa53eadafea7 + md5: 68ad4732fc951212bcc67e7d60de42e5 + depends: + - libgcc-ng >=12 + - libllvm18 >=18.1.1,<18.2.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 11069471 + timestamp: 1710472508192 +- kind: conda + name: libclang13 + version: 18.1.1 + build: default_h83d0a53_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-18.1.1-default_h83d0a53_0.conda + sha256: a3e12d97d6f3a06b1375eca3057e12c262be568755236689efb076352eb84636 + md5: 591cdf454c3db0328daf524a5b6b15d0 + depends: + - libcxx >=16.0.6 + - libllvm18 >=18.1.1,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 7513624 + timestamp: 1710475008752 +- kind: conda + name: libclang13 + version: 18.1.1 + build: default_hf64faad_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libclang13-18.1.1-default_hf64faad_0.conda + sha256: 36dbad4abb730d6ba9904d60cac670c2b9d19bd11a5664db67b9c17660cef43a + md5: 2a7bf5472a4decbe0f800c84c384fb08 + depends: + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 25314400 + timestamp: 1710479378028 +- kind: conda + name: libclang13 + version: 18.1.1 + build: default_hf9b4efe_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-18.1.1-default_hf9b4efe_0.conda + sha256: 2411bd3412f2007d3b640fb1bd71cb2ae7a6ae32186b3fbdf625a98b0cf4fd36 + md5: aa206882a3e166cb08b24c55f2092a4e + depends: + - libgcc-ng >=12 + - libllvm18 >=18.1.1,<18.2.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 10874336 + timestamp: 1710473662256 +- kind: conda + name: libcrc32c + version: 1.1.2 + build: h01db608_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libcrc32c-1.1.2-h01db608_0.tar.bz2 + sha256: b8b8c57a87da86b3ea24280fd6aa8efaf92f4e684b606bf2db5d3cb06ffbe2ea + md5: 268ee639c17ada0002fb04dd21816cc2 + depends: + - libgcc-ng >=9.4.0 + - libstdcxx-ng >=9.4.0 + license: BSD-3-Clause + license_family: BSD + size: 18669 + timestamp: 1633683724891 - kind: conda name: libcrc32c version: 1.1.2 @@ -7483,13 +11087,33 @@ packages: - kind: conda name: libcurl version: 8.5.0 - build: h2d989ff_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.5.0-h2d989ff_0.conda - sha256: f1c04be217aaf161ce3c99a8d618871295b5dc1eae2f7ff7b32078af50303f5b - md5: f1211ed00947a84e15a964a8f459f620 + build: h2d989ff_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.5.0-h2d989ff_0.conda + sha256: f1c04be217aaf161ce3c99a8d618871295b5dc1eae2f7ff7b32078af50303f5b + md5: f1211ed00947a84e15a964a8f459f620 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.0,<4.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: curl + license_family: MIT + size: 350298 + timestamp: 1701860532373 +- kind: conda + name: libcurl + version: 8.5.0 + build: h4e8248e_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.5.0-h4e8248e_0.conda + sha256: 4f4f8b884927d0c6fad4a8f5d7afaf789fe4f6554448ac8b416231f2f3dc7490 + md5: fa0f5edc06ffc25a01eed005c6dc3d8c depends: - krb5 >=1.21.2,<1.22.0a0 + - libgcc-ng >=12 - libnghttp2 >=1.58.0,<2.0a0 - libssh2 >=1.11.0,<2.0a0 - libzlib >=1.2.13,<1.3.0a0 @@ -7497,8 +11121,8 @@ packages: - zstd >=1.5.5,<1.6.0a0 license: curl license_family: MIT - size: 350298 - timestamp: 1701860532373 + size: 399469 + timestamp: 1701860213311 - kind: conda name: libcurl version: 8.5.0 @@ -7627,6 +11251,22 @@ packages: license_family: BSD size: 123878 timestamp: 1597616541093 +- kind: conda + name: libedit + version: 3.1.20191231 + build: he28a2e2_2 + build_number: 2 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + sha256: debc31fb2f07ba2b0363f90e455873670734082822926ba4a9556431ec0bf36d + md5: 29371161d77933a54fccf1bb66b96529 + depends: + - libgcc-ng >=7.5.0 + - ncurses >=6.2,<7.0.0a0 + license: BSD-2-Clause + license_family: BSD + size: 134104 + timestamp: 1597617110769 - kind: conda name: libev version: '4.33' @@ -7640,6 +11280,21 @@ packages: license_family: BSD size: 106663 timestamp: 1702146352558 +- kind: conda + name: libev + version: '4.33' + build: h31becfc_2 + build_number: 2 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + sha256: 973af77e297f1955dd1f69c2cbdc5ab9dfc88388a5576cd152cda178af0fd006 + md5: a9a13cb143bbaa477b1ebaefbe47a302 + depends: + - libgcc-ng >=12 + license: BSD-2-Clause + license_family: BSD + size: 115123 + timestamp: 1702146237623 - kind: conda name: libev version: '4.33' @@ -7748,6 +11403,22 @@ packages: license_family: BSD size: 410555 timestamp: 1685726568668 +- kind: conda + name: libevent + version: 2.1.12 + build: h4ba1bb4_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda + sha256: 01333cc7d6e6985dd5700b43660d90e9e58049182017fd24862088ecbe1458e4 + md5: 96ae6083cd1ac9f6bc81631ac835b317 + depends: + - libgcc-ng >=12 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 438992 + timestamp: 1685726046519 - kind: conda name: libevent version: 2.1.12 @@ -7841,6 +11512,80 @@ packages: license_family: MIT size: 69602 timestamp: 1680191040160 +- kind: conda + name: libexpat + version: 2.6.2 + build: h2f0025b_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda + sha256: 07453df3232a649f39fb4d1e68cfe1c78c3457764f85225f6f3ccd1bdd9818a4 + md5: 1b9f46b804a2c3c5d7fd6a80b77c35f9 + depends: + - libgcc-ng >=12 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 72544 + timestamp: 1710362309065 +- kind: conda + name: libexpat + version: 2.6.2 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + sha256: 331bb7c7c05025343ebd79f86ae612b9e1e74d2687b8f3179faec234f986ce19 + md5: e7ba12deb7020dd080c6c70e7b6f6a3d + depends: + - libgcc-ng >=12 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 73730 + timestamp: 1710362120304 +- kind: conda + name: libexpat + version: 2.6.2 + build: h63175ca_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + sha256: 79f612f75108f3e16bbdc127d4885bb74729cf66a8702fca0373dad89d40c4b7 + md5: bc592d03f62779511d392c175dcece64 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 139224 + timestamp: 1710362609641 +- kind: conda + name: libexpat + version: 2.6.2 + build: h73e2aa4_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + sha256: a188a77b275d61159a32ab547f7d17892226e7dac4518d2c6ac3ac8fc8dfde92 + md5: 3d1d51c8f716d97c864d12f7af329526 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 69246 + timestamp: 1710362566073 +- kind: conda + name: libexpat + version: 2.6.2 + build: hebf3989_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + sha256: ba7173ac30064ea901a4c9fb5a51846dcc25512ceb565759be7d18cbf3e5415e + md5: e3cde7cfa87f82f7cb13d482d5e0ad09 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 63655 + timestamp: 1710362424980 - kind: conda name: libffi version: 3.4.2 @@ -7867,6 +11612,21 @@ packages: license_family: MIT size: 39020 timestamp: 1636488587153 +- kind: conda + name: libffi + version: 3.4.2 + build: h3557bc0_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 + sha256: 7e9258a102480757fe3faeb225a3ca04dffd10fecd2a958c65cdb4cdf75f2c3c + md5: dddd85f4d52121fab0a8b099c5e06501 + depends: + - libgcc-ng >=9.4.0 + license: MIT + license_family: MIT + size: 59450 + timestamp: 1636488255090 - kind: conda name: libffi version: 3.4.2 @@ -7950,6 +11710,23 @@ packages: license_family: GPL size: 770506 timestamp: 1706819192021 +- kind: conda + name: libgcc-ng + version: 13.2.0 + build: hf8544c7_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-13.2.0-hf8544c7_5.conda + sha256: 869e44e1cf329198f5bea56c146207ed639b24b6281187159435b9499ecb3959 + md5: dee934e640275d9e74e7bbd455f25162 + depends: + - _openmp_mutex >=4.5 + constrains: + - libgomp 13.2.0 hf8544c7_5 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 456795 + timestamp: 1706820691781 - kind: conda name: libgfortran version: 5.0.0 @@ -8046,6 +11823,21 @@ packages: license_family: GPL size: 23829 timestamp: 1706819413770 +- kind: conda + name: libgfortran-ng + version: 13.2.0 + build: he9431aa_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-ng-13.2.0-he9431aa_5.conda + sha256: a7e5d1ac34118a4fad8286050af0146226d2fb2bd63e7a1066dc4dae7ba42daa + md5: fab7c6a8c84492e18cbe578820e97a56 + depends: + - libgfortran5 13.2.0 h582850c_5 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 23994 + timestamp: 1706820985230 - kind: conda name: libgfortran5 version: 13.2.0 @@ -8082,6 +11874,23 @@ packages: license_family: GPL size: 1571379 timestamp: 1707328880361 +- kind: conda + name: libgfortran5 + version: 13.2.0 + build: h582850c_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-13.2.0-h582850c_5.conda + sha256: f778346e85eb19bca36d1a5c8cddf8e089dcd6799b8f3e1b3f2d5a3157920827 + md5: 547486aac825d236de3beecb927b389c + depends: + - libgcc-ng >=13.2.0 + constrains: + - libgfortran-ng 13.2.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 1082835 + timestamp: 1706820715400 - kind: conda name: libgfortran5 version: 13.2.0 @@ -8186,6 +11995,19 @@ packages: license_family: GPL size: 419751 timestamp: 1706819107383 +- kind: conda + name: libgomp + version: 13.2.0 + build: hf8544c7_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-13.2.0-hf8544c7_5.conda + sha256: a98d4f242a351feb7983a28e7d6a0ca51da764c6233ea3dfc776975a3aba8a01 + md5: 379be2f115ffb73860e4e260dd2170b7 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 423091 + timestamp: 1706820564165 - kind: conda name: libgoogle-cloud version: 2.12.0 @@ -8364,6 +12186,126 @@ packages: license_family: Apache size: 1209079 timestamp: 1708638321316 +- kind: conda + name: libgoogle-cloud + version: 2.22.0 + build: h651e89d_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.22.0-h651e89d_1.conda + sha256: 39f2f50202e50e41ee8581c99a0b3023c2c21cab80ba597f8c5be7c8c8c6a059 + md5: 3f2faf53ecb3b51b92b3eee155b50233 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libcxx >=16 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - openssl >=3.2.1,<4.0a0 + constrains: + - libgoogle-cloud 2.22.0 *_1 + license: Apache-2.0 + license_family: Apache + size: 849198 + timestamp: 1709738549021 +- kind: conda + name: libgoogle-cloud + version: 2.22.0 + build: h9be4e54_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.22.0-h9be4e54_1.conda + sha256: b9980209438b22113f4352df2b260bf43b2eb63a7b6325192ec5ae3a562872ed + md5: 4b4e36a91e7dabf7345b82d85767a7c3 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgcc-ng >=12 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + - openssl >=3.2.1,<4.0a0 + constrains: + - libgoogle-cloud 2.22.0 *_1 + license: Apache-2.0 + license_family: Apache + size: 1209816 + timestamp: 1709737846418 +- kind: conda + name: libgoogle-cloud + version: 2.22.0 + build: h9cad5c0_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.22.0-h9cad5c0_1.conda + sha256: f76e892d13e1db405777c968787678d8ba912b7e4eef7f950fcdcca185e06e71 + md5: 63cd44a71f00d4e72844bf0e8be56be4 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - openssl >=3.2.1,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - libgoogle-cloud 2.22.0 *_1 + license: Apache-2.0 + license_family: Apache + size: 14420 + timestamp: 1709737037941 +- kind: conda + name: libgoogle-cloud + version: 2.22.0 + build: hbebe991_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.22.0-hbebe991_1.conda + sha256: a114b4d46eebede7e514abaf9203ea8c952a6382c5c57d1b989da062e3899bd7 + md5: ec7ea95b08e8cbc39fa16b6eafee36e6 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libcxx >=16 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - openssl >=3.2.1,<4.0a0 + constrains: + - libgoogle-cloud 2.22.0 *_1 + license: Apache-2.0 + license_family: Apache + size: 836916 + timestamp: 1709739767863 +- kind: conda + name: libgoogle-cloud + version: 2.22.0 + build: hd739bbb_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-2.22.0-hd739bbb_1.conda + sha256: ed838cad9631c37fa12159594f2bc5b4eae1dfa5db09a83e0939a4410ef3b8c3 + md5: 85707855a6af6e3bf37779a478403b37 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgcc-ng >=12 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + - openssl >=3.2.1,<4.0a0 + constrains: + - libgoogle-cloud 2.22.0 *_1 + license: Apache-2.0 + license_family: Apache + size: 1192943 + timestamp: 1709738727212 - kind: conda name: libgoogle-cloud-storage version: 2.21.0 @@ -8431,26 +12373,135 @@ packages: timestamp: 1708637621024 - kind: conda name: libgoogle-cloud-storage - version: 2.21.0 - build: hc7a4891_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.21.0-hc7a4891_2.conda - sha256: c2237a8fffd58553d31e0a135746de979e2b6a7eaf001748bdb98cf618db3d52 - md5: cc54c794dac0d76eb1adaf6172e9c59e + version: 2.21.0 + build: hc7a4891_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.21.0-hc7a4891_2.conda + sha256: c2237a8fffd58553d31e0a135746de979e2b6a7eaf001748bdb98cf618db3d52 + md5: cc54c794dac0d76eb1adaf6172e9c59e + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libgcc-ng >=12 + - libgoogle-cloud 2.21.0 h72bcb37_2 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + size: 749865 + timestamp: 1708638542903 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: h8a76758_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-2.22.0-h8a76758_1.conda + sha256: e23be5896fd78e0e8b1098aab8803192f0c4a328d3d30a57d20d80194045d793 + md5: a89fb5b36b08efaae128d4933e593315 + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libcxx >=16 + - libgoogle-cloud 2.22.0 hbebe991_1 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + size: 507478 + timestamp: 1709740510222 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: ha67e85c_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.22.0-ha67e85c_1.conda + sha256: e4f351e55fe7c0656cb608eba8690063e3b407d25a855c9d1fd832486d4a1244 + md5: 0c25180c34b1a58d309b28386698fb6e + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libcxx >=16 + - libgoogle-cloud 2.22.0 h651e89d_1 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + size: 523045 + timestamp: 1709739227970 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: hb581fae_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.22.0-hb581fae_1.conda + sha256: 5ee34f168948211db14874f521e6edf9b4032d533c61fd429caaa282be1d0e7b + md5: f63348292dea55cf834e631cf26e2669 + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libgoogle-cloud 2.22.0 h9cad5c0_1 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 14330 + timestamp: 1709737542249 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: hc7a4891_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.22.0-hc7a4891_1.conda + sha256: 0e00e1ca2a981db1c96071edf266bc29fd6f13ac484225de1736fc4dac5c64a8 + md5: 7811f043944e010e54640918ea82cecd + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libgcc-ng >=12 + - libgoogle-cloud 2.22.0 h9be4e54_1 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + size: 748818 + timestamp: 1709738181078 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: hdb39181_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-storage-2.22.0-hdb39181_1.conda + sha256: e0be5d1add9e3332e6155cebddd3f9f2ea4cc2840e2f3cb4413ed53bd8a42129 + md5: 7c15ecbf56d3a5467ae399e963dacbb8 depends: - libabseil - libcrc32c >=1.1.2,<1.2.0a0 - libcurl - libgcc-ng >=12 - - libgoogle-cloud 2.21.0 h72bcb37_2 + - libgoogle-cloud 2.22.0 hd739bbb_1 - libstdcxx-ng >=12 - libzlib >=1.2.13,<1.3.0a0 - openssl license: Apache-2.0 license_family: Apache - size: 749865 - timestamp: 1708638542903 + size: 698963 + timestamp: 1709739002982 - kind: conda name: libgrpc version: 1.59.3 @@ -8634,6 +12685,131 @@ packages: license_family: APACHE size: 4975767 timestamp: 1707807808364 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h15f2491_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.62.1-h15f2491_0.conda + sha256: 1d4ece94dfef73d904dcba0fd9d56098796f5fdc62ea5f9edff60c71be7a3d63 + md5: 564517a8cbd095cff75eb996d33d2b7e + depends: + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 7667664 + timestamp: 1709938059287 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h384b2fc_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.1-h384b2fc_0.conda + sha256: 8c9898d259e2343df52259b599ec342c386679e1c420df603cba6f06078fcdd6 + md5: 2ac05daca7276a4d6ca4465707670380 + depends: + - __osx >=10.13 + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 4432823 + timestamp: 1709938959215 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h5273850_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.62.1-h5273850_0.conda + sha256: 338cb58d1095ee651acd168af9636834b41908f7a94e613088e284dc53d2947c + md5: 99ac2f772591801641ec692fee843796 + depends: + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 15963245 + timestamp: 1709939262816 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h98a9317_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libgrpc-1.62.1-h98a9317_0.conda + sha256: 64f196a0893223bcf0f91ea89b0118a07f32c7dae8377bdee2d9f7fdf39cd3d5 + md5: 17107fbb7822215e90d12bb8c42102f4 + depends: + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 6820015 + timestamp: 1709938779780 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h9c18a4f_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.62.1-h9c18a4f_0.conda + sha256: b8c6b48430d0778e9452df88fa7c07fc7828aac87291372ac42dbe78be4078d5 + md5: 24f15c1a9e111825d39bf77881430107 + depends: + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 4753906 + timestamp: 1709939281511 - kind: conda name: libhwloc version: 2.9.3 @@ -8680,6 +12856,20 @@ packages: license: GPL and LGPL size: 1450368 timestamp: 1652700749886 +- kind: conda + name: libiconv + version: '1.17' + build: h31becfc_2 + build_number: 2 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.17-h31becfc_2.conda + sha256: a30e09d089cb75a0d5b8e5c354694c1317da98261185ed65aa3793e741060614 + md5: 9a8eb13f14de7d761555a98712e6df65 + depends: + - libgcc-ng >=12 + license: LGPL-2.1-only + size: 705787 + timestamp: 1702684557134 - kind: conda name: libiconv version: '1.17' @@ -8867,6 +13057,25 @@ packages: license_family: BSD size: 14599 timestamp: 1705979579648 +- kind: conda + name: liblapack + version: 3.9.0 + build: 21_linuxaarch64_openblas + build_number: 21 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.9.0-21_linuxaarch64_openblas.conda + sha256: 87c110c6a1171c62d6a8802098c4186dcc8eca0ee2d0376a843e0cd025096e4a + md5: ab08b651e3630c20d3032e59859f34f7 + depends: + - libblas 3.9.0 21_linuxaarch64_openblas + constrains: + - liblapacke 3.9.0 21_linuxaarch64_openblas + - blas * openblas + - libcblas 3.9.0 21_linuxaarch64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14583 + timestamp: 1705979400733 - kind: conda name: liblapack version: 3.9.0 @@ -9000,6 +13209,24 @@ packages: license_family: Apache size: 33321457 timestamp: 1701375836233 +- kind: conda + name: libllvm15 + version: 15.0.7 + build: hb4f23b0_4 + build_number: 4 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm15-15.0.7-hb4f23b0_4.conda + sha256: 12da3344f2ef37dcb80b4e2d106cf36ebc267c3be6211a8306dd1dbf07399d61 + md5: 8d7aa8eae04dc19426a417528d7041eb + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<1.3.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 32882415 + timestamp: 1701366839578 - kind: conda name: libllvm15 version: 15.0.7 @@ -9038,6 +13265,25 @@ packages: license_family: Apache size: 23877550 timestamp: 1690533932497 +- kind: conda + name: libllvm16 + version: 16.0.6 + build: h0b931ab_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm16-16.0.6-h0b931ab_3.conda + sha256: 4b1e37e830983d4d0886a894b984411914a25eb6cf9db9d806c4e93053a99d4b + md5: 333f681d34b2fb5d1947b3b6b3e798a6 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 34835275 + timestamp: 1701373096012 - kind: conda name: libllvm16 version: 16.0.6 @@ -9255,6 +13501,76 @@ packages: license_family: Apache size: 26306756 timestamp: 1701378823527 +- kind: conda + name: libllvm18 + version: 18.1.1 + build: h2448989_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.1-h2448989_0.conda + sha256: 4501e62ee42644f158b2273e6cef621c2bac148ebe729fb3ca10b337df83fa3a + md5: a77e3c2c568b3b5d8a79b158d0c5dd47 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.5,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 38392079 + timestamp: 1710432419352 +- kind: conda + name: libllvm18 + version: 18.1.1 + build: h30cc82d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.1-h30cc82d_0.conda + sha256: 35f2fbe7f87c9fda6f36c0ee8efc5b99c347a2f7a0d4bca3d0511b612773a30d + md5: a215b38429566e17aa4d9dba24680d0d + depends: + - libcxx >=16 + - libxml2 >=2.12.5,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 25777635 + timestamp: 1710434884978 +- kind: conda + name: libllvm18 + version: 18.1.1 + build: hbcf5fad_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.1-hbcf5fad_0.conda + sha256: d5f0042e48091740f7084d390a4948b2a739acbc4045f852f7561c0597e1a078 + md5: 9cfc7fa4bdbf1f0558f053285b4b6afb + depends: + - libcxx >=16 + - libxml2 >=2.12.5,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 27599082 + timestamp: 1710435070093 +- kind: conda + name: libllvm18 + version: 18.1.1 + build: hbfe100b_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm18-18.1.1-hbfe100b_0.conda + sha256: dbe94b626d33e2ea273ea8d86e500ae5911cd4b6aaf84d0aab881f6c7c531c20 + md5: cf5da33f6f0ea717dc71d73e5ff7f93f + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.5,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 37702614 + timestamp: 1710430191630 - kind: conda name: libnghttp2 version: 1.58.0 @@ -9318,6 +13634,41 @@ packages: license_family: MIT size: 565451 timestamp: 1702130473930 +- kind: conda + name: libnghttp2 + version: 1.58.0 + build: hb0e430d_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.58.0-hb0e430d_1.conda + sha256: ecc11e4f92f9d5830a90d42b4db55c66c4ad531e00dcf30d55171d934a568cb5 + md5: 8f724cdddffa79152de61f5564a3526b + depends: + - c-ares >=1.23.0,<2.0a0 + - libev >=4.33,<4.34.0a0 + - libev >=4.33,<5.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.0,<4.0a0 + license: MIT + license_family: MIT + size: 677508 + timestamp: 1702130071743 +- kind: conda + name: libnl + version: 3.9.0 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libnl-3.9.0-h31becfc_0.conda + sha256: f69dd5a4ed9f51e8e3abaa529f8f9127541c5b2afb8ec75b9deddbb72a054498 + md5: eb3aee596100fbb7eb4d69056be75868 + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + license_family: LGPL + size: 747627 + timestamp: 1702657818170 - kind: conda name: libnl version: 3.9.0 @@ -9332,6 +13683,20 @@ packages: license_family: LGPL size: 732866 timestamp: 1702657849946 +- kind: conda + name: libnsl + version: 2.0.1 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h31becfc_0.conda + sha256: fd18c2b75d7411096428d36a70b36b1a17e31f7b8956b6905d145792d49e97f8 + md5: c14f32510f694e3185704d89967ec422 + depends: + - libgcc-ng >=12 + license: LGPL-2.1-only + license_family: GPL + size: 34501 + timestamp: 1697358973269 - kind: conda name: libnsl version: 2.0.1 @@ -9474,6 +13839,24 @@ packages: license_family: BSD size: 5578031 timestamp: 1704950143521 +- kind: conda + name: libopenblas + version: 0.3.26 + build: pthreads_h5a5ec62_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.26-pthreads_h5a5ec62_0.conda + sha256: b72719014a86f69162398fc32af0f23e6e1746ec795f7c5d38ad5998a78eb6f8 + md5: 2ea496754b596063335b3aeaa2b982ac + depends: + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + constrains: + - openblas >=0.3.26,<0.3.27.0a0 + license: BSD-3-Clause + license_family: BSD + size: 4306237 + timestamp: 1704951018697 - kind: conda name: libparquet version: 14.0.2 @@ -9493,6 +13876,25 @@ packages: license_family: APACHE size: 1158188 timestamp: 1708689889111 +- kind: conda + name: libparquet + version: 14.0.2 + build: h352af49_13_cpu + build_number: 13 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libparquet-14.0.2-h352af49_13_cpu.conda + sha256: 3675da7fee45dfe0f053bbcb71b5dc32c58eba86eb04dd5e7dbd2e3f5b076edb + md5: 0c4ee07d6a56434b8e1abfdce42ffe9a + depends: + - libarrow 14.0.2 h6bfc85a_13_cpu + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 1160002 + timestamp: 1710345544372 - kind: conda name: libparquet version: 14.0.2 @@ -9530,6 +13932,24 @@ packages: license_family: APACHE size: 925350 timestamp: 1708690516278 +- kind: conda + name: libparquet + version: 14.0.2 + build: h381d950_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h381d950_13_cpu.conda + sha256: e1227a121d942be15d02ec1fde3e43f2a17e5c5a37ed006e5382977d355a3294 + md5: 273a1178373fffd8d76a8e813699297e + depends: + - libarrow 14.0.2 he79e29d_13_cpu + - libcxx >=14 + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 924906 + timestamp: 1710346971895 - kind: conda name: libparquet version: 14.0.2 @@ -9568,6 +13988,45 @@ packages: license_family: APACHE size: 783467 timestamp: 1708690358780 +- kind: conda + name: libparquet + version: 14.0.2 + build: h7ec3a38_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h7ec3a38_13_cpu.conda + sha256: d59b700882bbe39cb387151638bb0becbbb04c86a668426867fb32bad8a37d82 + md5: babba3c50f817f425964de492844a521 + depends: + - libarrow 14.0.2 h2a83f13_13_cpu + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 782893 + timestamp: 1710346323580 +- kind: conda + name: libparquet + version: 14.0.2 + build: hb18b541_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libparquet-14.0.2-hb18b541_12_cpu.conda + sha256: c5befb28607fe3c44b98792fa18f5b6784a801135d70cfde93f44414b9f565da + md5: 9ab277c46fa4ce629ef1b66483b38765 + depends: + - libarrow 14.0.2 h25df049_12_cpu + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 1074395 + timestamp: 1710293046583 - kind: conda name: libparquet version: 14.0.2 @@ -9584,8 +14043,26 @@ packages: - openssl >=3.2.1,<4.0a0 license: Apache-2.0 license_family: APACHE - size: 910129 - timestamp: 1708691448291 + size: 910129 + timestamp: 1708691448291 +- kind: conda + name: libparquet + version: 14.0.2 + build: hf6ce1d5_13_cpu + build_number: 13 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-14.0.2-hf6ce1d5_13_cpu.conda + sha256: f265cc71bb623ce3fef0a681a4744d35562e1ae9a8ed23707cf0d629dc2763ff + md5: 9451897b618c5007a9adc5d9b4ebb0e2 + depends: + - libarrow 14.0.2 h5233fb5_13_cpu + - libcxx >=14 + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 909954 + timestamp: 1710346299150 - kind: conda name: libparquet version: 14.0.2 @@ -9741,6 +14218,96 @@ packages: license_family: BSD size: 2163244 timestamp: 1708436969402 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: h08a7969_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.25.3-h08a7969_0.conda + sha256: 70e0eef046033af2e8d21251a785563ad738ed5281c74e21c31c457780845dcd + md5: 6945825cebd2aeb16af4c69d97c32c13 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2811207 + timestamp: 1709514552541 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: h4e4d658_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-h4e4d658_0.conda + sha256: 3f126769fb5820387d436370ad48600e05d038a28689fdf9988b64e1059947a8 + md5: 57b7ee4f1fd8573781cfdabaec4a7782 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libzlib >=1.2.13,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2216001 + timestamp: 1709514908146 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: h503648d_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.3-h503648d_0.conda + sha256: 5d4c5592be3994657ebf47e52f26b734cc50b0ea9db007d920e2e31762aac216 + md5: 4da7de0ba35777742edf67bf7a1075df + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + size: 5650604 + timestamp: 1709514804631 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: h648ac29_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-4.25.3-h648ac29_0.conda + sha256: 76775a1457b2d4de1097bec2fda16b8e6e80f761d11aa7a525fa215bff4ab87c + md5: a239d63913ec9e008bdbe35899f677f4 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2576197 + timestamp: 1709513627963 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: hbfab5d5_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-4.25.3-hbfab5d5_0.conda + sha256: d754519abc3ddbdedab2a38d0639170f5347c1573eef80c707f3a8dc5dff706a + md5: 5f70b2b945a9741cba7e6dfe735a02a7 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libzlib >=1.2.13,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2154402 + timestamp: 1709514097574 - kind: conda name: libre2-11 version: 2023.06.02 @@ -9858,6 +14425,26 @@ packages: license_family: BSD size: 184017 timestamp: 1708947106275 +- kind: conda + name: libre2-11 + version: 2023.09.01 + build: h9d008c2_2 + build_number: 2 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libre2-11-2023.09.01-h9d008c2_2.conda + sha256: 1da5cfd57091a52c822ec9580694f1e07817e53db43b0407a477daa2d2a16fcd + md5: 387c114aadcaeb02210f646c4b5efca2 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + constrains: + - re2 2023.09.01.* + license: BSD-3-Clause + license_family: BSD + size: 217529 + timestamp: 1708946830978 - kind: conda name: libre2-11 version: 2023.09.01 @@ -9949,6 +14536,75 @@ packages: license: Unlicense size: 870045 timestamp: 1707495642340 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h091b4b1_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + sha256: 7c234320a1a2132b9cc972aaa06bb215bb220a5b1addb0bed7a5a321c805920e + md5: 9d07427ee5bd9afd1e11ce14368a48d6 + depends: + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 825300 + timestamp: 1710255078823 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h194ca79_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda + sha256: 0ce6de6369c04386cfc8696b1f795f425843789609ae2e04e7a1eb7deae62a8b + md5: bf4c96a21fbfc6a6ef6a7781a534a4e0 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 1038462 + timestamp: 1710253998432 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h2797004_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + sha256: 8cdbeb7902729e319510a82d7c642402981818702b58812af265ef55d1315473 + md5: 866983a220e27a80cb75e85cb30466a1 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 857489 + timestamp: 1710254744982 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h92b6c6a_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda + sha256: 320ec73a4e3dd377757a2595770b8137ec4583df4d7782472d76377cdbdc4543 + md5: 086f56e13a96a6cfb1bf640505ae6b70 + depends: + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 902355 + timestamp: 1710254991672 +- kind: conda + name: libsqlite + version: 3.45.2 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda + sha256: 4bb24b986550275a6d02835150d943c4c675808d05c0efc5c2a22154d007a69f + md5: f95359f8dc5abf7da7776ece9ef10bc5 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Unlicense + size: 869606 + timestamp: 1710255095740 - kind: conda name: libssh2 version: 1.11.0 @@ -9965,6 +14621,22 @@ packages: license_family: BSD size: 271133 timestamp: 1685837707056 +- kind: conda + name: libssh2 + version: 1.11.0 + build: h492db2e_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.0-h492db2e_0.conda + sha256: 409163dd4a888b9266369f1bce57b5ca56c216e34249637c3e10eb404e356171 + md5: 45532845e121677ad328c9af9953f161 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.1.1,<4.0a0 + license: BSD-3-Clause + license_family: BSD + size: 284335 + timestamp: 1685837600415 - kind: conda name: libssh2 version: 1.11.0 @@ -10055,6 +14727,19 @@ packages: license_family: GPL size: 3834139 timestamp: 1706819252496 +- kind: conda + name: libstdcxx-ng + version: 13.2.0 + build: h9a76618_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-13.2.0-h9a76618_5.conda + sha256: c209f23a8a497fc87107a68b6bbc8d2089cf15fd4015b558dfdce63544379b05 + md5: 1b79d37dce0fad96bdf3de03925f43b4 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 3752658 + timestamp: 1706820778418 - kind: conda name: libthrift version: 0.19.0 @@ -10073,6 +14758,25 @@ packages: license_family: APACHE size: 331154 timestamp: 1695958512679 +- kind: conda + name: libthrift + version: 0.19.0 + build: h043aeee_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libthrift-0.19.0-h043aeee_1.conda + sha256: 83d38df283ae258eb73807442ccee62364cf50b853d238a5b03092374c7bcf45 + md5: 591ef1567ed4989d824fe35b45e3ae68 + depends: + - libevent >=2.1.12,<2.1.13.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.1.3,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 400010 + timestamp: 1695958016227 - kind: conda name: libthrift version: 0.19.0 @@ -10156,6 +14860,20 @@ packages: license_family: MIT size: 103492 timestamp: 1667316405233 +- kind: conda + name: libutf8proc + version: 2.8.0 + build: h4e544f5_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libutf8proc-2.8.0-h4e544f5_0.tar.bz2 + sha256: c1956b64ad9613c66cf87398f5e2c36d071034a93892da7e8cc22e75cface878 + md5: bf0defbd8ac06270fb5ec05c85fb3c96 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 101529 + timestamp: 1667315331359 - kind: conda name: libutf8proc version: 2.8.0 @@ -10198,6 +14916,20 @@ packages: license_family: BSD size: 33601 timestamp: 1680112270483 +- kind: conda + name: libuuid + version: 2.38.1 + build: hb4cce97_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.38.1-hb4cce97_0.conda + sha256: 616277b0c5f7616c2cdf36f6c316ea3f9aa5bb35f2d4476a349ab58b9b91675f + md5: 000e30b09db0b7c775b21695dff30969 + depends: + - libgcc-ng >=12 + license: BSD-3-Clause + license_family: BSD + size: 35720 + timestamp: 1680113474501 - kind: conda name: libuv version: 1.44.2 @@ -10227,6 +14959,20 @@ packages: license_family: MIT size: 396101 timestamp: 1693539567563 +- kind: conda + name: libuv + version: 1.46.0 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.46.0-h31becfc_0.conda + sha256: 8c7aca3bb0cdcdc94984dbdeeb6e81669e140e4e70e1b58243a39019380aa600 + md5: 9f34d91c42a7820676a895c314910ba7 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 625152 + timestamp: 1693539400188 - kind: conda name: libuv version: 1.46.0 @@ -10253,6 +14999,60 @@ packages: license_family: MIT size: 893348 timestamp: 1693539405436 +- kind: conda + name: libuv + version: 1.47.0 + build: h67532ce_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.47.0-h67532ce_0.conda + sha256: a452b8fbb906e72d6c633ed133413f6a604471597f4c80dc73b4e81d2ef56b32 + md5: c2c8307836ecebc2799400a4eca27b37 + license: MIT + license_family: MIT + size: 404907 + timestamp: 1707450430194 +- kind: conda + name: libuv + version: 1.47.0 + build: h93a5062_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.47.0-h93a5062_0.conda + sha256: 802da3ad57041480f15fe0581d6fcd421d9cdae17d796d2b126b0a12aa2d3d44 + md5: b586a09ba87849e37634cbaf9ea0e60f + license: MIT + license_family: MIT + size: 404350 + timestamp: 1707450365805 +- kind: conda + name: libuv + version: 1.48.0 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda + sha256: 6151c51857c2407139ce22fdc956022353e675b2bc96991a9201d51cceaa90b4 + md5: 485e49e1d500d996844df14cabf64d73 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + size: 289753 + timestamp: 1709913743184 +- kind: conda + name: libxcrypt + version: 4.4.36 + build: h31becfc_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + sha256: 6b46c397644091b8a26a3048636d10b989b1bf266d4be5e9474bf763f828f41f + md5: b4df5d7d4b63579d081fd3a4cf99740e + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + size: 114269 + timestamp: 1702724369203 - kind: conda name: libxcrypt version: 4.4.36 @@ -10363,6 +15163,24 @@ packages: license_family: MIT size: 704829 timestamp: 1707084502281 +- kind: conda + name: libxml2 + version: 2.12.5 + build: h3091e33_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.5-h3091e33_0.conda + sha256: 34f7a007fa23b70c56358738d7ba801df9a923422f2dcd23f3b2ca790ea2460a + md5: 2fcb5d64474a337f2a4213ec1dd40ce2 + depends: + - icu >=73.2,<74.0a0 + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 752149 + timestamp: 1707084726972 - kind: conda name: libxml2 version: 2.12.5 @@ -10398,6 +15216,23 @@ packages: license_family: MIT size: 1567894 timestamp: 1707084720091 +- kind: conda + name: libzlib + version: 1.2.13 + build: h31becfc_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda + sha256: aeeefbb61e5e8227e53566d5e42dbb49e120eb99109996bf0dbfde8f180747a7 + md5: b213aa87eea9491ef7b129179322e955 + depends: + - libgcc-ng >=12 + constrains: + - zlib 1.2.13 *_5 + license: Zlib + license_family: Other + size: 67036 + timestamp: 1686575148440 - kind: conda name: libzlib version: 1.2.13 @@ -10615,6 +15450,21 @@ packages: license_family: BSD size: 134235 timestamp: 1674728465431 +- kind: conda + name: lz4-c + version: 1.9.4 + build: hd600fc2_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.9.4-hd600fc2_0.conda + sha256: 076870eb72411f41c46598c7582a2f3f42ba94c526a2d60a0c8f70a0a7a64429 + md5: 500145a83ed07ce79c8cef24252f366b + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: BSD-2-Clause + license_family: BSD + size: 163770 + timestamp: 1674727020254 - kind: conda name: lz4-c version: 1.9.4 @@ -10710,7 +15560,7 @@ packages: name: markdown-it-py version: 3.0.0 build: pyhd8ed1ab_0 - subdir: win-64 + subdir: noarch noarch: python url: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda sha256: c041b0eaf7a6af3344d5dd452815cdc148d6284fec25a4fa3f4263b3a021e962 @@ -10718,85 +15568,50 @@ packages: depends: - mdurl >=0.1,<1 - python >=3.8 - arch: x86_64 - platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/markdown-it-py size: 64356 timestamp: 1686175179621 - kind: conda - name: markupsafe - version: 2.1.5 - build: py311h05b510d_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda - sha256: 3f2127bd8788dc4b7c3d6d65ae4b7d2f8c7d02a246fc17b819390edeca53fd93 - md5: a27177455a9d29f4ac9d687a489e5d52 - depends: - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - jinja2 >=3.0.0 - license: BSD-3-Clause - license_family: BSD - size: 26578 - timestamp: 1706900556332 -- kind: conda - name: markupsafe - version: 2.1.5 - build: py311h459d7ec_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda - sha256: 14912e557a6576e03f65991be89e9d289c6e301921b6ecfb4e7186ba974f453d - md5: a322b4185121935c871d201ae00ac143 - depends: - - libgcc-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - jinja2 >=3.0.0 - license: BSD-3-Clause - license_family: BSD - size: 27502 - timestamp: 1706900084436 -- kind: conda - name: markupsafe - version: 2.1.5 - build: py311ha68e1ae_0 + name: markdown-it-py + version: 3.0.0 + build: pyhd8ed1ab_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda - sha256: c629f79fe78b5df7f08daa6b7f125f7a67f789bf734949c6d68aa063d7296208 - md5: 07da1326e2837e055ef6f44ef3334b0a + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + sha256: c041b0eaf7a6af3344d5dd452815cdc148d6284fec25a4fa3f4263b3a021e962 + md5: 93a8e71256479c62074356ef6ebf501b depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - jinja2 >=3.0.0 - license: BSD-3-Clause - license_family: BSD - size: 30011 - timestamp: 1706900632904 + - mdurl >=0.1,<1 + - python >=3.8 + arch: x86_64 + platform: win + license: MIT + license_family: MIT + purls: + - pkg:pypi/markdown-it-py + size: 64356 + timestamp: 1686175179621 - kind: conda - name: markupsafe - version: 2.1.5 - build: py311he705e18_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-2.1.5-py311he705e18_0.conda - sha256: 83a2b764a4946a04e693a4dd8fe5a35bf093a378da9ce18bf0689cd5dcb3c3fe - md5: 75abe7e2e3a0874a49d7c175115f443f + name: maturin + version: 1.4.0 + build: py311h06e5ef9_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.4.0-py311h06e5ef9_0.conda + sha256: 2a24157cc1247c02bfbb7a7e214622035548ed9e5bef52bcff3b13e091286791 + md5: dc365d844be0acc4fc0e24d8b7f33f4a depends: + - libgcc-ng >=12 + - openssl >=3.2.0,<4.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - constrains: - - jinja2 >=3.0.0 - license: BSD-3-Clause - license_family: BSD - size: 26155 - timestamp: 1706900211496 + - tomli >=1.1.0 + license: MIT + license_family: MIT + size: 6218103 + timestamp: 1701556894019 - kind: conda name: maturin version: 1.4.0 @@ -10883,6 +15698,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/mdurl size: 13707 timestamp: 1639515992326 - kind: conda @@ -10898,44 +15715,10 @@ packages: - python >=3.6 license: MIT license_family: MIT + purls: + - pkg:pypi/mdurl size: 14680 timestamp: 1704317789138 -- kind: conda - name: meilisearch - version: 1.5.1 - build: h5ef7bb8_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/meilisearch-1.5.1-h5ef7bb8_0.conda - sha256: c359718f193da18e77b7d19402d7453fa732978433ac562bbc86dfd17ef1bff8 - md5: 595899dbe10e2a0ab8e37f894f683082 - license: MIT - license_family: MIT - size: 81671718 - timestamp: 1702680633448 -- kind: conda - name: meilisearch - version: 1.5.1 - build: h8b8d39b_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/meilisearch-1.5.1-h8b8d39b_0.conda - sha256: 20d6cb4a77ef155a3dd86bc671681ed2c616dab96fd0a9a6aea0a85119411a12 - md5: 7e7bf2fea36389d2177cdca54df2d4ce - license: MIT - license_family: MIT - size: 80798614 - timestamp: 1702681657601 -- kind: conda - name: meilisearch - version: 1.5.1 - build: hc85fda4_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/meilisearch-1.5.1-hc85fda4_0.conda - sha256: b6545f77a15b4535f28f7b20d6d9cf957d06537a14e83ba159694effc6f546e2 - md5: d84149b3fce1ed6384959f7096a27877 - license: MIT - license_family: MIT - size: 81301310 - timestamp: 1702680502752 - kind: conda name: meilisearch version: 1.5.1 @@ -10999,6 +15782,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/more-itertools size: 53654 timestamp: 1691087125209 - kind: conda @@ -11014,6 +15799,8 @@ packages: - python >=3.8 license: MIT license_family: MIT + purls: + - pkg:pypi/more-itertools size: 54469 timestamp: 1704738585811 - kind: conda @@ -11086,6 +15873,26 @@ packages: license_family: MIT size: 9963457 timestamp: 1703184979309 +- kind: conda + name: mypy + version: 1.8.0 + build: py311hcd402e7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda + sha256: 2a1d84dc94a02ed3cae2fad6dfea0fab4a9504649c1a009d1fff7bfbd9d48e57 + md5: 22b4d0e0a591e6dba331d95f8a702517 + depends: + - libgcc-ng >=12 + - 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 + license: MIT + license_family: MIT + size: 15129179 + timestamp: 1703185374507 - kind: conda name: mypy version: 1.8.0 @@ -11104,6 +15911,23 @@ packages: license_family: MIT size: 11969071 timestamp: 1703184938293 +- kind: conda + name: mypy_extensions + version: 1.0.0 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda + sha256: f240217476e148e825420c6bc3a0c0efb08c0718b7042fae960400c02af858a3 + md5: 4eccaeba205f0aed9ac3a9ea58568ca3 + depends: + - python >=3.5 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy-extensions + size: 10492 + timestamp: 1675543414256 - kind: conda name: mypy_extensions version: 1.0.0 @@ -11119,8 +15943,24 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/mypy-extensions size: 10492 timestamp: 1675543414256 +- kind: conda + name: ncurses + version: '6.4' + build: h0425590_2 + build_number: 2 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4-h0425590_2.conda + sha256: d71cf2f2b1a9fae7ee2455a35a890423838e9594294beb4a002fe7c7b10bc086 + md5: 4ff0a396150dedad4269e16e5810f769 + depends: + - libgcc-ng >=12 + license: X11 AND BSD-3-Clause + size: 920540 + timestamp: 1698751239554 - kind: conda name: ncurses version: '6.4' @@ -11249,6 +16089,21 @@ packages: license_family: Apache size: 121284 timestamp: 1676837793132 +- kind: conda + name: ninja + version: 1.11.1 + build: hdd96247_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda + sha256: 2ba2e59f619c58d748f4b1b858502587691a7ed0fa9ac2c26ac04091908d95ae + md5: 58f4c67113cda9171e3c03d3e62731e1 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 2398482 + timestamp: 1676839419214 - kind: conda name: ninja version: 1.11.1 @@ -11343,29 +16198,114 @@ packages: size: 15614862 timestamp: 1700389549489 - kind: conda - name: nox - version: 2021.10.1 - build: pyhd8ed1ab_0 + name: nodejs + version: 18.19.0 + build: h119ffd7_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.19.0-h119ffd7_0.conda + sha256: 896ca8a8683f7d6c3402364f6d28bd00b9d3cb9acb88c85d2fc9ecefbbf4f7db + md5: 022ff05e89afedc3db2decb77a8af207 + depends: + - icu >=73.2,<74.0a0 + - libcxx >=14 + - libuv >=1.47.0,<1.48.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zlib + constrains: + - __osx >=10.15 + license: MIT + license_family: MIT + size: 11439181 + timestamp: 1707771884027 +- kind: conda + name: nodejs + version: 18.19.0 + build: h57928b3_0 subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/nox-2021.10.1-pyhd8ed1ab_0.tar.bz2 - sha256: 2f453a747762a186a500c2dbbc8dd78bc717223725d3701686083e79b02aee50 - md5: c29de03dc9c5595cb011a6b2204c14f5 - depends: - - argcomplete >=1.9.4,<2.0 - - colorlog >=2.6.1,<5.0.0 - - importlib_metadata - - jinja2 + url: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.19.0-h57928b3_0.conda + sha256: de01dd21f413e0e230b62082d5ee7f25b19b3c7296e1172c7cef94c9d36b8c38 + md5: 41ce77dc534e5bc71b0fc1687a89dcfd + license: MIT + license_family: MIT + size: 22479049 + timestamp: 1707403072267 +- kind: conda + name: nodejs + version: 18.19.0 + build: h5f47a4d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.19.0-h5f47a4d_0.conda + sha256: 1263d3c8aa9adaf4e11616dc05fb28cfdb761d70f2298959728f847688073240 + md5: 7798b881265f448c752fbae08e221b10 + depends: + - icu >=73.2,<74.0a0 + - libcxx >=14 + - libuv >=1.47.0,<1.48.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zlib + license: MIT + license_family: MIT + size: 10879191 + timestamp: 1707778803050 +- kind: conda + name: nodejs + version: 18.19.0 + build: hb753e55_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.19.0-hb753e55_0.conda + sha256: d233fe4da686125c2b89d588349eccc78cdcb5a75a2b5b5bc9dc4d0c8c23eda1 + md5: 0b4a67051e3b3812818ccf2f4ee2fd4e + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=73.2,<74.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libuv >=1.46.0,<1.47.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zlib + license: MIT + license_family: MIT + size: 15917143 + timestamp: 1707407233064 +- kind: conda + name: nodejs + version: 18.19.0 + build: hc1f8a26_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda + sha256: 161e061a43f9069c2fb7daab8ee3e442d9eb6cd27f332c5bd2e5746643030c72 + md5: b83df948ac353669bab45fa6efb4c312 + depends: + - icu >=73.2,<74.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libuv >=1.46.0,<1.47.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zlib + license: MIT + license_family: MIT + size: 16126685 + timestamp: 1707414728922 +- kind: pypi + name: nox + version: 2024.3.2 + url: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + sha256: e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + requires_dist: + - argcomplete <4.0, >=1.9.4 + - colorlog <7.0.0, >=2.6.1 + - importlib-metadata ; python_version < '3.8' - packaging >=20.9 - - py >=1.4.0,<2.0.0 - - python >=3.6 - - virtualenv >=14.0.0 - arch: x86_64 - platform: win - license: Apache-2.0 - license_family: Apache - size: 39937 - timestamp: 1633199959832 + - typing-extensions >=3.7.4 ; python_version < '3.8' + - virtualenv >=20.14.1 + - jinja2 ; extra == 'tox_to_nox' + - tox ; extra == 'tox_to_nox' + - uv ; extra == 'uv' + requires_python: '>=3.7' - kind: conda name: numpy version: 1.26.4 @@ -11387,6 +16327,8 @@ packages: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/numpy size: 7104093 timestamp: 1707226459646 - kind: conda @@ -11409,8 +16351,35 @@ packages: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/numpy size: 8065890 timestamp: 1707225944355 +- kind: conda + name: numpy + version: 1.26.4 + build: py311h69ead2a_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda + sha256: 88800a1d9d11c2fccab09d40d36f7001616f5119eaf0ec86186562f33564e651 + md5: 3fd00dd400c8d3f9da12bf33061dd28d + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy + size: 7234391 + timestamp: 1707225781489 - kind: conda name: numpy version: 1.26.4 @@ -11431,6 +16400,8 @@ packages: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/numpy size: 6652352 timestamp: 1707226297967 - kind: conda @@ -11452,6 +16423,8 @@ packages: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/numpy size: 7504319 timestamp: 1707226235372 - kind: conda @@ -11470,6 +16443,23 @@ packages: license_family: Apache size: 2862719 timestamp: 1706635779319 +- kind: conda + name: openssl + version: 3.2.1 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda + sha256: 952ef5de4e3913621a89ca2eb8186683bb73832527219c6443c260a6b46cd149 + md5: b7e7c53240214ae96f52a440c0b0126a + depends: + - ca-certificates + - libgcc-ng >=12 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 3382700 + timestamp: 1706635800272 - kind: conda name: openssl version: 3.2.1 @@ -11602,77 +16592,175 @@ packages: - lz4-c >=1.9.3,<1.10.0a0 - snappy >=1.1.10,<2.0a0 - zstd >=1.5.5,<1.6.0a0 - arch: x86_64 - platform: linux + arch: x86_64 + platform: linux + license: Apache-2.0 + license_family: Apache + size: 1018308 + timestamp: 1700372809593 +- kind: conda + name: orc + version: 1.9.2 + build: h798d188_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h798d188_2.conda + sha256: eb45795b9d965fe7c066d283a72a883697bc9940d6696b641073d53a332bfa94 + md5: f09fc67b7de2e85b573b929fab0af059 + depends: + - libcxx >=16 + - libprotobuf >=4.25.2,<4.25.3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 407007 + timestamp: 1708632909550 +- kind: conda + name: orc + version: 1.9.2 + build: h7c018df_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h7c018df_0.conda + sha256: b1ad0f09dc69a8956079371d9853534f991f8311352e4e21503e6e5d20e4017b + md5: 1ef4159e9686d95ce8ea9f1d4d999f29 + depends: + - __osx >=10.9 + - libcxx >=16.0.6 + - libprotobuf >=4.24.4,<4.24.5.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + arch: aarch64 + platform: osx + license: Apache-2.0 + license_family: Apache + size: 405599 + timestamp: 1700373052638 +- kind: conda + name: orc + version: 1.9.2 + build: h9ab30d4_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h9ab30d4_0.conda + sha256: a948db80c0b756db07abce1972d6b8d1a08a7ced5a687b02435348c81443de08 + md5: 8fb76f7b135aec885cfe47c52b2eb4b5 + depends: + - __osx >=10.13 + - __osx >=10.9 + - libcxx >=16.0.6 + - libprotobuf >=4.24.4,<4.24.5.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + arch: x86_64 + platform: osx + license: Apache-2.0 + license_family: Apache + size: 423917 + timestamp: 1700373043647 +- kind: conda + name: orc + version: 2.0.0 + build: h1e5e2c1_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/orc-2.0.0-h1e5e2c1_0.conda + sha256: ed8cfe1f35e8ef703e540e7731e77fade1410bba406e17727a10dee08c37d5b4 + md5: 53e8f030579d34e1a36a735d527c021f + depends: + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 1028974 + timestamp: 1710232781925 +- kind: conda + name: orc + version: 2.0.0 + build: h3d3088e_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.0.0-h3d3088e_0.conda + sha256: 6a1f553e2ea3d2df3c465b02c7ece5c001cc2d3afb1fe7e2678a7ff7a5a14168 + md5: a8e452c3f2b6fecfd86e8f2b72450a9b + depends: + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 license: Apache-2.0 license_family: Apache - size: 1018308 - timestamp: 1700372809593 + size: 413922 + timestamp: 1710233361620 - kind: conda name: orc - version: 1.9.2 - build: h798d188_2 - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h798d188_2.conda - sha256: eb45795b9d965fe7c066d283a72a883697bc9940d6696b641073d53a332bfa94 - md5: f09fc67b7de2e85b573b929fab0af059 + version: 2.0.0 + build: h6c6cd50_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.0-h6c6cd50_0.conda + sha256: 0c198b6a8de238d53002e7c03e4b1e94e769cf388adac2717fdaadfee9381a14 + md5: 5ce58b9a5679fe6640d6d68228099ce9 depends: + - __osx >=10.13 - libcxx >=16 - - libprotobuf >=4.25.2,<4.25.3.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - snappy >=1.1.10,<2.0a0 - zstd >=1.5.5,<1.6.0a0 license: Apache-2.0 license_family: Apache - size: 407007 - timestamp: 1708632909550 + size: 433224 + timestamp: 1710233383447 - kind: conda name: orc - version: 1.9.2 - build: h7c018df_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h7c018df_0.conda - sha256: b1ad0f09dc69a8956079371d9853534f991f8311352e4e21503e6e5d20e4017b - md5: 1ef4159e9686d95ce8ea9f1d4d999f29 + version: 2.0.0 + build: h75d905f_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-h75d905f_0.conda + sha256: 32c843b4ce01d29ed04e81ea5c20d78051d47091c6a27b9f6e1eb7c428983b01 + md5: 7fb160bb1300a3043fec7e40d50e9aa6 depends: - - __osx >=10.9 - - libcxx >=16.0.6 - - libprotobuf >=4.24.4,<4.24.5.0a0 + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - snappy >=1.1.10,<2.0a0 - zstd >=1.5.5,<1.6.0a0 - arch: aarch64 - platform: osx license: Apache-2.0 license_family: Apache - size: 405599 - timestamp: 1700373052638 + size: 999580 + timestamp: 1710232876736 - kind: conda name: orc - version: 1.9.2 - build: h9ab30d4_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h9ab30d4_0.conda - sha256: a948db80c0b756db07abce1972d6b8d1a08a7ced5a687b02435348c81443de08 - md5: 8fb76f7b135aec885cfe47c52b2eb4b5 + version: 2.0.0 + build: heb0c069_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/orc-2.0.0-heb0c069_0.conda + sha256: 5a9c0904f38e5c2e1d1494bd192ff98fca13ca07ed1590497b16a801bef497a0 + md5: 2733034196c084cdc07e0facfea995ea depends: - - __osx >=10.13 - - __osx >=10.9 - - libcxx >=16.0.6 - - libprotobuf >=4.24.4,<4.24.5.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - snappy >=1.1.10,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 - zstd >=1.5.5,<1.6.0a0 - arch: x86_64 - platform: osx license: Apache-2.0 license_family: Apache - size: 423917 - timestamp: 1700373043647 + size: 953672 + timestamp: 1710233287310 - kind: conda name: packaging version: '23.2' @@ -11688,8 +16776,27 @@ packages: platform: win license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/packaging size: 49452 timestamp: 1696202521121 +- kind: conda + name: packaging + version: '24.0' + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + sha256: a390182d74c31dfd713c16db888c92c277feeb6d1fe96ff9d9c105f9564be48a + md5: 248f521b64ce055e7feae3105e7abeb8 + depends: + - python >=3.8 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging + size: 49832 + timestamp: 1710076089469 - kind: conda name: patchelf version: 0.17.2 @@ -11720,6 +16827,8 @@ packages: platform: win license: MPL-2.0 license_family: MOZILLA + purls: + - pkg:pypi/pathspec size: 38649 timestamp: 1690598108100 - kind: conda @@ -11735,6 +16844,8 @@ packages: - python >=3.7 license: MPL-2.0 license_family: MOZILLA + purls: + - pkg:pypi/pathspec size: 41173 timestamp: 1702250135032 - kind: conda @@ -11754,6 +16865,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/pip size: 1386212 timestamp: 1690024763393 - kind: conda @@ -11771,6 +16884,8 @@ packages: - wheel license: MIT license_family: MIT + purls: + - pkg:pypi/pip size: 1398245 timestamp: 1706960660581 - kind: conda @@ -11789,6 +16904,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/platformdirs size: 19985 timestamp: 1696272419779 - kind: conda @@ -11804,6 +16921,8 @@ packages: - python >=3.8 license: MIT license_family: MIT + purls: + - pkg:pypi/platformdirs size: 20210 timestamp: 1706713564353 - kind: conda @@ -11821,6 +16940,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/pluggy size: 22548 timestamp: 1693086745921 - kind: conda @@ -11836,6 +16957,8 @@ packages: - python >=3.8 license: MIT license_family: MIT + purls: + - pkg:pypi/pluggy size: 23384 timestamp: 1706116931972 - kind: conda @@ -11884,6 +17007,21 @@ packages: license_family: MIT size: 12979886 timestamp: 1691677482320 +- kind: conda + name: prettier + version: 2.8.8 + build: hc2da131_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda + sha256: 92edf0f0b6b5464ba65c16cdd4c9c589904d702f31cfa3da083d2e9148a208ac + md5: 76323f2eb984976e77da9b357f488a6b + depends: + - nodejs >=18.16.1,<19.0a0 + license: MIT + license_family: MIT + size: 12873889 + timestamp: 1691677118975 - kind: conda name: prettier version: 2.8.8 @@ -11913,6 +17051,8 @@ packages: - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/psutil size: 513415 timestamp: 1705722847446 - kind: conda @@ -11929,6 +17069,8 @@ packages: - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/psutil size: 505516 timestamp: 1705722586221 - kind: conda @@ -11947,8 +17089,29 @@ packages: - vc14_runtime >=14.29.30139 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/psutil size: 520242 timestamp: 1705723070638 +- kind: conda + name: psutil + version: 5.9.8 + build: py311hcd402e7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda + sha256: d04efc76d734ac2f1e00f52e3385ba80b089becf60aaae52f0edf185ca9f69e0 + md5: 858767f880caa447ae640a991ec5ba9e + depends: + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil + size: 506604 + timestamp: 1705722743163 - kind: conda name: psutil version: 5.9.8 @@ -11962,6 +17125,8 @@ packages: - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/psutil size: 513371 timestamp: 1705722716862 - kind: conda @@ -11979,22 +17144,35 @@ packages: size: 144301 timestamp: 1537755684331 - kind: conda - name: py - version: 1.11.0 - build: pyh6c4a22f_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/py-1.11.0-pyh6c4a22f_0.tar.bz2 - sha256: 268be33a290e3d51467ab29cbb5a80cf79f69dade2f2dead25d7f80d76c3543a - md5: b4613d7e7a493916d867842a6a148054 - depends: - - python >=2.7 - arch: x86_64 - platform: win - license: MIT - license_family: MIT - size: 76038 - timestamp: 1636301988765 + name: pyarrow + version: 14.0.2 + build: py311h1eb6f34_12_cpu + build_number: 12 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda + sha256: b8946dd95fe52d3b11332738f9a14191590d7c53820de424e43209ed7b94066c + md5: f99ad4baaa57ab44e9af3aaa89c7bfc3 + depends: + - libarrow 14.0.2 h25df049_12_cpu + - libarrow-acero 14.0.2 h2f0025b_12_cpu + - libarrow-dataset 14.0.2 h2f0025b_12_cpu + - libarrow-flight 14.0.2 h2f4a9e5_12_cpu + - libarrow-flight-sql 14.0.2 hc81a7a7_12_cpu + - libarrow-gandiva 14.0.2 h3a2b1eb_12_cpu + - libarrow-substrait 14.0.2 hd45466a_12_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 hb18b541_12_cpu + - libstdcxx-ng >=12 + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 4398440 + timestamp: 1710295377459 - kind: conda name: pyarrow version: 14.0.2 @@ -12024,6 +17202,35 @@ packages: license_family: APACHE size: 4524767 timestamp: 1708692350829 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h39c9aba_13_cpu + build_number: 13 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_13_cpu.conda + sha256: 2eef5e752f71b9a2f74491e0f9d3c9e58761f179f8198cb8d710627ca3e9a13d + md5: e95c99f69395f1a43582de9b0d35a553 + depends: + - libarrow 14.0.2 h6bfc85a_13_cpu + - libarrow-acero 14.0.2 h59595ed_13_cpu + - libarrow-dataset 14.0.2 h59595ed_13_cpu + - libarrow-flight 14.0.2 hc6145d9_13_cpu + - libarrow-flight-sql 14.0.2 h757c851_13_cpu + - libarrow-gandiva 14.0.2 hb016d2e_13_cpu + - libarrow-substrait 14.0.2 h757c851_13_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 h352af49_13_cpu + - libstdcxx-ng >=12 + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 4543451 + timestamp: 1710347598355 - kind: conda name: pyarrow version: 14.0.2 @@ -12081,6 +17288,34 @@ packages: license_family: APACHE size: 4009410 timestamp: 1708691836141 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h54e7ce8_13_cpu + build_number: 13 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_13_cpu.conda + sha256: 543f8b4e7cc6453b64b0dd20b43ac312cc61fe28e10869f04edf5ee29214ce13 + md5: 9b4945755f71df2d66e2e9af881b4b0c + depends: + - libarrow 14.0.2 he79e29d_13_cpu + - libarrow-acero 14.0.2 h000cb23_13_cpu + - libarrow-dataset 14.0.2 h000cb23_13_cpu + - libarrow-flight 14.0.2 h2382776_13_cpu + - libarrow-flight-sql 14.0.2 h7e3fe20_13_cpu + - libarrow-gandiva 14.0.2 ha5acb15_13_cpu + - libarrow-substrait 14.0.2 h7e3fe20_13_cpu + - libcxx >=14 + - libparquet 14.0.2 h381d950_13_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 4020354 + timestamp: 1710348158705 - kind: conda name: pyarrow version: 14.0.2 @@ -12139,6 +17374,36 @@ packages: license_family: APACHE size: 3465525 timestamp: 1708693288111 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h6a6099b_13_cpu + build_number: 13 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_13_cpu.conda + sha256: 76d0f17e140cb3f22adefe568fa6fb5b0eaec250dc22306d4da21b8ce5869260 + md5: b22193a1d8c2d28f6c3dbb94da33147d + depends: + - libarrow 14.0.2 h2a83f13_13_cpu + - libarrow-acero 14.0.2 h63175ca_13_cpu + - libarrow-dataset 14.0.2 h63175ca_13_cpu + - libarrow-flight 14.0.2 h02312f3_13_cpu + - libarrow-flight-sql 14.0.2 h55b4db4_13_cpu + - libarrow-gandiva 14.0.2 hcb01e45_13_cpu + - libarrow-substrait 14.0.2 h89268de_13_cpu + - libparquet 14.0.2 h7ec3a38_13_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 3470330 + timestamp: 1710349686722 - kind: conda name: pyarrow version: 14.0.2 @@ -12168,6 +17433,35 @@ packages: license_family: APACHE size: 4094429 timestamp: 1708693258443 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311hd7bc329_13_cpu + build_number: 13 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_13_cpu.conda + sha256: 077d688f4c748f99760d7b8555c6ecf0c071381d2978032316d0c50389a083a0 + md5: fdd086b17f9ae33004bdd1991ccb1321 + depends: + - libarrow 14.0.2 h5233fb5_13_cpu + - libarrow-acero 14.0.2 h13dd4ca_13_cpu + - libarrow-dataset 14.0.2 h13dd4ca_13_cpu + - libarrow-flight 14.0.2 h95ca633_13_cpu + - libarrow-flight-sql 14.0.2 hdc5392b_13_cpu + - libarrow-gandiva 14.0.2 hfef958d_13_cpu + - libarrow-substrait 14.0.2 hef52601_13_cpu + - libcxx >=14 + - libparquet 14.0.2 hf6ce1d5_13_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 4084630 + timestamp: 1710348774061 - kind: conda name: pyarrow version: 14.0.2 @@ -12212,6 +17506,8 @@ packages: platform: win license: BSD-2-Clause license_family: BSD + purls: + - pkg:pypi/pygments size: 853439 timestamp: 1691408777841 - kind: conda @@ -12227,6 +17523,8 @@ packages: - python >=3.7 license: BSD-2-Clause license_family: BSD + purls: + - pkg:pypi/pygments size: 860425 timestamp: 1700608076927 - kind: conda @@ -12252,6 +17550,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/pytest size: 244691 timestamp: 1694128618921 - kind: conda @@ -12275,8 +17575,35 @@ packages: - pytest-faulthandler >=2 license: MIT license_family: MIT + purls: + - pkg:pypi/pytest size: 251713 timestamp: 1706448088334 +- kind: conda + name: pytest + version: 8.1.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + sha256: 3c481d6b54af1a33c32a3f3eaa3e0971955431e7023db55808740cd062271c73 + md5: 94ff09cdedcb7b17e9cd5097ee2cfcff + depends: + - colorama + - exceptiongroup >=1.0.0rc8 + - iniconfig + - packaging + - pluggy <2.0,>=1.4 + - python >=3.8 + - tomli >=1 + constrains: + - pytest-faulthandler >=2 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pytest + size: 255523 + timestamp: 1709992719691 - kind: conda name: python version: 3.11.8 @@ -12303,6 +17630,36 @@ packages: license: Python-2.0 size: 18096526 timestamp: 1708116524168 +- kind: conda + name: python + version: 3.11.8 + build: h43d1f9e_0_cpython + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda + sha256: 4dbd3ac5f760cbf8c613df0a29d970ed1e8235101be1fa74ccd833300661706f + md5: fec01f7d8fdfec9c4881a1c9bdbc959e + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-aarch64 >=2.36.1 + - libexpat >=2.5.0,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc-ng >=12 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.45.1,<4.0a0 + - libuuid >=2.38.1,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.2.13,<1.3.0a0 + - ncurses >=6.4,<7.0a0 + - openssl >=3.2.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.11.* *_cp311 + license: Python-2.0 + size: 15317480 + timestamp: 1708116052369 - kind: conda name: python version: 3.11.8 @@ -12398,6 +17755,21 @@ packages: license_family: BSD size: 6385 timestamp: 1695147338551 +- kind: conda + name: python_abi + version: '3.11' + build: 4_cp311 + build_number: 4 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda + sha256: 135a21de5721a2667613529b4ac50a9454979bf969fa99d74b6e5ad9a4ff284d + md5: 89983f987dfee288f94ddb2ee550ea60 + constrains: + - python 3.11.* *_cpython + license: BSD-3-Clause + license_family: BSD + size: 6384 + timestamp: 1695147390555 - kind: conda name: python_abi version: '3.11' @@ -12462,6 +17834,23 @@ packages: license_family: BSD size: 3735644 timestamp: 1684785130341 +- kind: conda + name: rdma-core + version: '50.0' + build: h0425590_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda + sha256: 146c5f5c0162b39508b0f8d5b87e01e788ff6d553165e901e813afbf3b81ab50 + md5: 0e2cbcc4194d73065fcad8a4fb049893 + depends: + - libgcc-ng >=12 + - libnl >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + license: Linux-OpenIB + license_family: BSD + size: 4744617 + timestamp: 1710157969911 - kind: conda name: rdma-core version: '50.0' @@ -12479,6 +17868,24 @@ packages: license_family: BSD size: 4724921 timestamp: 1706524445013 +- kind: conda + name: rdma-core + version: '50.0' + build: hd3aeb46_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-50.0-hd3aeb46_1.conda + sha256: 85e38508eb4921e53cf1cb97435f9c9408ea2ddc582c6588ec50f3f3ec3abdc0 + md5: f462219598fcf46c0cdfb985c3482b4f + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libnl >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + license: Linux-OpenIB + license_family: BSD + size: 4713842 + timestamp: 1710157799992 - kind: conda name: re2 version: 2023.06.02 @@ -12551,6 +17958,21 @@ packages: license_family: BSD size: 26617 timestamp: 1708946796423 +- kind: conda + name: re2 + version: 2023.09.01 + build: h9caee61_2 + build_number: 2 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda + sha256: 31db9c598bfa7586ac2e3ba06681d676caa5d252b5b68f4b6173edc71f70681e + md5: a9667ab785e1686d53313364c695f58e + depends: + - libre2-11 2023.09.01 h9d008c2_2 + license: BSD-3-Clause + license_family: BSD + size: 26726 + timestamp: 1708946863063 - kind: conda name: re2 version: 2023.09.01 @@ -12597,6 +18019,22 @@ packages: license_family: GPL size: 281456 timestamp: 1679532220005 +- kind: conda + name: readline + version: '8.2' + build: h8fc344f_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + sha256: 4c99f7417419734e3797d45bc355e61c26520e111893b0d7087a01a7fbfbe3dd + md5: 105eb1e16bf83bfb2eb380a48032b655 + depends: + - libgcc-ng >=12 + - ncurses >=6.3,<7.0a0 + license: GPL-3.0-only + license_family: GPL + size: 294092 + timestamp: 1679532238805 - kind: conda name: readline version: '8.2' @@ -12639,6 +18077,20 @@ packages: license_family: MIT size: 177229 timestamp: 1693456080514 +- kind: conda + name: rhash + version: 1.4.4 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda + sha256: 11c44602ac8f3054da83bfcfff0d8e04e83e231b51b0f8c660ff007669de14ff + md5: 8e4df96fa39923f420006095785a0e4b + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 199565 + timestamp: 1693455889616 - kind: conda name: rhash version: 1.4.4 @@ -12703,6 +18155,24 @@ packages: license_family: MIT size: 184071 timestamp: 1700160247583 +- kind: conda + name: rich + version: 13.7.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda + sha256: 2b26d58aa59e46f933c3126367348651b0dab6e0bf88014e857415bb184a4667 + md5: ba445bf767ae6f0d959ff2b40c20912b + depends: + - markdown-it-py >=2.2.0 + - pygments >=2.13.0,<3.0.0 + - python >=3.7.0 + - typing_extensions >=4.0.0,<5.0.0 + license: MIT + license_family: MIT + size: 184347 + timestamp: 1709150578093 - kind: conda name: ruff version: 0.2.2 @@ -12718,6 +18188,8 @@ packages: - python_abi 3.11.* *_cp311 license: MIT license_family: MIT + purls: + - pkg:pypi/ruff size: 5717696 timestamp: 1708223090811 - kind: conda @@ -12737,6 +18209,8 @@ packages: - __osx >=11.0 license: MIT license_family: MIT + purls: + - pkg:pypi/ruff size: 5280983 timestamp: 1708223865116 - kind: conda @@ -12755,8 +18229,30 @@ packages: - vc14_runtime >=14.29.30139 license: MIT license_family: MIT + purls: + - pkg:pypi/ruff size: 5662517 timestamp: 1708224151838 +- kind: conda + name: ruff + version: 0.2.2 + build: py311he69e3a7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.2.2-py311he69e3a7_0.conda + sha256: 79692d93fd01d2600aad350d34efa4faae33b87f35acce1560de61b4f14cc597 + md5: d43da3e0a735527d540d7f8947ee179b + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruff + size: 5439861 + timestamp: 1708223383662 - kind: conda name: ruff version: 0.2.2 @@ -12773,6 +18269,8 @@ packages: - __osx >=10.12 license: MIT license_family: MIT + purls: + - pkg:pypi/ruff size: 5540591 timestamp: 1708224008985 - kind: conda @@ -12807,6 +18305,53 @@ packages: license_family: Apache size: 337907 timestamp: 1708664518615 +- kind: conda + name: s2n + version: 1.4.5 + build: h5a25046_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda + sha256: a72687e4bab7c9a0f2b502335f93daa84e3a8fcec0787e08923a62607cf01191 + md5: a7fa2e8f06035a24564ff3a7b84d2bd3 + depends: + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 333810 + timestamp: 1708664562153 +- kind: conda + name: s2n + version: 1.4.6 + build: h06160fa_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.6-h06160fa_0.conda + sha256: 2d03e27d607e3b797ada1ab805deebdd321c3ec99c1581188ac22041c06fd7b6 + md5: 88350a8ea5a9aa734b8b553bfd2ff78c + depends: + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 339401 + timestamp: 1709937040957 +- kind: conda + name: semver + version: 2.13.0 + build: pyh9f0ad1d_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + sha256: 673ef5ef04cef60c3584b1d9b81024646b9d9a4c50749356c7ba5cede755e61d + md5: 2cab9f3a9683cb40a2176ccaf76e66c6 + depends: + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/semver + size: 15712 + timestamp: 1603697876069 - kind: conda name: semver version: 2.13.0 @@ -12822,6 +18367,8 @@ packages: platform: win license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/semver size: 15712 timestamp: 1603697876069 - kind: conda @@ -12839,6 +18386,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/setuptools size: 464399 timestamp: 1694548452441 - kind: conda @@ -12854,8 +18403,27 @@ packages: - python >=3.7 license: MIT license_family: MIT + purls: + - pkg:pypi/setuptools size: 470548 timestamp: 1704224855187 +- kind: conda + name: setuptools + version: 69.2.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + sha256: 78a75c75a5dacda6de5f4056c9c990141bdaf4f64245673a590594d00bc63713 + md5: da214ecd521a720a9d521c68047682dc + depends: + - python >=3.8 + license: MIT + license_family: MIT + purls: + - pkg:pypi/setuptools + size: 471183 + timestamp: 1710344615844 - kind: conda name: sigtool version: 0.1.3 @@ -12884,6 +18452,23 @@ packages: license_family: MIT size: 213817 timestamp: 1643442169866 +- kind: conda + name: smmap + version: 5.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + sha256: 23011cb3e064525bdb8787c75126a2e78d2344a72cd6773922006d1da1f2af16 + md5: 62f26a3d1387acee31322208f0cfa3e0 + depends: + - python >=3.5 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/smmap + size: 22483 + timestamp: 1634310465482 - kind: conda name: smmap version: 5.0.0 @@ -12899,6 +18484,8 @@ packages: platform: win license: BSD-3-Clause license_family: BSD + purls: + - pkg:pypi/smmap size: 22483 timestamp: 1634310465482 - kind: conda @@ -12944,6 +18531,21 @@ packages: license_family: BSD size: 38865 timestamp: 1678534590321 +- kind: conda + name: snappy + version: 1.1.10 + build: he8610fa_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda + sha256: 5a7d6cf781cbaaea4effce4d8f2677cd6173af5e8b744912e1283a704eb91946 + md5: 11c25e55894bb8207a81a87e6a32b6e7 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: BSD-3-Clause + license_family: BSD + size: 38265 + timestamp: 1678534683114 - kind: conda name: snappy version: 1.1.10 @@ -13095,6 +18697,21 @@ packages: license_family: APACHE size: 161382 timestamp: 1706164225098 +- kind: conda + name: tk + version: 8.6.13 + build: h194ca79_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda + sha256: 7fa27cc512d3a783f38bd16bbbffc008807372499d5b65d089a8e43bde9db267 + md5: f75105e0585851f818e0009dd1dde4dc + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: TCL + license_family: BSD + size: 3351802 + timestamp: 1695506242997 - kind: conda name: tk version: 8.6.13 @@ -13225,6 +18842,23 @@ packages: license_family: BSD size: 3318875 timestamp: 1699202167581 +- kind: conda + name: tomli + version: 2.0.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + sha256: 4cd48aba7cd026d17e86886af48d0d2ebc67ed36f87f6534f4b67138f5a5a58f + md5: 5844808ffab9ebdb694585b50ba02a96 + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli + size: 15940 + timestamp: 1644342331069 - kind: conda name: tomli version: 2.0.1 @@ -13240,8 +18874,27 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/tomli size: 15940 timestamp: 1644342331069 +- kind: conda + name: tomlkit + version: 0.12.3 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + sha256: 53cc436ab92d38683df1320e4468a8b978428e800195bf1c8c2460e90b0bc117 + md5: 074d0ce7a6261ab8b497c3518796ef3e + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomlkit + size: 37132 + timestamp: 1700046842169 - kind: conda name: tomlkit version: 0.12.3 @@ -13257,6 +18910,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/tomlkit size: 37132 timestamp: 1700046842169 - kind: conda @@ -13291,6 +18946,8 @@ packages: platform: win license: PSF-2.0 license_family: PSF + purls: + - pkg:pypi/typing-extensions size: 35108 timestamp: 1695040948828 - kind: conda @@ -13306,8 +18963,27 @@ packages: - python >=3.8 license: PSF-2.0 license_family: PSF + purls: + - pkg:pypi/typing-extensions size: 36058 timestamp: 1702176292645 +- kind: conda + name: typing_extensions + version: 4.10.0 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + sha256: 4be24d557897b2f6609f5d5f7c437833c62f4d4a96581e39530067e96a2d0451 + md5: 16ae769069b380646c47142d719ef466 + depends: + - python >=3.8 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions + size: 37018 + timestamp: 1708904796013 - kind: conda name: typos version: 1.16.20 @@ -13426,6 +19102,77 @@ packages: license_family: MIT size: 3652168 timestamp: 1707161817201 +- kind: conda + name: typos + version: 1.19.0 + build: h11a7dfb_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/typos-1.19.0-h11a7dfb_0.conda + sha256: 79da26e5585382a4ec5dde9ba0d43435f0dd441e9f344ef99d12f2dab0117b74 + md5: 97b99652ce2673198b2ab73b7cf85c31 + constrains: + - __osx >=10.12 + license: MIT + license_family: MIT + size: 3305763 + timestamp: 1709332590675 +- kind: conda + name: typos + version: 1.19.0 + build: h1d8f897_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda + sha256: 3cb7579ee8924d3fb0ba10ae42620aec9f6decaf8499510910ce8052ba269b82 + md5: 1b4263817ba9418e1c6bd7547028eef3 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 3607084 + timestamp: 1709332306391 +- kind: conda + name: typos + version: 1.19.0 + build: h5ef7bb8_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.19.0-h5ef7bb8_0.conda + sha256: d73ae2b63301e440049a9b0f78c9b6747d9ef1a6be360a5856ab77c6cefceca7 + md5: 8516e396a23de65bad5066799fdbecf2 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 3307039 + timestamp: 1709332619096 +- kind: conda + name: typos + version: 1.19.0 + build: h7f3b576_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/typos-1.19.0-h7f3b576_0.conda + sha256: b9dc051dccb7cc9fb99d130f42703f0b14b711408d5b94d5864984b982981eb8 + md5: 0066abed96ba51601722fda1eee87973 + depends: + - m2w64-gcc-libs + - m2w64-gcc-libs-core + license: MIT + license_family: MIT + size: 2571575 + timestamp: 1709333263031 +- kind: conda + name: typos + version: 1.19.0 + build: he8a937b_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/typos-1.19.0-he8a937b_0.conda + sha256: ee886a360248e517b75980e7c7249fbba7bed97e5f67371257f8dc29b5c348df + md5: 97d8f139e4fb369369fb71f53e29be45 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 3616719 + timestamp: 1709332292966 - kind: conda name: tzdata version: 2024a @@ -13452,6 +19199,25 @@ packages: license_family: PROPRIETARY size: 1283972 timestamp: 1666630199266 +- kind: conda + name: ucx + version: 1.15.0 + build: h11edf95_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h11edf95_7.conda + sha256: 3e381ec5918045a43e0f349214a4d38e53990897ba07a6abf025f9e0156acaf2 + md5: 20a94f617ad76922f8737ad1fe317f4d + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - rdma-core >=50.0 + constrains: + - cuda-version >=11.2,<12 + license: BSD-3-Clause + license_family: BSD + size: 6847943 + timestamp: 1710357262334 - kind: conda name: ucx version: 1.15.0 @@ -13493,6 +19259,25 @@ packages: license_family: BSD size: 15172395 timestamp: 1705978902381 +- kind: conda + name: ucx + version: 1.15.0 + build: hcf8619e_7 + build_number: 7 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda + sha256: a22855693b154dc1a691d93b2acf21b3b485c355535d2f5bc23981fb6e330b53 + md5: 1c7268d3f881267e4f3c181257b3ad41 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - rdma-core >=50.0 + constrains: + - cuda-version >=11.2,<12 + license: BSD-3-Clause + license_family: BSD + size: 6868398 + timestamp: 1710357060520 - kind: conda name: vc version: '14.3' @@ -13565,44 +19350,36 @@ packages: license_family: Proprietary size: 749868 timestamp: 1702511239004 -- kind: conda - name: virtualenv - version: 20.24.6 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.24.6-pyhd8ed1ab_0.conda - sha256: 09492f89a22dc17d9b32f2a791deee93d06e99fb312c3d47430fe35343b7fbde - md5: fb1fc875719e217ed799a7aae11d3be4 - depends: - - distlib <1,>=0.3.7 - - filelock <4,>=3.12.2 - - platformdirs <4,>=3.9.1 - - python >=3.8 - arch: x86_64 - platform: win - license: MIT - license_family: MIT - size: 3067859 - timestamp: 1698092779433 -- kind: conda +- kind: pypi name: virtualenv - version: 20.25.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.25.0-pyhd8ed1ab_0.conda - sha256: 50827c3721a9dbf973b568709d4381add2a6552fa562f26a385c5edc16a534af - md5: c119653cba436d8183c27bf6d190e587 - depends: - - distlib <1,>=0.3.7 - - filelock <4,>=3.12.2 - - platformdirs <5,>=3.9.1 - - python >=3.8 - license: MIT - license_family: MIT - size: 3122816 - timestamp: 1701458945559 + version: 20.25.1 + url: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + sha256: 961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + requires_dist: + - distlib <1, >=0.3.7 + - filelock <4, >=3.12.2 + - importlib-metadata >=6.6 ; python_version < '3.8' + - platformdirs <5, >=3.9.1 + - furo >=2023.7.26 ; extra == 'docs' + - proselint >=0.13 ; extra == 'docs' + - sphinx-argparse >=0.4 ; extra == 'docs' + - sphinx >=7.1.2 ; extra == 'docs' + - sphinxcontrib-towncrier >=0.2.1a0 ; extra == 'docs' + - towncrier >=23.6 ; extra == 'docs' + - covdefaults >=2.3 ; extra == 'test' + - coverage-enable-subprocess >=1 ; extra == 'test' + - coverage >=7.2.7 ; extra == 'test' + - flaky >=3.7 ; extra == 'test' + - packaging >=23.1 ; extra == 'test' + - pytest-env >=0.8.2 ; extra == 'test' + - pytest-freezer >=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' + - pytest-mock >=3.11.1 ; extra == 'test' + - pytest-randomly >=3.12 ; extra == 'test' + - pytest-timeout >=2.1 ; extra == 'test' + - pytest >=7.4 ; extra == 'test' + - setuptools >=68 ; extra == 'test' + - time-machine >=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' + requires_python: '>=3.7' - kind: conda name: vs2015_runtime version: 14.36.32532 @@ -13664,6 +19441,23 @@ packages: license_family: MIT size: 218421 timestamp: 1682376911339 +- kind: conda + name: wheel + version: 0.38.4 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + sha256: bd4f11ff075ff251ade9f57686f31473e25be46ab282d9603f551401250f9f44 + md5: c829cfb8cb826acb9de0ac1a2df0a940 + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/wheel + size: 32521 + timestamp: 1668051714265 - kind: conda name: wheel version: 0.38.4 @@ -13679,6 +19473,8 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/wheel size: 32521 timestamp: 1668051714265 - kind: conda @@ -13730,6 +19526,36 @@ packages: license: LGPL-2.1 and GPL-2.0 size: 217804 timestamp: 1660346976440 +- kind: conda + name: xz + version: 5.2.6 + build: h9cdd2b7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + sha256: 93f58a7b393adf41fa007ac8c55978765e957e90cd31877ece1e5a343cb98220 + md5: 83baad393a31d59c20b63ba4da6592df + depends: + - libgcc-ng >=12 + license: LGPL-2.1 and GPL-2.0 + size: 440555 + timestamp: 1660348056328 +- kind: conda + name: zipp + version: 3.17.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda + sha256: bced1423fdbf77bca0a735187d05d9b9812d2163f60ab426fc10f11f92ecbe26 + md5: 2e4d6bc0b14e10f895fc6791a7d9b26a + depends: + - python >=3.8 + license: MIT + license_family: MIT + purls: + - pkg:pypi/zipp + size: 18954 + timestamp: 1695255262261 - kind: conda name: zipp version: 3.17.0 @@ -13745,8 +19571,26 @@ packages: platform: win license: MIT license_family: MIT + purls: + - pkg:pypi/zipp size: 18954 timestamp: 1695255262261 +- kind: conda + name: zlib + version: 1.2.13 + build: h31becfc_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + sha256: aa3e9d46b13d1959faf634f03d929d7dec950dc1b84a8ff109f7f0e3f364b562 + md5: 96866c7301479abaf8308c50958c71a4 + depends: + - libgcc-ng >=12 + - libzlib 1.2.13 h31becfc_5 + license: Zlib + license_family: Other + size: 95842 + timestamp: 1686575155348 - kind: conda name: zlib version: 1.2.13 @@ -13810,6 +19654,22 @@ packages: license_family: BSD size: 343428 timestamp: 1693151615801 +- kind: conda + name: zstd + version: 1.5.5 + build: h4c53e97_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + sha256: d1e070029e9d07a3f25e6ed082d507b0f3cff1b109dd18d0b091a5c7b86dd07b + md5: b74eb9dbb5c3c15cb3cee7cbdf198c75 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + size: 528989 + timestamp: 1693151197934 - kind: conda name: zstd version: 1.5.5 diff --git a/pixi.toml b/pixi.toml index 50e264179e07..abd900d9619e 100644 --- a/pixi.toml +++ b/pixi.toml @@ -16,13 +16,14 @@ channels = ["conda-forge"] description = "Log images, point clouds, etc, and visualize them effortlessly" homepage = "https://rerun.io" license = "MIT OR Apache-2.0" -platforms = ["linux-64", "osx-arm64", "osx-64", "win-64"] +platforms = ["linux-64", "linux-aarch64", "osx-arm64", "osx-64", "win-64"] readme = "README.md" repository = "https://github.com/rerun-io/rerun" version = "0.1.0" # TODO(emilk): sync version with `Cargo.toml` with help from `crates.py` [environments] cpp = ["cpp"] +taplo = ["taplo"] [tasks] # Note: extra CLI argument after `pixi run TASK` are passed to the task cmd. @@ -78,12 +79,10 @@ lint-py-fmt-check = "ruff format --check --config rerun_py/pyproject.toml" lint-py-blackdoc = "blackdoc --check" lint-py-mypy = "mypy --install-types --non-interactive --no-warn-unused-ignore" lint-py-ruff = "ruff format --check --config rerun_py/pyproject.toml" -lint-taplo = "taplo fmt --check --diff" lint-typos = "typos" misc-fmt = "prettier --write '**/*.{yml,yaml,js,css,html}'" misc-fmt-check = "prettier --check '**/*.{yml,yaml,js,css,html}'" -toml-fmt = "taplo fmt" ruff-fmt = "ruff format --config rerun_py/pyproject.toml ." ruff-fix = "ruff --fix --config rerun_py/pyproject.toml ." @@ -109,6 +108,14 @@ search-index = "cargo run -p re_build_search_index --release --" # Files are stored in the `meilisearch` directory, so you can fully wipe it via `rm -rf meilisearch`. meilisearch = "meilisearch --db-path=./meilisearch/data.ms --dump-dir=./meilisearch/dumps/ --snapshot-dir=./meilisearch/snapshots/ --env=development --no-analytics --experimental-reduce-indexing-memory-usage --master-key=test" +# TODO(ab): move everything back to the main tasks/dependencies once taplo supports linux-aarch64. +[feature.taplo] +platforms = ["linux-64", "osx-arm64", "osx-64", "win-64"] + +[feature.taplo.tasks] +lint-taplo = "taplo fmt --check --diff" +toml-fmt = "taplo fmt" + [feature.cpp.tasks] # All the cpp-* tasks can be configured with environment variables, e.g.: RERUN_WERROR=ON CXX=clang++ cpp-prepare-release = "cmake -G 'Ninja' -B build/release -S . -DCMAKE_BUILD_TYPE=Release" @@ -152,6 +159,18 @@ cpp-prepare-msvc = "cmake -G 'Visual Studio 17 2022' -B build-msvc -S ." [dependencies] +# IMPORTANT: do not add any dependencies here that may break CI. All dependencies should be available on all supported +# platforms (including linux-aarch64), or added conditionally. +# +# Hints: +# - To check a given package, go to https://prefix.dev/channels/conda-forge/packages/XXXX. It should support Windows, +# x86_64 and aarch64 macOS architectures, and x86_64 and aarch64 Linux architectures. +# - Some pure Python packages may wrongly be tagged as platform-specific. In this case, use `[pypi-dependencies]` +# instead (e.g. `nox`). +# - If a package is only used for a very specific CI job on a specific target, include it under that target (e.g. +# `meilisearch`). +# - Last resort, use a feature to conditionally include a dependency (e.g. `taplo`). + attrs = ">=23.1.0" blackdoc = "0.3.8" clang-tools = "16.0.6" # clang-format @@ -161,7 +180,6 @@ gitignore-parser = ">=0.1.9" gitpython = ">=3.1.40" just = ">=1.15.0" maturin = "1.4.0" -meilisearch = "1.5.1.*" mypy = "1.8.0" numpy = ">=1.23,<2" pip = ">=23" @@ -170,7 +188,6 @@ pytest = ">=7" python = "=3.11" # We use the latest Python version here, so we get the latest mypy etc, EXCEPT 3.12 is too new for some of our examples. We run our CI tests on ALL supported versions though. ruff = "0.2.2" semver = ">=2.13,<2.14" -taplo = "=0.8.1" typing_extensions = ">4.5" typos = ">=1.16.20" wheel = ">=0.38,<0.39" @@ -178,13 +195,19 @@ ninja = "1.11.1" # Make sure to use a version that is compatible with # the theme we're using, see https://github.com/jothepro/doxygen-awesome-css/blob/v2.2.1/README.md doxygen = "1.9.7.*" -binaryen = "116.*" # for `wasm-opt` -nox = "2021.10.1.*" +binaryen = "117.*" # for `wasm-opt` prettier = "2.8.8.*" tomlkit = "0.12.3.*" +[pypi-dependencies] +nox = ">=2024.3.2" # the conda-forge package is (wrongly) tagged as platform-specific + [target.linux-64.dependencies] patchelf = ">=0.17" +meilisearch = "1.5.1.*" # not available for linux-aarch64 + +[feature.taplo.dependencies] +taplo = "=0.8.1" # not (yet?) available for linux-aarch64 [feature.cpp.target.linux-64.dependencies] clang = "16.0.6" From b068aa71979ce5ca5e4dee91f0f3cca1127051ca Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 18 Mar 2024 15:16:55 +0100 Subject: [PATCH 050/508] Fix recommendation from one Space View class affecting recommendation from another (#5554) ### What This broke recently due to the tracking of space view recommendation hashes _without_ taking into account their class. Cleaned up the whole thing a little bit in the progress. * Fixes #5455 * Also mentioned on this ticket is this issue but it turned out to be unrelated (thus now a separate ticket) #5553 * #5455 is new to 0.15alpha, but #5553 happens on 0.14! --- For this script: ```py import rerun as rr rr.init("rerun_example_bug") rr.connect() rr.set_time_sequence("frame_nr", 0) rr.log("boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3)) rr.log("boxes2d", rr.Boxes2D(centers=[[0, 0], [1.3, 0.5], [3, 2]], half_sizes=[0.5, 1] * 3)) rr.log("text_logs", rr.TextLog("Hello, world!", level=rr.TextLogLevel.INFO)) rr.log("points2d", rr.Points2D([[0, 0], [1, 1], [3, 2]], labels=["a", "b", "c"])) ``` Before: Only text view visible. After: image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5554/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5554/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5554/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5554) - [Docs preview](https://rerun.io/preview/707ea2ce9502cfeb726292ae7e43ee8b8a705e92/docs) - [Examples preview](https://rerun.io/preview/707ea2ce9502cfeb726292ae7e43ee8b8a705e92/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 1 + crates/re_types/Cargo.toml | 1 + .../re_types/src/blueprint/components/mod.rs | 1 + .../viewer_recommendation_hash_ext.rs | 10 +++++ .../src/space_view/spawn_heuristics.rs | 24 +++++++++++- crates/re_viewport/src/viewport_blueprint.rs | 23 +++++------ .../release_checklist/check_annotations.py | 2 - .../check_container_hierarchy.py | 2 - ...ntext_menu_add_entity_to_new_space_view.py | 2 - .../check_context_menu_collapse_expand_all.py | 2 - ...heck_context_menu_invalid_sub_container.py | 2 - .../check_context_menu_multi_selection.py | 2 - .../check_context_menu_single_selection.py | 2 - ...xt_menu_single_selection_blueprint_tree.py | 2 - .../check_context_menu_suggested_origin.py | 2 - tests/python/release_checklist/check_focus.py | 2 - .../release_checklist/check_heuristics_2d.py | 2 - .../check_heuristics_mixed_2d_and_3d.py | 5 +-- .../check_heuristics_mixed_all_root.py | 39 +++++++++++++++++++ .../check_hover_select_reset.py | 2 - .../check_parallelism_caching_reentrancy.py | 2 - .../release_checklist/check_plot_overrides.py | 2 - .../release_checklist/check_scalar_clears.py | 2 - 23 files changed, 88 insertions(+), 46 deletions(-) create mode 100644 crates/re_types/src/blueprint/components/viewer_recommendation_hash_ext.rs create mode 100644 tests/python/release_checklist/check_heuristics_mixed_all_root.py diff --git a/Cargo.lock b/Cargo.lock index 4f315aca96a8..9aa5700027ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4923,6 +4923,7 @@ dependencies = [ "mime_guess2", "mint", "ndarray", + "nohash-hasher", "once_cell", "ply-rs", "rand", diff --git a/crates/re_types/Cargo.toml b/crates/re_types/Cargo.toml index 6d32e54cfbc8..35ad4d6d24c5 100644 --- a/crates/re_types/Cargo.toml +++ b/crates/re_types/Cargo.toml @@ -71,6 +71,7 @@ itertools.workspace = true linked-hash-map.workspace = true mime_guess2.workspace = true ndarray.workspace = true +nohash-hasher.workspace = true once_cell.workspace = true ply-rs.workspace = true smallvec.workspace = true diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index d3670e91167c..91c656fa8b69 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -13,6 +13,7 @@ mod row_share; mod space_view_class; mod space_view_origin; mod viewer_recommendation_hash; +mod viewer_recommendation_hash_ext; mod visible; mod visible_ext; mod visible_time_range; diff --git a/crates/re_types/src/blueprint/components/viewer_recommendation_hash_ext.rs b/crates/re_types/src/blueprint/components/viewer_recommendation_hash_ext.rs new file mode 100644 index 000000000000..7cceb882c4fc --- /dev/null +++ b/crates/re_types/src/blueprint/components/viewer_recommendation_hash_ext.rs @@ -0,0 +1,10 @@ +use super::ViewerRecommendationHash; + +impl std::hash::Hash for ViewerRecommendationHash { + #[inline] + fn hash(&self, state: &mut H) { + state.write_u64(self.0 .0); + } +} + +impl nohash_hasher::IsEnabled for ViewerRecommendationHash {} diff --git a/crates/re_viewer_context/src/space_view/spawn_heuristics.rs b/crates/re_viewer_context/src/space_view/spawn_heuristics.rs index 6d5e3302d0ea..7da42a08ddf5 100644 --- a/crates/re_viewer_context/src/space_view/spawn_heuristics.rs +++ b/crates/re_viewer_context/src/space_view/spawn_heuristics.rs @@ -1,7 +1,9 @@ -use re_log_types::{EntityPath, EntityPathFilter, EntityPathSubs}; +use re_log_types::{hash::Hash64, EntityPath, EntityPathFilter, EntityPathSubs}; + +use crate::SpaceViewClassIdentifier; /// Properties of a space view that as recommended to be spawned by default via space view spawn heuristics. -#[derive(Hash, Debug, Clone)] +#[derive(Debug, Clone)] pub struct RecommendedSpaceView { pub origin: EntityPath, pub query_filter: EntityPathFilter, @@ -42,4 +44,22 @@ impl RecommendedSpaceView { pub fn root() -> Self { Self::new_subtree(EntityPath::root()) } + + /// Hash together with the Space View class id to the `ViewerRecommendationHash` component. + /// + /// Recommendations are usually tied to a specific Space View class. + /// Therefore, to identify a recommendation for identification purposes, the class id should be included in the hash. + pub fn recommendation_hash( + &self, + class_id: SpaceViewClassIdentifier, + ) -> re_types::blueprint::components::ViewerRecommendationHash { + let Self { + origin, + query_filter, + } = self; + + Hash64::hash((origin, query_filter, class_id)) + .hash64() + .into() + } } diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index fda7eccd491b..1a621b073e92 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -8,7 +8,6 @@ use smallvec::SmallVec; use re_data_store::LatestAtQuery; use re_entity_db::EntityPath; -use re_log_types::hash::Hash64; use re_query::query_archetype; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::ViewerRecommendationHash; @@ -59,7 +58,7 @@ pub struct ViewportBlueprint { auto_space_views: AtomicBool, /// Hashes of all recommended space views the viewer has already added and that should not be added again. - past_viewer_recommendation_hashes: IntSet, + past_viewer_recommendations: IntSet, /// Channel to pass Blueprint mutation messages back to the [`crate::Viewport`] tree_action_sender: std::sync::mpsc::Sender, @@ -80,7 +79,7 @@ impl ViewportBlueprint { maximized, auto_layout, auto_space_views, - past_viewer_recommendations: past_viewer_recommendation_hashes, + past_viewer_recommendations, } = match query_archetype(blueprint_db.store(), query, &VIEWPORT_PATH.into()) .and_then(|arch| arch.to_archetype()) { @@ -149,10 +148,9 @@ impl ViewportBlueprint { root_container, ); - let past_viewer_recommendation_hashes = past_viewer_recommendation_hashes + let past_viewer_recommendations = past_viewer_recommendations .unwrap_or_default() .into_iter() - .map(|h| Hash64::from_u64(h.0 .0)) .collect(); ViewportBlueprint { @@ -163,7 +161,7 @@ impl ViewportBlueprint { maximized: maximized.map(|id| id.0.into()), auto_layout, auto_space_views, - past_viewer_recommendation_hashes, + past_viewer_recommendations, tree_action_sender, } } @@ -301,8 +299,8 @@ impl ViewportBlueprint { // Remove all space views that we already spawned via heuristic before. recommended_space_views.retain(|recommended_view| { !self - .past_viewer_recommendation_hashes - .contains(&Hash64::hash(recommended_view)) + .past_viewer_recommendations + .contains(&recommended_view.recommendation_hash(class_id)) }); // Each of the remaining recommendations would individually be a candidate for spawning if there were @@ -321,11 +319,14 @@ impl ViewportBlueprint { // mean we should suddenly add `/camera/**` to the viewport. if !recommended_space_views.is_empty() { let new_viewer_recommendation_hashes = self - .past_viewer_recommendation_hashes + .past_viewer_recommendations .iter() .cloned() - .chain(recommended_space_views.iter().map(Hash64::hash)) - .map(|hash| ViewerRecommendationHash(hash.hash64().into())) + .chain( + recommended_space_views + .iter() + .map(|recommendation| recommendation.recommendation_hash(class_id)), + ) .collect::>(); ctx.save_blueprint_component( diff --git a/tests/python/release_checklist/check_annotations.py b/tests/python/release_checklist/check_annotations.py index de25046f7336..e701206fb127 100644 --- a/tests/python/release_checklist/check_annotations.py +++ b/tests/python/release_checklist/check_annotations.py @@ -43,8 +43,6 @@ def log_annotations() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_container_hierarchy.py b/tests/python/release_checklist/check_container_hierarchy.py index 25daf19d5ce7..fac16afd3384 100644 --- a/tests/python/release_checklist/check_container_hierarchy.py +++ b/tests/python/release_checklist/check_container_hierarchy.py @@ -83,8 +83,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py index 99a458e21a79..15407e44c62f 100644 --- a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py +++ b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py @@ -44,8 +44,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py index f3ecb3b14654..c5e74b16a359 100644 --- a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py +++ b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py @@ -40,8 +40,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py index 62b76362976c..53b92e31fb8d 100644 --- a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py +++ b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py @@ -38,8 +38,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_context_menu_multi_selection.py b/tests/python/release_checklist/check_context_menu_multi_selection.py index 030d83bfbe5f..0b7b361fd5c5 100644 --- a/tests/python/release_checklist/check_context_menu_multi_selection.py +++ b/tests/python/release_checklist/check_context_menu_multi_selection.py @@ -84,8 +84,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_context_menu_single_selection.py b/tests/python/release_checklist/check_context_menu_single_selection.py index 04a7b53437fb..9b11958bb713 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection.py +++ b/tests/python/release_checklist/check_context_menu_single_selection.py @@ -94,8 +94,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py index b92577a3a334..40c1a4e03a80 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py +++ b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py @@ -79,8 +79,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_context_menu_suggested_origin.py b/tests/python/release_checklist/check_context_menu_suggested_origin.py index d735b8f98289..6e29e336aeb0 100644 --- a/tests/python/release_checklist/check_context_menu_suggested_origin.py +++ b/tests/python/release_checklist/check_context_menu_suggested_origin.py @@ -66,8 +66,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_focus.py b/tests/python/release_checklist/check_focus.py index 2f4a711e957e..61b590d64242 100644 --- a/tests/python/release_checklist/check_focus.py +++ b/tests/python/release_checklist/check_focus.py @@ -42,8 +42,6 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_heuristics_2d.py b/tests/python/release_checklist/check_heuristics_2d.py index 9b25b5481073..e289a8b2ab34 100644 --- a/tests/python/release_checklist/check_heuristics_2d.py +++ b/tests/python/release_checklist/check_heuristics_2d.py @@ -63,8 +63,6 @@ def log_images() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py b/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py index fa76c569bed7..c0e7dab2d53d 100644 --- a/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py +++ b/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py @@ -15,7 +15,7 @@ Reset the blueprint to make sure you are viewing new heuristics and not a cached blueprint. ### Action -You should see 4 space-views: +You should see 5 space-views: - 2D: `image1` with an all red image - 2D: `image2` with an all green image - 2D: `3D/camera` with an all blue image @@ -23,6 +23,7 @@ - a 3D box - a pinhole camera, showing the blue image - no red or green image + - Text: This readme. """ @@ -49,8 +50,6 @@ def log_3d_scene() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_heuristics_mixed_all_root.py b/tests/python/release_checklist/check_heuristics_mixed_all_root.py new file mode 100644 index 000000000000..8444059469f2 --- /dev/null +++ b/tests/python/release_checklist/check_heuristics_mixed_all_root.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr + +README = """ +# Mixed objects Heuristics with everything directly under root + +This checks whether the heuristics do the right thing with mixed 2D, 3D and test data. + +### Action +You should see 4 space-views: + - 2D: Boxes and points, `$origin` == `/` + - 3D: 3D boxes, `$origin` == `/` + - Text log: A single log line, `$origin` == `/` + - Text: This readme, `$origin` == `/readme` +""" + + +def run(args: Namespace) -> None: + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + rr.log("boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3)) + rr.log("boxes2d", rr.Boxes2D(centers=[[0, 0], [1.3, 0.5], [3, 2]], half_sizes=[0.5, 1] * 3)) + rr.log("text_logs", rr.TextLog("Hello, world!", level=rr.TextLogLevel.INFO)) + rr.log("points2d", rr.Points2D([[0, 0], [1, 1], [3, 2]], labels=["a", "b", "c"])) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) diff --git a/tests/python/release_checklist/check_hover_select_reset.py b/tests/python/release_checklist/check_hover_select_reset.py index f64436e80945..c58b29b41020 100644 --- a/tests/python/release_checklist/check_hover_select_reset.py +++ b/tests/python/release_checklist/check_hover_select_reset.py @@ -80,8 +80,6 @@ def log_points_2d() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py index 40e1fc9bd0bb..b2aeb3632c08 100644 --- a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py +++ b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py @@ -138,8 +138,6 @@ def log_spatial() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_plot_overrides.py b/tests/python/release_checklist/check_plot_overrides.py index b2b1af4595d1..c52ebb5c1e65 100644 --- a/tests/python/release_checklist/check_plot_overrides.py +++ b/tests/python/release_checklist/check_plot_overrides.py @@ -54,8 +54,6 @@ def log_plots() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() diff --git a/tests/python/release_checklist/check_scalar_clears.py b/tests/python/release_checklist/check_scalar_clears.py index 1f4035e4e9e3..6bed4c3fbdfc 100644 --- a/tests/python/release_checklist/check_scalar_clears.py +++ b/tests/python/release_checklist/check_scalar_clears.py @@ -42,8 +42,6 @@ def log_plots() -> None: def run(args: Namespace) -> None: - # TODO(cmc): I have no idea why this works without specifying a `recording_id`, but - # I'm not gonna rely on it anyway. rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) log_readme() From 766c4744a71be67a0837a703d504bbd74e52a8d8 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 18 Mar 2024 16:27:54 +0100 Subject: [PATCH 051/508] Workaround for Github's Ubuntu image getting spurious Asan failures (#5557) ### What Hitting some spurious asan issues on ci: Some Linux runs end up spamming `AddressSanitizer:DEADLYSIGNAL` indefinitely with no additional information. Originally I suspected this came from * #5544 But it's actually a Github image issue, see https://github.com/actions/runner-images/issues/9491 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5557/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5557/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5557/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5557) - [Docs preview](https://rerun.io/preview/8ac1180d749f9bf9ae62ee57f96c66c832758a9d/docs) - [Examples preview](https://rerun.io/preview/8ac1180d749f9bf9ae62ee57f96c66c832758a9d/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/reusable_checks_cpp.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index d98471e91e36..faa590f9eff9 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -84,6 +84,14 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} + # Workaround for ASAN issues on Github images https://github.com/actions/runner-images/issues/9491 + - name: Fix kernel mmap rnd bits + if: runner.os == 'Linux' + # Asan in llvm 14 provided in ubuntu 22.04 is incompatible with + # high-entropy ASLR in much newer kernels that GitHub runners are + # using leading to random crashes: https://reviews.llvm.org/D148280 + run: sudo sysctl vm.mmap_rnd_bits=28 + - name: Build and run C++ tests shell: bash run: | From fd65304d7af45ba75652ad07693803a2cd8f3165 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Mon, 18 Mar 2024 11:48:33 -0400 Subject: [PATCH 052/508] Don't merge recording and blueprint in --test-receive (#5560) ### What This was causing CI failures. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5560/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5560/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5560/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5560) - [Docs preview](https://rerun.io/preview/3747cde334e6ed28de85c5d41353423813d5d706/docs) - [Examples preview](https://rerun.io/preview/3747cde334e6ed28de85c5d41353423813d5d706/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/rerun/src/run.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/rerun/src/run.rs b/crates/rerun/src/run.rs index 9437471ab927..d54501580eb4 100644 --- a/crates/rerun/src/run.rs +++ b/crates/rerun/src/run.rs @@ -793,7 +793,8 @@ fn assert_receive_into_entity_db( ) -> anyhow::Result { re_log::info!("Receiving messages into a EntityDb…"); - let mut db: Option = None; + let mut rec: Option = None; + let mut bp: Option = None; let mut num_messages = 0; @@ -810,9 +811,14 @@ fn assert_receive_into_entity_db( match msg.payload { SmartMessagePayload::Msg(msg) => { - let mut_db = db.get_or_insert_with(|| { - re_entity_db::EntityDb::new(msg.store_id().clone()) - }); + let mut_db = match msg.store_id().kind { + re_log_types::StoreKind::Recording => rec.get_or_insert_with(|| { + re_entity_db::EntityDb::new(msg.store_id().clone()) + }), + re_log_types::StoreKind::Blueprint => bp.get_or_insert_with(|| { + re_entity_db::EntityDb::new(msg.store_id().clone()) + }), + }; mut_db.add(&msg)?; num_messages += 1; @@ -820,7 +826,7 @@ fn assert_receive_into_entity_db( SmartMessagePayload::Quit(err) => { if let Some(err) = err { anyhow::bail!("data source has disconnected unexpectedly: {err}") - } else if let Some(db) = db { + } else if let Some(db) = rec { db.store().sanity_check()?; anyhow::ensure!(0 < num_messages, "No messages received"); re_log::info!("Successfully ingested {num_messages} messages."); From 1385bcd657507f0620673dc6b5f1700b0d6953aa Mon Sep 17 00:00:00 2001 From: rerun-bot <132550499+rerun-bot@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:13:26 +0100 Subject: [PATCH 053/508] Release 0.15.0-alpha.3 (#5559) ### What - [x] Bump all crate versions to `0.15.0-alpha.3` The release process will begin once this pull request is merged. --- Cargo.lock | 186 +++++++++--------- Cargo.toml | 94 ++++----- examples/rust/clock/Cargo.toml | 2 +- examples/rust/custom_data_loader/Cargo.toml | 2 +- examples/rust/custom_space_view/Cargo.toml | 2 +- .../rust/custom_store_subscriber/Cargo.toml | 2 +- examples/rust/dna/Cargo.toml | 2 +- examples/rust/extend_viewer_ui/Cargo.toml | 2 +- examples/rust/external_data_loader/Cargo.toml | 2 +- examples/rust/incremental_logging/Cargo.toml | 2 +- examples/rust/log_file/Cargo.toml | 2 +- examples/rust/minimal/Cargo.toml | 2 +- examples/rust/minimal_options/Cargo.toml | 2 +- examples/rust/minimal_serve/Cargo.toml | 2 +- examples/rust/objectron/Cargo.toml | 2 +- examples/rust/raw_mesh/Cargo.toml | 2 +- examples/rust/shared_recording/Cargo.toml | 2 +- examples/rust/spawn_viewer/Cargo.toml | 2 +- examples/rust/stdio/Cargo.toml | 2 +- examples/rust/template/Cargo.toml | 2 +- tests/rust/plot_dashboard_stress/Cargo.toml | 2 +- 21 files changed, 159 insertions(+), 159 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9aa5700027ea..12859d24a49d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1057,7 +1057,7 @@ dependencies = [ [[package]] name = "clock" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -1394,7 +1394,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] name = "custom_data_loader" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "re_build_tools", "rerun", @@ -1402,7 +1402,7 @@ dependencies = [ [[package]] name = "custom_space_view" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "mimalloc", "re_crash_handler", @@ -1413,7 +1413,7 @@ dependencies = [ [[package]] name = "custom_store_subscriber" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "re_build_tools", "rerun", @@ -1524,7 +1524,7 @@ dependencies = [ [[package]] name = "dna" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "itertools 0.12.0", "rand", @@ -1944,7 +1944,7 @@ dependencies = [ [[package]] name = "extend_viewer_ui" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "mimalloc", "re_crash_handler", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "incremental_logging" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -2957,7 +2957,7 @@ dependencies = [ [[package]] name = "log_benchmark" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -2968,7 +2968,7 @@ dependencies = [ [[package]] name = "log_file" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -3109,14 +3109,14 @@ dependencies = [ [[package]] name = "minimal" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "rerun", ] [[package]] name = "minimal_options" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -3126,7 +3126,7 @@ dependencies = [ [[package]] name = "minimal_serve" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "rerun", "tokio", @@ -3494,7 +3494,7 @@ dependencies = [ [[package]] name = "objectron" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -3677,7 +3677,7 @@ dependencies = [ [[package]] name = "plot_dashboard_stress" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -4094,7 +4094,7 @@ checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" [[package]] name = "raw_mesh" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "bytes", @@ -4133,7 +4133,7 @@ dependencies = [ [[package]] name = "re_analytics" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "crossbeam", "directories-next", @@ -4175,7 +4175,7 @@ dependencies = [ [[package]] name = "re_build_examples" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "argh", @@ -4190,11 +4190,11 @@ dependencies = [ [[package]] name = "re_build_info" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" [[package]] name = "re_build_search_index" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "argh", @@ -4219,7 +4219,7 @@ dependencies = [ [[package]] name = "re_build_tools" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "cargo_metadata 0.18.1", @@ -4232,7 +4232,7 @@ dependencies = [ [[package]] name = "re_build_web_viewer" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "cargo_metadata 0.18.1", @@ -4242,7 +4242,7 @@ dependencies = [ [[package]] name = "re_crash_handler" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "backtrace", "itertools 0.12.0", @@ -4254,7 +4254,7 @@ dependencies = [ [[package]] name = "re_data_source" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4277,7 +4277,7 @@ dependencies = [ [[package]] name = "re_data_store" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4307,7 +4307,7 @@ dependencies = [ [[package]] name = "re_data_ui" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4334,7 +4334,7 @@ dependencies = [ [[package]] name = "re_entity_db" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4368,14 +4368,14 @@ dependencies = [ [[package]] name = "re_error" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", ] [[package]] name = "re_format" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "comfy-table", "re_arrow2", @@ -4385,7 +4385,7 @@ dependencies = [ [[package]] name = "re_int_histogram" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "criterion", "insta", @@ -4396,7 +4396,7 @@ dependencies = [ [[package]] name = "re_log" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "env_logger", "js-sys", @@ -4409,7 +4409,7 @@ dependencies = [ [[package]] name = "re_log_encoding" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "criterion", "ehttp", @@ -4434,7 +4434,7 @@ dependencies = [ [[package]] name = "re_log_types" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4472,7 +4472,7 @@ dependencies = [ [[package]] name = "re_memory" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "backtrace", @@ -4493,7 +4493,7 @@ dependencies = [ [[package]] name = "re_query" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "backtrace", "criterion", @@ -4517,7 +4517,7 @@ dependencies = [ [[package]] name = "re_query_cache" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "criterion", @@ -4542,7 +4542,7 @@ dependencies = [ [[package]] name = "re_renderer" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4589,7 +4589,7 @@ dependencies = [ [[package]] name = "re_renderer_examples" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4613,7 +4613,7 @@ dependencies = [ [[package]] name = "re_sdk" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4645,7 +4645,7 @@ dependencies = [ [[package]] name = "re_sdk_comms" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "crossbeam", @@ -4661,7 +4661,7 @@ dependencies = [ [[package]] name = "re_smart_channel" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "crossbeam", "parking_lot", @@ -4671,7 +4671,7 @@ dependencies = [ [[package]] name = "re_space_view" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "egui", @@ -4692,7 +4692,7 @@ dependencies = [ [[package]] name = "re_space_view_bar_chart" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "egui", "egui_plot", @@ -4710,7 +4710,7 @@ dependencies = [ [[package]] name = "re_space_view_dataframe" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "egui", "egui_extras", @@ -4728,7 +4728,7 @@ dependencies = [ [[package]] name = "re_space_view_spatial" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4766,7 +4766,7 @@ dependencies = [ [[package]] name = "re_space_view_tensor" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4792,7 +4792,7 @@ dependencies = [ [[package]] name = "re_space_view_text_document" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "egui", "egui_commonmark", @@ -4810,7 +4810,7 @@ dependencies = [ [[package]] name = "re_space_view_text_log" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "egui", "egui_extras", @@ -4830,7 +4830,7 @@ dependencies = [ [[package]] name = "re_space_view_time_series" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "egui", "egui_plot", @@ -4853,7 +4853,7 @@ dependencies = [ [[package]] name = "re_string_interner" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "nohash-hasher", @@ -4865,7 +4865,7 @@ dependencies = [ [[package]] name = "re_time_panel" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "egui", "itertools 0.12.0", @@ -4884,7 +4884,7 @@ dependencies = [ [[package]] name = "re_tracing" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "puffin", "puffin_http", @@ -4894,7 +4894,7 @@ dependencies = [ [[package]] name = "re_tuid" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "criterion", "document-features", @@ -4906,7 +4906,7 @@ dependencies = [ [[package]] name = "re_types" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "array-init", @@ -4945,7 +4945,7 @@ dependencies = [ [[package]] name = "re_types_builder" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "camino", @@ -4971,7 +4971,7 @@ dependencies = [ [[package]] name = "re_types_core" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "backtrace", @@ -4991,7 +4991,7 @@ dependencies = [ [[package]] name = "re_ui" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "eframe", "egui", @@ -5012,7 +5012,7 @@ dependencies = [ [[package]] name = "re_viewer" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5076,7 +5076,7 @@ dependencies = [ [[package]] name = "re_viewer_context" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5115,7 +5115,7 @@ dependencies = [ [[package]] name = "re_viewport" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "array-init", @@ -5149,7 +5149,7 @@ dependencies = [ [[package]] name = "re_web_viewer_server" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "clap", "document-features", @@ -5164,7 +5164,7 @@ dependencies = [ [[package]] name = "re_ws_comms" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "bincode", @@ -5254,7 +5254,7 @@ checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" [[package]] name = "rerun" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5288,7 +5288,7 @@ dependencies = [ [[package]] name = "rerun-cli" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "document-features", "mimalloc", @@ -5304,7 +5304,7 @@ dependencies = [ [[package]] name = "rerun-loader-rust-file" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "argh", @@ -5313,7 +5313,7 @@ dependencies = [ [[package]] name = "rerun_c" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "ahash", "once_cell", @@ -5325,7 +5325,7 @@ dependencies = [ [[package]] name = "rerun_py" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "crossbeam", "document-features", @@ -5424,7 +5424,7 @@ dependencies = [ [[package]] name = "roundtrip_annotation_context" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5434,7 +5434,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows2d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5444,7 +5444,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows3d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5454,7 +5454,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes2d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5464,7 +5464,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes3d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5474,7 +5474,7 @@ dependencies = [ [[package]] name = "roundtrip_depth_image" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5485,7 +5485,7 @@ dependencies = [ [[package]] name = "roundtrip_disconnected_space" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5495,7 +5495,7 @@ dependencies = [ [[package]] name = "roundtrip_image" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5508,7 +5508,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips2d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5518,7 +5518,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips3d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5528,7 +5528,7 @@ dependencies = [ [[package]] name = "roundtrip_pinhole" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5538,7 +5538,7 @@ dependencies = [ [[package]] name = "roundtrip_points2d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5548,7 +5548,7 @@ dependencies = [ [[package]] name = "roundtrip_points3d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5558,7 +5558,7 @@ dependencies = [ [[package]] name = "roundtrip_segmentation_image" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5569,7 +5569,7 @@ dependencies = [ [[package]] name = "roundtrip_tensor" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5580,7 +5580,7 @@ dependencies = [ [[package]] name = "roundtrip_text_document" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5590,7 +5590,7 @@ dependencies = [ [[package]] name = "roundtrip_text_log" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5600,7 +5600,7 @@ dependencies = [ [[package]] name = "roundtrip_transform3d" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5610,7 +5610,7 @@ dependencies = [ [[package]] name = "roundtrip_view_coordinates" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -5626,7 +5626,7 @@ checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" [[package]] name = "run_wasm" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "cargo-run-wasm", "pico-args", @@ -5901,7 +5901,7 @@ dependencies = [ [[package]] name = "shared_recording" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "rerun", ] @@ -6037,7 +6037,7 @@ dependencies = [ [[package]] name = "snippets" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "itertools 0.12.0", "ndarray", @@ -6059,7 +6059,7 @@ dependencies = [ [[package]] name = "spawn_viewer" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "rerun", ] @@ -6093,7 +6093,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stdio" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "rerun", ] @@ -6189,7 +6189,7 @@ dependencies = [ [[package]] name = "template" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "rerun", ] @@ -6205,7 +6205,7 @@ dependencies = [ [[package]] name = "test_api" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6220,7 +6220,7 @@ dependencies = [ [[package]] name = "test_image_memory" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" dependencies = [ "mimalloc", "re_format", diff --git a/Cargo.toml b/Cargo.toml index 2a4110640321..1c1450e42119 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,59 +20,59 @@ include = ["../../LICENSE-APACHE", "../../LICENSE-MIT", "**/*.rs", "Cargo.toml"] license = "MIT OR Apache-2.0" repository = "https://github.com/rerun-io/rerun" rust-version = "1.74" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" [workspace.dependencies] # When using alpha-release, always use exact version, e.g. `version = "=0.x.y-alpha.z" # This is because we treat alpha-releases as incompatible, but semver doesn't. # In particular: if we compile rerun 0.3.0-alpha.0 we only want it to use # re_log_types 0.3.0-alpha.0, NOT 0.3.0-alpha.4 even though it is newer and semver-compatible. -re_analytics = { path = "crates/re_analytics", version = "=0.15.0-alpha.2", default-features = false } -re_build_search_index = { path = "crates/re_build_search_index", version = "=0.15.0-alpha.2", default-features = false } -re_build_examples = { path = "crates/re_build_examples", version = "=0.15.0-alpha.2", default-features = false } -re_build_info = { path = "crates/re_build_info", version = "=0.15.0-alpha.2", default-features = false } -re_build_tools = { path = "crates/re_build_tools", version = "=0.15.0-alpha.2", default-features = false } -re_build_web_viewer = { path = "crates/re_build_web_viewer", version = "=0.15.0-alpha.2", default-features = false } -re_crash_handler = { path = "crates/re_crash_handler", version = "=0.15.0-alpha.2", default-features = false } -re_data_source = { path = "crates/re_data_source", version = "=0.15.0-alpha.2", default-features = false } -re_data_store = { path = "crates/re_data_store", version = "=0.15.0-alpha.2", default-features = false } -re_data_ui = { path = "crates/re_data_ui", version = "=0.15.0-alpha.2", default-features = false } -re_entity_db = { path = "crates/re_entity_db", version = "=0.15.0-alpha.2", default-features = false } -re_error = { path = "crates/re_error", version = "=0.15.0-alpha.2", default-features = false } -re_format = { path = "crates/re_format", version = "=0.15.0-alpha.2", default-features = false } -re_int_histogram = { path = "crates/re_int_histogram", version = "=0.15.0-alpha.2", default-features = false } -re_log = { path = "crates/re_log", version = "=0.15.0-alpha.2", default-features = false } -re_log_encoding = { path = "crates/re_log_encoding", version = "=0.15.0-alpha.2", default-features = false } -re_log_types = { path = "crates/re_log_types", version = "=0.15.0-alpha.2", default-features = false } -re_memory = { path = "crates/re_memory", version = "=0.15.0-alpha.2", default-features = false } -re_query = { path = "crates/re_query", version = "=0.15.0-alpha.2", default-features = false } -re_query_cache = { path = "crates/re_query_cache", version = "=0.15.0-alpha.2", default-features = false } -re_renderer = { path = "crates/re_renderer", version = "=0.15.0-alpha.2", default-features = false } -re_sdk = { path = "crates/re_sdk", version = "=0.15.0-alpha.2", default-features = false } -re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.15.0-alpha.2", default-features = false } -re_smart_channel = { path = "crates/re_smart_channel", version = "=0.15.0-alpha.2", default-features = false } -re_space_view = { path = "crates/re_space_view", version = "=0.15.0-alpha.2", default-features = false } -re_space_view_bar_chart = { path = "crates/re_space_view_bar_chart", version = "=0.15.0-alpha.2", default-features = false } -re_space_view_dataframe = { path = "crates/re_space_view_dataframe", version = "=0.15.0-alpha.2", default-features = false } -re_space_view_spatial = { path = "crates/re_space_view_spatial", version = "=0.15.0-alpha.2", default-features = false } -re_space_view_tensor = { path = "crates/re_space_view_tensor", version = "=0.15.0-alpha.2", default-features = false } -re_space_view_text_document = { path = "crates/re_space_view_text_document", version = "=0.15.0-alpha.2", default-features = false } -re_space_view_text_log = { path = "crates/re_space_view_text_log", version = "=0.15.0-alpha.2", default-features = false } -re_space_view_time_series = { path = "crates/re_space_view_time_series", version = "=0.15.0-alpha.2", default-features = false } -re_string_interner = { path = "crates/re_string_interner", version = "=0.15.0-alpha.2", default-features = false } -re_time_panel = { path = "crates/re_time_panel", version = "=0.15.0-alpha.2", default-features = false } -re_tracing = { path = "crates/re_tracing", version = "=0.15.0-alpha.2", default-features = false } -re_tuid = { path = "crates/re_tuid", version = "=0.15.0-alpha.2", default-features = false } -re_types = { path = "crates/re_types", version = "=0.15.0-alpha.2", default-features = false } -re_types_builder = { path = "crates/re_types_builder", version = "=0.15.0-alpha.2", default-features = false } -re_types_core = { path = "crates/re_types_core", version = "=0.15.0-alpha.2", default-features = false } -re_ui = { path = "crates/re_ui", version = "=0.15.0-alpha.2", default-features = false } -re_viewer = { path = "crates/re_viewer", version = "=0.15.0-alpha.2", default-features = false } -re_viewer_context = { path = "crates/re_viewer_context", version = "=0.15.0-alpha.2", default-features = false } -re_viewport = { path = "crates/re_viewport", version = "=0.15.0-alpha.2", default-features = false } -re_web_viewer_server = { path = "crates/re_web_viewer_server", version = "=0.15.0-alpha.2", default-features = false } -re_ws_comms = { path = "crates/re_ws_comms", version = "=0.15.0-alpha.2", default-features = false } -rerun = { path = "crates/rerun", version = "=0.15.0-alpha.2", default-features = false } +re_analytics = { path = "crates/re_analytics", version = "=0.15.0-alpha.3", default-features = false } +re_build_search_index = { path = "crates/re_build_search_index", version = "=0.15.0-alpha.3", default-features = false } +re_build_examples = { path = "crates/re_build_examples", version = "=0.15.0-alpha.3", default-features = false } +re_build_info = { path = "crates/re_build_info", version = "=0.15.0-alpha.3", default-features = false } +re_build_tools = { path = "crates/re_build_tools", version = "=0.15.0-alpha.3", default-features = false } +re_build_web_viewer = { path = "crates/re_build_web_viewer", version = "=0.15.0-alpha.3", default-features = false } +re_crash_handler = { path = "crates/re_crash_handler", version = "=0.15.0-alpha.3", default-features = false } +re_data_source = { path = "crates/re_data_source", version = "=0.15.0-alpha.3", default-features = false } +re_data_store = { path = "crates/re_data_store", version = "=0.15.0-alpha.3", default-features = false } +re_data_ui = { path = "crates/re_data_ui", version = "=0.15.0-alpha.3", default-features = false } +re_entity_db = { path = "crates/re_entity_db", version = "=0.15.0-alpha.3", default-features = false } +re_error = { path = "crates/re_error", version = "=0.15.0-alpha.3", default-features = false } +re_format = { path = "crates/re_format", version = "=0.15.0-alpha.3", default-features = false } +re_int_histogram = { path = "crates/re_int_histogram", version = "=0.15.0-alpha.3", default-features = false } +re_log = { path = "crates/re_log", version = "=0.15.0-alpha.3", default-features = false } +re_log_encoding = { path = "crates/re_log_encoding", version = "=0.15.0-alpha.3", default-features = false } +re_log_types = { path = "crates/re_log_types", version = "=0.15.0-alpha.3", default-features = false } +re_memory = { path = "crates/re_memory", version = "=0.15.0-alpha.3", default-features = false } +re_query = { path = "crates/re_query", version = "=0.15.0-alpha.3", default-features = false } +re_query_cache = { path = "crates/re_query_cache", version = "=0.15.0-alpha.3", default-features = false } +re_renderer = { path = "crates/re_renderer", version = "=0.15.0-alpha.3", default-features = false } +re_sdk = { path = "crates/re_sdk", version = "=0.15.0-alpha.3", default-features = false } +re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.15.0-alpha.3", default-features = false } +re_smart_channel = { path = "crates/re_smart_channel", version = "=0.15.0-alpha.3", default-features = false } +re_space_view = { path = "crates/re_space_view", version = "=0.15.0-alpha.3", default-features = false } +re_space_view_bar_chart = { path = "crates/re_space_view_bar_chart", version = "=0.15.0-alpha.3", default-features = false } +re_space_view_dataframe = { path = "crates/re_space_view_dataframe", version = "=0.15.0-alpha.3", default-features = false } +re_space_view_spatial = { path = "crates/re_space_view_spatial", version = "=0.15.0-alpha.3", default-features = false } +re_space_view_tensor = { path = "crates/re_space_view_tensor", version = "=0.15.0-alpha.3", default-features = false } +re_space_view_text_document = { path = "crates/re_space_view_text_document", version = "=0.15.0-alpha.3", default-features = false } +re_space_view_text_log = { path = "crates/re_space_view_text_log", version = "=0.15.0-alpha.3", default-features = false } +re_space_view_time_series = { path = "crates/re_space_view_time_series", version = "=0.15.0-alpha.3", default-features = false } +re_string_interner = { path = "crates/re_string_interner", version = "=0.15.0-alpha.3", default-features = false } +re_time_panel = { path = "crates/re_time_panel", version = "=0.15.0-alpha.3", default-features = false } +re_tracing = { path = "crates/re_tracing", version = "=0.15.0-alpha.3", default-features = false } +re_tuid = { path = "crates/re_tuid", version = "=0.15.0-alpha.3", default-features = false } +re_types = { path = "crates/re_types", version = "=0.15.0-alpha.3", default-features = false } +re_types_builder = { path = "crates/re_types_builder", version = "=0.15.0-alpha.3", default-features = false } +re_types_core = { path = "crates/re_types_core", version = "=0.15.0-alpha.3", default-features = false } +re_ui = { path = "crates/re_ui", version = "=0.15.0-alpha.3", default-features = false } +re_viewer = { path = "crates/re_viewer", version = "=0.15.0-alpha.3", default-features = false } +re_viewer_context = { path = "crates/re_viewer_context", version = "=0.15.0-alpha.3", default-features = false } +re_viewport = { path = "crates/re_viewport", version = "=0.15.0-alpha.3", default-features = false } +re_web_viewer_server = { path = "crates/re_web_viewer_server", version = "=0.15.0-alpha.3", default-features = false } +re_ws_comms = { path = "crates/re_ws_comms", version = "=0.15.0-alpha.3", default-features = false } +rerun = { path = "crates/rerun", version = "=0.15.0-alpha.3", default-features = false } # egui-crates: ecolor = "0.26.2" diff --git a/examples/rust/clock/Cargo.toml b/examples/rust/clock/Cargo.toml index 2fa83f3f2fa8..0e9a6c8515f5 100644 --- a/examples/rust/clock/Cargo.toml +++ b/examples/rust/clock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clock" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_data_loader/Cargo.toml b/examples/rust/custom_data_loader/Cargo.toml index b57fb6a919f8..2b85c41653c1 100644 --- a/examples/rust/custom_data_loader/Cargo.toml +++ b/examples/rust/custom_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_data_loader" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index d210477765e9..2d8f1e78018d 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_space_view" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_store_subscriber/Cargo.toml b/examples/rust/custom_store_subscriber/Cargo.toml index 67606bcdffcb..df8f5c269393 100644 --- a/examples/rust/custom_store_subscriber/Cargo.toml +++ b/examples/rust/custom_store_subscriber/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_store_subscriber" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml index ae5f33a579e0..c913bf792d2b 100644 --- a/examples/rust/dna/Cargo.toml +++ b/examples/rust/dna/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dna" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml index 9f836451c001..bf75342bcf04 100644 --- a/examples/rust/extend_viewer_ui/Cargo.toml +++ b/examples/rust/extend_viewer_ui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extend_viewer_ui" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/external_data_loader/Cargo.toml b/examples/rust/external_data_loader/Cargo.toml index 41ad4d19be70..a36d13fc0d8a 100644 --- a/examples/rust/external_data_loader/Cargo.toml +++ b/examples/rust/external_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rerun-loader-rust-file" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml index 34635f1109ae..ac5205661110 100644 --- a/examples/rust/incremental_logging/Cargo.toml +++ b/examples/rust/incremental_logging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "incremental_logging" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml index b3a5f3ddb04f..2d584d81bb49 100644 --- a/examples/rust/log_file/Cargo.toml +++ b/examples/rust/log_file/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "log_file" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal/Cargo.toml b/examples/rust/minimal/Cargo.toml index 7c1073483dad..3e9b4064acab 100644 --- a/examples/rust/minimal/Cargo.toml +++ b/examples/rust/minimal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_options/Cargo.toml b/examples/rust/minimal_options/Cargo.toml index f870a72f1c45..7fbebef29dab 100644 --- a/examples/rust/minimal_options/Cargo.toml +++ b/examples/rust/minimal_options/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_options" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml index 49ba06a7b388..58c0e3cebf3a 100644 --- a/examples/rust/minimal_serve/Cargo.toml +++ b/examples/rust/minimal_serve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_serve" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/objectron/Cargo.toml b/examples/rust/objectron/Cargo.toml index f1fa4d3ba081..aac6e6bbc9f8 100644 --- a/examples/rust/objectron/Cargo.toml +++ b/examples/rust/objectron/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "objectron" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/raw_mesh/Cargo.toml b/examples/rust/raw_mesh/Cargo.toml index 7a8a790fb46c..11dbf7b167c2 100644 --- a/examples/rust/raw_mesh/Cargo.toml +++ b/examples/rust/raw_mesh/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "raw_mesh" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/shared_recording/Cargo.toml b/examples/rust/shared_recording/Cargo.toml index 0129378a6782..703657ded727 100644 --- a/examples/rust/shared_recording/Cargo.toml +++ b/examples/rust/shared_recording/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared_recording" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/spawn_viewer/Cargo.toml b/examples/rust/spawn_viewer/Cargo.toml index 14ff9a9fc36e..91d0df47ff2b 100644 --- a/examples/rust/spawn_viewer/Cargo.toml +++ b/examples/rust/spawn_viewer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spawn_viewer" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/stdio/Cargo.toml b/examples/rust/stdio/Cargo.toml index 4ce902180e3c..797ac4debbc3 100644 --- a/examples/rust/stdio/Cargo.toml +++ b/examples/rust/stdio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stdio" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/template/Cargo.toml b/examples/rust/template/Cargo.toml index d4fc62487209..34e5ca05682d 100644 --- a/examples/rust/template/Cargo.toml +++ b/examples/rust/template/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "template" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/tests/rust/plot_dashboard_stress/Cargo.toml b/tests/rust/plot_dashboard_stress/Cargo.toml index 6ee75304ddbe..9c67fd0cbee6 100644 --- a/tests/rust/plot_dashboard_stress/Cargo.toml +++ b/tests/rust/plot_dashboard_stress/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "plot_dashboard_stress" -version = "0.15.0-alpha.2" +version = "0.15.0-alpha.3" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" From cb19989974861108fad51b35c8c5a52bdf186bd5 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:53:47 +0100 Subject: [PATCH 054/508] Fix a bug where an incorrect 3D space view origin could be suggested (#5565) ### What Fix a bug introduced in #5411 and #5423 where the wrong origin would be suggested when creating a 3D space view from an entity part of a 2D space view. Quoting the original PR: > For 3D space views: the origin of the subspace that contains the selected entities common ancestor, _or_, if that one is rooted on a pinhole, the origin of the parent sub-space. Further, if a `ViewCoordinate` is logged in between the subspace origin and the common ancestor, then it's used as suggested origin. In most case, that means `/`, unless a `DisconnectedSpace` is encountered. The part of that logic where we check for a `ViewCoordinate` in the parent subspace was implemented incorrectly, which resulted in `check_context_menu_suggested_origin` to fail. With this PR, this test now passes. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5565/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5565/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5565/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5565) - [Docs preview](https://rerun.io/preview/268125aaddc63e0524743528cf3b34c9ea0640e3/docs) - [Examples preview](https://rerun.io/preview/268125aaddc63e0524743528cf3b34c9ea0640e3/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/space_view_3d.rs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 19287fd40a20..1c8c56b9ed26 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -98,14 +98,16 @@ impl SpaceViewClass for SpatialSpaceView3D { // Also, if a ViewCoordinate3D is logged somewhere between the common ancestor and the // subspace origin, we use it as origin. SpatialTopology::access(entity_db.store_id(), |topo| { - let subspace = topo.subspace_for_entity(&common_ancestor); + let common_ancestor_subspace = topo.subspace_for_entity(&common_ancestor); - let subspace_origin = if subspace.supports_3d_content() { - Some(subspace) + // Consider the case where the common ancestor might be in a 2D space that is connected + // to a parent space. In this case, the parent space is the correct space. + let subspace = if common_ancestor_subspace.supports_3d_content() { + Some(common_ancestor_subspace) } else { - topo.subspace_for_subspace_origin(subspace.parent_space) - } - .map(|subspace| subspace.origin.clone()); + topo.subspace_for_subspace_origin(common_ancestor_subspace.parent_space) + }; + let subspace_origin = subspace.map(|subspace| subspace.origin.clone()); // Find the first ViewCoordinates3d logged, walking up from the common ancestor to the // subspace origin. @@ -114,10 +116,12 @@ impl SpaceViewClass for SpatialSpaceView3D { .into_iter() .rev() .find(|path| { - subspace - .heuristic_hints - .get(path) - .is_some_and(|hint| hint.contains(HeuristicHints::ViewCoordinates3d)) + subspace.is_some_and(|subspace| { + subspace + .heuristic_hints + .get(path) + .is_some_and(|hint| hint.contains(HeuristicHints::ViewCoordinates3d)) + }) }) .or(subspace_origin) }) From 71cd663e2c5b2c217763f4942a7fc72170cc7a30 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 18 Mar 2024 18:54:56 +0100 Subject: [PATCH 055/508] Add blueprint to the `nuscenes` example (#5556) ### What * Part of https://github.com/rerun-io/rerun/issues/5468 An interesting part of this is that the blueprint is dynamically created based on the the data (which cameras there are). Before: ![image](https://github.com/rerun-io/rerun/assets/1148717/e8c8c5f2-6502-4325-8268-1067d824494a) After: ![image](https://github.com/rerun-io/rerun/assets/1148717/60e0673e-5e72-4dc8-8bc3-d5c6e49c7d64) The 3D camera is (still) too zoomed out, but gathering all the 2D images in a tab view puts more focus on the 3D view. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5556/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5556/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5556/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5556) - [Docs preview](https://rerun.io/preview/b620da1066ab9c4ba09a3bd0dee813cc3af1de57/docs) - [Examples preview](https://rerun.io/preview/b620da1066ab9c4ba09a3bd0dee813cc3af1de57/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/ui/selection_panel.rs | 2 +- examples/python/arkit_scenes/main.py | 40 ++++++++--------- examples/python/nuscenes/main.py | 45 +++++++++++++++++-- rerun_py/rerun_sdk/rerun/blueprint/api.py | 2 +- .../rerun_sdk/rerun/blueprint/containers.py | 4 +- 5 files changed, 64 insertions(+), 29 deletions(-) diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 84136ab00b68..7f380246eb33 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -855,7 +855,7 @@ fn blueprint_ui_for_space_view( .root_handle() .and_then(|root| query_result.tree.lookup_result(root)) else { - re_log::error!("Could not find root data result for Space View {space_view_id:?}"); + re_log::error_once!("Could not find root data result for Space View {space_view_id:?}"); return; }; diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py index 8f0b0046591e..b56c7234f4ba 100755 --- a/examples/python/arkit_scenes/main.py +++ b/examples/python/arkit_scenes/main.py @@ -330,31 +330,29 @@ def main() -> None: primary_camera_entity = highres_entity_path if args.include_highres else lowres_posed_entity_path - rr.script_setup( - args, - "rerun_example_arkit_scenes", - blueprint=rbl.Horizontal( - rbl.Spatial3DView(name="3D"), - rbl.Vertical( - rbl.Tabs( - # Note that we re-project the annotations into the 2D views: - # For this to work, the origin of the 2D views has to be a pinhole camera, - # this way the viewer knows how to project the 3D annotations into the 2D views. - rbl.Spatial2DView( - name="RGB", - origin=primary_camera_entity, - contents=[f"{primary_camera_entity}/rgb", "/world/annotations/**"], - ), - rbl.Spatial2DView( - name="Depth", - origin=primary_camera_entity, - contents=[f"{primary_camera_entity}/depth", "/world/annotations/**"], - ), + blueprint = rbl.Horizontal( + rbl.Spatial3DView(name="3D"), + rbl.Vertical( + rbl.Tabs( + # Note that we re-project the annotations into the 2D views: + # For this to work, the origin of the 2D views has to be a pinhole camera, + # this way the viewer knows how to project the 3D annotations into the 2D views. + rbl.Spatial2DView( + name="RGB", + origin=primary_camera_entity, + contents=["$origin/rgb", "/world/annotations/**"], + ), + rbl.Spatial2DView( + name="Depth", + origin=primary_camera_entity, + contents=["$origin/depth", "/world/annotations/**"], ), - rbl.TextDocumentView(name="Readme"), ), + rbl.TextDocumentView(name="Readme"), ), ) + + rr.script_setup(args, "rerun_example_arkit_scenes", blueprint=blueprint) recording_path = ensure_recording_available(args.video_id, args.include_highres) log_arkit(recording_path, args.include_highres) diff --git a/examples/python/nuscenes/main.py b/examples/python/nuscenes/main.py index 0c9157970cb1..253772dd053a 100755 --- a/examples/python/nuscenes/main.py +++ b/examples/python/nuscenes/main.py @@ -9,6 +9,7 @@ import matplotlib import numpy as np import rerun as rr +import rerun.blueprint as rbl from download_dataset import MINISPLIT_SCENES, download_minisplit from nuscenes import nuscenes @@ -47,9 +48,28 @@ def ensure_scene_available(root_dir: pathlib.Path, dataset_version: str, scene_n raise ValueError(f"{scene_name=} not found in dataset") -def log_nuscenes(root_dir: pathlib.Path, dataset_version: str, scene_name: str, max_time_sec: float) -> None: +def nuscene_sensor_names(nusc: nuscenes.NuScenes, scene_name: str) -> set[str]: + """Return all sensor names in the scene.""" + + sensor_names = set() + + scene = next(s for s in nusc.scene if s["name"] == scene_name) + first_sample = nusc.get("sample", scene["first_sample_token"]) + for sample_data_token in first_sample["data"].values(): + sample_data = nusc.get("sample_data", sample_data_token) + if sample_data["sensor_modality"] == "camera": + current_camera_token = sample_data_token + while current_camera_token != "": + sample_data = nusc.get("sample_data", current_camera_token) + sensor_name = sample_data["channel"] + sensor_names.add(sensor_name) + current_camera_token = sample_data["next"] + + return sensor_names + + +def log_nuscenes(nusc: nuscenes.NuScenes, scene_name: str, max_time_sec: float) -> None: """Log nuScenes scene.""" - nusc = nuscenes.NuScenes(version=dataset_version, dataroot=root_dir, verbose=True) scene = next(s for s in nusc.scene if s["name"] == scene_name) @@ -233,8 +253,25 @@ def main() -> None: ensure_scene_available(args.root_dir, args.dataset_version, args.scene_name) - rr.script_setup(args, "rerun_example_nuscenes") - log_nuscenes(args.root_dir, args.dataset_version, args.scene_name, max_time_sec=args.seconds) + nusc = nuscenes.NuScenes(version=args.dataset_version, dataroot=args.root_dir, verbose=True) + + # Set up the Rerun Blueprint (how the visualization is organized): + sensor_space_views = [ + rbl.Spatial2DView( + name=sensor_name, + origin=f"world/ego_vehicle/{sensor_name}", + ) + for sensor_name in nuscene_sensor_names(nusc, args.scene_name) + ] + blueprint = rbl.Vertical( + rbl.Spatial3DView(name="3D", origin="world"), + rbl.Grid(*sensor_space_views), + row_shares=[3, 2], + ) + + rr.script_setup(args, "rerun_example_nuscenes", blueprint=blueprint) + + log_nuscenes(nusc, args.scene_name, max_time_sec=args.seconds) rr.script_teardown(args) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index b106feb23f3d..bd7cc25fde72 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -142,7 +142,7 @@ def __init__( This is only applicable to `Horizontal` or `Grid` containers. row_shares The layout shares of the rows in the container. The share is used to determine what fraction of the total height each - row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. + row should take up. The row with index `i` will take up the fraction `shares[i] / total_shares`. This is only applicable to `Vertical` or `Grid` containers. grid_columns The number of columns in the grid. This is only applicable to `Grid` containers. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/containers.py b/rerun_py/rerun_sdk/rerun/blueprint/containers.py index 243201151c37..40c6bc825fb5 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/containers.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/containers.py @@ -39,7 +39,7 @@ def __init__(self, *contents: Container | SpaceView, row_shares: Optional[RowSha All positional arguments are the contents of the container, which may be either other containers or space views. row_shares The layout shares of the rows in the container. The share is used to determine what fraction of the total height each - row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. + row should take up. The row with index `i` will take up the fraction `shares[i] / total_shares`. """ super().__init__(*contents, kind=ContainerKind.Vertical, row_shares=row_shares) @@ -67,7 +67,7 @@ def __init__( column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. row_shares The layout shares of the rows in the container. The share is used to determine what fraction of the total height each - row should take up. The ros with index `i` will take up the fraction `shares[i] / total_shares`. + row should take up. The row with index `i` will take up the fraction `shares[i] / total_shares`. grid_columns The number of columns in the grid. From 21d010ea4304167983d38a151bd61587c6a3c1ac Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Mon, 18 Mar 2024 19:57:03 +0100 Subject: [PATCH 056/508] Improve many release checks with blueprints (#5561) ### What * Fixes #5477 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5561/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5561/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5561/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5561) - [Docs preview](https://rerun.io/preview/84194327e6aed95892948de58f757d177b6e2c21/docs) - [Examples preview](https://rerun.io/preview/84194327e6aed95892948de58f757d177b6e2c21/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- ...ntext_menu_add_entity_to_new_space_view.py | 26 ++++-- .../check_context_menu_collapse_expand_all.py | 23 +++-- ...heck_context_menu_invalid_sub_container.py | 34 ++++--- .../check_context_menu_multi_selection.py | 67 +++++++------- .../check_context_menu_single_selection.py | 89 +++++++++++-------- ...xt_menu_single_selection_blueprint_tree.py | 81 +++++++++-------- .../check_context_menu_suggested_origin.py | 50 +++++++---- tests/python/release_checklist/check_focus.py | 34 +++---- 8 files changed, 238 insertions(+), 166 deletions(-) diff --git a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py index 15407e44c62f..e90604396a0d 100644 --- a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py +++ b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py @@ -7,19 +7,19 @@ import numpy as np import rerun as rr +import rerun.blueprint as rrb README = """ # Context Menu - Add entity to new space view -## Blueprint tree +#### Blueprint tree -* Reset the blueprint. -* Expend all space views and data result. +* "Expand all" on the Vertical containers. * Right-click on the `boxes3d` entity and select "Add to new space view" -> "3D". Check a new space view is created _and selected_ with the boxes3d entity and origin set to root. * In each space view, right-click on the leaf entity, and check that "Add to new space view" recommends at least space views of the same kind. * Select both the `boxes3d` entity and the `text_logs` entity. Check no space view is recommended (except Dataframe if enabled). -## Streams tree +#### Streams tree * Right-click on the `bars` entity and check that a Bar Plot space view can successfully be created. """ @@ -29,6 +29,22 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) +def blueprint() -> rrb.BlueprintLike: + return rrb.Viewport( + rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical( + rrb.Spatial3DView(origin="/boxes3d"), + rrb.Spatial2DView(origin="/boxes2d"), + rrb.TextLogView(origin="/text_logs"), + rrb.BarChartView(origin="/bars"), + rrb.TensorView(origin="/tensor"), + ), + column_shares=[2, 1], + ) + ) + + def log_some_space_views() -> None: rr.set_time_sequence("frame_nr", 0) @@ -44,7 +60,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py index c5e74b16a359..141fd1169b52 100644 --- a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py +++ b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py @@ -5,13 +5,13 @@ from uuid import uuid4 import rerun as rr +import rerun.blueprint as rrb README = """ # Context Menu - Add entity to new space view ## Blueprint tree -* Reset the blueprint. * Right-click on Viewport and select "Collapse all". Check everything is collapsed by manually expending everything. * Right-click on Viewport and select "Collapse all" and then "Expend all". Check everything is expanded. @@ -30,17 +30,30 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) -def log_some_space_views() -> None: - # TODO(ab): add a deep-ish container hierarchy blueprint for more collapse/expand fun +def blueprint() -> rrb.BlueprintLike: + return rrb.Viewport( + rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical( + rrb.Horizontal( + rrb.Vertical( + rrb.Spatial3DView(origin="/"), + ) + ) + ), + column_shares=[2, 1], + ) + ) - rr.set_time_sequence("frame_nr", 0) +def log_some_space_views() -> None: + rr.set_time_sequence("frame_nr", 0) rr.log("/", rr.Boxes3D(centers=[0, 0, 0], half_sizes=[1, 1, 1])) rr.log("/world/robot/arm/actuator/thing", rr.Boxes3D(centers=[0.5, 0, 0], half_sizes=[0.1, 0.1, 0.1])) def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py index 53b92e31fb8d..d8bf755cd0cb 100644 --- a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py +++ b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py @@ -5,22 +5,14 @@ from uuid import uuid4 import rerun as rr +import rerun.blueprint as rrb README = """ # Context Menu - Invalid sub-container kind -## Preparation -TODO(ab): automate this with blueprints - -- Reset the blueprint -- Add a Horizontal container and a Vertical container in the viewport, and move one space view into each. - - -## Checks - -* Single-select a horizontal container, check that it disallow adding a horizontal container inside it. -* Same for a vertical container. +* Single-select the horizontal container, check that it disallow adding a horizontal container inside it. +* Same for the vertical container. * Single select a space view inside a horizontal container, check that it disallow moving to a new horizontal container. * Same for a space view inside a vertical container. """ @@ -30,6 +22,24 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) +def blueprint() -> rrb.BlueprintLike: + return rrb.Viewport( + rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Grid( + rrb.Vertical( + rrb.Spatial3DView(origin="/"), + ), + rrb.Horizontal( + rrb.Spatial2DView(origin="/"), + ), + grid_columns=1, + ), + column_shares=[2, 1], + ) + ) + + def log_some_space_views() -> None: rr.set_time_sequence("frame_nr", 0) @@ -38,7 +48,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_multi_selection.py b/tests/python/release_checklist/check_context_menu_multi_selection.py index 0b7b361fd5c5..e8b5afd22e61 100644 --- a/tests/python/release_checklist/check_context_menu_multi_selection.py +++ b/tests/python/release_checklist/check_context_menu_multi_selection.py @@ -5,69 +5,57 @@ from uuid import uuid4 import rerun as rr +import rerun.blueprint as rrb README = """ # Context Menu - Multi-selection - -## Preparation - -TODO(ab): automate this with blueprints - -- Reset the blueprint -- Add a Horizontal container in the viewport and move both the 2D and 3D space view into it - - -## Checks - For each of the multi-selection below, check the context menu content as per the following table. ```plaintext +========================================================== ITEMS CONTEXT MENU CONTENT - - +========================================================== 2x Space views Hide all Remove + Expand all Collapse all - Move to new Container - -+ Horizontal container Hide all + Move to new Container +---------------------------------------------------------- ++ Vertical container Hide all Remove + Expand all Collapse all - Move to new Container - + Move to new Container +---------------------------------------------------------- + Viewport Hide all + Expand all Collapse all - - - --deselect all-- - - +========================================================== Space view + 'box2d' data result Hide all Remove + Expand all Collapse all - - - --deselect all-- - - +========================================================== 'box2d' data result Hide all -+ 'box3d' entity (streams tree) Expand all ++ 'box3d' entity (streams tree) + Expand all Collapse all - Add to new Space View - + Add to new Space View +---------------------------------------------------------- + some component Hide all + Expand all Collapse all - +========================================================== ``` """ @@ -76,6 +64,19 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) +def blueprint() -> rrb.BlueprintLike: + return rrb.Viewport( + rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical( + rrb.Spatial3DView(origin="/"), + rrb.Spatial2DView(origin="/"), + ), + column_shares=[2, 1], + ) + ) + + def log_some_space_views() -> None: rr.set_time_sequence("frame_nr", 0) @@ -84,7 +85,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_single_selection.py b/tests/python/release_checklist/check_context_menu_single_selection.py index 9b11958bb713..a197508638e3 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection.py +++ b/tests/python/release_checklist/check_context_menu_single_selection.py @@ -5,20 +5,12 @@ from uuid import uuid4 import rerun as rr +import rerun.blueprint as rrb README = """ # Context Menu - Single Selection -## Preparation - -TODO(ab): automate this with blueprints - -- Reset the blueprint -- Add a Horizontal container in the viewport and move the 3D space view into it -- Right-click on the viewport and "Expand All" - - -## Streams tree +#### Streams tree - Right-click on various _unselected_ items, and check that: - It becomes selected as the context menu appears. @@ -26,58 +18,64 @@ ```plaintext -ITEM CONTEXT MENU CONTENT - - -'group/' entity Expand all - Collapse all - Add to new Space View - - -Component - +================================================= +ITEM CONTEXT MENU CONTENT +================================================= +'group/' entity Expand all + Collapse all + + Add to new Space View +------------------------------------------------- +Component +================================================= ``` -## Tile Title UI +#### Tile Title UI -- Multi-select the 3D space view and the Horizontal container in the Blueprint tree. +- Multi-select the 3D space view and the Vertical container in the Blueprint tree. - Right-click on the 3D space view tab title: - The selection is set to the space view _only_. - The context menu content is as per the following table. ```plaintext -ITEM CONTEXT MENU CONTENT +================================================= +ITEM CONTEXT MENU CONTENT +================================================= +space view (tab title) Hide + Remove + Expand all + Collapse all -space view (tab title) Hide (or Show, depending on visibility)d - Remove - Expand all - Collapse all - Clone - Move to new Container + Clone + Move to new Container +================================================= ``` -## Container Selection Panel child list +#### Container Selection Panel child list -- Select the Horizontal container. +- Select the Vertical container. - In the selection panel, right-click on the 3D space view, and check that: - The selection remains unchanged. - The context menu content is as per the following table. ```plaintext -ITEM CONTEXT MENU CONTENT +================================================= +ITEM CONTEXT MENU CONTENT +================================================= +space view (child list) Hide + Remove + Expand all + Collapse all -space view (child list) Hide (or Show, depending on visibility) - Remove - Expand all - Collapse all - Clone - Move to new Container + Clone + Move to new Container +================================================= ``` """ @@ -87,6 +85,19 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) +def blueprint() -> rrb.BlueprintLike: + return rrb.Viewport( + rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical( + rrb.Spatial3DView(origin="/"), + rrb.Spatial2DView(origin="/"), + ), + column_shares=[2, 1], + ) + ) + + def log_some_space_views() -> None: rr.set_time_sequence("frame_nr", 0) @@ -94,7 +105,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py index 40c1a4e03a80..87c329a2dd76 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py +++ b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py @@ -5,64 +5,60 @@ from uuid import uuid4 import rerun as rr +import rerun.blueprint as rrb README = """ # Context Menu - Single Selection in the Blueprint tree -## Preparation - -TODO(ab): automate this with blueprints - -- Reset the blueprint -- Add a Horizontal container in the viewport and move the 3D space view into it - Right-click on the viewport and "Expand All" - - -## Checks - - Right-click on various _unselected_ items, and check that: - It becomes selected as the context menu appears. - The context menu content is as per the following table. ```plaintext -ITEM CONTEXT MENU CONTENT - +================================================================== +ITEM CONTEXT MENU CONTENT +================================================================== +Viewport Expand all + Collapse all -Viewport Expand all - Collapse all - Add Container - Add Space View + Add Container + Add Space View +------------------------------------------------------------------ +Container Hide (or Show, depending on visibility) + Remove + Expand all + Collapse all -Container Hide (or Show, depending on visibility) - Remove - Expand all - Collapse all - Add Container - Add Space View - Move to new Container + Add Container + Add Space View + Move to new Container +------------------------------------------------------------------ +Space View Hide (or Show, depending on visibility) + Remove -Space View Hide (or Show, depending on visibility) - Remove - Expand all - Collapse all - Clone - Move to new Container + Expand all + Collapse all + Clone -'group' Data Result Hide (or Show, depending on visibility) - Remove - Expand all - Collapse all - Add to new Space View + Move to new Container +------------------------------------------------------------------ +'group' Data Result Hide (or Show, depending on visibility) + Remove + Expand all + Collapse all -'boxes3d' Data Result Hide (or Show, depending on visibility) - Remove - Add to new Space View + Add to new Space View +------------------------------------------------------------------ +'boxes3d' Data Result Hide (or Show, depending on visibility) + Remove + Add to new Space View ``` """ @@ -72,6 +68,15 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) +def blueprint() -> rrb.BlueprintLike: + return rrb.Viewport( + rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical(rrb.Spatial3DView(origin="/")), + ) + ) + + def log_some_space_views() -> None: rr.set_time_sequence("frame_nr", 0) @@ -79,7 +84,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_suggested_origin.py b/tests/python/release_checklist/check_context_menu_suggested_origin.py index 6e29e336aeb0..33d1bed9b34b 100644 --- a/tests/python/release_checklist/check_context_menu_suggested_origin.py +++ b/tests/python/release_checklist/check_context_menu_suggested_origin.py @@ -7,25 +7,35 @@ import numpy as np import rerun as rr +import rerun.blueprint as rrb README = """ # Context Menu - Test the origin selection heuristics -Right click on each of the following entities and check that for the given space view class, the resulting suggested origin is as expected. +Repeat these steps for each of the following entities and space view class: +- right-click the entity (either in the blueprint or streams tree) +- select "Add to new Space View" and create the space view of the listed class +- check that the created space view has the expected origin +- delete the space view + + +check that for the given space view class, the resulting suggested origin is as expected. ```plaintext +=========================================================== ENTITY CLASS EXPECTED ORIGIN - +----------------------------------------------------------- / 3D / /world 3D /world /world/camera 3D /world /world/camera/image 3D /world /world/camera/keypoint 3D /world - +----------------------------------------------------------- /world 2D /world/camera 2D /world/camera/image 2D /world/camera/image /world/camera/keypoint 2D /world/camera/image +=========================================================== ``` """ @@ -34,13 +44,22 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) +def blueprint() -> rrb.BlueprintLike: + return rrb.Viewport( + rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Spatial3DView(origin="/", contents="", name="root entity"), + column_shares=[2, 1], + ) + ) + + def log_some_space_views() -> None: rr.set_time_sequence("frame_nr", 0) rr.log("/", rr.Boxes3D(centers=[0, 0, 0], half_sizes=[1, 1, 1])) rr.log("/world", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, timeless=True) rr.log( "/world/camera/image", - # rr.Pinhole(fov_y=0.7853982, aspect_ratio=1, camera_xyz=rr.ViewCoordinates.RUB, resolution=[10, 10]), rr.Pinhole( resolution=[10, 10], focal_length=[4, 4], @@ -50,23 +69,18 @@ def log_some_space_views() -> None: rr.log("/world/camera/image", rr.Image(np.random.rand(10, 10, 3))) rr.log("/world/camera/image/keypoint", rr.Points2D(np.random.rand(10, 2) * 10, radii=0.5)) - for i in range(100): - rr.set_time_sequence("frame_nr", i) - angle = 2 * math.pi * i / 100 - - rr.log( - "/world/camera", - rr.Transform3D( - rr.TranslationRotationScale3D( - translation=[math.cos(angle), math.sin(angle), 0], - rotation=rr.RotationAxisAngle(axis=[0, 0, 1], angle=angle), - ) - ), - ) + rr.log( + "/world/camera", + rr.Transform3D( + rr.TranslationRotationScale3D( + rotation=rr.RotationAxisAngle(axis=[0, 0, 1], angle=math.pi / 2), + ) + ), + ) def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_focus.py b/tests/python/release_checklist/check_focus.py index 61b590d64242..bb37018df0d5 100644 --- a/tests/python/release_checklist/check_focus.py +++ b/tests/python/release_checklist/check_focus.py @@ -5,26 +5,15 @@ from uuid import uuid4 import rerun as rr +import rerun.blueprint as rrb README = """ # Focus checks -## Preparation - -TODO(ab): automate this with blueprints -TODO(ab): add lots of stuff via blueprint to make the tree more crowded and check scrolling - -- Reset the blueprint -- Clone the 3D space view such as to have 2 of them. - -## Checks - -- Collapse all in the blueprint tree and the streams view -- Double-click on the box in the first space view - - check corresponding space view expands and scrolls +- Double-click on a box in the first space view + - check ONLY the corresponding space view expands and scrolls - check the streams view expands and scrolls -- Collapse all in the blueprint tree. -- Double-click on the leaf "boxes3d" entity in the streams view, check both space views expand. +- Double-click on the leaf "boxes3d" entity in the streams view, check both space views expand (manual scrolling might be needed). """ @@ -32,9 +21,22 @@ def log_readme() -> None: rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) +def blueprint() -> rrb.BlueprintLike: + return rrb.Viewport( + rrb.Horizontal( + rrb.Tabs(*[rrb.TextDocumentView(origin="readme") for _ in range(100)]), + rrb.Vertical(rrb.Spatial3DView(origin="/", name="SV1"), rrb.Spatial3DView(origin="/", name="SV2")), + column_shares=[1, 2], + ) + ) + + def log_some_space_views() -> None: rr.set_time_sequence("frame_nr", 0) + for i in range(500): + rr.log(f"a_entity_{i}", rr.AnyValues(empty=0)) + rr.log( "/objects/boxes/boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3), @@ -42,7 +44,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) log_readme() log_some_space_views() From f6baaadfc6ecf44ec22a1af90dcc624a5015b282 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 19 Mar 2024 09:07:11 +0100 Subject: [PATCH 057/508] Tensor space view can now show images (#5567) ### What == allow showing tensor data that was logged via the Image archetype. * Fixes #5420 https://github.com/rerun-io/rerun/assets/1220815/8b4dab05-b50a-4946-813f-0d206f00d417 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5567/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5567/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5567/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5567) - [Docs preview](https://rerun.io/preview/d802e3bb5c024c3d7afdbdadb77493a9f4d87f80/docs) - [Examples preview](https://rerun.io/preview/d802e3bb5c024c3d7afdbdadb77493a9f4d87f80/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/space_view_class.rs | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/crates/re_space_view_tensor/src/space_view_class.rs b/crates/re_space_view_tensor/src/space_view_class.rs index ddf038787c30..e6518f6afea3 100644 --- a/crates/re_space_view_tensor/src/space_view_class.rs +++ b/crates/re_space_view_tensor/src/space_view_class.rs @@ -15,9 +15,10 @@ use re_types::{ }; use re_viewer_context::{ gpu_bridge::{self, colormap_dropdown_button_ui}, - SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, - SpaceViewState, SpaceViewStateExt as _, SpaceViewSystemExecutionError, TensorStatsCache, - ViewQuery, ViewerContext, + IdentifiedViewSystem as _, IndicatedEntities, PerVisualizer, SpaceViewClass, + SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, + SpaceViewStateExt as _, SpaceViewSystemExecutionError, TensorStatsCache, ViewQuery, + ViewerContext, VisualizableEntities, }; use crate::{tensor_dimension_mapper::dimension_mapping_ui, visualizer_system::TensorSystem}; @@ -171,6 +172,27 @@ impl SpaceViewClass for TensorSpaceView { Box::::default() } + fn choose_default_visualizers( + &self, + entity_path: &EntityPath, + visualizable_entities_per_visualizer: &PerVisualizer, + _indicated_entities_per_visualizer: &PerVisualizer, + ) -> re_viewer_context::SmallVisualizerSet { + // Default implementation would not suggest the Tensor visualizer for images, + // since they're not indicated with a Tensor indicator. + // (and as of writing, something needs to be both visualizable and indicated to be shown in a visualizer) + + // Keeping this implementation simple: We know there's only a single visualizer here. + if visualizable_entities_per_visualizer + .get(&TensorSystem::identifier()) + .map_or(false, |entities| entities.contains(entity_path)) + { + std::iter::once(TensorSystem::identifier()).collect() + } else { + Default::default() + } + } + fn selection_ui( &self, ctx: &ViewerContext<'_>, From 4d2a8b98cc16cfda516ddd16750951fad41856aa Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 19 Mar 2024 09:08:23 +0100 Subject: [PATCH 058/508] Fix not creating 3D space views for pinhole-only 3D scenes (#5563) ### What * Fixes #5553 `python /Users/andreas/dev/rerun-io/rerun/docs/snippets/all/pinhole_simple.py` Before (0.14): ![image](https://github.com/rerun-io/rerun/assets/1220815/1b447151-86a1-4873-9283-905e0276a9b0) After: ![image](https://github.com/rerun-io/rerun/assets/1220815/f7f0d75b-0866-4f3b-9322-570b1f60deb2) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/space_view_3d.rs | 78 ++++++++++++------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 1c8c56b9ed26..252af4ffac51 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -216,36 +216,58 @@ impl SpaceViewClass for SpatialSpaceView3D { recommended_space_views: topo .iter_subspaces() .filter_map(|subspace| { - if !subspace.supports_3d_content() || subspace.entities.is_empty() { - None - } else { - // Creates space views at each view coordinates if there's any. - // (yes, we do so even if they're empty at the moment!) - // - // An exception to this rule is not to create a view there if this is already _also_ a subspace root. - // (e.g. this also has a camera or a `disconnect` logged there) - let mut origins = subspace - .heuristic_hints - .iter() - .filter(|(path, hint)| { - hint.contains(HeuristicHints::ViewCoordinates3d) - && !subspace.child_spaces.contains(path) - }) - .map(|(path, _)| path.clone()) - .collect::>(); - - // If there's no view coordinates or there are still some entities not covered, - // create a view at the subspace origin. - if !origins.iter().contains(&subspace.origin) - && indicated_entities - .intersection(&subspace.entities) - .any(|e| origins.iter().all(|origin| !e.starts_with(origin))) - { - origins.push(subspace.origin.clone()); - } + if !subspace.supports_3d_content() { + return None; + } - Some(origins.into_iter().map(RecommendedSpaceView::new_subtree)) + let mut pinhole_child_spaces = subspace + .child_spaces + .iter() + .filter(|child| { + topo.subspace_for_subspace_origin(child.hash()).map_or( + false, + |child_space| { + child_space.connection_to_parent.is_connected_pinhole() + }, + ) + }) + .peekable(); // Don't collect the iterator, we're only interested in 'any'-style operations. + + // Empty space views are still of interest if any of the child spaces is connected via a pinhole. + if subspace.entities.is_empty() && pinhole_child_spaces.peek().is_none() { + return None; } + + // Creates space views at each view coordinates if there's any. + // (yes, we do so even if they're empty at the moment!) + // + // An exception to this rule is not to create a view there if this is already _also_ a subspace root. + // (e.g. this also has a camera or a `disconnect` logged there) + let mut origins = subspace + .heuristic_hints + .iter() + .filter(|(path, hint)| { + hint.contains(HeuristicHints::ViewCoordinates3d) + && !subspace.child_spaces.contains(path) + }) + .map(|(path, _)| path.clone()) + .collect::>(); + + let path_not_covered_yet = + |e: &EntityPath| origins.iter().all(|origin| !e.starts_with(origin)); + + // If there's no view coordinates or there are still some entities not covered, + // create a view at the subspace origin. + if !origins.iter().contains(&subspace.origin) + && (indicated_entities + .intersection(&subspace.entities) + .any(path_not_covered_yet) + || pinhole_child_spaces.any(path_not_covered_yet)) + { + origins.push(subspace.origin.clone()); + } + + Some(origins.into_iter().map(RecommendedSpaceView::new_subtree)) }) .flatten() .collect(), From 91439eda16052b75a1d11df7b331b5bd488ab8da Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 19 Mar 2024 04:14:31 -0400 Subject: [PATCH 059/508] Make space view use its own data-result when editing visible history (#5571) ### What Also renamed the API because root_data_result is **very** overloaded. * Fixes #5568 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5571/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5571/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5571/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5571) - [Docs preview](https://rerun.io/preview/5f8ed4cf08e9cbc8b723284d2af622c664ede60c/docs) - [Examples preview](https://rerun.io/preview/5f8ed4cf08e9cbc8b723284d2af622c664ede60c/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view/src/space_view.rs | 16 ++++++++++--- .../re_space_view/src/space_view_contents.rs | 2 +- crates/re_viewer/src/ui/selection_panel.rs | 23 ++++++------------- crates/re_viewer/src/ui/visible_history.rs | 18 +++++++++++---- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 4b8dc2214af7..38be63729fd1 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -391,8 +391,9 @@ impl SpaceViewBlueprint { let class = self.class(ctx.space_view_class_registry); - let root_data_result = self.root_data_result(ctx.store_context, ctx.blueprint_query); - let props = root_data_result + let space_view_data_result = + self.space_view_data_result(ctx.store_context, ctx.blueprint_query); + let props = space_view_data_result .individual_properties() .cloned() .unwrap_or_default(); @@ -415,7 +416,16 @@ impl SpaceViewBlueprint { self.id.as_entity_path() } - pub fn root_data_result(&self, ctx: &StoreContext<'_>, query: &LatestAtQuery) -> DataResult { + /// A special data result for the space view that sits "above" the [`SpaceViewContents`]. + /// + /// This allows us to use interfaces that take a [`DataResult`] to modify things on the + /// space view that can then be inherited into the contents. For example, controlling + /// visible history. + pub fn space_view_data_result( + &self, + ctx: &StoreContext<'_>, + query: &LatestAtQuery, + ) -> DataResult { let base_override_root = self.entity_path(); let individual_override_path = base_override_root.join(&DataResult::INDIVIDUAL_OVERRIDES_PREFIX.into()); diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index ab75c2ea9922..0f896be2f9cf 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -348,7 +348,7 @@ impl DataQueryPropertyResolver<'_> { // the space-view. This isn't totally generic once we add container overrides, but it's a start. let (mut root_entity_properties, root_component_overrides) = self .space_view - .root_data_result(ctx, query) + .space_view_data_result(ctx, query) .property_overrides .map(|p| (p.accumulated_properties, p.resolved_component_overrides)) .unwrap_or_default(); diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 7f380246eb33..e74edaa1c0cd 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -847,28 +847,19 @@ fn blueprint_ui_for_space_view( ); // Space View don't inherit properties. - let root_data_result = space_view.root_data_result(ctx.store_context, ctx.blueprint_query); - - let query_result = ctx.lookup_query_result(space_view.id); - let Some(data_result) = query_result - .tree - .root_handle() - .and_then(|root| query_result.tree.lookup_result(root)) - else { - re_log::error_once!("Could not find root data result for Space View {space_view_id:?}"); - return; - }; + let space_view_data_result = + space_view.space_view_data_result(ctx.store_context, ctx.blueprint_query); visual_time_range_ui( ctx, ui, - &query_result.tree, - data_result, + None, // There is no tree above the space view yet + &space_view_data_result, class_identifier, true, ); - let mut props = root_data_result + let mut props = space_view_data_result .individual_properties() .cloned() .unwrap_or_default(); @@ -889,7 +880,7 @@ fn blueprint_ui_for_space_view( ); } - root_data_result.save_individual_override_properties(ctx, Some(props)); + space_view_data_result.save_individual_override_properties(ctx, Some(props)); } } @@ -1122,7 +1113,7 @@ fn entity_props_ui( visual_time_range_ui( ctx, ui, - &query_result.tree, + Some(&query_result.tree), data_result, *space_view_class, false, diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index f223f3eca65d..f8e223cfa6ac 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -69,7 +69,7 @@ fn entity_with_visible_history( pub fn visual_time_range_ui( ctx: &ViewerContext<'_>, ui: &mut Ui, - data_result_tree: &re_viewer_context::DataResultTree, + data_result_tree: Option<&re_viewer_context::DataResultTree>, data_result: &re_viewer_context::DataResult, space_view_class: SpaceViewClassIdentifier, is_space_view: bool, @@ -92,10 +92,18 @@ pub fn visual_time_range_ui( let mut resolved_range = data_result .lookup_override::(ctx) .unwrap_or(default_time_range(space_view_class)); - let mut has_individual_range = data_result - .component_override_source(data_result_tree, &VisibleTimeRange::name()) - .as_ref() - == Some(&data_result.entity_path); + let mut has_individual_range = if let Some(data_result_tree) = data_result_tree { + // If there is a data-tree, we know we have individual settings if we are our own source. + data_result + .component_override_source(data_result_tree, &VisibleTimeRange::name()) + .as_ref() + == Some(&data_result.entity_path) + } else { + // Otherwise we can inspect directly. + data_result + .lookup_override::(ctx) + .is_some() + }; let collapsing_response = re_ui.collapsing_header(ui, "Visible time range", false, |ui| { let has_individual_range_before = has_individual_range; From 7cfa13c3c6738382a4094ba601b5acd19fa6ec4d Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 19 Mar 2024 09:35:26 +0100 Subject: [PATCH 060/508] Show visible time range on all entities of a space view that supports it (#5564) ### What * Fixes #5463 Another fallout of group removal: Previously, you could always change the Visible Time Range on groups, since there's no groups anymore we have to show the ui on all entities. image (screenshot showing Visible Time Range on the root Data Result) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5564/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5564/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5564/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5564) - [Docs preview](https://rerun.io/preview/a419df11b8c11a3436a1484d064d62b487460497/docs) - [Examples preview](https://rerun.io/preview/a419df11b8c11a3436a1484d064d62b487460497/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/ui/visible_history.rs | 40 ++-------------------- 1 file changed, 3 insertions(+), 37 deletions(-) diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index f8e223cfa6ac..664bf1ba3e94 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -4,7 +4,7 @@ use std::ops::RangeInclusive; use egui::{NumExt as _, Response, Ui}; use re_entity_db::{TimeHistogram, VisibleHistory, VisibleHistoryBoundary}; -use re_log_types::{EntityPath, TimeType, TimeZone}; +use re_log_types::{TimeType, TimeZone}; use re_space_view::{ default_time_range, time_range_boundary_to_visible_history_boundary, visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, @@ -12,9 +12,9 @@ use re_space_view::{ use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D}; use re_space_view_time_series::TimeSeriesSpaceView; use re_types::blueprint::components::VisibleTimeRange; -use re_types_core::{ComponentName, Loggable as _}; +use re_types_core::Loggable as _; use re_ui::{markdown_ui, ReUi}; -use re_viewer_context::{SpaceViewClass, SpaceViewClassIdentifier, TimeControl, ViewerContext}; +use re_viewer_context::{SpaceViewClass, SpaceViewClassIdentifier, ViewerContext}; /// These space views support the Visible History feature. static VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS: once_cell::sync::Lazy< @@ -29,43 +29,12 @@ static VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS: once_cell::sync::Lazy< .into() }); -/// Entities containing one of these components support the visible history feature. -static VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES: once_cell::sync::Lazy> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.HalfSizes2D", - "rerun.components.HalfSizes3D", - "rerun.components.LineStrip2D", - "rerun.components.LineStrip3D", - "rerun.components.Position2D", - "rerun.components.Position3D", - "rerun.components.Scalar", - "rerun.components.TensorData", - "rerun.components.Vector3D", - ] - .map(Into::into) - .into() - }); - // TODO(#4145): This method is obviously unfortunate. It's a temporary solution until the Visualizer // system is able to report its ability to handle the visible history feature. fn space_view_with_visible_history(space_view_class: SpaceViewClassIdentifier) -> bool { VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS.contains(&space_view_class) } -fn entity_with_visible_history( - ctx: &ViewerContext<'_>, - time_ctrl: &TimeControl, - entity_path: &EntityPath, -) -> bool { - let store = ctx.entity_db.store(); - let component_names = store.all_components(time_ctrl.timeline(), entity_path); - component_names - .iter() - .flatten() - .any(|name| VISIBLE_HISTORY_SUPPORTED_COMPONENT_NAMES.contains(name)) -} - pub fn visual_time_range_ui( ctx: &ViewerContext<'_>, ui: &mut Ui, @@ -79,9 +48,6 @@ pub fn visual_time_range_ui( if is_space_view && !space_view_with_visible_history(space_view_class) { return; } - if !is_space_view && !entity_with_visible_history(ctx, &time_ctrl, &data_result.entity_path) { - return; - } let re_ui = ctx.re_ui; From cd8633ef08080760d1fd41ed33cc0433b18383bc Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 19 Mar 2024 18:58:23 +0100 Subject: [PATCH 061/508] Refactor `Selection` use a `BTreeMap` and make it more encapsulated (#5569) ### What This PR change `Selection` to use a `BTreeMap>` instead of a `Vec<(Item, Option)`. This is a much better model for the selection that we currently have (`Item` may not be duplicated, even with different space context) and paves the way for a clean "remove" API (needed by #5465). **NOTE**: with this approach we loose ordering by "cmd-click". Advantage: - in some case its better (e.g when selecting multiple instances of the same entity, now they are sorted by instance key) - the selection panel is sorted by "category" of item Disadvantage: - well, not the order of clicks, so Selection Panel ordering be slightly surprising in some cases ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5569/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5569/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5569/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5569) - [Docs preview](https://rerun.io/preview/fe5c33da7ac42466e55073e658fd9a1edef5fd9e/docs) - [Examples preview](https://rerun.io/preview/fe5c33da7ac42466e55073e658fd9a1edef5fd9e/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 2 + Cargo.toml | 1 + crates/re_space_view_spatial/src/ui.rs | 2 +- crates/re_viewer/src/ui/selection_panel.rs | 2 +- crates/re_viewer_context/Cargo.toml | 1 + crates/re_viewer_context/src/item.rs | 2 +- .../src/selection_history.rs | 2 +- .../re_viewer_context/src/selection_state.rs | 97 ++++++++++++------- .../re_viewer_context/src/viewer_context.rs | 5 +- crates/re_viewport/src/context_menu/mod.rs | 6 +- 10 files changed, 74 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12859d24a49d..1f9ca221a1f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2640,6 +2640,7 @@ checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown 0.14.2", + "serde", ] [[package]] @@ -5088,6 +5089,7 @@ dependencies = [ "egui_tiles", "glam", "half 2.3.1", + "indexmap 2.1.0", "itertools 0.12.0", "macaw", "ndarray", diff --git a/Cargo.toml b/Cargo.toml index 1c1450e42119..9eccf3aa39a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -142,6 +142,7 @@ half = "2.3.1" hyper = "0.14" image = { version = "0.24", default-features = false } indent = "0.1" +indexmap = "2.1" # Version chosen to align with other dependencies indicatif = "0.17.7" # Progress bar infer = "0.15" # infer MIME type by checking the magic number signaturefer MIME type by checking the magic number signature insta = "1.23" diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index d4e992dab371..56ca7f9ef75f 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -641,7 +641,7 @@ pub fn picking( }); }; - ctx.select_hovered_on_click(&response, re_viewer_context::Selection(hovered_items)); + ctx.select_hovered_on_click(&response, hovered_items.into_iter()); Ok(response) } diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index e74edaa1c0cd..342cd2218a96 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -758,7 +758,7 @@ fn show_list_item_for_container_child( &response, SelectionUpdateBehavior::Ignore, ); - ctx.select_hovered_on_click(&response, std::iter::once(item)); + ctx.select_hovered_on_click(&response, item); if remove_contents { viewport.blueprint.mark_user_interaction(ctx); diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index d00eef5fb7f7..08dd6d0be4b0 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -37,6 +37,7 @@ egui.workspace = true egui_tiles.workspace = true glam = { workspace = true, features = ["serde"] } half.workspace = true +indexmap = { workspace = true, features = ["std", "serde"] } itertools.workspace = true macaw.workspace = true ndarray.workspace = true diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 8dd6dc9daa5d..847c10213227 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -6,7 +6,7 @@ use crate::{ContainerId, SpaceViewId}; /// One "thing" in the UI. /// /// This is the granularity of what is selectable and hoverable. -#[derive(Clone, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)] +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Deserialize, serde::Serialize)] pub enum Item { /// A recording (or blueprint) StoreId(re_log_types::StoreId), diff --git a/crates/re_viewer_context/src/selection_history.rs b/crates/re_viewer_context/src/selection_history.rs index 2b4d350d8f4f..34e1f4574517 100644 --- a/crates/re_viewer_context/src/selection_history.rs +++ b/crates/re_viewer_context/src/selection_history.rs @@ -36,7 +36,7 @@ impl SelectionHistory { let mut i = 0; self.stack.retain_mut(|selection| { - selection.retain(f); + selection.retain(|item, _| f(item)); let retain = !selection.is_empty(); if !retain && i <= self.current { self.current = self.current.saturating_sub(1); diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index 168e1f9fdedb..9743cbf7c4e1 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -1,4 +1,5 @@ use ahash::HashMap; +use indexmap::IndexMap; use parking_lot::Mutex; use re_entity_db::EntityPath; @@ -82,66 +83,62 @@ impl InteractionHighlight { /// /// Used to store what is currently selected and/or hovered. #[derive(Debug, Default, Clone, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct Selection(pub Vec<(Item, Option)>); +pub struct Selection(IndexMap>); impl From for Selection { #[inline] fn from(val: Item) -> Self { - Selection(vec![(val, None)]) + Selection([(val, None)].into()) } } impl From for Selection where - T: Iterator, + T: Iterator)>, { #[inline] fn from(value: T) -> Self { - Selection(value.map(|item| (item, None)).collect()) - } -} - -impl std::ops::Deref for Selection { - type Target = Vec<(Item, Option)>; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl std::ops::DerefMut for Selection { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 + Selection(value.collect()) } } impl Selection { - /// For each item in this selection, if it refers to the first element of an instance with a single element, resolve it to a splatted entity path. - pub fn resolve_mono_instance_path_items(&mut self, ctx: &ViewerContext<'_>) { - for (item, _) in self.iter_mut() { - *item = - resolve_mono_instance_path_item(&ctx.current_query(), ctx.entity_db.store(), item); - } + /// For each item in this selection, if it refers to the first element of an instance with a + /// single element, resolve it to a splatted entity path. + pub fn into_mono_instance_path_items(self, ctx: &ViewerContext<'_>) -> Self { + Selection( + self.0 + .into_iter() + .map(|(item, space_ctx)| { + ( + resolve_mono_instance_path_item( + &ctx.current_query(), + ctx.entity_db.store(), + &item, + ), + space_ctx, + ) + }) + .collect(), + ) } /// The first selected object if any. pub fn first_item(&self) -> Option<&Item> { - self.0.first().map(|(item, _)| item) + self.0.keys().next() } /// Check if the selection contains a single item and returns it if so. pub fn single_item(&self) -> Option<&Item> { - if self.0.len() == 1 { - Some(&self.0[0].0) + if self.len() == 1 { + self.first_item() } else { None } } pub fn iter_items(&self) -> impl Iterator { - self.0.iter().map(|(item, _)| item) + self.0.keys() } pub fn iter_space_context(&self) -> impl Iterator { @@ -169,8 +166,36 @@ impl Selection { } /// Retains elements that fulfill a certain condition. - pub fn retain(&mut self, f: impl Fn(&Item) -> bool) { - self.0.retain(|(item, _)| f(item)); + pub fn retain(&mut self, f: impl FnMut(&Item, &mut Option) -> bool) { + self.0.retain(f); + } + + /// Returns the number of items in the selection. + pub fn len(&self) -> usize { + self.0.len() + } + + /// Check if the selection is empty. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Returns an iterator over the items and their selected space context. + pub fn iter(&self) -> impl Iterator)> { + self.0.iter() + } + + /// Returns a mutable iterator over the items and their selected space context. + pub fn iter_mut(&mut self) -> impl Iterator)> { + self.0.iter_mut() + } + + /// Extend the selection with more items. + pub fn extend( + &mut self, + other: impl IntoIterator)>, + ) { + self.0.extend(other); } } @@ -268,14 +293,16 @@ impl ApplicationSelectionState { pub fn toggle_selection(&self, toggle_items: Selection) { re_tracing::profile_function!(); - let mut toggle_items_set: HashMap> = - toggle_items.iter().cloned().collect(); + let mut toggle_items_set: HashMap> = toggle_items + .iter() + .map(|(item, ctx)| (item.clone(), ctx.clone())) + .collect(); let mut new_selection = self.selection_previous_frame.clone(); // If an item was already selected with the exact same context remove it. // If an item was already selected and loses its context, remove it. - new_selection.0.retain(|(item, ctx)| { + new_selection.retain(|item, ctx| { if let Some(new_ctx) = toggle_items_set.get(item) { if new_ctx == ctx || new_ctx.is_none() { toggle_items_set.remove(item); diff --git a/crates/re_viewer_context/src/viewer_context.rs b/crates/re_viewer_context/src/viewer_context.rs index 985ec924085a..c5cfa1323ff5 100644 --- a/crates/re_viewer_context/src/viewer_context.rs +++ b/crates/re_viewer_context/src/viewer_context.rs @@ -100,8 +100,7 @@ impl<'a> ViewerContext<'a> { ) { re_tracing::profile_function!(); - let mut selection = selection.into(); - selection.resolve_mono_instance_path_items(self); + let selection = selection.into().into_mono_instance_path_items(self); let selection_state = self.selection_state(); if response.hovered() { @@ -109,7 +108,7 @@ impl<'a> ViewerContext<'a> { } if response.double_clicked() { - if let Some((item, _)) = selection.first() { + if let Some(item) = selection.first_item() { self.command_sender .send_system(crate::SystemCommand::SetFocus(item.clone())); } diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index dfaab61cbe15..43e43cf7308f 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -66,8 +66,7 @@ pub fn context_menu_ui_for_item( // When the context menu is triggered open, we check if we're part of the selection, // and, if not, we update the selection to include only the item that was clicked. if item_response.hovered() && item_response.secondary_clicked() { - ctx.selection_state() - .set_selection(std::iter::once(item.clone())); + ctx.selection_state().set_selection(item.clone()); show_context_menu(&Selection::from(item.clone())); } else { @@ -80,8 +79,7 @@ pub fn context_menu_ui_for_item( SelectionUpdateBehavior::OverrideSelection => { if item_response.secondary_clicked() { - ctx.selection_state() - .set_selection(std::iter::once(item.clone())); + ctx.selection_state().set_selection(item.clone()); } show_context_menu(&Selection::from(item.clone())); From 2d433c1458b4a101e74cae9751c30136a9b3ef5f Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 20 Mar 2024 10:32:09 +0100 Subject: [PATCH 062/508] Self-documenting example manifest (#5591) Opening `manifest.toml` should tell you what's going on. --- examples/manifest.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/manifest.toml b/examples/manifest.toml index 8638e49769b0..d70f04efb117 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -1,5 +1,11 @@ #:schema ./schema.json +# Examples listed in this manifest will appear on our website. +# This has no effect whatsoever on whether they appear in the app itself. +# +# To add examples to the app itself, use the `channel` attribute in the example's readme's frontmatter. +# See for more information. + [categories.real-data] order = 1 title = "Examples with Real Data" From c867f2f309661ff1a0f350040e373645bf7cd90c Mon Sep 17 00:00:00 2001 From: Leonard Bruns Date: Wed, 20 Mar 2024 10:34:04 +0100 Subject: [PATCH 063/508] Fix C++ and Python data loader examples to use nanoseconds instead of seconds (#5580) --- examples/cpp/external_data_loader/main.cpp | 2 +- examples/python/external_data_loader/main.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/cpp/external_data_loader/main.cpp b/examples/cpp/external_data_loader/main.cpp index 0a39a9499db9..3c9c78a71f83 100644 --- a/examples/cpp/external_data_loader/main.cpp +++ b/examples/cpp/external_data_loader/main.cpp @@ -17,7 +17,7 @@ void set_time_from_args(const rerun::RecordingStream& rec, cxxopts::ParseResult& if (pos != std::string::npos) { auto timeline_name = time_str.substr(0, pos); int64_t time = std::stol(time_str.substr(pos + 1)); - rec.set_time_seconds(timeline_name, static_cast(time)); + rec.set_time_nanos(timeline_name, time); } } } diff --git a/examples/python/external_data_loader/main.py b/examples/python/external_data_loader/main.py index 3ae4e381ed05..b9f4621c11e9 100755 --- a/examples/python/external_data_loader/main.py +++ b/examples/python/external_data_loader/main.py @@ -87,7 +87,7 @@ def set_time_from_args() -> None: if len(parts) != 2: continue timeline_name, time = parts - rr.set_time_seconds(timeline_name, float(time)) + rr.set_time_nanos(timeline_name, int(time)) for time_str in args.sequence: parts = time_str.split("=") From 24c8638e8d9a4ecdb6decd40ead44ed2a980483a Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:40:31 +0100 Subject: [PATCH 064/508] Moved taplo back to the default feature in `pixi.toml` (#5587) ### What Taplo now supports linux-aarch64 so we no longer need to special-case it (https://github.com/conda-forge/taplo-feedstock/issues/3) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5587/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5587/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5587/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5587) - [Docs preview](https://rerun.io/preview/40e7333ef4d9d008dc29a4983885987afbf65dad/docs) - [Examples preview](https://rerun.io/preview/40e7333ef4d9d008dc29a4983885987afbf65dad/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- pixi.lock | 3944 ++--------------------------------------------------- pixi.toml | 14 +- 2 files changed, 140 insertions(+), 3818 deletions(-) diff --git a/pixi.lock b/pixi.lock index de4e93572c55..a54f54fa6b92 100644 --- a/pixi.lock +++ b/pixi.lock @@ -156,6 +156,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_16.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda @@ -304,6 +305,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda @@ -460,6 +462,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda @@ -615,6 +618,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda @@ -743,6 +747,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.11.0-h91493d7_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 @@ -902,6 +907,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda @@ -1051,6 +1057,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda @@ -1188,6 +1195,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hef22860_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda @@ -1325,6 +1333,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hb31c410_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda @@ -1454,6 +1463,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.10.0-h91493d7_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 @@ -1476,571 +1486,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - taplo: - channels: - - url: https://conda.anaconda.org/conda-forge/ - packages: - linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.16-haed3651_8.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.10-ha9bf9b1_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.14-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.2.18-h4466546_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.4.2-he635cd5_6.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.8.1-hbfc29b2_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.14.6-h9e7f0e3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.10.3-hffff1cc_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.5.2-h4893938_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.1.15-h4466546_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.18-h4466546_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.3-h137ae52_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-he0cb598_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.27.0-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.7-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/just-1.24.0-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20240116.1-cxx17_h59595ed_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-h6bfc85a_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-14.0.2-h59595ed_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-14.0.2-h59595ed_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-14.0.2-hc6145d9_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-sql-14.0.2-h757c851_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hb016d2e_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-14.0.2-h757c851_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-21_linux64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-21_linux64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp16-16.0.6-default_h127d8a8_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-18.1.1-default_h5d6823c_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.5.0-hca28451_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.22.0-h9be4e54_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.22.0-hc7a4891_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.62.1-h15f2491_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-21_linux64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm15-15.0.7-hb3ce162_4.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm16-16.0.6-hb3ce162_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.1-h2448989_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libnl-3.9.0-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.26-pthreads_h413a1c8_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-14.0.2-h352af49_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.25.3-h08a7969_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libre2-11-2023.09.01-h5a48ba9_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.19.0-hb90f79a_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.8.0-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.46.0-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.5-h232c23b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.4.0-py311h63ff55d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_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/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-h59595ed_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.19.0-hb753e55_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.0.0-h1e5e2c1_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-50.0-hd3aeb46_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.6-h06160fa_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.8.1-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.19.0-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h11edf95_7.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - osx-64: - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.16-h9d28af5_8.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.10-hf9de6f9_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.14-h10d778d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.18-h905ab21_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.2-h30f2259_6.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.1-hce3b3da_7.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.6-hf76ed93_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.3-ha335edc_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.5.2-h6f42f56_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.15-h905ab21_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.18-h905ab21_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.3-hf5b2fc6_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h232afc9_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.27.0-h10d778d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.7-h73e2aa4_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/just-1.24.0-h11a7dfb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20240116.1-cxx17_hc1bcbd7_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-he79e29d_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-h000cb23_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-h000cb23_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-h2382776_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-h7e3fe20_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-ha5acb15_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-h7e3fe20_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-21_osx64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.1.0-h0dc2134_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.1.0-h0dc2134_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.1.0-h0dc2134_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-21_osx64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp16-16.0.6-default_h7151d67_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-18.1.1-default_h0edc4dd_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.5.0-h726d00d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-16.0.6-hd57cbcb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-5.0.0-13_2_0_h97931a8_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-13.2.0-h2873a65_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.22.0-h651e89d_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.22.0-ha67e85c_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.1-h384b2fc_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-21_osx64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm15-15.0.7-hbedff68_4.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm16-16.0.6-hbedff68_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.1-hbcf5fad_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.26-openmp_hfef2a42_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h381d950_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-h4e4d658_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2023.09.01-h81f5012_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.19.0-h064b379_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.8.0-hb7f2c08_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.47.0-h67532ce_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.5-hc0ae0f7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.6-hb6ac08f_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.4.0-py311h24bb903_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4-h93d8f39_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.19.0-h119ffd7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.0-h6c6cd50_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.19.0-h11a7dfb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.16-h0d2f7a6_8.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.10-h677d54c_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.14-h93a5062_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.2.18-h677d54c_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.4.2-h59ac3ca_6.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.8.1-hfe5d766_7.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.14.6-h9ac2cdb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.10.3-hb8a1441_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.5.2-h4398043_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.1.15-h677d54c_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.18-h677d54c_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.3-h0de420c_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h2fb64bc_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.27.0-h93a5062_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.7-hebf3989_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.24.0-h5ef7bb8_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20240116.1-cxx17_hebf3989_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h5233fb5_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-14.0.2-h13dd4ca_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-14.0.2-h13dd4ca_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-14.0.2-h95ca633_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-sql-14.0.2-hdc5392b_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-gandiva-14.0.2-hfef958d_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-14.0.2-hef52601_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-21_osxarm64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.1.0-hb547adb_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.1.0-hb547adb_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-hb547adb_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-21_osxarm64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp16-16.0.6-default_he012953_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-18.1.1-default_h83d0a53_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.5.0-h2d989ff_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-16.0.6-h4653b0c_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-13_2_0_hd922786_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-13.2.0-hf226fd6_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.22.0-hbebe991_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-2.22.0-h8a76758_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.62.1-h9c18a4f_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-21_osxarm64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm15-15.0.7-h2621b3d_4.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm16-16.0.6-haab561b_3.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.1-h30cc82d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.26-openmp_h6c19121_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-14.0.2-hf6ce1d5_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-4.25.3-hbfab5d5_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2023.09.01-h7b2c953_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.19.0-h026a170_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.8.0-h1a8c8d9_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.47.0-h93a5062_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.5-h0d0cfa8_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-17.0.6-hcd81f8e_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.4.0-py311h71175c2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h463b476_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.19.0-h5f47a4d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.0.0-h3d3088e_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.19.0-h5ef7bb8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - win-64: - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-h7613915_8.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hf6fcf4e_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.14-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-hf6fcf4e_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-h3df98b0_6.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-h4e3df0f_7.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.6-hf0b8b6f_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.3-h96fac68_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.2-h08df315_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-hf6fcf4e_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-hf6fcf4e_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.3-h6047f0a_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h558341a_3.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.7-h63175ca_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.0.0-h57928b3_49841.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.24.0-h7f3b576_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h2a83f13_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h63175ca_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h63175ca_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-h02312f3_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h55b4db4_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-hcb01e45_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-h89268de_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-21_win64_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlicommon-1.1.0-hcfcfb64_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlidec-1.1.0-hcfcfb64_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlienc-1.1.0-hcfcfb64_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-21_win64_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libclang13-18.1.1-default_hf64faad_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.5.0-hd5e4a3a_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.22.0-h9cad5c0_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.22.0-hb581fae_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.62.1-h5273850_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.9.3-default_haede6df_1009.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.17-hcfcfb64_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-21_win64_mkl.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h7ec3a38_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.3-h503648d_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libre2-11-2023.09.01-hf8d8778_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libthrift-0.19.0-ha2b3283_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libutf8proc-2.8.0-h82a8f57_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.5-hc3477c8_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.4-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libgfortran-5.3.0-6.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-5.3.0-7.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.4.0-py311h9a9e57f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.0.0-h66d3029_49657.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.19.0-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/orc-2.0.0-heb0c069_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_13_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.8.1-h7f3b576_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.11.0-h91493d7_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.19.0-h7f3b576_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl packages: - kind: conda name: _libgcc_mutex @@ -2201,25 +1646,6 @@ packages: license_family: Apache size: 89155 timestamp: 1704306064106 -- kind: conda - name: aws-c-auth - version: 0.7.16 - build: h0d2f7a6_8 - build_number: 8 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.16-h0d2f7a6_8.conda - sha256: 82006dd3067f4d09fd8cee0ea9c4836b6ac0c02db68acd001ff5c7b8669522b5 - md5: a37cb159ebfb3d3adc1a351c98c1027f - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - license: Apache-2.0 - license_family: Apache - size: 89205 - timestamp: 1710282202281 - kind: conda name: aws-c-auth version: 0.7.16 @@ -2239,28 +1665,6 @@ packages: license_family: Apache size: 89495 timestamp: 1708633374785 -- kind: conda - name: aws-c-auth - version: 0.7.16 - build: h7613915_8 - build_number: 8 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-h7613915_8.conda - sha256: 9ac4ebfc14faa7377a0df29ebf562d55e04a99d6d72f8ce8bb6a661e4753cde3 - md5: 61c802b7e9c8d6215116c01ce7d582d9 - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 99468 - timestamp: 1710282357839 - kind: conda name: aws-c-auth version: 0.7.16 @@ -2300,45 +1704,6 @@ packages: license_family: Apache size: 90856 timestamp: 1708633418805 -- kind: conda - name: aws-c-auth - version: 0.7.16 - build: h9d28af5_8 - build_number: 8 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.16-h9d28af5_8.conda - sha256: f75a39577b61fc649e3a8c926b91218ebad6ea78beb2f2b16f90d3ae9493c1c4 - md5: 0b451cddce1ea8f9247b386ba3285edc - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - license: Apache-2.0 - license_family: Apache - size: 90270 - timestamp: 1710282294532 -- kind: conda - name: aws-c-auth - version: 0.7.16 - build: haed3651_8 - build_number: 8 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.16-haed3651_8.conda - sha256: 75a540b313e5dc212fc0a6057f8a5bee2dda443f17a5a076bd3ea4d7195d483e - md5: ce96c083829ab2727c942243ac93ffe0 - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 103298 - timestamp: 1710281865011 - kind: conda name: aws-c-auth version: 0.7.16 @@ -2434,21 +1799,6 @@ packages: license_family: Apache size: 39662 timestamp: 1701212885323 -- kind: conda - name: aws-c-cal - version: 0.6.10 - build: h677d54c_2 - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.10-h677d54c_2.conda - sha256: d4f0fa97a3f6f5a090b0c9ed078fedf6b50f19a406d272f8e4b2b214f074323e - md5: a501703d122cdf7cf38c1bbc8c16f981 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - license: Apache-2.0 - license_family: Apache - size: 38986 - timestamp: 1709815581194 - kind: conda name: aws-c-cal version: 0.6.10 @@ -2481,23 +1831,6 @@ packages: license_family: Apache size: 48505 timestamp: 1708003694470 -- kind: conda - name: aws-c-cal - version: 0.6.10 - build: ha9bf9b1_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.10-ha9bf9b1_2.conda - sha256: e45d9f1eb862f566bdea3d3229dfc74f31e647a72198fe04aab58ccc03a30a37 - md5: ce2471034f5459a39636aacc292c96b6 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - libgcc-ng >=12 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: Apache - size: 55421 - timestamp: 1709815095625 - kind: conda name: aws-c-cal version: 0.6.10 @@ -2533,24 +1866,6 @@ packages: license_family: Apache size: 55726 timestamp: 1708004211846 -- kind: conda - name: aws-c-cal - version: 0.6.10 - build: hf6fcf4e_2 - build_number: 2 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hf6fcf4e_2.conda - sha256: 800b25ee5590f3ddd9186e225c756b9e5d00d3ecce8c2de5d9343af85213d883 - md5: 7490ede93a75acc3589a2e43f77c79e9 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 55818 - timestamp: 1709815582485 - kind: conda name: aws-c-cal version: 0.6.10 @@ -2566,21 +1881,6 @@ packages: license_family: Apache size: 39206 timestamp: 1708003965707 -- kind: conda - name: aws-c-cal - version: 0.6.10 - build: hf9de6f9_2 - build_number: 2 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.10-hf9de6f9_2.conda - sha256: cb9b20aeec4cd037117fd0bfe2ae5a0a5f6a08a71f941be0f163bb27c87b98ea - md5: 393dbe9973160cb09cb3594c9246e260 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - license: Apache-2.0 - license_family: Apache - size: 45249 - timestamp: 1709815427644 - kind: conda name: aws-c-common version: 0.9.10 @@ -2693,60 +1993,6 @@ packages: license_family: Apache size: 225560 timestamp: 1707964559211 -- kind: conda - name: aws-c-common - version: 0.9.14 - build: h10d778d_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.14-h10d778d_0.conda - sha256: 1d207a8aee42700763e6a7801c69721ccc06ce75e62e0e5d8fc6df0197c0a88b - md5: c620ac518f3086eaf4f105f64908a57c - license: Apache-2.0 - license_family: Apache - size: 208228 - timestamp: 1709669491258 -- kind: conda - name: aws-c-common - version: 0.9.14 - build: h93a5062_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.14-h93a5062_0.conda - sha256: c58aea968814459ef485c1f1aeb889423b0fa808b7c1216d96d5282ff2e796ab - md5: 028bc18a1ef8bb1a4e4d6ec94e9b50da - license: Apache-2.0 - license_family: Apache - size: 203827 - timestamp: 1709669473014 -- kind: conda - name: aws-c-common - version: 0.9.14 - build: hcfcfb64_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.14-hcfcfb64_0.conda - sha256: 46f4dced6c9d553d65e6f721d51ef43e6a343487a3073299c03a073161d7637f - md5: 169998d49ac3c4800187bfc546e1d165 - depends: - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 222375 - timestamp: 1709669884758 -- kind: conda - name: aws-c-common - version: 0.9.14 - build: hd590300_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.14-hd590300_0.conda - sha256: c71dd835b1d8c7097c8d152a65680f119a203b73a6a62c5aac414bafe5e997ad - md5: d44fe0d9a6971a4fb245be0055775d9d - depends: - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 225655 - timestamp: 1709669368566 - kind: conda name: aws-c-compression version: 0.2.17 @@ -2810,57 +2056,11 @@ packages: md5: 16f4516d03cbc0aba2bdda73db85ca37 depends: - aws-c-common >=0.9.13,<0.9.14.0a0 - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 19873 - timestamp: 1708003535938 -- kind: conda - name: aws-c-compression - version: 0.2.18 - build: h4466546_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.2.18-h4466546_2.conda - sha256: 7fcc6a924691f9de65c82fd559cb1cb2ebd121c42da544a9a43623d69a284e23 - md5: b0d9153fc7cfa8dc36b8703e1a59f5f3 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 19072 - timestamp: 1709815144275 -- kind: conda - name: aws-c-compression - version: 0.2.18 - build: h677d54c_2 - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.2.18-h677d54c_2.conda - sha256: bbc73d8ec3d760d528f15edad66835d1fe63a035f254e760235e745cf360de20 - md5: 71e953c1c0fac25dd5d65d63d47389d8 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - license: Apache-2.0 - license_family: Apache - size: 17911 - timestamp: 1709815495665 -- kind: conda - name: aws-c-compression - version: 0.2.18 - build: h905ab21_2 - build_number: 2 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.18-h905ab21_2.conda - sha256: 021cee135f0d9b58fbc8d212618cd9bd6bd0012da41a6469edf010b2853dd3ef - md5: ffd7cfb55b1aa4e3eef477583b1ad87d - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 + - libgcc-ng >=12 license: Apache-2.0 license_family: Apache - size: 17930 - timestamp: 1709815482244 + size: 19873 + timestamp: 1708003535938 - kind: conda name: aws-c-compression version: 0.2.18 @@ -2910,24 +2110,6 @@ packages: license_family: Apache size: 18067 timestamp: 1708003629797 -- kind: conda - name: aws-c-compression - version: 0.2.18 - build: hf6fcf4e_2 - build_number: 2 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-hf6fcf4e_2.conda - sha256: ecb5ab2353c4499311fe17c82210955a498526c9563861777b3b0cd6dcc5cfea - md5: 6efdf7af73d7043a00394a2f1b039650 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 22366 - timestamp: 1709815905155 - kind: conda name: aws-c-compression version: 0.2.18 @@ -3058,62 +2240,6 @@ packages: license_family: Apache size: 46870 timestamp: 1708602815747 -- kind: conda - name: aws-c-event-stream - version: 0.4.2 - build: h30f2259_6 - build_number: 6 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.2-h30f2259_6.conda - sha256: 65ea5552f7a87783b75a3ecf6e4acd2aee5357c4275a9932d732ee516acab0a9 - md5: 0923a8e81839b0b2d9787d85d635b196 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - libcxx >=16 - license: Apache-2.0 - license_family: Apache - size: 46261 - timestamp: 1710264045535 -- kind: conda - name: aws-c-event-stream - version: 0.4.2 - build: h3df98b0_6 - build_number: 6 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-h3df98b0_6.conda - sha256: 823a4665b3d38a4078b34b6f891bd388400942a3bcbad55b4c6223c559b15de6 - md5: 80ca7e9993f6b0141ae5425a69771a9a - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 54211 - timestamp: 1710264185867 -- kind: conda - name: aws-c-event-stream - version: 0.4.2 - build: h59ac3ca_6 - build_number: 6 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.4.2-h59ac3ca_6.conda - sha256: 86db342fd921f17a50cf7648b45566b2449ac1408a94c2e6cae132b876f1c17c - md5: 7278d0ef10644f95a2dd619b9917e8a2 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - libcxx >=16 - license: Apache-2.0 - license_family: Apache - size: 47119 - timestamp: 1710264020154 - kind: conda name: aws-c-event-stream version: 0.4.2 @@ -3132,25 +2258,6 @@ packages: license_family: Apache size: 46676 timestamp: 1708602620909 -- kind: conda - name: aws-c-event-stream - version: 0.4.2 - build: he635cd5_6 - build_number: 6 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.4.2-he635cd5_6.conda - sha256: 38a30beabafc1dd86c0264b6746315a1010e541a1b3ed7f97e1702873e5eaa51 - md5: 58fc78e523e35a08423c913751a51fde - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - libgcc-ng >=12 - - libstdcxx-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 53665 - timestamp: 1710263650074 - kind: conda name: aws-c-event-stream version: 0.4.2 @@ -3246,27 +2353,6 @@ packages: license_family: Apache size: 163076 timestamp: 1708602693889 -- kind: conda - name: aws-c-http - version: 0.8.1 - build: h4e3df0f_7 - build_number: 7 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-h4e3df0f_7.conda - sha256: 651bdcbe53630bf9665b76c18a6cb21a7b53fe347b03d88c1cb99ed0281c267e - md5: 08ba30d73686a5129f4209c25b31252a - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-compression >=0.2.18,<0.2.19.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 180557 - timestamp: 1710264351681 - kind: conda name: aws-c-http version: 0.8.1 @@ -3286,43 +2372,6 @@ packages: license_family: Apache size: 195024 timestamp: 1708602547845 -- kind: conda - name: aws-c-http - version: 0.8.1 - build: hbfc29b2_7 - build_number: 7 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.8.1-hbfc29b2_7.conda - sha256: 0dc5b73aa31cef3faeeb902a11f12e1244ac241f995d73e4f4e3e0c01622f7a1 - md5: 8476ec099649e9a6de52f7f4d916cd2a - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-compression >=0.2.18,<0.2.19.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 194307 - timestamp: 1710263686092 -- kind: conda - name: aws-c-http - version: 0.8.1 - build: hce3b3da_7 - build_number: 7 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.1-hce3b3da_7.conda - sha256: a3e6bfd71bbc4119da1e79f2bce6094f045112c230b3fd5cc9e6ccd36aba3156 - md5: d287122dfb77c5fa0147fdf368c86d54 - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-compression >=0.2.18,<0.2.19.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - license: Apache-2.0 - license_family: Apache - size: 162710 - timestamp: 1710263951106 - kind: conda name: aws-c-http version: 0.8.1 @@ -3381,24 +2430,6 @@ packages: license_family: Apache size: 151481 timestamp: 1708602772972 -- kind: conda - name: aws-c-http - version: 0.8.1 - build: hfe5d766_7 - build_number: 7 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.8.1-hfe5d766_7.conda - sha256: 0a454c1280e87b4bfd3ab1d70498c5f60c62139ddcd06d1a68c39dcd81e05e75 - md5: 4096407e9d908ef9a292980f93034fcd - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-compression >=0.2.18,<0.2.19.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - license: Apache-2.0 - license_family: Apache - size: 151329 - timestamp: 1710264327114 - kind: conda name: aws-c-io version: 0.13.36 @@ -3542,70 +2573,6 @@ packages: license_family: Apache size: 136989 timestamp: 1708687976415 -- kind: conda - name: aws-c-io - version: 0.14.6 - build: h9ac2cdb_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.14.6-h9ac2cdb_0.conda - sha256: 1dcae62df79786292e841275994c9ded564eb49d7200284c09f7d61326a06c1b - md5: b0c80a8220ddc90196e3b76d856dc6b0 - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - license: Apache-2.0 - license_family: Apache - size: 136547 - timestamp: 1710222457819 -- kind: conda - name: aws-c-io - version: 0.14.6 - build: h9e7f0e3_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.14.6-h9e7f0e3_0.conda - sha256: bb9e7bee234532f7905faf4abc15e3a1be1d8f683b8a0d5863761daad18a7cac - md5: 3fef14ef6e79ea0da149cebb1d0635bf - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - s2n >=1.4.6,<1.4.7.0a0 - license: Apache-2.0 - license_family: Apache - size: 157726 - timestamp: 1710222250665 -- kind: conda - name: aws-c-io - version: 0.14.6 - build: hf0b8b6f_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.6-hf0b8b6f_0.conda - sha256: ab046e34dcaa533d75f8f4892c63ec503812a69fa6e8d23bfbdb0d74926cdc40 - md5: aee3f042f60da448ab622b0a149d6ec2 - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 160412 - timestamp: 1710222753707 -- kind: conda - name: aws-c-io - version: 0.14.6 - build: hf76ed93_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.6-hf76ed93_0.conda - sha256: 824eb1fcf69f67c4fee4e05fd401dba6d5c55f9e37e3cb9904b8b81909e3c3be - md5: 586e11f2969f1f2a61104c5cec8a7957 - depends: - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - license: Apache-2.0 - license_family: Apache - size: 137968 - timestamp: 1710222523409 - kind: conda name: aws-c-mqtt version: 0.10.0 @@ -3754,78 +2721,6 @@ packages: license_family: Apache size: 157819 timestamp: 1708621381498 -- kind: conda - name: aws-c-mqtt - version: 0.10.3 - build: h96fac68_2 - build_number: 2 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.3-h96fac68_2.conda - sha256: 70b62dcf6314a9e1f514fe6f838eb02dfc4a28f4d17723768211a60c28c3429b - md5: 463c0be9e1fb416192174156f58bb2af - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 157436 - timestamp: 1710283031953 -- kind: conda - name: aws-c-mqtt - version: 0.10.3 - build: ha335edc_2 - build_number: 2 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.3-ha335edc_2.conda - sha256: 99304e5095193b937745d0ce6812d0333186a31c41a51b1e4297ddcd962824eb - md5: c8bacb9a988fd8fb6b560a966c4979a8 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - license: Apache-2.0 - license_family: Apache - size: 139008 - timestamp: 1710282888188 -- kind: conda - name: aws-c-mqtt - version: 0.10.3 - build: hb8a1441_2 - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.10.3-hb8a1441_2.conda - sha256: 344ba23eb2cd45105a09d775dd7449e17304b3930d5ff08fbc1426f0f8030b08 - md5: 26421a2d8a329048bb1a5673ce620de5 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - license: Apache-2.0 - license_family: Apache - size: 117955 - timestamp: 1710282576148 -- kind: conda - name: aws-c-mqtt - version: 0.10.3 - build: hffff1cc_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.10.3-hffff1cc_2.conda - sha256: 6b2de4a0e6e907310127b1025a0030d023e1051da48ea5821dcc6db094d69ab7 - md5: 14ad8defb307e1edb293c3fc9da8648f - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 163172 - timestamp: 1710282530222 - kind: conda name: aws-c-s3 version: 0.4.7 @@ -3894,29 +2789,6 @@ packages: license_family: Apache size: 90455 timestamp: 1704321754265 -- kind: conda - name: aws-c-s3 - version: 0.5.2 - build: h08df315_2 - build_number: 2 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.2-h08df315_2.conda - sha256: 2f7af939a87176de471bac1a1c6cc7336c714a64c495f1a5d967e0cfa7bb0e07 - md5: 0a7a232878640624469d3ca4923d146b - depends: - - aws-c-auth >=0.7.16,<0.7.17.0a0 - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 101487 - timestamp: 1710296653111 - kind: conda name: aws-c-s3 version: 0.5.2 @@ -3957,48 +2829,6 @@ packages: license_family: Apache size: 109725 timestamp: 1709172552237 -- kind: conda - name: aws-c-s3 - version: 0.5.2 - build: h4398043_2 - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.5.2-h4398043_2.conda - sha256: 27e90ada0ae6895159a49bc4ed7172b2757cd8fc63e0189dd8cce5d057c6ee06 - md5: 5ddebd5447f4baba6215b1bafcf605dc - depends: - - aws-c-auth >=0.7.16,<0.7.17.0a0 - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - license: Apache-2.0 - license_family: Apache - size: 90478 - timestamp: 1710296516337 -- kind: conda - name: aws-c-s3 - version: 0.5.2 - build: h4893938_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.5.2-h4893938_2.conda - sha256: 312d67b236c9c6003f92f682c55ff344721f79d50d9a4bcdea44f2144f637642 - md5: 7e24759a8b8ead67ce687f3c31ffd12f - depends: - - aws-c-auth >=0.7.16,<0.7.17.0a0 - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - libgcc-ng >=12 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: Apache - size: 105455 - timestamp: 1710296220268 - kind: conda name: aws-c-s3 version: 0.5.2 @@ -4042,26 +2872,6 @@ packages: license_family: Apache size: 101468 timestamp: 1709173131467 -- kind: conda - name: aws-c-s3 - version: 0.5.2 - build: h6f42f56_2 - build_number: 2 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.5.2-h6f42f56_2.conda - sha256: 950a37ab27ec0145a4c92a3524b8862a4f5affec08049dda7b9ab83403969fd6 - md5: 9f5dc9ef044d3c13b0959d04a2005753 - depends: - - aws-c-auth >=0.7.16,<0.7.17.0a0 - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - license: Apache-2.0 - license_family: Apache - size: 91371 - timestamp: 1710296654896 - kind: conda name: aws-c-s3 version: 0.5.2 @@ -4133,65 +2943,19 @@ packages: - kind: conda name: aws-c-sdkutils version: 0.1.15 - build: h00d1b86_1 - build_number: 1 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-sdkutils-0.1.15-h00d1b86_1.conda - sha256: e2ec786734acca3a7449f27aee7052f93e627a76459c3718a4d9236b0e813dad - md5: 222e0288b02a00e62232dde9ff479146 - depends: - - aws-c-common >=0.9.13,<0.9.14.0a0 - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 57857 - timestamp: 1708014280193 -- kind: conda - name: aws-c-sdkutils - version: 0.1.15 - build: h4466546_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.1.15-h4466546_2.conda - sha256: 349a05cf5fbcb3f6f358fc05098b210aa7da4ec3ab6d4719c79bb93b50a629f8 - md5: 258194cedccd33fd8a7b95a8aa105015 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 55383 - timestamp: 1709830510021 -- kind: conda - name: aws-c-sdkutils - version: 0.1.15 - build: h677d54c_2 - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.1.15-h677d54c_2.conda - sha256: 02649707625df0c8908fd807f5d599b5f60b90d7b4e0e71953ff10b9aa0f010c - md5: a68e269534f50d5a94107b9b9b6be747 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - license: Apache-2.0 - license_family: Apache - size: 48880 - timestamp: 1709830883787 -- kind: conda - name: aws-c-sdkutils - version: 0.1.15 - build: h905ab21_2 - build_number: 2 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.15-h905ab21_2.conda - sha256: 77f58ac3aec0cd987f80e202a8197e123beb13b9b25b0137dd921c7a6ddc86ac - md5: bb1523b7de7ac6f112b1992cfcfb250b + build: h00d1b86_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-sdkutils-0.1.15-h00d1b86_1.conda + sha256: e2ec786734acca3a7449f27aee7052f93e627a76459c3718a4d9236b0e813dad + md5: 222e0288b02a00e62232dde9ff479146 depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 + - aws-c-common >=0.9.13,<0.9.14.0a0 + - libgcc-ng >=12 license: Apache-2.0 license_family: Apache - size: 50028 - timestamp: 1709830709542 + size: 57857 + timestamp: 1708014280193 - kind: conda name: aws-c-sdkutils version: 0.1.15 @@ -4241,24 +3005,6 @@ packages: license_family: Apache size: 50255 timestamp: 1708014587926 -- kind: conda - name: aws-c-sdkutils - version: 0.1.15 - build: hf6fcf4e_2 - build_number: 2 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-hf6fcf4e_2.conda - sha256: 03f361182431688732e7173f0d71e5778e0616e68d9ebf994d3ecb70483468a0 - md5: 87fb9f67d4c936a704d6a23a748fad77 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 54282 - timestamp: 1709830762581 - kind: conda name: aws-c-sdkutils version: 0.1.15 @@ -4342,52 +3088,6 @@ packages: license_family: Apache size: 50114 timestamp: 1708017850698 -- kind: conda - name: aws-checksums - version: 0.1.18 - build: h4466546_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.18-h4466546_2.conda - sha256: 9080f064f572ac1747d32b4dff30452ff44ef2df399e6ec7bf9730da1eb99bba - md5: 8a04fc5a5ecaba31f66904b47dcc7797 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - libgcc-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 49940 - timestamp: 1709826415680 -- kind: conda - name: aws-checksums - version: 0.1.18 - build: h677d54c_2 - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.18-h677d54c_2.conda - sha256: 3a7cc8824a23a39478e479865df20d88c12a954895fb9c8a91152cc76976183a - md5: 21b73ab89b82b17ae50d635ce675fea6 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - license: Apache-2.0 - license_family: Apache - size: 48836 - timestamp: 1709826804838 -- kind: conda - name: aws-checksums - version: 0.1.18 - build: h905ab21_2 - build_number: 2 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.18-h905ab21_2.conda - sha256: 5760728e7320a01519bcbbae8dcd31b86e819f66c58f641b86b27ce592e5fff3 - md5: f17e778398011e88d45edf58f24c18ae - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - license: Apache-2.0 - license_family: Apache - size: 48733 - timestamp: 1709826868797 - kind: conda name: aws-checksums version: 0.1.18 @@ -4437,24 +3137,6 @@ packages: license_family: Apache size: 48808 timestamp: 1708017957232 -- kind: conda - name: aws-checksums - version: 0.1.18 - build: hf6fcf4e_2 - build_number: 2 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-hf6fcf4e_2.conda - sha256: 1a67c0ee80cb2d18bd7cfc9ec1aae2ad78d51adc7ac9442ec70e370bbcef24de - md5: ffa6601a628ccc6ec5eddb0def2db1d2 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 52016 - timestamp: 1709827173669 - kind: conda name: aws-checksums version: 0.1.18 @@ -4673,105 +3355,6 @@ packages: license_family: Apache size: 242812 timestamp: 1709208518468 -- kind: conda - name: aws-crt-cpp - version: 0.26.3 - build: h0de420c_2 - build_number: 2 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.3-h0de420c_2.conda - sha256: 578ffab0c981ea227d5a9d70b32af5bcba58c632d0f8b38d4eb1ed88cc05eaaa - md5: e6d964373064af06199c6e4dff9f174e - depends: - - aws-c-auth >=0.7.16,<0.7.17.0a0 - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-c-mqtt >=0.10.3,<0.10.4.0a0 - - aws-c-s3 >=0.5.2,<0.5.3.0a0 - - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - - libcxx >=16 - license: Apache-2.0 - license_family: Apache - size: 218109 - timestamp: 1710309757551 -- kind: conda - name: aws-crt-cpp - version: 0.26.3 - build: h137ae52_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.3-h137ae52_2.conda - sha256: 596b6d63352b7ae189842dc86510d53438f88d1e2c1d56779eeebc130beef2b6 - md5: 21c8acfdfa31ab5582897dda7c9c8a75 - depends: - - aws-c-auth >=0.7.16,<0.7.17.0a0 - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-c-mqtt >=0.10.3,<0.10.4.0a0 - - aws-c-s3 >=0.5.2,<0.5.3.0a0 - - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - - libgcc-ng >=12 - - libstdcxx-ng >=12 - license: Apache-2.0 - license_family: Apache - size: 333634 - timestamp: 1710309442818 -- kind: conda - name: aws-crt-cpp - version: 0.26.3 - build: h6047f0a_2 - build_number: 2 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.3-h6047f0a_2.conda - sha256: 1cb3c3f8d0b19dad52eaa64758629f47aea88591cf3bc354fcb87c0923dc9e73 - md5: 5c8a2ba1c7a6477b10d0bcd33ee1202f - depends: - - aws-c-auth >=0.7.16,<0.7.17.0a0 - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-c-mqtt >=0.10.3,<0.10.4.0a0 - - aws-c-s3 >=0.5.2,<0.5.3.0a0 - - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 242851 - timestamp: 1710309795536 -- kind: conda - name: aws-crt-cpp - version: 0.26.3 - build: hf5b2fc6_2 - build_number: 2 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.3-hf5b2fc6_2.conda - sha256: d4ec9488f2052276b4b119e62b2b08df52deec3e38dc7c57311f51413046de8b - md5: bcea6861674e784e2eb2f1de4f3bac35 - depends: - - aws-c-auth >=0.7.16,<0.7.17.0a0 - - aws-c-cal >=0.6.10,<0.6.11.0a0 - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - - aws-c-http >=0.8.1,<0.8.2.0a0 - - aws-c-io >=0.14.6,<0.14.7.0a0 - - aws-c-mqtt >=0.10.3,<0.10.4.0a0 - - aws-c-s3 >=0.5.2,<0.5.3.0a0 - - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 - - libcxx >=16 - license: Apache-2.0 - license_family: Apache - size: 280273 - timestamp: 1710309758427 - kind: conda name: aws-sdk-cpp version: 1.11.210 @@ -4845,50 +3428,6 @@ packages: license_family: Apache size: 3267017 timestamp: 1704353210503 -- kind: conda - name: aws-sdk-cpp - version: 1.11.267 - build: h232afc9_3 - build_number: 3 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h232afc9_3.conda - sha256: d83b5e4728d61f996115251fbb1670b79c6b5c0a02f2f1f458b80a6b06b08eb1 - md5: f707d57fee350a6b47726b2996f8e4e1 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - - libcurl >=8.5.0,<9.0a0 - - libcxx >=16 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: Apache - size: 3367065 - timestamp: 1710323636919 -- kind: conda - name: aws-sdk-cpp - version: 1.11.267 - build: h2fb64bc_3 - build_number: 3 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h2fb64bc_3.conda - sha256: 5ad2be70779844380b8b8567814ed3966ef2efd9c48cc258975cec7f072c9753 - md5: e11e8d3c0ca63039e4b8101a5063fa30 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - - libcurl >=8.5.0,<9.0a0 - - libcxx >=16 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: Apache - size: 3423557 - timestamp: 1710323443841 - kind: conda name: aws-sdk-cpp version: 1.11.267 @@ -4911,28 +3450,6 @@ packages: license_family: Apache size: 3375381 timestamp: 1708527712169 -- kind: conda - name: aws-sdk-cpp - version: 1.11.267 - build: h558341a_3 - build_number: 3 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h558341a_3.conda - sha256: 886817ef6b059f715ab3d93025d5306c5046688fdbdade21f6fb3ce33e053561 - md5: 42633be391d0a113f39356a37ce7ea40 - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 3409008 - timestamp: 1710323920901 - kind: conda name: aws-sdk-cpp version: 1.11.267 @@ -5000,29 +3517,6 @@ packages: license_family: Apache size: 3413748 timestamp: 1708528552370 -- kind: conda - name: aws-sdk-cpp - version: 1.11.267 - build: he0cb598_3 - build_number: 3 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-he0cb598_3.conda - sha256: 55bf5d47ba2591507abb9b2120905cdb0b1834b2867f03c6cff4bb88f7ec7c58 - md5: ca4aebdc89bb9b08b3b6dd68ae09080d - depends: - - aws-c-common >=0.9.14,<0.9.15.0a0 - - aws-c-event-stream >=0.4.2,<0.4.3.0a0 - - aws-checksums >=0.1.18,<0.1.19.0a0 - - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - - libcurl >=8.5.0,<9.0a0 - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: Apache - size: 3636564 - timestamp: 1710322529863 - kind: conda name: aws-sdk-cpp version: 1.11.267 @@ -5266,28 +3760,6 @@ packages: license_family: MIT size: 386639 timestamp: 1708248423560 -- kind: conda - name: blackdoc - version: 0.3.8 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - sha256: ec7b75c0f88db3e8c8b506ec48fa4fa210b0c1d09b0969df726a68b5563d151d - md5: c03749cb0d5874fd5b9c1620a3d230c4 - depends: - - black - - importlib-metadata - - more-itertools - - python >=3.7 - - rich - - tomli - license: MIT - license_family: MIT - purls: - - pkg:pypi/blackdoc - size: 30092 - timestamp: 1667565048643 - kind: conda name: blackdoc version: 0.3.8 @@ -5532,18 +4004,6 @@ packages: license_family: MIT size: 162725 timestamp: 1706299899438 -- kind: conda - name: c-ares - version: 1.27.0 - build: h10d778d_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.27.0-h10d778d_0.conda - sha256: a53e14c071dcce756ce80673f2a90a1c6dff695a26bc9f5e54d56b55e76ee3dc - md5: 713dd57081dfe8535eb961b45ed26a0c - license: MIT - license_family: MIT - size: 148568 - timestamp: 1708685147963 - kind: conda name: c-ares version: 1.27.0 @@ -5558,18 +4018,6 @@ packages: license_family: MIT size: 170421 timestamp: 1708684764494 -- kind: conda - name: c-ares - version: 1.27.0 - build: h93a5062_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.27.0-h93a5062_0.conda - sha256: a168e53ee462980cd78b324e055afdd00080ded378ca974969a0917eb4ae1ccb - md5: d3579ba506791b1f8f8a16cfc2885326 - license: MIT - license_family: MIT - size: 145697 - timestamp: 1708685057216 - kind: conda name: c-ares version: 1.27.0 @@ -5586,20 +4034,6 @@ packages: license_family: MIT size: 153934 timestamp: 1708685329364 -- kind: conda - name: c-ares - version: 1.27.0 - build: hd590300_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.27.0-hd590300_0.conda - sha256: 2a5866b19d28cb963fab291a62ff1c884291b9d6f59de14643e52f103e255749 - md5: f6afff0e9ee08d2f1b897881a4f38cdb - depends: - - libgcc-ng >=12 - license: MIT - license_family: MIT - size: 163578 - timestamp: 1708684786032 - kind: conda name: c-compiler version: 1.6.0 @@ -5964,25 +4398,6 @@ packages: license_family: Apache size: 692537 timestamp: 1706894104516 -- kind: conda - name: clang-format - version: 16.0.6 - build: default_h127d8a8_5 - build_number: 5 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_5.conda - sha256: 8ae23380654712d8e8440871419cd8409903c3e2fd7c051978f2923e662a9c92 - md5: 1fe9ee2e961ecae22f5a0413b34f9f5d - depends: - - clang-format-16 16.0.6 default_h127d8a8_5 - - libclang-cpp16 >=16.0.6,<16.1.0a0 - - libgcc-ng >=12 - - libllvm16 >=16.0.6,<16.1.0a0 - - libstdcxx-ng >=12 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 21690 - timestamp: 1709765119029 - kind: conda name: clang-format version: 16.0.6 @@ -6074,24 +4489,6 @@ packages: license_family: Apache size: 21914 timestamp: 1706894694897 -- kind: conda - name: clang-format-16 - version: 16.0.6 - build: default_h127d8a8_5 - build_number: 5 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_5.conda - sha256: 9843007a8ffd53008240aec77b74068733daf5a00c60480d0978d05146511522 - md5: 72cd7fd253434f1c6c6ee0af962ee700 - depends: - - libclang-cpp16 >=16.0.6,<16.1.0a0 - - libgcc-ng >=12 - - libllvm16 >=16.0.6,<16.1.0a0 - - libstdcxx-ng >=12 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 61980 - timestamp: 1709765062005 - kind: conda name: clang-format-16 version: 16.0.6 @@ -6162,32 +4559,6 @@ packages: license_family: Apache size: 56848 timestamp: 1706894594045 -- kind: conda - name: clang-tools - version: 16.0.6 - build: default_h127d8a8_5 - build_number: 5 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_5.conda - sha256: 4b1c26e1058995181efcbd31b9d952241f9c561aad79ca6b7261ec7dc4796bd7 - md5: a85978ea2f9ea8b3a0c0b5ccea48a42e - depends: - - clang-format 16.0.6 default_h127d8a8_5 - - libclang-cpp16 >=16.0.6,<16.1.0a0 - - libclang13 >=16.0.6 - - libgcc-ng >=12 - - libllvm16 >=16.0.6,<16.1.0a0 - - libstdcxx-ng >=12 - constrains: - - clangdev 16.0.6 - - clang 16.0.6.* - - llvm 16.0.6.* - - llvm-tools 16.0.6.* - - llvmdev 16.0.6.* - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 26812015 - timestamp: 1709765163586 - kind: conda name: clang-tools version: 16.0.6 @@ -6484,24 +4855,6 @@ packages: license_family: BSD size: 19330 timestamp: 1706832814124 -- kind: conda - name: click - version: 8.1.7 - build: unix_pyh707e725_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - sha256: f0016cbab6ac4138a429e28dbcb904a90305b34b3fe41a9b89d697c90401caec - md5: f3ad426304898027fc619827ff428eca - depends: - - __unix - - python >=3.8 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/click - size: 84437 - timestamp: 1692311973840 - kind: conda name: click version: 8.1.7 @@ -6522,25 +4875,6 @@ packages: - pkg:pypi/click size: 84437 timestamp: 1692311973840 -- kind: conda - name: click - version: 8.1.7 - build: win_pyh7428d3b_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - sha256: 90236b113b9a20041736e80b80ee965167f9aac0468315c55e2bad902d673fb0 - md5: 3549ecbceb6cd77b91a105511b7d0786 - depends: - - __win - - colorama - - python >=3.8 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/click - size: 85051 - timestamp: 1692312207348 - kind: conda name: click version: 8.1.7 @@ -6678,23 +5012,6 @@ packages: license_family: BSD size: 16525734 timestamp: 1695270838345 -- kind: conda - name: colorama - version: 0.4.6 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - sha256: 2c1b2e9755ce3102bca8d69e8f26e4f087ece73f50418186aee7c74bef8e1698 - md5: 3faab06a954c2a04039983f2c4a50d99 - depends: - - python >=3.7 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/colorama - size: 25170 - timestamp: 1666700778190 - kind: conda name: colorama version: 0.4.6 @@ -7063,65 +5380,6 @@ packages: license_family: APACHE size: 1298784 timestamp: 1710058440028 -- kind: conda - name: flatbuffers - version: 24.3.7 - build: h59595ed_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.7-h59595ed_0.conda - sha256: 30b53ebe46e902ea80479406d8d849f6d552d1f3ea4ee0eef6048a7a2201d93e - md5: e72ffaf09c193f6bebbb0054079ab7d1 - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - license: Apache-2.0 - license_family: APACHE - size: 1453620 - timestamp: 1710058292298 -- kind: conda - name: flatbuffers - version: 24.3.7 - build: h63175ca_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.7-h63175ca_0.conda - sha256: 40613c4386464f2a1fa8ccebf1a38fede56669b8cdb6e4b0307e427720805232 - md5: 030adc8125b572439459ea9f063cf3de - depends: - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: APACHE - size: 1727810 - timestamp: 1710058620131 -- kind: conda - name: flatbuffers - version: 24.3.7 - build: h73e2aa4_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.7-h73e2aa4_0.conda - sha256: e4d0e09f5f27825fc8ccb42cc4ebb20951b364a303aa4e95fc996afbac78bf79 - md5: 4bca4cc7c9864063a92b08fb6975b802 - depends: - - libcxx >=16 - license: Apache-2.0 - license_family: APACHE - size: 1336422 - timestamp: 1710058653949 -- kind: conda - name: flatbuffers - version: 24.3.7 - build: hebf3989_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.7-hebf3989_0.conda - sha256: accfeff694d2b95a4a0ec6cd2ae5206028ce63a72583523e74bbb9d8e5b9ab53 - md5: 51f4a8e083d8caf54e945a9cf858a966 - depends: - - libcxx >=16 - license: Apache-2.0 - license_family: APACHE - size: 1278204 - timestamp: 1710058972127 - kind: conda name: gcc version: 12.3.0 @@ -7237,24 +5495,6 @@ packages: license_family: BSD size: 116549 timestamp: 1594303828933 -- kind: conda - name: gitdb - version: 4.0.11 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - sha256: 52ab2798be31b8f509eeec458712f447ced4f96ecb672c6c9a42778f47e07b1b - md5: 623b19f616f2ca0c261441067e18ae40 - depends: - - python >=3.7 - - smmap >=3.0.1,<6 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/gitdb - size: 52872 - timestamp: 1697791718749 - kind: conda name: gitdb version: 4.0.11 @@ -7618,23 +5858,6 @@ packages: license_family: APACHE size: 26900 timestamp: 1709821273570 -- kind: conda - name: iniconfig - version: 2.0.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - sha256: 38740c939b668b36a50ef455b077e8015b8c9cf89860d421b3fff86048f49666 - md5: f800d2da156d08e289b14e87e43c1ae5 - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/iniconfig - size: 11101 - timestamp: 1673103208955 - kind: conda name: iniconfig version: 2.0.0 @@ -7788,19 +6011,6 @@ packages: license: CC0-1.0 size: 1178083 timestamp: 1704893025811 -- kind: conda - name: just - version: 1.24.0 - build: h11a7dfb_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/just-1.24.0-h11a7dfb_0.conda - sha256: 802572940bc1208d135637b9859517d4262d156d956a98c96ca5502240da7d7d - md5: 5ac25104279a5589381ade8bd8e56552 - constrains: - - __osx >=10.12 - license: CC0-1.0 - size: 1113461 - timestamp: 1708241218651 - kind: conda name: just version: 1.24.0 @@ -7814,46 +6024,6 @@ packages: license: CC0-1.0 size: 1104293 timestamp: 1708246328468 -- kind: conda - name: just - version: 1.24.0 - build: h5ef7bb8_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.24.0-h5ef7bb8_0.conda - sha256: 8a887ad3b46cb7df6e6f28301bf498a1d546a191b4e856f5ec68b51508534efd - md5: cd1e84db2e7aafc373279d6ac9746e20 - constrains: - - __osx >=11.0 - license: CC0-1.0 - size: 1033268 - timestamp: 1708241219422 -- kind: conda - name: just - version: 1.24.0 - build: h7f3b576_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/just-1.24.0-h7f3b576_0.conda - sha256: 00ef2294055adaf43115f0929172e8cd6cecec3ec03fa73d0fd10d6c34ed4aa2 - md5: 969f459714747b46af1159ee41dabd6d - depends: - - m2w64-gcc-libs - - m2w64-gcc-libs-core - license: CC0-1.0 - size: 1166282 - timestamp: 1708241728702 -- kind: conda - name: just - version: 1.24.0 - build: he8a937b_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/just-1.24.0-he8a937b_0.conda - sha256: 6d230b47d7548158e92d54580abdb2c1c767c986dc3d72431db7025570bf82cd - md5: 1de85b6ac80b52ce66fab344945cf2c3 - depends: - - libgcc-ng >=12 - license: CC0-1.0 - size: 1203601 - timestamp: 1708240909235 - kind: conda name: kernel-headers_linux-64 version: 2.6.32 @@ -8320,47 +6490,6 @@ packages: license_family: APACHE size: 7385058 timestamp: 1710292910535 -- kind: conda - name: libarrow - version: 14.0.2 - build: h2a83f13_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h2a83f13_13_cpu.conda - sha256: 1e20499fa3ec9e4abb03ec91fa5422019868b36dcf2ae3d123e1b5785a9c7424 - md5: 3c1e5bd6b032045ee42bb09302f1c01f - depends: - - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 - - bzip2 >=1.0.8,<2.0a0 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libbrotlidec >=1.1.0,<1.2.0a0 - - libbrotlienc >=1.1.0,<1.2.0a0 - - libcrc32c >=1.1.2,<1.2.0a0 - - libcurl >=8.5.0,<9.0a0 - - libgoogle-cloud >=2.22.0,<2.23.0a0 - - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libutf8proc >=2.8.0,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - lz4-c >=1.9.3,<1.10.0a0 - - openssl >=3.2.1,<4.0a0 - - orc >=2.0.0,<2.0.1.0a0 - - re2 - - snappy >=1.1.10,<2.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - - zstd >=1.5.5,<1.6.0a0 - constrains: - - parquet-cpp <0.0a0 - - arrow-cpp <0.0a0 - - apache-arrow-proc =*=cpu - license: Apache-2.0 - license_family: APACHE - size: 4907643 - timestamp: 1710345937957 - kind: conda name: libarrow version: 14.0.2 @@ -8453,100 +6582,25 @@ packages: - libbrotlidec >=1.1.0,<1.2.0a0 - libbrotlienc >=1.1.0,<1.2.0a0 - libgcc-ng >=12 - - libgoogle-cloud >=2.21.0,<2.22.0a0 - - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 - - libre2-11 >=2023.6.2,<2024.0a0 - - libstdcxx-ng >=12 - - libutf8proc >=2.8.0,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - lz4-c >=1.9.3,<1.10.0a0 - - orc >=1.9.2,<1.9.3.0a0 - - re2 - - snappy >=1.1.10,<2.0a0 - - zstd >=1.5.5,<1.6.0a0 - constrains: - - arrow-cpp <0.0a0 - - apache-arrow-proc =*=cpu - - parquet-cpp <0.0a0 - license: Apache-2.0 - license_family: APACHE - size: 8080771 - timestamp: 1708689749260 -- kind: conda - name: libarrow - version: 14.0.2 - build: h5233fb5_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h5233fb5_13_cpu.conda - sha256: b2fdb38eac0220e2588548c13e1b599e567c147450e19011cb661786085c64f0 - md5: 5964f068ac691eb417ecc6173e3ec288 - depends: - - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 - - bzip2 >=1.0.8,<2.0a0 - - glog >=0.7.0,<0.8.0a0 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libbrotlidec >=1.1.0,<1.2.0a0 - - libbrotlienc >=1.1.0,<1.2.0a0 - - libcxx >=14 - - libgoogle-cloud >=2.22.0,<2.23.0a0 - - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libutf8proc >=2.8.0,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - lz4-c >=1.9.3,<1.10.0a0 - - orc >=2.0.0,<2.0.1.0a0 - - re2 - - snappy >=1.1.10,<2.0a0 - - zstd >=1.5.5,<1.6.0a0 - constrains: - - parquet-cpp <0.0a0 - - apache-arrow-proc =*=cpu - - arrow-cpp <0.0a0 - license: Apache-2.0 - license_family: APACHE - size: 5325718 - timestamp: 1710345870461 -- kind: conda - name: libarrow - version: 14.0.2 - build: h6bfc85a_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-h6bfc85a_13_cpu.conda - sha256: f62f6a0a50b94f55c4ee90288b599c17980f1c0b7d18ae9533c42fc18437fc8f - md5: 0b97d14e02c9a6c3a259f9cd88335c9f - depends: - - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 - - bzip2 >=1.0.8,<2.0a0 - - glog >=0.7.0,<0.8.0a0 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libbrotlidec >=1.1.0,<1.2.0a0 - - libbrotlienc >=1.1.0,<1.2.0a0 - - libgcc-ng >=12 - - libgoogle-cloud >=2.22.0,<2.23.0a0 - - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 + - libgoogle-cloud >=2.21.0,<2.22.0a0 + - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 + - libre2-11 >=2023.6.2,<2024.0a0 - libstdcxx-ng >=12 - libutf8proc >=2.8.0,<3.0a0 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - - orc >=2.0.0,<2.0.1.0a0 + - orc >=1.9.2,<1.9.3.0a0 - re2 - snappy >=1.1.10,<2.0a0 - zstd >=1.5.5,<1.6.0a0 constrains: + - arrow-cpp <0.0a0 - apache-arrow-proc =*=cpu - parquet-cpp <0.0a0 - - arrow-cpp <0.0a0 license: Apache-2.0 license_family: APACHE - size: 8070162 - timestamp: 1710345363045 + size: 8080771 + timestamp: 1708689749260 - kind: conda name: libarrow version: 14.0.2 @@ -8663,44 +6717,6 @@ packages: license_family: APACHE size: 5696868 timestamp: 1708690271784 -- kind: conda - name: libarrow - version: 14.0.2 - build: he79e29d_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-he79e29d_13_cpu.conda - sha256: 613a144ad341462f08e7be43a028441501c810dc59023cbe12e3e56e27ad1c92 - md5: 02fa4f5f3f8287b5914f8ee7cff7487b - depends: - - __osx >=10.13 - - aws-crt-cpp >=0.26.3,<0.26.4.0a0 - - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 - - bzip2 >=1.0.8,<2.0a0 - - glog >=0.7.0,<0.8.0a0 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libbrotlidec >=1.1.0,<1.2.0a0 - - libbrotlienc >=1.1.0,<1.2.0a0 - - libcxx >=14 - - libgoogle-cloud >=2.22.0,<2.23.0a0 - - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libutf8proc >=2.8.0,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - lz4-c >=1.9.3,<1.10.0a0 - - orc >=2.0.0,<2.0.1.0a0 - - re2 - - snappy >=1.1.10,<2.0a0 - - zstd >=1.5.5,<1.6.0a0 - constrains: - - arrow-cpp <0.0a0 - - apache-arrow-proc =*=cpu - - parquet-cpp <0.0a0 - license: Apache-2.0 - license_family: APACHE - size: 5718166 - timestamp: 1710346534084 - kind: conda name: libarrow-acero version: 14.0.2 @@ -8717,22 +6733,6 @@ packages: license_family: APACHE size: 512509 timestamp: 1708690347206 -- kind: conda - name: libarrow-acero - version: 14.0.2 - build: h000cb23_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-h000cb23_13_cpu.conda - sha256: bd071a96a8b4da5cf7fe88d586c5ecc77cff17a80dc5bb46873c73d29c70f788 - md5: f8a9bb4d1aef7853c734c829456efcff - depends: - - libarrow 14.0.2 he79e29d_13_cpu - - libcxx >=14 - license: Apache-2.0 - license_family: APACHE - size: 512740 - timestamp: 1710346674065 - kind: conda name: libarrow-acero version: 14.0.2 @@ -8765,22 +6765,6 @@ packages: license_family: APACHE size: 494852 timestamp: 1708691198827 -- kind: conda - name: libarrow-acero - version: 14.0.2 - build: h13dd4ca_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-14.0.2-h13dd4ca_13_cpu.conda - sha256: c43bf0f7c5fda78df3830656ad600b061fe3a3d1a2596f95e1d152fa9d36c936 - md5: c9f53116aac6f41597e004e42f479591 - depends: - - libarrow 14.0.2 h5233fb5_13_cpu - - libcxx >=14 - license: Apache-2.0 - license_family: APACHE - size: 495434 - timestamp: 1710345986422 - kind: conda name: libarrow-acero version: 14.0.2 @@ -8831,23 +6815,6 @@ packages: license_family: APACHE size: 577227 timestamp: 1708689800054 -- kind: conda - name: libarrow-acero - version: 14.0.2 - build: h59595ed_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-14.0.2-h59595ed_13_cpu.conda - sha256: 16cadd969ffd3d68a0821c7d9af4fb7772ad2f54187852b09026677a1c203410 - md5: 28e25c6db46fc5542c858cf701909d84 - depends: - - libarrow 14.0.2 h6bfc85a_13_cpu - - libgcc-ng >=12 - - libstdcxx-ng >=12 - license: Apache-2.0 - license_family: APACHE - size: 577795 - timestamp: 1710345426232 - kind: conda name: libarrow-acero version: 14.0.2 @@ -8883,24 +6850,6 @@ packages: license_family: APACHE size: 430548 timestamp: 1708690137226 -- kind: conda - name: libarrow-acero - version: 14.0.2 - build: h63175ca_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h63175ca_13_cpu.conda - sha256: 8ee3b272ebdadbf4e41f4ea4d1b36db62555870378f8be941f83220bf3cd3b2e - md5: 389ccdec73910798474ab1517d5a5747 - depends: - - libarrow 14.0.2 h2a83f13_13_cpu - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: APACHE - size: 431459 - timestamp: 1710346036673 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -8919,24 +6868,6 @@ packages: license_family: APACHE size: 511903 timestamp: 1708690574393 -- kind: conda - name: libarrow-dataset - version: 14.0.2 - build: h000cb23_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-h000cb23_13_cpu.conda - sha256: 0f013a4a208723516f0049585994dc2363c120cf11c18849c4b3b01bc4986f40 - md5: d6db4c70e3a1fc9ac0a48c9165e2e820 - depends: - - libarrow 14.0.2 he79e29d_13_cpu - - libarrow-acero 14.0.2 h000cb23_13_cpu - - libcxx >=14 - - libparquet 14.0.2 h381d950_13_cpu - license: Apache-2.0 - license_family: APACHE - size: 512999 - timestamp: 1710347067673 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -8973,24 +6904,6 @@ packages: license_family: APACHE size: 526964 timestamp: 1708691531170 -- kind: conda - name: libarrow-dataset - version: 14.0.2 - build: h13dd4ca_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-14.0.2-h13dd4ca_13_cpu.conda - sha256: a0833d1bc74cb554ab5da8b01f65c77525190b295da1d77071adc778ebfb1072 - md5: 90c1416a2538df8b3343716cfec2c4f8 - depends: - - libarrow 14.0.2 h5233fb5_13_cpu - - libarrow-acero 14.0.2 h13dd4ca_13_cpu - - libcxx >=14 - - libparquet 14.0.2 hf6ce1d5_13_cpu - license: Apache-2.0 - license_family: APACHE - size: 527932 - timestamp: 1710346391216 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -9047,25 +6960,6 @@ packages: license_family: APACHE size: 580942 timestamp: 1708689918 -- kind: conda - name: libarrow-dataset - version: 14.0.2 - build: h59595ed_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-14.0.2-h59595ed_13_cpu.conda - sha256: eae222df321ea3408a3b28ea85cb40504e86975cd6f258d37912f6ce6d0b9ad1 - md5: 5266653f8b74e0ba57401be532055410 - depends: - - libarrow 14.0.2 h6bfc85a_13_cpu - - libarrow-acero 14.0.2 h59595ed_13_cpu - - libgcc-ng >=12 - - libparquet 14.0.2 h352af49_13_cpu - - libstdcxx-ng >=12 - license: Apache-2.0 - license_family: APACHE - size: 581399 - timestamp: 1710345583152 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -9105,48 +6999,6 @@ packages: license_family: APACHE size: 429115 timestamp: 1708690422907 -- kind: conda - name: libarrow-dataset - version: 14.0.2 - build: h63175ca_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h63175ca_13_cpu.conda - sha256: 50ba7bff4899da18c8791071cbc733496eccc65d6948b2faac6a5f2e0a98e9b7 - md5: daeb4b650d02b601783ea6799f9afd6c - depends: - - libarrow 14.0.2 h2a83f13_13_cpu - - libarrow-acero 14.0.2 h63175ca_13_cpu - - libparquet 14.0.2 h7ec3a38_13_cpu - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: APACHE - size: 429023 - timestamp: 1710346405791 -- kind: conda - name: libarrow-flight - version: 14.0.2 - build: h02312f3_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-h02312f3_13_cpu.conda - sha256: 9a64a061f5d42e7c021f9e65066957cd1650f6a97cf3897363111b52f464021f - md5: f51f43c16adcee3ed9a1e151c1aeb92e - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 h2a83f13_13_cpu - - libgrpc >=1.62.1,<1.63.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: APACHE - size: 286961 - timestamp: 1710346136713 - kind: conda name: libarrow-flight version: 14.0.2 @@ -9169,27 +7021,6 @@ packages: license_family: APACHE size: 501085 timestamp: 1706609649937 -- kind: conda - name: libarrow-flight - version: 14.0.2 - build: h2382776_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-h2382776_13_cpu.conda - sha256: bbd32e1906eb567d95d41b72d64f993d88761dc2b2760fe508854baab7802966 - md5: 3bf6df6c793a2ea01f3e0612c741b372 - depends: - - __osx >=10.13 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 he79e29d_13_cpu - - libcxx >=14 - - libgrpc >=1.62.1,<1.63.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 322715 - timestamp: 1710346774669 - kind: conda name: libarrow-flight version: 14.0.2 @@ -9233,26 +7064,6 @@ packages: license_family: APACHE size: 321632 timestamp: 1708690401993 -- kind: conda - name: libarrow-flight - version: 14.0.2 - build: h95ca633_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-14.0.2-h95ca633_13_cpu.conda - sha256: c44b819b5efb283c01aa43c805de17266cb407256c4e86427bb64b6cfd392e42 - md5: 392cd88b061dbc1c4366871e65a68ed9 - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 h5233fb5_13_cpu - - libcxx >=14 - - libgrpc >=1.62.1,<1.63.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 333172 - timestamp: 1710346111062 - kind: conda name: libarrow-flight version: 14.0.2 @@ -9294,28 +7105,6 @@ packages: license_family: APACHE size: 332020 timestamp: 1706610826254 -- kind: conda - name: libarrow-flight - version: 14.0.2 - build: hc6145d9_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-14.0.2-hc6145d9_13_cpu.conda - sha256: 5bb091f548f124d9aa0f1a2bb070be2f3713dabd7995e7b82c61427cf7b1f9a5 - md5: be1e8c18e141e9fb3358f1225c583d0d - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 h6bfc85a_13_cpu - - libgcc-ng >=12 - - libgrpc >=1.62.1,<1.63.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libstdcxx-ng >=12 - - ucx >=1.15.0,<1.16.0a0 - license: Apache-2.0 - license_family: APACHE - size: 503693 - timestamp: 1710345464269 - kind: conda name: libarrow-flight version: 14.0.2 @@ -9456,26 +7245,6 @@ packages: license_family: APACHE size: 154009 timestamp: 1708690633124 -- kind: conda - name: libarrow-flight-sql - version: 14.0.2 - build: h55b4db4_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h55b4db4_13_cpu.conda - sha256: 4ba5130101c323580e9f8ae86ab9a7389aa1a27a62c1d793e89cc99d24ff84c2 - md5: 8c27d39e7147c7ee420bcbdf12b83200 - depends: - - libarrow 14.0.2 h2a83f13_13_cpu - - libarrow-flight 14.0.2 h02312f3_13_cpu - - libprotobuf >=4.25.3,<4.25.4.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: APACHE - size: 235314 - timestamp: 1710346485995 - kind: conda name: libarrow-flight-sql version: 14.0.2 @@ -9513,44 +7282,6 @@ packages: license_family: APACHE size: 195809 timestamp: 1706609745191 -- kind: conda - name: libarrow-flight-sql - version: 14.0.2 - build: h757c851_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-sql-14.0.2-h757c851_13_cpu.conda - sha256: 669a52f7240ab55fa51b89c805acb91c89975db6081347aff14ea8363c9f2b34 - md5: 690b85e4586d37c997a090d42e20295a - depends: - - libarrow 14.0.2 h6bfc85a_13_cpu - - libarrow-flight 14.0.2 hc6145d9_13_cpu - - libgcc-ng >=12 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libstdcxx-ng >=12 - license: Apache-2.0 - license_family: APACHE - size: 195497 - timestamp: 1710345622444 -- kind: conda - name: libarrow-flight-sql - version: 14.0.2 - build: h7e3fe20_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-h7e3fe20_13_cpu.conda - sha256: 90bd62adf53cd99da17365ab73f53b90df0af79b6861a9e21051b1a0b811174e - md5: 4c5fea48489a40db78b2fcbfe262900f - depends: - - __osx >=10.13 - - libarrow 14.0.2 he79e29d_13_cpu - - libarrow-flight 14.0.2 h2382776_13_cpu - - libcxx >=14 - - libprotobuf >=4.25.3,<4.25.4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 155420 - timestamp: 1710347160360 - kind: conda name: libarrow-flight-sql version: 14.0.2 @@ -9589,24 +7320,6 @@ packages: license_family: APACHE size: 182885 timestamp: 1710293099163 -- kind: conda - name: libarrow-flight-sql - version: 14.0.2 - build: hdc5392b_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-sql-14.0.2-hdc5392b_13_cpu.conda - sha256: a74ba3c1ed45cc6b89b66b5dd465d6a1210bc75481d79b80028034f404a7968a - md5: d98a1133d4bba9a05325954e662f5295 - depends: - - libarrow 14.0.2 h5233fb5_13_cpu - - libarrow-flight 14.0.2 h95ca633_13_cpu - - libcxx >=14 - - libprotobuf >=4.25.3,<4.25.4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 163324 - timestamp: 1710346482468 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -9724,101 +7437,28 @@ packages: license_family: APACHE size: 10170570 timestamp: 1708690279861 -- kind: conda - name: libarrow-gandiva - version: 14.0.2 - build: ha5acb15_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-ha5acb15_13_cpu.conda - sha256: 6d06c71df682907daf6a37deac2fac394388b8e3947b5171ba6fa280e45b1ebc - md5: e864ce81130c6fbae77fd7ffb768b41d - depends: - - __osx >=10.13 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 he79e29d_13_cpu - - libcxx >=14 - - libllvm15 >=15.0.7,<15.1.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libutf8proc >=2.8.0,<3.0a0 - - openssl >=3.2.1,<4.0a0 - - re2 - license: Apache-2.0 - license_family: APACHE - size: 700321 - timestamp: 1710346874742 - kind: conda name: libarrow-gandiva version: 14.0.2 build: hacb8726_3_cpu - build_number: 3 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hacb8726_3_cpu.conda - sha256: a2f62e378fd618ba4c7f554bb923d72677c70a6b07fe07c5daec5ad26038b912 - md5: 44be88e1cf0aa51576460d0f268820f6 - depends: - - libarrow 14.0.2 h84dd17c_3_cpu - - libgcc-ng >=12 - - libllvm15 >=15.0.7,<15.1.0a0 - - libre2-11 >=2023.6.2,<2024.0a0 - - libstdcxx-ng >=12 - - libutf8proc >=2.8.0,<3.0a0 - - openssl >=3.2.0,<4.0a0 - - re2 - license: Apache-2.0 - license_family: APACHE - size: 895232 - timestamp: 1706609674431 -- kind: conda - name: libarrow-gandiva - version: 14.0.2 - build: hb016d2e_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hb016d2e_13_cpu.conda - sha256: a82694957ba8209fa9eb7f5e26c4ad71a936fe3c963c133368c60da078267566 - md5: 677a678f1794a6a6c4efff894a5a92cb - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 h6bfc85a_13_cpu - - libgcc-ng >=12 - - libllvm15 >=15.0.7,<15.1.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libstdcxx-ng >=12 - - libutf8proc >=2.8.0,<3.0a0 - - openssl >=3.2.1,<4.0a0 - - re2 - license: Apache-2.0 - license_family: APACHE - size: 894432 - timestamp: 1710345503892 -- kind: conda - name: libarrow-gandiva - version: 14.0.2 - build: hcb01e45_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-hcb01e45_13_cpu.conda - sha256: 0d5764893b016216fada279215d7ac77d7791f1e724cb3d977538720e1ab3158 - md5: b01782c5a1e218bc257bb0a15fabd8b5 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hacb8726_3_cpu.conda + sha256: a2f62e378fd618ba4c7f554bb923d72677c70a6b07fe07c5daec5ad26038b912 + md5: 44be88e1cf0aa51576460d0f268820f6 depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 h2a83f13_13_cpu - - libre2-11 >=2023.9.1,<2024.0a0 + - libarrow 14.0.2 h84dd17c_3_cpu + - libgcc-ng >=12 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.6.2,<2024.0a0 + - libstdcxx-ng >=12 - libutf8proc >=2.8.0,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 + - openssl >=3.2.0,<4.0a0 - re2 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 license: Apache-2.0 license_family: APACHE - size: 10177269 - timestamp: 1710346223297 + size: 895232 + timestamp: 1706609674431 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -9864,29 +7504,6 @@ packages: license_family: APACHE size: 688245 timestamp: 1706610908126 -- kind: conda - name: libarrow-gandiva - version: 14.0.2 - build: hfef958d_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-gandiva-14.0.2-hfef958d_13_cpu.conda - sha256: 692521ca74dc6ce6de168a5ae1d1c11136b0541af5e2aab388deeb3c35e61a59 - md5: 28e850b27dd93367bb783d0d16d55afc - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 h5233fb5_13_cpu - - libcxx >=14 - - libllvm15 >=15.0.7,<15.1.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libutf8proc >=2.8.0,<3.0a0 - - openssl >=3.2.1,<4.0a0 - - re2 - license: Apache-2.0 - license_family: APACHE - size: 688483 - timestamp: 1710346205367 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -9966,46 +7583,6 @@ packages: license_family: APACHE size: 509163 timestamp: 1706609767216 -- kind: conda - name: libarrow-substrait - version: 14.0.2 - build: h757c851_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-14.0.2-h757c851_13_cpu.conda - sha256: e4e15042a93bc3a6e4e0717a2802c6859a5a9cafdcc8f49957f0948a249b2816 - md5: 15c79e6f7b9686ebff4d687a33a52a76 - depends: - - libarrow 14.0.2 h6bfc85a_13_cpu - - libarrow-acero 14.0.2 h59595ed_13_cpu - - libarrow-dataset 14.0.2 h59595ed_13_cpu - - libgcc-ng >=12 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libstdcxx-ng >=12 - license: Apache-2.0 - license_family: APACHE - size: 518209 - timestamp: 1710345660675 -- kind: conda - name: libarrow-substrait - version: 14.0.2 - build: h7e3fe20_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-h7e3fe20_13_cpu.conda - sha256: 4e27d6f673e8ef27d62d5c5a8bd00a8ae2b93d65c0b90373f2a5917479d6e68d - md5: c50111280b8d2f2c176d949e5c7ddfd1 - depends: - - __osx >=10.13 - - libarrow 14.0.2 he79e29d_13_cpu - - libarrow-acero 14.0.2 h000cb23_13_cpu - - libarrow-dataset 14.0.2 h000cb23_13_cpu - - libcxx >=14 - - libprotobuf >=4.25.3,<4.25.4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 454371 - timestamp: 1710347255673 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -10025,29 +7602,6 @@ packages: license_family: APACHE size: 472877 timestamp: 1706611234135 -- kind: conda - name: libarrow-substrait - version: 14.0.2 - build: h89268de_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-h89268de_13_cpu.conda - sha256: 816be5f4ac5ed5b35fcc3966b39314acbf9aef31e50162656b53d103560f002c - md5: c3599d0881c8f26df0900993f40f7c10 - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libarrow 14.0.2 h2a83f13_13_cpu - - libarrow-acero 14.0.2 h63175ca_13_cpu - - libarrow-dataset 14.0.2 h63175ca_13_cpu - - libprotobuf >=4.25.3,<4.25.4.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: APACHE - size: 361120 - timestamp: 1710346569221 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -10088,25 +7642,6 @@ packages: license_family: APACHE size: 503549 timestamp: 1710293136119 -- kind: conda - name: libarrow-substrait - version: 14.0.2 - build: hef52601_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-14.0.2-hef52601_13_cpu.conda - sha256: 3a9302c70f68e7b1fd433b5b0176b8317fb85ea840155c520ae012c619c5785c - md5: d5ac1ee4616a6caa87ba3f84b47e3de1 - depends: - - libarrow 14.0.2 h5233fb5_13_cpu - - libarrow-acero 14.0.2 h13dd4ca_13_cpu - - libarrow-dataset 14.0.2 h13dd4ca_13_cpu - - libcxx >=14 - - libprotobuf >=4.25.3,<4.25.4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 473073 - timestamp: 1710346607250 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -10734,23 +8269,6 @@ packages: license_family: BSD size: 5017024 timestamp: 1705980469944 -- kind: conda - name: libclang-cpp16 - version: 16.0.6 - build: default_h127d8a8_5 - build_number: 5 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp16-16.0.6-default_h127d8a8_5.conda - sha256: 8d034d92a7f7a9841796297bc18c2d8d8133583a6f3b661bfb1ca88ba01a076b - md5: 9fed40c47995a15eca939c4562d879bf - depends: - - libgcc-ng >=12 - - libllvm16 >=16.0.6,<16.1.0a0 - - libstdcxx-ng >=12 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 17942793 - timestamp: 1709764754399 - kind: conda name: libclang-cpp16 version: 16.0.6 @@ -10931,70 +8449,6 @@ packages: license_family: Apache size: 7164068 timestamp: 1704280614681 -- kind: conda - name: libclang13 - version: 18.1.1 - build: default_h0edc4dd_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libclang13-18.1.1-default_h0edc4dd_0.conda - sha256: 6706f35efe4f45bd50c56854e93715eb59bb948feb098aabd23923d5bbd409a7 - md5: badbda562ead0bcae661586067298002 - depends: - - libcxx >=16.0.6 - - libllvm18 >=18.1.1,<18.2.0a0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 8055181 - timestamp: 1710477023799 -- kind: conda - name: libclang13 - version: 18.1.1 - build: default_h5d6823c_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libclang13-18.1.1-default_h5d6823c_0.conda - sha256: eab9467b8e7bef6152af4ac2a167abab76f5453396f62755605cfa53eadafea7 - md5: 68ad4732fc951212bcc67e7d60de42e5 - depends: - - libgcc-ng >=12 - - libllvm18 >=18.1.1,<18.2.0a0 - - libstdcxx-ng >=12 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 11069471 - timestamp: 1710472508192 -- kind: conda - name: libclang13 - version: 18.1.1 - build: default_h83d0a53_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-18.1.1-default_h83d0a53_0.conda - sha256: a3e12d97d6f3a06b1375eca3057e12c262be568755236689efb076352eb84636 - md5: 591cdf454c3db0328daf524a5b6b15d0 - depends: - - libcxx >=16.0.6 - - libllvm18 >=18.1.1,<18.2.0a0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 7513624 - timestamp: 1710475008752 -- kind: conda - name: libclang13 - version: 18.1.1 - build: default_hf64faad_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libclang13-18.1.1-default_hf64faad_0.conda - sha256: 36dbad4abb730d6ba9904d60cac670c2b9d19bd11a5664db67b9c17660cef43a - md5: 2a7bf5472a4decbe0f800c84c384fb08 - depends: - - libzlib >=1.2.13,<1.3.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 25314400 - timestamp: 1710479378028 - kind: conda name: libclang13 version: 18.1.1 @@ -11528,64 +8982,6 @@ packages: license_family: MIT size: 72544 timestamp: 1710362309065 -- kind: conda - name: libexpat - version: 2.6.2 - build: h59595ed_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda - sha256: 331bb7c7c05025343ebd79f86ae612b9e1e74d2687b8f3179faec234f986ce19 - md5: e7ba12deb7020dd080c6c70e7b6f6a3d - depends: - - libgcc-ng >=12 - constrains: - - expat 2.6.2.* - license: MIT - license_family: MIT - size: 73730 - timestamp: 1710362120304 -- kind: conda - name: libexpat - version: 2.6.2 - build: h63175ca_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda - sha256: 79f612f75108f3e16bbdc127d4885bb74729cf66a8702fca0373dad89d40c4b7 - md5: bc592d03f62779511d392c175dcece64 - constrains: - - expat 2.6.2.* - license: MIT - license_family: MIT - size: 139224 - timestamp: 1710362609641 -- kind: conda - name: libexpat - version: 2.6.2 - build: h73e2aa4_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda - sha256: a188a77b275d61159a32ab547f7d17892226e7dac4518d2c6ac3ac8fc8dfde92 - md5: 3d1d51c8f716d97c864d12f7af329526 - constrains: - - expat 2.6.2.* - license: MIT - license_family: MIT - size: 69246 - timestamp: 1710362566073 -- kind: conda - name: libexpat - version: 2.6.2 - build: hebf3989_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda - sha256: ba7173ac30064ea901a4c9fb5a51846dcc25512ceb565759be7d18cbf3e5415e - md5: e3cde7cfa87f82f7cb13d482d5e0ad09 - constrains: - - expat 2.6.2.* - license: MIT - license_family: MIT - size: 63655 - timestamp: 1710362424980 - kind: conda name: libffi version: 3.4.2 @@ -12120,168 +9516,72 @@ packages: build: h23ec1f3_2 build_number: 2 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.21.0-h23ec1f3_2.conda - sha256: 8a991729c200f931537f3085dc3755a1bf26e5b4735816f55f0189bb4b6bf584 - md5: 7e987dc8d614e32cc62aad371db94ae5 - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libcurl >=8.5.0,<9.0a0 - - libcxx >=16 - - libgrpc >=1.61.1,<1.62.0a0 - - libprotobuf >=4.25.2,<4.25.3.0a0 - - openssl >=3.2.1,<4.0a0 - constrains: - - libgoogle-cloud 2.21.0 *_2 - license: Apache-2.0 - license_family: Apache - size: 839546 - timestamp: 1708639487970 -- kind: conda - name: libgoogle-cloud - version: 2.21.0 - build: h2b62511_2 - build_number: 2 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.21.0-h2b62511_2.conda - sha256: d7ad7f35aa5abdbcd9a3c576a23ed2fc1906b83aaf24acfafb768496a0330f41 - md5: 73c00d021383065be34ed4d7efc2c94c - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libcurl >=8.5.0,<9.0a0 - - libgrpc >=1.61.1,<1.62.0a0 - - libprotobuf >=4.25.2,<4.25.3.0a0 - - openssl >=3.2.1,<4.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - libgoogle-cloud 2.21.0 *_2 - license: Apache-2.0 - license_family: Apache - size: 14562 - timestamp: 1708637250255 -- kind: conda - name: libgoogle-cloud - version: 2.21.0 - build: h72bcb37_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.21.0-h72bcb37_2.conda - sha256: 055f17ab4621fbcbe68c0656b4811c1a18d8e564fb10287024c67c8d244e7771 - md5: 14b15b923b9e45038f4193d06ecf5ae1 - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libcurl >=8.5.0,<9.0a0 - - libgcc-ng >=12 - - libgrpc >=1.61.1,<1.62.0a0 - - libprotobuf >=4.25.2,<4.25.3.0a0 - - libstdcxx-ng >=12 - - openssl >=3.2.1,<4.0a0 - constrains: - - libgoogle-cloud 2.21.0 *_2 - license: Apache-2.0 - license_family: Apache - size: 1209079 - timestamp: 1708638321316 -- kind: conda - name: libgoogle-cloud - version: 2.22.0 - build: h651e89d_1 - build_number: 1 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.22.0-h651e89d_1.conda - sha256: 39f2f50202e50e41ee8581c99a0b3023c2c21cab80ba597f8c5be7c8c8c6a059 - md5: 3f2faf53ecb3b51b92b3eee155b50233 - depends: - - __osx >=10.13 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libcurl >=8.5.0,<9.0a0 - - libcxx >=16 - - libgrpc >=1.62.0,<1.63.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - openssl >=3.2.1,<4.0a0 - constrains: - - libgoogle-cloud 2.22.0 *_1 - license: Apache-2.0 - license_family: Apache - size: 849198 - timestamp: 1709738549021 -- kind: conda - name: libgoogle-cloud - version: 2.22.0 - build: h9be4e54_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.22.0-h9be4e54_1.conda - sha256: b9980209438b22113f4352df2b260bf43b2eb63a7b6325192ec5ae3a562872ed - md5: 4b4e36a91e7dabf7345b82d85767a7c3 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.21.0-h23ec1f3_2.conda + sha256: 8a991729c200f931537f3085dc3755a1bf26e5b4735816f55f0189bb4b6bf584 + md5: 7e987dc8d614e32cc62aad371db94ae5 depends: - libabseil * cxx17* - libabseil >=20240116.1,<20240117.0a0 - libcurl >=8.5.0,<9.0a0 - - libgcc-ng >=12 - - libgrpc >=1.62.0,<1.63.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libstdcxx-ng >=12 + - libcxx >=16 + - libgrpc >=1.61.1,<1.62.0a0 + - libprotobuf >=4.25.2,<4.25.3.0a0 - openssl >=3.2.1,<4.0a0 constrains: - - libgoogle-cloud 2.22.0 *_1 + - libgoogle-cloud 2.21.0 *_2 license: Apache-2.0 license_family: Apache - size: 1209816 - timestamp: 1709737846418 + size: 839546 + timestamp: 1708639487970 - kind: conda name: libgoogle-cloud - version: 2.22.0 - build: h9cad5c0_1 - build_number: 1 + version: 2.21.0 + build: h2b62511_2 + build_number: 2 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.22.0-h9cad5c0_1.conda - sha256: f76e892d13e1db405777c968787678d8ba912b7e4eef7f950fcdcca185e06e71 - md5: 63cd44a71f00d4e72844bf0e8be56be4 + url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.21.0-h2b62511_2.conda + sha256: d7ad7f35aa5abdbcd9a3c576a23ed2fc1906b83aaf24acfafb768496a0330f41 + md5: 73c00d021383065be34ed4d7efc2c94c depends: - libabseil * cxx17* - libabseil >=20240116.1,<20240117.0a0 - libcurl >=8.5.0,<9.0a0 - - libgrpc >=1.62.0,<1.63.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 + - libgrpc >=1.61.1,<1.62.0a0 + - libprotobuf >=4.25.2,<4.25.3.0a0 - openssl >=3.2.1,<4.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 constrains: - - libgoogle-cloud 2.22.0 *_1 + - libgoogle-cloud 2.21.0 *_2 license: Apache-2.0 license_family: Apache - size: 14420 - timestamp: 1709737037941 + size: 14562 + timestamp: 1708637250255 - kind: conda name: libgoogle-cloud - version: 2.22.0 - build: hbebe991_1 - build_number: 1 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.22.0-hbebe991_1.conda - sha256: a114b4d46eebede7e514abaf9203ea8c952a6382c5c57d1b989da062e3899bd7 - md5: ec7ea95b08e8cbc39fa16b6eafee36e6 + version: 2.21.0 + build: h72bcb37_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.21.0-h72bcb37_2.conda + sha256: 055f17ab4621fbcbe68c0656b4811c1a18d8e564fb10287024c67c8d244e7771 + md5: 14b15b923b9e45038f4193d06ecf5ae1 depends: - libabseil * cxx17* - libabseil >=20240116.1,<20240117.0a0 - libcurl >=8.5.0,<9.0a0 - - libcxx >=16 - - libgrpc >=1.62.0,<1.63.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 + - libgcc-ng >=12 + - libgrpc >=1.61.1,<1.62.0a0 + - libprotobuf >=4.25.2,<4.25.3.0a0 + - libstdcxx-ng >=12 - openssl >=3.2.1,<4.0a0 constrains: - - libgoogle-cloud 2.22.0 *_1 + - libgoogle-cloud 2.21.0 *_2 license: Apache-2.0 license_family: Apache - size: 836916 - timestamp: 1709739767863 + size: 1209079 + timestamp: 1708638321316 - kind: conda name: libgoogle-cloud version: 2.22.0 @@ -12393,93 +9693,6 @@ packages: license_family: Apache size: 749865 timestamp: 1708638542903 -- kind: conda - name: libgoogle-cloud-storage - version: 2.22.0 - build: h8a76758_1 - build_number: 1 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-2.22.0-h8a76758_1.conda - sha256: e23be5896fd78e0e8b1098aab8803192f0c4a328d3d30a57d20d80194045d793 - md5: a89fb5b36b08efaae128d4933e593315 - depends: - - libabseil - - libcrc32c >=1.1.2,<1.2.0a0 - - libcurl - - libcxx >=16 - - libgoogle-cloud 2.22.0 hbebe991_1 - - libzlib >=1.2.13,<1.3.0a0 - - openssl - license: Apache-2.0 - license_family: Apache - size: 507478 - timestamp: 1709740510222 -- kind: conda - name: libgoogle-cloud-storage - version: 2.22.0 - build: ha67e85c_1 - build_number: 1 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.22.0-ha67e85c_1.conda - sha256: e4f351e55fe7c0656cb608eba8690063e3b407d25a855c9d1fd832486d4a1244 - md5: 0c25180c34b1a58d309b28386698fb6e - depends: - - libabseil - - libcrc32c >=1.1.2,<1.2.0a0 - - libcurl - - libcxx >=16 - - libgoogle-cloud 2.22.0 h651e89d_1 - - libzlib >=1.2.13,<1.3.0a0 - - openssl - license: Apache-2.0 - license_family: Apache - size: 523045 - timestamp: 1709739227970 -- kind: conda - name: libgoogle-cloud-storage - version: 2.22.0 - build: hb581fae_1 - build_number: 1 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.22.0-hb581fae_1.conda - sha256: 5ee34f168948211db14874f521e6edf9b4032d533c61fd429caaa282be1d0e7b - md5: f63348292dea55cf834e631cf26e2669 - depends: - - libabseil - - libcrc32c >=1.1.2,<1.2.0a0 - - libcurl - - libgoogle-cloud 2.22.0 h9cad5c0_1 - - libzlib >=1.2.13,<1.3.0a0 - - openssl - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: Apache - size: 14330 - timestamp: 1709737542249 -- kind: conda - name: libgoogle-cloud-storage - version: 2.22.0 - build: hc7a4891_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.22.0-hc7a4891_1.conda - sha256: 0e00e1ca2a981db1c96071edf266bc29fd6f13ac484225de1736fc4dac5c64a8 - md5: 7811f043944e010e54640918ea82cecd - depends: - - libabseil - - libcrc32c >=1.1.2,<1.2.0a0 - - libcurl - - libgcc-ng >=12 - - libgoogle-cloud 2.22.0 h9be4e54_1 - - libstdcxx-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 - - openssl - license: Apache-2.0 - license_family: Apache - size: 748818 - timestamp: 1709738181078 - kind: conda name: libgoogle-cloud-storage version: 2.22.0 @@ -12685,82 +9898,6 @@ packages: license_family: APACHE size: 4975767 timestamp: 1707807808364 -- kind: conda - name: libgrpc - version: 1.62.1 - build: h15f2491_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.62.1-h15f2491_0.conda - sha256: 1d4ece94dfef73d904dcba0fd9d56098796f5fdc62ea5f9edff60c71be7a3d63 - md5: 564517a8cbd095cff75eb996d33d2b7e - depends: - - c-ares >=1.27.0,<2.0a0 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libgcc-ng >=12 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libstdcxx-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - - re2 - constrains: - - grpc-cpp =1.62.1 - license: Apache-2.0 - license_family: APACHE - size: 7667664 - timestamp: 1709938059287 -- kind: conda - name: libgrpc - version: 1.62.1 - build: h384b2fc_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.1-h384b2fc_0.conda - sha256: 8c9898d259e2343df52259b599ec342c386679e1c420df603cba6f06078fcdd6 - md5: 2ac05daca7276a4d6ca4465707670380 - depends: - - __osx >=10.13 - - c-ares >=1.27.0,<2.0a0 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libcxx >=16 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - - re2 - constrains: - - grpc-cpp =1.62.1 - license: Apache-2.0 - license_family: APACHE - size: 4432823 - timestamp: 1709938959215 -- kind: conda - name: libgrpc - version: 1.62.1 - build: h5273850_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.62.1-h5273850_0.conda - sha256: 338cb58d1095ee651acd168af9636834b41908f7a94e613088e284dc53d2947c - md5: 99ac2f772591801641ec692fee843796 - depends: - - c-ares >=1.27.0,<2.0a0 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - - re2 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - grpc-cpp =1.62.1 - license: Apache-2.0 - license_family: APACHE - size: 15963245 - timestamp: 1709939262816 - kind: conda name: libgrpc version: 1.62.1 @@ -12786,30 +9923,6 @@ packages: license_family: APACHE size: 6820015 timestamp: 1709938779780 -- kind: conda - name: libgrpc - version: 1.62.1 - build: h9c18a4f_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.62.1-h9c18a4f_0.conda - sha256: b8c6b48430d0778e9452df88fa7c07fc7828aac87291372ac42dbe78be4078d5 - md5: 24f15c1a9e111825d39bf77881430107 - depends: - - c-ares >=1.27.0,<2.0a0 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libcxx >=16 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libre2-11 >=2023.9.1,<2024.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - - re2 - constrains: - - grpc-cpp =1.62.1 - license: Apache-2.0 - license_family: APACHE - size: 4753906 - timestamp: 1709939281511 - kind: conda name: libhwloc version: 2.9.3 @@ -13501,58 +10614,6 @@ packages: license_family: Apache size: 26306756 timestamp: 1701378823527 -- kind: conda - name: libllvm18 - version: 18.1.1 - build: h2448989_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.1-h2448989_0.conda - sha256: 4501e62ee42644f158b2273e6cef621c2bac148ebe729fb3ca10b337df83fa3a - md5: a77e3c2c568b3b5d8a79b158d0c5dd47 - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - libxml2 >=2.12.5,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 38392079 - timestamp: 1710432419352 -- kind: conda - name: libllvm18 - version: 18.1.1 - build: h30cc82d_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.1-h30cc82d_0.conda - sha256: 35f2fbe7f87c9fda6f36c0ee8efc5b99c347a2f7a0d4bca3d0511b612773a30d - md5: a215b38429566e17aa4d9dba24680d0d - depends: - - libcxx >=16 - - libxml2 >=2.12.5,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 25777635 - timestamp: 1710434884978 -- kind: conda - name: libllvm18 - version: 18.1.1 - build: hbcf5fad_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.1-hbcf5fad_0.conda - sha256: d5f0042e48091740f7084d390a4948b2a739acbc4045f852f7561c0597e1a078 - md5: 9cfc7fa4bdbf1f0558f053285b4b6afb - depends: - - libcxx >=16 - - libxml2 >=2.12.5,<3.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 27599082 - timestamp: 1710435070093 - kind: conda name: libllvm18 version: 18.1.1 @@ -13876,25 +10937,6 @@ packages: license_family: APACHE size: 1158188 timestamp: 1708689889111 -- kind: conda - name: libparquet - version: 14.0.2 - build: h352af49_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libparquet-14.0.2-h352af49_13_cpu.conda - sha256: 3675da7fee45dfe0f053bbcb71b5dc32c58eba86eb04dd5e7dbd2e3f5b076edb - md5: 0c4ee07d6a56434b8e1abfdce42ffe9a - depends: - - libarrow 14.0.2 h6bfc85a_13_cpu - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - libthrift >=0.19.0,<0.19.1.0a0 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 1160002 - timestamp: 1710345544372 - kind: conda name: libparquet version: 14.0.2 @@ -13932,24 +10974,6 @@ packages: license_family: APACHE size: 925350 timestamp: 1708690516278 -- kind: conda - name: libparquet - version: 14.0.2 - build: h381d950_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h381d950_13_cpu.conda - sha256: e1227a121d942be15d02ec1fde3e43f2a17e5c5a37ed006e5382977d355a3294 - md5: 273a1178373fffd8d76a8e813699297e - depends: - - libarrow 14.0.2 he79e29d_13_cpu - - libcxx >=14 - - libthrift >=0.19.0,<0.19.1.0a0 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 924906 - timestamp: 1710346971895 - kind: conda name: libparquet version: 14.0.2 @@ -13978,27 +11002,7 @@ packages: sha256: 6151bbb6ad607291234f1d1ecae0055f17bf0479984edec037a591235199ea50 md5: 6a9d9de2a251e42522463dc576381e3e depends: - - libarrow 14.0.2 hd01637b_10_cpu - - libthrift >=0.19.0,<0.19.1.0a0 - - openssl >=3.2.1,<4.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Apache-2.0 - license_family: APACHE - size: 783467 - timestamp: 1708690358780 -- kind: conda - name: libparquet - version: 14.0.2 - build: h7ec3a38_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h7ec3a38_13_cpu.conda - sha256: d59b700882bbe39cb387151638bb0becbbb04c86a668426867fb32bad8a37d82 - md5: babba3c50f817f425964de492844a521 - depends: - - libarrow 14.0.2 h2a83f13_13_cpu + - libarrow 14.0.2 hd01637b_10_cpu - libthrift >=0.19.0,<0.19.1.0a0 - openssl >=3.2.1,<4.0a0 - ucrt >=10.0.20348.0 @@ -14006,8 +11010,8 @@ packages: - vc14_runtime >=14.29.30139 license: Apache-2.0 license_family: APACHE - size: 782893 - timestamp: 1710346323580 + size: 783467 + timestamp: 1708690358780 - kind: conda name: libparquet version: 14.0.2 @@ -14045,24 +11049,6 @@ packages: license_family: APACHE size: 910129 timestamp: 1708691448291 -- kind: conda - name: libparquet - version: 14.0.2 - build: hf6ce1d5_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-14.0.2-hf6ce1d5_13_cpu.conda - sha256: f265cc71bb623ce3fef0a681a4744d35562e1ae9a8ed23707cf0d629dc2763ff - md5: 9451897b618c5007a9adc5d9b4ebb0e2 - depends: - - libarrow 14.0.2 h5233fb5_13_cpu - - libcxx >=14 - - libthrift >=0.19.0,<0.19.1.0a0 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: APACHE - size: 909954 - timestamp: 1710346299150 - kind: conda name: libparquet version: 14.0.2 @@ -14218,61 +11204,6 @@ packages: license_family: BSD size: 2163244 timestamp: 1708436969402 -- kind: conda - name: libprotobuf - version: 4.25.3 - build: h08a7969_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.25.3-h08a7969_0.conda - sha256: 70e0eef046033af2e8d21251a785563ad738ed5281c74e21c31c457780845dcd - md5: 6945825cebd2aeb16af4c69d97c32c13 - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 - license: BSD-3-Clause - license_family: BSD - size: 2811207 - timestamp: 1709514552541 -- kind: conda - name: libprotobuf - version: 4.25.3 - build: h4e4d658_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-h4e4d658_0.conda - sha256: 3f126769fb5820387d436370ad48600e05d038a28689fdf9988b64e1059947a8 - md5: 57b7ee4f1fd8573781cfdabaec4a7782 - depends: - - __osx >=10.13 - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libcxx >=16 - - libzlib >=1.2.13,<1.3.0a0 - license: BSD-3-Clause - license_family: BSD - size: 2216001 - timestamp: 1709514908146 -- kind: conda - name: libprotobuf - version: 4.25.3 - build: h503648d_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.3-h503648d_0.conda - sha256: 5d4c5592be3994657ebf47e52f26b734cc50b0ea9db007d920e2e31762aac216 - md5: 4da7de0ba35777742edf67bf7a1075df - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: BSD-3-Clause - license_family: BSD - size: 5650604 - timestamp: 1709514804631 - kind: conda name: libprotobuf version: 4.25.3 @@ -14291,23 +11222,6 @@ packages: license_family: BSD size: 2576197 timestamp: 1709513627963 -- kind: conda - name: libprotobuf - version: 4.25.3 - build: hbfab5d5_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-4.25.3-hbfab5d5_0.conda - sha256: d754519abc3ddbdedab2a38d0639170f5347c1573eef80c707f3a8dc5dff706a - md5: 5f70b2b945a9741cba7e6dfe735a02a7 - depends: - - libabseil * cxx17* - - libabseil >=20240116.1,<20240117.0a0 - - libcxx >=16 - - libzlib >=1.2.13,<1.3.0a0 - license: BSD-3-Clause - license_family: BSD - size: 2154402 - timestamp: 1709514097574 - kind: conda name: libre2-11 version: 2023.06.02 @@ -14536,19 +11450,6 @@ packages: license: Unlicense size: 870045 timestamp: 1707495642340 -- kind: conda - name: libsqlite - version: 3.45.2 - build: h091b4b1_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda - sha256: 7c234320a1a2132b9cc972aaa06bb215bb220a5b1addb0bed7a5a321c805920e - md5: 9d07427ee5bd9afd1e11ce14368a48d6 - depends: - - libzlib >=1.2.13,<1.3.0a0 - license: Unlicense - size: 825300 - timestamp: 1710255078823 - kind: conda name: libsqlite version: 3.45.2 @@ -14563,48 +11464,6 @@ packages: license: Unlicense size: 1038462 timestamp: 1710253998432 -- kind: conda - name: libsqlite - version: 3.45.2 - build: h2797004_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda - sha256: 8cdbeb7902729e319510a82d7c642402981818702b58812af265ef55d1315473 - md5: 866983a220e27a80cb75e85cb30466a1 - depends: - - libgcc-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 - license: Unlicense - size: 857489 - timestamp: 1710254744982 -- kind: conda - name: libsqlite - version: 3.45.2 - build: h92b6c6a_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda - sha256: 320ec73a4e3dd377757a2595770b8137ec4583df4d7782472d76377cdbdc4543 - md5: 086f56e13a96a6cfb1bf640505ae6b70 - depends: - - libzlib >=1.2.13,<1.3.0a0 - license: Unlicense - size: 902355 - timestamp: 1710254991672 -- kind: conda - name: libsqlite - version: 3.45.2 - build: hcfcfb64_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda - sha256: 4bb24b986550275a6d02835150d943c4c675808d05c0efc5c2a22154d007a69f - md5: f95359f8dc5abf7da7776ece9ef10bc5 - depends: - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: Unlicense - size: 869606 - timestamp: 1710255095740 - kind: conda name: libssh2 version: 1.11.0 @@ -14999,46 +11858,6 @@ packages: license_family: MIT size: 893348 timestamp: 1693539405436 -- kind: conda - name: libuv - version: 1.47.0 - build: h67532ce_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.47.0-h67532ce_0.conda - sha256: a452b8fbb906e72d6c633ed133413f6a604471597f4c80dc73b4e81d2ef56b32 - md5: c2c8307836ecebc2799400a4eca27b37 - license: MIT - license_family: MIT - size: 404907 - timestamp: 1707450430194 -- kind: conda - name: libuv - version: 1.47.0 - build: h93a5062_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.47.0-h93a5062_0.conda - sha256: 802da3ad57041480f15fe0581d6fcd421d9cdae17d796d2b126b0a12aa2d3d44 - md5: b586a09ba87849e37634cbaf9ea0e60f - license: MIT - license_family: MIT - size: 404350 - timestamp: 1707450365805 -- kind: conda - name: libuv - version: 1.48.0 - build: hcfcfb64_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda - sha256: 6151c51857c2407139ce22fdc956022353e675b2bc96991a9201d51cceaa90b4 - md5: 485e49e1d500d996844df14cabf64d73 - depends: - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: MIT - license_family: MIT - size: 289753 - timestamp: 1709913743184 - kind: conda name: libxcrypt version: 4.4.36 @@ -15556,24 +12375,6 @@ packages: license: MIT, BSD size: 31928 timestamp: 1608166099896 -- kind: conda - name: markdown-it-py - version: 3.0.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - sha256: c041b0eaf7a6af3344d5dd452815cdc148d6284fec25a4fa3f4263b3a021e962 - md5: 93a8e71256479c62074356ef6ebf501b - depends: - - mdurl >=0.1,<1 - - python >=3.8 - license: MIT - license_family: MIT - purls: - - pkg:pypi/markdown-it-py - size: 64356 - timestamp: 1686175179621 - kind: conda name: markdown-it-py version: 3.0.0 @@ -15911,23 +12712,6 @@ packages: license_family: MIT size: 11969071 timestamp: 1703184938293 -- kind: conda - name: mypy_extensions - version: 1.0.0 - build: pyha770c72_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - sha256: f240217476e148e825420c6bc3a0c0efb08c0718b7042fae960400c02af858a3 - md5: 4eccaeba205f0aed9ac3a9ea58568ca3 - depends: - - python >=3.5 - license: MIT - license_family: MIT - purls: - - pkg:pypi/mypy-extensions - size: 10492 - timestamp: 1675543414256 - kind: conda name: mypy_extensions version: 1.0.0 @@ -16197,79 +12981,6 @@ packages: license_family: MIT size: 15614862 timestamp: 1700389549489 -- kind: conda - name: nodejs - version: 18.19.0 - build: h119ffd7_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.19.0-h119ffd7_0.conda - sha256: 896ca8a8683f7d6c3402364f6d28bd00b9d3cb9acb88c85d2fc9ecefbbf4f7db - md5: 022ff05e89afedc3db2decb77a8af207 - depends: - - icu >=73.2,<74.0a0 - - libcxx >=14 - - libuv >=1.47.0,<1.48.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - - zlib - constrains: - - __osx >=10.15 - license: MIT - license_family: MIT - size: 11439181 - timestamp: 1707771884027 -- kind: conda - name: nodejs - version: 18.19.0 - build: h57928b3_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.19.0-h57928b3_0.conda - sha256: de01dd21f413e0e230b62082d5ee7f25b19b3c7296e1172c7cef94c9d36b8c38 - md5: 41ce77dc534e5bc71b0fc1687a89dcfd - license: MIT - license_family: MIT - size: 22479049 - timestamp: 1707403072267 -- kind: conda - name: nodejs - version: 18.19.0 - build: h5f47a4d_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.19.0-h5f47a4d_0.conda - sha256: 1263d3c8aa9adaf4e11616dc05fb28cfdb761d70f2298959728f847688073240 - md5: 7798b881265f448c752fbae08e221b10 - depends: - - icu >=73.2,<74.0a0 - - libcxx >=14 - - libuv >=1.47.0,<1.48.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - - zlib - license: MIT - license_family: MIT - size: 10879191 - timestamp: 1707778803050 -- kind: conda - name: nodejs - version: 18.19.0 - build: hb753e55_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.19.0-hb753e55_0.conda - sha256: d233fe4da686125c2b89d588349eccc78cdcb5a75a2b5b5bc9dc4d0c8c23eda1 - md5: 0b4a67051e3b3812818ccf2f4ee2fd4e - depends: - - __glibc >=2.17,<3.0.a0 - - icu >=73.2,<74.0a0 - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - libuv >=1.46.0,<1.47.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.2.1,<4.0a0 - - zlib - license: MIT - license_family: MIT - size: 15917143 - timestamp: 1707407233064 - kind: conda name: nodejs version: 18.19.0 @@ -16663,63 +13374,6 @@ packages: license_family: Apache size: 423917 timestamp: 1700373043647 -- kind: conda - name: orc - version: 2.0.0 - build: h1e5e2c1_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/orc-2.0.0-h1e5e2c1_0.conda - sha256: ed8cfe1f35e8ef703e540e7731e77fade1410bba406e17727a10dee08c37d5b4 - md5: 53e8f030579d34e1a36a735d527c021f - depends: - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - lz4-c >=1.9.3,<1.10.0a0 - - snappy >=1.1.10,<2.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 - license_family: Apache - size: 1028974 - timestamp: 1710232781925 -- kind: conda - name: orc - version: 2.0.0 - build: h3d3088e_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.0.0-h3d3088e_0.conda - sha256: 6a1f553e2ea3d2df3c465b02c7ece5c001cc2d3afb1fe7e2678a7ff7a5a14168 - md5: a8e452c3f2b6fecfd86e8f2b72450a9b - depends: - - libcxx >=16 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - lz4-c >=1.9.3,<1.10.0a0 - - snappy >=1.1.10,<2.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 - license_family: Apache - size: 413922 - timestamp: 1710233361620 -- kind: conda - name: orc - version: 2.0.0 - build: h6c6cd50_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.0-h6c6cd50_0.conda - sha256: 0c198b6a8de238d53002e7c03e4b1e94e769cf388adac2717fdaadfee9381a14 - md5: 5ce58b9a5679fe6640d6d68228099ce9 - depends: - - __osx >=10.13 - - libcxx >=16 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - lz4-c >=1.9.3,<1.10.0a0 - - snappy >=1.1.10,<2.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 - license_family: Apache - size: 433224 - timestamp: 1710233383447 - kind: conda name: orc version: 2.0.0 @@ -16727,40 +13381,19 @@ packages: subdir: linux-aarch64 url: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-h75d905f_0.conda sha256: 32c843b4ce01d29ed04e81ea5c20d78051d47091c6a27b9f6e1eb7c428983b01 - md5: 7fb160bb1300a3043fec7e40d50e9aa6 - depends: - - libgcc-ng >=12 - - libprotobuf >=4.25.3,<4.25.4.0a0 - - libstdcxx-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 - - lz4-c >=1.9.3,<1.10.0a0 - - snappy >=1.1.10,<2.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 - license_family: Apache - size: 999580 - timestamp: 1710232876736 -- kind: conda - name: orc - version: 2.0.0 - build: heb0c069_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/orc-2.0.0-heb0c069_0.conda - sha256: 5a9c0904f38e5c2e1d1494bd192ff98fca13ca07ed1590497b16a801bef497a0 - md5: 2733034196c084cdc07e0facfea995ea + md5: 7fb160bb1300a3043fec7e40d50e9aa6 depends: + - libgcc-ng >=12 - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - snappy >=1.1.10,<2.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - zstd >=1.5.5,<1.6.0a0 license: Apache-2.0 license_family: Apache - size: 953672 - timestamp: 1710233287310 + size: 999580 + timestamp: 1710232876736 - kind: conda name: packaging version: '23.2' @@ -17202,35 +13835,6 @@ packages: license_family: APACHE size: 4524767 timestamp: 1708692350829 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311h39c9aba_13_cpu - build_number: 13 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_13_cpu.conda - sha256: 2eef5e752f71b9a2f74491e0f9d3c9e58761f179f8198cb8d710627ca3e9a13d - md5: e95c99f69395f1a43582de9b0d35a553 - depends: - - libarrow 14.0.2 h6bfc85a_13_cpu - - libarrow-acero 14.0.2 h59595ed_13_cpu - - libarrow-dataset 14.0.2 h59595ed_13_cpu - - libarrow-flight 14.0.2 hc6145d9_13_cpu - - libarrow-flight-sql 14.0.2 h757c851_13_cpu - - libarrow-gandiva 14.0.2 hb016d2e_13_cpu - - libarrow-substrait 14.0.2 h757c851_13_cpu - - libgcc-ng >=12 - - libparquet 14.0.2 h352af49_13_cpu - - libstdcxx-ng >=12 - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - license_family: APACHE - size: 4543451 - timestamp: 1710347598355 - kind: conda name: pyarrow version: 14.0.2 @@ -17288,34 +13892,6 @@ packages: license_family: APACHE size: 4009410 timestamp: 1708691836141 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311h54e7ce8_13_cpu - build_number: 13 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_13_cpu.conda - sha256: 543f8b4e7cc6453b64b0dd20b43ac312cc61fe28e10869f04edf5ee29214ce13 - md5: 9b4945755f71df2d66e2e9af881b4b0c - depends: - - libarrow 14.0.2 he79e29d_13_cpu - - libarrow-acero 14.0.2 h000cb23_13_cpu - - libarrow-dataset 14.0.2 h000cb23_13_cpu - - libarrow-flight 14.0.2 h2382776_13_cpu - - libarrow-flight-sql 14.0.2 h7e3fe20_13_cpu - - libarrow-gandiva 14.0.2 ha5acb15_13_cpu - - libarrow-substrait 14.0.2 h7e3fe20_13_cpu - - libcxx >=14 - - libparquet 14.0.2 h381d950_13_cpu - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - license_family: APACHE - size: 4020354 - timestamp: 1710348158705 - kind: conda name: pyarrow version: 14.0.2 @@ -17374,36 +13950,6 @@ packages: license_family: APACHE size: 3465525 timestamp: 1708693288111 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311h6a6099b_13_cpu - build_number: 13 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_13_cpu.conda - sha256: 76d0f17e140cb3f22adefe568fa6fb5b0eaec250dc22306d4da21b8ce5869260 - md5: b22193a1d8c2d28f6c3dbb94da33147d - depends: - - libarrow 14.0.2 h2a83f13_13_cpu - - libarrow-acero 14.0.2 h63175ca_13_cpu - - libarrow-dataset 14.0.2 h63175ca_13_cpu - - libarrow-flight 14.0.2 h02312f3_13_cpu - - libarrow-flight-sql 14.0.2 h55b4db4_13_cpu - - libarrow-gandiva 14.0.2 hcb01e45_13_cpu - - libarrow-substrait 14.0.2 h89268de_13_cpu - - libparquet 14.0.2 h7ec3a38_13_cpu - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - license_family: APACHE - size: 3470330 - timestamp: 1710349686722 - kind: conda name: pyarrow version: 14.0.2 @@ -17433,35 +13979,6 @@ packages: license_family: APACHE size: 4094429 timestamp: 1708693258443 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311hd7bc329_13_cpu - build_number: 13 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_13_cpu.conda - sha256: 077d688f4c748f99760d7b8555c6ecf0c071381d2978032316d0c50389a083a0 - md5: fdd086b17f9ae33004bdd1991ccb1321 - depends: - - libarrow 14.0.2 h5233fb5_13_cpu - - libarrow-acero 14.0.2 h13dd4ca_13_cpu - - libarrow-dataset 14.0.2 h13dd4ca_13_cpu - - libarrow-flight 14.0.2 h95ca633_13_cpu - - libarrow-flight-sql 14.0.2 hdc5392b_13_cpu - - libarrow-gandiva 14.0.2 hfef958d_13_cpu - - libarrow-substrait 14.0.2 hef52601_13_cpu - - libcxx >=14 - - libparquet 14.0.2 hf6ce1d5_13_cpu - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - license_family: APACHE - size: 4084630 - timestamp: 1710348774061 - kind: conda name: pyarrow version: 14.0.2 @@ -17868,24 +14385,6 @@ packages: license_family: BSD size: 4724921 timestamp: 1706524445013 -- kind: conda - name: rdma-core - version: '50.0' - build: hd3aeb46_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-50.0-hd3aeb46_1.conda - sha256: 85e38508eb4921e53cf1cb97435f9c9408ea2ddc582c6588ec50f3f3ec3abdc0 - md5: f462219598fcf46c0cdfb985c3482b4f - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc-ng >=12 - - libnl >=3.9.0,<4.0a0 - - libstdcxx-ng >=12 - license: Linux-OpenIB - license_family: BSD - size: 4713842 - timestamp: 1710157799992 - kind: conda name: re2 version: 2023.06.02 @@ -18320,38 +14819,6 @@ packages: license_family: Apache size: 333810 timestamp: 1708664562153 -- kind: conda - name: s2n - version: 1.4.6 - build: h06160fa_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.6-h06160fa_0.conda - sha256: 2d03e27d607e3b797ada1ab805deebdd321c3ec99c1581188ac22041c06fd7b6 - md5: 88350a8ea5a9aa734b8b553bfd2ff78c - depends: - - libgcc-ng >=12 - - openssl >=3.2.1,<4.0a0 - license: Apache-2.0 - license_family: Apache - size: 339401 - timestamp: 1709937040957 -- kind: conda - name: semver - version: 2.13.0 - build: pyh9f0ad1d_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - sha256: 673ef5ef04cef60c3584b1d9b81024646b9d9a4c50749356c7ba5cede755e61d - md5: 2cab9f3a9683cb40a2176ccaf76e66c6 - depends: - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/semver - size: 15712 - timestamp: 1603697876069 - kind: conda name: semver version: 2.13.0 @@ -18452,23 +14919,6 @@ packages: license_family: MIT size: 213817 timestamp: 1643442169866 -- kind: conda - name: smmap - version: 5.0.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - sha256: 23011cb3e064525bdb8787c75126a2e78d2344a72cd6773922006d1da1f2af16 - md5: 62f26a3d1387acee31322208f0cfa3e0 - depends: - - python >=3.5 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/smmap - size: 22483 - timestamp: 1634310465482 - kind: conda name: smmap version: 5.0.0 @@ -18608,57 +15058,81 @@ packages: timestamp: 1602687595316 - kind: conda name: taplo - version: 0.8.1 - build: h69fbcac_0 + version: 0.9.1 + build: h16c8c8b_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.8.1-h69fbcac_0.conda - sha256: 5a46bbdac42c2aa1d59f3f7f61aa92eaed5f6936b01de4f3519f5ad40374973f - md5: 268425eeb6db286378bb05f69331feea + url: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda + sha256: 3a387ea7779d061d28af0426d1249fe81f798f35a2d0cb979a6ff84525187667 + md5: 8171587b7a366dbbaab309ae1c45bd93 + depends: + - openssl >=3.2.1,<4.0a0 + constrains: + - __osx >=11.0 license: MIT license_family: MIT - size: 3339855 - timestamp: 1689048706766 + size: 3560280 + timestamp: 1710793219601 - kind: conda name: taplo - version: 0.8.1 - build: h7205ca4_0 + version: 0.9.1 + build: h1ff36dd_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda + sha256: 82b3528f63ae71e0158fdbf8b66e66f619cb70584c471f3d89a2ee6fd44ef20b + md5: 29207c9b716932300221e5acd0b310f7 + depends: + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: MIT + license_family: MIT + size: 3877123 + timestamp: 1710792099600 +- kind: conda + name: taplo + version: 0.9.1 + build: h236d3af_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.8.1-h7205ca4_0.conda - sha256: 493b5f8db450f37e8bb50fdfd02c06499c18391c806d2220e65ac801f6b7c2f0 - md5: 8e99d4b2850401094fe7c83273d3c4e8 + url: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda + sha256: 3e9032084b3f8d686b15f67500323ae2cae5637dc427b309b661a30026d8f00c + md5: 02c8d9c54b2887c5456fb7a0ecec62f3 + depends: + - openssl >=3.2.1,<4.0a0 + constrains: + - __osx >=10.12 license: MIT license_family: MIT - size: 3446470 - timestamp: 1689048461323 + size: 3773670 + timestamp: 1710793055293 - kind: conda name: taplo - version: 0.8.1 + version: 0.9.1 build: h7f3b576_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/taplo-0.8.1-h7f3b576_0.conda - sha256: 4f0ddb3c2942ff9b2d627de9093075df30f28f64bf71520710c031cb7fff8d9d - md5: 2041cd474504dd82b83aa58ccec82a78 + url: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda + sha256: 7ef6b5f23fd749fde17628793e4e76e36395b9645a3d3b8b0fa5a4d9b2b9ccfb + md5: 0a798b7bf999885c00e40fcb0cfe7136 depends: - m2w64-gcc-libs - m2w64-gcc-libs-core license: MIT license_family: MIT - size: 3652740 - timestamp: 1689048946860 + size: 3924159 + timestamp: 1710794002174 - kind: conda name: taplo - version: 0.8.1 - build: he8a937b_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.8.1-he8a937b_0.conda - sha256: 901e0ba452bd249db45cbea25e7d865e43eb5322078e4724f43d83641b73335b - md5: 3d83fa9962fc353485bab815c9df9fe4 + version: 0.9.1 + build: hb8f9562_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda + sha256: dbcd4fa63270cef1c777cdbba2b697845704470bb7f3011e2b1b318fb9eb59b7 + md5: 0cf5ee26646e7780a0f89e0fbeac329e depends: - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 license: MIT license_family: MIT - size: 3586993 - timestamp: 1689047789269 + size: 3717546 + timestamp: 1710801928738 - kind: conda name: tbb version: 2021.10.0 @@ -18842,23 +15316,6 @@ packages: license_family: BSD size: 3318875 timestamp: 1699202167581 -- kind: conda - name: tomli - version: 2.0.1 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - sha256: 4cd48aba7cd026d17e86886af48d0d2ebc67ed36f87f6534f4b67138f5a5a58f - md5: 5844808ffab9ebdb694585b50ba02a96 - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/tomli - size: 15940 - timestamp: 1644342331069 - kind: conda name: tomli version: 2.0.1 @@ -18878,23 +15335,6 @@ packages: - pkg:pypi/tomli size: 15940 timestamp: 1644342331069 -- kind: conda - name: tomlkit - version: 0.12.3 - build: pyha770c72_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - sha256: 53cc436ab92d38683df1320e4468a8b978428e800195bf1c8c2460e90b0bc117 - md5: 074d0ce7a6261ab8b497c3518796ef3e - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/tomlkit - size: 37132 - timestamp: 1700046842169 - kind: conda name: tomlkit version: 0.12.3 @@ -19102,20 +15542,6 @@ packages: license_family: MIT size: 3652168 timestamp: 1707161817201 -- kind: conda - name: typos - version: 1.19.0 - build: h11a7dfb_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/typos-1.19.0-h11a7dfb_0.conda - sha256: 79da26e5585382a4ec5dde9ba0d43435f0dd441e9f344ef99d12f2dab0117b74 - md5: 97b99652ce2673198b2ab73b7cf85c31 - constrains: - - __osx >=10.12 - license: MIT - license_family: MIT - size: 3305763 - timestamp: 1709332590675 - kind: conda name: typos version: 1.19.0 @@ -19130,49 +15556,6 @@ packages: license_family: MIT size: 3607084 timestamp: 1709332306391 -- kind: conda - name: typos - version: 1.19.0 - build: h5ef7bb8_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.19.0-h5ef7bb8_0.conda - sha256: d73ae2b63301e440049a9b0f78c9b6747d9ef1a6be360a5856ab77c6cefceca7 - md5: 8516e396a23de65bad5066799fdbecf2 - constrains: - - __osx >=11.0 - license: MIT - license_family: MIT - size: 3307039 - timestamp: 1709332619096 -- kind: conda - name: typos - version: 1.19.0 - build: h7f3b576_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/typos-1.19.0-h7f3b576_0.conda - sha256: b9dc051dccb7cc9fb99d130f42703f0b14b711408d5b94d5864984b982981eb8 - md5: 0066abed96ba51601722fda1eee87973 - depends: - - m2w64-gcc-libs - - m2w64-gcc-libs-core - license: MIT - license_family: MIT - size: 2571575 - timestamp: 1709333263031 -- kind: conda - name: typos - version: 1.19.0 - build: he8a937b_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/typos-1.19.0-he8a937b_0.conda - sha256: ee886a360248e517b75980e7c7249fbba7bed97e5f67371257f8dc29b5c348df - md5: 97d8f139e4fb369369fb71f53e29be45 - depends: - - libgcc-ng >=12 - license: MIT - license_family: MIT - size: 3616719 - timestamp: 1709332292966 - kind: conda name: tzdata version: 2024a @@ -19199,25 +15582,6 @@ packages: license_family: PROPRIETARY size: 1283972 timestamp: 1666630199266 -- kind: conda - name: ucx - version: 1.15.0 - build: h11edf95_7 - build_number: 7 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h11edf95_7.conda - sha256: 3e381ec5918045a43e0f349214a4d38e53990897ba07a6abf025f9e0156acaf2 - md5: 20a94f617ad76922f8737ad1fe317f4d - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - rdma-core >=50.0 - constrains: - - cuda-version >=11.2,<12 - license: BSD-3-Clause - license_family: BSD - size: 6847943 - timestamp: 1710357262334 - kind: conda name: ucx version: 1.15.0 @@ -19441,23 +15805,6 @@ packages: license_family: MIT size: 218421 timestamp: 1682376911339 -- kind: conda - name: wheel - version: 0.38.4 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - sha256: bd4f11ff075ff251ade9f57686f31473e25be46ab282d9603f551401250f9f44 - md5: c829cfb8cb826acb9de0ac1a2df0a940 - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/wheel - size: 32521 - timestamp: 1668051714265 - kind: conda name: wheel version: 0.38.4 @@ -19539,23 +15886,6 @@ packages: license: LGPL-2.1 and GPL-2.0 size: 440555 timestamp: 1660348056328 -- kind: conda - name: zipp - version: 3.17.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - sha256: bced1423fdbf77bca0a735187d05d9b9812d2163f60ab426fc10f11f92ecbe26 - md5: 2e4d6bc0b14e10f895fc6791a7d9b26a - depends: - - python >=3.8 - license: MIT - license_family: MIT - purls: - - pkg:pypi/zipp - size: 18954 - timestamp: 1695255262261 - kind: conda name: zipp version: 3.17.0 diff --git a/pixi.toml b/pixi.toml index abd900d9619e..a92d738dc1fe 100644 --- a/pixi.toml +++ b/pixi.toml @@ -23,7 +23,6 @@ version = "0.1.0" # [environments] cpp = ["cpp"] -taplo = ["taplo"] [tasks] # Note: extra CLI argument after `pixi run TASK` are passed to the task cmd. @@ -79,12 +78,14 @@ lint-py-fmt-check = "ruff format --check --config rerun_py/pyproject.toml" lint-py-blackdoc = "blackdoc --check" lint-py-mypy = "mypy --install-types --non-interactive --no-warn-unused-ignore" lint-py-ruff = "ruff format --check --config rerun_py/pyproject.toml" +lint-taplo = "taplo fmt --check --diff" lint-typos = "typos" misc-fmt = "prettier --write '**/*.{yml,yaml,js,css,html}'" misc-fmt-check = "prettier --check '**/*.{yml,yaml,js,css,html}'" ruff-fmt = "ruff format --config rerun_py/pyproject.toml ." ruff-fix = "ruff --fix --config rerun_py/pyproject.toml ." +toml-fmt = "taplo fmt" py-build = "maturin develop --manifest-path rerun_py/Cargo.toml --extras=tests" @@ -108,13 +109,6 @@ search-index = "cargo run -p re_build_search_index --release --" # Files are stored in the `meilisearch` directory, so you can fully wipe it via `rm -rf meilisearch`. meilisearch = "meilisearch --db-path=./meilisearch/data.ms --dump-dir=./meilisearch/dumps/ --snapshot-dir=./meilisearch/snapshots/ --env=development --no-analytics --experimental-reduce-indexing-memory-usage --master-key=test" -# TODO(ab): move everything back to the main tasks/dependencies once taplo supports linux-aarch64. -[feature.taplo] -platforms = ["linux-64", "osx-arm64", "osx-64", "win-64"] - -[feature.taplo.tasks] -lint-taplo = "taplo fmt --check --diff" -toml-fmt = "taplo fmt" [feature.cpp.tasks] # All the cpp-* tasks can be configured with environment variables, e.g.: RERUN_WERROR=ON CXX=clang++ @@ -197,6 +191,7 @@ ninja = "1.11.1" doxygen = "1.9.7.*" binaryen = "117.*" # for `wasm-opt` prettier = "2.8.8.*" +taplo = "=0.9.1" tomlkit = "0.12.3.*" [pypi-dependencies] @@ -206,9 +201,6 @@ nox = ">=2024.3.2" # the conda-forge package is (wrongly) tagged as platform-spe patchelf = ">=0.17" meilisearch = "1.5.1.*" # not available for linux-aarch64 -[feature.taplo.dependencies] -taplo = "=0.8.1" # not (yet?) available for linux-aarch64 - [feature.cpp.target.linux-64.dependencies] clang = "16.0.6" ninja = "1.11.1" From 7e5901812721827005f43ffc7fd2c394e7ee9f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Birger=20Mo=C3=ABll?= Date: Wed, 20 Mar 2024 12:20:52 +0100 Subject: [PATCH 065/508] Update `controlnet` example readme (#5490) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5490/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5490/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5490/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5490) - [Docs preview](https://rerun.io/preview/a51fb38b36335a5a1a5949878a6a527cbcfe46b6/docs) - [Examples preview](https://rerun.io/preview/a51fb38b36335a5a1a5949878a6a527cbcfe46b6/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Nikolaus West Co-authored-by: Emil Ernerfeldt --- docs/cspell.json | 3 ++ examples/python/controlnet/README.md | 79 ++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/docs/cspell.json b/docs/cspell.json index 1816892358b9..4286104d050b 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -72,6 +72,7 @@ "consts", "controlnet", "CSRT", + "CUDA", "customizability", "CVPR", "dangush", @@ -348,6 +349,8 @@ "timepoint", "timepoints", "timeseries", + "timestep", + "timesteps", "tinyvec", "Tpng", "tqdm", diff --git a/examples/python/controlnet/README.md b/examples/python/controlnet/README.md index d5eaad46dc50..f898dbcd252d 100644 --- a/examples/python/controlnet/README.md +++ b/examples/python/controlnet/README.md @@ -1,22 +1,95 @@ + + + + + + + -This example integrates Rerun into [Hugging Face's ControlNet example](https://huggingface.co/docs/diffusers/using-diffusers/controlnet#controlnet). ControlNet allows to condition Stable Diffusion on various modalities. In this example we condition on edges detected by the Canny edge detector. +Use [Hugging Face's ControlNet](https://huggingface.co/docs/diffusers/using-diffusers/controlnet#controlnet) to generate an image from text, conditioned on detected edges from another image. + + + +## Used Rerun Types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) + + +## Background +[Hugging Face's ControlNet](https://huggingface.co/docs/diffusers/using-diffusers/controlnet#controlnet) allows to condition Stable Diffusion on various modalities. In this example we condition on edges detected by the Canny edge detector to keep our shape intact while generating an image with Stable Diffusion. This generates a new image based on the text prompt, but that still retains the structure of the control image. We visualize the whole generation process with Rerun. https://vimeo.com/870289439?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=1440:1080 -To run this example use +# Logging and Visualizing with Rerun +The visualizations in this example were created with the following Rerun code. + +## Images +```python +rr.log("input/raw", rr.Image(image), timeless=True) +rr.log("input/canny", rr.Image(canny_image), timeless=True) +``` +The input image and control canny_image are marked as timeless and logged in rerun. + +Timeless entities belong to all timelines (existing ones, and ones not yet created) and are shown leftmost in the time panel in the viewer. This is useful for entities that aren't part of normal data capture, but set the scene for how they are shown. + +This designation ensures their constant availability across all timelines in Rerun, aiding in consistent comparison and documentation. + +## Prompts +```python +rr.log("positive_prompt", rr.TextDocument(prompt), timeless=True) +rr.log("negative_prompt", rr.TextDocument(negative_prompt), timeless=True) +``` +The positive and negative prompt used for generation is logged to Rerun. + +## Custom diffusion step callback +We use a custom callback function for ControlNet that logs the output and the latent values at each timestep, which makes it possible for us to view all timesteps of the generation in Rerun. +```python +def controlnet_callback( + iteration: int, timestep: float, latents: torch.Tensor, pipeline: StableDiffusionXLControlNetPipeline +) -> None: + rr.set_time_sequence("iteration", iteration) + rr.set_time_seconds("timestep", timestep) + rr.log("output", rr.Image(image)) + rr.log("latent", rr.Tensor(latents.squeeze(), dim_names=["channel", "height", "width"])) +``` + +## Output image +```python +rr.log("output", rr.Image(images)) +``` +Finally we log the output image generated by ControlNet. + +# Run the Code + +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` + +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/controlnet/requirements.txt +``` + +To experiment with the provided example, simply execute the main Python script: +```bash python examples/python/controlnet/main.py ``` You can specify your own image and prompts using ```bash -main.py [--img-path IMG_PATH] [--prompt PROMPT] [--negative-prompt NEGATIVE_PROMPT] +python examples/python/controlnet/main.py [--img-path IMG_PATH] [--prompt PROMPT] [--negative-prompt NEGATIVE_PROMPT] ``` + +This example requires a machine with CUDA backend available for pytorch (GPU) to work. From dd84dd448508d870361893ec48e5c79df9de4994 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 20 Mar 2024 12:31:00 +0100 Subject: [PATCH 066/508] `import rerun.blueprint as rbl` -> `import rerun.blueprint as rrb` (#5592) That's what we settled on. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5592/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5592/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5592/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5592) - [Docs preview](https://rerun.io/preview/0c10fe5f6058636e943b2c739244d90c294b2af1/docs) - [Examples preview](https://rerun.io/preview/0c10fe5f6058636e943b2c739244d90c294b2af1/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/arkit_scenes/main.py | 16 ++++++++-------- examples/python/nuscenes/main.py | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py index b56c7234f4ba..1c35a287cda1 100755 --- a/examples/python/arkit_scenes/main.py +++ b/examples/python/arkit_scenes/main.py @@ -10,7 +10,7 @@ import cv2 import numpy as np import rerun as rr # pip install rerun-sdk -import rerun.blueprint as rbl +import rerun.blueprint as rrb import trimesh from download_dataset import AVAILABLE_RECORDINGS, ensure_recording_available from scipy.spatial.transform import Rotation as R @@ -330,25 +330,25 @@ def main() -> None: primary_camera_entity = highres_entity_path if args.include_highres else lowres_posed_entity_path - blueprint = rbl.Horizontal( - rbl.Spatial3DView(name="3D"), - rbl.Vertical( - rbl.Tabs( + blueprint = rrb.Horizontal( + rrb.Spatial3DView(name="3D"), + rrb.Vertical( + rrb.Tabs( # Note that we re-project the annotations into the 2D views: # For this to work, the origin of the 2D views has to be a pinhole camera, # this way the viewer knows how to project the 3D annotations into the 2D views. - rbl.Spatial2DView( + rrb.Spatial2DView( name="RGB", origin=primary_camera_entity, contents=["$origin/rgb", "/world/annotations/**"], ), - rbl.Spatial2DView( + rrb.Spatial2DView( name="Depth", origin=primary_camera_entity, contents=["$origin/depth", "/world/annotations/**"], ), ), - rbl.TextDocumentView(name="Readme"), + rrb.TextDocumentView(name="Readme"), ), ) diff --git a/examples/python/nuscenes/main.py b/examples/python/nuscenes/main.py index 253772dd053a..a8f0d28998d6 100755 --- a/examples/python/nuscenes/main.py +++ b/examples/python/nuscenes/main.py @@ -9,7 +9,7 @@ import matplotlib import numpy as np import rerun as rr -import rerun.blueprint as rbl +import rerun.blueprint as rrb from download_dataset import MINISPLIT_SCENES, download_minisplit from nuscenes import nuscenes @@ -257,15 +257,15 @@ def main() -> None: # Set up the Rerun Blueprint (how the visualization is organized): sensor_space_views = [ - rbl.Spatial2DView( + rrb.Spatial2DView( name=sensor_name, origin=f"world/ego_vehicle/{sensor_name}", ) for sensor_name in nuscene_sensor_names(nusc, args.scene_name) ] - blueprint = rbl.Vertical( - rbl.Spatial3DView(name="3D", origin="world"), - rbl.Grid(*sensor_space_views), + blueprint = rrb.Vertical( + rrb.Spatial3DView(name="3D", origin="world"), + rrb.Grid(*sensor_space_views), row_shares=[3, 2], ) From ea576b719f117865c6c8b954a847f443460e27b0 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 20 Mar 2024 13:38:34 +0100 Subject: [PATCH 067/508] Remove car example (#5576) ### What RGBD example is almost as good. Car was useful when we didn't have much else, but now it's mostly just ugly ;) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5576/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5576/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5576/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5576) - [Docs preview](https://rerun.io/preview/174aaf57d6120d1d087f346503dcf1bd34ad4282/docs) - [Examples preview](https://rerun.io/preview/174aaf57d6120d1d087f346503dcf1bd34ad4282/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- BUILD.md | 2 +- examples/manifest.toml | 1 - examples/python/README.md | 8 +- examples/python/car/README.md | 22 --- examples/python/car/main.py | 270 --------------------------- examples/python/car/requirements.txt | 3 - examples/python/requirements.txt | 1 - rerun_py/README.md | 4 +- scripts/run_python_e2e_test.py | 2 - 9 files changed, 7 insertions(+), 306 deletions(-) delete mode 100644 examples/python/car/README.md delete mode 100755 examples/python/car/main.py delete mode 100644 examples/python/car/requirements.txt diff --git a/BUILD.md b/BUILD.md index e9a11cbabc69..1a5f3a58c335 100644 --- a/BUILD.md +++ b/BUILD.md @@ -93,7 +93,7 @@ This needs to be repeated each time the Rust source code is updated, for example Now you can run the python examples from the repository, given that you're still in the virtual environment. ```sh -python examples/python/car/main.py +python examples/python/minimal/main.py ``` ## Building and installing the Rerun C++ SDK diff --git a/examples/manifest.toml b/examples/manifest.toml index d70f04efb117..15f978fb09e1 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -54,7 +54,6 @@ check out [Types](/docs/reference/types). """ examples = [ "minimal", - "car", "clock", "eigen_opencv", "multithreading", diff --git a/examples/python/README.md b/examples/python/README.md index 40f9e37e9c9e..3986c90b73dc 100644 --- a/examples/python/README.md +++ b/examples/python/README.md @@ -11,11 +11,11 @@ For example, if your SDK version is `0.4.0`, check out the matching tag for this repository by running `git checkout v0.4.0`. ## Dependencies -Each example comes with its own set of dependencies listed in a `requirements.txt` file. For example, to install dependencies and run the toy `car` example (which doesn't need to download any data) run: +Each example comes with its own set of dependencies listed in a `requirements.txt` file. For example, to install dependencies and run the toy `minimal` example (which doesn't need to download any data) run: ```sh -pip install -r examples/python/car/requirements.txt -examples/python/car/main.py +pip install -r examples/python/minimal/requirements.txt +python examples/python/minimal/main.py ``` You can also install all dependencies needed to run all examples with: @@ -27,7 +27,7 @@ pip install -r examples/python/requirements.txt ## Running the examples By default, the examples spawn a Rerun Viewer and stream log data to it. -You can instead save the log data to an `.rrd` file using `examples/python/car/main.py --save data.rrd`. You can then view that `.rrd` file with `rerun data.rrd`. +For most examples you can instead save the log data to an `.rrd` file using `examples/python/plots/main.py --save data.rrd`. You can then view that `.rrd` file with `rerun data.rrd`. (`rerun` is an alias for `python -m rerun`). diff --git a/examples/python/car/README.md b/examples/python/car/README.md deleted file mode 100644 index f1c75cded900..000000000000 --- a/examples/python/car/README.md +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - Car example screenshot - - - -A very simple 2D car is drawn using OpenCV, and a depth image is simulated and logged as a point cloud. - -```bash -pip install -r examples/python/car/requirements.txt -python examples/python/car/main.py -``` diff --git a/examples/python/car/main.py b/examples/python/car/main.py deleted file mode 100755 index 2a90537714b5..000000000000 --- a/examples/python/car/main.py +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env python3 -"""Shows how to use the Rerun SDK.""" -from __future__ import annotations - -import argparse -from dataclasses import dataclass -from typing import Iterator - -import cv2 -import numpy as np -import numpy.typing as npt -import rerun as rr # pip install rerun-sdk - - -def log_car_data() -> None: - """Log a few frames of generated data to show how the Rerun SDK is used.""" - NUM_FRAMES = 40 - - # Set our preferred up-axis on the space that we will log the points to: - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, timeless=True) - - for sample in generate_car_data(num_frames=NUM_FRAMES): - # This will assign logged entities a timeline called `frame_nr`. - # In the viewer you can select how to view entities - by frame_nr or the built-in `log_time`. - rr.set_time_sequence("frame_nr", sample.frame_idx) - - # Log the camera pose: - rr.log( - "world/camera", - rr.Transform3D(translation=sample.camera.position, rotation=rr.Quaternion(xyzw=sample.camera.rotation_q)), - ) - rr.log("world/camera", rr.ViewCoordinates.RDF, timeless=True) # X=Right, Y=Down, Z=Forward - - # Log the camera projection matrix: - rr.log( - "world/camera/image", - rr.Pinhole(image_from_camera=sample.camera.intrinsics, resolution=sample.camera.resolution), - ) - - # We log the rgb image to the image-space of the camera: - rr.log("world/camera/image/rgb", rr.Image(sample.rgb_image)) - - # Same with the bounding box: - ((car_x, car_y), (car_w, car_h)) = sample.car_bbox - rr.log( - "world/camera/image/bbox", - rr.Boxes2D(mins=[car_x, car_y], sizes=[car_w, car_h], labels="A car", colors=(0, 128, 255)), - ) - - # The depth image is in millimeters, so we set meter=1000 - rr.log("world/camera/image/depth", rr.DepthImage(sample.depth_image_mm, meter=1000)) - - -class DummyCar: - """Class representing a dummy car for generating dummy data to log.""" - - BODY_COLOR = (79, 91, 102) - TIRES_COLOR = (0, 0, 0) - - def __init__( - self, - center: tuple[int, int], - size: tuple[int, int], - distance_mm: float, - ): - self.center: npt.NDArray[np.int32] = np.array(center, dtype=np.int32) - self.size: npt.NDArray[np.int32] = np.array(size, dtype=np.int32) - self.distance_mm = distance_mm - - @property - def min(self) -> npt.NDArray[np.int32]: - return np.array(self.center - self.size / 2, dtype=np.int32) - - @property - def max(self) -> npt.NDArray[np.int32]: - return np.array(self.center + self.size / 2, dtype=np.int32) - - def drive_one_step(self) -> None: - self.center[0] += 5 - self.distance_mm -= 1 - - def draw( - self, - depth_image_mm: npt.NDArray[np.float32], - rgb: npt.NDArray[np.float32], - ) -> None: - # 1. Draw the tires of the car - tire_radius = (self.size[1] * (1.0 / 5)).astype(int) - tire_center_y = self.max[1] - tire_radius - tire_distance_mm = self.distance_mm + 200 - - # 1.1 Draw the left tire - left_tire_center = np.array((self.center[0] - 2 * tire_radius, tire_center_y)).astype(int) - cv2.circle(depth_image_mm, left_tire_center, tire_radius, tire_distance_mm, cv2.FILLED) - cv2.circle(rgb, left_tire_center, tire_radius, DummyCar.TIRES_COLOR, cv2.FILLED) - - # 1.2 Draw the right tire - right_tire_center = np.array((self.center[0] + 2 * tire_radius, tire_center_y)).astype(int) - cv2.circle(depth_image_mm, right_tire_center, tire_radius, tire_distance_mm, cv2.FILLED) - cv2.circle(rgb, right_tire_center, tire_radius, DummyCar.TIRES_COLOR, cv2.FILLED) - - # 2. Draw the body - body_section_height = self.size[1] * (2.0 / 5) - - # 2.1 Draw the top part of the car - top_section_distance_mm = self.distance_mm + 100 - top_section_width = self.size[0] * (3.0 / 5) - top_min = self.min + np.array((self.size[1] - top_section_width / 2, 0)) - top_max = top_min + np.array((top_section_width, body_section_height)) - cv2.rectangle( - depth_image_mm, - top_min.astype(int), - top_max.astype(int), - top_section_distance_mm, - cv2.FILLED, - ) - cv2.rectangle( - rgb, - top_min.astype(int), - top_max.astype(int), - DummyCar.BODY_COLOR, - cv2.FILLED, - ) - - # 2.2 Draw the middle part of the car - middle_min = self.min + np.array((0, body_section_height)) - middle_max = middle_min + np.array((self.size[0], body_section_height)) - cv2.rectangle( - depth_image_mm, - middle_min.astype(int), - middle_max.astype(int), - self.distance_mm, - cv2.FILLED, - ) - cv2.rectangle( - rgb, - middle_min.astype(int), - middle_max.astype(int), - DummyCar.BODY_COLOR, - cv2.FILLED, - ) - - -@dataclass -class CameraParameters: - """Holds the intrinsic and extrinsic parameters of a camera.""" - - resolution: npt.NDArray[np.int32] - intrinsics: npt.NDArray[np.float32] - rotation_q: npt.NDArray[np.float32] - position: npt.NDArray[np.float32] - - -@dataclass -class SampleFrame: - """Holds data for a single frame of data.""" - - frame_idx: int - camera: CameraParameters - depth_image_mm: npt.NDArray[np.float32] - rgb_image: npt.NDArray[np.float32] - car_bbox: tuple[npt.NDArray[np.int32], npt.NDArray[np.int32]] - - -class SimpleDepthCamera: - def __init__(self, image_width: int, image_height: int) -> None: - self.w = image_width - self.h = image_height - - # Simplest reasonable camera intrinsics given the resolution - self.u_center = self.w / 2 - self.v_center = self.h / 2 - self.focal_length = (self.h * self.w) ** 0.5 - - # Pre-generate image containing the x and y coordinates per pixel - self.u_coords, self.v_coords = np.meshgrid(np.arange(0, self.w), np.arange(0, self.h)) - - def render_dummy_slanted_plane_mm(self) -> npt.NDArray[np.float32]: - """Renders a depth image of a slanted plane in millimeters.""" - return 1000.0 * 1.0 / (0.01 + 0.4 * self.v_coords / self.h) - - @property - def intrinsics(self) -> npt.NDArray[np.float32]: - """The camera's row-major intrinsics matrix.""" - return np.array( - ( - (self.focal_length, 0, self.u_center), - (0, self.focal_length, self.v_center), - (0, 0, 1), - ), - dtype=np.float32, - ) - - @property - def rotation_q(self) -> npt.NDArray[np.float32]: - """The camera's rotation (world from camera) as a xyzw encoded quaternion.""" - return np.array((0, 0, 0, 1), dtype=np.float32) # Dummy "identity" value - - @property - def position(self) -> npt.NDArray[np.float32]: - """The camera's position in world space.""" - return np.array((0, 0, 0), dtype=np.float32) # Dummy "identity" value - - @property - def resolution(self) -> npt.NDArray[np.int32]: - """Image resolution as [width, height].""" - return np.array([self.w, self.h]) - - @property - def parameters(self) -> CameraParameters: - """The camera's parameters.""" - return CameraParameters( - resolution=self.resolution, - intrinsics=self.intrinsics, - rotation_q=self.rotation_q, - position=self.position, - ) - - -def generate_car_data(num_frames: int) -> Iterator[SampleFrame]: - """Generates dummy data to log.""" - # Generate some fake data - im_w = 480 - im_h = 270 - - camera = SimpleDepthCamera(image_width=im_w, image_height=im_h) - - # Background image as a simple slanted plane - # 1. Depth - depth_background_mm = camera.render_dummy_slanted_plane_mm() - - # 2. Color - sand_color = (194, 178, 128) - intensity = 1.0 / depth_background_mm - intensity /= intensity.max() - rgb_background = intensity[:, :, np.newaxis] * np.array(sand_color)[np.newaxis, np.newaxis, :] - rgb_background = rgb_background.astype(np.uint8) - - # Generate `num_frames` sample data - car = DummyCar(center=(140, 100), size=(200, 100), distance_mm=4000) - for i in range(num_frames): - depth_image_mm = depth_background_mm.copy() - rgb = rgb_background.copy() - car.draw(depth_image_mm=depth_image_mm, rgb=rgb) - sample = SampleFrame( - frame_idx=i, - camera=camera.parameters, - depth_image_mm=depth_image_mm, - rgb_image=rgb, - car_bbox=(car.min, car.size), - ) - - yield sample - car.drive_one_step() - - -def main() -> None: - parser = argparse.ArgumentParser( - description="A very simple 2D car is drawn using OpenCV, and a depth image is simulated and logged as a point cloud." - ) - rr.script_add_args(parser) - args = parser.parse_args() - - rr.script_setup(args, "rerun_example_car") - log_car_data() - rr.script_teardown(args) - - -if __name__ == "__main__": - main() diff --git a/examples/python/car/requirements.txt b/examples/python/car/requirements.txt deleted file mode 100644 index c3e8d077ec5a..000000000000 --- a/examples/python/car/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -numpy -opencv-python>4.6 # Avoid opencv-4.6 since it rotates images incorrectly (https://github.com/opencv/opencv/issues/22088) -rerun-sdk diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt index e96506de5b14..c39318a01368 100644 --- a/examples/python/requirements.txt +++ b/examples/python/requirements.txt @@ -1,6 +1,5 @@ -r arkit_scenes/requirements.txt -r blueprint/requirements.txt --r car/requirements.txt -r clock/requirements.txt -r controlnet/requirements.txt -r depth_guided_stable_diffusion/requirements.txt diff --git a/rerun_py/README.md b/rerun_py/README.md index a5f7da8a6de3..6d11703500fc 100644 --- a/rerun_py/README.md +++ b/rerun_py/README.md @@ -47,7 +47,7 @@ python3 -m rerun In a second terminal, run the example with the `--connect` option: ```sh -python3 examples/python/car/main.py --connect +python3 python examples/python/plots/main.py --connect ``` ------------------------- @@ -105,7 +105,7 @@ just py-test just py-lint # Run an example -python examples/python/car/main.py +python examples/python/minimal/main.py ``` ## Building an installable Python Wheel diff --git a/scripts/run_python_e2e_test.py b/scripts/run_python_e2e_test.py index e0a3a3431cb0..b3ab62996b76 100755 --- a/scripts/run_python_e2e_test.py +++ b/scripts/run_python_e2e_test.py @@ -44,7 +44,6 @@ def main() -> None: if not parser.parse_args().no_pip_reqs: requirements = [ "tests/python/test_api/requirements.txt", - "examples/python/car/requirements.txt", "examples/python/minimal_options/requirements.txt", "examples/python/multithreading/requirements.txt", "examples/python/plots/requirements.txt", @@ -62,7 +61,6 @@ def main() -> None: examples = [ # Trivial examples that don't require weird dependencies, or downloading data ("tests/python/test_api/main.py", ["--test", "all"]), - ("examples/python/car/main.py", []), ("examples/python/minimal_options/main.py", []), ("examples/python/multithreading/main.py", []), ("examples/python/plots/main.py", []), From aba8fca72038fdc176c5ceadbb41312d805f3b65 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 20 Mar 2024 13:39:03 +0100 Subject: [PATCH 068/508] Fix depth cloud bounding boxes for depth cloud visualizations with transforms (#5578) ### What Bounding box was accidentally transformed twice! Noticed by @roym899 - bounding boxes for depth clouds are still not perfect since they take the bounding box of the full theoretical frustum and not the points displayed, but it's a lot better Before: image After: image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5578/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5578/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5578/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5578) - [Docs preview](https://rerun.io/preview/ef53c8daf8f6a2b26616e8e4a5efaf35aeccc9ba/docs) - [Examples preview](https://rerun.io/preview/ef53c8daf8f6a2b26616e8e4a5efaf35aeccc9ba/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_renderer/src/renderer/depth_cloud.rs | 2 +- crates/re_space_view_spatial/src/visualizers/images.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/re_renderer/src/renderer/depth_cloud.rs b/crates/re_renderer/src/renderer/depth_cloud.rs index 7aa4f604a6b5..e861d3054d7b 100644 --- a/crates/re_renderer/src/renderer/depth_cloud.rs +++ b/crates/re_renderer/src/renderer/depth_cloud.rs @@ -168,7 +168,7 @@ pub struct DepthCloud { impl DepthCloud { /// World-space bounding-box. - pub fn bbox(&self) -> macaw::BoundingBox { + pub fn world_space_bbox(&self) -> macaw::BoundingBox { let max_depth = self.max_depth_in_world; let w = self.depth_dimensions.x as f32; let h = self.depth_dimensions.y as f32; diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index e08e822a82ae..31f9c158af6d 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -384,8 +384,8 @@ impl ImageVisualizer { Ok(cloud) => { self.data.add_bounding_box( ent_path.hash(), - cloud.bbox(), - cloud.world_from_rdf, + cloud.world_space_bbox(), + glam::Affine3A::IDENTITY, ); self.depth_cloud_entities.insert(ent_path.hash()); depth_clouds.push(cloud); From c6bbfaf1b706d84fbf737588225e0357dc23e4f6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 20 Mar 2024 13:44:23 +0100 Subject: [PATCH 069/508] Fix image view not handling images with extra leading dimensions of size 1 (#5579) ### What Encountered this while inspecting the `depth_guided_stable_diffusion` example: Before: Nothing shown for a depth image with dimensions `1x1x64x96` image After: image Note that the changed `shape_short` is only used for `image_height_width_channels`. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5579/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5579/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5579/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5579) - [Docs preview](https://rerun.io/preview/ce7eab6287449b0573583223c0cf643c6caf065b/docs) - [Examples preview](https://rerun.io/preview/ce7eab6287449b0573583223c0cf643c6caf065b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Clement Rey --- .../re_types/src/datatypes/tensor_data_ext.rs | 11 ++-- .../depth_guided_stable_diffusion/README.md | 13 +++-- .../huggingface_pipeline.py | 4 +- .../depth_guided_stable_diffusion/main.py | 53 ++++++++++++++++++- .../rerun/archetypes/bar_chart_ext.py | 2 +- 5 files changed, 65 insertions(+), 18 deletions(-) diff --git a/crates/re_types/src/datatypes/tensor_data_ext.rs b/crates/re_types/src/datatypes/tensor_data_ext.rs index 479838ac1075..0dea58904bb3 100644 --- a/crates/re_types/src/datatypes/tensor_data_ext.rs +++ b/crates/re_types/src/datatypes/tensor_data_ext.rs @@ -21,7 +21,7 @@ impl TensorData { self.shape.as_slice() } - /// Returns the shape of the tensor with all trailing dimensions of size 1 ignored. + /// Returns the shape of the tensor with all leading & trailing dimensions of size 1 ignored. /// /// If all dimension sizes are one, this returns only the first dimension. #[inline] @@ -29,12 +29,9 @@ impl TensorData { if self.shape.is_empty() { &self.shape } else { - self.shape - .iter() - .enumerate() - .rev() - .find(|(_, dim)| dim.size != 1) - .map_or(&self.shape[0..1], |(i, _)| &self.shape[..(i + 1)]) + let first_not_one = self.shape.iter().position(|dim| dim.size != 1); + let last_not_one = self.shape.iter().rev().position(|dim| dim.size != 1); + &self.shape[first_not_one.unwrap_or(0)..self.shape.len() - last_not_one.unwrap_or(0)] } } diff --git a/examples/python/depth_guided_stable_diffusion/README.md b/examples/python/depth_guided_stable_diffusion/README.md index eeae6dfaf07f..867c02c0e774 100644 --- a/examples/python/depth_guided_stable_diffusion/README.md +++ b/examples/python/depth_guided_stable_diffusion/README.md @@ -6,13 +6,12 @@ thumbnail_dimensions = [480, 253] channel = "nightly" --> - - - - - - - Depth-guided stable diffusion screenshot + + Depth-guided stable diffusion screenshot + + + + A more elaborate example running Depth Guided Stable Diffusion 2.0. diff --git a/examples/python/depth_guided_stable_diffusion/huggingface_pipeline.py b/examples/python/depth_guided_stable_diffusion/huggingface_pipeline.py index dd1d71ad5b46..eab92e43bd89 100644 --- a/examples/python/depth_guided_stable_diffusion/huggingface_pipeline.py +++ b/examples/python/depth_guided_stable_diffusion/huggingface_pipeline.py @@ -218,7 +218,7 @@ def _encode_prompt(self, prompt, device, num_images_per_prompt, do_classifier_fr return_tensors="pt", ) text_input_ids = text_inputs.input_ids - rr.log("prompt/text_input/ids", rr.Tensor(text_input_ids)) + rr.log("prompt/text_input/ids", rr.BarChart(text_input_ids)) untruncated_ids = self.tokenizer(prompt, padding="longest", return_tensors="pt").input_ids if untruncated_ids.shape[-1] >= text_input_ids.shape[-1] and not torch.equal(text_input_ids, untruncated_ids): @@ -229,7 +229,7 @@ def _encode_prompt(self, prompt, device, num_images_per_prompt, do_classifier_fr ) if hasattr(self.text_encoder.config, "use_attention_mask") and self.text_encoder.config.use_attention_mask: - rr.log("prompt/text_input/attention_mask", rr.Tensor(text_inputs.attention_mask)) + rr.log("prompt/text_input/attention_mask", rr.BarChart(text_inputs.attention_mask)) attention_mask = text_inputs.attention_mask.to(device) else: attention_mask = None diff --git a/examples/python/depth_guided_stable_diffusion/main.py b/examples/python/depth_guided_stable_diffusion/main.py index 214fad722d40..31712eb4dccf 100755 --- a/examples/python/depth_guided_stable_diffusion/main.py +++ b/examples/python/depth_guided_stable_diffusion/main.py @@ -17,6 +17,7 @@ import requests import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb import torch from huggingface_pipeline import StableDiffusionDepth2ImgPipeline from PIL import Image @@ -112,7 +113,57 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_depth_guided_stable_diffusion") + rr.script_setup( + args, + "rerun_example_depth_guided_stable_diffusion", + # This example is very complex, making it too hard for the Viewer to infer a good layout. + # Therefore, we specify everything explicitly: + # We set up three columns using a `Horizontal` layout, one each for + # * inputs + # * depth & initializations + # * diffusion outputs + blueprint=rrb.Blueprint( + rrb.Horizontal( + rrb.Vertical( + rrb.Tabs( + rrb.Spatial2DView(name="Image original", origin="image/original"), + rrb.TensorView(name="Image preprocessed", origin="input_image/preprocessed"), + ), + rrb.Vertical( + rrb.TextLogView(name="Prompt", contents=["prompt/text", "prompt/text_negative"]), + rrb.Tabs( + rrb.TensorView(name="Text embeddings", origin="prompt/text_embeddings"), + rrb.TensorView(name="Unconditional embeddings", origin="prompt/uncond_embeddings"), + ), + rrb.BarChartView(name="Prompt ids", origin="prompt/text_input"), + ), + ), + rrb.Vertical( + rrb.Tabs( + rrb.Spatial2DView(name="Depth estimated", origin="depth/estimated"), + rrb.Spatial2DView(name="Depth interpolated", origin="depth/interpolated"), + rrb.Spatial2DView(name="Depth normalized", origin="depth/normalized"), + rrb.TensorView(name="Depth input pre-processed", origin="depth/input_preprocessed"), + active_tab="Depth interpolated", + ), + rrb.Tabs( + rrb.TensorView(name="Encoded input", origin="encoded_input_image"), + rrb.TensorView(name="Decoded init latents", origin="decoded_init_latents"), + ), + ), + rrb.Vertical( + rrb.Spatial2DView(name="Image diffused", origin="image/diffused"), + rrb.Horizontal( + rrb.TensorView(name="Latent Model Input", origin="diffusion/latent_model_input"), + rrb.TensorView(name="Diffusion latents", origin="diffusion/latents"), + # rrb.TensorView(name="Noise Prediction", origin="diffusion/noise_pred"), + ), + ), + ), + rrb.SelectionPanel(expanded=False), + rrb.TimePanel(expanded=False), + ), + ) image_path = args.image_path # type: str if not image_path: diff --git a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart_ext.py b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart_ext.py index 297a99cb7999..4e329817545c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart_ext.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart_ext.py @@ -23,7 +23,7 @@ def values__field_converter_override(data: TensorDataArrayLike) -> TensorDataBat # once we coerce to a canonical non-arrow type. shape_dims = tensor_data.as_arrow_array()[0].value["shape"].values.field(0).to_numpy() - if len(shape_dims) != 1: + if len([d for d in shape_dims if d != 1]) != 1: _send_warning_or_raise( f"Bar chart data should only be 1D. Got values with shape: {shape_dims}", 2, From cbcceac40e9238e6ef3aacc4d2bad02766444a14 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 20 Mar 2024 14:12:02 +0100 Subject: [PATCH 070/508] Update to uuid 1.8.0 (#5594) This cuts out a lot of dependencies in native builds: * https://github.com/uuid-rs/uuid/pull/738 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5594/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5594/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5594/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5594) - [Docs preview](https://rerun.io/preview/74c77cd1e9544764e174d0fafbb7fe37d9709bf7/docs) - [Examples preview](https://rerun.io/preview/74c77cd1e9544764e174d0fafbb7fe37d9709bf7/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f9ca221a1f2..6d299a087086 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6668,9 +6668,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", "serde", From 493bc5ba84c657bac0a86d58761904a1b40514b9 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 20 Mar 2024 15:49:16 +0100 Subject: [PATCH 071/508] Rename some structures and APIs around selection (#5597) ### What This PR is pure renames, to address some seriously bad names and bring some consistency. - `Selection` -> `ItemCollection` - `SelectedSpaceContext` -> `ItemSpaceContext` - in `ApplicationSelectionState` (which contains both the selection and hovered states: - `clear_current` -> `clear_selection` - `current` -> `selected_items` - `hovered` -> `hovered_items` - `selected_space_context` -> `selection_space_contexts` **Reviewer**: check `selection_state.rs`. Everything else is just Rust analyser's work. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5597/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5597/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5597/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5597) - [Docs preview](https://rerun.io/preview/79db70275f6c80dcef78b2452e3fc5515891321c/docs) - [Examples preview](https://rerun.io/preview/79db70275f6c80dcef78b2452e3fc5515891321c/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view_spatial/src/ui.rs | 6 +- crates/re_space_view_spatial/src/ui_2d.rs | 10 +-- crates/re_space_view_spatial/src/ui_3d.rs | 12 ++-- crates/re_viewer/src/app_state.rs | 2 +- .../re_viewer/src/ui/selection_history_ui.rs | 10 +-- crates/re_viewer_context/src/lib.rs | 4 +- .../src/selection_history.rs | 16 ++--- .../re_viewer_context/src/selection_state.rs | 65 +++++++++---------- .../re_viewer_context/src/viewer_context.rs | 12 ++-- crates/re_viewport/src/context_menu/mod.rs | 20 +++--- .../re_viewport/src/space_view_highlights.rs | 4 +- .../re_viewport/src/viewport_blueprint_ui.rs | 2 +- 12 files changed, 82 insertions(+), 81 deletions(-) diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 56ca7f9ef75f..04f45d1b4e5b 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -9,7 +9,7 @@ use re_space_view::ScreenshotMode; use re_types::components::{DepthMeter, InstanceKey, TensorData, ViewCoordinates}; use re_types::tensor_data::TensorDataMeaning; use re_viewer_context::{ - HoverHighlight, Item, SelectedSpaceContext, SelectionHighlight, SpaceViewHighlights, + HoverHighlight, Item, ItemSpaceContext, SelectionHighlight, SpaceViewHighlights, SpaceViewState, SpaceViewSystemExecutionError, TensorDecodeCache, TensorStatsCache, UiVerbosity, ViewContextCollection, ViewQuery, ViewerContext, VisualizerCollection, }; @@ -613,7 +613,7 @@ pub fn picking( if let Some((_, context)) = hovered_items.first_mut() { *context = Some(match spatial_kind { - SpatialSpaceViewKind::TwoD => SelectedSpaceContext::TwoD { + SpatialSpaceViewKind::TwoD => ItemSpaceContext::TwoD { space_2d: query.space_origin.clone(), pos: picking_context .pointer_in_space2d @@ -621,7 +621,7 @@ pub fn picking( }, SpatialSpaceViewKind::ThreeD => { let hovered_point = picking_result.space_position(); - SelectedSpaceContext::ThreeD { + ItemSpaceContext::ThreeD { space_3d: query.space_origin.clone(), pos: hovered_point, tracked_entity: state.state_3d.tracked_entity.clone(), diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index e82999f72101..03f1468f1155 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -9,8 +9,8 @@ use re_renderer::view_builder::{TargetConfiguration, ViewBuilder}; use re_space_view::controls::{DRAG_PAN2D_BUTTON, RESET_VIEW_BUTTON_TEXT, ZOOM_SCROLL_MODIFIER}; use re_types::{archetypes::Pinhole, components::ViewCoordinates}; use re_viewer_context::{ - gpu_bridge, SelectedSpaceContext, SpaceViewSystemExecutionError, SystemExecutionOutput, - ViewQuery, ViewerContext, + gpu_bridge, ItemSpaceContext, SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, + ViewerContext, }; use super::{ @@ -364,7 +364,7 @@ pub fn view_2d( )); // Make sure to _first_ draw the selected, and *then* the hovered context on top! - for selected_context in ctx.selection_state().selected_space_context() { + for selected_context in ctx.selection_state().selection_space_contexts() { painter.extend(show_projections_from_3d_space( ui, query.space_origin, @@ -507,11 +507,11 @@ fn show_projections_from_3d_space( ui: &egui::Ui, space: &EntityPath, ui_from_canvas: &RectTransform, - space_context: &SelectedSpaceContext, + space_context: &ItemSpaceContext, color: egui::Color32, ) -> Vec { let mut shapes = Vec::new(); - if let SelectedSpaceContext::ThreeD { + if let ItemSpaceContext::ThreeD { point_in_space_cameras: target_spaces, .. } = space_context diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 2aa7a9cec49f..353310f78f8a 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -17,7 +17,7 @@ use re_space_view::{ }; use re_types::{components::ViewCoordinates, view_coordinates::SignedAxis3}; use re_viewer_context::{ - gpu_bridge, Item, SelectedSpaceContext, SpaceViewSystemExecutionError, SystemExecutionOutput, + gpu_bridge, Item, ItemSpaceContext, SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, ViewerContext, }; @@ -615,7 +615,7 @@ pub fn view_3d( .ok(); } - for selected_context in ctx.selection_state().selected_space_context() { + for selected_context in ctx.selection_state().selection_space_contexts() { show_projections_from_2d_space( &mut line_builder, space_cameras, @@ -839,11 +839,11 @@ fn show_projections_from_2d_space( line_builder: &mut re_renderer::LineDrawableBuilder<'_>, space_cameras: &[SpaceCamera3D], state: &SpatialSpaceViewState, - space_context: &SelectedSpaceContext, + space_context: &ItemSpaceContext, color: egui::Color32, ) { match space_context { - SelectedSpaceContext::TwoD { space_2d, pos } => { + ItemSpaceContext::TwoD { space_2d, pos } => { if let Some(cam) = space_cameras.iter().find(|cam| &cam.ent_path == space_2d) { if let Some(pinhole) = cam.pinhole.as_ref() { // Render a thick line to the actual z value if any and a weaker one as an extension @@ -879,7 +879,7 @@ fn show_projections_from_2d_space( } } } - SelectedSpaceContext::ThreeD { + ItemSpaceContext::ThreeD { pos: Some(pos), tracked_entity: Some(tracked_entity), .. @@ -906,7 +906,7 @@ fn show_projections_from_2d_space( } } } - SelectedSpaceContext::ThreeD { .. } => {} + ItemSpaceContext::ThreeD { .. } => {} } } diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 4678373d7049..69ebb0087b3c 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -174,7 +174,7 @@ impl AppState { recording_config_entry(recording_configs, entity_db.store_id().clone(), entity_db); if ui.input(|i| i.key_pressed(egui::Key::Escape)) { - rec_cfg.selection_state.clear_current(); + rec_cfg.selection_state.clear_selection(); } let applicable_entities_per_visualizer = space_view_class_registry diff --git a/crates/re_viewer/src/ui/selection_history_ui.rs b/crates/re_viewer/src/ui/selection_history_ui.rs index ac85d0ce1376..6055389c33ae 100644 --- a/crates/re_viewer/src/ui/selection_history_ui.rs +++ b/crates/re_viewer/src/ui/selection_history_ui.rs @@ -1,6 +1,6 @@ use egui::RichText; use re_ui::UICommand; -use re_viewer_context::{Item, Selection, SelectionHistory}; +use re_viewer_context::{Item, ItemCollection, SelectionHistory}; use re_viewport::ViewportBlueprint; // --- @@ -16,7 +16,7 @@ impl SelectionHistoryUi { ui: &mut egui::Ui, blueprint: &ViewportBlueprint, history: &mut SelectionHistory, - ) -> Option { + ) -> Option { let next = self.next_button_ui(re_ui, ui, blueprint, history); let prev = self.prev_button_ui(re_ui, ui, blueprint, history); prev.or(next) @@ -28,7 +28,7 @@ impl SelectionHistoryUi { ui: &mut egui::Ui, blueprint: &ViewportBlueprint, history: &mut SelectionHistory, - ) -> Option { + ) -> Option { // undo selection if let Some(previous) = history.previous() { let response = re_ui @@ -78,7 +78,7 @@ impl SelectionHistoryUi { ui: &mut egui::Ui, blueprint: &ViewportBlueprint, history: &mut SelectionHistory, - ) -> Option { + ) -> Option { // redo selection if let Some(next) = history.next() { let response = re_ui @@ -156,7 +156,7 @@ fn item_kind_ui(ui: &mut egui::Ui, sel: &Item) { ui.weak(RichText::new(format!("({})", sel.kind()))); } -fn selection_to_string(blueprint: &ViewportBlueprint, selection: &Selection) -> String { +fn selection_to_string(blueprint: &ViewportBlueprint, selection: &ItemCollection) -> String { debug_assert!( !selection.is_empty(), "History should never contain empty selections." diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 44d4b95371ec..0ae2fb383825 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -41,8 +41,8 @@ pub use item::Item; pub use query_context::{DataQueryResult, DataResultHandle, DataResultNode, DataResultTree}; pub use selection_history::SelectionHistory; pub use selection_state::{ - ApplicationSelectionState, HoverHighlight, InteractionHighlight, SelectedSpaceContext, - Selection, SelectionHighlight, + ApplicationSelectionState, HoverHighlight, InteractionHighlight, ItemCollection, + ItemSpaceContext, SelectionHighlight, }; pub use space_view::{ DataResult, IdentifiedViewSystem, OverridePath, PerSystemDataResults, PerSystemEntities, diff --git a/crates/re_viewer_context/src/selection_history.rs b/crates/re_viewer_context/src/selection_history.rs index 34e1f4574517..99b26391f7fb 100644 --- a/crates/re_viewer_context/src/selection_history.rs +++ b/crates/re_viewer_context/src/selection_history.rs @@ -1,4 +1,4 @@ -use crate::selection_state::Selection; +use crate::selection_state::ItemCollection; use super::Item; @@ -6,11 +6,11 @@ use super::Item; #[derive(Debug, Clone)] pub struct HistoricalSelection { pub index: usize, - pub selection: Selection, + pub selection: ItemCollection, } -impl From<(usize, Selection)> for HistoricalSelection { - fn from((index, selection): (usize, Selection)) -> Self { +impl From<(usize, ItemCollection)> for HistoricalSelection { + fn from((index, selection): (usize, ItemCollection)) -> Self { Self { index, selection } } } @@ -26,7 +26,7 @@ pub struct SelectionHistory { pub current: usize, /// Oldest first. - pub stack: Vec, + pub stack: Vec, } impl SelectionHistory { @@ -69,7 +69,7 @@ impl SelectionHistory { } #[must_use] - pub fn select_previous(&mut self) -> Option { + pub fn select_previous(&mut self) -> Option { if let Some(previous) = self.previous() { if previous.index != self.current { self.current = previous.index; @@ -80,7 +80,7 @@ impl SelectionHistory { } #[must_use] - pub fn select_next(&mut self) -> Option { + pub fn select_next(&mut self) -> Option { if let Some(next) = self.next() { if next.index != self.current { self.current = next.index; @@ -90,7 +90,7 @@ impl SelectionHistory { None } - pub fn update_selection(&mut self, selection: &Selection) { + pub fn update_selection(&mut self, selection: &ItemCollection) { // Selecting nothing is irrelevant from a history standpoint. if selection.is_empty() { return; diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index 9743cbf7c4e1..d793759d36d1 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -8,8 +8,10 @@ use crate::{item::resolve_mono_instance_path_item, ViewerContext}; use super::{Item, SelectionHistory}; +/// Context information that a space view might attach to an item from [`ItemCollection`] and useful +/// for how a selection might be displayed and interacted with. #[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)] -pub enum SelectedSpaceContext { +pub enum ItemSpaceContext { /// Hovering/Selecting in a 2D space. TwoD { space_2d: EntityPath, @@ -79,34 +81,34 @@ impl InteractionHighlight { } } -/// An ordered collection of [`Item`] and optional associated selected space context objects. +/// An ordered collection of [`Item`] and optional associated space context objects. /// /// Used to store what is currently selected and/or hovered. #[derive(Debug, Default, Clone, PartialEq, serde::Deserialize, serde::Serialize)] -pub struct Selection(IndexMap>); +pub struct ItemCollection(IndexMap>); -impl From for Selection { +impl From for ItemCollection { #[inline] fn from(val: Item) -> Self { - Selection([(val, None)].into()) + ItemCollection([(val, None)].into()) } } -impl From for Selection +impl From for ItemCollection where - T: Iterator)>, + T: Iterator)>, { #[inline] fn from(value: T) -> Self { - Selection(value.collect()) + ItemCollection(value.collect()) } } -impl Selection { +impl ItemCollection { /// For each item in this selection, if it refers to the first element of an instance with a /// single element, resolve it to a splatted entity path. pub fn into_mono_instance_path_items(self, ctx: &ViewerContext<'_>) -> Self { - Selection( + ItemCollection( self.0 .into_iter() .map(|(item, space_ctx)| { @@ -141,7 +143,7 @@ impl Selection { self.0.keys() } - pub fn iter_space_context(&self) -> impl Iterator { + pub fn iter_space_context(&self) -> impl Iterator { self.0 .iter() .filter_map(|(_, space_context)| space_context.as_ref()) @@ -166,7 +168,7 @@ impl Selection { } /// Retains elements that fulfill a certain condition. - pub fn retain(&mut self, f: impl FnMut(&Item, &mut Option) -> bool) { + pub fn retain(&mut self, f: impl FnMut(&Item, &mut Option) -> bool) { self.0.retain(f); } @@ -181,20 +183,17 @@ impl Selection { } /// Returns an iterator over the items and their selected space context. - pub fn iter(&self) -> impl Iterator)> { + pub fn iter(&self) -> impl Iterator)> { self.0.iter() } /// Returns a mutable iterator over the items and their selected space context. - pub fn iter_mut(&mut self) -> impl Iterator)> { + pub fn iter_mut(&mut self) -> impl Iterator)> { self.0.iter_mut() } /// Extend the selection with more items. - pub fn extend( - &mut self, - other: impl IntoIterator)>, - ) { + pub fn extend(&mut self, other: impl IntoIterator)>) { self.0.extend(other); } } @@ -211,19 +210,19 @@ pub struct ApplicationSelectionState { pub history: Mutex, /// Selection of the previous frame. Read from this. - selection_previous_frame: Selection, + selection_previous_frame: ItemCollection, /// Selection of the current frame. Write to this. #[serde(skip)] - selection_this_frame: Mutex, + selection_this_frame: Mutex, /// What objects are hovered? Read from this. #[serde(skip)] - hovered_previous_frame: Selection, + hovered_previous_frame: ItemCollection, /// What objects are hovered? Write to this. #[serde(skip)] - hovered_this_frame: Mutex, + hovered_this_frame: Mutex, } impl ApplicationSelectionState { @@ -261,39 +260,39 @@ impl ApplicationSelectionState { } /// Clears the current selection out. - pub fn clear_current(&self) { - self.set_selection(Selection::default()); + pub fn clear_selection(&self) { + self.set_selection(ItemCollection::default()); } /// Sets several objects to be selected, updating history as needed. /// /// Clears the selected space context if none was specified. - pub fn set_selection(&self, items: impl Into) { + pub fn set_selection(&self, items: impl Into) { *self.selection_this_frame.lock() = items.into(); } /// Returns the current selection. - pub fn current(&self) -> &Selection { + pub fn selected_items(&self) -> &ItemCollection { &self.selection_previous_frame } /// Returns the currently hovered objects. - pub fn hovered(&self) -> &Selection { + pub fn hovered_items(&self) -> &ItemCollection { &self.hovered_previous_frame } - /// Set the hovered objects. Will be in [`Self::hovered`] on the next frame. - pub fn set_hovered(&self, hovered: impl Into) { + /// Set the hovered objects. Will be in [`Self::hovered_items`] on the next frame. + pub fn set_hovered(&self, hovered: impl Into) { *self.hovered_this_frame.lock() = hovered.into(); } /// Select passed objects unless already selected in which case they get unselected. /// If however an object is already selected but now gets passed a *different* selected space context, it stays selected after all /// but with an updated selected space context! - pub fn toggle_selection(&self, toggle_items: Selection) { + pub fn toggle_selection(&self, toggle_items: ItemCollection) { re_tracing::profile_function!(); - let mut toggle_items_set: HashMap> = toggle_items + let mut toggle_items_set: HashMap> = toggle_items .iter() .map(|(item, ctx)| (item.clone(), ctx.clone())) .collect(); @@ -335,11 +334,11 @@ impl ApplicationSelectionState { *self.selection_this_frame.lock() = new_selection; } - pub fn selected_space_context(&self) -> impl Iterator { + pub fn selection_space_contexts(&self) -> impl Iterator { self.selection_previous_frame.iter_space_context() } - pub fn hovered_space_context(&self) -> Option<&SelectedSpaceContext> { + pub fn hovered_space_context(&self) -> Option<&ItemSpaceContext> { self.hovered_previous_frame.iter_space_context().next() } diff --git a/crates/re_viewer_context/src/viewer_context.rs b/crates/re_viewer_context/src/viewer_context.rs index c5cfa1323ff5..33b1264bcefc 100644 --- a/crates/re_viewer_context/src/viewer_context.rs +++ b/crates/re_viewer_context/src/viewer_context.rs @@ -6,7 +6,7 @@ use re_entity_db::entity_db::EntityDb; use crate::{ query_context::DataQueryResult, AppOptions, ApplicableEntities, ApplicationSelectionState, - Caches, CommandSender, ComponentUiRegistry, IndicatedEntities, PerVisualizer, Selection, + Caches, CommandSender, ComponentUiRegistry, IndicatedEntities, ItemCollection, PerVisualizer, SpaceViewClassRegistry, SpaceViewId, StoreContext, SystemCommandSender as _, TimeControl, }; @@ -74,13 +74,13 @@ pub struct ViewerContext<'a> { impl<'a> ViewerContext<'a> { /// Returns the current selection. - pub fn selection(&self) -> &Selection { - self.rec_cfg.selection_state.current() + pub fn selection(&self) -> &ItemCollection { + self.rec_cfg.selection_state.selected_items() } /// Returns the currently hovered objects. - pub fn hovered(&self) -> &Selection { - self.rec_cfg.selection_state.hovered() + pub fn hovered(&self) -> &ItemCollection { + self.rec_cfg.selection_state.hovered_items() } pub fn selection_state(&self) -> &ApplicationSelectionState { @@ -96,7 +96,7 @@ impl<'a> ViewerContext<'a> { pub fn select_hovered_on_click( &self, response: &egui::Response, - selection: impl Into, + selection: impl Into, ) { re_tracing::profile_function!(); diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index 43e43cf7308f..073a4f52840a 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use once_cell::sync::OnceCell; use re_entity_db::InstancePath; -use re_viewer_context::{ContainerId, Item, Selection, SpaceViewId, ViewerContext}; +use re_viewer_context::{ContainerId, Item, ItemCollection, SpaceViewId, ViewerContext}; use crate::{ContainerBlueprint, Contents, ViewportBlueprint}; @@ -48,7 +48,7 @@ pub fn context_menu_ui_for_item( return; } - let mut show_context_menu = |selection: &Selection| { + let mut show_context_menu = |selection: &ItemCollection| { let context_menu_ctx = ContextMenuContext { viewer_context: ctx, viewport_blueprint, @@ -68,7 +68,7 @@ pub fn context_menu_ui_for_item( if item_response.hovered() && item_response.secondary_clicked() { ctx.selection_state().set_selection(item.clone()); - show_context_menu(&Selection::from(item.clone())); + show_context_menu(&ItemCollection::from(item.clone())); } else { show_context_menu(ctx.selection()); } @@ -82,10 +82,12 @@ pub fn context_menu_ui_for_item( ctx.selection_state().set_selection(item.clone()); } - show_context_menu(&Selection::from(item.clone())); + show_context_menu(&ItemCollection::from(item.clone())); } - SelectionUpdateBehavior::Ignore => show_context_menu(&Selection::from(item.clone())), + SelectionUpdateBehavior::Ignore => { + show_context_menu(&ItemCollection::from(item.clone())); + } }; }); } @@ -196,7 +198,7 @@ struct ContextMenuContext<'a> { viewer_context: &'a ViewerContext<'a>, viewport_blueprint: &'a ViewportBlueprint, egui_context: egui::Context, - selection: &'a Selection, + selection: &'a ItemCollection, clicked_item: &'a Item, } @@ -235,9 +237,9 @@ impl<'a> ContextMenuContext<'a> { /// Context menu actions must implement this trait. /// /// Actions must do three things, corresponding to three core methods: -/// 1. Decide if it can operate a given [`Selection`] ([`Self::supports_selection`]). +/// 1. Decide if it can operate a given [`ItemCollection`] ([`Self::supports_selection`]). /// 2. If so, draw some UI in the context menu ([`Self::ui`]). -/// 3. If clicked, actually process the [`Selection`] ([`Self::process_selection`]). +/// 3. If clicked, actually process the [`ItemCollection`] ([`Self::process_selection`]). /// /// For convenience, these core methods have default implementations which delegates to simpler /// methods (see their respective docstrings). Implementor may either implement the core method for @@ -293,7 +295,7 @@ trait ContextMenuAction { // --- - /// Process the provided [`Selection`]. + /// Process the provided [`ItemCollection`]. /// /// The default implementation dispatches to [`Self::process_store_id`] and friends. fn process_selection(&self, ctx: &ContextMenuContext<'_>) { diff --git a/crates/re_viewport/src/space_view_highlights.rs b/crates/re_viewport/src/space_view_highlights.rs index 513aecc78f4f..c5859ca0899a 100644 --- a/crates/re_viewport/src/space_view_highlights.rs +++ b/crates/re_viewport/src/space_view_highlights.rs @@ -42,7 +42,7 @@ pub fn highlights_for_space_view( .add(&instance, next_selection_mask()); }; - for current_selection in ctx.selection_state().current().iter_items() { + for current_selection in ctx.selection_state().selected_items().iter_items() { match current_selection { Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => {} @@ -78,7 +78,7 @@ pub fn highlights_for_space_view( OutlineMaskPreference::some(hover_mask_index, 0) }; - for current_hover in ctx.selection_state().hovered().iter_items() { + for current_hover in ctx.selection_state().hovered_items().iter_items() { match current_hover { Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => {} diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 382e62c8880e..7f405569315f 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -76,7 +76,7 @@ impl Viewport<'_, '_> { // clear selection upon clicking on empty space if empty_space_response.clicked() { - ctx.selection_state().clear_current(); + ctx.selection_state().clear_selection(); } // handle drag and drop interaction on empty space From bd7a6b40ecac11cf5e6a477522639644c0ca3d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Wed, 20 Mar 2024 15:51:43 +0100 Subject: [PATCH 072/508] Fix doc snippets (#5575) ### What - When checking for opt outs we were not checking the opted out language - Emit `data-inline-viewer` in docs codegen ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5575/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5575/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5575/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5575) - [Docs preview](https://rerun.io/preview/bd9b28685e736311a8745f9db2446a67584cc2b0/docs) - [Examples preview](https://rerun.io/preview/bd9b28685e736311a8745f9db2446a67584cc2b0/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_build_examples/src/snippets.rs | 7 +- crates/re_types_builder/src/codegen/common.rs | 91 ++++++++++++++++--- .../re_types_builder/src/codegen/docs/mod.rs | 2 +- .../src/codegen/python/mod.rs | 5 +- .../re_types_builder/src/codegen/rust/api.rs | 3 +- .../types/archetypes/annotation_context.md | 18 ++-- .../reference/types/archetypes/arrows2d.md | 6 +- .../reference/types/archetypes/arrows3d.md | 6 +- .../reference/types/archetypes/asset3d.md | 6 +- .../reference/types/archetypes/bar_chart.md | 6 +- .../reference/types/archetypes/boxes2d.md | 6 +- .../reference/types/archetypes/boxes3d.md | 12 +-- .../reference/types/archetypes/clear.md | 6 +- .../reference/types/archetypes/depth_image.md | 12 +-- .../types/archetypes/disconnected_space.md | 6 +- .../reference/types/archetypes/image.md | 6 +- .../types/archetypes/line_strips2d.md | 18 ++-- .../types/archetypes/line_strips3d.md | 18 ++-- .../reference/types/archetypes/mesh3d.md | 12 +-- .../reference/types/archetypes/pinhole.md | 12 +-- .../reference/types/archetypes/points2d.md | 12 +-- .../reference/types/archetypes/points3d.md | 12 +-- .../reference/types/archetypes/scalar.md | 12 +-- .../types/archetypes/segmentation_image.md | 6 +- .../reference/types/archetypes/series_line.md | 6 +- .../types/archetypes/series_point.md | 6 +- .../reference/types/archetypes/tensor.md | 6 +- .../types/archetypes/text_document.md | 6 +- .../reference/types/archetypes/text_log.md | 6 +- .../types/archetypes/time_series_scalar.md | 12 +-- .../reference/types/archetypes/transform3d.md | 6 +- .../types/archetypes/view_coordinates.md | 6 +- docs/snippets/build.rs | 45 ++++----- docs/snippets/src/lib.rs | 4 +- .../src/{examples => snippets}/.gitignore | 0 35 files changed, 199 insertions(+), 204 deletions(-) rename docs/snippets/src/{examples => snippets}/.gitignore (100%) diff --git a/crates/re_build_examples/src/snippets.rs b/crates/re_build_examples/src/snippets.rs index ecbd9e568327..a75ed82f9f6c 100644 --- a/crates/re_build_examples/src/snippets.rs +++ b/crates/re_build_examples/src/snippets.rs @@ -57,7 +57,12 @@ impl Snippets { continue; } - if config.opt_out.run.contains_key(&name) { + let is_opted_out = config + .opt_out + .run + .get(&name) + .is_some_and(|languages| languages.iter().any(|v| v == "py")); + if is_opted_out { println!( "Skipping {}: explicit opt-out in `snippets.toml`", path.display() diff --git a/crates/re_types_builder/src/codegen/common.rs b/crates/re_types_builder/src/codegen/common.rs index 19118a4d0734..32da398c557b 100644 --- a/crates/re_types_builder/src/codegen/common.rs +++ b/crates/re_types_builder/src/codegen/common.rs @@ -138,14 +138,58 @@ pub enum ImageUrl<'a> { Other(&'a str), } -impl ImageUrl<'_> { +impl<'a> ImageUrl<'a> { pub fn parse(s: &str) -> ImageUrl<'_> { RerunImageUrl::parse(s).map_or(ImageUrl::Other(s), ImageUrl::Rerun) } - pub fn image_stack(&self) -> Vec { - match self { - ImageUrl::Rerun(rerun) => rerun.image_stack(), + /// Try to generate a `` stack, falling back to a single `` element. + pub fn image_stack(&self) -> ImageStack<'_> { + ImageStack { + url: self, + width: None, + snippet_id: None, + center: false, + } + } +} + +pub struct ImageStack<'a> { + url: &'a ImageUrl<'a>, + width: Option, + snippet_id: Option>, + center: bool, +} + +impl<'a> ImageStack<'a> { + /// Set the `width` attribute of the image. + #[inline] + pub fn width(mut self, v: u16) -> Self { + self.width = Some(v); + self + } + + /// Whether or not the image should be wrapped in `
`. + #[inline] + pub fn center(mut self) -> Self { + self.center = true; + self + } + + /// Set the snippet ID. + /// + /// If set, the resulting `` element will have the `data-inline-viewr` + /// attribute set with the value of this ID. + /// `data-inline-viewer` is not set for `` elements. + #[inline] + pub fn snippet_id(mut self, id: &'a str) -> Self { + self.snippet_id = Some(SnippetId(id)); + self + } + + pub fn finish(self) -> Vec { + match self.url { + ImageUrl::Rerun(rerun) => rerun.image_stack(self.snippet_id, self.width, self.center), ImageUrl::Other(url) => { vec![format!(r#""#)] } @@ -153,6 +197,14 @@ impl ImageUrl<'_> { } } +pub struct SnippetId<'a>(pub &'a str); + +impl<'a> std::fmt::Display for SnippetId<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "snippets/{}", self.0) + } +} + #[derive(Clone, Copy)] pub struct RerunImageUrl<'a> { pub name: &'a str, @@ -186,12 +238,14 @@ impl RerunImageUrl<'_> { }) } - pub fn image_stack(&self) -> Vec { + pub fn image_stack( + &self, + snippet_id: Option>, + desired_width: Option, + center: bool, + ) -> Vec { const WIDTHS: [u16; 4] = [480, 768, 1024, 1200]; - // Don't let the images take up too much space on the page. - let desired_with = Some(640); - let RerunImageUrl { name, hash, @@ -199,7 +253,17 @@ impl RerunImageUrl<'_> { extension, } = *self; - let mut stack = vec!["
".into(), "".into()]; + let mut stack = vec![]; + + if center { + stack.push("
".into()); + } + + match snippet_id { + Some(id) => stack.push(format!(r#""#)), + None => stack.push("".into()), + } + if let Some(max_width) = max_width { for width in WIDTHS { if width > max_width { @@ -211,9 +275,9 @@ impl RerunImageUrl<'_> { } } - if let Some(desired_with) = desired_with { + if let Some(desired_width) = desired_width { stack.push(format!( - r#" "# + r#" "# )); } else { stack.push(format!( @@ -221,7 +285,10 @@ impl RerunImageUrl<'_> { )); } stack.push("".into()); - stack.push("
".into()); + + if center { + stack.push("
".into()); + } stack } diff --git a/crates/re_types_builder/src/codegen/docs/mod.rs b/crates/re_types_builder/src/codegen/docs/mod.rs index d695c838031c..1acf6e21fce7 100644 --- a/crates/re_types_builder/src/codegen/docs/mod.rs +++ b/crates/re_types_builder/src/codegen/docs/mod.rs @@ -457,7 +457,7 @@ fn write_example_list(o: &mut String, examples: &[ExampleInfo<'_>]) { putln!(o, "snippet: {name}"); if let Some(image_url) = image { putln!(o); - for line in image_url.image_stack() { + for line in image_url.image_stack().snippet_id(name).finish() { putln!(o, "{line}"); } } diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index d9dd3d71402a..08d806e0c3e0 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -1132,7 +1132,10 @@ fn quote_examples(examples: Vec>, lines: &mut Vec) { lines.extend(example_lines.into_iter()); lines.push("```".into()); if let Some(image) = &image { - lines.extend(image.image_stack()); + lines.extend( + // Don't let the images take up too much space on the page. + image.image_stack().center().width(640).finish(), + ); } if examples.peek().is_some() { // blank line between examples diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index 61d9f4b5fe8b..fd7966e76afa 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -757,7 +757,8 @@ fn doc_as_lines(reporter: &Reporter, virtpath: &str, fqname: &str, docs: &Docs) lines.push("```".into()); if let Some(image) = &image { - lines.extend(image.image_stack().into_iter()); + // Don't let the images take up too much space on the page. + lines.extend(image.image_stack().center().width(640).finish()); } if examples.peek().is_some() { // blank line between examples diff --git a/docs/content/reference/types/archetypes/annotation_context.md b/docs/content/reference/types/archetypes/annotation_context.md index 3dff9cc93a10..46e54abebc8b 100644 --- a/docs/content/reference/types/archetypes/annotation_context.md +++ b/docs/content/reference/types/archetypes/annotation_context.md @@ -25,41 +25,35 @@ path. snippet: annotation_context_rects -
- + - + -
### Segmentation snippet: annotation_context_segmentation -
- + - + -
### Connections snippet: annotation_context_connections -
- + - + -
diff --git a/docs/content/reference/types/archetypes/arrows2d.md b/docs/content/reference/types/archetypes/arrows2d.md index b0231ca8b43f..ecc3d8aa0a90 100644 --- a/docs/content/reference/types/archetypes/arrows2d.md +++ b/docs/content/reference/types/archetypes/arrows2d.md @@ -23,13 +23,11 @@ title: "Arrows2D" snippet: arrow2d_simple -
- + - + -
diff --git a/docs/content/reference/types/archetypes/arrows3d.md b/docs/content/reference/types/archetypes/arrows3d.md index 3699afc0fbb7..376946187c7d 100644 --- a/docs/content/reference/types/archetypes/arrows3d.md +++ b/docs/content/reference/types/archetypes/arrows3d.md @@ -23,13 +23,11 @@ title: "Arrows3D" snippet: arrow3d_simple -
- + - + -
diff --git a/docs/content/reference/types/archetypes/asset3d.md b/docs/content/reference/types/archetypes/asset3d.md index 75e5f4188533..5b67987244e1 100644 --- a/docs/content/reference/types/archetypes/asset3d.md +++ b/docs/content/reference/types/archetypes/asset3d.md @@ -23,15 +23,13 @@ A prepacked 3D asset (`.gltf`, `.glb`, `.obj`, `.stl`, etc.). snippet: asset3d_simple -
- + - + -
### 3D asset with out-of-tree transform diff --git a/docs/content/reference/types/archetypes/bar_chart.md b/docs/content/reference/types/archetypes/bar_chart.md index 5a37a466ff3f..e8e6fe677938 100644 --- a/docs/content/reference/types/archetypes/bar_chart.md +++ b/docs/content/reference/types/archetypes/bar_chart.md @@ -23,13 +23,11 @@ The x values will be the indices of the array, and the bar heights will be the p snippet: bar_chart -
- + - + -
diff --git a/docs/content/reference/types/archetypes/boxes2d.md b/docs/content/reference/types/archetypes/boxes2d.md index 5da8ad3f9434..5d7464b0a9f9 100644 --- a/docs/content/reference/types/archetypes/boxes2d.md +++ b/docs/content/reference/types/archetypes/boxes2d.md @@ -23,13 +23,11 @@ title: "Boxes2D" snippet: box2d_simple -
- + - + -
diff --git a/docs/content/reference/types/archetypes/boxes3d.md b/docs/content/reference/types/archetypes/boxes3d.md index 741c5c4c7b66..6ce2d08e14ed 100644 --- a/docs/content/reference/types/archetypes/boxes3d.md +++ b/docs/content/reference/types/archetypes/boxes3d.md @@ -23,27 +23,23 @@ title: "Boxes3D" snippet: box3d_simple -
- + - + -
### Batch of 3D boxes snippet: box3d_batch -
- + - + -
diff --git a/docs/content/reference/types/archetypes/clear.md b/docs/content/reference/types/archetypes/clear.md index ef0787e47d1b..11fd4b92b1c7 100644 --- a/docs/content/reference/types/archetypes/clear.md +++ b/docs/content/reference/types/archetypes/clear.md @@ -29,15 +29,13 @@ data (i.e. discontinuous lines). snippet: clear_simple -
- + - + -
### Recursive diff --git a/docs/content/reference/types/archetypes/depth_image.md b/docs/content/reference/types/archetypes/depth_image.md index 8017e1e822ee..48377c17b7c3 100644 --- a/docs/content/reference/types/archetypes/depth_image.md +++ b/docs/content/reference/types/archetypes/depth_image.md @@ -24,27 +24,23 @@ Each pixel corresponds to a depth value in units specified by `meter`. snippet: depth_image_simple -
- + - + -
### Depth to 3D example snippet: depth_image_3d -
- + - + -
diff --git a/docs/content/reference/types/archetypes/disconnected_space.md b/docs/content/reference/types/archetypes/disconnected_space.md index a53a280c0a49..fd617c1979dc 100644 --- a/docs/content/reference/types/archetypes/disconnected_space.md +++ b/docs/content/reference/types/archetypes/disconnected_space.md @@ -24,13 +24,11 @@ This is useful for specifying that a subgraph is independent of the rest of the snippet: disconnected_space -
- + - + -
diff --git a/docs/content/reference/types/archetypes/image.md b/docs/content/reference/types/archetypes/image.md index 8e323397c58a..e67efab56d48 100644 --- a/docs/content/reference/types/archetypes/image.md +++ b/docs/content/reference/types/archetypes/image.md @@ -29,13 +29,11 @@ Leading and trailing unit-dimensions are ignored, so that snippet: image_simple -
- + - + -
diff --git a/docs/content/reference/types/archetypes/line_strips2d.md b/docs/content/reference/types/archetypes/line_strips2d.md index faefdf1201c2..42c97368ced9 100644 --- a/docs/content/reference/types/archetypes/line_strips2d.md +++ b/docs/content/reference/types/archetypes/line_strips2d.md @@ -23,41 +23,35 @@ title: "LineStrips2D" snippet: line_strip2d_simple -
- + - + -
### line_segments2d_simple snippet: line_segments2d_simple -
- + - + -
### line_strip2d_batch snippet: line_strip2d_batch -
- + - + -
diff --git a/docs/content/reference/types/archetypes/line_strips3d.md b/docs/content/reference/types/archetypes/line_strips3d.md index a2e8d1dbebaa..ec137e440219 100644 --- a/docs/content/reference/types/archetypes/line_strips3d.md +++ b/docs/content/reference/types/archetypes/line_strips3d.md @@ -23,41 +23,35 @@ title: "LineStrips3D" snippet: line_strip3d_simple -
- + - + -
### Many individual segments snippet: line_segments3d_simple -
- + - + -
### Many strips snippet: line_strip3d_batch -
- + - + -
diff --git a/docs/content/reference/types/archetypes/mesh3d.md b/docs/content/reference/types/archetypes/mesh3d.md index 4d3c0443a236..348b81e1fa6a 100644 --- a/docs/content/reference/types/archetypes/mesh3d.md +++ b/docs/content/reference/types/archetypes/mesh3d.md @@ -23,27 +23,23 @@ A 3D triangle mesh as specified by its per-mesh and per-vertex properties. snippet: mesh3d_indexed -
- + - + -
### 3D mesh with partial updates snippet: mesh3d_partial_updates -
- + - + -
diff --git a/docs/content/reference/types/archetypes/pinhole.md b/docs/content/reference/types/archetypes/pinhole.md index 9c124df7762e..790df5927231 100644 --- a/docs/content/reference/types/archetypes/pinhole.md +++ b/docs/content/reference/types/archetypes/pinhole.md @@ -23,27 +23,23 @@ Camera perspective projection (a.k.a. intrinsics). snippet: pinhole_simple -
- + - + -
### Perspective Pinhole Camera snippet: pinhole_perspective -
- + - + -
diff --git a/docs/content/reference/types/archetypes/points2d.md b/docs/content/reference/types/archetypes/points2d.md index 032d67924eab..2b30e9d39540 100644 --- a/docs/content/reference/types/archetypes/points2d.md +++ b/docs/content/reference/types/archetypes/points2d.md @@ -23,27 +23,23 @@ A 2D point cloud with positions and optional colors, radii, labels, etc. snippet: point2d_simple -
- + - + -
### Randomly distributed 2D points with varying color and radius snippet: point2d_random -
- + - + -
diff --git a/docs/content/reference/types/archetypes/points3d.md b/docs/content/reference/types/archetypes/points3d.md index e5717824498e..619df822d6af 100644 --- a/docs/content/reference/types/archetypes/points3d.md +++ b/docs/content/reference/types/archetypes/points3d.md @@ -23,27 +23,23 @@ A 3D point cloud with positions and optional colors, radii, labels, etc. snippet: point3d_simple -
- + - + -
### Randomly distributed 3D points with varying color and radius snippet: point3d_random -
- + - + -
diff --git a/docs/content/reference/types/archetypes/scalar.md b/docs/content/reference/types/archetypes/scalar.md index 246d1f88e8eb..8f7ee75d1715 100644 --- a/docs/content/reference/types/archetypes/scalar.md +++ b/docs/content/reference/types/archetypes/scalar.md @@ -27,27 +27,23 @@ the plot-specific archetypes through the blueprint. snippet: scalar_simple -
- + - + -
### Multiple time series plots snippet: scalar_multiple_plots -
- + - + -
diff --git a/docs/content/reference/types/archetypes/segmentation_image.md b/docs/content/reference/types/archetypes/segmentation_image.md index 39c943f9d5b2..f44318e55d1e 100644 --- a/docs/content/reference/types/archetypes/segmentation_image.md +++ b/docs/content/reference/types/archetypes/segmentation_image.md @@ -30,13 +30,11 @@ Leading and trailing unit-dimensions are ignored, so that snippet: segmentation_image_simple -
- + - + -
diff --git a/docs/content/reference/types/archetypes/series_line.md b/docs/content/reference/types/archetypes/series_line.md index 940acd5bca52..0315fab0f341 100644 --- a/docs/content/reference/types/archetypes/series_line.md +++ b/docs/content/reference/types/archetypes/series_line.md @@ -23,13 +23,11 @@ the `Scalar` archetype. snippet: series_line_style -
- + - + -
diff --git a/docs/content/reference/types/archetypes/series_point.md b/docs/content/reference/types/archetypes/series_point.md index 6e3761c346eb..3d62588e8276 100644 --- a/docs/content/reference/types/archetypes/series_point.md +++ b/docs/content/reference/types/archetypes/series_point.md @@ -23,13 +23,11 @@ the `Scalar` archetype. snippet: series_point_style -
- + - + -
diff --git a/docs/content/reference/types/archetypes/tensor.md b/docs/content/reference/types/archetypes/tensor.md index a11008eb9fb9..f94c08466489 100644 --- a/docs/content/reference/types/archetypes/tensor.md +++ b/docs/content/reference/types/archetypes/tensor.md @@ -19,13 +19,11 @@ A generic n-dimensional Tensor. snippet: tensor_simple -
- + - + -
diff --git a/docs/content/reference/types/archetypes/text_document.md b/docs/content/reference/types/archetypes/text_document.md index a52953b8e34c..6f4604a45340 100644 --- a/docs/content/reference/types/archetypes/text_document.md +++ b/docs/content/reference/types/archetypes/text_document.md @@ -23,13 +23,11 @@ Supports raw text and markdown. snippet: text_document -
- + - + -
diff --git a/docs/content/reference/types/archetypes/text_log.md b/docs/content/reference/types/archetypes/text_log.md index f3d2506631d9..d04df3bc4d37 100644 --- a/docs/content/reference/types/archetypes/text_log.md +++ b/docs/content/reference/types/archetypes/text_log.md @@ -23,13 +23,11 @@ A log entry in a text log, comprised of a text body and its log level. snippet: text_log_integration -
- + - + -
diff --git a/docs/content/reference/types/archetypes/time_series_scalar.md b/docs/content/reference/types/archetypes/time_series_scalar.md index 982a179e99a7..adddd41abef6 100644 --- a/docs/content/reference/types/archetypes/time_series_scalar.md +++ b/docs/content/reference/types/archetypes/time_series_scalar.md @@ -32,27 +32,23 @@ This archetype is in the process of being deprecated. Prefer usage of snippet: scalar_simple -
- + - + -
### Multiple time series plots snippet: scalar_multiple_plots -
- + - + -
diff --git a/docs/content/reference/types/archetypes/transform3d.md b/docs/content/reference/types/archetypes/transform3d.md index 188dfe9c1241..4ec1bbda5a3e 100644 --- a/docs/content/reference/types/archetypes/transform3d.md +++ b/docs/content/reference/types/archetypes/transform3d.md @@ -19,13 +19,11 @@ A 3D transform. snippet: transform3d_simple -
- + - + -
diff --git a/docs/content/reference/types/archetypes/view_coordinates.md b/docs/content/reference/types/archetypes/view_coordinates.md index 3277a337ab43..4dfa52805d23 100644 --- a/docs/content/reference/types/archetypes/view_coordinates.md +++ b/docs/content/reference/types/archetypes/view_coordinates.md @@ -26,13 +26,11 @@ down, and the Z axis points forward. snippet: view_coordinates_simple -
- + - + -
diff --git a/docs/snippets/build.rs b/docs/snippets/build.rs index ca96022f5515..41615ef4742d 100644 --- a/docs/snippets/build.rs +++ b/docs/snippets/build.rs @@ -1,7 +1,7 @@ //! Finds all the `*.rs` files in `docs/snippets/all`, -//! copies them to `src/examples` (with slight modifications), and generate a `examples/mod.rs` for them. +//! copies them to `src/snippets` (with slight modifications), and generate a `snippets/mod.rs` for them. //! -//! The reason we combine all the examples into a single binary +//! The reason we combine all the snippets into a single binary //! is to reduce the amount of binaries in our workspace. //! //! Motivation: @@ -16,25 +16,25 @@ fn main() { Path::new(&re_build_tools::get_and_track_env_var("CARGO_MANIFEST_DIR").unwrap()).to_owned(); let all_path = crate_path.join("all"); let src_path = crate_path.join("src"); - let examples_path = src_path.join("examples"); + let snippets_path = src_path.join("snippets"); assert!( all_path.exists() && all_path.is_dir(), "Failed to find {all_path:?}" ); - let mut examples = Vec::new(); + let mut snippets = Vec::new(); re_build_tools::rerun_if_changed(&all_path); for entry in fs::read_dir(&all_path).unwrap().flatten() { let path = entry.path(); if let Some(extension) = path.extension() { if extension == "rs" { - let example_name = path.file_stem().unwrap().to_str().unwrap().to_owned(); + let snippet_name = path.file_stem().unwrap().to_str().unwrap().to_owned(); let contents = fs::read_to_string(&path).unwrap(); - // TODO(#515): some examples lack a main, they should come with their necessary stub code commented out so that we can re-add it here. + // TODO(#515): some snippets lack a main, they should come with their necessary stub code commented out so that we can re-add it here. if contents.contains("fn main()") { // Patch the source code so we can call into `main` and pass arguments to it: let contents = contents.replace("fn main()", "pub fn main(_args: &[String])"); @@ -48,19 +48,20 @@ fn main() { path.to_str().unwrap().replace('\\', "/"), ); - let target_path = examples_path.join(format!("{example_name}.rs")); + let target_path = snippets_path.join(format!("{snippet_name}.rs")); + println!("{}", target_path.display()); re_build_tools::write_file_if_necessary(target_path, contents.as_bytes()) - .unwrap(); + .expect("failed to write snippet??"); - examples.push(example_name); + snippets.push(snippet_name); } } } } assert!( - examples.len() > 10, - "Found too few examples in {all_path:?}" + snippets.len() > 10, + "Found too few snippets in {all_path:?}" ); let source = r#" @@ -74,17 +75,17 @@ fn main() { let args: Vec = std::env::args().skip(1).collect(); if args.is_empty() { - eprintln!("Usage: {} \n", std::env::args().next().unwrap()); - eprintln!("Available examples ${EXAMPLES}:\n"); + eprintln!("Usage: {} \n", std::env::args().next().unwrap()); + eprintln!("Available snippets ${SNIPPETS}:\n"); std::process::exit(1); } - let example_name = args[0].as_str(); + let snippet_name = args[0].as_str(); - match example_name { - ${MATCH_EXAMPLES} + match snippet_name { + ${MATCH_SNIPPETS} _ => { - eprintln!("Unknown example: {example_name}"); + eprintln!("Unknown snippet: {snippet_name}"); std::process::exit(1); } } @@ -94,12 +95,12 @@ fn main() { .replace("${FILE}", file!()) .replace( "${MODS}", - &examples.iter().map(|m| format!("mod {m};")).join("\n"), + &snippets.iter().map(|m| format!("mod {m};")).join("\n"), ) - .replace("${EXAMPLES}", &examples.iter().join(" ")) + .replace("${SNIPPETS}", &snippets.iter().join(" ")) .replace( - "${MATCH_EXAMPLES}", - &examples + "${MATCH_SNIPPETS}", + &snippets .iter() .map(|m| { format!( @@ -117,6 +118,6 @@ fn main() { .format_str(source) .expect("Failed to format"); - re_build_tools::write_file_if_necessary(examples_path.join("mod.rs"), source.as_bytes()) + re_build_tools::write_file_if_necessary(snippets_path.join("mod.rs"), source.as_bytes()) .unwrap(); } diff --git a/docs/snippets/src/lib.rs b/docs/snippets/src/lib.rs index 0caa1b4e110d..f4269681a569 100644 --- a/docs/snippets/src/lib.rs +++ b/docs/snippets/src/lib.rs @@ -1,5 +1,5 @@ //! Snippets that we show in documentation. -mod examples; +mod snippets; -pub use examples::run; +pub use snippets::run; diff --git a/docs/snippets/src/examples/.gitignore b/docs/snippets/src/snippets/.gitignore similarity index 100% rename from docs/snippets/src/examples/.gitignore rename to docs/snippets/src/snippets/.gitignore From 3bda4213e01ef01dd6a6e97f25938f85c133aaaa Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:32:17 +0100 Subject: [PATCH 073/508] Removing items with the context menu now also removes them from the selection (#5598) ### What What the title says. - Fixes #5465 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5598/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5598/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5598/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5598) - [Docs preview](https://rerun.io/preview/85e8eb0e47d2602ced27f2a7439304caff963482/docs) - [Examples preview](https://rerun.io/preview/85e8eb0e47d2602ced27f2a7439304caff963482/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Andreas Reich --- crates/re_viewer_context/src/selection_state.rs | 11 +++++++++++ crates/re_viewport/src/context_menu/actions/remove.rs | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index d793759d36d1..faeb7acd17d7 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -286,6 +286,17 @@ impl ApplicationSelectionState { *self.hovered_this_frame.lock() = hovered.into(); } + /// Remove given items from the selection. + /// + /// Has no effect on items that were not selected in the first place. + /// Ignores `ItemSpaceContext`s in the passed collection if any. + pub fn remove_from_selection(&self, items: impl Into) { + let removed_items = items.into(); + self.selection_this_frame + .lock() + .retain(|item, _| !removed_items.contains_item(item)); + } + /// Select passed objects unless already selected in which case they get unselected. /// If however an object is already selected but now gets passed a *different* selected space context, it stays selected after all /// but with an updated selected space context! diff --git a/crates/re_viewport/src/context_menu/actions/remove.rs b/crates/re_viewport/src/context_menu/actions/remove.rs index ff7ef6e1ce20..78c459dbdade 100644 --- a/crates/re_viewport/src/context_menu/actions/remove.rs +++ b/crates/re_viewport/src/context_menu/actions/remove.rs @@ -33,6 +33,9 @@ impl ContextMenuAction for RemoveAction { .mark_user_interaction(ctx.viewer_context); ctx.viewport_blueprint .remove_contents(Contents::Container(*container_id)); + ctx.viewer_context + .selection_state() + .remove_from_selection(Item::Container(*container_id)); } fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { @@ -40,6 +43,9 @@ impl ContextMenuAction for RemoveAction { .mark_user_interaction(ctx.viewer_context); ctx.viewport_blueprint .remove_contents(Contents::SpaceView(*space_view_id)); + ctx.viewer_context + .selection_state() + .remove_from_selection(Item::SpaceView(*space_view_id)); } fn process_data_result( @@ -53,6 +59,10 @@ impl ContextMenuAction for RemoveAction { ctx.viewer_context, EntityPathRule::including_subtree(instance_path.entity_path.clone()), ); + + ctx.viewer_context + .selection_state() + .remove_from_selection(Item::DataResult(*space_view_id, instance_path.clone())); } } } From 9bc24b86f1f4362145d6aaa84767c4b9a7f580c3 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:32:34 +0100 Subject: [PATCH 074/508] Fix indentation of leaf items in hierarchical lists (#5590) ### What - Fixes #5457 (introduced in #5340) Also sneaks a minor UI tweak in the plot marker selection list. Before/after: image image

cc @martenbjork ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5590/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5590/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5590/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5590) - [Docs preview](https://rerun.io/preview/380d08c73607cca35c2640ca2206e0d7c8676ed3/docs) - [Examples preview](https://rerun.io/preview/380d08c73607cca35c2640ca2206e0d7c8676ed3/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/editors.rs | 5 ++- crates/re_time_panel/src/lib.rs | 4 +- crates/re_ui/examples/re_ui_example.rs | 45 +++++++++++++------ crates/re_ui/src/list_item.rs | 29 +++++++++--- crates/re_viewer/src/ui/recordings_panel.rs | 45 ++++++++++--------- crates/re_viewer/src/ui/selection_panel.rs | 8 ++-- .../src/ui/space_view_space_origin_ui.rs | 4 +- .../re_viewport/src/viewport_blueprint_ui.rs | 12 ++--- 8 files changed, 96 insertions(+), 56 deletions(-) diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index 62b603e3c516..2886043d7e3c 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -260,6 +260,9 @@ fn edit_marker_shape_ui( .width(100.0) .height(320.0) .show_ui(ui, |ui| { + // no spacing between list items + ui.spacing_mut().item_spacing.y = 0.0; + // Hack needed for ListItem to click its highlight bg rect correctly: ui.set_clip_rect( ui.clip_rect() @@ -272,7 +275,7 @@ fn edit_marker_shape_ui( paint_marker(ui, marker.into(), rect, visuals.text_color()); }) .selected(edit_marker == marker); - if list_item.show(ui).clicked() { + if list_item.show_flat(ui).clicked() { edit_marker = marker; } } diff --git a/crates/re_time_panel/src/lib.rs b/crates/re_time_panel/src/lib.rs index 64a4ffd9d262..ae213a976824 100644 --- a/crates/re_time_panel/src/lib.rs +++ b/crates/re_time_panel/src/lib.rs @@ -607,7 +607,7 @@ impl TimePanel { .width_allocation_mode(WidthAllocationMode::Compact) .selected(is_selected) .force_hovered(is_item_hovered) - .show_collapsing( + .show_hierarchical_with_content( ui, CollapseScope::StreamsTree.entity(tree.path.clone()), default_open, @@ -756,7 +756,7 @@ impl TimePanel { == HoverHighlight::Hovered, ) .with_icon(&re_ui::icons::COMPONENT) - .show(ui); + .show_hierarchical(ui); ui.set_clip_rect(clip_rect_save); diff --git a/crates/re_ui/examples/re_ui_example.rs b/crates/re_ui/examples/re_ui_example.rs index 0075c5babb3d..02c7bc0a4edb 100644 --- a/crates/re_ui/examples/re_ui_example.rs +++ b/crates/re_ui/examples/re_ui_example.rs @@ -260,7 +260,8 @@ impl eframe::App for ExampleApp { || re_ui::modal::Modal::new("Modal window").full_span_content(true), |_, ui, _| { for idx in 0..10 { - ListItem::new(&self.re_ui, format!("Item {idx}")).show(ui); + ListItem::new(&self.re_ui, format!("Item {idx}")) + .show_flat(ui); } }, ); @@ -401,7 +402,7 @@ impl eframe::App for ExampleApp { item.with_icon(&re_ui::icons::SPACE_VIEW_TEXT) }; - if item.show(ui).clicked() { + if item.show_flat(ui).clicked() { self.selected_list_item = Some(i); } } @@ -418,15 +419,31 @@ impl eframe::App for ExampleApp { self.re_ui .list_item("Collapsing list item with icon") .with_icon(&re_ui::icons::SPACE_VIEW_2D) - .show_collapsing(ui, "collapsing example", true, |_re_ui, ui| { - self.re_ui.list_item("Sub-item").show(ui); - self.re_ui.list_item("Sub-item").show(ui); - self.re_ui - .list_item("Sub-item with icon") - .with_icon(&re_ui::icons::SPACE_VIEW_TEXT) - .show(ui); - self.re_ui.list_item("Sub-item").show(ui); - }); + .show_hierarchical_with_content( + ui, + "collapsing example", + true, + |_re_ui, ui| { + self.re_ui.list_item("Sub-item").show_hierarchical(ui); + self.re_ui.list_item("Sub-item").show_hierarchical(ui); + self.re_ui + .list_item("Sub-item with icon") + .with_icon(&re_ui::icons::SPACE_VIEW_TEXT) + .show_hierarchical(ui); + self.re_ui + .list_item("Sub-item") + .show_hierarchical_with_content( + ui, + "sub-collapsing", + true, + |_re_ui, ui| { + self.re_ui + .list_item("Sub-sub-item") + .show_hierarchical(ui) + }, + ); + }, + ); }); }); }); @@ -678,7 +695,7 @@ mod drag_and_drop { .list_item(label.as_str()) .selected(self.selected_items.contains(item_id)) .draggable(true) - .show(ui); + .show_flat(ui); // // Handle item selection @@ -1050,7 +1067,7 @@ mod hierarchical_drag_and_drop { .selected(self.selected(item_id)) .draggable(true) .drop_target_style(self.target_container == Some(item_id)) - .show_collapsing(ui, item_id, true, |re_ui, ui| { + .show_hierarchical_with_content(ui, item_id, true, |re_ui, ui| { self.container_children_ui(re_ui, ui, children); }); @@ -1087,7 +1104,7 @@ mod hierarchical_drag_and_drop { .list_item(label) .selected(self.selected(item_id)) .draggable(true) - .show(ui); + .show_hierarchical(ui); self.handle_interaction(ui, item_id, false, &response, None); } diff --git a/crates/re_ui/src/list_item.rs b/crates/re_ui/src/list_item.rs index 67885f357123..d304cac2735b 100644 --- a/crates/re_ui/src/list_item.rs +++ b/crates/re_ui/src/list_item.rs @@ -11,7 +11,7 @@ struct ListItemResponse { collapse_response: Option, } -/// Responses returned by [`ListItem::show_collapsing`]. +/// Responses returned by [`ListItem::show_hierarchical_with_content`]. pub struct ShowCollapsingResponse { /// Response from the item itself. pub item_response: Response, @@ -226,8 +226,8 @@ impl<'a> ListItem<'a> { /// Override the hovered state even if the item is not actually hovered. /// /// Used to highlight items representing things that are hovered elsewhere in the UI. Note that - /// the [`egui::Response`] returned by [`Self::show`] and ]`Self::show_collapsing`] will still - /// reflect the actual hover state. + /// the [`egui::Response`] returned by [`Self::show_flat`], [`Self::show_hierarchical`], and + /// [`Self::show_hierarchical_with_content`] will still reflect the actual hover state. #[inline] pub fn force_hovered(mut self, force_hovered: bool) -> Self { self.force_hovered = force_hovered; @@ -286,14 +286,29 @@ impl<'a> ListItem<'a> { self } - /// Draw the item. - pub fn show(self, ui: &mut Ui) -> Response { + /// Draw the item as part of a flat list. + pub fn show_flat(self, ui: &mut Ui) -> Response { // Note: the purpose of the scope is to minimise interferences on subsequent items' id ui.scope(|ui| self.ui(ui, None)).inner.response } - /// Draw the item as a collapsing header. - pub fn show_collapsing( + /// Draw the item as a leaf node from a hierarchical list. + pub fn show_hierarchical(self, ui: &mut Ui) -> Response { + // Note: the purpose of the scope is to minimise interferences on subsequent items' id + ui.scope(|ui| { + ui.horizontal(|ui| { + ui.add_space(ReUi::small_icon_size().x + ReUi::text_to_icon_padding()); + ui.vertical(|ui| self.ui(ui, None)) + }) + }) + .inner + .inner + .inner + .response + } + + /// Draw the item as a non-leaf node from a hierarchical list. + pub fn show_hierarchical_with_content( mut self, ui: &mut Ui, id: impl Into, diff --git a/crates/re_viewer/src/ui/recordings_panel.rs b/crates/re_viewer/src/ui/recordings_panel.rs index dd67a18ca10b..cfb16cbeeec1 100644 --- a/crates/re_viewer/src/ui/recordings_panel.rs +++ b/crates/re_viewer/src/ui/recordings_panel.rs @@ -92,7 +92,7 @@ fn loading_receivers_ui( } resp }) - .show(ui); + .show_flat(ui); // never more than one level deep if let SmartChannelSource::TcpServer { .. } = source.as_ref() { response.on_hover_text("You can connect to this viewer from a Rerun SDK"); } @@ -129,16 +129,19 @@ fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) -> bool { let entity_db = entity_dbs[0]; recording_ui(ctx, ui, entity_db, Some(app_id), active_recording); } else { - ctx.re_ui.list_item(app_id).active(false).show_collapsing( - ui, - ui.make_persistent_id(app_id), - true, - |_, ui| { - for entity_db in entity_dbs { - recording_ui(ctx, ui, entity_db, None, active_recording); - } - }, - ); + ctx.re_ui + .list_item(app_id) + .active(false) + .show_hierarchical_with_content( + ui, + ui.make_persistent_id(app_id), + true, + |_, ui| { + for entity_db in entity_dbs { + recording_ui(ctx, ui, entity_db, None, active_recording); + } + }, + ); } } @@ -203,15 +206,17 @@ fn recording_ui( list_item = list_item.force_hovered(true); } - let response = list_item.show(ui).on_hover_ui(|ui| { - entity_db.data_ui( - ctx, - ui, - re_viewer_context::UiVerbosity::Full, - &ctx.current_query(), - entity_db.store(), - ); - }); + let response = list_item + .show_flat(ui) // never more than one level deep + .on_hover_ui(|ui| { + entity_db.data_ui( + ctx, + ui, + re_viewer_context::UiVerbosity::Full, + &ctx.current_query(), + entity_db.store(), + ); + }); if response.hovered() { ctx.selection_state().set_hovered(item.clone()); diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 342cd2218a96..a93857e4c027 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -227,7 +227,7 @@ fn container_children( .weak(true) .italics(true) .active(false) - .show(ui); + .show_flat(ui); } }; @@ -380,7 +380,7 @@ fn what_is_selected_ui( .with_icon(space_view.class(ctx.space_view_class_registry).icon()) .with_height(ReUi::title_bar_height()) .selected(true) - .show(ui) + .show_flat(ui) .on_hover_text(hover_text); } } @@ -485,7 +485,7 @@ fn item_title_ui( list_item = list_item.with_icon(icon); } - list_item.show(ui).on_hover_text(hover) + list_item.show_flat(ui).on_hover_text(hover) } /// Display a list of all the space views an entity appears in. @@ -749,7 +749,7 @@ fn show_list_item_for_container_child( list_item = list_item.force_hovered(true); } - let response = list_item.show(ui); + let response = list_item.show_flat(ui); context_menu_ui_for_item( ctx, diff --git a/crates/re_viewer/src/ui/space_view_space_origin_ui.rs b/crates/re_viewer/src/ui/space_view_space_origin_ui.rs index fd3b55de8b4a..7da6db8d4ac3 100644 --- a/crates/re_viewer/src/ui/space_view_space_origin_ui.rs +++ b/crates/re_viewer/src/ui/space_view_space_origin_ui.rs @@ -192,7 +192,7 @@ fn space_view_space_origin_widget_editing_ui( .syntax_highlighted(ui.style()), ) .force_hovered(*selected_suggestion == Some(idx)) - .show(ui); + .show_flat(ui); if response.hovered() { *selected_suggestion = None; @@ -213,7 +213,7 @@ fn space_view_space_origin_widget_editing_ui( .weak(true) .italics(true) .active(false) - .show(ui); + .show_flat(ui); } }; diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 7f405569315f..97bc47a28368 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -275,7 +275,7 @@ impl Viewport<'_, '_> { .with_icon(crate::icon_for_container_kind( &container_blueprint.container_kind, )) - .show(ui); + .show_flat(ui); for child in &container_blueprint.contents { self.contents_ui(ctx, ui, child, true); @@ -344,7 +344,7 @@ impl Viewport<'_, '_> { remove_response | vis_response }) - .show_collapsing( + .show_hierarchical_with_content( ui, CollapseScope::BlueprintTree.container(*container_id), default_open, @@ -429,7 +429,7 @@ impl Viewport<'_, '_> { response | vis_response }) - .show_collapsing( + .show_hierarchical_with_content( ui, CollapseScope::BlueprintTree.space_view(*space_view_id), default_open, @@ -532,7 +532,7 @@ impl Viewport<'_, '_> { .subdued(true) .italics(true) .with_icon(&re_ui::icons::LINK) - .show(ui) + .show_hierarchical(ui) .on_hover_text( "This subtree corresponds to the Space View's origin, and is displayed above \ the 'Projections' section. Click to select it.", @@ -621,7 +621,7 @@ impl Viewport<'_, '_> { && Self::default_open_for_data_result(node); list_item - .show_collapsing( + .show_hierarchical_with_content( ui, CollapseScope::BlueprintTree.data_result(space_view.id, entity_path.clone()), default_open, @@ -654,7 +654,7 @@ impl Viewport<'_, '_> { ) .item_response } else { - list_item.show(ui) + list_item.show_hierarchical(ui) }; let response = response.on_hover_ui(|ui| { From d1a1537618471d7e6b85b29c388266236d6cec8f Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 20 Mar 2024 17:42:17 +0100 Subject: [PATCH 075/508] Do not display non-visualizable items as hidden in the blueprint tree (#5600) ### What I posit that displaying visibility is more important than visualizability in the blueprint tree. This PR stops confounding both aspects in the styling. - Fixes #5469 Before/after: image image

It would still be interesting to somehow display visualizability there. We need a design for that. - Relates to #5410 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5600/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5600/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5600/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5600) - [Docs preview](https://rerun.io/preview/b2e30f22c442163dfed3b12dbb7df4585e1fba8c/docs) - [Examples preview](https://rerun.io/preview/b2e30f22c442163dfed3b12dbb7df4585e1fba8c/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewport/src/viewport_blueprint_ui.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 97bc47a28368..ca1c48a6ea02 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -570,9 +570,7 @@ impl Viewport<'_, '_> { ctx.re_ui.warning_text(item_label) }; - let subdued = !space_view_visible - || !visible - || data_result_node.map_or(true, |n| n.data_result.visualizers.is_empty()); + let subdued = !space_view_visible || !visible; let list_item = ListItem::new(ctx.re_ui, item_label) .selected(is_selected) From 69f5aacfef4c848347861d5124d14adf403cb6cd Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 21 Mar 2024 03:24:20 -0400 Subject: [PATCH 076/508] Fix bad link from trouble shooting guide (#5610) ### What Looks like vulkan doesn't keep old docs up indefinitely. Switching link to latest instead. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5610/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5610/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5610/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5610) - [Docs preview](https://rerun.io/preview/97dad63d96c63657e0b6020453285acf79755ffb/docs) - [Examples preview](https://rerun.io/preview/97dad63d96c63657e0b6020453285acf79755ffb/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../getting-started/troubleshooting.md | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/content/getting-started/troubleshooting.md b/docs/content/getting-started/troubleshooting.md index 4009ea129d69..f0adfd4fe314 100644 --- a/docs/content/getting-started/troubleshooting.md +++ b/docs/content/getting-started/troubleshooting.md @@ -9,6 +9,7 @@ If you run into any issues don't hesitate to [open a ticket](https://github.com/ or [join our Discord](https://discord.gg/Gcm8BbTaAj). ## Running on Linux + Rerun should work out-of-the-box on Mac and Windows, but on Linux you need to first run: ```sh @@ -54,6 +55,7 @@ sudo apt-get -y install \ sometimes causes Rerun to crash. Try unsetting the wayland display (`unset WAYLAND_DISPLAY` or `WAYLAND_DISPLAY= `) as a workaround. ## Startup issues + If Rerun is having trouble starting, you can try resetting its memory with: ``` @@ -61,20 +63,22 @@ rerun reset ``` ## Graphics issues + [Wgpu](https://github.com/gfx-rs/wgpu) (the graphics API we use) maintains a list of [known driver issues](https://github.com/gfx-rs/wgpu/wiki/Known-Driver-Issues) and workarounds for them. The configuration we use for wgpu can be influenced in the following ways: -* pass `--renderer=` on startup: `` must be one of `vulkan`, `metal` or `gl` for native and - either `webgl` or `webgpu` for the web viewer (see also `--web-viewer` argument). - Naturally, support depends on your OS. The default backend is `vulkan` everywhere except on Mac where we use `metal`. - On the web we prefer WebGPU and fall back automatically to WebGL if no support for WebGPU was detected. - * For instance, you can try `rerun --renderer=gl` or for the web viewer respectively `rerun --web-viewer --renderer=webgl`. - * Alternatively, for the native viewer you can also use the `WGPU_BACKEND` environment variable with the above values. - * The web viewer is configured by the `renderer=` url argument, e.g. [https://app.rerun.io/?renderer=webgl] -* `WGPU_POWER_PREF`: Overwrites the power setting used for choosing a graphics adapter, must be `high` or `low`. (Default is `high`) + +- pass `--renderer=` on startup: `` must be one of `vulkan`, `metal` or `gl` for native and + either `webgl` or `webgpu` for the web viewer (see also `--web-viewer` argument). + Naturally, support depends on your OS. The default backend is `vulkan` everywhere except on Mac where we use `metal`. + On the web we prefer WebGPU and fall back automatically to WebGL if no support for WebGPU was detected. + - For instance, you can try `rerun --renderer=gl` or for the web viewer respectively `rerun --web-viewer --renderer=webgl`. + - Alternatively, for the native viewer you can also use the `WGPU_BACKEND` environment variable with the above values. + - The web viewer is configured by the `renderer=` url argument, e.g. [https://app.rerun.io/?renderer=webgl] +- `WGPU_POWER_PREF`: Overwrites the power setting used for choosing a graphics adapter, must be `high` or `low`. (Default is `high`) We recommend setting these only if you're asked to try them or know what you're doing, since we don't support all of these settings equally well. @@ -83,9 +87,10 @@ since we don't support all of these settings equally well. When using Wgpu's Vulkan backend (the default on Windows & Linux) on a computer that has both integrated and dedicated GPUs, a lot of issues can arise from Vulkan either picking the "wrong" GPU at runtime, or even simply from the fact that this choice conflicts with other driver picking technologies (e.g. NVIDIA Optimus). -In both cases, forcing Vulkan to pick either the integrated or discrete GPU (try both!) using the [`VK_ICD_FILENAMES`](https://vulkan.lunarg.com/doc/view/1.3.204.1/mac/LoaderDriverInterface.html#user-content-driver-discovery) environment variable might help with crashes, artifacts and bad performance. E.g.: -- Force the Intel integrated GPU: - - Linux: `export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/intel.json`. -- Force the discrete Nvidia GPU: - - Linux: `export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia.json`. - - Windows: `set VK_ICD_FILENAMES=\windows\system32\nv-vk64.json`. +In both cases, forcing Vulkan to pick either the integrated or discrete GPU (try both!) using the [`VK_ICD_FILENAMES`](https://vulkan.lunarg.com/doc/view/latest/mac/LoaderDriverInterface.html#user-content-driver-discovery) environment variable might help with crashes, artifacts and bad performance. E.g.: + +- Force the Intel integrated GPU: + - Linux: `export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/intel.json`. +- Force the discrete Nvidia GPU: + - Linux: `export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia.json`. + - Windows: `set VK_ICD_FILENAMES=\windows\system32\nv-vk64.json`. From cc0e8956a49056182db8afbe61e13c48cc4044eb Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Thu, 21 Mar 2024 09:09:15 +0100 Subject: [PATCH 077/508] Remove deprecated `TimeSeriesScalar` (#5604) It's now officially getting in my way. :hocho: --- crates/re_query_cache/src/flat_vec_deque.rs | 3 +- .../src/legacy_visualizer_system.rs | 276 -------------- crates/re_space_view_time_series/src/lib.rs | 1 - .../src/space_view_class.rs | 8 +- .../re_types/definitions/rerun/archetypes.fbs | 1 - .../rerun/archetypes/time_series_scalar.fbs | 79 ---- crates/re_types/src/archetypes/.gitattributes | 1 - crates/re_types/src/archetypes/mod.rs | 4 - .../src/archetypes/time_series_scalar.rs | 344 ------------------ .../getting-started/viewer-walkthrough.md | 2 +- docs/content/howto/ros2-nav-turtlebot.md | 4 +- .../reference/migration/migration-0-13.md | 6 +- .../reference/migration/migration-0-9.md | 4 +- docs/content/reference/types.md | 1 - docs/content/reference/types/archetypes.md | 5 - .../reference/types/archetypes/.gitattributes | 1 - .../types/archetypes/time_series_scalar.md | 54 --- .../reference/types/components/color.md | 1 - .../reference/types/components/radius.md | 1 - .../reference/types/components/scalar.md | 1 - .../types/components/scalar_scattering.md | 3 - .../reference/types/components/text.md | 1 - rerun_cpp/src/rerun/archetypes.hpp | 1 - rerun_cpp/src/rerun/archetypes/.gitattributes | 2 - .../rerun/archetypes/time_series_scalar.cpp | 58 --- .../rerun/archetypes/time_series_scalar.hpp | 197 ---------- rerun_py/docs/gen_common_index.py | 1 - rerun_py/rerun_sdk/rerun/__init__.py | 2 - .../rerun_sdk/rerun/archetypes/.gitattributes | 1 - .../rerun_sdk/rerun/archetypes/__init__.py | 2 - .../rerun/archetypes/time_series_scalar.py | 218 ----------- .../check_container_hierarchy.py | 7 +- ...ntext_menu_add_entity_to_new_space_view.py | 2 +- .../check_parallelism_caching_reentrancy.py | 7 +- .../release_checklist/check_plot_overrides.py | 7 +- .../release_checklist/check_scalar_clears.py | 1 - tests/roundtrips.py | 1 - 37 files changed, 25 insertions(+), 1283 deletions(-) delete mode 100644 crates/re_space_view_time_series/src/legacy_visualizer_system.rs delete mode 100644 crates/re_types/definitions/rerun/archetypes/time_series_scalar.fbs delete mode 100644 crates/re_types/src/archetypes/time_series_scalar.rs delete mode 100644 docs/content/reference/types/archetypes/time_series_scalar.md delete mode 100644 rerun_cpp/src/rerun/archetypes/time_series_scalar.cpp delete mode 100644 rerun_cpp/src/rerun/archetypes/time_series_scalar.hpp delete mode 100644 rerun_py/rerun_sdk/rerun/archetypes/time_series_scalar.py diff --git a/crates/re_query_cache/src/flat_vec_deque.rs b/crates/re_query_cache/src/flat_vec_deque.rs index 91b587692ffe..8cc9abc9b1a8 100644 --- a/crates/re_query_cache/src/flat_vec_deque.rs +++ b/crates/re_query_cache/src/flat_vec_deque.rs @@ -111,8 +111,7 @@ impl ErasedFlatVecDeque for FlatVecDeque { /// optimizes for writes. /// /// You can think of this as the native/deserialized version of an Arrow `ListArray`. -/// This is particularly useful when working with many small arrays of data (e.g. Rerun's -/// `TimeSeriesScalar`s). +/// This is particularly useful when working with many small arrays of data (e.g. Rerun's `Scalar`s). // // TODO(cmc): We could even use a bitmap for T=Option, which would bring this that much // closer to a deserialized version of an Arrow array. diff --git a/crates/re_space_view_time_series/src/legacy_visualizer_system.rs b/crates/re_space_view_time_series/src/legacy_visualizer_system.rs deleted file mode 100644 index bd9753f1d33c..000000000000 --- a/crates/re_space_view_time_series/src/legacy_visualizer_system.rs +++ /dev/null @@ -1,276 +0,0 @@ -use itertools::Itertools; -use re_query_cache::QueryError; -use re_types::{ - components::{Color, Radius, Scalar, ScalarScattering, Text}, - Archetype, Loggable, -}; -use re_viewer_context::{ - AnnotationMap, DefaultColor, IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewQuery, - ViewerContext, VisualizerQueryInfo, VisualizerSystem, -}; - -use crate::{ - overrides::initial_override_color, - util::{determine_plot_bounds_and_time_per_pixel, determine_time_range, points_to_series}, - PlotPoint, PlotPointAttrs, PlotSeries, PlotSeriesKind, ScatterAttrs, -}; - -#[allow(deprecated)] -use re_types::archetypes::TimeSeriesScalar; - -/// The legacy system for rendering [`TimeSeriesScalar`] archetypes. -#[derive(Default, Debug)] -pub struct LegacyTimeSeriesSystem { - pub annotation_map: AnnotationMap, - pub all_series: Vec, -} - -impl IdentifiedViewSystem for LegacyTimeSeriesSystem { - fn identifier() -> re_viewer_context::ViewSystemIdentifier { - "LegacyTimeSeries".into() - } -} - -impl VisualizerSystem for LegacyTimeSeriesSystem { - #[allow(deprecated)] - fn visualizer_query_info(&self) -> VisualizerQueryInfo { - let mut query_info = VisualizerQueryInfo::from_archetype::(); - // Although we don't normally include indicator components in required components, - // we don't want to show this legacy visualizer unless a user is actively using - // the legacy archetype for their logging. Users just working with Scalar will - // only see the new visualizer options. - query_info - .required - .insert(TimeSeriesScalar::indicator().name()); - query_info - } - - fn execute( - &mut self, - ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, - _context: &re_viewer_context::ViewContextCollection, - ) -> Result, SpaceViewSystemExecutionError> { - re_tracing::profile_function!(); - - self.annotation_map.load( - ctx, - &query.latest_at_query(), - query - .iter_visible_data_results(ctx, Self::identifier()) - .map(|data| &data.entity_path), - ); - - match self.load_scalars(ctx, query) { - Ok(_) | Err(QueryError::PrimaryNotFound(_)) => Ok(Vec::new()), - Err(err) => Err(err.into()), - } - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn initial_override_value( - &self, - _ctx: &ViewerContext<'_>, - _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, - entity_path: &re_log_types::EntityPath, - component: &re_types::ComponentName, - ) -> Option { - if *component == Color::name() { - Some([initial_override_color(entity_path)].into()) - } else { - None - } - } -} - -impl LegacyTimeSeriesSystem { - #[allow(deprecated)] - fn load_scalars( - &mut self, - ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, - ) -> Result<(), QueryError> { - re_tracing::profile_function!(); - - let query_caches = ctx.entity_db.query_caches(); - let store = ctx.entity_db.store(); - - let (plot_bounds, time_per_pixel) = determine_plot_bounds_and_time_per_pixel(ctx, query); - - // TODO(cmc): this should be thread-pooled in case there are a gazillon series in the same plot… - for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { - let annotations = self.annotation_map.find(&data_result.entity_path); - let annotation_info = annotations - .resolved_class_description(None) - .annotation_info(); - let default_color = DefaultColor::EntityPath(&data_result.entity_path); - - const DEFAULT_RADIUS: f32 = 0.75; - - let override_color = data_result - .lookup_override::(ctx) - .map(|c| c.to_array()); - let override_label = data_result.lookup_override::(ctx).map(|t| t.0); - let override_scattered = data_result - .lookup_override::(ctx) - .map(|s| s.0); - let override_radius = data_result.lookup_override::(ctx).map(|r| r.0); - - // All the default values for a `PlotPoint`, accounting for both overrides and default - // values. - let default_point = PlotPoint { - time: 0, - value: 0.0, - attrs: PlotPointAttrs { - label: override_label.clone(), // default value is simply None - color: annotation_info.color(override_color, default_color), - marker_size: override_radius.unwrap_or(DEFAULT_RADIUS), - kind: if override_scattered.unwrap_or(false) { - PlotSeriesKind::Scatter(ScatterAttrs::default()) - } else { - PlotSeriesKind::Continuous - }, - }, - }; - - let mut points = Vec::new(); - - let time_range = determine_time_range( - ctx, - query, - data_result, - plot_bounds, - ctx.app_options.experimental_plot_query_clamping, - ); - - { - re_tracing::profile_scope!("primary", &data_result.entity_path.to_string()); - - let entity_path = &data_result.entity_path; - let query = re_data_store::RangeQuery::new(query.timeline, time_range); - - query_caches.query_archetype_range_pov1_comp4::< - TimeSeriesScalar, - Scalar, - ScalarScattering, - Color, - Radius, - Text, - _, - >( - store, - &query, - entity_path, - |_timeless, entry_range, (times, _, scalars, scatterings, colors, radii, labels)| { - let times = times.range(entry_range.clone()).map(|(time, _)| time.as_i64()); - - // Allocate all points. - points = times.map(|time| PlotPoint { - time, - ..default_point.clone() - }).collect_vec(); - - // Fill in values. - for (i, scalar) in scalars.range(entry_range.clone()).enumerate() { - if scalar.len() > 1 { - re_log::warn_once!("found a scalar batch in {entity_path:?} -- those have no effect"); - } else if scalar.is_empty() { - points[i].attrs.kind = PlotSeriesKind::Clear; - } else { - points[i].value = scalar.first().map_or(0.0, |s| s.0); - } - } - - // Make it as clear as possible to the optimizer that some parameters - // go completely unused as soon as overrides have been defined. - - // Fill in series kind -- if available _and_ not overridden. - if override_scattered.is_none() { - if let Some(scatterings) = scatterings { - for (i, scattered) in scatterings.range(entry_range.clone()).enumerate() { - if i >= points.len() { - re_log::debug_once!("more scattered attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; - } - if scattered.first().copied().flatten().map_or(false, |s| s.0) { - points[i].attrs.kind = PlotSeriesKind::Scatter(ScatterAttrs::default()); - }; - } - } - } - - // Fill in colors -- if available _and_ not overridden. - if override_color.is_none() { - if let Some(colors) = colors { - for (i, color) in colors.range(entry_range.clone()).enumerate() { - if i >= points.len() { - re_log::debug_once!("more color attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; - } - if let Some(color) = color.first().copied().flatten().map(|c| { - let [r,g,b,a] = c.to_array(); - if a == 255 { - // Common-case optimization - re_renderer::Color32::from_rgb(r, g, b) - } else { - re_renderer::Color32::from_rgba_unmultiplied(r, g, b, a) - } - }) { - points[i].attrs.color = color; - } - } - } - } - - // Fill in radii -- if available _and_ not overridden. - if override_radius.is_none() { - if let Some(radii) = radii { - for (i, radius) in radii.range(entry_range.clone()).enumerate() { - if i >= radii.num_entries() { - re_log::debug_once!("more radius attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; - } - if let Some(radius) = radius.first().copied().flatten().map(|r| r.0) { - points[i].attrs.marker_size = radius; - } - } - } - } - - // Fill in labels -- if available _and_ not overridden. - if override_label.is_none() { - if let Some(labels) = labels { - for (i, label) in labels.range(entry_range.clone()).enumerate() { - if i >= labels.num_entries() { - re_log::debug_once!("more label attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; - } - if let Some(label) = label.first().cloned().flatten().map(|l| l.0) { - points[i].attrs.label = Some(label); - } - } - } - } - }, - )?; - } - - // Now convert the `PlotPoints` into `Vec` - points_to_series( - data_result, - time_per_pixel, - points, - store, - query, - None, // Legacy visualizer labels its scalars, not the series. - &mut self.all_series, - ); - } - - Ok(()) - } -} diff --git a/crates/re_space_view_time_series/src/lib.rs b/crates/re_space_view_time_series/src/lib.rs index 3f0b23ee1dbc..d7c1cabc5cb7 100644 --- a/crates/re_space_view_time_series/src/lib.rs +++ b/crates/re_space_view_time_series/src/lib.rs @@ -3,7 +3,6 @@ //! A Space View that shows plots over Rerun timelines. mod aggregation; -mod legacy_visualizer_system; mod line_visualizer_system; mod overrides; mod point_visualizer_system; diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 1b76b4a2f2fc..b77b87db0524 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -19,7 +19,6 @@ use re_viewer_context::{ ViewerContext, VisualizableEntities, }; -use crate::legacy_visualizer_system::LegacyTimeSeriesSystem; use crate::line_visualizer_system::SeriesLineSystem; use crate::point_visualizer_system::SeriesPointSystem; use crate::PlotSeriesKind; @@ -121,7 +120,6 @@ impl SpaceViewClass for TimeSeriesSpaceView { &self, system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - system_registry.register_visualizer::()?; system_registry.register_visualizer::()?; system_registry.register_visualizer::()?; Ok(()) @@ -190,7 +188,6 @@ It can greatly improve performance (and readability) in such situations as it pr let mut indicated_entities = IndicatedEntities::default(); for indicated in [ - LegacyTimeSeriesSystem::identifier(), SeriesLineSystem::identifier(), SeriesPointSystem::identifier(), ] @@ -341,13 +338,10 @@ It can greatly improve performance (and readability) in such situations as it pr let timeline_name = timeline.name().to_string(); - let legacy_time_series = system_output.view_systems.get::()?; let line_series = system_output.view_systems.get::()?; let point_series = system_output.view_systems.get::()?; - let all_plot_series: Vec<_> = legacy_time_series - .all_series - .iter() + let all_plot_series: Vec<_> = std::iter::empty() .chain(line_series.all_series.iter()) .chain(point_series.all_series.iter()) .collect(); diff --git a/crates/re_types/definitions/rerun/archetypes.fbs b/crates/re_types/definitions/rerun/archetypes.fbs index a8837e79a9d7..4ddccbed02f3 100644 --- a/crates/re_types/definitions/rerun/archetypes.fbs +++ b/crates/re_types/definitions/rerun/archetypes.fbs @@ -22,7 +22,6 @@ include "./archetypes/series_point.fbs"; include "./archetypes/tensor.fbs"; include "./archetypes/text_document.fbs"; include "./archetypes/text_log.fbs"; -include "./archetypes/time_series_scalar.fbs"; include "./archetypes/transform3d.fbs"; include "./archetypes/view_coordinates.fbs"; diff --git a/crates/re_types/definitions/rerun/archetypes/time_series_scalar.fbs b/crates/re_types/definitions/rerun/archetypes/time_series_scalar.fbs deleted file mode 100644 index 26318824764e..000000000000 --- a/crates/re_types/definitions/rerun/archetypes/time_series_scalar.fbs +++ /dev/null @@ -1,79 +0,0 @@ -include "fbs/attributes.fbs"; - -include "rerun/attributes.fbs"; -include "rerun/datatypes.fbs"; -include "rerun/components.fbs"; - -namespace rerun.archetypes; - -// --- - -/// Log a double-precision scalar that will be visualized as a time-series plot. -/// -/// The current simulation time will be used for the time/X-axis, hence scalars -/// cannot be timeless! -/// -/// This archetype is in the process of being deprecated. Prefer usage of -/// `Scalar`, `SeriesLine`, and `SeriesPoint` instead. -/// -/// \py See also [`Scalar`][rerun.archetypes.Scalar], [`SeriesPoint`][rerun.archetypes.SeriesPoint], [`SeriesLine`][rerun.archetypes.SeriesLine]. -/// \rs See also [`Scalar`][crate::archetypes.Scalar], [`SeriesPoint`][crate::archetypes::SeriesPoint], [`SeriesLine`][crate::archetypes::SeriesLine]. -/// \cpp See also `rerun::archetypes::Scalar`, `rerun::archetypes::SeriesPoint`, `rerun::archetypes::SeriesLine`. -/// -/// \example scalar_simple title="Simple line plot" image="https://static.rerun.io/scalar_simple/8bcc92f56268739f8cd24d60d1fe72a655f62a46/1200w.png" -/// \example scalar_multiple_plots !api title="Multiple time series plots" image="https://static.rerun.io/scalar_multiple/15845c2a348f875248fbd694e03eabd922741c4c/1200w.png" -table TimeSeriesScalar ( - "attr.rerun.deprecated": "Use the `Scalar` + (optional) `SeriesLine`/`SeriesPoint` archetypes instead, logged on the same entity. See [0.13 migration guide](https://www.rerun.io/docs/reference/migration/migration-0-13).", - "attr.rust.derive": "PartialEq" -) { - // --- Required --- - - /// The scalar value to log. - scalar: rerun.components.Scalar ("attr.rerun.component_required", order: 1000); - - // --- Recommended --- - - /// An optional radius for the point. - /// - /// Points within a single line do not have to share the same radius, the line - /// will have differently sized segments as appropriate. - /// - /// If all points within a single entity path (i.e. a line) share the same - /// radius, then this radius will be used as the line width too. Otherwise, the - /// line will use the default width of `1.0`. - radius: rerun.components.Radius ("attr.rerun.component_recommended", nullable, order: 2000); - - /// Optional color for the scalar entry. - /// - /// If left unspecified, a pseudo-random color will be used instead. That - /// same color will apply to all points residing in the same entity path - /// that don't have a color specified. - /// - /// Points within a single line do not have to share the same color, the line - /// will have differently colored segments as appropriate. - /// If all points within a single entity path (i.e. a line) share the same - /// color, then this color will be used as the line color in the plot legend. - /// Otherwise, the line will appear gray in the legend. - color: rerun.components.Color ("attr.rerun.component_recommended", nullable, order: 2100); - - // --- Optional --- - - /// An optional label for the point. - /// - /// TODO(#1289): This won't show up on points at the moment, as our plots don't yet - /// support displaying labels for individual points. - /// If all points within a single entity path (i.e. a line) share the same label, then - /// this label will be used as the label for the line itself. Otherwise, the - /// line will be named after the entity path. The plot itself is named after - /// the space it's in. - label: rerun.components.Text ("attr.rerun.component_optional", nullable, order: 3000); - - /// Specifies whether a point in a scatter plot should form a continuous line. - /// - /// If set to true, this scalar will be drawn as a point, akin to a scatterplot. - /// Otherwise, it will form a continuous line with its neighbors. - /// Points within a single line do not have to all share the same scatteredness: - /// the line will switch between a scattered and a continuous representation as - /// required. - scattered: rerun.components.ScalarScattering ("attr.rerun.component_optional", nullable, order: 3100); -} diff --git a/crates/re_types/src/archetypes/.gitattributes b/crates/re_types/src/archetypes/.gitattributes index 386c8f9ca898..cc96164742f4 100644 --- a/crates/re_types/src/archetypes/.gitattributes +++ b/crates/re_types/src/archetypes/.gitattributes @@ -25,6 +25,5 @@ series_point.rs linguist-generated=true tensor.rs linguist-generated=true text_document.rs linguist-generated=true text_log.rs linguist-generated=true -time_series_scalar.rs linguist-generated=true transform3d.rs linguist-generated=true view_coordinates.rs linguist-generated=true diff --git a/crates/re_types/src/archetypes/mod.rs b/crates/re_types/src/archetypes/mod.rs index e349283f9c76..6ce5a6ebc872 100644 --- a/crates/re_types/src/archetypes/mod.rs +++ b/crates/re_types/src/archetypes/mod.rs @@ -36,7 +36,6 @@ mod tensor_ext; mod text_document; mod text_document_ext; mod text_log; -mod time_series_scalar; mod transform3d; mod transform3d_ext; mod view_coordinates; @@ -67,6 +66,3 @@ pub use self::text_document::TextDocument; pub use self::text_log::TextLog; pub use self::transform3d::Transform3D; pub use self::view_coordinates::ViewCoordinates; - -#[allow(deprecated)] -pub use self::time_series_scalar::TimeSeriesScalar; diff --git a/crates/re_types/src/archetypes/time_series_scalar.rs b/crates/re_types/src/archetypes/time_series_scalar.rs deleted file mode 100644 index 964b6f45d93f..000000000000 --- a/crates/re_types/src/archetypes/time_series_scalar.rs +++ /dev/null @@ -1,344 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/archetypes/time_series_scalar.fbs". - -#![allow(trivial_numeric_casts)] -#![allow(unused_imports)] -#![allow(unused_parens)] -#![allow(clippy::clone_on_copy)] -#![allow(clippy::iter_on_single_items)] -#![allow(clippy::map_flatten)] -#![allow(clippy::match_wildcard_for_single_variants)] -#![allow(clippy::needless_question_mark)] -#![allow(clippy::new_without_default)] -#![allow(clippy::redundant_closure)] -#![allow(clippy::too_many_arguments)] -#![allow(clippy::too_many_lines)] -#![allow(clippy::unnecessary_cast)] -#![allow(deprecated)] - -use ::re_types_core::external::arrow2; -use ::re_types_core::ComponentName; -use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; -use ::re_types_core::{DeserializationError, DeserializationResult}; - -/// **Archetype**: Log a double-precision scalar that will be visualized as a time-series plot. -/// -/// The current simulation time will be used for the time/X-axis, hence scalars -/// cannot be timeless! -/// -/// This archetype is in the process of being deprecated. Prefer usage of -/// `Scalar`, `SeriesLine`, and `SeriesPoint` instead. -/// -/// See also [`Scalar`][crate::archetypes.Scalar], [`SeriesPoint`][crate::archetypes::SeriesPoint], [`SeriesLine`][crate::archetypes::SeriesLine]. -/// -/// ## Example -/// -/// ### Simple line plot -/// ```ignore -/// fn main() -> Result<(), Box> { -/// let rec = rerun::RecordingStreamBuilder::new("rerun_example_scalar").spawn()?; -/// -/// // Log the data on a timeline called "step". -/// for step in 0..64 { -/// rec.set_time_sequence("step", step); -/// rec.log("scalar", &rerun::Scalar::new((step as f64 / 10.0).sin()))?; -/// } -/// -/// Ok(()) -/// } -/// ``` -///
-/// -/// -/// -/// -/// -/// -/// -///
-#[derive(Clone, Debug, PartialEq)] -#[deprecated( - note = "Use the `Scalar` + (optional) `SeriesLine`/`SeriesPoint` archetypes instead, logged on the same entity. See [0.13 migration guide](https://www.rerun.io/docs/reference/migration/migration-0-13)." -)] -pub struct TimeSeriesScalar { - /// The scalar value to log. - pub scalar: crate::components::Scalar, - - /// An optional radius for the point. - /// - /// Points within a single line do not have to share the same radius, the line - /// will have differently sized segments as appropriate. - /// - /// If all points within a single entity path (i.e. a line) share the same - /// radius, then this radius will be used as the line width too. Otherwise, the - /// line will use the default width of `1.0`. - pub radius: Option, - - /// Optional color for the scalar entry. - /// - /// If left unspecified, a pseudo-random color will be used instead. That - /// same color will apply to all points residing in the same entity path - /// that don't have a color specified. - /// - /// Points within a single line do not have to share the same color, the line - /// will have differently colored segments as appropriate. - /// If all points within a single entity path (i.e. a line) share the same - /// color, then this color will be used as the line color in the plot legend. - /// Otherwise, the line will appear gray in the legend. - pub color: Option, - - /// An optional label for the point. - /// - /// TODO(#1289): This won't show up on points at the moment, as our plots don't yet - /// support displaying labels for individual points. - /// If all points within a single entity path (i.e. a line) share the same label, then - /// this label will be used as the label for the line itself. Otherwise, the - /// line will be named after the entity path. The plot itself is named after - /// the space it's in. - pub label: Option, - - /// Specifies whether a point in a scatter plot should form a continuous line. - /// - /// If set to true, this scalar will be drawn as a point, akin to a scatterplot. - /// Otherwise, it will form a continuous line with its neighbors. - /// Points within a single line do not have to all share the same scatteredness: - /// the line will switch between a scattered and a continuous representation as - /// required. - pub scattered: Option, -} - -impl ::re_types_core::SizeBytes for TimeSeriesScalar { - #[inline] - fn heap_size_bytes(&self) -> u64 { - self.scalar.heap_size_bytes() - + self.radius.heap_size_bytes() - + self.color.heap_size_bytes() - + self.label.heap_size_bytes() - + self.scattered.heap_size_bytes() - } - - #[inline] - fn is_pod() -> bool { - ::is_pod() - && >::is_pod() - && >::is_pod() - && >::is_pod() - && >::is_pod() - } -} - -static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.Scalar".into()]); - -static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.Color".into(), - "rerun.components.Radius".into(), - "rerun.components.TimeSeriesScalarIndicator".into(), - ] - }); - -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.InstanceKey".into(), - "rerun.components.ScalarScattering".into(), - "rerun.components.Text".into(), - ] - }); - -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.Scalar".into(), - "rerun.components.Color".into(), - "rerun.components.Radius".into(), - "rerun.components.TimeSeriesScalarIndicator".into(), - "rerun.components.InstanceKey".into(), - "rerun.components.ScalarScattering".into(), - "rerun.components.Text".into(), - ] - }); - -impl TimeSeriesScalar { - pub const NUM_COMPONENTS: usize = 7usize; -} - -/// Indicator component for the [`TimeSeriesScalar`] [`::re_types_core::Archetype`] -pub type TimeSeriesScalarIndicator = ::re_types_core::GenericIndicatorComponent; - -impl ::re_types_core::Archetype for TimeSeriesScalar { - type Indicator = TimeSeriesScalarIndicator; - - #[inline] - fn name() -> ::re_types_core::ArchetypeName { - "rerun.archetypes.TimeSeriesScalar".into() - } - - #[inline] - fn indicator() -> MaybeOwnedComponentBatch<'static> { - static INDICATOR: TimeSeriesScalarIndicator = TimeSeriesScalarIndicator::DEFAULT; - MaybeOwnedComponentBatch::Ref(&INDICATOR) - } - - #[inline] - fn required_components() -> ::std::borrow::Cow<'static, [ComponentName]> { - REQUIRED_COMPONENTS.as_slice().into() - } - - #[inline] - fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentName]> { - RECOMMENDED_COMPONENTS.as_slice().into() - } - - #[inline] - fn optional_components() -> ::std::borrow::Cow<'static, [ComponentName]> { - OPTIONAL_COMPONENTS.as_slice().into() - } - - #[inline] - fn all_components() -> ::std::borrow::Cow<'static, [ComponentName]> { - ALL_COMPONENTS.as_slice().into() - } - - #[inline] - fn from_arrow_components( - arrow_data: impl IntoIterator)>, - ) -> DeserializationResult { - re_tracing::profile_function!(); - use ::re_types_core::{Loggable as _, ResultExt as _}; - let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data - .into_iter() - .map(|(name, array)| (name.full_name(), array)) - .collect(); - let scalar = { - let array = arrays_by_name - .get("rerun.components.Scalar") - .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.archetypes.TimeSeriesScalar#scalar")?; - ::from_arrow_opt(&**array) - .with_context("rerun.archetypes.TimeSeriesScalar#scalar")? - .into_iter() - .next() - .flatten() - .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.archetypes.TimeSeriesScalar#scalar")? - }; - let radius = if let Some(array) = arrays_by_name.get("rerun.components.Radius") { - ::from_arrow_opt(&**array) - .with_context("rerun.archetypes.TimeSeriesScalar#radius")? - .into_iter() - .next() - .flatten() - } else { - None - }; - let color = if let Some(array) = arrays_by_name.get("rerun.components.Color") { - ::from_arrow_opt(&**array) - .with_context("rerun.archetypes.TimeSeriesScalar#color")? - .into_iter() - .next() - .flatten() - } else { - None - }; - let label = if let Some(array) = arrays_by_name.get("rerun.components.Text") { - ::from_arrow_opt(&**array) - .with_context("rerun.archetypes.TimeSeriesScalar#label")? - .into_iter() - .next() - .flatten() - } else { - None - }; - let scattered = if let Some(array) = arrays_by_name.get("rerun.components.ScalarScattering") - { - ::from_arrow_opt(&**array) - .with_context("rerun.archetypes.TimeSeriesScalar#scattered")? - .into_iter() - .next() - .flatten() - } else { - None - }; - Ok(Self { - scalar, - radius, - color, - label, - scattered, - }) - } -} - -impl ::re_types_core::AsComponents for TimeSeriesScalar { - fn as_component_batches(&self) -> Vec> { - re_tracing::profile_function!(); - use ::re_types_core::Archetype as _; - [ - Some(Self::indicator()), - Some((&self.scalar as &dyn ComponentBatch).into()), - self.radius - .as_ref() - .map(|comp| (comp as &dyn ComponentBatch).into()), - self.color - .as_ref() - .map(|comp| (comp as &dyn ComponentBatch).into()), - self.label - .as_ref() - .map(|comp| (comp as &dyn ComponentBatch).into()), - self.scattered - .as_ref() - .map(|comp| (comp as &dyn ComponentBatch).into()), - ] - .into_iter() - .flatten() - .collect() - } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } -} - -impl TimeSeriesScalar { - pub fn new(scalar: impl Into) -> Self { - Self { - scalar: scalar.into(), - radius: None, - color: None, - label: None, - scattered: None, - } - } - - #[inline] - pub fn with_radius(mut self, radius: impl Into) -> Self { - self.radius = Some(radius.into()); - self - } - - #[inline] - pub fn with_color(mut self, color: impl Into) -> Self { - self.color = Some(color.into()); - self - } - - #[inline] - pub fn with_label(mut self, label: impl Into) -> Self { - self.label = Some(label.into()); - self - } - - #[inline] - pub fn with_scattered( - mut self, - scattered: impl Into, - ) -> Self { - self.scattered = Some(scattered.into()); - self - } -} diff --git a/docs/content/getting-started/viewer-walkthrough.md b/docs/content/getting-started/viewer-walkthrough.md index e88b569eb059..3c22802b6e74 100644 --- a/docs/content/getting-started/viewer-walkthrough.md +++ b/docs/content/getting-started/viewer-walkthrough.md @@ -125,7 +125,7 @@ primitives, also known as [entities](../concepts/entity-component.md): * a [pinhole](../reference/types/archetypes/pinhole.md) camera model that describes the relationship between 2D and 3D space. * [3D points](../reference/types/archetypes/points3d.md) that were computed by the COLMAP slam pipeline. * A sequence of [transforms](../reference/types/archetypes/transform3d.md) describing the 3D location of the camera in space. -* A [scalar](../reference/types/archetypes/time_series_scalar.md) error metric that was computed by the algorithm for each frame. +* A [scalar](../reference/types/archetypes/scalar.md) error metric that was computed by the algorithm for each frame. ### Hover and selection You can find out more about these entities by hovering over them in the different views. Hovering will bring up a diff --git a/docs/content/howto/ros2-nav-turtlebot.md b/docs/content/howto/ros2-nav-turtlebot.md index a13e934bdf54..f7f4328de4c6 100644 --- a/docs/content/howto/ros2-nav-turtlebot.md +++ b/docs/content/howto/ros2-nav-turtlebot.md @@ -112,8 +112,8 @@ If you are familiar with the turtlebot nav example and rviz, this view will like * `map/robot/camera/points` contains a `PointCloud2` msg logged as a [point3d](../reference/types/archetypes/points3d.md). * `map/points` contains a second copy of `PointCloud2` with a different transform. (This is a workaround until Rerun has support for ROS-style fixed frames [#1522](https://github.com/rerun-io/rerun/issues/1522).) - * `odometry/vel` is a plot of the linear velocity of the robot logged as a [scalar](../reference/types/archetypes/time_series_scalar.md). - * `odometry/ang_vel` is a plot of the angular velocity of the robot logged as a [scalar](../reference/types/archetypes/time_series_scalar.md). + * `odometry/vel` is a plot of the linear velocity of the robot logged as a [scalar](../reference/types/archetypes/scalar.md). + * `odometry/ang_vel` is a plot of the angular velocity of the robot logged as a [scalar](../reference/types/archetypes/scalar.md). ## Code Explanation diff --git a/docs/content/reference/migration/migration-0-13.md b/docs/content/reference/migration/migration-0-13.md index 6ca5a0cb4b5f..28cade6f3aad 100644 --- a/docs/content/reference/migration/migration-0-13.md +++ b/docs/content/reference/migration/migration-0-13.md @@ -3,16 +3,16 @@ title: Migrating from 0.12 to 0.13 order: 11 --- -## [TimeSeriesScalar](../types/archetypes/time_series_scalar.md) deprecated in favor of [Scalar](../types/archetypes/scalar.md) & [SeriesLine](../types/archetypes/series_line.md)/[SeriesPoint](../types/archetypes/series_point.md) +## `TimeSeriesScalar` deprecated in favor of [Scalar](../types/archetypes/scalar.md) & [SeriesLine](../types/archetypes/series_line.md)/[SeriesPoint](../types/archetypes/series_point.md) -Previously, [TimeSeriesScalar](../types/archetypes/time_series_scalar.md) was used to define both +Previously, `TimeSeriesScalar` was used to define both data and styling of time series plots. Going forward, this is done separately: data is now logged via [Scalar](../types/archetypes/scalar.md). Styling for point/marker series via [SeriesPoint](../types/archetypes/series_point.md) and styling for line series via [SeriesLine](../types/archetypes/series_line.md). (Both styling archetypes are typically logged as `timeless` but this is not a requirement and any property may change over time!) -[TimeSeriesScalar](../types/archetypes/time_series_scalar.md) will be removed in a future release. +`TimeSeriesScalar` will be removed in a future release. ## Changes in Space View creation heuristics diff --git a/docs/content/reference/migration/migration-0-9.md b/docs/content/reference/migration/migration-0-9.md index 3b18d7a4e1d2..38c28369a764 100644 --- a/docs/content/reference/migration/migration-0-9.md +++ b/docs/content/reference/migration/migration-0-9.md @@ -195,9 +195,7 @@ Notes: - `identifiers` has become `instance_keys`. ### log_scalar -Replace with [TimeSeriesScalar](../types/archetypes/time_series_scalar.md) - -Python docs: [TimeSeriesScalar](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.TimeSeriesScalar) +Replace with `TimeSeriesScalar` ### log_segmentation_image Replace with [SegmentationImage](../types/archetypes/segmentation_image.md) diff --git a/docs/content/reference/types.md b/docs/content/reference/types.md index d6286a445256..ea9fd7fa17a1 100644 --- a/docs/content/reference/types.md +++ b/docs/content/reference/types.md @@ -51,7 +51,6 @@ generic container for arrays of data. Images are restricted to tensors of rank 2 - [Scalar](types/archetypes/scalar.md): a single scalar / metric value. - [SeriesPoint](types/archetypes/series_point.md): define the style properties for a point series in a chart. - [SeriesLine](types/archetypes/series_line.md): define the style properties for a line series in a chart. -- [TimeSeriesScalar (deprecated)](types/archetypes/time_series_scalar.md): a single scalar / metric value as well as styling options. Can be viewed in the `TimeSeries` space view. ## Other **Archetypes** diff --git a/docs/content/reference/types/archetypes.md b/docs/content/reference/types/archetypes.md index 9997df3b12f7..36b682a1e4a5 100644 --- a/docs/content/reference/types/archetypes.md +++ b/docs/content/reference/types/archetypes.md @@ -33,8 +33,3 @@ Archetypes are bundles of components * [`TextLog`](archetypes/text_log.md) * [`Transform3D`](archetypes/transform3d.md) * [`ViewCoordinates`](archetypes/view_coordinates.md) - - -## Deprecated archetypes - -* [`TimeSeriesScalar`](archetypes/time_series_scalar.md) diff --git a/docs/content/reference/types/archetypes/.gitattributes b/docs/content/reference/types/archetypes/.gitattributes index c40751970306..5035912305cd 100644 --- a/docs/content/reference/types/archetypes/.gitattributes +++ b/docs/content/reference/types/archetypes/.gitattributes @@ -25,6 +25,5 @@ series_point.md linguist-generated=true tensor.md linguist-generated=true text_document.md linguist-generated=true text_log.md linguist-generated=true -time_series_scalar.md linguist-generated=true transform3d.md linguist-generated=true view_coordinates.md linguist-generated=true diff --git a/docs/content/reference/types/archetypes/time_series_scalar.md b/docs/content/reference/types/archetypes/time_series_scalar.md deleted file mode 100644 index adddd41abef6..000000000000 --- a/docs/content/reference/types/archetypes/time_series_scalar.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "TimeSeriesScalar (deprecated)" ---- - -**⚠️ This type is deprecated and may be removed in future versions** -Use the `Scalar` + (optional) `SeriesLine`/`SeriesPoint` archetypes instead, logged on the same entity. See [0.13 migration guide](https://www.rerun.io/docs/reference/migration/migration-0-13). - -Log a double-precision scalar that will be visualized as a time-series plot. - -The current simulation time will be used for the time/X-axis, hence scalars -cannot be timeless! - -This archetype is in the process of being deprecated. Prefer usage of -`Scalar`, `SeriesLine`, and `SeriesPoint` instead. - -## Components - -**Required**: [`Scalar`](../components/scalar.md) - -**Recommended**: [`Radius`](../components/radius.md), [`Color`](../components/color.md) - -**Optional**: [`Text`](../components/text.md), [`ScalarScattering`](../components/scalar_scattering.md) - -## Links - * 🌊 [C++ API docs for `TimeSeriesScalar`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1archetypes_1_1TimeSeriesScalar.html) - * 🐍 [Python API docs for `TimeSeriesScalar`](https://ref.rerun.io/docs/python/stable/common/archetypes#rerun.archetypes.TimeSeriesScalar) - * 🦀 [Rust API docs for `TimeSeriesScalar`](https://docs.rs/rerun/latest/rerun/archetypes/struct.TimeSeriesScalar.html) - -## Examples - -### Simple line plot - -snippet: scalar_simple - - - - - - - - - -### Multiple time series plots - -snippet: scalar_multiple_plots - - - - - - - - - diff --git a/docs/content/reference/types/components/color.md b/docs/content/reference/types/components/color.md index 0549921ebdf8..d412ebb62db4 100644 --- a/docs/content/reference/types/components/color.md +++ b/docs/content/reference/types/components/color.md @@ -32,4 +32,3 @@ byte is `R` and the least significant byte is `A`. * [`SeriesLine`](../archetypes/series_line.md) * [`SeriesPoint`](../archetypes/series_point.md) * [`TextLog`](../archetypes/text_log.md) -* [`TimeSeriesScalar`](../archetypes/time_series_scalar.md) diff --git a/docs/content/reference/types/components/radius.md b/docs/content/reference/types/components/radius.md index 1b20693fcafa..5e0f5ed7dd77 100644 --- a/docs/content/reference/types/components/radius.md +++ b/docs/content/reference/types/components/radius.md @@ -24,4 +24,3 @@ A Radius component. * [`LineStrips3D`](../archetypes/line_strips3d.md) * [`Points2D`](../archetypes/points2d.md) * [`Points3D`](../archetypes/points3d.md) -* [`TimeSeriesScalar`](../archetypes/time_series_scalar.md) diff --git a/docs/content/reference/types/components/scalar.md b/docs/content/reference/types/components/scalar.md index 3d1034b18eae..616d384d745b 100644 --- a/docs/content/reference/types/components/scalar.md +++ b/docs/content/reference/types/components/scalar.md @@ -19,4 +19,3 @@ Used for time series plots. ## Used by * [`Scalar`](../archetypes/scalar.md) -* [`TimeSeriesScalar`](../archetypes/time_series_scalar.md) diff --git a/docs/content/reference/types/components/scalar_scattering.md b/docs/content/reference/types/components/scalar_scattering.md index dbd022d4e646..a2218a6bd86d 100644 --- a/docs/content/reference/types/components/scalar_scattering.md +++ b/docs/content/reference/types/components/scalar_scattering.md @@ -14,6 +14,3 @@ If true, a scalar will be shown as individual point in a scatter plot. * 🦀 [Rust API docs for `ScalarScattering`](https://docs.rs/rerun/latest/rerun/components/struct.ScalarScattering.html) -## Used by - -* [`TimeSeriesScalar`](../archetypes/time_series_scalar.md) diff --git a/docs/content/reference/types/components/text.md b/docs/content/reference/types/components/text.md index d0e239ada355..980b18cf06fd 100644 --- a/docs/content/reference/types/components/text.md +++ b/docs/content/reference/types/components/text.md @@ -26,4 +26,3 @@ A string of text, e.g. for labels and text documents. * [`Points3D`](../archetypes/points3d.md) * [`TextDocument`](../archetypes/text_document.md) * [`TextLog`](../archetypes/text_log.md) -* [`TimeSeriesScalar`](../archetypes/time_series_scalar.md) diff --git a/rerun_cpp/src/rerun/archetypes.hpp b/rerun_cpp/src/rerun/archetypes.hpp index a7bab709edaa..f001bdc6d371 100644 --- a/rerun_cpp/src/rerun/archetypes.hpp +++ b/rerun_cpp/src/rerun/archetypes.hpp @@ -26,6 +26,5 @@ #include "archetypes/tensor.hpp" #include "archetypes/text_document.hpp" #include "archetypes/text_log.hpp" -#include "archetypes/time_series_scalar.hpp" #include "archetypes/transform3d.hpp" #include "archetypes/view_coordinates.hpp" diff --git a/rerun_cpp/src/rerun/archetypes/.gitattributes b/rerun_cpp/src/rerun/archetypes/.gitattributes index 5a8d85a0149a..395fe533c718 100644 --- a/rerun_cpp/src/rerun/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/archetypes/.gitattributes @@ -49,8 +49,6 @@ text_document.cpp linguist-generated=true text_document.hpp linguist-generated=true text_log.cpp linguist-generated=true text_log.hpp linguist-generated=true -time_series_scalar.cpp linguist-generated=true -time_series_scalar.hpp linguist-generated=true transform3d.cpp linguist-generated=true transform3d.hpp linguist-generated=true view_coordinates.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/archetypes/time_series_scalar.cpp b/rerun_cpp/src/rerun/archetypes/time_series_scalar.cpp deleted file mode 100644 index 576473bb44a2..000000000000 --- a/rerun_cpp/src/rerun/archetypes/time_series_scalar.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/archetypes/time_series_scalar.fbs". - -#include "time_series_scalar.hpp" - -#include "../collection_adapter_builtins.hpp" - -RR_PUSH_WARNINGS -RR_DISABLE_DEPRECATION_WARNING - -namespace rerun::archetypes {} - -namespace rerun { - - Result> AsComponents::serialize( - const archetypes::TimeSeriesScalar& archetype - ) { - using namespace archetypes; - std::vector cells; - cells.reserve(6); - - { - auto result = DataCell::from_loggable(archetype.scalar); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); - } - if (archetype.radius.has_value()) { - auto result = DataCell::from_loggable(archetype.radius.value()); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); - } - if (archetype.color.has_value()) { - auto result = DataCell::from_loggable(archetype.color.value()); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); - } - if (archetype.label.has_value()) { - auto result = DataCell::from_loggable(archetype.label.value()); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); - } - if (archetype.scattered.has_value()) { - auto result = DataCell::from_loggable(archetype.scattered.value()); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); - } - { - auto indicator = TimeSeriesScalar::IndicatorComponent(); - auto result = DataCell::from_loggable(indicator); - RR_RETURN_NOT_OK(result.error); - cells.emplace_back(std::move(result.value)); - } - - return cells; - } -} // namespace rerun - -RR_POP_WARNINGS diff --git a/rerun_cpp/src/rerun/archetypes/time_series_scalar.hpp b/rerun_cpp/src/rerun/archetypes/time_series_scalar.hpp deleted file mode 100644 index 44f2d97141ef..000000000000 --- a/rerun_cpp/src/rerun/archetypes/time_series_scalar.hpp +++ /dev/null @@ -1,197 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/archetypes/time_series_scalar.fbs". - -#pragma once - -#include "../collection.hpp" -#include "../compiler_utils.hpp" -#include "../components/color.hpp" -#include "../components/radius.hpp" -#include "../components/scalar.hpp" -#include "../components/scalar_scattering.hpp" -#include "../components/text.hpp" -#include "../data_cell.hpp" -#include "../indicator_component.hpp" -#include "../result.hpp" - -#include -#include -#include -#include - -namespace rerun::archetypes { - /// **Archetype**: Log a double-precision scalar that will be visualized as a time-series plot. - /// - /// The current simulation time will be used for the time/X-axis, hence scalars - /// cannot be timeless! - /// - /// This archetype is in the process of being deprecated. Prefer usage of - /// `Scalar`, `SeriesLine`, and `SeriesPoint` instead. - /// - /// See also `rerun::archetypes::Scalar`, `rerun::archetypes::SeriesPoint`, `rerun::archetypes::SeriesLine`. - /// - /// ## Example - /// - /// ### Simple line plot - /// ![image](https://static.rerun.io/scalar_simple/8bcc92f56268739f8cd24d60d1fe72a655f62a46/full.png) - /// - /// ```cpp - /// #include - /// - /// #include - /// - /// int main() { - /// const auto rec = rerun::RecordingStream("rerun_example_scalar"); - /// rec.spawn().exit_on_failure(); - /// - /// // Log the data on a timeline called "step". - /// for (int step = 0; step <64; ++step) { - /// rec.set_time_sequence("step", step); - /// rec.log("scalar", rerun::Scalar(std::sin(static_cast(step) / 10.0))); - /// } - /// } - /// ``` - struct [[deprecated( - "Use the `Scalar` + (optional) `SeriesLine`/`SeriesPoint` archetypes instead, logged on the same entity. See [0.13 migration guide](https://www.rerun.io/docs/reference/migration/migration-0-13)." - )]] TimeSeriesScalar { - /// The scalar value to log. - rerun::components::Scalar scalar; - - /// An optional radius for the point. - /// - /// Points within a single line do not have to share the same radius, the line - /// will have differently sized segments as appropriate. - /// - /// If all points within a single entity path (i.e. a line) share the same - /// radius, then this radius will be used as the line width too. Otherwise, the - /// line will use the default width of `1.0`. - std::optional radius; - - /// Optional color for the scalar entry. - /// - /// If left unspecified, a pseudo-random color will be used instead. That - /// same color will apply to all points residing in the same entity path - /// that don't have a color specified. - /// - /// Points within a single line do not have to share the same color, the line - /// will have differently colored segments as appropriate. - /// If all points within a single entity path (i.e. a line) share the same - /// color, then this color will be used as the line color in the plot legend. - /// Otherwise, the line will appear gray in the legend. - std::optional color; - - /// An optional label for the point. - /// - /// TODO(#1289): This won't show up on points at the moment, as our plots don't yet - /// support displaying labels for individual points. - /// If all points within a single entity path (i.e. a line) share the same label, then - /// this label will be used as the label for the line itself. Otherwise, the - /// line will be named after the entity path. The plot itself is named after - /// the space it's in. - std::optional label; - - /// Specifies whether a point in a scatter plot should form a continuous line. - /// - /// If set to true, this scalar will be drawn as a point, akin to a scatterplot. - /// Otherwise, it will form a continuous line with its neighbors. - /// Points within a single line do not have to all share the same scatteredness: - /// the line will switch between a scattered and a continuous representation as - /// required. - std::optional scattered; - - public: - static constexpr const char IndicatorComponentName[] = - "rerun.components.TimeSeriesScalarIndicator"; - - /// Indicator component, used to identify the archetype when converting to a list of components. - using IndicatorComponent = rerun::components::IndicatorComponent; - - public: - TimeSeriesScalar() = default; - TimeSeriesScalar(TimeSeriesScalar&& other) = default; - - explicit TimeSeriesScalar(rerun::components::Scalar _scalar) : scalar(std::move(_scalar)) {} - - /// An optional radius for the point. - /// - /// Points within a single line do not have to share the same radius, the line - /// will have differently sized segments as appropriate. - /// - /// If all points within a single entity path (i.e. a line) share the same - /// radius, then this radius will be used as the line width too. Otherwise, the - /// line will use the default width of `1.0`. - TimeSeriesScalar with_radius(rerun::components::Radius _radius) && { - radius = std::move(_radius); - // See: https://github.com/rerun-io/rerun/issues/4027 - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) - } - - /// Optional color for the scalar entry. - /// - /// If left unspecified, a pseudo-random color will be used instead. That - /// same color will apply to all points residing in the same entity path - /// that don't have a color specified. - /// - /// Points within a single line do not have to share the same color, the line - /// will have differently colored segments as appropriate. - /// If all points within a single entity path (i.e. a line) share the same - /// color, then this color will be used as the line color in the plot legend. - /// Otherwise, the line will appear gray in the legend. - TimeSeriesScalar with_color(rerun::components::Color _color) && { - color = std::move(_color); - // See: https://github.com/rerun-io/rerun/issues/4027 - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) - } - - /// An optional label for the point. - /// - /// TODO(#1289): This won't show up on points at the moment, as our plots don't yet - /// support displaying labels for individual points. - /// If all points within a single entity path (i.e. a line) share the same label, then - /// this label will be used as the label for the line itself. Otherwise, the - /// line will be named after the entity path. The plot itself is named after - /// the space it's in. - TimeSeriesScalar with_label(rerun::components::Text _label) && { - label = std::move(_label); - // See: https://github.com/rerun-io/rerun/issues/4027 - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) - } - - /// Specifies whether a point in a scatter plot should form a continuous line. - /// - /// If set to true, this scalar will be drawn as a point, akin to a scatterplot. - /// Otherwise, it will form a continuous line with its neighbors. - /// Points within a single line do not have to all share the same scatteredness: - /// the line will switch between a scattered and a continuous representation as - /// required. - TimeSeriesScalar with_scattered(rerun::components::ScalarScattering _scattered) && { - scattered = std::move(_scattered); - // See: https://github.com/rerun-io/rerun/issues/4027 - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) - } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } - }; - -} // namespace rerun::archetypes - -namespace rerun { - /// \private - template - struct AsComponents; - RR_PUSH_WARNINGS - RR_DISABLE_DEPRECATION_WARNING - - /// \private - template <> - struct AsComponents { - /// Serialize all set component batches. - static Result> serialize(const archetypes::TimeSeriesScalar& archetype - ); - }; - - RR_POP_WARNINGS -} // namespace rerun diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 66a2d5446046..2fb852bc90e9 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -168,7 +168,6 @@ class Section: "archetypes.Scalar", "archetypes.SeriesLine", "archetypes.SeriesPoint", - "archetypes.TimeSeriesScalar", ], gen_page=False, ), diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 5cd47eb194f4..797d714460de 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -56,7 +56,6 @@ "TextDocument", "TextLog", "TextLogLevel", - "TimeSeriesScalar", "Transform3D", "TranslationAndMat3x3", "TranslationRotationScale3D", @@ -137,7 +136,6 @@ Tensor, TextDocument, TextLog, - TimeSeriesScalar, Transform3D, ViewCoordinates, ) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes index 8f3d7cf6da30..d249edf2df81 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/archetypes/.gitattributes @@ -26,6 +26,5 @@ series_point.py linguist-generated=true tensor.py linguist-generated=true text_document.py linguist-generated=true text_log.py linguist-generated=true -time_series_scalar.py linguist-generated=true transform3d.py linguist-generated=true view_coordinates.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/archetypes/__init__.py index 554869557102..6b6b4e518c5f 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/__init__.py @@ -26,7 +26,6 @@ from .tensor import Tensor from .text_document import TextDocument from .text_log import TextLog -from .time_series_scalar import TimeSeriesScalar from .transform3d import Transform3D from .view_coordinates import ViewCoordinates @@ -55,7 +54,6 @@ "Tensor", "TextDocument", "TextLog", - "TimeSeriesScalar", "Transform3D", "ViewCoordinates", ] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/time_series_scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/time_series_scalar.py deleted file mode 100644 index 56a076fca967..000000000000 --- a/rerun_py/rerun_sdk/rerun/archetypes/time_series_scalar.py +++ /dev/null @@ -1,218 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/archetypes/time_series_scalar.fbs". - -# You can extend this class by creating a "TimeSeriesScalarExt" class in "time_series_scalar_ext.py". - -from __future__ import annotations - -from typing import Any - -from attrs import define, field -from typing_extensions import deprecated # type: ignore[misc, unused-ignore] - -from .. import components, datatypes -from .._baseclasses import Archetype -from ..error_utils import catch_and_log_exceptions - -__all__ = ["TimeSeriesScalar"] - - -@deprecated( - """Use the `Scalar` + (optional) `SeriesLine`/`SeriesPoint` archetypes instead, logged on the same entity. See [0.13 migration guide](https://www.rerun.io/docs/reference/migration/migration-0-13).""" -) -@define(str=False, repr=False, init=False) -class TimeSeriesScalar(Archetype): - """ - **Archetype**: Log a double-precision scalar that will be visualized as a time-series plot. - - The current simulation time will be used for the time/X-axis, hence scalars - cannot be timeless! - - This archetype is in the process of being deprecated. Prefer usage of - `Scalar`, `SeriesLine`, and `SeriesPoint` instead. - - See also [`Scalar`][rerun.archetypes.Scalar], [`SeriesPoint`][rerun.archetypes.SeriesPoint], [`SeriesLine`][rerun.archetypes.SeriesLine]. - - Example - ------- - ### Simple line plot: - ```python - import math - - import rerun as rr - - rr.init("rerun_example_scalar", spawn=True) - - # Log the data on a timeline called "step". - for step in range(0, 64): - rr.set_time_sequence("step", step) - rr.log("scalar", rr.Scalar(math.sin(step / 10.0))) - ``` -
- - - - - - - -
- - """ - - def __init__( - self: Any, - scalar: components.ScalarLike, - *, - radius: components.RadiusLike | None = None, - color: datatypes.Rgba32Like | None = None, - label: datatypes.Utf8Like | None = None, - scattered: components.ScalarScatteringLike | None = None, - ): - """ - Create a new instance of the TimeSeriesScalar archetype. - - Parameters - ---------- - scalar: - The scalar value to log. - radius: - An optional radius for the point. - - Points within a single line do not have to share the same radius, the line - will have differently sized segments as appropriate. - - If all points within a single entity path (i.e. a line) share the same - radius, then this radius will be used as the line width too. Otherwise, the - line will use the default width of `1.0`. - color: - Optional color for the scalar entry. - - If left unspecified, a pseudo-random color will be used instead. That - same color will apply to all points residing in the same entity path - that don't have a color specified. - - Points within a single line do not have to share the same color, the line - will have differently colored segments as appropriate. - If all points within a single entity path (i.e. a line) share the same - color, then this color will be used as the line color in the plot legend. - Otherwise, the line will appear gray in the legend. - label: - An optional label for the point. - - TODO(#1289): This won't show up on points at the moment, as our plots don't yet - support displaying labels for individual points. - If all points within a single entity path (i.e. a line) share the same label, then - this label will be used as the label for the line itself. Otherwise, the - line will be named after the entity path. The plot itself is named after - the space it's in. - scattered: - Specifies whether a point in a scatter plot should form a continuous line. - - If set to true, this scalar will be drawn as a point, akin to a scatterplot. - Otherwise, it will form a continuous line with its neighbors. - Points within a single line do not have to all share the same scatteredness: - the line will switch between a scattered and a continuous representation as - required. - - """ - - # You can define your own __init__ function as a member of TimeSeriesScalarExt in time_series_scalar_ext.py - with catch_and_log_exceptions(context=self.__class__.__name__): - self.__attrs_init__(scalar=scalar, radius=radius, color=color, label=label, scattered=scattered) - return - self.__attrs_clear__() - - def __attrs_clear__(self) -> None: - """Convenience method for calling `__attrs_init__` with all `None`s.""" - self.__attrs_init__( - scalar=None, # type: ignore[arg-type] - radius=None, # type: ignore[arg-type] - color=None, # type: ignore[arg-type] - label=None, # type: ignore[arg-type] - scattered=None, # type: ignore[arg-type] - ) - - @classmethod - def _clear(cls) -> TimeSeriesScalar: - """Produce an empty TimeSeriesScalar, bypassing `__init__`.""" - inst = cls.__new__(cls) - inst.__attrs_clear__() - return inst - - scalar: components.ScalarBatch = field( - metadata={"component": "required"}, - converter=components.ScalarBatch._required, # type: ignore[misc] - ) - # The scalar value to log. - # - # (Docstring intentionally commented out to hide this field from the docs) - - radius: components.RadiusBatch | None = field( - metadata={"component": "optional"}, - default=None, - converter=components.RadiusBatch._optional, # type: ignore[misc] - ) - # An optional radius for the point. - # - # Points within a single line do not have to share the same radius, the line - # will have differently sized segments as appropriate. - # - # If all points within a single entity path (i.e. a line) share the same - # radius, then this radius will be used as the line width too. Otherwise, the - # line will use the default width of `1.0`. - # - # (Docstring intentionally commented out to hide this field from the docs) - - color: components.ColorBatch | None = field( - metadata={"component": "optional"}, - default=None, - converter=components.ColorBatch._optional, # type: ignore[misc] - ) - # Optional color for the scalar entry. - # - # If left unspecified, a pseudo-random color will be used instead. That - # same color will apply to all points residing in the same entity path - # that don't have a color specified. - # - # Points within a single line do not have to share the same color, the line - # will have differently colored segments as appropriate. - # If all points within a single entity path (i.e. a line) share the same - # color, then this color will be used as the line color in the plot legend. - # Otherwise, the line will appear gray in the legend. - # - # (Docstring intentionally commented out to hide this field from the docs) - - label: components.TextBatch | None = field( - metadata={"component": "optional"}, - default=None, - converter=components.TextBatch._optional, # type: ignore[misc] - ) - # An optional label for the point. - # - # TODO(#1289): This won't show up on points at the moment, as our plots don't yet - # support displaying labels for individual points. - # If all points within a single entity path (i.e. a line) share the same label, then - # this label will be used as the label for the line itself. Otherwise, the - # line will be named after the entity path. The plot itself is named after - # the space it's in. - # - # (Docstring intentionally commented out to hide this field from the docs) - - scattered: components.ScalarScatteringBatch | None = field( - metadata={"component": "optional"}, - default=None, - converter=components.ScalarScatteringBatch._optional, # type: ignore[misc] - ) - # Specifies whether a point in a scatter plot should form a continuous line. - # - # If set to true, this scalar will be drawn as a point, akin to a scatterplot. - # Otherwise, it will form a continuous line with its neighbors. - # Points within a single line do not have to all share the same scatteredness: - # the line will switch between a scattered and a continuous representation as - # required. - # - # (Docstring intentionally commented out to hide this field from the docs) - - __str__ = Archetype.__str__ - __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/tests/python/release_checklist/check_container_hierarchy.py b/tests/python/release_checklist/check_container_hierarchy.py index fac16afd3384..3dd9bece9b44 100644 --- a/tests/python/release_checklist/check_container_hierarchy.py +++ b/tests/python/release_checklist/check_container_hierarchy.py @@ -72,14 +72,17 @@ def log_some_space_views() -> None: rr.log("points2d", rr.Points2D([[0, 0], [1, 1], [3, 2]], labels=["a", "b", "c"])) rr.log("points2d/bbx", rr.Boxes2D(centers=[1, 1], half_sizes=[3, 3])) + rr.log("plots/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), timeless=True) + rr.log("plots/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), timeless=True) + for t in range(0, int(tau * 2 * 10.0)): rr.set_time_sequence("frame_nr", t) sin_of_t = sin(float(t) / 10.0) - rr.log("plots/sin", rr.TimeSeriesScalar(sin_of_t, label="sin(0.01t)", color=[255, 0, 0])) + rr.log("plots/sin", rr.Scalar(sin_of_t)) cos_of_t = cos(float(t) / 10.0) - rr.log("plots/cos", rr.TimeSeriesScalar(cos_of_t, label="cos(0.01t)", color=[0, 255, 0])) + rr.log("plots/cos", rr.Scalar(cos_of_t)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py index e90604396a0d..e6bb9501ef9e 100644 --- a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py +++ b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py @@ -56,7 +56,7 @@ def log_some_space_views() -> None: for i in range(10): rr.set_time_sequence("frame_nr", i) - rr.log("timeseries", rr.TimeSeriesScalar(random.randint(0, 100))) + rr.log("timeseries", rr.Scalar(random.randint(0, 100))) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py index b2aeb3632c08..f307060b721b 100644 --- a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py +++ b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py @@ -48,14 +48,17 @@ def log_text_logs() -> None: def log_plots() -> None: from math import cos, sin, tau + rr.log("plots/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), timeless=True) + rr.log("plots/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), timeless=True) + for t in range(0, int(tau * 2 * 10.0)): rr.set_time_sequence("frame_nr", t) sin_of_t = sin(float(t) / 10.0) - rr.log("plots/sin", rr.TimeSeriesScalar(sin_of_t, label="sin(0.01t)", color=[255, 0, 0])) + rr.log("plots/sin", rr.Scalar(sin_of_t)) cos_of_t = cos(float(t) / 10.0) - rr.log("plots/cos", rr.TimeSeriesScalar(cos_of_t, label="cos(0.01t)", color=[0, 255, 0])) + rr.log("plots/cos", rr.Scalar(cos_of_t)) def log_spatial() -> None: diff --git a/tests/python/release_checklist/check_plot_overrides.py b/tests/python/release_checklist/check_plot_overrides.py index c52ebb5c1e65..7aecd2460ac3 100644 --- a/tests/python/release_checklist/check_plot_overrides.py +++ b/tests/python/release_checklist/check_plot_overrides.py @@ -43,14 +43,17 @@ def log_readme() -> None: def log_plots() -> None: from math import cos, sin, tau + rr.log("plots/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), timeless=True) + rr.log("plots/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), timeless=True) + for t in range(0, int(tau * 2 * 10.0)): rr.set_time_sequence("frame_nr", t) sin_of_t = sin(float(t) / 10.0) - rr.log("plots/sin", rr.TimeSeriesScalar(sin_of_t, label="sin(0.01t)", color=[255, 0, 0])) + rr.log("plots/sin", rr.Scalar(sin_of_t)) cos_of_t = cos(float(t) / 10.0) - rr.log("plots/cos", rr.TimeSeriesScalar(cos_of_t, label="cos(0.01t)", color=[0, 255, 0])) + rr.log("plots/cos", rr.Scalar(cos_of_t)) def run(args: Namespace) -> None: diff --git a/tests/python/release_checklist/check_scalar_clears.py b/tests/python/release_checklist/check_scalar_clears.py index 6bed4c3fbdfc..0a3691d08dad 100644 --- a/tests/python/release_checklist/check_scalar_clears.py +++ b/tests/python/release_checklist/check_scalar_clears.py @@ -36,7 +36,6 @@ def log_plots() -> None: if t > 30 and t < 90: rr.log("plots", rr.Clear(recursive=True)) else: - rr.log("plots/legacy", rr.TimeSeriesScalar(sin_of_t)) rr.log("plots/line", rr.Scalar(sin_of_t)) rr.log("plots/point", rr.Scalar(sin_of_t)) diff --git a/tests/roundtrips.py b/tests/roundtrips.py index 6745e6dd96e5..ba8c8e43f7d9 100755 --- a/tests/roundtrips.py +++ b/tests/roundtrips.py @@ -27,7 +27,6 @@ "bar_chart": ["cpp", "py", "rust"], # Don't need it, API example roundtrips cover it all "clear": ["cpp", "py", "rust"], # Don't need it, API example roundtrips cover it all "mesh3d": ["cpp", "py", "rust"], # Don't need it, API example roundtrips cover it all - "time_series_scalar": ["cpp", "py", "rust"], # Don't need it, API example roundtrips cover it all "scalar": ["cpp", "py", "rust"], # TODO(jleibs) "series_line": ["cpp", "py", "rust"], # TODO(jleibs) "series_point": ["cpp", "py", "rust"], # TODO(jleibs) From dc46941c388c5cee102d807191475d0f52ef379e Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 21 Mar 2024 09:15:57 +0100 Subject: [PATCH 078/508] =?UTF-8?q?Add=20option=20to=20include=20blueprint?= =?UTF-8?q?=20in=20an=20`.rrd`=20when=20calling=20`.save(=E2=80=A6)`=20(#5?= =?UTF-8?q?572)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What * Closes https://github.com/rerun-io/rerun/issues/5558 This adds an optional `blueprint` argument to `rr.save` which if provided, will end up first in the written .rrd file. When using `rr.script_setup` (like all our examples do) with a `blueprint`, `--save` will put that blueprint in the .rrd file. This should mean that the examples build by CI will include blueprints. **BONUS**: this also adds the blueprint to `rr.serve` and `rr.stdout` (and `--serve/--stdout` in our examples). ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5572/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5572/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5572/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5572) - [Docs preview](https://rerun.io/preview/3ec8fddde8caa12a00097353c257fdd60be9a48f/docs) - [Examples preview](https://rerun.io/preview/3ec8fddde8caa12a00097353c257fdd60be9a48f/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_build_examples/src/example.rs | 7 +- crates/re_build_info/src/build_info.rs | 4 + crates/re_sdk/src/recording_stream.rs | 79 +++++++++++++--- examples/python/structure_from_motion/main.py | 13 ++- rerun_py/rerun_sdk/rerun/script_helpers.py | 6 +- rerun_py/rerun_sdk/rerun/sinks.py | 94 +++++++++++++++---- rerun_py/src/python_bridge.rs | 53 +++++++---- 7 files changed, 201 insertions(+), 55 deletions(-) diff --git a/crates/re_build_examples/src/example.rs b/crates/re_build_examples/src/example.rs index bb1780f02a82..69f68b481705 100644 --- a/crates/re_build_examples/src/example.rs +++ b/crates/re_build_examples/src/example.rs @@ -160,10 +160,15 @@ pub struct ExampleCategory { #[derive(Default, Clone, Copy, serde::Deserialize, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum Channel { + /// Our main examples, built on each PR #[default] Main, - Nightly, + + /// Examples built for each release, plus all `Main` examples. Release, + + /// Examples built nightly, plus all `Main` and `Nightly`. + Nightly, } impl Channel { diff --git a/crates/re_build_info/src/build_info.rs b/crates/re_build_info/src/build_info.rs index 85934fc826b4..511d06197a89 100644 --- a/crates/re_build_info/src/build_info.rs +++ b/crates/re_build_info/src/build_info.rs @@ -113,6 +113,10 @@ impl std::fmt::Display for BuildInfo { write!(f, ", built {datetime}")?; } + if cfg!(debug_assertions) { + write!(f, " (debug)")?; + } + Ok(()) } } diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs index 35f0ff073e46..228df35375af 100644 --- a/crates/re_sdk/src/recording_stream.rs +++ b/crates/re_sdk/src/recording_stream.rs @@ -1554,20 +1554,7 @@ impl RecordingStream { // If a blueprint was provided, send it first. if let Some(blueprint) = blueprint { - let mut store_id = None; - for msg in blueprint { - if store_id.is_none() { - store_id = Some(msg.store_id().clone()); - } - sink.send(msg); - } - if let Some(store_id) = store_id { - // Let the viewer know that the blueprint has been fully received, - // and that it can now be activated. - // We don't want to activate half-loaded blueprints, because that can be confusing, - // and can also lead to problems with space-view heuristics. - sink.send(LogMsg::ActivateStore(store_id)); - } + Self::send_blueprint(blueprint, &sink); } self.set_sink(Box::new(sink)); @@ -1656,6 +1643,22 @@ impl RecordingStream { pub fn save( &self, path: impl Into, + ) -> Result<(), crate::sink::FileSinkError> { + self.save_opts(path, None) + } + + /// Swaps the underlying sink for a [`crate::sink::FileSink`] at the specified `path`. + /// + /// This is a convenience wrapper for [`Self::set_sink`] that upholds the same guarantees in + /// terms of data durability and ordering. + /// See [`Self::set_sink`] for more information. + /// + /// If a blueprint was provided, it will be stored first in the file. + /// Blueprints are currently an experimental part of the Rust SDK. + pub fn save_opts( + &self, + path: impl Into, + blueprint: Option>, ) -> Result<(), crate::sink::FileSinkError> { if forced_sink_path().is_some() { re_log::debug!("Ignored setting new file since _RERUN_FORCE_SINK is set"); @@ -1663,6 +1666,12 @@ impl RecordingStream { } let sink = crate::sink::FileSink::new(path)?; + + // If a blueprint was provided, store it first. + if let Some(blueprint) = blueprint { + Self::send_blueprint(blueprint, &sink); + } + self.set_sink(Box::new(sink)); Ok(()) @@ -1677,6 +1686,24 @@ impl RecordingStream { /// terms of data durability and ordering. /// See [`Self::set_sink`] for more information. pub fn stdout(&self) -> Result<(), crate::sink::FileSinkError> { + self.stdout_opts(None) + } + + /// Swaps the underlying sink for a [`crate::sink::FileSink`] pointed at stdout. + /// + /// If there isn't any listener at the other end of the pipe, the [`RecordingStream`] will + /// default back to `buffered` mode, in order not to break the user's terminal. + /// + /// This is a convenience wrapper for [`Self::set_sink`] that upholds the same guarantees in + /// terms of data durability and ordering. + /// See [`Self::set_sink`] for more information. + /// + /// If a blueprint was provided, it will be stored first in the file. + /// Blueprints are currently an experimental part of the Rust SDK. + pub fn stdout_opts( + &self, + blueprint: Option>, + ) -> Result<(), crate::sink::FileSinkError> { if forced_sink_path().is_some() { re_log::debug!("Ignored setting new file since _RERUN_FORCE_SINK is set"); return Ok(()); @@ -1689,6 +1716,12 @@ impl RecordingStream { } let sink = crate::sink::FileSink::stdout()?; + + // If a blueprint was provided, write it first. + if let Some(blueprint) = blueprint { + Self::send_blueprint(blueprint, &sink); + } + self.set_sink(Box::new(sink)); Ok(()) @@ -1711,6 +1744,24 @@ impl RecordingStream { re_log::warn_once!("Recording disabled - call to disconnect() ignored"); } } + + /// Send the blueprint to the sink, and then activate it. + pub fn send_blueprint(blueprint: Vec, sink: &dyn crate::sink::LogSink) { + let mut store_id = None; + for msg in blueprint { + if store_id.is_none() { + store_id = Some(msg.store_id().clone()); + } + sink.send(msg); + } + if let Some(store_id) = store_id { + // Let the viewer know that the blueprint has been fully received, + // and that it can now be activated. + // We don't want to activate half-loaded blueprints, because that can be confusing, + // and can also lead to problems with space-view heuristics. + sink.send(LogMsg::ActivateStore(store_id)); + } + } } impl fmt::Debug for RecordingStream { diff --git a/examples/python/structure_from_motion/main.py b/examples/python/structure_from_motion/main.py index 6e3f469639e0..5030f4c39944 100755 --- a/examples/python/structure_from_motion/main.py +++ b/examples/python/structure_from_motion/main.py @@ -15,6 +15,7 @@ import numpy.typing as npt import requests import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb from read_write_model import Camera, read_model from tqdm import tqdm @@ -221,7 +222,17 @@ def main() -> None: if args.resize: args.resize = tuple(int(x) for x in args.resize.split("x")) - rr.script_setup(args, "rerun_example_structure_from_motion") + blueprint = rrb.Vertical( + rrb.Spatial3DView(name="3D", origin="/"), + rrb.Horizontal( + rrb.TextDocumentView(name="README", origin="/description"), + rrb.Spatial2DView(name="Camera", origin="/camera/image"), + rrb.TimeSeriesView(origin="/plot"), + ), + row_shares=[3, 2], + ) + + rr.script_setup(args, "rerun_example_structure_from_motion", blueprint=blueprint) dataset_path = get_downloaded_dataset_path(args.dataset) read_and_log_sparse_reconstruction(dataset_path, filter_output=not args.unfiltered, resize=args.resize) rr.script_teardown(args) diff --git a/rerun_py/rerun_sdk/rerun/script_helpers.py b/rerun_py/rerun_sdk/rerun/script_helpers.py index 666ac742a392..cbb3c10680f8 100644 --- a/rerun_py/rerun_sdk/rerun/script_helpers.py +++ b/rerun_py/rerun_sdk/rerun/script_helpers.py @@ -102,16 +102,16 @@ def script_setup( # NOTE: mypy thinks these methods don't exist because they're monkey-patched. if args.stdout: - rec.stdout() # type: ignore[attr-defined] + rec.stdout(blueprint=blueprint) # type: ignore[attr-defined] elif args.serve: - rec.serve() # type: ignore[attr-defined] + rec.serve(blueprint=blueprint) # type: ignore[attr-defined] elif args.connect: # Send logging data to separate `rerun` process. # You can omit the argument to connect to the default address, # which is `127.0.0.1:9876`. rec.connect(args.addr, blueprint=blueprint) # type: ignore[attr-defined] elif args.save is not None: - rec.save(args.save) # type: ignore[attr-defined] + rec.save(args.save, blueprint=blueprint) # type: ignore[attr-defined] elif not args.headless: rec.spawn(blueprint=blueprint) # type: ignore[attr-defined] diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index 0f0f7d4f22e1..f436d58c16ba 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -29,13 +29,13 @@ def connect( Parameters ---------- - addr + addr: The ip:port to connect to - flush_timeout_sec: float + flush_timeout_sec: The minimum time the SDK will wait during a flush before potentially dropping data if progress is not being made. Passing `None` indicates no timeout, and can cause a call to `flush` to block indefinitely. - blueprint: Optional[BlueprintLike] + blueprint: An optional blueprint to configure the UI. recording: Specifies the [`rerun.RecordingStream`][] to use. @@ -43,9 +43,12 @@ def connect( See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. """ - application_id = get_application_id(recording=recording) - recording = RecordingStream.to_native(recording) + if not bindings.is_enabled(): + logging.warning("Rerun is disabled - connect() call ignored") + return + + application_id = get_application_id(recording=recording) if application_id is None: raise ValueError( "No application id found. You must call rerun.init before connecting to a viewer, or provide a recording." @@ -56,13 +59,17 @@ def connect( if blueprint is not None: blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + recording = RecordingStream.to_native(recording) + bindings.connect(addr=addr, flush_timeout_sec=flush_timeout_sec, blueprint=blueprint_storage, recording=recording) _connect = connect # we need this because Python scoping is horrible -def save(path: str | pathlib.Path, recording: RecordingStream | None = None) -> None: +def save( + path: str | pathlib.Path, blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None +) -> None: """ Stream all log-data to a file. @@ -70,8 +77,11 @@ def save(path: str | pathlib.Path, recording: RecordingStream | None = None) -> Parameters ---------- - path : str + path: The path to save the data to. + blueprint: + An optional blueprint to configure the UI. + This will be written first to the .rrd file, before appending the recording data. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. @@ -83,11 +93,23 @@ def save(path: str | pathlib.Path, recording: RecordingStream | None = None) -> logging.warning("Rerun is disabled - save() call ignored. You must call rerun.init before saving a recording.") return + application_id = get_application_id(recording=recording) + if application_id is None: + raise ValueError( + "No application id found. You must call rerun.init before connecting to a viewer, or provide a recording." + ) + + # If a blueprint is provided, we need to create a blueprint storage object + blueprint_storage = None + if blueprint is not None: + blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + recording = RecordingStream.to_native(recording) - bindings.save(path=str(path), recording=recording) + + bindings.save(path=str(path), blueprint=blueprint_storage, recording=recording) -def stdout(recording: RecordingStream | None = None) -> None: +def stdout(blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None) -> None: """ Stream all log-data to stdout. @@ -100,6 +122,8 @@ def stdout(recording: RecordingStream | None = None) -> None: Parameters ---------- + blueprint: + An optional blueprint to configure the UI. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. @@ -111,8 +135,19 @@ def stdout(recording: RecordingStream | None = None) -> None: logging.warning("Rerun is disabled - save() call ignored. You must call rerun.init before saving a recording.") return + application_id = get_application_id(recording=recording) + if application_id is None: + raise ValueError( + "No application id found. You must call rerun.init before connecting to a viewer, or provide a recording." + ) + + # If a blueprint is provided, we need to create a blueprint storage object + blueprint_storage = None + if blueprint is not None: + blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + recording = RecordingStream.to_native(recording) - bindings.stdout(recording=recording) + bindings.stdout(blueprint=blueprint_storage, recording=recording) def disconnect(recording: RecordingStream | None = None) -> None: @@ -165,6 +200,7 @@ def serve( open_browser: bool = True, web_port: int | None = None, ws_port: int | None = None, + blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None, server_memory_limit: str = "25%", ) -> None: @@ -182,12 +218,14 @@ def serve( Parameters ---------- - open_browser + open_browser: Open the default browser to the viewer. web_port: The port to serve the web viewer on (defaults to 9090). ws_port: The port to serve the WebSocket server on (defaults to 9877) + blueprint: + An optional blueprint to configure the UI. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. @@ -198,8 +236,30 @@ def serve( """ + if not bindings.is_enabled(): + logging.warning("Rerun is disabled - serve() call ignored") + return + + application_id = get_application_id(recording=recording) + if application_id is None: + raise ValueError( + "No application id found. You must call rerun.init before connecting to a viewer, or provide a recording." + ) + + # If a blueprint is provided, we need to create a blueprint storage object + blueprint_storage = None + if blueprint is not None: + blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + recording = RecordingStream.to_native(recording) - bindings.serve(open_browser, web_port, ws_port, server_memory_limit=server_memory_limit, recording=recording) + bindings.serve( + open_browser, + web_port, + ws_port, + server_memory_limit=server_memory_limit, + blueprint=blueprint_storage, + recording=recording, + ) # TODO(#4019): application-level handshake @@ -236,19 +296,19 @@ def spawn( Parameters ---------- - port : int + port: The port to listen on. - connect + connect: also connect to the viewer and stream logging data to it. - memory_limit + memory_limit: An upper limit on how much memory the Rerun Viewer should use. When this limit is reached, Rerun will drop the oldest data. Example: `16GB` or `50%` (of system total). - recording + recording: Specifies the [`rerun.RecordingStream`][] to use if `connect = True`. If left unspecified, defaults to the current active data recording, if there is one. See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. - blueprint: Optional[BlueprintLike] + blueprint: An optional blueprint to configure the UI. """ diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index 856c74b188db..df650128e468 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -557,8 +557,13 @@ fn connect( } #[pyfunction] -#[pyo3(signature = (path, recording = None))] -fn save(path: &str, recording: Option<&PyRecordingStream>, py: Python<'_>) -> PyResult<()> { +#[pyo3(signature = (path, blueprint = None, recording = None))] +fn save( + path: &str, + blueprint: Option<&PyMemorySinkStorage>, + recording: Option<&PyRecordingStream>, + py: Python<'_>, +) -> PyResult<()> { let Some(recording) = get_data_recording(recording) else { return Ok(()); }; @@ -567,7 +572,7 @@ fn save(path: &str, recording: Option<&PyRecordingStream>, py: Python<'_>) -> Py // Release the GIL in case any flushing behavior needs to cleanup a python object. py.allow_threads(|| { let res = recording - .save(path) + .save_opts(path, blueprint.map(|b| b.inner.take())) .map_err(|err| PyRuntimeError::new_err(err.to_string())); flush_garbage_queue(); res @@ -575,8 +580,12 @@ fn save(path: &str, recording: Option<&PyRecordingStream>, py: Python<'_>) -> Py } #[pyfunction] -#[pyo3(signature = (recording = None))] -fn stdout(recording: Option<&PyRecordingStream>, py: Python<'_>) -> PyResult<()> { +#[pyo3(signature = (blueprint = None, recording = None))] +fn stdout( + blueprint: Option<&PyMemorySinkStorage>, + recording: Option<&PyRecordingStream>, + py: Python<'_>, +) -> PyResult<()> { let Some(recording) = get_data_recording(recording) else { return Ok(()); }; @@ -585,7 +594,7 @@ fn stdout(recording: Option<&PyRecordingStream>, py: Python<'_>) -> PyResult<()> // Release the GIL in case any flushing behavior needs to cleanup a python object. py.allow_threads(|| { let res = recording - .stdout() + .stdout_opts(blueprint.map(|b| b.inner.take())) .map_err(|err| PyRuntimeError::new_err(err.to_string())); flush_garbage_queue(); res @@ -670,12 +679,13 @@ fn enter_tokio_runtime() -> tokio::runtime::EnterGuard<'static> { /// Serve a web-viewer. #[allow(clippy::unnecessary_wraps)] // False positive #[pyfunction] -#[pyo3(signature = (open_browser, web_port, ws_port, server_memory_limit, recording = None))] +#[pyo3(signature = (open_browser, web_port, ws_port, server_memory_limit, blueprint = None, recording = None))] fn serve( open_browser: bool, web_port: Option, ws_port: Option, server_memory_limit: String, + blueprint: Option<&PyMemorySinkStorage>, recording: Option<&PyRecordingStream>, ) -> PyResult<()> { #[cfg(feature = "web_viewer")] @@ -684,27 +694,32 @@ fn serve( return Ok(()); }; - let _guard = enter_tokio_runtime(); - let server_memory_limit = re_memory::MemoryLimit::parse(&server_memory_limit) .map_err(|err| PyRuntimeError::new_err(format!("Bad server_memory_limit: {err}:")))?; - recording.set_sink( - rerun::web_viewer::new_sink( - open_browser, - "0.0.0.0", - web_port.map(WebViewerServerPort).unwrap_or_default(), - ws_port.map(RerunServerPort).unwrap_or_default(), - server_memory_limit, - ) - .map_err(|err| PyRuntimeError::new_err(err.to_string()))?, - ); + let _guard = enter_tokio_runtime(); + + let sink = rerun::web_viewer::new_sink( + open_browser, + "0.0.0.0", + web_port.map(WebViewerServerPort).unwrap_or_default(), + ws_port.map(RerunServerPort).unwrap_or_default(), + server_memory_limit, + ) + .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; + + if let Some(blueprint) = blueprint { + RecordingStream::send_blueprint(blueprint.inner.take(), &*sink); + } + + recording.set_sink(sink); Ok(()) } #[cfg(not(feature = "web_viewer"))] { + _ = blueprint; _ = recording; _ = web_port; _ = ws_port; From 5244bfcf435e4bcee82e0e546e1ee481c8283e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Thu, 21 Mar 2024 09:33:23 +0100 Subject: [PATCH 079/508] Fix build workflows (#5611) ### What CI on main has not been running at all since https://github.com/rerun-io/rerun/pull/5511 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/on_push_main.yml | 4 ++-- .github/workflows/release.yml | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index da7500ae4568..6d5abbe983a0 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -87,12 +87,12 @@ jobs: build-examples: name: "Build Examples" - needs: [build-wheel-linux] + needs: [build-wheel-linux-x64] uses: ./.github/workflows/reusable_build_examples.yml with: CONCURRENCY: push-${{ github.ref_name }} CHANNEL: main - WHEEL_ARTIFACT_NAME: linux-wheel + WHEEL_ARTIFACT_NAME: linux-x64-wheel secrets: inherit track-sizes: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c75eeddc2c1f..71eb649fc20e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -238,7 +238,6 @@ jobs: with: release-version: ${{ needs.version.outputs.current }} concurrency: ${{ github.ref_name }} - linux-wheel-name: linux-wheel release-commit: ${{ needs.version.outputs.release-commit }} secrets: inherit @@ -250,7 +249,7 @@ jobs: release-version: ${{ needs.version.outputs.current }} release-commit: ${{ needs.version.outputs.release-commit }} concurrency: ${{ github.ref_name }} - wheel-artifact-name: linux-wheel + wheel-artifact-name: linux-x64-wheel update-latest: ${{ inputs.release-type == 'final' }} secrets: inherit From bbf97d194e50c3656dbc5ef51ef8be156c7bafc5 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:33:18 +0100 Subject: [PATCH 080/508] Add blueprint to Live Camera Edge Detection example (#5613) ### What Add blueprint to Live Camera Edge Detection example: image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5613/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5613/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5613/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5613) - [Docs preview](https://rerun.io/preview/ebd7e2fa11ced1becfd06d333933741e7fe288f1/docs) - [Examples preview](https://rerun.io/preview/ebd7e2fa11ced1becfd06d333933741e7fe288f1/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/live_camera_edge_detection/main.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/python/live_camera_edge_detection/main.py b/examples/python/live_camera_edge_detection/main.py index 33bab093a440..d7fe9103b95a 100755 --- a/examples/python/live_camera_edge_detection/main.py +++ b/examples/python/live_camera_edge_detection/main.py @@ -10,6 +10,7 @@ import cv2 import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb def run_canny(num_frames: int | None) -> None: @@ -62,7 +63,18 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_live_camera_edge_detection") + rr.script_setup( + args, + "rerun_example_live_camera_edge_detection", + blueprint=rrb.Vertical( + rrb.Horizontal( + rrb.Spatial2DView(origin="/image/rgb", name="Video"), + rrb.Spatial2DView(origin="/image/gray", name="Video (Grayscale)"), + ), + rrb.Spatial2DView(origin="/image/canny", name="Canny Edge Detector"), + row_shares=[1, 2], + ), + ) run_canny(args.num_frames) From 13a290c42e8f9d589325ba2e4752700e65ce70c7 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:45:22 +0100 Subject: [PATCH 081/508] Add blueprint to LLM Embedding Ner example (#5614) ### What Add blueprint to LLM Embedding Ner example image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5614/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5614/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5614/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5614) - [Docs preview](https://rerun.io/preview/66e788d6aa6f9966f54a7e8ad0b888da91e93220/docs) - [Examples preview](https://rerun.io/preview/66e788d6aa6f9966f54a7e8ad0b888da91e93220/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/llm_embedding_ner/main.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/examples/python/llm_embedding_ner/main.py b/examples/python/llm_embedding_ner/main.py index b371d238188d..094de3faa2da 100755 --- a/examples/python/llm_embedding_ner/main.py +++ b/examples/python/llm_embedding_ner/main.py @@ -14,6 +14,7 @@ from typing import Any import rerun as rr +import rerun.blueprint as rrb import torch import umap from transformers import AutoModelForTokenClassification, AutoTokenizer, pipeline @@ -165,7 +166,19 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_llm_embedding_ner") + rr.script_setup( + args, + "rerun_example_llm_embedding_ner", + blueprint=rrb.Horizontal( + rrb.Vertical( + rrb.TextDocumentView(origin="/text", name="Original Text"), + rrb.TextDocumentView(origin="/tokenized_text", name="Tokenized Text"), + rrb.TextDocumentView(origin="/named_entities", name="Named Entities"), + row_shares=[3, 2, 2], + ), + rrb.Spatial3DView(origin="/umap_embeddings", name="UMAP Embeddings"), + ), + ) run_llm_ner(args.text) rr.script_teardown(args) From d2ead0ca5e6db1a063282232639461c208da6bd7 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 21 Mar 2024 10:57:20 +0100 Subject: [PATCH 082/508] Add blueprint to Human Pose Tracking example (#5612) ### What Add blueprint to Human Pose Tracking. That example was pretty good already, but still a nice touch. image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5612/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5612/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5612/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5612) - [Docs preview](https://rerun.io/preview/2a0e41c68fa57f01eeccf451bcba4dfe0de2fa7d/docs) - [Examples preview](https://rerun.io/preview/2a0e41c68fa57f01eeccf451bcba4dfe0de2fa7d/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/human_pose_tracking/main.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py index 2884f99a3d45..edda91627c43 100755 --- a/examples/python/human_pose_tracking/main.py +++ b/examples/python/human_pose_tracking/main.py @@ -16,12 +16,12 @@ import numpy.typing as npt import requests import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb EXAMPLE_DIR: Final = Path(os.path.dirname(__file__)) DATASET_DIR: Final = EXAMPLE_DIR / "dataset" / "pose_movement" DATASET_URL_BASE: Final = "https://storage.googleapis.com/rerun-example-datasets/pose_movement" - DESCRIPTION = """ # Human Pose Tracking This example uses Rerun to visualize the output of [MediaPipe](https://developers.google.com/mediapipe)-based tracking @@ -214,7 +214,22 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_human_pose_tracking") + rr.script_setup( + args, + "rerun_example_human_pose_tracking", + blueprint=rrb.Horizontal( + rrb.Vertical( + rrb.Spatial2DView(origin="video", name="Result"), + rrb.Spatial3DView(origin="person", name="3D pose"), + ), + rrb.Vertical( + rrb.Spatial2DView(origin="video/rgb", name="Raw video"), + rrb.TextDocumentView(origin="description", name="Description"), + row_shares=[2, 3], + ), + column_shares=[3, 2], + ), + ) video_path = args.video_path # type: str if not video_path: From 7100bfe3ea94c5121f25efb41dee092fdc5cbb1a Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 21 Mar 2024 11:06:56 +0100 Subject: [PATCH 083/508] Add blueprint to Face Tracking example (#5616) ### What ![image](https://github.com/rerun-io/rerun/assets/1220815/6f979a98-6f18-4640-8f30-7e8c40159813) Didn't name the space views this time around since the default cursive names were good enough already. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5616/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5616/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5616/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5616) - [Docs preview](https://rerun.io/preview/965dae698a17a25a2aa5ca56bf7d6f58ffe1ec10/docs) - [Examples preview](https://rerun.io/preview/965dae698a17a25a2aa5ca56bf7d6f58ffe1ec10/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/face_tracking/main.py | 110 +++++++++++++++----------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/examples/python/face_tracking/main.py b/examples/python/face_tracking/main.py index a146e31343c4..ea9dde7a40a1 100755 --- a/examples/python/face_tracking/main.py +++ b/examples/python/face_tracking/main.py @@ -16,6 +16,7 @@ import numpy.typing as npt import requests import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb import tqdm from mediapipe.tasks.python import vision @@ -29,58 +30,58 @@ # uncomment blendshapes of interest BLENDSHAPES_CATEGORIES = { - # "_neutral", - # "browDownLeft", - # "browDownRight", - # "browInnerUp", - # "browOuterUpLeft", - # "browOuterUpRight", - # "cheekPuff", - # "cheekSquintLeft", - # "cheekSquintRight", + "_neutral", + "browDownLeft", + "browDownRight", + "browInnerUp", + "browOuterUpLeft", + "browOuterUpRight", + "cheekPuff", + "cheekSquintLeft", + "cheekSquintRight", "eyeBlinkLeft", "eyeBlinkRight", - # "eyeLookDownLeft", - # "eyeLookDownRight", - # "eyeLookInLeft", - # "eyeLookInRight", - # "eyeLookOutLeft", - # "eyeLookOutRight", - # "eyeLookUpLeft", - # "eyeLookUpRight", + "eyeLookDownLeft", + "eyeLookDownRight", + "eyeLookInLeft", + "eyeLookInRight", + "eyeLookOutLeft", + "eyeLookOutRight", + "eyeLookUpLeft", + "eyeLookUpRight", "eyeSquintLeft", "eyeSquintRight", "eyeWideLeft", "eyeWideRight", - # "jawForward", - # "jawLeft", + "jawForward", + "jawLeft", "jawOpen", - # "jawRight", - # "mouthClose", - # "mouthDimpleLeft", - # "mouthDimpleRight", - # "mouthFrownLeft", - # "mouthFrownRight", - # "mouthFunnel", - # "mouthLeft", - # "mouthLowerDownLeft", - # "mouthLowerDownRight", - # "mouthPressLeft", - # "mouthPressRight", - # "mouthPucker", - # "mouthRight", - # "mouthRollLower", - # "mouthRollUpper", - # "mouthShrugLower", - # "mouthShrugUpper", + "jawRight", + "mouthClose", + "mouthDimpleLeft", + "mouthDimpleRight", + "mouthFrownLeft", + "mouthFrownRight", + "mouthFunnel", + "mouthLeft", + "mouthLowerDownLeft", + "mouthLowerDownRight", + "mouthPressLeft", + "mouthPressRight", + "mouthPucker", + "mouthRight", + "mouthRollLower", + "mouthRollUpper", + "mouthShrugLower", + "mouthShrugUpper", "mouthSmileLeft", "mouthSmileRight", - # "mouthStretchLeft", - # "mouthStretchRight", - # "mouthUpperUpLeft", - # "mouthUpperUpRight", - # "noseSneerLeft", - # "noseSneerRight", + "mouthStretchLeft", + "mouthStretchRight", + "mouthUpperUpLeft", + "mouthUpperUpRight", + "noseSneerLeft", + "noseSneerRight", } @@ -430,7 +431,28 @@ def main() -> None: args, unknown = parser.parse_known_args() for arg in unknown: logging.warning(f"unknown arg: {arg}") - rr.script_setup(args, "rerun_example_mp_face_detection") + + rr.script_setup( + args, + "rerun_example_mp_face_detection", + blueprint=rrb.Horizontal( + rrb.Spatial3DView(origin="reconstruction"), + rrb.Vertical( + rrb.Spatial2DView(origin="video"), + rrb.TimeSeriesView( + origin="blendshapes", + # Enable only certain blend shapes by default. More can be added in the viewer ui + contents=[ + "+ blendshapes/0/eyeBlinkLeft", + "+ blendshapes/0/eyeBlinkRight", + "+ blendshapes/0/jawOpen", + "+ blendshapes/0/mouthSmileLeft", + "+ blendshapes/0/mouthSmileRight", + ], + ), + ), + ), + ) if args.demo_image: if not SAMPLE_IMAGE_PATH.exists(): From 49b275987528d4be970a73ca69f4493e9643bd69 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:14:58 +0100 Subject: [PATCH 084/508] Add blueprint to Objectron example (#5617) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What Add blueprint to Objectron example. I've removed all frame-based stuff in favour of reprojecting world stuff into the 2D space view ✨ image - Fixes #3412 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5617/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5617/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5617/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5617) - [Docs preview](https://rerun.io/preview/59dccf1eeed6eb93c003d07c0091f22ce91fe8c5/docs) - [Examples preview](https://rerun.io/preview/59dccf1eeed6eb93c003d07c0091f22ce91fe8c5/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/objectron/main.py | 70 +++++-------------------------- 1 file changed, 10 insertions(+), 60 deletions(-) diff --git a/examples/python/objectron/main.py b/examples/python/objectron/main.py index 6c026111dcb1..e4db83e39325 100755 --- a/examples/python/objectron/main.py +++ b/examples/python/objectron/main.py @@ -17,17 +17,16 @@ from typing import Iterable, Iterator import numpy as np -import numpy.typing as npt import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb from download_dataset import ( ANNOTATIONS_FILENAME, AVAILABLE_RECORDINGS, GEOMETRY_FILENAME, - IMAGE_RESOLUTION, LOCAL_DATASET_DIR, ensure_recording_available, ) -from proto.objectron.proto import ARCamera, ARFrame, ARPointCloud, FrameAnnotation, Object, ObjectType, Sequence +from proto.objectron.proto import ARCamera, ARFrame, ARPointCloud, Object, ObjectType, Sequence from scipy.spatial.transform import Rotation as R @@ -120,8 +119,6 @@ def log_ar_frames(samples: Iterable[SampleARFrame], seq: Sequence) -> None: log_camera(sample.frame.camera) log_point_cloud(sample.frame.raw_feature_points) - log_frame_annotations(frame_times, seq.frame_annotations) - def log_camera(cam: ARCamera) -> None: """Logs a camera from an `ARFrame` using the Rerun SDK.""" @@ -186,60 +183,6 @@ def log_annotated_bboxes(bboxes: Iterable[Object]) -> None: ) -def log_frame_annotations(frame_times: list[float], frame_annotations: list[FrameAnnotation]) -> None: - """Maps annotations to their associated `ARFrame` then logs them using the Rerun SDK.""" - - for frame_ann in frame_annotations: - frame_idx = frame_ann.frame_id - if frame_idx >= len(frame_times): - continue - - time = frame_times[frame_idx] - rr.set_time_sequence("frame", frame_idx) - rr.set_time_seconds("time", time) - - for obj_ann in frame_ann.annotations: - keypoint_ids = [kp.id for kp in obj_ann.keypoints] - keypoint_pos2s = np.asarray([[kp.point_2d.x, kp.point_2d.y] for kp in obj_ann.keypoints], dtype=np.float32) - # NOTE: These are normalized points, so we need to bring them back to image space - keypoint_pos2s *= IMAGE_RESOLUTION - - if len(keypoint_pos2s) == 9: - log_projected_bbox(f"world/camera/estimates/box-{obj_ann.object_id}", keypoint_pos2s) - else: - for id, pos2 in zip(keypoint_ids, keypoint_pos2s): - rr.log( - f"world/camera/estimates/box-{obj_ann.object_id}/{id}", - rr.Points2D(pos2, colors=[130, 160, 250, 255]), - ) - - -# TODO(#3412): replace once we can auto project 3D bboxes on 2D views (need blueprints) -def log_projected_bbox(path: str, keypoints: npt.NDArray[np.float32]) -> None: - """ - Projects the 3D bounding box to a 2D plane, using line segments. - - The 3D bounding box is described by the keypoints of an `ObjectAnnotation` - """ - # fmt: off - segments = np.array([[keypoints[1], keypoints[2]], - [keypoints[1], keypoints[3]], - [keypoints[4], keypoints[2]], - [keypoints[4], keypoints[3]], - - [keypoints[5], keypoints[6]], - [keypoints[5], keypoints[7]], - [keypoints[8], keypoints[6]], - [keypoints[8], keypoints[7]], - - [keypoints[1], keypoints[5]], - [keypoints[2], keypoints[6]], - [keypoints[3], keypoints[7]], - [keypoints[4], keypoints[8]]], dtype=np.float32) - # fmt: on - rr.log(path, rr.LineStrips2D(segments, colors=[130, 160, 250, 255])) - - def main() -> None: # Ensure the logging in download_dataset.py gets written to stderr: logging.getLogger().addHandler(logging.StreamHandler()) @@ -272,7 +215,14 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_objectron") + rr.script_setup( + args, + "rerun_example_objectron", + blueprint=rrb.Horizontal( + rrb.Spatial3DView(origin="/world", name="World"), + rrb.Spatial2DView(origin="/world/camera", name="Camera", contents=["+ $origin/**", "+ /world/**"]), + ), + ) dir = ensure_recording_available(args.recording, args.dataset_dir, args.force_reprocess_video) From 3844083077f5691d5358dc92e715e53a37762fa3 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 21 Mar 2024 12:50:50 +0100 Subject: [PATCH 085/508] Reduce the height of the the tab bars and side panel titles (#5609) ### What Small step towards a more efficient use of vertical space. Set to 24px, down from 28px. Now on par with `ListItem`: image image - Part of https://github.com/rerun-io/rerun/issues/5589 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5609/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5609/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5609/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5609) - [Docs preview](https://rerun.io/preview/24c1f9ff1fd6d36c6ae46901a2779b4ab105ab66/docs) - [Examples preview](https://rerun.io/preview/24c1f9ff1fd6d36c6ae46901a2779b4ab105ab66/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_ui/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/re_ui/src/lib.rs b/crates/re_ui/src/lib.rs index 18cd4abf257d..e64dc2a3d32e 100644 --- a/crates/re_ui/src/lib.rs +++ b/crates/re_ui/src/lib.rs @@ -184,7 +184,7 @@ impl ReUi { /// Height of the title row in the blueprint view and selection view, /// as well as the tab bar height in the viewport view. pub fn title_bar_height() -> f32 { - 28.0 // from figma 2022-02-03 + 24.0 // https://github.com/rerun-io/rerun/issues/5589 } pub fn list_item_height() -> f32 { From 0530f58f5565344345fe745e4005cd16fee679c1 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 21 Mar 2024 14:26:06 +0100 Subject: [PATCH 086/508] Add blueprint to Gesture Detection example (#5619) ### What Allows getting rid of redundant logging \o/ and making all paths lower case ![image](https://github.com/rerun-io/rerun/assets/1220815/eb710dbe-930c-4c9f-9499-33090bc4b191) cc: @andreasnaoum ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5619/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5619/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5619/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5619) - [Docs preview](https://rerun.io/preview/b4c62bf6da4d6fa8e105ddb33a1d222ee2439ae8/docs) - [Examples preview](https://rerun.io/preview/b4c62bf6da4d6fa8e105ddb33a1d222ee2439ae8/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/gesture_detection/main.py | 37 +++++++++++++++-------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/examples/python/gesture_detection/main.py b/examples/python/gesture_detection/main.py index d8b4974e8745..1aad2ad74481 100755 --- a/examples/python/gesture_detection/main.py +++ b/examples/python/gesture_detection/main.py @@ -15,6 +15,7 @@ import numpy.typing as npt import requests import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb import tqdm from mediapipe.tasks import python from mediapipe.tasks.python import vision @@ -87,8 +88,7 @@ def __init__(self, video_mode: bool = False): ), timeless=True, ) - # rr.log("Hand3D", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, timeless=True) - rr.log("Hand3D", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, timeless=True) + rr.log("hand3d", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, timeless=True) @staticmethod def convert_landmarks_to_image_coordinates( @@ -111,7 +111,7 @@ def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> else self.recognizer.recognize(image) ) - for log_key in ["Media/Points", "Hand/Points", "Media/Connections", "Hand/Connections", "Hand3D/Points"]: + for log_key in ["hand2d/points", "hand2d/connections", "hand3d/points"]: rr.log(log_key, rr.Clear(recursive=True)) for i, gesture in enumerate(recognition_result.gestures): @@ -125,7 +125,7 @@ def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> landmark_positions_3d = self.convert_landmarks_to_3d(hand_landmarks) if landmark_positions_3d is not None: rr.log( - "Hand3D/Points", + "hand3d/points", rr.Points3D( landmark_positions_3d, radii=20, @@ -138,8 +138,7 @@ def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> points = self.convert_landmarks_to_image_coordinates(hand_landmarks, width, height) # Log points to the image and Hand Entity - for log_key in ["Media/Points", "Hand/Points"]: - rr.log(log_key, rr.Points2D(points, radii=10, colors=[255, 0, 0])) + rr.log("hand2d/points", rr.Points2D(points, radii=10, colors=[255, 0, 0])) # Obtain hand connections from MediaPipe mp_hands_connections = mp.solutions.hands.HAND_CONNECTIONS @@ -147,8 +146,7 @@ def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> points2 = [points[connection[1]] for connection in mp_hands_connections] # Log connections to the image and Hand Entity [128, 128, 128] - for log_key in ["Media/Connections", "Hand/Connections"]: - rr.log(log_key, rr.LineStrips2D(np.stack((points1, points2), axis=1), colors=[255, 165, 0])) + rr.log("hand2d/connections", rr.LineStrips2D(np.stack((points1, points2), axis=1), colors=[255, 165, 0])) def present_detected_gesture(self, category: str) -> None: # Get the corresponding ulr of the picture for the detected gesture category @@ -159,7 +157,7 @@ def present_detected_gesture(self, category: str) -> None: # Log the detection by using the appropriate image rr.log( - "Detection", + "detection", rr.TextDocument(f"![Image]({GESTURE_URL + gesture_pic})".strip(), media_type=rr.MediaType.MARKDOWN), ) @@ -195,7 +193,7 @@ def run_from_sample_image(path: Path | str) -> None: image = cv2.imread(str(path)) # image = resize_image(image, max_dim) show_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) - rr.log("Media/Image", rr.Image(show_image)) + rr.log("media/image", rr.Image(show_image)) logger = GestureDetectorLogger(video_mode=False) logger.detect_and_log(show_image, 0) @@ -245,7 +243,7 @@ def run_from_video_capture(vid: int | str, max_frame_count: int | None) -> None: rr.set_time_sequence("frame_nr", frame_idx) rr.set_time_nanos("frame_time", frame_time_nano) detector.detect_and_log(frame, frame_time_nano) - rr.log("Media/Video", rr.Image(frame).compress(jpeg_quality=75)) + rr.log("media/video", rr.Image(frame).compress(jpeg_quality=75)) except KeyboardInterrupt: pass @@ -298,7 +296,22 @@ def main() -> None: logging.warning(f"unknown arg: {arg}") # Set up Rerun with script name - rr.script_setup(args, "rerun_example_mp_gesture_recognition") + rr.script_setup( + args, + "rerun_example_mp_gesture_recognition", + blueprint=rrb.Horizontal( + rrb.Spatial2DView(name="Input & Hand", contents=["media/**", "hand2d/**"]), + rrb.Vertical( + rrb.Tabs( + rrb.Spatial3DView(name="Hand 3D", origin="hand3d"), + rrb.Spatial2DView(name="Hand 2D", origin="hand2d"), + ), + rrb.TextDocumentView(name="Detection", origin="detection"), + row_shares=[3, 2], + ), + column_shares=[3, 1], + ), + ) # Choose the appropriate run mode based on provided arguments if args.demo_image: From b5bdd431194ec9c1e6836ef1f4d69039f359db9c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 21 Mar 2024 14:49:40 +0100 Subject: [PATCH 087/508] Update to latest egui master (#5621) ### What Keeping up with the latest bugs ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5621/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5621/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5621/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5621) - [Docs preview](https://rerun.io/preview/28a080fc118179a004e2186aab3f44c7e11a28c6/docs) - [Examples preview](https://rerun.io/preview/28a080fc118179a004e2186aab3f44c7e11a28c6/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 14 +++++++------- crates/re_space_view_spatial/src/eye.rs | 2 +- crates/re_ui/src/command.rs | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d299a087086..93888629f08e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1555,7 +1555,7 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "bytemuck", "serde", @@ -1564,7 +1564,7 @@ dependencies = [ [[package]] name = "eframe" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "bytemuck", "cocoa", @@ -1599,7 +1599,7 @@ dependencies = [ [[package]] name = "egui" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "accesskit", "ahash", @@ -1615,7 +1615,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "bytemuck", "document-features", @@ -1633,7 +1633,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "accesskit_winit", "arboard", @@ -1662,7 +1662,7 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "egui", "ehttp", @@ -1677,7 +1677,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "bytemuck", "egui", @@ -1694,7 +1694,7 @@ dependencies = [ [[package]] name = "egui_plot" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "egui", ] @@ -1736,7 +1736,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "bytemuck", "serde", @@ -1837,7 +1837,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=820fa3c43a2d20e140bc4525e0a1405e7420bb66#820fa3c43a2d20e140bc4525e0a1405e7420bb66" +source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" dependencies = [ "ab_glyph", "ahash", diff --git a/Cargo.toml b/Cargo.toml index 9eccf3aa39a6..73fa74c0ec6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -284,13 +284,13 @@ debug = true # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 -eframe = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 -egui = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 -egui_plot = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 -emath = { git = "https://github.com/emilk/egui.git", rev = "820fa3c43a2d20e140bc4525e0a1405e7420bb66" } # egui master 2024-03-17 +ecolor = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 +eframe = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 +egui = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 +egui_extras = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 +egui_plot = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 +egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 +emath = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } diff --git a/crates/re_space_view_spatial/src/eye.rs b/crates/re_space_view_spatial/src/eye.rs index 032a5463108e..325d82a49be5 100644 --- a/crates/re_space_view_spatial/src/eye.rs +++ b/crates/re_space_view_spatial/src/eye.rs @@ -439,7 +439,7 @@ impl ViewEye { /// /// Returns `true` if we did anything. fn keyboard_navigation(&mut self, egui_ctx: &egui::Context, speed: f32) -> bool { - let anything_has_focus = egui_ctx.memory(|mem| mem.focus().is_some()); + let anything_has_focus = egui_ctx.memory(|mem| mem.focused().is_some()); if anything_has_focus { return false; // e.g. we're typing in a TextField } diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs index 918d875442b1..592a84bf0c7f 100644 --- a/crates/re_ui/src/command.rs +++ b/crates/re_ui/src/command.rs @@ -331,7 +331,7 @@ impl UICommand { pub fn listen_for_kb_shortcut(egui_ctx: &egui::Context) -> Option { use strum::IntoEnumIterator as _; - let anything_has_focus = egui_ctx.memory(|mem| mem.focus().is_some()); + let anything_has_focus = egui_ctx.memory(|mem| mem.focused().is_some()); if anything_has_focus { return None; // e.g. we're typing in a TextField } From ea59abff5339c7764460e0b69133368baedb250d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Thu, 21 Mar 2024 14:51:19 +0100 Subject: [PATCH 088/508] Document `data-inline-viewer` (#5618) ### What - Closes https://github.com/rerun-io/rerun/issues/5316 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5618/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5618/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5618/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5618) - [Docs preview](https://rerun.io/preview/5d11587b3ddcf4f179ed9c79515aa57e383ebd96/docs) - [Examples preview](https://rerun.io/preview/5d11587b3ddcf4f179ed9c79515aa57e383ebd96/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/README.md | 21 +++++++++++++++++++ examples/python/arkit_scenes/README.md | 2 +- .../python/detect_and_track_objects/README.md | 2 +- examples/python/dicom_mri/README.md | 2 +- examples/python/dna/README.md | 2 +- examples/python/human_pose_tracking/README.md | 2 +- examples/python/incremental_logging/README.md | 2 +- examples/python/nuscenes/README.md | 2 +- .../open_photogrammetry_format/README.md | 2 +- examples/python/plots/README.md | 2 +- examples/python/raw_mesh/README.md | 2 +- examples/python/rgbd/README.md | 2 +- .../python/segment_anything_model/README.md | 2 +- .../python/structure_from_motion/README.md | 2 +- 14 files changed, 34 insertions(+), 13 deletions(-) diff --git a/docs/README.md b/docs/README.md index 046f27b98d65..700af1ce313b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -55,3 +55,24 @@ Once the snippet is in `snippet/all`, it may be referenced in a documentation Ma ``` snippet: my-example ``` + +### Screenshot links + +If a screenshot shows an example or snippet which is runnable and built on CI, then you can turn the screenshot +to a link to `app.rerun.io` pointing at the example using the `data-inline-viewer` attribute. + +Add the attribute to any `` element like so: + +```html + + + + + + + +``` + +The value should be: +- `examples/{NAME}` for examples +- `snippets/{NAME}` for snippets diff --git a/examples/python/arkit_scenes/README.md b/examples/python/arkit_scenes/README.md index b4bbf5038515..ba8c8cf64c9f 100644 --- a/examples/python/arkit_scenes/README.md +++ b/examples/python/arkit_scenes/README.md @@ -8,7 +8,7 @@ channel = "main" --> - + diff --git a/examples/python/detect_and_track_objects/README.md b/examples/python/detect_and_track_objects/README.md index b721c6d84f20..c99893270df9 100644 --- a/examples/python/detect_and_track_objects/README.md +++ b/examples/python/detect_and_track_objects/README.md @@ -8,7 +8,7 @@ channel = "release" --> - + diff --git a/examples/python/dicom_mri/README.md b/examples/python/dicom_mri/README.md index 0cbd8d9b510b..2841b985ffc0 100644 --- a/examples/python/dicom_mri/README.md +++ b/examples/python/dicom_mri/README.md @@ -8,7 +8,7 @@ channel = "main" --> - + diff --git a/examples/python/dna/README.md b/examples/python/dna/README.md index 0539c8463edd..011336123732 100644 --- a/examples/python/dna/README.md +++ b/examples/python/dna/README.md @@ -7,7 +7,7 @@ thumbnail_dimensions = [480, 285] channel = "main" --> - + diff --git a/examples/python/human_pose_tracking/README.md b/examples/python/human_pose_tracking/README.md index 09d41b873476..8cd77b4557bd 100644 --- a/examples/python/human_pose_tracking/README.md +++ b/examples/python/human_pose_tracking/README.md @@ -7,7 +7,7 @@ thumbnail_dimensions = [480, 272] channel = "main" --> - + diff --git a/examples/python/incremental_logging/README.md b/examples/python/incremental_logging/README.md index 96f8bae946c5..7ed52ebc905c 100644 --- a/examples/python/incremental_logging/README.md +++ b/examples/python/incremental_logging/README.md @@ -7,7 +7,7 @@ thumbnail_dimensions = [480, 301] --> - + diff --git a/examples/python/nuscenes/README.md b/examples/python/nuscenes/README.md index e383da597eb1..7c5dd3001552 100644 --- a/examples/python/nuscenes/README.md +++ b/examples/python/nuscenes/README.md @@ -8,7 +8,7 @@ channel = "release" build_args = ["--seconds=5"] --> - + diff --git a/examples/python/open_photogrammetry_format/README.md b/examples/python/open_photogrammetry_format/README.md index 98d5dc4799b1..a679c873f9fc 100644 --- a/examples/python/open_photogrammetry_format/README.md +++ b/examples/python/open_photogrammetry_format/README.md @@ -8,7 +8,7 @@ channel = "release" build_args = ["--jpeg-quality=50"] --> - + diff --git a/examples/python/plots/README.md b/examples/python/plots/README.md index 2db5f09adf8c..b86a3806592d 100644 --- a/examples/python/plots/README.md +++ b/examples/python/plots/README.md @@ -8,7 +8,7 @@ channel = "main" --> - + diff --git a/examples/python/raw_mesh/README.md b/examples/python/raw_mesh/README.md index b42f6ebd9b67..c285d0daf7be 100644 --- a/examples/python/raw_mesh/README.md +++ b/examples/python/raw_mesh/README.md @@ -7,7 +7,7 @@ thumbnail_dimensions = [480, 296] channel = "release" --> - + diff --git a/examples/python/rgbd/README.md b/examples/python/rgbd/README.md index 7cdcd283c91b..7ac0b30bfd8f 100644 --- a/examples/python/rgbd/README.md +++ b/examples/python/rgbd/README.md @@ -8,7 +8,7 @@ channel = "release" build_args = ["--frames=300"] --> - + diff --git a/examples/python/segment_anything_model/README.md b/examples/python/segment_anything_model/README.md index e0a8ef776694..221a694c6aec 100644 --- a/examples/python/segment_anything_model/README.md +++ b/examples/python/segment_anything_model/README.md @@ -8,7 +8,7 @@ channel = "release" --> - + diff --git a/examples/python/structure_from_motion/README.md b/examples/python/structure_from_motion/README.md index ea26881ef83b..c0611b2b25a9 100644 --- a/examples/python/structure_from_motion/README.md +++ b/examples/python/structure_from_motion/README.md @@ -9,7 +9,7 @@ build_args = ["--dataset=colmap_fiat", "--resize=800x600"] --> - + From 9236a91c809db45e8014fbf6f7334522d1441d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Thu, 21 Mar 2024 14:55:37 +0100 Subject: [PATCH 089/508] Update example thumbnails (#5615) ### What - Closes https://github.com/rerun-io/rerun/issues/5453 Some changes to the `scripts/ci/thumbnails.py` script: - Parallelized because it took quite a while to run, and was embarrassingly parallel - Improved the output of `check` to not print a checkmark if the thumbnail dimensions were incorrect - Made both `check` and `update` also look through readmes of other examples ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5615/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5615/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5615/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5615) - [Docs preview](https://rerun.io/preview/18e9c7fea1befe50a6ad871a4a8b696bbbddd78f/docs) - [Examples preview](https://rerun.io/preview/18e9c7fea1befe50a6ad871a4a8b696bbbddd78f/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/cspell.json | 1 + examples/cpp/clock/README.md | 3 +- examples/cpp/eigen_opencv/README.md | 4 +- examples/cpp/incremental_logging/README.md | 2 +- examples/cpp/minimal/README.md | 3 +- examples/cpp/stdio/README.md | 1 + examples/cpp/vrs/README.md | 4 +- examples/python/arflow/README.md | 4 +- examples/python/arkit_scenes/README.md | 4 +- examples/python/clock/README.md | 4 +- examples/python/controlnet/README.md | 4 +- .../depth_guided_stable_diffusion/README.md | 4 +- .../python/detect_and_track_objects/README.md | 4 +- examples/python/dicom_mri/README.md | 4 +- .../differentiable_blocks_world/README.md | 4 +- examples/python/face_tracking/README.md | 4 +- examples/python/gesture_detection/README.md | 4 +- examples/python/human_pose_tracking/README.md | 4 +- examples/python/lidar/README.md | 4 +- examples/python/limap/README.md | 4 +- .../live_camera_edge_detection/README.md | 4 +- examples/python/llm_embedding_ner/README.md | 4 +- examples/python/mcc/README.md | 4 +- examples/python/minimal/README.md | 4 +- examples/python/multiprocessing/README.md | 4 +- examples/python/multithreading/README.md | 4 +- examples/python/objectron/README.md | 4 +- examples/python/plots/README.md | 4 +- examples/python/raw_mesh/README.md | 4 +- examples/python/rgbd/README.md | 4 +- examples/python/ros_node/README.md | 4 +- .../python/segment_anything_model/README.md | 4 +- examples/python/shape_pointe/README.md | 4 +- .../python/signed_distance_fields/README.md | 4 +- examples/python/simplerecon/README.md | 4 +- examples/python/slahmr/README.md | 4 +- .../python/structure_from_motion/README.md | 4 +- examples/python/tapir/README.md | 4 +- examples/python/widebaseline/README.md | 4 +- examples/rust/clock/README.md | 3 +- examples/rust/custom_space_view/README.md | 1 + examples/rust/extend_viewer_ui/README.md | 1 + examples/rust/incremental_logging/README.md | 2 +- examples/rust/minimal/README.md | 3 +- examples/rust/minimal_serve/README.md | 3 +- examples/rust/objectron/README.md | 3 +- examples/rust/raw_mesh/README.md | 3 +- examples/rust/stdio/README.md | 1 + scripts/ci/thumbnails.py | 94 ++++++++++++------- 49 files changed, 147 insertions(+), 113 deletions(-) diff --git a/docs/cspell.json b/docs/cspell.json index 4286104d050b..ca7ba3b7552d 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -228,6 +228,7 @@ "Nichol", "Nikhila", "nohash", + "NOLINT", "noqa", "numpages", "numpy", diff --git a/examples/cpp/clock/README.md b/examples/cpp/clock/README.md index 7f0343f21390..0aedcd1212a1 100644 --- a/examples/cpp/clock/README.md +++ b/examples/cpp/clock/README.md @@ -1,6 +1,7 @@ diff --git a/examples/cpp/eigen_opencv/README.md b/examples/cpp/eigen_opencv/README.md index f90f7c0ee712..0f70b8ee41b7 100644 --- a/examples/cpp/eigen_opencv/README.md +++ b/examples/cpp/eigen_opencv/README.md @@ -2,8 +2,8 @@ title = "Eigen and OpenCV C++ Integration" source = "https://github.com/rerun-io/cpp-example-opencv-eigen" tags = ["2D", "3D", "C++", "Eigen", "OpenCV"] -thumbnail = "https://static.rerun.io/cpp-example-opencv-eigen/2fc6355fd87fbb4d07cda384ee8805edb68b5e01/480w.png" -thumbnail_dimensions = [480, 267] +thumbnail = "https://static.rerun.io/eigen-and-opencv-c-integration/5d271725bb9215b55f53767c9dc0db980c73dade/480w.png" +thumbnail_dimensions = [480, 480] --> This is a minimal CMake project that shows how to use Rerun in your code in conjunction with [Eigen](https://eigen.tuxfamily.org/) and [OpenCV](https://opencv.org/). diff --git a/examples/cpp/incremental_logging/README.md b/examples/cpp/incremental_logging/README.md index 8903c7e83aad..707b7aefd6a0 100644 --- a/examples/cpp/incremental_logging/README.md +++ b/examples/cpp/incremental_logging/README.md @@ -3,7 +3,7 @@ title = "Incremental Logging" tags = ["3D", "api-example"] description = "Showcases how to incrementally log data belonging to the same archetype." thumbnail = "https://static.rerun.io/incremental_logging/b7a2bd889b09c3840f56dc31bd6d677934ab3126/480w.png" -thumbnail_dimensions = [480, 285] +thumbnail_dimensions = [480, 301] --> diff --git a/examples/cpp/minimal/README.md b/examples/cpp/minimal/README.md index 0ecce0696a94..fc23daa441c1 100644 --- a/examples/cpp/minimal/README.md +++ b/examples/cpp/minimal/README.md @@ -1,6 +1,7 @@ diff --git a/examples/cpp/stdio/README.md b/examples/cpp/stdio/README.md index 2307966e370e..fde1a696b6d7 100644 --- a/examples/cpp/stdio/README.md +++ b/examples/cpp/stdio/README.md @@ -1,6 +1,7 @@ diff --git a/examples/cpp/vrs/README.md b/examples/cpp/vrs/README.md index 01e5fb03e47d..82521c276f0a 100644 --- a/examples/cpp/vrs/README.md +++ b/examples/cpp/vrs/README.md @@ -2,8 +2,8 @@ title = "VRS Viewer" source = "https://github.com/rerun-io/cpp-example-vrs" tags = ["2D", "3D", "vrs", "viewer", "C++"] -thumbnail = "https://static.rerun.io/cpp-example-vrs/c765460d4448da27bb9ee2a2a15f092f82a402d2/480w.png" -thumbnail_dimensions = [480, 286] +thumbnail = "https://static.rerun.io/vrs-viewer/28da92ebc2f0bccd5cf904314d2f8b0b0c45c879/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/arflow/README.md b/examples/python/arflow/README.md index 64409706dae5..909c020e9a4a 100644 --- a/examples/python/arflow/README.md +++ b/examples/python/arflow/README.md @@ -2,8 +2,8 @@ title = "ARFlow: A Framework for Simplifying AR Experimentation Workflow" source = "https://github.com/cake-lab/ARFlow" tags = ["3D", "Augmented Reality", "Spatial Computing"] -thumbnail = "https://static.rerun.io/arflow/cc3b0c748e8fc49a78b33631a7005ede3fce44be/480w.png" -thumbnail_dimensions = [480, 261] +thumbnail = "https://static.rerun.io/arflow/a6b509af10a42b3c7ad3909d44e972a3cb1a9c41/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/arkit_scenes/README.md b/examples/python/arkit_scenes/README.md index ba8c8cf64c9f..9b230c9584cb 100644 --- a/examples/python/arkit_scenes/README.md +++ b/examples/python/arkit_scenes/README.md @@ -2,8 +2,8 @@ title = "ARKit Scenes" tags = ["2D", "3D", "depth", "mesh", "object-detection", "pinhole-camera"] description = "Visualize the ARKitScenes dataset, which contains color+depth images, the reconstructed mesh and labeled bounding boxes." -thumbnail = "https://static.rerun.io/arkit_scenes/fb9ec9e8d965369d39d51b17fc7fc5bae6be10cc/480w.png" -thumbnail_dimensions = [480, 243] +thumbnail = "https://static.rerun.io/arkit-scenes/6d920eaa42fb86cfd264d47180ecbecbb6dd3e09/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" --> diff --git a/examples/python/clock/README.md b/examples/python/clock/README.md index db90bf1543cb..d3a4b5c189d2 100644 --- a/examples/python/clock/README.md +++ b/examples/python/clock/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/controlnet/README.md b/examples/python/controlnet/README.md index f898dbcd252d..c9da19dce97a 100644 --- a/examples/python/controlnet/README.md +++ b/examples/python/controlnet/README.md @@ -2,8 +2,8 @@ title = "ControlNet" tags = ["controlnet", "canny", "huggingface", "stable-diffusion", "tensor", "text"] description = "Use Hugging Face's ControlNet to generate an image from text, conditioned on detected edges from another image." -thumbnail = "https://static.rerun.io/controlnet/8aace9c59a423c2eeabe4b7f9abb5187559c52e8/480w.png" -thumbnail_dimensions = [480, 303] +thumbnail = "https://static.rerun.io/controlnet/2e984b27dd8120fb89d4e805df9da506ea6d9138/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/depth_guided_stable_diffusion/README.md b/examples/python/depth_guided_stable_diffusion/README.md index 867c02c0e774..be85cd53c7ad 100644 --- a/examples/python/depth_guided_stable_diffusion/README.md +++ b/examples/python/depth_guided_stable_diffusion/README.md @@ -1,8 +1,8 @@ diff --git a/examples/python/detect_and_track_objects/README.md b/examples/python/detect_and_track_objects/README.md index c99893270df9..8dacfd1fbb00 100644 --- a/examples/python/detect_and_track_objects/README.md +++ b/examples/python/detect_and_track_objects/README.md @@ -2,8 +2,8 @@ title = "Detect and Track Objects" tags = ["2D", "huggingface", "object-detection", "object-tracking", "opencv"] description = "Visualize object detection and segmentation using the Huggingface `transformers` library." -thumbnail = "https://static.rerun.io/detect_and_track_objects/59f5b97a8724f9037353409ab3d0b7cb47d1544b/480w.png" -thumbnail_dimensions = [480, 279] +thumbnail = "https://static.rerun.io/detect-and-track-objects/63d7684ab1504c86a5375cb5db0fc515af433e08/480w.png" +thumbnail_dimensions = [480, 480] channel = "release" --> diff --git a/examples/python/dicom_mri/README.md b/examples/python/dicom_mri/README.md index 2841b985ffc0..2f4477b8af60 100644 --- a/examples/python/dicom_mri/README.md +++ b/examples/python/dicom_mri/README.md @@ -2,8 +2,8 @@ title = "Dicom MRI" tags = ["tensor", "mri", "dicom"] description = "Example using a DICOM MRI scan. This demonstrates the flexible tensor slicing capabilities of the Rerun viewer." -thumbnail = "https://static.rerun.io/dicom_mri/e39f34a1b1ddd101545007f43a61783e1d2e5f8e/480w.png" -thumbnail_dimensions = [480, 285] +thumbnail = "https://static.rerun.io/dicom-mri/d5a434f92504e8dda8af6c7f4eded2a9d662c991/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" --> diff --git a/examples/python/differentiable_blocks_world/README.md b/examples/python/differentiable_blocks_world/README.md index 7704ab6b8cb7..2541ca5ca06a 100644 --- a/examples/python/differentiable_blocks_world/README.md +++ b/examples/python/differentiable_blocks_world/README.md @@ -2,8 +2,8 @@ title = "Differentiable Blocks World: Qualitative 3D Decomposition by Rendering Primitives" source = "https://github.com/rerun-io/differentiable-blocksworld" tags = ["3D", "mesh", "pinhole-camera"] -thumbnail = "https://static.rerun.io/dbw/1da9e778d5fc9875a28a1fd74b61654c287e950d/480w.png" -thumbnail_dimensions = [480, 311] +thumbnail = "https://static.rerun.io/differentiable-blocks/42f3a5481162a0e75f1c52ef1a12d4fedb35389e/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/face_tracking/README.md b/examples/python/face_tracking/README.md index 7500611e49e1..c5c491e65efc 100644 --- a/examples/python/face_tracking/README.md +++ b/examples/python/face_tracking/README.md @@ -1,8 +1,8 @@ diff --git a/examples/python/gesture_detection/README.md b/examples/python/gesture_detection/README.md index c70dd9c9dbd2..58231fe484a0 100644 --- a/examples/python/gesture_detection/README.md +++ b/examples/python/gesture_detection/README.md @@ -2,8 +2,8 @@ title = "Hand Tracking and Gesture Recognition" tags = ["mediapipe", "keypoint-detection", "2D", "3D"] description = "Use the MediaPipe Gesture Detection solution to track hand and recognize gestures in image/video." -thumbnail = "https://static.rerun.io/gesture_detection/2a5a3ec83962623063297fd95de57062372d5db0/480w.png" -thumbnail_dimensions = [480, 259] +thumbnail = "https://static.rerun.io/hand-tracking-and-gesture-recognition/56d097e347af2a4b7c4649c7d994cc038c02c2f4/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/human_pose_tracking/README.md b/examples/python/human_pose_tracking/README.md index 8cd77b4557bd..adec70e1b05c 100644 --- a/examples/python/human_pose_tracking/README.md +++ b/examples/python/human_pose_tracking/README.md @@ -2,8 +2,8 @@ title = "Human Pose Tracking" tags = ["mediapipe", "keypoint-detection", "2D", "3D"] description = "Use the MediaPipe Pose solution to detect and track a human pose in video." -thumbnail = "https://static.rerun.io/human_pose_tracking/37d47fe7e3476513f9f58c38da515e2cd4a093f9/480w.png" -thumbnail_dimensions = [480, 272] +thumbnail = "https://static.rerun.io/human-pose-tracking/5d62a38b48bed1467698d4dc95c1f9fba786d254/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" --> diff --git a/examples/python/lidar/README.md b/examples/python/lidar/README.md index 518b4180660c..15feac668d08 100644 --- a/examples/python/lidar/README.md +++ b/examples/python/lidar/README.md @@ -2,8 +2,8 @@ title = "Lidar" tags = ["lidar", "3D"] description = "Visualize the lidar data from the nuScenes dataset." -thumbnail = "https://static.rerun.io/lidar/bcea9337044919c1524429bd26bc51a3c4db8ccb/480w.png" -thumbnail_dimensions = [480, 286] +thumbnail = "https://static.rerun.io/lidar/caaf3b9531e50285442d17f0bc925eb7c8e12246/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/limap/README.md b/examples/python/limap/README.md index 553078485678..05b8f021827f 100644 --- a/examples/python/limap/README.md +++ b/examples/python/limap/README.md @@ -2,8 +2,8 @@ title = "3D Line Mapping Revisited" source = "https://github.com/rerun-io/limap" tags = ["2D", "3D", "structure-from-motion", "time-series", "line-detection", "pinhole-camera"] -thumbnail = "https://static.rerun.io/limap/30b9ad1ae36df7dc809edfd40c11620292bc7294/480w.png" -thumbnail_dimensions = [480, 277] +thumbnail = "https://static.rerun.io/3d-line-mapping-revisited/be0a3b8ac0836036862d773b4276ea9d7ffb27b8/480w.png" # NOLINT +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/live_camera_edge_detection/README.md b/examples/python/live_camera_edge_detection/README.md index 6b7ae789f8b7..3b404e072867 100644 --- a/examples/python/live_camera_edge_detection/README.md +++ b/examples/python/live_camera_edge_detection/README.md @@ -1,8 +1,8 @@ diff --git a/examples/python/llm_embedding_ner/README.md b/examples/python/llm_embedding_ner/README.md index 2c84a1577235..d6ae8025d0b2 100644 --- a/examples/python/llm_embedding_ner/README.md +++ b/examples/python/llm_embedding_ner/README.md @@ -1,8 +1,8 @@ diff --git a/examples/python/mcc/README.md b/examples/python/mcc/README.md index 74ea26745d8d..1ed1dbf3ff10 100644 --- a/examples/python/mcc/README.md +++ b/examples/python/mcc/README.md @@ -2,8 +2,8 @@ title = "Single Image 3D Reconstruction using MCC, SAM, and ZoeDepth" source = "https://github.com/rerun-io/MCC" tags = ["2D", "3D", "segmentation", "point-cloud", "sam"] -thumbnail = "https://static.rerun.io/mcc/d244be2806b5abcc0e905a2c262b491b73914658/480w.png" -thumbnail_dimensions = [480, 274] +thumbnail = "https://static.rerun.io/single-image-3D-reconstruction/c54498053d53148cfa43901f39a084c549df2b72/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/minimal/README.md b/examples/python/minimal/README.md index d7ae9f724eb8..388248e9d268 100644 --- a/examples/python/minimal/README.md +++ b/examples/python/minimal/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/multiprocessing/README.md b/examples/python/multiprocessing/README.md index ba091f51b874..9448190c965c 100644 --- a/examples/python/multiprocessing/README.md +++ b/examples/python/multiprocessing/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/multithreading/README.md b/examples/python/multithreading/README.md index 2cd2a50b9e3e..730090633cc6 100644 --- a/examples/python/multithreading/README.md +++ b/examples/python/multithreading/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/objectron/README.md b/examples/python/objectron/README.md index a57c3be51bca..c1bfc41a39f3 100644 --- a/examples/python/objectron/README.md +++ b/examples/python/objectron/README.md @@ -2,8 +2,8 @@ title = "Objectron" tags = ["2D", "3D", "object-detection", "pinhole-camera"] description = "Example of using the Rerun SDK to log the Google Research Objectron dataset." -thumbnail = "https://static.rerun.io/objectron/8ea3a37e6b4af2e06f8e2ea5e70c1951af67fea8/480w.png" -thumbnail_dimensions = [480, 268] +thumbnail = "https://static.rerun.io/objectron/b645ef3c8eff33fbeaefa6d37e0f9711be15b202/480w.png" +thumbnail_dimensions = [480, 480] # channel = "release" - Disabled because it sometimes have bad first-frame heuristics build_args = ["--frames=150"] --> diff --git a/examples/python/plots/README.md b/examples/python/plots/README.md index b86a3806592d..4599b7b7a192 100644 --- a/examples/python/plots/README.md +++ b/examples/python/plots/README.md @@ -2,8 +2,8 @@ title = "Plots" tags = ["2D", "plots", "api-example"] description = "Demonstration of various plots and charts supported by Rerun." -thumbnail = "https://static.rerun.io/plots/c5b91cf0bf2eaf91c71d6cdcd4fe312d4aeac572/480w.png" -thumbnail_dimensions = [480, 271] +thumbnail = "https://static.rerun.io/plots/e8e51071f6409f61dc04a655d6b9e1caf8179226/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" --> diff --git a/examples/python/raw_mesh/README.md b/examples/python/raw_mesh/README.md index c285d0daf7be..f97e05850902 100644 --- a/examples/python/raw_mesh/README.md +++ b/examples/python/raw_mesh/README.md @@ -2,8 +2,8 @@ title = "Raw Mesh" tags = ["mesh"] description = "Demonstrates logging of raw 3D mesh data with simple material properties." -thumbnail = "https://static.rerun.io/raw_mesh/d5d008b9f1b53753a86efe2580443a9265070b77/480w.png" -thumbnail_dimensions = [480, 296] +thumbnail = "https://static.rerun.io/raw-mesh/7731418dda47e15dbfc0f9a2c32673909071cb40/480w.png" +thumbnail_dimensions = [480, 480] channel = "release" --> diff --git a/examples/python/rgbd/README.md b/examples/python/rgbd/README.md index 7ac0b30bfd8f..025f716b0ef3 100644 --- a/examples/python/rgbd/README.md +++ b/examples/python/rgbd/README.md @@ -2,8 +2,8 @@ title = "RGBD" tags = ["2D", "3D", "depth", "nyud", "pinhole-camera"] description = "Visualizes an example recording from the NYUD dataset with RGB and Depth channels." -thumbnail = "https://static.rerun.io/rgbd/4109d29ed52fa0a8f980fcdd0e9673360c76879f/480w.png" -thumbnail_dimensions = [480, 254] +thumbnail = "https://static.rerun.io/rgbd/2fde3a620adc8bd9a5680260f0792d16ac5498bd/480w.png" +thumbnail_dimensions = [480, 480] channel = "release" build_args = ["--frames=300"] --> diff --git a/examples/python/ros_node/README.md b/examples/python/ros_node/README.md index 8600aa22e1e2..f4cefa111421 100644 --- a/examples/python/ros_node/README.md +++ b/examples/python/ros_node/README.md @@ -1,8 +1,8 @@ diff --git a/examples/python/segment_anything_model/README.md b/examples/python/segment_anything_model/README.md index 221a694c6aec..3f2629960d80 100644 --- a/examples/python/segment_anything_model/README.md +++ b/examples/python/segment_anything_model/README.md @@ -2,8 +2,8 @@ title = "Segment Anything Model" tags = ["2D", "sam", "segmentation"] description = "Example of using Rerun to log and visualize the output of Meta AI's Segment Anything model." -thumbnail = "https://static.rerun.io/segment_anything_model/6aa2651907efbcf81be55b343caa76b9de5f2138/480w.png" -thumbnail_dimensions = [480, 283] +thumbnail = "https://static.rerun.io/segment-anything-model/36438df27a287e5eff3a673e2464af071e665fdf/480w.png" +thumbnail_dimensions = [480, 480] channel = "release" --> diff --git a/examples/python/shape_pointe/README.md b/examples/python/shape_pointe/README.md index 118688b34927..08ea096db6d6 100644 --- a/examples/python/shape_pointe/README.md +++ b/examples/python/shape_pointe/README.md @@ -2,8 +2,8 @@ title = "Point-E and Shap-E" source = "https://github.com/rerun-io/point-shap-e" tags = ["3D", "diffusion", "point", "mesh"] -thumbnail = "https://static.rerun.io/overview/6516611ebcf25c4b946e3d99c21c6930d4c9f0bd/480w.png" -thumbnail_dimensions = [480, 293] +thumbnail = "https://static.rerun.io/point-e/5b5beb36dce77d2dac7123b197b825421afcaec0/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/signed_distance_fields/README.md b/examples/python/signed_distance_fields/README.md index 1bface96cd58..9c3a04786293 100644 --- a/examples/python/signed_distance_fields/README.md +++ b/examples/python/signed_distance_fields/README.md @@ -1,8 +1,8 @@ diff --git a/examples/python/simplerecon/README.md b/examples/python/simplerecon/README.md index adb6da7453ef..6c86fd86d69a 100644 --- a/examples/python/simplerecon/README.md +++ b/examples/python/simplerecon/README.md @@ -2,8 +2,8 @@ title = "SimpleRecon: 3D Reconstruction Without 3D Convolutions" source = "https://github.com/rerun-io/simplerecon" tags = ["3D", "depth", "time-series", "pinhole-camera", "mesh"] -thumbnail = "https://static.rerun.io/simplerecon/e309760134e44ba5ca1a547cb310d47a19257e5b/480w.png" -thumbnail_dimensions = [480, 271] +thumbnail = "https://static.rerun.io/simplecon/e0f234159cc0f934e6d4a26886b751579f5191f0/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/slahmr/README.md b/examples/python/slahmr/README.md index dbad445366bb..696ccb35f1bc 100644 --- a/examples/python/slahmr/README.md +++ b/examples/python/slahmr/README.md @@ -2,8 +2,8 @@ title = "Decoupling Human and Camera Motion from Videos in the Wild" source = "https://github.com/rerun-io/slahmr" tags = ["3D", "SLAM", "keypoint-detection", "mesh", "time-series"] -thumbnail = "https://static.rerun.io/slahmr/3fad4f6b2c1a807fb92e8d33a2f90f7391c290a2/480w.png" -thumbnail_dimensions = [480, 293] +thumbnail = "https://static.rerun.io/decoupling-human/2f1c7f027668a6fb15865c51197d2ea98b5725a6/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/structure_from_motion/README.md b/examples/python/structure_from_motion/README.md index c0611b2b25a9..052264ca61d7 100644 --- a/examples/python/structure_from_motion/README.md +++ b/examples/python/structure_from_motion/README.md @@ -2,8 +2,8 @@ title = "Structure from Motion" tags = ["2D", "3D", "colmap", "pinhole-camera", "time-series"] description = "Visualize a sparse reconstruction by COLMAP, a general-purpose Structure-from-Motion and Multi-View Stereo pipeline." -thumbnail = "https://static.rerun.io/structure_from_motion/b17f8824291fa1102a4dc2184d13c91f92d2279c/480w.png" -thumbnail_dimensions = [480, 275] +thumbnail = "https://static.rerun.io/structure-from-motion/af24e5e8961f46a9c10399dbc31b6611eea563b4/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" build_args = ["--dataset=colmap_fiat", "--resize=800x600"] --> diff --git a/examples/python/tapir/README.md b/examples/python/tapir/README.md index 984fe670ff99..dc43111ef7d8 100644 --- a/examples/python/tapir/README.md +++ b/examples/python/tapir/README.md @@ -2,8 +2,8 @@ title = "TAPIR: Tracking Any Point with per-frame Initialization and temporal Refinement" source = "https://github.com/rerun-io/tapnet" tags = ["2D", "point-tracking", "time-series", "tensor", "jax"] -thumbnail = "https://static.rerun.io/tapir/f6a7697848c2ac1e7f0b8db5964f39133c520896/480w.png" -thumbnail_dimensions = [480, 288] +thumbnail = "https://static.rerun.io/tapir/35e5cdca6938d6d26a901f9345b1c331ea8ca96c/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/python/widebaseline/README.md b/examples/python/widebaseline/README.md index bea1f81f7e74..5c9a6a6e0e98 100644 --- a/examples/python/widebaseline/README.md +++ b/examples/python/widebaseline/README.md @@ -2,8 +2,8 @@ title = "Learning to Render Novel Views from Wide-Baseline Stereo Pairs" source = "https://github.com/rerun-io/cross_attention_renderer/" tags = ["2D", "3D", "view-synthesis", "time-series", "pinhole-camera"] -thumbnail = "https://static.rerun.io/widebaseline/7bee6a2a13ede34f06a962019080d0dc102707b5/480w.png" -thumbnail_dimensions = [480, 316] +thumbnail = "https://static.rerun.io/learning-to-render/75c96220e356938037dce35fcb5349f5f8064d8f/480w.png" +thumbnail_dimensions = [480, 480] --> diff --git a/examples/rust/clock/README.md b/examples/rust/clock/README.md index b3b78137a610..d91625095c07 100644 --- a/examples/rust/clock/README.md +++ b/examples/rust/clock/README.md @@ -1,6 +1,7 @@ diff --git a/examples/rust/custom_space_view/README.md b/examples/rust/custom_space_view/README.md index 8fc2bb1fa27c..055b5fa03ed5 100644 --- a/examples/rust/custom_space_view/README.md +++ b/examples/rust/custom_space_view/README.md @@ -1,6 +1,7 @@ diff --git a/examples/rust/extend_viewer_ui/README.md b/examples/rust/extend_viewer_ui/README.md index 07716aa596ed..ca90fed23b5a 100644 --- a/examples/rust/extend_viewer_ui/README.md +++ b/examples/rust/extend_viewer_ui/README.md @@ -1,6 +1,7 @@ diff --git a/examples/rust/incremental_logging/README.md b/examples/rust/incremental_logging/README.md index a71984bdf504..3da523165c7d 100644 --- a/examples/rust/incremental_logging/README.md +++ b/examples/rust/incremental_logging/README.md @@ -3,7 +3,7 @@ title = "Incremental Logging" tags = ["3D", "api-example"] description = "Showcases how to incrementally log data belonging to the same archetype." thumbnail = "https://static.rerun.io/incremental_logging/b7a2bd889b09c3840f56dc31bd6d677934ab3126/480w.png" -thumbnail_dimensions = [480, 285] +thumbnail_dimensions = [480, 301] --> diff --git a/examples/rust/minimal/README.md b/examples/rust/minimal/README.md index a2bccf294694..a9bee0fd09a5 100644 --- a/examples/rust/minimal/README.md +++ b/examples/rust/minimal/README.md @@ -1,6 +1,7 @@ diff --git a/examples/rust/minimal_serve/README.md b/examples/rust/minimal_serve/README.md index cab433a1c783..a0f87a2ab11e 100644 --- a/examples/rust/minimal_serve/README.md +++ b/examples/rust/minimal_serve/README.md @@ -1,6 +1,7 @@ diff --git a/examples/rust/objectron/README.md b/examples/rust/objectron/README.md index a2b02adf8a93..2c2726e5ffc6 100644 --- a/examples/rust/objectron/README.md +++ b/examples/rust/objectron/README.md @@ -2,7 +2,8 @@ title = "Objectron" tags = ["2D", "3D", "object-detection", "pinhole-camera"] description = "Example of using the Rerun SDK to log the Google Research Objectron dataset." -thumbnail = "https://static.rerun.io/objectron/8ea3a37e6b4af2e06f8e2ea5e70c1951af67fea8/480w.png" +thumbnail = "https://static.rerun.io/objectron/b645ef3c8eff33fbeaefa6d37e0f9711be15b202/480w.png" +thumbnail_dimensions = [480, 480] build_args = ["--frames=100"] --> diff --git a/examples/rust/raw_mesh/README.md b/examples/rust/raw_mesh/README.md index 3b2b4f29766d..3a58fbeb4295 100644 --- a/examples/rust/raw_mesh/README.md +++ b/examples/rust/raw_mesh/README.md @@ -1,7 +1,8 @@ diff --git a/examples/rust/stdio/README.md b/examples/rust/stdio/README.md index 30862b0e19f2..83eed1d02431 100644 --- a/examples/rust/stdio/README.md +++ b/examples/rust/stdio/README.md @@ -1,6 +1,7 @@ diff --git a/scripts/ci/thumbnails.py b/scripts/ci/thumbnails.py index 0e51b5c8f582..53a8c247d7e7 100755 --- a/scripts/ci/thumbnails.py +++ b/scripts/ci/thumbnails.py @@ -4,6 +4,7 @@ from __future__ import annotations import argparse +from concurrent.futures import ThreadPoolExecutor from io import BytesIO from pathlib import Path from typing import Any, Dict, Generator @@ -30,52 +31,73 @@ def get_thumbnail_dimensions(thumbnail: str) -> tuple[int, int]: def examples_with_thumbnails() -> Generator[Example, None, None]: - for path in Path("examples/python").iterdir(): - if (path / "README.md").exists(): - readme = (path / "README.md").read_text() - fm = load_frontmatter(readme) - if fm is not None and fm.get("thumbnail"): - yield Example(path, readme, fm) + def single_language(lang: str) -> Generator[Example, None, None]: + for path in Path(f"examples/{lang}").iterdir(): + if (path / "README.md").exists(): + readme = (path / "README.md").read_text() + fm = load_frontmatter(readme) + if fm is not None and fm.get("thumbnail"): + yield Example(path, readme, fm) + + yield from single_language("c") + yield from single_language("cpp") + yield from single_language("rust") + yield from single_language("python") def update() -> None: - for example in examples_with_thumbnails(): - width, height = get_thumbnail_dimensions(example.fm["thumbnail"]) + with ThreadPoolExecutor() as ex: + + def work(example: Example): + width, height = get_thumbnail_dimensions(example.fm["thumbnail"]) + + if "thumbnail_dimensions" not in example.fm: + start = example.readme.find("thumbnail = ") + assert start != -1 + end = example.readme.find("\n", start) + assert end != -1 + start = end + 1 + else: + start = example.readme.find("thumbnail_dimensions = ") + assert start != -1 + end = example.readme.find("\n", start) + assert end != -1 - if "thumbnail_dimensions" not in example.fm: - start = example.readme.find("thumbnail: ") - assert start != -1 - end = example.readme.find("\n", start) - assert end != -1 - start = end + 1 - else: - start = example.readme.find("thumbnail_dimensions = ") - assert start != -1 - end = example.readme.find("\n", start) - assert end != -1 + (example.path / "README.md").write_text( + example.readme[:start] + f"thumbnail_dimensions = [{width}, {height}]" + example.readme[end:] + ) - (example.path / "README.md").write_text( - example.readme[:start] + f"thumbnail_dimensions = [{width}, {height}]" + example.readme[end:] - ) + print(f"✔ {example.path}") - print(f"✔ {example.path}") + futures = [ex.submit(work, example) for example in examples_with_thumbnails()] + ex.shutdown() + for future in futures: + future.result() def check() -> None: bad = False - for example in examples_with_thumbnails(): - if not example.fm.get("thumbnail_dimensions"): - print(f"{example.path} has no `thumbnail_dimensions`") - bad = True - continue - - current = tuple(example.fm["thumbnail_dimensions"]) - actual = get_thumbnail_dimensions(example.fm["thumbnail"]) - if current != actual: - print(f"{example.path} `thumbnail_dimensions` are incorrect (current: {current}, actual: {actual})") - bad = True - - print(f"✔ {example.path}") + with ThreadPoolExecutor() as ex: + + def work(example: Example): + nonlocal bad + if not example.fm.get("thumbnail_dimensions"): + print(f"{example.path} has no `thumbnail_dimensions`") + bad = True + return + + current = tuple(example.fm["thumbnail_dimensions"]) + actual = get_thumbnail_dimensions(example.fm["thumbnail"]) + if current != actual: + print(f"{example.path} `thumbnail_dimensions` are incorrect (current: {current}, actual: {actual})") + bad = True + else: + print(f"✔ {example.path}") + + futures = [ex.submit(work, example) for example in examples_with_thumbnails()] + ex.shutdown() + for future in futures: + future.result() if bad: print("Please run `scripts/ci/thumbnails.py update`.") From 4a1f6a4110c7231a4a7507aa08582d28f3ca2209 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 21 Mar 2024 16:45:33 +0100 Subject: [PATCH 090/508] Support toggling item visibility on touch screens (#5624) ### What You can now click the "hover" buttons on list items on touch screens, by first selecting the item, which will now make the buttons appear. I also did a few other improvements. **Best reviewed commit by commit** ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5624/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5624/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5624/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5624) - [Docs preview](https://rerun.io/preview/0e0bee82f711f38ac23dcae16ffed87bf9cf96b0/docs) - [Examples preview](https://rerun.io/preview/0e0bee82f711f38ac23dcae16ffed87bf9cf96b0/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_ui/examples/re_ui_example.rs | 2 +- crates/re_ui/src/list_item.rs | 135 ++++++++++-------- crates/re_viewer/src/ui/recordings_panel.rs | 2 +- crates/re_viewer/src/ui/selection_panel.rs | 2 +- .../src/ui/space_view_space_origin_ui.rs | 2 +- 5 files changed, 79 insertions(+), 64 deletions(-) diff --git a/crates/re_ui/examples/re_ui_example.rs b/crates/re_ui/examples/re_ui_example.rs index 02c7bc0a4edb..575b2482fa1b 100644 --- a/crates/re_ui/examples/re_ui_example.rs +++ b/crates/re_ui/examples/re_ui_example.rs @@ -382,7 +382,7 @@ impl eframe::App for ExampleApp { let mut item = re_ui .list_item(label) .selected(Some(i) == self.selected_list_item) - .active(i != 3) + .interactive(i != 3) .with_buttons(|re_ui, ui| { re_ui.small_icon_button(ui, &re_ui::icons::ADD) | re_ui.small_icon_button(ui, &re_ui::icons::REMOVE) diff --git a/crates/re_ui/src/list_item.rs b/crates/re_ui/src/list_item.rs index d304cac2735b..95ed98475803 100644 --- a/crates/re_ui/src/list_item.rs +++ b/crates/re_ui/src/list_item.rs @@ -1,5 +1,5 @@ use crate::{Icon, LabelStyle, ReUi}; -use egui::epaint::text::TextWrapping; +use egui::{epaint::text::TextWrapping, WidgetText}; use egui::{Align, Align2, Response, Shape, Ui}; use std::default::Default; @@ -111,7 +111,7 @@ pub enum WidthAllocationMode { pub struct ListItem<'a> { text: egui::WidgetText, re_ui: &'a ReUi, - active: bool, + interactive: bool, selected: bool, draggable: bool, drag_target: bool, @@ -133,7 +133,7 @@ impl<'a> ListItem<'a> { Self { text: text.into(), re_ui, - active: true, + interactive: true, selected: false, draggable: false, drag_target: false, @@ -150,10 +150,12 @@ impl<'a> ListItem<'a> { } } - /// Set the active state the item. + /// Can the user click and interact with it? + /// + /// Set to `false` for items that only show info, but shouldn't be interactive. #[inline] - pub fn active(mut self, active: bool) -> Self { - self.active = active; + pub fn interactive(mut self, interactive: bool) -> Self { + self.interactive = interactive; self } @@ -272,6 +274,8 @@ impl<'a> ListItem<'a> { /// Provide a closure to display on-hover buttons on the right of the item. /// + /// Buttons also show when the item is selected, in order to support clicking them on touch screens. + /// /// Notes: /// - If buttons are used, the item will allocate the full available width of the parent. If the /// enclosing UI adapts to the childrens width, it will unnecessarily grow. If buttons aren't @@ -352,42 +356,59 @@ impl<'a> ListItem<'a> { } } - fn ui(mut self, ui: &mut Ui, id: Option) -> ListItemResponse { - let collapse_extra = if self.collapse_openness.is_some() { + fn ui(self, ui: &mut Ui, id: Option) -> ListItemResponse { + let Self { + mut text, + re_ui, + interactive, + selected, + draggable, + drag_target, + subdued, + weak, + mut italics, + label_style, + force_hovered, + collapse_openness, + height, + width_allocation_mode, + icon_fn, + buttons_fn, + } = self; + + let collapse_extra = if collapse_openness.is_some() { ReUi::collapsing_triangle_area().x + ReUi::text_to_icon_padding() } else { 0.0 }; - let icon_extra = if self.icon_fn.is_some() { + let icon_extra = if icon_fn.is_some() { ReUi::small_icon_size().x + ReUi::text_to_icon_padding() } else { 0.0 }; - match self.label_style { + match label_style { LabelStyle::Normal => {} LabelStyle::Unnamed => { - self.italics = true; + italics = true; } } - if self.italics { - self.text = self.text.italics(); + if italics { + text = text.italics(); } /// Compute the "ideal" desired width of the item, accounting for text and icon(s) (but not /// buttons). fn icons_and_label_width( ui: &egui::Ui, - item: &ListItem<'_>, + text: &WidgetText, collapse_extra: f32, icon_extra: f32, ) -> f32 { - let layout_job = item.text.clone().into_layout_job( - ui.style(), - egui::FontSelection::Default, - Align::LEFT, - ); + let layout_job = + text.clone() + .into_layout_job(ui.style(), egui::FontSelection::Default, Align::LEFT); let galley = ui.fonts(|fonts| fonts.layout_job(layout_job)); let text_width = galley.size().x; @@ -397,22 +418,23 @@ impl<'a> ListItem<'a> { (collapse_extra + icon_extra + text_width).ceil() } - let desired_width = match self.width_allocation_mode { + let desired_width = match width_allocation_mode { WidthAllocationMode::Available => ui.available_width(), WidthAllocationMode::Compact => { - icons_and_label_width(ui, &self, collapse_extra, icon_extra) + icons_and_label_width(ui, &text, collapse_extra, icon_extra) } }; - let desired_size = egui::vec2(desired_width, self.height); - let (rect, mut response) = ui.allocate_at_least( - desired_size, - if self.draggable { - egui::Sense::click_and_drag() - } else { - egui::Sense::click() - }, - ); + let desired_size = egui::vec2(desired_width, height); + + let sense = if !interactive { + egui::Sense::hover() + } else if draggable { + egui::Sense::click_and_drag() + } else { + egui::Sense::click() + }; + let (rect, mut response) = ui.allocate_at_least(desired_size, sense); // compute the full-span background rect let mut bg_rect = rect; @@ -421,14 +443,14 @@ impl<'a> ListItem<'a> { // we want to be able to select/hover the item across its full span, so we sense that and // update the response accordingly. - let full_span_response = ui.interact(bg_rect, response.id, egui::Sense::click()); + let full_span_response = ui.interact(bg_rect, response.id, sense); response.clicked = full_span_response.clicked; response.contains_pointer = full_span_response.contains_pointer; response.hovered = full_span_response.hovered; // override_hover should not affect the returned response let mut style_response = response.clone(); - if self.force_hovered { + if force_hovered { style_response.contains_pointer = true; style_response.hovered = true; } @@ -436,24 +458,19 @@ impl<'a> ListItem<'a> { let mut collapse_response = None; if ui.is_rect_visible(bg_rect) { - let mut visuals = if self.active { - ui.style() - .interact_selectable(&style_response, self.selected) - } else { - ui.visuals().widgets.inactive - }; + let mut visuals = ui.style().interact_selectable(&style_response, selected); // TODO(ab): use design tokens instead - if self.weak { + if weak { visuals.fg_stroke.color = ui.visuals().weak_text_color(); - } else if self.subdued { + } else if subdued { visuals.fg_stroke.color = visuals.fg_stroke.color.gamma_multiply(0.5); } let background_frame = ui.painter().add(egui::Shape::Noop); // Draw collapsing triangle - if let Some(openness) = self.collapse_openness { + if let Some(openness) = collapse_openness { let triangle_pos = ui.painter().round_pos_to_pixels(egui::pos2( rect.min.x, rect.center().y - 0.5 * ReUi::collapsing_triangle_area().y, @@ -470,28 +487,27 @@ impl<'a> ListItem<'a> { } // Draw icon - if let Some(icon_fn) = self.icon_fn { + if let Some(icon_fn) = icon_fn { let icon_pos = ui.painter().round_pos_to_pixels(egui::pos2( rect.min.x + collapse_extra, rect.center().y - 0.5 * ReUi::small_icon_size().y, )); let icon_rect = egui::Rect::from_min_size(icon_pos, ReUi::small_icon_size()); - icon_fn(self.re_ui, ui, icon_rect, visuals); + icon_fn(re_ui, ui, icon_rect, visuals); } - // Handle buttons - // Note: We should be able to just use `response.hovered()` here, which only returns `true` if no drag is in - // progress. Due to the response merging we do above, this breaks though. This is why we do an explicit - // rectangle and drag payload check. - //TODO(ab): refactor responses to address that. - let should_show_buttons = self.active - && ui.rect_contains_pointer(rect) - && !egui::DragAndDrop::has_any_payload(ui.ctx()); + // We can't use `.hovered()` or the buttons disappear just as the user clicks, + // so we use `contains_pointer` instead. That also means we need to check + // that we aren't dragging anything. + let should_show_buttons = interactive + && full_span_response.contains_pointer() + && !egui::DragAndDrop::has_any_payload(ui.ctx()) + || selected; // by showing the buttons when selected, we allow users to find them on touch screens let button_response = if should_show_buttons { - if let Some(buttons) = self.buttons_fn { + if let Some(buttons) = buttons_fn { let mut ui = ui.child_ui(rect, egui::Layout::right_to_left(egui::Align::Center)); - Some(buttons(self.re_ui, &mut ui)) + Some(buttons(re_ui, &mut ui)) } else { None } @@ -506,16 +522,15 @@ impl<'a> ListItem<'a> { text_rect.max.x -= button_response.rect.width() + ReUi::text_to_icon_padding(); } - match self.label_style { + match label_style { LabelStyle::Normal => {} LabelStyle::Unnamed => { - self.text = self.text.color(visuals.fg_stroke.color.gamma_multiply(0.5)); + text = text.color(visuals.fg_stroke.color.gamma_multiply(0.5)); } } let mut layout_job = - self.text - .into_layout_job(ui.style(), egui::FontSelection::Default, Align::LEFT); + text.into_layout_job(ui.style(), egui::FontSelection::Default, Align::LEFT); layout_job.wrap = TextWrapping::truncate_at_width(text_rect.width()); let galley = ui.fonts(|fonts| fonts.layout_job(layout_job)); @@ -524,7 +539,7 @@ impl<'a> ListItem<'a> { response.widget_info(|| { egui::WidgetInfo::selected( egui::WidgetType::SelectableLabel, - self.selected, + selected, galley.text(), ) }); @@ -536,7 +551,7 @@ impl<'a> ListItem<'a> { ui.painter().galley(text_pos, galley, visuals.text_color()); // Draw background on interaction. - if self.drag_target { + if drag_target { ui.painter().set( background_frame, Shape::rect_stroke(bg_rect, 0.0, (1.0, ui.visuals().selection.bg_fill)), @@ -544,7 +559,7 @@ impl<'a> ListItem<'a> { } else { let bg_fill = if button_response.map_or(false, |r| r.hovered()) { Some(visuals.bg_fill) - } else if self.selected + } else if selected || style_response.hovered() || style_response.highlighted() || style_response.has_focus() diff --git a/crates/re_viewer/src/ui/recordings_panel.rs b/crates/re_viewer/src/ui/recordings_panel.rs index cfb16cbeeec1..fd250e645dd3 100644 --- a/crates/re_viewer/src/ui/recordings_panel.rs +++ b/crates/re_viewer/src/ui/recordings_panel.rs @@ -131,7 +131,7 @@ fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) -> bool { } else { ctx.re_ui .list_item(app_id) - .active(false) + .interactive(false) .show_hierarchical_with_content( ui, ui.make_persistent_id(app_id), diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index a93857e4c027..e85e9fcd20c4 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -226,7 +226,7 @@ fn container_children( ListItem::new(ctx.re_ui, "empty — use the + button to add content") .weak(true) .italics(true) - .active(false) + .interactive(false) .show_flat(ui); } }; diff --git a/crates/re_viewer/src/ui/space_view_space_origin_ui.rs b/crates/re_viewer/src/ui/space_view_space_origin_ui.rs index 7da6db8d4ac3..a5a920b13ad6 100644 --- a/crates/re_viewer/src/ui/space_view_space_origin_ui.rs +++ b/crates/re_viewer/src/ui/space_view_space_origin_ui.rs @@ -212,7 +212,7 @@ fn space_view_space_origin_widget_editing_ui( ) .weak(true) .italics(true) - .active(false) + .interactive(false) .show_flat(ui); } }; From 740bbd9273a46e17590c6d7e3f83a8f50e40cee0 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 21 Mar 2024 16:46:30 +0100 Subject: [PATCH 091/508] Fix RRT-Star example not showing up on website & app-rerun.io (#5628) ### What * Fixes #5387 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/manifest.toml | 3 ++- examples/python/rrt-star/README.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/manifest.toml b/examples/manifest.toml index 15f978fb09e1..fb8519cbae54 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -25,8 +25,8 @@ examples = [ "detect_and_track_objects", "dicom_mri", "face_tracking", - "human_pose_tracking", "gesture_detection", + "human_pose_tracking", "lidar", "live_camera_edge_detection", "live_depth_sensor", @@ -37,6 +37,7 @@ examples = [ "raw_mesh", "rgbd", "ros_node", + "rrt-star", "segment_anything_model", "signed_distance_fields", "structure_from_motion", diff --git a/examples/python/rrt-star/README.md b/examples/python/rrt-star/README.md index 0525c6290947..7566a3c664fc 100644 --- a/examples/python/rrt-star/README.md +++ b/examples/python/rrt-star/README.md @@ -4,6 +4,7 @@ tags = ["2D"] description = "Visualization of the path finding algorithm RRT* in a simple environment." thumbnail= "https://static.rerun.io/rrt-star/4d4684a24eab7d5def5768b7c1685d8b1cb2c010/full.png" thumbnail_dimensions = [1496, 840] +channel = "main" --> From 62c79c7df3a420f72d7defc9d2309f18fb03f0dd Mon Sep 17 00:00:00 2001 From: Andreas Naoum <49308613+andreasnaoum@users.noreply.github.com> Date: Thu, 21 Mar 2024 16:55:07 +0100 Subject: [PATCH 092/508] Fix not logging 3D gesture z component correctly in Gesture Detection example (#5630) Thanks to @Wumpf, we identified a problem in the 3D view and fixed it. It was a typo (y instead z) and made the view look 2D instead of 3D. ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5630/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5630/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5630/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5630) - [Docs preview](https://rerun.io/preview/914724bb330117effecfc3521136802d84f45a0b/docs) - [Examples preview](https://rerun.io/preview/914724bb330117effecfc3521136802d84f45a0b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/gesture_detection/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/python/gesture_detection/main.py b/examples/python/gesture_detection/main.py index 1aad2ad74481..7e617dc3cb87 100755 --- a/examples/python/gesture_detection/main.py +++ b/examples/python/gesture_detection/main.py @@ -98,7 +98,7 @@ def convert_landmarks_to_image_coordinates( @staticmethod def convert_landmarks_to_3d(hand_landmarks: list[list[NormalizedLandmark]]) -> list[tuple[float, float, float]]: - return [(lm.x, lm.y, lm.y) for hand_landmark in hand_landmarks for lm in hand_landmark] + return [(lm.x, lm.y, lm.z) for hand_landmark in hand_landmarks for lm in hand_landmark] def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> None: # Recognize gestures in the image From db2796270eb8cac6e8d0bd651f390a5beac0f913 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 21 Mar 2024 13:38:52 -0400 Subject: [PATCH 093/508] New standalone example showing blueprint configuration of some stock (#5603) ### What This is the example that the blueprint getting started guide / tutorials will be built off of. However, this is a slightly more full-featured example that can be used as a reference and standalone application. ![](https://static.rerun.io/blueprint_stocks/8bfe6f16963acdceb2debb9de9a206dc2eb9b280/1024w.png) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5603/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5603/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5603/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5603) - [Docs preview](https://rerun.io/preview/588e1abcebb80a6b5c2974b3067cfcdb0f7986f9/docs) - [Examples preview](https://rerun.io/preview/588e1abcebb80a6b5c2974b3067cfcdb0f7986f9/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt --- .../src/space_view_class.rs | 1 + examples/python/blueprint_stocks/README.md | 38 ++++ examples/python/blueprint_stocks/main.py | 215 ++++++++++++++++++ .../python/blueprint_stocks/requirements.txt | 3 + examples/python/requirements.txt | 1 + .../rerun_sdk/rerun/blueprint/__init__.py | 2 + rerun_py/rerun_sdk/rerun/blueprint/api.py | 41 +++- .../rerun_sdk/rerun/blueprint/containers.py | 63 +++-- 8 files changed, 338 insertions(+), 26 deletions(-) create mode 100644 examples/python/blueprint_stocks/README.md create mode 100755 examples/python/blueprint_stocks/main.py create mode 100644 examples/python/blueprint_stocks/requirements.txt diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index b77b87db0524..8df51c8066ac 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -404,6 +404,7 @@ It can greatly improve performance (and readability) in such situations as it pr time_zone_for_timestamps, ) }) + .y_axis_width(3) // in digits .label_formatter(move |name, value| { let name = if name.is_empty() { "y" } else { name }; let label = time_type.format( diff --git a/examples/python/blueprint_stocks/README.md b/examples/python/blueprint_stocks/README.md new file mode 100644 index 000000000000..7e8ea96d1ff8 --- /dev/null +++ b/examples/python/blueprint_stocks/README.md @@ -0,0 +1,38 @@ + + + + + + + + + + +This example fetches the last 5 days of stock data for a few different stocks. +We show how Rerun blueprints can then be used to present many different views of the same data. + +```bash +pip install -r examples/python/blueprint_stocks/requirements.txt +python examples/python/blueprint_stocks/blueprint_main.py +``` + +The different blueprints can be explored using the `--blueprint` flag. For example: + +``` +python examples/python/blueprint_stocks/main.py --blueprint=one-stock +``` + +Available choices are: + +- `auto`: Reset the blueprint to the auto layout used by the viewer. +- `one-stock`: Uses a filter to show only a single chart. +- `one-stock-with-info`: Uses a container to layout a chart and its info document +- `one-stock-no-peaks`: Uses a filter to additionally remove some of the data from the chart. +- `compare-two`: Adds data from multiple sources to a single chart. +- `grid`: Shows all the charts in a grid layout. diff --git a/examples/python/blueprint_stocks/main.py b/examples/python/blueprint_stocks/main.py new file mode 100755 index 000000000000..e847587f7038 --- /dev/null +++ b/examples/python/blueprint_stocks/main.py @@ -0,0 +1,215 @@ +#!/usr/bin/env python3 +""" +A simple application that fetches stock data from Yahoo Finance and visualizes it using the Rerun SDK. + +The main focus of this example is using blueprints to control how the data is displayed in the viewer. +""" +from __future__ import annotations + +import argparse +import datetime as dt +from typing import Any + +import humanize +import pytz +import rerun as rr +import rerun.blueprint as rrb +import yfinance as yf + +################################################################################ +# Helper functions to create blueprints +################################################################################ + + +def auto_blueprint() -> rrb.ViewportLike: + """A blueprint enabling auto space views, which matches the application default.""" + return rrb.Viewport(auto_space_views=True, auto_layout=True) + + +def one_stock(symbol: str) -> rrb.ViewportLike: + """Create a blueprint showing a single stock.""" + return rrb.TimeSeriesView(name=f"{symbol}", origin=f"/stocks/{symbol}") + + +def one_stock_with_info(symbol: str) -> rrb.ViewportLike: + """Create a blueprint showing a single stock with its info arranged vertically.""" + return rrb.Vertical( + rrb.TextDocumentView(name=f"{symbol}", origin=f"/stocks/{symbol}/info"), + rrb.TimeSeriesView(name=f"{symbol}", origin=f"/stocks/{symbol}"), + row_shares=[1, 4], + ) + + +def compare_two(symbol1: str, symbol2: str, day: Any) -> rrb.ViewportLike: + """Create a blueprint comparing 2 stocks for a single day.""" + return rrb.TimeSeriesView( + name=f"{symbol1} vs {symbol2} ({day})", + contents=[ + f"+ /stocks/{symbol1}/{day}", + f"+ /stocks/{symbol2}/{day}", + ], + ) + + +def one_stock_no_peaks(symbol: str) -> rrb.ViewportLike: + """ + Create a blueprint showing a single stock without annotated peaks. + + This uses an exclusion pattern to hide the peaks. + """ + return rrb.TimeSeriesView( + name=f"{symbol}", + origin=f"/stocks/{symbol}", + contents=[ + "+ $origin/**", + "- $origin/peaks/**", + ], + ) + + +def stock_grid(symbols: list[str], dates: list[Any]) -> rrb.ViewportLike: + """Create a grid of stocks and their time series over all days.""" + return rrb.Vertical( + contents=[ + rrb.Horizontal( + contents=[rrb.TextDocumentView(name=f"{symbol}", origin=f"/stocks/{symbol}/info")] + + [rrb.TimeSeriesView(name=f"{day}", origin=f"/stocks/{symbol}/{day}") for day in dates], + ) + for symbol in symbols + ] + ) + + +def hide_panels(viewport: rrb.ViewportLike) -> rrb.BlueprintLike: + """Wrap a viewport in a blueprint that hides the time and selection panels.""" + return rrb.Blueprint( + viewport, + rrb.TimePanel(expanded=False), + rrb.SelectionPanel(expanded=False), + ) + + +################################################################################ +# Helper functions for styling +################################################################################ + +brand_colors = { + "AAPL": 0xA2AAADFF, + "AMZN": 0xFF9900FF, + "GOOGL": 0x34A853FF, + "META": 0x0081FBFF, + "MSFT": 0xF14F21FF, +} + + +def style_plot(symbol: str) -> rr.SeriesLine: + return rr.SeriesLine( + color=brand_colors[symbol], + name=symbol, + ) + + +def style_peak(symbol: str) -> rr.SeriesPoint: + return rr.SeriesPoint( + color=0xFF0000FF, + name=f"{symbol} (peak)", + marker="Up", + ) + + +################################################################################ +# Main script +################################################################################ + + +def main() -> None: + parser = argparse.ArgumentParser(description="Visualize stock data using the Rerun SDK") + parser.add_argument( + "--blueprint", + choices=["auto", "one-stock", "one-stock-with-info", "compare-two", "one-stock-no-peaks", "grid"], + default="grid", + help="Select the blueprint to use", + ) + parser.add_argument( + "--show_panels", + action="store_true", + help="Show the time and selection panels", + ) + + rr.script_add_args(parser) + args = parser.parse_args() + + et_timezone = pytz.timezone("America/New_York") + current_date = dt.datetime.now(et_timezone).date() + symbols = ["AAPL", "AMZN", "GOOGL", "META", "MSFT"] + dates = list(filter(lambda x: x.weekday() < 5, [current_date - dt.timedelta(days=i) for i in range(7, 0, -1)])) + + blueprint: rrb.BlueprintLike + + if args.blueprint == "auto": + blueprint = auto_blueprint() + elif args.blueprint == "one-stock": + blueprint = one_stock("AAPL") + elif args.blueprint == "one-stock-with-info": + blueprint = one_stock_with_info("AMZN") + elif args.blueprint == "one-stock-no-peaks": + blueprint = one_stock_no_peaks("GOOGL") + elif args.blueprint == "compare-two": + blueprint = compare_two("META", "MSFT", dates[-1]) + elif args.blueprint == "grid": + blueprint = stock_grid(symbols, dates) + else: + raise ValueError(f"Unknown blueprint: {args.blueprint}") + + if not args.show_panels: + blueprint = hide_panels(blueprint) + + rr.init("rerun_example_blueprint_stocks", spawn=True, blueprint=blueprint) + + # In a future blueprint release, this can move into the blueprint as well + for symbol in symbols: + for day in dates: + rr.log(f"stocks/{symbol}/{day}", style_plot(symbol), timeless=True) + rr.log(f"stocks/{symbol}/peaks/{day}", style_peak(symbol), timeless=True) + + for symbol in symbols: + stock = yf.Ticker(symbol) + + name = stock.info["shortName"] + industry = stock.info["industry"] + marketCap = humanize.intword(stock.info["marketCap"]) + revenue = humanize.intword(stock.info["totalRevenue"]) + + info_md = ( + f"- **Name**: {name}\n" + f"- **Industry**: {industry}\n" + f"- **Market cap**: ${marketCap}\n" + f"- **Total Revenue**: ${revenue}\n" + ) + + rr.log( + f"stocks/{symbol}/info", + rr.TextDocument(info_md, media_type=rr.MediaType.MARKDOWN), + timeless=True, + ) + + for day in dates: + open_time = dt.datetime.combine(day, dt.time(9, 30)) + close_time = dt.datetime.combine(day, dt.time(16, 00)) + + hist = stock.history(start=open_time, end=close_time, interval="5m") + + hist.index = hist.index - et_timezone.localize(open_time) + peak = hist.High.idxmax() + + for row in hist.itertuples(): + rr.set_time_seconds("time", row.Index.total_seconds()) + rr.log(f"stocks/{symbol}/{day}", rr.Scalar(row.High)) + if row.Index == peak: + rr.log(f"stocks/{symbol}/peaks/{day}", rr.Scalar(row.High)) + + rr.script_teardown(args) + + +if __name__ == "__main__": + main() diff --git a/examples/python/blueprint_stocks/requirements.txt b/examples/python/blueprint_stocks/requirements.txt new file mode 100644 index 000000000000..25678ffa93ea --- /dev/null +++ b/examples/python/blueprint_stocks/requirements.txt @@ -0,0 +1,3 @@ +humanize +rerun-sdk +yfinance diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt index c39318a01368..2d9899ef7976 100644 --- a/examples/python/requirements.txt +++ b/examples/python/requirements.txt @@ -1,5 +1,6 @@ -r arkit_scenes/requirements.txt -r blueprint/requirements.txt +-r blueprint_stocks/requirements.txt -r clock/requirements.txt -r controlnet/requirements.txt -r depth_guided_stable_diffusion/requirements.txt diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 0924e508e31a..f0c78a7630b8 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -21,6 +21,7 @@ "TimeSeriesView", "Vertical", "Viewport", + "ViewportLike", ] from . import archetypes, components, datatypes @@ -31,6 +32,7 @@ SelectionPanel, TimePanel, Viewport, + ViewportLike, ) from .containers import Grid, Horizontal, Tabs, Vertical from .space_views import ( diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index bd7cc25fde72..4979406f4d87 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -119,7 +119,8 @@ class Container: def __init__( self, - *contents: Container | SpaceView, + *args: Container | SpaceView, + contents: Optional[Iterable[Container | SpaceView]] = None, kind: ContainerKindLike, column_shares: Optional[ColumnShareArrayLike] = None, row_shares: Optional[RowShareArrayLike] = None, @@ -131,8 +132,11 @@ def __init__( Parameters ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. + *args: + All positional arguments are forwarded to the `contents` parameter for convenience. + contents: + The contents of the container. Each item in the iterable must be a `SpaceView` or a `Container`. + This can only be used if no positional arguments are provided. kind The kind of the container. This must correspond to a known container kind. Prefer to use one of the subclasses of `Container` which will populate this for you. @@ -150,9 +154,17 @@ def __init__( The active tab in the container. This is only applicable to `Tabs` containers. """ + + if args and contents is not None: + raise ValueError("Cannot provide both positional and keyword arguments for contents") + + if contents is not None: + self.contents = contents + else: + self.contents = args + self.id = uuid.uuid4() self.kind = kind - self.contents = contents self.column_shares = column_shares self.row_shares = row_shares self.grid_columns = grid_columns @@ -214,7 +226,11 @@ class Viewport: """ def __init__( - self, root_container: Container, *, auto_layout: bool | None = None, auto_space_views: bool | None = None + self, + root_container: Container | None = None, + *, + auto_layout: bool | None = None, + auto_space_views: bool | None = None, ): """ Construct a new viewport. @@ -255,11 +271,18 @@ def to_blueprint(self) -> Blueprint: def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" - self.root_container._log_to_stream(stream) + if self.root_container is not None: + self.root_container._log_to_stream(stream) + + root_container_id = self.root_container.id.bytes + space_views = list(self.root_container._iter_space_views()) + else: + root_container_id = None + space_views = [] arch = ViewportBlueprint( - space_views=list(self.root_container._iter_space_views()), - root_container=self.root_container.id.bytes, + space_views=space_views, + root_container=root_container_id, auto_layout=self.auto_layout, auto_space_views=self.auto_space_views, ) @@ -434,7 +457,7 @@ def _log_to_stream(self, stream: RecordingStream) -> None: self.time_panel._log_to_stream(stream) -BlueprintLike = Union[Blueprint, Viewport, Container, SpaceView] +BlueprintLike = Union[Blueprint, ViewportLike] """ A type that can be converted to a blueprint. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/containers.py b/rerun_py/rerun_sdk/rerun/blueprint/containers.py index 40c6bc825fb5..b54a509ed36a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/containers.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/containers.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Optional +from typing import Iterable, Optional from .api import Container, SpaceView from .components import ColumnShareArrayLike, RowShareArrayLike @@ -10,39 +10,55 @@ class Horizontal(Container): """A horizontal container.""" - def __init__(self, *contents: Container | SpaceView, column_shares: Optional[ColumnShareArrayLike] = None): + def __init__( + self, + *args: Container | SpaceView, + contents: Optional[Iterable[Container | SpaceView]] = None, + column_shares: Optional[ColumnShareArrayLike] = None, + ): """ Construct a new horizontal container. Parameters ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. + *args: + All positional arguments are forwarded to the `contents` parameter for convenience. + contents: + The contents of the container. Each item in the iterable must be a `SpaceView` or a `Container`. + This can only be used if no positional arguments are provided. column_shares The layout shares of the columns in the container. The share is used to determine what fraction of the total width each column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. """ - super().__init__(*contents, kind=ContainerKind.Horizontal, column_shares=column_shares) + super().__init__(*args, contents=contents, kind=ContainerKind.Horizontal, column_shares=column_shares) class Vertical(Container): """A vertical container.""" - def __init__(self, *contents: Container | SpaceView, row_shares: Optional[RowShareArrayLike] = None): + def __init__( + self, + *args: Container | SpaceView, + contents: Optional[Iterable[Container | SpaceView]] = None, + row_shares: Optional[RowShareArrayLike] = None, + ): """ Construct a new vertical container. Parameters ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. + *args: + All positional arguments are forwarded to the `contents` parameter for convenience. + contents: + The contents of the container. Each item in the iterable must be a `SpaceView` or a `Container`. + This can only be used if no positional arguments are provided. row_shares The layout shares of the rows in the container. The share is used to determine what fraction of the total height each row should take up. The row with index `i` will take up the fraction `shares[i] / total_shares`. """ - super().__init__(*contents, kind=ContainerKind.Vertical, row_shares=row_shares) + super().__init__(*args, contents=contents, kind=ContainerKind.Vertical, row_shares=row_shares) class Grid(Container): @@ -50,7 +66,8 @@ class Grid(Container): def __init__( self, - *contents: Container | SpaceView, + *args: Container | SpaceView, + contents: Optional[Iterable[Container | SpaceView]] = None, column_shares: Optional[ColumnShareArrayLike] = None, row_shares: Optional[RowShareArrayLike] = None, grid_columns: Optional[int] = None, @@ -60,8 +77,11 @@ def __init__( Parameters ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. + *args: + All positional arguments are forwarded to the `contents` parameter for convenience. + contents: + The contents of the container. Each item in the iterable must be a `SpaceView` or a `Container`. + This can only be used if no positional arguments are provided. column_shares The layout shares of the columns in the container. The share is used to determine what fraction of the total width each column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. @@ -73,7 +93,8 @@ def __init__( """ super().__init__( - *contents, + *args, + contents=contents, kind=ContainerKind.Grid, column_shares=column_shares, row_shares=row_shares, @@ -84,16 +105,24 @@ def __init__( class Tabs(Container): """A tab container.""" - def __init__(self, *contents: Container | SpaceView, active_tab: Optional[int | str] = None): + def __init__( + self, + *args: Container | SpaceView, + contents: Optional[Iterable[Container | SpaceView]] = None, + active_tab: Optional[int | str] = None, + ): """ Construct a new tab container. Parameters ---------- - *contents: - All positional arguments are the contents of the container, which may be either other containers or space views. + *args: + All positional arguments are forwarded to the `contents` parameter for convenience. + contents: + The contents of the container. Each item in the iterable must be a `SpaceView` or a `Container`. + This can only be used if no positional arguments are provided. active_tab: The index or name of the active tab. """ - super().__init__(*contents, kind=ContainerKind.Tabs, active_tab=active_tab) + super().__init__(*args, contents=contents, kind=ContainerKind.Tabs, active_tab=active_tab) From 938dadef7de9c9868c4290b022ceea211a4c47b5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 21 Mar 2024 19:03:49 +0100 Subject: [PATCH 094/508] Add blueprint to the RGBD example (#5623) ### What straight forward one, still better with blueprint that without ![image](https://github.com/rerun-io/rerun/assets/1220815/a5dfd820-ef7b-49c8-9f83-4d0c6ceb507c) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5623/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5623/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5623/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5623) - [Docs preview](https://rerun.io/preview/5ab75e993add7467596178e7d71bc9feef0b6984/docs) - [Examples preview](https://rerun.io/preview/5ab75e993add7467596178e7d71bc9feef0b6984/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/rgbd/main.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/examples/python/rgbd/main.py b/examples/python/rgbd/main.py index a70efdcc4be4..14031c5f756a 100755 --- a/examples/python/rgbd/main.py +++ b/examples/python/rgbd/main.py @@ -19,6 +19,7 @@ import numpy.typing as npt import requests import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb from tqdm import tqdm DEPTH_IMAGE_SCALING: Final = 1e4 @@ -160,7 +161,20 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_rgbd") + rr.script_setup( + args, + "rerun_example_rgbd", + blueprint=rrb.Horizontal( + rrb.Spatial3DView(name="3D", origin="world"), + rrb.Vertical( + # Put the origin for both 2D spaces where the pinhole is logged. Doing so allows them to understand how they're connected to the 3D space. + # This enables interactions like clicking on a point in the 3D space to show the corresponding point in the 2D spaces and vice versa. + rrb.Spatial2DView(name="Depth & RGB", origin="world/camera/image"), + rrb.Spatial2DView(name="RGB", origin="world/camera/image", contents="world/camera/image/rgb"), + ), + column_shares=[2, 1], + ), + ) recording_path = ensure_recording_downloaded(args.recording) log_nyud_data( From ae09d2f91bf4c39da764d7c93fc199d94f4f6172 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 21 Mar 2024 19:24:41 +0100 Subject: [PATCH 095/508] Refactor and move `StoreBundle` (#5632) ### What I wanted access to `StoreBundle` in the `SelectionPanel`, which means I wanted access to the `StoreBundle` in the `StoreHub`, which means putting `StoreBundle` in `ViewerContext`, which means moving `StoreBundle` into `re_entity_db` where it belong, which lead me to a bunch of cleanup related to this. `ViewerContext::entity_db` is the badly named recording, and is never `None`. This is duplicated in `StoreContext::recording`, which _could_ be `None`, but now I made it so it is never `None`, making it consistent with `ViewerContext::entity_db`. More is coming, but I am already afraid of merge conflicts, so I wanted to get this in in small pieces. **Best reviewed commit by commit**. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5632/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5632/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5632/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5632) - [Docs preview](https://rerun.io/preview/618967249e9016a70740311dd477c81d16cb68e2/docs) - [Examples preview](https://rerun.io/preview/618967249e9016a70740311dd477c81d16cb68e2/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/annotation_context.rs | 3 +- crates/re_data_ui/src/component_path.rs | 2 +- crates/re_data_ui/src/image.rs | 6 +- crates/re_data_ui/src/instance_path.rs | 2 +- crates/re_data_ui/src/item_ui.rs | 6 +- crates/re_data_ui/src/store_id.rs | 2 +- crates/re_entity_db/Cargo.toml | 2 +- crates/re_entity_db/src/lib.rs | 18 +- crates/re_entity_db/src/store_bundle.rs | 188 +++++++++++++ crates/re_space_view/src/heuristics.rs | 2 +- crates/re_space_view/src/space_view.rs | 16 +- .../re_space_view/src/space_view_contents.rs | 11 +- .../src/visualizer_system.rs | 2 +- .../src/space_view_class.rs | 2 +- .../src/contexts/depth_offsets.rs | 2 +- .../src/contexts/transform_context.rs | 8 +- .../re_space_view_spatial/src/heuristics.rs | 11 +- .../src/space_view_2d.rs | 13 +- .../src/space_view_3d.rs | 7 +- crates/re_space_view_spatial/src/ui.rs | 8 +- crates/re_space_view_spatial/src/ui_2d.rs | 2 +- crates/re_space_view_spatial/src/ui_3d.rs | 3 +- .../src/visualizers/cameras.rs | 2 +- .../src/visualizers/entity_iterator.rs | 12 +- .../src/visualizers/images.rs | 10 +- .../src/visualizers/transform3d_arrows.rs | 6 +- .../src/visualizer_system.rs | 2 +- .../src/visualizer_system.rs | 2 +- .../src/space_view_class.rs | 6 +- .../src/visualizer_system.rs | 4 +- .../src/line_visualizer_system.rs | 7 +- .../src/point_visualizer_system.rs | 7 +- .../src/space_view_class.rs | 2 +- crates/re_time_panel/src/lib.rs | 4 +- crates/re_viewer/src/app.rs | 75 ++--- crates/re_viewer/src/app_state.rs | 45 ++- crates/re_viewer/src/lib.rs | 1 - crates/re_viewer/src/loading.rs | 4 +- crates/re_viewer/src/store_hub.rs | 258 ++---------------- crates/re_viewer/src/ui/override_ui.rs | 6 +- crates/re_viewer/src/ui/recordings_panel.rs | 10 +- crates/re_viewer/src/ui/rerun_menu.rs | 8 +- crates/re_viewer/src/ui/selection_panel.rs | 4 +- crates/re_viewer/src/ui/top_panel.rs | 2 +- crates/re_viewer/src/ui/visible_history.rs | 12 +- crates/re_viewer_context/src/annotations.rs | 2 +- .../re_viewer_context/src/selection_state.rs | 2 +- .../src/space_view/view_query.rs | 3 +- crates/re_viewer_context/src/store_context.rs | 22 +- .../re_viewer_context/src/viewer_context.rs | 22 +- .../actions/add_entities_to_new_space_view.rs | 10 +- .../actions/collapse_expand_all.rs | 6 +- .../src/space_view_entity_picker.rs | 6 +- .../re_viewport/src/viewport_blueprint_ui.rs | 4 +- .../src/color_coordinates_space_view.rs | 4 +- .../color_coordinates_visualizer_system.rs | 2 +- 56 files changed, 423 insertions(+), 465 deletions(-) create mode 100644 crates/re_entity_db/src/store_bundle.rs diff --git a/crates/re_data_ui/src/annotation_context.rs b/crates/re_data_ui/src/annotation_context.rs index 7299e46cc767..2ec9e980e353 100644 --- a/crates/re_data_ui/src/annotation_context.rs +++ b/crates/re_data_ui/src/annotation_context.rs @@ -87,8 +87,7 @@ fn annotation_info( keypoint_id: KeypointId, ) -> Option { let class_id = ctx - .entity_db - .store() + .recording_store() .query_latest_component::(entity_path, query)?; let annotations = crate::annotations(ctx, query, entity_path); let class = annotations.resolved_class_description(Some(*class_id)); diff --git a/crates/re_data_ui/src/component_path.rs b/crates/re_data_ui/src/component_path.rs index c291bcb7083c..49496d789fe0 100644 --- a/crates/re_data_ui/src/component_path.rs +++ b/crates/re_data_ui/src/component_path.rs @@ -29,7 +29,7 @@ impl DataUi for ComponentPath { component_data, } .data_ui(ctx, ui, verbosity, query, store); - } else if let Some(entity_tree) = ctx.entity_db.tree().subtree(entity_path) { + } else if let Some(entity_tree) = ctx.recording().tree().subtree(entity_path) { if entity_tree.entity.components.contains_key(component_name) { ui.label(""); } else { diff --git a/crates/re_data_ui/src/image.rs b/crates/re_data_ui/src/image.rs index 571506da5106..2e71764b2d83 100644 --- a/crates/re_data_ui/src/image.rs +++ b/crates/re_data_ui/src/image.rs @@ -33,8 +33,7 @@ impl EntityDataUi for re_types::components::TensorData { re_tracing::profile_function!(); let tensor_data_row_id = ctx - .entity_db - .store() + .recording_store() .query_latest_component::(entity_path, query) .map_or(RowId::ZERO, |tensor| tensor.row_id); @@ -87,8 +86,7 @@ pub fn tensor_ui( let meaning = image_meaning_for_entity(entity_path, query, store); let meter = if meaning == TensorDataMeaning::Depth { - ctx.entity_db - .store() + ctx.recording_store() .query_latest_component::(entity_path, query) .map(|meter| meter.value.0) } else { diff --git a/crates/re_data_ui/src/instance_path.rs b/crates/re_data_ui/src/instance_path.rs index e54b9f0c7246..3afeaed83944 100644 --- a/crates/re_data_ui/src/instance_path.rs +++ b/crates/re_data_ui/src/instance_path.rs @@ -21,7 +21,7 @@ impl DataUi for InstancePath { } = self; let Some(components) = store.all_components(&query.timeline, entity_path) else { - if ctx.entity_db.is_known_entity(entity_path) { + if ctx.recording().is_known_entity(entity_path) { // This is fine - e.g. we're looking at `/world` and the user has only logged to `/world/car`. ui.label(format!( "No components logged on timeline {:?}", diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 261c1bb61af5..e44124b2d126 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -176,7 +176,7 @@ pub fn guess_query_and_store_for_selected_entity<'a>( } else { ( ctx.rec_cfg.time_ctrl.read().current_query(), - ctx.entity_db.store(), + ctx.recording_store(), ) } } @@ -512,7 +512,7 @@ pub fn instance_hover_card_ui( store: &re_data_store::DataStore, instance_path: &InstancePath, ) { - if !ctx.entity_db.is_known_entity(&instance_path.entity_path) { + if !ctx.recording().is_known_entity(&instance_path.entity_path) { ui.label("Unknown entity."); return; } @@ -529,7 +529,7 @@ pub fn instance_hover_card_ui( // Then we can move the size view into `data_ui`. if instance_path.instance_key.is_splat() { - if let Some(subtree) = ctx.entity_db.tree().subtree(&instance_path.entity_path) { + if let Some(subtree) = ctx.recording().tree().subtree(&instance_path.entity_path) { entity_tree_stats_ui(ui, &query.timeline, subtree); } } else { diff --git a/crates/re_data_ui/src/store_id.rs b/crates/re_data_ui/src/store_id.rs index a9f255e0490f..3aef5003ed2a 100644 --- a/crates/re_data_ui/src/store_id.rs +++ b/crates/re_data_ui/src/store_id.rs @@ -7,7 +7,7 @@ impl crate::DataUi for re_log_types::StoreId { query: &re_data_store::LatestAtQuery, store: &re_data_store::DataStore, ) { - if let Some(entity_db) = ctx.store_context.recording(self) { + if let Some(entity_db) = ctx.store_context.bundle.get(self) { entity_db.data_ui(ctx, ui, verbosity, query, store); } else { ui.label(format!("{} ID {} (not found)", self.kind, self.id)); diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index 74d343032e1d..02e5d93cd799 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -28,7 +28,7 @@ re_data_store.workspace = true re_format.workspace = true re_int_histogram.workspace = true re_log.workspace = true -re_log_encoding = { workspace = true, optional = true } +re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true re_query.workspace = true re_query_cache.workspace = true diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index 6410617d9e4f..af1acbd99217 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -8,6 +8,7 @@ pub mod entity_db; pub mod entity_properties; pub mod entity_tree; mod instance_path; +mod store_bundle; mod time_histogram_per_timeline; mod times_per_timeline; mod versioned_instance_path; @@ -17,13 +18,16 @@ pub mod blueprint; #[cfg(feature = "serde")] mod editable_auto_value; -pub use self::entity_db::EntityDb; -pub use self::entity_properties::*; -pub use self::entity_tree::EntityTree; -pub use self::instance_path::{InstancePath, InstancePathHash}; -pub use self::time_histogram_per_timeline::{TimeHistogram, TimeHistogramPerTimeline}; -pub use self::times_per_timeline::{TimeCounts, TimesPerTimeline}; -pub use self::versioned_instance_path::{VersionedInstancePath, VersionedInstancePathHash}; +pub use self::{ + entity_db::EntityDb, + entity_properties::*, + entity_tree::EntityTree, + instance_path::{InstancePath, InstancePathHash}, + store_bundle::{StoreBundle, StoreLoadError}, + time_histogram_per_timeline::{TimeHistogram, TimeHistogramPerTimeline}, + times_per_timeline::{TimeCounts, TimesPerTimeline}, + versioned_instance_path::{VersionedInstancePath, VersionedInstancePathHash}, +}; pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents}; diff --git a/crates/re_entity_db/src/store_bundle.rs b/crates/re_entity_db/src/store_bundle.rs new file mode 100644 index 000000000000..c7f8592551ba --- /dev/null +++ b/crates/re_entity_db/src/store_bundle.rs @@ -0,0 +1,188 @@ +use itertools::Itertools as _; + +use crate::EntityDb; +use re_log_encoding::decoder::VersionPolicy; +use re_log_types::{StoreId, StoreKind}; + +#[derive(thiserror::Error, Debug)] +pub enum StoreLoadError { + #[error(transparent)] + Decode(#[from] re_log_encoding::decoder::DecodeError), + + #[error(transparent)] + DataStore(#[from] crate::Error), +} + +/// Stores many [`EntityDb`]s of recordings and blueprints. +#[derive(Default)] +pub struct StoreBundle { + // TODO(emilk): two separate maps per [`StoreKind`]. + entity_dbs: ahash::HashMap, +} + +impl StoreBundle { + /// Decode an rrd stream. + /// It can theoretically contain multiple recordings, and blueprints. + pub fn from_rrd( + version_policy: VersionPolicy, + read: impl std::io::Read, + ) -> Result { + re_tracing::profile_function!(); + + let decoder = re_log_encoding::decoder::Decoder::new(version_policy, read)?; + + let mut slf = Self::default(); + + for msg in decoder { + let msg = msg?; + slf.entry(msg.store_id()).add(&msg)?; + } + Ok(slf) + } + + /// All loaded [`EntityDb`], both recordings and blueprints, in arbitrary order. + pub fn entity_dbs(&self) -> impl Iterator { + self.entity_dbs.values() + } + + /// All loaded [`EntityDb`], both recordings and blueprints, in arbitrary order. + pub fn entity_dbs_mut(&mut self) -> impl Iterator { + self.entity_dbs.values_mut() + } + + pub fn append(&mut self, mut other: Self) { + for (id, entity_db) in other.entity_dbs.drain() { + self.entity_dbs.insert(id, entity_db); + } + } + + pub fn remove(&mut self, id: &StoreId) { + self.entity_dbs.remove(id); + } + + // -- + + pub fn contains(&self, id: &StoreId) -> bool { + self.entity_dbs.contains_key(id) + } + + pub fn get(&self, id: &StoreId) -> Option<&EntityDb> { + self.entity_dbs.get(id) + } + + pub fn get_mut(&mut self, id: &StoreId) -> Option<&mut EntityDb> { + self.entity_dbs.get_mut(id) + } + + /// Returns either a recording or blueprint [`EntityDb`]. + /// One is created if it doesn't already exist. + pub fn entry(&mut self, id: &StoreId) -> &mut EntityDb { + self.entity_dbs.entry(id.clone()).or_insert_with(|| { + re_log::debug!("Creating new store: {id}"); + EntityDb::new(id.clone()) + }) + } + + /// Creates one if it doesn't exist. + /// + /// Like [`Self::entry`] but also sets `StoreInfo` to a default value. + pub fn blueprint_entry(&mut self, id: &StoreId) -> &mut EntityDb { + debug_assert_eq!(id.kind, StoreKind::Blueprint); + + self.entity_dbs.entry(id.clone()).or_insert_with(|| { + // TODO(jleibs): If the blueprint doesn't exist this probably means we are + // initializing a new default-blueprint for the application in question. + // Make sure it's marked as a blueprint. + + let mut blueprint_db = EntityDb::new(id.clone()); + + re_log::debug!("Creating a new blueprint {id}"); + + blueprint_db.set_store_info(re_log_types::SetStoreInfo { + row_id: re_log_types::RowId::new(), + info: re_log_types::StoreInfo { + application_id: id.as_str().into(), + store_id: id.clone(), + is_official_example: false, + started: re_log_types::Time::now(), + store_source: re_log_types::StoreSource::Other("viewer".to_owned()), + store_kind: StoreKind::Blueprint, + }, + }); + + blueprint_db + }) + } + + pub fn insert(&mut self, entity_db: EntityDb) { + self.entity_dbs + .insert(entity_db.store_id().clone(), entity_db); + } + + /// In no particular order. + pub fn recordings(&self) -> impl Iterator { + self.entity_dbs + .values() + .filter(|log| log.store_kind() == StoreKind::Recording) + } + + /// In no particular order. + pub fn blueprints(&self) -> impl Iterator { + self.entity_dbs + .values() + .filter(|log| log.store_kind() == StoreKind::Blueprint) + } + + // -- + + pub fn retain(&mut self, mut f: impl FnMut(&EntityDb) -> bool) { + self.entity_dbs.retain(|_, db| f(db)); + } + + pub fn purge_empty(&mut self) { + self.entity_dbs.retain(|_, entity_db| !entity_db.is_empty()); + } + + pub fn drain_entity_dbs(&mut self) -> impl Iterator + '_ { + self.entity_dbs.drain().map(|(_, store)| store) + } + + // -- + + /// Returns the closest "neighbor" recording to the given id. + /// + /// The closest neighbor is the next recording when sorted by (app ID, time), if any, or the + /// previous one otherwise. This is used to update the selected recording when the current one + /// is deleted. + pub fn find_closest_recording(&self, id: &StoreId) -> Option<&StoreId> { + let mut recs = self.recordings().collect_vec(); + recs.sort_by_key(|entity_db| entity_db.sort_key()); + + let cur_pos = recs.iter().position(|rec| rec.store_id() == id); + + if let Some(cur_pos) = cur_pos { + if recs.len() > cur_pos + 1 { + Some(recs[cur_pos + 1].store_id()) + } else if cur_pos > 0 { + Some(recs[cur_pos - 1].store_id()) + } else { + None + } + } else { + None + } + } + + /// Returns the [`StoreId`] of the oldest modified recording, according to [`EntityDb::last_modified_at`]. + pub fn find_oldest_modified_recording(&self) -> Option<&StoreId> { + let mut entity_dbs = self + .entity_dbs + .values() + .filter(|db| db.store_kind() == StoreKind::Recording) + .collect_vec(); + + entity_dbs.sort_by_key(|db| db.last_modified_at()); + + entity_dbs.first().map(|db| db.store_id()) + } +} diff --git a/crates/re_space_view/src/heuristics.rs b/crates/re_space_view/src/heuristics.rs index 264ccfb51d84..386264427582 100644 --- a/crates/re_space_view/src/heuristics.rs +++ b/crates/re_space_view/src/heuristics.rs @@ -33,7 +33,7 @@ where let recommended_space_views = applicable_entities .intersection(indicator_matching_entities) .filter_map(|entity| { - let context = space_view.visualizable_filter_context(entity, ctx.entity_db); + let context = space_view.visualizable_filter_context(entity, ctx.recording()); if visualizer .filter_visualizable_entities( ApplicableEntities(std::iter::once(entity.clone()).collect()), diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 38be63729fd1..49aefde8dfa6 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -577,8 +577,8 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], + recording: &recording, + bundle: &Default::default(), }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -620,8 +620,8 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], + recording: &recording, + bundle: &Default::default(), }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -669,8 +669,8 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], + recording: &recording, + bundle: &Default::default(), }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -941,8 +941,8 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], + recording: &recording, + bundle: &Default::default(), }; let mut query_result = space_view .contents diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 0f896be2f9cf..70287ab685f1 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -223,10 +223,11 @@ impl DataQuery for SpaceViewContents { let executor = QueryExpressionEvaluator::new(self, visualizable_entities_for_visualizer_systems); - let root_handle = ctx.recording.and_then(|store| { + let root_handle = { re_tracing::profile_scope!("add_entity_tree_to_data_results_recursive"); - executor.add_entity_tree_to_data_results_recursive(store.tree(), &mut data_results) - }); + executor + .add_entity_tree_to_data_results_recursive(ctx.recording.tree(), &mut data_results) + }; DataQueryResult { tree: DataResultTree::new(data_results, root_handle), @@ -642,8 +643,8 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, - recording: Some(&recording), - all_recordings: vec![], + recording: &recording, + bundle: &Default::default(), }; struct Scenario { diff --git a/crates/re_space_view_bar_chart/src/visualizer_system.rs b/crates/re_space_view_bar_chart/src/visualizer_system.rs index ef93f0024656..fd7ba62be6ca 100644 --- a/crates/re_space_view_bar_chart/src/visualizer_system.rs +++ b/crates/re_space_view_bar_chart/src/visualizer_system.rs @@ -48,7 +48,7 @@ impl VisualizerSystem for BarChartVisualizerSystem { ) -> Result, SpaceViewSystemExecutionError> { re_tracing::profile_function!(); - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let query = LatestAtQuery::new(query.timeline, query.latest_at); diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index 82454150c679..05f379c5c714 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -86,7 +86,7 @@ impl SpaceViewClass for DataframeSpaceView { .cloned() .collect(); - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); let latest_at_query = query.latest_at_query(); let sorted_instance_paths: Vec<_>; diff --git a/crates/re_space_view_spatial/src/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/contexts/depth_offsets.rs index 736192b302dd..1ed969e30649 100644 --- a/crates/re_space_view_spatial/src/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/contexts/depth_offsets.rs @@ -44,7 +44,7 @@ impl ViewContextSystem for EntityDepthOffsets { DefaultPoints, } - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); // Use a BTreeSet for entity hashes to get a stable order. let mut entities_per_draw_order = BTreeMap::>::new(); diff --git a/crates/re_space_view_spatial/src/contexts/transform_context.rs b/crates/re_space_view_spatial/src/contexts/transform_context.rs index c1356eb592c3..ec76952736b8 100644 --- a/crates/re_space_view_spatial/src/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/contexts/transform_context.rs @@ -91,7 +91,7 @@ impl ViewContextSystem for TransformContext { ) { re_tracing::profile_function!(); - let entity_tree = ctx.entity_db.tree(); + let entity_tree = ctx.recording().tree(); // TODO(jleibs): The need to do this hints at a problem with how we think about // the interaction between properties and "context-systems". @@ -123,7 +123,7 @@ impl ViewContextSystem for TransformContext { // Child transforms of this space self.gather_descendants_transforms( current_tree, - ctx.entity_db, + ctx.recording(), &time_query, &entity_prop_map, glam::Affine3A::IDENTITY, @@ -148,7 +148,7 @@ impl ViewContextSystem for TransformContext { // Generally, the transform _at_ a node isn't relevant to it's children, but only to get to its parent in turn! match transform_at( current_tree, - ctx.entity_db, + ctx.recording(), &time_query, // TODO(#1025): See comment in transform_at. This is a workaround for precision issues // and the fact that there is no meaningful image plane distance for 3D->2D views. @@ -169,7 +169,7 @@ impl ViewContextSystem for TransformContext { // (skip over everything at and under `current_tree` automatically) self.gather_descendants_transforms( parent_tree, - ctx.entity_db, + ctx.recording(), &time_query, &entity_prop_map, reference_from_ancestor, diff --git a/crates/re_space_view_spatial/src/heuristics.rs b/crates/re_space_view_spatial/src/heuristics.rs index 5becb064a3df..702a5ed3747b 100644 --- a/crates/re_space_view_spatial/src/heuristics.rs +++ b/crates/re_space_view_spatial/src/heuristics.rs @@ -111,7 +111,7 @@ fn update_depth_cloud_property_heuristics( .get(&ImageVisualizer::identifier()) .unwrap_or(&BTreeSet::new()) { - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); let Some(tensor) = store.query_latest_component::(ent_path, &ctx.current_query()) else { @@ -171,7 +171,7 @@ fn update_transform3d_lines_heuristics( return Some(ent_path); } else { // Any direct child has a pinhole camera? - if let Some(child_tree) = ctx.entity_db.tree().subtree(ent_path) { + if let Some(child_tree) = ctx.recording().tree().subtree(ent_path) { for child in child_tree.children.values() { if query_pinhole(store, &ctx.current_query(), &child.path).is_some() { return Some(&child.path); @@ -188,8 +188,7 @@ fn update_transform3d_lines_heuristics( // By default show the transform if it is a camera extrinsic, // or if this entity only contains Transform3D components. let only_has_transform_components = ctx - .entity_db - .store() + .recording_store() .all_components(&ctx.current_query().timeline, ent_path) .map_or(false, |c| { c.iter() @@ -197,13 +196,13 @@ fn update_transform3d_lines_heuristics( }); properties.transform_3d_visible = EditableAutoValue::Auto( only_has_transform_components - || is_pinhole_extrinsics_of(ctx.entity_db.store(), ent_path, ctx).is_some(), + || is_pinhole_extrinsics_of(ctx.recording_store(), ent_path, ctx).is_some(), ); } if properties.transform_3d_size.is_auto() { if let Some(pinhole_path) = - is_pinhole_extrinsics_of(ctx.entity_db.store(), ent_path, ctx) + is_pinhole_extrinsics_of(ctx.recording_store(), ent_path, ctx) { // If there's a pinhole, we orient ourselves on its image plane distance let pinhole_path_props = entity_properties.get(pinhole_path); diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index 3141b66c504c..22268a10cb35 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -177,16 +177,15 @@ impl SpaceViewClass for SpatialSpaceView2D { SpatialSpaceViewKind::TwoD, ); - let image_dimensions = - MaxImageDimensions::access(ctx.entity_db.store_id(), |image_dimensions| { - image_dimensions.clone() - }) - .unwrap_or_default(); + let image_dimensions = MaxImageDimensions::access(ctx.recording_id(), |image_dimensions| { + image_dimensions.clone() + }) + .unwrap_or_default(); // Spawn a space view at each subspace that has any potential 2D content. // Note that visualizability filtering is all about being in the right subspace, // so we don't need to call the visualizers' filter functions here. - SpatialTopology::access(ctx.entity_db.store_id(), |topo| SpaceViewSpawnHeuristics { + SpatialTopology::access(ctx.recording_id(), |topo| SpaceViewSpawnHeuristics { recommended_space_views: topo .iter_subspaces() .flat_map(|subspace| { @@ -347,7 +346,7 @@ fn recommended_space_views_with_image_splits( ) { re_tracing::profile_function!(); - let tree = ctx.entity_db.tree(); + let tree = ctx.recording().tree(); let Some(subtree) = tree.subtree(recommended_root) else { if cfg!(debug_assertions) { diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 252af4ffac51..8f167802a34b 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -201,7 +201,7 @@ impl SpaceViewClass for SpatialSpaceView3D { // It's tempting to add a visualizer for view coordinates so that it's already picked up via `entities_with_indicator_for_visualizer_kind`. // Is there a nicer way for this or do we want a visualizer for view coordinates anyways? // There's also a strong argument to be made that ViewCoordinates implies a 3D space, thus changing the SpacialTopology accordingly! - ctx.entity_db + ctx.recording() .tree() .visit_children_recursively(&mut |path, info| { if info.components.contains_key(&ViewCoordinates::name()) { @@ -212,7 +212,7 @@ impl SpaceViewClass for SpatialSpaceView3D { // Spawn a space view at each subspace that has any potential 3D content. // Note that visualizability filtering is all about being in the right subspace, // so we don't need to call the visualizers' filter functions here. - SpatialTopology::access(ctx.entity_db.store_id(), |topo| SpaceViewSpawnHeuristics { + SpatialTopology::access(ctx.recording_id(), |topo| SpaceViewSpawnHeuristics { recommended_space_views: topo .iter_subspaces() .filter_map(|subspace| { @@ -306,8 +306,7 @@ impl SpaceViewClass for SpatialSpaceView3D { let state = state.downcast_mut::()?; let scene_view_coordinates = ctx - .entity_db - .store() + .recording_store() .query_latest_component::(space_origin, &ctx.current_query()) .map(|c| c.value); diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 04f45d1b4e5b..21395c1fc1ee 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -473,7 +473,7 @@ pub fn picking( // TODO(#1818): Depth at pointer only works for depth images so far. let mut depth_at_pointer = None; for hit in &picking_result.hits { - let Some(mut instance_path) = hit.instance_path_hash.resolve(ctx.entity_db) else { + let Some(mut instance_path) = hit.instance_path_hash.resolve(ctx.recording()) else { continue; }; @@ -489,7 +489,7 @@ pub fn picking( continue; } - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); // Special hover ui for images. let is_depth_cloud = images @@ -674,7 +674,7 @@ fn image_hover_ui( ui, UiVerbosity::Small, &ctx.current_query(), - ctx.entity_db.store(), + ctx.recording_store(), ); } else { // Show it all, like we do for any other thing we hover @@ -683,7 +683,7 @@ fn image_hover_ui( ui, UiVerbosity::Small, &ctx.current_query(), - ctx.entity_db.store(), + ctx.recording_store(), ); } diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index 03f1468f1155..c150d160ef3b 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -240,7 +240,7 @@ pub fn view_2d( // Save off the available_size since this is used for some of the layout updates later let available_size = ui.available_size(); - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); let scene_rect_accum = state.bounding_boxes.accumulated; let scene_rect_accum = egui::Rect::from_min_max( diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 353310f78f8a..eb30830cf00d 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -445,8 +445,7 @@ pub fn view_3d( let highlights = &query.highlights; let space_cameras = &parts.get::()?.space_cameras; let scene_view_coordinates = ctx - .entity_db - .store() + .recording_store() // Allow logging view-coordinates to `/` and have it apply to `/world` etc. // See https://github.com/rerun-io/rerun/issues/3538 .query_latest_component_at_closest_ancestor(query.space_origin, &ctx.current_query()) diff --git a/crates/re_space_view_spatial/src/visualizers/cameras.rs b/crates/re_space_view_spatial/src/visualizers/cameras.rs index f9e79bc524b9..cf09142e9c5b 100644 --- a/crates/re_space_view_spatial/src/visualizers/cameras.rs +++ b/crates/re_space_view_spatial/src/visualizers/cameras.rs @@ -206,7 +206,7 @@ impl VisualizerSystem for CamerasVisualizer { view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { let transforms = view_ctx.get::()?; - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); // Counting all cameras ahead of time is a bit wasteful, but we also don't expect a huge amount, // so let re_renderer's allocator internally decide what buffer sizes to pick & grow them as we go. diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 8b37590166dc..54117f54ea94 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -51,7 +51,7 @@ where } else { transforms.reference_from_entity_ignoring_pinhole( &data_result.entity_path, - ctx.entity_db, + ctx.recording(), &query.latest_at_query(), ) }; @@ -75,7 +75,7 @@ where let extra_history = query_visual_history(ctx, data_result); match query_archetype_with_history::( - ctx.entity_db.store(), + ctx.recording_store(), &query.timeline, &query.latest_at, &extra_history, @@ -161,7 +161,7 @@ macro_rules! impl_process_archetype { } else { transforms.reference_from_entity_ignoring_pinhole( &data_result.entity_path, - ctx.entity_db, + ctx.recording(), &query.latest_at_query(), ) }; @@ -184,8 +184,8 @@ macro_rules! impl_process_archetype { let extra_history = query_visual_history(ctx, data_result); - match ctx.entity_db.query_caches().[]::( - ctx.entity_db.store(), + match ctx.recording().query_caches().[]::( + ctx.recording_store(), &query.timeline, &query.latest_at, &extra_history, @@ -265,7 +265,7 @@ pub fn count_instances_in_archetype_views< let extra_history = query_visual_history(ctx, data_result); match query_archetype_with_history::( - ctx.entity_db.store(), + ctx.recording_store(), &query.timeline, &query.latest_at, &extra_history, diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index 31f9c158af6d..5dda2cea54d2 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -222,7 +222,7 @@ impl ImageVisualizer { // If this isn't an image, return // TODO(jleibs): The ArchetypeView should probably do this for us. - if !ctx.entity_db.store().entity_has_component( + if !ctx.recording_store().entity_has_component( &ctx.current_query().timeline, ent_path, &Image::indicator().name(), @@ -319,7 +319,7 @@ impl ImageVisualizer { // If this isn't an image, return // TODO(jleibs): The ArchetypeView should probably to this for us. - if !ctx.entity_db.store().entity_has_component( + if !ctx.recording_store().entity_has_component( &ctx.current_query().timeline, ent_path, &DepthImage::indicator().name(), @@ -464,7 +464,7 @@ impl ImageVisualizer { // If this isn't an image, return // TODO(jleibs): The ArchetypeView should probably to this for us. - if !ctx.entity_db.store().entity_has_component( + if !ctx.recording_store().entity_has_component( &ctx.current_query().timeline, ent_path, &SegmentationImage::indicator().name(), @@ -559,7 +559,7 @@ impl ImageVisualizer { re_tracing::profile_function!(); let Some(intrinsics) = query_pinhole( - ctx.entity_db.store(), + ctx.recording_store(), &ctx.current_query(), parent_pinhole_path, ) else { @@ -569,7 +569,7 @@ impl ImageVisualizer { // Place the cloud at the pinhole's location. Note that this means we ignore any 2D transforms that might be there. let world_from_view = transforms.reference_from_entity_ignoring_pinhole( parent_pinhole_path, - ctx.entity_db, + ctx.recording(), &ctx.current_query(), ); let Some(world_from_view) = world_from_view else { diff --git a/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs b/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs index bcb11e63061c..78d6de34efea 100644 --- a/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs +++ b/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs @@ -51,8 +51,8 @@ impl VisualizerSystem for Transform3DArrowsVisualizer { ) -> Result, SpaceViewSystemExecutionError> { let transforms = view_ctx.get::()?; - let query_caches = ctx.entity_db.query_caches(); - let store = ctx.entity_db.store(); + let query_caches = ctx.recording().query_caches(); + let store = ctx.recording_store(); let latest_at_query = re_data_store::LatestAtQuery::new(query.timeline, query.latest_at); @@ -83,7 +83,7 @@ impl VisualizerSystem for Transform3DArrowsVisualizer { // Use transform without potential pinhole, since we don't want to visualize image-space coordinates. let Some(world_from_obj) = transforms.reference_from_entity_ignoring_pinhole( &data_result.entity_path, - ctx.entity_db, + ctx.recording(), &latest_at_query, ) else { continue; diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index 55559fc1797b..11807f00afd2 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -47,7 +47,7 @@ impl VisualizerSystem for TensorSystem { ) -> Result, SpaceViewSystemExecutionError> { re_tracing::profile_function!(); - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let timeline_query = LatestAtQuery::new(query.timeline, query.latest_at); diff --git a/crates/re_space_view_text_document/src/visualizer_system.rs b/crates/re_space_view_text_document/src/visualizer_system.rs index b0f55e9cf04f..ea8b404f0a74 100644 --- a/crates/re_space_view_text_document/src/visualizer_system.rs +++ b/crates/re_space_view_text_document/src/visualizer_system.rs @@ -40,7 +40,7 @@ impl VisualizerSystem for TextDocumentSystem { query: &ViewQuery<'_>, _view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); let timeline_query = LatestAtQuery::new(query.timeline, query.latest_at); diff --git a/crates/re_space_view_text_log/src/space_view_class.rs b/crates/re_space_view_text_log/src/space_view_class.rs index c4da833d154e..15d5e273731f 100644 --- a/crates/re_space_view_text_log/src/space_view_class.rs +++ b/crates/re_space_view_text_log/src/space_view_class.rs @@ -255,7 +255,7 @@ impl ViewTextFilters { row_log_levels, } = self; - for timeline in ctx.entity_db.timelines() { + for timeline in ctx.recording().timelines() { col_timelines.entry(*timeline).or_insert(true); } @@ -268,7 +268,7 @@ impl ViewTextFilters { // --- fn get_time_point(ctx: &ViewerContext<'_>, entry: &Entry) -> Option { - if let Some((time_point, _)) = ctx.entity_db.store().get_msg_metadata(&entry.row_id) { + if let Some((time_point, _)) = ctx.recording_store().get_msg_metadata(&entry.row_id) { Some(time_point.clone()) } else { re_log::warn_once!("Missing metadata for {:?}", entry.entity_path); @@ -359,7 +359,7 @@ fn table_ui( body_clip_rect = Some(body.max_rect()); let query = ctx.current_query(); - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); let row_heights = entries.iter().map(|te| calc_row_height(te)); body.heterogeneous_rows(row_heights, |mut row| { diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index 192d051668f6..a29a828ef7da 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -50,8 +50,8 @@ impl VisualizerSystem for TextLogSystem { query: &ViewQuery<'_>, _view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let query_caches = ctx.entity_db.query_caches(); - let store = ctx.entity_db.store(); + let query_caches = ctx.recording().query_caches(); + let store = ctx.recording_store(); for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { re_tracing::profile_scope!("primary", &data_result.entity_path.to_string()); diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 4668bb409c53..afa1d667878e 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -155,8 +155,8 @@ fn load_series( ) -> Result<(), QueryError> { re_tracing::profile_function!(); - let store = ctx.entity_db.store(); - let query_caches = ctx.entity_db.query_caches(); + let store = ctx.recording_store(); + let query_caches = ctx.recording().query_caches(); let annotation_info = annotations .resolved_class_description(None) @@ -282,8 +282,7 @@ fn load_series( let series_name = if let Some(override_name) = override_series_name { Some(override_name) } else { - ctx.entity_db - .store() + ctx.recording_store() .query_latest_component::(&data_result.entity_path, &ctx.current_query()) .map(|name| name.value.0) }; diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 58a7d5423639..5ff4969259b8 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -100,8 +100,8 @@ impl SeriesPointSystem { ) -> Result<(), QueryError> { re_tracing::profile_function!(); - let query_caches = ctx.entity_db.query_caches(); - let store = ctx.entity_db.store(); + let query_caches = ctx.recording().query_caches(); + let store = ctx.recording_store(); let (plot_bounds, time_per_pixel) = determine_plot_bounds_and_time_per_pixel(ctx, query); @@ -253,8 +253,7 @@ impl SeriesPointSystem { let series_name = if let Some(override_name) = override_series_name { Some(override_name) } else { - ctx.entity_db - .store() + ctx.recording_store() .query_latest_component::(&data_result.entity_path, &ctx.current_query()) .map(|name| name.value.0) }; diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 8df51c8066ac..6e666a353355 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -213,7 +213,7 @@ It can greatly improve performance (and readability) in such situations as it pr // Spawn time series data at the root if there's time series data either // directly at the root or one of its children. // TODO(#4926): This seems to be unnecessarily complicated. - let subtree_of_root_entity = &ctx.entity_db.tree().children; + let subtree_of_root_entity = &ctx.recording().tree().children; if indicated_entities.contains(&EntityPath::root()) || subtree_of_root_entity .iter() diff --git a/crates/re_time_panel/src/lib.rs b/crates/re_time_panel/src/lib.rs index ae213a976824..001d8938b3e0 100644 --- a/crates/re_time_panel/src/lib.rs +++ b/crates/re_time_panel/src/lib.rs @@ -554,7 +554,7 @@ impl TimePanel { let tree_has_data_in_current_timeline = time_ctrl.tree_has_data_in_current_timeline(tree); let store = match self.source { - TimePanelSource::Recording => ctx.entity_db.store(), + TimePanelSource::Recording => ctx.recording_store(), TimePanelSource::Blueprint => ctx.store_context.blueprint.store(), }; @@ -808,7 +808,7 @@ impl TimePanel { highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); let store = match self.source { - TimePanelSource::Recording => ctx.entity_db.store(), + TimePanelSource::Recording => ctx.recording_store(), TimePanelSource::Blueprint => ctx.store_context.blueprint.store(), }; diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index df008fb327a5..ecb29be28f23 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -486,9 +486,7 @@ impl App { })); } UICommand::CloseCurrentRecording => { - let cur_rec = store_context - .and_then(|ctx| ctx.recording) - .map(|rec| rec.store_id()); + let cur_rec = store_context.map(|ctx| ctx.recording.store_id()); if let Some(cur_rec) = cur_rec { self.command_sender .send_system(SystemCommand::CloseRecordingId(cur_rec.clone())); @@ -571,8 +569,7 @@ impl App { UICommand::SelectionPrevious => { let state = &mut self.state; if let Some(rec_cfg) = store_context - .and_then(|ctx| ctx.recording) - .map(|rec| rec.store_id()) + .map(|ctx| ctx.recording.store_id()) .and_then(|rec_id| state.recording_config_mut(rec_id)) { rec_cfg.selection_state.select_previous(); @@ -581,8 +578,7 @@ impl App { UICommand::SelectionNext => { let state = &mut self.state; if let Some(rec_cfg) = store_context - .and_then(|store_context| store_context.recording) - .map(|rec| rec.store_id()) + .map(|ctx| ctx.recording.store_id()) .and_then(|rec_id| state.recording_config_mut(rec_id)) { rec_cfg.selection_state.select_next(); @@ -615,19 +611,17 @@ impl App { #[cfg(not(target_arch = "wasm32"))] UICommand::PrintDataStore => { if let Some(ctx) = store_context { - if let Some(recording) = ctx.recording { - let table = recording.store().to_data_table(); - match table { - Ok(table) => { - let text = format!("{table}"); - self.re_ui - .egui_ctx - .output_mut(|o| o.copied_text = text.clone()); - println!("{text}"); - } - Err(err) => { - println!("{err}"); - } + let table = ctx.recording.store().to_data_table(); + match table { + Ok(table) => { + let text = format!("{table}"); + self.re_ui + .egui_ctx + .output_mut(|o| o.copied_text = text.clone()); + println!("{text}"); + } + Err(err) => { + println!("{err}"); } } } @@ -653,21 +647,17 @@ impl App { #[cfg(not(target_arch = "wasm32"))] UICommand::ClearPrimaryCache => { if let Some(ctx) = store_context { - if let Some(recording) = ctx.recording { - recording.query_caches().clear(); - } + ctx.recording.query_caches().clear(); } } #[cfg(not(target_arch = "wasm32"))] UICommand::PrintPrimaryCache => { if let Some(ctx) = store_context { - if let Some(recording) = ctx.recording { - let text = format!("{:?}", recording.query_caches()); - self.re_ui - .egui_ctx - .output_mut(|o| o.copied_text = text.clone()); - println!("{text}"); - } + let text = format!("{:?}", ctx.recording.query_caches()); + self.re_ui + .egui_ctx + .output_mut(|o| o.copied_text = text.clone()); + println!("{text}"); } } @@ -697,7 +687,7 @@ impl App { store_context: Option<&StoreContext<'_>>, command: TimeControlCommand, ) { - let Some(entity_db) = store_context.as_ref().and_then(|ctx| ctx.recording) else { + let Some(entity_db) = store_context.as_ref().map(|ctx| ctx.recording) else { return; }; let rec_id = entity_db.store_id(); @@ -743,7 +733,7 @@ impl App { href = format!("{href}/{path}"); } let direct_link = match store_context - .and_then(|ctx| ctx.recording) + .map(|ctx| ctx.recording) .and_then(|rec| rec.data_source.as_ref()) { Some(SmartChannelSource::RrdHttpStream { url }) => format!("{href}/?url={url}"), @@ -849,24 +839,7 @@ impl App { self.egui_debug_panel_ui(ui); if let Some(store_view) = store_context { - static EMPTY_ENTITY_DB: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - EntityDb::new(re_log_types::StoreId::from_string( - StoreKind::Recording, - "".to_owned(), - )) - }); - - // We want the regular UI as soon as a blueprint is available (or, rather, an - // app ID is set). If no recording is available, we use a default, empty one. - // Note that EMPTY_STORE_DB is *not* part of the list of available recordings - // (StoreContext::alternate_recordings), which means that it's not displayed in - // the recordings UI. - let entity_db = if let Some(entity_db) = store_view.recording { - entity_db - } else { - &EMPTY_ENTITY_DB - }; + let entity_db = store_view.recording; // TODO(andreas): store the re_renderer somewhere else. let egui_renderer = { @@ -1579,7 +1552,7 @@ fn save_recording( store_context: Option<&StoreContext<'_>>, loop_selection: Option<(re_entity_db::Timeline, re_log_types::TimeRangeF)>, ) -> anyhow::Result<()> { - let Some(entity_db) = store_context.as_ref().and_then(|view| view.recording) else { + let Some(entity_db) = store_context.as_ref().map(|view| view.recording) else { // NOTE: Can only happen if saving through the command palette. anyhow::bail!("No recording data to save"); }; diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 69ebb0087b3c..de733f6d2f59 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -87,21 +87,14 @@ impl AppState { &self, store_context: Option<&StoreContext<'_>>, ) -> Option<(re_entity_db::Timeline, TimeRangeF)> { - store_context - .as_ref() - .and_then(|ctx| ctx.recording) - .map(|rec| rec.store_id()) - .and_then(|rec_id| { - self.recording_configs - .get(rec_id) - // is there an active loop selection? - .and_then(|rec_cfg| { - let time_ctrl = rec_cfg.time_ctrl.read(); - time_ctrl - .loop_selection() - .map(|q| (*time_ctrl.timeline(), q)) - }) - }) + let rec_id = store_context.as_ref()?.recording.store_id(); + let rec_cfg = self.recording_configs.get(rec_id)?; + + // is there an active loop selection? + let time_ctrl = rec_cfg.time_ctrl.read(); + time_ctrl + .loop_selection() + .map(|q| (*time_ctrl.timeline(), q)) } #[allow(clippy::too_many_arguments)] @@ -110,7 +103,7 @@ impl AppState { app_blueprint: &AppBlueprint<'_>, ui: &mut egui::Ui, render_ctx: &re_renderer::RenderContext, - entity_db: &EntityDb, + recording: &EntityDb, store_context: &StoreContext<'_>, re_ui: &re_ui::ReUi, component_ui_registry: &ComponentUiRegistry, @@ -166,21 +159,21 @@ impl AppState { return; } - recording_config_entry(recording_configs, entity_db.store_id().clone(), entity_db) + recording_config_entry(recording_configs, recording.store_id().clone(), recording) .selection_state .on_frame_start(|item| viewport.is_item_valid(item)); let rec_cfg = - recording_config_entry(recording_configs, entity_db.store_id().clone(), entity_db); + recording_config_entry(recording_configs, recording.store_id().clone(), recording); if ui.input(|i| i.key_pressed(egui::Key::Escape)) { rec_cfg.selection_state.clear_selection(); } let applicable_entities_per_visualizer = space_view_class_registry - .applicable_entities_for_visualizer_systems(entity_db.store_id()); + .applicable_entities_for_visualizer_systems(recording.store_id()); let indicated_entities_per_visualizer = - space_view_class_registry.indicated_entities_per_visualizer(entity_db.store_id()); + space_view_class_registry.indicated_entities_per_visualizer(recording.store_id()); // Execute the queries for every `SpaceView` let mut query_results = { @@ -195,7 +188,7 @@ impl AppState { // In a store subscriber set this is fine, but on a per-frame basis it's wasteful. let visualizable_entities = determine_visualizable_entities( &applicable_entities_per_visualizer, - entity_db, + recording, &space_view_class_registry .new_visualizer_collection(*space_view.class_identifier()), space_view.class(space_view_class_registry), @@ -217,7 +210,6 @@ impl AppState { cache, space_view_class_registry, component_ui_registry, - entity_db, store_context, applicable_entities_per_visualizer: &applicable_entities_per_visualizer, indicated_entities_per_visualizer: &indicated_entities_per_visualizer, @@ -246,7 +238,7 @@ impl AppState { // In a store subscriber set this is fine, but on a per-frame basis it's wasteful. let visualizable_entities = determine_visualizable_entities( &applicable_entities_per_visualizer, - entity_db, + recording, &space_view_class_registry .new_visualizer_collection(*space_view.class_identifier()), space_view.class(space_view_class_registry), @@ -273,7 +265,6 @@ impl AppState { cache, space_view_class_registry, component_ui_registry, - entity_db, store_context, applicable_entities_per_visualizer: &applicable_entities_per_visualizer, indicated_entities_per_visualizer: &indicated_entities_per_visualizer, @@ -300,7 +291,7 @@ impl AppState { time_panel.show_panel( &ctx, &viewport_blueprint, - ctx.entity_db, + ctx.recording(), ctx.rec_cfg, ui, app_blueprint.time_panel_expanded, @@ -383,14 +374,14 @@ impl AppState { let dt = ui.ctx().input(|i| i.stable_dt); // Are we still connected to the data source for the current store? - let more_data_is_coming = if let Some(store_source) = &entity_db.data_source { + let more_data_is_coming = if let Some(store_source) = &recording.data_source { rx.sources().iter().any(|s| s.as_ref() == store_source) } else { false }; let recording_needs_repaint = ctx.rec_cfg.time_ctrl.write().update( - entity_db.times_per_timeline(), + recording.times_per_timeline(), dt, more_data_is_coming, ); diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 3ac1076ba30f..796125b26241 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -29,7 +29,6 @@ pub(crate) use { }; pub use app::{App, StartupOptions}; -pub use store_hub::StoreBundle; pub mod external { pub use re_data_ui; diff --git a/crates/re_viewer/src/loading.rs b/crates/re_viewer/src/loading.rs index fa04fc1a93a9..33d820323630 100644 --- a/crates/re_viewer/src/loading.rs +++ b/crates/re_viewer/src/loading.rs @@ -1,4 +1,4 @@ -use crate::{store_hub::StoreLoadError, StoreBundle}; +use re_entity_db::{StoreBundle, StoreLoadError}; #[derive(thiserror::Error, Debug)] enum BlueprintLoadError { @@ -16,7 +16,7 @@ enum BlueprintLoadError { pub fn load_blueprint_file( path: &std::path::Path, with_notifications: bool, -) -> Option { +) -> Option { fn load_file_path_impl(path: &std::path::Path) -> Result { re_tracing::profile_function!(); diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer/src/store_hub.rs index 93c558fbf02c..333627eded1e 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer/src/store_hub.rs @@ -1,10 +1,8 @@ use ahash::{HashMap, HashMapExt}; -use itertools::Itertools; use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; -use re_entity_db::EntityDb; -use re_log_encoding::decoder::VersionPolicy; +use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId, StoreKind}; use re_query_cache::CachesStats; use re_viewer_context::{AppOptions, StoreContext}; @@ -89,6 +87,14 @@ impl StoreHub { /// All of the returned references to blueprints and recordings will have a /// matching [`ApplicationId`]. pub fn read_context(&mut self) -> Option> { + static EMPTY_ENTITY_DB: once_cell::sync::Lazy = + once_cell::sync::Lazy::new(|| { + EntityDb::new(re_log_types::StoreId::from_string( + StoreKind::Recording, + "".to_owned(), + )) + }); + // If we have an app-id, then use it to look up the blueprint. let app_id = self.selected_application_id.clone()?; @@ -99,18 +105,18 @@ impl StoreHub { // Get or create the blueprint: self.store_bundle.blueprint_entry(blueprint_id); - let blueprint = self.store_bundle.blueprint(blueprint_id)?; + let blueprint = self.store_bundle.get(blueprint_id)?; let recording = self .selected_rec_id .as_ref() - .and_then(|id| self.store_bundle.recording(id)); + .and_then(|id| self.store_bundle.get(id)); Some(StoreContext { app_id, blueprint, - recording, - all_recordings: self.store_bundle.recordings().collect_vec(), + recording: recording.unwrap_or(&EMPTY_ENTITY_DB), + bundle: &self.store_bundle, }) } @@ -127,7 +133,7 @@ impl StoreHub { // If this recording corresponds to an app that we know about, then update the app-id. if let Some(app_id) = self .store_bundle - .recording(&recording_id) + .get(&recording_id) .as_ref() .and_then(|recording| recording.app_id()) { @@ -206,12 +212,12 @@ impl StoreHub { /// Note that the recording is not automatically made active. Use [`StoreHub::set_recording_id`] /// if needed. pub fn insert_entity_db(&mut self, entity_db: EntityDb) { - self.store_bundle.insert_entity_db(entity_db); + self.store_bundle.insert(entity_db); } /// Mutable access to a [`EntityDb`] by id pub fn entity_db_mut(&mut self, store_id: &StoreId) -> &mut EntityDb { - self.store_bundle.entity_db_entry(store_id) + self.store_bundle.entry(store_id) } /// Remove any empty [`EntityDb`]s from the hub @@ -230,9 +236,9 @@ impl StoreHub { return; }; - let entity_dbs = &mut self.store_bundle.entity_dbs; + let store_bundle = &mut self.store_bundle; - let Some(entity_db) = entity_dbs.get_mut(&store_id) else { + let Some(entity_db) = store_bundle.get_mut(&store_id) else { if cfg!(debug_assertions) { unreachable!(); } @@ -259,7 +265,8 @@ impl StoreHub { // // If the user needs the memory for something else, they will get it back as soon as they // log new things anyhow. - if store_size_before == store_size_after && entity_dbs.len() > 1 { + let num_recordings = store_bundle.recordings().count(); + if store_size_before == store_size_after && num_recordings > 1 { self.remove_recording_id(&store_id); } @@ -276,12 +283,12 @@ impl StoreHub { pub fn current_recording(&self) -> Option<&EntityDb> { self.selected_rec_id .as_ref() - .and_then(|id| self.store_bundle.recording(id)) + .and_then(|id| self.store_bundle.get(id)) } /// Check whether the [`StoreHub`] contains the referenced store (recording or blueprint). pub fn contains_store(&self, id: &StoreId) -> bool { - self.store_bundle.contains_store(id) + self.store_bundle.contains(id) } pub fn entity_dbs_from_channel_source<'a>( @@ -289,15 +296,14 @@ impl StoreHub { source: &'a re_smart_channel::SmartChannelSource, ) -> impl Iterator + 'a { self.store_bundle - .entity_dbs - .values() + .entity_dbs() .filter(move |db| db.data_source.as_ref() == Some(source)) } /// Remove any recordings with a network source pointing at this `uri`. #[cfg(target_arch = "wasm32")] pub fn remove_recording_by_uri(&mut self, uri: &str) { - self.store_bundle.entity_dbs.retain(|_, db| { + self.store_bundle.retain(|db| { let Some(data_source) = &db.data_source else { // no data source, keep return true; @@ -320,7 +326,7 @@ impl StoreHub { re_tracing::profile_function!(); if app_options.blueprint_gc { for blueprint_id in self.blueprint_by_app_id.values() { - if let Some(blueprint) = self.store_bundle.blueprint_mut(blueprint_id) { + if let Some(blueprint) = self.store_bundle.get_mut(blueprint_id) { // TODO(jleibs): Decide a better tuning for this. Would like to save a // reasonable amount of history, or incremental snapshots. blueprint.gc_everything_but_the_latest_row(); @@ -342,7 +348,7 @@ impl StoreHub { // there may be other Blueprints in the Hub. for (app_id, blueprint_id) in &self.blueprint_by_app_id { - if let Some(blueprint) = self.store_bundle.blueprint_mut(blueprint_id) { + if let Some(blueprint) = self.store_bundle.get_mut(blueprint_id) { if self.blueprint_last_save.get(blueprint_id) != Some(&blueprint.generation()) { if app_options.blueprint_gc { blueprint.gc_everything_but_the_latest_row(); @@ -407,7 +413,7 @@ impl StoreHub { .insert(app_id.clone(), store.store_id().clone()); self.blueprint_last_save .insert(store.store_id().clone(), store.generation()); - self.store_bundle.insert_blueprint(store); + self.store_bundle.insert(store); } else { anyhow::bail!( "Found unexpected store while loading blueprint: {:?}", @@ -432,7 +438,7 @@ impl StoreHub { .selected_application_id .as_ref() .and_then(|app_id| self.blueprint_by_app_id.get(app_id)) - .and_then(|blueprint_id| self.store_bundle.blueprint(blueprint_id)); + .and_then(|blueprint_id| self.store_bundle.get(blueprint_id)); let blueprint_stats = blueprint .map(|entity_db| DataStoreStats::from_store(entity_db.store())) @@ -445,7 +451,7 @@ impl StoreHub { let recording = self .selected_rec_id .as_ref() - .and_then(|rec_id| self.store_bundle.recording(rec_id)); + .and_then(|rec_id| self.store_bundle.get(rec_id)); let recording_stats = recording .map(|entity_db| DataStoreStats::from_store(entity_db.store())) @@ -468,209 +474,3 @@ impl StoreHub { } } } - -#[derive(thiserror::Error, Debug)] -pub enum StoreLoadError { - #[error(transparent)] - Decode(#[from] re_log_encoding::decoder::DecodeError), - - #[error(transparent)] - DataStore(#[from] re_entity_db::Error), -} - -/// Stores many [`EntityDb`]s of recordings and blueprints. -#[derive(Default)] -pub struct StoreBundle { - // TODO(emilk): two separate maps per [`StoreKind`]. - entity_dbs: ahash::HashMap, -} - -impl StoreBundle { - /// Decode an rrd stream. - /// It can theoretically contain multiple recordings, and blueprints. - pub fn from_rrd( - version_policy: VersionPolicy, - read: impl std::io::Read, - ) -> Result { - re_tracing::profile_function!(); - - let decoder = re_log_encoding::decoder::Decoder::new(version_policy, read)?; - - let mut slf = Self::default(); - - for msg in decoder { - let msg = msg?; - slf.entity_db_entry(msg.store_id()).add(&msg)?; - } - Ok(slf) - } - - /// Returns either a recording or blueprint [`EntityDb`]. - /// One is created if it doesn't already exist. - pub fn entity_db_entry(&mut self, id: &StoreId) -> &mut EntityDb { - self.entity_dbs.entry(id.clone()).or_insert_with(|| { - re_log::debug!("Creating new store: {id}"); - EntityDb::new(id.clone()) - }) - } - - /// All loaded [`EntityDb`], both recordings and blueprints, in arbitrary order. - pub fn entity_dbs(&self) -> impl Iterator { - self.entity_dbs.values() - } - - /// All loaded [`EntityDb`], both recordings and blueprints, in arbitrary order. - pub fn entity_dbs_mut(&mut self) -> impl Iterator { - self.entity_dbs.values_mut() - } - - pub fn append(&mut self, mut other: Self) { - for (id, entity_db) in other.entity_dbs.drain() { - self.entity_dbs.insert(id, entity_db); - } - } - - pub fn remove(&mut self, id: &StoreId) { - self.entity_dbs.remove(id); - } - - /// Returns the closest "neighbor" recording to the given id. - /// - /// The closest neighbor is the next recording when sorted by (app ID, time), if any, or the - /// previous one otherwise. This is used to update the selected recording when the current one - /// is deleted. - pub fn find_closest_recording(&self, id: &StoreId) -> Option<&StoreId> { - let mut recs = self.recordings().collect_vec(); - recs.sort_by_key(|entity_db| entity_db.sort_key()); - - let cur_pos = recs.iter().position(|rec| rec.store_id() == id); - - if let Some(cur_pos) = cur_pos { - if recs.len() > cur_pos + 1 { - Some(recs[cur_pos + 1].store_id()) - } else if cur_pos > 0 { - Some(recs[cur_pos - 1].store_id()) - } else { - None - } - } else { - None - } - } - - /// Returns the [`StoreId`] of the oldest modified recording, according to [`EntityDb::last_modified_at`]. - pub fn find_oldest_modified_recording(&self) -> Option<&StoreId> { - let mut entity_dbs = self - .entity_dbs - .values() - .filter(|db| db.store_kind() == StoreKind::Recording) - .collect_vec(); - - entity_dbs.sort_by_key(|db| db.last_modified_at()); - - entity_dbs.first().map(|db| db.store_id()) - } - - // -- - - pub fn contains_store(&self, id: &StoreId) -> bool { - self.entity_dbs.contains_key(id) - } - - pub fn recording(&self, id: &StoreId) -> Option<&EntityDb> { - debug_assert_eq!(id.kind, StoreKind::Recording); - self.entity_dbs.get(id) - } - - pub fn recording_mut(&mut self, id: &StoreId) -> Option<&mut EntityDb> { - debug_assert_eq!(id.kind, StoreKind::Recording); - self.entity_dbs.get_mut(id) - } - - /// Creates one if it doesn't exist. - pub fn recording_entry(&mut self, id: &StoreId) -> &mut EntityDb { - debug_assert_eq!(id.kind, StoreKind::Recording); - self.entity_dbs - .entry(id.clone()) - .or_insert_with(|| EntityDb::new(id.clone())) - } - - pub fn insert_entity_db(&mut self, entity_db: EntityDb) { - self.entity_dbs - .insert(entity_db.store_id().clone(), entity_db); - } - - pub fn insert_blueprint(&mut self, entity_db: EntityDb) { - debug_assert_eq!(entity_db.store_kind(), StoreKind::Blueprint); - self.entity_dbs - .insert(entity_db.store_id().clone(), entity_db); - } - - pub fn recordings(&self) -> impl Iterator { - self.entity_dbs - .values() - .filter(|log| log.store_kind() == StoreKind::Recording) - } - - pub fn blueprints(&self) -> impl Iterator { - self.entity_dbs - .values() - .filter(|log| log.store_kind() == StoreKind::Blueprint) - } - - // -- - - pub fn contains_blueprint(&self, id: &StoreId) -> bool { - debug_assert_eq!(id.kind, StoreKind::Blueprint); - self.entity_dbs.contains_key(id) - } - - pub fn blueprint(&self, id: &StoreId) -> Option<&EntityDb> { - debug_assert_eq!(id.kind, StoreKind::Blueprint); - self.entity_dbs.get(id) - } - - pub fn blueprint_mut(&mut self, id: &StoreId) -> Option<&mut EntityDb> { - debug_assert_eq!(id.kind, StoreKind::Blueprint); - self.entity_dbs.get_mut(id) - } - - /// Creates one if it doesn't exist. - pub fn blueprint_entry(&mut self, id: &StoreId) -> &mut EntityDb { - debug_assert_eq!(id.kind, StoreKind::Blueprint); - - self.entity_dbs.entry(id.clone()).or_insert_with(|| { - // TODO(jleibs): If the blueprint doesn't exist this probably means we are - // initializing a new default-blueprint for the application in question. - // Make sure it's marked as a blueprint. - - let mut blueprint_db = EntityDb::new(id.clone()); - - re_log::debug!("Creating a new blueprint {id}"); - - blueprint_db.set_store_info(re_log_types::SetStoreInfo { - row_id: re_log_types::RowId::new(), - info: re_log_types::StoreInfo { - application_id: id.as_str().into(), - store_id: id.clone(), - is_official_example: false, - started: re_log_types::Time::now(), - store_source: re_log_types::StoreSource::Other("viewer".to_owned()), - store_kind: StoreKind::Blueprint, - }, - }); - - blueprint_db - }) - } - - // -- - - pub fn purge_empty(&mut self) { - self.entity_dbs.retain(|_, entity_db| !entity_db.is_empty()); - } - - pub fn drain_entity_dbs(&mut self) -> impl Iterator + '_ { - self.entity_dbs.drain().map(|(_, store)| store) - } -} diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index 41c110c9d858..b69f46aca3b3 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -33,7 +33,7 @@ pub fn override_ui( // entity from the blueprint-inspector since it isn't "part" of a space-view to provide // the overrides. let query = ctx.current_query(); - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); let query_result = ctx.lookup_query_result(space_view.id); let Some(data_result) = query_result @@ -313,7 +313,7 @@ pub fn override_visualizer_ui( instance_key: _, } = instance_path; - let entity_db = ctx.entity_db; + let recording = ctx.recording(); let query_result = ctx.lookup_query_result(space_view.id); let Some(data_result) = query_result @@ -336,7 +336,7 @@ pub fn override_visualizer_ui( add_new_visualizer( ctx, - entity_db, + recording, ui, space_view, &data_result, diff --git a/crates/re_viewer/src/ui/recordings_panel.rs b/crates/re_viewer/src/ui/recordings_panel.rs index fd250e645dd3..8bb03b5c0eac 100644 --- a/crates/re_viewer/src/ui/recordings_panel.rs +++ b/crates/re_viewer/src/ui/recordings_panel.rs @@ -51,8 +51,8 @@ fn loading_receivers_ui( ) -> bool { let sources_with_stores: ahash::HashSet = ctx .store_context - .all_recordings - .iter() + .bundle + .recordings() .filter_map(|store| store.data_source.clone()) .collect(); @@ -107,11 +107,11 @@ fn loading_receivers_ui( /// Returns `true` if any recordings were shown. fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) -> bool { let mut entity_dbs_map: BTreeMap<_, Vec<_>> = BTreeMap::new(); - for entity_db in &ctx.store_context.all_recordings { + for entity_db in ctx.store_context.bundle.recordings() { let key = entity_db .store_info() .map_or("", |info| info.application_id.as_str()); - entity_dbs_map.entry(key).or_default().push(*entity_db); + entity_dbs_map.entry(key).or_default().push(entity_db); } if entity_dbs_map.is_empty() { @@ -122,7 +122,7 @@ fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) -> bool { entity_dbs.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started)); } - let active_recording = ctx.store_context.recording.map(|rec| rec.store_id()); + let active_recording = Some(ctx.store_context.recording.store_id()); for (app_id, entity_dbs) in entity_dbs_map { if entity_dbs.len() == 1 { diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index aa0a945b6e57..306ea50548b5 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -162,7 +162,7 @@ impl App { } } - fn save_buttons_ui(&mut self, ui: &mut egui::Ui, store_view: Option<&StoreContext<'_>>) { + fn save_buttons_ui(&mut self, ui: &mut egui::Ui, store_ctx: Option<&StoreContext<'_>>) { use re_ui::UICommandSender; let file_save_in_progress = self.background_tasks.is_file_save_in_progress(); @@ -182,9 +182,7 @@ impl App { }); }); } else { - let entity_db_is_nonempty = store_view - .and_then(|view| view.recording) - .map_or(false, |recording| !recording.is_empty()); + let entity_db_is_nonempty = store_ctx.map_or(false, |ctx| !ctx.recording.is_empty()); ui.add_enabled_ui(entity_db_is_nonempty, |ui| { if ui .add(save_recording_button) @@ -199,7 +197,7 @@ impl App { // button, as this will determine whether its grayed out or not! // TODO(cmc): In practice the loop (green) selection is always there // at the moment so… - let loop_selection = self.state.loop_selection(store_view); + let loop_selection = self.state.loop_selection(store_ctx); if ui .add_enabled(loop_selection.is_some(), save_selection_button) diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index e85e9fcd20c4..4480916d2375 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -145,7 +145,7 @@ impl SelectionPanel { let (query, store) = if let Some(entity_path) = item.entity_path() { guess_query_and_store_for_selected_entity(ctx, entity_path) } else { - (ctx.current_query(), ctx.entity_db.store()) + (ctx.current_query(), ctx.recording_store()) }; data_ui_item.data_ui(ctx, ui, multi_selection_verbosity, &query, store); }); @@ -299,7 +299,7 @@ fn what_is_selected_ui( Item::StoreId(store_id) => { let id_str = format!("{} ID: {}", store_id.kind, store_id); - let title = if let Some(entity_db) = ctx.store_context.recording(store_id) { + let title = if let Some(entity_db) = ctx.store_context.bundle.get(store_id) { if let Some(info) = entity_db.store_info() { let time = info .started diff --git a/crates/re_viewer/src/ui/top_panel.rs b/crates/re_viewer/src/ui/top_panel.rs index 17c8af83c078..3329e69a38ea 100644 --- a/crates/re_viewer/src/ui/top_panel.rs +++ b/crates/re_viewer/src/ui/top_panel.rs @@ -408,7 +408,7 @@ fn e2e_latency_ui( store_context: Option<&StoreContext<'_>>, ) -> Option { let store_context = store_context?; - let recording = store_context.recording?; + let recording = store_context.recording; let e2e_latency_sec = recording.ingestion_stats().current_e2e_latency_sec()?; if e2e_latency_sec > 60.0 { diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index 664bf1ba3e94..5d52cb4f83fc 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -93,12 +93,12 @@ pub fn visual_time_range_ui( }); }); - let timeline_spec = if let Some(times) = ctx.entity_db.time_histogram(time_ctrl.timeline()) - { - TimelineSpec::from_time_histogram(times) - } else { - TimelineSpec::from_time_range(0..=0) - }; + let timeline_spec = + if let Some(times) = ctx.recording().time_histogram(time_ctrl.timeline()) { + TimelineSpec::from_time_histogram(times) + } else { + TimelineSpec::from_time_range(0..=0) + }; let current_time = time_ctrl .time_i64() diff --git a/crates/re_viewer_context/src/annotations.rs b/crates/re_viewer_context/src/annotations.rs index 86727ead20eb..1853690a5e0d 100644 --- a/crates/re_viewer_context/src/annotations.rs +++ b/crates/re_viewer_context/src/annotations.rs @@ -253,7 +253,7 @@ impl AnnotationMap { let mut visited = IntSet::::default(); - let data_store = ctx.entity_db.store(); + let data_store = ctx.recording_store(); // This logic is borrowed from `iter_ancestor_meta_field`, but using the arrow-store instead // not made generic as `AnnotationContext` was the only user of that function diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index faeb7acd17d7..e020443230c1 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -115,7 +115,7 @@ impl ItemCollection { ( resolve_mono_instance_path_item( &ctx.current_query(), - ctx.entity_db.store(), + ctx.recording_store(), &item, ), space_ctx, diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 24a2ebcd15ad..635ed9d69f62 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -322,8 +322,7 @@ impl DataResult { .store() .query_latest_component::(path, ctx.blueprint_query), StoreKind::Recording => ctx - .entity_db - .store() + .recording_store() .query_latest_component::(path, &ctx.current_query()), }) .map(|c| c.value) diff --git a/crates/re_viewer_context/src/store_context.rs b/crates/re_viewer_context/src/store_context.rs index c0756192ec0d..abafb0d9c050 100644 --- a/crates/re_viewer_context/src/store_context.rs +++ b/crates/re_viewer_context/src/store_context.rs @@ -1,19 +1,19 @@ -use re_entity_db::EntityDb; +use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::ApplicationId; /// The current Blueprint and Recording being displayed by the viewer pub struct StoreContext<'a> { + /// The `app_id` of the current recording pub app_id: ApplicationId, + + /// The current active recording. pub blueprint: &'a EntityDb, - pub recording: Option<&'a EntityDb>, - pub all_recordings: Vec<&'a EntityDb>, -} -impl<'a> StoreContext<'a> { - pub fn recording(&self, store_id: &re_log_types::StoreId) -> Option<&'a EntityDb> { - self.all_recordings - .iter() - .find(|rec| rec.store_id() == store_id) - .copied() - } + /// The current open recording. + /// + /// If none is open, this will point to a dummy empty recording. + pub recording: &'a EntityDb, + + /// All the loaded recordings and blueprints. + pub bundle: &'a StoreBundle, } diff --git a/crates/re_viewer_context/src/viewer_context.rs b/crates/re_viewer_context/src/viewer_context.rs index 33b1264bcefc..575f19f237d8 100644 --- a/crates/re_viewer_context/src/viewer_context.rs +++ b/crates/re_viewer_context/src/viewer_context.rs @@ -26,10 +26,6 @@ pub struct ViewerContext<'a> { /// Registry of all known classes of space views. pub space_view_class_registry: &'a SpaceViewClassRegistry, - /// The current recording. - /// TODO(jleibs): This can go away - pub entity_db: &'a EntityDb, - /// The current view of the store pub store_context: &'a StoreContext<'a>, @@ -73,6 +69,24 @@ pub struct ViewerContext<'a> { } impl<'a> ViewerContext<'a> { + /// The active recording. + #[inline] + pub fn recording(&self) -> &EntityDb { + self.store_context.recording + } + + /// The data store of the active recording. + #[inline] + pub fn recording_store(&self) -> &re_data_store::DataStore { + self.store_context.recording.store() + } + + /// The `StoreId` of the active recording. + #[inline] + pub fn recording_id(&self) -> &re_log_types::StoreId { + self.store_context.recording.store_id() + } + /// Returns the current selection. pub fn selection(&self) -> &ItemCollection { self.rec_cfg.selection_state.selected_items() diff --git a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs index 0378902a6296..d31511db78e1 100644 --- a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs +++ b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs @@ -87,21 +87,21 @@ fn recommended_space_views_for_selection( let mut output: IntSet = IntSet::default(); let space_view_class_registry = ctx.viewer_context.space_view_class_registry; - let entity_db = ctx.viewer_context.entity_db; + let recording = ctx.viewer_context.recording(); let applicable_entities_per_visualizer = - space_view_class_registry.applicable_entities_for_visualizer_systems(entity_db.store_id()); + space_view_class_registry.applicable_entities_for_visualizer_systems(recording.store_id()); for entry in space_view_class_registry.iter_registry() { let Some(suggested_root) = entry .class - .recommended_root_for_entities(&entities_of_interest, entity_db) + .recommended_root_for_entities(&entities_of_interest, recording) else { continue; }; let visualizable_entities = determine_visualizable_entities( &applicable_entities_per_visualizer, - entity_db, + recording, &space_view_class_registry.new_visualizer_collection(entry.identifier), &*entry.class, &suggested_root, @@ -144,7 +144,7 @@ fn create_space_view_for_selected_entities( .viewer_context .space_view_class_registry .get_class_or_log_error(&identifier) - .recommended_root_for_entities(&entities_of_interest, ctx.viewer_context.entity_db) + .recommended_root_for_entities(&entities_of_interest, ctx.viewer_context.recording()) .unwrap_or_else(EntityPath::root); let mut filter = EntityPathFilter::default(); diff --git a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs index 74d9878fd02f..1d699ae91217 100644 --- a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs +++ b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs @@ -30,7 +30,7 @@ impl ContextMenuAction for CollapseExpandAllAction { //TODO(ab): for DataResult, walk the data result tree instead! Item::DataResult(_, instance_path) => ctx .viewer_context - .entity_db + .recording() .tree() .subtree(&instance_path.entity_path) .is_some_and(|subtree| !subtree.is_leaf()), @@ -80,7 +80,7 @@ impl ContextMenuAction for CollapseExpandAllAction { // but the current API isn't super ergonomic. let Some(subtree) = ctx .viewer_context - .entity_db + .recording() .tree() .subtree(&instance_path.entity_path) else { @@ -97,7 +97,7 @@ impl ContextMenuAction for CollapseExpandAllAction { fn process_instance_path(&self, ctx: &ContextMenuContext<'_>, instance_path: &InstancePath) { let Some(subtree) = ctx .viewer_context - .entity_db + .recording() .tree() .subtree(&instance_path.entity_path) else { diff --git a/crates/re_viewport/src/space_view_entity_picker.rs b/crates/re_viewport/src/space_view_entity_picker.rs index 644aaaa38463..35fcce9b290c 100644 --- a/crates/re_viewport/src/space_view_entity_picker.rs +++ b/crates/re_viewport/src/space_view_entity_picker.rs @@ -57,7 +57,7 @@ impl SpaceViewEntityPicker { fn add_entities_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui, space_view: &SpaceViewBlueprint) { re_tracing::profile_function!(); - let tree = &ctx.entity_db.tree(); + let tree = &ctx.recording().tree(); // TODO(jleibs): Avoid clone let query_result = ctx.lookup_query_result(space_view.id).clone(); let entity_path_filter = &space_view.contents.entity_path_filter; @@ -154,7 +154,7 @@ fn add_entities_line_ui( re_tracing::profile_function!(); let query = ctx.current_query(); - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); ui.horizontal(|ui| { let entity_path = &entity_tree.path; @@ -322,7 +322,7 @@ fn create_entity_add_info( let class = space_view.class(ctx.space_view_class_registry); let visualizable_entities = determine_visualizable_entities( ctx.applicable_entities_per_visualizer, - ctx.entity_db, + ctx.recording(), &ctx.space_view_class_registry .new_visualizer_collection(*space_view.class_identifier()), class, diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index ca1c48a6ea02..2a726ce80922 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -523,7 +523,7 @@ impl Viewport<'_, '_> { space_view_visible: bool, projection_mode: bool, ) { - let store = ctx.entity_db.store(); + let store = ctx.recording_store(); let entity_path = node_or_path.path(); @@ -564,7 +564,7 @@ impl Viewport<'_, '_> { .last() .map_or("unknown".to_owned(), |e| e.ui_string()) }; - let item_label = if ctx.entity_db.is_known_entity(entity_path) { + let item_label = if ctx.recording().is_known_entity(entity_path) { egui::RichText::new(item_label) } else { ctx.re_ui.warning_text(item_label) diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index c1151493a22c..339c0edd97af 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -275,7 +275,7 @@ fn color_space_ui( item_ui::instance_path_button( ctx, &ctx.current_query(), - ctx.entity_db.store(), + ctx.recording_store(), ui, Some(query.space_view_id), &instance, @@ -285,7 +285,7 @@ fn color_space_ui( ui, UiVerbosity::Reduced, &ctx.current_query(), - ctx.entity_db.store(), + ctx.recording_store(), ); }); ctx.select_hovered_on_click(&interact, Item::DataResult(query.space_view_id, instance)); diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index 4d072495bf04..66a37ce5c786 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -57,7 +57,7 @@ impl VisualizerSystem for InstanceColorSystem { for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { // …gather all colors and their instance ids. if let Ok(arch_view) = query_archetype::( - ctx.entity_db.store(), + ctx.recording_store(), &ctx.current_query(), &data_result.entity_path, ) { From d70a0f59f26c58d64abbd4687d23366a5ddded48 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 21 Mar 2024 19:46:35 +0100 Subject: [PATCH 096/508] Select active recording if nothing else is selected (#5627) ### What If nothing is selected (or user presses escape), the active recording gets selected. In a future PR I will improve the contents of the selection panel when a recording is selected, e.g. show the blueprints in the recording etc, but for that I need to do some refactors first. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5627/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5627/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5627/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5627) - [Docs preview](https://rerun.io/preview/88a9b028b16bf7c2750b808ba4b10b49393e81a1/docs) - [Examples preview](https://rerun.io/preview/88a9b028b16bf7c2750b808ba4b10b49393e81a1/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app_state.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index de733f6d2f59..88b3cbc30afd 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -296,12 +296,22 @@ impl AppState { ui, app_blueprint.time_panel_expanded, ); - selection_panel.show_panel( - &ctx, - ui, - &mut viewport, - app_blueprint.selection_panel_expanded, - ); + + { + if ctx.selection().is_empty() { + // Make sure something is selected before showing the selection panel. + ctx.selection_state() + .set_selection(re_viewer_context::Item::StoreId( + ctx.entity_db.store_id().clone(), + )); + } + selection_panel.show_panel( + &ctx, + ui, + &mut viewport, + app_blueprint.selection_panel_expanded, + ); + } let central_panel_frame = egui::Frame { fill: ui.style().visuals.panel_fill, From eac4a9c1300048421fde9b1e0b9a4a59f8c6c3db Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 21 Mar 2024 15:47:18 -0400 Subject: [PATCH 097/508] Fix build on main (#5637) ### What Looks like a merge race. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5637/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5637/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5637/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5637) - [Docs preview](https://rerun.io/preview/a84f97aab2d47e4622f30b4f5d1698cdc60196eb/docs) - [Examples preview](https://rerun.io/preview/a84f97aab2d47e4622f30b4f5d1698cdc60196eb/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app_state.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 88b3cbc30afd..ff2ce961b36d 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -301,9 +301,7 @@ impl AppState { if ctx.selection().is_empty() { // Make sure something is selected before showing the selection panel. ctx.selection_state() - .set_selection(re_viewer_context::Item::StoreId( - ctx.entity_db.store_id().clone(), - )); + .set_selection(re_viewer_context::Item::StoreId(ctx.recording_id().clone())); } selection_panel.show_panel( &ctx, From 76fd4cbeaf48454b3ef7001810b3f0d07c918124 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 21 Mar 2024 21:11:08 +0100 Subject: [PATCH 098/508] Allow setting custom names to container (#5626) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What As the title say ☝🏻 Decisions: - Keep "Viewport" in the name of the root container (see screenshot below). - Refactor some stuff: - moved `Contents` to re_viewer_contex (I actually been meaning to do that for a while but can't remember why now) - moved/renamed `SpaceViewName` to `ContentsName` in re_viewer_context ⚠️ review commit by commit https://github.com/rerun-io/rerun/assets/49431240/cac22100-c0fb-4ff8-9fe0-195607c222a4 ```python import rerun as rr import rerun.blueprint as rrb rr.init( "rerun_example_demo", blueprint=rrb.Horizontal( rrb.Vertical( rrb.Spatial3DView(origin="/point3d"), rrb.Spatial3DView(origin="/point3d"), name="First Vertical", ), rrb.Vertical( rrb.Spatial3DView(origin="/point3d"), rrb.Spatial3DView(origin="/point3d"), name="Second Vertical", ), name="Top-Level", ), ) rr.connect() rr.log("point3d", rr.Points3D([0, 1, 2])) ``` image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5626/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5626/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5626/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5626) - [Docs preview](https://rerun.io/preview/df3fd74ffb59adfb22bfa15b1b28fea2e916d2b5/docs) - [Examples preview](https://rerun.io/preview/df3fd74ffb59adfb22bfa15b1b28fea2e916d2b5/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view/src/lib.rs | 2 +- crates/re_space_view/src/space_view.rs | 41 +---- .../re_viewer/src/ui/selection_history_ui.rs | 3 +- crates/re_viewer/src/ui/selection_panel.rs | 55 ++++-- crates/re_viewer_context/src/contents.rs | 124 ++++++++++++++ crates/re_viewer_context/src/lib.rs | 3 + .../src/add_space_view_or_container_modal.rs | 5 +- crates/re_viewport/src/container.rs | 159 ++++++------------ .../actions/collapse_expand_all.rs | 3 +- .../src/context_menu/actions/remove.rs | 3 +- .../src/context_menu/actions/show_hide.rs | 3 +- crates/re_viewport/src/context_menu/mod.rs | 4 +- crates/re_viewport/src/lib.rs | 4 +- crates/re_viewport/src/viewport.rs | 33 +++- crates/re_viewport/src/viewport_blueprint.rs | 6 +- .../re_viewport/src/viewport_blueprint_ui.rs | 100 ++++++----- rerun_py/rerun_sdk/rerun/blueprint/api.py | 5 + .../rerun_sdk/rerun/blueprint/containers.py | 22 ++- 18 files changed, 338 insertions(+), 237 deletions(-) create mode 100644 crates/re_viewer_context/src/contents.rs diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index fc879706ef7d..900e4bf482b8 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -15,7 +15,7 @@ mod visualizable; pub use data_query::{DataQuery, EntityOverrideContext, PropertyResolver}; pub use heuristics::suggest_space_view_for_each_entity; pub use screenshot::ScreenshotMode; -pub use space_view::{SpaceViewBlueprint, SpaceViewName}; +pub use space_view::SpaceViewBlueprint; pub use space_view_contents::SpaceViewContents; pub use sub_archetypes::{ entity_path_for_space_view_sub_archetype, query_space_view_sub_archetype, diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 49aefde8dfa6..d65881892b7e 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -14,36 +14,12 @@ use re_types::{ use re_types_core::archetypes::Clear; use re_types_core::Archetype as _; use re_viewer_context::{ - DataResult, OverridePath, PerSystemEntities, PropertyOverrides, RecommendedSpaceView, - SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, StoreContext, - SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, + ContentsName, DataResult, OverridePath, PerSystemEntities, PropertyOverrides, + RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, + StoreContext, SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, + ViewerContext, }; -// ---------------------------------------------------------------------------- - -/// The name of a space view. -/// -/// Space views are unnamed by default, but have a placeholder name to be used in the UI. -#[derive(Clone, Debug)] -pub enum SpaceViewName { - /// This space view has been given a name by the user. - Named(String), - - /// This space view is unnamed and should be displayed with this placeholder name. - Placeholder(String), -} - -impl AsRef for SpaceViewName { - #[inline] - fn as_ref(&self) -> &str { - match self { - SpaceViewName::Named(name) | SpaceViewName::Placeholder(name) => name, - } - } -} - -// ---------------------------------------------------------------------------- - /// A view of a space. /// /// Note: [`SpaceViewBlueprint`] doesn't implement Clone because it stores an internal @@ -96,7 +72,6 @@ impl SpaceViewBlueprint { } /// Placeholder name displayed in the UI if the user hasn't explicitly named the space view. - #[allow(clippy::unused_self)] pub fn missing_name_placeholder(&self) -> String { let entity_path = self .space_origin @@ -125,12 +100,12 @@ impl SpaceViewBlueprint { /// Returns this space view's display name /// - /// When returning [`SpaceViewName::Placeholder`], the UI should display the resulting name using + /// When returning [`ContentsName::Placeholder`], the UI should display the resulting name using /// `re_ui::LabelStyle::Unnamed`. - pub fn display_name_or_default(&self) -> SpaceViewName { + pub fn display_name_or_default(&self) -> ContentsName { self.display_name.clone().map_or_else( - || SpaceViewName::Placeholder(self.missing_name_placeholder()), - SpaceViewName::Named, + || ContentsName::Placeholder(self.missing_name_placeholder()), + ContentsName::Named, ) } diff --git a/crates/re_viewer/src/ui/selection_history_ui.rs b/crates/re_viewer/src/ui/selection_history_ui.rs index 6055389c33ae..14121600bb23 100644 --- a/crates/re_viewer/src/ui/selection_history_ui.rs +++ b/crates/re_viewer/src/ui/selection_history_ui.rs @@ -206,8 +206,9 @@ fn item_to_string(blueprint: &ViewportBlueprint, item: &Item) -> String { format!("{}:{}", path.entity_path, path.component_name.short_name(),) } Item::Container(container_id) => { + // TODO(#4678): unnamed container should have their label formatted accordingly (subdued) if let Some(container) = blueprint.container(container_id) { - format!("{:?}", container.container_kind) + container.display_name_or_default().as_ref().to_owned() } else { "".to_owned() } diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 4480916d2375..9c8d48e87c6a 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -17,11 +17,12 @@ use re_types::{ use re_ui::list_item::ListItem; use re_ui::{ReUi, SyntaxHighlighting as _}; use re_viewer_context::{ - gpu_bridge::colormap_dropdown_button_ui, ContainerId, DataQueryResult, HoverHighlight, Item, - SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, UiVerbosity, ViewerContext, + gpu_bridge::colormap_dropdown_button_ui, ContainerId, Contents, DataQueryResult, + HoverHighlight, Item, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, UiVerbosity, + ViewerContext, }; use re_viewport::{ - context_menu_ui_for_item, icon_for_container_kind, space_view_name_style, Contents, + contents_name_style, context_menu_ui_for_item, icon_for_container_kind, SelectionUpdateBehavior, Viewport, ViewportBlueprint, }; @@ -280,7 +281,7 @@ fn space_view_button( space_view.class(ctx.space_view_class_registry).icon(), space_view_name.as_ref(), is_selected, - space_view_name_style(&space_view_name), + contents_name_style(&space_view_name), ) .on_hover_text("Space View"); item_ui::cursor_interact_with_selectable(ctx, response, item) @@ -319,15 +320,26 @@ fn what_is_selected_ui( Item::Container(container_id) => { if let Some(container_blueprint) = viewport.container(container_id) { - item_title_ui( - ctx.re_ui, - ui, - &format!("{:?}", container_blueprint.container_kind), - Some(re_viewport::icon_for_container_kind( + let hover_text = + if let Some(display_name) = container_blueprint.display_name.as_ref() { + format!( + "{:?} Container {display_name:?}", + container_blueprint.container_kind, + ) + } else { + format!("Unnamed {:?} Container", container_blueprint.container_kind,) + }; + + let container_name = container_blueprint.display_name_or_default(); + ListItem::new(ctx.re_ui, container_name.as_ref()) + .label_style(contents_name_style(&container_name)) + .with_icon(re_viewport::icon_for_container_kind( &container_blueprint.container_kind, - )), - &format!("{:?} container", container_blueprint.container_kind), - ); + )) + .with_height(ReUi::title_bar_height()) + .selected(true) + .show_flat(ui) + .on_hover_text(hover_text); } } @@ -376,7 +388,7 @@ fn what_is_selected_ui( let space_view_name = space_view.display_name_or_default(); ListItem::new(ctx.re_ui, space_view_name.as_ref()) - .label_style(space_view_name_style(&space_view_name)) + .label_style(contents_name_style(&space_view_name)) .with_icon(space_view.class(ctx.space_view_class_registry).icon()) .with_height(ReUi::title_bar_height()) .selected(true) @@ -586,6 +598,15 @@ fn container_top_level_properties( egui::Grid::new("container_top_level_properties") .num_columns(2) .show(ui, |ui| { + let mut name = container.display_name.clone().unwrap_or_default(); + ui.label("Name").on_hover_text( + "The name of the Container used for display purposes. This can be any text string.", + ); + ui.text_edit_singleline(&mut name); + container.set_display_name(ctx, if name.is_empty() { None } else { Some(name) }); + + ui.end_row(); + ui.label("Kind"); let mut container_kind = container.container_kind; @@ -701,7 +722,7 @@ fn show_list_item_for_container_child( ( Item::SpaceView(*space_view_id), ListItem::new(ctx.re_ui, space_view_name.as_ref()) - .label_style(space_view_name_style(&space_view_name)) + .label_style(contents_name_style(&space_view_name)) .with_icon(space_view.class(ctx.space_view_class_registry).icon()) .with_buttons(|re_ui, ui| { let response = re_ui @@ -722,10 +743,12 @@ fn show_list_item_for_container_child( return false; }; + let container_name = container.display_name_or_default(); + ( Item::Container(*container_id), - ListItem::new(ctx.re_ui, format!("{:?}", container.container_kind)) - .label_style(re_ui::LabelStyle::Unnamed) + ListItem::new(ctx.re_ui, container_name.as_ref()) + .label_style(contents_name_style(&container_name)) .with_icon(icon_for_container_kind(&container.container_kind)) .with_buttons(|re_ui, ui| { let response = re_ui diff --git a/crates/re_viewer_context/src/contents.rs b/crates/re_viewer_context/src/contents.rs new file mode 100644 index 000000000000..87305c1448f0 --- /dev/null +++ b/crates/re_viewer_context/src/contents.rs @@ -0,0 +1,124 @@ +use std::convert::{TryFrom, TryInto}; + +use egui_tiles::TileId; + +use re_log_types::EntityPath; + +use crate::item::Item; +use crate::{BlueprintId, BlueprintIdRegistry, ContainerId, SpaceViewId}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Contents { + Container(ContainerId), + SpaceView(SpaceViewId), +} + +impl Contents { + pub fn try_from(path: &EntityPath) -> Option { + if path.starts_with(SpaceViewId::registry()) { + Some(Self::SpaceView(SpaceViewId::from_entity_path(path))) + } else if path.starts_with(ContainerId::registry()) { + Some(Self::Container(ContainerId::from_entity_path(path))) + } else { + None + } + } + + #[inline] + pub fn as_entity_path(&self) -> EntityPath { + match self { + Self::Container(id) => id.as_entity_path(), + Self::SpaceView(id) => id.as_entity_path(), + } + } + + #[inline] + pub fn as_tile_id(&self) -> TileId { + match self { + Self::Container(id) => blueprint_id_to_tile_id(id), + Self::SpaceView(id) => blueprint_id_to_tile_id(id), + } + } + + #[inline] + pub fn as_item(&self) -> Item { + match self { + Contents::Container(container_id) => Item::Container(*container_id), + Contents::SpaceView(space_view_id) => Item::SpaceView(*space_view_id), + } + } + + #[inline] + pub fn as_container_id(&self) -> Option { + match self { + Self::Container(id) => Some(*id), + Self::SpaceView(_) => None, + } + } + + #[inline] + pub fn as_space_view_id(&self) -> Option { + match self { + Self::SpaceView(id) => Some(*id), + Self::Container(_) => None, + } + } +} + +impl TryFrom for Contents { + type Error = (); + + fn try_from(item: Item) -> Result { + (&item).try_into() + } +} + +impl TryFrom<&Item> for Contents { + type Error = (); + + fn try_from(item: &Item) -> Result { + match item { + Item::Container(id) => Ok(Self::Container(*id)), + Item::SpaceView(id) => Ok(Self::SpaceView(*id)), + _ => Err(()), + } + } +} + +impl From for Contents { + #[inline] + fn from(id: SpaceViewId) -> Self { + Self::SpaceView(id) + } +} + +impl From for Contents { + #[inline] + fn from(id: ContainerId) -> Self { + Self::Container(id) + } +} + +/// The name of a [`Contents`]. +#[derive(Clone, Debug)] +pub enum ContentsName { + /// This [`Contents`] has been given a name by the user. + Named(String), + + /// This [`Contents`] is unnamed and should be displayed with this placeholder name. + Placeholder(String), +} + +impl AsRef for ContentsName { + #[inline] + fn as_ref(&self) -> &str { + match self { + ContentsName::Named(name) | ContentsName::Placeholder(name) => name, + } + } +} + +#[inline] +pub fn blueprint_id_to_tile_id(id: &BlueprintId) -> TileId { + TileId::from_u64(id.hash()) +} diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 0ae2fb383825..27b2950552ab 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -10,6 +10,7 @@ mod caches; mod collapsed_id; mod command_sender; mod component_ui_registry; +mod contents; mod item; mod query_context; mod selection_history; @@ -37,6 +38,7 @@ pub use command_sender::{ command_channel, CommandReceiver, CommandSender, SystemCommand, SystemCommandSender, }; pub use component_ui_registry::{ComponentUiRegistry, UiVerbosity}; +pub use contents::{blueprint_id_to_tile_id, Contents, ContentsName}; pub use item::Item; pub use query_context::{DataQueryResult, DataResultHandle, DataResultNode, DataResultTree}; pub use selection_history::SelectionHistory; @@ -66,6 +68,7 @@ pub use viewer_context::{RecordingConfig, ViewerContext}; #[cfg(not(target_arch = "wasm32"))] mod clipboard; + #[cfg(not(target_arch = "wasm32"))] pub use clipboard::Clipboard; diff --git a/crates/re_viewport/src/add_space_view_or_container_modal.rs b/crates/re_viewport/src/add_space_view_or_container_modal.rs index cfda7c7f900d..26a2ec536a3f 100644 --- a/crates/re_viewport/src/add_space_view_or_container_modal.rs +++ b/crates/re_viewport/src/add_space_view_or_container_modal.rs @@ -2,11 +2,12 @@ use itertools::Itertools; -use crate::container::blueprint_id_to_tile_id; use crate::{icon_for_container_kind, ViewportBlueprint}; use re_space_view::SpaceViewBlueprint; use re_ui::ReUi; -use re_viewer_context::{ContainerId, RecommendedSpaceView, ViewerContext}; +use re_viewer_context::{ + blueprint_id_to_tile_id, ContainerId, RecommendedSpaceView, ViewerContext, +}; #[derive(Default)] pub struct AddSpaceViewOrContainerModal { diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index 7e5d3f2d287c..3748905ddfc9 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -7,111 +7,15 @@ use re_log::ResultExt; use re_log_types::{DataRow, EntityPath, RowId}; use re_query::query_archetype; use re_types::blueprint::components::Visible; +use re_types::components::Name; use re_types_core::archetypes::Clear; use re_viewer_context::{ - BlueprintId, BlueprintIdRegistry, ContainerId, Item, SpaceViewId, SystemCommand, - SystemCommandSender as _, ViewerContext, + ContainerId, Contents, ContentsName, SpaceViewId, SystemCommand, SystemCommandSender as _, + ViewerContext, }; use crate::blueprint::components::GridColumns; -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum Contents { - Container(ContainerId), - SpaceView(SpaceViewId), -} - -impl Contents { - fn try_from(path: &EntityPath) -> Option { - if path.starts_with(SpaceViewId::registry()) { - Some(Self::SpaceView(SpaceViewId::from_entity_path(path))) - } else if path.starts_with(ContainerId::registry()) { - Some(Self::Container(ContainerId::from_entity_path(path))) - } else { - None - } - } - - #[inline] - fn as_entity_path(&self) -> EntityPath { - match self { - Self::Container(id) => id.as_entity_path(), - Self::SpaceView(id) => id.as_entity_path(), - } - } - - #[inline] - pub fn as_tile_id(&self) -> TileId { - match self { - Self::Container(id) => blueprint_id_to_tile_id(id), - Self::SpaceView(id) => blueprint_id_to_tile_id(id), - } - } - - #[inline] - pub fn as_item(&self) -> Item { - match self { - Contents::Container(container_id) => Item::Container(*container_id), - Contents::SpaceView(space_view_id) => Item::SpaceView(*space_view_id), - } - } - - #[inline] - pub fn as_container_id(&self) -> Option { - match self { - Self::Container(id) => Some(*id), - Self::SpaceView(_) => None, - } - } - - #[inline] - pub fn as_space_view_id(&self) -> Option { - match self { - Self::SpaceView(id) => Some(*id), - Self::Container(_) => None, - } - } -} - -impl TryFrom for Contents { - type Error = (); - - fn try_from(item: Item) -> Result { - (&item).try_into() - } -} - -impl TryFrom<&Item> for Contents { - type Error = (); - - fn try_from(item: &Item) -> Result { - match item { - Item::Container(id) => Ok(Self::Container(*id)), - Item::SpaceView(id) => Ok(Self::SpaceView(*id)), - _ => Err(()), - } - } -} - -#[inline] -pub fn blueprint_id_to_tile_id(id: &BlueprintId) -> TileId { - TileId::from_u64(id.hash()) -} - -impl From for Contents { - #[inline] - fn from(id: SpaceViewId) -> Self { - Self::SpaceView(id) - } -} - -impl From for Contents { - #[inline] - fn from(id: ContainerId) -> Self { - Self::Container(id) - } -} - /// The native version of a [`crate::blueprint::archetypes::ContainerBlueprint`]. /// /// This represents a single container in the blueprint. On each frame, it is @@ -124,7 +28,7 @@ impl From for Contents { pub struct ContainerBlueprint { pub id: ContainerId, pub container_kind: egui_tiles::ContainerKind, - pub display_name: String, + pub display_name: Option, pub contents: Vec, pub col_shares: Vec, pub row_shares: Vec, @@ -165,10 +69,7 @@ impl ContainerBlueprint { .ok()?; let container_kind = container_kind.into(); - - // TODO(jleibs): Don't use debug print for this - let display_name = - display_name.map_or_else(|| format!("{container_kind:?}"), |v| v.0.to_string()); + let display_name = display_name.map(|v| v.0.to_string()); let contents = contents .unwrap_or_default() @@ -235,12 +136,18 @@ impl ContainerBlueprint { let contents: Vec<_> = contents.iter().map(|item| item.as_entity_path()).collect(); let mut arch = crate::blueprint::archetypes::ContainerBlueprint::new(*container_kind) - .with_display_name(display_name.clone()) .with_contents(&contents) .with_col_shares(col_shares.clone()) .with_row_shares(row_shares.clone()) .with_visible(*visible); + // Note: it's important to _not_ clear the `Name` component if `display_name` is set to + // `None`, as we call this function with `ContainerBlueprint` recreated from `egui_tiles`, + // which is lossy with custom names. + if let Some(display_name) = display_name { + arch = arch.with_display_name(display_name.clone()); + } + // TODO(jleibs): The need for this pattern is annoying. Should codegen // a version of this that can take an Option. if let Some(active_tab) = &active_tab { @@ -297,7 +204,7 @@ impl ContainerBlueprint { Self { id: container_id, container_kind: egui_tiles::ContainerKind::Tabs, - display_name: format!("{:?}", egui_tiles::ContainerKind::Tabs), + display_name: None, // keep whatever name is already set contents, col_shares: vec![], row_shares: vec![], @@ -312,7 +219,7 @@ impl ContainerBlueprint { Self { id: container_id, container_kind: kind, - display_name: format!("{kind:?}"), + display_name: None, // keep whatever name is already set contents, col_shares: linear .children @@ -330,7 +237,7 @@ impl ContainerBlueprint { Self { id: container_id, container_kind: kind, - display_name: format!("{kind:?}"), + display_name: None, // keep whatever name is already set contents, col_shares: vec![], row_shares: linear @@ -347,7 +254,7 @@ impl ContainerBlueprint { egui_tiles::Container::Grid(grid) => Self { id: container_id, container_kind: egui_tiles::ContainerKind::Grid, - display_name: format!("{:?}", egui_tiles::ContainerKind::Grid), + display_name: None, // keep whatever name is already set contents, col_shares: grid.col_shares.clone(), row_shares: grid.row_shares.clone(), @@ -361,6 +268,40 @@ impl ContainerBlueprint { } } + /// Placeholder name displayed in the UI if the user hasn't explicitly named the space view. + #[inline] + pub fn missing_name_placeholder(&self) -> String { + format!("{:?}", self.container_kind) + } + + /// Returns this container's display name + /// + /// When returning [`ContentsName::Placeholder`], the UI should display the resulting name using + /// `re_ui::LabelStyle::Unnamed`. + #[inline] + pub fn display_name_or_default(&self) -> ContentsName { + self.display_name.clone().map_or_else( + || ContentsName::Placeholder(self.missing_name_placeholder()), + ContentsName::Named, + ) + } + + /// Sets the display name for this container. + #[inline] + pub fn set_display_name(&self, ctx: &ViewerContext<'_>, name: Option) { + if name != self.display_name { + match name { + Some(name) => { + let component = Name(name.into()); + ctx.save_blueprint_component(&self.entity_path(), &component); + } + None => { + ctx.save_empty_blueprint_component::(&self.entity_path()); + } + } + } + } + #[inline] pub fn set_visible(&self, ctx: &ViewerContext<'_>, visible: bool) { if visible != self.visible { diff --git a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs index 1d699ae91217..dcd2072f8229 100644 --- a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs +++ b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs @@ -1,8 +1,7 @@ use re_entity_db::InstancePath; -use re_viewer_context::{CollapseScope, ContainerId, Item, SpaceViewId}; +use re_viewer_context::{CollapseScope, ContainerId, Contents, Item, SpaceViewId}; use crate::context_menu::{ContextMenuAction, ContextMenuContext}; -use crate::Contents; /// Collapse or expand all items in the selection. // TODO(ab): the current implementation makes strong assumptions of which CollapseScope to use based diff --git a/crates/re_viewport/src/context_menu/actions/remove.rs b/crates/re_viewport/src/context_menu/actions/remove.rs index 78c459dbdade..e29411a4d57b 100644 --- a/crates/re_viewport/src/context_menu/actions/remove.rs +++ b/crates/re_viewport/src/context_menu/actions/remove.rs @@ -1,9 +1,8 @@ use re_entity_db::InstancePath; use re_log_types::EntityPathRule; -use re_viewer_context::{ContainerId, Item, SpaceViewId}; +use re_viewer_context::{ContainerId, Contents, Item, SpaceViewId}; use crate::context_menu::{ContextMenuAction, ContextMenuContext}; -use crate::Contents; /// Remove a container, space view, or data result. pub(crate) struct RemoveAction; diff --git a/crates/re_viewport/src/context_menu/actions/show_hide.rs b/crates/re_viewport/src/context_menu/actions/show_hide.rs index b4488c42eb32..88de08180776 100644 --- a/crates/re_viewport/src/context_menu/actions/show_hide.rs +++ b/crates/re_viewport/src/context_menu/actions/show_hide.rs @@ -1,8 +1,7 @@ use re_entity_db::InstancePath; -use re_viewer_context::{ContainerId, Item, SpaceViewId}; +use re_viewer_context::{ContainerId, Contents, Item, SpaceViewId}; use crate::context_menu::{ContextMenuAction, ContextMenuContext}; -use crate::Contents; pub(crate) struct ShowAction; diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index 073a4f52840a..964b29d6889c 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -2,9 +2,9 @@ use itertools::Itertools; use once_cell::sync::OnceCell; use re_entity_db::InstancePath; -use re_viewer_context::{ContainerId, Item, ItemCollection, SpaceViewId, ViewerContext}; +use re_viewer_context::{ContainerId, Contents, Item, ItemCollection, SpaceViewId, ViewerContext}; -use crate::{ContainerBlueprint, Contents, ViewportBlueprint}; +use crate::{ContainerBlueprint, ViewportBlueprint}; mod actions; mod sub_menu; diff --git a/crates/re_viewport/src/lib.rs b/crates/re_viewport/src/lib.rs index 5ea14a7736aa..61f29fd1538b 100644 --- a/crates/re_viewport/src/lib.rs +++ b/crates/re_viewport/src/lib.rs @@ -24,11 +24,11 @@ mod viewport_blueprint_ui; /// Unstable. Used for the ongoing blueprint experimentation. pub mod blueprint; -pub use container::{ContainerBlueprint, Contents}; +pub use container::ContainerBlueprint; pub use context_menu::{context_menu_ui_for_item, SelectionUpdateBehavior}; pub use viewport::{Viewport, ViewportState}; pub use viewport_blueprint::ViewportBlueprint; -pub use viewport_blueprint_ui::space_view_name_style; +pub use viewport_blueprint_ui::contents_name_style; pub mod external { pub use re_space_view; diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index 8285bccc8897..d2f5ea496fa7 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -10,16 +10,15 @@ use re_entity_db::EntityPropertyMap; use re_renderer::ScreenshotProcessor; use re_ui::{Icon, ReUi}; use re_viewer_context::{ - ContainerId, Item, SpaceViewClassIdentifier, SpaceViewClassRegistry, SpaceViewId, - SpaceViewState, SystemExecutionOutput, ViewQuery, ViewerContext, + blueprint_id_to_tile_id, ContainerId, Contents, Item, SpaceViewClassIdentifier, + SpaceViewClassRegistry, SpaceViewId, SpaceViewState, SystemExecutionOutput, ViewQuery, + ViewerContext, }; -use crate::container::blueprint_id_to_tile_id; use crate::screenshot::handle_pending_space_view_screenshots; use crate::{ - add_space_view_or_container_modal::AddSpaceViewOrContainerModal, container::Contents, - context_menu_ui_for_item, icon_for_container_kind, - space_view_entity_picker::SpaceViewEntityPicker, + add_space_view_or_container_modal::AddSpaceViewOrContainerModal, context_menu_ui_for_item, + icon_for_container_kind, space_view_entity_picker::SpaceViewEntityPicker, system_execution::execute_systems_for_all_space_views, SelectionUpdateBehavior, ViewportBlueprint, }; @@ -924,9 +923,27 @@ impl TabWidget { if let Some(Contents::Container(container_id)) = tab_viewer.contents_per_tile_id.get(&tile_id) { + let (label, user_named) = if let Some(container_blueprint) = + tab_viewer.viewport_blueprint.container(container_id) + { + ( + container_blueprint + .display_name_or_default() + .as_ref() + .into(), + container_blueprint.display_name.is_some(), + ) + } else { + re_log::warn_once!("Container {container_id} missing during egui_tiles"); + ( + tab_viewer.ctx.re_ui.error_text("Internal error").into(), + false, + ) + }; + TabDesc { - label: format!("{:?}", container.kind()).into(), - user_named: false, + label, + user_named, icon: icon_for_container_kind(&container.kind()), item: Some(Item::Container(*container_id)), } diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 1a621b073e92..fa94be5932af 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -12,15 +12,15 @@ use re_query::query_archetype; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::ViewerRecommendationHash; use re_viewer_context::{ - ContainerId, Item, SpaceViewClassIdentifier, SpaceViewId, SpaceViewSpawnHeuristics, - ViewerContext, + blueprint_id_to_tile_id, ContainerId, Contents, Item, SpaceViewClassIdentifier, SpaceViewId, + SpaceViewSpawnHeuristics, ViewerContext, }; use crate::{ blueprint::components::{ AutoLayout, AutoSpaceViews, IncludedSpaceView, RootContainer, SpaceViewMaximized, }, - container::{blueprint_id_to_tile_id, ContainerBlueprint, Contents}, + container::ContainerBlueprint, viewport::TreeAction, VIEWPORT_PATH, }; diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 2a726ce80922..05973962d86b 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -6,22 +6,22 @@ use smallvec::SmallVec; use re_entity_db::InstancePath; use re_log_types::EntityPath; use re_log_types::EntityPathRule; -use re_space_view::{SpaceViewBlueprint, SpaceViewName}; +use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::Visible; use re_ui::{drag_and_drop::DropTarget, list_item::ListItem, ReUi}; -use re_viewer_context::{CollapseScope, DataResultTree}; +use re_viewer_context::{CollapseScope, Contents, ContentsName, DataResultTree}; use re_viewer_context::{ ContainerId, DataQueryResult, DataResultNode, HoverHighlight, Item, SpaceViewId, ViewerContext, }; use crate::context_menu::context_menu_ui_for_item; -use crate::{container::Contents, SelectionUpdateBehavior, Viewport}; +use crate::{SelectionUpdateBehavior, Viewport}; /// The style to use for displaying this space view name in the UI. -pub fn space_view_name_style(name: &SpaceViewName) -> re_ui::LabelStyle { +pub fn contents_name_style(name: &ContentsName) -> re_ui::LabelStyle { match name { - SpaceViewName::Named(_) => re_ui::LabelStyle::Normal, - SpaceViewName::Placeholder(_) => re_ui::LabelStyle::Unnamed, + ContentsName::Named(_) => re_ui::LabelStyle::Normal, + ContentsName::Placeholder(_) => re_ui::LabelStyle::Unnamed, } } @@ -263,19 +263,18 @@ impl Viewport<'_, '_> { }; let item = Item::Container(container_id); - - let item_response = ListItem::new( - ctx.re_ui, - format!("Viewport ({:?})", container_blueprint.container_kind), - ) - .selected(ctx.selection().contains_item(&item)) - .draggable(false) - .drop_target_style(self.state.is_candidate_drop_parent_container(&container_id)) - .label_style(re_ui::LabelStyle::Unnamed) - .with_icon(crate::icon_for_container_kind( - &container_blueprint.container_kind, - )) - .show_flat(ui); + let container_name = container_blueprint.display_name_or_default(); + + let item_response = + ListItem::new(ctx.re_ui, format!("Viewport ({})", container_name.as_ref())) + .selected(ctx.selection().contains_item(&item)) + .draggable(false) + .drop_target_style(self.state.is_candidate_drop_parent_container(&container_id)) + .label_style(contents_name_style(&container_name)) + .with_icon(crate::icon_for_container_kind( + &container_blueprint.container_kind, + )) + .show_flat(ui); for child in &container_blueprint.contents { self.contents_ui(ctx, ui, child, true); @@ -318,42 +317,41 @@ impl Viewport<'_, '_> { let default_open = true; + let container_name = container_blueprint.display_name_or_default(); + let re_ui::list_item::ShowCollapsingResponse { item_response: response, body_response, - } = ListItem::new( - ctx.re_ui, - format!("{:?}", container_blueprint.container_kind), - ) - .subdued(!container_visible) - .selected(ctx.selection().contains_item(&item)) - .draggable(true) - .drop_target_style(self.state.is_candidate_drop_parent_container(container_id)) - .label_style(re_ui::LabelStyle::Unnamed) - .with_icon(crate::icon_for_container_kind( - &container_blueprint.container_kind, - )) - .with_buttons(|re_ui, ui| { - let vis_response = visibility_button_ui(re_ui, ui, parent_visible, &mut visible); - - let remove_response = remove_button_ui(re_ui, ui, "Remove container"); - if remove_response.clicked() { - self.blueprint.mark_user_interaction(ctx); - self.blueprint.remove_contents(content); - } + } = ListItem::new(ctx.re_ui, container_name.as_ref()) + .subdued(!container_visible) + .selected(ctx.selection().contains_item(&item)) + .draggable(true) + .drop_target_style(self.state.is_candidate_drop_parent_container(container_id)) + .label_style(contents_name_style(&container_name)) + .with_icon(crate::icon_for_container_kind( + &container_blueprint.container_kind, + )) + .with_buttons(|re_ui, ui| { + let vis_response = visibility_button_ui(re_ui, ui, parent_visible, &mut visible); - remove_response | vis_response - }) - .show_hierarchical_with_content( - ui, - CollapseScope::BlueprintTree.container(*container_id), - default_open, - |_, ui| { - for child in &container_blueprint.contents { - self.contents_ui(ctx, ui, child, container_visible); + let remove_response = remove_button_ui(re_ui, ui, "Remove container"); + if remove_response.clicked() { + self.blueprint.mark_user_interaction(ctx); + self.blueprint.remove_contents(content); } - }, - ); + + remove_response | vis_response + }) + .show_hierarchical_with_content( + ui, + CollapseScope::BlueprintTree.container(*container_id), + default_open, + |_, ui| { + for child in &container_blueprint.contents { + self.contents_ui(ctx, ui, child, container_visible); + } + }, + ); context_menu_ui_for_item( ctx, @@ -411,7 +409,7 @@ impl Viewport<'_, '_> { item_response: mut response, body_response, } = ListItem::new(ctx.re_ui, space_view_name.as_ref()) - .label_style(space_view_name_style(&space_view_name)) + .label_style(contents_name_style(&space_view_name)) .with_icon(space_view.class(ctx.space_view_class_registry).icon()) .selected(ctx.selection().contains_item(&item)) .draggable(true) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 4979406f4d87..d7093311a19f 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -126,6 +126,7 @@ def __init__( row_shares: Optional[RowShareArrayLike] = None, grid_columns: Optional[int] = None, active_tab: Optional[int | str] = None, + name: Utf8Like | None, ): """ Construct a new container. @@ -152,6 +153,8 @@ def __init__( The number of columns in the grid. This is only applicable to `Grid` containers. active_tab The active tab in the container. This is only applicable to `Tabs` containers. + name + The name of the container """ @@ -169,6 +172,7 @@ def __init__( self.row_shares = row_shares self.grid_columns = grid_columns self.active_tab = active_tab + self.name = name def blueprint_path(self) -> str: """ @@ -207,6 +211,7 @@ def _log_to_stream(self, stream: RecordingStream) -> None: visible=True, grid_columns=self.grid_columns, active_tab=active_tab_path, + display_name=self.name, ) stream.log(self.blueprint_path(), arch) # type: ignore[attr-defined] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/containers.py b/rerun_py/rerun_sdk/rerun/blueprint/containers.py index b54a509ed36a..dc0f14b4ac31 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/containers.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/containers.py @@ -2,6 +2,7 @@ from typing import Iterable, Optional +from ..datatypes import Utf8Like from .api import Container, SpaceView from .components import ColumnShareArrayLike, RowShareArrayLike from .components.container_kind import ContainerKind @@ -15,6 +16,7 @@ def __init__( *args: Container | SpaceView, contents: Optional[Iterable[Container | SpaceView]] = None, column_shares: Optional[ColumnShareArrayLike] = None, + name: Utf8Like | None = None, ): """ Construct a new horizontal container. @@ -29,9 +31,13 @@ def __init__( column_shares The layout shares of the columns in the container. The share is used to determine what fraction of the total width each column should take up. The column with index `i` will take up the fraction `shares[i] / total_shares`. + name + The name of the container """ - super().__init__(*args, contents=contents, kind=ContainerKind.Horizontal, column_shares=column_shares) + super().__init__( + *args, contents=contents, kind=ContainerKind.Horizontal, column_shares=column_shares, name=name + ) class Vertical(Container): @@ -42,6 +48,7 @@ def __init__( *args: Container | SpaceView, contents: Optional[Iterable[Container | SpaceView]] = None, row_shares: Optional[RowShareArrayLike] = None, + name: Utf8Like | None = None, ): """ Construct a new vertical container. @@ -56,9 +63,11 @@ def __init__( row_shares The layout shares of the rows in the container. The share is used to determine what fraction of the total height each row should take up. The row with index `i` will take up the fraction `shares[i] / total_shares`. + name + The name of the container """ - super().__init__(*args, contents=contents, kind=ContainerKind.Vertical, row_shares=row_shares) + super().__init__(*args, contents=contents, kind=ContainerKind.Vertical, row_shares=row_shares, name=name) class Grid(Container): @@ -71,6 +80,7 @@ def __init__( column_shares: Optional[ColumnShareArrayLike] = None, row_shares: Optional[RowShareArrayLike] = None, grid_columns: Optional[int] = None, + name: Utf8Like | None = None, ): """ Construct a new grid container. @@ -90,6 +100,8 @@ def __init__( row should take up. The row with index `i` will take up the fraction `shares[i] / total_shares`. grid_columns The number of columns in the grid. + name + The name of the container """ super().__init__( @@ -99,6 +111,7 @@ def __init__( column_shares=column_shares, row_shares=row_shares, grid_columns=grid_columns, + name=name, ) @@ -110,6 +123,7 @@ def __init__( *args: Container | SpaceView, contents: Optional[Iterable[Container | SpaceView]] = None, active_tab: Optional[int | str] = None, + name: Utf8Like | None = None, ): """ Construct a new tab container. @@ -123,6 +137,8 @@ def __init__( This can only be used if no positional arguments are provided. active_tab: The index or name of the active tab. + name + The name of the container """ - super().__init__(*args, contents=contents, kind=ContainerKind.Tabs, active_tab=active_tab) + super().__init__(*args, contents=contents, kind=ContainerKind.Tabs, active_tab=active_tab, name=name) From b10ed163c80baf8b1b4ff7c7a7daa732614292d3 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 21 Mar 2024 16:44:05 -0400 Subject: [PATCH 099/508] Avoid warning on win/mac by not making the blueprint stream thread-local (#5638) ### What Enabling thread_local for the blueprint was causing a warning on windows/mac, that in turn would cause our e2e tests to fail. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5638/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5638/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5638/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5638) - [Docs preview](https://rerun.io/preview/5806a292e7bea8543d44cb161edeea9a72c48b9a/docs) - [Examples preview](https://rerun.io/preview/5806a292e7bea8543d44cb161edeea9a72c48b9a/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- rerun_py/rerun_sdk/rerun/blueprint/api.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index d7093311a19f..49e0db70c8cb 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -478,9 +478,15 @@ def create_in_memory_blueprint(*, application_id: str, blueprint: BlueprintLike) # Convert the BlueprintLike to a full blueprint blueprint = blueprint.to_blueprint() + # We only use this stream object directly, so don't need to make it + # default or thread default. Making it the thread-default will also + # lead to an unnecessary warning on mac/win. blueprint_stream = RecordingStream( bindings.new_blueprint( application_id=application_id, + make_default=False, + make_thread_default=False, + default_enabled=True, ) ) From 7bfe1bd3b97b8ac65db32babb8bf14ecca4a1777 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 22 Mar 2024 10:21:19 +0100 Subject: [PATCH 100/508] Add blueprint to Signed Distance Fields example (#5635) ### What Also replace the somewhat broken screenshot it had (thumbnail was alright) ![image](https://github.com/rerun-io/rerun/assets/1220815/1496c03b-a4d8-4e38-8e9d-075e0da9fc75) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5635/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5635/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5635/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5635) - [Docs preview](https://rerun.io/preview/8bd47c05b89f3eefd1fda0e4a9564799b8c5a76d/docs) - [Examples preview](https://rerun.io/preview/8bd47c05b89f3eefd1fda0e4a9564799b8c5a76d/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/signed_distance_fields/README.md | 11 +++++------ examples/python/signed_distance_fields/main.py | 16 +++++++++++++++- scripts/ci/thumbnails.py | 6 ++++-- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/examples/python/signed_distance_fields/README.md b/examples/python/signed_distance_fields/README.md index 9c3a04786293..977eff806012 100644 --- a/examples/python/signed_distance_fields/README.md +++ b/examples/python/signed_distance_fields/README.md @@ -5,13 +5,12 @@ thumbnail = "https://static.rerun.io/signed-distance-fields/0b0a200e0a5ec2b16e5f thumbnail_dimensions = [480, 480] --> - - - - - - Signed Distance Fields example screenshot + Signed Distance Fields example screenshot + + + + Generate Signed Distance Fields for arbitrary meshes using both traditional methods and the one described in the [DeepSDF paper](https://arxiv.org/abs/1901.05103), and visualize the results using the Rerun SDK. diff --git a/examples/python/signed_distance_fields/main.py b/examples/python/signed_distance_fields/main.py index 9a78cbabfc80..e2669fcfd608 100755 --- a/examples/python/signed_distance_fields/main.py +++ b/examples/python/signed_distance_fields/main.py @@ -37,6 +37,7 @@ import numpy as np import numpy.typing as npt import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb import trimesh from download_dataset import AVAILABLE_MESHES, ensure_mesh_downloaded from trimesh import Trimesh @@ -194,7 +195,20 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_signed_distance_fields") + rr.script_setup( + args, + "rerun_example_signed_distance_fields", + blueprint=rrb.Horizontal( + rrb.Vertical( + rrb.Horizontal( + rrb.Spatial3DView(name="Input Mesh", origin="/world/mesh"), + rrb.TensorView(name="SDF", origin="/tensor"), + ), + rrb.TextLogView(name="Execution Log"), + ), + rrb.Spatial3DView(name="Distance Field Samples", origin="/world/sdf"), + ), + ) mesh_path = args.mesh_path if mesh_path is None: diff --git a/scripts/ci/thumbnails.py b/scripts/ci/thumbnails.py index 53a8c247d7e7..968a9d5676de 100755 --- a/scripts/ci/thumbnails.py +++ b/scripts/ci/thumbnails.py @@ -34,7 +34,7 @@ def examples_with_thumbnails() -> Generator[Example, None, None]: def single_language(lang: str) -> Generator[Example, None, None]: for path in Path(f"examples/{lang}").iterdir(): if (path / "README.md").exists(): - readme = (path / "README.md").read_text() + readme = (path / "README.md").read_text(encoding="utf-8") fm = load_frontmatter(readme) if fm is not None and fm.get("thumbnail"): yield Example(path, readme, fm) @@ -64,7 +64,9 @@ def work(example: Example): assert end != -1 (example.path / "README.md").write_text( - example.readme[:start] + f"thumbnail_dimensions = [{width}, {height}]" + example.readme[end:] + example.readme[:start] + f"thumbnail_dimensions = [{width}, {height}]" + example.readme[end:], + encoding="utf-8", + newline="\n", ) print(f"✔ {example.path}") From 9c34d72ad924957b5fe3e83ea5e1a4ea601cd6b4 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 22 Mar 2024 10:23:18 +0100 Subject: [PATCH 101/508] Remove unstable notes from blueprint type docs, some minor cleanup (#5625) ### What * Fixes #5527 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5625/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5625/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5625/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5625) - [Docs preview](https://rerun.io/preview/861e0663ce88cdf222b06931252274ed71a54d48/docs) - [Examples preview](https://rerun.io/preview/861e0663ce88cdf222b06931252274ed71a54d48/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../components/entity_properties_component.rs | 2 -- .../archetypes/space_view_contents.fbs | 9 ++++-- .../archetypes/viewport_blueprint.fbs | 18 ++++++------ .../blueprint/components/auto_layout.fbs | 2 -- .../blueprint/components/auto_space_views.fbs | 2 -- .../components/background_3d_kind.fbs | 2 +- .../entity_properties_component.fbs | 2 -- .../components/included_space_view.fbs | 4 +-- .../blueprint/components/query_expression.fbs | 2 -- .../components/space_view_maximized.fbs | 2 -- .../components/visible_time_range.fbs | 2 +- .../archetypes/space_view_contents.rs | 9 ++++-- .../blueprint/components/background3d_kind.rs | 2 +- .../blueprint/components/query_expression.rs | 2 -- .../components/visible_time_range.rs | 2 +- .../archetypes/viewport_blueprint.rs | 14 +++++----- .../src/blueprint/components/auto_layout.rs | 2 -- .../blueprint/components/auto_space_views.rs | 2 -- .../components/included_space_view.rs | 4 +-- .../components/space_view_maximized.rs | 2 -- .../archetypes/space_view_contents.hpp | 9 ++++-- .../archetypes/viewport_blueprint.hpp | 28 +++++++++---------- .../blueprint/components/auto_layout.hpp | 2 -- .../blueprint/components/auto_space_views.hpp | 2 -- .../components/background3d_kind.hpp | 2 +- .../entity_properties_component.hpp | 2 -- .../components/included_space_view.hpp | 4 +-- .../blueprint/components/query_expression.hpp | 2 -- .../components/space_view_maximized.hpp | 2 -- .../components/visible_time_range.hpp | 2 +- .../archetypes/space_view_contents.py | 9 ++++-- .../archetypes/viewport_blueprint.py | 28 +++++++++---------- .../rerun/blueprint/components/auto_layout.py | 6 +--- .../blueprint/components/auto_space_views.py | 6 +--- .../blueprint/components/background3d_kind.py | 2 +- .../components/entity_properties_component.py | 6 +--- .../components/included_space_view.py | 6 +--- .../blueprint/components/query_expression.py | 2 -- .../components/space_view_maximized.py | 6 +--- .../components/visible_time_range.py | 2 +- 40 files changed, 88 insertions(+), 126 deletions(-) diff --git a/crates/re_entity_db/src/blueprint/components/entity_properties_component.rs b/crates/re_entity_db/src/blueprint/components/entity_properties_component.rs index b3c83651162a..0e615a7128ae 100644 --- a/crates/re_entity_db/src/blueprint/components/entity_properties_component.rs +++ b/crates/re_entity_db/src/blueprint/components/entity_properties_component.rs @@ -22,8 +22,6 @@ use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: The configurable set of overridable properties. -/// -/// Unstable. Used for the ongoing blueprint experimentations. #[derive(Clone)] pub struct EntityPropertiesComponent(pub crate::EntityProperties); diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/space_view_contents.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/space_view_contents.fbs index 95250bf0558b..fc2938de4a97 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/space_view_contents.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/space_view_contents.fbs @@ -21,6 +21,13 @@ namespace rerun.blueprint.archetypes; /// If there are multiple rules of the same specificity, the last one wins. /// If no rules match, the path is excluded. /// +/// Specifying a path without a `+` or `-` prefix is equivalent to `+`: +/// ```diff +/// /world/** # add everything… +/// - /world/roads/** # …but remove all roads… +/// /world/roads/main # …but show main road +/// ``` +/// /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. @@ -38,8 +45,6 @@ namespace rerun.blueprint.archetypes; /// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. /// The last rule matching `/world` is `- /world`, so it is excluded. /// The last rule matching `/world/house` is `+ /world/**`, so it is included. -/// -/// Unstable. Used for the ongoing blueprint experimentations. table SpaceViewContents ( "attr.rerun.scope": "blueprint", "attr.rust.derive": "Default" diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs index b87721d45262..66565cf2a609 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs @@ -25,7 +25,7 @@ table ViewportBlueprint ( /// Show one tab as maximized? maximized: rerun.blueprint.components.SpaceViewMaximized ("attr.rerun.component_optional", nullable, order: 3000); - // TODO(andreas): This is to be removed in the future, all new Space Views without an explicit container + // TODO(andreas): This is to be removed in the future, all new space views without an explicit container // should always insert themselves using a heuristic. /// Whether the viewport layout is determined automatically. /// @@ -33,19 +33,19 @@ table ViewportBlueprint ( /// This defaults to `false` and is automatically set to `false` when there is user determined layout. auto_layout: rerun.blueprint.components.AutoLayout ("attr.rerun.component_optional", nullable, order: 4000); - // TODO(jleibs): This should come with an optional container id that specifies where to insert new Space Views. - /// Whether or not Space Views should be created automatically. + // TODO(jleibs): This should come with an optional container id that specifies where to insert new space views. + /// Whether or not space views should be created automatically. /// - /// If `true`, the viewer will only add Space Views that it hasn't considered previously (as identified by `past_viewer_recommendations`) - /// and which aren't deemed redundant to existing Space Views. - /// This defaults to `false` and is automatically set to `false` when the user adds Space Views manually in the viewer. + /// If `true`, the viewer will only add space views that it hasn't considered previously (as identified by `past_viewer_recommendations`) + /// and which aren't deemed redundant to existing space views. + /// This defaults to `false` and is automatically set to `false` when the user adds space views manually in the viewer. auto_space_views: rerun.blueprint.components.AutoSpaceViews ("attr.rerun.component_optional", nullable, order: 5000); - /// Hashes of all recommended Space Views the viewer has already added and that should not be added again. + /// Hashes of all recommended space 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 Space Views, you should set `auto_space_views` to `false`. + /// If you want the viewer from stopping to add space views, you should set `auto_space_views` to `false`. /// - /// The viewer uses this to determine whether it should keep adding Space Views. + /// The viewer uses this to determine whether it should keep adding space views. past_viewer_recommendations: [rerun.blueprint.components.ViewerRecommendationHash] ("attr.rerun.component_optional", nullable, order: 6000); } diff --git a/crates/re_types/definitions/rerun/blueprint/components/auto_layout.fbs b/crates/re_types/definitions/rerun/blueprint/components/auto_layout.fbs index 4e4f37f588c3..3a7497584889 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/auto_layout.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/auto_layout.fbs @@ -10,8 +10,6 @@ namespace rerun.blueprint.components; // --- /// Whether the viewport layout is determined automatically. -/// -/// Unstable. Used for the ongoing blueprint experimentations. struct AutoLayout ( "attr.arrow.transparent", "attr.rerun.scope": "blueprint", diff --git a/crates/re_types/definitions/rerun/blueprint/components/auto_space_views.fbs b/crates/re_types/definitions/rerun/blueprint/components/auto_space_views.fbs index e50ce3284672..343995d83e25 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/auto_space_views.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/auto_space_views.fbs @@ -10,8 +10,6 @@ namespace rerun.blueprint.components; // --- /// Whether or not space views should be created automatically. -/// -/// Unstable. Used for the ongoing blueprint experimentations. struct AutoSpaceViews ( "attr.arrow.transparent", "attr.rerun.scope": "blueprint", diff --git a/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs b/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs index 092a71bf0b5c..f8879516c473 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs @@ -8,7 +8,7 @@ include "rerun/attributes.fbs"; namespace rerun.blueprint.components; -/// The type of the background in 3D Space Views. +/// The type of the background in 3D space views. enum Background3DKind: byte ( "attr.rerun.scope": "blueprint", "attr.docs.unreleased" diff --git a/crates/re_types/definitions/rerun/blueprint/components/entity_properties_component.fbs b/crates/re_types/definitions/rerun/blueprint/components/entity_properties_component.fbs index 33eddc492092..0be4a4e5d601 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/entity_properties_component.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/entity_properties_component.fbs @@ -10,8 +10,6 @@ namespace rerun.blueprint.components; // --- /// The configurable set of overridable properties. -/// -/// Unstable. Used for the ongoing blueprint experimentations. table EntityPropertiesComponent ( "attr.rerun.scope": "blueprint", "attr.rust.derive_only": "Clone", diff --git a/crates/re_types/definitions/rerun/blueprint/components/included_space_view.fbs b/crates/re_types/definitions/rerun/blueprint/components/included_space_view.fbs index 9cc09dae54e7..340f01da2ec0 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/included_space_view.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/included_space_view.fbs @@ -10,9 +10,7 @@ namespace rerun.blueprint.components; // --- -/// The id of a `SpaceView`. -/// -/// Unstable. Used for the ongoing blueprint experimentations. +/// The unique id of a space view, used to refer to views in containers. table IncludedSpaceView ( "attr.rerun.scope": "blueprint", "attr.python.aliases": "npt.NDArray[np.uint8], npt.ArrayLike, Sequence[int], bytes", diff --git a/crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs b/crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs index 12efe195ed8c..dfcd8c9bfad2 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/query_expression.fbs @@ -18,8 +18,6 @@ namespace rerun.blueprint.components; /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. -/// -/// Unstable. Used for the ongoing blueprint experimentations. table QueryExpression ( "attr.rerun.scope": "blueprint", "attr.arrow.transparent", diff --git a/crates/re_types/definitions/rerun/blueprint/components/space_view_maximized.fbs b/crates/re_types/definitions/rerun/blueprint/components/space_view_maximized.fbs index cb7737517ed4..20334d0703a3 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/space_view_maximized.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/space_view_maximized.fbs @@ -10,8 +10,6 @@ namespace rerun.blueprint.components; // --- /// Whether a space view is maximized. -/// -/// Unstable. Used for the ongoing blueprint experimentations. table SpaceViewMaximized ( "attr.rerun.scope": "blueprint", "attr.python.aliases": "npt.NDArray[np.uint8], npt.ArrayLike, Sequence[int], bytes", diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs index 7e71f15c0d08..af8c5262bdd2 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs @@ -9,7 +9,7 @@ namespace rerun.blueprint.components; // --- -/// The range of values that will be included in a Space View query. +/// The range of values that will be included in a space view query. table VisibleTimeRange ( "attr.arrow.transparent", "attr.rerun.scope": "blueprint", diff --git a/crates/re_types/src/blueprint/archetypes/space_view_contents.rs b/crates/re_types/src/blueprint/archetypes/space_view_contents.rs index d2bae9513ae3..1fee7d521ac2 100644 --- a/crates/re_types/src/blueprint/archetypes/space_view_contents.rs +++ b/crates/re_types/src/blueprint/archetypes/space_view_contents.rs @@ -35,6 +35,13 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// If there are multiple rules of the same specificity, the last one wins. /// If no rules match, the path is excluded. /// +/// Specifying a path without a `+` or `-` prefix is equivalent to `+`: +/// ```diff +/// /world/** # add everything… +/// - /world/roads/** # …but remove all roads… +/// /world/roads/main # …but show main road +/// ``` +/// /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. @@ -52,8 +59,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. /// The last rule matching `/world` is `- /world`, so it is excluded. /// The last rule matching `/world/house` is `+ /world/**`, so it is included. -/// -/// Unstable. Used for the ongoing blueprint experimentations. #[derive(Clone, Debug, Default)] pub struct SpaceViewContents { /// The `QueryExpression` that populates the contents for the `SpaceView`. diff --git a/crates/re_types/src/blueprint/components/background3d_kind.rs b/crates/re_types/src/blueprint/components/background3d_kind.rs index f2bae7c2de6f..51422cc0bb62 100644 --- a/crates/re_types/src/blueprint/components/background3d_kind.rs +++ b/crates/re_types/src/blueprint/components/background3d_kind.rs @@ -21,7 +21,7 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Component**: The type of the background in 3D Space Views. +/// **Component**: The type of the background in 3D space views. #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] pub enum Background3DKind { /// Gradient depending on the direction of the view, dark theme. diff --git a/crates/re_types/src/blueprint/components/query_expression.rs b/crates/re_types/src/blueprint/components/query_expression.rs index fb0dddbec79c..70c53a35521e 100644 --- a/crates/re_types/src/blueprint/components/query_expression.rs +++ b/crates/re_types/src/blueprint/components/query_expression.rs @@ -31,8 +31,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. -/// -/// Unstable. Used for the ongoing blueprint experimentations. #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct QueryExpression(pub crate::datatypes::Utf8); diff --git a/crates/re_types/src/blueprint/components/visible_time_range.rs b/crates/re_types/src/blueprint/components/visible_time_range.rs index 053681357c0c..42ab941670c2 100644 --- a/crates/re_types/src/blueprint/components/visible_time_range.rs +++ b/crates/re_types/src/blueprint/components/visible_time_range.rs @@ -21,7 +21,7 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Component**: The range of values that will be included in a Space View query. +/// **Component**: The range of values that will be included in a space view query. #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] pub struct VisibleTimeRange(pub crate::blueprint::datatypes::VisibleTimeRange); diff --git a/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs b/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs index 1773aae2afe9..2551f2fcd98f 100644 --- a/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs +++ b/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs @@ -39,19 +39,19 @@ pub struct ViewportBlueprint { /// This defaults to `false` and is automatically set to `false` when there is user determined layout. pub auto_layout: Option, - /// Whether or not Space Views should be created automatically. + /// Whether or not space views should be created automatically. /// - /// If `true`, the viewer will only add Space Views that it hasn't considered previously (as identified by `past_viewer_recommendations`) - /// and which aren't deemed redundant to existing Space Views. - /// This defaults to `false` and is automatically set to `false` when the user adds Space Views manually in the viewer. + /// If `true`, the viewer will only add space views that it hasn't considered previously (as identified by `past_viewer_recommendations`) + /// and which aren't deemed redundant to existing space views. + /// This defaults to `false` and is automatically set to `false` when the user adds space views manually in the viewer. pub auto_space_views: Option, - /// Hashes of all recommended Space Views the viewer has already added and that should not be added again. + /// Hashes of all recommended space 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 Space Views, you should set `auto_space_views` to `false`. + /// If you want the viewer from stopping to add space views, you should set `auto_space_views` to `false`. /// - /// The viewer uses this to determine whether it should keep adding Space Views. + /// The viewer uses this to determine whether it should keep adding space views. pub past_viewer_recommendations: Option>, } diff --git a/crates/re_viewport/src/blueprint/components/auto_layout.rs b/crates/re_viewport/src/blueprint/components/auto_layout.rs index cef2d3d17d3a..5f6f507f243d 100644 --- a/crates/re_viewport/src/blueprint/components/auto_layout.rs +++ b/crates/re_viewport/src/blueprint/components/auto_layout.rs @@ -22,8 +22,6 @@ use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Whether the viewport layout is determined automatically. -/// -/// Unstable. Used for the ongoing blueprint experimentations. #[derive(Clone, Debug, Copy)] #[repr(transparent)] pub struct AutoLayout(pub bool); diff --git a/crates/re_viewport/src/blueprint/components/auto_space_views.rs b/crates/re_viewport/src/blueprint/components/auto_space_views.rs index 9b147d84ffe0..14b338b98974 100644 --- a/crates/re_viewport/src/blueprint/components/auto_space_views.rs +++ b/crates/re_viewport/src/blueprint/components/auto_space_views.rs @@ -22,8 +22,6 @@ use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Whether or not space views should be created automatically. -/// -/// Unstable. Used for the ongoing blueprint experimentations. #[derive(Clone, Debug, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] pub struct AutoSpaceViews(pub bool); diff --git a/crates/re_viewport/src/blueprint/components/included_space_view.rs b/crates/re_viewport/src/blueprint/components/included_space_view.rs index b496455b791f..3b781777c50e 100644 --- a/crates/re_viewport/src/blueprint/components/included_space_view.rs +++ b/crates/re_viewport/src/blueprint/components/included_space_view.rs @@ -21,9 +21,7 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Component**: The id of a `SpaceView`. -/// -/// Unstable. Used for the ongoing blueprint experimentations. +/// **Component**: The unique id of a space view, used to refer to views in containers. #[derive(Clone, Debug, Default)] #[repr(transparent)] pub struct IncludedSpaceView(pub crate::datatypes::Uuid); diff --git a/crates/re_viewport/src/blueprint/components/space_view_maximized.rs b/crates/re_viewport/src/blueprint/components/space_view_maximized.rs index 21258e36d64c..cd1fb6e5b7e6 100644 --- a/crates/re_viewport/src/blueprint/components/space_view_maximized.rs +++ b/crates/re_viewport/src/blueprint/components/space_view_maximized.rs @@ -22,8 +22,6 @@ use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Whether a space view is maximized. -/// -/// Unstable. Used for the ongoing blueprint experimentations. #[derive(Clone, Debug, Default)] #[repr(transparent)] pub struct SpaceViewMaximized(pub crate::datatypes::Uuid); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp index 53ffc874c3d6..fbbee2e116fd 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp @@ -28,6 +28,13 @@ namespace rerun::blueprint::archetypes { /// If there are multiple rules of the same specificity, the last one wins. /// If no rules match, the path is excluded. /// + /// Specifying a path without a `+` or `-` prefix is equivalent to `+`: + /// ```diff + /// /world/** # add everything… + /// - /world/roads/** # …but remove all roads… + /// /world/roads/main # …but show main road + /// ``` + /// /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. @@ -45,8 +52,6 @@ namespace rerun::blueprint::archetypes { /// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. /// The last rule matching `/world` is `- /world`, so it is excluded. /// The last rule matching `/world/house` is `+ /world/**`, so it is included. - /// - /// Unstable. Used for the ongoing blueprint experimentations. struct SpaceViewContents { /// The `QueryExpression` that populates the contents for the `SpaceView`. /// diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp index fff310ce9a58..5420e0e6b680 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp @@ -38,19 +38,19 @@ namespace rerun::blueprint::archetypes { /// This defaults to `false` and is automatically set to `false` when there is user determined layout. std::optional auto_layout; - /// Whether or not Space Views should be created automatically. + /// Whether or not space views should be created automatically. /// - /// If `true`, the viewer will only add Space Views that it hasn't considered previously (as identified by `past_viewer_recommendations`) - /// and which aren't deemed redundant to existing Space Views. - /// This defaults to `false` and is automatically set to `false` when the user adds Space Views manually in the viewer. + /// If `true`, the viewer will only add space views that it hasn't considered previously (as identified by `past_viewer_recommendations`) + /// and which aren't deemed redundant to existing space views. + /// This defaults to `false` and is automatically set to `false` when the user adds space views manually in the viewer. std::optional auto_space_views; - /// Hashes of all recommended Space Views the viewer has already added and that should not be added again. + /// Hashes of all recommended space 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 Space Views, you should set `auto_space_views` to `false`. + /// If you want the viewer from stopping to add space views, you should set `auto_space_views` to `false`. /// - /// The viewer uses this to determine whether it should keep adding Space Views. + /// The viewer uses this to determine whether it should keep adding space views. std::optional> past_viewer_recommendations; @@ -102,11 +102,11 @@ namespace rerun::blueprint::archetypes { RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - /// Whether or not Space Views should be created automatically. + /// Whether or not space views should be created automatically. /// - /// If `true`, the viewer will only add Space Views that it hasn't considered previously (as identified by `past_viewer_recommendations`) - /// and which aren't deemed redundant to existing Space Views. - /// This defaults to `false` and is automatically set to `false` when the user adds Space Views manually in the viewer. + /// If `true`, the viewer will only add space views that it hasn't considered previously (as identified by `past_viewer_recommendations`) + /// and which aren't deemed redundant to existing space views. + /// This defaults to `false` and is automatically set to `false` when the user adds space views manually in the viewer. ViewportBlueprint with_auto_space_views( rerun::blueprint::components::AutoSpaceViews _auto_space_views ) && { @@ -115,12 +115,12 @@ namespace rerun::blueprint::archetypes { RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - /// Hashes of all recommended Space Views the viewer has already added and that should not be added again. + /// Hashes of all recommended space 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 Space Views, you should set `auto_space_views` to `false`. + /// If you want the viewer from stopping to add space views, you should set `auto_space_views` to `false`. /// - /// The viewer uses this to determine whether it should keep adding Space Views. + /// The viewer uses this to determine whether it should keep adding space views. ViewportBlueprint with_past_viewer_recommendations( Collection _past_viewer_recommendations diff --git a/rerun_cpp/src/rerun/blueprint/components/auto_layout.hpp b/rerun_cpp/src/rerun/blueprint/components/auto_layout.hpp index 5d9536882109..1207069ff856 100644 --- a/rerun_cpp/src/rerun/blueprint/components/auto_layout.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/auto_layout.hpp @@ -16,8 +16,6 @@ namespace arrow { namespace rerun::blueprint::components { /// **Component**: Whether the viewport layout is determined automatically. - /// - /// Unstable. Used for the ongoing blueprint experimentations. struct AutoLayout { bool auto_layout; diff --git a/rerun_cpp/src/rerun/blueprint/components/auto_space_views.hpp b/rerun_cpp/src/rerun/blueprint/components/auto_space_views.hpp index c4e520a722f9..c28925ad2417 100644 --- a/rerun_cpp/src/rerun/blueprint/components/auto_space_views.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/auto_space_views.hpp @@ -16,8 +16,6 @@ namespace arrow { namespace rerun::blueprint::components { /// **Component**: Whether or not space views should be created automatically. - /// - /// Unstable. Used for the ongoing blueprint experimentations. struct AutoSpaceViews { bool auto_space_views; diff --git a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp index 17af1c8a3ea2..1989dc6c301a 100644 --- a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp @@ -15,7 +15,7 @@ namespace arrow { } // namespace arrow namespace rerun::blueprint::components { - /// **Component**: The type of the background in 3D Space Views. + /// **Component**: The type of the background in 3D space views. enum class Background3DKind : uint8_t { /// Gradient depending on the direction of the view, dark theme. diff --git a/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.hpp b/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.hpp index bf2af30ef06f..ba853d22dd07 100644 --- a/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/entity_properties_component.hpp @@ -18,8 +18,6 @@ namespace arrow { namespace rerun::blueprint::components { /// **Component**: The configurable set of overridable properties. - /// - /// Unstable. Used for the ongoing blueprint experimentations. struct EntityPropertiesComponent { rerun::Collection props; diff --git a/rerun_cpp/src/rerun/blueprint/components/included_space_view.hpp b/rerun_cpp/src/rerun/blueprint/components/included_space_view.hpp index b55cd76bc089..6e71dda7eaf7 100644 --- a/rerun_cpp/src/rerun/blueprint/components/included_space_view.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/included_space_view.hpp @@ -11,9 +11,7 @@ #include namespace rerun::blueprint::components { - /// **Component**: The id of a `SpaceView`. - /// - /// Unstable. Used for the ongoing blueprint experimentations. + /// **Component**: The unique id of a space view, used to refer to views in containers. struct IncludedSpaceView { rerun::datatypes::Uuid space_view_id; diff --git a/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp b/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp index 5d9042ab6dcd..26ce3c1f1315 100644 --- a/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/query_expression.hpp @@ -22,8 +22,6 @@ namespace rerun::blueprint::components { /// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively /// (`/world/**` matches both `/world` and `/world/car/driver`). /// Other uses of `*` are not (yet) supported. - /// - /// Unstable. Used for the ongoing blueprint experimentations. struct QueryExpression { rerun::datatypes::Utf8 filter; diff --git a/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.hpp b/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.hpp index 525a1323b604..f17ee0d645ea 100644 --- a/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/space_view_maximized.hpp @@ -12,8 +12,6 @@ namespace rerun::blueprint::components { /// **Component**: Whether a space view is maximized. - /// - /// Unstable. Used for the ongoing blueprint experimentations. struct SpaceViewMaximized { rerun::datatypes::Uuid space_view_id; diff --git a/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp b/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp index f55840689b09..572ec3e8003a 100644 --- a/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp @@ -10,7 +10,7 @@ #include namespace rerun::blueprint::components { - /// **Component**: The range of values that will be included in a Space View query. + /// **Component**: The range of values that will be included in a space view query. struct VisibleTimeRange { rerun::blueprint::datatypes::VisibleTimeRange value; diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/space_view_contents.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/space_view_contents.py index dd1ee215cc54..0f4a861853b9 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/space_view_contents.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/space_view_contents.py @@ -34,6 +34,13 @@ class SpaceViewContents(Archetype): If there are multiple rules of the same specificity, the last one wins. If no rules match, the path is excluded. + Specifying a path without a `+` or `-` prefix is equivalent to `+`: + ```diff + /world/** # add everything… + - /world/roads/** # …but remove all roads… + /world/roads/main # …but show main road + ``` + The `/**` suffix matches the whole subtree, i.e. self and any child, recursively (`/world/**` matches both `/world` and `/world/car/driver`). Other uses of `*` are not (yet) supported. @@ -51,8 +58,6 @@ class SpaceViewContents(Archetype): The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded. The last rule matching `/world` is `- /world`, so it is excluded. The last rule matching `/world/house` is `+ /world/**`, so it is included. - - Unstable. Used for the ongoing blueprint experimentations. """ def __init__(self: Any, query: datatypes.Utf8ArrayLike): 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 5e8a72a7b33b..db6198bddb8b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py @@ -48,18 +48,18 @@ def __init__( If `true`, the container layout will be reset whenever a new space view is added or removed. This defaults to `false` and is automatically set to `false` when there is user determined layout. auto_space_views: - Whether or not Space Views should be created automatically. + Whether or not space views should be created automatically. - If `true`, the viewer will only add Space Views that it hasn't considered previously (as identified by `past_viewer_recommendations`) - and which aren't deemed redundant to existing Space Views. - This defaults to `false` and is automatically set to `false` when the user adds Space Views manually in the viewer. + If `true`, the viewer will only add space views that it hasn't considered previously (as identified by `past_viewer_recommendations`) + and which aren't deemed redundant to existing space views. + This defaults to `false` and is automatically set to `false` when the user adds space views manually in the viewer. past_viewer_recommendations: - Hashes of all recommended Space Views the viewer has already added and that should not be added again. + Hashes of all recommended space 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 Space Views, you should set `auto_space_views` to `false`. + If you want the viewer from stopping to add space views, you should set `auto_space_views` to `false`. - The viewer uses this to determine whether it should keep adding Space Views. + The viewer uses this to determine whether it should keep adding space views. """ @@ -138,11 +138,11 @@ def _clear(cls) -> ViewportBlueprint: default=None, converter=blueprint_components.AutoSpaceViewsBatch._optional, # type: ignore[misc] ) - # Whether or not Space Views should be created automatically. + # Whether or not space views should be created automatically. # - # If `true`, the viewer will only add Space Views that it hasn't considered previously (as identified by `past_viewer_recommendations`) - # and which aren't deemed redundant to existing Space Views. - # This defaults to `false` and is automatically set to `false` when the user adds Space Views manually in the viewer. + # If `true`, the viewer will only add space views that it hasn't considered previously (as identified by `past_viewer_recommendations`) + # and which aren't deemed redundant to existing space views. + # This defaults to `false` and is automatically set to `false` when the user adds space views manually in the viewer. # # (Docstring intentionally commented out to hide this field from the docs) @@ -151,12 +151,12 @@ def _clear(cls) -> ViewportBlueprint: default=None, converter=blueprint_components.ViewerRecommendationHashBatch._optional, # type: ignore[misc] ) - # Hashes of all recommended Space Views the viewer has already added and that should not be added again. + # Hashes of all recommended space 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 Space Views, you should set `auto_space_views` to `false`. + # If you want the viewer from stopping to add space views, you should set `auto_space_views` to `false`. # - # The viewer uses this to determine whether it should keep adding Space Views. + # The viewer uses this to determine whether it should keep adding space views. # # (Docstring intentionally commented out to hide this field from the docs) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout.py b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout.py index 71e8613600a4..d3400a4a65e7 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout.py @@ -18,11 +18,7 @@ @define(init=False) class AutoLayout(AutoLayoutExt): - """ - **Component**: Whether the viewport layout is determined automatically. - - Unstable. Used for the ongoing blueprint experimentations. - """ + """**Component**: Whether the viewport layout is determined automatically.""" def __init__(self: Any, auto_layout: AutoLayoutLike): """Create a new instance of the AutoLayout component.""" diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views.py b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views.py index 1b12e156e2b9..f39878bc24ff 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views.py @@ -24,11 +24,7 @@ @define(init=False) class AutoSpaceViews(AutoSpaceViewsExt): - """ - **Component**: Whether or not space views should be created automatically. - - Unstable. Used for the ongoing blueprint experimentations. - """ + """**Component**: Whether or not space views should be created automatically.""" def __init__(self: Any, auto_space_views: AutoSpaceViewsLike): """Create a new instance of the AutoSpaceViews component.""" diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py b/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py index 89cb07f3035a..c37142f11140 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py @@ -24,7 +24,7 @@ class Background3DKind(Enum): - """**Component**: The type of the background in 3D Space Views.""" + """**Component**: The type of the background in 3D space views.""" GradientDark = 1 """Gradient depending on the direction of the view, dark theme.""" diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py b/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py index d49a21d80490..c8263bc611ae 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py @@ -28,11 +28,7 @@ @define(init=False) class EntityPropertiesComponent: - """ - **Component**: The configurable set of overridable properties. - - Unstable. Used for the ongoing blueprint experimentations. - """ + """**Component**: The configurable set of overridable properties.""" def __init__(self: Any, props: EntityPropertiesComponentLike): """Create a new instance of the EntityPropertiesComponent component.""" diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/included_space_view.py b/rerun_py/rerun_sdk/rerun/blueprint/components/included_space_view.py index 1f77f44fa770..11479a2788f7 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/included_space_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/included_space_view.py @@ -12,11 +12,7 @@ class IncludedSpaceView(datatypes.Uuid): - """ - **Component**: The id of a `SpaceView`. - - Unstable. Used for the ongoing blueprint experimentations. - """ + """**Component**: The unique id of a space view, used to refer to views in containers.""" # You can define your own __init__ function as a member of IncludedSpaceViewExt in included_space_view_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/query_expression.py b/rerun_py/rerun_sdk/rerun/blueprint/components/query_expression.py index ab9a59cfd592..9d6b437b6657 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/query_expression.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/query_expression.py @@ -23,8 +23,6 @@ class QueryExpression(datatypes.Utf8): The `/**` suffix matches the whole subtree, i.e. self and any child, recursively (`/world/**` matches both `/world` and `/world/car/driver`). Other uses of `*` are not (yet) supported. - - Unstable. Used for the ongoing blueprint experimentations. """ # You can define your own __init__ function as a member of QueryExpressionExt in query_expression_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/space_view_maximized.py b/rerun_py/rerun_sdk/rerun/blueprint/components/space_view_maximized.py index 5285f4897aa4..da51b5597ee1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/space_view_maximized.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/space_view_maximized.py @@ -12,11 +12,7 @@ class SpaceViewMaximized(datatypes.Uuid): - """ - **Component**: Whether a space view is maximized. - - Unstable. Used for the ongoing blueprint experimentations. - """ + """**Component**: Whether a space view is maximized.""" # You can define your own __init__ function as a member of SpaceViewMaximizedExt in space_view_maximized_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py index 7ffed4d09f56..21c45c02ac84 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py @@ -12,7 +12,7 @@ class VisibleTimeRange(blueprint_datatypes.VisibleTimeRange): - """**Component**: The range of values that will be included in a Space View query.""" + """**Component**: The range of values that will be included in a space view query.""" # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py From 980099f74a172b774b7d27ff0613670f5d0e93f3 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 22 Mar 2024 10:24:04 +0100 Subject: [PATCH 102/508] Fix web viewer crash on invalid url parameter (#5631) ### What Gracefully handle broken or missing urls for websocket connections. * Fixes #5405 image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5631/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5631/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5631/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5631) - [Docs preview](https://rerun.io/preview/077d99a586094d3ad1c6f7d240426d6a29e3d8db/docs) - [Examples preview](https://rerun.io/preview/077d99a586094d3ad1c6f7d240426d6a29e3d8db/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/web.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/crates/re_viewer/src/web.rs b/crates/re_viewer/src/web.rs index 3fade48b17d9..0a0008aa92a3 100644 --- a/crates/re_viewer/src/web.rs +++ b/crates/re_viewer/src/web.rs @@ -1,5 +1,6 @@ #![allow(clippy::mem_forget)] // False positives from #[wasm_bindgen] macro +use anyhow::Context as _; use eframe::wasm_bindgen::{self, prelude::*}; use std::ops::ControlFlow; @@ -90,7 +91,9 @@ impl WebHandle { return; }; let rx = url_to_receiver(url, app.re_ui.egui_ctx.clone()); - app.add_receiver(rx); + if let Some(rx) = rx.ok_or_log_error() { + app.add_receiver(rx); + } } #[wasm_bindgen] @@ -142,11 +145,15 @@ fn create_app( } if let Some(url) = url { - app.add_receiver(url_to_receiver(url, egui_ctx)); + if let Some(receiver) = url_to_receiver(url, egui_ctx).ok_or_log_error() { + app.add_receiver(receiver); + } } else { // NOTE: we support passing in multiple urls to multiple different recorording, blueprints, etc for url in query_map.get("url").into_iter().flatten() { - app.add_receiver(url_to_receiver(url, egui_ctx.clone())); + if let Some(receiver) = url_to_receiver(url, egui_ctx.clone()).ok_or_log_error() { + app.add_receiver(receiver); + } } } @@ -156,19 +163,19 @@ fn create_app( fn url_to_receiver( url: &str, egui_ctx: egui::Context, -) -> re_smart_channel::Receiver { +) -> anyhow::Result> { let ui_waker = Box::new(move || { // Spend a few more milliseconds decoding incoming messages, // then trigger a repaint (https://github.com/rerun-io/rerun/issues/963): egui_ctx.request_repaint_after(std::time::Duration::from_millis(10)); }); match categorize_uri(url) { - EndpointCategory::HttpRrd(url) => { + EndpointCategory::HttpRrd(url) => Ok( re_log_encoding::stream_rrd_from_http::stream_rrd_from_http_to_channel( url, Some(ui_waker), - ) - } + ), + ), EndpointCategory::WebEventListener => { // Process an rrd when it's posted via `window.postMessage` let (tx, rx) = re_smart_channel::smart_channel( @@ -200,10 +207,10 @@ fn url_to_receiver( } } })); - rx + Ok(rx) } EndpointCategory::WebSocket(url) => re_data_source::connect_to_ws_url(&url, Some(ui_waker)) - .unwrap_or_else(|err| panic!("Failed to connect to WebSocket server at {url}: {err}")), + .with_context(|| format!("Failed to connect to WebSocket server at {url}.")), } } From 404c1e023eef61e96ed097437a6fc06bc758aa7d Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 22 Mar 2024 10:25:09 +0100 Subject: [PATCH 103/508] Fix controlnet example for current `controlnet` package version and add blueprint (#5634) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What Again, this time the default view names were good enough, so didn't specify them. Example looks now like in the marketing material out of the box ✨ ![image](https://github.com/rerun-io/rerun/assets/1220815/2ac9a735-b9d8-4db7-b134-ca93f2247999) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5634/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5634/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5634/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5634) - [Docs preview](https://rerun.io/preview/03c6a4905631d445446c9041e1e72f44949d3d42/docs) - [Examples preview](https://rerun.io/preview/03c6a4905631d445446c9041e1e72f44949d3d42/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/controlnet/main.py | 34 ++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/examples/python/controlnet/main.py b/examples/python/controlnet/main.py index 53d6193d334f..8179fd43fa97 100755 --- a/examples/python/controlnet/main.py +++ b/examples/python/controlnet/main.py @@ -13,12 +13,14 @@ import argparse import os +from typing import Any import cv2 import numpy as np import PIL.Image import requests import rerun as rr +import rerun.blueprint as rrb import torch from diffusers import ( AutoencoderKL, @@ -30,16 +32,19 @@ def controlnet_callback( - iteration: int, timestep: float, latents: torch.Tensor, pipeline: StableDiffusionXLControlNetPipeline -) -> None: - rr.set_time_sequence("iteration", iteration) + pipe: StableDiffusionXLControlNetPipeline, step_index: int, timestep: float, callback_kwargs: dict[str, Any] +) -> dict[str, Any]: + rr.set_time_sequence("iteration", step_index) rr.set_time_seconds("timestep", timestep) + latents = callback_kwargs["latents"] - image = pipeline.vae.decode(latents / pipeline.vae.config.scaling_factor, return_dict=False)[0] - image = pipeline.image_processor.postprocess(image, output_type="np").squeeze() + image = pipe.vae.decode(latents / pipe.vae.config.scaling_factor, return_dict=False)[0] + image = pipe.image_processor.postprocess(image, output_type="np").squeeze() rr.log("output", rr.Image(image)) rr.log("latent", rr.Tensor(latents.squeeze(), dim_names=["channel", "height", "width"])) + return callback_kwargs + def run_canny_controlnet(image_path: str, prompt: str, negative_prompt: str) -> None: if not torch.cuda.is_available(): @@ -98,7 +103,7 @@ def run_canny_controlnet(image_path: str, prompt: str, negative_prompt: str) -> negative_prompt=negative_prompt, image=canny_image, # add batch dimension controlnet_conditioning_scale=0.5, - callback=lambda i, t, latents: controlnet_callback(i, t, latents, pipeline), + callback_on_step_end=controlnet_callback, ).images[0] rr.log("output", rr.Image(images)) @@ -127,7 +132,22 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_controlnet") + rr.script_setup( + args, + "rerun_example_controlnet", + blueprint=rrb.Horizontal( + rrb.Grid( + rrb.Spatial2DView(origin="input/raw"), + rrb.Spatial2DView(origin="input/canny"), + rrb.Vertical( + rrb.TextDocumentView(origin="positive_prompt"), + rrb.TextDocumentView(origin="negative_prompt"), + ), + rrb.TensorView(origin="latent"), + ), + rrb.Spatial2DView(origin="output"), + ), + ) run_canny_controlnet(args.img_path, args.prompt, args.negative_prompt) rr.script_teardown(args) From 6efb35be02710b7f62660fa9bc267be462b1e92b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 22 Mar 2024 13:24:58 +0100 Subject: [PATCH 104/508] Update egui (#5647) ### What * closes https://github.com/rerun-io/rerun/issues/5642 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5647/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5647/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5647/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5647) - [Docs preview](https://rerun.io/preview/5c7d9c54438b85f4679ff956b102e06a765ce851/docs) - [Examples preview](https://rerun.io/preview/5c7d9c54438b85f4679ff956b102e06a765ce851/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 14 +++++++------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93888629f08e..a9ac1d30aa89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1555,7 +1555,7 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "bytemuck", "serde", @@ -1564,7 +1564,7 @@ dependencies = [ [[package]] name = "eframe" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "bytemuck", "cocoa", @@ -1599,7 +1599,7 @@ dependencies = [ [[package]] name = "egui" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "accesskit", "ahash", @@ -1615,7 +1615,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "bytemuck", "document-features", @@ -1633,7 +1633,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "accesskit_winit", "arboard", @@ -1662,7 +1662,7 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "egui", "ehttp", @@ -1677,7 +1677,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "bytemuck", "egui", @@ -1694,7 +1694,7 @@ dependencies = [ [[package]] name = "egui_plot" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "egui", ] @@ -1736,7 +1736,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "bytemuck", "serde", @@ -1837,7 +1837,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=0299663cdd1da6b716bb62083bd1e212fb7e4abe#0299663cdd1da6b716bb62083bd1e212fb7e4abe" +source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" dependencies = [ "ab_glyph", "ahash", diff --git a/Cargo.toml b/Cargo.toml index 73fa74c0ec6d..e835d5011241 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -284,13 +284,13 @@ debug = true # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 -eframe = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 -egui = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 -egui_plot = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 -emath = { git = "https://github.com/emilk/egui.git", rev = "0299663cdd1da6b716bb62083bd1e212fb7e4abe" } # egui master 2024-03-21 +ecolor = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 +eframe = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 +egui = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 +egui_extras = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 +egui_plot = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 +egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 +emath = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } From 84d19d11cfbd1651d6469edce89e571f9ea63e9a Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 22 Mar 2024 13:39:34 +0100 Subject: [PATCH 105/508] Remove items from selection upon removal consistently (#5643) ### What This was done in various places and somewhat inconsistently. This change unifies selection & history purging as well as selection fallback. * Fixes #5406 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5643/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5643/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5643/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5643) - [Docs preview](https://rerun.io/preview/9f723b58c2966da96bad42369c51c8d8f77d3c97/docs) - [Examples preview](https://rerun.io/preview/9f723b58c2966da96bad42369c51c8d8f77d3c97/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app_state.rs | 24 +++++++---------- .../re_viewer_context/src/selection_state.rs | 26 +++++++++---------- .../src/context_menu/actions/remove.rs | 10 ------- crates/re_viewport/src/viewport_blueprint.rs | 13 ++++++++-- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index ff2ce961b36d..579f028baded 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -161,7 +161,10 @@ impl AppState { recording_config_entry(recording_configs, recording.store_id().clone(), recording) .selection_state - .on_frame_start(|item| viewport.is_item_valid(item)); + .on_frame_start( + |item| viewport.is_item_valid(item), + re_viewer_context::Item::StoreId(store_context.recording.store_id().clone()), + ); let rec_cfg = recording_config_entry(recording_configs, recording.store_id().clone(), recording); @@ -297,19 +300,12 @@ impl AppState { app_blueprint.time_panel_expanded, ); - { - if ctx.selection().is_empty() { - // Make sure something is selected before showing the selection panel. - ctx.selection_state() - .set_selection(re_viewer_context::Item::StoreId(ctx.recording_id().clone())); - } - selection_panel.show_panel( - &ctx, - ui, - &mut viewport, - app_blueprint.selection_panel_expanded, - ); - } + selection_panel.show_panel( + &ctx, + ui, + &mut viewport, + app_blueprint.selection_panel_expanded, + ); let central_panel_frame = egui::Frame { fill: ui.style().visuals.panel_fill, diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index e020443230c1..61ac60951e73 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -227,18 +227,29 @@ pub struct ApplicationSelectionState { impl ApplicationSelectionState { /// Called at the start of each frame - pub fn on_frame_start(&mut self, item_retain_condition: impl Fn(&Item) -> bool) { + pub fn on_frame_start( + &mut self, + item_retain_condition: impl Fn(&Item) -> bool, + fallback_selection: Item, + ) { // Use a different name so we don't get a collision in puffin. re_tracing::profile_scope!("SelectionState::on_frame_start"); + // Purge history of invalid items. let history = self.history.get_mut(); history.retain(&item_retain_condition); + // Purge selection of invalid items. + let selection_this_frame = self.selection_this_frame.get_mut(); + selection_this_frame.retain(|item, _| item_retain_condition(item)); + if selection_this_frame.is_empty() { + *selection_this_frame = ItemCollection::from(fallback_selection); + } + // Hovering needs to be refreshed every frame: If it wasn't hovered last frame, it's no longer hovered! self.hovered_previous_frame = std::mem::take(self.hovered_this_frame.get_mut()); // Selection in contrast, is sticky! - let selection_this_frame = self.selection_this_frame.get_mut(); if selection_this_frame != &self.selection_previous_frame { history.update_selection(selection_this_frame); self.selection_previous_frame = selection_this_frame.clone(); @@ -286,17 +297,6 @@ impl ApplicationSelectionState { *self.hovered_this_frame.lock() = hovered.into(); } - /// Remove given items from the selection. - /// - /// Has no effect on items that were not selected in the first place. - /// Ignores `ItemSpaceContext`s in the passed collection if any. - pub fn remove_from_selection(&self, items: impl Into) { - let removed_items = items.into(); - self.selection_this_frame - .lock() - .retain(|item, _| !removed_items.contains_item(item)); - } - /// Select passed objects unless already selected in which case they get unselected. /// If however an object is already selected but now gets passed a *different* selected space context, it stays selected after all /// but with an updated selected space context! diff --git a/crates/re_viewport/src/context_menu/actions/remove.rs b/crates/re_viewport/src/context_menu/actions/remove.rs index e29411a4d57b..423bc5157f38 100644 --- a/crates/re_viewport/src/context_menu/actions/remove.rs +++ b/crates/re_viewport/src/context_menu/actions/remove.rs @@ -32,9 +32,6 @@ impl ContextMenuAction for RemoveAction { .mark_user_interaction(ctx.viewer_context); ctx.viewport_blueprint .remove_contents(Contents::Container(*container_id)); - ctx.viewer_context - .selection_state() - .remove_from_selection(Item::Container(*container_id)); } fn process_space_view(&self, ctx: &ContextMenuContext<'_>, space_view_id: &SpaceViewId) { @@ -42,9 +39,6 @@ impl ContextMenuAction for RemoveAction { .mark_user_interaction(ctx.viewer_context); ctx.viewport_blueprint .remove_contents(Contents::SpaceView(*space_view_id)); - ctx.viewer_context - .selection_state() - .remove_from_selection(Item::SpaceView(*space_view_id)); } fn process_data_result( @@ -58,10 +52,6 @@ impl ContextMenuAction for RemoveAction { ctx.viewer_context, EntityPathRule::including_subtree(instance_path.entity_path.clone()), ); - - ctx.viewer_context - .selection_state() - .remove_from_selection(Item::DataResult(*space_view_id, instance_path.clone())); } } } diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index fa94be5932af..a062f8fb3ad3 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -257,9 +257,18 @@ impl ViewportBlueprint { pub fn is_item_valid(&self, item: &Item) -> bool { match item { Item::StoreId(_) | Item::ComponentPath(_) | Item::InstancePath(_) => true, - Item::SpaceView(space_view_id) | Item::DataResult(space_view_id, _) => { - self.space_view(space_view_id).is_some() + + Item::SpaceView(space_view_id) => self.space_view(space_view_id).is_some(), + + Item::DataResult(space_view_id, instance_path) => { + self.space_view(space_view_id).map_or(false, |space_view| { + space_view + .contents + .entity_path_filter + .is_included(&instance_path.entity_path) + }) } + Item::Container(container_id) => self.container(container_id).is_some(), } } From 58c2cb186e025c3900bf5826e84c1926c9618281 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 22 Mar 2024 14:10:15 +0100 Subject: [PATCH 106/508] Remove no longer needed `NonInteractiveEntities` view system (#5644) We can query propagated blueprint queries directly by now ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5644/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5644/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5644/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5644) - [Docs preview](https://rerun.io/preview/29615f3701dfb4882ff92e5d99ed573824cc4cbf/docs) - [Examples preview](https://rerun.io/preview/29615f3701dfb4882ff92e5d99ed573824cc4cbf/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt --- .../re_space_view_spatial/src/contexts/mod.rs | 3 -- .../src/contexts/non_interactive_entities.rs | 43 ------------------- crates/re_space_view_spatial/src/ui.rs | 13 +++--- 3 files changed, 7 insertions(+), 52 deletions(-) delete mode 100644 crates/re_space_view_spatial/src/contexts/non_interactive_entities.rs diff --git a/crates/re_space_view_spatial/src/contexts/mod.rs b/crates/re_space_view_spatial/src/contexts/mod.rs index e5f78cdb7180..ee4183cc0935 100644 --- a/crates/re_space_view_spatial/src/contexts/mod.rs +++ b/crates/re_space_view_spatial/src/contexts/mod.rs @@ -1,13 +1,11 @@ mod annotation_context; mod depth_offsets; -mod non_interactive_entities; mod transform_context; use std::sync::atomic::AtomicUsize; pub use annotation_context::AnnotationSceneContext; pub use depth_offsets::EntityDepthOffsets; -pub use non_interactive_entities::NonInteractiveEntities; pub use transform_context::TransformContext; // ----------------------------------------------------------------------------- @@ -62,7 +60,6 @@ pub fn register_spatial_contexts( system_registry.register_context_system::()?; system_registry.register_context_system::()?; system_registry.register_context_system::()?; - system_registry.register_context_system::()?; system_registry.register_context_system::()?; Ok(()) } diff --git a/crates/re_space_view_spatial/src/contexts/non_interactive_entities.rs b/crates/re_space_view_spatial/src/contexts/non_interactive_entities.rs deleted file mode 100644 index d1842b1a99e6..000000000000 --- a/crates/re_space_view_spatial/src/contexts/non_interactive_entities.rs +++ /dev/null @@ -1,43 +0,0 @@ -use nohash_hasher::IntSet; -use re_log_types::EntityPathHash; -use re_types::ComponentNameSet; -use re_viewer_context::{IdentifiedViewSystem, ViewContextSystem}; - -/// List of all non-interactive entities for lookup during picking evaluation. -/// -/// TODO(wumpf, jleibs): This is a temporary solution until the picking code can query propagated blueprint properties directly. -#[derive(Default)] -pub struct NonInteractiveEntities(pub IntSet); - -impl IdentifiedViewSystem for NonInteractiveEntities { - fn identifier() -> re_viewer_context::ViewSystemIdentifier { - "NonInteractiveEntities".into() - } -} - -impl ViewContextSystem for NonInteractiveEntities { - fn compatible_component_sets(&self) -> Vec { - Vec::new() - } - - fn execute( - &mut self, - _ctx: &re_viewer_context::ViewerContext<'_>, - query: &re_viewer_context::ViewQuery<'_>, - ) { - self.0 = query - .iter_all_data_results() - .filter_map(|data_result| { - if data_result.accumulated_properties().interactive { - None - } else { - Some(data_result.entity_path.hash()) - } - }) - .collect(); - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } -} diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 21395c1fc1ee..90239198db90 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -17,7 +17,7 @@ use re_viewer_context::{ use super::{eye::Eye, ui_2d::View2DState, ui_3d::View3DState}; use crate::scene_bounding_boxes::SceneBoundingBoxes; use crate::{ - contexts::{AnnotationSceneContext, NonInteractiveEntities}, + contexts::AnnotationSceneContext, picking::{PickableUiRect, PickingContext, PickingHitType, PickingResult}, view_kind::SpatialSpaceViewKind, visualizers::{CamerasVisualizer, ImageVisualizer, UiLabel, UiLabelTarget}, @@ -454,7 +454,6 @@ pub fn picking( ctx.app_options.show_picking_debug_overlay, ); - let non_interactive = view_ctx.get::()?; let annotations = view_ctx.get::()?; let images = visualizers.get::()?; @@ -482,10 +481,12 @@ pub fn picking( instance_path.instance_key = InstanceKey::SPLAT; } - if non_interactive - .0 - .contains(&instance_path.entity_path.hash()) - { + let interactive = ctx + .lookup_query_result(query.space_view_id) + .tree + .lookup_result_by_path(&instance_path.entity_path) + .map_or(false, |result| result.accumulated_properties().interactive); + if !interactive { continue; } From 8ffc8e89eeeab30256af769ab0c46d0be9ff3b10 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 22 Mar 2024 15:53:03 +0100 Subject: [PATCH 107/508] Don't activate all blueprints in a data source when the end is reached (#5648) Instead rely on `LogMsg::ActivateStore` * Closes https://github.com/rerun-io/rerun/issues/5584 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5648/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5648/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5648/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5648) - [Docs preview](https://rerun.io/preview/0be33edf82f68ff9f6412da8d1d60233d80b8e57/docs) - [Examples preview](https://rerun.io/preview/0be33edf82f68ff9f6412da8d1d60233d80b8e57/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_entity_db/src/entity_db.rs | 8 +++++-- crates/re_viewer/src/app.rs | 35 ---------------------------- crates/re_viewer/src/store_hub.rs | 9 ------- 3 files changed, 6 insertions(+), 46 deletions(-) diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index b2f60470fbcd..cac8833924de 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -525,7 +525,7 @@ impl EntityDb { let set_store_info_msg = self .store_info_msg() - .map(|msg| LogMsg::SetStoreInfo(msg.clone())); + .map(|msg| Ok(LogMsg::SetStoreInfo(msg.clone()))); let time_filter = time_selection.map(|(timeline, range)| { ( @@ -540,10 +540,14 @@ impl EntityDb { .map(|msg| LogMsg::ArrowMsg(self.store_id().clone(), msg)) }); + // Signal that the store is done loading. + // Important for blueprints. + let activate_store_msg = LogMsg::ActivateStore(self.store_id().clone()); + let messages: Result, _> = set_store_info_msg - .map(re_log_types::DataTableResult::Ok) .into_iter() .chain(data_messages) + .chain(std::iter::once(Ok(activate_store_msg))) .collect(); messages diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index ecb29be28f23..96d4fd4625a6 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -1,5 +1,3 @@ -use itertools::Itertools as _; - use re_data_source::{DataSource, FileContents}; use re_entity_db::entity_db::EntityDb; use re_log_types::{FileSource, LogMsg, StoreKind}; @@ -917,39 +915,6 @@ impl App { re_log::warn!("Data source {} has left unexpectedly: {err}", msg.source); } else { re_log::debug!("Data source {} has finished", msg.source); - - // This could be the signal that we finished loading a blueprint. - // In that case, we want to make it the default. - // We wait with activaing blueprints until they are fully loaded, - // so that we don't run heuristics on half-loaded blueprints. - // This is a fallback in case `LogMsg::ActivateStore` isn't sent (for whatever reason). - - let blueprints = store_hub - .entity_dbs_from_channel_source(&channel_source) - .filter_map(|entity_db| { - if let Some(store_info) = entity_db.store_info() { - match store_info.store_id.kind { - StoreKind::Recording => { - // Recordings become active as soon as we start streaming them. - } - StoreKind::Blueprint => { - return Some(store_info.clone()); - } - } - } - None - }) - .collect_vec(); - - for re_log_types::StoreInfo { - store_id, - application_id, - .. - } in blueprints - { - re_log::debug!("Activating newly loaded blueprint"); - store_hub.set_blueprint_for_app_id(store_id, application_id); - } } continue; } diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer/src/store_hub.rs index 333627eded1e..4239c65e0ba2 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer/src/store_hub.rs @@ -291,15 +291,6 @@ impl StoreHub { self.store_bundle.contains(id) } - pub fn entity_dbs_from_channel_source<'a>( - &'a self, - source: &'a re_smart_channel::SmartChannelSource, - ) -> impl Iterator + 'a { - self.store_bundle - .entity_dbs() - .filter(move |db| db.data_source.as_ref() == Some(source)) - } - /// Remove any recordings with a network source pointing at this `uri`. #[cfg(target_arch = "wasm32")] pub fn remove_recording_by_uri(&mut self, uri: &str) { From e9e90254fa40430fb1503ed4d1206dd87287a60f Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 22 Mar 2024 16:35:42 +0100 Subject: [PATCH 108/508] Fix layouting issue on welcome screen for narrow window, triggering debug assertion (#5650) ### What * Fixes #5649 ~This is a speculative fix, didn't have a repro.~ From the callstack we know that a certain `ui.set_max_width(column_width - 8.0);` might have gotten a too small width. Looking at how `column_width` is produced this may very well happen if for some reason there's very little `available_width`. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5650/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5650/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5650/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5650) - [Docs preview](https://rerun.io/preview/4207de64817bf7002b8ff271b8a875ab63f62b23/docs) - [Examples preview](https://rerun.io/preview/4207de64817bf7002b8ff271b8a875ab63f62b23/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/ui/welcome_screen/welcome_section.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs index 56bbc564a6af..b82026176960 100644 --- a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs @@ -192,6 +192,7 @@ fn onboarding_content_ui(ui: &mut Ui, command_sender: &CommandSender, accepts_co let column_width = ((ui.available_width() + grid_spacing.x) / column_count as f32 - grid_spacing.x) .floor() + .at_least(MIN_COLUMN_WIDTH) .at_most(MAX_COLUMN_WIDTH); ui.horizontal(|ui| { From 6cef0931e67d0bdf4e34fb125404cc7671a0d426 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 22 Mar 2024 17:28:00 +0100 Subject: [PATCH 109/508] Use container names in some blueprints (#5652) ### What Wherever it makes sense. Also (unrelated) bump the number of iterations on depth guided stable diffusion to make the result look better by default. This example runs only on nightly, so it's not affecting PR & main build performance. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5652/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5652/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5652/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5652) - [Docs preview](https://rerun.io/preview/4fa66859734f386ef617f89c0e800e3dc547a345/docs) - [Examples preview](https://rerun.io/preview/4fa66859734f386ef617f89c0e800e3dc547a345/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/arkit_scenes/main.py | 1 + examples/python/blueprint_stocks/main.py | 1 + examples/python/depth_guided_stable_diffusion/main.py | 9 ++++++++- examples/python/rgbd/main.py | 1 + 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py index 1c35a287cda1..f465d5b6ff71 100755 --- a/examples/python/arkit_scenes/main.py +++ b/examples/python/arkit_scenes/main.py @@ -347,6 +347,7 @@ def main() -> None: origin=primary_camera_entity, contents=["$origin/depth", "/world/annotations/**"], ), + name="2D", ), rrb.TextDocumentView(name="Readme"), ), diff --git a/examples/python/blueprint_stocks/main.py b/examples/python/blueprint_stocks/main.py index e847587f7038..1776b6598b09 100755 --- a/examples/python/blueprint_stocks/main.py +++ b/examples/python/blueprint_stocks/main.py @@ -74,6 +74,7 @@ def stock_grid(symbols: list[str], dates: list[Any]) -> rrb.ViewportLike: rrb.Horizontal( contents=[rrb.TextDocumentView(name=f"{symbol}", origin=f"/stocks/{symbol}/info")] + [rrb.TimeSeriesView(name=f"{day}", origin=f"/stocks/{symbol}/{day}") for day in dates], + name=symbol, ) for symbol in symbols ] diff --git a/examples/python/depth_guided_stable_diffusion/main.py b/examples/python/depth_guided_stable_diffusion/main.py index 31712eb4dccf..a1daab0674a6 100755 --- a/examples/python/depth_guided_stable_diffusion/main.py +++ b/examples/python/depth_guided_stable_diffusion/main.py @@ -103,7 +103,7 @@ def main() -> None: parser.add_argument( "--num-inference-steps", type=int, - default=10, + default=20, help=""" The number of denoising steps. More denoising steps usually lead to a higher quality image at the expense of slower inference. This parameter will be modulated by `strength`. @@ -128,6 +128,7 @@ def main() -> None: rrb.Tabs( rrb.Spatial2DView(name="Image original", origin="image/original"), rrb.TensorView(name="Image preprocessed", origin="input_image/preprocessed"), + name="Image Inputs", ), rrb.Vertical( rrb.TextLogView(name="Prompt", contents=["prompt/text", "prompt/text_negative"]), @@ -136,7 +137,9 @@ def main() -> None: rrb.TensorView(name="Unconditional embeddings", origin="prompt/uncond_embeddings"), ), rrb.BarChartView(name="Prompt ids", origin="prompt/text_input"), + name="Prompt Inputs", ), + name="Inputs", ), rrb.Vertical( rrb.Tabs( @@ -145,11 +148,14 @@ def main() -> None: rrb.Spatial2DView(name="Depth normalized", origin="depth/normalized"), rrb.TensorView(name="Depth input pre-processed", origin="depth/input_preprocessed"), active_tab="Depth interpolated", + name="Depth", ), rrb.Tabs( rrb.TensorView(name="Encoded input", origin="encoded_input_image"), rrb.TensorView(name="Decoded init latents", origin="decoded_init_latents"), + name="Initialization", ), + name="Depth & Initialization", ), rrb.Vertical( rrb.Spatial2DView(name="Image diffused", origin="image/diffused"), @@ -158,6 +164,7 @@ def main() -> None: rrb.TensorView(name="Diffusion latents", origin="diffusion/latents"), # rrb.TensorView(name="Noise Prediction", origin="diffusion/noise_pred"), ), + name="Output & Iteration", ), ), rrb.SelectionPanel(expanded=False), diff --git a/examples/python/rgbd/main.py b/examples/python/rgbd/main.py index 14031c5f756a..8a0c8271c0a3 100755 --- a/examples/python/rgbd/main.py +++ b/examples/python/rgbd/main.py @@ -171,6 +171,7 @@ def main() -> None: # This enables interactions like clicking on a point in the 3D space to show the corresponding point in the 2D spaces and vice versa. rrb.Spatial2DView(name="Depth & RGB", origin="world/camera/image"), rrb.Spatial2DView(name="RGB", origin="world/camera/image", contents="world/camera/image/rgb"), + name="2D", ), column_shares=[2, 1], ), From dde0be0db26e973b5fdf328b404f3b043238f5e3 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 22 Mar 2024 15:35:55 -0400 Subject: [PATCH 110/508] Add blueprint APIs to common index for python docs (#5651) ### What These docs could use their own inline examples, etc. but getting them into the python index is a good starting point. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5651/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5651/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5651/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5651) - [Docs preview](https://rerun.io/preview/ff47637cd1cbb784f739b2d7c391e9840ca22bb7/docs) - [Examples preview](https://rerun.io/preview/ff47637cd1cbb784f739b2d7c391e9840ca22bb7/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- rerun_py/docs/gen_common_index.py | 65 +++++++++++++++++-- .../rerun_sdk/rerun/blueprint/__init__.py | 6 ++ rerun_py/rerun_sdk/rerun/blueprint/api.py | 47 ++++++++------ .../rerun_sdk/rerun/blueprint/space_views.py | 35 ++++------ 4 files changed, 109 insertions(+), 44 deletions(-) diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 2fb852bc90e9..11cb5b9d6dac 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -65,6 +65,7 @@ def all_archetypes() -> list[str]: @dataclass class Section: title: str + sub_title: str | None = None func_list: list[str] | None = None class_list: list[str] | None = None gen_page: bool = True @@ -213,7 +214,7 @@ class Section: gen_page=False, ), ################################################################################ - # Remaining sections of other referenced things + # Other referenced things Section( title="Enums", mod_path="rerun", @@ -230,6 +231,54 @@ class Section: class_list=["AsComponents", "ComponentBatchLike"], default_filters=False, ), + ################################################################################ + # Blueprint APIs + Section( + title="Blueprint", + sub_title="APIs", + mod_path="rerun.blueprint", + class_list=[ + "Blueprint", + "BlueprintPart", + "Container", + "Horizontal", + "Vertical", + "Grid", + "Tabs", + "SpaceView", + "BarChartView", + "Spatial2DView", + "Spatial3DView", + "TensorView", + "TextDocumentView", + "TextLogView", + "TimeSeriesView", + "BlueprintPanel", + "SelectionPanel", + "TimePanel", + "Viewport", + ], + ), + Section( + title="Blueprint", + sub_title="Archetypes", + mod_path="rerun.blueprint.archetypes", + show_tables=False, + ), + Section( + title="Blueprint", + sub_title="Components", + mod_path="rerun.blueprint.datatypes", + show_tables=False, + ), + Section( + title="Blueprint", + sub_title="Datatypes", + mod_path="rerun.blueprint.components", + show_tables=False, + ), + ################################################################################ + # Remaining sections Section( title="Script Helpers", func_list=[ @@ -337,9 +386,14 @@ def make_slug(s: str) -> str: for section in SECTION_TABLE: if section.gen_page: # Turn the heading into a slug and add it to the nav - md_name = make_slug(section.title) - md_file = md_name + ".md" - nav[section.title] = md_file + if section.sub_title: + md_name = make_slug("_".join([section.title, section.sub_title])) + md_file = md_name + ".md" + nav[(section.title, section.sub_title)] = md_file + else: + md_name = make_slug(section.title) + md_file = md_name + ".md" + nav[section.title] = md_file # Write out the contents of this section write_path = common_dir.joinpath(md_file) @@ -375,6 +429,9 @@ def make_slug(s: str) -> str: index_file.write("Class | Description\n") index_file.write("-------- | -----------\n") for class_name in section.class_list: + if section.mod_path != "rerun": + mod_tail = section.mod_path.split(".")[1:] + class_name = ".".join(mod_tail + [class_name]) cls = rerun_pkg[class_name] show_class = class_name for maybe_strip in ["archetypes.", "components.", "datatypes."]: diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index f0c78a7630b8..dcb0d6e06c95 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -6,6 +6,7 @@ "Blueprint", "BlueprintLike", "BlueprintPanel", + "BlueprintPart", "components", "datatypes", "Grid", @@ -22,6 +23,8 @@ "Vertical", "Viewport", "ViewportLike", + "SpaceView", + "Container", ] from . import archetypes, components, datatypes @@ -29,7 +32,10 @@ Blueprint, BlueprintLike, BlueprintPanel, + BlueprintPart, + Container, SelectionPanel, + SpaceView, TimePanel, Viewport, ViewportLike, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 49e0db70c8cb..3208cfe1c0a4 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -21,10 +21,16 @@ class SpaceView: Base class for all space view types. Consider using one of the subclasses instead of this class directly: - - [Spatial3D][] for 3D space views - - [Spatial2D][] for 2D space views - This is an ergonomic helper on top of [rerun.blueprint.archetypes.SpaceViewBlueprint][]. + - [rerun.blueprint.BarChartView][] + - [rerun.blueprint.Spatial2DView][] + - [rerun.blueprint.Spatial3DView][] + - [rerun.blueprint.TensorView][] + - [rerun.blueprint.TextDocumentView][] + - [rerun.blueprint.TextLogView][] + - [rerun.blueprint.TimeSeriesView][] + + These are ergonomic helpers on top of [rerun.blueprint.archetypes.SpaceViewBlueprint][]. """ def __init__( @@ -49,8 +55,8 @@ def __init__( The `EntityPath` to use as the origin of this space view. All other entities will be transformed to be displayed relative to this origin. contents - The contents of the space view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. + The contents of the space view specified as a query expression. This is either a single expression, + or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. """ self.id = uuid.uuid4() @@ -109,12 +115,13 @@ class Container: Base class for all container types. Consider using one of the subclasses instead of this class directly: - - [Horizontal][] for horizontal containers - - [Vertical][] for vertical containers - - [Grid][] for grid containers - - [Tabs][] for tab containers - This is an ergonomic helper on top of [rerun.blueprint.archetypes.ContainerBlueprint][]. + - [rerun.blueprint.Horizontal][] + - [rerun.blueprint.Vertical][] + - [rerun.blueprint.Grid][] + - [rerun.blueprint.Tabs][] + + These are ergonomic helpers on top of [rerun.blueprint.archetypes.ContainerBlueprint][]. """ def __init__( @@ -300,11 +307,12 @@ class Panel: Base class for the panel types. Consider using one of the subclasses instead of this class directly: - - [BlueprintPanel][] - - [SelectionPanel][] - - [TimePanel][] - This is an ergonomic helper on top of [rerun.blueprint.archetypes.PanelBlueprint][]. + - [BlueprintPanel][rerun.blueprint.BlueprintPanel] + - [SelectionPanel][rerun.blueprint.SelectionPanel] + - [TimePanel][rerun.blueprint.TimePanel] + + These are ergonomic helpers on top of [rerun.blueprint.archetypes.PanelBlueprint][]. """ def __init__(self, *, blueprint_path: str, expanded: bool | None = None): @@ -412,11 +420,12 @@ def __init__( """ Construct a new blueprint from the given parts. - Each [BlueprintPart][] can be one of the following: - - [Viewport][] - - [BlueprintPanel][] - - [SelectionPanel][] - - [TimePanel][] + Each [BlueprintPart][rerun.blueprint.BlueprintPart] can be one of the following: + + - [Viewport][rerun.blueprint.Viewport] + - [BlueprintPanel][rerun.blueprint.BlueprintPanel] + - [SelectionPanel][rerun.blueprint.SelectionPanel] + - [TimePanel][rerun.blueprint.TimePanel] It is an error to provide more than one of any type of part. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py index c9d127d5947b..6a5c2293ad09 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py @@ -23,9 +23,8 @@ def __init__( The `EntityPath` to use as the origin of this view. All other entities will be transformed to be displayed relative to this origin. contents - The contents of the view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. + The contents of the space view specified as a query expression. This is either a single expression, + or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. name The name of the view. @@ -52,9 +51,8 @@ def __init__( The `EntityPath` to use as the origin of this view. All other entities will be transformed to be displayed relative to this origin. contents - The contents of the view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. + The contents of the space view specified as a query expression. This is either a single expression, + or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. name The name of the view. @@ -81,9 +79,8 @@ def __init__( The `EntityPath` to use as the origin of this view. All other entities will be transformed to be displayed relative to this origin. contents - The contents of the view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. + The contents of the space view specified as a query expression. This is either a single expression, + or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. name The name of the view. @@ -110,9 +107,8 @@ def __init__( The `EntityPath` to use as the origin of this view. All other entities will be transformed to be displayed relative to this origin. contents - The contents of the view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. + The contents of the space view specified as a query expression. This is either a single expression, + or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. name The name of the view. @@ -139,9 +135,8 @@ def __init__( The `EntityPath` to use as the origin of this view. All other entities will be transformed to be displayed relative to this origin. contents - The contents of the view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. + The contents of the space view specified as a query expression. This is either a single expression, + or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. name The name of the view. @@ -168,9 +163,8 @@ def __init__( The `EntityPath` to use as the origin of this view. All other entities will be transformed to be displayed relative to this origin. contents - The contents of the view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. + The contents of the space view specified as a query expression. This is either a single expression, + or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. name The name of the view. @@ -197,9 +191,8 @@ def __init__( The `EntityPath` to use as the origin of this view. All other entities will be transformed to be displayed relative to this origin. contents - The contents of the view. Most commonly specified as a query expression. The individual - sub-expressions must either be newline separate, or provided as a list of strings. - See: [rerun.blueprint.components.QueryExpression][]. + The contents of the space view specified as a query expression. This is either a single expression, + or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. name The name of the view. From 7e1bde90b5ef24e4a5aa019b416fb3906d5e197e Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 25 Mar 2024 09:05:10 +0100 Subject: [PATCH 111/508] Enable selecting data sources and blueprints and recordings in them (#5646) ### What * Part of https://github.com/rerun-io/rerun/issues/5645 If you click a recording you will now see what blueprints are in the same data source. You can also select the data source directly to see all recordings and blueprints in it. Selecting a blueprint is now also possible. I also added the size of the store to the selection panel. https://github.com/rerun-io/rerun/assets/1148717/e353339b-56c1-4924-9523-59afea2b5da0 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5646/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5646/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5646/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5646) - [Docs preview](https://rerun.io/preview/920381f809c2d96122511ff18de54795d7db7bd6/docs) - [Examples preview](https://rerun.io/preview/920381f809c2d96122511ff18de54795d7db7bd6/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 5 + .../src/ingest/python.rs | 4 +- crates/re_data_store/src/store_stats.rs | 7 + crates/re_data_ui/Cargo.toml | 2 + crates/re_data_ui/src/data_source.rs | 63 ++++++++ crates/re_data_ui/src/entity_db.rs | 120 +++++++++++++-- crates/re_data_ui/src/item_ui.rs | 141 ++++++++++++++++++ crates/re_data_ui/src/lib.rs | 1 + crates/re_entity_db/src/entity_db.rs | 7 + crates/re_entity_db/src/store_bundle.rs | 10 ++ crates/re_smart_channel/Cargo.toml | 1 + crates/re_smart_channel/src/lib.rs | 2 +- crates/re_space_view_spatial/src/ui_3d.rs | 2 +- crates/re_viewer/src/app.rs | 41 ++--- crates/re_viewer/src/app_state.rs | 2 +- crates/re_viewer/src/store_hub.rs | 122 +++++++++------ crates/re_viewer/src/ui/recordings_panel.rs | 99 +----------- .../re_viewer/src/ui/selection_history_ui.rs | 1 + crates/re_viewer/src/ui/selection_panel.rs | 22 ++- crates/re_viewer_context/Cargo.toml | 1 + .../re_viewer_context/src/command_sender.rs | 20 ++- crates/re_viewer_context/src/item.rs | 25 +++- .../re_viewer_context/src/selection_state.rs | 18 ++- crates/re_viewer_context/src/store_context.rs | 8 +- crates/re_viewport/Cargo.toml | 1 + .../actions/collapse_expand_all.rs | 4 +- crates/re_viewport/src/context_menu/mod.rs | 8 + .../re_viewport/src/space_view_highlights.rs | 4 +- crates/re_viewport/src/viewport_blueprint.rs | 5 +- .../re_viewport/src/viewport_blueprint_ui.rs | 4 +- rerun_cpp/src/rerun/c/rerun.h | 2 +- 31 files changed, 543 insertions(+), 209 deletions(-) create mode 100644 crates/re_data_ui/src/data_source.rs diff --git a/Cargo.lock b/Cargo.lock index a9ac1d30aa89..dcbaa3a9101f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4326,8 +4326,10 @@ dependencies = [ "re_log_types", "re_query", "re_renderer", + "re_smart_channel", "re_tracing", "re_types", + "re_types_core", "re_ui", "re_viewer_context", "rfd", @@ -4667,6 +4669,7 @@ dependencies = [ "crossbeam", "parking_lot", "re_tracing", + "serde", "web-time", ] @@ -5103,6 +5106,7 @@ dependencies = [ "re_log_types", "re_query", "re_renderer", + "re_smart_channel", "re_string_interner", "re_tracing", "re_types", @@ -5138,6 +5142,7 @@ dependencies = [ "re_log_types", "re_query", "re_renderer", + "re_smart_channel", "re_space_view", "re_space_view_time_series", "re_tracing", diff --git a/crates/re_build_search_index/src/ingest/python.rs b/crates/re_build_search_index/src/ingest/python.rs index 713e822471ce..94635422b63a 100644 --- a/crates/re_build_search_index/src/ingest/python.rs +++ b/crates/re_build_search_index/src/ingest/python.rs @@ -88,9 +88,7 @@ impl Docstrings { } // if `path` is an alias, get the qualified path - let Some(path) = self.aliases.get(path) else { - return None; - }; + let path = self.aliases.get(path)?; self.docstrings.get(path) } diff --git a/crates/re_data_store/src/store_stats.rs b/crates/re_data_store/src/store_stats.rs index c2d2d9a51165..11d2d15efb77 100644 --- a/crates/re_data_store/src/store_stats.rs +++ b/crates/re_data_store/src/store_stats.rs @@ -179,6 +179,13 @@ impl SizeBytes for ClusterCellCache { } } +impl SizeBytes for DataStore { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.timeless_size_bytes() + self.temporal_size_bytes() // approximate + } +} + impl DataStore { /// Returns the number of timeless index rows stored across this entire store, i.e. the sum of /// the number of rows across all of its timeless indexed tables. diff --git a/crates/re_data_ui/Cargo.toml b/crates/re_data_ui/Cargo.toml index 32399c8dee8e..d954b449ff70 100644 --- a/crates/re_data_ui/Cargo.toml +++ b/crates/re_data_ui/Cargo.toml @@ -24,10 +24,12 @@ re_log.workspace = true re_log_types.workspace = true re_query.workspace = true re_renderer.workspace = true +re_smart_channel.workspace = true re_tracing.workspace = true re_types = { workspace = true, features = [ "egui_plot", # Needed to draw marker shapes. ] } +re_types_core.workspace = true re_ui.workspace = true re_viewer_context.workspace = true diff --git a/crates/re_data_ui/src/data_source.rs b/crates/re_data_ui/src/data_source.rs new file mode 100644 index 000000000000..251f0a63a90b --- /dev/null +++ b/crates/re_data_ui/src/data_source.rs @@ -0,0 +1,63 @@ +use re_log_types::StoreKind; +use re_viewer_context::{UiVerbosity, ViewerContext}; + +use crate::item_ui::entity_db_button_ui; + +impl crate::DataUi for re_smart_channel::SmartChannelSource { + fn data_ui( + &self, + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + verbosity: UiVerbosity, + _query: &re_data_store::LatestAtQuery, + _store: &re_data_store::DataStore, + ) { + ui.label(self.to_string()); + + if verbosity == UiVerbosity::Small { + return; + } + + // TODO(emilk): show if we're still connected to this data source + + // Find all stores from this data source + // (e.g. find the recordings and blueprint in this .rrd file). + let mut recordings = vec![]; + let mut blueprints = vec![]; + + for other in ctx + .store_context + .bundle + .entity_dbs_from_channel_source(self) + { + match other.store_kind() { + StoreKind::Recording => { + recordings.push(other); + } + StoreKind::Blueprint => { + blueprints.push(other); + } + } + } + + { + ui.add_space(8.0); + ui.strong("Recordings in this data source"); + ui.indent("recordings", |ui| { + for entity_db in recordings { + entity_db_button_ui(ctx, ui, entity_db, true); + } + }); + } + + { + ui.add_space(8.0); + ui.strong("Blueprints in this data source"); + ui.indent("blueprints", |ui| { + for entity_db in blueprints { + entity_db_button_ui(ctx, ui, entity_db, true); + } + }); + } + } +} diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index 1b6854d64636..ed6234788e82 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -1,15 +1,22 @@ -impl crate::DataUi for re_entity_db::EntityDb { +use re_entity_db::EntityDb; +use re_log_types::StoreKind; +use re_types::SizeBytes; +use re_viewer_context::{UiVerbosity, ViewerContext}; + +use crate::item_ui::{data_source_button_ui, entity_db_button_ui}; + +impl crate::DataUi for EntityDb { fn data_ui( &self, - ctx: &re_viewer_context::ViewerContext<'_>, + ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - verbosity: re_viewer_context::UiVerbosity, + verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, _store: &re_data_store::DataStore, ) { let re_ui = &ctx.re_ui; - if verbosity == re_viewer_context::UiVerbosity::Small { + if verbosity == UiVerbosity::Small { let mut string = self.store_id().to_string(); if let Some(data_source) = &self.data_source { string += &format!(", {data_source}"); @@ -22,13 +29,9 @@ impl crate::DataUi for re_entity_db::EntityDb { } egui::Grid::new("entity_db").num_columns(2).show(ui, |ui| { - re_ui.grid_left_hand_label(ui, &format!("{} ID", self.store_id().kind)); - ui.label(self.store_id().to_string()); - ui.end_row(); - - if let Some(data_source) = &self.data_source { - re_ui.grid_left_hand_label(ui, "Data source"); - ui.label(data_source.to_string()); + { + re_ui.grid_left_hand_label(ui, &format!("{} ID", self.store_id().kind)); + ui.label(self.store_id().to_string()); ui.end_row(); } @@ -54,12 +57,97 @@ impl crate::DataUi for re_entity_db::EntityDb { ui.label(store_source.to_string()); ui.end_row(); - // We are in the recordings menu, we know the kind - if false { - re_ui.grid_left_hand_label(ui, "Kind"); - ui.label(store_kind.to_string()); - ui.end_row(); + re_ui.grid_left_hand_label(ui, "Kind"); + ui.label(store_kind.to_string()); + ui.end_row(); + } + + { + re_ui.grid_left_hand_label(ui, "Size"); + ui.label(re_format::format_bytes(self.total_size_bytes() as _)) + .on_hover_text( + "Approximate size in RAM (decompressed).\n\ + If you hover an entity in the streams view (bottom panel) you can see the size of individual entities."); + ui.end_row(); + } + + if let Some(data_source) = &self.data_source { + re_ui.grid_left_hand_label(ui, "Data source"); + data_source_button_ui(ctx, ui, data_source); + ui.end_row(); + } + }); + + if ctx.store_context.is_active(self.store_id()) { + ui.add_space(8.0); + match self.store_kind() { + StoreKind::Recording => { + ui.label("This is the active recording"); } + StoreKind::Blueprint => { + ui.label("This is the active blueprint"); + } + } + } + + if verbosity == UiVerbosity::Full { + sibling_stores_ui(ctx, ui, self); + } + } +} + +/// Show the other stores in the same data source. +fn sibling_stores_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui, entity_db: &EntityDb) { + let Some(data_source) = &entity_db.data_source else { + return; + }; + + // Find other stores from the same data source + // (e.g. find the blueprint in this .rrd file, if any). + let mut other_recordings = vec![]; + let mut other_blueprints = vec![]; + + for other in ctx + .store_context + .bundle + .entity_dbs_from_channel_source(data_source) + { + if other.store_id() == entity_db.store_id() { + continue; + } + match other.store_kind() { + StoreKind::Recording => { + other_recordings.push(other); + } + StoreKind::Blueprint => { + other_blueprints.push(other); + } + } + } + + if !other_recordings.is_empty() { + ui.add_space(8.0); + if entity_db.store_kind() == StoreKind::Recording { + ui.strong("Other recordings in this data source"); + } else { + ui.strong("Recordings in this data source"); + } + ui.indent("recordings", |ui| { + for entity_db in other_recordings { + entity_db_button_ui(ctx, ui, entity_db, true); + } + }); + } + if !other_blueprints.is_empty() { + ui.add_space(8.0); + if entity_db.store_kind() == StoreKind::Blueprint { + ui.strong("Other blueprints in this data source"); + } else { + ui.strong("Blueprints in this data source"); + } + ui.indent("blueprints", |ui| { + for entity_db in other_blueprints { + entity_db_button_ui(ctx, ui, entity_db, true); } }); } diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index e44124b2d126..ed6251f09dcb 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -550,3 +550,144 @@ pub fn entity_hover_card_ui( let instance_path = InstancePath::entity_splat(entity_path.clone()); instance_hover_card_ui(ui, ctx, query, store, &instance_path); } + +pub fn data_source_button_ui( + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + data_source: &re_smart_channel::SmartChannelSource, +) -> egui::Response { + let item = Item::DataSource(data_source.clone()); + + // TODO(#5645): an icon for data sources + + let response = ui.selectable_label( + ctx.selection().contains_item(&item), + data_source.to_string(), + ); + + let response = response.on_hover_ui(|ui| { + data_source.data_ui( + ctx, + ui, + re_viewer_context::UiVerbosity::Reduced, + &ctx.current_query(), + ctx.recording_store(), // unused + ); + }); + + cursor_interact_with_selectable(ctx, response, item) +} + +/// Show button for a store (recording or blueprint). +/// +/// You can set `include_app_id` to hide the App Id, but usually you want to show it. +pub fn entity_db_button_ui( + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + entity_db: &re_entity_db::EntityDb, + include_app_id: bool, +) { + use re_types_core::SizeBytes as _; + use re_viewer_context::{SystemCommand, SystemCommandSender as _}; + + let app_id_prefix = if include_app_id { + entity_db + .app_id() + .map_or(String::default(), |app_id| format!("{app_id} - ")) + } else { + String::default() + }; + + let time = entity_db + .store_info() + .and_then(|info| { + info.started + .format_time_custom("[hour]:[minute]:[second]", ctx.app_options.time_zone) + }) + .unwrap_or("".to_owned()); + + let size = re_format::format_bytes(entity_db.total_size_bytes() as _); + let title = format!("{app_id_prefix}{time} - {size}"); + + let store_id = entity_db.store_id().clone(); + let item = re_viewer_context::Item::StoreId(store_id.clone()); + + let mut list_item = ctx + .re_ui + .list_item(title) + .selected(ctx.selection().contains_item(&item)) + .with_icon_fn(|_re_ui, ui, rect, visuals| { + // Color icon based on whether this is the active recording or not: + let color = if ctx.store_context.is_active(&store_id) { + visuals.fg_stroke.color + } else { + ui.visuals().widgets.noninteractive.fg_stroke.color + }; + re_ui::icons::STORE + .as_image() + .tint(color) + .paint_at(ui, rect); + }) + .with_buttons(|re_ui, ui| { + // Close-button: + let resp = re_ui + .small_icon_button(ui, &re_ui::icons::REMOVE) + .on_hover_text(match store_id.kind { + re_log_types::StoreKind::Recording => { + "Close this recording (unsaved data will be lost)" + } + re_log_types::StoreKind::Blueprint => { + "Close this blueprint (unsaved data will be lost)" + } + }); + if resp.clicked() { + ctx.command_sender + .send_system(SystemCommand::CloseStore(store_id.clone())); + } + resp + }); + + if ctx.hovered().contains_item(&item) { + list_item = list_item.force_hovered(true); + } + + let response = list_item + .show_flat(ui) // never more than one level deep + .on_hover_ui(|ui| { + entity_db.data_ui( + ctx, + ui, + re_viewer_context::UiVerbosity::Reduced, + &ctx.current_query(), + entity_db.store(), + ); + }); + + if response.hovered() { + ctx.selection_state().set_hovered(item.clone()); + } + + if response.clicked() { + // Open the recording / switch to this blueprint… + ctx.command_sender + .send_system(SystemCommand::ActivateStore(store_id.clone())); + + // …and select the store in the selection panel. + // Note that we must do it in this order, since the selection state is stored in the recording. + // That's also why we use a command to set the selection. + match store_id.kind { + re_log_types::StoreKind::Recording => { + ctx.command_sender.send_system(SystemCommand::SetSelection { + recording_id: Some(store_id), + item, + }); + } + re_log_types::StoreKind::Blueprint => { + ctx.command_sender.send_system(SystemCommand::SetSelection { + recording_id: None, + item, + }); + } + } + } +} diff --git a/crates/re_data_ui/src/lib.rs b/crates/re_data_ui/src/lib.rs index 8b04f717df86..4a513b8ed30e 100644 --- a/crates/re_data_ui/src/lib.rs +++ b/crates/re_data_ui/src/lib.rs @@ -14,6 +14,7 @@ mod component; mod component_path; mod component_ui_registry; mod data; +mod data_source; mod editors; mod entity_db; mod entity_path; diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index cac8833924de..2d0231aefbf8 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -554,6 +554,13 @@ impl EntityDb { } } +impl re_types_core::SizeBytes for EntityDb { + fn heap_size_bytes(&self) -> u64 { + // TODO(emilk): size of entire EntityDb, including secondary indices etc + self.data_store.heap_size_bytes() + } +} + // ---------------------------------------------------------------------------- pub struct IngestionStatistics { diff --git a/crates/re_entity_db/src/store_bundle.rs b/crates/re_entity_db/src/store_bundle.rs index c7f8592551ba..ef90623a3032 100644 --- a/crates/re_entity_db/src/store_bundle.rs +++ b/crates/re_entity_db/src/store_bundle.rs @@ -133,6 +133,16 @@ impl StoreBundle { .filter(|log| log.store_kind() == StoreKind::Blueprint) } + /// All stores that came from the given source + pub fn entity_dbs_from_channel_source<'a>( + &'a self, + source: &'a re_smart_channel::SmartChannelSource, + ) -> impl Iterator + 'a { + self.entity_dbs + .values() + .filter(move |db| db.data_source.as_ref() == Some(source)) + } + // -- pub fn retain(&mut self, mut f: impl FnMut(&EntityDb) -> bool) { diff --git a/crates/re_smart_channel/Cargo.toml b/crates/re_smart_channel/Cargo.toml index cfbc12a68c3d..c39f8049aa71 100644 --- a/crates/re_smart_channel/Cargo.toml +++ b/crates/re_smart_channel/Cargo.toml @@ -21,4 +21,5 @@ re_tracing.workspace = true crossbeam.workspace = true parking_lot.workspace = true +serde.workspace = true web-time.workspace = true diff --git a/crates/re_smart_channel/src/lib.rs b/crates/re_smart_channel/src/lib.rs index 718f04870cab..56f844a2022d 100644 --- a/crates/re_smart_channel/src/lib.rs +++ b/crates/re_smart_channel/src/lib.rs @@ -18,7 +18,7 @@ pub use sender::Sender; /// Identifies in what context this smart channel was created, and who/what is holding its /// receiving end. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)] pub enum SmartChannelSource { /// The channel was created in the context of loading a file from disk (could be /// `.rrd` files, or `.glb`, `.png`, …). diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index eb30830cf00d..d9b9610e7656 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -552,7 +552,7 @@ pub fn view_3d( // Track focused entity if any. if let Some(focused_item) = ctx.focused_item { let focused_entity = match focused_item { - Item::StoreId(_) | Item::Container(_) => None, + Item::DataSource(_) | Item::StoreId(_) | Item::Container(_) => None, Item::SpaceView(space_view_id) => { if space_view_id == &query.space_view_id { diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 96d4fd4625a6..c66ccee0f361 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -336,11 +336,11 @@ impl App { egui_ctx: &egui::Context, ) { match cmd { - SystemCommand::SetRecordingId(recording_id) => { - store_hub.set_recording_id(recording_id); + SystemCommand::ActivateStore(store_id) => { + store_hub.activate_store(store_id); } - SystemCommand::CloseRecordingId(recording_id) => { - store_hub.remove_recording_id(&recording_id); + SystemCommand::CloseStore(store_id) => { + store_hub.remove(&store_id); } SystemCommand::LoadDataSource(data_source) => { @@ -368,7 +368,7 @@ impl App { SystemCommand::LoadStoreDb(entity_db) => { let store_id = entity_db.store_id().clone(); store_hub.insert_entity_db(entity_db); - store_hub.set_recording_id(store_id); + store_hub.set_active_recording_id(store_id); } SystemCommand::ResetViewer => self.reset(store_hub, egui_ctx), @@ -376,7 +376,7 @@ impl App { // By clearing the blueprint it will be re-populated with the defaults // at the beginning of the next frame. re_log::debug!("Reset blueprint"); - store_hub.clear_current_blueprint(); + store_hub.clear_active_blueprint(); egui_ctx.request_repaint(); // Many changes take a frame delay to show up. } SystemCommand::UpdateBlueprint(blueprint_id, updates) => { @@ -421,11 +421,17 @@ impl App { } } - SystemCommand::SetSelection(store_id, item) => { - if let Some(rec_cfg) = self.state.recording_config_mut(&store_id) { - rec_cfg.selection_state.set_selection(item); - } else { - re_log::debug!("Failed to select item {item:?}"); + SystemCommand::SetSelection { recording_id, item } => { + let recording_id = + recording_id.or_else(|| store_hub.active_recording_id().cloned()); + if let Some(recording_id) = recording_id { + if let Some(rec_cfg) = self.state.recording_config_mut(&recording_id) { + rec_cfg.selection_state.set_selection(item); + } else { + re_log::debug!( + "Failed to select item {item:?}: failed to find recording {recording_id}" + ); + } } } @@ -487,7 +493,7 @@ impl App { let cur_rec = store_context.map(|ctx| ctx.recording.store_id()); if let Some(cur_rec) = cur_rec { self.command_sender - .send_system(SystemCommand::CloseRecordingId(cur_rec.clone())); + .send_system(SystemCommand::CloseStore(cur_rec.clone())); } } @@ -945,7 +951,7 @@ impl App { match store_id.kind { StoreKind::Recording => { re_log::debug!("Opening a new recording: {store_id}"); - store_hub.set_recording_id(store_id.clone()); + store_hub.set_active_recording_id(store_id.clone()); } StoreKind::Blueprint => { // We wait with activaing blueprints until they are fully loaded, @@ -965,7 +971,7 @@ impl App { match store_id.kind { StoreKind::Recording => { re_log::debug!("Opening a new recording: {store_id}"); - store_hub.set_recording_id(store_id.clone()); + store_hub.set_active_recording_id(store_id.clone()); } StoreKind::Blueprint => { re_log::debug!("Activating newly loaded blueprint"); @@ -1077,7 +1083,7 @@ impl App { pub fn recording_db(&self) -> Option<&EntityDb> { self.store_hub .as_ref() - .and_then(|store_hub| store_hub.current_recording()) + .and_then(|store_hub| store_hub.active_recording()) } fn handle_dropping_files(&mut self, egui_ctx: &egui::Context) { @@ -1119,8 +1125,7 @@ impl App { /// in the users face. fn should_show_welcome_screen(&mut self, store_hub: &StoreHub) -> bool { // Don't show the welcome screen if we have actual data to display. - if store_hub.current_recording().is_some() || store_hub.selected_application_id().is_some() - { + if store_hub.active_recording().is_some() || store_hub.active_application_id().is_some() { return false; } @@ -1279,7 +1284,7 @@ impl eframe::App for App { // Heuristic to set the app_id to the welcome screen blueprint. // Must be called before `read_context` below. if self.should_show_welcome_screen(&store_hub) { - store_hub.set_app_id(StoreHub::welcome_screen_app_id()); + store_hub.set_active_app_id(StoreHub::welcome_screen_app_id()); } let store_context = store_hub.read_context(); diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 579f028baded..816c526abe06 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -426,7 +426,7 @@ impl AppState { re_tracing::profile_function!(); self.recording_configs - .retain(|store_id, _| store_hub.contains_store(store_id)); + .retain(|store_id, _| store_hub.store_bundle().contains(store_id)); } /// Returns the blueprint query that should be used for generating the current diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer/src/store_hub.rs index 4239c65e0ba2..689c6ba8bebc 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer/src/store_hub.rs @@ -16,11 +16,11 @@ use crate::{loading::load_blueprint_file, saving::default_blueprint_path}; /// to store both blueprints and recordings. /// /// Internally, the [`StoreHub`] tracks which [`ApplicationId`] and `recording -/// id` ([`StoreId`]) are currently selected in the viewer. These can be configured -/// using [`StoreHub::set_recording_id`] and [`StoreHub::set_app_id`] respectively. +/// id` ([`StoreId`]) are currently active in the viewer. These can be configured +/// using [`StoreHub::set_active_recording_id`] and [`StoreHub::set_active_app_id`] respectively. pub struct StoreHub { - selected_rec_id: Option, - selected_application_id: Option, + active_rec_id: Option, + active_application_id: Option, blueprint_by_app_id: HashMap, store_bundle: StoreBundle, @@ -71,8 +71,8 @@ impl StoreHub { crate::app_blueprint::setup_welcome_screen_blueprint(welcome_screen_blueprint); Self { - selected_rec_id: None, - selected_application_id: None, + active_rec_id: None, + active_application_id: None, blueprint_by_app_id, store_bundle, @@ -82,6 +82,12 @@ impl StoreHub { } } + /// All the loaded recordings and blueprints. + #[inline] + pub fn store_bundle(&self) -> &StoreBundle { + &self.store_bundle + } + /// Get a read-only [`StoreContext`] from the [`StoreHub`] if one is available. /// /// All of the returned references to blueprints and recordings will have a @@ -96,7 +102,7 @@ impl StoreHub { }); // If we have an app-id, then use it to look up the blueprint. - let app_id = self.selected_application_id.clone()?; + let app_id = self.active_application_id.clone()?; let blueprint_id = self .blueprint_by_app_id @@ -108,7 +114,7 @@ impl StoreHub { let blueprint = self.store_bundle.get(blueprint_id)?; let recording = self - .selected_rec_id + .active_rec_id .as_ref() .and_then(|id| self.store_bundle.get(id)); @@ -127,9 +133,43 @@ impl StoreHub { self.was_recording_active } - /// Change the selected/visible recording id. - /// This will also change the application-id to match the newly selected recording. - pub fn set_recording_id(&mut self, recording_id: StoreId) { + /// Activate a store by its [`StoreId`]. + /// + /// If this is a recording, switch to it. + /// If this is a blueprint, switch to the `AppId` of the blueprint, + /// and make this blueprint the active blueprint for that `AppId`. + pub fn activate_store(&mut self, store_id: StoreId) { + match store_id.kind { + StoreKind::Recording => self.set_active_recording_id(store_id), + StoreKind::Blueprint => { + if let Some(store) = self.store_bundle.get(&store_id) { + if let Some(app_id) = store.app_id().cloned() { + self.set_blueprint_for_app_id(store_id.clone(), app_id.clone()); + self.set_active_app_id(app_id.clone()); + } + } + } + } + } + + /// Directly access the [`EntityDb`] for the active recording. + pub fn active_recording_id(&self) -> Option<&StoreId> { + self.active_rec_id.as_ref() + } + + /// Directly access the [`EntityDb`] for the active recording. + pub fn active_recording(&self) -> Option<&EntityDb> { + self.active_rec_id + .as_ref() + .and_then(|id| self.store_bundle.get(id)) + } + + /// Change the active/visible recording id. + /// + /// This will also change the application-id to match the newly active recording. + pub fn set_active_recording_id(&mut self, recording_id: StoreId) { + debug_assert_eq!(recording_id.kind, StoreKind::Recording); + // If this recording corresponds to an app that we know about, then update the app-id. if let Some(app_id) = self .store_bundle @@ -137,28 +177,28 @@ impl StoreHub { .as_ref() .and_then(|recording| recording.app_id()) { - self.set_app_id(app_id.clone()); + self.set_active_app_id(app_id.clone()); } - self.selected_rec_id = Some(recording_id); + self.active_rec_id = Some(recording_id); self.was_recording_active = true; } - pub fn remove_recording_id(&mut self, recording_id: &StoreId) { - if self.selected_rec_id.as_ref() == Some(recording_id) { - if let Some(new_selection) = self.store_bundle.find_closest_recording(recording_id) { - self.set_recording_id(new_selection.clone()); + pub fn remove(&mut self, store_id: &StoreId) { + if self.active_rec_id.as_ref() == Some(store_id) { + if let Some(new_selection) = self.store_bundle.find_closest_recording(store_id) { + self.set_active_recording_id(new_selection.clone()); } else { - self.selected_application_id = None; - self.selected_rec_id = None; + self.active_application_id = None; + self.active_rec_id = None; } } - self.store_bundle.remove(recording_id); + self.store_bundle.remove(store_id); } - /// Change the selected [`ApplicationId`] - pub fn set_app_id(&mut self, app_id: ApplicationId) { + /// Change the active [`ApplicationId`] + pub fn set_active_app_id(&mut self, app_id: ApplicationId) { // If we don't know of a blueprint for this `ApplicationId` yet, // try to load one from the persisted store // TODO(#2579): implement web-storage for blueprints as well @@ -169,11 +209,11 @@ impl StoreHub { } } - self.selected_application_id = Some(app_id); + self.active_application_id = Some(app_id); } - pub fn selected_application_id(&self) -> Option<&ApplicationId> { - self.selected_application_id.as_ref() + pub fn active_application_id(&self) -> Option<&ApplicationId> { + self.active_application_id.as_ref() } /// Change which blueprint is active for a given [`ApplicationId`] @@ -190,9 +230,9 @@ impl StoreHub { .any(|id| id == blueprint_id) } - /// Clear the current blueprint - pub fn clear_current_blueprint(&mut self) { - if let Some(app_id) = &self.selected_application_id { + /// Clear the currently active blueprint + pub fn clear_active_blueprint(&mut self) { + if let Some(app_id) = &self.active_application_id { if let Some(blueprint_id) = self.blueprint_by_app_id.remove(app_id) { re_log::debug!("Clearing blueprint for {app_id}: {blueprint_id}"); self.store_bundle.remove(&blueprint_id); @@ -209,7 +249,7 @@ impl StoreHub { /// Insert a new recording or blueprint into the [`StoreHub`]. /// - /// Note that the recording is not automatically made active. Use [`StoreHub::set_recording_id`] + /// Note that the recording is not automatically made active. Use [`StoreHub::set_active_recording_id`] /// if needed. pub fn insert_entity_db(&mut self, entity_db: EntityDb) { self.store_bundle.insert(entity_db); @@ -253,7 +293,7 @@ impl StoreHub { // No point keeping an empty recording around. if entity_db.is_empty() { - self.remove_recording_id(&store_id); + self.remove(&store_id); return; } @@ -267,7 +307,7 @@ impl StoreHub { // log new things anyhow. let num_recordings = store_bundle.recordings().count(); if store_size_before == store_size_after && num_recordings > 1 { - self.remove_recording_id(&store_id); + self.remove(&store_id); } // Either we've reached our target goal or we couldn't fetch memory stats, in which case @@ -279,18 +319,6 @@ impl StoreHub { // we can get an accurate reading of the current memory used and decide if we should go on. } - /// Directly access the [`EntityDb`] for the selected recording - pub fn current_recording(&self) -> Option<&EntityDb> { - self.selected_rec_id - .as_ref() - .and_then(|id| self.store_bundle.get(id)) - } - - /// Check whether the [`StoreHub`] contains the referenced store (recording or blueprint). - pub fn contains_store(&self, id: &StoreId) -> bool { - self.store_bundle.contains(id) - } - /// Remove any recordings with a network source pointing at this `uri`. #[cfg(target_arch = "wasm32")] pub fn remove_recording_by_uri(&mut self, uri: &str) { @@ -417,16 +445,16 @@ impl StoreHub { Ok(()) } - /// Populate a [`StoreHubStats`] based on the selected app. + /// Populate a [`StoreHubStats`] based on the active app. // // TODO(jleibs): We probably want stats for all recordings, not just - // the currently selected recording. + // the active recording. pub fn stats(&self, detailed_cache_stats: bool) -> StoreHubStats { re_tracing::profile_function!(); // If we have an app-id, then use it to look up the blueprint. let blueprint = self - .selected_application_id + .active_application_id .as_ref() .and_then(|app_id| self.blueprint_by_app_id.get(app_id)) .and_then(|blueprint_id| self.store_bundle.get(blueprint_id)); @@ -440,7 +468,7 @@ impl StoreHub { .unwrap_or_default(); let recording = self - .selected_rec_id + .active_rec_id .as_ref() .and_then(|rec_id| self.store_bundle.get(rec_id)); diff --git a/crates/re_viewer/src/ui/recordings_panel.rs b/crates/re_viewer/src/ui/recordings_panel.rs index 8bb03b5c0eac..64c96c745cb8 100644 --- a/crates/re_viewer/src/ui/recordings_panel.rs +++ b/crates/re_viewer/src/ui/recordings_panel.rs @@ -1,9 +1,9 @@ use std::collections::BTreeMap; -use re_data_ui::DataUi; +use re_data_ui::item_ui::entity_db_button_ui; use re_log_types::LogMsg; use re_smart_channel::{ReceiveSet, SmartChannelSource}; -use re_viewer_context::{SystemCommand, SystemCommandSender, ViewerContext}; +use re_viewer_context::ViewerContext; /// Show the currently open Recordings in a selectable list. /// Also shows the currently loading receivers. @@ -122,12 +122,11 @@ fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) -> bool { entity_dbs.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started)); } - let active_recording = Some(ctx.store_context.recording.store_id()); - for (app_id, entity_dbs) in entity_dbs_map { if entity_dbs.len() == 1 { let entity_db = entity_dbs[0]; - recording_ui(ctx, ui, entity_db, Some(app_id), active_recording); + let include_app_id = true; + entity_db_button_ui(ctx, ui, entity_db, include_app_id); } else { ctx.re_ui .list_item(app_id) @@ -138,7 +137,8 @@ fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) -> bool { true, |_, ui| { for entity_db in entity_dbs { - recording_ui(ctx, ui, entity_db, None, active_recording); + let include_app_id = false; // we already show it in the parent + entity_db_button_ui(ctx, ui, entity_db, include_app_id); } }, ); @@ -148,93 +148,6 @@ fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) -> bool { true } -/// Show the UI for a single recording. -/// -/// If an `app_id_label` is provided, it will be shown in front of the recording time. -fn recording_ui( - ctx: &ViewerContext<'_>, - ui: &mut egui::Ui, - entity_db: &re_entity_db::EntityDb, - app_id_label: Option<&str>, - active_recording: Option<&re_log_types::StoreId>, -) { - let app_id_label = - app_id_label.map_or(String::new(), |app_id_label| format!("{app_id_label} - ")); - - let time = entity_db - .store_info() - .and_then(|info| { - info.started - .format_time_custom("[hour]:[minute]:[second]", ctx.app_options.time_zone) - }) - .unwrap_or("".to_owned()); - - let title = format!("{app_id_label}{time}"); - - let store_id = entity_db.store_id().clone(); - let item = re_viewer_context::Item::StoreId(store_id.clone()); - - let mut list_item = ctx - .re_ui - .list_item(title) - .selected(ctx.selection().contains_item(&item)) - .with_icon_fn(|_re_ui, ui, rect, visuals| { - let color = if active_recording == Some(&store_id) { - visuals.fg_stroke.color - } else { - ui.visuals().widgets.noninteractive.fg_stroke.color - }; - - re_ui::icons::STORE - .as_image() - .tint(color) - .paint_at(ui, rect); - }) - .with_buttons(|re_ui, ui| { - // Close-button: - let resp = re_ui - .small_icon_button(ui, &re_ui::icons::REMOVE) - .on_hover_text("Close this Recording (unsaved data will be lost)"); - if resp.clicked() { - ctx.command_sender - .send_system(SystemCommand::CloseRecordingId(store_id.clone())); - } - resp - }); - - if ctx.hovered().contains_item(&item) { - list_item = list_item.force_hovered(true); - } - - let response = list_item - .show_flat(ui) // never more than one level deep - .on_hover_ui(|ui| { - entity_db.data_ui( - ctx, - ui, - re_viewer_context::UiVerbosity::Full, - &ctx.current_query(), - entity_db.store(), - ); - }); - - if response.hovered() { - ctx.selection_state().set_hovered(item.clone()); - } - - if response.clicked() { - // Open the recording… - ctx.command_sender - .send_system(SystemCommand::SetRecordingId(store_id.clone())); - - // …and select the recording in the recording. - // Note that we must do it in this order, since the selection state is stored in the recording. - // That's also why we use a command to set the selection. - ctx.command_sender - .send_system(SystemCommand::SetSelection(store_id, item)); - } -} - fn add_button_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { use re_ui::UICommandSender; diff --git a/crates/re_viewer/src/ui/selection_history_ui.rs b/crates/re_viewer/src/ui/selection_history_ui.rs index 14121600bb23..e994fce08fe2 100644 --- a/crates/re_viewer/src/ui/selection_history_ui.rs +++ b/crates/re_viewer/src/ui/selection_history_ui.rs @@ -181,6 +181,7 @@ fn selection_to_string(blueprint: &ViewportBlueprint, selection: &ItemCollection fn item_to_string(blueprint: &ViewportBlueprint, item: &Item) -> String { match item { + Item::DataSource(data_source) => data_source.to_string(), Item::StoreId(store_id) => store_id.to_string(), Item::SpaceView(space_view_id) => { // TODO(#4678): unnamed space views should have their label formatted accordingly (subdued) diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 9c8d48e87c6a..86c8730ed697 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -255,6 +255,7 @@ fn container_children( fn data_section_ui(item: &Item) -> Option> { match item { + Item::DataSource(data_source) => Some(Box::new(data_source.clone())), Item::StoreId(store_id) => Some(Box::new(store_id.clone())), Item::ComponentPath(component_path) => Some(Box::new(component_path.clone())), Item::InstancePath(instance_path) | Item::DataResult(_, instance_path) => { @@ -297,6 +298,12 @@ fn what_is_selected_ui( item: &Item, ) { match item { + Item::DataSource(data_source) => { + let title = data_source.to_string(); + let icon = None; // TODO(#5645): an icon for data sources + item_title_ui(ctx.re_ui, ui, &title, icon, &title); + } + Item::StoreId(store_id) => { let id_str = format!("{} ID: {}", store_id.kind, store_id); @@ -793,9 +800,12 @@ fn show_list_item_for_container_child( fn has_blueprint_section(item: &Item) -> bool { match item { - Item::StoreId(_) | Item::ComponentPath(_) | Item::Container(_) | Item::InstancePath(_) => { - false - } + Item::DataSource(_) + | Item::StoreId(_) + | Item::ComponentPath(_) + | Item::Container(_) + | Item::InstancePath(_) => false, + Item::SpaceView(_) | Item::DataResult(_, _) => true, } } @@ -816,7 +826,11 @@ fn blueprint_ui( blueprint_ui_for_data_result(ui, ctx, viewport, space_view_id, instance_path); } - Item::StoreId(_) | Item::ComponentPath(_) | Item::Container(_) | Item::InstancePath(_) => {} + Item::DataSource(_) + | Item::StoreId(_) + | Item::ComponentPath(_) + | Item::Container(_) + | Item::InstancePath(_) => {} } } diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 08dd6d0be4b0..c7cd22ffdc79 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -23,6 +23,7 @@ re_log_types.workspace = true re_log.workspace = true re_query.workspace = true re_renderer.workspace = true +re_smart_channel.workspace = true re_string_interner.workspace = true re_tracing.workspace = true re_types = { workspace = true, features = ["ecolor", "glam", "image"] } diff --git a/crates/re_viewer_context/src/command_sender.rs b/crates/re_viewer_context/src/command_sender.rs index d07b33efaa1e..e0e3852efdf8 100644 --- a/crates/re_viewer_context/src/command_sender.rs +++ b/crates/re_viewer_context/src/command_sender.rs @@ -20,11 +20,13 @@ pub enum SystemCommand { /// Reset the `Blueprint` to the default state ResetBlueprint, - /// Change the active recording-id in the `StoreHub` - SetRecordingId(StoreId), + /// If this is a recording, switch to it. + /// If this is a blueprint, switch to the `AppId` of the blueprint, + /// and make this blueprint the active blueprint for that `AppId`. + ActivateStore(StoreId), - /// Close a recording - CloseRecordingId(StoreId), + /// Close a recording or blueprint (free its memory). + CloseStore(StoreId), /// Update the blueprint with additional data /// @@ -40,8 +42,14 @@ pub enum SystemCommand { /// Enable or disable the experimental dataframe space views. EnableExperimentalDataframeSpaceView(bool), - /// Set the selection in the recording config of the given recording. - SetSelection(StoreId, crate::Item), + /// Set the item selection. + SetSelection { + /// If set, use the recording config of this recording. + /// Else, use the currently active recording. + recording_id: Option, + + item: crate::Item, + }, /// Sets the focus to the given item. /// diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 847c10213227..71d1cb15f4a6 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -6,8 +6,11 @@ use crate::{ContainerId, SpaceViewId}; /// One "thing" in the UI. /// /// This is the granularity of what is selectable and hoverable. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Deserialize, serde::Serialize)] +#[derive(Clone, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)] pub enum Item { + /// A place where data comes from, e.g. the path to a .rrd or a TCP port. + DataSource(re_smart_channel::SmartChannelSource), + /// A recording (or blueprint) StoreId(re_log_types::StoreId), @@ -30,9 +33,13 @@ pub enum Item { impl Item { pub fn entity_path(&self) -> Option<&EntityPath> { match self { - Item::ComponentPath(component_path) => Some(&component_path.entity_path), - Item::SpaceView(_) | Item::Container(_) | Item::StoreId(_) => None, - Item::InstancePath(instance_path) | Item::DataResult(_, instance_path) => { + Self::DataSource(_) | Self::SpaceView(_) | Self::Container(_) | Self::StoreId(_) => { + None + } + + Self::ComponentPath(component_path) => Some(&component_path.entity_path), + + Self::InstancePath(instance_path) | Self::DataResult(_, instance_path) => { Some(&instance_path.entity_path) } } @@ -93,6 +100,7 @@ impl std::str::FromStr for Item { impl std::fmt::Debug for Item { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + Item::DataSource(data_source) => data_source.fmt(f), Item::StoreId(store_id) => store_id.fmt(f), Item::ComponentPath(s) => s.fmt(f), Item::SpaceView(s) => write!(f, "{s:?}"), @@ -108,6 +116,7 @@ impl std::fmt::Debug for Item { impl Item { pub fn kind(self: &Item) -> &'static str { match self { + Item::DataSource(_) => "Data source", Item::StoreId(store_id) => match store_id.kind { re_log_types::StoreKind::Recording => "Recording ID", re_log_types::StoreKind::Blueprint => "Blueprint ID", @@ -148,9 +157,11 @@ pub fn resolve_mono_instance_path_item( *space_view_id, resolve_mono_instance_path(query, store, instance_path), ), - Item::StoreId(_) | Item::ComponentPath(_) | Item::SpaceView(_) | Item::Container(_) => { - item.clone() - } + Item::DataSource(_) + | Item::StoreId(_) + | Item::ComponentPath(_) + | Item::SpaceView(_) + | Item::Container(_) => item.clone(), } } diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index 61ac60951e73..8f8810af75d4 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -358,10 +358,16 @@ impl ApplicationSelectionState { .hovered_previous_frame .iter_items() .any(|current| match current { - Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => current == test, + Item::DataSource(_) + | Item::StoreId(_) + | Item::SpaceView(_) + | Item::Container(_) => current == test, Item::ComponentPath(component_path) => match test { - Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => false, + Item::DataSource(_) + | Item::StoreId(_) + | Item::SpaceView(_) + | Item::Container(_) => false, Item::ComponentPath(test_component_path) => { test_component_path == component_path @@ -377,10 +383,12 @@ impl ApplicationSelectionState { }, Item::InstancePath(current_instance_path) => match test { - Item::StoreId(_) + Item::DataSource(_) + | Item::StoreId(_) | Item::ComponentPath(_) | Item::SpaceView(_) | Item::Container(_) => false, + Item::InstancePath(test_instance_path) | Item::DataResult(_, test_instance_path) => { current_instance_path.entity_path == test_instance_path.entity_path @@ -392,10 +400,12 @@ impl ApplicationSelectionState { }, Item::DataResult(_current_space_view_id, current_instance_path) => match test { - Item::StoreId(_) + Item::DataSource(_) + | Item::StoreId(_) | Item::ComponentPath(_) | Item::SpaceView(_) | Item::Container(_) => false, + Item::InstancePath(test_instance_path) | Item::DataResult(_, test_instance_path) => { current_instance_path.entity_path == test_instance_path.entity_path diff --git a/crates/re_viewer_context/src/store_context.rs b/crates/re_viewer_context/src/store_context.rs index abafb0d9c050..7f27eb3f9cd6 100644 --- a/crates/re_viewer_context/src/store_context.rs +++ b/crates/re_viewer_context/src/store_context.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityDb, StoreBundle}; -use re_log_types::ApplicationId; +use re_log_types::{ApplicationId, StoreId}; /// The current Blueprint and Recording being displayed by the viewer pub struct StoreContext<'a> { @@ -17,3 +17,9 @@ pub struct StoreContext<'a> { /// All the loaded recordings and blueprints. pub bundle: &'a StoreBundle, } + +impl StoreContext<'_> { + pub fn is_active(&self, store_id: &StoreId) -> bool { + self.recording.store_id() == store_id || self.blueprint.store_id() == store_id + } +} diff --git a/crates/re_viewport/Cargo.toml b/crates/re_viewport/Cargo.toml index b10509c45c57..d62d1827523e 100644 --- a/crates/re_viewport/Cargo.toml +++ b/crates/re_viewport/Cargo.toml @@ -28,6 +28,7 @@ re_renderer = { workspace = true, default-features = false, features = [ "import-obj", "serde", ] } +re_smart_channel.workspace = true re_space_view.workspace = true re_space_view_time_series.workspace = true re_tracing.workspace = true diff --git a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs index dcd2072f8229..6e04cb82f41e 100644 --- a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs +++ b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs @@ -24,8 +24,10 @@ impl ContextMenuAction for CollapseExpandAllAction { // TODO(ab): in an ideal world, we'd check the fully expended/collapsed state of the item to // avoid showing a command that wouldn't have an effect but that's lots of added complexity. match item { - Item::StoreId(_) | Item::ComponentPath(_) => false, + Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) => false, + Item::SpaceView(_) | Item::Container(_) | Item::InstancePath(_) => true, + //TODO(ab): for DataResult, walk the data result tree instead! Item::DataResult(_, instance_path) => ctx .viewer_context diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index 964b29d6889c..b7119855acae 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -301,6 +301,7 @@ trait ContextMenuAction { fn process_selection(&self, ctx: &ContextMenuContext<'_>) { for (item, _) in ctx.selection.iter() { match item { + Item::DataSource(data_source) => self.process_data_source(ctx, data_source), Item::StoreId(store_id) => self.process_store_id(ctx, store_id), Item::ComponentPath(component_path) => { self.process_component_path(ctx, component_path); @@ -315,6 +316,13 @@ trait ContextMenuAction { } } + fn process_data_source( + &self, + _ctx: &ContextMenuContext<'_>, + _data_source: &re_smart_channel::SmartChannelSource, + ) { + } + /// Process a single recording. fn process_store_id(&self, _ctx: &ContextMenuContext<'_>, _store_id: &re_log_types::StoreId) {} diff --git a/crates/re_viewport/src/space_view_highlights.rs b/crates/re_viewport/src/space_view_highlights.rs index c5859ca0899a..a06e3ebdaf3a 100644 --- a/crates/re_viewport/src/space_view_highlights.rs +++ b/crates/re_viewport/src/space_view_highlights.rs @@ -44,7 +44,7 @@ pub fn highlights_for_space_view( for current_selection in ctx.selection_state().selected_items().iter_items() { match current_selection { - Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => {} + Item::DataSource(_) | Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => {} Item::ComponentPath(component_path) => { let entity_hash = component_path.entity_path.hash(); @@ -80,7 +80,7 @@ pub fn highlights_for_space_view( for current_hover in ctx.selection_state().hovered_items().iter_items() { match current_hover { - Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => {} + Item::DataSource(_) | Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => {} Item::ComponentPath(component_path) => { let entity_hash = component_path.entity_path.hash(); diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index a062f8fb3ad3..cc23a5660392 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -256,7 +256,10 @@ impl ViewportBlueprint { /// If `false`, the item is referring to data that is not present in this blueprint. pub fn is_item_valid(&self, item: &Item) -> bool { match item { - Item::StoreId(_) | Item::ComponentPath(_) | Item::InstancePath(_) => true, + Item::DataSource(_) + | Item::StoreId(_) + | Item::ComponentPath(_) + | Item::InstancePath(_) => true, Item::SpaceView(space_view_id) => self.space_view(space_view_id).is_some(), diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 05973962d86b..79c7dcc8d3ef 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -88,7 +88,7 @@ impl Viewport<'_, '_> { }); } - /// Expend all required items and compute which item we should scroll to. + /// Expand all required items and compute which item we should scroll to. fn handle_focused_item( &self, ctx: &ViewerContext<'_>, @@ -144,7 +144,7 @@ impl Viewport<'_, '_> { )), ), - Item::StoreId(_) => None, + Item::DataSource(_) | Item::StoreId(_) => None, } } diff --git a/rerun_cpp/src/rerun/c/rerun.h b/rerun_cpp/src/rerun/c/rerun.h index 1cbd0191b6ca..52e7de7ee858 100644 --- a/rerun_cpp/src/rerun/c/rerun.h +++ b/rerun_cpp/src/rerun/c/rerun.h @@ -268,7 +268,7 @@ typedef struct rr_error { /// /// This should match the string returned by `rr_version_string`. /// If not, the SDK's binary and the C header are out of sync. -#define RERUN_SDK_HEADER_VERSION "0.15.0-alpha.2" +#define RERUN_SDK_HEADER_VERSION "0.15.0-alpha.3" /// Returns a human-readable version string of the Rerun C SDK. /// From 995a123c7af16847f4499416b99e37d9f5bd6305 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 25 Mar 2024 09:20:58 +0100 Subject: [PATCH 112/508] Warn user when a software rasterizer is used (#5655) ### What * Closes https://github.com/rerun-io/rerun/issues/5596 ![software-rasterizer](https://github.com/rerun-io/rerun/assets/1148717/ccab5b1d-fb40-4c0d-9379-8bf00aa73725) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5655/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5655/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5655/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5655) - [Docs preview](https://rerun.io/preview/4b8237229e8245e6b38dc915d52fc6d25fb34c95/docs) - [Examples preview](https://rerun.io/preview/4b8237229e8245e6b38dc915d52fc6d25fb34c95/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_renderer/src/context.rs | 4 ++-- crates/re_renderer/src/lib.rs | 2 +- crates/re_viewer/src/ui/top_panel.rs | 25 +++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/crates/re_renderer/src/context.rs b/crates/re_renderer/src/context.rs index be796b62c34c..d770785495a4 100644 --- a/crates/re_renderer/src/context.rs +++ b/crates/re_renderer/src/context.rs @@ -532,7 +532,7 @@ fn log_adapter_info(info: &wgpu::AdapterInfo) { let human_readable_summary = adapter_info_summary(info); if is_software_rasterizer_with_known_crashes { - re_log::warn!("Software rasterizer detected - expect poor performance and crashes. See: https://www.rerun.io/docs/getting-started/troubleshooting#graphics-issues"); + re_log::warn!("Bad software rasterizer detected - expect poor performance and crashes. See: https://www.rerun.io/docs/getting-started/troubleshooting#graphics-issues"); re_log::info!("wgpu adapter {human_readable_summary}"); } else if info.device_type == wgpu::DeviceType::Cpu { re_log::warn!("Software rasterizer detected - expect poor performance. See: https://www.rerun.io/docs/getting-started/troubleshooting#graphics-issues"); @@ -543,7 +543,7 @@ fn log_adapter_info(info: &wgpu::AdapterInfo) { } /// A human-readable summary about an adapter -fn adapter_info_summary(info: &wgpu::AdapterInfo) -> String { +pub fn adapter_info_summary(info: &wgpu::AdapterInfo) -> String { let wgpu::AdapterInfo { name, vendor: _, // skip integer id diff --git a/crates/re_renderer/src/lib.rs b/crates/re_renderer/src/lib.rs index 0ee7162edfcc..dc7eafa27232 100644 --- a/crates/re_renderer/src/lib.rs +++ b/crates/re_renderer/src/lib.rs @@ -51,7 +51,7 @@ pub use colormap::{ colormap_inferno_srgb, colormap_magma_srgb, colormap_plasma_srgb, colormap_srgb, colormap_turbo_srgb, colormap_viridis_srgb, grayscale_srgb, Colormap, }; -pub use context::RenderContext; +pub use context::{adapter_info_summary, RenderContext}; pub use debug_label::DebugLabel; pub use depth_offset::DepthOffset; pub use line_drawable_builder::{LineDrawableBuilder, LineStripBuilder}; diff --git a/crates/re_viewer/src/ui/top_panel.rs b/crates/re_viewer/src/ui/top_panel.rs index 3329e69a38ea..57826fc872f0 100644 --- a/crates/re_viewer/src/ui/top_panel.rs +++ b/crates/re_viewer/src/ui/top_panel.rs @@ -100,6 +100,31 @@ fn top_bar_ui( connection_status_ui(ui, app.msg_receive_set()); } + if let Some(wgpu) = frame.wgpu_render_state() { + let info = wgpu.adapter.get_info(); + if info.device_type == wgpu::DeviceType::Cpu { + // TODO(#4304): replace with a panel showing recent log messages + ui.hyperlink_to( + egui::RichText::new("⚠ Software rasterizer ⚠") + .small() + .color(ui.visuals().warn_fg_color), + "https://www.rerun.io/docs/getting-started/troubleshooting#graphics-issues", + ) + .on_hover_ui(|ui| { + ui.label("Software rasterizer detected - expect poor performance."); + ui.label( + "Rerun requires hardware accelerated graphics (i.e. a GPU) for good performance.", + ); + ui.label("Click for troubleshooting."); + ui.add_space(8.0); + ui.label(format!( + "wgpu adapter {}", + re_renderer::adapter_info_summary(&info) + )); + }); + } + } + // Warn if in debug build if cfg!(debug_assertions) && !app.is_screenshotting() { ui.vertical_centered(|ui| { From 10f963c19d26630c8d22621a73b37a6ad6cb2b66 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Mon, 25 Mar 2024 05:38:21 -0400 Subject: [PATCH 113/508] Simplify blueprint API by removing Viewport concept (#5656) ### What In writing the documentation I realized the distinction between the `rrb.Blueprint` object and the `rrb.Viewport` object was not meaningful enough to warrant its own concept for the user. Practically, the only time a user would ever use `rrb.Viewport` was to set `auto_layout`, `auto_space_views`, (and maybe maximized if we expose an API for that). Most of the other time they use a `ContainerLike` anyways. This makes introducing the extra `Viewport` indirection just feel like cognitive overhead. This moves the viewport properties to `rrb.Blueprint` object directly, and makes the viewport just be a single optional `ContainerLike` on the blueprint. Before: ``` ContainerLike: Container | SpaceView Viewport: root_container: ContainerLike auto_layout: bool auto_space_views: bool ViewportLike: Viewport | ContainerLIke Blueprint: viewport: ViewportLike blueprint_panel: BlueprintPanel selection_panel: SelectionPanel time_panel: TimePanel ``` After ``` ContainerLike: Container | SpaceView Blueprint: viewport: ContainerLike blueprint_panel: BlueprintPanel selection_panel: SelectionPanel time_panel: TimePanel auto_layout: bool auto_space_views: bool ``` Note: this does not change the archetype or viewer side of the code -- only the exposed APIs. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5656/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5656/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5656/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5656) - [Docs preview](https://rerun.io/preview/711bafa6af2902189d2458127e25468b1d8a03eb/docs) - [Examples preview](https://rerun.io/preview/711bafa6af2902189d2458127e25468b1d8a03eb/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/blueprint/main.py | 12 +- examples/python/blueprint_stocks/main.py | 49 +++--- rerun_py/docs/gen_common_index.py | 2 +- .../rerun_sdk/rerun/blueprint/__init__.py | 16 +- rerun_py/rerun_sdk/rerun/blueprint/api.py | 144 +++++++----------- tests/python/blueprint/main.py | 37 +++-- ...ntext_menu_add_entity_to_new_space_view.py | 22 ++- .../check_context_menu_collapse_expand_all.py | 20 ++- ...heck_context_menu_invalid_sub_container.py | 24 ++- .../check_context_menu_multi_selection.py | 16 +- .../check_context_menu_single_selection.py | 16 +- ...xt_menu_single_selection_blueprint_tree.py | 8 +- .../check_context_menu_suggested_origin.py | 10 +- tests/python/release_checklist/check_focus.py | 10 +- 14 files changed, 162 insertions(+), 224 deletions(-) diff --git a/examples/python/blueprint/main.py b/examples/python/blueprint/main.py index 401cc955fdfa..6a041918e2d4 100755 --- a/examples/python/blueprint/main.py +++ b/examples/python/blueprint/main.py @@ -6,7 +6,7 @@ import numpy as np import rerun as rr # pip install rerun-sdk -from rerun.blueprint import Blueprint, BlueprintPanel, Grid, SelectionPanel, Spatial2DView, TimePanel, Viewport +from rerun.blueprint import Blueprint, BlueprintPanel, Grid, SelectionPanel, Spatial2DView, TimePanel def main() -> None: @@ -26,16 +26,14 @@ def main() -> None: # If auto_space_views is True, the blueprint will automatically add one of the heuristic # space views, which will include the image and both rectangles. blueprint = Blueprint( - Viewport( - Grid( - Spatial2DView(name="Rect 0", origin="/", contents=["image", "rect/0"]), - Spatial2DView(name="Rect 1", origin="/", contents=["image", "rect/1"]), - ), - auto_space_views=args.auto_space_views, + Grid( + Spatial2DView(name="Rect 0", origin="/", contents=["image", "rect/0"]), + Spatial2DView(name="Rect 1", origin="/", contents=["image", "rect/1"]), ), BlueprintPanel(expanded=False), SelectionPanel(expanded=False), TimePanel(expanded=False), + auto_space_views=args.auto_space_views, ) rr.init("rerun_example_blueprint", spawn=True, blueprint=blueprint) diff --git a/examples/python/blueprint_stocks/main.py b/examples/python/blueprint_stocks/main.py index 1776b6598b09..35372767db88 100755 --- a/examples/python/blueprint_stocks/main.py +++ b/examples/python/blueprint_stocks/main.py @@ -21,17 +21,17 @@ ################################################################################ -def auto_blueprint() -> rrb.ViewportLike: +def auto_blueprint() -> rrb.BlueprintLike: """A blueprint enabling auto space views, which matches the application default.""" - return rrb.Viewport(auto_space_views=True, auto_layout=True) + return rrb.Blueprint(auto_space_views=True, auto_layout=True) -def one_stock(symbol: str) -> rrb.ViewportLike: +def one_stock(symbol: str) -> rrb.ContainerLike: """Create a blueprint showing a single stock.""" return rrb.TimeSeriesView(name=f"{symbol}", origin=f"/stocks/{symbol}") -def one_stock_with_info(symbol: str) -> rrb.ViewportLike: +def one_stock_with_info(symbol: str) -> rrb.ContainerLike: """Create a blueprint showing a single stock with its info arranged vertically.""" return rrb.Vertical( rrb.TextDocumentView(name=f"{symbol}", origin=f"/stocks/{symbol}/info"), @@ -40,7 +40,7 @@ def one_stock_with_info(symbol: str) -> rrb.ViewportLike: ) -def compare_two(symbol1: str, symbol2: str, day: Any) -> rrb.ViewportLike: +def compare_two(symbol1: str, symbol2: str, day: Any) -> rrb.ContainerLike: """Create a blueprint comparing 2 stocks for a single day.""" return rrb.TimeSeriesView( name=f"{symbol1} vs {symbol2} ({day})", @@ -51,7 +51,7 @@ def compare_two(symbol1: str, symbol2: str, day: Any) -> rrb.ViewportLike: ) -def one_stock_no_peaks(symbol: str) -> rrb.ViewportLike: +def one_stock_no_peaks(symbol: str) -> rrb.ContainerLike: """ Create a blueprint showing a single stock without annotated peaks. @@ -67,7 +67,7 @@ def one_stock_no_peaks(symbol: str) -> rrb.ViewportLike: ) -def stock_grid(symbols: list[str], dates: list[Any]) -> rrb.ViewportLike: +def stock_grid(symbols: list[str], dates: list[Any]) -> rrb.ContainerLike: """Create a grid of stocks and their time series over all days.""" return rrb.Vertical( contents=[ @@ -81,7 +81,7 @@ def stock_grid(symbols: list[str], dates: list[Any]) -> rrb.ViewportLike: ) -def hide_panels(viewport: rrb.ViewportLike) -> rrb.BlueprintLike: +def hide_panels(viewport: rrb.ContainerLike) -> rrb.BlueprintLike: """Wrap a viewport in a blueprint that hides the time and selection panels.""" return rrb.Blueprint( viewport, @@ -145,25 +145,26 @@ def main() -> None: symbols = ["AAPL", "AMZN", "GOOGL", "META", "MSFT"] dates = list(filter(lambda x: x.weekday() < 5, [current_date - dt.timedelta(days=i) for i in range(7, 0, -1)])) - blueprint: rrb.BlueprintLike - if args.blueprint == "auto": blueprint = auto_blueprint() - elif args.blueprint == "one-stock": - blueprint = one_stock("AAPL") - elif args.blueprint == "one-stock-with-info": - blueprint = one_stock_with_info("AMZN") - elif args.blueprint == "one-stock-no-peaks": - blueprint = one_stock_no_peaks("GOOGL") - elif args.blueprint == "compare-two": - blueprint = compare_two("META", "MSFT", dates[-1]) - elif args.blueprint == "grid": - blueprint = stock_grid(symbols, dates) else: - raise ValueError(f"Unknown blueprint: {args.blueprint}") - - if not args.show_panels: - blueprint = hide_panels(blueprint) + if args.blueprint == "one-stock": + viewport = one_stock("AAPL") + elif args.blueprint == "one-stock-with-info": + viewport = one_stock_with_info("AMZN") + elif args.blueprint == "one-stock-no-peaks": + viewport = one_stock_no_peaks("GOOGL") + elif args.blueprint == "compare-two": + viewport = compare_two("META", "MSFT", dates[-1]) + elif args.blueprint == "grid": + viewport = stock_grid(symbols, dates) + else: + raise ValueError(f"Unknown blueprint: {args.blueprint}") + + if not args.show_panels: + blueprint = hide_panels(viewport) + else: + blueprint = viewport rr.init("rerun_example_blueprint_stocks", spawn=True, blueprint=blueprint) diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 11cb5b9d6dac..76019472fc93 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -241,6 +241,7 @@ class Section: "Blueprint", "BlueprintPart", "Container", + "ContainerLike", "Horizontal", "Vertical", "Grid", @@ -256,7 +257,6 @@ class Section: "BlueprintPanel", "SelectionPanel", "TimePanel", - "Viewport", ], ), Section( diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index dcb0d6e06c95..1062d5442b12 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -1,17 +1,17 @@ from __future__ import annotations __all__ = [ - "archetypes", "BarChartView", "Blueprint", "BlueprintLike", "BlueprintPanel", "BlueprintPart", - "components", - "datatypes", + "Container", + "ContainerLike", "Grid", "Horizontal", "SelectionPanel", + "SpaceView", "Spatial2DView", "Spatial3DView", "Tabs", @@ -21,10 +21,9 @@ "TimePanel", "TimeSeriesView", "Vertical", - "Viewport", - "ViewportLike", - "SpaceView", - "Container", + "archetypes", + "components", + "datatypes", ] from . import archetypes, components, datatypes @@ -34,11 +33,10 @@ BlueprintPanel, BlueprintPart, Container, + ContainerLike, SelectionPanel, SpaceView, TimePanel, - Viewport, - ViewportLike, ) from .containers import Grid, Horizontal, Tabs, Vertical from .space_views import ( diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 3208cfe1c0a4..b296107065e2 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -74,15 +74,15 @@ def blueprint_path(self) -> str: """ return f"space_view/{self.id}" - def to_viewport(self) -> Viewport: - """Convert this space view to a viewport.""" + def to_container(self) -> Container: + """Convert this space view to a container.""" from .containers import Grid - return Viewport(Grid(self)) + return Grid(self) def to_blueprint(self) -> Blueprint: """Convert this space view to a full blueprint.""" - return Blueprint(self.to_viewport()) + return Blueprint(self) def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" @@ -190,13 +190,13 @@ def blueprint_path(self) -> str: """ return f"container/{self.id}" - def to_viewport(self) -> Viewport: - """Convert this container to a viewport.""" - return Viewport(self) + def to_container(self) -> Container: + """Convert this space view to a container.""" + return self def to_blueprint(self) -> Blueprint: """Convert this container to a full blueprint.""" - return Blueprint(self.to_viewport()) + return Blueprint(self) def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" @@ -230,78 +230,6 @@ def _iter_space_views(self) -> Iterable[bytes]: return itertools.chain.from_iterable(sub._iter_space_views() for sub in self.contents) -class Viewport: - """ - The top-level description of the Viewport. - - This is an ergonomic helper on top of [rerun.blueprint.archetypes.ViewportBlueprint][]. - """ - - def __init__( - self, - root_container: Container | None = None, - *, - auto_layout: bool | None = None, - auto_space_views: bool | None = None, - ): - """ - Construct a new viewport. - - Parameters - ---------- - root_container: - The container that sits at the top of the viewport hierarchy. The only content visible - in this viewport must be contained within this container. - auto_layout: - Whether to automatically layout the viewport. If `True`, the container layout will be - reset whenever a new space view is added to the viewport. Defaults to `False`. - auto_space_views: - Whether to automatically add space views to the viewport. If `True`, the viewport will - automatically add space views based on content in the data store. Defaults to `False`. - - """ - self.root_container = root_container - self.auto_layout = auto_layout - self.auto_space_views = auto_space_views - - def blueprint_path(self) -> str: - """ - The blueprint path where this space view will be logged. - - Note that although this is an `EntityPath`, is scoped to the blueprint tree and - not a part of the regular data hierarchy. - """ - return "viewport" - - def to_viewport(self) -> Viewport: - """Conform with the `ViewportLike` interface.""" - return self - - def to_blueprint(self) -> Blueprint: - """Convert this viewport to a full blueprint.""" - return Blueprint(self) - - def _log_to_stream(self, stream: RecordingStream) -> None: - """Internal method to convert to an archetype and log to the stream.""" - if self.root_container is not None: - self.root_container._log_to_stream(stream) - - root_container_id = self.root_container.id.bytes - space_views = list(self.root_container._iter_space_views()) - else: - root_container_id = None - space_views = [] - - arch = ViewportBlueprint( - space_views=space_views, - root_container=root_container_id, - auto_layout=self.auto_layout, - auto_space_views=self.auto_space_views, - ) - - stream.log(self.blueprint_path(), arch) # type: ignore[attr-defined] - - class Panel: """ Base class for the panel types. @@ -396,15 +324,15 @@ def __init__(self, *, expanded: bool | None = None): super().__init__(blueprint_path="time_panel", expanded=expanded) -ViewportLike = Union[Viewport, Container, SpaceView] +ContainerLike = Union[Container, SpaceView] """ -A type that can be converted to a viewport. +A type that can be converted to a container. -These types all implement a `to_viewport()` method that wraps them in the necessary +These types all implement a `to_container()` method that wraps them in the necessary helper classes. """ -BlueprintPart = Union[ViewportLike, BlueprintPanel, SelectionPanel, TimePanel] +BlueprintPart = Union[ContainerLike, BlueprintPanel, SelectionPanel, TimePanel] """ The types that make up a blueprint. """ @@ -416,31 +344,44 @@ class Blueprint: def __init__( self, *parts: BlueprintPart, + auto_layout: bool | None = None, + auto_space_views: bool | None = None, ): """ Construct a new blueprint from the given parts. Each [BlueprintPart][rerun.blueprint.BlueprintPart] can be one of the following: - - [Viewport][rerun.blueprint.Viewport] + - [ContainerLike][rerun.blueprint.ContainerLike] - [BlueprintPanel][rerun.blueprint.BlueprintPanel] - [SelectionPanel][rerun.blueprint.SelectionPanel] - [TimePanel][rerun.blueprint.TimePanel] It is an error to provide more than one of any type of part. + Blueprints only have a single top-level "root" container that defines the viewport. Any + other content should be nested under this container (or a nested sub-container). + Parameters ---------- *parts: The parts of the blueprint. + auto_layout: + Whether to automatically layout the viewport. If `True`, the container layout will be + reset whenever a new space view is added to the viewport. Defaults to `False`. + auto_space_views: + Whether to automatically add space views to the viewport. If `True`, the viewport will + automatically add space views based on content in the data store. Defaults to `False`. """ for part in parts: - if isinstance(part, (Viewport, Container, SpaceView)): - if hasattr(self, "viewport"): - raise ValueError("Only one viewport can be provided") - self.viewport = part.to_viewport() + if isinstance(part, (Container, SpaceView)): + if hasattr(self, "root_container"): + raise ValueError( + "Only one ContainerLike can be provided to serve as the root container for the viewport" + ) + self.root_container = part.to_container() elif isinstance(part, BlueprintPanel): if hasattr(self, "blueprint_panel"): raise ValueError("Only one blueprint panel can be provided") @@ -456,13 +397,33 @@ def __init__( else: raise ValueError(f"Unknown part type: {part}") + self.auto_layout = auto_layout + self.auto_space_views = auto_space_views + def to_blueprint(self) -> Blueprint: """Conform with the `BlueprintLike` interface.""" return self def _log_to_stream(self, stream: RecordingStream) -> None: """Internal method to convert to an archetype and log to the stream.""" - self.viewport._log_to_stream(stream) + if hasattr(self, "root_container"): + self.root_container._log_to_stream(stream) + + root_container_id = self.root_container.id.bytes + space_views = list(self.root_container._iter_space_views()) + else: + root_container_id = None + space_views = [] + + viewport_arch = ViewportBlueprint( + space_views=space_views, + root_container=root_container_id, + auto_layout=self.auto_layout, + auto_space_views=self.auto_space_views, + ) + + stream.log("viewport", viewport_arch) # type: ignore[attr-defined] + if hasattr(self, "blueprint_panel"): self.blueprint_panel._log_to_stream(stream) if hasattr(self, "selection_panel"): @@ -471,8 +432,7 @@ def _log_to_stream(self, stream: RecordingStream) -> None: self.time_panel._log_to_stream(stream) -BlueprintLike = Union[Blueprint, ViewportLike] - +BlueprintLike = Union[Blueprint, SpaceView, Container] """ A type that can be converted to a blueprint. diff --git a/tests/python/blueprint/main.py b/tests/python/blueprint/main.py index 73723bea1d9c..ab74738b558d 100644 --- a/tests/python/blueprint/main.py +++ b/tests/python/blueprint/main.py @@ -11,31 +11,28 @@ Tabs, TimePanel, Vertical, - Viewport, ) if __name__ == "__main__": blueprint = Blueprint( - Viewport( - Vertical( - Spatial3DView(origin="/test1"), - Horizontal( - Tabs( - Spatial3DView(origin="/test1"), - Spatial2DView(origin="/test2"), - ), - Grid( - Spatial3DView(origin="/test1"), - Spatial2DView(origin="/test2"), - Spatial3DView(origin="/test1"), - Spatial2DView(origin="/test2"), - grid_columns=3, - column_shares=[1, 1, 1], - ), - column_shares=[1, 2], + Vertical( + Spatial3DView(origin="/test1"), + Horizontal( + Tabs( + Spatial3DView(origin="/test1"), + Spatial2DView(origin="/test2"), ), - row_shares=[2, 1], - ) + Grid( + Spatial3DView(origin="/test1"), + Spatial2DView(origin="/test2"), + Spatial3DView(origin="/test1"), + Spatial2DView(origin="/test2"), + grid_columns=3, + column_shares=[1, 1, 1], + ), + column_shares=[1, 2], + ), + row_shares=[2, 1], ), TimePanel(expanded=False), ) diff --git a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py index e6bb9501ef9e..eb6df7907d83 100644 --- a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py +++ b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py @@ -30,18 +30,16 @@ def log_readme() -> None: def blueprint() -> rrb.BlueprintLike: - return rrb.Viewport( - rrb.Horizontal( - rrb.TextDocumentView(origin="readme"), - rrb.Vertical( - rrb.Spatial3DView(origin="/boxes3d"), - rrb.Spatial2DView(origin="/boxes2d"), - rrb.TextLogView(origin="/text_logs"), - rrb.BarChartView(origin="/bars"), - rrb.TensorView(origin="/tensor"), - ), - column_shares=[2, 1], - ) + return rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical( + rrb.Spatial3DView(origin="/boxes3d"), + rrb.Spatial2DView(origin="/boxes2d"), + rrb.TextLogView(origin="/text_logs"), + rrb.BarChartView(origin="/bars"), + rrb.TensorView(origin="/tensor"), + ), + column_shares=[2, 1], ) diff --git a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py index 141fd1169b52..9779ba648392 100644 --- a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py +++ b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py @@ -31,18 +31,16 @@ def log_readme() -> None: def blueprint() -> rrb.BlueprintLike: - return rrb.Viewport( - rrb.Horizontal( - rrb.TextDocumentView(origin="readme"), - rrb.Vertical( - rrb.Horizontal( - rrb.Vertical( - rrb.Spatial3DView(origin="/"), - ) + return rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical( + rrb.Horizontal( + rrb.Vertical( + rrb.Spatial3DView(origin="/"), ) - ), - column_shares=[2, 1], - ) + ) + ), + column_shares=[2, 1], ) diff --git a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py index d8bf755cd0cb..923fd4337827 100644 --- a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py +++ b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py @@ -23,20 +23,18 @@ def log_readme() -> None: def blueprint() -> rrb.BlueprintLike: - return rrb.Viewport( - rrb.Horizontal( - rrb.TextDocumentView(origin="readme"), - rrb.Grid( - rrb.Vertical( - rrb.Spatial3DView(origin="/"), - ), - rrb.Horizontal( - rrb.Spatial2DView(origin="/"), - ), - grid_columns=1, + return rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Grid( + rrb.Vertical( + rrb.Spatial3DView(origin="/"), ), - column_shares=[2, 1], - ) + rrb.Horizontal( + rrb.Spatial2DView(origin="/"), + ), + grid_columns=1, + ), + column_shares=[2, 1], ) diff --git a/tests/python/release_checklist/check_context_menu_multi_selection.py b/tests/python/release_checklist/check_context_menu_multi_selection.py index e8b5afd22e61..78fd703c6b10 100644 --- a/tests/python/release_checklist/check_context_menu_multi_selection.py +++ b/tests/python/release_checklist/check_context_menu_multi_selection.py @@ -65,15 +65,13 @@ def log_readme() -> None: def blueprint() -> rrb.BlueprintLike: - return rrb.Viewport( - rrb.Horizontal( - rrb.TextDocumentView(origin="readme"), - rrb.Vertical( - rrb.Spatial3DView(origin="/"), - rrb.Spatial2DView(origin="/"), - ), - column_shares=[2, 1], - ) + return rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical( + rrb.Spatial3DView(origin="/"), + rrb.Spatial2DView(origin="/"), + ), + column_shares=[2, 1], ) diff --git a/tests/python/release_checklist/check_context_menu_single_selection.py b/tests/python/release_checklist/check_context_menu_single_selection.py index a197508638e3..07bb9a73f7e0 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection.py +++ b/tests/python/release_checklist/check_context_menu_single_selection.py @@ -86,15 +86,13 @@ def log_readme() -> None: def blueprint() -> rrb.BlueprintLike: - return rrb.Viewport( - rrb.Horizontal( - rrb.TextDocumentView(origin="readme"), - rrb.Vertical( - rrb.Spatial3DView(origin="/"), - rrb.Spatial2DView(origin="/"), - ), - column_shares=[2, 1], - ) + return rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical( + rrb.Spatial3DView(origin="/"), + rrb.Spatial2DView(origin="/"), + ), + column_shares=[2, 1], ) diff --git a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py index 87c329a2dd76..ac5ce1211e47 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py +++ b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py @@ -69,11 +69,9 @@ def log_readme() -> None: def blueprint() -> rrb.BlueprintLike: - return rrb.Viewport( - rrb.Horizontal( - rrb.TextDocumentView(origin="readme"), - rrb.Vertical(rrb.Spatial3DView(origin="/")), - ) + return rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Vertical(rrb.Spatial3DView(origin="/")), ) diff --git a/tests/python/release_checklist/check_context_menu_suggested_origin.py b/tests/python/release_checklist/check_context_menu_suggested_origin.py index 33d1bed9b34b..66a079e9489f 100644 --- a/tests/python/release_checklist/check_context_menu_suggested_origin.py +++ b/tests/python/release_checklist/check_context_menu_suggested_origin.py @@ -45,12 +45,10 @@ def log_readme() -> None: def blueprint() -> rrb.BlueprintLike: - return rrb.Viewport( - rrb.Horizontal( - rrb.TextDocumentView(origin="readme"), - rrb.Spatial3DView(origin="/", contents="", name="root entity"), - column_shares=[2, 1], - ) + return rrb.Horizontal( + rrb.TextDocumentView(origin="readme"), + rrb.Spatial3DView(origin="/", contents="", name="root entity"), + column_shares=[2, 1], ) diff --git a/tests/python/release_checklist/check_focus.py b/tests/python/release_checklist/check_focus.py index bb37018df0d5..e72f11dd0469 100644 --- a/tests/python/release_checklist/check_focus.py +++ b/tests/python/release_checklist/check_focus.py @@ -22,12 +22,10 @@ def log_readme() -> None: def blueprint() -> rrb.BlueprintLike: - return rrb.Viewport( - rrb.Horizontal( - rrb.Tabs(*[rrb.TextDocumentView(origin="readme") for _ in range(100)]), - rrb.Vertical(rrb.Spatial3DView(origin="/", name="SV1"), rrb.Spatial3DView(origin="/", name="SV2")), - column_shares=[1, 2], - ) + return rrb.Horizontal( + rrb.Tabs(*[rrb.TextDocumentView(origin="readme") for _ in range(100)]), + rrb.Vertical(rrb.Spatial3DView(origin="/", name="SV1"), rrb.Spatial3DView(origin="/", name="SV2")), + column_shares=[1, 2], ) From 71ecddb31e9c9be562a40093ac225ccbc092e3a8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 25 Mar 2024 12:35:55 +0100 Subject: [PATCH 114/508] Improve logging around blueprint saving during shutdown (#5664) ### What * Part of https://github.com/rerun-io/rerun/issues/5629 Ignore whitespace when reading the diff ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5664/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5664/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5664/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5664) - [Docs preview](https://rerun.io/preview/3661ee3766211d083f381da0ad1d912c1382d5ef/docs) - [Examples preview](https://rerun.io/preview/3661ee3766211d083f381da0ad1d912c1382d5ef/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app.rs | 38 ++++++++++++++---------- crates/re_viewer/src/store_hub.rs | 49 ++++++++++++++++++------------- 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index c66ccee0f361..2820ccf812d4 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -974,8 +974,10 @@ impl App { store_hub.set_active_recording_id(store_id.clone()); } StoreKind::Blueprint => { - re_log::debug!("Activating newly loaded blueprint"); if let Some(info) = entity_db.store_info() { + re_log::debug!( + "Activating blueprint that was loaded from {channel_source}" + ); let app_id = info.application_id.clone(); store_hub.set_blueprint_for_app_id(store_id.clone(), app_id); } else { @@ -1179,20 +1181,26 @@ impl eframe::App for App { } fn save(&mut self, storage: &mut dyn eframe::Storage) { - if self.startup_options.persist_state { - // Save the app state - eframe::set_value(storage, eframe::APP_KEY, &self.state); - - // Save the blueprints - // TODO(#2579): implement web-storage for blueprints as well - if let Some(hub) = &mut self.store_hub { - match hub.gc_and_persist_app_blueprints(&self.state.app_options) { - Ok(f) => f, - Err(err) => { - re_log::error!("Saving blueprints failed: {err}"); - } - }; - } + if !self.startup_options.persist_state { + return; + } + + re_tracing::profile_function!(); + + // Save the app state + eframe::set_value(storage, eframe::APP_KEY, &self.state); + + // Save the blueprints + // TODO(#2579): implement web-storage for blueprints as well + if let Some(hub) = &mut self.store_hub { + match hub.gc_and_persist_app_blueprints(&self.state.app_options) { + Ok(f) => f, + Err(err) => { + re_log::error!("Saving blueprints failed: {err}"); + } + }; + } else { + re_log::error!("Could not save blueprints: the store hub is not available"); } } diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer/src/store_hub.rs index 689c6ba8bebc..ed6bc19786b6 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer/src/store_hub.rs @@ -367,33 +367,40 @@ impl StoreHub { // there may be other Blueprints in the Hub. for (app_id, blueprint_id) in &self.blueprint_by_app_id { - if let Some(blueprint) = self.store_bundle.get_mut(blueprint_id) { - if self.blueprint_last_save.get(blueprint_id) != Some(&blueprint.generation()) { - if app_options.blueprint_gc { - blueprint.gc_everything_but_the_latest_row(); - } + let Some(blueprint) = self.store_bundle.get_mut(blueprint_id) else { + re_log::debug!("Failed to find blueprint {blueprint_id}."); + continue; + }; + if self.blueprint_last_save.get(blueprint_id) == Some(&blueprint.generation()) { + continue; // no change since last save + } - #[cfg(not(target_arch = "wasm32"))] - { - let blueprint_path = default_blueprint_path(app_id)?; - re_log::debug_once!("Saving blueprint for {app_id} to {blueprint_path:?}"); + if app_options.blueprint_gc { + blueprint.gc_everything_but_the_latest_row(); + } - let messages = blueprint.to_messages(None)?; + #[cfg(not(target_arch = "wasm32"))] + { + let blueprint_path = default_blueprint_path(app_id)?; - // TODO(jleibs): Should we push this into a background thread? Blueprints should generally - // be small & fast to save, but maybe not once we start adding big pieces of user data? - crate::saving::encode_to_file(&blueprint_path, messages.iter())?; + let messages = blueprint.to_messages(None)?; - self.blueprint_last_save - .insert(blueprint_id.clone(), blueprint.generation()); - } - #[cfg(target_arch = "wasm32")] - { - _ = app_id; - } - } + // TODO(jleibs): Should we push this into a background thread? Blueprints should generally + // be small & fast to save, but maybe not once we start adding big pieces of user data? + crate::saving::encode_to_file(&blueprint_path, messages.iter())?; + + re_log::debug!("Saved blueprint for {app_id} to {blueprint_path:?}"); + + self.blueprint_last_save + .insert(blueprint_id.clone(), blueprint.generation()); + } + + #[cfg(target_arch = "wasm32")] + { + _ = app_id; } } + Ok(()) } From 32e28ae0785c46b12ab66da17d46ad447134d07d Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 25 Mar 2024 18:50:16 +0100 Subject: [PATCH 115/508] Fix crashing when querying app url from python without webviewer & build info (#5667) ### What Excluded from changelog since this can't happen in the releases we ship. Bit of a nieche case you'll hit when running a python notebook with a local rerun build that is lacking the webviewer. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5667/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5667/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5667/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5667) - [Docs preview](https://rerun.io/preview/f5e2106e27d5c62d59c5cba403cd16743b02f20b/docs) - [Examples preview](https://rerun.io/preview/f5e2106e27d5c62d59c5cba403cd16743b02f20b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt --- rerun_py/src/python_bridge.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index df650128e468..2f6393bbaf1e 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -930,7 +930,7 @@ fn version() -> String { /// Get a url to an instance of the web-viewer /// /// This may point to app.rerun.io or localhost depending on -/// whether `host_assets` was called. +/// whether [`start_web_viewer_server()`] was called. #[pyfunction] fn get_app_url() -> String { #[cfg(feature = "web_viewer")] @@ -939,8 +939,14 @@ fn get_app_url() -> String { } let build_info = re_build_info::build_info!(); - let short_git_hash = &build_info.git_hash[..7]; - format!("https://app.rerun.io/commit/{short_git_hash}") + if let Some(short_git_hash) = build_info.git_hash.get(..7) { + format!("https://app.rerun.io/commit/{short_git_hash}") + } else { + re_log::warn_once!( + "No valid git hash found in build info. Defaulting to app.rerun.io for app url." + ); + "https://app.rerun.io".to_owned() + } } // TODO(jleibs) expose this as a python type From 430a4c0489832fad415b9255f3f1dee1430c1708 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 25 Mar 2024 19:54:02 +0100 Subject: [PATCH 116/508] Fix missing application id in RRT* example (#5676) ### What * Closes https://github.com/rerun-io/rerun/issues/5668 (we seed the RNG for examples that start with "rerun_example_") ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5676/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5676/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5676/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5676) - [Docs preview](https://rerun.io/preview/59dd55d0123687ba0d419e658e6a89c3592ab9e9/docs) - [Examples preview](https://rerun.io/preview/59dd55d0123687ba0d419e658e6a89c3592ab9e9/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/rrt-star/main.py | 2 +- scripts/lint.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/python/rrt-star/main.py b/examples/python/rrt-star/main.py index 073a17d4c428..1438640d1392 100755 --- a/examples/python/rrt-star/main.py +++ b/examples/python/rrt-star/main.py @@ -259,7 +259,7 @@ def main() -> None: parser.add_argument("--max-step-size", type=float, default=0.1) parser.add_argument("--iterations", type=int, help="How many iterations it should do") args = parser.parse_args() - rr.script_setup(args, "") + rr.script_setup(args, "rerun_example_rrt_star") max_step_size = args.max_step_size neighborhood_size = max_step_size * 1.5 diff --git a/scripts/lint.py b/scripts/lint.py index 2ef7126ff478..130f0eca1144 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -156,10 +156,10 @@ def lint_line( if not is_in_docstring: if m := re.search( - r'(RecordingStreamBuilder::new|\.init|RecordingStream)\("(\w+)', + r'(RecordingStreamBuilder::new|\.init|RecordingStream)\("(\w*)', line, ) or re.search( - r'(rr.script_setup)\(args, "(\w+)', + r'(rr.script_setup)\(args, "(\w*)', line, ): app_id = m.group(2) @@ -229,6 +229,7 @@ def test_lint_line() -> None: "template ", 'protoc_prebuilt::init("22.0")', 'rr.init("rerun_example_app")', + 'rr.script_setup(args, "rerun_example_app")', """ #[inline] fn foo(mut self) -> Self { @@ -310,6 +311,7 @@ def test_lint_line() -> None: 'RecordingStream("missing_prefix")', 'rr.init("missing_prefix")', 'rr.script_setup(args, "missing_prefix")', + 'rr.script_setup(args, "")', "I accidentally wrote the same same word twice", "fn foo(mut self) -> Self {", "fn deref(&self) -> Self::Target {", From 4280fd47d35f1b59a89d61e237f3dd7228f97b1f Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 26 Mar 2024 09:36:13 +0100 Subject: [PATCH 117/508] Fix broken 2D Space View heuristics in Python Notebooks (#5674) ### What * Fixes #5654 could in theory affect also non-notebooks, but practically in only manifested there. Fixes a few typos I encountered on the way and added a new pixi command for building the rerun webviewer wasm. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5674/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5674/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5674/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5674) - [Docs preview](https://rerun.io/preview/618e0091e723020b96d06445d36c51c14a9067e3/docs) - [Examples preview](https://rerun.io/preview/618e0091e723020b96d06445d36c51c14a9067e3/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/max_image_dimension_subscriber.rs | 2 +- .../src/space_view_2d.rs | 5 ++-- .../src/spatial_topology.rs | 3 +- crates/re_viewer/src/app.rs | 2 +- pixi.toml | 29 ++++++++++++------- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/crates/re_space_view_spatial/src/max_image_dimension_subscriber.rs b/crates/re_space_view_spatial/src/max_image_dimension_subscriber.rs index 1dd5cc4d8ec9..d20bc630e1f9 100644 --- a/crates/re_space_view_spatial/src/max_image_dimension_subscriber.rs +++ b/crates/re_space_view_spatial/src/max_image_dimension_subscriber.rs @@ -32,7 +32,7 @@ impl MaxImageDimensions { } #[derive(Default)] -struct MaxImageDimensionSubscriber { +pub struct MaxImageDimensionSubscriber { max_dimensions: HashMap, } diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index 22268a10cb35..b2f3e1b841d4 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -63,8 +63,9 @@ impl SpaceViewClass for SpatialSpaceView2D { &self, system_registry: &mut re_viewer_context::SpaceViewSystemRegistrator<'_>, ) -> Result<(), SpaceViewClassRegistryError> { - // Ensure spatial topology is registered. + // Ensure spatial topology & max image dimension is registered. crate::spatial_topology::SpatialTopologyStoreSubscriber::subscription_handle(); + crate::max_image_dimension_subscriber::MaxImageDimensionSubscriber::subscription_handle(); register_spatial_contexts(system_registry)?; register_2d_spatial_visualizers(system_registry)?; @@ -410,7 +411,7 @@ fn recommended_space_views_with_image_splits( } } } else { - // Otherwise we can use the space as it is + // Otherwise we can use the space as it is. recommended.push(RecommendedSpaceView::new_subtree(recommended_root.clone())); } } diff --git a/crates/re_space_view_spatial/src/spatial_topology.rs b/crates/re_space_view_spatial/src/spatial_topology.rs index 01bcdb11dcc3..d70a1fe3f377 100644 --- a/crates/re_space_view_spatial/src/spatial_topology.rs +++ b/crates/re_space_view_spatial/src/spatial_topology.rs @@ -44,6 +44,7 @@ bitflags::bitflags! { /// Within the tree of all subspaces, every entity is contained in exactly one subspace. /// The subtree at (and including) the `origin` minus the /// subtrees of all child spaces are considered to be contained in a subspace. +#[derive(Debug)] pub struct SubSpace { /// The transform root of this subspace. /// @@ -166,7 +167,7 @@ impl StoreSubscriber for SpatialTopologyStoreSubscriber { } } -/// Spatial toopological information about a store. +/// Spatial topological information about a store. /// /// Describes how 2D & 3D spaces are connected/disconnected. /// diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 2820ccf812d4..83295a21eb31 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -954,7 +954,7 @@ impl App { store_hub.set_active_recording_id(store_id.clone()); } StoreKind::Blueprint => { - // We wait with activaing blueprints until they are fully loaded, + // We wait with activating blueprints until they are fully loaded, // so that we don't run heuristics on half-loaded blueprints. // TODO(#5297): heed special "end-of-blueprint" message to activate blueprint. // Otherwise on a mixed connection (SDK sending both blueprint and recording) diff --git a/pixi.toml b/pixi.toml index a92d738dc1fe..82b873e67fcf 100644 --- a/pixi.toml +++ b/pixi.toml @@ -46,11 +46,15 @@ rerun-release = "cargo run --package rerun-cli --no-default-features --features # # This installs the `wasm32-unknown-unknown` rust target if it's not already installed. # (this looks heavy but takes typically below 0.1s!) -rerun-web = """ - rustup target add wasm32-unknown-unknown - && cargo run -p re_build_web_viewer -- --debug - && cargo run --package rerun-cli --no-default-features --features web_viewer -- --web-viewer -""" +rerun-web = { cmd = "cargo run --package rerun-cli --no-default-features --features web_viewer -- --web-viewer", depends_on = [ + "rerun-build-web", +] } + +# Compile the web-viewer wasm, does not include the cli. +# +# This installs the `wasm32-unknown-unknown` rust target if it's not already installed. +# (this looks heavy but takes typically below 0.1s!) +rerun-build-web = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --debug" # Compile and run the web-viewer in release mode via rerun-cli. # @@ -58,11 +62,16 @@ rerun-web = """ # # This installs the `wasm32-unknown-unknown` rust target if it's not already installed. # (this looks heavy but takes typically below 0.1s!) -rerun-release-web = """ - rustup target add wasm32-unknown-unknown - && cargo run -p re_build_web_viewer -- --release - && cargo run --package rerun-cli --no-default-features --features web_viewer --release -- --web-viewer -""" +rerun-web-release = { cmd = "cargo run --package rerun-cli --no-default-features --features web_viewer --release -- --web-viewer", depends_on = [ + "rerun-build-web-release", +] } + +# Compile the web-viewer wasm in release mode, doe not include the cli. +# +# This installs the `wasm32-unknown-unknown` rust target if it's not already installed. +# (this looks heavy but takes typically below 0.1s!) +rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --release" + build-examples = "cargo run -q --locked -p re_build_examples --" From e5ebdf66ce7d2cd47623b31fd78826a68b92fb39 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 26 Mar 2024 10:47:09 +0100 Subject: [PATCH 118/508] Docs: improve discoverability of image compression (#5675) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What We often talk to customers that are unaware that we support logging encoded/compressed images. So I added some docs for this (in 3096c17). This became a 🐰🕳️ because the doc tags (`\py` etc) didn't work as expected: they would put all language-specific stuff _at the end_, but in this case I wanted it interleaved into the rest of the docs. So I fixed that, with a lot of effort. Now `\cpp`, `\py`, `\rs` acts like a simple per-line filter. In the meantime I removed some unused code, making everything shorter in the process. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5675/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5675/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5675/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5675) - [Docs preview](https://rerun.io/preview/5e9c4730e352b2fa9ed32406937e317552387660/docs) - [Examples preview](https://rerun.io/preview/5e9c4730e352b2fa9ed32406937e317552387660/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../definitions/rerun/archetypes/image.fbs | 8 +- .../definitions/rerun/archetypes/points2d.fbs | 4 +- .../definitions/rerun/archetypes/points3d.fbs | 4 +- .../rerun/datatypes/tensor_buffer.fbs | 2 +- crates/re_types/src/archetypes/image.rs | 4 + .../re_types/src/datatypes/tensor_buffer.rs | 2 +- crates/re_types_builder/src/codegen/common.rs | 190 +++++++----------- .../re_types_builder/src/codegen/cpp/mod.rs | 2 +- .../re_types_builder/src/codegen/docs/mod.rs | 13 +- crates/re_types_builder/src/codegen/mod.rs | 2 +- .../src/codegen/python/mod.rs | 11 +- .../re_types_builder/src/codegen/rust/api.rs | 2 +- crates/re_types_builder/src/docs.rs | 110 ++++++++++ crates/re_types_builder/src/lib.rs | 21 +- crates/re_types_builder/src/objects.rs | 158 +-------------- .../reference/types/archetypes/image.md | 3 + rerun_cpp/src/rerun/archetypes/image.hpp | 4 + .../src/rerun/datatypes/tensor_buffer.hpp | 4 +- rerun_py/rerun_sdk/rerun/archetypes/image.py | 5 +- .../rerun/datatypes/tensor_buffer.py | 4 +- 20 files changed, 250 insertions(+), 303 deletions(-) create mode 100644 crates/re_types_builder/src/docs.rs diff --git a/crates/re_types/definitions/rerun/archetypes/image.fbs b/crates/re_types/definitions/rerun/archetypes/image.fbs index d7f4bccf7b6b..3d9ab91b2126 100644 --- a/crates/re_types/definitions/rerun/archetypes/image.fbs +++ b/crates/re_types/definitions/rerun/archetypes/image.fbs @@ -16,10 +16,16 @@ namespace rerun.archetypes; /// Leading and trailing unit-dimensions are ignored, so that /// `1x640x480x3x1` is treated as a `640x480x3` RGB image. /// +/// Rerun also supports compressed image encoded as JPEG, N12, and YUY2. +/// Using these formats can save a lot of bandwidth and memory. +/// \py To compress an image, use [`rerun.Image.compress`][]. +/// \py To pass in an already encoded image, use [`rerun.ImageEncoded`][]. +/// \rs See [`crate::components::TensorData`] for more. +/// \cpp See [`rerun::datatypes::TensorBuffer`] for more. +/// /// \cpp Since the underlying `rerun::datatypes::TensorData` uses `rerun::Collection` internally, /// \cpp data can be passed in without a copy from raw pointers or by reference from `std::vector`/`std::array`/c-arrays. /// \cpp If needed, this "borrow-behavior" can be extended by defining your own `rerun::CollectionAdapter`. -/// \python For an easy way to pass in image formats or encoded images, see [`rerun.ImageEncoded`][]. /// /// \example image_simple image="https://static.rerun.io/image_simple/06ba7f8582acc1ffb42a7fd0006fad7816f3e4e4/1200w.png" table Image ( diff --git a/crates/re_types/definitions/rerun/archetypes/points2d.fbs b/crates/re_types/definitions/rerun/archetypes/points2d.fbs index 7e4f70d4fb94..fdc48f20edf9 100644 --- a/crates/re_types/definitions/rerun/archetypes/points2d.fbs +++ b/crates/re_types/definitions/rerun/archetypes/points2d.fbs @@ -28,8 +28,8 @@ table Points2D ( /// Optional colors for the points. /// - /// \python The colors are interpreted as RGB or RGBA in sRGB gamma-space, - /// \python As either 0-1 floats or 0-255 integers, with separate alpha. + /// \py The colors are interpreted as RGB or RGBA in sRGB gamma-space, + /// \py As either 0-1 floats or 0-255 integers, with separate alpha. colors: [rerun.components.Color] ("attr.rerun.component_recommended", nullable, order: 2100); // --- Optional --- diff --git a/crates/re_types/definitions/rerun/archetypes/points3d.fbs b/crates/re_types/definitions/rerun/archetypes/points3d.fbs index aa109118fe3d..f569f0caabec 100644 --- a/crates/re_types/definitions/rerun/archetypes/points3d.fbs +++ b/crates/re_types/definitions/rerun/archetypes/points3d.fbs @@ -26,8 +26,8 @@ table Points3D ( /// Optional colors for the points. /// - /// \python The colors are interpreted as RGB or RGBA in sRGB gamma-space, - /// \python As either 0-1 floats or 0-255 integers, with separate alpha. + /// \py The colors are interpreted as RGB or RGBA in sRGB gamma-space, + /// \py As either 0-1 floats or 0-255 integers, with separate alpha. colors: [rerun.components.Color] ("attr.rerun.component_recommended", nullable, order: 2100); // --- Optional --- diff --git a/crates/re_types/definitions/rerun/datatypes/tensor_buffer.fbs b/crates/re_types/definitions/rerun/datatypes/tensor_buffer.fbs index a84830e4c89c..52b25cf07c5e 100644 --- a/crates/re_types/definitions/rerun/datatypes/tensor_buffer.fbs +++ b/crates/re_types/definitions/rerun/datatypes/tensor_buffer.fbs @@ -110,7 +110,7 @@ union TensorBuffer ( /// First comes entire image in Y, followed by interleaved lines ordered as U0, V0, U1, V1, etc. NV12: NV12Buffer (transparent), - /// YUY2, also known as YUYV is a YUV 4:2:2 chrome downsampled format with 8 bits per channel. + /// YUY2, also known as YUYV is a YUV 4:2:2 chroma downsampled format with 8 bits per channel. /// /// The order of the channels is Y0, U0, Y1, V0. YUY2: YUY2Buffer (transparent), diff --git a/crates/re_types/src/archetypes/image.rs b/crates/re_types/src/archetypes/image.rs index 524ce24a934f..8b8ce27d2bda 100644 --- a/crates/re_types/src/archetypes/image.rs +++ b/crates/re_types/src/archetypes/image.rs @@ -31,6 +31,10 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// Leading and trailing unit-dimensions are ignored, so that /// `1x640x480x3x1` is treated as a `640x480x3` RGB image. /// +/// Rerun also supports compressed image encoded as JPEG, N12, and YUY2. +/// Using these formats can save a lot of bandwidth and memory. +/// See [`crate::components::TensorData`] for more. +/// /// ## Example /// /// ### `image_simple`: diff --git a/crates/re_types/src/datatypes/tensor_buffer.rs b/crates/re_types/src/datatypes/tensor_buffer.rs index d52e2d0fdfa8..9a2f31994eca 100644 --- a/crates/re_types/src/datatypes/tensor_buffer.rs +++ b/crates/re_types/src/datatypes/tensor_buffer.rs @@ -67,7 +67,7 @@ pub enum TensorBuffer { /// First comes entire image in Y, followed by interleaved lines ordered as U0, V0, U1, V1, etc. Nv12(::re_types_core::ArrowBuffer), - /// YUY2, also known as YUYV is a YUV 4:2:2 chrome downsampled format with 8 bits per channel. + /// YUY2, also known as YUYV is a YUV 4:2:2 chroma downsampled format with 8 bits per channel. /// /// The order of the channels is Y0, U0, Y1, V0. Yuy2(::re_types_core::ArrowBuffer), diff --git a/crates/re_types_builder/src/codegen/common.rs b/crates/re_types_builder/src/codegen/common.rs index 32da398c557b..e3ee8423e00e 100644 --- a/crates/re_types_builder/src/codegen/common.rs +++ b/crates/re_types_builder/src/codegen/common.rs @@ -12,35 +12,6 @@ fn is_blank>(line: T) -> bool { line.as_ref().chars().all(char::is_whitespace) } -/// Retrieves the global and tagged documentation from a [`Docs`] object. -pub fn get_documentation(docs: &Docs, tags: &[&str]) -> Vec { - let mut lines = docs.doc.clone(); - - for tag in tags { - lines.extend( - docs.tagged_docs - .get(*tag) - .unwrap_or(&Vec::new()) - .iter() - .cloned(), - ); - } - - // NOTE: remove duplicated blank lines. - lines.dedup(); - - // NOTE: remove trailing blank lines. - while let Some(line) = lines.last() { - if line.is_empty() { - lines.pop(); - } else { - break; - } - } - - lines -} - #[derive(Clone)] pub struct ExampleInfo<'a> { /// The snake_case name of the example. @@ -60,66 +31,62 @@ pub struct ExampleInfo<'a> { impl<'a> ExampleInfo<'a> { /// Parses e.g. `// \example example_name title="Example Title" image="https://www.example.com/img.png"` - pub fn parse(tag_content: &'a impl AsRef) -> Self { - fn mono(tag_content: &str) -> ExampleInfo<'_> { - fn find_keyed<'a>(tag: &str, args: &'a str) -> Option<&'a str> { - let mut prev_end = 0; - loop { - if prev_end + tag.len() + "=\"\"".len() >= args.len() { - return None; - } - let key_start = prev_end + args[prev_end..].find(tag)?; - let key_end = key_start + tag.len(); - if !args[key_end..].starts_with("=\"") { - prev_end = key_end; - continue; - }; - let value_start = key_end + "=\"".len(); - let Some(mut value_end) = args[value_start..].find('"') else { - prev_end = value_start; - continue; - }; - value_end += value_start; - return Some(&args[value_start..value_end]); + pub fn parse(tag_content: &'a str) -> Self { + fn find_keyed<'a>(tag: &str, args: &'a str) -> Option<&'a str> { + let mut prev_end = 0; + loop { + if prev_end + tag.len() + "=\"\"".len() >= args.len() { + return None; } + let key_start = prev_end + args[prev_end..].find(tag)?; + let key_end = key_start + tag.len(); + if !args[key_end..].starts_with("=\"") { + prev_end = key_end; + continue; + }; + let value_start = key_end + "=\"".len(); + let Some(mut value_end) = args[value_start..].find('"') else { + prev_end = value_start; + continue; + }; + value_end += value_start; + return Some(&args[value_start..value_end]); } + } - let tag_content = tag_content.trim(); - let (name, args) = tag_content - .split_once(' ') - .map_or((tag_content, None), |(a, b)| (a, Some(b))); - - let (mut title, mut image, mut exclude_from_api_docs) = (None, None, false); + let tag_content = tag_content.trim(); + let (name, args) = tag_content + .split_once(' ') + .map_or((tag_content, None), |(a, b)| (a, Some(b))); - if let Some(args) = args { - let args = args.trim(); + let (mut title, mut image, mut exclude_from_api_docs) = (None, None, false); - exclude_from_api_docs = args.contains("!api"); - let args = if let Some(args_without_api_prefix) = args.strip_prefix("!api") { - args_without_api_prefix.trim() - } else { - args - }; + if let Some(args) = args { + let args = args.trim(); - if args.starts_with('"') { - // \example example_name "Example Title" - title = args.strip_prefix('"').and_then(|v| v.strip_suffix('"')); - } else { - // \example example_name title="Example Title" image="https://static.rerun.io/annotation_context_rects/9b446c36011ed30fce7dc6ed03d5fd9557460f70/1200w.png" - title = find_keyed("title", args); - image = find_keyed("image", args).map(ImageUrl::parse); - } - } + exclude_from_api_docs = args.contains("!api"); + let args = if let Some(args_without_api_prefix) = args.strip_prefix("!api") { + args_without_api_prefix.trim() + } else { + args + }; - ExampleInfo { - name, - title, - image, - exclude_from_api_docs, + if args.starts_with('"') { + // \example example_name "Example Title" + title = args.strip_prefix('"').and_then(|v| v.strip_suffix('"')); + } else { + // \example example_name title="Example Title" image="https://static.rerun.io/annotation_context_rects/9b446c36011ed30fce7dc6ed03d5fd9557460f70/1200w.png" + title = find_keyed("title", args); + image = find_keyed("image", args).map(ImageUrl::parse); } } - mono(tag_content.as_ref()) + ExampleInfo { + name, + title, + image, + exclude_from_api_docs, + } } } @@ -314,46 +281,41 @@ pub fn collect_snippets_for_api_docs<'a>( extension: &str, required: bool, ) -> anyhow::Result>> { - let mut out = Vec::new(); + let base_path = crate::rerun_workspace_path().join("docs/snippets/all"); - if let Some(examples) = docs.tagged_docs.get("example") { - let base_path = crate::rerun_workspace_path().join("docs/snippets/all"); + let examples: Vec<&'a str> = docs.doc_lines_tagged("example"); - for base @ ExampleInfo { - name, - exclude_from_api_docs, - .. - } in examples.iter().map(ExampleInfo::parse) - { - if exclude_from_api_docs { - continue; - } + let mut out: Vec> = Vec::new(); - let path = base_path.join(format!("{name}.{extension}")); - let content = match std::fs::read_to_string(&path) { - Ok(content) => content, - Err(_) if !required => continue, - Err(err) => { - return Err(err).with_context(|| format!("couldn't open snippet {path:?}")) - } - }; - let mut content = content - .split('\n') - .map(String::from) - .skip_while(|line| line.starts_with("//") || line.starts_with(r#"""""#)) // Skip leading comments. - .skip_while(|line| line.trim().is_empty()) // Strip leading empty lines. - .collect_vec(); - - // trim trailing blank lines - while content.last().is_some_and(is_blank) { - content.pop(); - } + for example in &examples { + let base: ExampleInfo<'a> = ExampleInfo::parse(example); + let name = &base.name; + if base.exclude_from_api_docs { + continue; + } - out.push(Example { - base, - lines: content, - }); + let path = base_path.join(format!("{name}.{extension}")); + let content = match std::fs::read_to_string(&path) { + Ok(content) => content, + Err(_) if !required => continue, + Err(err) => return Err(err).with_context(|| format!("couldn't open snippet {path:?}")), + }; + let mut content = content + .split('\n') + .map(String::from) + .skip_while(|line| line.starts_with("//") || line.starts_with(r#"""""#)) // Skip leading comments. + .skip_while(|line| line.trim().is_empty()) // Strip leading empty lines. + .collect_vec(); + + // trim trailing blank lines + while content.last().is_some_and(is_blank) { + content.pop(); } + + out.push(Example { + base, + lines: content, + }); } Ok(out) diff --git a/crates/re_types_builder/src/codegen/cpp/mod.rs b/crates/re_types_builder/src/codegen/cpp/mod.rs index 697546ab5146..1c48d66edfb3 100644 --- a/crates/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/re_types_builder/src/codegen/cpp/mod.rs @@ -2265,7 +2265,7 @@ fn quote_field_docs(field: &ObjectField) -> TokenStream { } fn lines_from_docs(docs: &Docs) -> Vec { - let mut lines = crate::codegen::get_documentation(docs, &["cpp", "c++"]); + let mut lines = docs.doc_lines_for_untagged_and("cpp"); let required = true; let examples = collect_snippets_for_api_docs(docs, "cpp", required).unwrap_or_default(); diff --git a/crates/re_types_builder/src/codegen/docs/mod.rs b/crates/re_types_builder/src/codegen/docs/mod.rs index 1acf6e21fce7..119c48fb76c7 100644 --- a/crates/re_types_builder/src/codegen/docs/mod.rs +++ b/crates/re_types_builder/src/codegen/docs/mod.rs @@ -9,8 +9,6 @@ use crate::{ type ObjectMap = std::collections::BTreeMap; -use super::common::get_documentation; - macro_rules! putln { ($o:ident) => ( writeln!($o).ok() ); ($o:ident, $($tt:tt)*) => ( writeln!($o, $($tt)*).ok() ); @@ -143,19 +141,16 @@ fn index_page(kind: ObjectKind, order: u64, prelude: &str, objects: &[&Object]) fn object_page(reporter: &Reporter, object: &Object, object_map: &ObjectMap) -> String { let is_unreleased = object.is_attr_set(crate::ATTR_DOCS_UNRELEASED); - let top_level_docs = get_documentation(&object.docs, &[]); + let top_level_docs = object.docs.untagged(); if top_level_docs.is_empty() { reporter.error(&object.virtpath, &object.fqname, "Undocumented object"); } - let examples = object - .docs - .tagged_docs - .get("example") + let examples = &object.docs.doc_lines_tagged("example"); + let examples = examples .iter() - .flat_map(|v| v.iter()) - .map(ExampleInfo::parse) + .map(|line| ExampleInfo::parse(line)) .collect::>(); let mut page = String::new(); diff --git a/crates/re_types_builder/src/codegen/mod.rs b/crates/re_types_builder/src/codegen/mod.rs index 32428d554476..2f5aaa3fee35 100644 --- a/crates/re_types_builder/src/codegen/mod.rs +++ b/crates/re_types_builder/src/codegen/mod.rs @@ -32,7 +32,7 @@ pub(crate) use macros::autogen_warning; // Hack for declaring macros as `pub(cra // --- pub(crate) mod common; -use self::common::{get_documentation, StringExt}; +use self::common::StringExt; mod cpp; mod docs; diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index 08d806e0c3e0..f41c57804000 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -1157,7 +1157,7 @@ fn quote_obj_docs(obj: &Object) -> String { } fn lines_from_docs(docs: &Docs) -> Vec { - let mut lines = crate::codegen::get_documentation(docs, &["py", "python"]); + let mut lines = docs.doc_lines_for_untagged_and("py"); let examples = collect_snippets_for_api_docs(docs, "py", true).unwrap(); if !examples.is_empty() { @@ -1208,7 +1208,7 @@ fn quote_doc_from_fields(objects: &Objects, fields: &Vec) -> String let mut lines = vec!["Must be one of:".to_owned(), String::new()]; for field in fields { - let mut content = crate::codegen::get_documentation(&field.docs, &["py", "python"]); + let mut content = field.docs.doc_lines_for_untagged_and("py"); for line in &mut content { if line.starts_with(char::is_whitespace) { line.remove(0); @@ -1250,7 +1250,7 @@ fn quote_union_kind_from_fields(fields: &Vec) -> String { let mut lines = vec!["Possible values:".to_owned(), String::new()]; for field in fields { - let mut content = crate::codegen::get_documentation(&field.docs, &["py", "python"]); + let mut content = field.docs.doc_lines_for_untagged_and("py"); for line in &mut content { if line.starts_with(char::is_whitespace) { line.remove(0); @@ -1950,7 +1950,8 @@ fn quote_init_method( obj.fields .iter() .filter_map(|field| { - if field.docs.doc.is_empty() { + let doc_content = field.docs.doc_lines_for_untagged_and("py"); + if doc_content.is_empty() { if !field.is_testing() && obj.fields.len() > 1 { reporter.error( &field.virtpath, @@ -1960,8 +1961,6 @@ fn quote_init_method( } None } else { - let doc_content = - crate::codegen::get_documentation(&field.docs, &["py", "python"]); Some(format!( "{}:\n {}", field.name, diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index fd7966e76afa..a89613137681 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -714,7 +714,7 @@ fn quote_obj_docs(reporter: &Reporter, obj: &Object) -> TokenStream { } fn doc_as_lines(reporter: &Reporter, virtpath: &str, fqname: &str, docs: &Docs) -> Vec { - let mut lines = crate::codegen::get_documentation(docs, &["rs", "rust"]); + let mut lines = docs.doc_lines_for_untagged_and("rs"); let examples = collect_snippets_for_api_docs(docs, "rs", true) .map_err(|err| reporter.error(virtpath, fqname, err)) diff --git a/crates/re_types_builder/src/docs.rs b/crates/re_types_builder/src/docs.rs new file mode 100644 index 000000000000..3bfe9b2cf339 --- /dev/null +++ b/crates/re_types_builder/src/docs.rs @@ -0,0 +1,110 @@ +/// A high-level representation of a flatbuffers object's documentation. +#[derive(Debug, Clone)] +pub struct Docs { + /// All docmentation lines, including the leading tag, if any. + /// + /// If the tag is the empty string, it means the line is untagged. + /// + /// Each line excludes the leading space and trailing newline. + /// * `/// COMMENT\n` => `("", "COMMENT")` + /// * `/// \py COMMENT\n` => `("py", "COMMENT")`. + lines: Vec<(String, String)>, +} + +impl Docs { + pub fn from_raw_docs( + docs: Option>>, + ) -> Self { + let parse_line = |line: &str| { + if let Some(line) = line.strip_prefix(" \\") { + // \tagged comment + let tag = line.split_whitespace().next().unwrap().to_owned(); + let line = &line[tag.len()..]; + if let Some(line) = line.strip_prefix(' ') { + // Removed space between tag and comment. + (tag, line.to_owned()) + } else { + assert!(line.is_empty()); + (tag, String::new()) + } + } else if let Some(line) = line.strip_prefix(' ') { + // Removed space between `///` and comment. + (String::new(), line.to_owned()) + } else { + assert!( + line.is_empty(), + "Comments should start with a single space; found {line:?}" + ); + (String::new(), String::new()) + } + }; + + let lines: Vec<(String, String)> = docs + .into_iter() + .flat_map(|doc| doc.into_iter()) + .map(parse_line) + .collect(); + + for (tag, comment) in &lines { + assert!( + matches!(tag.as_str(), "" | "example" | "cpp" | "py" | "rs"), + "Unsupported tag: '\\{tag} {comment}'" + ); + } + + Self { lines } + } + + /// Get all doc lines that start with the given tag. + /// + /// For instance, pass `"example"` to get all lines that start with `"\example"`. + pub fn doc_lines_tagged(&self, tag: &str) -> Vec<&str> { + self.lines_with_tag_matching(|t| t == tag) + } + + /// Get all doc lines that are untagged. + pub fn untagged(&self) -> Vec { + self.lines_with_tag_matching(|t| t.is_empty()) + .iter() + .map(|&s| s.to_owned()) + .collect() + } + + /// Get all doc lines that are untagged, or match the given tag. + /// + /// For instance, pass `"py"` to get all lines that are untagged or starta with `"\py"`. + pub fn doc_lines_for_untagged_and(&self, tag: &str) -> Vec { + self.lines_with_tag_matching(|t| t.is_empty() || t == tag) + .iter() + .map(|&s| s.to_owned()) + .collect() + } + + pub fn lines_with_tag_matching(&self, include_tag: impl Fn(&str) -> bool) -> Vec<&str> { + let mut lines: Vec<&str> = self + .lines + .iter() + .filter_map(|(tag, line)| { + if include_tag(tag) { + Some(line.as_str()) + } else { + None + } + }) + .collect(); + + // NOTE: remove duplicated blank lines. + lines.dedup(); + + // NOTE: remove trailing blank lines. + while let Some(line) = lines.last() { + if line.is_empty() { + lines.pop(); + } else { + break; + } + } + + lines + } +} diff --git a/crates/re_types_builder/src/lib.rs b/crates/re_types_builder/src/lib.rs index 17d6b1615fb7..80b0ca697ab9 100644 --- a/crates/re_types_builder/src/lib.rs +++ b/crates/re_types_builder/src/lib.rs @@ -139,6 +139,8 @@ mod format; #[allow(clippy::unimplemented)] mod objects; +mod docs; + pub mod report; /// In-memory generated files. @@ -147,15 +149,18 @@ pub mod report; /// etc), and finally written to disk by the I/O pass. pub type GeneratedFiles = std::collections::BTreeMap; -pub use self::arrow_registry::{ArrowRegistry, LazyDatatype, LazyField}; -pub use self::codegen::{ - CodeGenerator, CppCodeGenerator, DocsCodeGenerator, PythonCodeGenerator, RustCodeGenerator, -}; -pub use self::format::{CodeFormatter, CppCodeFormatter, PythonCodeFormatter, RustCodeFormatter}; -pub use self::objects::{ - Attributes, Docs, ElementType, Object, ObjectClass, ObjectField, ObjectKind, Objects, Type, +pub use self::{ + arrow_registry::{ArrowRegistry, LazyDatatype, LazyField}, + codegen::{ + CodeGenerator, CppCodeGenerator, DocsCodeGenerator, PythonCodeGenerator, RustCodeGenerator, + }, + docs::Docs, + format::{CodeFormatter, CppCodeFormatter, PythonCodeFormatter, RustCodeFormatter}, + objects::{ + Attributes, ElementType, Object, ObjectClass, ObjectField, ObjectKind, Objects, Type, + }, + report::{Report, Reporter}, }; -pub use self::report::{Report, Reporter}; // --- Attributes --- diff --git a/crates/re_types_builder/src/objects.rs b/crates/re_types_builder/src/objects.rs index e332fb9e89ca..d368f7a4eab9 100644 --- a/crates/re_types_builder/src/objects.rs +++ b/crates/re_types_builder/src/objects.rs @@ -3,15 +3,15 @@ //! The semantic pass transforms the low-level raw reflection data into higher level types that //! are much easier to inspect and manipulate / friendler to work with. -use std::collections::{BTreeMap, HashSet}; +use std::collections::BTreeMap; use anyhow::Context as _; use camino::{Utf8Path, Utf8PathBuf}; use itertools::Itertools; use crate::{ - root_as_schema, FbsBaseType, FbsEnum, FbsEnumVal, FbsField, FbsKeyValue, FbsObject, FbsSchema, - FbsType, Reporter, ATTR_RERUN_OVERRIDE_TYPE, + root_as_schema, Docs, FbsBaseType, FbsEnum, FbsEnumVal, FbsField, FbsKeyValue, FbsObject, + FbsSchema, FbsType, Reporter, ATTR_RERUN_OVERRIDE_TYPE, }; // --- @@ -253,150 +253,6 @@ impl ObjectKind { } } -/// A high-level representation of a flatbuffers object's documentation. -#[derive(Debug, Clone)] -pub struct Docs { - /// General documentation for the object. - /// - /// Each entry in the vector is a line of comment, - /// excluding the leading space end trailing newline, - /// i.e. the `COMMENT` from `/// COMMENT\n` - /// - /// See also [`Docs::tagged_docs`]. - pub doc: Vec, - - /// Tagged documentation for the object. - /// - /// Each entry in the vector is a line of comment, - /// excluding the leading space end trailing newline, - /// i.e. the `COMMENT` from `/// \py COMMENT\n` - /// - /// E.g. the following will be associated with the `py` tag: - /// ```flatbuffers - /// /// \py Something something about how this fields behave in python. - /// my_field: uint32, - /// ``` - /// - /// See also [`Docs::doc`]. - pub tagged_docs: BTreeMap>, - - /// Contents of all the files included using `\include:`. - pub included_files: BTreeMap, -} - -impl Docs { - fn from_raw_docs( - filepath: &Utf8Path, - docs: Option>>, - ) -> Self { - let mut included_files = BTreeMap::default(); - - let include_file = |included_files: &mut BTreeMap<_, _>, raw_path: &str| { - let path: Utf8PathBuf = raw_path - .parse() - .with_context(|| format!("couldn't parse included path: {raw_path:?}")) - .unwrap(); - - let path = filepath.parent().unwrap().join(path); - - included_files - .entry(path.clone()) - .or_insert_with(|| { - std::fs::read_to_string(&path) - .with_context(|| { - format!("couldn't parse read file at included path: {path:?}") - }) - .unwrap() - }) - .clone() - }; - - // language-agnostic docs - let doc = docs - .into_iter() - .flat_map(|doc| doc.into_iter()) - // NOTE: discard tagged lines! - .filter(|line| !line.trim().starts_with('\\')) - .flat_map(|line| { - assert!(!line.ends_with('\n')); - assert!(!line.ends_with('\r')); - - if let Some((_, path)) = line.split_once("\\include:") { - include_file(&mut included_files, path) - .lines() - .map(|line| line.to_owned()) - .collect_vec() - } else if let Some(line) = line.strip_prefix(' ') { - // Removed space between `///` and comment. - vec![line.to_owned()] - } else { - assert!( - line.is_empty(), - "{filepath}: Comments should start with a single space; found {line:?}" - ); - vec![line.to_owned()] - } - }) - .collect::>(); - - // tagged docs, e.g. `\py this only applies to python!` - let tagged_docs = { - let tagged_lines = docs - .into_iter() - .flat_map(|doc| doc.into_iter()) - // NOTE: discard _un_tagged lines! - .filter_map(|line| { - let trimmed = line.trim(); - trimmed.starts_with('\\').then(|| { - let tag = trimmed.split_whitespace().next().unwrap(); - let line = &trimmed[tag.len()..]; - let tag = tag[1..].to_owned(); - if let Some(line) = line.strip_prefix(' ') { - // Removed space between tag and comment. - (tag, line.to_owned()) - } else { - assert!(line.is_empty()); - (tag, String::default()) - } - }) - }) - .flat_map(|(tag, line)| { - if let Some((_, path)) = line.split_once("\\include:") { - include_file(&mut included_files, path) - .lines() - .map(|line| (tag.clone(), line.to_owned())) - .collect_vec() - } else { - vec![(tag, line)] - } - }) - .collect::>(); - - let all_tags: HashSet<_> = tagged_lines.iter().map(|(tag, _)| tag).collect(); - let mut tagged_docs = BTreeMap::new(); - - for cur_tag in all_tags { - tagged_docs.insert( - cur_tag.clone(), - tagged_lines - .iter() - .filter(|(tag, _)| cur_tag == tag) - .map(|(_, line)| line.clone()) - .collect(), - ); - } - - tagged_docs - }; - - Self { - doc, - tagged_docs, - included_files, - } - } -} - /// A high-level representation of a flatbuffers object, which can be either a struct, a union or /// an enum. #[derive(Debug, Clone)] @@ -471,7 +327,7 @@ impl Object { "Bad filepath: {filepath:?}" ); - let docs = Docs::from_raw_docs(&filepath, obj.documentation()); + let docs = Docs::from_raw_docs(obj.documentation()); let attrs = Attributes::from_raw_attrs(obj.attributes()); let kind = ObjectKind::from_pkg_name(&pkg_name, &attrs); @@ -551,7 +407,7 @@ impl Object { .unwrap(); let filepath = filepath_from_declaration_file(include_dir_path, &virtpath); - let docs = Docs::from_raw_docs(&filepath, enm.documentation()); + let docs = Docs::from_raw_docs(enm.documentation()); let attrs = Attributes::from_raw_attrs(enm.attributes()); let kind = ObjectKind::from_pkg_name(&pkg_name, &attrs); @@ -791,7 +647,7 @@ impl ObjectField { .unwrap(); let filepath = filepath_from_declaration_file(include_dir_path, &virtpath); - let docs = Docs::from_raw_docs(&filepath, field.documentation()); + let docs = Docs::from_raw_docs(field.documentation()); let attrs = Attributes::from_raw_attrs(field.attributes()); @@ -839,7 +695,7 @@ impl ObjectField { .unwrap(); let filepath = filepath_from_declaration_file(include_dir_path, &virtpath); - let docs = Docs::from_raw_docs(&filepath, val.documentation()); + let docs = Docs::from_raw_docs(val.documentation()); let attrs = Attributes::from_raw_attrs(val.attributes()); diff --git a/docs/content/reference/types/archetypes/image.md b/docs/content/reference/types/archetypes/image.md index e67efab56d48..04aac2a6cdc0 100644 --- a/docs/content/reference/types/archetypes/image.md +++ b/docs/content/reference/types/archetypes/image.md @@ -12,6 +12,9 @@ The shape of the `TensorData` must be mappable to: Leading and trailing unit-dimensions are ignored, so that `1x640x480x3x1` is treated as a `640x480x3` RGB image. +Rerun also supports compressed image encoded as JPEG, N12, and YUY2. +Using these formats can save a lot of bandwidth and memory. + ## Components **Required**: [`TensorData`](../components/tensor_data.md) diff --git a/rerun_cpp/src/rerun/archetypes/image.hpp b/rerun_cpp/src/rerun/archetypes/image.hpp index 1b98de979f72..95c7ba3a25a1 100644 --- a/rerun_cpp/src/rerun/archetypes/image.hpp +++ b/rerun_cpp/src/rerun/archetypes/image.hpp @@ -27,6 +27,10 @@ namespace rerun::archetypes { /// Leading and trailing unit-dimensions are ignored, so that /// `1x640x480x3x1` is treated as a `640x480x3` RGB image. /// + /// Rerun also supports compressed image encoded as JPEG, N12, and YUY2. + /// Using these formats can save a lot of bandwidth and memory. + /// See [`rerun::datatypes::TensorBuffer`] for more. + /// /// Since the underlying `rerun::datatypes::TensorData` uses `rerun::Collection` internally, /// data can be passed in without a copy from raw pointers or by reference from `std::vector`/`std::array`/c-arrays. /// If needed, this "borrow-behavior" can be extended by defining your own `rerun::CollectionAdapter`. diff --git a/rerun_cpp/src/rerun/datatypes/tensor_buffer.hpp b/rerun_cpp/src/rerun/datatypes/tensor_buffer.hpp index 9d73a88eac21..f1a40ad5fc0b 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_buffer.hpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_buffer.hpp @@ -85,7 +85,7 @@ namespace rerun::datatypes { /// First comes entire image in Y, followed by interleaved lines ordered as U0, V0, U1, V1, etc. rerun::Collection nv12; - /// YUY2, also known as YUYV is a YUV 4:2:2 chrome downsampled format with 8 bits per channel. + /// YUY2, also known as YUYV is a YUV 4:2:2 chroma downsampled format with 8 bits per channel. /// /// The order of the channels is Y0, U0, Y1, V0. rerun::Collection yuy2; @@ -420,7 +420,7 @@ namespace rerun::datatypes { return self; } - /// YUY2, also known as YUYV is a YUV 4:2:2 chrome downsampled format with 8 bits per channel. + /// YUY2, also known as YUYV is a YUV 4:2:2 chroma downsampled format with 8 bits per channel. /// /// The order of the channels is Y0, U0, Y1, V0. static TensorBuffer yuy2(rerun::Collection yuy2) { diff --git a/rerun_py/rerun_sdk/rerun/archetypes/image.py b/rerun_py/rerun_sdk/rerun/archetypes/image.py index f92faa9add66..0f3bb50cdb27 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/image.py @@ -30,7 +30,10 @@ class Image(ImageExt, Archetype): Leading and trailing unit-dimensions are ignored, so that `1x640x480x3x1` is treated as a `640x480x3` RGB image. - For an easy way to pass in image formats or encoded images, see [`rerun.ImageEncoded`][]. + Rerun also supports compressed image encoded as JPEG, N12, and YUY2. + Using these formats can save a lot of bandwidth and memory. + To compress an image, use [`rerun.Image.compress`][]. + To pass in an already encoded image, use [`rerun.ImageEncoded`][]. Example ------- diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py index b608bf32c8cd..34cd5165a0be 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py @@ -88,7 +88,7 @@ class TensorBuffer(TensorBufferExt): First comes entire image in Y, followed by interleaved lines ordered as U0, V0, U1, V1, etc. * YUY2 (npt.NDArray[np.uint8]): - YUY2, also known as YUYV is a YUV 4:2:2 chrome downsampled format with 8 bits per channel. + YUY2, also known as YUYV is a YUV 4:2:2 chroma downsampled format with 8 bits per channel. The order of the channels is Y0, U0, Y1, V0. """ @@ -141,7 +141,7 @@ class TensorBuffer(TensorBufferExt): First comes entire image in Y, followed by interleaved lines ordered as U0, V0, U1, V1, etc. * "YUY2": - YUY2, also known as YUYV is a YUV 4:2:2 chrome downsampled format with 8 bits per channel. + YUY2, also known as YUYV is a YUV 4:2:2 chroma downsampled format with 8 bits per channel. The order of the channels is Y0, U0, Y1, V0. """ From 1f672209ca6414ade00b18998caf383423c768bd Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 26 Mar 2024 05:47:24 -0400 Subject: [PATCH 119/508] Use script_setup in blueprint_stocks example (#5677) ### What Script flags weren't working as expected. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5677/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5677/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5677/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5677) - [Docs preview](https://rerun.io/preview/39b2ddeadbb4b16e5438a2bbe10aec0058b3d9d6/docs) - [Examples preview](https://rerun.io/preview/39b2ddeadbb4b16e5438a2bbe10aec0058b3d9d6/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/blueprint_stocks/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/python/blueprint_stocks/main.py b/examples/python/blueprint_stocks/main.py index 35372767db88..d4f8c55e9c4e 100755 --- a/examples/python/blueprint_stocks/main.py +++ b/examples/python/blueprint_stocks/main.py @@ -166,7 +166,7 @@ def main() -> None: else: blueprint = viewport - rr.init("rerun_example_blueprint_stocks", spawn=True, blueprint=blueprint) + rr.script_setup(args, "rerun_example_blueprint_stocks", blueprint=blueprint) # In a future blueprint release, this can move into the blueprint as well for symbol in symbols: From 03db295bccef7bc4b211be23dbd689180f8e5272 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 26 Mar 2024 11:48:17 +0100 Subject: [PATCH 120/508] Improve spacing and alignment of menus (#5680) ### What Based on: * https://github.com/emilk/egui/pull/4232 * https://github.com/emilk/egui/pull/4230 * https://github.com/emilk/egui/pull/4233 ## Before Screenshot 2024-03-26 at 11 17 57 Screenshot 2024-03-26 at 11 17 40 ## After Screenshot 2024-03-26 at 11 20 36 Screenshot 2024-03-26 at 11 20 43 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5680/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5680/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5680/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5680) - [Docs preview](https://rerun.io/preview/003d45654e7ddf9335aa82d9c50d67dd5a0695c6/docs) - [Examples preview](https://rerun.io/preview/003d45654e7ddf9335aa82d9c50d67dd5a0695c6/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 14 +++++++------- crates/re_ui/src/design_tokens.rs | 1 + 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dcbaa3a9101f..95792ccc79c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1555,7 +1555,7 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "bytemuck", "serde", @@ -1564,7 +1564,7 @@ dependencies = [ [[package]] name = "eframe" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "bytemuck", "cocoa", @@ -1599,7 +1599,7 @@ dependencies = [ [[package]] name = "egui" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "accesskit", "ahash", @@ -1615,7 +1615,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "bytemuck", "document-features", @@ -1633,7 +1633,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "accesskit_winit", "arboard", @@ -1662,7 +1662,7 @@ dependencies = [ [[package]] name = "egui_extras" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "egui", "ehttp", @@ -1677,7 +1677,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "bytemuck", "egui", @@ -1694,7 +1694,7 @@ dependencies = [ [[package]] name = "egui_plot" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "egui", ] @@ -1736,7 +1736,7 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "bytemuck", "serde", @@ -1837,7 +1837,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=20b0637d42892b87fb8411b39c5c256fd32d7ee3#20b0637d42892b87fb8411b39c5c256fd32d7ee3" +source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" dependencies = [ "ab_glyph", "ahash", diff --git a/Cargo.toml b/Cargo.toml index e835d5011241..d415e500880d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -284,13 +284,13 @@ debug = true # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 -eframe = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 -egui = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 -egui_plot = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 -emath = { git = "https://github.com/emilk/egui.git", rev = "20b0637d42892b87fb8411b39c5c256fd32d7ee3" } # egui master 2024-03-22 +ecolor = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +eframe = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +egui = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +egui_extras = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +egui_plot = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +emath = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } diff --git a/crates/re_ui/src/design_tokens.rs b/crates/re_ui/src/design_tokens.rs index 5a81e0fe1982..7f4afe5f8f53 100644 --- a/crates/re_ui/src/design_tokens.rs +++ b/crates/re_ui/src/design_tokens.rs @@ -173,6 +173,7 @@ fn apply_design_tokens(ctx: &egui::Context) -> DesignTokens { egui_style.spacing.item_spacing = egui::vec2(8.0, 8.0); egui_style.spacing.menu_margin = crate::ReUi::view_padding().into(); + egui_style.spacing.menu_spacing = 1.0; // avoid some visual glitches with the default non-zero value egui_style.visuals.clip_rect_margin = 0.0; From 22ffea055bf637e648356741a0f702f502204bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Tue, 26 Mar 2024 14:24:54 +0100 Subject: [PATCH 121/508] Fix update PR body workflow (#5684) ### What It shared its concurrency ID with PR summary which meant it would be cancelled if that ran first. That would only happen if the dependencies took a really long time to install, because we were installing everything in `scripts/ci/requirements.txt`, and it wasn't cached. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/reusable_update_pr_body.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable_update_pr_body.yml b/.github/workflows/reusable_update_pr_body.yml index 5f3987958999..9e45202eb980 100644 --- a/.github/workflows/reusable_update_pr_body.yml +++ b/.github/workflows/reusable_update_pr_body.yml @@ -11,7 +11,7 @@ on: type: string concurrency: - group: ${{ inputs.CONCURRENCY }}-pr-summary + group: ${{ inputs.CONCURRENCY }}-pr-update-body cancel-in-progress: true jobs: @@ -39,7 +39,7 @@ jobs: - name: Install deps shell: bash run: | - python3 -m pip install -r ./scripts/ci/requirements.txt + python3 -m pip install PyGithub==1.59.0 Jinja2==3.1.2 - name: Update PR description shell: bash From 43cbc67e658d84b163b2962bdd191250eb08d133 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 26 Mar 2024 16:32:27 +0100 Subject: [PATCH 122/508] Apply shadows under menus (#5681) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What It's a bit ugly that the shadow of one menu appears on top of the other imho, but that's not easily fixed in egui (and Mårten is okay with it). The alternative is a smaller blur radius. ## Using the shadows from Figma Screenshot 2024-03-26 at 12 01 56 Screenshot 2024-03-26 at 12 02 54 ## Alternative Here are the default shadows in egui: Screenshot 2024-03-26 at 12 05 10 Screenshot 2024-03-26 at 12 06 01 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_ui/src/design_tokens.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/re_ui/src/design_tokens.rs b/crates/re_ui/src/design_tokens.rs index 7f4afe5f8f53..e62dbbef034a 100644 --- a/crates/re_ui/src/design_tokens.rs +++ b/crates/re_ui/src/design_tokens.rs @@ -155,8 +155,15 @@ fn apply_design_tokens(ctx: &egui::Context) -> DesignTokens { egui_style.visuals.widgets.inactive.fg_stroke.color = default; // button text egui_style.visuals.widgets.active.fg_stroke.color = strong; // strong text and active button text - egui_style.visuals.popup_shadow = egui::epaint::Shadow::NONE; - egui_style.visuals.window_shadow = egui::epaint::Shadow::NONE; + // From figma + let shadow = egui::epaint::Shadow { + offset: egui::vec2(0.0, 15.0), + blur: 50.0, + spread: 0.0, + color: egui::Color32::from_black_alpha(128), + }; + egui_style.visuals.popup_shadow = shadow; + egui_style.visuals.window_shadow = shadow; egui_style.visuals.window_fill = floating_color; // tooltips and menus egui_style.visuals.window_stroke = egui::Stroke::NONE; From 1f0f374c117ecde86c79a1edae83746e2dcb7497 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 27 Mar 2024 10:21:03 +0100 Subject: [PATCH 123/508] Update to egui 0.27.0 (#5696) ### What * Fixes https://github.com/rerun-io/rerun/issues/5588 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5696/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5696/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5696/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5696) - [Docs preview](https://rerun.io/preview/8112c31c9f8503de7c3d201f0a78d637ba4c8b50/docs) - [Examples preview](https://rerun.io/preview/8112c31c9f8503de7c3d201f0a78d637ba4c8b50/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 74 +++++++++++++++++++++++++++++++++++------------------- Cargo.toml | 34 ++++++++++++------------- deny.toml | 1 + 3 files changed, 66 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95792ccc79c0..1dbd44ac32b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1554,8 +1554,9 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c416b34b29e8f6b2492b5c80319cf9792d339550f0d75a54b53ed070045bbdeb" dependencies = [ "bytemuck", "serde", @@ -1563,8 +1564,9 @@ dependencies = [ [[package]] name = "eframe" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86811b20df847cfa73637020ee78de780407110f49785df2dea6741146ea5aac" dependencies = [ "bytemuck", "cocoa", @@ -1598,8 +1600,9 @@ dependencies = [ [[package]] name = "egui" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8e20541e5d3da08cf817eb5c8a2bc4024f21aad7acf98de201442d6d76e0ecc" dependencies = [ "accesskit", "ahash", @@ -1614,8 +1617,9 @@ dependencies = [ [[package]] name = "egui-wgpu" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25d1c9a6f17f48a75148e7a3db7cc0221b7261db577281267301f83d79d0834a" dependencies = [ "bytemuck", "document-features", @@ -1632,8 +1636,9 @@ dependencies = [ [[package]] name = "egui-winit" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4fc01bc3617dba9280475e9ab2382015e298f401d2318c2a1d78c419b6dffe" dependencies = [ "accesskit_winit", "arboard", @@ -1650,19 +1655,20 @@ dependencies = [ [[package]] name = "egui_commonmark" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f491836e627bc98e00dd86c061d6b1be5e331c157f41dd8a8d512196f1b89aa" +checksum = "e30fc4d40a8ef399a8debfbdae0462ca45912d81b9e81b24373337669e961201" dependencies = [ "egui", "egui_extras", - "pulldown-cmark", + "pulldown-cmark 0.10.0", ] [[package]] name = "egui_extras" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f097daa92d09cc4561f817e2f9733c55af3b157cf437ee3a401cdf038e75fcdc" dependencies = [ "egui", "ehttp", @@ -1676,8 +1682,9 @@ dependencies = [ [[package]] name = "egui_glow" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743380a1c0f1dbb7bfe29663ce62b10785adda51105c9bb4e544e2f9955b4958" dependencies = [ "bytemuck", "egui", @@ -1693,16 +1700,18 @@ dependencies = [ [[package]] name = "egui_plot" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8385c285c2157bb94ae572e48d137587bac31207707ad86b7f8d09612b9657" dependencies = [ "egui", ] [[package]] name = "egui_tiles" -version = "0.7.2" -source = "git+https://github.com/rerun-io/egui_tiles?rev=5245a28df8a3a5befd0c55085de4f7044a6d831e#5245a28df8a3a5befd0c55085de4f7044a6d831e" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e2c0ff99daddcbdc54b141dbb7be3b014463da48a03ebc801bf63e500b23d75" dependencies = [ "ahash", "egui", @@ -1735,8 +1744,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87799f56edee11422267e1764dd0bf3fe1734888e8d2d0924a67b85f4998fbe" dependencies = [ "bytemuck", "serde", @@ -1836,8 +1846,9 @@ dependencies = [ [[package]] name = "epaint" -version = "0.26.2" -source = "git+https://github.com/emilk/egui.git?rev=8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc#8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "392eccd6d6b13fadccc268f4f61d9363775ec5711ffdece2a79006d676920bcf" dependencies = [ "ab_glyph", "ahash", @@ -3960,6 +3971,17 @@ dependencies = [ "unicase", ] +[[package]] +name = "pulldown-cmark" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce76ce678ffc8e5675b22aa1405de0b7037e2fdf8913fea40d1926c6fe1e6e7" +dependencies = [ + "bitflags 2.4.1", + "memchr", + "unicase", +] + [[package]] name = "pyo3" version = "0.20.3" @@ -5964,7 +5986,7 @@ dependencies = [ "cargo_metadata 0.14.2", "error-chain", "glob", - "pulldown-cmark", + "pulldown-cmark 0.9.3", "tempfile", "walkdir", ] diff --git a/Cargo.toml b/Cargo.toml index d415e500880d..de5ce3c5bf60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,27 +75,27 @@ re_ws_comms = { path = "crates/re_ws_comms", version = "=0.15.0-alpha.3", defaul rerun = { path = "crates/rerun", version = "=0.15.0-alpha.3", default-features = false } # egui-crates: -ecolor = "0.26.2" -eframe = { version = "0.26.2", default-features = false, features = [ +ecolor = "0.27.0" +eframe = { version = "0.27.0", default-features = false, features = [ "accesskit", "default_fonts", "puffin", "wayland", "x11", ] } -egui = { version = "0.26.2", features = [ +egui = { version = "0.27.0", features = [ "callstack", "extra_debug_asserts", "log", "puffin", "rayon", ] } -egui_commonmark = { version = "0.12", default-features = false } -egui_extras = { version = "0.26.2", features = ["http", "image", "puffin"] } -egui_plot = "0.26.2" -egui_tiles = "0.7.2" -egui-wgpu = "0.26.2" -emath = "0.26.2" +egui_commonmark = { version = "0.14", default-features = false } +egui_extras = { version = "0.27.0", features = ["http", "image", "puffin"] } +egui_plot = "0.27.0" +egui_tiles = "0.8.0" +egui-wgpu = "0.27.0" +emath = "0.27.0" # All of our direct external dependencies should be found here: ahash = "0.8" @@ -284,13 +284,13 @@ debug = true # As a last resport, patch with a commit to our own repository. # ALWAYS document what PR the commit hash is part of, or when it was merged into the upstream trunk. -ecolor = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 -eframe = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 -egui = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 -egui_extras = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 -egui_plot = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 -egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 -emath = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +# ecolor = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +# eframe = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +# egui = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +# egui_extras = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +# egui_plot = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +# egui-wgpu = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 +# emath = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd6e08d02fdd2063f1ddcc" } # egui master 2024-03-26 # Useful while developing: # ecolor = { path = "../../egui/crates/ecolor" } @@ -301,6 +301,6 @@ emath = { git = "https://github.com/emilk/egui.git", rev = "8a10f81ca01b2ba4e0bd # egui-wgpu = { path = "../../egui/crates/egui-wgpu" } # emath = { path = "../../egui/crates/emath" } -egui_tiles = { git = "https://github.com/rerun-io/egui_tiles", rev = "5245a28df8a3a5befd0c55085de4f7044a6d831e" } # main 2024-02-27, which works with egui master +# egui_tiles = { git = "https://github.com/rerun-io/egui_tiles", rev = "5245a28df8a3a5befd0c55085de4f7044a6d831e" } # main 2024-02-27, which works with egui master # egui_commonmark = { git = "https://github.com/rerun-io/egui_commonmark", rev = "3d83a92f995a1d18ab1172d0b129d496e0eedaae" } # Update to egui 0.25 https://github.com/lampsitter/egui_commonmark/pull/27 diff --git a/deny.toml b/deny.toml index b433fb9cd89d..07df1b13bf8b 100644 --- a/deny.toml +++ b/deny.toml @@ -50,6 +50,7 @@ skip = [ { name = "libloading" }, # Old version used by ash (vulkan binding), newer version used by khronos-egl { name = "memoffset" }, # Small crate { name = "prettyplease" }, # Old version being used by prost + { name = "pulldown-cmark" }, # Build-dependency via `ply-rs` (!). TODO(emilk): use a better crate for .ply parsing { name = "raw-window-handle" }, # Pretty small crate; some crates still on old version { name = "redox_syscall" }, # Plenty of versions in the wild { name = "spin" }, # Old version used by rusttls From 8934a211ad948dfb8498814a9d4a7f933eeb8e26 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 27 Mar 2024 10:40:14 +0100 Subject: [PATCH 124/508] Remove a bunch of title casing, and add simple lint against it (#5688) ### What I discovered a bunch of places with the old convention. The lint doesn't cover everything, but it is a start. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5688/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5688/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5688/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5688) - [Docs preview](https://rerun.io/preview/d60ac20005d31901d71daeb03898897ecb391d33/docs) - [Examples preview](https://rerun.io/preview/d60ac20005d31901d71daeb03898897ecb391d33/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- CHANGELOG.md | 4 +- crates/re_data_ui/src/item_ui.rs | 2 +- crates/re_entity_db/examples/memory_usage.rs | 2 +- crates/re_sdk/src/global.rs | 8 ++-- crates/re_smart_channel/src/lib.rs | 6 +-- crates/re_space_view/Cargo.toml | 2 +- crates/re_space_view/src/space_view.rs | 2 +- crates/re_space_view_bar_chart/Cargo.toml | 2 +- crates/re_space_view_dataframe/Cargo.toml | 2 +- .../src/contexts/transform_context.rs | 2 +- .../src/space_view_3d.rs | 6 +-- crates/re_space_view_tensor/Cargo.toml | 2 +- .../src/space_view_class.rs | 2 +- crates/re_space_view_text_document/Cargo.toml | 2 +- crates/re_space_view_text_log/Cargo.toml | 2 +- crates/re_space_view_time_series/Cargo.toml | 2 +- .../rerun/archetypes/disconnected_space.fbs | 2 +- .../src/archetypes/disconnected_space.rs | 2 +- crates/re_ui/src/command.rs | 4 +- crates/re_viewer/src/app.rs | 2 +- crates/re_viewer/src/ui/blueprint_panel.rs | 4 +- crates/re_viewer/src/ui/memory_panel.rs | 6 +-- crates/re_viewer/src/ui/rerun_menu.rs | 8 ++-- .../re_viewer/src/ui/selection_history_ui.rs | 6 +-- crates/re_viewer/src/ui/selection_panel.rs | 38 +++++++++---------- crates/re_viewer/src/ui/top_panel.rs | 2 +- crates/re_viewer/src/ui/visible_history.rs | 10 ++--- crates/re_viewer_context/src/item.rs | 10 ++--- .../re_viewer_context/src/space_view/mod.rs | 2 +- .../space_view_class_placeholder.rs | 6 +-- .../space_view/space_view_class_registry.rs | 8 ++-- .../src/add_space_view_or_container_modal.rs | 4 +- crates/re_viewport/src/container.rs | 6 +-- .../actions/add_entities_to_new_space_view.rs | 2 +- crates/re_viewport/src/context_menu/mod.rs | 2 +- .../src/space_view_entity_picker.rs | 12 +++--- crates/re_viewport/src/viewport.rs | 14 +++---- .../re_viewport/src/viewport_blueprint_ui.rs | 10 ++--- .../types/archetypes/disconnected_space.md | 2 +- examples/cpp/shared_recording/README.md | 2 +- examples/python/shared_recording/README.md | 2 +- examples/rust/custom_space_view/README.md | 2 +- .../rust/custom_store_subscriber/README.md | 2 +- .../rust/custom_store_subscriber/src/main.rs | 2 +- examples/rust/shared_recording/README.md | 2 +- .../rerun/archetypes/disconnected_space.hpp | 2 +- .../rerun/archetypes/disconnected_space.py | 2 +- .../tests/unit/test_space_view_blueprint.py | 4 +- scripts/lint.py | 38 ++++++++++++++++++- .../check_context_menu_suggested_origin.py | 2 +- 50 files changed, 153 insertions(+), 117 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23faef07585b..284313ca4493 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -208,9 +208,9 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Only show the LegacyVisualizer if a user logs with TimeSeriesScalar archetype [#5023](https://github.com/rerun-io/rerun/pull/5023) - Fix lagging time cursor when panning a time series plot [#4972](https://github.com/rerun-io/rerun/pull/4972) - New Space View and Container creation workflow: - - Use the "Add Space View/Container" modal for the `+` button of the blueprint tree [#5012](https://github.com/rerun-io/rerun/pull/5012) + - Use the "Add space view/container" modal for the `+` button of the blueprint tree [#5012](https://github.com/rerun-io/rerun/pull/5012) - Add support for removing container children from the selection panel [#4930](https://github.com/rerun-io/rerun/pull/4930) - - Add support for full span highlighting to modal and use it in the "Add Space View or Container" modal [#4822](https://github.com/rerun-io/rerun/pull/4822) + - Add support for full span highlighting to modal and use it in the "Add space view or container" modal [#4822](https://github.com/rerun-io/rerun/pull/4822) - Remove the "+" icon from the "Add SV/Container" modal and close on click [#4927](https://github.com/rerun-io/rerun/pull/4927) - New empty space view defaults to uncollapsed in blueprint tree [#4982](https://github.com/rerun-io/rerun/pull/4982) - Do not allow adding Horizontal/Vertical containers inside of containers with the same type [#5091](https://github.com/rerun-io/rerun/pull/5091) diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index ed6251f09dcb..4668c88a8449 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -520,7 +520,7 @@ pub fn instance_hover_card_ui( let subtype_string = if instance_path.instance_key.is_splat() { "Entity" } else { - "Entity Instance" + "Entity instance" }; ui.strong(subtype_string); ui.label(instance_path.syntax_highlighted(ui.style())); diff --git a/crates/re_entity_db/examples/memory_usage.rs b/crates/re_entity_db/examples/memory_usage.rs index 50ec9ef490e3..dd56faf8a728 100644 --- a/crates/re_entity_db/examples/memory_usage.rs +++ b/crates/re_entity_db/examples/memory_usage.rs @@ -101,7 +101,7 @@ fn log_messages() { let used_bytes_start = live_bytes(); let entity_path = entity_path!("points"); let used_bytes = live_bytes() - used_bytes_start; - println!("Short EntityPath uses {used_bytes} bytes in RAM"); + println!("Short entity path uses {used_bytes} bytes in RAM"); drop(entity_path); } diff --git a/crates/re_sdk/src/global.rs b/crates/re_sdk/src/global.rs index 9ee92ce1b1c9..52f557dfea34 100644 --- a/crates/re_sdk/src/global.rs +++ b/crates/re_sdk/src/global.rs @@ -81,28 +81,28 @@ thread_local! { pub fn cleanup_if_forked_child() { if let Some(global_recording) = RecordingStream::global(StoreKind::Recording) { if global_recording.is_forked_child() { - re_log::debug!("Fork detected. Forgetting global Recording"); + re_log::debug!("Fork detected. Forgetting global recording"); RecordingStream::forget_global(StoreKind::Recording); } } if let Some(global_blueprint) = RecordingStream::global(StoreKind::Blueprint) { if global_blueprint.is_forked_child() { - re_log::debug!("Fork detected. Forgetting global Blueprint"); + re_log::debug!("Fork detected. Forgetting global blueprint"); RecordingStream::forget_global(StoreKind::Recording); } } if let Some(thread_recording) = RecordingStream::thread_local(StoreKind::Recording) { if thread_recording.is_forked_child() { - re_log::debug!("Fork detected. Forgetting thread-local Recording"); + re_log::debug!("Fork detected. Forgetting thread-local recording"); RecordingStream::forget_thread_local(StoreKind::Recording); } } if let Some(thread_blueprint) = RecordingStream::thread_local(StoreKind::Blueprint) { if thread_blueprint.is_forked_child() { - re_log::debug!("Fork detected. Forgetting thread-local Blueprint"); + re_log::debug!("Fork detected. Forgetting thread-local blueprint"); RecordingStream::forget_thread_local(StoreKind::Blueprint); } } diff --git a/crates/re_smart_channel/src/lib.rs b/crates/re_smart_channel/src/lib.rs index 56f844a2022d..2998d5f561f5 100644 --- a/crates/re_smart_channel/src/lib.rs +++ b/crates/re_smart_channel/src/lib.rs @@ -60,11 +60,11 @@ impl std::fmt::Display for SmartChannelSource { match self { Self::File(path) => path.display().fmt(f), Self::RrdHttpStream { url } => url.fmt(f), - Self::RrdWebEventListener => "Web Event Listener".fmt(f), + Self::RrdWebEventListener => "Web event listener".fmt(f), Self::Sdk => "SDK".fmt(f), Self::WsClient { ws_server_url } => ws_server_url.fmt(f), - Self::TcpServer { port } => write!(f, "TCP Server, port {port}"), - Self::Stdin => "Standard Input".fmt(f), + Self::TcpServer { port } => write!(f, "TCP server, port {port}"), + Self::Stdin => "Standard input".fmt(f), } } } diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml index af4c0b89b6bd..8cad48981e5e 100644 --- a/crates/re_space_view/Cargo.toml +++ b/crates/re_space_view/Cargo.toml @@ -1,6 +1,6 @@ [package] authors.workspace = true -description = "Types & utilities for defining Space View classes and communicating with the Viewport." +description = "Types & utilities for defining space view classes and communicating with the viewport." edition.workspace = true homepage.workspace = true license.workspace = true diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index d65881892b7e..80bcaa582447 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -378,7 +378,7 @@ impl SpaceViewBlueprint { .ui(ctx, ui, view_state, &props, query, system_output) .unwrap_or_else(|err| { re_log::error!( - "Error in Space View UI (class: {}, display name: {}): {err}", + "Error in space view UI (class: {}, display name: {}): {err}", self.class_identifier, class.display_name(), ); diff --git a/crates/re_space_view_bar_chart/Cargo.toml b/crates/re_space_view_bar_chart/Cargo.toml index 0e18dac2cfa1..e7104dcdf78a 100644 --- a/crates/re_space_view_bar_chart/Cargo.toml +++ b/crates/re_space_view_bar_chart/Cargo.toml @@ -1,6 +1,6 @@ [package] authors.workspace = true -description = "A Space View that shows a single bar chart." +description = "A space view that shows a single bar chart." edition.workspace = true homepage.workspace = true license.workspace = true diff --git a/crates/re_space_view_dataframe/Cargo.toml b/crates/re_space_view_dataframe/Cargo.toml index 9ea94fa942df..9bfbf233c859 100644 --- a/crates/re_space_view_dataframe/Cargo.toml +++ b/crates/re_space_view_dataframe/Cargo.toml @@ -1,6 +1,6 @@ [package] authors.workspace = true -description = "A Space View that shows the data contained in entities in a table." +description = "A space view that shows the data contained in entities in a table." edition.workspace = true homepage.workspace = true license.workspace = true diff --git a/crates/re_space_view_spatial/src/contexts/transform_context.rs b/crates/re_space_view_spatial/src/contexts/transform_context.rs index ec76952736b8..1bdc7fcb053d 100644 --- a/crates/re_space_view_spatial/src/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/contexts/transform_context.rs @@ -137,7 +137,7 @@ impl ViewContextSystem for TransformContext { let Some(parent_tree) = entity_tree.subtree(&parent_path) else { // Unlike not having the space path in the hierarchy, this should be impossible. re_log::error_once!( - "Path {} is not part of the global Entity tree whereas its child {} is", + "Path {} is not part of the global entity tree whereas its child {} is", parent_path, query.space_origin ); diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 8f167802a34b..4e5c34bcf4e3 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -457,8 +457,8 @@ fn background_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mut e fn background_color_text(kind: Background3DKind) -> &'static str { match kind { - Background3DKind::GradientDark => "Dark Gradient", - Background3DKind::GradientBright => "Bright Gradient", - Background3DKind::SolidColor => "Solid Color", + Background3DKind::GradientDark => "Dark gradient", + Background3DKind::GradientBright => "Bright gradient", + Background3DKind::SolidColor => "Solid color", } } diff --git a/crates/re_space_view_tensor/Cargo.toml b/crates/re_space_view_tensor/Cargo.toml index 0953dffd4470..3b1a6c3272a3 100644 --- a/crates/re_space_view_tensor/Cargo.toml +++ b/crates/re_space_view_tensor/Cargo.toml @@ -1,6 +1,6 @@ [package] authors.workspace = true -description = "A Space View dedicated to visualizing tensors with arbitrary dimensionality." +description = "A space view dedicated to visualizing tensors with arbitrary dimensionality." edition.workspace = true homepage.workspace = true license.workspace = true diff --git a/crates/re_space_view_tensor/src/space_view_class.rs b/crates/re_space_view_tensor/src/space_view_class.rs index e6518f6afea3..eb6eec99447c 100644 --- a/crates/re_space_view_tensor/src/space_view_class.rs +++ b/crates/re_space_view_tensor/src/space_view_class.rs @@ -150,7 +150,7 @@ impl SpaceViewClass for TensorSpaceView { } fn help_text(&self, _re_ui: &re_ui::ReUi) -> egui::WidgetText { - "Select the Space View to configure which dimensions are shown.".into() + "Select the space view to configure which dimensions are shown.".into() } fn on_register( diff --git a/crates/re_space_view_text_document/Cargo.toml b/crates/re_space_view_text_document/Cargo.toml index 248d417f219b..a1666e1f7ea4 100644 --- a/crates/re_space_view_text_document/Cargo.toml +++ b/crates/re_space_view_text_document/Cargo.toml @@ -1,6 +1,6 @@ [package] authors.workspace = true -description = "A simple Space View that shows a single text box." +description = "A simple space view that shows a single text box." edition.workspace = true homepage.workspace = true license.workspace = true diff --git a/crates/re_space_view_text_log/Cargo.toml b/crates/re_space_view_text_log/Cargo.toml index ca2b1962512e..040f317fbd18 100644 --- a/crates/re_space_view_text_log/Cargo.toml +++ b/crates/re_space_view_text_log/Cargo.toml @@ -1,6 +1,6 @@ [package] authors.workspace = true -description = "A Space View that shows text entries in a table and scrolls with the active time." +description = "A space view that shows text entries in a table and scrolls with the active time." edition.workspace = true homepage.workspace = true license.workspace = true diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml index f79a6e402b24..5612ffea50e5 100644 --- a/crates/re_space_view_time_series/Cargo.toml +++ b/crates/re_space_view_time_series/Cargo.toml @@ -1,6 +1,6 @@ [package] authors.workspace = true -description = "A Space View that shows plots over Rerun timelines." +description = "A space view that shows plots over Rerun timelines." edition.workspace = true homepage.workspace = true license.workspace = true diff --git a/crates/re_types/definitions/rerun/archetypes/disconnected_space.fbs b/crates/re_types/definitions/rerun/archetypes/disconnected_space.fbs index 14f6441023b4..75849dff3047 100644 --- a/crates/re_types/definitions/rerun/archetypes/disconnected_space.fbs +++ b/crates/re_types/definitions/rerun/archetypes/disconnected_space.fbs @@ -12,7 +12,7 @@ namespace rerun.archetypes; /// It *only* applies to space views that work with spatial transformations, i.e. 2D & 3D space views. /// This is useful for specifying that a subgraph is independent of the rest of the scene. /// -/// \example disconnected_space title="Disconnected Space" image="https://static.rerun.io/disconnected_space/b8f95b0e32359de625a765247c84935146c1fba9/1200w.png" +/// \example disconnected_space title="Disconnected space" image="https://static.rerun.io/disconnected_space/b8f95b0e32359de625a765247c84935146c1fba9/1200w.png" table DisconnectedSpace ( "attr.rust.derive": "Copy, PartialEq, Eq" ) { diff --git a/crates/re_types/src/archetypes/disconnected_space.rs b/crates/re_types/src/archetypes/disconnected_space.rs index 109613957ebc..284906ed0390 100644 --- a/crates/re_types/src/archetypes/disconnected_space.rs +++ b/crates/re_types/src/archetypes/disconnected_space.rs @@ -30,7 +30,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// ## Example /// -/// ### Disconnected Space +/// ### Disconnected space /// ```ignore /// fn main() -> Result<(), Box> { /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_disconnected_space").spawn()?; diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs index 592a84bf0c7f..678f15a3f924 100644 --- a/crates/re_ui/src/command.rs +++ b/crates/re_ui/src/command.rs @@ -106,8 +106,8 @@ impl UICommand { Self::Open => ("Open…", "Open any supported files (.rrd, images, meshes, …)"), Self::CloseCurrentRecording => ( - "Close current Recording", - "Close the current Recording (unsaved data will be lost)", + "Close current recording", + "Close the current recording (unsaved data will be lost)", ), #[cfg(not(target_arch = "wasm32"))] diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 83295a21eb31..a20c8a4a5d08 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -192,7 +192,7 @@ impl App { state.app_options(), ) { re_log::error!( - "Failed to populate Space View type registry with built-in Space Views: {}", + "Failed to populate space view type registry with built-in space views: {}", err ); } diff --git a/crates/re_viewer/src/ui/blueprint_panel.rs b/crates/re_viewer/src/ui/blueprint_panel.rs index 38e1ba0cf23a..737e0a69fe8c 100644 --- a/crates/re_viewer/src/ui/blueprint_panel.rs +++ b/crates/re_viewer/src/ui/blueprint_panel.rs @@ -11,7 +11,7 @@ pub fn blueprint_panel_ui( ctx.re_ui.panel_title_bar_with_buttons( ui, "Blueprint", - Some("The Blueprint is where you can configure the Rerun Viewer"), + Some("The blueprint is where you can configure the Rerun Viewer"), |ui| { viewport.add_new_spaceview_button_ui(ctx, ui); reset_blueprint_button_ui(ctx, ui); @@ -28,7 +28,7 @@ fn reset_blueprint_button_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { if ctx .re_ui .small_icon_button(ui, &re_ui::icons::RESET) - .on_hover_text("Re-populate Viewport with automatically chosen Space Views") + .on_hover_text("Re-populate viewport with automatically chosen space views") .clicked() { ctx.command_sender diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index b4fe6692b852..393009f3815f 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -578,15 +578,15 @@ impl MemoryPanel { plot_ui.line(to_line(resident).name("Resident").width(1.5)); plot_ui.line(to_line(counted).name("Counted").width(1.5)); plot_ui.line(to_line(counted_gpu).name("Counted GPU").width(1.5)); - plot_ui.line(to_line(counted_store).name("Counted Store").width(1.5)); + plot_ui.line(to_line(counted_store).name("Counted store").width(1.5)); plot_ui.line( to_line(counted_primary_caches) - .name("Counted Primary Caches") + .name("Counted primary caches") .width(1.5), ); plot_ui.line( to_line(counted_blueprint) - .name("Counted Blueprint") + .name("Counted blueprint") .width(1.5), ); }); diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index 306ea50548b5..84356f86840c 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -330,7 +330,7 @@ fn options_menu_ui( ui, &mut app_options.time_zone, TimeZone::UnixEpoch, - "Unix Epoch", + "Unix epoch", ) .on_hover_text("Display timestamps in seconds since unix epoch"); }); @@ -367,14 +367,14 @@ fn experimental_feature_ui( ) { #[cfg(not(target_arch = "wasm32"))] re_ui - .checkbox(ui, &mut app_options.experimental_space_view_screenshots, "Space View screenshots") - .on_hover_text("Allow taking screenshots of 2D and 3D Space Views via their context menu. Does not contain labels."); + .checkbox(ui, &mut app_options.experimental_space_view_screenshots, "Space view screenshots") + .on_hover_text("Allow taking screenshots of 2D and 3D space views via their context menu. Does not contain labels."); if re_ui .checkbox( ui, &mut app_options.experimental_dataframe_space_view, - "Dataframe Space View", + "Dataframe space view", ) .on_hover_text("Enable the experimental dataframe space view.") .clicked() diff --git a/crates/re_viewer/src/ui/selection_history_ui.rs b/crates/re_viewer/src/ui/selection_history_ui.rs index e994fce08fe2..41d8a818e842 100644 --- a/crates/re_viewer/src/ui/selection_history_ui.rs +++ b/crates/re_viewer/src/ui/selection_history_ui.rs @@ -188,7 +188,7 @@ fn item_to_string(blueprint: &ViewportBlueprint, item: &Item) -> String { if let Some(space_view) = blueprint.space_view(space_view_id) { space_view.display_name_or_default().as_ref().to_owned() } else { - "".to_owned() + "".to_owned() } } Item::InstancePath(instance_path) => instance_path.to_string(), @@ -198,7 +198,7 @@ fn item_to_string(blueprint: &ViewportBlueprint, item: &Item) -> String { if let Some(space_view) = blueprint.space_view(space_view_id) { space_view.display_name_or_default().as_ref().to_owned() } else { - "".to_owned() + "".to_owned() }; format!("{instance_path} in {space_view_display_name}") @@ -211,7 +211,7 @@ fn item_to_string(blueprint: &ViewportBlueprint, item: &Item) -> String { if let Some(container) = blueprint.container(container_id) { container.display_name_or_default().as_ref().to_owned() } else { - "".to_owned() + "".to_owned() } } } diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 86c8730ed697..09a7cf9b3039 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -33,7 +33,7 @@ use super::{selection_history_ui::SelectionHistoryUi, visible_history::visual_ti // --- -/// The "Selection View" sidebar. +/// The "Selection view" sidebar. #[derive(Default, serde::Deserialize, serde::Serialize)] #[serde(default)] pub(crate) struct SelectionPanel { @@ -284,7 +284,7 @@ fn space_view_button( is_selected, contents_name_style(&space_view_name), ) - .on_hover_text("Space View"); + .on_hover_text("Space view"); item_ui::cursor_interact_with_selectable(ctx, response, item) } @@ -330,11 +330,11 @@ fn what_is_selected_ui( let hover_text = if let Some(display_name) = container_blueprint.display_name.as_ref() { format!( - "{:?} Container {display_name:?}", + "{:?} container {display_name:?}", container_blueprint.container_kind, ) } else { - format!("Unnamed {:?} Container", container_blueprint.container_kind,) + format!("Unnamed {:?} container", container_blueprint.container_kind,) }; let container_name = container_blueprint.display_name_or_default(); @@ -382,13 +382,13 @@ fn what_is_selected_ui( let hover_text = if let Some(display_name) = space_view.display_name.as_ref() { format!( - "Space View {:?} of type {}", + "Space view {:?} of type {}", display_name, space_view_class.display_name() ) } else { format!( - "Unnamed Space View of type {}", + "Unnamed space view of type {}", space_view_class.display_name() ) }; @@ -447,7 +447,7 @@ fn what_is_selected_ui( name, Some(guess_instance_path_icon(ctx, instance_path)), &format!( - "{typ} '{instance_path}' as shown in Space View {:?}", + "{typ} '{instance_path}' as shown in space view {:?}", space_view.display_name ), ); @@ -520,7 +520,7 @@ fn list_existing_data_blueprints( let (query, store) = guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); if space_views_with_path.is_empty() { - ui.weak("(Not shown in any Space View)"); + ui.weak("(Not shown in any space view)"); } else { for space_view_id in &space_views_with_path { if let Some(space_view) = blueprint.space_view(space_view_id) { @@ -545,7 +545,7 @@ fn list_existing_data_blueprints( /// Display the top-level properties of a space view. /// /// This includes the name, space origin entity, and space view type. These properties are singled -/// out as needing to be edited in most case when creating a new Space View, which is why they are +/// out as needing to be edited in most case when creating a new space view, which is why they are /// shown at the very top. fn space_view_top_level_properties( ui: &mut egui::Ui, @@ -559,7 +559,7 @@ fn space_view_top_level_properties( .show(ui, |ui| { let mut name = space_view.display_name.clone().unwrap_or_default(); ui.label("Name").on_hover_text( - "The name of the Space View used for display purposes. This can be any text \ + "The name of the space view used for display purposes. This can be any text \ string.", ); ui.text_edit_singleline(&mut name); @@ -568,8 +568,8 @@ fn space_view_top_level_properties( ui.end_row(); ui.label("Space origin").on_hover_text( - "The origin Entity for this Space View. For spatial Space Views, the Space \ - View's origin is the same as this Entity's origin and all transforms are \ + "The origin entity for this space view. For spatial space views, the space \ + View's origin is the same as this entity's origin and all transforms are \ relative to it.", ); @@ -580,7 +580,7 @@ fn space_view_top_level_properties( ui.end_row(); ui.label("Type") - .on_hover_text("The type of this Space View"); + .on_hover_text("The type of this space view"); ui.label( space_view .class(ctx.space_view_class_registry) @@ -607,7 +607,7 @@ fn container_top_level_properties( .show(ui, |ui| { let mut name = container.display_name.clone().unwrap_or_default(); ui.label("Name").on_hover_text( - "The name of the Container used for display purposes. This can be any text string.", + "The name of the container used for display purposes. This can be any text string.", ); ui.text_edit_singleline(&mut name); container.set_display_name(ctx, if name.is_empty() { None } else { Some(name) }); @@ -734,7 +734,7 @@ fn show_list_item_for_container_child( .with_buttons(|re_ui, ui| { let response = re_ui .small_icon_button(ui, &re_ui::icons::REMOVE) - .on_hover_text("Remove this Space View"); + .on_hover_text("Remove this space view"); if response.clicked() { remove_contents = true; @@ -760,7 +760,7 @@ fn show_list_item_for_container_child( .with_buttons(|re_ui, ui| { let response = re_ui .small_icon_button(ui, &re_ui::icons::REMOVE) - .on_hover_text("Remove this Container"); + .on_hover_text("Remove this container"); if response.clicked() { remove_contents = true; @@ -856,9 +856,9 @@ fn blueprint_ui_for_space_view( } if ui - .button("Clone Space View") + .button("Clone space view") .on_hover_text( - "Create an exact duplicate of this Space View including all Blueprint settings", + "Create an exact duplicate of this space view including all blueprint settings", ) .clicked() { @@ -911,7 +911,7 @@ fn blueprint_ui_for_space_view( &mut props, ) { re_log::error!( - "Error in Space View selection UI (class: {}, display name: {}): {err}", + "Error in space view selection UI (class: {}, display name: {}): {err}", space_view.class_identifier(), space_view_class.display_name(), ); diff --git a/crates/re_viewer/src/ui/top_panel.rs b/crates/re_viewer/src/ui/top_panel.rs index 57826fc872f0..33f7a5ac8b0b 100644 --- a/crates/re_viewer/src/ui/top_panel.rs +++ b/crates/re_viewer/src/ui/top_panel.rs @@ -268,7 +268,7 @@ fn panel_buttons_r2l(app: &App, app_blueprint: &AppBlueprint<'_>, ui: &mut egui: &mut blueprint_panel_expanded, ) .on_hover_text(format!( - "Toggle Blueprint View{}", + "Toggle blueprint view{}", UICommand::ToggleBlueprintPanel.format_shortcut_tooltip_suffix(ui.ctx()) )) .clicked() diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index 5d52cb4f83fc..b88a9b7e88cb 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -79,15 +79,15 @@ pub fn visual_time_range_ui( re_ui .radio_value(ui, &mut has_individual_range, false, "Default") .on_hover_text(if is_space_view { - "Default visible time range settings for this kind of Space View" + "Default visible time range settings for this kind of space view" } else { "Visible time range settings inherited from parent Entity or enclosing \ - Space View" + space view" }); re_ui .radio_value(ui, &mut has_individual_range, true, "Override") .on_hover_text(if is_space_view { - "Set visible time range settings for the contents of this Space View" + "Set visible time range settings for the contents of this space view" } else { "Set visible time range settings for this entity" }); @@ -261,9 +261,9 @@ pub fn visual_time_range_ui( } let markdown = format!("# Visible time range\n -This feature controls the time range used to display data in the Space View. +This feature controls the time range used to display data in the space view. -The settings are inherited from the parent Entity or enclosing Space View if not overridden. +The settings are inherited from the parent Entity or enclosing space view if not overridden. Visible time range properties are stored separately for each _type_ of timelines. They may differ depending on \ whether the current timeline is temporal or a sequence. The current settings apply to all _{}_ timelines. diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 71d1cb15f4a6..27d68d583140 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -123,19 +123,19 @@ impl Item { }, Item::InstancePath(instance_path) => { if instance_path.instance_key.is_specific() { - "Entity Instance" + "Entity instance" } else { "Entity" } } - Item::ComponentPath(_) => "Entity Component", - Item::SpaceView(_) => "Space View", + Item::ComponentPath(_) => "Entity component", + Item::SpaceView(_) => "Space view", Item::Container(_) => "Container", Item::DataResult(_, instance_path) => { if instance_path.instance_key.is_specific() { - "Data Result Instance" + "Data result instance" } else { - "Data Result Entity" + "Data result entity" } } } diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index df6bc0a3cff1..b4da1ba5f82b 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -57,7 +57,7 @@ pub enum SpaceViewSystemExecutionError { #[error(transparent)] GpuTransferError(#[from] re_renderer::CpuWriteGpuReadError), - #[error("Failed to downcast Space View's to the {0}.")] + #[error("Failed to downcast space view's to the {0}.")] StateCastError(&'static str), } diff --git a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs index 3ad5ac0a8563..f60bcea30617 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs @@ -11,11 +11,11 @@ pub struct SpaceViewClassPlaceholder; impl SpaceViewClass for SpaceViewClassPlaceholder { fn identifier() -> SpaceViewClassIdentifier { - "Unknown Space View Class".into() + "Unknown space view class".into() } fn display_name(&self) -> &'static str { - "Unknown Space View Class" + "Unknown space view class" } fn icon(&self) -> &'static re_ui::Icon { @@ -23,7 +23,7 @@ impl SpaceViewClass for SpaceViewClassPlaceholder { } fn help_text(&self, _re_ui: &re_ui::ReUi) -> egui::WidgetText { - "The Space View Class was not recognized.\nThis happens if either the Blueprint specifies an invalid Space View Class or this version of the Viewer does not know about this type.".into() + "The space view class was not recognized.\nThis happens if either the blueprint specifies an invalid space view class or this version of the viewer does not know about this type.".into() } fn on_register( diff --git a/crates/re_viewer_context/src/space_view/space_view_class_registry.rs b/crates/re_viewer_context/src/space_view/space_view_class_registry.rs index 722b87851bf7..d15450ab8681 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_registry.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_registry.rs @@ -15,16 +15,16 @@ use super::{ #[derive(Debug, thiserror::Error)] #[allow(clippy::enum_variant_names)] pub enum SpaceViewClassRegistryError { - #[error("Space View with class identifier {0:?} was already registered.")] + #[error("Space view with class identifier {0:?} was already registered.")] DuplicateClassIdentifier(SpaceViewClassIdentifier), - #[error("A Context System with identifier {0:?} was already registered.")] + #[error("A context system with identifier {0:?} was already registered.")] IdentifierAlreadyInUseForContextSystem(&'static str), - #[error("A Visualizer System with identifier {0:?} was already registered.")] + #[error("A visualizer system with identifier {0:?} was already registered.")] IdentifierAlreadyInUseForVisualizer(&'static str), - #[error("Space View with class identifier {0:?} was not registered.")] + #[error("Space view with class identifier {0:?} was not registered.")] UnknownClassIdentifier(SpaceViewClassIdentifier), } diff --git a/crates/re_viewport/src/add_space_view_or_container_modal.rs b/crates/re_viewport/src/add_space_view_or_container_modal.rs index 26a2ec536a3f..b1c6e00f73fd 100644 --- a/crates/re_viewport/src/add_space_view_or_container_modal.rs +++ b/crates/re_viewport/src/add_space_view_or_container_modal.rs @@ -31,7 +31,7 @@ impl AddSpaceViewOrContainerModal { ctx.re_ui, egui_ctx, || { - re_ui::modal::Modal::new("Add Space View or Container") + re_ui::modal::Modal::new("Add space view or container") .min_width(500.0) .full_span_content(true) }, @@ -118,7 +118,7 @@ fn modal_ui( let title = space_view .class(ctx.space_view_class_registry) .display_name(); - let subtitle = format!("Create a new Space View to display {title} content."); + let subtitle = format!("Create a new space view to display {title} content."); if row_ui(ui, icon, title, &subtitle).clicked() { viewport.add_space_views(std::iter::once(space_view), ctx, target_container, None); diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index 3748905ddfc9..1dcabc0a84a7 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -60,9 +60,9 @@ impl ContainerBlueprint { .map_err(|err| { if !matches!(err, re_query::QueryError::PrimaryNotFound(_)) { if cfg!(debug_assertions) { - re_log::error!("Failed to load Container blueprint: {err}."); + re_log::error!("Failed to load container blueprint: {err}."); } else { - re_log::debug!("Failed to load Container blueprint: {err}."); + re_log::debug!("Failed to load container blueprint: {err}."); } } }) @@ -165,7 +165,7 @@ impl ContainerBlueprint { if let Some(row) = DataRow::from_archetype(RowId::new(), timepoint.clone(), id.as_entity_path(), &arch) - .warn_on_err_once("Failed to create Container blueprint.") + .warn_on_err_once("Failed to create container blueprint.") { deltas.push(row); diff --git a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs index d31511db78e1..005d8ce42d15 100644 --- a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs +++ b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs @@ -34,7 +34,7 @@ impl ContextMenuAction for AddEntitiesToNewSpaceViewAction { .cloned() .collect(); - ui.menu_button("Add to new Space View", |ui| { + ui.menu_button("Add to new space view", |ui| { let buttons_for_space_view_classes = |ui: &mut egui::Ui, space_view_classes: &IntSet| { for (identifier, display_name) in space_view_classes diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index b7119855acae..d3b62368203e 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -125,7 +125,7 @@ fn action_list( ], }), Box::new(SubMenu { - label: "Add Space View".to_owned(), + label: "Add space view".to_owned(), actions: ctx .space_view_class_registry .iter_registry() diff --git a/crates/re_viewport/src/space_view_entity_picker.rs b/crates/re_viewport/src/space_view_entity_picker.rs index 35fcce9b290c..898911edacb8 100644 --- a/crates/re_viewport/src/space_view_entity_picker.rs +++ b/crates/re_viewport/src/space_view_entity_picker.rs @@ -201,9 +201,9 @@ fn add_entities_line_ui( } if is_explicitly_excluded { - response.on_hover_text("Stop excluding this EntityPath."); + response.on_hover_text("Stop excluding this entity path."); } else if is_explicitly_included { - response.on_hover_text("Stop including this EntityPath."); + response.on_hover_text("Stop including this entity path."); } } else if is_included { // Remove-button @@ -218,7 +218,7 @@ fn add_entities_line_ui( } response.on_hover_text( - "Exclude this Entity and all its descendants from the Space View", + "Exclude this entity and all its descendants from the space view", ); } else { // Add-button: @@ -239,11 +239,11 @@ fn add_entities_line_ui( if enabled { if add_info.can_add.is_compatible_and_missing() { response.on_hover_text( - "Include this Entity and all its descendants in the Space View", + "Include this entity and all its descendants in the space view", ); } else { response - .on_hover_text("Add descendants of this Entity to the Space View"); + .on_hover_text("Add descendants of this entity to the space view"); } } else if let CanAddToSpaceView::No { reason } = &add_info.can_add { response.on_disabled_hover_text(reason); @@ -339,7 +339,7 @@ fn create_entity_add_info( // TODO(#4826): This shouldn't necessarily prevent us from adding it. CanAddToSpaceView::No { reason: format!( - "Entity can't be displayed by any of the available visualizers in this class of Space View ({}).", + "Entity can't be displayed by any of the available visualizers in this class of space view ({}).", space_view.class_identifier() ), } diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index d2f5ea496fa7..ed568402f5f9 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -35,10 +35,10 @@ pub struct PerSpaceViewState { /// is not saved. #[derive(Default)] pub struct ViewportState { - /// State for the "Add Entity" modal. + /// State for the "Add entity" modal. space_view_entity_modal: SpaceViewEntityPicker, - /// State for the "Add Space View or Container" modal. + /// State for the "Add space view or container" modal. add_space_view_container_modal: AddSpaceViewOrContainerModal, space_view_states: HashMap, @@ -768,7 +768,7 @@ impl<'a, 'b> egui_tiles::Behavior for TabViewer<'a, 'b> { .ctx .re_ui .small_icon_button(ui, &re_ui::icons::MAXIMIZE) - .on_hover_text("Maximize Space View") + .on_hover_text("Maximize space view") .clicked() { *self.maximized = Some(space_view_id); @@ -865,7 +865,7 @@ impl<'a, 'b> egui_tiles::Behavior for TabViewer<'a, 'b> { /// A tab button for a tab in the viewport. /// /// The tab can contain any `egui_tiles::Tile`, -/// which is either a Pane with a Space View, or a Container, +/// which is either a Pane with a Space View, or a container, /// e.g. a grid of tiles. struct TabWidget { galley: std::sync::Arc, @@ -909,10 +909,10 @@ impl TabWidget { item: Some(Item::SpaceView(*space_view_id)), } } else { - re_log::warn_once!("Space View {space_view_id} not found"); + re_log::warn_once!("Space view {space_view_id} not found"); TabDesc { - label: tab_viewer.ctx.re_ui.error_text("Unknown Space View").into(), + label: tab_viewer.ctx.re_ui.error_text("Unknown space view").into(), icon: &re_ui::icons::SPACE_VIEW_GENERIC, user_named: false, item: None, @@ -960,7 +960,7 @@ impl TabWidget { re_log::warn_once!("Container for tile ID {tile_id:?} not found"); TabDesc { - label: tab_viewer.ctx.re_ui.error_text("Unknown Container").into(), + label: tab_viewer.ctx.re_ui.error_text("Unknown container").into(), icon: &re_ui::icons::SPACE_VIEW_GENERIC, user_named: false, item: None, diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 79c7dcc8d3ef..32896c41d78a 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -383,7 +383,7 @@ impl Viewport<'_, '_> { container_visible: bool, ) { let Some(space_view) = self.blueprint.space_views.get(space_view_id) else { - re_log::warn_once!("Bug: asked to show a ui for a Space View that doesn't exist"); + re_log::warn_once!("Bug: asked to show a ui for a space view that doesn't exist"); return; }; debug_assert_eq!(space_view.id, *space_view_id); @@ -418,7 +418,7 @@ impl Viewport<'_, '_> { .with_buttons(|re_ui, ui| { let vis_response = visibility_button_ui(re_ui, ui, container_visible, &mut visible); - let response = remove_button_ui(re_ui, ui, "Remove Space View from the Viewport"); + let response = remove_button_ui(re_ui, ui, "Remove space view from the viewport"); if response.clicked() { self.blueprint.mark_user_interaction(ctx); self.blueprint @@ -481,7 +481,7 @@ impl Viewport<'_, '_> { }, ); - response = response.on_hover_text("Space View"); + response = response.on_hover_text("Space view"); if response.clicked() { self.blueprint.focus_tab(space_view.id); @@ -597,7 +597,7 @@ impl Viewport<'_, '_> { let response = remove_button_ui( re_ui, ui, - "Remove Group and all its children from the Space View", + "Remove group and all its children from the space view", ); if response.clicked() { space_view.contents.add_entity_exclusion( @@ -673,7 +673,7 @@ impl Viewport<'_, '_> { if ctx .re_ui .small_icon_button(ui, &re_ui::icons::ADD) - .on_hover_text("Add a new Space View or Container") + .on_hover_text("Add a new space view or container") .clicked() { // If a single container is selected, we use it as target. Otherwise, we target the diff --git a/docs/content/reference/types/archetypes/disconnected_space.md b/docs/content/reference/types/archetypes/disconnected_space.md index fd617c1979dc..4aca844f0471 100644 --- a/docs/content/reference/types/archetypes/disconnected_space.md +++ b/docs/content/reference/types/archetypes/disconnected_space.md @@ -20,7 +20,7 @@ This is useful for specifying that a subgraph is independent of the rest of the ## Example -### Disconnected Space +### Disconnected space snippet: disconnected_space diff --git a/examples/cpp/shared_recording/README.md b/examples/cpp/shared_recording/README.md index 167352c49895..3a7b00a958a9 100644 --- a/examples/cpp/shared_recording/README.md +++ b/examples/cpp/shared_recording/README.md @@ -1,5 +1,5 @@ diff --git a/examples/python/shared_recording/README.md b/examples/python/shared_recording/README.md index db773eedd4dc..0124c90a37f5 100644 --- a/examples/python/shared_recording/README.md +++ b/examples/python/shared_recording/README.md @@ -1,5 +1,5 @@ diff --git a/examples/rust/custom_space_view/README.md b/examples/rust/custom_space_view/README.md index 055b5fa03ed5..9c6d74bd59ce 100644 --- a/examples/rust/custom_space_view/README.md +++ b/examples/rust/custom_space_view/README.md @@ -1,5 +1,5 @@ diff --git a/examples/rust/custom_store_subscriber/README.md b/examples/rust/custom_store_subscriber/README.md index 7ec39623d007..337543e0dbb3 100644 --- a/examples/rust/custom_store_subscriber/README.md +++ b/examples/rust/custom_store_subscriber/README.md @@ -1,5 +1,5 @@ diff --git a/examples/rust/custom_store_subscriber/src/main.rs b/examples/rust/custom_store_subscriber/src/main.rs index 4c985ce79d92..ed9b8c03e706 100644 --- a/examples/rust/custom_store_subscriber/src/main.rs +++ b/examples/rust/custom_store_subscriber/src/main.rs @@ -127,7 +127,7 @@ impl StoreSubscriber for ComponentsPerRecording { println!("---------------"); for (recording, per_component) in &self.counters { - println!(" Recording '{recording}':"); + println!(" Recording '{recording}':"); // NOLINT for (component, counter) in per_component { println!(" {component}: {counter} occurrences"); } diff --git a/examples/rust/shared_recording/README.md b/examples/rust/shared_recording/README.md index af954e850bb2..d03a4acd6067 100644 --- a/examples/rust/shared_recording/README.md +++ b/examples/rust/shared_recording/README.md @@ -1,5 +1,5 @@ diff --git a/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp b/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp index d3ba12bdc95c..04328cbff25c 100644 --- a/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp +++ b/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp @@ -23,7 +23,7 @@ namespace rerun::archetypes { /// /// ## Example /// - /// ### Disconnected Space + /// ### Disconnected space /// ![image](https://static.rerun.io/disconnected_space/b8f95b0e32359de625a765247c84935146c1fba9/full.png) /// /// ```cpp diff --git a/rerun_py/rerun_sdk/rerun/archetypes/disconnected_space.py b/rerun_py/rerun_sdk/rerun/archetypes/disconnected_space.py index 78cd13d92b58..7c8502be84bd 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/disconnected_space.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/disconnected_space.py @@ -26,7 +26,7 @@ class DisconnectedSpace(DisconnectedSpaceExt, Archetype): Example ------- - ### Disconnected Space: + ### Disconnected space: ```python import rerun as rr diff --git a/rerun_py/tests/unit/test_space_view_blueprint.py b/rerun_py/tests/unit/test_space_view_blueprint.py index 1555794dbbd6..90728b39aa66 100644 --- a/rerun_py/tests/unit/test_space_view_blueprint.py +++ b/rerun_py/tests/unit/test_space_view_blueprint.py @@ -16,7 +16,7 @@ def test_space_view_blueprint() -> None: class_identifier_arrays = ["3D", SpaceViewClass("3D")] - display_name_arrays = ["3D View", Name("3D View"), None] + display_name_arrays = ["3D view", Name("3D view"), None] space_origin_arrays = ["/robot/arm", None, SpaceViewOrigin("/robot/arm")] visible_arrays = [False, Visible(False), None] @@ -54,6 +54,6 @@ def test_space_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 == SpaceViewClassBatch("3D") - assert arch.display_name == NameBatch._optional(none_empty_or_value(display_name, "3D View")) + assert arch.display_name == NameBatch._optional(none_empty_or_value(display_name, "3D view")) assert arch.space_origin == SpaceViewOriginBatch._optional(none_empty_or_value(space_origin, "/robot/arm")) assert arch.visible == VisibleBatch._optional(none_empty_or_value(visible, False)) diff --git a/scripts/lint.py b/scripts/lint.py index 130f0eca1144..6cce10c4fe70 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -53,6 +53,36 @@ def is_valid_todo_part(part: str) -> bool: return False +def check_string(s: str) -> str | None: + """Check that the string has the correct casing.""" + if len(s) == 0: + return None + + bad_titles = [ + "Blueprint", + "Class", + "Container", + "Entity", + "EntityPath", + "Epoch", + "Instance", + "Path", + "Recording", + "Result", + "Space", + "Store", + "View", + "Viewport", + ] + + if m := re.search(r"[^.] ([A-Z]\w+)", s): + word = m.group(1) + if word in bad_titles: + return f"Do not use title casing ({word}). See https://github.com/rerun-io/rerun/blob/main/DESIGN.md" + + return None + + def lint_line( line: str, prev_line: str | None, file_extension: str = "rs", is_in_docstring: bool = False ) -> str | None: @@ -151,6 +181,10 @@ def lint_line( if explicit_quotes.search(line): return "Prefer using {:?} - it will also escape newlines etc" + if m := re.search(r'"([^"]*)"', line): + if err := check_string(m.group(1)): + return err + if "rec_stream" in line or "rr_stream" in line: return "Instantiated RecordingStreams should be named `rec`" @@ -195,7 +229,7 @@ def test_lint_line() -> None: "hello world", "this is a 2D spaceview", "todo lowercase is fine", - 'todo!("macro is ok with text")', + 'todo!("Macro is ok with text")', "TODO_TOKEN", "TODO(bob):", "TODO(bob,alice):", @@ -223,6 +257,7 @@ def test_lint_line() -> None: "instances_count", "let Some(foo) = bar else { return; };", "{foo:?}", + 'ui.label("This is fine. Correct casing.")', "rec", "anyhow::Result<()>", "The theme is great", @@ -300,6 +335,7 @@ def test_lint_line() -> None: r'println!("Problem: \"{}\"", string)', r'println!("Problem: \"{0}\"")', r'println!("Problem: \"{string}\"")', + 'ui.label("This uses ugly title casing for Space View.")', "trailing whitespace ", "rr_stream", "rec_stream", diff --git a/tests/python/release_checklist/check_context_menu_suggested_origin.py b/tests/python/release_checklist/check_context_menu_suggested_origin.py index 66a079e9489f..c68136ba868e 100644 --- a/tests/python/release_checklist/check_context_menu_suggested_origin.py +++ b/tests/python/release_checklist/check_context_menu_suggested_origin.py @@ -14,7 +14,7 @@ Repeat these steps for each of the following entities and space view class: - right-click the entity (either in the blueprint or streams tree) -- select "Add to new Space View" and create the space view of the listed class +- select "Add to new space view" and create the space view of the listed class - check that the created space view has the expected origin - delete the space view From 07e52dab08fc691fab8653177d3a303c14ce7d79 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 27 Mar 2024 12:32:13 +0100 Subject: [PATCH 125/508] Update `mimalloc` to latest to fix stack unwinding (#5705) - Fixes https://github.com/rerun-io/rerun/issues/5704 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5705/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5705/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5705/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5705) - [Docs preview](https://rerun.io/preview/5b839fefd58264bac04f689a7e0f26e539747920/docs) - [Examples preview](https://rerun.io/preview/5b839fefd58264bac04f689a7e0f26e539747920/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1dbd44ac32b4..6162eb0b69e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2906,9 +2906,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" [[package]] name = "libmimalloc-sys" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e" +checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664" dependencies = [ "cc", "libc", @@ -3096,9 +3096,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.37" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98" +checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c" dependencies = [ "libmimalloc-sys", ] diff --git a/Cargo.toml b/Cargo.toml index de5ce3c5bf60..5b120454ed26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -156,7 +156,7 @@ log-once = "0.4" lz4_flex = "0.11" macaw = "0.18" memory-stats = "1.1" -mimalloc = "0.1.29" +mimalloc = "0.1.39" mime = "0.3" mime_guess2 = "2.0" mint = "0.5.9" From bb89dd2e15714ccd38a954bae8c31d62f46de876 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 27 Mar 2024 15:05:24 +0100 Subject: [PATCH 126/508] Enable the `derive` feature of `serde` (#5706) ### What Fix the nightly build: https://github.com/rerun-io/rerun/actions/runs/8451663141/job/23150464681 Whenever we use `serde` we want the `derive` feature. However, in many places we forgot to enable it, and things work anyway _mostly_, unless you're compiling crates individually, like we do on nightly. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5706/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5706/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5706/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5706) - [Docs preview](https://rerun.io/preview/bc9e5ad8caffbc32ba2ed1b342c92786d7a411e2/docs) - [Examples preview](https://rerun.io/preview/bc9e5ad8caffbc32ba2ed1b342c92786d7a411e2/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5b120454ed26..97954681b203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -193,7 +193,7 @@ rmp-serde = "1" ron = "0.8.0" rust-format = "0.3" seq-macro = "0.3" -serde = "1" +serde = { version = "1", features = ["derive"] } serde_bytes = "0.11" serde_json = { version = "1", default-features = false, features = ["std"] } serde_test = "1" From 1c3016f8a5060a43856b8f1f34b3ef6b36ea0bbc Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:40:58 +0100 Subject: [PATCH 127/508] Remove item spacing in sibling recordings/blueprints list (#5710) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What As the title say ☝🏻 PSA: always set `spacing.item_spacing.y` to 0 when using `ListItem`. Before: unsightly 😄 After: image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5710/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5710/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5710/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5710) - [Docs preview](https://rerun.io/preview/27968b00d8395aa7be2bcd8b076962533afd4bde/docs) - [Examples preview](https://rerun.io/preview/27968b00d8395aa7be2bcd8b076962533afd4bde/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/data_source.rs | 6 ++++-- crates/re_data_ui/src/entity_db.rs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/re_data_ui/src/data_source.rs b/crates/re_data_ui/src/data_source.rs index 251f0a63a90b..08ed29e80ab8 100644 --- a/crates/re_data_ui/src/data_source.rs +++ b/crates/re_data_ui/src/data_source.rs @@ -40,20 +40,22 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { } } - { + if !recordings.is_empty() { ui.add_space(8.0); ui.strong("Recordings in this data source"); ui.indent("recordings", |ui| { + ui.spacing_mut().item_spacing.y = 0.0; for entity_db in recordings { entity_db_button_ui(ctx, ui, entity_db, true); } }); } - { + if !blueprints.is_empty() { ui.add_space(8.0); ui.strong("Blueprints in this data source"); ui.indent("blueprints", |ui| { + ui.spacing_mut().item_spacing.y = 0.0; for entity_db in blueprints { entity_db_button_ui(ctx, ui, entity_db, true); } diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index ed6234788e82..7d4fb5fd09eb 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -133,6 +133,7 @@ fn sibling_stores_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui, entity_db: &Ent ui.strong("Recordings in this data source"); } ui.indent("recordings", |ui| { + ui.spacing_mut().item_spacing.y = 0.0; for entity_db in other_recordings { entity_db_button_ui(ctx, ui, entity_db, true); } @@ -146,6 +147,7 @@ fn sibling_stores_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui, entity_db: &Ent ui.strong("Blueprints in this data source"); } ui.indent("blueprints", |ui| { + ui.spacing_mut().item_spacing.y = 0.0; for entity_db in other_blueprints { entity_db_button_ui(ctx, ui, entity_db, true); } From a06cbdfba32822337215f8cff2fc17166f841e93 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 27 Mar 2024 17:41:10 +0100 Subject: [PATCH 128/508] Build release `.wasm` with debug symbols (#5708) ### What This makes the compressed .wasm around 300kB bigger (+5%). In return we get: * Good callstacks on panics * In-browser profiling using the normal browser profiling tools ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5708/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5708/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5708/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5708) - [Docs preview](https://rerun.io/preview/cc960afe63cccaddb8371596b8388033cba547bb/docs) - [Examples preview](https://rerun.io/preview/cc960afe63cccaddb8371596b8388033cba547bb/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_checks.yml | 2 +- .github/workflows/reusable_build_and_upload_rerun_cli.yml | 2 +- .github/workflows/reusable_build_web.yml | 2 +- .github/workflows/reusable_checks_rust.yml | 4 ++-- .github/workflows/reusable_publish_web.yml | 2 +- .github/workflows/reusable_release_crates.yml | 2 +- crates/re_build_web_viewer/README.md | 6 +++--- pixi.toml | 4 ++-- rerun_js/web-viewer/package.json | 4 ++-- scripts/ci/build_and_upload_wheels.py | 2 +- web_viewer/README.md | 2 +- 11 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 74d6d97b8594..9f90076c3b44 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -202,7 +202,7 @@ jobs: with: command: run # We build in release so that we can reuse the results for actual publishing, if necessary - args: --locked -p re_build_web_viewer -- --release + args: --locked -p re_build_web_viewer -- --release -g toml-lints: name: Lint TOML files diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index 056670dd6eef..79267dfd46cf 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -153,7 +153,7 @@ jobs: - name: Build web-viewer (release) shell: bash run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release + pixi run cargo run --locked -p re_build_web_viewer -- --release -g # This does not run in the pixi environment, doing so # causes it to select the wrong compiler on macos-arm64 diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 622561dd96c7..1e1adbf50573 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -63,7 +63,7 @@ jobs: if [ ${{ inputs.CHANNEL }} = "nightly" ]; then export DEFAULT_EXAMPLES_MANIFEST_URL="https://app.rerun.io/version/nightly/examples_manifest.json" fi - pixi run cargo run --locked -p re_build_web_viewer -- --release + pixi run cargo run --locked -p re_build_web_viewer -- --release -g # We build a single manifest pointing to the `commit` # All the `pr`, `main`, release tag, etc. variants will always just point to the resolved commit diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 3b4ce9353576..b23c31b79a81 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -64,7 +64,7 @@ jobs: - name: Build web-viewer (release) shell: bash run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release + pixi run cargo run --locked -p re_build_web_viewer -- --release -g - name: Rust checks & tests if: ${{ !inputs.ALL_CHECKS }} @@ -114,7 +114,7 @@ jobs: - name: Build web-viewer (release) shell: bash run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release + pixi run cargo run --locked -p re_build_web_viewer -- --release -g # --------------------------------------------------------------------------- diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index 1d0ed09555fc..f7d480a56b81 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -108,7 +108,7 @@ jobs: - name: Build web-viewer (release) shell: bash run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release + pixi run cargo run --locked -p re_build_web_viewer -- --release -g - name: Build examples shell: bash diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml index 92646766fd95..ca769ed0a13c 100644 --- a/.github/workflows/reusable_release_crates.yml +++ b/.github/workflows/reusable_release_crates.yml @@ -31,7 +31,7 @@ jobs: - name: Build web-viewer (release) shell: bash run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release + pixi run cargo run --locked -p re_build_web_viewer -- --release -g - name: Publish shell: bash diff --git a/crates/re_build_web_viewer/README.md b/crates/re_build_web_viewer/README.md index 222e3dcdaf8e..ca71944cbf2d 100644 --- a/crates/re_build_web_viewer/README.md +++ b/crates/re_build_web_viewer/README.md @@ -6,8 +6,8 @@ This is also called by the `build.rs` of `re_web_viewer_server`. ``` cargo r -p re_build_web_viewer -- --debug -```` +``` ``` -cargo r -p re_build_web_viewer -- --release -```` +cargo r -p re_build_web_viewer -- --release -g +``` diff --git a/pixi.toml b/pixi.toml index 82b873e67fcf..5ba5abd9c5d9 100644 --- a/pixi.toml +++ b/pixi.toml @@ -66,11 +66,11 @@ rerun-web-release = { cmd = "cargo run --package rerun-cli --no-default-features "rerun-build-web-release", ] } -# Compile the web-viewer wasm in release mode, doe not include the cli. +# Compile the web-viewer wasm in release mode. # # This installs the `wasm32-unknown-unknown` rust target if it's not already installed. # (this looks heavy but takes typically below 0.1s!) -rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --release" +rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --release -g" build-examples = "cargo run -q --locked -p re_build_examples --" diff --git a/rerun_js/web-viewer/package.json b/rerun_js/web-viewer/package.json index c822c78f1bb0..c085c6f4f161 100644 --- a/rerun_js/web-viewer/package.json +++ b/rerun_js/web-viewer/package.json @@ -11,7 +11,7 @@ } ], "scripts": { - "build:wasm": "cargo run -p re_build_web_viewer -- --release --module -o rerun_js/web-viewer", + "build:wasm": "cargo run -p re_build_web_viewer -- --release -g --module -o rerun_js/web-viewer", "build:wasm:debug": "cargo run -p re_build_web_viewer -- --debug --module -o rerun_js/web-viewer", "build:types": "tsc --noEmit && dts-buddy", "build": "npm run build:wasm && npm run build:types" @@ -53,4 +53,4 @@ "dts-buddy": "^0.3.0", "typescript": "^5.2.2" } -} \ No newline at end of file +} diff --git a/scripts/ci/build_and_upload_wheels.py b/scripts/ci/build_and_upload_wheels.py index 306dfb70d181..1916d56d9812 100755 --- a/scripts/ci/build_and_upload_wheels.py +++ b/scripts/ci/build_and_upload_wheels.py @@ -72,7 +72,7 @@ def build_and_upload(bucket: Bucket, mode: BuildMode, gcs_dir: str, target: str, if mode is BuildMode.PYPI: # Only build web viewer when publishing to pypi - run("pixi run cargo run --locked -p re_build_web_viewer -- --release") + run("pixi run cargo run --locked -p re_build_web_viewer -- --release -g") maturin_feature_flags = "--no-default-features --features pypi" elif mode is BuildMode.PR: maturin_feature_flags = "--no-default-features --features extension-module" diff --git a/web_viewer/README.md b/web_viewer/README.md index 9b75b22ba816..c532f4ace282 100644 --- a/web_viewer/README.md +++ b/web_viewer/README.md @@ -2,4 +2,4 @@ This folder contains the files required for the web viewer app. You can build the web viewer with: -`cargo r -p re_build_web_viewer -- --release` +`cargo r -p re_build_web_viewer -- --release -g` From a1f59db5ec213b058b8657750814c0f687fa907c Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 27 Mar 2024 17:55:55 +0100 Subject: [PATCH 129/508] Entity path query now shows simple statistics and warns if nothing is displayed (#5693) ### What * Fixes #5669 https://github.com/rerun-io/rerun/assets/1220815/91c63fbb-4b6e-4eb9-a5b5-3d14ea41d412 a small step towards making it easy to debug why no data might be shown ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5693/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5693/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5693/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5693) - [Docs preview](https://rerun.io/preview/b9425379e1b41bf8f1891ffada4e6e0d15edc3cc/docs) - [Examples preview](https://rerun.io/preview/b9425379e1b41bf8f1891ffada4e6e0d15edc3cc/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt --- .../re_space_view/src/space_view_contents.rs | 33 ++++++++++---- crates/re_viewer/src/ui/selection_panel.rs | 43 ++++++++++++++----- crates/re_viewer_context/src/query_context.rs | 11 +++++ 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 70287ab685f1..d04c87b26245 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -223,14 +223,22 @@ impl DataQuery for SpaceViewContents { let executor = QueryExpressionEvaluator::new(self, visualizable_entities_for_visualizer_systems); + let mut num_matching_entities = 0; + let mut num_visualized_entities = 0; let root_handle = { re_tracing::profile_scope!("add_entity_tree_to_data_results_recursive"); - executor - .add_entity_tree_to_data_results_recursive(ctx.recording.tree(), &mut data_results) + executor.add_entity_tree_to_data_results_recursive( + ctx.recording.tree(), + &mut data_results, + &mut num_matching_entities, + &mut num_visualized_entities, + ) }; DataQueryResult { tree: DataResultTree::new(data_results, root_handle), + num_matching_entities, + num_visualized_entities, } } } @@ -262,6 +270,8 @@ impl<'a> QueryExpressionEvaluator<'a> { &self, tree: &EntityTree, data_results: &mut SlotMap, + num_matching_entities: &mut usize, + num_visualized_entities: &mut usize, ) -> Option { // Early-out optimization if !self @@ -275,27 +285,34 @@ impl<'a> QueryExpressionEvaluator<'a> { let entity_path = &tree.path; - let tree_prefix_only = !self.entity_path_filter.is_included(entity_path); + let matches_filter = self.entity_path_filter.is_included(entity_path); + *num_matching_entities += matches_filter as usize; // TODO(#5067): For now, we always start by setting visualizers to the full list of available visualizers. // This is currently important for evaluating auto-properties during the space-view `on_frame_start`, which // is called before the property-overrider has a chance to update this list. // This list will be updated below during `update_overrides_recursive` by calling `choose_default_visualizers` // on the space view. - let visualizers: SmallVec<[_; 4]> = if tree_prefix_only { - Default::default() - } else { + let visualizers: SmallVec<[_; 4]> = if matches_filter { self.visualizable_entities_for_visualizer_systems .iter() .filter_map(|(visualizer, ents)| ents.contains(entity_path).then_some(*visualizer)) .collect() + } else { + Default::default() }; + *num_visualized_entities += !visualizers.is_empty() as usize; let children: SmallVec<[_; 4]> = tree .children .values() .filter_map(|subtree| { - self.add_entity_tree_to_data_results_recursive(subtree, data_results) + self.add_entity_tree_to_data_results_recursive( + subtree, + data_results, + num_matching_entities, + num_visualized_entities, + ) }) .collect(); @@ -308,7 +325,7 @@ impl<'a> QueryExpressionEvaluator<'a> { data_result: DataResult { entity_path: entity_path.clone(), visualizers, - tree_prefix_only, + tree_prefix_only: !matches_filter, property_overrides: None, }, children, diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 09a7cf9b3039..f357992e42e7 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -819,11 +819,11 @@ fn blueprint_ui( ) { match item { Item::SpaceView(space_view_id) => { - blueprint_ui_for_space_view(ui, ctx, viewport, space_view_id); + blueprint_ui_for_space_view(ui, ctx, viewport, *space_view_id); } Item::DataResult(space_view_id, instance_path) => { - blueprint_ui_for_data_result(ui, ctx, viewport, space_view_id, instance_path); + blueprint_ui_for_data_result(ui, ctx, viewport, *space_view_id, instance_path); } Item::DataSource(_) @@ -838,14 +838,16 @@ fn blueprint_ui_for_space_view( ui: &mut Ui, ctx: &ViewerContext<'_>, viewport: &mut Viewport<'_, '_>, - space_view_id: &SpaceViewId, + space_view_id: SpaceViewId, ) { - if let Some(space_view) = viewport.blueprint.space_view(space_view_id) { + if let Some(space_view) = viewport.blueprint.space_view(&space_view_id) { if let Some(new_entity_path_filter) = entity_path_filter_ui( ui, + ctx, viewport, space_view_id, &space_view.contents.entity_path_filter, + &space_view.space_origin, ) { space_view .contents @@ -862,7 +864,8 @@ fn blueprint_ui_for_space_view( ) .clicked() { - if let Some(new_space_view_id) = viewport.blueprint.duplicate_space_view(space_view_id, ctx) + if let Some(new_space_view_id) = + viewport.blueprint.duplicate_space_view(&space_view_id, ctx) { ctx.selection_state() .set_selection(Item::SpaceView(new_space_view_id)); @@ -874,7 +877,7 @@ fn blueprint_ui_for_space_view( ReUi::full_span_separator(ui); ui.add_space(ui.spacing().item_spacing.y / 2.0); - if let Some(space_view) = viewport.blueprint.space_view(space_view_id) { + if let Some(space_view) = viewport.blueprint.space_view(&space_view_id) { let class_identifier = *space_view.class_identifier(); let space_view_state = viewport.state.space_view_state_mut( @@ -925,10 +928,10 @@ fn blueprint_ui_for_data_result( ui: &mut Ui, ctx: &ViewerContext<'_>, viewport: &Viewport<'_, '_>, - space_view_id: &SpaceViewId, + space_view_id: SpaceViewId, instance_path: &InstancePath, ) { - if let Some(space_view) = viewport.blueprint.space_view(space_view_id) { + if let Some(space_view) = viewport.blueprint.space_view(&space_view_id) { if instance_path.instance_key.is_splat() { // splat - the whole entity let space_view_class = *space_view.class_identifier(); @@ -948,7 +951,7 @@ fn blueprint_ui_for_data_result( entity_props_ui( ctx, ui, - ctx.lookup_query_result(*space_view_id), + ctx.lookup_query_result(space_view_id), &space_view_class, entity_path, &mut props, @@ -962,9 +965,11 @@ fn blueprint_ui_for_data_result( /// Returns a new filter when the editing is done, and there has been a change. fn entity_path_filter_ui( ui: &mut egui::Ui, + ctx: &ViewerContext<'_>, viewport: &mut Viewport<'_, '_>, - space_view_id: &SpaceViewId, + space_view_id: SpaceViewId, filter: &EntityPathFilter, + origin: &EntityPath, ) -> Option { fn entity_path_filter_help_ui(ui: &mut egui::Ui) { let markdown = r#" @@ -1077,7 +1082,7 @@ The last rule matching `/world/house` is `+ /world/**`, so it is included. .on_hover_text("Modify the entity query using the editor") .clicked() { - viewport.show_add_remove_entities_modal(*space_view_id); + viewport.show_add_remove_entities_modal(space_view_id); } }, ); @@ -1093,6 +1098,22 @@ The last rule matching `/world/house` is `+ /world/**`, so it is included. ui.data_mut(|data| data.remove::(filter_text_id)); } + // Show some statistics about the query, print a warning text if something seems off. + let query = ctx.lookup_query_result(space_view_id); + if query.num_matching_entities == 0 { + ui.label(ctx.re_ui.warning_text("Does not match any entity")); + } else if query.num_matching_entities == 1 { + ui.label("Matches 1 entity"); + } else { + ui.label(format!("Matches {} entities", query.num_matching_entities)); + } + if query.num_matching_entities != 0 && query.num_visualized_entities == 0 { + // TODO(andreas): Talk about this root bit only if it's a spatial view. + ui.label(ctx.re_ui.warning_text( + format!("This space view is not able to visualize any of the matched entities using the current root \"{origin:?}\"."), + )); + } + // Apply the edit. let new_filter = EntityPathFilter::parse_forgiving(&filter_string, &Default::default()); if &new_filter == filter { diff --git a/crates/re_viewer_context/src/query_context.rs b/crates/re_viewer_context/src/query_context.rs index fc7a6079a28d..2b5302a8f560 100644 --- a/crates/re_viewer_context/src/query_context.rs +++ b/crates/re_viewer_context/src/query_context.rs @@ -17,6 +17,15 @@ slotmap::new_key_type! { pub struct DataQueryResult { /// The [`DataResultTree`] for the query pub tree: DataResultTree, + + /// The number of entities that matched the query, including those that are not visualizable. + pub num_matching_entities: usize, + + /// Of the matched queries, the number of entities that are visualizable by any given visualizer. + /// + /// This does *not* take into account the actual selection of visualizers + /// which may be an explicit none for any given entity. + pub num_visualized_entities: usize, } impl DataQueryResult { @@ -38,6 +47,8 @@ impl Clone for DataQueryResult { re_tracing::profile_function!(); Self { tree: self.tree.clone(), + num_matching_entities: self.num_matching_entities, + num_visualized_entities: self.num_visualized_entities, } } } From bd2f64abbde533be15f2071dae627f54fb240f04 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 27 Mar 2024 18:02:51 +0100 Subject: [PATCH 130/508] Improve getting started doc section (#5689) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What * Fixes #5460 Various improvements to the getting started doc sections: * better layout / new nesting structure * improved titles, updated some references accordingly * better & more complete install instructions * remove 'Welcome' page, make index == new "What is Rerun?" page ⚠️ adds a placeholder page for getting started on blueprint ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5689/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5689/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5689/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5689) - [Docs preview](https://rerun.io/preview/8a94f170002e4417e723545ef3005fc4b04966dc/docs) - [Examples preview](https://rerun.io/preview/8a94f170002e4417e723545ef3005fc4b04966dc/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt --- docs/content/getting-started.md | 10 +-- docs/content/getting-started/data-in.md | 12 ++++ .../data-in}/open-any-file.md | 6 +- .../getting-started/data-in/streaming.md | 10 +++ .../streaming/cpp.md} | 26 ++++---- .../streaming/python.md} | 28 ++++---- .../streaming/rust.md} | 28 ++++---- .../getting-started/installing-viewer.md | 65 ++++++++++++++----- docs/content/getting-started/quick-start.md | 10 +++ .../getting-started/{ => quick-start}/cpp.md | 12 ++-- .../{ => quick-start}/python.md | 14 ++-- .../getting-started/{ => quick-start}/rust.md | 10 +-- .../getting-started/troubleshooting.md | 2 +- docs/content/getting-started/visualize.md | 5 ++ .../getting-started/visualize/blueprint.md | 6 ++ .../{ => visualize}/viewer-walkthrough.md | 43 ++++++------ docs/content/getting-started/what-is-rerun.md | 50 ++++++++++++++ docs/content/howto/ros2-nav-turtlebot.md | 4 +- docs/content/index.md | 47 +------------- 19 files changed, 230 insertions(+), 158 deletions(-) create mode 100644 docs/content/getting-started/data-in.md rename docs/content/{howto => getting-started/data-in}/open-any-file.md (98%) create mode 100644 docs/content/getting-started/data-in/streaming.md rename docs/content/getting-started/{logging-cpp.md => data-in/streaming/cpp.md} (91%) rename docs/content/getting-started/{logging-python.md => data-in/streaming/python.md} (90%) rename docs/content/getting-started/{logging-rust.md => data-in/streaming/rust.md} (89%) create mode 100644 docs/content/getting-started/quick-start.md rename docs/content/getting-started/{ => quick-start}/cpp.md (92%) rename docs/content/getting-started/{ => quick-start}/python.md (92%) rename docs/content/getting-started/{ => quick-start}/rust.md (83%) create mode 100644 docs/content/getting-started/visualize.md create mode 100644 docs/content/getting-started/visualize/blueprint.md rename docs/content/getting-started/{ => visualize}/viewer-walkthrough.md (91%) create mode 100644 docs/content/getting-started/what-is-rerun.md diff --git a/docs/content/getting-started.md b/docs/content/getting-started.md index b1f0a8edb1c0..d647789fd9dd 100644 --- a/docs/content/getting-started.md +++ b/docs/content/getting-started.md @@ -1,13 +1,5 @@ --- title: Getting Started order: 0 +redirect: getting-started/what-is-rerun --- - -Rerun currently works with both [Python](getting-started/logging-python.md) and [Rust](getting-started/logging-rust.md). -If you are looking for other language support, search for an open issue on [GitHub](https://github.com/rerun-io/rerun/issues) to find the status. If you can't find an issue for your language, [open one](https://github.com/rerun-io/rerun/issues/new/choose). - -The fastest way to get started is with a quick start guide for [C++](getting-started/cpp.md), [Python](getting-started/python.md) or [Rust](getting-started/rust.md). - -Many of our [examples](/examples) currently utilize Python. Even for -Rust users, these examples are a good way to get a sense of how Rerun works and how you might use it in your own -project. diff --git a/docs/content/getting-started/data-in.md b/docs/content/getting-started/data-in.md new file mode 100644 index 000000000000..0f59e61801b0 --- /dev/null +++ b/docs/content/getting-started/data-in.md @@ -0,0 +1,12 @@ +--- +title: Get data into Rerun +order: 3 +--- + +This section talks about how to get data out of your application into Rerun. + +* Streaming data from your code + * [C++](./data-in/streaming/cpp.md) + * [Python](./data-in/streaming/python.md) + * [Rust](./data-in/streaming/rust.md) +* [Opening files](./data-in/open-any-file.md) diff --git a/docs/content/howto/open-any-file.md b/docs/content/getting-started/data-in/open-any-file.md similarity index 98% rename from docs/content/howto/open-any-file.md rename to docs/content/getting-started/data-in/open-any-file.md index b1cb45618dfa..3d0755b0a043 100644 --- a/docs/content/howto/open-any-file.md +++ b/docs/content/getting-started/data-in/open-any-file.md @@ -1,6 +1,6 @@ --- -title: Open any file -order: -10 +title: Opening files +order: 1 --- The Rerun Viewer and SDK have built-in support for opening many kinds of files, and can be extended to support any other file type without needing to modify the Rerun codebase itself. @@ -52,7 +52,7 @@ The easiest way to create your own `DataLoader` is by implementing what we call This executable takes a file path as a command line argument and outputs Rerun logs on `stdout`. It will be called by the Rerun Viewer/SDK when the user opens a file, and be passed the path to that file. -From there, it can log data as usual, using the [`stdout` logging sink](../reference/sdk-operating-modes.md#standard-inputoutput). +From there, it can log data as usual, using the [`stdout` logging sink](../../reference/sdk-operating-modes.md#standard-inputoutput). The Rerun Viewer/SDK will then automatically load the data streamed to the external loader's standard output. diff --git a/docs/content/getting-started/data-in/streaming.md b/docs/content/getting-started/data-in/streaming.md new file mode 100644 index 000000000000..fc7d7a592025 --- /dev/null +++ b/docs/content/getting-started/data-in/streaming.md @@ -0,0 +1,10 @@ +--- +title: Streaming data +order: 0 +--- + +A step by step tutorial for how to stream data from your application to the Rerun viewer. + +* [C++](./streaming/cpp.md) +* [Python](./streaming/python.md) +* [Rust](./streaming/rust.md) diff --git a/docs/content/getting-started/logging-cpp.md b/docs/content/getting-started/data-in/streaming/cpp.md similarity index 91% rename from docs/content/getting-started/logging-cpp.md rename to docs/content/getting-started/data-in/streaming/cpp.md index e903eca898be..06a9b47ea198 100644 --- a/docs/content/getting-started/logging-cpp.md +++ b/docs/content/getting-started/data-in/streaming/cpp.md @@ -1,5 +1,5 @@ --- -title: Logging Data in C++ +title: C++ order: 5 --- @@ -34,7 +34,7 @@ build\Debug\example_dna.exe ## Prerequisites -You should have already [installed the viewer](installing-viewer.md). +You should have already [installed the viewer](../../installing-viewer.md). We assume you have a working C++ toolchain and are using `CMake` to build your project. For this example we will let Rerun download build [Apache Arrow](https://arrow.apache.org/)'s C++ library itself. @@ -99,9 +99,9 @@ int main() { } ``` -Among other things, a stable `ApplicationId` will make it so the [Rerun Viewer](../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. +Among other things, a stable `ApplicationId` will make it so the [Rerun Viewer](../../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. -Check out the reference to learn more about how Rerun deals with [applications and recordings](../concepts/apps-and-recordings.md). +Check out the reference to learn more about how Rerun deals with [applications and recordings](../../../concepts/apps-and-recordings.md). ## Testing our app @@ -160,7 +160,7 @@ and now you should now see this scene in the viewer: _This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ -_Checkout the [Viewer Walkthrough](viewer-walkthrough.md) and [viewer reference](../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ +_Checkout the [Viewer Walkthrough](../../visualize/viewer-walkthrough.md) and [viewer reference](../../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood @@ -176,23 +176,23 @@ Under the hood, the Rerun C++ SDK logs individual *components* like positions, c and radii. Archetypes are just one high-level, convenient way of building such collections of components. For advanced use cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. -For more information on how the rerun data model works, refer to our section on [Entities and Components](../concepts/entity-component.md). +For more information on how the rerun data model works, refer to our section on [Entities and Components](../../../concepts/entity-component.md). Notably, the [`RecordingStream::log`](https://github.com/rerun-io/rerun/blob/d962b34b07775bbacf14883d683cca6746852b6a/rerun_cpp/src/rerun/recording_stream.hpp#L236) method will handle any data type that implements the [`AsComponents`](https://github.com/rerun-io/rerun/blob/latest/rerun_cpp/src/rerun/as_components.hpp) trait, making it easy to add your own data. -For more information on how to supply your own components see [Use custom data](../howto/extend/custom-data.md). +For more information on how to supply your own components see [Use custom data](../../../howto/extend/custom-data.md). ### Entities & hierarchies Note the two strings we're passing in: `"dna/structure/left"` and `"dna/structure/right"`. -These are [*entity paths*](../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. -[Entity paths typically form a hierarchy](../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). +These are [*entity paths*](../../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. +[Entity paths typically form a hierarchy](../../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Batches One final observation: notice how we're logging a whole batch of points and colors all at once here. -[Batches of data](../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. +[Batches of data](../../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this *splatting*. --- @@ -258,9 +258,9 @@ Once again, although we are getting fancier and fancier with our iterator mappin ### Introducing Time -Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../concepts/timelines.md). +Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../../concepts/timelines.md). -Even so, if you look at your [Timeline View](../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. +Even so, if you look at your [Timeline View](../../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. @@ -390,4 +390,4 @@ You can also save a recording (or a portion of it) as you're visualizing it, dir This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. -As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../reference/types.md) section for more simple examples of how to use the main data types. +As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../../reference/types.md) section for more simple examples of how to use the main data types. diff --git a/docs/content/getting-started/logging-python.md b/docs/content/getting-started/data-in/streaming/python.md similarity index 90% rename from docs/content/getting-started/logging-python.md rename to docs/content/getting-started/data-in/streaming/python.md index d4f3772ed2fe..19dc1ede4dcb 100644 --- a/docs/content/getting-started/logging-python.md +++ b/docs/content/getting-started/data-in/streaming/python.md @@ -1,5 +1,5 @@ --- -title: Logging Data in Python +title: Python order: 6 --- @@ -17,7 +17,7 @@ At any time, you can checkout the complete code listing for this tutorial [here] ## Prerequisites -We assume you have working Python and `rerun-sdk` installations. If not, check out the [setup page](python.md). +We assume you have working Python and `rerun-sdk` installations. If not, check out the [setup page](../../quick-start/python.md). ## Initializing the SDK @@ -32,13 +32,13 @@ import rerun as rr rr.init("rerun_example_dna_abacus") ``` -Among other things, a stable [`ApplicationId`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init) will make it so the [Rerun Viewer](../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. +Among other things, a stable [`ApplicationId`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init) will make it so the [Rerun Viewer](../../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. -Check out the reference to learn more about how Rerun deals with [applications and recordings](../concepts/apps-and-recordings.md). +Check out the reference to learn more about how Rerun deals with [applications and recordings](../../../concepts/apps-and-recordings.md). ## Starting the Viewer -Next up, we want to spawn the [Rerun Viewer](../reference/viewer/overview.md) itself. +Next up, we want to spawn the [Rerun Viewer](../../../reference/viewer/overview.md) itself. To do this, you can add the line: ```python @@ -95,7 +95,7 @@ rr.log("dna/structure/right", rr.Points3D(points2, colors=colors2, radii=0.08)) ``` Run your script once again and you should now see this scene in the viewer. -Note that if the viewer was still running, Rerun will simply connect to this existing session and replace the data with this new [_recording_](../concepts/apps-and-recordings.md). +Note that if the viewer was still running, Rerun will simply connect to this existing session and replace the data with this new [_recording_](../../../concepts/apps-and-recordings.md). @@ -108,7 +108,7 @@ Note that if the viewer was still running, Rerun will simply connect to this exi _This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ -_Checkout the [Viewer Walkthrough](viewer-walkthrough.md) and [viewer reference](../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ +_Checkout the [Viewer Walkthrough](../../visualize/viewer-walkthrough.md) and [viewer reference](../../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood @@ -126,7 +126,7 @@ and radii. Archetypes are just one high-level, convenient way of building such c cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. -For more information on how the rerun data model works, refer to our section on [Entities and Components](../concepts/entity-component.md). +For more information on how the rerun data model works, refer to our section on [Entities and Components](../../../concepts/entity-component.md). Our [Python SDK](https://ref.rerun.io/docs/python) integrates with the rest of the Python ecosystem: the points and colors returned by [`build_color_spiral`](https://ref.rerun.io/docs/python/stable/common/demo_utilities/#rerun.utilities.data.build_color_spiral) in this example are vanilla `numpy` arrays. Rerun takes care of mapping those arrays to actual Rerun components depending on the context (e.g. we're calling [`rr.Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points3D) in this case). @@ -135,13 +135,13 @@ Rerun takes care of mapping those arrays to actual Rerun components depending on Note the two strings we're passing in: `"dna/structure/left"` & `"dna/structure/right"`. -These are [*entity paths*](../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. -[Entity paths typically form a hierarchy](../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). +These are [*entity paths*](../../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. +[Entity paths typically form a hierarchy](../../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Batches One final observation: notice how we're logging a whole batch of points and colors all at once here. -[Batches of data](../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. +[Batches of data](../../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this *splatting*. --- @@ -190,9 +190,9 @@ there is nothing new here: it's all about building out `numpy` arrays and feedin ### Introducing Time -Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../concepts/timelines.md). +Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../../concepts/timelines.md). -Even so, if you look at your [Timeline View](../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. +Even so, if you look at your [Timeline View](../../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. @@ -321,4 +321,4 @@ You can also save a recording (or a portion of it) as you're visualizing it, dir This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. -As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../reference/types.md) section for more simple examples of how to use the main datatypes. +As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../../reference/types.md) section for more simple examples of how to use the main datatypes. diff --git a/docs/content/getting-started/logging-rust.md b/docs/content/getting-started/data-in/streaming/rust.md similarity index 89% rename from docs/content/getting-started/logging-rust.md rename to docs/content/getting-started/data-in/streaming/rust.md index c8eb045fd986..476da651f710 100644 --- a/docs/content/getting-started/logging-rust.md +++ b/docs/content/getting-started/data-in/streaming/rust.md @@ -1,5 +1,5 @@ --- -title: Logging Data in Rust +title: Rust order: 7 --- @@ -41,7 +41,7 @@ use rerun::{ ``` ## Starting the viewer -Just run `rerun` to start the [Rerun Viewer](../reference/viewer/overview.md). It will wait for your application to log some data to it. This viewer is in fact a server that's ready to accept data over TCP (it's listening on `0.0.0.0:9876` by default). +Just run `rerun` to start the [Rerun Viewer](../../../reference/viewer/overview.md). It will wait for your application to log some data to it. This viewer is in fact a server that's ready to accept data over TCP (it's listening on `0.0.0.0:9876` by default). Checkout `rerun --help` for more options. @@ -68,9 +68,9 @@ fn main() -> Result<(), Box> { } ``` -Among other things, a stable [`ApplicationId`](https://docs.rs/rerun/latest/rerun/struct.ApplicationId.html) will make it so the [Rerun Viewer](../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. +Among other things, a stable [`ApplicationId`](https://docs.rs/rerun/latest/rerun/struct.ApplicationId.html) will make it so the [Rerun Viewer](../../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. -Check out the reference to learn more about how Rerun deals with [applications and recordings](../concepts/apps-and-recordings.md). +Check out the reference to learn more about how Rerun deals with [applications and recordings](../../../concepts/apps-and-recordings.md). ## Logging our first points @@ -108,7 +108,7 @@ Run your program with `cargo run` and you should now see this scene in the viewe _This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ -_Checkout the [Viewer Walkthrough](viewer-walkthrough.md) and [viewer reference](../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ +_Checkout the [Viewer Walkthrough](../../visualize/viewer-walkthrough.md) and [viewer reference](../../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood @@ -126,25 +126,25 @@ Under the hood, the Rerun [Rust SDK](https://ref.rerun.io/docs/rust) logs indivi and radii. Archetypes are just one high-level, convenient way of building such collections of components. For advanced use cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. -For more information on how the rerun data model works, refer to our section on [Entities and Components](../concepts/entity-component.md). +For more information on how the rerun data model works, refer to our section on [Entities and Components](../../../concepts/entity-component.md). Notably, the [`RecordingStream::log`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log) method will handle any data type that implements the [`AsComponents`](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html) trait, making it easy to add your own data. -For more information on how to supply your own components see [Use custom data](../howto/extend/custom-data.md). +For more information on how to supply your own components see [Use custom data](../../../howto/extend/custom-data.md). ### Entities & hierarchies Note the two strings we're passing in: `"dna/structure/left"` and `"dna/structure/right"`. -These are [*entity paths*](../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. -[Entity paths typically form a hierarchy](../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). +These are [*entity paths*](../../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. +[Entity paths typically form a hierarchy](../../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Batches One final observation: notice how we're logging a whole batch of points and colors all at once here. -[Batches of data](../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. +[Batches of data](../../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this *splatting*. --- @@ -211,9 +211,9 @@ Once again, although we are getting fancier and fancier with our iterator mappin ### Introducing Time -Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../concepts/timelines.md). +Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../../concepts/timelines.md). -Even so, if you look at your [Timeline View](../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. +Even so, if you look at your [Timeline View](../../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. @@ -333,7 +333,7 @@ You can also save a recording (or a portion of it) as you're visualizing it, dir ### Spawning the Viewer from your process -If the Rerun Viewer is [installed](installing-viewer.md) and available in your `PATH`, you can use [`RecordingStream::spawn`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.spawn) to automatically start a viewer in a new process and connect to it over TCP. +If the Rerun Viewer is [installed](../../installing-viewer.md) and available in your `PATH`, you can use [`RecordingStream::spawn`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.spawn) to automatically start a viewer in a new process and connect to it over TCP. If an external viewer was already running, `spawn` will connect to that one instead of spawning a new one. ```rust @@ -368,4 +368,4 @@ The viewer will block the main thread until it is closed. This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. -As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../reference/types.md) section for more simple examples of how to use the main data types. +As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../../reference/types.md) section for more simple examples of how to use the main data types. diff --git a/docs/content/getting-started/installing-viewer.md b/docs/content/getting-started/installing-viewer.md index e4b82922f13e..2b4e117409fb 100644 --- a/docs/content/getting-started/installing-viewer.md +++ b/docs/content/getting-started/installing-viewer.md @@ -1,28 +1,61 @@ --- -title: Installing the Rerun Viewer -order: -1 +title: Installing Rerun +order: 2 --- -The [Rerun Viewer](../reference/viewer/overview.md) can be installed independent of the SDK language you're using. -Generally, you should make sure that your SDK version matches the version of the Viewer you're using to display any data you are logging. +## Installing the SDK + +### C++ + +If you're using CMake you can add the SDK to your project using `FetchContent`: + +```cmake +include(FetchContent) +FetchContent_Declare(rerun_sdk URL + https://github.com/rerun-io/rerun/releases/latest/download/rerun_cpp_sdk.zip) +FetchContent_MakeAvailable(rerun_sdk) +``` + +For more details see [Build & Distribution](https://ref.rerun.io/docs/cpp/stable/index.html#autotoc_md8) in the C++ reference documentation. +You'll additionally need to install the Viewer, see [below](#installing-the-viewer) + +### Python + +- `pip install rerun-sdk` via pip +- `conda install -c conda-forge rerun-sdk` via Conda + +Either way this includes both the SDK & the viewer and you're ready to go! + +### Rust + +Add the [Rerun crate](https://crates.io/crates/rerun) using `cargo add rerun`. You'll additionally need to install the Viewer, see [below](#installing-the-viewer). + +## Installing the Viewer + +The [Viewer](../reference/viewer/overview.md) can be installed independent of the library language you're using. +Make sure that your library version matches the version of the Viewer you're using. There are many ways to install the viewer. Please pick whatever works best for your setup: -* `cargo binstall rerun-cli` - download binaries via [`cargo binstall`](https://github.com/cargo-bins/cargo-binstall) -* `cargo install rerun-cli` - build it from source (this requires Rust 1.74+) -* Download it from the [GitHub Release artifacts](https://github.com/rerun-io/rerun/releases/latest/) -* Together with the Rerun [Python SDK](python.md): - * `pip3 install rerun-sdk` - download it via pip - * `conda install -c conda-forge rerun-sdk` - download via Conda - * `pixi global install rerun-sdk` - download it via [Pixi](https://prefix.dev/docs/pixi/overview) +- Download it from the [GitHub Release artifacts](https://github.com/rerun-io/rerun/releases/latest/) +- Via Cargo + - `cargo binstall rerun-cli` - download binaries via [`cargo binstall`](https://github.com/cargo-bins/cargo-binstall) + - `cargo install rerun-cli` - build it from source (this requires Rust 1.74+) +- Together with the Rerun [Python SDK](./quick-start/python.md): + - `pip3 install rerun-sdk` - download it via pip + - `conda install -c conda-forge rerun-sdk` - download via Conda + - `pixi global install rerun-sdk` - download it via [Pixi](https://prefix.dev/docs/pixi/overview) In any case you should be able to run `rerun` afterwards to start the Viewer. You'll be welcomed by an overview page that allows you to jump into some examples. If you're facing any difficulties, don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose) or [join the Discord server](https://discord.gg/PXtCgFBSmH). -The Rerun Viewer has built-in support for opening many kinds of files, and can be [extended to open any other file type](../howto/open-any-file.md) without needing to modify the Rerun codebase itself. +The Rerun Viewer has built-in support for opening many kinds of files, and can be [extended to open any other file type](./data-in/open-any-file.md) without needing to modify the Rerun codebase itself. + +## Next Steps + +To start getting your own data streamed to the viewer, check one of the respective getting started guides: -To start getting your own data logged & visualized in the viewer check one of the respective getting started guides: -* [Python](python.md) -* [C++](cpp.md) -* [Rust](rust.md) +- [C++](./quick-start/cpp.md) +- [Python](./quick-start/python.md) +- [Rust](./quick-start/rust.md) diff --git a/docs/content/getting-started/quick-start.md b/docs/content/getting-started/quick-start.md new file mode 100644 index 000000000000..cb8b97e1988e --- /dev/null +++ b/docs/content/getting-started/quick-start.md @@ -0,0 +1,10 @@ +--- +title: Quick start +order: 1 +--- + +Dive right into using the Rerun SDK with your favorite programming language! + +* [C++](./quick-start/cpp.md) +* [Python](./quick-start/python.md) +* [Rust](./quick-start/rust.md) diff --git a/docs/content/getting-started/cpp.md b/docs/content/getting-started/quick-start/cpp.md similarity index 92% rename from docs/content/getting-started/cpp.md rename to docs/content/getting-started/quick-start/cpp.md index 683c4d8a7ff3..ba4d52bca8ec 100644 --- a/docs/content/getting-started/cpp.md +++ b/docs/content/getting-started/quick-start/cpp.md @@ -1,10 +1,10 @@ --- -title: C++ Quick Start +title: C++ order: 1 --- ## Setup -Before adding Rerun to your application, start by [installing the viewer](installing-viewer.md). +Before adding Rerun to your application, start by [installing the viewer](../installing-viewer.md#installing-the-viewer). ## Learning by example If you prefer to learn by example, check out our example repository which uses the Rerun C++ SDK to log some data from Eigen and OpenCV: . @@ -122,14 +122,14 @@ If you're facing any difficulties, don't hesitate to [open an issue](https://git ## What's next -If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](viewer-walkthrough.md) or our -more advanced guide for [Logging Data in C++](logging-cpp.md) where we will explore the core concepts that make +If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../visualize/viewer-walkthrough.md) or our +more advanced guide for [Logging Data in C++](../data-in/streaming/cpp.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. -If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../reference/types.md) section for more simple examples of how to use the main datatypes. +If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. There's also a stand-alone example that shows [interop with Eigen and OpenCV](https://github.com/rerun-io/cpp-example-opencv-eigen). To learn more about how to work with your own types, check the [Custom Collection Adapter](https://github.com/rerun-io/rerun/tree/latest/examples/cpp/custom_collection_adapter) example on how to zero-copy adapt to Rerun types -and the [Use custom data](../howto/extend/custom-data.md) page for completely custom types. +and the [Use custom data](../../howto/extend/custom-data.md) page for completely custom types. To learn more about how to configure the C++ SDK's CMake file, check [CMake Setup in Detail](https://ref.rerun.io/docs/cpp/stable/md__2home_2runner_2work_2rerun_2rerun_2rerun__cpp_2cmake__setup__in__detail.html). diff --git a/docs/content/getting-started/python.md b/docs/content/getting-started/quick-start/python.md similarity index 92% rename from docs/content/getting-started/python.md rename to docs/content/getting-started/quick-start/python.md index 9f094fd23ebb..d0c275929efe 100644 --- a/docs/content/getting-started/python.md +++ b/docs/content/getting-started/quick-start/python.md @@ -1,5 +1,5 @@ --- -title: Python Quick Start +title: Python order: 2 --- @@ -49,7 +49,7 @@ data usage policy. Rerun collects anonymous usage data to help improve the proje would like.* ### If you're having problems - * Checkout out our [troubleshooting guide](troubleshooting.md). + * Checkout out our [troubleshooting guide](../troubleshooting.md). * [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). * Or [join the Discord server](https://discord.gg/PXtCgFBSmH). @@ -64,7 +64,7 @@ Try out the following to interact with the viewer: * Hover and select individual points to see more information. This is just a taste of some of what you can do with the viewer. We will cover other functionality in much -more detail later in the [Viewer Walkthrough](viewer-walkthrough.md) +more detail later in the [Viewer Walkthrough](../visualize/viewer-walkthrough.md) ## Logging your own data After exploring a built-in example, let's create some data ourselves. We will start with an @@ -90,7 +90,7 @@ rr.log( ) ``` -When you run this script you will again be greeted with the [Rerun Viewer](../reference/viewer/overview.md), this time +When you run this script you will again be greeted with the Rerun Viewer, this time only showing a simple line of red points. @@ -139,8 +139,8 @@ rr.log( ## What's next -If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](viewer-walkthrough.md) or our -more advanced guide for [Logging Data in Python](logging-python.md) where we will explore the core concepts that make +If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../visualize/viewer-walkthrough.md) or our +more advanced guide for [Logging Data in Python](../data-in/streaming/python.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. -If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../reference/types.md) section for more simple examples of how to use the main datatypes. +If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. diff --git a/docs/content/getting-started/rust.md b/docs/content/getting-started/quick-start/rust.md similarity index 83% rename from docs/content/getting-started/rust.md rename to docs/content/getting-started/quick-start/rust.md index e6fda417e6d4..9beee14a84be 100644 --- a/docs/content/getting-started/rust.md +++ b/docs/content/getting-started/quick-start/rust.md @@ -1,12 +1,12 @@ --- -title: Rust Quick Start +title: Rust order: 3 --- ## Setup The Rerun SDK for Rust requires a working installation of Rust 1.74+. -After you have [installed the viewer](installing-viewer.md) you can simply add [the rerun crate](https://crates.io/crates/rerun) to your project with `cargo add rerun`. +After you have [installed the viewer](../installing-viewer.md#installing-the-viewer) you can simply add [the rerun crate](https://crates.io/crates/rerun) to your project with `cargo add rerun`. Let's try it out in a brand new Rust project: ```bash @@ -65,8 +65,8 @@ If you're facing any difficulties, don't hesitate to [open an issue](https://git ## What's next -If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](viewer-walkthrough.md) or our -more advanced guide for [Logging Data in Rust](logging-rust.md) where we will explore the core concepts that make +If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../visualize/viewer-walkthrough.md) or our +more advanced guide for [Logging Data in Rust](../data-in/streaming/rust.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. -If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../reference/types.md) section for more simple examples of how to use the main datatypes. +If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. diff --git a/docs/content/getting-started/troubleshooting.md b/docs/content/getting-started/troubleshooting.md index f0adfd4fe314..24dfa7975c70 100644 --- a/docs/content/getting-started/troubleshooting.md +++ b/docs/content/getting-started/troubleshooting.md @@ -1,6 +1,6 @@ --- title: Troubleshooting -order: 8 +order: 5 --- You can set `RUST_LOG=debug` before running to get some verbose logging output. diff --git a/docs/content/getting-started/visualize.md b/docs/content/getting-started/visualize.md new file mode 100644 index 000000000000..a658f87687c5 --- /dev/null +++ b/docs/content/getting-started/visualize.md @@ -0,0 +1,5 @@ +--- +title: Using the viewer +order: 4 +redirect: getting-started/visualize/viewer-walkthrough +--- diff --git a/docs/content/getting-started/visualize/blueprint.md b/docs/content/getting-started/visualize/blueprint.md new file mode 100644 index 000000000000..f4afdc697dfc --- /dev/null +++ b/docs/content/getting-started/visualize/blueprint.md @@ -0,0 +1,6 @@ +--- +title: Configure from code +order: 1 +--- + +TODO(#5466): diff --git a/docs/content/getting-started/viewer-walkthrough.md b/docs/content/getting-started/visualize/viewer-walkthrough.md similarity index 91% rename from docs/content/getting-started/viewer-walkthrough.md rename to docs/content/getting-started/visualize/viewer-walkthrough.md index 3c22802b6e74..9555deda6260 100644 --- a/docs/content/getting-started/viewer-walkthrough.md +++ b/docs/content/getting-started/visualize/viewer-walkthrough.md @@ -1,6 +1,6 @@ --- -title: Viewer Walkthrough -order: 4 +title: Viewer walkthrough +order: 0 --- This guide will familiarize you with the basics of using the Rerun Viewer with an example dataset. By the end you should @@ -31,7 +31,7 @@ to take the images. ## Prerequisites Although the Rerun SDK is available in both Python and Rust, this walkthrough makes use the Python installation. Even if you plan to use Rerun with Rust, we still recommend having a Rerun Python environment available for quick -experimentation and working with examples. You can either follow the [Python Quickstart](python.md) or simply run: +experimentation and working with examples. You can either follow the [Python Quickstart](../quick-start/python.md) or simply run: ```bash pip install rerun-sdk @@ -80,13 +80,13 @@ preview, but the remainder of this guide will walk you through how to configure ## The viewer panels There are 4 main parts to this window: -- In the middle of the screen is the [Viewport](../reference/viewer/viewport.md). This is where you see the rendered +- In the middle of the screen is the [Viewport](../../reference/viewer/viewport.md). This is where you see the rendered space views for your session. -- On the left is the [Blueprint](../reference/viewer/blueprint.md) panel. This is where the different space views can be +- On the left is the [Blueprint](../../reference/viewer/blueprint.md) panel. This is where the different space views can be controlled. -- On the right is the [Selection](../reference/viewer/selection.md) panel. This is where you see extra information +- On the right is the [Selection](../../reference/viewer/selection.md) panel. This is where you see extra information and configuration information for things that you have selected. -- On the bottom is the [Timeline](../reference/viewer/timeline.md) panel. This is where you can control the current +- On the bottom is the [Timeline](../../reference/viewer/timeline.md) panel. This is where you can control the current point in time that is being viewed. Each of the 3 side panels has a corresponding button in the upper right corner. Try clicking each of these to hide and @@ -119,18 +119,18 @@ Feel free to move the views around until you are happy with the layout. ## Exploring data The space views are where you can see the data that was actually logged. This scene has streams of data for 6 different -primitives, also known as [entities](../concepts/entity-component.md): -* [images](../reference/types/archetypes/image.md) that were captured from a camera. -* [2D keypoints](../reference/types/archetypes/points2d.md) that were detected and tracked in those images. -* a [pinhole](../reference/types/archetypes/pinhole.md) camera model that describes the relationship between 2D and 3D space. -* [3D points](../reference/types/archetypes/points3d.md) that were computed by the COLMAP slam pipeline. -* A sequence of [transforms](../reference/types/archetypes/transform3d.md) describing the 3D location of the camera in space. -* A [scalar](../reference/types/archetypes/scalar.md) error metric that was computed by the algorithm for each frame. +primitives, also known as [entities](../../concepts/entity-component.md): +* [images](../../reference/types/archetypes/image.md) that were captured from a camera. +* [2D keypoints](../../reference/types/archetypes/points2d.md) that were detected and tracked in those images. +* a [pinhole](../../reference/types/archetypes/pinhole.md) camera model that describes the relationship between 2D and 3D space. +* [3D points](../../reference/types/archetypes/points3d.md) that were computed by the COLMAP slam pipeline. +* A sequence of [transforms](../../reference/types/archetypes/transform3d.md) describing the 3D location of the camera in space. +* A [scalar](../../reference/types/archetypes/scalar.md) error metric that was computed by the algorithm for each frame. ### Hover and selection You can find out more about these entities by hovering over them in the different views. Hovering will bring up a context popup with additional information. You can also click on entities to select them and see more details in the -[Selection panel](../reference/viewer/selection.md). +[Selection panel](../../reference/viewer/selection.md). @@ -149,7 +149,7 @@ Try each of the following: Note that the views are actually connected. As you hover over points in the `/ (Spatial)` view you will see information about the depth of the projection in the image view. Conversely as you hover over pixels in the `image` you will see the corresponding ray projected into the `/ (Spatial)` view. See the section on -[Spaces and Transforms](../concepts/spaces-and-transforms.md) for more information on how this linking works. +[Spaces and Transforms](../../concepts/spaces-and-transforms.md) for more information on how this linking works. ### Rotate, zoom, and pan Clicking and dragging the contents of any view will move it. You can rotate 3D views, or pan 2D views and plots. You can @@ -221,10 +221,10 @@ to the "frame" timeline and double-click the timeline panel to reset it to the d One thing to notice is there is a gap in the timeline in the "frame" view. This dataset is actually missing a few frames, and the timeline view of frames makes this easy to spot. This highlights the importance of applying meaningful timestamps to your data as you log it. You also aren't limited to frame and log_time. Rerun lets you define your own -timelines however you would like. You can read more about timelines [here](../concepts/timelines.md). +timelines however you would like. You can read more about timelines [here](../../concepts/timelines.md). ## Configuring views -Views in Rerun are configured by [Blueprints](../reference/viewer/blueprint.md). We will now use blueprints to adjust +Views in Rerun are configured by [Blueprints](../../reference/viewer/blueprint.md). We will now use blueprints to adjust both an individual entity as well as the contents of a space view itself. ### Adjusting entity properties @@ -314,7 +314,7 @@ That brings us to the end of this walkthrough. To recap, you have learned how to - Install the `rerun-sdk` pypi package. - Run the Rerun Viewer using the `rerun` command. - Open the examples integrated in the viewer. -- Work with the [Blueprint](../reference/viewer/blueprint.md), [Selection](../reference/viewer/selection.md) and [Timeline](../reference/viewer/timeline.md) panels. +- Work with the [Blueprint](../../reference/viewer/blueprint.md), [Selection](../../reference/viewer/selection.md) and [Timeline](../../reference/viewer/timeline.md) panels. - Rearrange space view layouts. - Explore data through hover and selection. - Change the time selection. @@ -327,9 +327,8 @@ That brings us to the end of this walkthrough. To recap, you have learned how to Again, if you ran into any issues following this guide, please don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). ### Up next -To get started with writing a program to logging data with the Rerun SDK see the [Python](logging-python.md) or -[Rust](logging-rust.md) getting started guides. +To get started with writing a program to logging data with the Rerun SDK see the [getting started guides](../quick-start). To see and explore other data, you can check out the [examples](/examples). -For deeper context on the ideas covered here, consult the [Concept overview](../concepts.md). +For deeper context on the ideas covered here, consult the [Concept overview](../../concepts.md). diff --git a/docs/content/getting-started/what-is-rerun.md b/docs/content/getting-started/what-is-rerun.md new file mode 100644 index 000000000000..c7df7a64a175 --- /dev/null +++ b/docs/content/getting-started/what-is-rerun.md @@ -0,0 +1,50 @@ +--- +title: What is Rerun? +order: 0 +--- +To get a feeling of what you can do with Rerun +- browse the [example gallery](/examples) or +- try Rerun directly [in your browser](https://app.rerun.io/). + +## What is Rerun? + +Rerun is an SDK and engine for visualizing and interacting with multimodal data streams. + +Rerun is +- Simple to integrate and get started with +- Usable from Python, Rust, and C++ +- Powerful, flexible, and extensible +- Built in Rust to be cross platform and fast +- Open source, dual licensed under MIT and Apache 2 + +Rerun is used by engineers and researchers in fields like computer vision and robotics +to verify, debug, and demo. + +For a list of built-in data types, see the [Types](../reference/types.md) section. + +## How do you use it? + + + + + + + + +1. Stream multimodal data from your code by logging it with the Rerun SDK +2. Visualize and interact with live or recorded streams, whether local or remote +3. Interactively build layouts and customize visualizations +4. Extend Rerun when you need to + +## How does it work? +That's a big question for a welcome page. The short answer is that +Rerun goes to extreme lengths to make handling and visualizing +multimodal data streams easy and performant. + + + +## Can't find what you're looking for? + +- Join us in the [Rerun Community Discord](https://discord.gg/xwcxHUjD35) +- Or [submit an issue](https://github.com/rerun-io/rerun/issues) in the Rerun GitHub project + diff --git a/docs/content/howto/ros2-nav-turtlebot.md b/docs/content/howto/ros2-nav-turtlebot.md index f7f4328de4c6..964e3f9e84ea 100644 --- a/docs/content/howto/ros2-nav-turtlebot.md +++ b/docs/content/howto/ros2-nav-turtlebot.md @@ -30,8 +30,8 @@ All of the code for this guide can be found on GitHub in ## Prerequisites Other relevant tutorials: - - [Logging with Python](../getting-started/logging-python.md) - - [Viewer Walkthrough](../getting-started/viewer-walkthrough.md) + - [Python SDK Tutorial](../getting-started/data-in/streaming/python.md) + - [Viewer Walkthrough](../getting-started/visualize/viewer-walkthrough.md) ### ROS 2 & navigation You will need to have installed [ROS 2 Humble Hawksbill](https://docs.ros.org/en/humble/index.html) diff --git a/docs/content/index.md b/docs/content/index.md index a446312766c1..e15b321dc76d 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -1,50 +1,5 @@ --- title: Welcome order: 0 +redirect: getting-started/what-is-rerun --- -To get a feeling of what you can do with Rerun -- browse the [example gallery](/examples) or -- try Rerun directly [in your browser](https://app.rerun.io/). - -## What is Rerun? - -Rerun is an SDK and engine for visualizing and interacting with multimodal data streams. - -Rerun is -- Simple to integrate and get started with -- Usable from Python, Rust, and C++ -- Powerful, flexible, and extensible -- Built in Rust to be cross platform and fast -- Open source, dual licensed under MIT and Apache 2 - -Rerun is used by engineers and researchers in fields like computer vision and robotics -to verify, debug, and demo. - -For a list of built-in data types, see the [Types](reference/types.md) section. - -## How do you use it? - - - - - - - - -1. Stream multimodal data from your code by logging it with the Rerun SDK -2. Visualize and interact with live or recorded streams, whether local or remote -3. Interactively build layouts and customize visualizations -4. Extend Rerun when you need to - -## How does it work? -That's a big question for a welcome page. The short answer is that -Rerun goes to extreme lengths to make handling and visualizing -multimodal data streams easy and performant. - - - -## Can't find what you're looking for? - -- Join us in the [Rerun Community Discord](https://discord.gg/xwcxHUjD35) -- Or [submit an issue](https://github.com/rerun-io/rerun/issues) in the Rerun GitHub project - From 4636188996038f4be913f813fb263a3751c1d469 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Wed, 27 Mar 2024 14:11:25 -0400 Subject: [PATCH 131/508] Introduce the concepts of "default" and "active" blueprint. Make reset return to default. (#5678) ### What - Partial implementation of: - https://github.com/rerun-io/rerun/issues/5583 - https://github.com/rerun-io/rerun/issues/5298 - This does not yet fully track a blueprint-per-recording-id, but playing with this I think doing so might still be worth exploring. - Introduces a new "default blueprint" per app-id in the store-hub. - Changes the ActivateStore -> BlueprintReady with a mechanism to specify `make_default` and `make_active` - Introduces new python API: `send_blueprint` Important aspect of implementation: - When you click the reset button we now clone the default blueprint into a new blueprint. This way we don't modify the blueprint that is the target for the reset. Future work we need to build on top of this (Feel free to push these improvements here, or we can push to a future PR). - [x] Biggest issue. This currently breaks File->Open / Drag-and-drop since those now **just** set the default. - Proposal: we should go ahead add the "force activate" bool into the `ActivateStore` message. We should set this bool in the message when we inject it into "File->Save" pathway. That way if you manually save a blueprint, it will always load when you open it. But if you are opening an RRD file that happens to have a blueprint it will still just use the "default" behavior. - [x] Should introduce SystemCommand & UI to clear the default blueprint so resetting goes back to heuristics. Future work: - Should introduce SystemCommand & UI to set a different blueprint as the default. - https://github.com/rerun-io/rerun/issues/5691 - Notification to user when default blueprint changes. Probably better as follow-on PR - https://github.com/rerun-io/rerun/issues/5692 - **Make state observable** by supporting a selection of the AppId. Probably better as follow-on PR: - https://github.com/rerun-io/rerun/issues/5672 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5678/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5678/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5678/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5678) - [Docs preview](https://rerun.io/preview/78935399ef8b4289c5ba6535f01e988e0cb26e70/docs) - [Examples preview](https://rerun.io/preview/78935399ef8b4289c5ba6535f01e988e0cb26e70/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/entity_db.rs | 6 + crates/re_data_ui/src/item_ui.rs | 14 +- crates/re_data_ui/src/log_msg.rs | 14 +- crates/re_entity_db/src/entity_db.rs | 46 +++++- crates/re_log_types/src/lib.rs | 69 ++++++++- crates/re_sdk/src/lib.rs | 3 +- crates/re_sdk/src/log_sink.rs | 39 ++++- crates/re_sdk/src/recording_stream.rs | 90 +++++------ crates/re_sdk_comms/src/server.rs | 2 +- crates/re_space_view/src/space_view.rs | 4 + .../re_space_view/src/space_view_contents.rs | 1 + crates/re_ui/src/command.rs | 9 ++ crates/re_viewer/src/app.rs | 61 +++++--- crates/re_viewer/src/store_hub.rs | 114 ++++++++++---- crates/re_viewer/src/ui/blueprint_panel.rs | 8 +- .../re_viewer_context/src/command_sender.rs | 7 +- crates/re_viewer_context/src/store_context.rs | 7 + crates/rerun/src/run.rs | 8 +- crates/rerun_c/src/lib.rs | 2 +- examples/python/arkit_scenes/main.py | 2 +- examples/python/blueprint/main.py | 2 +- examples/python/blueprint_stocks/main.py | 3 +- examples/python/controlnet/main.py | 2 +- .../depth_guided_stable_diffusion/main.py | 2 +- examples/python/face_tracking/main.py | 2 +- examples/python/gesture_detection/main.py | 2 +- examples/python/human_pose_tracking/main.py | 2 +- .../python/live_camera_edge_detection/main.py | 2 +- examples/python/llm_embedding_ner/main.py | 2 +- examples/python/nuscenes/main.py | 2 +- examples/python/objectron/main.py | 2 +- examples/python/plots/main.py | 2 +- examples/python/rgbd/main.py | 2 +- .../python/signed_distance_fields/main.py | 2 +- examples/python/structure_from_motion/main.py | 2 +- rerun_py/docs/gen_common_index.py | 1 + rerun_py/rerun_sdk/rerun/__init__.py | 16 +- rerun_py/rerun_sdk/rerun/script_helpers.py | 19 ++- rerun_py/rerun_sdk/rerun/sinks.py | 124 +++++++++++---- rerun_py/src/python_bridge.rs | 141 +++++++++++++++--- tests/python/blueprint/main.py | 2 +- ...ntext_menu_add_entity_to_new_space_view.py | 2 +- .../check_context_menu_collapse_expand_all.py | 2 +- ...heck_context_menu_invalid_sub_container.py | 2 +- .../check_context_menu_multi_selection.py | 2 +- .../check_context_menu_single_selection.py | 2 +- ...xt_menu_single_selection_blueprint_tree.py | 2 +- .../check_context_menu_suggested_origin.py | 2 +- tests/python/release_checklist/check_focus.py | 2 +- 49 files changed, 643 insertions(+), 213 deletions(-) diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index 7d4fb5fd09eb..cc2214fbb091 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -90,6 +90,12 @@ impl crate::DataUi for EntityDb { } } + if ctx.store_context.is_default_blueprint(self.store_id()) { + ui.add_space(8.0); + ui.label("This is the default blueprint") + .on_hover_text("When you reset the blueprint for the app, this blueprint will be used as the template."); + }; + if verbosity == UiVerbosity::Full { sibling_stores_ui(ctx, ui, self); } diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 4668c88a8449..6f000badc683 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -668,9 +668,17 @@ pub fn entity_db_button_ui( } if response.clicked() { - // Open the recording / switch to this blueprint… - ctx.command_sender - .send_system(SystemCommand::ActivateStore(store_id.clone())); + // When we click on a recording, we directly activate it. This is safe to do because + // it's non-destructive and recordings are immutable. Switching back is easy. + // We don't do the same thing for blueprints as swapping them can be much more disruptive. + // It is much less obvious how to undo a blueprint switch and what happened to your original + // blueprint. + // TODO(jleibs): We should still have an `Activate this Blueprint` button in the selection panel + // for the blueprint. + if store_id.kind == re_log_types::StoreKind::Recording { + ctx.command_sender + .send_system(SystemCommand::ActivateRecording(store_id.clone())); + } // …and select the store in the selection panel. // Note that we must do it in this order, since the selection state is stored in the recording. diff --git a/crates/re_data_ui/src/log_msg.rs b/crates/re_data_ui/src/log_msg.rs index 9abc4f29a76c..6f7ce45822ad 100644 --- a/crates/re_data_ui/src/log_msg.rs +++ b/crates/re_data_ui/src/log_msg.rs @@ -1,4 +1,6 @@ -use re_log_types::{ArrowMsg, DataTable, LogMsg, SetStoreInfo, StoreInfo}; +use re_log_types::{ + ArrowMsg, BlueprintActivationCommand, DataTable, LogMsg, SetStoreInfo, StoreInfo, +}; use re_viewer_context::{UiVerbosity, ViewerContext}; use super::DataUi; @@ -16,8 +18,14 @@ impl DataUi for LogMsg { match self { LogMsg::SetStoreInfo(msg) => msg.data_ui(ctx, ui, verbosity, query, store), LogMsg::ArrowMsg(_, msg) => msg.data_ui(ctx, ui, verbosity, query, store), - LogMsg::ActivateStore(store_id) => { - ui.label(format!("ActivateStore({store_id})")); + LogMsg::BlueprintActivationCommand(BlueprintActivationCommand { + blueprint_id, + make_active, + make_default, + }) => { + ui.label(format!( + "BlueprintActivationCommand({blueprint_id}, make_active: {make_active}, make_default: {make_default})" + )); } } } diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 2d0231aefbf8..a8283459e0fa 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -274,7 +274,7 @@ impl EntityDb { self.add_data_table(table)?; } - LogMsg::ActivateStore(_) => { + LogMsg::BlueprintActivationCommand(_) => { // Not for us to handle } } @@ -540,18 +540,54 @@ impl EntityDb { .map(|msg| LogMsg::ArrowMsg(self.store_id().clone(), msg)) }); - // Signal that the store is done loading. - // Important for blueprints. - let activate_store_msg = LogMsg::ActivateStore(self.store_id().clone()); + // If this is a blueprint, make sure to include the `BlueprintActivationCommand` message. + // We generally use `to_messages` to export a blueprint via "save". In that + // case, we want to make the blueprint active and default when it's reloaded. + // TODO(jleibs): Coupling this with the stored file instead of injecting seems + // architecturally weird. Would be great if we didn't need this in `.rbl` files + // at all. + let blueprint_ready = if self.store_kind() == StoreKind::Blueprint { + let activate_cmd = + re_log_types::BlueprintActivationCommand::make_active(self.store_id().clone()); + + itertools::Either::Left(std::iter::once(Ok(activate_cmd.into()))) + } else { + itertools::Either::Right(std::iter::empty()) + }; let messages: Result, _> = set_store_info_msg .into_iter() .chain(data_messages) - .chain(std::iter::once(Ok(activate_store_msg))) + .chain(blueprint_ready) .collect(); messages } + + /// Make a clone of this [`EntityDb`] with a different [`StoreId`]. + pub fn clone_with_new_id(&self, new_id: StoreId) -> Result { + self.store().sort_indices_if_needed(); + + let mut new_db = EntityDb::new(new_id.clone()); + + if let Some(store_info) = self.store_info() { + let mut new_info = store_info.clone(); + new_info.store_id = new_id; + + new_db.set_store_info(SetStoreInfo { + row_id: RowId::new(), + info: new_info, + }); + } + + new_db.data_source = self.data_source.clone(); + + for row in self.store().to_rows()? { + new_db.add_data_row(row)?; + } + + Ok(new_db) + } } impl re_types_core::SizeBytes for EntityDb { diff --git a/crates/re_log_types/src/lib.rs b/crates/re_log_types/src/lib.rs index 0606d24f6cbf..3ebbbd9cf226 100644 --- a/crates/re_log_types/src/lib.rs +++ b/crates/re_log_types/src/lib.rs @@ -205,6 +205,58 @@ impl std::fmt::Display for ApplicationId { // ---------------------------------------------------------------------------- +/// Command used for activating a blueprint once it has been fully transmitted. +/// +/// This command serves two purposes: +/// - It is important that a blueprint is never activated before it has been fully +/// transmitted. Displaying, or allowing a user to modify, a half-transmitted +/// blueprint can cause confusion and bad interactions with the space view heuristics. +/// - Additionally, this command allows fine-tuning the activation behavior itself +/// by specifying whether the blueprint should be immediately activated, or only +/// become the default for future activations. +#[derive(Clone, Debug, PartialEq, Eq)] // `PartialEq` used for tests in another crate +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub struct BlueprintActivationCommand { + /// The blueprint this command refers to. + pub blueprint_id: StoreId, + + /// Immediately make this the active blueprint for the associated `app_id`. + /// + /// Note that setting this to `false` does not mean the blueprint may not still end + /// up becoming active. In particular, if `make_default` is true and there is no other + /// currently active blueprint. + pub make_active: bool, + + /// Make this the default blueprint for the `app_id`. + /// + /// The default blueprint will be used as the template when the user resets the + /// blueprint for the app. It will also become the active blueprint if no other + /// blueprint is currently active. + pub make_default: bool, +} + +impl BlueprintActivationCommand { + /// Make `blueprint_id` the default blueprint for its associated `app_id`. + pub fn make_default(blueprint_id: StoreId) -> Self { + Self { + blueprint_id, + make_active: false, + make_default: true, + } + } + + /// Immediately make `blueprint_id` the active blueprint for its associated `app_id`. + /// + /// This also sets `make_default` to true. + pub fn make_active(blueprint_id: StoreId) -> Self { + Self { + blueprint_id, + make_active: true, + make_default: true, + } + } +} + /// The most general log message sent from the SDK to the server. #[must_use] #[derive(Clone, Debug, PartialEq)] // `PartialEq` used for tests in another crate @@ -224,14 +276,15 @@ pub enum LogMsg { /// This is so that the viewer can wait with activating the blueprint until it is /// fully transmitted. Showing a half-transmitted blueprint can cause confusion, /// and also lead to problems with space-view heuristics. - ActivateStore(StoreId), + BlueprintActivationCommand(BlueprintActivationCommand), } impl LogMsg { pub fn store_id(&self) -> &StoreId { match self { Self::SetStoreInfo(msg) => &msg.info.store_id, - Self::ArrowMsg(store_id, _) | Self::ActivateStore(store_id) => store_id, + Self::ArrowMsg(store_id, _) => store_id, + Self::BlueprintActivationCommand(cmd) => &cmd.blueprint_id, } } @@ -240,14 +293,22 @@ impl LogMsg { LogMsg::SetStoreInfo(store_info) => { store_info.info.store_id = new_store_id; } - LogMsg::ArrowMsg(msg_store_id, _) | LogMsg::ActivateStore(msg_store_id) => { - *msg_store_id = new_store_id; + LogMsg::ArrowMsg(store_id, _) => { + *store_id = new_store_id; + } + LogMsg::BlueprintActivationCommand(cmd) => { + cmd.blueprint_id = new_store_id; } } } } impl_into_enum!(SetStoreInfo, LogMsg, SetStoreInfo); +impl_into_enum!( + BlueprintActivationCommand, + LogMsg, + BlueprintActivationCommand +); // ---------------------------------------------------------------------------- diff --git a/crates/re_sdk/src/lib.rs b/crates/re_sdk/src/lib.rs index 33bca446f3b2..c8bb35319b59 100644 --- a/crates/re_sdk/src/lib.rs +++ b/crates/re_sdk/src/lib.rs @@ -26,7 +26,8 @@ mod spawn; pub use spawn::{spawn, SpawnError, SpawnOptions}; pub use self::recording_stream::{ - RecordingStream, RecordingStreamBuilder, RecordingStreamError, RecordingStreamResult, + forced_sink_path, RecordingStream, RecordingStreamBuilder, RecordingStreamError, + RecordingStreamResult, }; pub use re_sdk_comms::{default_flush_timeout, default_server_addr}; diff --git a/crates/re_sdk/src/log_sink.rs b/crates/re_sdk/src/log_sink.rs index de740506f5b8..73a8e9e493b9 100644 --- a/crates/re_sdk/src/log_sink.rs +++ b/crates/re_sdk/src/log_sink.rs @@ -2,7 +2,7 @@ use std::fmt; use std::sync::Arc; use parking_lot::RwLock; -use re_log_types::LogMsg; +use re_log_types::{BlueprintActivationCommand, LogMsg, StoreId}; /// Where the SDK sends its log messages. pub trait LogSink: Send + Sync + 'static { @@ -34,6 +34,35 @@ pub trait LogSink: Send + Sync + 'static { /// flush it for any reason (e.g. a broken TCP connection for a [`TcpSink`]). #[inline] fn drop_if_disconnected(&self) {} + + /// Send a blueprint directly to the log-sink. + /// + /// This mirrors the behavior of [`crate::RecordingStream::send_blueprint`]. + fn send_blueprint(&self, blueprint: Vec, activation_cmd: BlueprintActivationCommand) { + let mut blueprint_id = None; + for msg in blueprint { + if blueprint_id.is_none() { + blueprint_id = Some(msg.store_id().clone()); + } + self.send(msg); + } + + if let Some(blueprint_id) = blueprint_id { + if blueprint_id == activation_cmd.blueprint_id { + // Let the viewer know that the blueprint has been fully received, + // and that it can now be activated. + // We don't want to activate half-loaded blueprints, because that can be confusing, + // and can also lead to problems with space-view heuristics. + self.send(activation_cmd.into()); + } else { + re_log::warn!( + "Blueprint ID mismatch when sending blueprint: {} != {}. Ignoring activation.", + blueprint_id, + activation_cmd.blueprint_id + ); + } + } + } } // ---------------------------------------------------------------------------- @@ -206,6 +235,14 @@ impl MemorySinkStorage { Ok(buffer.into_inner()) } + + #[inline] + /// Get the [`StoreId`] from the associated `RecordingStream` if it exists. + pub fn store_id(&self) -> Option { + self.rec + .as_ref() + .and_then(|rec| rec.store_info().map(|info| info.store_id.clone())) + } } // ---------------------------------------------------------------------------- diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs index 228df35375af..b229c3094357 100644 --- a/crates/re_sdk/src/recording_stream.rs +++ b/crates/re_sdk/src/recording_stream.rs @@ -9,10 +9,10 @@ use crossbeam::channel::{Receiver, Sender}; use itertools::Either; use parking_lot::Mutex; use re_log_types::{ - ApplicationId, ArrowChunkReleaseCallback, DataCell, DataCellError, DataRow, DataTable, - DataTableBatcher, DataTableBatcherConfig, DataTableBatcherError, EntityPath, LogMsg, RowId, - StoreId, StoreInfo, StoreKind, StoreSource, Time, TimeInt, TimePoint, TimeType, Timeline, - TimelineName, + ApplicationId, ArrowChunkReleaseCallback, BlueprintActivationCommand, DataCell, DataCellError, + DataRow, DataTable, DataTableBatcher, DataTableBatcherConfig, DataTableBatcherError, + EntityPath, LogMsg, RowId, StoreId, StoreInfo, StoreKind, StoreSource, Time, TimeInt, + TimePoint, TimeType, Timeline, TimelineName, }; use re_types_core::{components::InstanceKey, AsComponents, ComponentBatch, SerializationError}; @@ -37,7 +37,7 @@ const ENV_FORCE_SAVE: &str = "_RERUN_TEST_FORCE_SAVE"; /// Furthermore, [`RecordingStream::set_sink`] calls after this should not swap out to a new sink but re-use the existing one. /// Note that creating a new [`crate::sink::FileSink`] to the same file path (even temporarily) can cause /// a race between file creation (and thus clearing) and pending file writes. -fn forced_sink_path() -> Option { +pub fn forced_sink_path() -> Option { std::env::var(ENV_FORCE_SAVE).ok() } @@ -1522,11 +1522,7 @@ impl RecordingStream { /// terms of data durability and ordering. /// See [`Self::set_sink`] for more information. pub fn connect(&self) { - self.connect_opts( - crate::default_server_addr(), - crate::default_flush_timeout(), - None, - ); + self.connect_opts(crate::default_server_addr(), crate::default_flush_timeout()); } /// Swaps the underlying sink for a [`crate::log_sink::TcpSink`] sink pre-configured to use @@ -1543,7 +1539,6 @@ impl RecordingStream { &self, addr: std::net::SocketAddr, flush_timeout: Option, - blueprint: Option>, ) { if forced_sink_path().is_some() { re_log::debug!("Ignored setting new TcpSink since _RERUN_FORCE_SINK is set"); @@ -1552,11 +1547,6 @@ impl RecordingStream { let sink = crate::log_sink::TcpSink::new(addr, flush_timeout); - // If a blueprint was provided, send it first. - if let Some(blueprint) = blueprint { - Self::send_blueprint(blueprint, &sink); - } - self.set_sink(Box::new(sink)); } @@ -1610,7 +1600,7 @@ impl RecordingStream { spawn(opts)?; - self.connect_opts(opts.connect_addr(), flush_timeout, None); + self.connect_opts(opts.connect_addr(), flush_timeout); Ok(()) } @@ -1623,16 +1613,17 @@ impl RecordingStream { /// See [`Self::set_sink`] for more information. pub fn memory(&self) -> MemorySinkStorage { let sink = crate::sink::MemorySink::default(); - let buffer = sink.buffer(); + let mut storage = sink.buffer(); if forced_sink_path().is_some() { re_log::debug!("Ignored setting new memory sink since _RERUN_FORCE_SINK is set"); - return buffer; + return storage; } self.set_sink(Box::new(sink)); + storage.rec = Some(self.clone()); - buffer + storage } /// Swaps the underlying sink for a [`crate::sink::FileSink`] at the specified `path`. @@ -1644,7 +1635,7 @@ impl RecordingStream { &self, path: impl Into, ) -> Result<(), crate::sink::FileSinkError> { - self.save_opts(path, None) + self.save_opts(path) } /// Swaps the underlying sink for a [`crate::sink::FileSink`] at the specified `path`. @@ -1658,7 +1649,6 @@ impl RecordingStream { pub fn save_opts( &self, path: impl Into, - blueprint: Option>, ) -> Result<(), crate::sink::FileSinkError> { if forced_sink_path().is_some() { re_log::debug!("Ignored setting new file since _RERUN_FORCE_SINK is set"); @@ -1667,11 +1657,6 @@ impl RecordingStream { let sink = crate::sink::FileSink::new(path)?; - // If a blueprint was provided, store it first. - if let Some(blueprint) = blueprint { - Self::send_blueprint(blueprint, &sink); - } - self.set_sink(Box::new(sink)); Ok(()) @@ -1686,7 +1671,7 @@ impl RecordingStream { /// terms of data durability and ordering. /// See [`Self::set_sink`] for more information. pub fn stdout(&self) -> Result<(), crate::sink::FileSinkError> { - self.stdout_opts(None) + self.stdout_opts() } /// Swaps the underlying sink for a [`crate::sink::FileSink`] pointed at stdout. @@ -1700,10 +1685,7 @@ impl RecordingStream { /// /// If a blueprint was provided, it will be stored first in the file. /// Blueprints are currently an experimental part of the Rust SDK. - pub fn stdout_opts( - &self, - blueprint: Option>, - ) -> Result<(), crate::sink::FileSinkError> { + pub fn stdout_opts(&self) -> Result<(), crate::sink::FileSinkError> { if forced_sink_path().is_some() { re_log::debug!("Ignored setting new file since _RERUN_FORCE_SINK is set"); return Ok(()); @@ -1717,11 +1699,6 @@ impl RecordingStream { let sink = crate::sink::FileSink::stdout()?; - // If a blueprint was provided, write it first. - if let Some(blueprint) = blueprint { - Self::send_blueprint(blueprint, &sink); - } - self.set_sink(Box::new(sink)); Ok(()) @@ -1745,21 +1722,34 @@ impl RecordingStream { } } - /// Send the blueprint to the sink, and then activate it. - pub fn send_blueprint(blueprint: Vec, sink: &dyn crate::sink::LogSink) { - let mut store_id = None; + /// Send a blueprint through this recording stream + pub fn send_blueprint( + &self, + blueprint: Vec, + activation_cmd: BlueprintActivationCommand, + ) { + let mut blueprint_id = None; for msg in blueprint { - if store_id.is_none() { - store_id = Some(msg.store_id().clone()); + if blueprint_id.is_none() { + blueprint_id = Some(msg.store_id().clone()); + } + self.record_msg(msg); + } + + if let Some(blueprint_id) = blueprint_id { + if blueprint_id == activation_cmd.blueprint_id { + // Let the viewer know that the blueprint has been fully received, + // and that it can now be activated. + // We don't want to activate half-loaded blueprints, because that can be confusing, + // and can also lead to problems with space-view heuristics. + self.record_msg(activation_cmd.into()); + } else { + re_log::warn!( + "Blueprint ID mismatch when sending blueprint: {} != {}. Ignoring activation.", + blueprint_id, + activation_cmd.blueprint_id + ); } - sink.send(msg); - } - if let Some(store_id) = store_id { - // Let the viewer know that the blueprint has been fully received, - // and that it can now be activated. - // We don't want to activate half-loaded blueprints, because that can be confusing, - // and can also lead to problems with space-view heuristics. - sink.send(LogMsg::ActivateStore(store_id)); } } } diff --git a/crates/re_sdk_comms/src/server.rs b/crates/re_sdk_comms/src/server.rs index f74033f6c9dc..3cfe096dfd79 100644 --- a/crates/re_sdk_comms/src/server.rs +++ b/crates/re_sdk_comms/src/server.rs @@ -249,7 +249,7 @@ impl CongestionManager { #[allow(clippy::match_same_arms)] match msg { // we don't want to drop any of these - LogMsg::SetStoreInfo(_) | LogMsg::ActivateStore(_) => true, + LogMsg::SetStoreInfo(_) | LogMsg::BlueprintActivationCommand { .. } => true, LogMsg::ArrowMsg(_, arrow_msg) => self.should_send_time_point(&arrow_msg.timepoint_max), } diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 80bcaa582447..67f22966fff0 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -554,6 +554,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), + default_blueprint: None, }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -597,6 +598,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), + default_blueprint: None, }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -646,6 +648,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), + default_blueprint: None, }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -918,6 +921,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), + default_blueprint: None, }; let mut query_result = space_view .contents diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index d04c87b26245..9d63fda4cd5f 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -662,6 +662,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), + default_blueprint: None, }; struct Scenario { diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs index 678f15a3f924..3f3753419614 100644 --- a/crates/re_ui/src/command.rs +++ b/crates/re_ui/src/command.rs @@ -25,6 +25,7 @@ pub enum UICommand { OpenRerunDiscord, ResetViewer, + ClearAndGenerateBlueprint, #[cfg(not(target_arch = "wasm32"))] OpenProfiler, @@ -121,6 +122,12 @@ impl UICommand { "Reset the Viewer to how it looked the first time you ran it, forgetting all stored blueprints and UI state", ), + Self::ClearAndGenerateBlueprint => ( + "Clear and generate new blueprint", + "Clear the current blueprint and generate a new one based on heuristics." + ), + + #[cfg(not(target_arch = "wasm32"))] Self::OpenProfiler => ( "Open profiler", @@ -262,6 +269,8 @@ impl UICommand { Self::Quit => Some(cmd(Key::Q)), Self::ResetViewer => Some(ctrl_shift(Key::R)), + Self::ClearAndGenerateBlueprint => None, + #[cfg(not(target_arch = "wasm32"))] Self::OpenProfiler => Some(ctrl_shift(Key::P)), Self::ToggleMemoryPanel => Some(ctrl_shift(Key::M)), diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index a20c8a4a5d08..d7dae6fa977d 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -336,8 +336,8 @@ impl App { egui_ctx: &egui::Context, ) { match cmd { - SystemCommand::ActivateStore(store_id) => { - store_hub.activate_store(store_id); + SystemCommand::ActivateRecording(store_id) => { + store_hub.activate_recording(store_id); } SystemCommand::CloseStore(store_id) => { store_hub.remove(&store_id); @@ -372,10 +372,17 @@ impl App { } SystemCommand::ResetViewer => self.reset(store_hub, egui_ctx), + SystemCommand::ClearAndGenerateBlueprint => { + re_log::debug!("Clear and generate new blueprint"); + // By clearing the default blueprint and the active blueprint + // it will be re-generated based on the default auto behavior. + store_hub.clear_default_blueprint(); + store_hub.clear_active_blueprint(); + } SystemCommand::ResetBlueprint => { - // By clearing the blueprint it will be re-populated with the defaults + // By clearing the blueprint the default blueprint will be restored // at the beginning of the next frame. - re_log::debug!("Reset blueprint"); + re_log::debug!("Reset blueprint to default"); store_hub.clear_active_blueprint(); egui_ctx.request_repaint(); // Many changes take a frame delay to show up. } @@ -517,6 +524,10 @@ impl App { } UICommand::ResetViewer => self.command_sender.send_system(SystemCommand::ResetViewer), + UICommand::ClearAndGenerateBlueprint => { + self.command_sender + .send_system(SystemCommand::ClearAndGenerateBlueprint); + } #[cfg(not(target_arch = "wasm32"))] UICommand::OpenProfiler => { @@ -967,25 +978,35 @@ impl App { // Andled by EntityDb::add } - LogMsg::ActivateStore(store_id) => { - match store_id.kind { - StoreKind::Recording => { - re_log::debug!("Opening a new recording: {store_id}"); - store_hub.set_active_recording_id(store_id.clone()); - } - StoreKind::Blueprint => { - if let Some(info) = entity_db.store_info() { - re_log::debug!( - "Activating blueprint that was loaded from {channel_source}" - ); - let app_id = info.application_id.clone(); - store_hub.set_blueprint_for_app_id(store_id.clone(), app_id); - } else { - re_log::warn!("Got ActivateStore message without first receiving a SetStoreInfo"); + LogMsg::BlueprintActivationCommand(cmd) => match store_id.kind { + StoreKind::Recording => { + re_log::debug!( + "Unexpected `BlueprintActivationCommand` message for {store_id}" + ); + } + StoreKind::Blueprint => { + if let Some(info) = entity_db.store_info() { + re_log::debug!( + "Activating blueprint that was loaded from {channel_source}" + ); + let app_id = info.application_id.clone(); + if cmd.make_default { + store_hub.set_default_blueprint_for_app_id(store_id, &app_id); + } + if cmd.make_active { + store_hub + .make_blueprint_active_for_app_id(store_id, &app_id) + .unwrap_or_else(|err| { + re_log::warn!("Failed to make blueprint active: {err}"); + }); } + } else { + re_log::warn!( + "Got ActivateStore message without first receiving a SetStoreInfo" + ); } } - } + }, } // Do analytics after ingesting the new message, diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer/src/store_hub.rs index ed6bc19786b6..dabeda3e3788 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer/src/store_hub.rs @@ -1,5 +1,6 @@ use ahash::{HashMap, HashMapExt}; +use anyhow::Context as _; use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; use re_entity_db::{EntityDb, StoreBundle}; @@ -21,7 +22,8 @@ use crate::{loading::load_blueprint_file, saving::default_blueprint_path}; pub struct StoreHub { active_rec_id: Option, active_application_id: Option, - blueprint_by_app_id: HashMap, + default_blueprint_by_app_id: HashMap, + active_blueprint_by_app_id: HashMap, store_bundle: StoreBundle, /// Was a recording ever activated? Used by the heuristic controlling the welcome screen. @@ -73,7 +75,8 @@ impl StoreHub { Self { active_rec_id: None, active_application_id: None, - blueprint_by_app_id, + default_blueprint_by_app_id: Default::default(), + active_blueprint_by_app_id: blueprint_by_app_id, store_bundle, was_recording_active: false, @@ -104,8 +107,19 @@ impl StoreHub { // If we have an app-id, then use it to look up the blueprint. let app_id = self.active_application_id.clone()?; + // If there's no active blueprint for this app, try to make the current default one active. + if !self.active_blueprint_by_app_id.contains_key(&app_id) { + if let Some(blueprint_id) = self.default_blueprint_by_app_id.get(&app_id).cloned() { + self.make_blueprint_active_for_app_id(&blueprint_id, &app_id) + .unwrap_or_else(|err| { + re_log::warn!("Failed to make blueprint active: {err}"); + }); + } + } + + // Get the id is of whatever blueprint is now active, falling back on the "app blueprint" if needed. let blueprint_id = self - .blueprint_by_app_id + .active_blueprint_by_app_id .entry(app_id.clone()) .or_insert_with(|| StoreId::from_string(StoreKind::Blueprint, app_id.clone().0)); @@ -119,6 +133,7 @@ impl StoreHub { .and_then(|id| self.store_bundle.get(id)); Some(StoreContext { + default_blueprint: self.default_blueprint_by_app_id.get(&app_id), app_id, blueprint, recording: recording.unwrap_or(&EMPTY_ENTITY_DB), @@ -129,35 +144,29 @@ impl StoreHub { /// Keeps track if a recording was ever activated. /// /// This is useful for the heuristic controlling the welcome screen. + #[inline] pub fn was_recording_active(&self) -> bool { self.was_recording_active } - /// Activate a store by its [`StoreId`]. - /// - /// If this is a recording, switch to it. - /// If this is a blueprint, switch to the `AppId` of the blueprint, - /// and make this blueprint the active blueprint for that `AppId`. - pub fn activate_store(&mut self, store_id: StoreId) { + /// Activate a recording by its [`StoreId`]. + pub fn activate_recording(&mut self, store_id: StoreId) { match store_id.kind { StoreKind::Recording => self.set_active_recording_id(store_id), StoreKind::Blueprint => { - if let Some(store) = self.store_bundle.get(&store_id) { - if let Some(app_id) = store.app_id().cloned() { - self.set_blueprint_for_app_id(store_id.clone(), app_id.clone()); - self.set_active_app_id(app_id.clone()); - } - } + re_log::debug!("Tried to activate the blueprint {store_id} as a recording."); } } } /// Directly access the [`EntityDb`] for the active recording. + #[inline] pub fn active_recording_id(&self) -> Option<&StoreId> { self.active_rec_id.as_ref() } /// Directly access the [`EntityDb`] for the active recording. + #[inline] pub fn active_recording(&self) -> Option<&EntityDb> { self.active_rec_id .as_ref() @@ -203,7 +212,7 @@ impl StoreHub { // try to load one from the persisted store // TODO(#2579): implement web-storage for blueprints as well #[cfg(not(target_arch = "wasm32"))] - if !self.blueprint_by_app_id.contains_key(&app_id) { + if !self.active_blueprint_by_app_id.contains_key(&app_id) { if let Err(err) = self.try_to_load_persisted_blueprint(&app_id) { re_log::warn!("Failed to load persisted blueprint: {err}"); } @@ -212,20 +221,56 @@ impl StoreHub { self.active_application_id = Some(app_id); } + #[inline] pub fn active_application_id(&self) -> Option<&ApplicationId> { self.active_application_id.as_ref() } - /// Change which blueprint is active for a given [`ApplicationId`] + /// Change which blueprint is the default for a given [`ApplicationId`] #[inline] - pub fn set_blueprint_for_app_id(&mut self, blueprint_id: StoreId, app_id: ApplicationId) { - re_log::debug!("Switching blueprint for {app_id} to {blueprint_id}"); - self.blueprint_by_app_id.insert(app_id, blueprint_id); + pub fn set_default_blueprint_for_app_id( + &mut self, + blueprint_id: &StoreId, + app_id: &ApplicationId, + ) { + re_log::debug!("Switching default blueprint for {app_id} to {blueprint_id}"); + self.default_blueprint_by_app_id + .insert(app_id.clone(), blueprint_id.clone()); + } + + /// Make blueprint active for a given [`ApplicationId`] + /// + /// We never activate a blueprint directly. Instead, we clone it and activate the clone. + //TODO(jleibs): In the future this can probably be handled with snapshots instead. + pub fn make_blueprint_active_for_app_id( + &mut self, + blueprint_id: &StoreId, + app_id: &ApplicationId, + ) -> anyhow::Result<()> { + let new_id = StoreId::random(StoreKind::Blueprint); + + re_log::debug!( + "Cloning {blueprint_id} as {new_id} the active blueprint for {app_id} to {blueprint_id}" + ); + + let blueprint = self + .store_bundle + .get(blueprint_id) + .context("missing blueprint")?; + + let new_blueprint = blueprint.clone_with_new_id(new_id.clone())?; + + self.store_bundle.insert(new_blueprint); + + self.active_blueprint_by_app_id + .insert(app_id.clone(), new_id); + + Ok(()) } /// Is the given blueprint id the active blueprint for any app id? pub fn is_active_blueprint(&self, blueprint_id: &StoreId) -> bool { - self.blueprint_by_app_id + self.active_blueprint_by_app_id .values() .any(|id| id == blueprint_id) } @@ -233,16 +278,27 @@ impl StoreHub { /// Clear the currently active blueprint pub fn clear_active_blueprint(&mut self) { if let Some(app_id) = &self.active_application_id { - if let Some(blueprint_id) = self.blueprint_by_app_id.remove(app_id) { + if let Some(blueprint_id) = self.active_blueprint_by_app_id.remove(app_id) { re_log::debug!("Clearing blueprint for {app_id}: {blueprint_id}"); self.store_bundle.remove(&blueprint_id); } } } + /// Clear the current default blueprint + pub fn clear_default_blueprint(&mut self) { + if let Some(app_id) = &self.active_application_id { + self.default_blueprint_by_app_id.remove(app_id); + } + } + /// Forgets all blueprints pub fn clear_all_blueprints(&mut self) { - for (_app_id, blueprint_id) in self.blueprint_by_app_id.drain() { + for (_app_id, blueprint_id) in self + .active_blueprint_by_app_id + .drain() + .chain(self.default_blueprint_by_app_id.drain()) + { self.store_bundle.remove(&blueprint_id); } } @@ -344,7 +400,11 @@ impl StoreHub { pub fn gc_blueprints(&mut self, app_options: &AppOptions) { re_tracing::profile_function!(); if app_options.blueprint_gc { - for blueprint_id in self.blueprint_by_app_id.values() { + for blueprint_id in self + .active_blueprint_by_app_id + .values() + .chain(self.default_blueprint_by_app_id.values()) + { if let Some(blueprint) = self.store_bundle.get_mut(blueprint_id) { // TODO(jleibs): Decide a better tuning for this. Would like to save a // reasonable amount of history, or incremental snapshots. @@ -366,7 +426,7 @@ impl StoreHub { // save the blueprints referenced by `blueprint_by_app_id`, even though // there may be other Blueprints in the Hub. - for (app_id, blueprint_id) in &self.blueprint_by_app_id { + for (app_id, blueprint_id) in &self.active_blueprint_by_app_id { let Some(blueprint) = self.store_bundle.get_mut(blueprint_id) else { re_log::debug!("Failed to find blueprint {blueprint_id}."); continue; @@ -435,7 +495,7 @@ impl StoreHub { "Switching blueprint for {app_id} to {} loaded from {blueprint_path:?}", store.store_id(), ); - self.blueprint_by_app_id + self.active_blueprint_by_app_id .insert(app_id.clone(), store.store_id().clone()); self.blueprint_last_save .insert(store.store_id().clone(), store.generation()); @@ -463,7 +523,7 @@ impl StoreHub { let blueprint = self .active_application_id .as_ref() - .and_then(|app_id| self.blueprint_by_app_id.get(app_id)) + .and_then(|app_id| self.active_blueprint_by_app_id.get(app_id)) .and_then(|blueprint_id| self.store_bundle.get(blueprint_id)); let blueprint_stats = blueprint diff --git a/crates/re_viewer/src/ui/blueprint_panel.rs b/crates/re_viewer/src/ui/blueprint_panel.rs index 737e0a69fe8c..3efb9248cf5e 100644 --- a/crates/re_viewer/src/ui/blueprint_panel.rs +++ b/crates/re_viewer/src/ui/blueprint_panel.rs @@ -25,10 +25,16 @@ pub fn blueprint_panel_ui( } fn reset_blueprint_button_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { + let hover_text = if ctx.store_context.default_blueprint.is_some() { + "Reset to the default blueprint for this app" + } else { + "Re-populate viewport with automatically chosen space views" + }; + if ctx .re_ui .small_icon_button(ui, &re_ui::icons::RESET) - .on_hover_text("Re-populate viewport with automatically chosen space views") + .on_hover_text(hover_text) .clicked() { ctx.command_sender diff --git a/crates/re_viewer_context/src/command_sender.rs b/crates/re_viewer_context/src/command_sender.rs index e0e3852efdf8..68a3ab54fa95 100644 --- a/crates/re_viewer_context/src/command_sender.rs +++ b/crates/re_viewer_context/src/command_sender.rs @@ -20,10 +20,11 @@ pub enum SystemCommand { /// Reset the `Blueprint` to the default state ResetBlueprint, + /// Clear the blueprint and generate a new one + ClearAndGenerateBlueprint, + /// If this is a recording, switch to it. - /// If this is a blueprint, switch to the `AppId` of the blueprint, - /// and make this blueprint the active blueprint for that `AppId`. - ActivateStore(StoreId), + ActivateRecording(StoreId), /// Close a recording or blueprint (free its memory). CloseStore(StoreId), diff --git a/crates/re_viewer_context/src/store_context.rs b/crates/re_viewer_context/src/store_context.rs index 7f27eb3f9cd6..5e77e57df839 100644 --- a/crates/re_viewer_context/src/store_context.rs +++ b/crates/re_viewer_context/src/store_context.rs @@ -16,10 +16,17 @@ pub struct StoreContext<'a> { /// All the loaded recordings and blueprints. pub bundle: &'a StoreBundle, + + /// The current default blueprint + pub default_blueprint: Option<&'a StoreId>, } impl StoreContext<'_> { pub fn is_active(&self, store_id: &StoreId) -> bool { self.recording.store_id() == store_id || self.blueprint.store_id() == store_id } + + pub fn is_default_blueprint(&self, store_id: &StoreId) -> bool { + self.default_blueprint == Some(store_id) + } } diff --git a/crates/rerun/src/run.rs b/crates/rerun/src/run.rs index d54501580eb4..956eeaba8b99 100644 --- a/crates/rerun/src/run.rs +++ b/crates/rerun/src/run.rs @@ -559,8 +559,12 @@ impl PrintCommand { } } - LogMsg::ActivateStore(store_id) => { - println!("ActivateStore({store_id})"); + LogMsg::BlueprintActivationCommand(re_log_types::BlueprintActivationCommand { + blueprint_id, + make_active, + make_default, + }) => { + println!("BlueprintActivationCommand({blueprint_id}, make_active: {make_active}, make_default: {make_default})"); } } } diff --git a/crates/rerun_c/src/lib.rs b/crates/rerun_c/src/lib.rs index 9f04baba1cad..e814a9dd530c 100644 --- a/crates/rerun_c/src/lib.rs +++ b/crates/rerun_c/src/lib.rs @@ -408,7 +408,7 @@ fn rr_recording_stream_connect_impl( } else { None }; - stream.connect_opts(tcp_addr, flush_timeout, None); + stream.connect_opts(tcp_addr, flush_timeout); Ok(()) } diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py index f465d5b6ff71..f6c3ffcb56d0 100755 --- a/examples/python/arkit_scenes/main.py +++ b/examples/python/arkit_scenes/main.py @@ -353,7 +353,7 @@ def main() -> None: ), ) - rr.script_setup(args, "rerun_example_arkit_scenes", blueprint=blueprint) + rr.script_setup(args, "rerun_example_arkit_scenes", default_blueprint=blueprint) recording_path = ensure_recording_available(args.video_id, args.include_highres) log_arkit(recording_path, args.include_highres) diff --git a/examples/python/blueprint/main.py b/examples/python/blueprint/main.py index 6a041918e2d4..ef100b2c5eed 100755 --- a/examples/python/blueprint/main.py +++ b/examples/python/blueprint/main.py @@ -36,7 +36,7 @@ def main() -> None: auto_space_views=args.auto_space_views, ) - rr.init("rerun_example_blueprint", spawn=True, blueprint=blueprint) + rr.init("rerun_example_blueprint", spawn=True, default_blueprint=blueprint) img = np.zeros([128, 128, 3], dtype="uint8") for i in range(8): diff --git a/examples/python/blueprint_stocks/main.py b/examples/python/blueprint_stocks/main.py index d4f8c55e9c4e..a0b036c99b6b 100755 --- a/examples/python/blueprint_stocks/main.py +++ b/examples/python/blueprint_stocks/main.py @@ -166,7 +166,8 @@ def main() -> None: else: blueprint = viewport - rr.script_setup(args, "rerun_example_blueprint_stocks", blueprint=blueprint) + rr.script_setup(args, "rerun_example_blueprint_stocks") + rr.send_blueprint(blueprint) # In a future blueprint release, this can move into the blueprint as well for symbol in symbols: diff --git a/examples/python/controlnet/main.py b/examples/python/controlnet/main.py index 8179fd43fa97..1b2f9f03f79d 100755 --- a/examples/python/controlnet/main.py +++ b/examples/python/controlnet/main.py @@ -135,7 +135,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_controlnet", - blueprint=rrb.Horizontal( + default_blueprint=rrb.Horizontal( rrb.Grid( rrb.Spatial2DView(origin="input/raw"), rrb.Spatial2DView(origin="input/canny"), diff --git a/examples/python/depth_guided_stable_diffusion/main.py b/examples/python/depth_guided_stable_diffusion/main.py index a1daab0674a6..abe0316d3fd5 100755 --- a/examples/python/depth_guided_stable_diffusion/main.py +++ b/examples/python/depth_guided_stable_diffusion/main.py @@ -122,7 +122,7 @@ def main() -> None: # * inputs # * depth & initializations # * diffusion outputs - blueprint=rrb.Blueprint( + default_blueprint=rrb.Blueprint( rrb.Horizontal( rrb.Vertical( rrb.Tabs( diff --git a/examples/python/face_tracking/main.py b/examples/python/face_tracking/main.py index ea9dde7a40a1..e017e90483c6 100755 --- a/examples/python/face_tracking/main.py +++ b/examples/python/face_tracking/main.py @@ -435,7 +435,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_mp_face_detection", - blueprint=rrb.Horizontal( + default_blueprint=rrb.Horizontal( rrb.Spatial3DView(origin="reconstruction"), rrb.Vertical( rrb.Spatial2DView(origin="video"), diff --git a/examples/python/gesture_detection/main.py b/examples/python/gesture_detection/main.py index 7e617dc3cb87..5e04ac9e76d5 100755 --- a/examples/python/gesture_detection/main.py +++ b/examples/python/gesture_detection/main.py @@ -299,7 +299,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_mp_gesture_recognition", - blueprint=rrb.Horizontal( + default_blueprint=rrb.Horizontal( rrb.Spatial2DView(name="Input & Hand", contents=["media/**", "hand2d/**"]), rrb.Vertical( rrb.Tabs( diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py index edda91627c43..e10089c0131e 100755 --- a/examples/python/human_pose_tracking/main.py +++ b/examples/python/human_pose_tracking/main.py @@ -217,7 +217,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_human_pose_tracking", - blueprint=rrb.Horizontal( + default_blueprint=rrb.Horizontal( rrb.Vertical( rrb.Spatial2DView(origin="video", name="Result"), rrb.Spatial3DView(origin="person", name="3D pose"), diff --git a/examples/python/live_camera_edge_detection/main.py b/examples/python/live_camera_edge_detection/main.py index d7fe9103b95a..86373d6006dd 100755 --- a/examples/python/live_camera_edge_detection/main.py +++ b/examples/python/live_camera_edge_detection/main.py @@ -66,7 +66,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_live_camera_edge_detection", - blueprint=rrb.Vertical( + default_blueprint=rrb.Vertical( rrb.Horizontal( rrb.Spatial2DView(origin="/image/rgb", name="Video"), rrb.Spatial2DView(origin="/image/gray", name="Video (Grayscale)"), diff --git a/examples/python/llm_embedding_ner/main.py b/examples/python/llm_embedding_ner/main.py index 094de3faa2da..363383999020 100755 --- a/examples/python/llm_embedding_ner/main.py +++ b/examples/python/llm_embedding_ner/main.py @@ -169,7 +169,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_llm_embedding_ner", - blueprint=rrb.Horizontal( + default_blueprint=rrb.Horizontal( rrb.Vertical( rrb.TextDocumentView(origin="/text", name="Original Text"), rrb.TextDocumentView(origin="/tokenized_text", name="Tokenized Text"), diff --git a/examples/python/nuscenes/main.py b/examples/python/nuscenes/main.py index a8f0d28998d6..8072177d3682 100755 --- a/examples/python/nuscenes/main.py +++ b/examples/python/nuscenes/main.py @@ -269,7 +269,7 @@ def main() -> None: row_shares=[3, 2], ) - rr.script_setup(args, "rerun_example_nuscenes", blueprint=blueprint) + rr.script_setup(args, "rerun_example_nuscenes", default_blueprint=blueprint) log_nuscenes(nusc, args.scene_name, max_time_sec=args.seconds) diff --git a/examples/python/objectron/main.py b/examples/python/objectron/main.py index e4db83e39325..f07549a59c51 100755 --- a/examples/python/objectron/main.py +++ b/examples/python/objectron/main.py @@ -218,7 +218,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_objectron", - blueprint=rrb.Horizontal( + default_blueprint=rrb.Horizontal( rrb.Spatial3DView(origin="/world", name="World"), rrb.Spatial2DView(origin="/world/camera", name="Camera", contents=["+ $origin/**", "+ /world/**"]), ), diff --git a/examples/python/plots/main.py b/examples/python/plots/main.py index a7dbc3e0f6a4..725ea8c2dda3 100755 --- a/examples/python/plots/main.py +++ b/examples/python/plots/main.py @@ -142,7 +142,7 @@ def main() -> None: rrb.TimePanel(expanded=False), ) - rr.script_setup(args, "rerun_example_plot", blueprint=blueprint) + rr.script_setup(args, "rerun_example_plot", default_blueprint=blueprint) rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) log_bar_chart() diff --git a/examples/python/rgbd/main.py b/examples/python/rgbd/main.py index 8a0c8271c0a3..33bf11f9f959 100755 --- a/examples/python/rgbd/main.py +++ b/examples/python/rgbd/main.py @@ -164,7 +164,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_rgbd", - blueprint=rrb.Horizontal( + default_blueprint=rrb.Horizontal( rrb.Spatial3DView(name="3D", origin="world"), rrb.Vertical( # Put the origin for both 2D spaces where the pinhole is logged. Doing so allows them to understand how they're connected to the 3D space. diff --git a/examples/python/signed_distance_fields/main.py b/examples/python/signed_distance_fields/main.py index e2669fcfd608..572c184fc2db 100755 --- a/examples/python/signed_distance_fields/main.py +++ b/examples/python/signed_distance_fields/main.py @@ -198,7 +198,7 @@ def main() -> None: rr.script_setup( args, "rerun_example_signed_distance_fields", - blueprint=rrb.Horizontal( + default_blueprint=rrb.Horizontal( rrb.Vertical( rrb.Horizontal( rrb.Spatial3DView(name="Input Mesh", origin="/world/mesh"), diff --git a/examples/python/structure_from_motion/main.py b/examples/python/structure_from_motion/main.py index 5030f4c39944..a8f01bbd0ab7 100755 --- a/examples/python/structure_from_motion/main.py +++ b/examples/python/structure_from_motion/main.py @@ -232,7 +232,7 @@ def main() -> None: row_shares=[3, 2], ) - rr.script_setup(args, "rerun_example_structure_from_motion", blueprint=blueprint) + rr.script_setup(args, "rerun_example_structure_from_motion", default_blueprint=blueprint) dataset_path = get_downloaded_dataset_path(args.dataset) read_and_log_sparse_reconstruction(dataset_path, filter_output=not args.unfiltered, resize=args.resize) rr.script_teardown(args) diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 76019472fc93..07eccbafc7f0 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -86,6 +86,7 @@ class Section: "connect", "disconnect", "save", + "send_blueprint", "serve", "spawn", "memory_recording", diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 797d714460de..1b07e374d1f7 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -93,6 +93,7 @@ "set_time_nanos", "set_time_seconds", "set_time_sequence", + "send_blueprint", "spawn", ] @@ -174,7 +175,7 @@ set_thread_local_data_recording, ) from .script_helpers import script_add_args, script_setup, script_teardown -from .sinks import connect, disconnect, memory_recording, save, serve, spawn, stdout +from .sinks import connect, disconnect, memory_recording, save, send_blueprint, serve, spawn, stdout from .time import ( disable_timeline, reset_time, @@ -222,7 +223,7 @@ def _init_recording_stream() -> None: from rerun.recording_stream import _patch as recording_stream_patch recording_stream_patch( - [connect, save, stdout, disconnect, memory_recording, serve, spawn] + [connect, save, stdout, disconnect, memory_recording, serve, spawn, send_blueprint] + [ set_time_sequence, set_time_seconds, @@ -247,7 +248,7 @@ def init( init_logging: bool = True, default_enabled: bool = True, strict: bool = False, - blueprint: BlueprintLike | None = None, + default_blueprint: BlueprintLike | None = None, ) -> None: """ Initialize the Rerun SDK with a user-chosen application id (name). @@ -315,8 +316,11 @@ def init( strict If `True`, an exceptions is raised on use error (wrong parameter types, etc.). If `False`, errors are logged as warnings instead. - blueprint - A blueprint to use for this application. If not provided, a new one will be created. + default_blueprint + Optionally set a default blueprint to use for this application. If the application + already has an active blueprint, the new blueprint won't become active until the user + clicks the "reset blueprint" button. If you want to activate the new blueprint + immediately, instead use the [`rerun.send_blueprint`][] API. """ @@ -347,7 +351,7 @@ def init( if spawn: from rerun.sinks import spawn as _spawn - _spawn(blueprint=blueprint) + _spawn(default_blueprint=default_blueprint) # TODO(#3793): defaulting recording_id to authkey should be opt-in diff --git a/rerun_py/rerun_sdk/rerun/script_helpers.py b/rerun_py/rerun_sdk/rerun/script_helpers.py index cbb3c10680f8..0a9062ac7127 100644 --- a/rerun_py/rerun_sdk/rerun/script_helpers.py +++ b/rerun_py/rerun_sdk/rerun/script_helpers.py @@ -65,7 +65,7 @@ def script_setup( args: Namespace, application_id: str, recording_id: str | UUID | None = None, - blueprint: rr.blueprint.BlueprintLike | None = None, + default_blueprint: rr.blueprint.BlueprintLike | None = None, ) -> RecordingStream: """ Run common Rerun script setup actions. Connect to the viewer if necessary. @@ -87,8 +87,11 @@ def script_setup( processes to log to the same Rerun instance (and be part of the same recording), you will need to manually assign them all the same recording_id. Any random UUIDv4 will work, or copy the recording id for the parent process. - blueprint : Optional[rr.blueprint.BlueprintLike] - An optional blueprint to use for the viewer. + default_blueprint + Optionally set a default blueprint to use for this application. If the application + already has an active blueprint, the new blueprint won't become active until the user + clicks the "reset blueprint" button. If you want to activate the new blueprint + immediately, instead use the [`rerun.send_blueprint`][] API. """ rr.init( @@ -102,18 +105,18 @@ def script_setup( # NOTE: mypy thinks these methods don't exist because they're monkey-patched. if args.stdout: - rec.stdout(blueprint=blueprint) # type: ignore[attr-defined] + rec.stdout(default_blueprint=default_blueprint) # type: ignore[attr-defined] elif args.serve: - rec.serve(blueprint=blueprint) # type: ignore[attr-defined] + rec.serve(default_blueprint=default_blueprint) # type: ignore[attr-defined] elif args.connect: # Send logging data to separate `rerun` process. # You can omit the argument to connect to the default address, # which is `127.0.0.1:9876`. - rec.connect(args.addr, blueprint=blueprint) # type: ignore[attr-defined] + rec.connect(args.addr, default_blueprint=default_blueprint) # type: ignore[attr-defined] elif args.save is not None: - rec.save(args.save, blueprint=blueprint) # type: ignore[attr-defined] + rec.save(args.save, default_blueprint=default_blueprint) # type: ignore[attr-defined] elif not args.headless: - rec.spawn(blueprint=blueprint) # type: ignore[attr-defined] + rec.spawn(default_blueprint=default_blueprint) # type: ignore[attr-defined] return rec diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index f436d58c16ba..64ffc59970f3 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -17,7 +17,7 @@ def connect( addr: str | None = None, *, flush_timeout_sec: float | None = 2.0, - blueprint: BlueprintLike | None = None, + default_blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None, ) -> None: """ @@ -35,8 +35,11 @@ def connect( The minimum time the SDK will wait during a flush before potentially dropping data if progress is not being made. Passing `None` indicates no timeout, and can cause a call to `flush` to block indefinitely. - blueprint: - An optional blueprint to configure the UI. + default_blueprint + Optionally set a default blueprint to use for this application. If the application + already has an active blueprint, the new blueprint won't become active until the user + clicks the "reset blueprint" button. If you want to activate the new blueprint + immediately, instead use the [`rerun.send_blueprint`][] API. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. @@ -56,19 +59,23 @@ def connect( # If a blueprint is provided, we need to create a blueprint storage object blueprint_storage = None - if blueprint is not None: - blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + if default_blueprint is not None: + blueprint_storage = create_in_memory_blueprint( + application_id=application_id, blueprint=default_blueprint + ).storage recording = RecordingStream.to_native(recording) - bindings.connect(addr=addr, flush_timeout_sec=flush_timeout_sec, blueprint=blueprint_storage, recording=recording) + bindings.connect( + addr=addr, flush_timeout_sec=flush_timeout_sec, default_blueprint=blueprint_storage, recording=recording + ) _connect = connect # we need this because Python scoping is horrible def save( - path: str | pathlib.Path, blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None + path: str | pathlib.Path, default_blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None ) -> None: """ Stream all log-data to a file. @@ -79,9 +86,11 @@ def save( ---------- path: The path to save the data to. - blueprint: - An optional blueprint to configure the UI. - This will be written first to the .rrd file, before appending the recording data. + default_blueprint + Optionally set a default blueprint to use for this application. If the application + already has an active blueprint, the new blueprint won't become active until the user + clicks the "reset blueprint" button. If you want to activate the new blueprint + immediately, instead use the [`rerun.send_blueprint`][] API. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. @@ -101,15 +110,17 @@ def save( # If a blueprint is provided, we need to create a blueprint storage object blueprint_storage = None - if blueprint is not None: - blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + if default_blueprint is not None: + blueprint_storage = create_in_memory_blueprint( + application_id=application_id, blueprint=default_blueprint + ).storage recording = RecordingStream.to_native(recording) - bindings.save(path=str(path), blueprint=blueprint_storage, recording=recording) + bindings.save(path=str(path), default_blueprint=blueprint_storage, recording=recording) -def stdout(blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None) -> None: +def stdout(default_blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None) -> None: """ Stream all log-data to stdout. @@ -122,8 +133,11 @@ def stdout(blueprint: BlueprintLike | None = None, recording: RecordingStream | Parameters ---------- - blueprint: - An optional blueprint to configure the UI. + default_blueprint + Optionally set a default blueprint to use for this application. If the application + already has an active blueprint, the new blueprint won't become active until the user + clicks the "reset blueprint" button. If you want to activate the new blueprint + immediately, instead use the [`rerun.send_blueprint`][] API. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. @@ -143,11 +157,13 @@ def stdout(blueprint: BlueprintLike | None = None, recording: RecordingStream | # If a blueprint is provided, we need to create a blueprint storage object blueprint_storage = None - if blueprint is not None: - blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + if default_blueprint is not None: + blueprint_storage = create_in_memory_blueprint( + application_id=application_id, blueprint=default_blueprint + ).storage recording = RecordingStream.to_native(recording) - bindings.stdout(blueprint=blueprint_storage, recording=recording) + bindings.stdout(default_blueprint=blueprint_storage, recording=recording) def disconnect(recording: RecordingStream | None = None) -> None: @@ -200,7 +216,7 @@ def serve( open_browser: bool = True, web_port: int | None = None, ws_port: int | None = None, - blueprint: BlueprintLike | None = None, + default_blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None, server_memory_limit: str = "25%", ) -> None: @@ -224,8 +240,11 @@ def serve( The port to serve the web viewer on (defaults to 9090). ws_port: The port to serve the WebSocket server on (defaults to 9877) - blueprint: - An optional blueprint to configure the UI. + default_blueprint + Optionally set a default blueprint to use for this application. If the application + already has an active blueprint, the new blueprint won't become active until the user + clicks the "reset blueprint" button. If you want to activate the new blueprint + immediately, instead use the [`rerun.send_blueprint`][] API. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. @@ -248,8 +267,10 @@ def serve( # If a blueprint is provided, we need to create a blueprint storage object blueprint_storage = None - if blueprint is not None: - blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + if default_blueprint is not None: + blueprint_storage = create_in_memory_blueprint( + application_id=application_id, blueprint=default_blueprint + ).storage recording = RecordingStream.to_native(recording) bindings.serve( @@ -257,11 +278,53 @@ def serve( web_port, ws_port, server_memory_limit=server_memory_limit, - blueprint=blueprint_storage, + default_blueprint=blueprint_storage, recording=recording, ) +def send_blueprint( + blueprint: BlueprintLike, + *, + make_active: bool = True, + make_default: bool = True, + recording: RecordingStream | None = None, +) -> None: + """ + Create a blueprint from a `BlueprintLike` and send it to the `RecordingStream`. + + Parameters + ---------- + blueprint: + A blueprint object to send to the viewer. + make_active: + Immediately make this the active blueprint for the associated `app_id`. + Note that setting this to `false` does not mean the blueprint may not still end + up becoming active. In particular, if `make_default` is true and there is no other + currently active blueprint. + make_default: + Make this the default blueprint for the `app_id`. + The default blueprint will be used as the template when the user resets the + blueprint for the app. It will also become the active blueprint if no other + blueprint is currently active. + recording: + Specifies the [`rerun.RecordingStream`][] to use. + If left unspecified, defaults to the current active data recording, if there is one. + See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. + + """ + application_id = get_application_id(recording=recording) + + if application_id is None: + raise ValueError("No application id found. You must call rerun.init before sending a blueprint.") + + recording = RecordingStream.to_native(recording) + + blueprint_storage = create_in_memory_blueprint(application_id=application_id, blueprint=blueprint).storage + + bindings.send_blueprint(blueprint_storage, make_active, make_default, recording=recording) + + # TODO(#4019): application-level handshake def _check_for_existing_viewer(port: int) -> bool: try: @@ -283,7 +346,7 @@ def spawn( port: int = 9876, connect: bool = True, memory_limit: str = "75%", - blueprint: BlueprintLike | None = None, + default_blueprint: BlueprintLike | None = None, recording: RecordingStream | None = None, ) -> None: """ @@ -308,8 +371,11 @@ def spawn( Specifies the [`rerun.RecordingStream`][] to use if `connect = True`. If left unspecified, defaults to the current active data recording, if there is one. See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. - blueprint: - An optional blueprint to configure the UI. + default_blueprint + Optionally set a default blueprint to use for this application. If the application + already has an active blueprint, the new blueprint won't become active until the user + clicks the "reset blueprint" button. If you want to activate the new blueprint + immediately, instead use the [`rerun.send_blueprint`][] API. """ @@ -368,4 +434,4 @@ def spawn( sleep(0.1) if connect: - _connect(f"127.0.0.1:{port}", recording=recording, blueprint=blueprint) + _connect(f"127.0.0.1:{port}", recording=recording, default_blueprint=default_blueprint) diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index 2f6393bbaf1e..52a0e3cdf265 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -3,6 +3,7 @@ #![allow(unsafe_op_in_unsafe_fn)] // False positive due to #[pufunction] macro use std::collections::HashMap; +use std::io::IsTerminal as _; use std::path::PathBuf; use itertools::Itertools; @@ -12,7 +13,7 @@ use pyo3::{ types::{PyBytes, PyDict}, }; -use re_log_types::{EntityPathPart, StoreKind}; +use re_log_types::{BlueprintActivationCommand, EntityPathPart, StoreKind}; use rerun::{ sink::MemorySinkStorage, time::TimePoint, EntityPath, RecordingStream, RecordingStreamBuilder, StoreId, @@ -180,6 +181,7 @@ fn rerun_bindings(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(log_arrow_msg, m)?)?; m.add_function(wrap_pyfunction!(log_file_from_path, m)?)?; m.add_function(wrap_pyfunction!(log_file_from_contents, m)?)?; + m.add_function(wrap_pyfunction!(send_blueprint, m)?)?; // misc m.add_function(wrap_pyfunction!(version, m)?)?; @@ -527,15 +529,37 @@ fn is_enabled(recording: Option<&PyRecordingStream>) -> bool { get_data_recording(recording).map_or(false, |rec| rec.is_enabled()) } +/// Helper for forwarding the blueprint memory-sink representation to a given sink +fn send_mem_sink_as_default_blueprint( + sink: &dyn rerun::sink::LogSink, + default_blueprint: &PyMemorySinkStorage, +) { + if let Some(id) = default_blueprint.inner.store_id() { + let activate_cmd = BlueprintActivationCommand::make_default(id); + sink.send_blueprint(default_blueprint.inner.take(), activate_cmd); + } else { + re_log::warn!("Provided `default_blueprint` has no store info, cannot send it."); + } +} + #[pyfunction] -#[pyo3(signature = (addr = None, flush_timeout_sec=rerun::default_flush_timeout().unwrap().as_secs_f32(), blueprint = None, recording = None))] +#[pyo3(signature = (addr = None, flush_timeout_sec=rerun::default_flush_timeout().unwrap().as_secs_f32(), default_blueprint = None, recording = None))] fn connect( addr: Option, flush_timeout_sec: Option, - blueprint: Option<&PyMemorySinkStorage>, + default_blueprint: Option<&PyMemorySinkStorage>, recording: Option<&PyRecordingStream>, py: Python<'_>, ) -> PyResult<()> { + let Some(recording) = get_data_recording(recording) else { + return Ok(()); + }; + + if rerun::forced_sink_path().is_some() { + re_log::debug!("Ignored call to `connect()` since _RERUN_TEST_FORCE_SAVE is set"); + return Ok(()); + } + let addr = if let Some(addr) = addr { addr.parse()? } else { @@ -547,9 +571,16 @@ fn connect( // The call to connect may internally flush. // Release the GIL in case any flushing behavior needs to cleanup a python object. py.allow_threads(|| { - if let Some(recording) = get_data_recording(recording) { - recording.connect_opts(addr, flush_timeout, blueprint.map(|b| b.inner.take())); - }; + // We create the sink manually so we can send the default blueprint + // first before the rest of the current recording stream. + let sink = rerun::sink::TcpSink::new(addr, flush_timeout); + + if let Some(default_blueprint) = default_blueprint { + send_mem_sink_as_default_blueprint(&sink, default_blueprint); + } + + recording.set_sink(Box::new(sink)); + flush_garbage_queue(); }); @@ -557,10 +588,10 @@ fn connect( } #[pyfunction] -#[pyo3(signature = (path, blueprint = None, recording = None))] +#[pyo3(signature = (path, default_blueprint = None, recording = None))] fn save( path: &str, - blueprint: Option<&PyMemorySinkStorage>, + default_blueprint: Option<&PyMemorySinkStorage>, recording: Option<&PyRecordingStream>, py: Python<'_>, ) -> PyResult<()> { @@ -568,21 +599,35 @@ fn save( return Ok(()); }; + if rerun::forced_sink_path().is_some() { + re_log::debug!("Ignored call to `save()` since _RERUN_TEST_FORCE_SAVE is set"); + return Ok(()); + } + // The call to save may internally flush. // Release the GIL in case any flushing behavior needs to cleanup a python object. py.allow_threads(|| { - let res = recording - .save_opts(path, blueprint.map(|b| b.inner.take())) - .map_err(|err| PyRuntimeError::new_err(err.to_string())); + // We create the sink manually so we can send the default blueprint + // first before the rest of the current recording stream. + let sink = rerun::sink::FileSink::new(path) + .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; + + if let Some(default_blueprint) = default_blueprint { + send_mem_sink_as_default_blueprint(&sink, default_blueprint); + } + + recording.set_sink(Box::new(sink)); + flush_garbage_queue(); - res + + Ok(()) }) } #[pyfunction] -#[pyo3(signature = (blueprint = None, recording = None))] +#[pyo3(signature = (default_blueprint = None, recording = None))] fn stdout( - blueprint: Option<&PyMemorySinkStorage>, + default_blueprint: Option<&PyMemorySinkStorage>, recording: Option<&PyRecordingStream>, py: Python<'_>, ) -> PyResult<()> { @@ -590,14 +635,33 @@ fn stdout( return Ok(()); }; + if rerun::forced_sink_path().is_some() { + re_log::debug!("Ignored call to `stdout()` since _RERUN_TEST_FORCE_SAVE is set"); + return Ok(()); + } + // The call to stdout may internally flush. // Release the GIL in case any flushing behavior needs to cleanup a python object. py.allow_threads(|| { - let res = recording - .stdout_opts(blueprint.map(|b| b.inner.take())) - .map_err(|err| PyRuntimeError::new_err(err.to_string())); + let sink: Box = if std::io::stdout().is_terminal() { + re_log::debug!("Ignored call to stdout() because stdout is a terminal"); + Box::new(rerun::sink::BufferedSink::new()) + } else { + Box::new( + rerun::sink::FileSink::stdout() + .map_err(|err| PyRuntimeError::new_err(err.to_string()))?, + ) + }; + + if let Some(default_blueprint) = default_blueprint { + send_mem_sink_as_default_blueprint(sink.as_ref(), default_blueprint); + } + flush_garbage_queue(); - res + + recording.set_sink(sink); + + Ok(()) }) } @@ -679,13 +743,13 @@ fn enter_tokio_runtime() -> tokio::runtime::EnterGuard<'static> { /// Serve a web-viewer. #[allow(clippy::unnecessary_wraps)] // False positive #[pyfunction] -#[pyo3(signature = (open_browser, web_port, ws_port, server_memory_limit, blueprint = None, recording = None))] +#[pyo3(signature = (open_browser, web_port, ws_port, server_memory_limit, default_blueprint = None, recording = None))] fn serve( open_browser: bool, web_port: Option, ws_port: Option, server_memory_limit: String, - blueprint: Option<&PyMemorySinkStorage>, + default_blueprint: Option<&PyMemorySinkStorage>, recording: Option<&PyRecordingStream>, ) -> PyResult<()> { #[cfg(feature = "web_viewer")] @@ -694,6 +758,11 @@ fn serve( return Ok(()); }; + if rerun::forced_sink_path().is_some() { + re_log::debug!("Ignored call to `serve()` since _RERUN_TEST_FORCE_SAVE is set"); + return Ok(()); + } + let server_memory_limit = re_memory::MemoryLimit::parse(&server_memory_limit) .map_err(|err| PyRuntimeError::new_err(format!("Bad server_memory_limit: {err}:")))?; @@ -708,8 +777,8 @@ fn serve( ) .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; - if let Some(blueprint) = blueprint { - RecordingStream::send_blueprint(blueprint.inner.take(), &*sink); + if let Some(default_blueprint) = default_blueprint { + send_mem_sink_as_default_blueprint(sink.as_ref(), default_blueprint); } recording.set_sink(sink); @@ -719,7 +788,7 @@ fn serve( #[cfg(not(feature = "web_viewer"))] { - _ = blueprint; + _ = default_blueprint; _ = recording; _ = web_port; _ = ws_port; @@ -919,6 +988,32 @@ fn log_file( Ok(()) } +/// Send a blueprint to the given recording stream. +#[pyfunction] +#[pyo3(signature = (blueprint, make_active = false, make_default = true, recording = None))] +fn send_blueprint( + blueprint: &PyMemorySinkStorage, + make_active: bool, + make_default: bool, + recording: Option<&PyRecordingStream>, +) { + let Some(recording) = get_data_recording(recording) else { + return; + }; + + if let Some(blueprint_id) = blueprint.inner.store_id() { + let activation_cmd = BlueprintActivationCommand { + blueprint_id, + make_active, + make_default, + }; + + recording.send_blueprint(blueprint.inner.take(), activation_cmd); + } else { + re_log::warn!("Provided `default_blueprint` has no store info, cannot send it."); + } +} + // --- Misc --- /// Return a verbose version string diff --git a/tests/python/blueprint/main.py b/tests/python/blueprint/main.py index ab74738b558d..5a750108932c 100644 --- a/tests/python/blueprint/main.py +++ b/tests/python/blueprint/main.py @@ -40,7 +40,7 @@ rr.init( "rerun_example_blueprint_test", spawn=True, - blueprint=blueprint, + default_blueprint=blueprint, ) rng = default_rng(12345) diff --git a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py index eb6df7907d83..20032eac8879 100644 --- a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py +++ b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py @@ -58,7 +58,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py index 9779ba648392..a0be96d164be 100644 --- a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py +++ b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py @@ -51,7 +51,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py index 923fd4337827..1a434cea1486 100644 --- a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py +++ b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py @@ -46,7 +46,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_multi_selection.py b/tests/python/release_checklist/check_context_menu_multi_selection.py index 78fd703c6b10..a1d03e2be884 100644 --- a/tests/python/release_checklist/check_context_menu_multi_selection.py +++ b/tests/python/release_checklist/check_context_menu_multi_selection.py @@ -83,7 +83,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_single_selection.py b/tests/python/release_checklist/check_context_menu_single_selection.py index 07bb9a73f7e0..7f2ba042e92f 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection.py +++ b/tests/python/release_checklist/check_context_menu_single_selection.py @@ -103,7 +103,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py index ac5ce1211e47..831b7c76e0bf 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py +++ b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py @@ -82,7 +82,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_context_menu_suggested_origin.py b/tests/python/release_checklist/check_context_menu_suggested_origin.py index c68136ba868e..dad86853b320 100644 --- a/tests/python/release_checklist/check_context_menu_suggested_origin.py +++ b/tests/python/release_checklist/check_context_menu_suggested_origin.py @@ -78,7 +78,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) log_readme() log_some_space_views() diff --git a/tests/python/release_checklist/check_focus.py b/tests/python/release_checklist/check_focus.py index e72f11dd0469..743c46229ec0 100644 --- a/tests/python/release_checklist/check_focus.py +++ b/tests/python/release_checklist/check_focus.py @@ -42,7 +42,7 @@ def log_some_space_views() -> None: def run(args: Namespace) -> None: - rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), blueprint=blueprint()) + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) log_readme() log_some_space_views() From 8cf3f921d84949fe2c1b2e755595219263041564 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:05:36 +0100 Subject: [PATCH 132/508] Simplify Welcome Screen and use card-based layout for examples (#5699) ### What * Closes #5452 Note: the "Source code" links are functional but disabled, as the example manifest must be updated to include the corresponding URL, see follow-up issues. Follow-up: - #5700 - #5701 Before/After: image image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5699/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5699/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5699/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5699) - [Docs preview](https://rerun.io/preview/6766af1787603295c4d4970a1c98849677409942/docs) - [Examples preview](https://rerun.io/preview/6766af1787603295c4d4970a1c98849677409942/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_ui/data/icons/github.png | Bin 0 -> 456 bytes crates/re_ui/data/images/configure-card.png | Bin 1878 -> 0 bytes crates/re_ui/data/images/live-data-card.png | Bin 2134 -> 0 bytes .../re_ui/data/images/recorded-data-card.png | Bin 2364 -> 0 bytes crates/re_ui/src/design_tokens.rs | 14 +- crates/re_ui/src/icons.rs | 16 +- crates/re_ui/src/lib.rs | 10 +- crates/re_viewer/src/app_state.rs | 2 +- crates/re_viewer/src/ui/top_panel.rs | 8 +- .../src/ui/welcome_screen/example_section.rs | 360 +++++++++-------- crates/re_viewer/src/ui/welcome_screen/mod.rs | 65 +-- .../src/ui/welcome_screen/welcome_section.rs | 370 +++--------------- 12 files changed, 289 insertions(+), 556 deletions(-) create mode 100644 crates/re_ui/data/icons/github.png delete mode 100644 crates/re_ui/data/images/configure-card.png delete mode 100644 crates/re_ui/data/images/live-data-card.png delete mode 100644 crates/re_ui/data/images/recorded-data-card.png diff --git a/crates/re_ui/data/icons/github.png b/crates/re_ui/data/icons/github.png new file mode 100644 index 0000000000000000000000000000000000000000..d899c05ad9aa55495a434fd3b7aee6a3302fc60b GIT binary patch literal 456 zcmV;(0XP1MP)VAdZ%(ViSfbO(7LCqxG+p#3tS+ots^P-hwrkOK-` y8_|}nOeo|xPKu$?YS;?ec0We$cYk8^ri5QZp?gohHh!i60000I}$AJ`Mage(c>fFu|xC_}{Ml$2!^l;sqaf#Nbs zDzZwd3JMwm3JO5=vWh^J$~p!{9^Sr1C1ojT8DWvp+WLmB9$qu(hM}{)2~a-oAVC?D?+!2P+%f zG7HNSGxMB0yft<8RW-G(>>Mm?Y%g88di&n}$b?jVV^eu$)vH&p7FN`S#w2R!=&fF} zwr|43`3o1VTEEH4-s$7Vk58UHv$C@f3Jq`U=uOQnN=eTQi;U`=FvZB+YWvPz{((Vr z=Px*V?6{PyoQb(bMt07TW5@jhgB)F4FJ8VfVbbIsJ9nvTX*adDl~q(;x_l)wJEys| z&BMpf!`mk=Ddq9w$E(+@S+!=(j$ONV?K@~?Yk&Lh{mO>6#EiV`y!IQ;Ew2iWjB)n#wRUt-(a}&+k8PZ)RJZ$iTqT z?djqeQZeW4o#(;AjuOW|ik`e_?PgM@(|%%Qgu_Nftuj}ikdQY@Qq}Lf_9lG)|F!RQ z>jIm}Dc?VqrT?wH|6um)n}5%2Dt`V#+2zKDu7^`OpWEvjCjB@OxM)M-;?nge=NuEc z(DV2Gd9TFB$K3QDm+BwgqSm4(T)O`79yd0<$y%lQhxZ5_v~8{~?>P2@-R-;7nVd~4 zF6?D7UM&z@qJQwrDwcKk6lZIdtUqvt!I?!u>3{%Z8;5~QgJM#nr{8M5y)TWq=J}kR zbM(R+%i`j*v*U%gB`kb2PaxoIn5SNNe_!kQBduH{$r4N2hbTQp}zw1nF8OZacAKN8akk zIjN-|_v8xt9RB8!*623F=>7B+X6i@ZJbHWLu!*sZWatdZBE5CHi^a`*wp%yd6h64* zNj^|;?r1tO ztRL}{(hu2doQUAOJg;*f^OMvyEt(n=CjQddAbV`OrS{__`=0jo+4sQN^|WlGA-J9tRO)`jc@Mc37j!9&#ji9?wwsZJ$hpIwNB@MGk3ltAM^;Tz+&dsQ=eV2fv(O&BeLk@tMK>NeT@4q zbmq<89}B8E)4l~hD9>DB$Eo;BXjgb*!oNnrN1NY;&bTgq@qYN-*9L3zogALM7m9b; yx9|O~@MOPGdDp~R`+EJz=$>8bg=d#Wzp$P!}@nU%Z diff --git a/crates/re_ui/data/images/live-data-card.png b/crates/re_ui/data/images/live-data-card.png deleted file mode 100644 index fb2dd78a25550beda86f09416b1e733d13badea1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2134 zcmcIlc~Fx{7Egv_xDgSFK=2C$3J~N&85HCYOCW)S+ki+g0U?N7h6K@(Nle0N!o3(E z1m%8$n7Zzl28Wdk zpm2DbKQ7nygM`$bcEpG=+xcaQ(htP@WOC; zdC64jiI~`>r6net(PB@p+G2XYHpT3 zeAq4S^}t}RibPBn$H~QweB#6pOlE9iN*W_0fp&KHUWbYbL8GW?Xn4eSufstP3?(sz zdX`~oVa3bKuMkwed?`;lO${OtrlzDrBO{i(L3>B%Zm}4H^QF@07$5uvHpj!qj}T4{ zkE8?;!Xhd07g!t&4o{9v5M67dBv9KrZcyoG@(YT5{DTSMq=b|-CYx<*@9>?Yb9~C# z6O`DDtQ?3#h|-;?FRVi3BLP#S2^s;B51#u!H&I3!AOS zfj;Jz0@-DdG%ia%m{ipVrQmB>_!s!U>G4)ZpW7Dye1HKm+*-4fL!qOnRD(V29-Jna zf3|k)Nid>+N%DR_{kmnY&)W86VqD$hZE?Rx*QVn95tGs!{UO04{O}aML3iO1{aIl_2j?!LKp6n};FRIgJ#x&e` z|AZ%^o}q1r+th*@LOF+A@K1p?9VJScpr4}#G%i|f&k?~*_9B80i{c9ex zeWky4V05s%^osaE{FsL>PRm$FDJ^(3w9->k9Lp+WR`WT-KXUbci%DegHA*m@mkQ5|2=A-w8cucA2EQH$?Cl0#aN#K%mn2)97|03@6)<)0 zMxIvP?zeknf&L{dOohjnD>3z>OpcM&UQ}AC7G`;`@Xp^#B;0&$m=1Or8qM3hGGj)y z)J-}JmZU>V{M(Mu_>INc=;n|JJnUT_k}x;tj$HZ&UdkJAF{Z_CjqoEnI;Q4PLznEN{qyt%f>>jHrov5jAfhes>1TKS zQkfr2;Y9*bEpg7LNEw0hzIz|5;_Nqeb}6{McDbMyG~YvIdMSHKl$NuVUHyrbS`x+8 z>T93Pi?ndWpCa@RPM_@3Ln8E97hhPm`hM$~xEnt6mq+G`rui$cq+fLTDQ_>Z#bN-R z`|qUwk>3A`wsH>?lcK#ry+vtAy<(8>A__i8veVc)2n1Zf<`Z*CuEDpg3)Ljsf=v*! zedd?HDW>pS>TZQ=OA0@&dhJZ-(#v4D>OK8Ng_<;;h92Tf`;GxzW5f-tk~vql75F-fokk#WL!2B2zKmnhu>c&!*IGrzBL7_Ecg|O9|hE z^xYO8QXfKAvSCh_*ylGi4b1r2b%9nEZ?Pq*bq*J|=pRYk#3`G{1aQ@G<~!7pe2#T6 zY2A_Ux7w!?+t2yjnmngP=v8vFK}-u_b;VjUBu;3Ng2?Di09$o@NKvDsv$3-&j$z}i>FM~Veg6-$ z8dkh3?X+A}Mbc&Nm`B>ID?WMlx#QPo+QrYE1-9#w41Q|K^xpn5!8GiM?2Vlgihc4IRt+Q9d0O`hh zAf;UBim0iOFq2eE&w0I@Ily{LyFPknvqrF^_$r)S9`%gfV*j2=%XCY+AH6uK^&nDk zjd+!^y7LitrMU2&U6*?n^dxDp?|_)E!tH?NWKdhjal!BP4J67wfevI{M-6|XKVCt{ z$5+Ys_mv4b8TT|jQzuvKn|HncUQuoYy6B90BWb^Gkk45WzT4Kjf2?X<<7U8{)(zh? m4B5@GtaFj8RfU?R4EW>lz!cu>+Z)hV0>gUv9=>*n#QHnLobm+# diff --git a/crates/re_ui/data/images/recorded-data-card.png b/crates/re_ui/data/images/recorded-data-card.png deleted file mode 100644 index 97eb24c54f0e4675bf11871ea2c3aa26d52ba522..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2364 zcmd5-iCdCc7k^#CGOf%?+z}Kp7hYEs%~S*t(NbJP3`#947sL{mFHzG{$*n~!%1Wzo z%gGjZ#WKXQ&&s8-bes{l%q2ye#+mYa?XURmbMLvodw#!j&hy-JpXcTr^zl$t)=~xl zK-H7%?gs#Ja0u6JR)DP9jAb{p$#MKV+~kIP%+jF4mN;?<2LQIJZ!9_Bnh=u9O&z5A z6Co0TK?iwX|~xWE^p)_+ZSi-n3x)kz-P4dJu`mIJ)4St26gWLV05G*$`G+>X=P-OH?sf$bMvrBJ=?8Cbw%HRh!hX(R6GJNecd2!)4^XW* zi=6w`oliMsn$H&h$xUpV=EU4A$Q|f-LoEf6i3d~)yANru4FB3^n$J7qg7JSh!;7s zL5rKYrKVdnqdI4YTG(x9D>|nrCjmYQoiSA=0bFayB!*SD$d-)6P z9?y?xvKHD7Y|ZQczTLh35J}+uA(YCYO;k^24*&A@g$+vICKbfv_)*UA)%d@edhe8F zaRaaBcL_Z1gjxK|>;w*#7et@c0j*4BT~o$o$;n=^<;MW&>fBJ+PG;-P&-0t8E`5K= zqkq)^)JO7oTVl2{Gd{uuf2;xOf;L?+ufFz_#bJP7JUZsW)&f*|UQV>-@`|o3*Sm@? z)F&O%1Y@3#7wgOO=^e`bN^qQ4mL`l(CuV8N@vq;YF-daLE56KJ-qNya>0ahYD&d|A z9D7>AmlIc4hz0=Z-EF1v%vSMkft={VWdmzv_*=y+O+`Lg*D657tt3Ql29Xhx6**Fc zN~spp{beDPmhAAme^_`}b35y@0ZoxlZ88D)R0lPz!iLCFBta9x!XKo-@!`t6qPMcw zY9h%@q2?x)oX|Te^4T`Tr_|k`6+S#0K$YX3{D)^yWI$6;$&(<8J*;t*L zK0SQgtxTrG=;a$L=G2+esooJ*zmrwNn3MfSS1??%Vy+-A5=03Ej@wFa*dB#+UntC3 zT_x1{UI~TyyKuDs%_l>+LpZ4fCL0?0s2KUzNPc2|!T`UBaIeuuFuK|{)v{>&<6&L< z7#nYs!d?6BlL1l96J_t}n**5>g(eEw=ssLGP;Qt_RRt;IJMRK;BR0(uvXBF#}AZW}An*|dS_ihOLW1Q3@bt{j9&T(}sJ zn%-}f03?6EZF&Hz{<4Oq=z{o)_AZeme&r82uzpK&raZiqxE&(3@AsV)6~<4%Hh~pe zmRn&eJxCmeXD~bg=^hK6xPXeeDWoHOE>YUfyFI*2gn^VxHC-_5n>LNCr7 zs#AV-X~Wu0>N)|W+VM81er*zsuFyMfwV;b*hW? z`{be=ohj*o{2u3v$%883-Jwpx09dAW^=O$#`w1AldKIZ|*{hMvuxEp8ir$ex60?15J&eYv%jRIqhxFIPq+sq@hqH@Bxx3p17W zfz6>@CR(Ub8k-{l<& zjdyLL^{ngF6NL|(Z)Mo{QkHJpvpaullBIonD*5!Glq1V?3EkD+eSjPaR#JcbTNYmf zJEfNX>>D*kU7OFzvErUF;O24J`!9X$g3+Q(iwmYpN6>cgvBVSKF-txlc;A>50}R_4 zqLq$ry503J6sON$e7>B+MK|;WzxsNA=Kg-IzKM#MD}hl``7!%cJ9Zs1>8`f67;Kh?k(QfJ+5BU?aN4leG@Fh) z>s_%DK}h&C));h2m~5f-*o&d@Yqa0Vlm|75u0Irdj9rUoci!F$eSLr@(Z~IP8#Cj7 DLakr_ diff --git a/crates/re_ui/src/design_tokens.rs b/crates/re_ui/src/design_tokens.rs index e62dbbef034a..d0c46ac563f6 100644 --- a/crates/re_ui/src/design_tokens.rs +++ b/crates/re_ui/src/design_tokens.rs @@ -84,21 +84,21 @@ fn apply_design_tokens(ctx: &egui::Context) -> DesignTokens { // TODO(ab): font sizes should come from design tokens egui_style .text_styles - .insert(ReUi::welcome_screen_h1(), egui::FontId::proportional(28.0)); + .insert(ReUi::welcome_screen_h1(), egui::FontId::proportional(41.0)); egui_style .text_styles - .insert(ReUi::welcome_screen_h2(), egui::FontId::proportional(24.0)); - egui_style - .text_styles - .insert(ReUi::welcome_screen_h3(), egui::FontId::proportional(15.0)); + .insert(ReUi::welcome_screen_h2(), egui::FontId::proportional(27.0)); egui_style.text_styles.insert( ReUi::welcome_screen_example_title(), - egui::FontId::proportional(16.0), + egui::FontId::proportional(13.0), ); egui_style.text_styles.insert( ReUi::welcome_screen_body(), - egui::FontId::proportional(13.0), + egui::FontId::proportional(15.0), ); + egui_style + .text_styles + .insert(ReUi::welcome_screen_tag(), egui::FontId::proportional(10.5)); let panel_bg_color = get_aliased_color(&json, "{Alias.Color.Surface.Default.value}"); // let floating_color = get_aliased_color(&json, "{Alias.Color.Surface.Floating.value}"); diff --git a/crates/re_ui/src/icons.rs b/crates/re_ui/src/icons.rs index c397e8568cb6..ee3e2eb29a0d 100644 --- a/crates/re_ui/src/icons.rs +++ b/crates/re_ui/src/icons.rs @@ -144,18 +144,4 @@ pub const LINK: Icon = Icon::new("link", include_bytes!("../data/icons/link.png" pub const COMPONENT: Icon = Icon::new("component", include_bytes!("../data/icons/component.png")); pub const STORE: Icon = Icon::new("store", include_bytes!("../data/icons/store.png")); - -pub const WELCOME_SCREEN_CONFIGURE: Icon = Icon::new( - "welcome_screen_configure", - include_bytes!("../data/images/configure-card.png"), -); - -pub const WELCOME_SCREEN_LIVE_DATA: Icon = Icon::new( - "welcome_screen_live_data", - include_bytes!("../data/images/live-data-card.png"), -); - -pub const WELCOME_SCREEN_RECORDED_DATA: Icon = Icon::new( - "welcome_screen_recorded_data", - include_bytes!("../data/images/recorded-data-card.png"), -); +pub const GITHUB: Icon = Icon::new("github", include_bytes!("../data/icons/github.png")); diff --git a/crates/re_ui/src/lib.rs b/crates/re_ui/src/lib.rs index e64dc2a3d32e..051a595e83eb 100644 --- a/crates/re_ui/src/lib.rs +++ b/crates/re_ui/src/lib.rs @@ -114,11 +114,6 @@ impl ReUi { egui::TextStyle::Name("welcome-screen-h2".into()) } - #[inline] - pub fn welcome_screen_h3() -> egui::TextStyle { - egui::TextStyle::Name("welcome-screen-h3".into()) - } - #[inline] pub fn welcome_screen_example_title() -> egui::TextStyle { egui::TextStyle::Name("welcome-screen-example-title".into()) @@ -129,6 +124,11 @@ impl ReUi { egui::TextStyle::Name("welcome-screen-body".into()) } + #[inline] + pub fn welcome_screen_tag() -> egui::TextStyle { + egui::TextStyle::Name("welcome-screen-tag".into()) + } + pub fn welcome_screen_tab_bar_style(ui: &mut egui::Ui) { ui.spacing_mut().item_spacing.x = 16.0; ui.visuals_mut().selection.bg_fill = egui::Color32::TRANSPARENT; diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 816c526abe06..65e38595b923 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -362,7 +362,7 @@ impl AppState { .frame(viewport_frame) .show_inside(ui, |ui| { if show_welcome { - welcome_screen.ui(ui, re_ui, rx, command_sender); + welcome_screen.ui(ui, re_ui, command_sender); } else { viewport.viewport_ui(ui, &ctx); } diff --git a/crates/re_viewer/src/ui/top_panel.rs b/crates/re_viewer/src/ui/top_panel.rs index 33f7a5ac8b0b..ca9165c90ab9 100644 --- a/crates/re_viewer/src/ui/top_panel.rs +++ b/crates/re_viewer/src/ui/top_panel.rs @@ -292,11 +292,9 @@ fn website_link_ui(ui: &mut egui::Ui) { .on_hover_cursor(egui::CursorIcon::PointingHand) .on_hover_text(url); if response.clicked() { - ui.ctx().output_mut(|o| { - o.open_url = Some(egui::output::OpenUrl { - url: url.to_owned(), - new_tab: true, - }); + ui.ctx().open_url(egui::output::OpenUrl { + url: url.to_owned(), + new_tab: true, }); } } diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index 6668d41dfb43..3c70ef89b558 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -1,11 +1,7 @@ -use egui::vec2; -use egui::Color32; use egui::{NumExt as _, Ui}; use ehttp::{fetch, Request}; use poll_promise::Promise; -use re_ui::icons::ARROW_DOWN; -use re_ui::ReUi; use re_viewer_context::SystemCommandSender; #[derive(Debug, serde::Deserialize)] @@ -20,24 +16,32 @@ struct ExampleDesc { /// snake_case version of the example name name: String, - /// human readable version of the example name + /// human-readable version of the example name title: String, tags: Vec, rrd_url: String, thumbnail: ExampleThumbnail, + + /// URL of the source code in GitHub + source_url: Option, } // TODO(ab): use design tokens -const MIN_COLUMN_WIDTH: f32 = 250.0; -const MAX_COLUMN_WIDTH: f32 = 340.0; +pub(super) const MIN_COLUMN_WIDTH: f32 = 250.0; +const MAX_COLUMN_WIDTH: f32 = 337.0; const MAX_COLUMN_COUNT: usize = 3; -const COLUMN_HSPACE: f32 = 24.0; +const COLUMN_HSPACE: f32 = 20.0; const TITLE_TO_GRID_VSPACE: f32 = 32.0; -const THUMBNAIL_TO_DESCRIPTION_VSPACE: f32 = 8.0; -const ROW_VSPACE: f32 = 32.0; -const THUMBNAIL_RADIUS: f32 = 4.0; +const ROW_VSPACE: f32 = 20.0; +const THUMBNAIL_RADIUS: f32 = 12.0; + +const CARD_THUMBNAIL_ASPECT_RATIO: f32 = 337.0 / 250.0; + +const CARD_DESCRIPTION_HEIGHT: f32 = 130.0; + +const DESCRIPTION_INNER_MARGIN: f32 = 20.0; /// Structure to track both an example description and its layout in the grid. /// @@ -62,14 +66,9 @@ impl ExampleDescLayout { } } - /// Saves the top left corner of the hover/click area for this example. - fn set_top_left(&mut self, pos: egui::Pos2) { - self.rect.min = pos; - } - - /// Saves the bottom right corner of the hover/click area for this example. - fn set_bottom_right(&mut self, pos: egui::Pos2) { - self.rect.max = pos; + /// Saves the rectangle of the hover/click area for this example. + fn set_rect(&mut self, rect: egui::Rect) { + self.rect = rect; } fn clicked(&self, ui: &egui::Ui, id: egui::Id) -> bool { @@ -81,6 +80,12 @@ impl ExampleDescLayout { ui.interact(self.rect, id.with(&self.desc.name), egui::Sense::hover()) .hovered() } + + /// Move the egui cursor to the bottom of this example card. + fn move_cursor_to_bottom(&self, ui: &mut Ui) { + let vspace = (self.rect.max.y - ui.cursor().min.y).at_least(0.0); + ui.add_space(vspace); + } } type ManifestJson = Vec; @@ -227,11 +232,45 @@ impl ExampleSection { } } + /// Draw the example section of the welcome screen. + /// + /// Layout: + /// ```text + /// {MIN|MAX}_COLUMN_WIDTH COLUMN_HSPACE + /// ◀───────────────────────────────▶◀──▶ + /// ╔═══════════════════════════════╗ ┌──────── + /// ║ THUMBNAIL ▲ ║ │ + /// ║ │ ║ │ + /// ║ │ ║ │ + /// ║ │ ║ │ + /// ║ CARD_THUMBNAIL_ │ ║ │ + /// ║ ASPECT_RATIO │ ║ │ + /// ║ │ ║ │ + /// ║ │ ║ │ + /// ║ ▼ ║ │ + /// ╠═══════════════════════════════╣ │ + /// ║ ▲ ║ │ + /// ║ ┌─────────────────────┼─┐ ║ │ + /// ║ │DESCRIPTION │ │ ║ │ + /// ║ │ │ │ ║ DESCRIPTION_ + /// ║ │ CARD_DESCRIPTION_ │ │◀─▶║ INNER_ + /// ║ │ HEIGHT │ │ ║ MARGIN + /// ║ └─────────────────────┼─┘ ║ │ + /// ║ ▼ ║ │ + /// ╚═══════════════════════════════╝ └──────── + /// ▲ + /// │ ROW_VSPACE + /// ▼ + /// ┌───────────────────────────────┐ ┌──────── + /// │ │ │ + /// │ │ │ + /// ``` pub(super) fn ui( &mut self, ui: &mut egui::Ui, re_ui: &re_ui::ReUi, command_sender: &re_viewer_context::CommandSender, + header_ui: &impl Fn(&mut Ui), ) { let examples = self .examples @@ -264,27 +303,7 @@ impl ExampleSection { let column_width = ((ui.available_width() + grid_spacing.x) / column_count as f32 - grid_spacing.x) .floor() - .at_most(MAX_COLUMN_WIDTH); - - // cursor is currently at the top of the section, - // so we use it to check for visibility of the whole section. - let example_section_rect = ui.cursor(); - let examples_visible = ui.is_rect_visible(ui.cursor().translate(vec2(0.0, 16.0))); - - let title_response = ui - .horizontal(|ui| { - ui.vertical_centered(|ui| { - ui.add(egui::Label::new( - egui::RichText::new("Examples") - .strong() - .line_height(Some(32.0)) - .text_style(re_ui::ReUi::welcome_screen_h1()), - )) - }) - .inner - }) - .inner; - ui.end_row(); + .clamp(MIN_COLUMN_WIDTH, MAX_COLUMN_WIDTH); ui.horizontal(|ui| { // this space is added on the left so that the grid is centered @@ -296,6 +315,15 @@ impl ExampleSection { ui.add_space(centering_hspace); ui.vertical(|ui| { + header_ui(ui); + + ui.add(egui::Label::new( + egui::RichText::new("View example recordings") + .strong() + .line_height(Some(32.0)) + .text_style(re_ui::ReUi::welcome_screen_h2()), + )); + ui.add_space(TITLE_TO_GRID_VSPACE); egui::Grid::new("example_section_grid") @@ -305,22 +333,27 @@ impl ExampleSection { .show(ui, |ui| { for example_layouts in examples.chunks_mut(column_count) { for example in &mut *example_layouts { - // this is the beginning of the first cell for this example - example.set_top_left(ui.cursor().min); + // this is the beginning of the first cell for this example, we can + // fully compute its rect now + example.set_rect(egui::Rect::from_min_size( + ui.cursor().min, + egui::vec2( + column_width, + column_width / CARD_THUMBNAIL_ASPECT_RATIO + + CARD_DESCRIPTION_HEIGHT, + ), + )); + + // paint background + ui.painter().rect_filled( + example.rect, + THUMBNAIL_RADIUS, + //TODO(ab): as per figma, use design tokens instead + egui::Color32::WHITE.gamma_multiply(0.04), + ); - let thumbnail = &example.desc.thumbnail; - let width = thumbnail.width as f32; - let height = thumbnail.height as f32; ui.vertical(|ui| { - let size = - egui::vec2(column_width, height * column_width / width); - - example_thumbnail( - ui, - &example.desc, - size, - example.hovered(ui, self.id), - ); + example_thumbnail(ui, &example.desc, column_width); }); } @@ -337,15 +370,37 @@ impl ExampleSection { for example in &mut *example_layouts { ui.vertical(|ui| { example_tags(ui, &example.desc); + }); + } + + ui.end_row(); + + for example in &mut *example_layouts { + ui.vertical(|ui| { + // The previous row (tags) may take one or two lines, depending + // on wrapping, so we use the bottom of the example card as + // reference to position the source link. + example.move_cursor_to_bottom(ui); + ui.add_space(-DESCRIPTION_INNER_MARGIN - 15.0); - // this is the end of the last cell for this example - example.set_bottom_right(egui::pos2( - ui.cursor().min.x + column_width, - ui.cursor().min.y, - )); + example_source(ui, &example.desc); + // Ensure the egui cursor is moved according to this card's + // geometry. + example.move_cursor_to_bottom(ui); + + // Manual spacing between rows. ui.add_space(ROW_VSPACE); }); + + if example.hovered(ui, self.id) { + ui.painter().rect_filled( + example.rect, + THUMBNAIL_RADIUS, + //TODO(ab): use design tokens + egui::Color32::from_additive_luminance(25), + ); + } } ui.end_row(); @@ -368,51 +423,34 @@ impl ExampleSection { } }); }); - - if !examples_visible { - let screen_rect = ui.ctx().screen_rect(); - let indicator_rect = example_section_rect - .with_min_y(screen_rect.bottom() - 125.0) - .with_max_y(screen_rect.bottom()); - - let mut ui = ui.child_ui( - indicator_rect, - egui::Layout::centered_and_justified(egui::Direction::LeftToRight), - ); - - ui.vertical_centered(|ui| { - ui.add_space(16.0); - - ui.scope(|ui| { - ui.spacing_mut().button_padding = vec2(16.0, 8.0); - let response = ui.add( - egui::Button::image_and_text( - ARROW_DOWN - .as_image() - .tint(egui::Color32::BLACK) - .fit_to_exact_size(ReUi::small_icon_size()), - egui::RichText::new("See examples").color(egui::Color32::BLACK), - ) - .rounding(16.0) - .fill(egui::Color32::from_gray(0xfa)), - ); - if response.clicked() { - title_response.scroll_to_me(Some(egui::Align::Min)); - } - }) - }); - } } } -fn example_thumbnail( - ui: &mut Ui, - example: &ExampleDesc, - thumbnail_size: egui::Vec2, - hovered: bool, -) { - const ASPECT_RATIO: f32 = 16.0 / 6.75; // same as `rerun.io/examples` - const PADDING_PCT: f32 = 0.07; // 7% +fn example_thumbnail(ui: &mut Ui, example: &ExampleDesc, column_width: f32) { + // dimensions of the source image to use as thumbnail + let image_width = example.thumbnail.width as f32; + let image_height = example.thumbnail.height as f32; + + // the thumbnail rect is determined by the column width and a fixed aspect ratio + let thumbnail_rect = egui::Rect::from_min_size( + ui.cursor().left_top(), + egui::vec2(column_width, column_width / CARD_THUMBNAIL_ASPECT_RATIO), + ); + let thumbnail_width = thumbnail_rect.width(); + let thumbnail_height = thumbnail_rect.height(); + + // compute image UV coordinates implementing a "cropping" scale to fit thumbnail rect + let display_aspect_ratio = thumbnail_width / thumbnail_height; + let image_aspect_ratio = image_width / image_height; + let uv_rect = if image_aspect_ratio > display_aspect_ratio { + let a = + (image_width / image_height * thumbnail_height - thumbnail_width) / 2.0 / image_width; + egui::Rect::from_min_max(egui::Pos2::new(a, 0.0), egui::Pos2::new(1.0 - a, 1.0)) + } else { + let a = + (image_height / image_width * thumbnail_width - thumbnail_height) / 2.0 / image_height; + egui::Rect::from_min_max(egui::Pos2::new(0.0, a), egui::Pos2::new(1.0, 1.0 - a)) + }; let rounding = egui::Rounding { nw: THUMBNAIL_RADIUS, @@ -420,77 +458,56 @@ fn example_thumbnail( sw: 0.0, se: 0.0, }; - - let clip_width = thumbnail_size.x; - let clip_height = thumbnail_size.x / ASPECT_RATIO; - let padding = thumbnail_size.x * PADDING_PCT; - - let clip_top_left = ui.cursor().left_top(); - let bottom_right = clip_top_left + vec2(clip_width, clip_height); - let clip_rect = egui::Rect::from_min_max(clip_top_left, bottom_right); - - let thumbnail_top_left = clip_top_left + vec2(padding, 0.0); - let thumbnail_rect = egui::Rect::from_min_max( - thumbnail_top_left, - thumbnail_top_left + thumbnail_size - vec2(padding * 2.0, padding * 2.0 / ASPECT_RATIO), - ); - - // manually clip the rect and paint the image - let orig_clip_rect = ui.clip_rect(); - ui.set_clip_rect(orig_clip_rect.intersect(clip_rect)); egui::Image::new(&example.thumbnail.url) + .uv(uv_rect) .rounding(rounding) .paint_at(ui, thumbnail_rect); - ui.advance_cursor_after_rect(clip_rect.expand2(vec2(0.0, THUMBNAIL_TO_DESCRIPTION_VSPACE))); - ui.set_clip_rect(orig_clip_rect); - - // TODO(ab): use design tokens - let border_color = if hovered { - ui.visuals_mut().widgets.hovered.fg_stroke.color - } else { - egui::Color32::from_gray(44) - }; - - // paint border - ui.painter().rect_stroke( - clip_rect.intersect(thumbnail_rect), - rounding, - (1.0, border_color), - ); - ui.painter().line_segment( - [clip_rect.left_bottom(), clip_rect.right_bottom()], - (1.0, border_color), - ); + ui.advance_cursor_after_rect(thumbnail_rect); } fn example_title(ui: &mut Ui, example: &ExampleDescLayout) { let title = egui::RichText::new(example.desc.title.clone()) .strong() - .line_height(Some(22.0)) - .color(Color32::from_rgb(178, 178, 187)) + .line_height(Some(16.0)) .text_style(re_ui::ReUi::welcome_screen_example_title()); - ui.horizontal(|ui| { - ui.add(egui::Label::new(title).wrap(true)); + ui.add_space(DESCRIPTION_INNER_MARGIN); + egui::Frame { + inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), + ..Default::default() + } + .show(ui, |ui| { + ui.horizontal(|ui| { + ui.add(egui::Label::new(title).truncate(true)); - if let Some(Some(size)) = example.rrd_byte_size_promise.ready().cloned() { - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - ui.label(re_format::format_bytes(size as f64)); - }); - } + if let Some(Some(size)) = example.rrd_byte_size_promise.ready().cloned() { + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + ui.label(egui::RichText::new(re_format::format_bytes(size as f64)).weak()); + }); + } + }); }); - - ui.add_space(1.0); } fn example_tags(ui: &mut Ui, example: &ExampleDesc) { - // TODO(ab): use design tokens - ui.horizontal_wrapped(|ui| { - ui.style_mut().spacing.button_padding = egui::vec2(4.0, 2.0); - ui.style_mut().spacing.item_spacing = egui::vec2(4.0, 4.0); - for tag in &example.tags { - ui.add( - egui::Button::new(tag) + ui.add_space(10.0); + + egui::Frame { + inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), + ..Default::default() + } + .show(ui, |ui| { + ui.horizontal_wrapped(|ui| { + // TODO(ab): use design tokens + ui.style_mut().spacing.button_padding = egui::vec2(4.0, 2.0); + ui.style_mut().spacing.item_spacing = egui::vec2(4.0, 4.0); + for tag in &example.tags { + ui.add( + egui::Button::new( + egui::RichText::new(tag) + .text_style(re_ui::ReUi::welcome_screen_tag()) + .strong(), + ) .sense(egui::Sense::hover()) .rounding(6.0) .fill(egui::Color32::from_rgb(26, 29, 30)) @@ -499,7 +516,34 @@ fn example_tags(ui: &mut Ui, example: &ExampleDesc) { egui::Color32::WHITE.gamma_multiply(0.086), )) .wrap(false), - ); + ); + } + }); + }); +} + +fn example_source(ui: &mut Ui, example: &ExampleDesc) { + let source_url = example.source_url.as_deref(); + + egui::Frame { + inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), + ..Default::default() + } + .show(ui, |ui| { + if ui + .add_enabled( + source_url.is_some(), + egui::Button::image_and_text(re_ui::icons::GITHUB.as_image(), "Source code"), + ) + .on_disabled_hover_text("Source code is not available for this example") + .clicked() + { + if let Some(source_url) = source_url { + ui.ctx().open_url(egui::output::OpenUrl { + url: source_url.to_owned(), + new_tab: true, + }); + } } }); } diff --git a/crates/re_viewer/src/ui/welcome_screen/mod.rs b/crates/re_viewer/src/ui/welcome_screen/mod.rs index 5dee8b9bee93..e1f5b4309f0c 100644 --- a/crates/re_viewer/src/ui/welcome_screen/mod.rs +++ b/crates/re_viewer/src/ui/welcome_screen/mod.rs @@ -1,14 +1,9 @@ mod example_section; mod welcome_section; -use egui::Widget; -use example_section::ExampleSection; +use example_section::{ExampleSection, MIN_COLUMN_WIDTH}; use welcome_section::welcome_section_ui; -use re_log_types::LogMsg; -use re_smart_channel::ReceiveSet; -use re_ui::ReUi; - #[derive(Default)] pub struct WelcomeScreen { example_page: ExampleSection, @@ -24,14 +19,15 @@ impl WelcomeScreen { &mut self, ui: &mut egui::Ui, re_ui: &re_ui::ReUi, - rx: &ReceiveSet, command_sender: &re_viewer_context::CommandSender, ) { // This is needed otherwise `example_page_ui` bleeds by a few pixels over the timeline panel // TODO(ab): figure out why that happens ui.set_clip_rect(ui.available_rect_before_wrap()); - egui::ScrollArea::vertical() + let horizontal_scroll = ui.available_width() < 40.0 * 2.0 + MIN_COLUMN_WIDTH; + + egui::ScrollArea::new([horizontal_scroll, true]) .id_source("welcome_screen_page") .auto_shrink([false, false]) .show(ui, |ui| { @@ -45,56 +41,11 @@ impl WelcomeScreen { ..Default::default() } .show(ui, |ui| { - welcome_section_ui(ui, rx, command_sender); - ui.add_space(80.0); - self.example_page.ui(ui, re_ui, command_sender); - }); - }); - } -} - -fn set_large_button_style(ui: &mut egui::Ui) { - ui.style_mut().spacing.button_padding = egui::vec2(10.0, 7.0); - let visuals = ui.visuals_mut(); - visuals.widgets.hovered.expansion = 0.0; - visuals.widgets.active.expansion = 0.0; - visuals.widgets.open.expansion = 0.0; + //welcome_section_ui(ui); - visuals.widgets.inactive.rounding = egui::Rounding::same(8.); - visuals.widgets.hovered.rounding = egui::Rounding::same(8.); - visuals.widgets.active.rounding = egui::Rounding::same(8.); - - visuals.widgets.inactive.weak_bg_fill = visuals.widgets.inactive.bg_fill; -} - -fn url_large_text_button(ui: &mut egui::Ui, text: impl Into, url: &str) { - ui.scope(|ui| { - set_large_button_style(ui); - - if egui::Button::image_and_text( - re_ui::icons::EXTERNAL_LINK - .as_image() - .fit_to_exact_size(ReUi::small_icon_size()), - text, - ) - .ui(ui) - .on_hover_cursor(egui::CursorIcon::PointingHand) - .clicked() - { - ui.ctx().output_mut(|o| { - o.open_url = Some(egui::output::OpenUrl { - url: url.to_owned(), - new_tab: true, + self.example_page + .ui(ui, re_ui, command_sender, &welcome_section_ui); }); }); - } - }); -} - -fn large_text_button(ui: &mut egui::Ui, text: impl Into) -> egui::Response { - ui.scope(|ui| { - set_large_button_style(ui); - ui.button(text) - }) - .inner + } } diff --git a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs index b82026176960..b18c86f2b873 100644 --- a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs @@ -1,322 +1,76 @@ -use super::{large_text_button, url_large_text_button}; -use egui::{NumExt, Ui}; -use re_entity_db::EntityDb; -use re_log_types::{ - DataRow, EntityPath, LogMsg, RowId, StoreId, StoreInfo, StoreKind, StoreSource, Time, TimePoint, -}; -use re_smart_channel::ReceiveSet; -use re_ui::UICommandSender; -use re_viewer_context::CommandSender; -use re_viewer_context::{SystemCommand, SystemCommandSender}; +use egui::Ui; -const SPACE_VIEWS_HELP: &str = "https://www.rerun.io/docs/getting-started/viewer-walkthrough"; - -const CPP_CONNECT_MARKDOWN: &str = include_str!("../../../data/quick_start_guides/cpp_connect.md"); -const CPP_SPAWN_MARKDOWN: &str = include_str!("../../../data/quick_start_guides/cpp_spawn.md"); -const PYTHON_CONNECT_MARKDOWN: &str = - include_str!("../../../data/quick_start_guides/python_connect.md"); -const PYTHON_SPAWN_MARKDOWN: &str = - include_str!("../../../data/quick_start_guides/python_spawn.md"); -const RUST_CONNECT_MARKDOWN: &str = - include_str!("../../../data/quick_start_guides/rust_connect.md"); -const RUST_SPAWN_MARKDOWN: &str = include_str!("../../../data/quick_start_guides/rust_spawn.md"); -const HOW_DOES_IT_WORK_MARKDOWN: &str = - include_str!("../../../data/quick_start_guides/how_does_it_work.md"); - -const CPP_CONNECT_SNIPPET: &str = - include_str!("../../../data/quick_start_guides/quick_start_connect.cpp"); -const CPP_SPAWN_SNIPPET: &str = - include_str!("../../../data/quick_start_guides/quick_start_spawn.cpp"); -const PYTHON_CONNECT_SNIPPET: &str = - include_str!("../../../data/quick_start_guides/quick_start_connect.py"); -const PYTHON_SPAWN_SNIPPET: &str = - include_str!("../../../data/quick_start_guides/quick_start_spawn.py"); -const RUST_CONNECT_SNIPPET: &str = - include_str!("../../../data/quick_start_guides/quick_start_connect.rs"); -const RUST_SPAWN_SNIPPET: &str = - include_str!("../../../data/quick_start_guides/quick_start_spawn.rs"); - -struct Placeholder<'a> { - key: &'a str, - value: &'a str, -} - -const PLACEHOLDERS: &[Placeholder<'_>] = &[ - Placeholder { - key: "HOW_DOES_IT_WORK", - value: HOW_DOES_IT_WORK_MARKDOWN, - }, - Placeholder { - key: "EXAMPLE_CODE_CPP_CONNECT", - value: CPP_CONNECT_SNIPPET, - }, - Placeholder { - key: "EXAMPLE_CODE_CPP_SPAWN", - value: CPP_SPAWN_SNIPPET, - }, - Placeholder { - key: "EXAMPLE_CODE_PYTHON_CONNECT", - value: PYTHON_CONNECT_SNIPPET, - }, - Placeholder { - key: "EXAMPLE_CODE_PYTHON_SPAWN", - value: PYTHON_SPAWN_SNIPPET, - }, - Placeholder { - key: "EXAMPLE_CODE_RUST_CONNECT", - value: RUST_CONNECT_SNIPPET, - }, - Placeholder { - key: "EXAMPLE_CODE_RUST_SPAWN", - value: RUST_SPAWN_SNIPPET, - }, -]; - -struct QuickStartEntry<'a> { - entity_path: &'a str, - markdown: &'a str, -} - -const QUICK_START_ENTRIES_CONNECT: &[QuickStartEntry<'_>] = &[ - QuickStartEntry { - entity_path: "quick_start/cpp", - markdown: CPP_CONNECT_MARKDOWN, - }, - QuickStartEntry { - entity_path: "quick_start/python", - markdown: PYTHON_CONNECT_MARKDOWN, - }, - QuickStartEntry { - entity_path: "quick_start/rust", - markdown: RUST_CONNECT_MARKDOWN, - }, -]; - -const QUICK_START_ENTRIES_SPAWN: &[QuickStartEntry<'_>] = &[ - QuickStartEntry { - entity_path: "quick_start/cpp", - markdown: CPP_SPAWN_MARKDOWN, - }, - QuickStartEntry { - entity_path: "quick_start/python", - markdown: PYTHON_SPAWN_MARKDOWN, - }, - QuickStartEntry { - entity_path: "quick_start/rust", - markdown: RUST_SPAWN_MARKDOWN, - }, -]; +const DOCS_URL: &str = "https://www.rerun.io/docs"; /// Show the welcome section. -pub(super) fn welcome_section_ui( - ui: &mut egui::Ui, - rx: &ReceiveSet, - command_sender: &re_viewer_context::CommandSender, -) { +pub(super) fn welcome_section_ui(ui: &mut egui::Ui) { ui.vertical(|ui| { - let accepts_connections = rx.accepts_tcp_connections(); - onboarding_content_ui(ui, command_sender, accepts_connections); - }); -} + let (style, line_height) = if ui.available_width() > 400.0 { + (re_ui::ReUi::welcome_screen_h1(), 50.0) + } else { + (re_ui::ReUi::welcome_screen_h2(), 36.0) + }; -struct Panel { - title: &'static str, - body: &'static str, - image: &'static re_ui::Icon, - add_buttons: PanelButtonsCallback, -} - -type PanelButtonsCallback = Box; - -fn onboarding_content_ui(ui: &mut Ui, command_sender: &CommandSender, accepts_connections: bool) { - // The panel data is stored in this ad hoc structure such that it can easily be iterated over - // in chunks, to make the layout grid code simpler. - let panels = [ - Panel { - title: "Connect to live data", - body: "Use the Rerun SDK to stream data from your code to the Rerun Viewer. \ - Visualize synchronized data from multiple processes, locally or over a network.", - image: &re_ui::icons::WELCOME_SCREEN_LIVE_DATA, - add_buttons: Box::new(move |ui, command_sender| { - if large_text_button(ui, "Quick start").clicked() { - let entries = if accepts_connections { - QUICK_START_ENTRIES_CONNECT - } else { - QUICK_START_ENTRIES_SPAWN - }; - - if let Err(err) = open_quick_start(command_sender, entries, PLACEHOLDERS) { - re_log::error!("Failed to load quick start: {}", err); - } - } - }), - }, - Panel { - title: "Load recorded data", - body: - "Open and visualize recorded data from previous Rerun sessions (.rrd) as well as \ - data in other formats like .gltf and .jpg. Files can be local or remote.", - image: &re_ui::icons::WELCOME_SCREEN_RECORDED_DATA, - add_buttons: Box::new(|ui, command_sender| { - if large_text_button(ui, "Open file…").clicked() { - command_sender.send_ui(re_ui::UICommand::Open); - } - }), - }, - Panel { - title: "Build your views", - body: "Add and rearrange views. Configure what data is shown and how. Design \ - interactively in the viewer or (coming soon) directly from code in the SDK.", - image: &re_ui::icons::WELCOME_SCREEN_CONFIGURE, - add_buttons: Box::new(|ui, _| { - url_large_text_button(ui, "Learn about views", SPACE_VIEWS_HELP); - }), - }, - ]; - - // Shrink images if needed so user can see all the content buttons - let max_image_height = ui.available_height() - 300.0; - - let panel_count = panels.len(); - - const MAX_COLUMN_WIDTH: f32 = 280.0; - const MIN_COLUMN_WIDTH: f32 = 164.0; - - let grid_spacing = egui::vec2(12.0, 16.0); - - let column_count = (((ui.available_width() + grid_spacing.x) - / (MIN_COLUMN_WIDTH + grid_spacing.x)) - .floor() as usize) - .clamp(1, panels.len()); - - let column_width = ((ui.available_width() + grid_spacing.x) / column_count as f32 - - grid_spacing.x) - .floor() - .at_least(MIN_COLUMN_WIDTH) - .at_most(MAX_COLUMN_WIDTH); - - ui.horizontal(|ui| { - ui.vertical_centered(|ui| { - ui.add(egui::Label::new( - egui::RichText::new("Welcome") + ui.add( + egui::Label::new( + egui::RichText::new("Visualize Multimodal Data") .strong() - .line_height(Some(32.0)) - .text_style(re_ui::ReUi::welcome_screen_h1()), - )) - }); - }); - ui.end_row(); - - ui.horizontal(|ui| { - // this space is added on the left so that the grid is centered - let centering_hspace = (ui.available_width() - - column_count as f32 * column_width - - (column_count - 1) as f32 * grid_spacing.x) - / 2.0; - ui.add_space(centering_hspace.at_least(0.0)); - - ui.vertical(|ui| { - ui.add_space(32.0); - - let grid = egui::Grid::new("welcome_section_grid") - .spacing(grid_spacing) - .min_col_width(column_width) - .max_col_width(column_width); - - grid.show(ui, |ui| { - for panels in panels.chunks(column_count) { - if column_count == panel_count { - for panel in panels { - image_banner(ui, panel.image, column_width, max_image_height); - } - } else { - for _ in panels { - ui.vertical(|ui| { - ui.add_space(20.0); - }); - } - } - - ui.end_row(); - - for panel in panels { - ui.vertical(|ui| { - // don't let the text get too close to the right-hand content - ui.set_max_width(column_width - 8.0); - - ui.label( - egui::RichText::new(panel.title) - .strong() - .text_style(re_ui::ReUi::welcome_screen_h3()), - ); - ui.label(egui::RichText::new(panel.body).line_height(Some(19.0))); - ui.horizontal(|ui| { - ui.spacing_mut().item_spacing.x = 4.0; - (panel.add_buttons)(ui, command_sender); - }); - }); - } + .line_height(Some(line_height)) + .text_style(style), + ) + .wrap(true), + ); - ui.end_row(); - } + ui.add_space(29.0); + + let bullet_text = |ui: &mut Ui, text: &str| { + ui.horizontal(|ui| { + ui.add_space(1.0); + bullet(ui); + ui.add_space(5.0); + ui.add( + egui::Label::new( + egui::RichText::new(text) + .color(ui.visuals().widgets.active.text_color()) + .text_style(re_ui::ReUi::welcome_screen_body()), + ) + .wrap(true), + ); }); - }); - }); -} - -fn image_banner(ui: &mut egui::Ui, icon: &re_ui::Icon, column_width: f32, max_image_height: f32) { - if max_image_height < 96.0 { - return; // skip the image if it is too small - } + ui.add_space(4.0); + }; + + bullet_text(ui, "Log with the Rerun SDK in Python, C++, or Rust"); + bullet_text(ui, "Visualize and explore live or recorded data"); + bullet_text(ui, "Customize in the UI or through code"); + + ui.add_space(9.0); + if ui + .button( + egui::RichText::new("Go to documentation →") + .color(egui::Color32::from_hex("#60A0FF").expect("this color is valid")) + .text_style(re_ui::ReUi::welcome_screen_body()), + ) + .clicked() + { + ui.ctx().open_url(egui::output::OpenUrl { + url: DOCS_URL.to_owned(), + new_tab: true, + }); + } - ui.centered_and_justified(|ui| { - ui.add( - icon.as_image() - .fit_to_exact_size(egui::Vec2::new(column_width, max_image_height)) - .rounding(egui::Rounding::same(8.)), - ); + ui.add_space(83.0); }); } -/// Open a Quick Start recording -/// -/// The markdown content may contain placeholders in the form of `${NAME}`. These will be replaced -/// with the corresponding value from the `placeholder_content` hash map. -fn open_quick_start( - command_sender: &re_viewer_context::CommandSender, - entries: &[QuickStartEntry<'_>], - placeholders: &[Placeholder<'_>], -) -> anyhow::Result<()> { - let mut rows = Vec::with_capacity(entries.len()); - for entry in entries { - let mut markdown = entry.markdown.to_owned(); - for Placeholder { key, value } in placeholders { - markdown = markdown.replace(&format!("${{{key}}}"), value); - } +fn bullet(ui: &mut Ui) { + static DIAMETER: f32 = 6.0; + let (rect, _) = ui.allocate_exact_size(egui::vec2(DIAMETER, DIAMETER), egui::Sense::hover()); - let text_doc = re_types::archetypes::TextDocument::new(markdown) - .with_media_type(re_types::components::MediaType::markdown()); - - let row = DataRow::from_archetype( - RowId::new(), - TimePoint::timeless(), - EntityPath::from(entry.entity_path), - &text_doc, - )?; - rows.push(row); - } - - let store_info = StoreInfo { - application_id: "Quick start".into(), - store_id: StoreId::random(StoreKind::Recording), - is_official_example: true, - started: Time::now(), - store_source: StoreSource::Viewer, - store_kind: StoreKind::Recording, - }; - - let entity_db = EntityDb::from_info_and_rows(store_info, rows)?; - command_sender.send_system(SystemCommand::LoadStoreDb(entity_db)); - - Ok(()) + ui.painter().add(egui::epaint::CircleShape { + center: rect.center(), + radius: DIAMETER / 2.0, + fill: ui.visuals().strong_text_color(), + stroke: egui::Stroke::NONE, + }); } From 88f2156489bac40645c41a5c46d06c98b355c40d Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 27 Mar 2024 20:35:33 +0100 Subject: [PATCH 133/508] Add source URL to example manifest (#5703) ### What - Fixes #5701 - Follow-up to #5699 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5703/index.html) - **LINKS SHOULD WORK _ONLY_ HERE** * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5703/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5703/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5703) - [Docs preview](https://rerun.io/preview/0530608694da108802e9898c85ea22905aadb3c5/docs) - [Examples preview](https://rerun.io/preview/0530608694da108802e9898c85ea22905aadb3c5/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_build_examples/src/manifest.rs | 26 ++++++++++++++++--- crates/re_viewer/src/ui/welcome_screen/mod.rs | 2 +- .../src/ui/welcome_screen/welcome_section.rs | 2 +- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/crates/re_build_examples/src/manifest.rs b/crates/re_build_examples/src/manifest.rs index 61937f40c8f1..4ddd85ce8102 100644 --- a/crates/re_build_examples/src/manifest.rs +++ b/crates/re_build_examples/src/manifest.rs @@ -1,7 +1,8 @@ +use std::path::PathBuf; + use re_build_tools::Environment; use crate::{Channel, Example}; -use std::path::PathBuf; /// Collect examples in the repository and produce a manifest file. /// @@ -36,12 +37,14 @@ impl Manifest { } }; + let base_source_url = get_base_source_url(build_env)?; + let workspace_root = re_build_tools::cargo_metadata()?.workspace_root; let manifest = self .channel .examples(workspace_root)? .into_iter() - .map(|example| ManifestEntry::new(example, &base_url)) + .map(|example| ManifestEntry::new(example, &base_url, &base_source_url)) .collect::>(); if manifest.is_empty() { @@ -62,10 +65,11 @@ struct ManifestEntry { tags: Vec, rrd_url: String, thumbnail: Thumbnail, + source_url: String, } impl ManifestEntry { - fn new(example: Example, base_url: &str) -> Self { + fn new(example: Example, base_url: &str, base_source_url: &str) -> Self { let name = example.name; Self { title: example.title, @@ -77,6 +81,11 @@ impl ManifestEntry { width: example.thumbnail_dimensions[0], height: example.thumbnail_dimensions[1], }, + source_url: format!( + "{base_source_url}/examples/{}/{name}/{}", + example.language.examples_dir().to_string_lossy(), + example.language.entrypoint_path().to_string_lossy() + ), name, } } @@ -124,6 +133,17 @@ fn get_base_url(build_env: Environment) -> anyhow::Result { Ok(format!("https://app.rerun.io/commit/{sha}")) } +fn get_base_source_url(build_env: Environment) -> anyhow::Result { + if build_env == Environment::DeveloperInWorkspace { + // There is a high chance the current commit isn't pushed to the remote, so we use main + // instead. + Ok("https://github.com/rerun-io/rerun/blob/main".to_owned()) + } else { + let commit = re_build_tools::git_commit_short_hash()?; + Ok(format!("https://github.com/rerun-io/rerun/tree/{commit}")) + } +} + fn parse_release_version(branch: &str) -> Option<&str> { // release-\d+.\d+.\d+(-alpha.\d+)? diff --git a/crates/re_viewer/src/ui/welcome_screen/mod.rs b/crates/re_viewer/src/ui/welcome_screen/mod.rs index e1f5b4309f0c..d40f9bfcbc83 100644 --- a/crates/re_viewer/src/ui/welcome_screen/mod.rs +++ b/crates/re_viewer/src/ui/welcome_screen/mod.rs @@ -35,7 +35,7 @@ impl WelcomeScreen { inner_margin: egui::Margin { left: 40.0, right: 40.0, - top: 32.0, + top: 50.0, bottom: 8.0, }, ..Default::default() diff --git a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs index b18c86f2b873..39c111386f60 100644 --- a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs @@ -21,7 +21,7 @@ pub(super) fn welcome_section_ui(ui: &mut egui::Ui) { .wrap(true), ); - ui.add_space(29.0); + ui.add_space(18.0); let bullet_text = |ui: &mut Ui, text: &str| { ui.horizontal(|ui| { From 2ebe6796f98b9356b5840c12c05f602c3a77e5fb Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 27 Mar 2024 21:01:21 +0100 Subject: [PATCH 134/508] Update thumbnails for some in-app examples (#5707) ### What - Closes #5700 - Follow-up to #5699 These were missing an up-to-date thumbnail. image image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5707/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5707/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5707/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5707) - [Docs preview](https://rerun.io/preview/28c1ce40fe0ac71a99c40ec2a0525e3a14405478/docs) - [Examples preview](https://rerun.io/preview/28c1ce40fe0ac71a99c40ec2a0525e3a14405478/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/cpp/dna/README.md | 4 ++-- examples/python/dna/README.md | 4 ++-- examples/python/nuscenes/README.md | 4 ++-- examples/python/open_photogrammetry_format/README.md | 4 ++-- examples/python/rrt-star/README.md | 4 ++-- examples/rust/dna/README.md | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/cpp/dna/README.md b/examples/cpp/dna/README.md index d7d7f44c8efd..6796bcfe5944 100644 --- a/examples/cpp/dna/README.md +++ b/examples/cpp/dna/README.md @@ -2,8 +2,8 @@ title = "Helix" tags = ["3D", "api-example"] description = "Simple example of logging point and line primitives to draw a 3D helix." -thumbnail = "https://static.rerun.io/helix/f4c375546fa9d24f7cd3a1a715ebf75b2978817a/480w.png" -thumbnail_dimensions = [480, 285] +thumbnail = "https://static.rerun.io/dna/40d9744af3f0e21d3b174054f0a935662a574ce0/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" --> diff --git a/examples/python/dna/README.md b/examples/python/dna/README.md index 011336123732..ea2fcba75c1a 100644 --- a/examples/python/dna/README.md +++ b/examples/python/dna/README.md @@ -2,8 +2,8 @@ title = "Helix" tags = ["3D", "api-example"] description = "Simple example of logging point and line primitives to draw a 3D helix." -thumbnail = "https://static.rerun.io/helix/f4c375546fa9d24f7cd3a1a715ebf75b2978817a/480w.png" -thumbnail_dimensions = [480, 285] +thumbnail = "https://static.rerun.io/dna/40d9744af3f0e21d3b174054f0a935662a574ce0/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" --> diff --git a/examples/python/nuscenes/README.md b/examples/python/nuscenes/README.md index 7c5dd3001552..8f716c101bb3 100644 --- a/examples/python/nuscenes/README.md +++ b/examples/python/nuscenes/README.md @@ -2,8 +2,8 @@ title = "nuScenes" tags = ["lidar", "3D", "2D", "object-detection", "pinhole-camera"] description = "Visualize the nuScenes dataset including lidar, radar, images, and bounding boxes." -thumbnail = "https://static.rerun.io/nuscenes/64a50a9d67cbb69ae872551989ee807b195f6b5d/480w.png" -thumbnail_dimensions = [480, 282] +thumbnail = "https://static.rerun.io/nuscenes/9c50bf5cadb879ef818ac3d35fe75696a9586cb4/480w.png" +thumbnail_dimensions = [480, 480] channel = "release" build_args = ["--seconds=5"] --> diff --git a/examples/python/open_photogrammetry_format/README.md b/examples/python/open_photogrammetry_format/README.md index a679c873f9fc..8ee8f926c22e 100644 --- a/examples/python/open_photogrammetry_format/README.md +++ b/examples/python/open_photogrammetry_format/README.md @@ -2,8 +2,8 @@ title = "Open Photogrammetry Format" tags = ["2D", "3D", "camera", "photogrammetry"] description = "Displays a photogrammetrically reconstructed 3D point cloud loaded from an Open Photogrammetry Format (OPF) file." -thumbnail = "https://static.rerun.io/open_photogrammetry_format/603d5605f9670889bc8bce3365f16b831fce1eb1/480w.png" -thumbnail_dimensions = [480, 310] +thumbnail = "https://static.rerun.io/open-photogrammetry-format/c9bec43a3a3abd725a55ee8eb527a4c0cb01979b/480w.png" +thumbnail_dimensions = [480, 480] channel = "release" build_args = ["--jpeg-quality=50"] --> diff --git a/examples/python/rrt-star/README.md b/examples/python/rrt-star/README.md index 7566a3c664fc..005caff1aa86 100644 --- a/examples/python/rrt-star/README.md +++ b/examples/python/rrt-star/README.md @@ -2,8 +2,8 @@ title = "RRT*" tags = ["2D"] description = "Visualization of the path finding algorithm RRT* in a simple environment." -thumbnail= "https://static.rerun.io/rrt-star/4d4684a24eab7d5def5768b7c1685d8b1cb2c010/full.png" -thumbnail_dimensions = [1496, 840] +thumbnail= "https://static.rerun.io/rrt-star/fbbda33bdbbfa469ec95c905178ac3653920473a/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" --> diff --git a/examples/rust/dna/README.md b/examples/rust/dna/README.md index 27ff4016de24..f9ea1ab4b7e5 100644 --- a/examples/rust/dna/README.md +++ b/examples/rust/dna/README.md @@ -2,8 +2,8 @@ title = "Helix" tags = ["3D", "api-example"] description = "Simple example of logging point and line primitives to draw a 3D helix." -thumbnail = "https://static.rerun.io/helix/f4c375546fa9d24f7cd3a1a715ebf75b2978817a/480w.png" -thumbnail_dimensions = [480, 285] +thumbnail = "https://static.rerun.io/dna/40d9744af3f0e21d3b174054f0a935662a574ce0/480w.png" +thumbnail_dimensions = [480, 480] channel = "main" --> From 52c23785b2c1ee2b599233fc7aa269cb5b7b7cef Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Wed, 27 Mar 2024 18:31:03 -0400 Subject: [PATCH 135/508] New Blueprint.save() API (#5698) ### What - Marked as `do-not-merge` until https://github.com/rerun-io/rerun/pull/5678 has landed I wanted to easily create just a `.rbl` from a script. Which required jumping through a few hoops. Figured I would streamline them. Example script to generate an `.rbl`: ``` import rerun.blueprint as rrb blueprint = rrb.Blueprint( rrb.Spatial3DView(origin="/test1"), rrb.TimePanel(expanded=False), rrb.SelectionPanel(expanded=False), rrb.BlueprintPanel(expanded=False), ) blueprint.save("rerun_example_blueprint_test") ``` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5698/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5698/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5698/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5698) - [Docs preview](https://rerun.io/preview/a89f0190ac343fff89209ec2d4d4a8299c943229/docs) - [Examples preview](https://rerun.io/preview/a89f0190ac343fff89209ec2d4d4a8299c943229/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- rerun_py/rerun_sdk/rerun/blueprint/api.py | 30 +++++++++++++++++++++ rerun_py/src/python_bridge.rs | 33 +++++++++++++++++++++++ tests/python/blueprint/save_blueprint.py | 12 +++++++++ 3 files changed, 75 insertions(+) create mode 100644 tests/python/blueprint/save_blueprint.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index b296107065e2..ec9cf45a4443 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -431,6 +431,36 @@ def _log_to_stream(self, stream: RecordingStream) -> None: if hasattr(self, "time_panel"): self.time_panel._log_to_stream(stream) + def save(self, application_id: str, path: str | None = None) -> None: + """ + Save this blueprint to a file. Rerun recommends the `.rbl` suffix. + + Parameters + ---------- + application_id: + The application ID to use for this blueprint. This must match the application ID used + when initiating rerun for any data logging you wish to associate with this blueprint. + path + The path to save the blueprint to. Defaults to `.rbl`. + + """ + + if path is None: + path = f"{application_id}.rbl" + + blueprint_file = RecordingStream( + bindings.new_blueprint( + application_id=application_id, + make_default=False, + make_thread_default=False, + default_enabled=True, + ) + ) + blueprint_file.set_time_sequence("blueprint", 0) # type: ignore[attr-defined] + self._log_to_stream(blueprint_file) + + bindings.save_blueprint(path, blueprint_file.to_native()) + BlueprintLike = Union[Blueprint, SpaceView, Container] """ diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index 52a0e3cdf265..c9b07c32eedb 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -164,6 +164,7 @@ fn rerun_bindings(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(is_enabled, m)?)?; m.add_function(wrap_pyfunction!(connect, m)?)?; m.add_function(wrap_pyfunction!(save, m)?)?; + m.add_function(wrap_pyfunction!(save_blueprint, m)?)?; m.add_function(wrap_pyfunction!(stdout, m)?)?; m.add_function(wrap_pyfunction!(memory_recording, m)?)?; m.add_function(wrap_pyfunction!(serve, m)?)?; @@ -624,6 +625,38 @@ fn save( }) } +#[pyfunction] +#[pyo3(signature = (path, blueprint_stream))] +/// Special binding for directly savings a blueprint stream to a file. +fn save_blueprint( + path: &str, + blueprint_stream: &PyRecordingStream, + py: Python<'_>, +) -> PyResult<()> { + if let Some(recording_id) = (*blueprint_stream).store_info().map(|info| info.store_id) { + // The call to save, needs to flush. + // Release the GIL in case any flushing behavior needs to cleanup a python object. + py.allow_threads(|| { + // Flush all the pending blueprint messages before we include the Ready message + blueprint_stream.flush_blocking(); + + let activation_cmd = BlueprintActivationCommand::make_active(recording_id.clone()); + + blueprint_stream.record_msg(activation_cmd.into()); + + let res = blueprint_stream + .save_opts(path) + .map_err(|err| PyRuntimeError::new_err(err.to_string())); + flush_garbage_queue(); + res + }) + } else { + Err(PyRuntimeError::new_err( + "Blueprint stream has no store info".to_owned(), + )) + } +} + #[pyfunction] #[pyo3(signature = (default_blueprint = None, recording = None))] fn stdout( diff --git a/tests/python/blueprint/save_blueprint.py b/tests/python/blueprint/save_blueprint.py new file mode 100644 index 000000000000..bb64a3df5614 --- /dev/null +++ b/tests/python/blueprint/save_blueprint.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +import rerun.blueprint as rrb + +blueprint = rrb.Blueprint( + rrb.Spatial3DView(origin="/test1"), + rrb.TimePanel(expanded=False), + rrb.SelectionPanel(expanded=False), + rrb.BlueprintPanel(expanded=False), +) + +blueprint.save("rerun_example_blueprint_test") From d6ba480efc66c0a6874f6cf288dd83e996a4e667 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 28 Mar 2024 08:06:12 +0100 Subject: [PATCH 136/508] Authenticate to docker hub in CI (#5714) ### What We are getting rate-limited on our BuildJet runner: ![image](https://github.com/rerun-io/rerun/assets/49431240/221d69af-72cd-49e4-a7d2-bc753c6c0f1a) The [documented workaround](https://buildjet.com/for-github-actions/docs/getting-started/troubleshooting#docker-rate-limiting-and-authentication) is to authenticate to docker hub. This PR does that using newly generate secrets. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5714/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5714/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5714/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5714) - [Docs preview](https://rerun.io/preview/2849c9a78b1520a6cd316573f56bc2a96167fb70/docs) - [Examples preview](https://rerun.io/preview/2849c9a78b1520a6cd316573f56bc2a96167fb70/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../workflows/reusable_build_and_upload_rerun_c.yml | 10 +++++++--- .../workflows/reusable_build_and_upload_rerun_cli.yml | 10 +++++++--- .github/workflows/reusable_build_and_upload_wheels.yml | 10 +++++++--- .github/workflows/reusable_test_wheels.yml | 10 +++++++--- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml index 04b2403ddd7e..79a1958a806d 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_c.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml @@ -76,13 +76,13 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.12.0'}" + container="'rerunio/ci_docker:0.12.0'" lib_name="librerun_c.a" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.12.0'}" + container="'rerunio/ci_docker:0.12.0'" lib_name="librerun_c.a" ;; windows-x64) @@ -116,7 +116,11 @@ jobs: needs: [set-config] runs-on: ${{ needs.set-config.outputs.RUNNER }} - container: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + container: + image: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + credentials: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} steps: - name: Show context diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index 79267dfd46cf..975405c3bcbc 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -77,13 +77,13 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.12.0'}" + container="'rerunio/ci_docker:0.12.0'" bin_name="rerun" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.12.0'}" + container="'rerunio/ci_docker:0.12.0'" bin_name="rerun" ;; windows-x64) @@ -117,7 +117,11 @@ jobs: needs: [set-config] runs-on: ${{ needs.set-config.outputs.RUNNER }} - container: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + container: + image: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + credentials: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} steps: - name: Show context diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index f5dee2423b65..b112dba1b864 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -101,14 +101,14 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.12.0'}" + container="'rerunio/ci_docker:0.12.0'" compat="manylinux_2_31" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" compat="manylinux_2_31" - container="{'image': 'rerunio/ci_docker:0.12.0'}" + container="'rerunio/ci_docker:0.12.0'" ;; windows-x64) runner="windows-latest-8-cores" @@ -143,7 +143,11 @@ jobs: needs: [set-config] runs-on: ${{ needs.set-config.outputs.RUNNER }} - container: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + container: + image: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + credentials: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} steps: - name: Show context diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 8c1cc08b4292..0a16a5fb7733 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -62,12 +62,12 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.12.0'}" + container="'rerunio/ci_docker:0.12.0'" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="{'image': 'rerunio/ci_docker:0.12.0'}" + container="'rerunio/ci_docker:0.12.0'" ;; windows-x64) runner="windows-latest-8-cores" @@ -98,7 +98,11 @@ jobs: needs: [set-config] runs-on: ${{ needs.set-config.outputs.RUNNER }} - container: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + container: + image: ${{ fromJson(needs.set-config.outputs.CONTAINER) }} + credentials: + username: ${{ secrets.DOCKER_HUB_USER }} + password: ${{ secrets.DOCKER_HUB_TOKEN }} steps: - name: Show context From f5a5a11009f26ed350b39078d99ccebe19814853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Thu, 28 Mar 2024 10:34:58 +0100 Subject: [PATCH 137/508] Document frontmatter attributes (#5716) ### What The list is growing and we didn't clearly document all the available attributes anywhere. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/README.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 700af1ce313b..ae85044a25f4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,9 +16,10 @@ The entry point to the documentation is [`/content/index.md`](./content/index.md ## Special syntax -### Title and Navigation Order -The display titles navigation order of documentation sections are managed by the Metadata at the top of the Markdown -file: +### Frontmatter + +YAML frontmatter at the top of the Markdown file is used for metadata: + ``` --- title: Examples @@ -26,6 +27,14 @@ order: 6 --- ``` +The available attributes are: +| name | type | required | description | +| -------- | ------- | -------- | --------------------------------------------- | +| title | string | yes | title displayes in the navigation | +| order | number | yes | used to sort navigation items | +| redirect | string | no | redirect to the given url | +| hidden | boolean | no | don't show the item in navigation | +| expand | boolean | no | expand the sub-items in navigation by default | ### Snippets From 46e4b7b1e80fa70dd9de9d412731b45a7f389ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Thu, 28 Mar 2024 10:41:07 +0100 Subject: [PATCH 138/508] Fix docs typo (#5717) ### What - Fix typo introduced in https://github.com/rerun-io/rerun/pull/5716 Note to self: [Should've wasted CI time on this](https://github.com/rerun-io/rerun/pull/5716#issuecomment-2024770178) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5717/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5717/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5717/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5717) - [Docs preview](https://rerun.io/preview/5c8bad58e9c98687c13452433ba3ae457f9b56e8/docs) - [Examples preview](https://rerun.io/preview/5c8bad58e9c98687c13452433ba3ae457f9b56e8/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index ae85044a25f4..ce54993d0201 100644 --- a/docs/README.md +++ b/docs/README.md @@ -30,7 +30,7 @@ order: 6 The available attributes are: | name | type | required | description | | -------- | ------- | -------- | --------------------------------------------- | -| title | string | yes | title displayes in the navigation | +| title | string | yes | navigation item title | | order | number | yes | used to sort navigation items | | redirect | string | no | redirect to the given url | | hidden | boolean | no | don't show the item in navigation | From 34e3feccf4337cff31dea656e35907382e7a65eb Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 28 Mar 2024 11:10:20 +0100 Subject: [PATCH 139/508] Add icons for Blueprint and Data Source (#5713) ### What * Closes https://github.com/rerun-io/rerun/issues/5658 Screenshot 2024-03-27 at 18 25 36 Some other alternatives Screenshot 2024-03-27 at 18 24 38 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5713/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5713/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5713/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5713) - [Docs preview](https://rerun.io/preview/3f2020baff6c736d0c7684053a5346ae4f2ef99e/docs) - [Examples preview](https://rerun.io/preview/3f2020baff6c736d0c7684053a5346ae4f2ef99e/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/item_ui.rs | 93 +++++++++++---------- crates/re_ui/data/icons/blueprint.png | Bin 0 -> 432 bytes crates/re_ui/data/icons/data_source.png | Bin 0 -> 438 bytes crates/re_ui/data/icons/recording.png | Bin 0 -> 12031 bytes crates/re_ui/data/icons/store.png | Bin 11784 -> 0 bytes crates/re_ui/src/icons.rs | 8 +- crates/re_viewer/src/ui/selection_panel.rs | 12 ++- 7 files changed, 63 insertions(+), 50 deletions(-) create mode 100644 crates/re_ui/data/icons/blueprint.png create mode 100644 crates/re_ui/data/icons/data_source.png create mode 100644 crates/re_ui/data/icons/recording.png delete mode 100644 crates/re_ui/data/icons/store.png diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 6f000badc683..87950372314c 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -4,7 +4,7 @@ use re_entity_db::{EntityTree, InstancePath}; use re_log_types::{ComponentPath, EntityPath, TimeInt, Timeline}; -use re_ui::SyntaxHighlighting; +use re_ui::{icons, SyntaxHighlighting}; use re_viewer_context::{HoverHighlight, Item, SpaceViewId, UiVerbosity, ViewerContext}; use super::DataUi; @@ -139,20 +139,20 @@ pub fn instance_path_icon( timeline: &re_data_store::Timeline, store: &re_data_store::DataStore, instance_path: &InstancePath, -) -> &'static re_ui::icons::Icon { +) -> &'static icons::Icon { if instance_path.is_splat() { // It is an entity path if store .all_components(timeline, &instance_path.entity_path) .is_some() { - &re_ui::icons::ENTITY + &icons::ENTITY } else { - &re_ui::icons::ENTITY_EMPTY + &icons::ENTITY_EMPTY } } else { // An instance path - &re_ui::icons::ENTITY + &icons::ENTITY } } @@ -184,7 +184,7 @@ pub fn guess_query_and_store_for_selected_entity<'a>( pub fn guess_instance_path_icon( ctx: &ViewerContext<'_>, instance_path: &InstancePath, -) -> &'static re_ui::icons::Icon { +) -> &'static icons::Icon { let (query, store) = guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); instance_path_icon(&query.timeline, store, instance_path) } @@ -401,7 +401,7 @@ pub fn component_path_button_to( let item = Item::ComponentPath(component_path.clone()); let response = ctx.re_ui.selectable_label_with_icon( ui, - &re_ui::icons::COMPONENT, + &icons::COMPONENT, text, ctx.selection().contains_item(&item), re_ui::LabelStyle::Normal, @@ -558,11 +558,12 @@ pub fn data_source_button_ui( ) -> egui::Response { let item = Item::DataSource(data_source.clone()); - // TODO(#5645): an icon for data sources - - let response = ui.selectable_label( - ctx.selection().contains_item(&item), + let response = ctx.re_ui.selectable_label_with_icon( + ui, + &icons::DATA_SOURCE, data_source.to_string(), + ctx.selection().contains_item(&item), + re_ui::LabelStyle::Normal, ); let response = response.on_hover_ui(|ui| { @@ -612,40 +613,42 @@ pub fn entity_db_button_ui( let store_id = entity_db.store_id().clone(); let item = re_viewer_context::Item::StoreId(store_id.clone()); - let mut list_item = ctx - .re_ui - .list_item(title) - .selected(ctx.selection().contains_item(&item)) - .with_icon_fn(|_re_ui, ui, rect, visuals| { - // Color icon based on whether this is the active recording or not: - let color = if ctx.store_context.is_active(&store_id) { - visuals.fg_stroke.color - } else { - ui.visuals().widgets.noninteractive.fg_stroke.color - }; - re_ui::icons::STORE - .as_image() - .tint(color) - .paint_at(ui, rect); - }) - .with_buttons(|re_ui, ui| { - // Close-button: - let resp = re_ui - .small_icon_button(ui, &re_ui::icons::REMOVE) - .on_hover_text(match store_id.kind { - re_log_types::StoreKind::Recording => { - "Close this recording (unsaved data will be lost)" - } - re_log_types::StoreKind::Blueprint => { - "Close this blueprint (unsaved data will be lost)" - } - }); - if resp.clicked() { - ctx.command_sender - .send_system(SystemCommand::CloseStore(store_id.clone())); - } - resp - }); + let icon = match entity_db.store_kind() { + re_log_types::StoreKind::Recording => &icons::RECORDING, + re_log_types::StoreKind::Blueprint => &icons::BLUEPRINT, + }; + + let mut list_item = + ctx.re_ui + .list_item(title) + .selected(ctx.selection().contains_item(&item)) + .with_icon_fn(|_re_ui, ui, rect, visuals| { + // Color icon based on whether this is the active recording or not: + let color = if ctx.store_context.is_active(&store_id) { + visuals.fg_stroke.color + } else { + ui.visuals().widgets.noninteractive.fg_stroke.color + }; + icon.as_image().tint(color).paint_at(ui, rect); + }) + .with_buttons(|re_ui, ui| { + // Close-button: + let resp = re_ui.small_icon_button(ui, &icons::REMOVE).on_hover_text( + match store_id.kind { + re_log_types::StoreKind::Recording => { + "Close this recording (unsaved data will be lost)" + } + re_log_types::StoreKind::Blueprint => { + "Close this blueprint (unsaved data will be lost)" + } + }, + ); + if resp.clicked() { + ctx.command_sender + .send_system(SystemCommand::CloseStore(store_id.clone())); + } + resp + }); if ctx.hovered().contains_item(&item) { list_item = list_item.force_hovered(true); diff --git a/crates/re_ui/data/icons/blueprint.png b/crates/re_ui/data/icons/blueprint.png new file mode 100644 index 0000000000000000000000000000000000000000..c6c0da9b9139b27a154ee115bdef6d06b0b5e9de GIT binary patch literal 432 zcmV;h0Z;ykP)ZT>X43VOI($hJ2 zfbqk=nBBQKoO1!U%UouIO3aji84>kdp>|M@nZwb99MkgD|S5R-mk%>-vq1M|( zj7`dhvA3D+tre%=z3f8Tv9$IRN2bH?99pTK`%cB2-`&A|ew<5df1ibC-nT(spfv2ST7O->HMGb+g`cXU6Lp}ma_w!Uel3mfe1_-@LvR>*;!cSQL{V?Kks zpR0Qa>ipw)`n6I!;~EXWL}(SGGj?QXNh3vv-<02lJ8gSb`+!R1EfNdG-h17;d8qBq aP4W$P0_%OgLE!EH0000LFYK$1a|Vv+M{-~jGSg30A*t)03E)`&J-e4%aO3lZH=^l^7VvUCGq zY!l6U6ThKFeyk{etc^(nFIZykf;q7wL9?>|^h-IhQbEBT@`6RBt@OvAW!9lh^%;e* z+EcFqJ=>GnfVcHA;&8D}VlmwL?@*L%zg!6OSkzq9(#gN4{G0 g`f2{Z%$*Fr0Ew`m>*#P`F#rGn07*qoM6N<$f`=!vivR!s literal 0 HcmV?d00001 diff --git a/crates/re_ui/data/icons/recording.png b/crates/re_ui/data/icons/recording.png new file mode 100644 index 0000000000000000000000000000000000000000..b00edcd39758a3e7daee8835cc8a67c700bdf137 GIT binary patch literal 12031 zcmeHsXIN9))^6ws(xr-YkYXT^&>{5Rdl7*U5_${0H${5y9YN`!Q~?1CNKvYE=~X(2 zbb%Y)`|Pv#bH6|5x%c~blFVeSImdYCc;7kJ$Xd^g($-WWBA_Dx002ZP%JRDCU;1AS z9~b?NB3eiV0BAve`oxy7P_}C!<0H2xXISyVcBCbzv;FKnq zhq&qC8=})P=>_{?sg5mkDe9w=PJJv2VPzGUoR*(2YHw!OrOr}RxjDMbbTu}YwaSWG zKjxt3f@jX{YF&foJ7YI8uYS(HArXOoe{*p;nVf%QQSkK?XD{Pp+u5${T1(pDp`6cTQ&raw(~6>(6&LB91mbEZ0{$`*ibttDWP$+$!ahcguZ=w?7Ymwb67;w?13#x?v|eZo-Q^ z@9(^JxZb5cG2}A#Pdhc^=iPuz-*G!wuAe_`4p_R-YruS1%x1lSup{c?I?gwJ#@ypcE_wKJ?a5=8NUZXuP2Ko+#^M% zbuo}dNT0lUoo6~loUskLke1$EA%=S$;v3cl~q{>tEdbGc?s&$5Ayh&Jm=k=Gt zww>0m;`Um`H)of8&yWRWEfidNnF~5AUve!nUWTQVWs-qx!q}Hhn3;<5th^}ihUu-| zsjn2PU=hQmrL4E3hbj-2Sm>5nNhXN5 zicXs@DYw^0;lc;@8-m}3o`if}R$SoG!t*=H`-!{chmmb%reKlvYS)*4+bVret5k|~0+9$MCSmC2WPIySr}PO4+hH<77T2xEHu_P2?)MziAWpj_J?>09RTX!L z3|^Bt{NX?(Wt8(yH{qU;<3No_&A^)^PNxBAo7*eBpp&f-Os)cam^$L=Sgk-`Z$o)U z(gsu%?h9Q2`X+~YGJj}(V!eyVHa6XoR;}$13o6GIW4i6EoYzhWjTeFYorxvmOrX^V^Vd52~Ds-oH|6SCX}UTM)GT&`9Ey#6oqwS*50)nhLDEt^0KYLJl35knq~^9Vd*%XFo*Lr!I6O!*8w}j+;Nx5_@RX zu%?tvH5kJ4e?m25TuF^(QF>w*qbZ~A>8G=QPBK89q>p8SE2i9%O z7g0Dxz%!IVV%E?*e2!}Ji9A^qfH`XsZ|%=8CO*}~F?W!Jh=sO+T;qz|U8DHwSZ$-s z{Q6AJIV~{5)A2|xWhZe1J81D0^qU85CTm;D{lw9d!5*(t+3l9Jb)JwD^=@0m%-8R; zlI$qXyCm_W8n3>QvcY&O&HlQr*TNi-uJ88=nc6*F($iZ#DA+=IOSWpI zDtyL~HC#d{UXqza`W{p9RMQ5iDuykO^7X;ggY$688AHM1?DB?NI;Zk=E@Q+jQOgwv z@65_MKgvZstJ%hp4wNNUETJm%&G=-NYS81&t}?4CVV1YTvd{$$%geRIC8YQu!_XzQvDEg3cM8NRlU~2FP|S=>9IL zeb57Yl354=GOAo9$TO0xd_qn2_J@L}581z|gi4I|>CVroRVRA~M6$8nd+o}n_{^cl zK{r=_h>Xsy$VWJH=^})dLtlwGrSQ;@qoo+?)ut*ZRY+j3pvt1yS7q1>5nn8q4YVj0 zl-&Bv*_a9OQpi(XOVzFg^+g%n3p-Yw4tqE#xN~9kxa+Z6qV7eU1af&oqx+|D4Mm^V z)tAci0!@)x%8>FjU++kU{R)nFvO~7Jbedok1Bbq)0pe*z|Wl1yT3W|Li;wS}NY6@I6< z5Jx;2>>p{M{e+E~_(7(1KVT-bh(`vK=vBIQwpKx}lRD#t2o;ZPW}V5SP$IIr zEbF>rW$CJ1or zDOy0Da)y*DP$ts44b=2fxU*JnK!QEZ#-f#<9RqxG;8QS{U2x>79Ur5Wb>IF87h(PaKbBIzMMYlE4S4 zDg_FI>kDgckJmsZINh~WW`2J164I+9Yy|Id@}HPhJdn$sN`G_)O@cG%RQtBP{(c}{ zQ0e~3!Ip!$viPS;q@yKE39prpoNXfEmdVivCw|&{&mwLwT8@0;rf6#!@l`ueZN+HV z{FwD!VkR^j&lWO8J?3hu&fyxz&TnRx`;vk5_KsQe%O(dFl*5F2dIb3hLt%iiFbIbe*@gXCOnNqFL7bZ4 zY(A!ZYaw+Y`Jzu(s-jWpXD`_`Z*U~>`z7m!JHu)>4NRVRl}xY~)6rz~0lOJLcBezF zfG6q_=MfKaGIfbriYq^)79I2r0UF|*%SRoxs;3oaqr^&UrUu97BZ|PA`1p>YAKPRk zndAm{V!v!b?9PKcDV%||2@&z&XN!^uZo&r7{sNoSA)fs0JhCK<)NJS0AW;RIuFe2x z?T7tq^!=w@I|)>{T6M~pUcezySH2L76Fj()PBf$kNQ~#e1t7sC={+0o8^v@S~!S3f}fvBr4CJI_9bm`j16 zdg;I?rb})m8O&1gOZQ2&@k?{gnxhbhRp=~ zT4mefwqfFhdUnM;|0jGA>)eYBvZo_hqL>NhXCyA#a|U}1YfM#L#uhA}jVoWYR_?F< z{2gl8=5c>QpgA)STJ@ZW9uHij#Of!DJEN3J|yRR>bIl!pl@YS}8LaeBN ze3pCSRC>>|_Sxy8hxf&#y#wEUDJmKH&Tqp_cl%yd7Vn*hZSB{acH@lD#XgJE)!NP+ zoV|&$MD0zVnKJ*(OAb7&qwvtyq^qyJ%OR=Z5Z~?nHdhk&ZLhg!(B{*Px04%6g9Q&+ zX9 zRsB@VZ9NuDqn>L_hBaS4RKR4bJl%P6S+nL zuf3^cCEX6vF>CO1>P;W&NZWsR4i?LrmY@?%a?_o~F_T^ZO%eij$zkU&q2U3M-SDW+_` z(%2F8a8;Li^rD$~OklAZ`}ukl<{hDMza0EeSbOgsA5WCq)d(w(PefG68*ss|mZB9|f`fegq^fhPJ#XiOT^ z;TFnUrIB53U3Gryl(ij#9R1Kl*X@?UX2$5vaC|?3%Ge_5@C%o?#;qsb#*V=T{cZl+ zU8k6OWm(avpjqSHS^ZBiGYh6YBaD)B^>18*-8(w^hHhTb zI-V3PTpq`>i;0g1FqA4Cw8zlDjLX0veC5tbj zmjX?TSuI9pnu_Fw=@We}P(|}f{-tb$^@)Ih2o?beZ}(dpyolmfs8Gk9m!`T(SPPhE zG2uATVuX~iYn18mbyg;bL!ElvZD<;wWspjEg&Cw(#N^pRek*YuvIjZp%}TzDEh<*P^>DiEd>KzJxkOfyvpTGIzB3!rVR-KH)ZcuY8y_T$aX&d zH07yK3bzT-(igwowHoHtnAjNUOs&~@J6PUJ4t}qla`cHl2iIItgc?sIF5T16iOPo! z#g+$41lz=T&lUK07%RHI|?8 z3+}y6G%t~4!e)!kDP+DzJ_1RYD$k7a`+I|D+}^B~O^BZ4=D4-)AEqilFx8f`Kg3=# zr*DSaG{DpI4oV-&Hi}&LrCjJ>niJ759kg+9>3vyylhy(Z84 zdiUz~I(~{r@-5{cFHnH^(zcIpM9}^dA1ABVU~!vpSX1f7Wp?zCQhBfc@p33C1KDqC zOqgkhE!R0dLHb|-`69YDX%mNa5a%9OWjE_GHy0IKzYlcRzN_4}fT-pvc~|VagR>T| ziO`nBrxHmfCD=F>nrAu^Jq8+FGpvRqs*7_CT8USPS z(5P{J|0-Dn@kF!stfb`V!s7I7IdLo_#+`L3rnq;bV??$Ah9UylTTK!QyY#4NCGojV zDa7WNWB+o`5$~XE?B+LVokqM;(H%Eln(3y4>+Bgrc_dA$V;?eK0hujcgO85rX{S#^ z^)f!a5h7Zxng_1r4Rq{R&2N4cnwl)y031#fwYjSu3#;?kNiKXOZu9;T(BWTr#5Hhq znBb;`$2tX;IO6Yk*w}cmyIpEF!MLJ%+2dAU(6YCXH{ze~uu(AaZLu#k*e?Qu!!Z{mc}OB;5{CnuX)3w!$2F(zZQ0~Xsb5nB#iF*}_;SvT0pus>1J z`{;W+tZZyy;{txNub8`(TDav`5S+d(~YO+pF)G$LdomIuRc;6@R<4(~;7PenAJ3X@ z$XIpSQCZ;d;`fQ~d>8n^3(@4LLX=Y845hf{qfV-cHjPNPgZ&CurN%92S;`DsqQEhw zl2(L{0PrZw_3p&;_D5_mQB3k0s|K2~RUjZF)~oci_cYIohEv(#9=-c{3C?|#)|F4` zHA6y4M8zF~Yxcw}6>&~Zmd0}Urmd$F$8eaLh%@E`p-JBdi2x4_A$YKp#uoWbXqTKN ztd@II^Ga(&p?TKcj+p{z#gDs^{gH9JoMfwuwRBb&P+Tt`R$aRmeeGx*;P={!)H@rw z)s3>!OTpn9?=+Ls;S-(n|1@JVc6K44?mH?5-8ggE$h<6hkKko{YfNp9jUg5f)v>U8 zuE?CMIt;a4-EB>iQ!ccqbr523*O24I4k#37Q0%9V@sw|w5q)*=Gjo6=cvMYg%o10q zU*6aKcs$V|4LjU!zbhC5RivrJ3S@mU*z|G|Wt_Ak(O$ldSj*s0$m{spni;n|hHDBK zI-e0+KBnd?%%h;;1WGMMlZ$Z1<|bp?Q`%l;bxSXM?mnrgP79mDQld#X-YHR(ysNtp zEYrssi^3|g=AnJBb9I9m{-sGrjbBtFt}M7f!O5xXbmp?n=x40iPY3k@T|rgPulu1_ zM_re_?eD7ken@W0*1X?y)?tB~2(t1zN$ap)SD;eOyGJEnVeWH_#utq>RTa$+tlpV= zdPlCAdVN9>+~DNbhEhHB69YE}Z!7sY$tufeIIZIqOPEedW?YxzRgj7pWAONyLh#K6 zD(%1twJ)jaq_;_+SQ}g#ocGQqp_g=n7qY4Q%+?QaCUmUlK}^Pt+rd7CGb_{g&yiml zUyPm8XOH=~_#|l_V#Un{4rYIzW@>0i^3P*2%TpJ>6gX*5LgnHxvJbWMEt&VHdnJ>P z2yv8W!{QHI`DENJ2PFIKiDVCvd(e=V}z#`GCxH8T4RBR3XMrkfQLySNmi@}ApiM;wqNsbXzu z|G2VKb0f)qrZ9-A44QD+Fitmv1U`hte#<+#Fioazvb*Hj3KnSgFcG{VQtYe0C(K{B z0RUh;wv&_7R*{qY*WL+w$0Ro}NmBWPG<~;)-g9osr(UGHiA7>2q?B%B+;@s(%P37f zK`lQBvmtC;yzyZU@7^VJSA@sZ*AUl)F`Z#7?<|&lV`0CpJSAygCtjGf zixq;`$H^7F*98DbNcp(J;0_26CM$%EowFp%ep@FClby9Bi;ufD^(4#^mGV=9>i8gCvWwhBlL& z3ktym;f3&mfC@f#UIHvo0wxKRHBwAhUhz)|^qC}!t%rxJ7$2Xvw>PghnAZhm!^bZw zD#`~E;1du4qAh^#zRn&nAE2{4>o15uFys;LaFm^^hnC$yHIwqwEJJU|FHfS_us~7D-8`Xc^A0nukcjlC0TyWFJ|omx3d=e zeJH{&0tfR8TLXoJ1Vw=mQG^f>W(@|T|GET)kRk{W7;Gi{Hz*ZncMq5|9PtYZ4bE$a z#u2cxg78}*;XrFqkN^-O3-M1WRsK`Wq$02pK~h!BAbfDpf-tl?scE+{7$dO7W!U^WOo zS7)2w1HS|plhIa@WD(#6{kuoo5$1tJJ4mu$FT^hb zhKPuQ(8r?xHZnw@+|jA{3zQ$k3;qN6*Sd(I*`Sq${Yq3cz;6#U88JB&0_Nd@(syxj zlw|o86Vorx-}%iX@yDtt+qt7He1E0L&}+V77cxGl`t27$i7|IDa=_1paqs|5ptAVM%92oNp=w*o>SU{RozwY4?S3W*dD zg;;}-){sAF{DtoBg7ol)p%5}QXr^d3=nVSJhKchJExG;~jJGY~mrx)92oS^%T7L5DVY`K1U=!49Sl~3IfrYDFlQFLBK!}5n&h*hCspv_z_@!h%n@z zLH|E+1Oo*`^!Y(zU;!}!k$-ZO;QLj({k!W9TRm^|Lz}PGH)Zq#AFh>}l04w%*SoO2GzHyr%T?LL9RMJt_|-4~*|{|6PCO44 z4F$Y!SoF7;=-1AcX8-`41{HZ3edV6CbQebhn|nP{o$mWi&zqkEbF9T=hdrNrOpI1X zf|^FtV)ad5xbbksTn#IONDqnty%Ol8bfDE4T@6U(HSp5CO5g1;nxE z(QIH+^DAn{@pIny?dVv{Uq>0uuKBv>yXPNW1{NG$UUw`UNslOV=o$J1e_u`9xC}y& zViU=bI(iIxifuHZKiHvPX|UhXEesjvNr+mff~xR)8GI~T=^*rq7TVpo*S&UA6Io*>!+kdAP|+IjnZvdfwwYKe_X~;OP%RGnzNZx z0j+?9&ix9s`%X;E9*5QVwyfk)U|R#LcW}2Q zQc_d*{Kboz>}@J3gn5wBC`q~hSI=}G`_L%Xp_W<+lE<&yK_RxEfo`$n{)_Mxzeb)%G_W}d-8R1 zaF9we-{!NDtHBnRiw=vl4cGRPK1qLKI_V#2MkfzLCB`Pbe{vkyEFSmwizG-+=+Z{{ z@C@vv_y!uTD-@(a2-Q_uw{q`F1^S&`{P>~n7Ho;cmH|k6Yz*2Q|2+DNu@%xGVZ*&> zEtF)-2sB_}-YDW7*kOKa_3E3`TUS=(iIt7b*JH4aqF;7S4pmq*`79-y8AGT~?K!Ixa+%ksh>~y0nr;roRcRY= z?CA)st?}7wap5#2brs3UyYYNLH3vg3#C2QoxlGsjV$&phFl1swu?3P*NGhC)khQm^ z1CD~j1P~0?Wa3p+i)50rbzIhN?^;+wz|vr`lKl$X^`*3V+qbV~gW2+qIC>99Z z%Ds#)xtq+<)p6;Dppen|*xj)$QNQM*=8yDyQJkvvjk%8ejjLBz8^prwn zgFSC(i2AcQ-4>RQR9?r4m6OxJ7vxD**43Mi4(Au>#>psgOMNYYZix)e@tk>XolQDF}}_%La{{i>$M=1yMD5w({D#DfDsjPZ1$)&&^TvjRj05IYLK z9Qka2^oR}vbCD`B9l~`ebnt#Q_og{ClwulWV`Gzp;o&J+{GRVK#vvx`>*8Yhx%{&$ zY*(vSb?GzOgDnJ>K}Coo)AP72Ph6P;5AJa(gKylYGv!ZMa|R51tX?&T=pj#vao!T$ z?O5zyp==9%T(W>G^YW(sG+u-HT0s?qglA;p#K!;I^CtX`y zmzUMod-UdmQaoFNv{0XXh1$m2uvk7?Z=9KMKFs*8%p>q*8>gX4*iM+^u<{$C@A=8U?)iXNtQy0 s^r(i4Ue@QG@uj5^Gjws8inw50kFj?-z#q&-mvn%Nf~I_ptYz5$0RSCD^Z)<= literal 0 HcmV?d00001 diff --git a/crates/re_ui/data/icons/store.png b/crates/re_ui/data/icons/store.png deleted file mode 100644 index 65f940e66efe5dc099d801c667ee945c5303906f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11784 zcmeIYWmKEZ7B(EDXo0r46n6*&f(9*4ad!zJxVw`AZ7EJE?p9n{ic6t*f#Rh=ffOxL z-1SZSJjd4e{yA%X@4u6*JGp0O?`!XU&7R3UGkK+{u1J7Kg$Dot2$YrNv{BzQzb_mt z)Tal*(i;GPk~cut&`TTYOYi34YGdyNr}y%AgVV$P>}>!5zq#T}N1qiDx94{-QX}*O ztd#H#(b*>{xqD%6oSGMsR3~y8rWobJO3SaGaKRJ_93HTBk?6O4OWI?sJ+=!pNA=3~_Tl%9p z+z4)=2o6DfP9IRWao5Ks!tKh`kJHqtY z%tWGg&moi0gZV34fO%;6L9B4f5@fh3_($;ZMUZ)JB8cJR$mA8#MtW8L3k!|Q$j?{V zH#eR~VB;={l5@JGti_s-AudkW5}dYM9~VU5Y-C?uw=tXSJ-kT^zF7!N3C>9`v18zy z-t;e>Da`WCnrVLSVs>9v#bDia_0h$(ZU~-{MC4ps-}D7#gR!D`1A)(+O{3X{_qVPG z;U<0XMG@gFDLS%TGw&5S{-6CWslg{nb`UA`Z{fas@4k7?2M~Df>Ng#I$lBs2uM1kU zxJwJYdfu*w_tkt&!XRcyR86Q`bM-iLGBR>uw5Si#qoKoogyBb#jJS$WQ?+U2KQHSf0^GIi${cWPJE#rEEB zyX=)pKyOwyEaXNcwLIChA$%VT`$|MV@<8vgY4I^xe!*1fsgseG5$oOI6v8YS;IJ|9 z)|L0V&(CQy$!R4A;@)0vsQE_etEiiJ71}$py8lr4EHpMt>*ppEHw#QapO8sTa8vfPO3Aig)p7CyJ&LrIkEdk! zoX@zvjuiL1Ag8}Lt~%qPrT4~m7~~Kh?}%Lxd^$lF=xvJX;D^m0S(R_(c$bupUY9G^ z(2*O1adgs`+s|!1x1-$AB~=D8$Wv*-{Je6tU>*Z2O$uOy%6T_BgYbUHg|2a&)mJLr z?F}^o6)-d~&Hkj6^P@+S9HloaZCCu}+19V+5Z03xKcw=$M}Z5v+j~>?$v7HpVw?fp zW$OHOflTj9PW!G^3(Qa;Yj@4~NP0$@t=Y?nB03Svr6adB3E#%R1Aq!mc)@4P%Pn); zsmFLTi|Z$AKejVeC~G(=_bHU)Vg_PG8L9nFThg8iGms4Cu0_L**`v_au{>E{SnSQv zRMIjubcuhHR=`qnHZR~Z(MO_vUXy6%r%o2Mt(I+BnAuUvUvd zl~_2QH_zQq3D~KHI{NgwJFmye**l)j#zto!))`=vC|$_mz&OQ_e;t?ap?J@CE%krzW3zzIQWA6;(r|1t%nC?7} ziykUx_6rWyEF+K1KF=9EZe6c&6*lp#d~C>(lTKLr5S<~6o>^4-UMGuTqPhWW$X(%PD}KMG1=CL^n+lpROG!x`eDf|ZW*_uo+JG<2|_oYjaRjypHTyt1Ctg~LYMJuQFN~o zpE+4eM1WHOv+;P)#G~7+djO1Ns?Ut`F0PKyp)U6R z;Wv@f2yuWnBF1Vyr@NNtwU<8f6Rd8PNZ-z6I>zDc1gqQv@nDCRSR`{)#V2gf;sOdH z%BYrVa=;0$C`F=i-nto&rFiLLK`}5!2c}QfJ3gzT5 z2g8%X#D$F7wZ7&Qq%W#XM51B&+RR|lB0^bIA3YM`v=Gbccw$8%q+6iSN!f-ZCoBzF z^%gbl+9ej3yH0)p88l~jp2J}<3Pa;6r!Y*&<6262^<({QVBRXlw~UOJJ)TdKDZLyE zjgOlyZCixkos%~5hMuXDs;?q2C9I4#sVbC$HHG7Ln3TfI?y|G*E~c;75U!h8ppn!G z?;SC-=n278=f}{Ea4HU!_x*?#O%p~=Rpgw@TQ!E`I2L2thWN+)4|`3cHxeVUn15In ztceMa$11m32bdVe@3GaR+3LnMqT|sc!)(NHlK1;(_rgTnaKjaT`A!h#ulE<6cB&Ox zrle)88oZ=PbZ9T?0bTny>4oKx3@~MLuPwAsar(1esW88zoIbT;Zt-bj?NvUZ$$v;5 z4sull{EEbXq(n{l=}G(hlf5_h8> z9aPW1M>xJ>Hr>O=m}4#5jcZ{%;$!f_;fB%ejlPjJP-df(5}hzeA@adXxn!mg!f)a5 z0cLiiA4d=Ff$f}ZT2AwsqsSHjJP9r(ZVLIDhiK8;sz-u4?K?7rx*@WmC6!}Fq8UQ4 zbZLNxh|*cMh8W0;MJbOV^c7R#E_URPP2%R*Og#oe*)A6ShaZ&*CKo=ecy9jR5^j6-{FGz{=s@tQ(lUZWWKK zrD3heJD(0y(TI=4jug+3d(zZdm!Ogik0hRdkH5s`G0aph$V+ZO8?xc)?cz@`!ffsR zMhZ8PKs91Y{=O>?fyWaG$B-rfDznESQz4pYpyJe5Lyt?$x#&3JOadG zU4>B*#tdRszhiz89ZmcdBkWoBHrZDnHB5Vf!e27WAi?p)T6k5Zrd=xRzF8Q(dLIZW zh3TF52|tV+rl}DODn}21Iy~*F8{WbKY-7Cz^v0wijIbjEj{-Mj(3S%E^lmcW8)-`! zZ7J5DM$(CXT3RC-eS$RT0_`XqF95vn;`{p_{&;|i@g6{@(~GIYZ$)@@L<~6Gv*=|AE<<8H#l#2v zFoBzYSZNbDcz#8%Yo(RRa4_DSYBcXWBevG4j-9ypkuscW z2BCy&W%0`2HW)^7Ixt;ELZtUO8?|_;al7e*!#1!$VL^7^60+W9)=rgn)WrJM`tf7+ zU;>Tw6q?TK&oLh9HtC#G(~L%CY-&n z`K~e1@qTy_F9}_Z1WYdLJIa$IPbgTIL-)u0bFFrziIT(!+vs6kDOe=YN7^63S4qc= zMBl(6hi-+hd6nryp$RGma@q1Y$wuD#5$$7&Yap=)QCGu~$l;cvAaC-Z1w8FsWu0j; z8%ng7F*rF8EF4SeA+GJ|u^p@uQ@_OLH(=h^vZR%!aB7sXL`fwNX zk&l}$`1Vk8TBJVKJfAUO?J?NX1@`g9#+lPiFj27j-=TdaP z}l}Vtfl~+=cZLj8~MZh*yn@88PL30&x46Dtqs~$ds}XE^2p@LOt~z zx$uAu<~5NRz6$zTLyDri|?XTpmEOkM-g zKltDGU{$`tT9$qr_PIFhMvp+u7C!}_c0fD8Auey63fJ|+a>K`05-$nkI7)|(zdkd@ zYD>J=%I1uAbg(4Q*!5B6!Z=WsWb78gZ=#@4>*9L5#?{zF@C1t5&d}8nYDbIkzT8$%{DCzcY!WQ^sm#3`3dcbs$`YNO- zwNEwRn|`6l?(2x{l`n<2tK;a~T>K#rcnL@TK4J8)ny3E0uG#12mUx0XT3_O+E3z{k zL}Rw`Ri`l0axEma44q9Ol+51KutKE;&wv(l0*c6Tw#D5bzvhYe9}z`7 zMLZo;2Sk&fNqv8)`uTDX_#9Ekf3&|oW73Outoq*hD|565N4z{`)hb{jnQil1GEsf9 zSZD-nZ?SSYo7r{uMYaALiW&Q#<>1T0lE4)5UDq!&!WTDELg6E~M}Z#~-^tmQWQ?vH z<8=5YVl*7^TQc|%_FB0Dc>~0YR<|aL+qEms;44=YSaH@8H@fad#SFMOBJCn0O#r29?N&}2^l)w zT&koW0&XoizZFWR|2kAQ8uF13{`HaO+57}To)8&UbU5}y$k*4Rk4zkV7Bw`egg!L^ zxftmma1>-Ut&15pSHQBB{?S!TalX^(raRN$mx`{hvSo)f0ff5ON^9BXGY(s*fkLWL|EYJ7%AXgybmK^#fkq3Ly@P z1qm>@x-EP|oR-|5?qiS=5A7mbwL6y-6U7ij*crwr=FVJIERWob#`ooJbIsudUu(B? zXQ+{x#_ptJa@3dOv5KaV;MW;OSGx*XKP1A%h9Vwk;#TpJCuYpietlT49~Zn}?^K^g zxp)2RvyS(pviB;4BxjIBMflXGh(49*Q>}G6LBH$duN|5{Q{5Cf>5tDi~aJbERM@1O+Cq5mGe;wp(U%4pZx7sNH*#FR|HG(4YDPSa(Ap(WN%j?j#HWqJ->{^ zuH@&x?9J(?wx5BsdJjfd)LZ8n@h!>7kV7CHwP?4EdBuyDrJ1 zT1yl!sl_wJrk@=!AwFGW4|$W_e6Yga8}NGW6NljOgM`EFLd6U-+nv%iguk!NHw=Y2 z3@Qp`&h0=%6$JZgNX*6>_zW{z&|*jN6cuz9Qc6m*Wz`StO0LdIxPx0lcO zQyLG?KCdZ`pDleE)E=5`TRm((>e7D|Kml%GS;hCY3CUq%x{`F;@<^X~`z&j^72Z}i zdzL*d7Ceu21v#dnUxax1x|H3%uxF{-nEwVni_01HCGwIi_Lscn+ugLp418fL+2>o) zK-Lj_^JeH0_TBzY#N`w`bJGeA81?*hJx%pkJpE9E$m4CaYay`t!Nfki^4!HeKIFDh zX0R=JqV(#^53PW^%A%4n$(zmj>~e3uXh`9Oqs09U*6;wbPTk6-Yx_;)ec~Y)GL}tF zcsfSV8mED6!y1uTF&kIgQwPhG_$87<3Kag$GAO$kiGvXs`=K zoU|KGHF1|EvGE`L8&~tF9Q}S z*M1y$`%dyog!q^Xd)hrzQ>$JKs?muSPr>Dj%-(t}bR6>o3Nxv+w+rQWpFQKL0gSMWC%5>5AR-W$1 zo{1J}-LzY((`waUwmtJHpb?jk@YalUw^V-t+gm#mQ~Pbl^3Org)3`lH2Y962^CrX)ih^2{G=Km50N4az7yDcFXAYrj}L`r!FwD!0%T>^sYnV?>$2BblU9HR4JQo0RpWH zM>yWIVQ#Sr)YZV{&BV~mC7l0Ic?lI?ASK5Mh_g^ z<8AMeK3KK=z;gtVSAVxsI_zB>yMY)RSq@#@?5aip$1AGgPK9)K*Xj-`kE+*}pkLYN z@qPU`Fz-CqqOn=BQ)5CdkE{}5@Ak^;iK5a;UlZ~=t*kj|e59y_iDKLB^1Tn9=orOo zY^GZ1*v}JnUQ1V@J4@A3D796$Yu49mKL|wPth~#~o+`DK-DQb>0bY4Fo{VGFdchhBy z6fedt#<-iawdgjoh&+^taH{BpL=978VOIFu5E1DHieE7=IbC(Xf#k|2QSA}%PH=?e zCAN+lC5ci;qzHM`=tNW`+1pz5bqH(6)gcR4o6lIjtISTQYctOEG3$YcAJXo!*txhP z(aoDyO*)f>=dqOf$ssI{1uW~Cb{8Ap^)hSMi(j{goXl*BYpYRDjiOI) zxaT$)%g$HAxndr+Pnuh(9DWjV4wb*rSWn@pSpSH&hEqrXZoq~Y06>edmzC92mX-a- z(Fy9nBr7;kLaAGmYI4*haMKE&t&srM8oNxn=esj)Z6f0IstkC}rfF3hp3 zE4Q~iJi4x$usV$X9AkM0S@e^UWige+xX16uf#jFgjs3-7#8@f+$QIQ-fdwIOSy9?h zO=P|S<^u&BoygC_{5C8c1WT7KB`)Qyn4^b#S9JvrT~^Z4%sJ2(_QW;B8ZL8K8^OyI zTtl1(q6d-64UXIt8EfzEzFdUp;=p!vFL3Cp3N0>O07zP3JAIAZ2rIc$L>(3vK zwGx<`HVVRtn!cl5=H8!uW5%JR!cO+=41D=ke9RX=!l1pm{)_u1z}jAalNyP9K*6JR znlaiM2-!Gw)o=`vQo;5}RZgGXMjdg{*rSfJ4AoR2Fjr?DsI{vVoX5}E4RzE70EkQZ zxj|u$a4&i*xUId51mj-oM@D*kYY9dJK{b$?n=IVUUMau>t`nfH3kz_BiCQyCN#cq7 zK~MnBa4#smpR<#TC&W*J@eeKpb^p7Xmy!ODh?k=TqoJB6y{xMToL+!OfCmJW_p|rm zXOzUF7x%EXfoRJq{0)IBNif=ZdAUJ&d3}9-d3?b%>s%K zUO%WCFCPzx*V&o(-!(kF?Pl)$r6soe1)3!#!QSJz#KoAGnJb)4xMl!~Uu7 z=I!D1Cmd@SFWd?4j1u)kS>^i=lZwh}n*Y@JO@Xbwv)dmn6xshF>1A*8FS7o_x8E&) z!ufYcQ0o80{SWDX#QsMZC8eeYk#mK4|8`GVPJ;2beTcOy%-$OE=T?MI1P104wgw6b z35o&*MBzd}s5KZ2wBi#KvJruUz+fxke}htX@$`baz~H~3P~bfFC>$G6Avm7^SQIEE zU=0Qe@QZ?gP(CX#5GE+hCu(H_gM$Ta{tZII!yc8DP^W+Q>Nk`%3Q7-*oZ`g9Jo`!2)1DQ6V7_L7{&M z>BBudQK|SFln=xM{tNhbzd%sYpqPdJPE-`Y9}QG65Lpj6)XUXF*VWZYg7LRc^uIO# zP6&hMG&Z_gS;rLs(WSigJLv-|xKkk|b0OuA7pPCjfv?{QE)!WMomGDzUwk)#R~%qTykS z;-6zTaRUJN3Y6uZ=qmMBrMNoj`BL^vEd_pQUOPP<1qu{DR|X|$&(%B5FyaHh``D_> z$E0VREBMu=HOZ;@*$TKP^;*ZiAXgx6AnzlWOQK{G5iTTf46x_ou8#1DjQPw;`JR7X zYuDK|aIg97Kz`IYkCeSDDJ$#R<1nz}TM>V(FcdHs$f%ygVsu9!kA4!c1TWgAr9GjdBf6{zc+cvAck|XOhaf7}e>s8r7y3Na4MY zcQwoWhn<~yEv>%&R`0&K=XDRqar5wWK*WP=Zp~3R#)y++@psjgl{*!$%>g`X9?dl+ z+J&A7Q|WhxJ2*^#9A6Qlp&P_~^pb?_GNYViw9EhiC z;^bD9DQ6wttP6;^G=Oker}A7b1?_%6 z-`Uxzn%9X*XLu!(UyJ!ugeAN7vC=|yld4Tze*O=WPB9{5s^a=0XT(z)1*>=75pr}V zH>(C)TMieYZxp<}lY^u#7n)%fI| zh5APVu0Z+!|rv8yAhu^rr%)vD$$5nf6kb=$L5SX&|FApV4Orim~%^Uj^TEADnN#J zZ)gKUe6-g+t6n4y@YMK~b=|CX?P>ja;fhG5i9y4onATb9eTq*0mr&EBz&!73JlJtsS}7#p&5;S#5{r-|A;D z8{A>p#>N>9%9rnpY`dFARUkVe3@@R8r;VpKMSxF2N}Dgx9(>Gx zS!a8fg8k*iUbn!C2R&V!w48&Zu%%6nazICo>)wki_T6V0?)&v5Cu){k$tCLV z>3^0#k!HwEb|)zo=y*9%JSYRn76M1g75Ry~0D)>Q; { let title = data_source.to_string(); - let icon = None; // TODO(#5645): an icon for data sources - item_title_ui(ctx.re_ui, ui, &title, icon, &title); + item_title_ui(ctx.re_ui, ui, &title, Some(&icons::DATA_SOURCE), &title); } Item::StoreId(store_id) => { @@ -322,7 +321,12 @@ fn what_is_selected_ui( id_str.clone() }; - item_title_ui(ctx.re_ui, ui, &title, Some(&re_ui::icons::STORE), &id_str); + let icon = match store_id.kind { + re_log_types::StoreKind::Recording => &icons::RECORDING, + re_log_types::StoreKind::Blueprint => &icons::BLUEPRINT, + }; + + item_title_ui(ctx.re_ui, ui, &title, Some(icon), &id_str); } Item::Container(container_id) => { From 8c0d3898efc67080cdbfd23ce0ff219041ff94c6 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 28 Mar 2024 13:18:18 -0400 Subject: [PATCH 140/508] Introduce `rr.notebook_show()` to simplify notebook experience (#5715) ### What As part of adding blueprint support to notebooks, I realized the experience of creating and logging memory recordings felt very incongruous with the normal rerun workflow. I introduced a new mechanism `rr.notebook_show()`, which uses the MemoryRecording behind the scenes, but doesn't require users to be aware of it. All Blueprint types now support `_repr_html_` and show the currently active recording stream. Uncovered several existing sharp-corners with notebooks: - MemoryStream was still generating spurious warnings about dropped messages, which I cleaned up. - The notebook was using random for its identifiers, which, in the case of examples was having its seed reset, leading to duplicate ids in the DOM. Lastly, updated the notebook cube example to use the new style: ![image](https://github.com/rerun-io/rerun/assets/3312232/cc9d354e-2744-4649-be2e-484499bc4f98) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5715/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5715/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5715/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5715) - [Docs preview](https://rerun.io/preview/c0177a9fb9cb1ef76f2eeba7b65aa7c861da2642/docs) - [Examples preview](https://rerun.io/preview/c0177a9fb9cb1ef76f2eeba7b65aa7c861da2642/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .typos.toml | 7 +- crates/re_sdk/src/log_sink.rs | 59 ++++--- examples/python/notebook/README.md | 30 +++- examples/python/notebook/cube.ipynb | 162 ++++++++++++------ rerun_py/docs/gen_common_index.py | 1 + rerun_py/rerun_sdk/rerun/__init__.py | 19 +- rerun_py/rerun_sdk/rerun/blueprint/api.py | 45 ++++- rerun_py/rerun_sdk/rerun/html_shared.py | 48 ++++++ .../rerun/{recording.py => memory.py} | 98 +++++------ rerun_py/rerun_sdk/rerun/notebook.py | 128 ++++++++++++++ rerun_py/rerun_sdk/rerun/sinks.py | 26 --- 11 files changed, 441 insertions(+), 182 deletions(-) create mode 100644 rerun_py/rerun_sdk/rerun/html_shared.py rename rerun_py/rerun_sdk/rerun/{recording.py => memory.py} (55%) create mode 100644 rerun_py/rerun_sdk/rerun/notebook.py diff --git a/.typos.toml b/.typos.toml index 6622c0ed9e3c..a63425b657c4 100644 --- a/.typos.toml +++ b/.typos.toml @@ -137,8 +137,9 @@ zeroterminated = "null-terminated" zero-terminated = "null-terminated" [default] -# Work around for typos inside of 8-character hashes. These show up inside of ipynb. +# Work around for typos inside of hashes. These show up inside of ipynb. # e.g. "f4e1caf9" -> `caf` should be `calf` -# Specifically limit ourselves to exactly 8 chars in a quoted strong. +# Specifically limit ourselves to exactly 8 chars in a quoted string, or +# 16 character hashses following a leading underscore. # Just don't spell "defaced" wrong. -extend-ignore-re = ["\"[a-f0-9]{8}\""] +extend-ignore-re = ["\"[a-f0-9]{8}\"", "_[a-f0-9]{16}"] diff --git a/crates/re_sdk/src/log_sink.rs b/crates/re_sdk/src/log_sink.rs index 73a8e9e493b9..f8fdfdb5efec 100644 --- a/crates/re_sdk/src/log_sink.rs +++ b/crates/re_sdk/src/log_sink.rs @@ -1,7 +1,7 @@ use std::fmt; use std::sync::Arc; -use parking_lot::RwLock; +use parking_lot::Mutex; use re_log_types::{BlueprintActivationCommand, LogMsg, StoreId}; /// Where the SDK sends its log messages. @@ -150,34 +150,44 @@ impl LogSink for MemorySink { #[inline] fn flush_blocking(&self) {} + + #[inline] + fn drain_backlog(&self) -> Vec { + self.0.take() + } } impl fmt::Debug for MemorySink { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "MemorySink {{ {} messages }}", - self.buffer().read().len() - ) + write!(f, "MemorySink {{ {} messages }}", self.buffer().num_msgs()) } } +#[derive(Default)] +struct MemorySinkStorageInner { + msgs: Vec, + has_been_used: bool, +} + /// The storage used by [`MemorySink`]. #[derive(Default, Clone)] pub struct MemorySinkStorage { - msgs: Arc>>, + inner: Arc>, pub(crate) rec: Option, } impl Drop for MemorySinkStorage { fn drop(&mut self) { - for msg in self.msgs.read().iter() { - // Sinks intentionally end up with pending SetStoreInfo messages - // these are fine to drop safely. Anything else should produce a - // warning. - if !matches!(msg, LogMsg::SetStoreInfo(_)) { - re_log::warn!("Dropping data in MemorySink"); - return; + let inner = self.inner.lock(); + if !inner.has_been_used { + for msg in &inner.msgs { + // Sinks intentionally end up with pending SetStoreInfo messages + // these are fine to drop safely. Anything else should produce a + // warning. + if !matches!(msg, LogMsg::SetStoreInfo(_)) { + re_log::warn!("Dropping data in MemorySink"); + return; + } } } } @@ -186,20 +196,16 @@ impl Drop for MemorySinkStorage { impl MemorySinkStorage { /// Write access to the inner array of [`LogMsg`]. #[inline] - fn write(&self) -> parking_lot::RwLockWriteGuard<'_, Vec> { - self.msgs.write() - } - - /// Read access to the inner array of [`LogMsg`]. - #[inline] - pub fn read(&self) -> parking_lot::RwLockReadGuard<'_, Vec> { - self.msgs.read() + fn write(&self) -> parking_lot::MappedMutexGuard<'_, Vec> { + let mut inner = self.inner.lock(); + inner.has_been_used = false; + parking_lot::MutexGuard::map(inner, |inner| &mut inner.msgs) } /// How many messages are currently written to this memory sink #[inline] pub fn num_msgs(&self) -> usize { - self.read().len() + self.inner.lock().msgs.len() } /// Consumes and returns the inner array of [`LogMsg`]. @@ -212,7 +218,7 @@ impl MemorySinkStorage { // in this flush; it's just a matter of making the table batcher tick early. rec.flush_blocking(); } - std::mem::take(&mut *self.msgs.write()) + std::mem::take(&mut (self.write())) } /// Convert the stored messages into an in-memory Rerun log file. @@ -227,7 +233,10 @@ impl MemorySinkStorage { let mut encoder = re_log_encoding::encoder::Encoder::new(encoding_options, &mut buffer)?; for sink in sinks { - for message in sink.read().iter() { + let mut inner = sink.inner.lock(); + inner.has_been_used = true; + + for message in &inner.msgs { encoder.append(message)?; } } diff --git a/examples/python/notebook/README.md b/examples/python/notebook/README.md index 11196287c876..039e2ece8f66 100644 --- a/examples/python/notebook/README.md +++ b/examples/python/notebook/README.md @@ -4,26 +4,42 @@ Rerun has limited support for direct embedding within a [Jupyter](https://jupyte Many additional environments beyond Jupyter are supported such as [Google Colab](https://colab.research.google.com/) or [VSCode](https://code.visualstudio.com/blogs/2021/08/05/notebooks). -In order to show a rerun viewer inline within the notebook you need to use a special in-memory -recording: -``` -rec = rr.memory_recording() +In order to show a rerun viewer inline within the notebook, you can call: + +```python +rr.init("rerun_example_notebook") + +rr.log(...) + +rr.notebook_show() ``` -After creating this recording all the normal rerun commands will work as expected and log -to this recording instance. When you are ready to show it you can return it at the end of your cell -or call `rec.show()`. +This will show the contents of the current global recording stream. Note that the global stream will accumulate +data in-memory. You can reset the stream by calling `rr.init` again to establish a new global context. + +As with the other stream viewing APIs (`rr.show`, `rr.connect`, `rr.spawn`), you can alternatively pass +a specific recording instance to `notebook_show` + +```python +rec = rr.new_recording("rerun_example_notebook_local") + +rec.log(...) + +rr.notebook_show(recording=rec) +``` # Running in Jupyter The easiest way to get a feel for working with notebooks is to use it: Install jupyter + ``` pip install -r requirements.txt ``` Open the notebook + ``` jupyter notebook cube.ipynb ``` diff --git a/examples/python/notebook/cube.ipynb b/examples/python/notebook/cube.ipynb index bca4aa039b1b..18ff9b205da5 100644 --- a/examples/python/notebook/cube.ipynb +++ b/examples/python/notebook/cube.ipynb @@ -21,8 +21,7 @@ "\n", "import numpy as np\n", "import rerun as rr # pip install rerun-sdk\n", - "\n", - "rr.init(\"rerun_example_cube\")" + "import rerun.blueprint as rrb" ] }, { @@ -39,7 +38,7 @@ "using your notebook in an offline environment.\n", "\n", "In these cases you can start a local viewer server by uncommenting the following\n", - "line:" + "lines:" ] }, { @@ -60,14 +59,18 @@ "source": [ "## Helper to create the colored cube\n", "\n", - "This code exists in the `rerun.utilities` package, but is repeated here for context." + "This code exists in the `rerun.utilities` package, but is included here for context." ] }, { "cell_type": "code", "execution_count": null, "id": "f709925e", - "metadata": {}, + "metadata": { + "jupyter": { + "source_hidden": true + } + }, "outputs": [], "source": [ "ColorGrid = namedtuple(\"ColorGrid\", [\"positions\", \"colors\"])\n", @@ -89,9 +92,9 @@ " \"\"\"\n", "\n", " grid = np.mgrid[\n", - " slice(-10, 10, x_count * 1j),\n", - " slice(-10, 10, y_count * 1j),\n", - " slice(-10, 10, z_count * 1j),\n", + " slice(-x_count, x_count, x_count * 1j),\n", + " slice(-y_count, y_count, y_count * 1j),\n", + " slice(-z_count, z_count, z_count * 1j),\n", " ]\n", "\n", " angle = np.linspace(-float(twist) / 2, float(twist) / 2, z_count)\n", @@ -119,128 +122,189 @@ }, { "cell_type": "markdown", - "id": "b9a75269", + "id": "04c095ef", "metadata": {}, "source": [ - "## Start a new recording\n", + "## Logging some data\n", "\n", - "To start a new recording all you need to do is call rr.memory_recording()." + "Now we can create some data and add it to the recording." ] }, { "cell_type": "code", "execution_count": null, - "id": "f4e1caf9", + "id": "92871ea1", "metadata": {}, "outputs": [], "source": [ - "rec = rr.memory_recording()" + "rr.init(\"rerun_example_cube\")\n", + "\n", + "STEPS = 100\n", + "twists = math.pi * np.sin(np.linspace(0, math.tau, STEPS)) / 4\n", + "for t in range(STEPS):\n", + " rr.set_time_sequence(\"step\", t)\n", + " cube = build_color_grid(10, 10, 10, twist=twists[t])\n", + " rr.log(\"cube\", rr.Points3D(cube.positions, colors=cube.colors, radii=0.5))" ] }, { "cell_type": "markdown", - "id": "6e4f945b", + "id": "da14cd43-f70f-4172-b907-ccecb43da6b9", "metadata": {}, "source": [ - "## Showing the recording\n", + "## Viewing the output\n", "\n", - "At any point you can show this recording by returning it as the last item in the cell.\n", - "In this case the recording simply does not have any data in it yet." + "The current global stream can be output to the cell using `rr.notebook_show()`" ] }, { "cell_type": "code", "execution_count": null, - "id": "d586d222", + "id": "25c99b7b-681b-4035-8f12-90392d5f7d79", "metadata": {}, "outputs": [], "source": [ - "rec" + "rr.notebook_show()" ] }, { "cell_type": "markdown", - "id": "04c095ef", + "id": "31d392a8", "metadata": {}, "source": [ - "## Logging some data\n", + "## Adjusting the view\n", "\n", - "Now we can create some data and add it to the recording before we show it again." + "The `show` method also lets you adjust properties such as width and height." ] }, { "cell_type": "code", "execution_count": null, - "id": "92871ea1", + "id": "1a1b0f66-4287-4705-8be5-ae837ffe3f90", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "rr.notebook_show(width=400, height=400)" + ] + }, + { + "cell_type": "markdown", + "id": "36f9f61b", + "metadata": {}, + "source": [ + "## Stating a new recording\n", + "\n", + "You can always start another recording by calling `rr.init(...)` again to reset the global stream, or alternatively creating a separate recording stream using `rr.new_recording` (discussed more below)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c4cc33fd", "metadata": {}, "outputs": [], "source": [ + "rr.init(\"rerun_example_cube\")\n", + "\n", "STEPS = 100\n", "twists = math.pi * np.sin(np.linspace(0, math.tau, STEPS)) / 4\n", "for t in range(STEPS):\n", " rr.set_time_sequence(\"step\", t)\n", - " cube = build_color_grid(10, 10, 10, twist=twists[t])\n", - " rr.log(\"cube\", rr.Points3D(cube.positions, colors=cube.colors, radii=0.5))\n", + " h_grid = build_color_grid(10, 3, 3, twist=twists[t])\n", + " rr.log(\"h_grid\", rr.Points3D(h_grid.positions, colors=h_grid.colors, radii=0.5))\n", + " v_grid = build_color_grid(3, 3, 10, twist=twists[t])\n", + " rr.log(\"v_grid\", rr.Points3D(v_grid.positions, colors=v_grid.colors, radii=0.5))\n", "\n", - "rec" + "rr.notebook_show()" ] }, { "cell_type": "markdown", - "id": "31d392a8", + "id": "a9812634-067f-4e07-95fb-cb9a506c42d3", "metadata": {}, "source": [ - "## Adjusting the view\n", + "## Using blueprints\n", "\n", - "The recording also as a `show` method that lets you adjust properties such as width and height.\n", - "In the future this will support additional blueprint and layout options." + "Rerun blueprints can be used with `rr.show()`\n", + "\n", + "For example, we can split the two grids into their own respective space-views." ] }, { "cell_type": "code", "execution_count": null, - "id": "1a1b0f66-4287-4705-8be5-ae837ffe3f90", - "metadata": { - "tags": [] - }, + "id": "eb8f7701", + "metadata": {}, "outputs": [], "source": [ - "rec.show(width=400, height=400)" + "blueprint = rrb.Blueprint(\n", + " rrb.Horizontal(\n", + " rrb.Spatial3DView(name=\"Horizontal grid\", origin=\"h_grid\"),\n", + " rrb.Spatial3DView(name=\"Vertical grid\", origin=\"v_grid\"),\n", + " column_shares=[2,1]),\n", + " collapse_panels=True\n", + ")\n", + "\n", + "rr.notebook_show(blueprint=blueprint)" ] }, { "cell_type": "markdown", - "id": "36f9f61b", + "id": "1a6d264c-df89-452a-9469-dc19519834fd", "metadata": {}, "source": [ - "## Stating a new recording\n", + "## Extra convenience\n", "\n", - "You can always start another recording by calling `rr.memory_recording()` again." + "Rerun blueprints types also implement `_repr_html_()` directly, so if a blueprint is the last element in your cell the right thing will happen.\n", + "\n", + "Note that this mechanism only works when you are using the global recording stream." ] }, { "cell_type": "code", "execution_count": null, - "id": "c4cc33fd", + "id": "34037cf5-39ae-4788-92ca-a63ed2667f1c", + "metadata": {}, + "outputs": [], + "source": [ + "rrb.Spatial3DView(name=\"Horizontal grid\", origin=\"h_grid\")" + ] + }, + { + "cell_type": "markdown", + "id": "ef9087de-d090-4c90-ab3e-18c20c92bff6", + "metadata": {}, + "source": [ + "## Working with non-global streams\n", + "\n", + "Sometimes it can be more explicit to work with specific (non-global recording) streams via the `new_recording` method.\n", + "\n", + "In this case, remember to call `notebook_show` directly on the recording stream. As noted above, there is no way to use a bare Blueprint object in conjunction with a non-global recording." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed86cc19-45cf-4c21-9a94-c4ce2ade7f65", "metadata": {}, "outputs": [], "source": [ - "rec2 = rr.memory_recording()\n", + "rec = rr.new_recording(\"rerun_example_cube_flat\")\n", "\n", - "STEPS = 1\n", - "twists = math.pi * np.sin(np.linspace(0, math.tau, STEPS)) / 4\n", - "for t in range(STEPS):\n", - " rr.set_time_sequence(\"step\", t)\n", - " cube = build_color_grid(50, 50, 50, twist=twists[t])\n", - " rr.log(\"cube\", rr.Points3D(cube.positions, colors=cube.colors, radii=0.5))\n", + "flat_grid = build_color_grid(20, 20, 1, twist=0)\n", + "rec.log(\"flat_grid\", rr.Points3D(flat_grid.positions, colors=flat_grid.colors, radii=0.5))\n", "\n", - "rec2" + "bp = rrb.Blueprint(collapse_panels=True)\n", + "\n", + "rec.notebook_show(blueprint=bp)" ] }, { "cell_type": "code", "execution_count": null, - "id": "eb8f7701", + "id": "cb9bbc17-4a20-4861-bc5b-fe1092fa609e", "metadata": {}, "outputs": [], "source": [] @@ -262,7 +326,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.11.8" } }, "nbformat": 4, diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 07eccbafc7f0..daeccdaa0376 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -90,6 +90,7 @@ class Section: "serve", "spawn", "memory_recording", + "notebook_show", ], ), Section( diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 1b07e374d1f7..e356a7af5005 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -82,6 +82,7 @@ "log_file_from_path", "memory_recording", "new_entity_path", + "notebook_show", "reset_time", "save", "script_add_args", @@ -162,7 +163,8 @@ ) from .error_utils import set_strict_mode from .logging_handler import LoggingHandler -from .recording import MemoryRecording +from .memory import MemoryRecording, memory_recording +from .notebook import notebook_show from .recording_stream import ( RecordingStream, get_application_id, @@ -175,7 +177,7 @@ set_thread_local_data_recording, ) from .script_helpers import script_add_args, script_setup, script_teardown -from .sinks import connect, disconnect, memory_recording, save, send_blueprint, serve, spawn, stdout +from .sinks import connect, disconnect, save, send_blueprint, serve, spawn, stdout from .time import ( disable_timeline, reset_time, @@ -223,7 +225,7 @@ def _init_recording_stream() -> None: from rerun.recording_stream import _patch as recording_stream_patch recording_stream_patch( - [connect, save, stdout, disconnect, memory_recording, serve, spawn, send_blueprint] + [connect, save, stdout, disconnect, memory_recording, serve, spawn, send_blueprint, notebook_show] + [ set_time_sequence, set_time_seconds, @@ -356,8 +358,8 @@ def init( # TODO(#3793): defaulting recording_id to authkey should be opt-in def new_recording( - *, application_id: str, + *, recording_id: str | UUID | None = None, make_default: bool = False, make_thread_default: bool = False, @@ -573,13 +575,4 @@ def start_web_viewer_server(port: int = 0) -> None: """ - if not bindings.is_enabled(): - import logging - - logging.warning( - "Rerun is disabled - start_web_viewer_server() call ignored. You must call rerun.init before starting the" - + " web viewer server." - ) - return - bindings.start_web_viewer_server(port) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index ec9cf45a4443..c2f4efa6740e 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -2,12 +2,13 @@ import itertools import uuid -from typing import Iterable, Optional, Union +from typing import Any, Iterable, Optional, Union import rerun_bindings as bindings from ..datatypes import EntityPathLike, Utf8ArrayLike, Utf8Like -from ..recording import MemoryRecording +from ..memory import MemoryRecording +from ..notebook import as_html from ..recording_stream import RecordingStream from .archetypes import ContainerBlueprint, PanelBlueprint, SpaceViewBlueprint, SpaceViewContents, ViewportBlueprint from .components import ColumnShareArrayLike, RowShareArrayLike @@ -109,6 +110,10 @@ def _iter_space_views(self) -> Iterable[bytes]: # the entity-path lookup instead. return [self.id.bytes] + def _repr_html_(self) -> Any: + """IPython interface to conversion to html.""" + return as_html(blueprint=self) + class Container: """ @@ -229,6 +234,10 @@ def _iter_space_views(self) -> Iterable[bytes]: # the entity-path lookup instead. return itertools.chain.from_iterable(sub._iter_space_views() for sub in self.contents) + def _repr_html_(self) -> Any: + """IPython interface to conversion to html.""" + return as_html(blueprint=self) + class Panel: """ @@ -346,6 +355,7 @@ def __init__( *parts: BlueprintPart, auto_layout: bool | None = None, auto_space_views: bool | None = None, + collapse_panels: bool = False, ): """ Construct a new blueprint from the given parts. @@ -369,12 +379,20 @@ def __init__( auto_layout: Whether to automatically layout the viewport. If `True`, the container layout will be reset whenever a new space view is added to the viewport. Defaults to `False`. + Defaults to `False` unless no Containers or SpaceViews are provided, in which case it defaults to `True`. + If you want to create a completely empty Blueprint, you must explicitly set this to `False`. auto_space_views: Whether to automatically add space views to the viewport. If `True`, the viewport will - automatically add space views based on content in the data store. Defaults to `False`. + automatically add space views based on content in the data store. + Defaults to `False` unless no Containers or SpaceViews are provided, in which case it defaults to `True`. + If you want to create a completely empty Blueprint, you must explicitly set this to `False`. + collapse_panels: + Whether to collapse the panels in the viewer. Defaults to `False`. """ + self.collapse_panels = collapse_panels + for part in parts: if isinstance(part, (Container, SpaceView)): if hasattr(self, "root_container"): @@ -397,8 +415,15 @@ def __init__( else: raise ValueError(f"Unknown part type: {part}") - self.auto_layout = auto_layout self.auto_space_views = auto_space_views + self.auto_layout = auto_layout + + # If there's no `root_container`, switch `auto_layout`` and `auto_space_views`` defaults to `True`. + if not hasattr(self, "root_container"): + if self.auto_space_views is None: + self.auto_space_views = True + if self.auto_layout is None: + self.auto_layout = True def to_blueprint(self) -> Blueprint: """Conform with the `BlueprintLike` interface.""" @@ -426,10 +451,22 @@ def _log_to_stream(self, stream: RecordingStream) -> None: if hasattr(self, "blueprint_panel"): self.blueprint_panel._log_to_stream(stream) + elif self.collapse_panels: + BlueprintPanel(expanded=False)._log_to_stream(stream) + if hasattr(self, "selection_panel"): self.selection_panel._log_to_stream(stream) + elif self.collapse_panels: + SelectionPanel(expanded=False)._log_to_stream(stream) + if hasattr(self, "time_panel"): self.time_panel._log_to_stream(stream) + elif self.collapse_panels: + TimePanel(expanded=False)._log_to_stream(stream) + + def _repr_html_(self) -> Any: + """IPython interface to conversion to html.""" + return as_html(blueprint=self) def save(self, application_id: str, path: str | None = None) -> None: """ diff --git a/rerun_py/rerun_sdk/rerun/html_shared.py b/rerun_py/rerun_sdk/rerun/html_shared.py new file mode 100644 index 000000000000..06ed25705598 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/html_shared.py @@ -0,0 +1,48 @@ +from __future__ import annotations + +import uuid + +DEFAULT_WIDTH = 950 +DEFAULT_HEIGHT = 712 +DEFAULT_TIMEOUT = 2000 + + +def render_html_template(base64_data: str, app_url: str, timeout_ms: int, width: int, height: int) -> str: + # Use a random presentation ID to avoid collisions when multiple recordings are shown in the same notebook. + presentation_id = "_" + uuid.uuid4().hex + + return f""" + + + +""" diff --git a/rerun_py/rerun_sdk/rerun/recording.py b/rerun_py/rerun_sdk/rerun/memory.py similarity index 55% rename from rerun_py/rerun_sdk/rerun/recording.py rename to rerun_py/rerun_sdk/rerun/memory.py index a494798a7bee..e01c3f5d8fb1 100644 --- a/rerun_py/rerun_sdk/rerun/recording.py +++ b/rerun_py/rerun_sdk/rerun/memory.py @@ -3,15 +3,39 @@ import base64 import logging -import random -import string from typing import Any +from typing_extensions import deprecated # type: ignore[misc, unused-ignore] + from rerun import bindings -DEFAULT_WIDTH = 950 -DEFAULT_HEIGHT = 712 -DEFAULT_TIMEOUT = 2000 +from .html_shared import DEFAULT_HEIGHT, DEFAULT_TIMEOUT, DEFAULT_WIDTH, render_html_template +from .recording_stream import RecordingStream + + +def memory_recording(recording: RecordingStream | None = None) -> MemoryRecording: + """ + Streams all log-data to a memory buffer. + + This can be used to display the RRD to alternative formats such as html. + See: [rerun.MemoryRecording.as_html][]. + + Parameters + ---------- + recording: + Specifies the [`rerun.RecordingStream`][] to use. + If left unspecified, defaults to the current active data recording, if there is one. + See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. + + Returns + ------- + MemoryRecording + A memory recording object that can be used to read the data. + + """ + + recording = RecordingStream.to_native(recording) + return MemoryRecording(bindings.memory_recording(recording=recording)) class MemoryRecording: @@ -20,14 +44,6 @@ class MemoryRecording: def __init__(self, storage: bindings.PyMemorySinkStorage) -> None: self.storage = storage - def reset_data(self) -> None: - """Reset the data in the MemoryRecording.""" - self.storage.reset_data() - - def reset_blueprint(self, *, add_to_app_default_blueprint: bool = False) -> None: - """Reset the blueprint in the MemoryRecording.""" - self.storage.reset_blueprint(add_to_app_default_blueprint) - def num_msgs(self) -> int: """ The number of pending messages in the MemoryRecording. @@ -36,6 +52,7 @@ def num_msgs(self) -> int: """ return self.storage.num_msgs() # type: ignore[no-any-return] + @deprecated("Please use rerun.notebook_show() instead.") def as_html( self, *, @@ -71,52 +88,23 @@ def as_html( if app_url is None: app_url = bindings.get_app_url() - # Use a random presentation ID to avoid collisions when multiple recordings are shown in the same notebook. - presentation_id = "".join(random.choice(string.ascii_letters) for i in range(6)) - if other: other = other.storage base64_data = base64.b64encode(self.storage.concat_as_bytes(other)).decode("utf-8") - html_template = f""" - - - - - """ - - return html_template - + return """ +
+ Direct rendering of MemoryRecording has been deprecated. Please prefer rerun.notebook_show(). +
+""" + render_html_template( + base64_data=base64_data, + app_url=app_url, + timeout_ms=timeout_ms, + width=width, + height=height, + ) + + @deprecated("Please use rerun.notebook_show() instead.") def show( self, *, diff --git a/rerun_py/rerun_sdk/rerun/notebook.py b/rerun_py/rerun_sdk/rerun/notebook.py new file mode 100644 index 000000000000..0b54dbb2e7f5 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/notebook.py @@ -0,0 +1,128 @@ +"""Helper functions for converting streams to inline html.""" +from __future__ import annotations + +import base64 +import logging +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from .blueprint import BlueprintLike + +from rerun import bindings + +from .html_shared import DEFAULT_HEIGHT, DEFAULT_TIMEOUT, DEFAULT_WIDTH, render_html_template +from .memory import memory_recording +from .recording_stream import RecordingStream, get_application_id + + +def as_html( + *, + width: int = DEFAULT_WIDTH, + height: int = DEFAULT_HEIGHT, + app_url: str | None = None, + timeout_ms: int = DEFAULT_TIMEOUT, + blueprint: BlueprintLike | None = None, + recording: RecordingStream | None = None, +) -> str: + """ + Generate an HTML snippet that displays the recording in an IFrame. + + For use in contexts such as Jupyter notebooks. + + ⚠️ This will do a blocking flush of the current sink before returning! + + Parameters + ---------- + width : int + The width of the viewer in pixels. + height : int + The height of the viewer in pixels. + app_url : str + Alternative HTTP url to find the Rerun web viewer. This will default to using https://app.rerun.io + or localhost if [rerun.start_web_viewer_server][] has been called. + timeout_ms : int + The number of milliseconds to wait for the Rerun web viewer to load. + blueprint : BlueprintLike + The blueprint to display in the viewer. + recording: + Specifies the [`rerun.RecordingStream`][] to use. + If left unspecified, defaults to the current active data recording, if there is one. + See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. + + """ + + application_id = get_application_id(recording) + if application_id is None: + raise ValueError( + "No application id found. You must call rerun.init before using the notebook APIs, or provide a recording." + ) + + if app_url is None: + app_url = bindings.get_app_url() + + output_stream = RecordingStream( + bindings.new_recording( + application_id=application_id, + make_default=False, + make_thread_default=False, + default_enabled=True, + ) + ) + if blueprint is not None: + output_stream.send_blueprint(blueprint, make_active=True) # type: ignore[attr-defined] + + data_memory = memory_recording(recording=recording) + output_memory = output_stream.memory_recording() # type: ignore[attr-defined] + + base64_data = base64.b64encode(output_memory.storage.concat_as_bytes(data_memory.storage)).decode("utf-8") + + return render_html_template( + base64_data=base64_data, + app_url=app_url, + timeout_ms=timeout_ms, + width=width, + height=height, + ) + + +def notebook_show( + *, + width: int = DEFAULT_WIDTH, + height: int = DEFAULT_HEIGHT, + app_url: str | None = None, + timeout_ms: int = DEFAULT_TIMEOUT, + blueprint: BlueprintLike | None = None, + recording: RecordingStream | None = None, +) -> Any: + """ + Output the Rerun viewer in a notebook using IPython [IPython.core.display.HTML][]. + + Parameters + ---------- + width : int + The width of the viewer in pixels. + height : int + The height of the viewer in pixels. + app_url : str + Alternative HTTP url to find the Rerun web viewer. This will default to using https://app.rerun.io + or localhost if [rerun.start_web_viewer_server][] has been called. + timeout_ms : int + The number of milliseconds to wait for the Rerun web viewer to load. + blueprint : BlueprintLike + The blueprint to display in the viewer. + recording: + Specifies the [`rerun.RecordingStream`][] to use. + If left unspecified, defaults to the current active data recording, if there is one. + See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. + + """ + html = as_html( + width=width, height=height, app_url=app_url, timeout_ms=timeout_ms, blueprint=blueprint, recording=recording + ) + try: + from IPython.core.display import HTML + + return HTML(html) # type: ignore[no-untyped-call] + except ImportError: + logging.warning("Could not import IPython.core.display. Returning raw HTML string instead.") + return html diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index 64ffc59970f3..89a99f4fa7f4 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -7,7 +7,6 @@ import rerun_bindings as bindings # type: ignore[attr-defined] from rerun.blueprint.api import BlueprintLike, create_in_memory_blueprint -from rerun.recording import MemoryRecording from rerun.recording_stream import RecordingStream, get_application_id # --- Sinks --- @@ -186,31 +185,6 @@ def disconnect(recording: RecordingStream | None = None) -> None: bindings.disconnect(recording=recording) -def memory_recording(recording: RecordingStream | None = None) -> MemoryRecording: - """ - Streams all log-data to a memory buffer. - - This can be used to display the RRD to alternative formats such as html. - See: [rerun.MemoryRecording.as_html][]. - - Parameters - ---------- - recording: - Specifies the [`rerun.RecordingStream`][] to use. - If left unspecified, defaults to the current active data recording, if there is one. - See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. - - Returns - ------- - MemoryRecording - A memory recording object that can be used to read the data. - - """ - - recording = RecordingStream.to_native(recording) - return MemoryRecording(bindings.memory_recording(recording=recording)) - - def serve( *, open_browser: bool = True, From ed5f5be12fdb19f80f463c0bde13b673671f765a Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 29 Mar 2024 07:34:49 -0400 Subject: [PATCH 141/508] If multiple ContainerLikes are passed to blueprint, wrap them in Tabs (#5722) ### What Previously it wass an error to do something like: ``` rrb.Blueprint( rrb.Spatial2DView(...), rrb.Spatial2DView(...), ) ``` The changes the behavior so if pass multiple ContainerLike's to the Blueprint, they get aggregated as a Tab container. The above would be equivalent to: ``` rrb.Blueprint( rrb.Tabs( rrb.Spatial2DView(...), rrb.Spatial2DView(...), ) ) ``` This seems less surprising than raising a value-error. Choice of `Tabs` over `Grid` is somewhat arbitrary, but Tabs feels more close to the "spirit" of multiple top-level contents, since each one still behaves essentially as fully-screen when selected. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5722/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5722/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5722/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5722) - [Docs preview](https://rerun.io/preview/4bcf0832a2d2898329259f74038bfa0bc6d8cabf/docs) - [Examples preview](https://rerun.io/preview/4bcf0832a2d2898329259f74038bfa0bc6d8cabf/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt --- rerun_py/rerun_sdk/rerun/blueprint/api.py | 28 +++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index c2f4efa6740e..74256bf100c6 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -77,9 +77,9 @@ def blueprint_path(self) -> str: def to_container(self) -> Container: """Convert this space view to a container.""" - from .containers import Grid + from .containers import Tabs - return Grid(self) + return Tabs(self) def to_blueprint(self) -> Blueprint: """Convert this space view to a full blueprint.""" @@ -367,10 +367,11 @@ def __init__( - [SelectionPanel][rerun.blueprint.SelectionPanel] - [TimePanel][rerun.blueprint.TimePanel] - It is an error to provide more than one of any type of part. + It is an error to provide more than one of instance of any of the panel types. - Blueprints only have a single top-level "root" container that defines the viewport. Any - other content should be nested under this container (or a nested sub-container). + Blueprints only have a single top-level "root" container that defines the viewport. + If you provide multiple `ContainerLike` instances, they will be combined under a single + root `Tab` container. Parameters ---------- @@ -390,16 +391,15 @@ def __init__( Whether to collapse the panels in the viewer. Defaults to `False`. """ + from .containers import Tabs self.collapse_panels = collapse_panels + contents: list[ContainerLike] = [] + for part in parts: if isinstance(part, (Container, SpaceView)): - if hasattr(self, "root_container"): - raise ValueError( - "Only one ContainerLike can be provided to serve as the root container for the viewport" - ) - self.root_container = part.to_container() + contents.append(part) elif isinstance(part, BlueprintPanel): if hasattr(self, "blueprint_panel"): raise ValueError("Only one blueprint panel can be provided") @@ -418,12 +418,16 @@ def __init__( self.auto_space_views = auto_space_views self.auto_layout = auto_layout - # If there's no `root_container`, switch `auto_layout`` and `auto_space_views`` defaults to `True`. - if not hasattr(self, "root_container"): + if len(contents) == 0: + # If there's no content, switch `auto_layout` and `auto_space_views` defaults to `True`. if self.auto_space_views is None: self.auto_space_views = True if self.auto_layout is None: self.auto_layout = True + elif len(contents) == 1: + self.root_container = contents[0].to_container() + else: + self.root_container = Tabs(contents=contents) def to_blueprint(self) -> Blueprint: """Conform with the `BlueprintLike` interface.""" From 8782c5bd99e63ba59559302e762be8e494409827 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 29 Mar 2024 13:40:09 +0100 Subject: [PATCH 142/508] Update to egui 0.27.1 (#5723) Fixes a bug in the shadow rendering, and another in the "press-and-hold" for context menu on touch screens. Full release notes: https://github.com/emilk/egui/releases/tag/0.27.1 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5723/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5723/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5723/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5723) - [Docs preview](https://rerun.io/preview/ea6161799168688207e700ae797a05d7e02ff1d7/docs) - [Examples preview](https://rerun.io/preview/ea6161799168688207e700ae797a05d7e02ff1d7/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 40 ++++++++++++++++++++-------------------- Cargo.toml | 14 +++++++------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6162eb0b69e7..ea2e096818c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1554,9 +1554,9 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c416b34b29e8f6b2492b5c80319cf9792d339550f0d75a54b53ed070045bbdeb" +checksum = "fb152797942f72b84496eb2ebeff0060240e0bf55096c4525ffa22dd54722d86" dependencies = [ "bytemuck", "serde", @@ -1564,9 +1564,9 @@ dependencies = [ [[package]] name = "eframe" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86811b20df847cfa73637020ee78de780407110f49785df2dea6741146ea5aac" +checksum = "3bcc8e06df6f0a6cf09a3247ff7e85fdfffc28dda4fe5561e05314bf7618a918" dependencies = [ "bytemuck", "cocoa", @@ -1600,9 +1600,9 @@ dependencies = [ [[package]] name = "egui" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8e20541e5d3da08cf817eb5c8a2bc4024f21aad7acf98de201442d6d76e0ecc" +checksum = "6d1b8cc14b0b260aa6bd124ef12c8a94f57ffe8e40aa970f3db710c21bb945f3" dependencies = [ "accesskit", "ahash", @@ -1617,9 +1617,9 @@ dependencies = [ [[package]] name = "egui-wgpu" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25d1c9a6f17f48a75148e7a3db7cc0221b7261db577281267301f83d79d0834a" +checksum = "04ee072f7cbd9e03ae4028db1c4a8677fbb4efc4b62feee6563763a6f041c88d" dependencies = [ "bytemuck", "document-features", @@ -1636,9 +1636,9 @@ dependencies = [ [[package]] name = "egui-winit" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4fc01bc3617dba9280475e9ab2382015e298f401d2318c2a1d78c419b6dffe" +checksum = "3733435d6788c760bb98ce4cb1b8b7a2d953a3a7b421656ba8b3e014019be3d0" dependencies = [ "accesskit_winit", "arboard", @@ -1666,9 +1666,9 @@ dependencies = [ [[package]] name = "egui_extras" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f097daa92d09cc4561f817e2f9733c55af3b157cf437ee3a401cdf038e75fcdc" +checksum = "70edf79855c42e55c357f7f97cd3be9be59cee2585cc39045ce8ff187aa8d4b0" dependencies = [ "egui", "ehttp", @@ -1682,9 +1682,9 @@ dependencies = [ [[package]] name = "egui_glow" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743380a1c0f1dbb7bfe29663ce62b10785adda51105c9bb4e544e2f9955b4958" +checksum = "f933e9e64c4d074c78ce71785a5778f648453c2b2a3efd28eea189dac3f19c28" dependencies = [ "bytemuck", "egui", @@ -1700,9 +1700,9 @@ dependencies = [ [[package]] name = "egui_plot" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8385c285c2157bb94ae572e48d137587bac31207707ad86b7f8d09612b9657" +checksum = "6989f08973c1142953796068f559c40e62204c90b9da07841dd5c991a4a451d8" dependencies = [ "egui", ] @@ -1744,9 +1744,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87799f56edee11422267e1764dd0bf3fe1734888e8d2d0924a67b85f4998fbe" +checksum = "555a7cbfcc52c81eb5f8f898190c840fa1c435f67f30b7ef77ce7cf6b7dcd987" dependencies = [ "bytemuck", "serde", @@ -1846,9 +1846,9 @@ dependencies = [ [[package]] name = "epaint" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "392eccd6d6b13fadccc268f4f61d9363775ec5711ffdece2a79006d676920bcf" +checksum = "bd63c37156e949bda80f7e39cc11508bc34840aecf52180567e67cdb2bf1a5fe" dependencies = [ "ab_glyph", "ahash", diff --git a/Cargo.toml b/Cargo.toml index 97954681b203..b22fd53c8e52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,15 +75,15 @@ re_ws_comms = { path = "crates/re_ws_comms", version = "=0.15.0-alpha.3", defaul rerun = { path = "crates/rerun", version = "=0.15.0-alpha.3", default-features = false } # egui-crates: -ecolor = "0.27.0" -eframe = { version = "0.27.0", default-features = false, features = [ +ecolor = "0.27.1" +eframe = { version = "0.27.1", default-features = false, features = [ "accesskit", "default_fonts", "puffin", "wayland", "x11", ] } -egui = { version = "0.27.0", features = [ +egui = { version = "0.27.1", features = [ "callstack", "extra_debug_asserts", "log", @@ -91,11 +91,11 @@ egui = { version = "0.27.0", features = [ "rayon", ] } egui_commonmark = { version = "0.14", default-features = false } -egui_extras = { version = "0.27.0", features = ["http", "image", "puffin"] } -egui_plot = "0.27.0" +egui_extras = { version = "0.27.1", features = ["http", "image", "puffin"] } +egui_plot = "0.27.1" egui_tiles = "0.8.0" -egui-wgpu = "0.27.0" -emath = "0.27.0" +egui-wgpu = "0.27.1" +emath = "0.27.1" # All of our direct external dependencies should be found here: ahash = "0.8" From bcd20921e4fc54e98da3daad82c7db61a9802b29 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 29 Mar 2024 08:42:05 -0400 Subject: [PATCH 143/508] Also remove nested inclusions when removing a subtree (#5720) ### What - Resolves: https://github.com/rerun-io/rerun/issues/5690 Introduce new helper method that not only adds an exclusion but also removes all the current matches within the subtree. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5720/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5720/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5720/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5720) - [Docs preview](https://rerun.io/preview/fe3ca4a5457776f4ade8171ce94b332b18fdf40e/docs) - [Examples preview](https://rerun.io/preview/fe3ca4a5457776f4ade8171ce94b332b18fdf40e/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/path/entity_path_filter.rs | 16 +++++++++++ .../re_space_view/src/space_view_contents.rs | 28 ++++++++++++++++--- .../src/context_menu/actions/remove.rs | 5 ++-- .../src/space_view_entity_picker.rs | 4 +-- .../re_viewport/src/viewport_blueprint_ui.rs | 8 ++---- 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/crates/re_log_types/src/path/entity_path_filter.rs b/crates/re_log_types/src/path/entity_path_filter.rs index 779e0a9fadc5..da33f0ed84c7 100644 --- a/crates/re_log_types/src/path/entity_path_filter.rs +++ b/crates/re_log_types/src/path/entity_path_filter.rs @@ -243,6 +243,22 @@ impl EntityPathFilter { ); } + /// Remove a subtree and any existing rules that it would match. + /// + /// Because most-specific matches win, if we only add a subtree exclusion + /// it can still be overridden by existing inclusions. This method ensures + /// that not only do we add a subtree exclusion, but clear out any existing + /// inclusions or (now redundant) exclusions that would match the subtree. + pub fn remove_subtree_and_matching_rules(&mut self, clone: EntityPath) { + let new_exclusion = EntityPathRule::including_subtree(clone); + + // Remove any rule that is a subtree of the new exclusion. + self.rules + .retain(|rule, _| !new_exclusion.matches(&rule.path)); + + self.rules.insert(new_exclusion, RuleEffect::Exclude); + } + /// Remove any rule for the given entity path (ignoring whether or not that rule includes the subtree). pub fn remove_rule_for(&mut self, entity_path: &EntityPath) { self.rules.retain(|rule, _| rule.path != *entity_path); diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 9d63fda4cd5f..cb8181921648 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -184,15 +184,35 @@ impl SpaceViewContents { } } - pub fn add_entity_exclusion(&self, ctx: &ViewerContext<'_>, rule: EntityPathRule) { - // TODO(emilk): ignore new rule if it is already covered by existing rules (noop) + /// Remove a subtree and any existing rules that it would match. + /// + /// Because most-specific matches win, if we only add a subtree exclusion + /// it can still be overridden by existing inclusions. This method ensures + /// that not only do we add a subtree exclusion, but clear out any existing + /// inclusions or (now redundant) exclusions that would match the subtree. + pub fn remove_subtree_and_matching_rules(&self, ctx: &ViewerContext<'_>, path: EntityPath) { + let mut new_entity_path_filter = self.entity_path_filter.clone(); + new_entity_path_filter.remove_subtree_and_matching_rules(path); + self.set_entity_path_filter(ctx, &new_entity_path_filter); + } + + /// Directly add an exclusion rule to the [`EntityPathFilter`]. + /// + /// This is a direct modification of the filter and will not do any simplification + /// related to overlapping or conflicting rules. + /// + /// If you are trying to remove an entire subtree, prefer using [`Self::remove_subtree_and_matching_rules`]. + pub fn raw_add_entity_exclusion(&self, ctx: &ViewerContext<'_>, rule: EntityPathRule) { let mut new_entity_path_filter = self.entity_path_filter.clone(); new_entity_path_filter.add_rule(RuleEffect::Exclude, rule); self.set_entity_path_filter(ctx, &new_entity_path_filter); } - pub fn add_entity_inclusion(&self, ctx: &ViewerContext<'_>, rule: EntityPathRule) { - // TODO(emilk): ignore new rule if it is already covered by existing rules (noop) + /// Directly add an inclusion rule to the [`EntityPathFilter`]. + /// + /// This is a direct modification of the filter and will not do any simplification + /// related to overlapping or conflicting rules. + pub fn raw_add_entity_inclusion(&self, ctx: &ViewerContext<'_>, rule: EntityPathRule) { let mut new_entity_path_filter = self.entity_path_filter.clone(); new_entity_path_filter.add_rule(RuleEffect::Include, rule); self.set_entity_path_filter(ctx, &new_entity_path_filter); diff --git a/crates/re_viewport/src/context_menu/actions/remove.rs b/crates/re_viewport/src/context_menu/actions/remove.rs index 423bc5157f38..838abe636990 100644 --- a/crates/re_viewport/src/context_menu/actions/remove.rs +++ b/crates/re_viewport/src/context_menu/actions/remove.rs @@ -1,5 +1,4 @@ use re_entity_db::InstancePath; -use re_log_types::EntityPathRule; use re_viewer_context::{ContainerId, Contents, Item, SpaceViewId}; use crate::context_menu::{ContextMenuAction, ContextMenuContext}; @@ -48,9 +47,9 @@ impl ContextMenuAction for RemoveAction { instance_path: &InstancePath, ) { if let Some(space_view) = ctx.viewport_blueprint.space_view(space_view_id) { - space_view.contents.add_entity_exclusion( + space_view.contents.remove_subtree_and_matching_rules( ctx.viewer_context, - EntityPathRule::including_subtree(instance_path.entity_path.clone()), + instance_path.entity_path.clone(), ); } } diff --git a/crates/re_viewport/src/space_view_entity_picker.rs b/crates/re_viewport/src/space_view_entity_picker.rs index 898911edacb8..4b59093a9537 100644 --- a/crates/re_viewport/src/space_view_entity_picker.rs +++ b/crates/re_viewport/src/space_view_entity_picker.rs @@ -211,7 +211,7 @@ fn add_entities_line_ui( let response = ctx.re_ui.small_icon_button(ui, &re_ui::icons::REMOVE); if response.clicked() { - space_view.contents.add_entity_exclusion( + space_view.contents.raw_add_entity_exclusion( ctx, EntityPathRule::including_subtree(entity_tree.path.clone()), ); @@ -230,7 +230,7 @@ fn add_entities_line_ui( let response = ctx.re_ui.small_icon_button(ui, &re_ui::icons::ADD); if response.clicked() { - space_view.contents.add_entity_inclusion( + space_view.contents.raw_add_entity_inclusion( ctx, EntityPathRule::including_subtree(entity_tree.path.clone()), ); diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 32896c41d78a..09738b7e9312 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -5,7 +5,6 @@ use smallvec::SmallVec; use re_entity_db::InstancePath; use re_log_types::EntityPath; -use re_log_types::EntityPathRule; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::Visible; use re_ui::{drag_and_drop::DropTarget, list_item::ListItem, ReUi}; @@ -600,10 +599,9 @@ impl Viewport<'_, '_> { "Remove group and all its children from the space view", ); if response.clicked() { - space_view.contents.add_entity_exclusion( - ctx, - EntityPathRule::including_subtree(entity_path.clone()), - ); + space_view + .contents + .remove_subtree_and_matching_rules(ctx, entity_path.clone()); } response | vis_response From b64d55f7835f0343abf674d8a1424073d59eee45 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 29 Mar 2024 13:58:23 +0100 Subject: [PATCH 144/508] Improve the selection panel for stores and data sources (#5719) --- Cargo.lock | 1 + crates/re_data_source/src/load_file.rs | 1 + crates/re_data_ui/src/data_source.rs | 12 +- crates/re_data_ui/src/entity_db.rs | 151 +++++---- crates/re_data_ui/src/item_ui.rs | 16 +- crates/re_data_ui/src/log_msg.rs | 28 +- crates/re_entity_db/src/entity_db.rs | 60 +++- crates/re_entity_db/src/store_bundle.rs | 1 + crates/re_log_encoding/src/decoder/mod.rs | 1 + crates/re_log_encoding/src/decoder/stream.rs | 1 + crates/re_log_types/src/lib.rs | 10 + crates/re_sdk/src/lib.rs | 1 + crates/re_sdk/src/recording_stream.rs | 1 + crates/re_space_view/src/space_view.rs | 8 +- .../re_space_view/src/space_view_contents.rs | 4 +- crates/re_ui/src/lib.rs | 11 +- crates/re_viewer/src/app.rs | 100 ++++-- crates/re_viewer/src/app_state.rs | 6 +- crates/re_viewer/src/blueprint/mod.rs | 4 +- crates/re_viewer/src/lib.rs | 1 - crates/re_viewer/src/ui/blueprint_panel.rs | 45 ++- crates/re_viewer/src/ui/memory_panel.rs | 3 +- crates/re_viewer_context/Cargo.toml | 1 + .../re_viewer_context/src/command_sender.rs | 6 +- crates/re_viewer_context/src/lib.rs | 2 + crates/re_viewer_context/src/store_context.rs | 20 +- .../src/store_hub.rs | 299 ++++++++++-------- docs/content/getting-started/what-is-rerun.md | 1 + 28 files changed, 510 insertions(+), 285 deletions(-) rename crates/{re_viewer => re_viewer_context}/src/store_hub.rs (80%) diff --git a/Cargo.lock b/Cargo.lock index ea2e096818c7..a4d26cdce758 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5127,6 +5127,7 @@ dependencies = [ "re_log", "re_log_types", "re_query", + "re_query_cache", "re_renderer", "re_smart_channel", "re_string_interner", diff --git a/crates/re_data_source/src/load_file.rs b/crates/re_data_source/src/load_file.rs index 158ec9028365..a8b653560e7a 100644 --- a/crates/re_data_source/src/load_file.rs +++ b/crates/re_data_source/src/load_file.rs @@ -119,6 +119,7 @@ pub(crate) fn prepare_store_info( info: re_log_types::StoreInfo { application_id: app_id.clone(), store_id: store_id.clone(), + cloned_from: None, is_official_example: false, started: re_log_types::Time::now(), store_source, diff --git a/crates/re_data_ui/src/data_source.rs b/crates/re_data_ui/src/data_source.rs index 08ed29e80ab8..1e3f4116bf9f 100644 --- a/crates/re_data_ui/src/data_source.rs +++ b/crates/re_data_ui/src/data_source.rs @@ -18,7 +18,7 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { return; } - // TODO(emilk): show if we're still connected to this data source + // TODO(emilk): show whether we're still connected to this data source // Find all stores from this data source // (e.g. find the recordings and blueprint in this .rrd file). @@ -30,6 +30,12 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { .bundle .entity_dbs_from_channel_source(self) { + let is_clone = other.cloned_from().is_some(); + if is_clone { + // Clones are not really from this data source (e.g. a cloned blueprint + continue; + } + match other.store_kind() { StoreKind::Recording => { recordings.push(other); @@ -42,7 +48,7 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { if !recordings.is_empty() { ui.add_space(8.0); - ui.strong("Recordings in this data source"); + ui.strong("Recordings from this data source"); ui.indent("recordings", |ui| { ui.spacing_mut().item_spacing.y = 0.0; for entity_db in recordings { @@ -53,7 +59,7 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { if !blueprints.is_empty() { ui.add_space(8.0); - ui.strong("Blueprints in this data source"); + ui.strong("Blueprints from this data source"); ui.indent("blueprints", |ui| { ui.spacing_mut().item_spacing.y = 0.0; for entity_db in blueprints { diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index cc2214fbb091..a47eaf51b2d4 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -3,7 +3,7 @@ use re_log_types::StoreKind; use re_types::SizeBytes; use re_viewer_context::{UiVerbosity, ViewerContext}; -use crate::item_ui::{data_source_button_ui, entity_db_button_ui}; +use crate::item_ui::data_source_button_ui; impl crate::DataUi for EntityDb { fn data_ui( @@ -17,6 +17,7 @@ impl crate::DataUi for EntityDb { let re_ui = &ctx.re_ui; if verbosity == UiVerbosity::Small { + // TODO(emilk): standardize this formatting with that in `entity_db_button_ui` let mut string = self.store_id().to_string(); if let Some(data_source) = &self.data_source { string += &format!(", {data_source}"); @@ -39,20 +40,23 @@ impl crate::DataUi for EntityDb { let re_log_types::StoreInfo { application_id, store_id: _, + cloned_from, is_official_example: _, started, store_source, store_kind, } = store_info; + if let Some(cloned_from) = cloned_from { + re_ui.grid_left_hand_label(ui, "Clone of"); + crate::item_ui::store_id_button_ui(ctx, ui, cloned_from); + ui.end_row(); + } + re_ui.grid_left_hand_label(ui, "Application ID"); ui.label(application_id.to_string()); ui.end_row(); - re_ui.grid_left_hand_label(ui, "Recording started"); - ui.label(started.format(ctx.app_options.time_zone)); - ui.end_row(); - re_ui.grid_left_hand_label(ui, "Source"); ui.label(store_source.to_string()); ui.end_row(); @@ -60,6 +64,19 @@ impl crate::DataUi for EntityDb { re_ui.grid_left_hand_label(ui, "Kind"); ui.label(store_kind.to_string()); ui.end_row(); + + re_ui.grid_left_hand_label(ui, "Recording started"); + ui.label(started.format(ctx.app_options.time_zone)); + ui.end_row(); + } + + if let Some(latest_row_id) = self.latest_row_id() { + if let Ok(nanos_since_epoch) = i64::try_from(latest_row_id.nanoseconds_since_epoch()) { + let time = re_log_types::Time::from_ns_since_epoch(nanos_since_epoch); + re_ui.grid_left_hand_label(ui, "Last modified at"); + ui.label(time.format(ctx.app_options.time_zone)); + ui.end_row(); + } } { @@ -78,85 +95,61 @@ impl crate::DataUi for EntityDb { } }); - if ctx.store_context.is_active(self.store_id()) { - ui.add_space(8.0); - match self.store_kind() { - StoreKind::Recording => { - ui.label("This is the active recording"); - } - StoreKind::Blueprint => { - ui.label("This is the active blueprint"); - } - } - } - - if ctx.store_context.is_default_blueprint(self.store_id()) { - ui.add_space(8.0); - ui.label("This is the default blueprint") - .on_hover_text("When you reset the blueprint for the app, this blueprint will be used as the template."); - }; - - if verbosity == UiVerbosity::Full { - sibling_stores_ui(ctx, ui, self); - } - } -} + let hub = ctx.store_context.hub; -/// Show the other stores in the same data source. -fn sibling_stores_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui, entity_db: &EntityDb) { - let Some(data_source) = &entity_db.data_source else { - return; - }; - - // Find other stores from the same data source - // (e.g. find the blueprint in this .rrd file, if any). - let mut other_recordings = vec![]; - let mut other_blueprints = vec![]; - - for other in ctx - .store_context - .bundle - .entity_dbs_from_channel_source(data_source) - { - if other.store_id() == entity_db.store_id() { - continue; - } - match other.store_kind() { + match self.store_kind() { StoreKind::Recording => { - other_recordings.push(other); + if Some(self.store_id()) == hub.active_recording_id() { + ui.add_space(8.0); + ui.label("This is the active recording"); + } } StoreKind::Blueprint => { - other_blueprints.push(other); - } - } - } - - if !other_recordings.is_empty() { - ui.add_space(8.0); - if entity_db.store_kind() == StoreKind::Recording { - ui.strong("Other recordings in this data source"); - } else { - ui.strong("Recordings in this data source"); - } - ui.indent("recordings", |ui| { - ui.spacing_mut().item_spacing.y = 0.0; - for entity_db in other_recordings { - entity_db_button_ui(ctx, ui, entity_db, true); + let active_app_id = &ctx.store_context.app_id; + let is_active_app_id = self.app_id() == Some(active_app_id); + + if is_active_app_id { + let is_default = + hub.default_blueprint_id_for_app(active_app_id) == Some(self.store_id()); + let is_active = + hub.active_blueprint_id_for_app(active_app_id) == Some(self.store_id()); + + match (is_default, is_active) { + (false, false) => {} + (true, false) => { + ui.add_space(8.0); + ui.label("This is the default blueprint for the current application."); + + if let Some(active_blueprint) = hub + .active_blueprint_id_for_app(active_app_id) + .and_then(|id| hub.store_bundle().get(id)) + { + if active_blueprint.cloned_from() == Some(self.store_id()) { + // The active blueprint is a clone of the selected blueprint. + if self.latest_row_id() == active_blueprint.latest_row_id() { + ui.label( + "The active blueprint is a clone of this blueprint.", + ); + } else { + ui.label("The active blueprint is a modified clone of this blueprint."); + } + } + } + } + (false, true) => { + ui.add_space(8.0); + ui.label(format!("This is the active blueprint for the current application, '{active_app_id}'")); + } + (true, true) => { + ui.add_space(8.0); + ui.label(format!("This is both the active and default blueprint for the current application, '{active_app_id}'")); + } + } + } else { + ui.add_space(8.0); + ui.label("This blueprint is not for the active application"); + } } - }); - } - if !other_blueprints.is_empty() { - ui.add_space(8.0); - if entity_db.store_kind() == StoreKind::Blueprint { - ui.strong("Other blueprints in this data source"); - } else { - ui.strong("Blueprints in this data source"); } - ui.indent("blueprints", |ui| { - ui.spacing_mut().item_spacing.y = 0.0; - for entity_db in other_blueprints { - entity_db_button_ui(ctx, ui, entity_db, true); - } - }); } } diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 87950372314c..24184b56645c 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -579,6 +579,18 @@ pub fn data_source_button_ui( cursor_interact_with_selectable(ctx, response, item) } +pub fn store_id_button_ui( + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + store_id: &re_log_types::StoreId, +) { + if let Some(entity_db) = ctx.store_context.bundle.get(store_id) { + entity_db_button_ui(ctx, ui, entity_db, true); + } else { + ui.label(store_id.to_string()); + } +} + /// Show button for a store (recording or blueprint). /// /// You can set `include_app_id` to hide the App Id, but usually you want to show it. @@ -599,7 +611,7 @@ pub fn entity_db_button_ui( String::default() }; - let time = entity_db + let creation_time = entity_db .store_info() .and_then(|info| { info.started @@ -608,7 +620,7 @@ pub fn entity_db_button_ui( .unwrap_or("".to_owned()); let size = re_format::format_bytes(entity_db.total_size_bytes() as _); - let title = format!("{app_id_prefix}{time} - {size}"); + let title = format!("{app_id_prefix}{creation_time} - {size}"); let store_id = entity_db.store_id().clone(); let item = re_viewer_context::Item::StoreId(store_id.clone()); diff --git a/crates/re_data_ui/src/log_msg.rs b/crates/re_data_ui/src/log_msg.rs index 6f7ce45822ad..a6636b5983e3 100644 --- a/crates/re_data_ui/src/log_msg.rs +++ b/crates/re_data_ui/src/log_msg.rs @@ -34,45 +34,55 @@ impl DataUi for LogMsg { impl DataUi for SetStoreInfo { fn data_ui( &self, - _ctx: &ViewerContext<'_>, + ctx: &ViewerContext<'_>, ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, _store: &re_data_store::DataStore, ) { - ui.code("SetStoreInfo"); let SetStoreInfo { row_id: _, info } = self; let StoreInfo { application_id, store_id, + cloned_from, started, store_source, is_official_example, store_kind, } = info; + let re_ui = &ctx.re_ui; + + ui.code("SetStoreInfo"); + egui::Grid::new("fields").num_columns(2).show(ui, |ui| { - ui.monospace("application_id:"); + re_ui.grid_left_hand_label(ui, "application_id:"); ui.label(application_id.to_string()); ui.end_row(); - ui.monospace("store_id:"); + re_ui.grid_left_hand_label(ui, "store_id:"); ui.label(format!("{store_id:?}")); ui.end_row(); - ui.monospace("started:"); - ui.label(started.format(_ctx.app_options.time_zone)); + re_ui.grid_left_hand_label(ui, "cloned_from"); + if let Some(cloned_from) = cloned_from { + crate::item_ui::store_id_button_ui(ctx, ui, cloned_from); + } + ui.end_row(); + + re_ui.grid_left_hand_label(ui, "started:"); + ui.label(started.format(ctx.app_options.time_zone)); ui.end_row(); - ui.monospace("store_source:"); + re_ui.grid_left_hand_label(ui, "store_source:"); ui.label(format!("{store_source}")); ui.end_row(); - ui.monospace("is_official_example:"); + re_ui.grid_left_hand_label(ui, "is_official_example:"); ui.label(format!("{is_official_example}")); ui.end_row(); - ui.monospace("store_kind:"); + re_ui.grid_left_hand_label(ui, "store_kind:"); ui.label(format!("{store_kind}")); ui.end_row(); }); diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index a8283459e0fa..f52bc629bbed 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -83,6 +83,8 @@ fn insert_row_with_retries( /// NOTE: all mutation is to be done via public functions! pub struct EntityDb { /// Set by whomever created this [`EntityDb`]. + /// + /// Clones of an [`EntityDb`] gets a `None` source. pub data_source: Option, /// Comes in a special message, [`LogMsg::SetStoreInfo`]. @@ -91,6 +93,11 @@ pub struct EntityDb { /// Keeps track of the last time data was inserted into this store (viewer wall-clock). last_modified_at: web_time::Instant, + /// The highest `RowId` in the store, + /// which corresponds to the last edit time. + /// Ignores deletions. + latest_row_id: Option, + /// In many places we just store the hashes, so we need a way to translate back. entity_path_from_hash: IntMap, @@ -126,6 +133,7 @@ impl EntityDb { data_source: None, set_store_info: None, last_modified_at: web_time::Instant::now(), + latest_row_id: None, entity_path_from_hash: Default::default(), times_per_timeline: Default::default(), tree: crate::EntityTree::root(), @@ -188,14 +196,29 @@ impl EntityDb { &self.data_store } + #[inline] pub fn store_kind(&self) -> StoreKind { self.store_id().kind } + #[inline] pub fn store_id(&self) -> &StoreId { self.data_store.id() } + /// If this entity db is the result of a clone, which store was it cloned from? + /// + /// A cloned store always gets a new unique ID. + /// + /// We currently only use entity db cloning for blueprints: + /// when we activate a _default_ blueprint that was received on the wire (e.g. from a recording), + /// we clone it and make the clone the _active_ blueprint. + /// This means all active blueprints are clones. + #[inline] + pub fn cloned_from(&self) -> Option<&StoreId> { + self.store_info().and_then(|info| info.cloned_from.as_ref()) + } + pub fn timelines(&self) -> impl ExactSizeIterator { self.times_per_timeline().keys() } @@ -220,14 +243,25 @@ impl EntityDb { /// Return the current `StoreGeneration`. This can be used to determine whether the /// database has been modified since the last time it was queried. + #[inline] pub fn generation(&self) -> re_data_store::StoreGeneration { self.data_store.generation() } + #[inline] pub fn last_modified_at(&self) -> web_time::Instant { self.last_modified_at } + /// The highest `RowId` in the store, + /// which corresponds to the last edit time. + /// Ignores deletions. + #[inline] + pub fn latest_row_id(&self) -> Option { + self.latest_row_id + } + + #[inline] pub fn is_empty(&self) -> bool { self.set_store_info.is_none() && self.num_rows() == 0 } @@ -303,6 +337,13 @@ impl EntityDb { self.register_entity_path(&row.entity_path); + if self + .latest_row_id + .map_or(true, |latest| latest < row.row_id) + { + self.latest_row_id = Some(row.row_id); + } + // ## RowId duplication // // We shouldn't be attempting to retry in this instance: a duplicated RowId at this stage @@ -489,6 +530,7 @@ impl EntityDb { data_source: _, set_store_info: _, last_modified_at: _, + latest_row_id: _, entity_path_from_hash: _, times_per_timeline, tree, @@ -564,15 +606,29 @@ impl EntityDb { messages } - /// Make a clone of this [`EntityDb`] with a different [`StoreId`]. + /// Make a clone of this [`EntityDb`], assigning it a new [`StoreId`]. pub fn clone_with_new_id(&self, new_id: StoreId) -> Result { + re_tracing::profile_function!(); + self.store().sort_indices_if_needed(); let mut new_db = EntityDb::new(new_id.clone()); + new_db.last_modified_at = self.last_modified_at; + new_db.latest_row_id = self.latest_row_id; + + // We do NOT clone the `data_source`, because the reason we clone an entity db + // is so that we can modify it, and then it would be wrong to say its from the same source. + // Specifically: if we load a blueprint from an `.rdd`, then modify it heavily and save it, + // it would be wrong to claim that this was the blueprint from that `.rrd`, + // and it would confuse the user. + // TODO(emilk): maybe we should use a special `Cloned` data source, + // wrapping either the original source, the original StoreId, or both. + if let Some(store_info) = self.store_info() { let mut new_info = store_info.clone(); new_info.store_id = new_id; + new_info.cloned_from = Some(self.store_id().clone()); new_db.set_store_info(SetStoreInfo { row_id: RowId::new(), @@ -580,8 +636,6 @@ impl EntityDb { }); } - new_db.data_source = self.data_source.clone(); - for row in self.store().to_rows()? { new_db.add_data_row(row)?; } diff --git a/crates/re_entity_db/src/store_bundle.rs b/crates/re_entity_db/src/store_bundle.rs index ef90623a3032..2e4ee2b562ea 100644 --- a/crates/re_entity_db/src/store_bundle.rs +++ b/crates/re_entity_db/src/store_bundle.rs @@ -103,6 +103,7 @@ impl StoreBundle { info: re_log_types::StoreInfo { application_id: id.as_str().into(), store_id: id.clone(), + cloned_from: None, is_official_example: false, started: re_log_types::Time::now(), store_source: re_log_types::StoreSource::Other("viewer".to_owned()), diff --git a/crates/re_log_encoding/src/decoder/mod.rs b/crates/re_log_encoding/src/decoder/mod.rs index fc278988e430..6f742cfa110e 100644 --- a/crates/re_log_encoding/src/decoder/mod.rs +++ b/crates/re_log_encoding/src/decoder/mod.rs @@ -232,6 +232,7 @@ fn test_encode_decode() { info: StoreInfo { application_id: ApplicationId("test".to_owned()), store_id: StoreId::random(StoreKind::Recording), + cloned_from: None, is_official_example: true, started: Time::now(), store_source: StoreSource::RustSdk { diff --git a/crates/re_log_encoding/src/decoder/stream.rs b/crates/re_log_encoding/src/decoder/stream.rs index 0840bd9ae439..d6b4111130af 100644 --- a/crates/re_log_encoding/src/decoder/stream.rs +++ b/crates/re_log_encoding/src/decoder/stream.rs @@ -235,6 +235,7 @@ mod tests { info: StoreInfo { application_id: ApplicationId::unknown(), store_id: StoreId::from_string(StoreKind::Recording, "test".into()), + cloned_from: None, is_official_example: false, started: Time::from_ns_since_epoch(0), store_source: StoreSource::Unknown, diff --git a/crates/re_log_types/src/lib.rs b/crates/re_log_types/src/lib.rs index 3ebbbd9cf226..df17ee4a0caa 100644 --- a/crates/re_log_types/src/lib.rs +++ b/crates/re_log_types/src/lib.rs @@ -330,6 +330,16 @@ pub struct StoreInfo { /// Should be unique for each recording. pub store_id: StoreId, + /// If this store is the result of a clone, which store was it cloned from? + /// + /// A cloned store always gets a new unique ID. + /// + /// We currently only clone stores for blueprints: + /// when we receive a _default_ blueprints on the wire (e.g. from a recording), + /// we clone it and make the clone the _active_ blueprint. + /// This means all active blueprints are clones. + pub cloned_from: Option, + /// True if the recording is one of the official Rerun examples. pub is_official_example: bool, diff --git a/crates/re_sdk/src/lib.rs b/crates/re_sdk/src/lib.rs index c8bb35319b59..21f533a3a113 100644 --- a/crates/re_sdk/src/lib.rs +++ b/crates/re_sdk/src/lib.rs @@ -175,6 +175,7 @@ pub fn new_store_info( re_log_types::StoreInfo { application_id: application_id.into(), store_id: StoreId::random(StoreKind::Recording), + cloned_from: None, is_official_example: called_from_official_rust_example(), started: re_log_types::Time::now(), store_source: re_log_types::StoreSource::RustSdk { diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs index b229c3094357..205e1ae8cabf 100644 --- a/crates/re_sdk/src/recording_stream.rs +++ b/crates/re_sdk/src/recording_stream.rs @@ -552,6 +552,7 @@ impl RecordingStreamBuilder { let store_info = StoreInfo { application_id, store_id, + cloned_from: None, is_official_example, started: Time::now(), store_source, diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 67f22966fff0..7feec0222a3b 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -554,7 +554,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), - default_blueprint: None, + hub: &re_viewer_context::StoreHub::test_hub(), }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -598,7 +598,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), - default_blueprint: None, + hub: &re_viewer_context::StoreHub::test_hub(), }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -648,7 +648,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), - default_blueprint: None, + hub: &re_viewer_context::StoreHub::test_hub(), }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); @@ -921,7 +921,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), - default_blueprint: None, + hub: &re_viewer_context::StoreHub::test_hub(), }; let mut query_result = space_view .contents diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index cb8181921648..a52dde9b327b 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -631,7 +631,7 @@ impl<'a> PropertyResolver for DataQueryPropertyResolver<'a> { mod tests { use re_entity_db::EntityDb; use re_log_types::{example_components::MyPoint, DataRow, RowId, StoreId, TimePoint, Timeline}; - use re_viewer_context::{StoreContext, VisualizableEntities}; + use re_viewer_context::{StoreContext, StoreHub, VisualizableEntities}; use super::*; @@ -682,7 +682,7 @@ mod tests { blueprint: &blueprint, recording: &recording, bundle: &Default::default(), - default_blueprint: None, + hub: &StoreHub::test_hub(), }; struct Scenario { diff --git a/crates/re_ui/src/lib.rs b/crates/re_ui/src/lib.rs index 051a595e83eb..6bbe9b05ca7b 100644 --- a/crates/re_ui/src/lib.rs +++ b/crates/re_ui/src/lib.rs @@ -349,11 +349,14 @@ impl ReUi { #[allow(clippy::unused_self)] pub fn small_icon_button(&self, ui: &mut egui::Ui, icon: &Icon) -> egui::Response { + ui.add(self.small_icon_button_widget(ui, icon)) + } + + #[allow(clippy::unused_self)] + pub fn small_icon_button_widget(&self, ui: &egui::Ui, icon: &Icon) -> egui::ImageButton<'_> { // TODO(emilk): change color and size on hover - ui.add( - egui::ImageButton::new(icon.as_image().fit_to_exact_size(Self::small_icon_size())) - .tint(ui.visuals().widgets.inactive.fg_stroke.color), - ) + egui::ImageButton::new(icon.as_image().fit_to_exact_size(Self::small_icon_size())) + .tint(ui.visuals().widgets.inactive.fg_stroke.color) } #[allow(clippy::unused_self)] diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index d7dae6fa977d..4986a5354734 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -5,17 +5,14 @@ use re_renderer::WgpuResourcePoolStatistics; use re_smart_channel::{ReceiveSet, SmartChannelSource}; use re_ui::{toasts, UICommand, UICommandSender}; use re_viewer_context::{ - command_channel, AppOptions, CommandReceiver, CommandSender, ComponentUiRegistry, PlayState, - SpaceViewClass, SpaceViewClassRegistry, SpaceViewClassRegistryError, StoreContext, - SystemCommand, SystemCommandSender, + command_channel, + store_hub::{BlueprintPersistence, StoreHub, StoreHubStats}, + AppOptions, CommandReceiver, CommandSender, ComponentUiRegistry, PlayState, SpaceViewClass, + SpaceViewClassRegistry, SpaceViewClassRegistryError, StoreContext, SystemCommand, + SystemCommandSender, }; -use crate::{ - app_blueprint::AppBlueprint, - background_tasks::BackgroundTasks, - store_hub::{StoreHub, StoreHubStats}, - AppState, -}; +use crate::{app_blueprint::AppBlueprint, background_tasks::BackgroundTasks, AppState}; // ---------------------------------------------------------------------------- @@ -234,7 +231,10 @@ impl App { open_files_promise: Default::default(), state, background_tasks: Default::default(), - store_hub: Some(StoreHub::new()), + store_hub: Some(StoreHub::new( + blueprint_loader(), + &crate::app_blueprint::setup_welcome_screen_blueprint, + )), toasts: toasts::Toasts::new(), memory_panel: Default::default(), memory_panel_open: false, @@ -337,7 +337,7 @@ impl App { ) { match cmd { SystemCommand::ActivateRecording(store_id) => { - store_hub.activate_recording(store_id); + store_hub.set_activate_recording(store_id); } SystemCommand::CloseStore(store_id) => { store_hub.remove(&store_id); @@ -365,12 +365,6 @@ impl App { } } - SystemCommand::LoadStoreDb(entity_db) => { - let store_id = entity_db.store_id().clone(); - store_hub.insert_entity_db(entity_db); - store_hub.set_active_recording_id(store_id); - } - SystemCommand::ResetViewer => self.reset(store_hub, egui_ctx), SystemCommand::ClearAndGenerateBlueprint => { re_log::debug!("Clear and generate new blueprint"); @@ -379,7 +373,7 @@ impl App { store_hub.clear_default_blueprint(); store_hub.clear_active_blueprint(); } - SystemCommand::ResetBlueprint => { + SystemCommand::ClearActiveBlueprint => { // By clearing the blueprint the default blueprint will be restored // at the beginning of the next frame. re_log::debug!("Reset blueprint to default"); @@ -991,11 +985,11 @@ impl App { ); let app_id = info.application_id.clone(); if cmd.make_default { - store_hub.set_default_blueprint_for_app_id(store_id, &app_id); + store_hub.set_default_blueprint_for_app(&app_id, store_id); } if cmd.make_active { store_hub - .make_blueprint_active_for_app_id(store_id, &app_id) + .set_cloned_blueprint_active_for_app(&app_id, store_id) .unwrap_or_else(|err| { re_log::warn!("Failed to make blueprint active: {err}"); }); @@ -1148,7 +1142,7 @@ impl App { /// in the users face. fn should_show_welcome_screen(&mut self, store_hub: &StoreHub) -> bool { // Don't show the welcome screen if we have actual data to display. - if store_hub.active_recording().is_some() || store_hub.active_application_id().is_some() { + if store_hub.active_recording().is_some() || store_hub.active_app().is_some() { return false; } @@ -1196,6 +1190,68 @@ impl App { } } +#[cfg(target_arch = "wasm32")] +fn blueprint_loader() -> BlueprintPersistence { + // TODO(#2579): implement persistence for web + BlueprintPersistence { + loader: None, + saver: None, + } +} + +#[cfg(not(target_arch = "wasm32"))] +fn blueprint_loader() -> BlueprintPersistence { + use re_entity_db::StoreBundle; + use re_log_types::ApplicationId; + + fn load_blueprint_from_disk(app_id: &ApplicationId) -> anyhow::Result> { + let blueprint_path = crate::saving::default_blueprint_path(app_id)?; + if !blueprint_path.exists() { + return Ok(None); + } + + re_log::debug!("Trying to load blueprint for {app_id} from {blueprint_path:?}"); + + let with_notifications = false; + + if let Some(bundle) = + crate::loading::load_blueprint_file(&blueprint_path, with_notifications) + { + for store in bundle.entity_dbs() { + if store.store_kind() == StoreKind::Blueprint + && !crate::blueprint::is_valid_blueprint(store) + { + re_log::warn_once!("Blueprint for {app_id} at {blueprint_path:?} appears invalid - will ignore. This is expected if you have just upgraded Rerun versions."); + return Ok(None); + } + } + Ok(Some(bundle)) + } else { + Ok(None) + } + } + + #[cfg(not(target_arch = "wasm32"))] + fn save_blueprint_to_disk(app_id: &ApplicationId, blueprint: &EntityDb) -> anyhow::Result<()> { + let blueprint_path = crate::saving::default_blueprint_path(app_id)?; + + let messages = blueprint.to_messages(None)?; + + // TODO(jleibs): Should we push this into a background thread? Blueprints should generally + // be small & fast to save, but maybe not once we start adding big pieces of user data? + crate::saving::encode_to_file(&blueprint_path, messages.iter())?; + + re_log::debug!("Saved blueprint for {app_id} to {blueprint_path:?}"); + + Ok(()) + } + + BlueprintPersistence { + loader: Some(Box::new(load_blueprint_from_disk)), + saver: Some(Box::new(save_blueprint_to_disk)), + } +} + impl eframe::App for App { fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] { [0.0; 4] // transparent so we can get rounded corners when doing [`re_ui::CUSTOM_WINDOW_DECORATIONS`] @@ -1313,7 +1369,7 @@ impl eframe::App for App { // Heuristic to set the app_id to the welcome screen blueprint. // Must be called before `read_context` below. if self.should_show_welcome_screen(&store_hub) { - store_hub.set_active_app_id(StoreHub::welcome_screen_app_id()); + store_hub.set_active_app(StoreHub::welcome_screen_app_id()); } let store_context = store_hub.read_context(); diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 65e38595b923..425b7be544c1 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -8,12 +8,12 @@ use re_space_view::{determine_visualizable_entities, DataQuery as _, PropertyRes use re_viewer_context::{ blueprint_timeline, AppOptions, ApplicationSelectionState, Caches, CommandSender, ComponentUiRegistry, PlayState, RecordingConfig, SpaceViewClassRegistry, StoreContext, - SystemCommandSender as _, ViewerContext, + StoreHub, SystemCommandSender as _, ViewerContext, }; use re_viewport::{Viewport, ViewportBlueprint, ViewportState}; use crate::ui::recordings_panel_ui; -use crate::{app_blueprint::AppBlueprint, store_hub::StoreHub, ui::blueprint_panel_ui}; +use crate::{app_blueprint::AppBlueprint, ui::blueprint_panel_ui}; const WATERMARK: bool = false; // Nice for recording media material @@ -149,7 +149,7 @@ impl AppState { // If the blueprint is invalid, reset it. if viewport.blueprint.is_invalid() { re_log::warn!("Incompatible blueprint detected. Resetting to default."); - command_sender.send_system(re_viewer_context::SystemCommand::ResetBlueprint); + command_sender.send_system(re_viewer_context::SystemCommand::ClearActiveBlueprint); // The blueprint isn't valid so nothing past this is going to work properly. // we might as well return and it will get fixed on the next frame. diff --git a/crates/re_viewer/src/blueprint/mod.rs b/crates/re_viewer/src/blueprint/mod.rs index 542d93ba57ec..7a8d8c101520 100644 --- a/crates/re_viewer/src/blueprint/mod.rs +++ b/crates/re_viewer/src/blueprint/mod.rs @@ -1,7 +1,5 @@ -#[cfg(not(target_arch = "wasm32"))] pub mod validation; -#[cfg(not(target_arch = "wasm32"))] + mod validation_gen; -#[cfg(not(target_arch = "wasm32"))] pub use validation_gen::is_valid_blueprint; diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 796125b26241..1c9b094191ad 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -12,7 +12,6 @@ pub mod env_vars; mod loading; mod saving; mod screenshotter; -mod store_hub; mod ui; mod viewer_analytics; diff --git a/crates/re_viewer/src/ui/blueprint_panel.rs b/crates/re_viewer/src/ui/blueprint_panel.rs index 3efb9248cf5e..823acee982ec 100644 --- a/crates/re_viewer/src/ui/blueprint_panel.rs +++ b/crates/re_viewer/src/ui/blueprint_panel.rs @@ -25,19 +25,44 @@ pub fn blueprint_panel_ui( } fn reset_blueprint_button_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { - let hover_text = if ctx.store_context.default_blueprint.is_some() { - "Reset to the default blueprint for this app" + let default_blueprint_id = ctx + .store_context + .hub + .default_blueprint_id_for_app(&ctx.store_context.app_id); + + let default_blueprint = default_blueprint_id.and_then(|id| ctx.store_context.bundle.get(id)); + + let mut disabled_reason = None; + + if let Some(default_blueprint) = default_blueprint { + let active_is_clone_of_default = + Some(default_blueprint.store_id()) == ctx.store_context.blueprint.cloned_from(); + let last_modified_at_the_same_time = + default_blueprint.latest_row_id() == ctx.store_context.blueprint.latest_row_id(); + if active_is_clone_of_default && last_modified_at_the_same_time { + disabled_reason = Some("No modifications has been made"); + } + } + + let enabled = disabled_reason.is_none(); + let response = ui.add_enabled( + enabled, + ctx.re_ui.small_icon_button_widget(ui, &re_ui::icons::RESET), + ); + + let response = if let Some(disabled_reason) = disabled_reason { + response.on_disabled_hover_text(disabled_reason) } else { - "Re-populate viewport with automatically chosen space views" + let hover_text = if default_blueprint_id.is_some() { + "Reset to the default blueprint for this app" + } else { + "Re-populate viewport with automatically chosen space views" + }; + response.on_hover_text(hover_text) }; - if ctx - .re_ui - .small_icon_button(ui, &re_ui::icons::RESET) - .on_hover_text(hover_text) - .clicked() - { + if response.clicked() { ctx.command_sender - .send_system(re_viewer_context::SystemCommand::ResetBlueprint); + .send_system(re_viewer_context::SystemCommand::ClearActiveBlueprint); } } diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index 393009f3815f..47918f38dcd6 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -5,8 +5,9 @@ use re_format::{format_bytes, format_number}; use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse}; use re_query_cache::{CachedComponentStats, CachedEntityStats, CachesStats}; use re_renderer::WgpuResourcePoolStatistics; +use re_viewer_context::store_hub::StoreHubStats; -use crate::{env_vars::RERUN_TRACK_ALLOCATIONS, store_hub::StoreHubStats}; +use crate::env_vars::RERUN_TRACK_ALLOCATIONS; // ---------------------------------------------------------------------------- diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index c7cd22ffdc79..f8273dda4419 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -21,6 +21,7 @@ re_data_store.workspace = true re_entity_db = { workspace = true, features = ["serde"] } re_log_types.workspace = true re_log.workspace = true +re_query_cache.workspace = true re_query.workspace = true re_renderer.workspace = true re_smart_channel.workspace = true diff --git a/crates/re_viewer_context/src/command_sender.rs b/crates/re_viewer_context/src/command_sender.rs index 68a3ab54fa95..d35e11f3a8f8 100644 --- a/crates/re_viewer_context/src/command_sender.rs +++ b/crates/re_viewer_context/src/command_sender.rs @@ -1,5 +1,4 @@ use re_data_source::DataSource; -use re_entity_db::EntityDb; use re_log_types::{DataRow, StoreId}; use re_ui::{UICommand, UICommandSender}; @@ -11,14 +10,11 @@ pub enum SystemCommand { /// Load some data. LoadDataSource(DataSource), - /// Load some log messages. - LoadStoreDb(EntityDb), - /// Reset the `Viewer` to the default state ResetViewer, /// Reset the `Blueprint` to the default state - ResetBlueprint, + ClearActiveBlueprint, /// Clear the blueprint and generate a new one ClearAndGenerateBlueprint, diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 27b2950552ab..a8413981515f 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -17,6 +17,7 @@ mod selection_history; mod selection_state; mod space_view; mod store_context; +pub mod store_hub; mod tensor; mod time_control; mod typed_entity_collections; @@ -58,6 +59,7 @@ pub use space_view::{ VisualizerQueryInfo, VisualizerSystem, }; pub use store_context::StoreContext; +pub use store_hub::StoreHub; pub use tensor::{TensorDecodeCache, TensorStats, TensorStatsCache}; pub use time_control::{Looping, PlayState, TimeControl, TimeView}; pub use typed_entity_collections::{ diff --git a/crates/re_viewer_context/src/store_context.rs b/crates/re_viewer_context/src/store_context.rs index 5e77e57df839..45891cd87e12 100644 --- a/crates/re_viewer_context/src/store_context.rs +++ b/crates/re_viewer_context/src/store_context.rs @@ -1,32 +1,32 @@ use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId}; +use crate::StoreHub; + /// The current Blueprint and Recording being displayed by the viewer pub struct StoreContext<'a> { - /// The `app_id` of the current recording + /// The `app_id` of the current recording. pub app_id: ApplicationId, - /// The current active recording. + /// The current active blueprint. pub blueprint: &'a EntityDb, - /// The current open recording. + /// The current active recording. /// - /// If none is open, this will point to a dummy empty recording. + /// If none is active, this will point to a dummy empty recording. pub recording: &'a EntityDb, /// All the loaded recordings and blueprints. + /// + /// This is the same bundle as is in [`Self::hub`], but extracted for ease-of-access. pub bundle: &'a StoreBundle, - /// The current default blueprint - pub default_blueprint: Option<&'a StoreId>, + /// The store hub, which keeps track of all the default and active blueprints, among other things. + pub hub: &'a StoreHub, } impl StoreContext<'_> { pub fn is_active(&self, store_id: &StoreId) -> bool { self.recording.store_id() == store_id || self.blueprint.store_id() == store_id } - - pub fn is_default_blueprint(&self, store_id: &StoreId) -> bool { - self.default_blueprint == Some(store_id) - } } diff --git a/crates/re_viewer/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs similarity index 80% rename from crates/re_viewer/src/store_hub.rs rename to crates/re_viewer_context/src/store_hub.rs index dabeda3e3788..628ea0be100c 100644 --- a/crates/re_viewer/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -1,15 +1,14 @@ use ahash::{HashMap, HashMapExt}; use anyhow::Context as _; + use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId, StoreKind}; use re_query_cache::CachesStats; -use re_viewer_context::{AppOptions, StoreContext}; -#[cfg(not(target_arch = "wasm32"))] -use crate::{loading::load_blueprint_file, saving::default_blueprint_path}; +use crate::{AppOptions, StoreContext}; /// Interface for accessing all blueprints and recordings /// @@ -18,8 +17,24 @@ use crate::{loading::load_blueprint_file, saving::default_blueprint_path}; /// /// Internally, the [`StoreHub`] tracks which [`ApplicationId`] and `recording /// id` ([`StoreId`]) are currently active in the viewer. These can be configured -/// using [`StoreHub::set_active_recording_id`] and [`StoreHub::set_active_app_id`] respectively. +/// using [`StoreHub::set_active_recording_id`] and [`StoreHub::set_active_app`] respectively. +/// +/// ## Blueprints +/// For each [`ApplicationId`], the [`StoreHub`] also keeps track of two blueprints: +/// * The active blueprint +/// * The default blueprint +/// +/// Either on of these can be `None`. +/// +/// The active blueprint is what the user would see and edit, if they were to select that app id. +/// If there is no active blueprint, the default will be cloned and made active. +/// +/// The default blueprint is usually the blueprint set by the SDK. +/// This lets users reset the active blueprint to the one sent by the SDK. pub struct StoreHub { + /// How we load and save blueprints. + persistence: BlueprintPersistence, + active_rec_id: Option, active_application_id: Option, default_blueprint_by_app_id: HashMap, @@ -33,6 +48,20 @@ pub struct StoreHub { blueprint_last_save: HashMap, } +/// Load a blueprint from persisted storage, e.g. disk. +/// Returns `Ok(None)` if no blueprint is found. +pub type BlueprintLoader = + dyn Fn(&ApplicationId) -> anyhow::Result> + Send + Sync; + +/// Save a blueprint to persisted storage, e.g. disk. +pub type BlueprintSaver = dyn Fn(&ApplicationId, &EntityDb) -> anyhow::Result<()> + Send + Sync; + +/// How to save and load blueprints +pub struct BlueprintPersistence { + pub loader: Option>, + pub saver: Option>, +} + /// Convenient information used for `MemoryPanel` #[derive(Default)] pub struct StoreHubStats { @@ -50,12 +79,26 @@ impl StoreHub { "".into() } + /// Used only for tests + pub fn test_hub() -> Self { + Self::new( + BlueprintPersistence { + loader: None, + saver: None, + }, + &|_| {}, + ) + } + /// Create a new [`StoreHub`]. /// /// The [`StoreHub`] will contain a single empty blueprint associated with the app ID returned /// by `[StoreHub::welcome_screen_app_id]`. It should be used as a marker to display the welcome /// screen. - pub fn new() -> Self { + pub fn new( + persistence: BlueprintPersistence, + setup_welcome_screen_blueprint: &dyn Fn(&mut EntityDb), + ) -> Self { re_tracing::profile_function!(); let mut blueprint_by_app_id = HashMap::new(); let mut store_bundle = StoreBundle::default(); @@ -70,9 +113,11 @@ impl StoreHub { ); let welcome_screen_blueprint = store_bundle.blueprint_entry(&welcome_screen_store_id); - crate::app_blueprint::setup_welcome_screen_blueprint(welcome_screen_blueprint); + (setup_welcome_screen_blueprint)(welcome_screen_blueprint); Self { + persistence, + active_rec_id: None, active_application_id: None, default_blueprint_by_app_id: Default::default(), @@ -85,6 +130,9 @@ impl StoreHub { } } + // --------------------- + // Accessors + /// All the loaded recordings and blueprints. #[inline] pub fn store_bundle(&self) -> &StoreBundle { @@ -110,7 +158,7 @@ impl StoreHub { // If there's no active blueprint for this app, try to make the current default one active. if !self.active_blueprint_by_app_id.contains_key(&app_id) { if let Some(blueprint_id) = self.default_blueprint_by_app_id.get(&app_id).cloned() { - self.make_blueprint_active_for_app_id(&blueprint_id, &app_id) + self.set_cloned_blueprint_active_for_app(&app_id, &blueprint_id) .unwrap_or_else(|err| { re_log::warn!("Failed to make blueprint active: {err}"); }); @@ -133,14 +181,67 @@ impl StoreHub { .and_then(|id| self.store_bundle.get(id)); Some(StoreContext { - default_blueprint: self.default_blueprint_by_app_id.get(&app_id), app_id, blueprint, recording: recording.unwrap_or(&EMPTY_ENTITY_DB), bundle: &self.store_bundle, + hub: self, }) } + /// Mutable access to a [`EntityDb`] by id + pub fn entity_db_mut(&mut self, store_id: &StoreId) -> &mut EntityDb { + self.store_bundle.entry(store_id) + } + + // --------------------- + // Add and remove stores + + /// Insert a new recording or blueprint into the [`StoreHub`]. + /// + /// Note that the recording is not automatically made active. Use [`StoreHub::set_active_recording_id`] + /// if needed. + pub fn insert_entity_db(&mut self, entity_db: EntityDb) { + self.store_bundle.insert(entity_db); + } + + pub fn remove(&mut self, store_id: &StoreId) { + if self.active_rec_id.as_ref() == Some(store_id) { + if let Some(new_selection) = self.store_bundle.find_closest_recording(store_id) { + self.set_active_recording_id(new_selection.clone()); + } else { + self.active_application_id = None; + self.active_rec_id = None; + } + } + + self.store_bundle.remove(store_id); + } + + // --------------------- + // Active app + + /// Change the active [`ApplicationId`] + pub fn set_active_app(&mut self, app_id: ApplicationId) { + // If we don't know of a blueprint for this `ApplicationId` yet, + // try to load one from the persisted store + if !self.active_blueprint_by_app_id.contains_key(&app_id) { + if let Err(err) = self.try_to_load_persisted_blueprint(&app_id) { + re_log::warn!("Failed to load persisted blueprint: {err}"); + } + } + + self.active_application_id = Some(app_id); + } + + #[inline] + pub fn active_app(&self) -> Option<&ApplicationId> { + self.active_application_id.as_ref() + } + + // --------------------- + // Active recording + /// Keeps track if a recording was ever activated. /// /// This is useful for the heuristic controlling the welcome screen. @@ -149,16 +250,6 @@ impl StoreHub { self.was_recording_active } - /// Activate a recording by its [`StoreId`]. - pub fn activate_recording(&mut self, store_id: StoreId) { - match store_id.kind { - StoreKind::Recording => self.set_active_recording_id(store_id), - StoreKind::Blueprint => { - re_log::debug!("Tried to activate the blueprint {store_id} as a recording."); - } - } - } - /// Directly access the [`EntityDb`] for the active recording. #[inline] pub fn active_recording_id(&self) -> Option<&StoreId> { @@ -186,66 +277,70 @@ impl StoreHub { .as_ref() .and_then(|recording| recording.app_id()) { - self.set_active_app_id(app_id.clone()); + self.set_active_app(app_id.clone()); } self.active_rec_id = Some(recording_id); self.was_recording_active = true; } - pub fn remove(&mut self, store_id: &StoreId) { - if self.active_rec_id.as_ref() == Some(store_id) { - if let Some(new_selection) = self.store_bundle.find_closest_recording(store_id) { - self.set_active_recording_id(new_selection.clone()); - } else { - self.active_application_id = None; - self.active_rec_id = None; + /// Activate a recording by its [`StoreId`]. + pub fn set_activate_recording(&mut self, store_id: StoreId) { + match store_id.kind { + StoreKind::Recording => self.set_active_recording_id(store_id), + StoreKind::Blueprint => { + re_log::debug!("Tried to activate the blueprint {store_id} as a recording."); } } - - self.store_bundle.remove(store_id); } - /// Change the active [`ApplicationId`] - pub fn set_active_app_id(&mut self, app_id: ApplicationId) { - // If we don't know of a blueprint for this `ApplicationId` yet, - // try to load one from the persisted store - // TODO(#2579): implement web-storage for blueprints as well - #[cfg(not(target_arch = "wasm32"))] - if !self.active_blueprint_by_app_id.contains_key(&app_id) { - if let Err(err) = self.try_to_load_persisted_blueprint(&app_id) { - re_log::warn!("Failed to load persisted blueprint: {err}"); - } - } + // --------------------- + // Default blueprint - self.active_application_id = Some(app_id); - } - - #[inline] - pub fn active_application_id(&self) -> Option<&ApplicationId> { - self.active_application_id.as_ref() + pub fn default_blueprint_id_for_app(&self, app_id: &ApplicationId) -> Option<&StoreId> { + self.default_blueprint_by_app_id.get(app_id) } /// Change which blueprint is the default for a given [`ApplicationId`] #[inline] - pub fn set_default_blueprint_for_app_id( + pub fn set_default_blueprint_for_app( &mut self, - blueprint_id: &StoreId, app_id: &ApplicationId, + blueprint_id: &StoreId, ) { re_log::debug!("Switching default blueprint for {app_id} to {blueprint_id}"); self.default_blueprint_by_app_id .insert(app_id.clone(), blueprint_id.clone()); } + /// Clear the current default blueprint + pub fn clear_default_blueprint(&mut self) { + if let Some(app_id) = &self.active_application_id { + self.default_blueprint_by_app_id.remove(app_id); + } + } + + // --------------------- + // Active blueprint + + /// What is the active blueprint for the active application? + pub fn active_blueprint_id(&self) -> Option<&StoreId> { + self.active_app() + .and_then(|app_id| self.active_blueprint_id_for_app(app_id)) + } + + pub fn active_blueprint_id_for_app(&self, app_id: &ApplicationId) -> Option<&StoreId> { + self.active_blueprint_by_app_id.get(app_id) + } + /// Make blueprint active for a given [`ApplicationId`] /// /// We never activate a blueprint directly. Instead, we clone it and activate the clone. //TODO(jleibs): In the future this can probably be handled with snapshots instead. - pub fn make_blueprint_active_for_app_id( + pub fn set_cloned_blueprint_active_for_app( &mut self, - blueprint_id: &StoreId, app_id: &ApplicationId, + blueprint_id: &StoreId, ) -> anyhow::Result<()> { let new_id = StoreId::random(StoreKind::Blueprint); @@ -285,12 +380,8 @@ impl StoreHub { } } - /// Clear the current default blueprint - pub fn clear_default_blueprint(&mut self) { - if let Some(app_id) = &self.active_application_id { - self.default_blueprint_by_app_id.remove(app_id); - } - } + // --------------------- + // Misc operations /// Forgets all blueprints pub fn clear_all_blueprints(&mut self) { @@ -303,19 +394,6 @@ impl StoreHub { } } - /// Insert a new recording or blueprint into the [`StoreHub`]. - /// - /// Note that the recording is not automatically made active. Use [`StoreHub::set_active_recording_id`] - /// if needed. - pub fn insert_entity_db(&mut self, entity_db: EntityDb) { - self.store_bundle.insert(entity_db); - } - - /// Mutable access to a [`EntityDb`] by id - pub fn entity_db_mut(&mut self, store_id: &StoreId) -> &mut EntityDb { - self.store_bundle.entry(store_id) - } - /// Remove any empty [`EntityDb`]s from the hub pub fn purge_empty(&mut self) { self.store_bundle.purge_empty(); @@ -376,7 +454,6 @@ impl StoreHub { } /// Remove any recordings with a network source pointing at this `uri`. - #[cfg(target_arch = "wasm32")] pub fn remove_recording_by_uri(&mut self, uri: &str) { self.store_bundle.retain(|db| { let Some(data_source) = &db.data_source else { @@ -422,6 +499,7 @@ impl StoreHub { app_options: &AppOptions, ) -> anyhow::Result<()> { re_tracing::profile_function!(); + // Because we save blueprints based on their `ApplicationId`, we only // save the blueprints referenced by `blueprint_by_app_id`, even though // there may be other Blueprints in the Hub. @@ -439,26 +517,11 @@ impl StoreHub { blueprint.gc_everything_but_the_latest_row(); } - #[cfg(not(target_arch = "wasm32"))] - { - let blueprint_path = default_blueprint_path(app_id)?; - - let messages = blueprint.to_messages(None)?; - - // TODO(jleibs): Should we push this into a background thread? Blueprints should generally - // be small & fast to save, but maybe not once we start adding big pieces of user data? - crate::saving::encode_to_file(&blueprint_path, messages.iter())?; - - re_log::debug!("Saved blueprint for {app_id} to {blueprint_path:?}"); - + if let Some(saver) = &self.persistence.saver { + (saver)(app_id, blueprint)?; self.blueprint_last_save .insert(blueprint_id.clone(), blueprint.generation()); } - - #[cfg(target_arch = "wasm32")] - { - _ = app_id; - } } Ok(()) @@ -467,48 +530,36 @@ impl StoreHub { /// Try to load the persisted blueprint for the given `ApplicationId`. /// Note: If no blueprint exists at the expected path, the result is still considered `Ok`. /// It is only an `Error` if a blueprint exists but fails to load. - // TODO(#2579): implement persistence for web - #[cfg(not(target_arch = "wasm32"))] - pub fn try_to_load_persisted_blueprint( - &mut self, - app_id: &ApplicationId, - ) -> anyhow::Result<()> { - use crate::blueprint::is_valid_blueprint; - + fn try_to_load_persisted_blueprint(&mut self, app_id: &ApplicationId) -> anyhow::Result<()> { re_tracing::profile_function!(); - let blueprint_path = default_blueprint_path(app_id)?; - if blueprint_path.exists() { - re_log::debug!("Trying to load blueprint for {app_id} from {blueprint_path:?}",); - - let with_notifications = false; - if let Some(mut bundle) = load_blueprint_file(&blueprint_path, with_notifications) { - for store in bundle.drain_entity_dbs() { - if store.store_kind() == StoreKind::Blueprint && store.app_id() == Some(app_id) - { - if !is_valid_blueprint(&store) { - re_log::warn_once!("Blueprint for {app_id} appears invalid - restoring to default. This is expected if you have just upgraded Rerun versions."); - continue; - } - // We found the blueprint we were looking for; make it active. - // borrow-checker won't let us just call `self.set_blueprint_for_app_id` - re_log::debug!( - "Switching blueprint for {app_id} to {} loaded from {blueprint_path:?}", - store.store_id(), - ); - self.active_blueprint_by_app_id - .insert(app_id.clone(), store.store_id().clone()); - self.blueprint_last_save - .insert(store.store_id().clone(), store.generation()); - self.store_bundle.insert(store); - } else { - anyhow::bail!( - "Found unexpected store while loading blueprint: {:?}", - store.store_id() - ); - } + + let Some(loader) = &self.persistence.loader else { + return Ok(()); + }; + + if let Some(mut bundle) = (loader)(app_id)? { + for store in bundle.drain_entity_dbs() { + if store.store_kind() == StoreKind::Blueprint && store.app_id() == Some(app_id) { + // We found the blueprint we were looking for; make it active. + // borrow-checker won't let us just call `self.set_blueprint_for_app_id` + re_log::debug!( + "Activating new blueprint {} for {app_id}; loaded from disk", + store.store_id(), + ); + self.active_blueprint_by_app_id + .insert(app_id.clone(), store.store_id().clone()); + self.blueprint_last_save + .insert(store.store_id().clone(), store.generation()); + self.store_bundle.insert(store); + } else { + anyhow::bail!( + "Found unexpected store while loading blueprint: {:?}", + store.store_id() + ); } } } + Ok(()) } diff --git a/docs/content/getting-started/what-is-rerun.md b/docs/content/getting-started/what-is-rerun.md index c7df7a64a175..17694769095b 100644 --- a/docs/content/getting-started/what-is-rerun.md +++ b/docs/content/getting-started/what-is-rerun.md @@ -11,6 +11,7 @@ To get a feeling of what you can do with Rerun Rerun is an SDK and engine for visualizing and interacting with multimodal data streams. Rerun is +- Free to use - Simple to integrate and get started with - Usable from Python, Rust, and C++ - Powerful, flexible, and extensible From a547820e84b9c12df05a8795a1d28c9af12dffd3 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 29 Mar 2024 11:29:35 -0400 Subject: [PATCH 145/508] Avoid a hang on linux by always create the renderer, even when we have no store_view (#5724) ### What - Mitigates: https://github.com/rerun-io/rerun/issues/5283 All this does is re-orders the calls so that we always create a renderer and call begin_frame / before_submit even if the case where we have no StoreView. In theory this uses a few more resources when skipping the welcome screen, but practically in almost all cases this is only for a few frames until log-data starts arriving. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5724/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5724/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5724/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5724) - [Docs preview](https://rerun.io/preview/9043a05f182790ade51cc78f6b979b5327d98617/docs) - [Examples preview](https://rerun.io/preview/9043a05f182790ade51cc78f6b979b5327d98617/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app.rs | 39 +++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 4986a5354734..91f6804ee5a1 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -847,19 +847,23 @@ impl App { self.egui_debug_panel_ui(ui); - if let Some(store_view) = store_context { - let entity_db = store_view.recording; - - // TODO(andreas): store the re_renderer somewhere else. - let egui_renderer = { - let render_state = frame.wgpu_render_state().unwrap(); - &mut render_state.renderer.write() - }; - if let Some(render_ctx) = egui_renderer - .callback_resources - .get_mut::() - { - render_ctx.begin_frame(); + // TODO(andreas): store the re_renderer somewhere else. + let egui_renderer = { + let render_state = frame.wgpu_render_state().unwrap(); + &mut render_state.renderer.write() + }; + + if let Some(render_ctx) = egui_renderer + .callback_resources + .get_mut::() + { + // TODO(#5283): There's no great reason to do this if we have no store-view and + // subsequently won't actually be rendering anything. However, doing this here + // avoids a hang on linux. Consider moving this back inside the below `if let`. + // once the upstream issues that fix the hang properly have been resolved. + render_ctx.begin_frame(); + if let Some(store_view) = store_context { + let entity_db = store_view.recording; self.state.show( app_blueprint, @@ -873,15 +877,8 @@ impl App { &self.rx, &self.command_sender, ); - - render_ctx.before_submit(); } - } else { - // There's nothing to show. - // We get here when - // A) there is nothing loaded - // B) we decided not to show the welcome screen, presumably because data is expected at any time now. - // The user can see the connection status in the top bar. + render_ctx.before_submit(); } }); } From a25b7788c9544d1a453df033828d9933f07a2227 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 29 Mar 2024 15:25:35 -0400 Subject: [PATCH 146/508] Don't crash the stock example when the market is closed (#5731) ### What Market was closed good friday, leading me to uncover a bug. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5731/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5731/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5731/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5731) - [Docs preview](https://rerun.io/preview/41fec0ec411fb2242fe22b8bc93e794679cb634c/docs) - [Examples preview](https://rerun.io/preview/41fec0ec411fb2242fe22b8bc93e794679cb634c/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/blueprint_stocks/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/python/blueprint_stocks/main.py b/examples/python/blueprint_stocks/main.py index a0b036c99b6b..17805e04442c 100755 --- a/examples/python/blueprint_stocks/main.py +++ b/examples/python/blueprint_stocks/main.py @@ -201,6 +201,8 @@ def main() -> None: close_time = dt.datetime.combine(day, dt.time(16, 00)) hist = stock.history(start=open_time, end=close_time, interval="5m") + if len(hist.index) == 0: + continue hist.index = hist.index - et_timezone.localize(open_time) peak = hist.High.idxmax() From 7f5c9b03538115d6155e32e7134f1c5fd49e8cba Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 29 Mar 2024 15:26:11 -0400 Subject: [PATCH 147/508] Upgrade maturin so wheel publishing functions again (#5730) ### What - Resolves: https://github.com/rerun-io/rerun/issues/5729 Pypi changed something in their parsing library that required an update to maturin. See: https://github.com/PyO3/maturin/issues/1998 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5730/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5730/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5730/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5730) - [Docs preview](https://rerun.io/preview/7a22dce6927e560a74b212cee636ee75a250826a/docs) - [Examples preview](https://rerun.io/preview/7a22dce6927e560a74b212cee636ee75a250826a/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_rerun_py.yml | 2 +- .github/workflows/reusable_publish_wheels.yml | 2 +- pixi.lock | 844 +++++++++--------- pixi.toml | 2 +- rerun_py/pyproject.toml | 2 +- rerun_py/requirements-build.txt | 2 +- 6 files changed, 429 insertions(+), 425 deletions(-) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index e0f0d65224c1..4b5da77f58d2 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -53,7 +53,7 @@ jobs: - name: Build Wheel uses: PyO3/maturin-action@v1 with: - maturin-version: "1.4.0" + maturin-version: "1.5.1" manylinux: manylinux_2_31 container: off command: build diff --git a/.github/workflows/reusable_publish_wheels.yml b/.github/workflows/reusable_publish_wheels.yml index 9f6512426bae..274b72c406dd 100644 --- a/.github/workflows/reusable_publish_wheels.yml +++ b/.github/workflows/reusable_publish_wheels.yml @@ -165,7 +165,7 @@ jobs: - name: Install dependencies shell: bash run: | - python3 -m pip install packaging==23.1 google-cloud-storage==2.9.0 maturin==1.4.0 + python3 -m pip install packaging==23.1 google-cloud-storage==2.9.0 maturin==1.5.1 - name: Publish to PyPI shell: bash diff --git a/pixi.lock b/pixi.lock index a54f54fa6b92..175f0d5dc038 100644 --- a/pixi.lock +++ b/pixi.lock @@ -7,7 +7,6 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.16-h79b3bcb_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.10-hb29e0c7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.13-hd590300_0.conda @@ -26,7 +25,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-hf600244_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.40-hbdbef99_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.26.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.6.0-hd590300_0.conda @@ -36,29 +34,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_hb11cfb5_4.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.6.0-h00ab1b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-23.5.26-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-12.3.0-h8d2909c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-12.3.0-he2b93b0_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-12.3.0-h76fc315_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-12.3.0-h8d2909c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-12.3.0-he2b93b0_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-12.3.0-h8a814eb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/just-1.22.1-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_16.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda @@ -84,7 +73,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h8bca6fd_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_5.conda @@ -108,7 +96,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-12.3.0-h0f45ef3_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.1-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h8bca6fd_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.19.0-hb90f79a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.8.0-h166bdaf_0.tar.bz2 @@ -118,66 +105,78 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.5-h232c23b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.4.0-py311h63ff55d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - 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/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-h59595ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.18.2-hb753e55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.2-h00e871a_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-50.0-hd3aeb46_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.5-h06160fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.18.1-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h75e419f_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_16.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h8bca6fd_105.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h8bca6fd_105.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_16.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.18.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h75e419f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.13-h31becfc_0.conda @@ -193,27 +192,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/black-24.2.0-py311hec3470c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/just-1.24.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda @@ -270,62 +260,103 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.5-h3091e33_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.9.4-hd600fc2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.4.0-py311h06e5ef9_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4-h0425590_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-h75d905f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.2.2-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-16.0.6-ha38d28d_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.16-h79cb451_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.10-h7beb4c2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.13-h10d778d_0.conda @@ -341,7 +372,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h4da54b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.26.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.6.0-h282daa2_0.conda @@ -358,23 +388,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-16.0.6-h6d92fbe_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-16.0.6-hb91bd55_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-16.0.6-ha38d28d_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-16.0.6-ha38d28d_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.6.0-h7728843_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-23.5.26-he965462_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/just-1.22.1-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-609-ha02d983_16.conda @@ -427,61 +448,71 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.6-hb6ac08f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-16.0.6-hbedff68_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.4.0-py311h24bb903_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311he705e18_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/ncurses-6.4-h93d8f39_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.18.2-h2713218_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h3758fe2_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.18.1-h11a7dfb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-16.0.6-h3808999_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.16-h51b92d1_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.10-hf888d4c_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.13-h93a5062_0.conda @@ -497,7 +528,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h73c0887_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.26.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.6.0-h6aa9301_0.conda @@ -514,23 +544,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx-16.0.6-default_h4cf2255_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-16.0.6-hcd7bac0_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-16.0.6-h54d7cd3_9.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-16.0.6-h3808999_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-16.0.6-h3808999_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.6.0-h2ffa867_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-23.5.26-h13dd4ca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.22.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-609-h634c8be_16.conda @@ -583,61 +604,70 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-17.0.6-hcd81f8e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-16.0.6-haab561b_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.4.0-py311h71175c2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda + - 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/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h463b476_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.18.2-h7ed3092_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h798d188_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.18.1-h5ef7bb8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.13-hcfcfb64_0.conda @@ -653,23 +683,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.0.0-h57928b3_49841.conda - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.22.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda @@ -714,63 +735,42 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.4.0-py311h9a9e57f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.0.0-h66d3029_49657.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.11.0-h91493d7_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.18.1-h7f3b576_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.37.32822-h0123c8e_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vswhere-3.1.4-h57928b3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 default: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -778,7 +778,6 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.10-h0100c56_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.9-h5d48c4d_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.10-hd590300_0.conda @@ -794,27 +793,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.210-hac0d6e5_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h7f98852_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.24.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.7.22-hbcca054_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_hb11cfb5_4.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-23.5.26-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.6.0-h6f12383_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/just-1.15.0-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda @@ -870,66 +860,75 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.11.5-h232c23b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.4.0-py311h63ff55d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - 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/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-hcb278e6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.18.2-hb753e55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.2-h4b38347_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_3_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-28.9-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.06.02-h2873b5e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.1-h06160fa_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.13-h31becfc_0.conda @@ -945,27 +944,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/black-24.2.0-py311hec3470c_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/just-1.24.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda @@ -1022,62 +1012,103 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.5-h3091e33_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/lz4-c-1.9.4-hd600fc2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.4.0-py311h06e5ef9_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4-h0425590_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-h75d905f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.2.2-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.10-h5ed86db_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.9-had988b7_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.10-h10d778d_0.conda @@ -1093,27 +1124,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.210-heeba50e_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h0d85af4_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.24.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2023.7.22-h8857fd0_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-23.5.26-he965462_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.6.0-h8ac2a54_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/just-1.15.0-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20230802.1-cxx17_h048a20a_0.conda @@ -1162,60 +1184,69 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.2-hff08bdf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/lz4-c-1.9.4-hf0c8a7f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.4.0-py311h24bb903_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311he705e18_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/ncurses-6.4-hf0c8a7f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.18.2-h2713218_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h9ab30d4_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_3_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.06.02-hd34609a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hef22860_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.16.20-h63b85fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.16.20-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - osx-arm64: - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.10-h8e8137d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.9-hb1772db_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.10-h93a5062_0.conda @@ -1231,27 +1262,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.210-ha042220_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h3422bc3_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.24.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2023.7.22-hf0a4a13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-23.5.26-h13dd4ca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.6.0-h6da1cb0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.15.0-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20230802.1-cxx17_h13dd4ca_0.conda @@ -1300,60 +1322,69 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-17.0.2-h1c12783_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.4.0-py311h71175c2_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.conda + - 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/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h7ea286d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.18.2-h7ed3092_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h7c018df_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_3_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.06.02-h6135d0a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hb31c410_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.16.20-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.16.20-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - win-64: - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.13-hcfcfb64_0.conda @@ -1369,23 +1400,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h8ffe710_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2023.7.22-h56e8100_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2023.2.0-h57928b3_50496.conda - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.15.0-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda @@ -1430,62 +1452,40 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.4.0-py311h9a9e57f_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2022.1.0-h6a75c08_874.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.10.0-h91493d7_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-hcfcfb64_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.16.20-h7f3b576_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h64f974e_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.36.32532-hdcecf7f_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.36.32532-h05e6639_17.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 packages: - kind: conda name: _libgcc_mutex @@ -1536,7 +1536,7 @@ packages: - kind: pypi name: argcomplete version: 3.2.3 - url: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + url: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c sha256: c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c requires_dist: - coverage ; extra == 'test' @@ -5034,7 +5034,7 @@ packages: - kind: pypi name: colorlog version: 6.8.2 - url: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + url: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 sha256: 4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 requires_dist: - colorama ; sys_platform == 'win32' @@ -5162,7 +5162,7 @@ packages: - kind: pypi name: distlib version: 0.3.8 - url: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + url: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 sha256: 034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - kind: conda name: doxygen @@ -5286,16 +5286,16 @@ packages: timestamp: 1704921321122 - kind: pypi name: filelock - version: 3.13.1 - url: https://files.pythonhosted.org/packages/81/54/84d42a0bee35edba99dee7b59a8d4970eccdd44b99fe728ed912106fc781/filelock-3.13.1-py3-none-any.whl - sha256: 57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c + version: 3.13.3 + url: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + sha256: 5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb requires_dist: - furo >=2023.9.10 ; extra == 'docs' - - sphinx-autodoc-typehints !=1.23.4, >=1.24 ; extra == 'docs' + - sphinx-autodoc-typehints !=1.23.4, >=1.25.2 ; extra == 'docs' - sphinx >=7.2.6 ; extra == 'docs' - covdefaults >=2.3 ; extra == 'testing' - coverage >=7.3.2 ; extra == 'testing' - - diff-cover >=8 ; extra == 'testing' + - diff-cover >=8.0.1 ; extra == 'testing' - pytest-cov >=4.1 ; extra == 'testing' - pytest-mock >=3.12 ; extra == 'testing' - pytest-timeout >=2.2 ; extra == 'testing' @@ -12397,83 +12397,87 @@ packages: timestamp: 1686175179621 - kind: conda name: maturin - version: 1.4.0 + version: 1.5.1 build: py311h06e5ef9_0 subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.4.0-py311h06e5ef9_0.conda - sha256: 2a24157cc1247c02bfbb7a7e214622035548ed9e5bef52bcff3b13e091286791 - md5: dc365d844be0acc4fc0e24d8b7f33f4a + url: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.5.1-py311h06e5ef9_0.conda + sha256: ec876128344c775817ce6c64a979c5570236fe4091eee96cf6547b72fb760736 + md5: f0abfc82e48c4179c8ebecdfc1ce7a59 depends: - libgcc-ng >=12 - - openssl >=3.2.0,<4.0a0 + - openssl >=3.2.1,<4.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - tomli >=1.1.0 license: MIT license_family: MIT - size: 6218103 - timestamp: 1701556894019 + size: 5883670 + timestamp: 1711053175449 - kind: conda name: maturin - version: 1.4.0 + version: 1.5.1 build: py311h24bb903_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.4.0-py311h24bb903_0.conda - sha256: 83453c09d3cc4b58612d616786849f0ab3ea179ba56d5dab1d8c5925dda4be17 - md5: 8ca576ad05b1e268332ffdae99ea2b95 + url: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.5.1-py311h24bb903_0.conda + sha256: 52f9e9e54d36ef40cd5c2fa171613750ee56d722e5ac718e5d71d5e4696e559c + md5: 0ffabfb12f4fbb545781a385744ae75a depends: - - openssl >=3.2.0,<4.0a0 + - openssl >=3.2.1,<4.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - tomli >=1.1.0 + constrains: + - __osx >=10.12 license: MIT license_family: MIT - size: 4909086 - timestamp: 1701548190159 + size: 4746594 + timestamp: 1711043864724 - kind: conda name: maturin - version: 1.4.0 + version: 1.5.1 build: py311h63ff55d_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.4.0-py311h63ff55d_0.conda - sha256: 1fbdd14ab02fd4eb1856f6975bbacd275c5aa21dc2082b534ee5397b0829d7f3 - md5: ed3f1ec9fde179766acc46419ea6cc30 + url: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.5.1-py311h63ff55d_0.conda + sha256: c16ac56fb748e39ae52387395f98c79d031b15d763c1877226bfe8b970690fdb + md5: b988008c60e0ffda52e533668a298c6f depends: - libgcc-ng >=12 - - openssl >=3.2.0,<4.0a0 + - openssl >=3.2.1,<4.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - tomli >=1.1.0 license: MIT license_family: MIT - size: 6178159 - timestamp: 1701547384359 + size: 5875793 + timestamp: 1711042912603 - kind: conda name: maturin - version: 1.4.0 + version: 1.5.1 build: py311h71175c2_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.4.0-py311h71175c2_0.conda - sha256: 361d4d77165ac74c89d8d5f987c0cded5de38e1477ef18e28bfc912e7a812c2e - md5: 4ee2cda2ce773cd860ca76ca2263c509 + url: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.5.1-py311h71175c2_0.conda + sha256: 5e508cb34bf0f2cfc1f06635d3cceefbe679d3fb81ce64d7d2dc0b4bf8af4584 + md5: 50560d0477396cebcaffc864bad10e42 depends: - - openssl >=3.2.0,<4.0a0 + - openssl >=3.2.1,<4.0a0 - python >=3.11,<3.12.0a0 - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 - tomli >=1.1.0 + constrains: + - __osx >=11.0 license: MIT license_family: MIT - size: 4751276 - timestamp: 1701548035331 + size: 4579808 + timestamp: 1711043620752 - kind: conda name: maturin - version: 1.4.0 + version: 1.5.1 build: py311h9a9e57f_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/maturin-1.4.0-py311h9a9e57f_0.conda - sha256: 94653c96a76437d53945f5f448f7da561cc05a47b246c7d8c9e4234fbfe9681e - md5: 5835068c4b34eb615fcbca0e63dadad7 + url: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda + sha256: 5307c7955e2a4da23b6a593c715edd8b9e2abe802c1056a225e757ef35eb3356 + md5: 9eeaf6831c4f0a721385e2e9d10c52a7 depends: - m2w64-gcc-libs - m2w64-gcc-libs-core @@ -12482,8 +12486,8 @@ packages: - tomli >=1.1.0 license: MIT license_family: MIT - size: 4592364 - timestamp: 1701548714524 + size: 4498445 + timestamp: 1711044494832 - kind: conda name: mdurl version: 0.1.0 @@ -13004,7 +13008,7 @@ packages: - kind: pypi name: nox version: 2024.3.2 - url: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + url: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be sha256: e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be requires_dist: - argcomplete <4.0, >=1.9.4 @@ -15717,7 +15721,7 @@ packages: - kind: pypi name: virtualenv version: 20.25.1 - url: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + url: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a sha256: 961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a requires_dist: - distlib <1, >=0.3.7 diff --git a/pixi.toml b/pixi.toml index 5ba5abd9c5d9..16a69c46e545 100644 --- a/pixi.toml +++ b/pixi.toml @@ -182,7 +182,7 @@ flatbuffers = ">=23" gitignore-parser = ">=0.1.9" gitpython = ">=3.1.40" just = ">=1.15.0" -maturin = "1.4.0" +maturin = "1.5.1" mypy = "1.8.0" numpy = ">=1.23,<2" pip = ">=23" diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index 4c9126eb6ffb..6b3c0bfb44d3 100644 --- a/rerun_py/pyproject.toml +++ b/rerun_py/pyproject.toml @@ -1,6 +1,6 @@ [build-system] build-backend = "maturin" -requires = ["maturin>=1.4.0"] +requires = ["maturin>=1.5.1"] [project] classifiers = [ diff --git a/rerun_py/requirements-build.txt b/rerun_py/requirements-build.txt index bffd92b14287..ae41c64d3506 100644 --- a/rerun_py/requirements-build.txt +++ b/rerun_py/requirements-build.txt @@ -1,5 +1,5 @@ attrs>=23.1.0 -maturin>=1.3.0 +maturin>=1.5.1 semver wheel pytest From 31d5c54abce89184c4992aa932ac76b66b3c4fa4 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 2 Apr 2024 04:14:05 -0400 Subject: [PATCH 148/508] Fix the publish jobs to account for new linux-arm target (#5726) ### What Got missed in the original arm refactor. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5726/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5726/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5726/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5726) - [Docs preview](https://rerun.io/preview/31ff400d9e6396939fe5ce7ef1fb5fc868bcb800/docs) - [Examples preview](https://rerun.io/preview/31ff400d9e6396939fe5ce7ef1fb5fc868bcb800/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/README.md | 125 +++++++++--------- .github/workflows/cpp_matrix_full.json | 2 +- .../workflows/reusable_publish_rerun_c.yml | 35 +++-- .../workflows/reusable_publish_rerun_cli.yml | 33 +++-- scripts/ci/generate_pr_summary.py | 9 +- 5 files changed, 113 insertions(+), 91 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 84d0f40efc34..9e15c804d538 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -4,72 +4,75 @@ Our CI workflows make heavy usage of [Reusable Workflows](https://docs.github.co Or integrated into CI jobs such has `on_pull_request.yml` or `on_main.yml`. By convention: -- All reusable workflows start with the `reusable_` prefix. -- All workflows that are triggered via `workflow_dispatch` start with the `manual_` prefix. -- All workflows that are triggered via an event start with the `on_` prefix. - - `on_pull_request` is triggered on pull requests. - - `on_push_main` is triggered on pushes to the main branch. + +- All reusable workflows start with the `reusable_` prefix. +- All workflows that are triggered via `workflow_dispatch` start with the `manual_` prefix. +- All workflows that are triggered via an event start with the `on_` prefix. + - `on_pull_request` is triggered on pull requests. + - `on_push_main` is triggered on pushes to the main branch. If you are going to be doing any editing of workflows, the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=cschleiden.vscode-github-actions) for GitHub Actions is highly recommended. ## Reusable Workflows -- [reusable_checks.yml](reusable_checks.yml) - These are all the checks that run to ensure the code is formatted, - linted, and tested. This job produces no artifacts other than a pass/fail criteria for the build. - - `SAVE_CACHE` - If true, the rust cache will be saved. Generally we only do this for builds on `main` -- [reusable_bench.yml](reusable_bench.yml) - This job runs the benchmarks to check for performance regressions. - - `SAVE_BENCH` - If true, then the benchmark results are saved to update https://ref.rerun.io/dev/bench/ -- [reusable_deploy_docs](reusable_deploy_docs.yml) - This job deploys the python and rust documentation to https://ref.rerun.io - - `PY_AND_CPP_DOCS_VERSION_NAME` - The name to use for versioning the python docs. This should generally match the version in - `Cargo.toml`. - - `UPDATE_LATEST` - If true, then the docs will be deployed to `latest/` as well as the versioned directory. -- [reusable_build_and_test_wheels.yml](reusable_build_and_test_wheels.yml) - This job builds the wheels, runs the -end-to-end test, and produces a sample RRD. The artifacts are accessible via GitHub artifacts, but not otherwise -uploaded anywhere. - - `MATURIN_FEATURE_FLAGS` - The feature flags to pass to maturin. - - `PLATFORM` - Which platform to build for: `linux`, `macos-arm`, `macos-intel`, or `windows`. - - `RELEASE_VERSION` - If producing a release, the version number. This must match the version in `Cargo.toml`. - - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact for passing to `reusable_upload_wheels.yml` - - `SAVE_CACHE` - If true, the rust cache will be saved. Generally we only do this for builds on `main` - - `WHEEL_ARTIFACT_NAME` - Intermediate name of the GitHub wheel artifact for passing to `reusable_upload_wheels.yml` -- [reusable_upload_wheels.yml](reusable_upload_wheels.yml) - This job uploads the wheels to google cloud - - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact. This should match the name passed to - `reusable_build_and_test_wheels.yml` - - `WHEEL_ARTIFACT_NAME` - Intermediate name of the GitHub wheel artifact. This should match the name passed to - `reusable_build_and_test_wheels.yml` -- [reusable_build_web.yml](reusable_build_web.yml) - This job builds the wasm artifacts for the web. - - `RELEASE_VERSION` - If producing a release, the version number. This must match the version in `Cargo.toml`. -- [reusable_upload_web.yml](reusable_upload_web.yml) - This job uploads the web assets to google cloud. By default this - only uploads to: `app.rerun.io/commit//` - - `MARK_TAGGED_VERSION` - If true, then the web assets will go to `app.rerun.io/version/` - - `RELEASE_VERSION` - If producing a release, the version number. - - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact. This should match the name passed to - `reusable_build_and_test_wheels.yml` - - `UPLOAD_COMMIT_OVERRIDE` - If set, will replace the value of ``. This is necessary because we want pull - request builds associated with their originating commit, even if the web-build happens on an ephemeral merge-commit. -- [reusable_build_web_demo.yml](reusable_build_web.yml) - This job builds the assets uploaded to `demo.rerun.io`. - - `SOURCE_LINK_COMMIT_OVERRIDE` - If set, will replace the value of `` in the built app. This ensures that the - source code link in the built app always points to the pull request's `HEAD`. -- [reusable_upload_web_demo.yml](reusable_upload_web_demo.yml) - This job uploads the `demo.rerun.io` assets to google cloud. By default this - only uploads to: `demo.rerun.io/commit//` - - `MARK_TAGGED_VERSION` - If true, then the web assets will go to `demo.rerun.io/version/` - - `RELEASE_VERSION` - If producing a release, the version number. - - `UPLOAD_COMMIT_OVERRIDE` - If set, will replace the value of ``. This is necessary because we want pull - request builds associated with their originating commit, even if the web-build happens on an ephemeral merge-commit. - - `PR_NUMBER` - If set, will upload `demo.rerun.io/pr/` -- [reusable_pr_summary.yml](reusable_pr_summary.yml) - This job updates the PR summary with the results of the CI run. - - This summary can be found at: - `https://build.rerun.io/pr//` - - `PR_NUMBER` - The PR number to update. This will generally be set by the `on_pull_request.yml` workflow using: - `${{github.event.pull_request.number}}` + +- [reusable_checks.yml](reusable_checks.yml) - These are all the checks that run to ensure the code is formatted, + linted, and tested. This job produces no artifacts other than a pass/fail criteria for the build. + - `SAVE_CACHE` - If true, the rust cache will be saved. Generally we only do this for builds on `main` +- [reusable_bench.yml](reusable_bench.yml) - This job runs the benchmarks to check for performance regressions. + - `SAVE_BENCH` - If true, then the benchmark results are saved to update https://ref.rerun.io/dev/bench/ +- [reusable_deploy_docs](reusable_deploy_docs.yml) - This job deploys the python and rust documentation to https://ref.rerun.io + - `PY_AND_CPP_DOCS_VERSION_NAME` - The name to use for versioning the python docs. This should generally match the version in + `Cargo.toml`. + - `UPDATE_LATEST` - If true, then the docs will be deployed to `latest/` as well as the versioned directory. +- [reusable_build_and_test_wheels.yml](reusable_build_and_test_wheels.yml) - This job builds the wheels, runs the + end-to-end test, and produces a sample RRD. The artifacts are accessible via GitHub artifacts, but not otherwise + uploaded anywhere. + - `MATURIN_FEATURE_FLAGS` - The feature flags to pass to maturin. + - `PLATFORM` - Which platform to build for: `linux-arm64`, `linux-x64`, `macos-arm64`, `macos-x64`, or `windows-x64`. + - `RELEASE_VERSION` - If producing a release, the version number. This must match the version in `Cargo.toml`. + - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact for passing to `reusable_upload_wheels.yml` + - `SAVE_CACHE` - If true, the rust cache will be saved. Generally we only do this for builds on `main` + - `WHEEL_ARTIFACT_NAME` - Intermediate name of the GitHub wheel artifact for passing to `reusable_upload_wheels.yml` +- [reusable_upload_wheels.yml](reusable_upload_wheels.yml) - This job uploads the wheels to google cloud + - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact. This should match the name passed to + `reusable_build_and_test_wheels.yml` + - `WHEEL_ARTIFACT_NAME` - Intermediate name of the GitHub wheel artifact. This should match the name passed to + `reusable_build_and_test_wheels.yml` +- [reusable_build_web.yml](reusable_build_web.yml) - This job builds the wasm artifacts for the web. + - `RELEASE_VERSION` - If producing a release, the version number. This must match the version in `Cargo.toml`. +- [reusable_upload_web.yml](reusable_upload_web.yml) - This job uploads the web assets to google cloud. By default this + only uploads to: `app.rerun.io/commit//` + - `MARK_TAGGED_VERSION` - If true, then the web assets will go to `app.rerun.io/version/` + - `RELEASE_VERSION` - If producing a release, the version number. + - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact. This should match the name passed to + `reusable_build_and_test_wheels.yml` + - `UPLOAD_COMMIT_OVERRIDE` - If set, will replace the value of ``. This is necessary because we want pull + request builds associated with their originating commit, even if the web-build happens on an ephemeral merge-commit. +- [reusable_build_web_demo.yml](reusable_build_web.yml) - This job builds the assets uploaded to `demo.rerun.io`. + - `SOURCE_LINK_COMMIT_OVERRIDE` - If set, will replace the value of `` in the built app. This ensures that the + source code link in the built app always points to the pull request's `HEAD`. +- [reusable_upload_web_demo.yml](reusable_upload_web_demo.yml) - This job uploads the `demo.rerun.io` assets to google cloud. By default this + only uploads to: `demo.rerun.io/commit//` + - `MARK_TAGGED_VERSION` - If true, then the web assets will go to `demo.rerun.io/version/` + - `RELEASE_VERSION` - If producing a release, the version number. + - `UPLOAD_COMMIT_OVERRIDE` - If set, will replace the value of ``. This is necessary because we want pull + request builds associated with their originating commit, even if the web-build happens on an ephemeral merge-commit. + - `PR_NUMBER` - If set, will upload `demo.rerun.io/pr/` +- [reusable_pr_summary.yml](reusable_pr_summary.yml) - This job updates the PR summary with the results of the CI run. + - This summary can be found at: + `https://build.rerun.io/pr//` + - `PR_NUMBER` - The PR number to update. This will generally be set by the `on_pull_request.yml` workflow using: + `${{github.event.pull_request.number}}` ## Manual Workflows -- [manual_dispatch](manual_dispatch.yml) - This workflow is used to manually trigger the assorted reusable workflows for - testing. - - See the workflow file for the list of parameters. -- [manual_build_wheels_for_pr.yml](manual_build_wheels_for_pr.yml) - This workflow can be dispatched on a branch and - will build all of the wheels for the associated pull-request. Uses: - - [reusable_build_and_test_wheels.yml](reusable_build_and_test_wheels.yml) - - [reusable_upload_wheels.yml](reusable_upload_wheels.yml) - - [reusable_pr_summary.yml](reusable_pr_summary.yml) + +- [manual_dispatch](manual_dispatch.yml) - This workflow is used to manually trigger the assorted reusable workflows for + testing. + - See the workflow file for the list of parameters. +- [manual_build_wheels_for_pr.yml](manual_build_wheels_for_pr.yml) - This workflow can be dispatched on a branch and + will build all of the wheels for the associated pull-request. Uses: + - [reusable_build_and_test_wheels.yml](reusable_build_and_test_wheels.yml) + - [reusable_upload_wheels.yml](reusable_upload_wheels.yml) + - [reusable_pr_summary.yml](reusable_pr_summary.yml) diff --git a/.github/workflows/cpp_matrix_full.json b/.github/workflows/cpp_matrix_full.json index ad018b0d0fd9..4d0fd316dbf7 100644 --- a/.github/workflows/cpp_matrix_full.json +++ b/.github/workflows/cpp_matrix_full.json @@ -22,7 +22,7 @@ { "name": "Mac aarch64", "runs_on": "macos-latest-large", - "cache_key": "build-macos-arm", + "cache_key": "build-macos-arm64", "extra_env_vars": "RERUN_USE_ASAN=1" } ] diff --git a/.github/workflows/reusable_publish_rerun_c.yml b/.github/workflows/reusable_publish_rerun_c.yml index 40a10bf22606..423d299f1d14 100644 --- a/.github/workflows/reusable_publish_rerun_c.yml +++ b/.github/workflows/reusable_publish_rerun_c.yml @@ -16,45 +16,54 @@ on: required: true jobs: - linux: + linux-arm64: + name: "Linux-Arm64" + uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml + with: + CONCURRENCY: publish-rerun-c-linux-arm64-${{ github.ref_name }} + PLATFORM: linux-arm64 + RELEASE_COMMIT: ${{ inputs.release-commit }} + secrets: inherit + + linux-x64: name: "Linux-x64" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-linux-${{ github.ref_name }} - PLATFORM: linux + CONCURRENCY: publish-rerun-c-linux-x64-${{ github.ref_name }} + PLATFORM: linux-x64 RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit - macos-intel: + macos-x64: name: "Mac-Intel" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-macos-intel-${{ github.ref_name }} - PLATFORM: macos-intel + CONCURRENCY: publish-rerun-c-macos-x64-${{ github.ref_name }} + PLATFORM: macos-x64 RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit - macos-arm: + macos-arm64: name: "Mac-Arm" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-macos-arm-${{ github.ref_name }} - PLATFORM: macos-arm + CONCURRENCY: publish-rerun-c-macos-arm64-${{ github.ref_name }} + PLATFORM: macos-arm64 RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit - windows: + windows-x64: name: "Windows-x64" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-windows-${{ github.ref_name }} - PLATFORM: windows + CONCURRENCY: publish-rerun-c-windows-${{ github.ref_name }} + PLATFORM: windows-x64 RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit bundle-and-upload-rerun_cpp: name: "Bundle and upload rerun_cpp_sdk.zip" - needs: [linux, macos-intel, macos-arm, windows] + needs: [linux-arm64, linux-x64, macos-x64, macos-arm64, windows-x64] uses: ./.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml with: RELEASE_COMMIT: ${{ inputs.release-commit }} diff --git a/.github/workflows/reusable_publish_rerun_cli.yml b/.github/workflows/reusable_publish_rerun_cli.yml index bb3d56a5a008..2b0f97bd0356 100644 --- a/.github/workflows/reusable_publish_rerun_cli.yml +++ b/.github/workflows/reusable_publish_rerun_cli.yml @@ -16,38 +16,47 @@ on: required: true jobs: - linux: + linux-arm64: + name: "Linux-arm64" + uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + with: + CONCURRENCY: publish-rerun-cli-linux-arm64-${{ github.ref_name }} + PLATFORM: linux-arm64 + RELEASE_COMMIT: ${{ inputs.release-commit }} + secrets: inherit + + linux-x64: name: "Linux-x64" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-linux-${{ github.ref_name }} - PLATFORM: linux + CONCURRENCY: publish-rerun-cli-linux-x64-${{ github.ref_name }} + PLATFORM: linux-x64 RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit - macos-intel: + macos-x64: name: "Mac-Intel" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-macos-intel-${{ github.ref_name }} - PLATFORM: macos-intel + CONCURRENCY: publish-rerun-cli-macos-x64-${{ github.ref_name }} + PLATFORM: macos-x64 RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit - macos-arm: + macos-arm64: name: "Mac-Arm" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-macos-arm-${{ github.ref_name }} - PLATFORM: macos-arm + CONCURRENCY: publish-rerun-cli-macos-arm64-${{ github.ref_name }} + PLATFORM: macos-arm64 RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit - windows: + windows-x64: name: "Windows-x64" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-windows-${{ github.ref_name }} - PLATFORM: windows + CONCURRENCY: publish-rerun-cli-windows-x64-${{ github.ref_name }} + PLATFORM: windows-x64 RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit diff --git a/scripts/ci/generate_pr_summary.py b/scripts/ci/generate_pr_summary.py index 77c31233d889..5a1b0bd0cd38 100644 --- a/scripts/ci/generate_pr_summary.py +++ b/scripts/ci/generate_pr_summary.py @@ -51,10 +51,11 @@ def generate_pr_summary(github_token: str, github_repository: str, pr_number: in # Check if there are rerun_c libraries rerun_libraries_blobs = [ - builds_bucket.blob(f"commit/{commit_short}/rerun_c/windows/rerun_c.lib"), - builds_bucket.blob(f"commit/{commit_short}/rerun_c/linux/librerun_c.a"), - builds_bucket.blob(f"commit/{commit_short}/rerun_c/macos-arm/librerun_c.a"), - builds_bucket.blob(f"commit/{commit_short}/rerun_c/macos-intel/librerun_c.a"), + builds_bucket.blob(f"commit/{commit_short}/rerun_c/windows-x64/rerun_c.lib"), + builds_bucket.blob(f"commit/{commit_short}/rerun_c/linux-arm64/librerun_c.a"), + builds_bucket.blob(f"commit/{commit_short}/rerun_c/linux-x64/librerun_c.a"), + builds_bucket.blob(f"commit/{commit_short}/rerun_c/macos-arm64/librerun_c.a"), + builds_bucket.blob(f"commit/{commit_short}/rerun_c/macos-x64/librerun_c.a"), ] rerun_libraries = [f"https://build.rerun.io/{blob.name}" for blob in rerun_libraries_blobs if blob.exists()] if rerun_libraries: From c504eba13bf5f5a490fa04a6995673b9c94ac58f Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 2 Apr 2024 10:54:02 +0200 Subject: [PATCH 149/508] Fix typos from new version of `typos` (#5735) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5735/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5735/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5735/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5735) - [Docs preview](https://rerun.io/preview/934361bf457e165e3a35a512e7076a569b8008af/docs) - [Examples preview](https://rerun.io/preview/934361bf457e165e3a35a512e7076a569b8008af/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .typos.toml | 24 ++++++++++++++----- CONTRIBUTING.md | 2 +- .../outlines/jumpflooding_init_shared.wgsl | 2 +- .../src/components/view_coordinates_ext.rs | 2 +- .../re_types_builder/src/codegen/cpp/mod.rs | 2 +- crates/re_ui/examples/re_ui_example.rs | 4 ++-- crates/re_viewer/src/screenshotter.rs | 2 +- rerun_cpp/download_and_build_arrow.cmake | 2 +- 8 files changed, 26 insertions(+), 14 deletions(-) diff --git a/.typos.toml b/.typos.toml index a63425b657c4..1786167ca30b 100644 --- a/.typos.toml +++ b/.typos.toml @@ -7,6 +7,7 @@ extend-exclude = [ ".typos.toml", "crates/re_ui/data/design_tokens.json", "crates/re_ui/src/design_tokens.rs", + "docs/cspell.json", "examples/assets", "rerun_cpp/src/rerun/third_party/cxxopts.hpp", ] @@ -109,6 +110,7 @@ saviour = "savior" savour = "savor" sceptical = "skeptical" sceptre = "scepter" +FUL = "FUL" # forward-up-left coordinate system sepulchre = "sepulcher" serialisation = "serialization" serialise = "serialize" @@ -127,8 +129,10 @@ tonne = "ton" travelogue = "travelog" tumour = "tumor" valour = "valor" +opf = "opf" # Open Photogrammetry Format (OPF) file vaporise = "vaporize" vigour = "vigor" +ws = "ws" # web-sockets, as in "ws://…" # null-terminated is the name of the wikipedia article! # https://en.wikipedia.org/wiki/Null-terminated_string @@ -137,9 +141,17 @@ zeroterminated = "null-terminated" zero-terminated = "null-terminated" [default] -# Work around for typos inside of hashes. These show up inside of ipynb. -# e.g. "f4e1caf9" -> `caf` should be `calf` -# Specifically limit ourselves to exactly 8 chars in a quoted string, or -# 16 character hashses following a leading underscore. -# Just don't spell "defaced" wrong. -extend-ignore-re = ["\"[a-f0-9]{8}\"", "_[a-f0-9]{16}"] +extend-ignore-re = [ + # Work around for typos inside of hashes. These show up inside of ipynb. + # e.g. "f4e1caf9" -> `caf` should be `calf` + # Specifically limit ourselves to exactly 8 chars in a quoted string, or + # 16 character hashses following a leading underscore. + # Just don't spell "defaced" wrong. + "\"[a-f0-9]{8}\"", + "_[a-f0-9]{16}", + + + "np.arange", # numpy spells "arrange" wrong + "phc_[a-zA-Z0-9]*", # Posthog public key + "PNG.?", # Workaround for https://github.com/crate-ci/typos/issues/967 +] diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 49f720671259..38cb6ce21e08 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -113,7 +113,7 @@ cargo run -p rerun -- --help ## Tools -We use the [`just`](https://github.com/casey/just) command runner tool for repository automation. See [here](https://github.com/casey/just#installation) for installation instructions. To see available automations, use `just --list`. +We use the [`just`](https://github.com/casey/just) command runner tool for repository automation. See [here](https://github.com/casey/just#installation) for installation instructions. To see available automation, use `just --list`. We use [cargo cranky](https://github.com/ericseppanen/cargo-cranky) and specify our clippy lints in [`Cranky.toml`](Cranky.toml). Usage: `cargo cranky`. diff --git a/crates/re_renderer/shader/outlines/jumpflooding_init_shared.wgsl b/crates/re_renderer/shader/outlines/jumpflooding_init_shared.wgsl index 98851acb6736..b0807413b438 100644 --- a/crates/re_renderer/shader/outlines/jumpflooding_init_shared.wgsl +++ b/crates/re_renderer/shader/outlines/jumpflooding_init_shared.wgsl @@ -2,7 +2,7 @@ #import <../screen_triangle_vertex.wgsl> fn compute_pixel_coords(center_coord: vec2i, unnormalized_edge_pos_a_and_b: vec4f, num_edges_a_and_b: vec2f) -> vec4f { - // Normalize edges ans get range from [0, 1] to [-0.5, 0.5]. + // Normalize edges and get range from [0, 1] to [-0.5, 0.5]. let edge_pos_a_and_b = unnormalized_edge_pos_a_and_b / num_edges_a_and_b.xxyy - vec4f(0.5); // We're outputting pixel coordinates (0-res) instead of texture coordinates (0-1). diff --git a/crates/re_types/src/components/view_coordinates_ext.rs b/crates/re_types/src/components/view_coordinates_ext.rs index f20d551b3101..9637441db83a 100644 --- a/crates/re_types/src/components/view_coordinates_ext.rs +++ b/crates/re_types/src/components/view_coordinates_ext.rs @@ -12,7 +12,7 @@ impl ViewCoordinates { Self([x as u8, y as u8, z as u8]) } - /// Choses a coordinate system based on just an up-axis. + /// Chooses a coordinate system based on just an up-axis. pub fn from_up_and_handedness(up: SignedAxis3, handedness: Handedness) -> Self { use ViewDir::{Back, Down, Forward, Right, Up}; match handedness { diff --git a/crates/re_types_builder/src/codegen/cpp/mod.rs b/crates/re_types_builder/src/codegen/cpp/mod.rs index 1c48d66edfb3..de1e378d6364 100644 --- a/crates/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/re_types_builder/src/codegen/cpp/mod.rs @@ -274,7 +274,7 @@ fn generate_object_files( /// /// Additionally, picks up all includes files that aren't including the header itself. /// -/// Returns what to inject, and what to repalce `HEADER_EXTENSION_TOKEN` with at the end. +/// Returns what to inject, and what to replace `HEADER_EXTENSION_TOKEN` with at the end. fn hpp_type_extensions( folder_path: &Utf8Path, filename_stem: &str, diff --git a/crates/re_ui/examples/re_ui_example.rs b/crates/re_ui/examples/re_ui_example.rs index 575b2482fa1b..abdc8c276628 100644 --- a/crates/re_ui/examples/re_ui_example.rs +++ b/crates/re_ui/examples/re_ui_example.rs @@ -187,7 +187,7 @@ impl eframe::App for ExampleApp { // no need to extend `ui.max_rect()` as the enclosing frame doesn't have margins ui.set_clip_rect(ui.max_rect()); - egui::TopBottomPanel::top("left_panel_tio_bar") + egui::TopBottomPanel::top("left_panel_top_bar") .exact_height(re_ui::ReUi::title_bar_height()) .frame(egui::Frame { inner_margin: egui::Margin::symmetric(re_ui::ReUi::view_padding(), 0.0), @@ -830,7 +830,7 @@ mod hierarchical_drag_and_drop { target_position_index: usize, }, - /// Specify the currently identifed target container to be highlighted. + /// Specify the currently identified target container to be highlighted. HighlightTargetContainer(ItemId), } diff --git a/crates/re_viewer/src/screenshotter.rs b/crates/re_viewer/src/screenshotter.rs index 99600500b6fb..cad6ed3da1fc 100644 --- a/crates/re_viewer/src/screenshotter.rs +++ b/crates/re_viewer/src/screenshotter.rs @@ -14,7 +14,7 @@ pub struct Screenshotter { #[cfg(not(target_arch = "wasm32"))] #[must_use] pub struct ScreenshotterOutput { - /// If true, the screenshotter was told at startup to quit after its donw. + /// If true, the screenshotter was told at startup to quit after it's done. pub quit: bool, } diff --git a/rerun_cpp/download_and_build_arrow.cmake b/rerun_cpp/download_and_build_arrow.cmake index d6c763313e5c..59cf734d937a 100644 --- a/rerun_cpp/download_and_build_arrow.cmake +++ b/rerun_cpp/download_and_build_arrow.cmake @@ -73,7 +73,7 @@ function(download_and_build_arrow) GIT_REPOSITORY https://github.com/apache/arrow.git GIT_TAG apache-arrow-10.0.1 GIT_SHALLOW ON - GIT_PROGRESS OFF # Git progress sounds like a nice idea but is in practive very spammy. + GIT_PROGRESS OFF # Git progress sounds like a nice idea but is in practice very spammy. # LOG_X ON means that the output of the command will # be logged to a file _instead_ of printed to the console. From cd07140b2ac257e4d3dfcc3dabb9cbd4c208f22f Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 2 Apr 2024 12:18:45 +0200 Subject: [PATCH 150/508] Fix appearance of `ListItem` in a tooltip (#5741) Requires a hack for the clip_rect. I opened an issue to track this: * https://github.com/rerun-io/rerun/issues/5740 Before: ![screenshot_2024-04-02_at_11 34 18](https://github.com/rerun-io/rerun/assets/1148717/8e4e55a2-4c97-4e4c-b504-061b56d7c624) After: Screenshot 2024-04-02 at 11 59 16 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5741/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5741/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5741/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5741) - [Docs preview](https://rerun.io/preview/04ae476663633878b1b60b6101d82e653454c0d2/docs) - [Examples preview](https://rerun.io/preview/04ae476663633878b1b60b6101d82e653454c0d2/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/data_source.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/re_data_ui/src/data_source.rs b/crates/re_data_ui/src/data_source.rs index 1e3f4116bf9f..da731ed2029f 100644 --- a/crates/re_data_ui/src/data_source.rs +++ b/crates/re_data_ui/src/data_source.rs @@ -49,7 +49,9 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { if !recordings.is_empty() { ui.add_space(8.0); ui.strong("Recordings from this data source"); + let max_rect = ui.max_rect(); ui.indent("recordings", |ui| { + ui.set_clip_rect(max_rect); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect. ui.spacing_mut().item_spacing.y = 0.0; for entity_db in recordings { entity_db_button_ui(ctx, ui, entity_db, true); @@ -60,7 +62,9 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { if !blueprints.is_empty() { ui.add_space(8.0); ui.strong("Blueprints from this data source"); + let max_rect = ui.max_rect(); ui.indent("blueprints", |ui| { + ui.set_clip_rect(max_rect); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect. ui.spacing_mut().item_spacing.y = 0.0; for entity_db in blueprints { entity_db_button_ui(ctx, ui, entity_db, true); From d00aa27e72ee292c4c0136c9ac9d3e0e84909b48 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 2 Apr 2024 12:20:55 +0200 Subject: [PATCH 151/508] Fix crash/freeze when zooming out too far in a plot (#5737) ### What We reach `i64::MAX` pretty quickly when zooming out on e.g. https://github.com/rerun-io/example-rs-github-stars. In debug builds this overflow would lead to a crash. In release I think it results in a freeze. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5737/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5737/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5737/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5737) - [Docs preview](https://rerun.io/preview/62226e544f05221313db4abd9476f40caef73c9d/docs) - [Examples preview](https://rerun.io/preview/62226e544f05221313db4abd9476f40caef73c9d/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/space_view_class.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 6e666a353355..cc78f74897c2 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -400,7 +400,7 @@ It can greatly improve performance (and readability) in such situations as it pr .x_axis_formatter(move |time, _, _| { format_time( time_type, - time.value as i64 + time_offset, + (time.value as i64).saturating_add(time_offset), time_zone_for_timestamps, ) }) @@ -408,7 +408,7 @@ It can greatly improve performance (and readability) in such situations as it pr .label_formatter(move |name, value| { let name = if name.is_empty() { "y" } else { name }; let label = time_type.format( - (value.x as i64 + time_offset).into(), + ((value.x as i64).saturating_add(time_offset)).into(), time_zone_for_timestamps, ); @@ -803,7 +803,12 @@ fn ns_grid_spacer( let mut small_spacing_ns = 1; while width_ns / (next_grid_tick_magnitude_ns(small_spacing_ns) as f64) > max_medium_lines { - small_spacing_ns = next_grid_tick_magnitude_ns(small_spacing_ns); + let next_ns = next_grid_tick_magnitude_ns(small_spacing_ns); + if small_spacing_ns < next_ns { + small_spacing_ns = next_ns; + } else { + break; // we've reached the max + } } let medium_spacing_ns = next_grid_tick_magnitude_ns(small_spacing_ns); let big_spacing_ns = next_grid_tick_magnitude_ns(medium_spacing_ns); @@ -828,7 +833,11 @@ fn ns_grid_spacer( step_size: step_size as f64, }); - current_ns += small_spacing_ns; + if let Some(new_ns) = current_ns.checked_add(small_spacing_ns) { + current_ns = new_ns; + } else { + break; + }; } marks From 2d78f6a26a33c8bd166bc43e26c0d0e135ec990c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Tue, 2 Apr 2024 13:18:03 +0200 Subject: [PATCH 152/508] Update web viewer links (#5738) ### What Update most web viewer links from `app.rerun.io` to `rerun.io/viewer`. - Part of https://github.com/rerun-io/landing/issues/730 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5738/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5738/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5738/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5738) - [Docs preview](https://rerun.io/preview/ea736f87a22392f5007a465f11b1576fe5537ad7/docs) - [Examples preview](https://rerun.io/preview/ea736f87a22392f5007a465f11b1576fe5537ad7/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/pull_request_template.md | 6 +-- .github/workflows/on_push_main.yml | 2 +- .github/workflows/release.yml | 4 +- crates/re_viewer/src/app.rs | 38 ++++++++++++------- docs/README.md | 2 +- .../getting-started/troubleshooting.md | 2 +- docs/content/getting-started/what-is-rerun.md | 2 +- examples/manifest.toml | 2 +- examples/python/notebook/cube.ipynb | 22 +++++------ rerun_py/src/python_bridge.rs | 8 ++-- scripts/ci/generate_pr_summary.py | 2 +- .../build_screenshot_compare.py | 2 +- 12 files changed, 51 insertions(+), 41 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 167184a55020..65291f2d6ad5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -16,9 +16,9 @@ To get an auto-generated PR description you can put "copilot:summary" or "copilo * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): - * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html) - * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) - * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) + * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}/index.html) + * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) + * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 6d5abbe983a0..922aa2dd73f6 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -359,7 +359,7 @@ jobs: Please report any issues you find. ## Example Hosted App - https://app.rerun.io/commit/${{ env.SHORT_SHA }} + https://rerun.io/viewer/commit/${{ env.SHORT_SHA }} ## Wheels can be installed with: ``` diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71eb649fc20e..83e533dd09e9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -445,11 +445,11 @@ jobs: short_commit_hash=$(echo ${{ needs.version.outputs.release-commit }} | cut -c1-7) if [ ${{ inputs.release-type }} = "final" ]; then - web_app_link="https://app.rerun.io/version/${{ needs.version.outputs.final }}" + web_app_link="https://rerun.io/viewer/version/${{ needs.version.outputs.final }}" rerun_io_docs_link="https://rerun.io/docs" py_docs_link="https://ref.rerun.io/docs/python/${{ needs.version.outputs.final }}" else - web_app_link="https://app.rerun.io/commit/$short_commit_hash" + web_app_link="https://rerun.io/viewer/commit/$short_commit_hash" rerun_io_docs_link="https://rerun.io/preview/$short_commit_hash/docs" py_docs_link="https://ref.rerun.io/docs/python/dev" fi diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 91f6804ee5a1..a399be13e7e0 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -728,26 +728,36 @@ impl App { #[cfg(target_arch = "wasm32")] fn run_copy_direct_link_command(&mut self, store_context: Option<&StoreContext<'_>>) { - let location = eframe::web::web_location(); - let mut href = location.origin; - if location.host == "app.rerun.io" { - // links to `app.rerun.io` can be made into permanent links: - let path = if self.build_info.is_final() { - // final release, use version tag - format!("version/{}", self.build_info.version) - } else { - // not a final release, use commit hash - format!("commit/{}", self.build_info.short_git_hash()) - }; - href = format!("{href}/{path}"); - } + let location = web_sys::window().unwrap().location(); + let origin = location.origin().unwrap(); + let host = location.host().unwrap(); + let pathname = location.pathname().unwrap(); + + let hosted_viewer_path = if self.build_info.is_final() { + // final release, use version tag + format!("version/{}", self.build_info.version) + } else { + // not a final release, use commit hash + format!("commit/{}", self.build_info.short_git_hash()) + }; + + // links to `app.rerun.io` can be made into permanent links: + let href = if host == "app.rerun.io" { + format!("https://app.rerun.io/{hosted_viewer_path}") + } else if host == "rerun.io" && pathname.starts_with("/viewer") { + format!("https://rerun.io/viewer/{hosted_viewer_path}") + } else { + format!("{origin}{pathname}") + }; + let direct_link = match store_context .map(|ctx| ctx.recording) .and_then(|rec| rec.data_source.as_ref()) { - Some(SmartChannelSource::RrdHttpStream { url }) => format!("{href}/?url={url}"), + Some(SmartChannelSource::RrdHttpStream { url }) => format!("{href}?url={url}"), _ => href, }; + self.re_ui .egui_ctx .output_mut(|o| o.copied_text = direct_link.clone()); diff --git a/docs/README.md b/docs/README.md index ce54993d0201..3b0bd54450f4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -68,7 +68,7 @@ snippet: my-example ### Screenshot links If a screenshot shows an example or snippet which is runnable and built on CI, then you can turn the screenshot -to a link to `app.rerun.io` pointing at the example using the `data-inline-viewer` attribute. +to a link to `rerun.io/viewer` pointing at the example using the `data-inline-viewer` attribute. Add the attribute to any `` element like so: diff --git a/docs/content/getting-started/troubleshooting.md b/docs/content/getting-started/troubleshooting.md index 24dfa7975c70..212b5435e46e 100644 --- a/docs/content/getting-started/troubleshooting.md +++ b/docs/content/getting-started/troubleshooting.md @@ -77,7 +77,7 @@ The configuration we use for wgpu can be influenced in the following ways: On the web we prefer WebGPU and fall back automatically to WebGL if no support for WebGPU was detected. - For instance, you can try `rerun --renderer=gl` or for the web viewer respectively `rerun --web-viewer --renderer=webgl`. - Alternatively, for the native viewer you can also use the `WGPU_BACKEND` environment variable with the above values. - - The web viewer is configured by the `renderer=` url argument, e.g. [https://app.rerun.io/?renderer=webgl] + - The web viewer is configured by the `renderer=` url argument, e.g. [https://rerun.io/viewer?renderer=webgl&speculative-link] - `WGPU_POWER_PREF`: Overwrites the power setting used for choosing a graphics adapter, must be `high` or `low`. (Default is `high`) We recommend setting these only if you're asked to try them or know what you're doing, diff --git a/docs/content/getting-started/what-is-rerun.md b/docs/content/getting-started/what-is-rerun.md index 17694769095b..177c5efc2065 100644 --- a/docs/content/getting-started/what-is-rerun.md +++ b/docs/content/getting-started/what-is-rerun.md @@ -4,7 +4,7 @@ order: 0 --- To get a feeling of what you can do with Rerun - browse the [example gallery](/examples) or -- try Rerun directly [in your browser](https://app.rerun.io/). +- try Rerun directly [in your browser](/viewer?speculative-link). ## What is Rerun? diff --git a/examples/manifest.toml b/examples/manifest.toml index fb8519cbae54..d3765693960a 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -16,7 +16,7 @@ Each example downloads it's own data, so no additional steps are needed. For the simplest possible examples showing how to use each api, check out [Types](/docs/reference/types). -You can try these examples live at . +You can try these examples live at [rerun.io/viewer](/viewer). """ examples = [ "arkit_scenes", diff --git a/examples/python/notebook/cube.ipynb b/examples/python/notebook/cube.ipynb index 18ff9b205da5..8b4f13d2588a 100644 --- a/examples/python/notebook/cube.ipynb +++ b/examples/python/notebook/cube.ipynb @@ -21,7 +21,7 @@ "\n", "import numpy as np\n", "import rerun as rr # pip install rerun-sdk\n", - "import rerun.blueprint as rrb" + "import rerun.blueprint as rrb\n" ] }, { @@ -31,7 +31,7 @@ "source": [ "## Optional: start a local web-viewer server\n", "\n", - "By default, Rerun will use a copy of the viewer hosted at [https://app.rerun.io](https://app.rerun.io).\n", + "By default, Rerun will use a copy of the viewer hosted at [https://rerun.io/viewer](https://rerun.io/viewer).\n", "This is generally preferable as it will work more seamlessly even if you\n", "are connected to a notebook instance on a remote machine. However there\n", "are some cases where this won't work such as running from source, or\n", @@ -48,7 +48,7 @@ "metadata": {}, "outputs": [], "source": [ - "# rr.start_web_viewer_server()" + "# rr.start_web_viewer_server()\n" ] }, { @@ -117,7 +117,7 @@ " ]\n", " )\n", "\n", - " return ColorGrid(positions.T, colors.T.astype(np.uint8))" + " return ColorGrid(positions.T, colors.T.astype(np.uint8))\n" ] }, { @@ -144,7 +144,7 @@ "for t in range(STEPS):\n", " rr.set_time_sequence(\"step\", t)\n", " cube = build_color_grid(10, 10, 10, twist=twists[t])\n", - " rr.log(\"cube\", rr.Points3D(cube.positions, colors=cube.colors, radii=0.5))" + " rr.log(\"cube\", rr.Points3D(cube.positions, colors=cube.colors, radii=0.5))\n" ] }, { @@ -164,7 +164,7 @@ "metadata": {}, "outputs": [], "source": [ - "rr.notebook_show()" + "rr.notebook_show()\n" ] }, { @@ -186,7 +186,7 @@ }, "outputs": [], "source": [ - "rr.notebook_show(width=400, height=400)" + "rr.notebook_show(width=400, height=400)\n" ] }, { @@ -217,7 +217,7 @@ " v_grid = build_color_grid(3, 3, 10, twist=twists[t])\n", " rr.log(\"v_grid\", rr.Points3D(v_grid.positions, colors=v_grid.colors, radii=0.5))\n", "\n", - "rr.notebook_show()" + "rr.notebook_show()\n" ] }, { @@ -247,7 +247,7 @@ " collapse_panels=True\n", ")\n", "\n", - "rr.notebook_show(blueprint=blueprint)" + "rr.notebook_show(blueprint=blueprint)\n" ] }, { @@ -269,7 +269,7 @@ "metadata": {}, "outputs": [], "source": [ - "rrb.Spatial3DView(name=\"Horizontal grid\", origin=\"h_grid\")" + "rrb.Spatial3DView(name=\"Horizontal grid\", origin=\"h_grid\")\n" ] }, { @@ -298,7 +298,7 @@ "\n", "bp = rrb.Blueprint(collapse_panels=True)\n", "\n", - "rec.notebook_show(blueprint=bp)" + "rec.notebook_show(blueprint=bp)\n" ] }, { diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index c9b07c32eedb..66adc08165b7 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -1057,7 +1057,7 @@ fn version() -> String { /// Get a url to an instance of the web-viewer /// -/// This may point to app.rerun.io or localhost depending on +/// This may point to rerun.io/viewer or localhost depending on /// whether [`start_web_viewer_server()`] was called. #[pyfunction] fn get_app_url() -> String { @@ -1068,12 +1068,12 @@ fn get_app_url() -> String { let build_info = re_build_info::build_info!(); if let Some(short_git_hash) = build_info.git_hash.get(..7) { - format!("https://app.rerun.io/commit/{short_git_hash}") + format!("https://rerun.io/viewer/commit/{short_git_hash}") } else { re_log::warn_once!( - "No valid git hash found in build info. Defaulting to app.rerun.io for app url." + "No valid git hash found in build info. Defaulting to rerun.io/viewer for app url." ); - "https://app.rerun.io".to_owned() + "https://rerun.io/viewer".to_owned() } } diff --git a/scripts/ci/generate_pr_summary.py b/scripts/ci/generate_pr_summary.py index 5a1b0bd0cd38..cfea39ee1528 100644 --- a/scripts/ci/generate_pr_summary.py +++ b/scripts/ci/generate_pr_summary.py @@ -47,7 +47,7 @@ def generate_pr_summary(github_token: str, github_repository: str, pr_number: in app_blob = viewer_bucket.blob(f"commit/{commit_short}/index.html") if app_blob.exists(): print(f"Found web assets commit: {commit_short}") - found["hosted_app"] = f"https://app.rerun.io/commit/{commit_short}" + found["hosted_app"] = f"https://rerun.io/viewer/commit/{commit_short}" # Check if there are rerun_c libraries rerun_libraries_blobs = [ diff --git a/scripts/screenshot_compare/build_screenshot_compare.py b/scripts/screenshot_compare/build_screenshot_compare.py index 38e334f7e03f..5a25c7f5e9c2 100755 --- a/scripts/screenshot_compare/build_screenshot_compare.py +++ b/scripts/screenshot_compare/build_screenshot_compare.py @@ -8,7 +8,7 @@ - The screenshots listed in .fbs files (crates/re_types/definitions/rerun/**/*.fbs), and the corresponding snippets in the docs (docs/snippets/*.rs) -- The `app.rerun.io` examples, as built by the `re_build_examples` script. +- The `rerun.io/viewer` examples, as built by the `re_build_examples` script. The comparisons are generated in the `compare_screenshot` directory. Use the `--serve` option to show them in a browser. From b4969cd1b8a590ea4791267cc37bcb41b43da634 Mon Sep 17 00:00:00 2001 From: rerun-bot <132550499+rerun-bot@users.noreply.github.com> Date: Tue, 2 Apr 2024 14:30:40 +0200 Subject: [PATCH 153/508] Release 0.15.0-alpha.5 (#5728) ### Next steps - Test the release - If this is an 'alpha' release, you can just merge the pull request. - Otherwise: - For any added commits, run the release workflow in 'rc' mode again - After testing, run the release workflow in 'release' mode - Once the final release workflow finishes it will create a GitHub release for you. Then: - [x] Sanity check the build artifacts: - [x] pip install: does it install and run? - [x] cargo install of cli tool: does it install and run? - [x] C++ SDK zip: does it contain rerun_c for all platforms? - [ ] Populate the release with the changelog and a nice header video/picture, check , then click . - [ ] Make sure the [conda feedstock PR](https://github.com/conda-forge/rerun-sdk-feedstock/pulls) gets merged. This will be created by the once the GitHub release is created. - [ ] Update the [google colab notebooks](https://drive.google.com/drive/folders/0AC0q24MFKh3fUk9PVA) to install this version and re-execute the notebook. - [ ] Tests - [ ] Windows - [ ] Linux - [ ] MacOS --------- Co-authored-by: Jeremy Leibs --- Cargo.lock | 186 +++++++++--------- Cargo.toml | 94 ++++----- examples/rust/clock/Cargo.toml | 2 +- examples/rust/custom_data_loader/Cargo.toml | 2 +- examples/rust/custom_space_view/Cargo.toml | 2 +- .../rust/custom_store_subscriber/Cargo.toml | 2 +- examples/rust/dna/Cargo.toml | 2 +- examples/rust/extend_viewer_ui/Cargo.toml | 2 +- examples/rust/external_data_loader/Cargo.toml | 2 +- examples/rust/incremental_logging/Cargo.toml | 2 +- examples/rust/log_file/Cargo.toml | 2 +- examples/rust/minimal/Cargo.toml | 2 +- examples/rust/minimal_options/Cargo.toml | 2 +- examples/rust/minimal_serve/Cargo.toml | 2 +- examples/rust/objectron/Cargo.toml | 2 +- examples/rust/raw_mesh/Cargo.toml | 2 +- examples/rust/shared_recording/Cargo.toml | 2 +- examples/rust/spawn_viewer/Cargo.toml | 2 +- examples/rust/stdio/Cargo.toml | 2 +- examples/rust/template/Cargo.toml | 2 +- rerun_cpp/src/rerun/c/rerun.h | 2 +- rerun_js/web-viewer-react/README.md | 2 +- rerun_js/web-viewer-react/package.json | 4 +- rerun_js/web-viewer/README.md | 2 +- rerun_js/web-viewer/package.json | 4 +- tests/rust/plot_dashboard_stress/Cargo.toml | 2 +- 26 files changed, 166 insertions(+), 166 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4d26cdce758..670a0a18fc8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1057,7 +1057,7 @@ dependencies = [ [[package]] name = "clock" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -1394,7 +1394,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] name = "custom_data_loader" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "re_build_tools", "rerun", @@ -1402,7 +1402,7 @@ dependencies = [ [[package]] name = "custom_space_view" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "mimalloc", "re_crash_handler", @@ -1413,7 +1413,7 @@ dependencies = [ [[package]] name = "custom_store_subscriber" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "re_build_tools", "rerun", @@ -1524,7 +1524,7 @@ dependencies = [ [[package]] name = "dna" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "itertools 0.12.0", "rand", @@ -1955,7 +1955,7 @@ dependencies = [ [[package]] name = "extend_viewer_ui" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "mimalloc", "re_crash_handler", @@ -2618,7 +2618,7 @@ dependencies = [ [[package]] name = "incremental_logging" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -2969,7 +2969,7 @@ dependencies = [ [[package]] name = "log_benchmark" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -2980,7 +2980,7 @@ dependencies = [ [[package]] name = "log_file" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -3121,14 +3121,14 @@ dependencies = [ [[package]] name = "minimal" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "rerun", ] [[package]] name = "minimal_options" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -3138,7 +3138,7 @@ dependencies = [ [[package]] name = "minimal_serve" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "rerun", "tokio", @@ -3506,7 +3506,7 @@ dependencies = [ [[package]] name = "objectron" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -3689,7 +3689,7 @@ dependencies = [ [[package]] name = "plot_dashboard_stress" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -4117,7 +4117,7 @@ checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" [[package]] name = "raw_mesh" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "bytes", @@ -4156,7 +4156,7 @@ dependencies = [ [[package]] name = "re_analytics" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "crossbeam", "directories-next", @@ -4198,7 +4198,7 @@ dependencies = [ [[package]] name = "re_build_examples" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "argh", @@ -4213,11 +4213,11 @@ dependencies = [ [[package]] name = "re_build_info" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" [[package]] name = "re_build_search_index" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "argh", @@ -4242,7 +4242,7 @@ dependencies = [ [[package]] name = "re_build_tools" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "cargo_metadata 0.18.1", @@ -4255,7 +4255,7 @@ dependencies = [ [[package]] name = "re_build_web_viewer" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "cargo_metadata 0.18.1", @@ -4265,7 +4265,7 @@ dependencies = [ [[package]] name = "re_crash_handler" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "backtrace", "itertools 0.12.0", @@ -4277,7 +4277,7 @@ dependencies = [ [[package]] name = "re_data_source" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4300,7 +4300,7 @@ dependencies = [ [[package]] name = "re_data_store" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4330,7 +4330,7 @@ dependencies = [ [[package]] name = "re_data_ui" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4359,7 +4359,7 @@ dependencies = [ [[package]] name = "re_entity_db" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4393,14 +4393,14 @@ dependencies = [ [[package]] name = "re_error" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", ] [[package]] name = "re_format" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "comfy-table", "re_arrow2", @@ -4410,7 +4410,7 @@ dependencies = [ [[package]] name = "re_int_histogram" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "criterion", "insta", @@ -4421,7 +4421,7 @@ dependencies = [ [[package]] name = "re_log" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "env_logger", "js-sys", @@ -4434,7 +4434,7 @@ dependencies = [ [[package]] name = "re_log_encoding" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "criterion", "ehttp", @@ -4459,7 +4459,7 @@ dependencies = [ [[package]] name = "re_log_types" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4497,7 +4497,7 @@ dependencies = [ [[package]] name = "re_memory" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "backtrace", @@ -4518,7 +4518,7 @@ dependencies = [ [[package]] name = "re_query" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "backtrace", "criterion", @@ -4542,7 +4542,7 @@ dependencies = [ [[package]] name = "re_query_cache" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "criterion", @@ -4567,7 +4567,7 @@ dependencies = [ [[package]] name = "re_renderer" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4614,7 +4614,7 @@ dependencies = [ [[package]] name = "re_renderer_examples" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4638,7 +4638,7 @@ dependencies = [ [[package]] name = "re_sdk" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4670,7 +4670,7 @@ dependencies = [ [[package]] name = "re_sdk_comms" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "crossbeam", @@ -4686,7 +4686,7 @@ dependencies = [ [[package]] name = "re_smart_channel" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "crossbeam", "parking_lot", @@ -4697,7 +4697,7 @@ dependencies = [ [[package]] name = "re_space_view" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "egui", @@ -4718,7 +4718,7 @@ dependencies = [ [[package]] name = "re_space_view_bar_chart" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "egui", "egui_plot", @@ -4736,7 +4736,7 @@ dependencies = [ [[package]] name = "re_space_view_dataframe" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "egui", "egui_extras", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "re_space_view_spatial" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4792,7 +4792,7 @@ dependencies = [ [[package]] name = "re_space_view_tensor" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -4818,7 +4818,7 @@ dependencies = [ [[package]] name = "re_space_view_text_document" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "egui", "egui_commonmark", @@ -4836,7 +4836,7 @@ dependencies = [ [[package]] name = "re_space_view_text_log" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "egui", "egui_extras", @@ -4856,7 +4856,7 @@ dependencies = [ [[package]] name = "re_space_view_time_series" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "egui", "egui_plot", @@ -4879,7 +4879,7 @@ dependencies = [ [[package]] name = "re_string_interner" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "nohash-hasher", @@ -4891,7 +4891,7 @@ dependencies = [ [[package]] name = "re_time_panel" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "egui", "itertools 0.12.0", @@ -4910,7 +4910,7 @@ dependencies = [ [[package]] name = "re_tracing" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "puffin", "puffin_http", @@ -4920,7 +4920,7 @@ dependencies = [ [[package]] name = "re_tuid" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "criterion", "document-features", @@ -4932,7 +4932,7 @@ dependencies = [ [[package]] name = "re_types" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "array-init", @@ -4971,7 +4971,7 @@ dependencies = [ [[package]] name = "re_types_builder" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "camino", @@ -4997,7 +4997,7 @@ dependencies = [ [[package]] name = "re_types_core" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "backtrace", @@ -5017,7 +5017,7 @@ dependencies = [ [[package]] name = "re_ui" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "eframe", "egui", @@ -5038,7 +5038,7 @@ dependencies = [ [[package]] name = "re_viewer" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -5102,7 +5102,7 @@ dependencies = [ [[package]] name = "re_viewer_context" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "anyhow", @@ -5144,7 +5144,7 @@ dependencies = [ [[package]] name = "re_viewport" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "array-init", @@ -5179,7 +5179,7 @@ dependencies = [ [[package]] name = "re_web_viewer_server" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "clap", "document-features", @@ -5194,7 +5194,7 @@ dependencies = [ [[package]] name = "re_ws_comms" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "bincode", @@ -5284,7 +5284,7 @@ checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" [[package]] name = "rerun" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5318,7 +5318,7 @@ dependencies = [ [[package]] name = "rerun-cli" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "document-features", "mimalloc", @@ -5334,7 +5334,7 @@ dependencies = [ [[package]] name = "rerun-loader-rust-file" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "argh", @@ -5343,7 +5343,7 @@ dependencies = [ [[package]] name = "rerun_c" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "ahash", "once_cell", @@ -5355,7 +5355,7 @@ dependencies = [ [[package]] name = "rerun_py" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "crossbeam", "document-features", @@ -5454,7 +5454,7 @@ dependencies = [ [[package]] name = "roundtrip_annotation_context" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5464,7 +5464,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows2d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5474,7 +5474,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows3d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5484,7 +5484,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes2d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5494,7 +5494,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes3d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5504,7 +5504,7 @@ dependencies = [ [[package]] name = "roundtrip_depth_image" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5515,7 +5515,7 @@ dependencies = [ [[package]] name = "roundtrip_disconnected_space" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5525,7 +5525,7 @@ dependencies = [ [[package]] name = "roundtrip_image" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5538,7 +5538,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips2d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5548,7 +5548,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips3d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5558,7 +5558,7 @@ dependencies = [ [[package]] name = "roundtrip_pinhole" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5568,7 +5568,7 @@ dependencies = [ [[package]] name = "roundtrip_points2d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5578,7 +5578,7 @@ dependencies = [ [[package]] name = "roundtrip_points3d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5588,7 +5588,7 @@ dependencies = [ [[package]] name = "roundtrip_segmentation_image" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5599,7 +5599,7 @@ dependencies = [ [[package]] name = "roundtrip_tensor" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5610,7 +5610,7 @@ dependencies = [ [[package]] name = "roundtrip_text_document" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5620,7 +5620,7 @@ dependencies = [ [[package]] name = "roundtrip_text_log" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5630,7 +5630,7 @@ dependencies = [ [[package]] name = "roundtrip_transform3d" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5640,7 +5640,7 @@ dependencies = [ [[package]] name = "roundtrip_view_coordinates" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -5656,7 +5656,7 @@ checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" [[package]] name = "run_wasm" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "cargo-run-wasm", "pico-args", @@ -5931,7 +5931,7 @@ dependencies = [ [[package]] name = "shared_recording" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "rerun", ] @@ -6067,7 +6067,7 @@ dependencies = [ [[package]] name = "snippets" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "itertools 0.12.0", "ndarray", @@ -6089,7 +6089,7 @@ dependencies = [ [[package]] name = "spawn_viewer" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "rerun", ] @@ -6123,7 +6123,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stdio" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "rerun", ] @@ -6219,7 +6219,7 @@ dependencies = [ [[package]] name = "template" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "rerun", ] @@ -6235,7 +6235,7 @@ dependencies = [ [[package]] name = "test_api" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "anyhow", "clap", @@ -6250,7 +6250,7 @@ dependencies = [ [[package]] name = "test_image_memory" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" dependencies = [ "mimalloc", "re_format", diff --git a/Cargo.toml b/Cargo.toml index b22fd53c8e52..9dce19564408 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,59 +20,59 @@ include = ["../../LICENSE-APACHE", "../../LICENSE-MIT", "**/*.rs", "Cargo.toml"] license = "MIT OR Apache-2.0" repository = "https://github.com/rerun-io/rerun" rust-version = "1.74" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" [workspace.dependencies] # When using alpha-release, always use exact version, e.g. `version = "=0.x.y-alpha.z" # This is because we treat alpha-releases as incompatible, but semver doesn't. # In particular: if we compile rerun 0.3.0-alpha.0 we only want it to use # re_log_types 0.3.0-alpha.0, NOT 0.3.0-alpha.4 even though it is newer and semver-compatible. -re_analytics = { path = "crates/re_analytics", version = "=0.15.0-alpha.3", default-features = false } -re_build_search_index = { path = "crates/re_build_search_index", version = "=0.15.0-alpha.3", default-features = false } -re_build_examples = { path = "crates/re_build_examples", version = "=0.15.0-alpha.3", default-features = false } -re_build_info = { path = "crates/re_build_info", version = "=0.15.0-alpha.3", default-features = false } -re_build_tools = { path = "crates/re_build_tools", version = "=0.15.0-alpha.3", default-features = false } -re_build_web_viewer = { path = "crates/re_build_web_viewer", version = "=0.15.0-alpha.3", default-features = false } -re_crash_handler = { path = "crates/re_crash_handler", version = "=0.15.0-alpha.3", default-features = false } -re_data_source = { path = "crates/re_data_source", version = "=0.15.0-alpha.3", default-features = false } -re_data_store = { path = "crates/re_data_store", version = "=0.15.0-alpha.3", default-features = false } -re_data_ui = { path = "crates/re_data_ui", version = "=0.15.0-alpha.3", default-features = false } -re_entity_db = { path = "crates/re_entity_db", version = "=0.15.0-alpha.3", default-features = false } -re_error = { path = "crates/re_error", version = "=0.15.0-alpha.3", default-features = false } -re_format = { path = "crates/re_format", version = "=0.15.0-alpha.3", default-features = false } -re_int_histogram = { path = "crates/re_int_histogram", version = "=0.15.0-alpha.3", default-features = false } -re_log = { path = "crates/re_log", version = "=0.15.0-alpha.3", default-features = false } -re_log_encoding = { path = "crates/re_log_encoding", version = "=0.15.0-alpha.3", default-features = false } -re_log_types = { path = "crates/re_log_types", version = "=0.15.0-alpha.3", default-features = false } -re_memory = { path = "crates/re_memory", version = "=0.15.0-alpha.3", default-features = false } -re_query = { path = "crates/re_query", version = "=0.15.0-alpha.3", default-features = false } -re_query_cache = { path = "crates/re_query_cache", version = "=0.15.0-alpha.3", default-features = false } -re_renderer = { path = "crates/re_renderer", version = "=0.15.0-alpha.3", default-features = false } -re_sdk = { path = "crates/re_sdk", version = "=0.15.0-alpha.3", default-features = false } -re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.15.0-alpha.3", default-features = false } -re_smart_channel = { path = "crates/re_smart_channel", version = "=0.15.0-alpha.3", default-features = false } -re_space_view = { path = "crates/re_space_view", version = "=0.15.0-alpha.3", default-features = false } -re_space_view_bar_chart = { path = "crates/re_space_view_bar_chart", version = "=0.15.0-alpha.3", default-features = false } -re_space_view_dataframe = { path = "crates/re_space_view_dataframe", version = "=0.15.0-alpha.3", default-features = false } -re_space_view_spatial = { path = "crates/re_space_view_spatial", version = "=0.15.0-alpha.3", default-features = false } -re_space_view_tensor = { path = "crates/re_space_view_tensor", version = "=0.15.0-alpha.3", default-features = false } -re_space_view_text_document = { path = "crates/re_space_view_text_document", version = "=0.15.0-alpha.3", default-features = false } -re_space_view_text_log = { path = "crates/re_space_view_text_log", version = "=0.15.0-alpha.3", default-features = false } -re_space_view_time_series = { path = "crates/re_space_view_time_series", version = "=0.15.0-alpha.3", default-features = false } -re_string_interner = { path = "crates/re_string_interner", version = "=0.15.0-alpha.3", default-features = false } -re_time_panel = { path = "crates/re_time_panel", version = "=0.15.0-alpha.3", default-features = false } -re_tracing = { path = "crates/re_tracing", version = "=0.15.0-alpha.3", default-features = false } -re_tuid = { path = "crates/re_tuid", version = "=0.15.0-alpha.3", default-features = false } -re_types = { path = "crates/re_types", version = "=0.15.0-alpha.3", default-features = false } -re_types_builder = { path = "crates/re_types_builder", version = "=0.15.0-alpha.3", default-features = false } -re_types_core = { path = "crates/re_types_core", version = "=0.15.0-alpha.3", default-features = false } -re_ui = { path = "crates/re_ui", version = "=0.15.0-alpha.3", default-features = false } -re_viewer = { path = "crates/re_viewer", version = "=0.15.0-alpha.3", default-features = false } -re_viewer_context = { path = "crates/re_viewer_context", version = "=0.15.0-alpha.3", default-features = false } -re_viewport = { path = "crates/re_viewport", version = "=0.15.0-alpha.3", default-features = false } -re_web_viewer_server = { path = "crates/re_web_viewer_server", version = "=0.15.0-alpha.3", default-features = false } -re_ws_comms = { path = "crates/re_ws_comms", version = "=0.15.0-alpha.3", default-features = false } -rerun = { path = "crates/rerun", version = "=0.15.0-alpha.3", default-features = false } +re_analytics = { path = "crates/re_analytics", version = "=0.15.0-alpha.5", default-features = false } +re_build_search_index = { path = "crates/re_build_search_index", version = "=0.15.0-alpha.5", default-features = false } +re_build_examples = { path = "crates/re_build_examples", version = "=0.15.0-alpha.5", default-features = false } +re_build_info = { path = "crates/re_build_info", version = "=0.15.0-alpha.5", default-features = false } +re_build_tools = { path = "crates/re_build_tools", version = "=0.15.0-alpha.5", default-features = false } +re_build_web_viewer = { path = "crates/re_build_web_viewer", version = "=0.15.0-alpha.5", default-features = false } +re_crash_handler = { path = "crates/re_crash_handler", version = "=0.15.0-alpha.5", default-features = false } +re_data_source = { path = "crates/re_data_source", version = "=0.15.0-alpha.5", default-features = false } +re_data_store = { path = "crates/re_data_store", version = "=0.15.0-alpha.5", default-features = false } +re_data_ui = { path = "crates/re_data_ui", version = "=0.15.0-alpha.5", default-features = false } +re_entity_db = { path = "crates/re_entity_db", version = "=0.15.0-alpha.5", default-features = false } +re_error = { path = "crates/re_error", version = "=0.15.0-alpha.5", default-features = false } +re_format = { path = "crates/re_format", version = "=0.15.0-alpha.5", default-features = false } +re_int_histogram = { path = "crates/re_int_histogram", version = "=0.15.0-alpha.5", default-features = false } +re_log = { path = "crates/re_log", version = "=0.15.0-alpha.5", default-features = false } +re_log_encoding = { path = "crates/re_log_encoding", version = "=0.15.0-alpha.5", default-features = false } +re_log_types = { path = "crates/re_log_types", version = "=0.15.0-alpha.5", default-features = false } +re_memory = { path = "crates/re_memory", version = "=0.15.0-alpha.5", default-features = false } +re_query = { path = "crates/re_query", version = "=0.15.0-alpha.5", default-features = false } +re_query_cache = { path = "crates/re_query_cache", version = "=0.15.0-alpha.5", default-features = false } +re_renderer = { path = "crates/re_renderer", version = "=0.15.0-alpha.5", default-features = false } +re_sdk = { path = "crates/re_sdk", version = "=0.15.0-alpha.5", default-features = false } +re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.15.0-alpha.5", default-features = false } +re_smart_channel = { path = "crates/re_smart_channel", version = "=0.15.0-alpha.5", default-features = false } +re_space_view = { path = "crates/re_space_view", version = "=0.15.0-alpha.5", default-features = false } +re_space_view_bar_chart = { path = "crates/re_space_view_bar_chart", version = "=0.15.0-alpha.5", default-features = false } +re_space_view_dataframe = { path = "crates/re_space_view_dataframe", version = "=0.15.0-alpha.5", default-features = false } +re_space_view_spatial = { path = "crates/re_space_view_spatial", version = "=0.15.0-alpha.5", default-features = false } +re_space_view_tensor = { path = "crates/re_space_view_tensor", version = "=0.15.0-alpha.5", default-features = false } +re_space_view_text_document = { path = "crates/re_space_view_text_document", version = "=0.15.0-alpha.5", default-features = false } +re_space_view_text_log = { path = "crates/re_space_view_text_log", version = "=0.15.0-alpha.5", default-features = false } +re_space_view_time_series = { path = "crates/re_space_view_time_series", version = "=0.15.0-alpha.5", default-features = false } +re_string_interner = { path = "crates/re_string_interner", version = "=0.15.0-alpha.5", default-features = false } +re_time_panel = { path = "crates/re_time_panel", version = "=0.15.0-alpha.5", default-features = false } +re_tracing = { path = "crates/re_tracing", version = "=0.15.0-alpha.5", default-features = false } +re_tuid = { path = "crates/re_tuid", version = "=0.15.0-alpha.5", default-features = false } +re_types = { path = "crates/re_types", version = "=0.15.0-alpha.5", default-features = false } +re_types_builder = { path = "crates/re_types_builder", version = "=0.15.0-alpha.5", default-features = false } +re_types_core = { path = "crates/re_types_core", version = "=0.15.0-alpha.5", default-features = false } +re_ui = { path = "crates/re_ui", version = "=0.15.0-alpha.5", default-features = false } +re_viewer = { path = "crates/re_viewer", version = "=0.15.0-alpha.5", default-features = false } +re_viewer_context = { path = "crates/re_viewer_context", version = "=0.15.0-alpha.5", default-features = false } +re_viewport = { path = "crates/re_viewport", version = "=0.15.0-alpha.5", default-features = false } +re_web_viewer_server = { path = "crates/re_web_viewer_server", version = "=0.15.0-alpha.5", default-features = false } +re_ws_comms = { path = "crates/re_ws_comms", version = "=0.15.0-alpha.5", default-features = false } +rerun = { path = "crates/rerun", version = "=0.15.0-alpha.5", default-features = false } # egui-crates: ecolor = "0.27.1" diff --git a/examples/rust/clock/Cargo.toml b/examples/rust/clock/Cargo.toml index 0e9a6c8515f5..d8d010536180 100644 --- a/examples/rust/clock/Cargo.toml +++ b/examples/rust/clock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clock" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_data_loader/Cargo.toml b/examples/rust/custom_data_loader/Cargo.toml index 2b85c41653c1..ac5f22c5234d 100644 --- a/examples/rust/custom_data_loader/Cargo.toml +++ b/examples/rust/custom_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_data_loader" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index 2d8f1e78018d..acdca2beaa81 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_space_view" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_store_subscriber/Cargo.toml b/examples/rust/custom_store_subscriber/Cargo.toml index df8f5c269393..541745d2e86f 100644 --- a/examples/rust/custom_store_subscriber/Cargo.toml +++ b/examples/rust/custom_store_subscriber/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_store_subscriber" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml index c913bf792d2b..66f92f5b5a2e 100644 --- a/examples/rust/dna/Cargo.toml +++ b/examples/rust/dna/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dna" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml index bf75342bcf04..e8b37eae7596 100644 --- a/examples/rust/extend_viewer_ui/Cargo.toml +++ b/examples/rust/extend_viewer_ui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extend_viewer_ui" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/external_data_loader/Cargo.toml b/examples/rust/external_data_loader/Cargo.toml index a36d13fc0d8a..7ee3d4e7565a 100644 --- a/examples/rust/external_data_loader/Cargo.toml +++ b/examples/rust/external_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rerun-loader-rust-file" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml index ac5205661110..3dea27f2945e 100644 --- a/examples/rust/incremental_logging/Cargo.toml +++ b/examples/rust/incremental_logging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "incremental_logging" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml index 2d584d81bb49..0b81f4632c78 100644 --- a/examples/rust/log_file/Cargo.toml +++ b/examples/rust/log_file/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "log_file" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal/Cargo.toml b/examples/rust/minimal/Cargo.toml index 3e9b4064acab..08ccde4af01a 100644 --- a/examples/rust/minimal/Cargo.toml +++ b/examples/rust/minimal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_options/Cargo.toml b/examples/rust/minimal_options/Cargo.toml index 7fbebef29dab..f91c036bb215 100644 --- a/examples/rust/minimal_options/Cargo.toml +++ b/examples/rust/minimal_options/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_options" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml index 58c0e3cebf3a..7f1b6d795c99 100644 --- a/examples/rust/minimal_serve/Cargo.toml +++ b/examples/rust/minimal_serve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_serve" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/objectron/Cargo.toml b/examples/rust/objectron/Cargo.toml index aac6e6bbc9f8..331b7d51f225 100644 --- a/examples/rust/objectron/Cargo.toml +++ b/examples/rust/objectron/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "objectron" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/raw_mesh/Cargo.toml b/examples/rust/raw_mesh/Cargo.toml index 11dbf7b167c2..c9be9caa5ddb 100644 --- a/examples/rust/raw_mesh/Cargo.toml +++ b/examples/rust/raw_mesh/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "raw_mesh" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/shared_recording/Cargo.toml b/examples/rust/shared_recording/Cargo.toml index 703657ded727..1110239a5e0a 100644 --- a/examples/rust/shared_recording/Cargo.toml +++ b/examples/rust/shared_recording/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared_recording" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/spawn_viewer/Cargo.toml b/examples/rust/spawn_viewer/Cargo.toml index 91d0df47ff2b..140a8c77f043 100644 --- a/examples/rust/spawn_viewer/Cargo.toml +++ b/examples/rust/spawn_viewer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spawn_viewer" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/stdio/Cargo.toml b/examples/rust/stdio/Cargo.toml index 797ac4debbc3..5379a7585c7c 100644 --- a/examples/rust/stdio/Cargo.toml +++ b/examples/rust/stdio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stdio" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/template/Cargo.toml b/examples/rust/template/Cargo.toml index 34e5ca05682d..a83e38fbca9a 100644 --- a/examples/rust/template/Cargo.toml +++ b/examples/rust/template/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "template" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/rerun_cpp/src/rerun/c/rerun.h b/rerun_cpp/src/rerun/c/rerun.h index 52e7de7ee858..6d8235c31fa4 100644 --- a/rerun_cpp/src/rerun/c/rerun.h +++ b/rerun_cpp/src/rerun/c/rerun.h @@ -268,7 +268,7 @@ typedef struct rr_error { /// /// This should match the string returned by `rr_version_string`. /// If not, the SDK's binary and the C header are out of sync. -#define RERUN_SDK_HEADER_VERSION "0.15.0-alpha.3" +#define RERUN_SDK_HEADER_VERSION "0.15.0-alpha.5" /// Returns a human-readable version string of the Rerun C SDK. /// diff --git a/rerun_js/web-viewer-react/README.md b/rerun_js/web-viewer-react/README.md index 244f3c31a2f7..8420a433f4c5 100644 --- a/rerun_js/web-viewer-react/README.md +++ b/rerun_js/web-viewer-react/README.md @@ -35,7 +35,7 @@ export default function App() { ``` The `rrd` in the snippet above should be a URL pointing to either: -- A hosted `.rrd` file, such as +- A hosted `.rrd` file, such as - A WebSocket connection to the SDK opened via the [`serve`](https://www.rerun.io/docs/reference/sdk-operating-modes#serve) API If `rrd` is not set, the viewer will display the same welcome screen as . diff --git a/rerun_js/web-viewer-react/package.json b/rerun_js/web-viewer-react/package.json index dcec745c59cb..06ce069a1df8 100644 --- a/rerun_js/web-viewer-react/package.json +++ b/rerun_js/web-viewer-react/package.json @@ -1,6 +1,6 @@ { "name": "@rerun-io/web-viewer-react", - "version": "0.14.0", + "version": "0.15.0-alpha.5", "description": "Embed the Rerun web viewer in your React app", "licenses": [ { @@ -39,7 +39,7 @@ "tsconfig.json" ], "dependencies": { - "@rerun-io/web-viewer": "0.14.0", + "@rerun-io/web-viewer": "0.15.0-alpha.5", "@types/react": "^18.2.33", "react": "^18.2.0" }, diff --git a/rerun_js/web-viewer/README.md b/rerun_js/web-viewer/README.md index aa4b42f30a60..a2aeda47572e 100644 --- a/rerun_js/web-viewer/README.md +++ b/rerun_js/web-viewer/README.md @@ -41,7 +41,7 @@ viewer.stop(); ``` The `rrd` in the snippet above should be a URL pointing to either: -- A hosted `.rrd` file, such as +- A hosted `.rrd` file, such as - A WebSocket connection to the SDK opened via the [`serve`](https://www.rerun.io/docs/reference/sdk-operating-modes#serve) API If `rrd` is not set, the viewer will display the same welcome screen as . diff --git a/rerun_js/web-viewer/package.json b/rerun_js/web-viewer/package.json index c085c6f4f161..c3841b2223c2 100644 --- a/rerun_js/web-viewer/package.json +++ b/rerun_js/web-viewer/package.json @@ -1,6 +1,6 @@ { "name": "@rerun-io/web-viewer", - "version": "0.14.0", + "version": "0.15.0-alpha.5", "description": "Embed the Rerun web viewer in your app", "licenses": [ { @@ -53,4 +53,4 @@ "dts-buddy": "^0.3.0", "typescript": "^5.2.2" } -} +} \ No newline at end of file diff --git a/tests/rust/plot_dashboard_stress/Cargo.toml b/tests/rust/plot_dashboard_stress/Cargo.toml index 9c67fd0cbee6..c939b36f9c51 100644 --- a/tests/rust/plot_dashboard_stress/Cargo.toml +++ b/tests/rust/plot_dashboard_stress/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "plot_dashboard_stress" -version = "0.15.0-alpha.3" +version = "0.15.0-alpha.5" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" From a4d8be49cd99d03a0d6735ee7f605b55fbb79915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Tue, 2 Apr 2024 15:47:20 +0200 Subject: [PATCH 154/508] Fix PR template links (#5745) ### What There's no `index.html` at the end of the link anymore ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5745/index.html) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5745/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5745/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5745) - [Docs preview](https://rerun.io/preview/fd764a9255a748362cb2bb270c01ce9c3d8e93c6/docs) - [Examples preview](https://rerun.io/preview/fd764a9255a748362cb2bb270c01ce9c3d8e93c6/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/pull_request_template.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 65291f2d6ad5..5a7ff934a584 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -16,9 +16,9 @@ To get an auto-generated PR description you can put "copilot:summary" or "copilo * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): - * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}/index.html) - * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) - * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) + * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}) + * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) + * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! From 779231bf2e3cb5dadb15d8cb3b817a609e342909 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 2 Apr 2024 09:58:07 -0400 Subject: [PATCH 155/508] Fix orphaned space views by constructing from tree rather than redundant component (#5744) ### What - Resolves: https://github.com/rerun-io/rerun/issues/5570 This was mostly just doing a code-cleanup I'd been meaning to do to avoid a foot-gun that was documented and ignored. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5744) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5744?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5744?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5744) - [Docs preview](https://rerun.io/preview/560dab5eeedc7953b2fe092d0a024652d72fd053/docs) - [Examples preview](https://rerun.io/preview/560dab5eeedc7953b2fe092d0a024652d72fd053/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../archetypes/viewport_blueprint.fbs | 3 -- .../archetypes/viewport_blueprint.rs | 47 ++----------------- crates/re_viewport/src/viewport_blueprint.rs | 34 +++++--------- .../archetypes/viewport_blueprint.cpp | 7 +-- .../archetypes/viewport_blueprint.hpp | 13 ----- rerun_py/rerun_sdk/rerun/blueprint/api.py | 16 ------- .../archetypes/viewport_blueprint.py | 14 ------ .../tests/unit/test_viewport_blueprint.py | 14 +----- 8 files changed, 20 insertions(+), 128 deletions(-) diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs index 66565cf2a609..bad0a07cd33f 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/viewport_blueprint.fbs @@ -16,9 +16,6 @@ table ViewportBlueprint ( // --- Required --- // --- Optional --- - /// All of the space-views that belong to the viewport. - space_views: [rerun.blueprint.components.IncludedSpaceView] ("attr.rerun.component_optional", nullable, order: 1000); - /// The layout of the space-views root_container: rerun.blueprint.components.RootContainer ("attr.rerun.component_optional", nullable, order: 2500); diff --git a/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs b/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs index 2551f2fcd98f..b458b1ed1edd 100644 --- a/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs +++ b/crates/re_viewport/src/blueprint/archetypes/viewport_blueprint.rs @@ -24,9 +24,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: The top-level description of the Viewport. #[derive(Clone, Debug, Default)] pub struct ViewportBlueprint { - /// All of the space-views that belong to the viewport. - pub space_views: Option>, - /// The layout of the space-views pub root_container: Option, @@ -59,8 +56,7 @@ pub struct ViewportBlueprint { impl ::re_types_core::SizeBytes for ViewportBlueprint { #[inline] fn heap_size_bytes(&self) -> u64 { - self.space_views.heap_size_bytes() - + self.root_container.heap_size_bytes() + self.root_container.heap_size_bytes() + self.maximized.heap_size_bytes() + self.auto_layout.heap_size_bytes() + self.auto_space_views.heap_size_bytes() @@ -69,8 +65,7 @@ impl ::re_types_core::SizeBytes for ViewportBlueprint { #[inline] fn is_pod() -> bool { - >>::is_pod() - && >::is_pod() + >::is_pod() && >::is_pod() && >::is_pod() && >::is_pod() @@ -84,12 +79,11 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.ViewportBlueprintIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.AutoLayout".into(), "rerun.blueprint.components.AutoSpaceViews".into(), - "rerun.blueprint.components.IncludedSpaceView".into(), "rerun.blueprint.components.RootContainer".into(), "rerun.blueprint.components.SpaceViewMaximized".into(), "rerun.blueprint.components.ViewerRecommendationHash".into(), @@ -97,13 +91,12 @@ static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.ViewportBlueprintIndicator".into(), "rerun.blueprint.components.AutoLayout".into(), "rerun.blueprint.components.AutoSpaceViews".into(), - "rerun.blueprint.components.IncludedSpaceView".into(), "rerun.blueprint.components.RootContainer".into(), "rerun.blueprint.components.SpaceViewMaximized".into(), "rerun.blueprint.components.ViewerRecommendationHash".into(), @@ -112,7 +105,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = }); impl ViewportBlueprint { - pub const NUM_COMPONENTS: usize = 8usize; + pub const NUM_COMPONENTS: usize = 7usize; } /// Indicator component for the [`ViewportBlueprint`] [`::re_types_core::Archetype`] @@ -162,20 +155,6 @@ impl ::re_types_core::Archetype for ViewportBlueprint { .into_iter() .map(|(name, array)| (name.full_name(), array)) .collect(); - let space_views = if let Some(array) = - arrays_by_name.get("rerun.blueprint.components.IncludedSpaceView") - { - Some({ - ::from_arrow_opt(&**array) - .with_context("rerun.blueprint.archetypes.ViewportBlueprint#space_views")? - .into_iter() - .map(|v| v.ok_or_else(DeserializationError::missing_data)) - .collect::>>() - .with_context("rerun.blueprint.archetypes.ViewportBlueprint#space_views")? - }) - } else { - None - }; let root_container = if let Some(array) = arrays_by_name.get("rerun.blueprint.components.RootContainer") { ::from_arrow_opt(&**array) @@ -236,7 +215,6 @@ impl ::re_types_core::Archetype for ViewportBlueprint { None }; Ok(Self { - space_views, root_container, maximized, auto_layout, @@ -252,9 +230,6 @@ impl ::re_types_core::AsComponents for ViewportBlueprint { use ::re_types_core::Archetype as _; [ Some(Self::indicator()), - self.space_views - .as_ref() - .map(|comp_batch| (comp_batch as &dyn ComponentBatch).into()), self.root_container .as_ref() .map(|comp| (comp as &dyn ComponentBatch).into()), @@ -285,7 +260,6 @@ impl ::re_types_core::AsComponents for ViewportBlueprint { impl ViewportBlueprint { pub fn new() -> Self { Self { - space_views: None, root_container: None, maximized: None, auto_layout: None, @@ -294,17 +268,6 @@ impl ViewportBlueprint { } } - #[inline] - pub fn with_space_views( - mut self, - space_views: impl IntoIterator< - Item = impl Into, - >, - ) -> Self { - self.space_views = Some(space_views.into_iter().map(Into::into).collect()); - self - } - #[inline] pub fn with_root_container( mut self, diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index cc23a5660392..58146df393e9 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -74,7 +74,6 @@ impl ViewportBlueprint { re_tracing::profile_function!(); let crate::blueprint::archetypes::ViewportBlueprint { - space_views, root_container, maximized, auto_layout, @@ -98,13 +97,19 @@ impl ViewportBlueprint { } }; - let space_view_ids: Vec = space_views - .unwrap_or(vec![]) - .iter() - .map(|id| id.0.into()) - .collect(); + let all_space_view_ids: Vec = blueprint_db + .tree() + .children + .get(SpaceViewId::registry_part()) + .map(|tree| { + tree.children + .values() + .map(|subtree| SpaceViewId::from_entity_path(&subtree.path)) + .collect() + }) + .unwrap_or_default(); - let space_views: BTreeMap = space_view_ids + let space_views: BTreeMap = all_space_view_ids .into_iter() .filter_map(|space_view: SpaceViewId| { SpaceViewBlueprint::try_from_db(space_view, blueprint_db, query) @@ -393,13 +398,6 @@ impl ViewportBlueprint { /// /// Note that this doesn't focus the corresponding tab. Use [`Self::focus_tab`] with the returned ID /// if needed. - /// - /// NOTE: Calling this more than once per frame will result in lost data. - /// Each call to `add_space_views` emits an updated list of [`IncludedSpaceView`]s - /// Built by taking the list of [`IncludedSpaceView`]s from the current frame - /// and adding the new space views to it. Since this the edit is not applied until - /// the end of frame the second call will see a stale version of the data. - // TODO(jleibs): Better safety check here. pub fn add_space_views( &self, space_views: impl Iterator, @@ -427,14 +425,6 @@ impl ViewportBlueprint { position_in_parent, )); } - - let components = self - .space_views - .keys() - .chain(new_ids.iter()) - .map(|id| IncludedSpaceView((*id).into())) - .collect::>(); - ctx.save_blueprint_component(&VIEWPORT_PATH.into(), &components); } new_ids diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp index 82770516049d..4ccf38c3458f 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.cpp @@ -14,13 +14,8 @@ namespace rerun { ) { using namespace blueprint::archetypes; std::vector cells; - cells.reserve(7); + cells.reserve(6); - if (archetype.space_views.has_value()) { - auto result = DataCell::from_loggable(archetype.space_views.value()); - RR_RETURN_NOT_OK(result.error); - cells.push_back(std::move(result.value)); - } if (archetype.root_container.has_value()) { auto result = DataCell::from_loggable(archetype.root_container.value()); RR_RETURN_NOT_OK(result.error); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp index 5420e0e6b680..3189bf8e2b7c 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp @@ -5,7 +5,6 @@ #include "../../blueprint/components/auto_layout.hpp" #include "../../blueprint/components/auto_space_views.hpp" -#include "../../blueprint/components/included_space_view.hpp" #include "../../blueprint/components/root_container.hpp" #include "../../blueprint/components/space_view_maximized.hpp" #include "../../blueprint/components/viewer_recommendation_hash.hpp" @@ -23,9 +22,6 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: The top-level description of the Viewport. struct ViewportBlueprint { - /// All of the space-views that belong to the viewport. - std::optional> space_views; - /// The layout of the space-views std::optional root_container; @@ -65,15 +61,6 @@ namespace rerun::blueprint::archetypes { ViewportBlueprint() = default; ViewportBlueprint(ViewportBlueprint&& other) = default; - /// All of the space-views that belong to the viewport. - ViewportBlueprint with_space_views( - Collection _space_views - ) && { - space_views = std::move(_space_views); - // See: https://github.com/rerun-io/rerun/issues/4027 - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) - } - /// The layout of the space-views ViewportBlueprint with_root_container( rerun::blueprint::components::RootContainer _root_container diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 74256bf100c6..367c0707f32f 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -1,6 +1,5 @@ from __future__ import annotations -import itertools import uuid from typing import Any, Iterable, Optional, Union @@ -104,12 +103,6 @@ def _log_to_stream(self, stream: RecordingStream) -> None: stream.log(self.blueprint_path(), arch, recording=stream) # type: ignore[attr-defined] - def _iter_space_views(self) -> Iterable[bytes]: - """Internal method to iterate over all of the space views in the blueprint.""" - # TODO(jleibs): This goes away when we get rid of `space_views` from the viewport and just use - # the entity-path lookup instead. - return [self.id.bytes] - def _repr_html_(self) -> Any: """IPython interface to conversion to html.""" return as_html(blueprint=self) @@ -228,12 +221,6 @@ def _log_to_stream(self, stream: RecordingStream) -> None: stream.log(self.blueprint_path(), arch) # type: ignore[attr-defined] - def _iter_space_views(self) -> Iterable[bytes]: - """Internal method to iterate over all of the space views in the blueprint.""" - # TODO(jleibs): This goes away when we get rid of `space_views` from the viewport and just use - # the entity-path lookup instead. - return itertools.chain.from_iterable(sub._iter_space_views() for sub in self.contents) - def _repr_html_(self) -> Any: """IPython interface to conversion to html.""" return as_html(blueprint=self) @@ -439,13 +426,10 @@ def _log_to_stream(self, stream: RecordingStream) -> None: self.root_container._log_to_stream(stream) root_container_id = self.root_container.id.bytes - space_views = list(self.root_container._iter_space_views()) else: root_container_id = None - space_views = [] viewport_arch = ViewportBlueprint( - space_views=space_views, root_container=root_container_id, auto_layout=self.auto_layout, auto_space_views=self.auto_space_views, 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 db6198bddb8b..1db5b3fa453a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/viewport_blueprint.py @@ -24,7 +24,6 @@ class ViewportBlueprint(Archetype): def __init__( self: Any, *, - space_views: datatypes.UuidArrayLike | None = None, root_container: datatypes.UuidLike | None = None, maximized: datatypes.UuidLike | None = None, auto_layout: blueprint_components.AutoLayoutLike | None = None, @@ -36,8 +35,6 @@ def __init__( Parameters ---------- - space_views: - All of the space-views that belong to the viewport. root_container: The layout of the space-views maximized: @@ -66,7 +63,6 @@ def __init__( # You can define your own __init__ function as a member of ViewportBlueprintExt in viewport_blueprint_ext.py with catch_and_log_exceptions(context=self.__class__.__name__): self.__attrs_init__( - space_views=space_views, root_container=root_container, maximized=maximized, auto_layout=auto_layout, @@ -79,7 +75,6 @@ def __init__( def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - space_views=None, # type: ignore[arg-type] root_container=None, # type: ignore[arg-type] maximized=None, # type: ignore[arg-type] auto_layout=None, # type: ignore[arg-type] @@ -94,15 +89,6 @@ def _clear(cls) -> ViewportBlueprint: inst.__attrs_clear__() return inst - space_views: blueprint_components.IncludedSpaceViewBatch | None = field( - metadata={"component": "optional"}, - default=None, - converter=blueprint_components.IncludedSpaceViewBatch._optional, # type: ignore[misc] - ) - # All of the space-views that belong to the viewport. - # - # (Docstring intentionally commented out to hide this field from the docs) - root_container: blueprint_components.RootContainerBatch | None = field( metadata={"component": "optional"}, default=None, diff --git a/rerun_py/tests/unit/test_viewport_blueprint.py b/rerun_py/tests/unit/test_viewport_blueprint.py index 0f6ab7ee67c2..fcd606fbf1b9 100644 --- a/rerun_py/tests/unit/test_viewport_blueprint.py +++ b/rerun_py/tests/unit/test_viewport_blueprint.py @@ -6,7 +6,6 @@ from rerun.blueprint.archetypes.viewport_blueprint import ViewportBlueprint from rerun.blueprint.components.auto_layout import AutoLayoutBatch, AutoLayoutLike from rerun.blueprint.components.auto_space_views import AutoSpaceViewsBatch, AutoSpaceViewsLike -from rerun.blueprint.components.included_space_view import IncludedSpaceViewBatch from rerun.blueprint.components.root_container import RootContainerBatch from rerun.blueprint.components.space_view_maximized import SpaceViewMaximizedBatch from rerun.blueprint.components.viewer_recommendation_hash import ( @@ -14,13 +13,12 @@ ViewerRecommendationHashBatch, ) from rerun.datatypes.uint64 import UInt64ArrayLike -from rerun.datatypes.uuid import UuidArrayLike, UuidLike +from rerun.datatypes.uuid import UuidLike -from .common_arrays import none_empty_or_value, uuid_bytes0, uuid_bytes1, uuids_arrays +from .common_arrays import none_empty_or_value, uuid_bytes0, uuid_bytes1 def test_viewport_blueprint() -> None: - space_views_arrays = uuids_arrays root_container_arrays = [ None, uuid_bytes0, @@ -38,7 +36,6 @@ def test_viewport_blueprint() -> None: ] all_arrays = itertools.zip_longest( - space_views_arrays, root_container_arrays, maximized_arrays, auto_layout_arrays, @@ -47,17 +44,13 @@ def test_viewport_blueprint() -> None: ) for ( - space_views, root_container, maximized, auto_layout, auto_space_views, past_viewer_recommendations, ) in all_arrays: - space_views = space_views if space_views is not None else space_views_arrays[-1] - # mypy can't track types properly through itertools zip so re-cast - space_views = cast(UuidArrayLike, space_views) root_container = cast(Optional[UuidLike], root_container) maximized = cast(Optional[UuidLike], maximized) auto_layout = cast(Optional[AutoLayoutLike], auto_layout) @@ -66,7 +59,6 @@ def test_viewport_blueprint() -> None: print( "rr.ViewportBlueprint(\n", - f" space_views={space_views!r}\n", f" root_container={root_container!r}\n", f" maximized={maximized!r}\n", f" auto_layout={auto_layout!r}\n", @@ -75,7 +67,6 @@ def test_viewport_blueprint() -> None: ")", ) arch = ViewportBlueprint( - space_views=space_views, root_container=root_container, maximized=maximized, auto_layout=auto_layout, @@ -84,7 +75,6 @@ def test_viewport_blueprint() -> None: ) print(f"{arch}\n") - assert arch.space_views == IncludedSpaceViewBatch._optional(none_empty_or_value(space_views, uuids_arrays[-1])) assert arch.root_container == RootContainerBatch._optional(none_empty_or_value(root_container, uuid_bytes0)) assert arch.maximized == SpaceViewMaximizedBatch._optional(none_empty_or_value(maximized, uuid_bytes1)) assert arch.auto_layout == AutoLayoutBatch._optional(none_empty_or_value(auto_layout, True)) From 15d8ba4aa3f4bbb337252acce480a2cfbd03881c Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 2 Apr 2024 16:00:09 +0200 Subject: [PATCH 156/508] Fix issue where "placeholder" `DataResults` couldn't be selected (#5743) ### What - Fixes #5683 This PR fixes an issue where "placeholder" `DataResult` (as per `DataResultNodeOrPath`) could not be selected because they would be rejected as invalid by `ViewportBlueprint::is_item_valid()`. This fix is quite hacky and should be improved: - https://github.com/rerun-io/rerun/issues/5742 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5743) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5743?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5743?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5743) - [Docs preview](https://rerun.io/preview/e1c43deb543078c413ec716c540255852b6dc429/docs) - [Examples preview](https://rerun.io/preview/e1c43deb543078c413ec716c540255852b6dc429/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewport/src/viewport_blueprint.rs | 17 +++++-- .../check_out_of_tree_data_results.py | 48 +++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 tests/python/release_checklist/check_out_of_tree_data_results.py diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 58146df393e9..b8072b183c52 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -259,6 +259,9 @@ impl ViewportBlueprint { } /// If `false`, the item is referring to data that is not present in this blueprint. + /// + /// TODO(#5742): note that `Item::DataResult` with entity path set to the space origin or some + /// of its descendent are always considered valid. pub fn is_item_valid(&self, item: &Item) -> bool { match item { Item::DataSource(_) @@ -270,10 +273,16 @@ impl ViewportBlueprint { Item::DataResult(space_view_id, instance_path) => { self.space_view(space_view_id).map_or(false, |space_view| { - space_view - .contents - .entity_path_filter - .is_included(&instance_path.entity_path) + let entity_path = &instance_path.entity_path; + + // TODO(#5742): including any path that is—or descend from—the space origin is + // necessary because such items may actually be displayed in the blueprint tree. + entity_path == &space_view.space_origin + || entity_path.is_descendant_of(&space_view.space_origin) + || space_view + .contents + .entity_path_filter + .is_included(&instance_path.entity_path) }) } diff --git a/tests/python/release_checklist/check_out_of_tree_data_results.py b/tests/python/release_checklist/check_out_of_tree_data_results.py new file mode 100644 index 000000000000..3fa03d7580b5 --- /dev/null +++ b/tests/python/release_checklist/check_out_of_tree_data_results.py @@ -0,0 +1,48 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr +import rerun.blueprint as rrb + +README = """ +# Out-of-tree data results + +[Background issue](https://github.com/rerun-io/rerun/issues/5742) + +* Expand all the "TEST" space view. +* Check that you can select each of its children. +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def blueprint() -> rrb.BlueprintLike: + return rrb.Blueprint(rrb.Spatial3DView(name="TEST", origin="/", contents="$origin/box/points/**")) + + +def log_data() -> None: + rr.log("/", rr.Transform3D(translation=[1, 0, 0])) + rr.log("/box", rr.Boxes3D(centers=[[0, 0, 0]], half_sizes=[0.5, 1, 0.5])) + rr.log("/box", rr.Transform3D(translation=[0, 1, 0])) + rr.log("/box/points", rr.Points3D(positions=[[0, 0, 0], [1, 1, 1]], radii=0.3)) + + +def run(args: Namespace) -> None: + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + + log_readme() + log_data() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) From e66f5725f317e693cb1a1ef5cbe12a531d545106 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 2 Apr 2024 19:14:13 +0200 Subject: [PATCH 157/508] Update to egui 0.27.2 (#5748) ### What See what's new in: https://github.com/emilk/egui/releases/tag/0.27.2 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5748) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5748?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5748?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5748) - [Docs preview](https://rerun.io/preview/4b3d1158959b50c3edb1448af5964408236219fd/docs) - [Examples preview](https://rerun.io/preview/4b3d1158959b50c3edb1448af5964408236219fd/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 40 ++++++++++++++++++++-------------------- Cargo.toml | 14 +++++++------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 670a0a18fc8f..bea4e0a2e543 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1554,9 +1554,9 @@ checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" [[package]] name = "ecolor" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb152797942f72b84496eb2ebeff0060240e0bf55096c4525ffa22dd54722d86" +checksum = "20930a432bbd57a6d55e07976089708d4893f3d556cf42a0d79e9e321fa73b10" dependencies = [ "bytemuck", "serde", @@ -1564,9 +1564,9 @@ dependencies = [ [[package]] name = "eframe" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcc8e06df6f0a6cf09a3247ff7e85fdfffc28dda4fe5561e05314bf7618a918" +checksum = "020e2ccef6bbcec71dbc542f7eed64a5846fc3076727f5746da8fd307c91bab2" dependencies = [ "bytemuck", "cocoa", @@ -1600,9 +1600,9 @@ dependencies = [ [[package]] name = "egui" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1b8cc14b0b260aa6bd124ef12c8a94f57ffe8e40aa970f3db710c21bb945f3" +checksum = "584c5d1bf9a67b25778a3323af222dbe1a1feb532190e103901187f92c7fe29a" dependencies = [ "accesskit", "ahash", @@ -1617,9 +1617,9 @@ dependencies = [ [[package]] name = "egui-wgpu" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04ee072f7cbd9e03ae4028db1c4a8677fbb4efc4b62feee6563763a6f041c88d" +checksum = "469ff65843f88a702b731a1532b7d03b0e8e96d283e70f3a22b0e06c46cb9b37" dependencies = [ "bytemuck", "document-features", @@ -1636,9 +1636,9 @@ dependencies = [ [[package]] name = "egui-winit" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3733435d6788c760bb98ce4cb1b8b7a2d953a3a7b421656ba8b3e014019be3d0" +checksum = "2e3da0cbe020f341450c599b35b92de4af7b00abde85624fd16f09c885573609" dependencies = [ "accesskit_winit", "arboard", @@ -1666,9 +1666,9 @@ dependencies = [ [[package]] name = "egui_extras" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70edf79855c42e55c357f7f97cd3be9be59cee2585cc39045ce8ff187aa8d4b0" +checksum = "1b78779f35ded1a853786c9ce0b43fe1053e10a21ea3b23ebea411805ce41593" dependencies = [ "egui", "ehttp", @@ -1682,9 +1682,9 @@ dependencies = [ [[package]] name = "egui_glow" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f933e9e64c4d074c78ce71785a5778f648453c2b2a3efd28eea189dac3f19c28" +checksum = "e0e5d975f3c86edc3d35b1db88bb27c15dde7c55d3b5af164968ab5ede3f44ca" dependencies = [ "bytemuck", "egui", @@ -1700,9 +1700,9 @@ dependencies = [ [[package]] name = "egui_plot" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6989f08973c1142953796068f559c40e62204c90b9da07841dd5c991a4a451d8" +checksum = "a7854b86dc1c2d352c5270db3d600011daa913d6b554141a03939761323288a1" dependencies = [ "egui", ] @@ -1744,9 +1744,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "emath" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555a7cbfcc52c81eb5f8f898190c840fa1c435f67f30b7ef77ce7cf6b7dcd987" +checksum = "e4c3a552cfca14630702449d35f41c84a0d15963273771c6059175a803620f3f" dependencies = [ "bytemuck", "serde", @@ -1846,9 +1846,9 @@ dependencies = [ [[package]] name = "epaint" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd63c37156e949bda80f7e39cc11508bc34840aecf52180567e67cdb2bf1a5fe" +checksum = "b381f8b149657a4acf837095351839f32cd5c4aec1817fc4df84e18d76334176" dependencies = [ "ab_glyph", "ahash", diff --git a/Cargo.toml b/Cargo.toml index 9dce19564408..e32cc1205c89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,15 +75,15 @@ re_ws_comms = { path = "crates/re_ws_comms", version = "=0.15.0-alpha.5", defaul rerun = { path = "crates/rerun", version = "=0.15.0-alpha.5", default-features = false } # egui-crates: -ecolor = "0.27.1" -eframe = { version = "0.27.1", default-features = false, features = [ +ecolor = "0.27.2" +eframe = { version = "0.27.2", default-features = false, features = [ "accesskit", "default_fonts", "puffin", "wayland", "x11", ] } -egui = { version = "0.27.1", features = [ +egui = { version = "0.27.2", features = [ "callstack", "extra_debug_asserts", "log", @@ -91,11 +91,11 @@ egui = { version = "0.27.1", features = [ "rayon", ] } egui_commonmark = { version = "0.14", default-features = false } -egui_extras = { version = "0.27.1", features = ["http", "image", "puffin"] } -egui_plot = "0.27.1" +egui_extras = { version = "0.27.2", features = ["http", "image", "puffin"] } +egui_plot = "0.27.2" egui_tiles = "0.8.0" -egui-wgpu = "0.27.1" -emath = "0.27.1" +egui-wgpu = "0.27.2" +emath = "0.27.2" # All of our direct external dependencies should be found here: ahash = "0.8" From e66d38e0152f9869eaba1fab7dff33c4f667c453 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 2 Apr 2024 19:25:40 +0200 Subject: [PATCH 158/508] Add feedback when no match exist under space origin (#5747) ### What Add some feedback when the query returns no match under the space origin: - the "eye" button is not displayed (visibility cannot be set on such entity) - a note is added to the hover tooltip This PR also sneakily changes the "Projections:" label for a `ListItem` for more consistent spacing. image - Fixes #5410 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../re_viewport/src/viewport_blueprint_ui.rs | 52 +++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 09738b7e9312..5a122f0dd71d 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -463,7 +463,10 @@ impl Viewport<'_, '_> { } }); if !projections.is_empty() { - ui.label(egui::RichText::new("Projections:").italics()); + ListItem::new(ctx.re_ui, "Projections:") + .interactive(false) + .italics(true) + .show_flat(ui); for projection in projections { self.space_view_entity_hierarchy_ui( @@ -552,6 +555,7 @@ impl Viewport<'_, '_> { ctx.selection_state().highlight_for_ui_element(&item) == HoverHighlight::Hovered; let visible = data_result_node.map_or(false, |n| n.data_result.is_visible(ctx)); + let empty_origin = entity_path == &space_view.space_origin && data_result_node.is_none(); let item_label = if entity_path.is_root() { "/ (root)".to_owned() @@ -578,22 +582,28 @@ impl Viewport<'_, '_> { .subdued(subdued) .force_hovered(is_item_hovered) .with_buttons(|re_ui: &_, ui: &mut egui::Ui| { - let mut visible_after = visible; - let vis_response = - visibility_button_ui(re_ui, ui, space_view_visible, &mut visible_after); - if visible_after != visible { - if let Some(data_result_node) = data_result_node { - data_result_node - .data_result - .save_recursive_override_or_clear_if_redundant( - ctx, - &query_result.tree, - &Visible(visible_after), - ); + let vis_response = if !empty_origin { + let mut visible_after = visible; + let vis_response = + visibility_button_ui(re_ui, ui, space_view_visible, &mut visible_after); + if visible_after != visible { + if let Some(data_result_node) = data_result_node { + data_result_node + .data_result + .save_recursive_override_or_clear_if_redundant( + ctx, + &query_result.tree, + &Visible(visible_after), + ); + } } - } - let response = remove_button_ui( + Some(vis_response) + } else { + None + }; + + let mut response = remove_button_ui( re_ui, ui, "Remove group and all its children from the space view", @@ -604,7 +614,11 @@ impl Viewport<'_, '_> { .remove_subtree_and_matching_rules(ctx, entity_path.clone()); } - response | vis_response + if let Some(vis_response) = vis_response { + response |= vis_response; + } + + response }); // If there's any children on the data result nodes, show them, otherwise we're good with this list item as is. @@ -654,6 +668,12 @@ impl Viewport<'_, '_> { let response = response.on_hover_ui(|ui| { let query = ctx.current_query(); re_data_ui::item_ui::entity_hover_card_ui(ui, ctx, &query, store, entity_path); + + if empty_origin { + ui.label(ctx.re_ui.warning_text( + "This space view's query did not match any data under the space origin", + )); + } }); context_menu_ui_for_item( From a671f0290fccfb4392343df2c3daae3cc268fad8 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 2 Apr 2024 20:35:19 +0200 Subject: [PATCH 159/508] Make selection history global instead of per recordings (#5739) ### What The selection history is now global, so the back/forward button work as expected when selecting various recordings. Note (quoting my comment in the original issue): > This is technically a functional regression. Before, we could have a different selection state for each recording (e.g "/world/robot" is selected in recording A and "/world/camera" is selected in recording B). However, in practice that's no longer true since recording have been made selectable: switching to a new recording now implies selecting said recording, in turn clearing the selection. This issue would make it harder to go back to the previous behaviour. - Fixes #5736 https://github.com/rerun-io/rerun/assets/49431240/d376605c-5306-4377-bcfa-acd9479c54d7 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5739/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5739/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5739/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5739) - [Docs preview](https://rerun.io/preview/3c9cbb2c945b6af1ddba49b0838de6227f8a4a2c/docs) - [Examples preview](https://rerun.io/preview/3c9cbb2c945b6af1ddba49b0838de6227f8a4a2c/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Jeremy Leibs --- crates/re_data_ui/src/item_ui.rs | 19 ++--------- crates/re_log_types/src/lib.rs | 9 +++++ crates/re_viewer/src/app.rs | 30 +++-------------- crates/re_viewer/src/app_state.rs | 33 +++++++++++++------ .../re_viewer_context/src/command_sender.rs | 8 +---- crates/re_viewer_context/src/store_hub.rs | 7 +--- .../re_viewer_context/src/viewer_context.rs | 12 +++---- 7 files changed, 46 insertions(+), 72 deletions(-) diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 24184b56645c..35faaf4c0206 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -695,22 +695,7 @@ pub fn entity_db_button_ui( .send_system(SystemCommand::ActivateRecording(store_id.clone())); } - // …and select the store in the selection panel. - // Note that we must do it in this order, since the selection state is stored in the recording. - // That's also why we use a command to set the selection. - match store_id.kind { - re_log_types::StoreKind::Recording => { - ctx.command_sender.send_system(SystemCommand::SetSelection { - recording_id: Some(store_id), - item, - }); - } - re_log_types::StoreKind::Blueprint => { - ctx.command_sender.send_system(SystemCommand::SetSelection { - recording_id: None, - item, - }); - } - } + ctx.command_sender + .send_system(SystemCommand::SetSelection(item)); } } diff --git a/crates/re_log_types/src/lib.rs b/crates/re_log_types/src/lib.rs index df17ee4a0caa..9319952f2bf9 100644 --- a/crates/re_log_types/src/lib.rs +++ b/crates/re_log_types/src/lib.rs @@ -130,6 +130,11 @@ impl StoreId { } } + #[inline] + pub fn empty_recording() -> Self { + Self::from_string(StoreKind::Recording, "".to_owned()) + } + #[inline] pub fn from_uuid(kind: StoreKind, uuid: uuid::Uuid) -> Self { Self { @@ -150,6 +155,10 @@ impl StoreId { pub fn as_str(&self) -> &str { self.id.as_str() } + + pub fn is_empty_recording(&self) -> bool { + self.kind == StoreKind::Recording && self.id.as_str() == "" + } } impl std::fmt::Display for StoreId { diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index a399be13e7e0..9b0079e43f34 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -422,18 +422,8 @@ impl App { } } - SystemCommand::SetSelection { recording_id, item } => { - let recording_id = - recording_id.or_else(|| store_hub.active_recording_id().cloned()); - if let Some(recording_id) = recording_id { - if let Some(rec_cfg) = self.state.recording_config_mut(&recording_id) { - rec_cfg.selection_state.set_selection(item); - } else { - re_log::debug!( - "Failed to select item {item:?}: failed to find recording {recording_id}" - ); - } - } + SystemCommand::SetSelection(item) => { + self.state.selection_state.set_selection(item); } SystemCommand::SetFocus(item) => { @@ -576,22 +566,10 @@ impl App { } UICommand::SelectionPrevious => { - let state = &mut self.state; - if let Some(rec_cfg) = store_context - .map(|ctx| ctx.recording.store_id()) - .and_then(|rec_id| state.recording_config_mut(rec_id)) - { - rec_cfg.selection_state.select_previous(); - } + self.state.selection_state.select_previous(); } UICommand::SelectionNext => { - let state = &mut self.state; - if let Some(rec_cfg) = store_context - .map(|ctx| ctx.recording.store_id()) - .and_then(|rec_id| state.recording_config_mut(rec_id)) - { - rec_cfg.selection_state.select_next(); - } + self.state.selection_state.select_next(); } UICommand::ToggleCommandPalette => { self.cmd_palette.toggle(); diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 425b7be544c1..8d6f72986307 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -43,6 +43,9 @@ pub struct AppState { #[serde(skip)] viewport_state: ViewportState, + /// Selection & hovering state. + pub selection_state: ApplicationSelectionState, + /// Item that got focused on the last frame if any. /// /// The focused item is cleared every frame, but views may react with side-effects @@ -63,6 +66,7 @@ impl Default for AppState { blueprint_panel: re_time_panel::TimePanel::new_blueprint_panel(), welcome_screen: Default::default(), viewport_state: Default::default(), + selection_state: Default::default(), focused_item: Default::default(), } } @@ -125,6 +129,7 @@ impl AppState { blueprint_panel, welcome_screen, viewport_state, + selection_state, focused_item, } = self; @@ -159,18 +164,21 @@ impl AppState { return; } - recording_config_entry(recording_configs, recording.store_id().clone(), recording) - .selection_state - .on_frame_start( - |item| viewport.is_item_valid(item), - re_viewer_context::Item::StoreId(store_context.recording.store_id().clone()), - ); + selection_state.on_frame_start( + |item| { + if let re_viewer_context::Item::StoreId(store_id) = item { + if store_id.is_empty_recording() { + return false; + } + } - let rec_cfg = - recording_config_entry(recording_configs, recording.store_id().clone(), recording); + viewport.is_item_valid(item) + }, + re_viewer_context::Item::StoreId(store_context.recording.store_id().clone()), + ); if ui.input(|i| i.key_pressed(egui::Key::Escape)) { - rec_cfg.selection_state.clear_selection(); + selection_state.clear_selection(); } let applicable_entities_per_visualizer = space_view_class_registry @@ -208,6 +216,9 @@ impl AppState { .collect::<_>() }; + let rec_cfg = + recording_config_entry(recording_configs, recording.store_id().clone(), recording); + let ctx = ViewerContext { app_options, cache, @@ -219,6 +230,7 @@ impl AppState { query_results: &query_results, rec_cfg, blueprint_cfg, + selection_state, blueprint_query: &blueprint_query, re_ui, render_ctx, @@ -274,6 +286,7 @@ impl AppState { query_results: &query_results, rec_cfg, blueprint_cfg, + selection_state, blueprint_query: &blueprint_query, re_ui, render_ctx, @@ -412,7 +425,7 @@ impl AppState { } // This must run after any ui code, or other code that tells egui to open an url: - check_for_clicked_hyperlinks(&re_ui.egui_ctx, &rec_cfg.selection_state); + check_for_clicked_hyperlinks(&re_ui.egui_ctx, ctx.selection_state); // Reset the focused item. *focused_item = None; diff --git a/crates/re_viewer_context/src/command_sender.rs b/crates/re_viewer_context/src/command_sender.rs index d35e11f3a8f8..53f1cc342e0d 100644 --- a/crates/re_viewer_context/src/command_sender.rs +++ b/crates/re_viewer_context/src/command_sender.rs @@ -40,13 +40,7 @@ pub enum SystemCommand { EnableExperimentalDataframeSpaceView(bool), /// Set the item selection. - SetSelection { - /// If set, use the recording config of this recording. - /// Else, use the currently active recording. - recording_id: Option, - - item: crate::Item, - }, + SetSelection(crate::Item), /// Sets the focus to the given item. /// diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 628ea0be100c..594fffbb3177 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -145,12 +145,7 @@ impl StoreHub { /// matching [`ApplicationId`]. pub fn read_context(&mut self) -> Option> { static EMPTY_ENTITY_DB: once_cell::sync::Lazy = - once_cell::sync::Lazy::new(|| { - EntityDb::new(re_log_types::StoreId::from_string( - StoreKind::Recording, - "".to_owned(), - )) - }); + once_cell::sync::Lazy::new(|| EntityDb::new(re_log_types::StoreId::empty_recording())); // If we have an app-id, then use it to look up the blueprint. let app_id = self.active_application_id.clone()?; diff --git a/crates/re_viewer_context/src/viewer_context.rs b/crates/re_viewer_context/src/viewer_context.rs index 575f19f237d8..d2bf51790df7 100644 --- a/crates/re_viewer_context/src/viewer_context.rs +++ b/crates/re_viewer_context/src/viewer_context.rs @@ -49,6 +49,9 @@ pub struct ViewerContext<'a> { /// UI config for the current blueprint. pub blueprint_cfg: &'a RecordingConfig, + /// Selection & hovering state. + pub selection_state: &'a ApplicationSelectionState, + /// The blueprint query used for resolving blueprint in this frame pub blueprint_query: &'a LatestAtQuery, @@ -89,16 +92,16 @@ impl<'a> ViewerContext<'a> { /// Returns the current selection. pub fn selection(&self) -> &ItemCollection { - self.rec_cfg.selection_state.selected_items() + self.selection_state.selected_items() } /// Returns the currently hovered objects. pub fn hovered(&self) -> &ItemCollection { - self.rec_cfg.selection_state.hovered_items() + self.selection_state.hovered_items() } pub fn selection_state(&self) -> &ApplicationSelectionState { - &self.rec_cfg.selection_state + self.selection_state } /// The current time query, based on the current time control. @@ -146,7 +149,4 @@ impl<'a> ViewerContext<'a> { pub struct RecordingConfig { /// The current time of the time panel, how fast it is moving, etc. pub time_ctrl: RwLock, - - /// Selection & hovering state. - pub selection_state: ApplicationSelectionState, } From af7283e3d3f7f048a040f507743768179759afc8 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 2 Apr 2024 15:00:42 -0400 Subject: [PATCH 160/508] Update docs with guides and tutorials for blueprint (#5641) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5641/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5641/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5641/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5641) - [Docs preview](https://rerun.io/preview/6f446839fca3b9fb1ac26407cb7ed65d1da1aa7c/docs) - [Examples preview](https://rerun.io/preview/6f446839fca3b9fb1ac26407cb7ed65d1da1aa7c/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/documentation.yaml | 3 +- .../getting-started/visualize/blueprint.md | 6 - docs/content/howto/configure-the-viewer.md | 25 ++ .../blueprint-api-tutorial.md | 389 ++++++++++++++++++ .../configure-the-viewer/interactively.md | 85 ++++ .../configure-the-viewer/save-and-load.md | 24 ++ .../configure-the-viewer/through-code.md | 290 +++++++++++++ docs/content/reference/entity-queries.md | 92 +++++ docs/content/reference/types.md | 2 +- docs/content/reference/viewer.md | 2 +- docs/cspell.json | 6 + .../rerun/datatypes/tensor_data_ext.py | 2 +- 12 files changed, 916 insertions(+), 10 deletions(-) delete mode 100644 docs/content/getting-started/visualize/blueprint.md create mode 100644 docs/content/howto/configure-the-viewer.md create mode 100644 docs/content/howto/configure-the-viewer/blueprint-api-tutorial.md create mode 100644 docs/content/howto/configure-the-viewer/interactively.md create mode 100644 docs/content/howto/configure-the-viewer/save-and-load.md create mode 100644 docs/content/howto/configure-the-viewer/through-code.md create mode 100644 docs/content/reference/entity-queries.md diff --git a/.github/workflows/documentation.yaml b/.github/workflows/documentation.yaml index 334af92eb3f8..1257c67eebad 100644 --- a/.github/workflows/documentation.yaml +++ b/.github/workflows/documentation.yaml @@ -38,10 +38,11 @@ jobs: # * skip changelog PR links (so many) # * skip speculative links # * Stackoverflow links are no longer accessible from CI. + # * Tuxfamily.org links are down intermittently. # * Nyud links are down every now and then. # * TODO(#4085): https://rerun-io.github.io/rerun/dev/bench/ often 404:s for unknown reasons # * TODO(#4556): remove the `static.rerun.io` and `github.com` skips - linksToSkip: "https://stackoverflow.com/.*, https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html, https://static.rerun.io/.*, https://github.com/.*, https://crates.io/crates/.*, https://github.com/rerun-io/rerun/pull/.*, .*?speculative-link, https://rerun-io.github.io/rerun/dev/bench/" + linksToSkip: "https://stackoverflow.com/.*, https://eigen.tuxfamily.org/, https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html, https://static.rerun.io/.*, https://github.com/.*, https://crates.io/crates/.*, https://github.com/rerun-io/rerun/pull/.*, .*?speculative-link, https://rerun-io.github.io/rerun/dev/bench/" retry: true retryErrors: true retryErrorsCount: 5 diff --git a/docs/content/getting-started/visualize/blueprint.md b/docs/content/getting-started/visualize/blueprint.md deleted file mode 100644 index f4afdc697dfc..000000000000 --- a/docs/content/getting-started/visualize/blueprint.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Configure from code -order: 1 ---- - -TODO(#5466): diff --git a/docs/content/howto/configure-the-viewer.md b/docs/content/howto/configure-the-viewer.md new file mode 100644 index 000000000000..d345a881ef1d --- /dev/null +++ b/docs/content/howto/configure-the-viewer.md @@ -0,0 +1,25 @@ +--- +title: Configure the Viewer +order: 10 +--- + +Although the Rerun Viewer tries to do a reasonable job of using heuristics to automatically determine +an appropriate layout given the data that you provide, there will always be situations where the heuristic +results don't match the needs of a particular use-case. + +Fortunately, almost all aspects of the viewer can be configured via the [Blueprint](../reference/viewer/blueprint.md). + +The viewer Blueprint completely determines: + +- What contents are included in each view +- The type of view used to visualize the data +- The organizational layout and names of the different view panels and containers +- Configuration and styling properties of the individual data visualizers + +There are a few different ways to work with Blueprints: + +- [Blueprints can be modified interactively](./configure-the-viewer/interactively.md) +- [Blueprint files (.rbl) can be saved and loaded from disk](./configure-the-viewer/save-and-load.md) +- [Blueprints can be controlled directly from code](./configure-the-viewer/through-code.md) + +For a hands on example, you can also follow the [Blueprint API Tutorial](./configure-the-viewer/blueprint-api-tutorial.md). diff --git a/docs/content/howto/configure-the-viewer/blueprint-api-tutorial.md b/docs/content/howto/configure-the-viewer/blueprint-api-tutorial.md new file mode 100644 index 000000000000..bbc9ec4c52cc --- /dev/null +++ b/docs/content/howto/configure-the-viewer/blueprint-api-tutorial.md @@ -0,0 +1,389 @@ +--- +title: Blueprint API Tutorial +order: 4 +--- + +This tutorial will walk you through using the Blueprint APIs to better control the +layout and appearance of your data in the Rerun Viewer in Python. + +This walkthrough is based on the [stock charts](https://github.com/rerun-io/rerun/tree/main/examples/python/blueprint_stocks?speculative-link) example. +The main differences between this tutorial and the linked example are related to additional processing of +command-line flags, which are omitted here for simplicity. + +## Create an environment for you example + +We start by creating a new virtual environment and installing the Rerun SDK along with the dependencies +we will use in this example. + +On linux or mac: + +```bash +mkdir stocks_example +cd stocks_example +python -m venv venv +source venv/bin/activate +pip install rerun-sdk humanize yfinance +``` + +On windows: + +```bash +mkdir stocks_example +cd stocks_example +python -m venv venv +.\venv\Scripts\activate +pip install rerun-sdk humanize yfinance +``` + +## Create your script + +In your project folder, add a new file, `stocks.py`. + +First, we import the necessary libraries: + +```python +#!/usr/bin/env python3 +import datetime as dt +import humanize +import pytz +import yfinance as yf +from typing import Any + +import rerun as rr +import rerun.blueprint as rrb +``` + +Next, we create some helper functions for style data and a template for an info card: + +```python +brand_colors = { + "AAPL": 0xA2AAADFF, + "AMZN": 0xFF9900FF, + "GOOGL": 0x34A853FF, + "META": 0x0081FBFF, + "MSFT": 0xF14F21FF, +} + + +def style_plot(symbol: str) -> rr.SeriesLine: + return rr.SeriesLine( + color=brand_colors[symbol], + name=symbol, + ) + + +def style_peak(symbol: str) -> rr.SeriesPoint: + return rr.SeriesPoint( + color=0xFF0000FF, + name=f"{symbol} (peak)", + marker="Up", + ) + + +def info_card( + shortName: str, + industry: str, + marketCap: int, + totalRevenue: int, + **args: dict[str, Any], +) -> rr.TextDocument: + markdown = f""" +- **Name**: {shortName} +- **Industry**: {industry} +- **Market cap**: ${humanize.intword(marketCap)} +- **Total Revenue**: ${humanize.intword(totalRevenue)} +""" + + return rr.TextDocument(markdown, media_type=rr.MediaType.MARKDOWN) +``` + +And finally, we create our main function that queries and logs the data: + +```python +def main() -> None: + symbols = ["AAPL", "AMZN", "GOOGL", "META", "MSFT"] + + # Use eastern time for market hours + et_timezone = pytz.timezone("America/New_York") + start_date = dt.date(2024, 3, 18) + dates = [start_date + dt.timedelta(days=i) for i in range(5)] + + # Initialize Rerun and spawn a new viewer + rr.init("rerun_example_blueprint_stocks", spawn=True) + + # This is where we will edit the blueprint + blueprint = None + #rr.send_blueprint(blueprint) + + # Log the stock data for each symbol and date + for symbol in symbols: + stock = yf.Ticker(symbol) + + # Log the stock info document as timeless + rr.log(f"stocks/{symbol}/info", info_card(**stock.info), timeless=True) + + for day in dates: + # Log the styling data as timeless + rr.log(f"stocks/{symbol}/{day}", style_plot(symbol), timeless=True) + rr.log(f"stocks/{symbol}/peaks/{day}", style_peak(symbol), timeless=True) + + # Query the stock data during market hours + open_time = dt.datetime.combine(day, dt.time(9, 30), et_timezone) + close_time = dt.datetime.combine(day, dt.time(16, 00), et_timezone) + + hist = stock.history(start=open_time, end=close_time, interval="5m") + + # Offset the index to be in seconds since the market open + hist.index = hist.index - open_time + peak = hist.High.idxmax() + + # Log the stock state over the course of the day + for row in hist.itertuples(): + rr.set_time_seconds("time", row.Index.total_seconds()) + rr.log(f"stocks/{symbol}/{day}", rr.Scalar(row.High)) + if row.Index == peak: + rr.log(f"stocks/{symbol}/peaks/{day}", rr.Scalar(row.High)) + + +if __name__ == "__main__": + main() +``` + +## Run your script + +You can now run the script and view the results in the Rerun Viewer: + +```bash +python stocks.py +``` + +You should see the application launch and display the stock data, but you will also notice the +layout is far from ideal: + + + + + + + + + +## Create a Blueprint + +To improve the layout, we will now use the blueprint APIs to create some custom layouts. + +All we need to do is modify the section of the code that currently reads: + +```python + # This is where we will edit the blueprint + blueprint = None + #rr.send_blueprint(blueprint) +``` + +### Create a view for an origin + +Replace these lines with the following: + +```python + # Create a single chart for all the AAPL data: + blueprint = rrb.Blueprint( + rrb.TimeSeriesView(name="AAPL", origin="/stocks/AAPL"), + ) + rr.send_blueprint(blueprint) +``` + +This blueprint uses the `origin` parameter to scope the view to just a portion of the entity tree. + +If you run the script again, you should see a single chart for the AAPL data: + + + + + + + + + +### Control the default panel state + +In addition to controlling the data, you can also control the default state of the blueprint, selection, +and time panels. + +Let's modify the code again to include additional blueprint specifications for these: + +```python + # Create a single chart for all the AAPL data, and collapse the selection and time panels: + blueprint = rrb.Blueprint( + rrb.TimeSeriesView(name="AAPL", origin="/stocks/AAPL"), + rrb.BlueprintPanel(expanded=True), + rrb.SelectionPanel(expanded=False), + rrb.TimePanel(expanded=False), + ) + rr.send_blueprint(blueprint) +``` + +This time when you run the script, you will now see the panels start off collapsed, giving you a +more focused view of your data: + + + + + + + + + +### Combining multiple views + +When using blueprints, you don't have to limit yourself to a single view. You can create multiple views +and use containers to combine them. + +Let's modify the code to include the info card as well. We will use the `Vertical` container and the +`row_shares` parameter to control the relative size of the views: + +```python + # Create a vertical layout of an info document and a time series chart + blueprint = rrb.Blueprint( + rrb.Vertical( + rrb.TextDocumentView(name="Info", origin="/stocks/AAPL/info"), + rrb.TimeSeriesView(name="Chart", origin="/stocks/AAPL"), + row_shares=[1, 4], + ), + rrb.BlueprintPanel(expanded=True), + rrb.SelectionPanel(expanded=False), + rrb.TimePanel(expanded=False), + ) + rr.send_blueprint(blueprint) +``` + +Running the script now produces two views stacked vertically: + + + + + + + + + +### Including specific contents + +Specifying the `origin` of a view is convenient, but sometimes you need more control. In this case, you can +specify the `contents` of a view by providing multiple content expressions. + +For example, we can create a stock that includes data from both META and MSFT for a single day on +the same chart. Using `origin` alone there is no way we could have expressed this: + +```python + # Create a view with two stock time series + blueprint = rrb.Blueprint( + rrb.TimeSeriesView( + name="META vs MSFT", + contents=[ + "+ /stocks/META/2024-03-19", + "+ /stocks/MSFT/2024-03-19", + ], + ), + rrb.BlueprintPanel(expanded=True), + rrb.SelectionPanel(expanded=False), + rrb.TimePanel(expanded=False), + ) + rr.send_blueprint(blueprint) +``` + +Running the script now produces a chart that combines data from multiple sources: + + + + + + + + + +### More complex filtering + +Just specifying single path inclusions can also be challenging when dealing datasets that +include large subtrees. + +Filter expressions can be used to include or exclude data based on a path pattern. This pattern can optionally +start with `$origin` to refer to the origin of the given space, and can end with the wildcard `/**` to include +or exclude an entire subtree, + +Going back to our single stock example, we can filter out the peaks data by excluding the `peaks` subtree: + +```python + # Create a single chart for all the AAPL data and filter out the peaks: + blueprint = rrb.Blueprint( + rrb.TimeSeriesView( + name="AAPL", + origin="/stocks/AAPL", + contents=[ + "+ $origin/**", + "- $origin/peaks/**", + ], + ), + rrb.BlueprintPanel(expanded=True), + rrb.SelectionPanel(expanded=False), + rrb.TimePanel(expanded=False), + ) + rr.send_blueprint(blueprint) +``` + +When you run the script you will see that the data from the peaks subtree is no longer part of the view: + + + + + + + + + +### Programmatic layouts + +Since these layouts are created by executing python code, they can also be generated programmatically. + +For example, we can create a create a separate view for every piece of data we were interested in. +Setting this up by hand would be extremely tedious. + +```python + # Iterate over all the symbols and days to log the stock data in a grid + blueprint = rrb.Blueprint( + rrb.Vertical( + contents=[ + rrb.Horizontal( + contents=[ + rrb.TextDocumentView( + name=f"{symbol}", + origin=f"/stocks/{symbol}/info", + ), + ] + + [ + rrb.TimeSeriesView( + name=f"{day}", + origin=f"/stocks/{symbol}/{day}", + ) + for day in dates + ], + name=symbol, + ) + for symbol in symbols + ] + ), + rrb.BlueprintPanel(expanded=True), + rrb.SelectionPanel(expanded=False), + rrb.TimePanel(expanded=False), + ) + rr.send_blueprint(blueprint) +``` + +Running the script again this final chart is a significant improvement over the original heuristic-based layout: + + + + + + + + diff --git a/docs/content/howto/configure-the-viewer/interactively.md b/docs/content/howto/configure-the-viewer/interactively.md new file mode 100644 index 000000000000..5f7d885ace81 --- /dev/null +++ b/docs/content/howto/configure-the-viewer/interactively.md @@ -0,0 +1,85 @@ +--- +title: Interactively setup up viewer +order: 1 +--- + +The Rerun Viewer is configurable directly through the UI itself. + +## Viewer overview + +TODO(#5636): Screenshot of the viewer, with the blueprint and selection panels highlighted. + +The left panel of the viewer is the "Blueprint Panel" this shows a visual tree view representing +the contents of the current blueprint. + +The right panel of the viewer is the "Selection Panel" this panel allows you to configure +specific blueprint properties of the currently selected element. + +After editing the viewer you may want to [save or share the blueprint](./save-and-load.md). + +## Configuring Layout and Contents + +### Show or hide parts of the blueprint + +Click the "eye" icon next to the container, view, or entity in the blueprint panel. +TODO(#5636): show_hide + +### Add new Containers or Views + +Clicking the "+" at the top of the blueprint panel. +TODO(#5636): add_1 + +Selecting a Container and clicking the "+" in the selection panel. +TODO(#5636): add_2 + +### Remove a View or Container + +Click the "-" button next to the container or view in the blueprint panel. +TODO(#5636): remove + +### Re-arrange existing Containers or Views + +Drag and drop the container or view in the blueprint panel. +TODO(#5636): drag_1 + +Drag and drop containers or views directly in the viewport +TODO(#5636): drag_2 + +### Change the size of Containers or Views + +Click and drag the edge of a view or container to resize it +TODO(#5636): resize + +### Rename a View or Container + +Select the Container or View and enter a name at the top of the selection panel +TODO(#5636): rename + +### Change the type of a Container + +Select the Container and choose a new type from the dropdown in the selection panel +TODO(#5636): change_type + +### Add a new Data to a View + +Select the view and click "edit" to bring up the entity editor +TODO(#5636): add_data_1 + +Select the view and directly edit the entity query +See [Entity Queries](../../reference/entity-queries.md) for more information on how to write queries. + +TODO(#5636): add_data_2 + +### Remove Data from a View + +Click the "-" next to the entity in the blueprint panel +TODO(#5636): remove_data_1 + +### Change the origin of a View + +Select the view, then click the "Space Origin" field and type or select a new origin +TODO(#5636): change_origin + +## Overriding Properties + +TODO(jleibs): do we include this now or wait for generalized component overrides? diff --git a/docs/content/howto/configure-the-viewer/save-and-load.md b/docs/content/howto/configure-the-viewer/save-and-load.md new file mode 100644 index 000000000000..ab8aa010b1a5 --- /dev/null +++ b/docs/content/howto/configure-the-viewer/save-and-load.md @@ -0,0 +1,24 @@ +--- +title: Save and load viewer configuration files +order: 1 +--- + +If you have made changes to your blueprint and you would like to save or share these changes, +you can do so by saving your blueprint to an `.rbl` file. + +## Saving a blueprint + +To save your blueprint, go to the file-menu and choose "Save blueprint…" +TODO(#5636): save + +## Loading a blueprint + +Once you have saved a blueprint, you can load it again. + +When loading a blueprint, it must match the "application_id" used by the recording. + +To load a blueprint, go to the file-menu and choose "Open…" and select the `.rbl` file you would like to load. +TODO(#5636): open_1 + +You can also drag and drop an `.rbl` file directly into the viewer +TODO(#5636): open_2 diff --git a/docs/content/howto/configure-the-viewer/through-code.md b/docs/content/howto/configure-the-viewer/through-code.md new file mode 100644 index 000000000000..76339ced0db4 --- /dev/null +++ b/docs/content/howto/configure-the-viewer/through-code.md @@ -0,0 +1,290 @@ +--- +title: Control the viewer through code +order: 2 +--- + +As of Rerun 0.15, the state of the [blueprint](../../reference/viewer/blueprint.md) can be directly manipulated using the +Rerun SDK. + +In the initial 0.15 release, the APIs are still somewhat limited and only available in the Python SDK. +Future releases will add support for the full scope of blueprint. See issues: [#5519](https://github.com/rerun-io/rerun/issues/5519), [#5520](https://github.com/rerun-io/rerun/issues/5520), [#5521](https://github.com/rerun-io/rerun/issues/5521). + +## Blueprint API overview + +All blueprint APIs are in the [`rerun.blueprint`](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/?speculative-link) namespace. In our python examples, we typically import this using the `rrb` alias: + +```python +import rerun.blueprint as rrb +``` + +The python blueprint API is declarative and object-centric. There are 3 main types of blueprint objects you will +encounter: + +- `Blueprint`: The root object that represents the entire viewer layout. +- `Container`: A layout object that contains other containers or views. +- `SpaceView`: A view object that represents a single view of the data. + +Both containers and spaceviews should be used via typed subclasses instead.: + +- `Container` has subclasses: `Horizontal`, `Vertical`, `Grid`, and `Tabs`. +- `SpaceView` has subclasses: `BarChartView`, `Spatial2DView`, `Spatial3DView`, `TensorView`, + `TextDocumentView`, `TextLogView`, and `TimeSeriesView`. + +These paths can be combined hierarchically to create a complex viewer layout. + +For example: + +```python +my_blueprint = rrb.Blueprint( + rrb.Horizontal( + rrb.SpaceView(rrb.BarChartView()), + rrb.Vertical( + rrb.SpaceView(rrb.Spatial2DView()), + rrb.SpaceView(rrb.Spatial3DView()), + ), + ), +) +``` + +## Sending the blueprint to the viewer + +To provide a blueprint, simply pass it to either `init` or `connect` using the `default_blueprint` +parameter. + +Using `init` with `spawn=True`: + +```python +my_blueprint = rrb.Blueprint(...) + +rr.init("rerun_example_my_blueprint", spawn=True, default_blueprint=my_blueprint) +``` + +Or if you use `connect` separate from `init`: + +```python +my_blueprint = rrb.Blueprint(...) + +rr.init("rerun_example_my_blueprint") + +... + +rr.connect(default_blueprint=my_blueprint) +``` + +## Activating the default blueprint + +Just like the viewer can store many different recordings internally, it can also +store many different blueprints. For each `application_id` in the viewer, are two +particularly important blueprints: the "default blueprint" and the "active blueprint". + +When a recording is selected, the active blueprint for the corresponding +`application_id` will completely determine what is displayed by the viewer. + +When you send a blueprint to the viewer, it will not necessarily be +activated immediately. The standard behavior is to only update the "default +blueprint" in the viewer. This minimizes the chance that you accidentally +overwrite blueprint edits you may have made locally. + +If you want to start using the new blueprint, after sending it, you will need to +click the reset button in the blueprint panel. This resets the active blueprint to the +current default: + +TODO(#5636): reset_blueprint + +## Always activating the blueprint + +If you want to always activate the blueprint as soon as it is received, you can instead use the `send_blueprint` +API. This API has two flags `make_active` and `make_default`, both of which default to `True`. + +If `make_active` is set, the blueprint will be activated immediately. Exercise care in using this API, as it can be +surprising for users to have their blueprint changed without warning. + +```python +my_blueprint = rrb.Blueprint(...) + +rr.init("rerun_example_my_blueprint", spawn=True) + +rr.send_blueprint(my_blueprint, make_active=True) + +``` + +## Customizing Space Views + +Any of the space views (`BarChartView`, `Spatial2DView`, `Spatial3DView`, `TensorView`, +`TextDocumentView`, `TextLogView`, or `TimeSeriesView`) can be instantiated with no arguments. +By default these views try to include all compatible entities. + +For example, the following blueprint creates a single 3D view that includes all the 3D content +you have logged to the entity tree: + +```python +rrb.Blueprint( + rrb.Spatial3DView() +) +``` + +Beyond, instantiating the space views, there are 3 parameters you may want to specify: `name`, `origin`, and `contents`. + +`name` is simply the name of the view used as a label in the viewer. + +However, both `origin` and `contents` play an important role in determining what data is included in the view. + +### `origin` + +The `origin` of a space-view is a generalized "frame of reference" for the view. We think of showing all data +in the space view as relative to the `origin`. + +By default, only data that is under the `origin` will be included in the view. As such this is one of the most +convenient ways of restricting a space-view to a particular subtree. + +Because the data in the space-view is relative to the `origin`, the `origin` will be the first entity displayed +in the blueprint tree, with all entities under the origin shown using relative paths. + +For Spatial views such as `Spatial2DView` and `Spatial3DView`, the `origin` plays an additional role with respect +to data transforms. All data in the view will be transformed to the `origin` space before being displayed. See [Spaces and Transforms](../../concepts/spaces-and-transforms.md) for more information. +TODO(jleibs): Re-review spaces-and-transforms for correctness + +For example: + +```python +rrb.Blueprint( + rrb.Horizontal( + rrb.Spatial3DView(origin="/world"), + rrb.Spatial2DView(origin="/world/robot/camera"), + ) +) +``` + +### `contents` + +If you need to further modify the contents of a space view, you can use the `contents` parameter. This parameter is +a list of [entity query expressions](../../reference/) that are either included or excluded from the +view. + +Each entity expressions starts with "+" for inclusion or "-" for an exclusion. The expressions can either be specific entity paths, or may end in a wildcard `/**` to include all entities under a specific subtree. + +When combining multiple expressions, the "most specific" rule wins. + +Additionally, these expressions can reference `$origin` to refer to the origin of the space view. + +For example: + +```python +rrb.Blueprint( + rrb.Horizontal( + rrb.Spatial3DView( + origin="/world", + contents=[ + "+ $origin/robot/**", + ], + ), + rrb.Spatial2DView( + origin="/world/robot/camera", + contents=[ + "+ $origin/**", + "+ /world/robot/actuator/**", + ], + ), + ) +) +``` + +## Implicit conversion + +For convenience all of the blueprint APIs take a `BlueprintLike` rather than requiring a `Blueprint` object. +Both `SpaceView`s and `Containers` are considered `BlueprintLike`. Similarly, the `Blueprint` object can +take a `SpaceView` or `Container` as an argument. + +All of the following are equivalent: + +```python +rr.send_blueprint(rrb.Spatial3DView()) +``` + +```python +rr.send_blueprint( + rrb.Grid( + Spatial3DView(), + ) +) +``` + +```python +rr.send_blueprint( + rrb.Blueprint( + Spatial3DView(), + ), +) + +``` + +```python +rr.send_blueprint( + rrb.Blueprint( + rrb.Grid( + Spatial3DView(), + ) + ), +) +``` + +## Customizing the top-level blueprint + +The top-level `Blueprint` object can also be customized. + +### Controlling the panel state + +The `Blueprint` controls the default panel-state of the 3 panels: the `BlueprintPanel`, the `SelectionPanel`, and the `TimePanel`. These can be controlled by passing them as additional arguments to the `Blueprint` constructor. + +```python +rrb.Blueprint( + rrb.TimePanel(expanded=False) +) +``` + +As an convenience, you can also use the blueprint argument: `collapse_panels=True` as a short-hand for: + +```python +rrb.Blueprint( + rrb.TimePanel(expanded=False), + rrb.SelectionPanel(expanded=False), + rrb.BlueprintPanel(expanded=False), +) +``` + +### Controlling the auto behaviors + +The blueprint has two additional parameters that influence the behavior of the viewer: + +- `auto_space_views` controls whether the viewer will automatically create space views for entities that are not explicitly included in the blueprint. +- `auto_layout` controls whether the viewer should automatically layout the containers when introducing new space-views. + +If you pass in your own `SpaceView` or `Container` objects, these will both default to `False` so that the Blueprint +you get is exactly what you specify. Otherwise they will default to `True` so that you will still get content (this +matches the default behavior of the viewer if no blueprint is provided). + +This means that: + +```python +rrb.Blueprint() +``` + +and + +```python +rrb.Blueprint( + auto_space_views=True, + auto_layout=True +) +``` + +are both equivalent to the viewer's default behavior. + +If you truly want to create an empty blueprint, you must set both values to `False`: + +```python +rrb.Blueprint( + auto_space_views=False, + auto_layout=False +), +``` diff --git a/docs/content/reference/entity-queries.md b/docs/content/reference/entity-queries.md new file mode 100644 index 000000000000..9f9300144321 --- /dev/null +++ b/docs/content/reference/entity-queries.md @@ -0,0 +1,92 @@ +--- +title: Entity Queries +order: 4 +--- + +Many space views are made up of visualizations that include more than one +entity. + +Rather that requiring you to specify each entity individually, Rerun supports +this through "entity queries" that allow you to use "query expressions" to +include or exclude entire subtrees. + +## Query expression syntax + +An entity query is made up of a set of "query expressions." Each query expression +is either an "inclusion," which starts with an optional `+` or an "exclusion," +which always starts with a `-`. + +Query expressions are also allowed to end with an optional `/**`. The`/**` +suffix matches the whole subtree, i.e. self and any child, recursively. For +example, `/world/**`matches both`/world`and`/world/car/driver`. Other uses of +`*` are not yet supported. + +When combining multiple query expressions, the rules are sorted by entity-path, +from least to most specific: + +- If there are multiple matching rules, the most specific rule wins. +- If there are multiple rules of the same specificity, the last one wins. +- If no rules match, the path is excluded. + +Consider the following example: + +```diff ++ /world/** +- /world +- /world/car/** ++ /world/car/driver +``` + +- The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it + is included. +- The last rule matching `/world/car/hood` is `- /world/car/**`, so it is + excluded. +- The last rule matching `/world` is `- /world`, so it is excluded. +- The last rule matching `/world/house` is `+ /world/**`, so it is included. + +## In the viewer + +In the viewer, an entity query is typically displayed as a multi-line +edit box, with each query expression shown on its own line. You can find the +query editor in the right-hand selection panel when selecting a space view. + + + + + + + + + + +## In the SDK + +In the SDK, query expressions are represented as a list or iterable, with each +expression written as a separate string. The query expression from above would +be written as: + +```python +rrb.Spatial3DView( + contents=[ + "+ helix/**, + "- helix/structure/scaffolding", + ], +), +``` + +## 'origin` substitution + +Query expressions also allow you to use the variable `$origin` to refer to the +origin of the space-view that the query belongs to. + +For example, the above query could be rewritten as: + +```python +rrb.Spatial3DView( + origin="helix", + contents=[ + "+ $origin/**, + "- $origin/structure/scaffolding", + ], +), +``` diff --git a/docs/content/reference/types.md b/docs/content/reference/types.md index ea9fd7fa17a1..c5711e2bf5e6 100644 --- a/docs/content/reference/types.md +++ b/docs/content/reference/types.md @@ -1,6 +1,6 @@ --- title: Types -order: 2 +order: 3 --- Rerun comes with built-in support for a number of different types that can be logged via the Python and Rust Logging diff --git a/docs/content/reference/viewer.md b/docs/content/reference/viewer.md index 00414c7f2739..379792ff12b4 100644 --- a/docs/content/reference/viewer.md +++ b/docs/content/reference/viewer.md @@ -1,5 +1,5 @@ --- title: Viewer -order: 1 +order: 2 redirect: reference/viewer/overview --- diff --git a/docs/cspell.json b/docs/cspell.json index ca7ba3b7552d..b9a42adfc4d6 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -148,14 +148,17 @@ "hstack", "Huggingface", "icosphere", + "idxmax", "imgmsg", "impls", "inproceedings", "interner", "intrinsics", + "intword", "ipynb", "ipython", "itertools", + "itertuples", "Jitendra", "jleibs", "Joao", @@ -271,6 +274,7 @@ "pypi", "pyright", "pytest", + "pytz", "Pythonic", "quickstart", "randn", @@ -346,6 +350,7 @@ "Texcoord", "thiserror", "Tian", + "timedelta", "timepanel", "timepoint", "timepoints", @@ -408,6 +413,7 @@ "XYWH", "XYXY", "xyzw", + "yfinance", "Yifan", "Yilun", "Yiqin", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py index 859904151c02..43b717d2231c 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py @@ -68,7 +68,7 @@ def __init__( self: TensorData The TensorData object to construct. shape: Sequence[TensorDimensionLike] | None - The shape of the tensor. If None, and an array is proviced, the shape will be inferred + The shape of the tensor. If None, and an array is provided, the shape will be inferred from the shape of the array. buffer: TensorBufferLike | None The buffer of the tensor. If None, and an array is provided, the buffer will be generated From 027e16db3ddb36d23bd17f079bcbfcb6289705da Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 3 Apr 2024 03:43:57 +0200 Subject: [PATCH 161/508] Go back to example page with browser Back-button (#5750) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What * Closes https://github.com/rerun-io/rerun/issues/5398 This uses the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to manipulate the web history. When leaving the example page, two entries in the history are added: * `?examples` (shows the examples) * `?url=https://….rrd` (the url for the example) This is then parsed on `popstate`. We thus support both going forward and back in history. This is not perfect, but a lot better than before. Best reviewed commit by commit. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5750) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5750?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5750?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5750) - [Docs preview](https://rerun.io/preview/d308ce076b28481d77fac64217df69a452cc54a9/docs) - [Examples preview](https://rerun.io/preview/d308ce076b28481d77fac64217df69a452cc54a9/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Jeremy Leibs --- Cargo.lock | 1 + crates/re_data_source/src/web_sockets.rs | 27 +-- .../src/stream_rrd_from_http.rs | 8 +- crates/re_smart_channel/src/receive_set.rs | 9 + crates/re_ui/src/command.rs | 6 + crates/re_viewer/Cargo.toml | 10 +- crates/re_viewer/src/app.rs | 29 +++ .../src/ui/welcome_screen/example_section.rs | 29 ++- crates/re_viewer/src/web.rs | 129 +++--------- crates/re_viewer/src/web_tools.rs | 186 ++++++++++++++++++ .../re_viewer_context/src/command_sender.rs | 6 + crates/re_viewer_context/src/store_hub.rs | 14 +- 12 files changed, 325 insertions(+), 129 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bea4e0a2e543..d1da8653b931 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5053,6 +5053,7 @@ dependencies = [ "ehttp", "image", "itertools 0.12.0", + "js-sys", "once_cell", "poll-promise", "re_analytics", diff --git a/crates/re_data_source/src/web_sockets.rs b/crates/re_data_source/src/web_sockets.rs index d0d6542cae2f..c258aa8e76ac 100644 --- a/crates/re_data_source/src/web_sockets.rs +++ b/crates/re_data_source/src/web_sockets.rs @@ -17,22 +17,25 @@ pub fn connect_to_ws_url( re_log::info!("Connecting to WebSocket server at {url:?}…"); - let callback = move |binary: Vec| match re_ws_comms::decode_log_msg(&binary) { - Ok(log_msg) => { - if tx.send(log_msg).is_ok() { - if let Some(on_msg) = &on_msg { - on_msg(); + let callback = { + let url = url.to_owned(); + move |binary: Vec| match re_ws_comms::decode_log_msg(&binary) { + Ok(log_msg) => { + if tx.send(log_msg).is_ok() { + if let Some(on_msg) = &on_msg { + on_msg(); + } + std::ops::ControlFlow::Continue(()) + } else { + re_log::info_once!("Closing connection to {url}"); + std::ops::ControlFlow::Break(()) } - std::ops::ControlFlow::Continue(()) - } else { - re_log::info!("Failed to send log message to viewer - closing"); + } + Err(err) => { + re_log::error!("Failed to parse message: {err}"); std::ops::ControlFlow::Break(()) } } - Err(err) => { - re_log::error!("Failed to parse message: {err}"); - std::ops::ControlFlow::Break(()) - } }; re_ws_comms::viewer_to_server(url.to_owned(), callback)?; diff --git a/crates/re_log_encoding/src/stream_rrd_from_http.rs b/crates/re_log_encoding/src/stream_rrd_from_http.rs index dbee815c1208..7662678258a6 100644 --- a/crates/re_log_encoding/src/stream_rrd_from_http.rs +++ b/crates/re_log_encoding/src/stream_rrd_from_http.rs @@ -15,7 +15,7 @@ pub fn stream_rrd_from_http_to_channel( re_smart_channel::SmartChannelSource::RrdHttpStream { url: url.clone() }, ); stream_rrd_from_http( - url, + url.clone(), Arc::new(move |msg| { if let Some(on_msg) = &on_msg { on_msg(); @@ -25,17 +25,17 @@ pub fn stream_rrd_from_http_to_channel( if tx.send(msg).is_ok() { ControlFlow::Continue(()) } else { - re_log::info!("Failed to send log message to viewer - closing"); + re_log::info_once!("Closing connection to {url}"); ControlFlow::Break(()) } } HttpMessage::Success => { - tx.quit(None).warn_on_err_once("failed to send quit marker"); + tx.quit(None).warn_on_err_once("Failed to send quit marker"); ControlFlow::Break(()) } HttpMessage::Failure(err) => { tx.quit(Some(err)) - .warn_on_err_once("failed to send quit marker"); + .warn_on_err_once("Failed to send quit marker"); ControlFlow::Break(()) } } diff --git a/crates/re_smart_channel/src/receive_set.rs b/crates/re_smart_channel/src/receive_set.rs index f13f745fb565..1a9ecc6f0c91 100644 --- a/crates/re_smart_channel/src/receive_set.rs +++ b/crates/re_smart_channel/src/receive_set.rs @@ -36,6 +36,15 @@ impl ReceiveSet { self.receivers.lock().retain(|r| r.source() != source); } + pub fn retain(&self, mut f: impl FnMut(&Receiver) -> bool) { + self.receivers.lock().retain(|r| f(r)); + } + + /// Remove all receivers. + pub fn clear(&self) { + self.receivers.lock().clear(); + } + /// Disconnect from any channel with a source pointing at this `uri`. #[cfg(target_arch = "wasm32")] pub fn remove_by_uri(&self, uri: &str) { diff --git a/crates/re_ui/src/command.rs b/crates/re_ui/src/command.rs index 3f3753419614..cce3a35a4ce1 100644 --- a/crates/re_ui/src/command.rs +++ b/crates/re_ui/src/command.rs @@ -18,6 +18,8 @@ pub enum UICommand { SaveRecordingSelection, SaveBlueprint, CloseCurrentRecording, + CloseAllRecordings, + #[cfg(not(target_arch = "wasm32"))] Quit, @@ -111,6 +113,9 @@ impl UICommand { "Close the current recording (unsaved data will be lost)", ), + Self::CloseAllRecordings => ("Close all recordings", + "Close all open current recording (unsaved data will be lost)",), + #[cfg(not(target_arch = "wasm32"))] Self::Quit => ("Quit", "Close the Rerun Viewer"), @@ -258,6 +263,7 @@ impl UICommand { Self::SaveBlueprint => None, Self::Open => Some(cmd(Key::O)), Self::CloseCurrentRecording => None, + Self::CloseAllRecordings => None, #[cfg(all(not(target_arch = "wasm32"), target_os = "windows"))] Self::Quit => Some(KeyboardShortcut::new(Modifiers::ALT, Key::F4)), diff --git a/crates/re_viewer/Cargo.toml b/crates/re_viewer/Cargo.toml index 5eb8fb025b16..8a8553a02143 100644 --- a/crates/re_viewer/Cargo.toml +++ b/crates/re_viewer/Cargo.toml @@ -106,14 +106,16 @@ wgpu.workspace = true # web dependencies: [target.'cfg(target_arch = "wasm32")'.dependencies] +js-sys.workspace = true wasm-bindgen.workspace = true wasm-bindgen-futures.workspace = true web-sys = { workspace = true, features = [ - 'Location', - 'Url', - 'UrlSearchParams', - 'Window', + "History", + "Location", "Storage", + "Url", + "UrlSearchParams", + "Window", ] } diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 9b0079e43f34..e85cd7ec3896 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -339,10 +339,35 @@ impl App { SystemCommand::ActivateRecording(store_id) => { store_hub.set_activate_recording(store_id); } + SystemCommand::CloseStore(store_id) => { store_hub.remove(&store_id); } + SystemCommand::CloseAllRecordings => { + store_hub.clear_recordings(); + + // Stop receiving into the old recordings. + // This is most important when going back to the example screen by using the "Back" + // button in the browser, and there is still a connection downloading an .rrd. + // That's the case of `SmartChannelSource::RrdHttpStream`. + // TODO(emilk): exactly what things get kept and what gets cleared? + self.rx.retain(|r| match r.source() { + SmartChannelSource::File(_) | SmartChannelSource::RrdHttpStream { .. } => false, + + SmartChannelSource::WsClient { .. } + | SmartChannelSource::RrdWebEventListener + | SmartChannelSource::Sdk + | SmartChannelSource::TcpServer { .. } + | SmartChannelSource::Stdin => true, + }); + } + + SystemCommand::AddReceiver(rx) => { + re_log::debug!("Received AddReceiver"); + self.add_receiver(rx); + } + SystemCommand::LoadDataSource(data_source) => { let egui_ctx = self.re_ui.egui_ctx.clone(); @@ -487,6 +512,10 @@ impl App { .send_system(SystemCommand::CloseStore(cur_rec.clone())); } } + UICommand::CloseAllRecordings => { + self.command_sender + .send_system(SystemCommand::CloseAllRecordings); + } #[cfg(not(target_arch = "wasm32"))] UICommand::Quit => { diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index 3c70ef89b558..066f9ae6af83 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -2,7 +2,7 @@ use egui::{NumExt as _, Ui}; use ehttp::{fetch, Request}; use poll_promise::Promise; -use re_viewer_context::SystemCommandSender; +use re_viewer_context::{CommandSender, SystemCommandSender as _}; #[derive(Debug, serde::Deserialize)] struct ExampleThumbnail { @@ -269,7 +269,7 @@ impl ExampleSection { &mut self, ui: &mut egui::Ui, re_ui: &re_ui::ReUi, - command_sender: &re_viewer_context::CommandSender, + command_sender: &CommandSender, header_ui: &impl Fn(&mut Ui), ) { let examples = self @@ -414,11 +414,7 @@ impl ExampleSection { // panel to quit auto-zoom mode. ui.input_mut(|i| i.pointer = Default::default()); - let data_source = - re_data_source::DataSource::RrdHttpUrl(example.desc.rrd_url.clone()); - command_sender.send_system( - re_viewer_context::SystemCommand::LoadDataSource(data_source), - ); + open_example_url(command_sender, &example.desc.rrd_url); } } }); @@ -426,6 +422,25 @@ impl ExampleSection { } } +fn open_example_url(command_sender: &CommandSender, rrd_url: &str) { + let data_source = re_data_source::DataSource::RrdHttpUrl(rrd_url.to_owned()); + command_sender.send_system(re_viewer_context::SystemCommand::LoadDataSource( + data_source, + )); + + #[cfg(target_arch = "wasm32")] + { + // Ensure that the user returns to the welcome page after navigating to an example. + use crate::web_tools; + + // So we know where to return to + web_tools::push_history("?examples"); + + // Where we're going: + web_tools::push_history(&format!("?url={}", web_tools::percent_encode(rrd_url))); + } +} + fn example_thumbnail(ui: &mut Ui, example: &ExampleDesc, column_width: f32) { // dimensions of the source image to use as thumbnail let image_width = example.thumbnail.width as f32; diff --git a/crates/re_viewer/src/web.rs b/crates/re_viewer/src/web.rs index 0a0008aa92a3..85614f686c2a 100644 --- a/crates/re_viewer/src/web.rs +++ b/crates/re_viewer/src/web.rs @@ -1,13 +1,14 @@ -#![allow(clippy::mem_forget)] // False positives from #[wasm_bindgen] macro +//! Main entry-point of the web app. -use anyhow::Context as _; -use eframe::wasm_bindgen::{self, prelude::*}; +#![allow(clippy::mem_forget)] // False positives from #[wasm_bindgen] macro -use std::ops::ControlFlow; -use std::sync::Arc; +use wasm_bindgen::prelude::*; use re_log::ResultExt as _; use re_memory::AccountingAllocator; +use re_viewer_context::CommandSender; + +use crate::web_tools::{string_from_js_value, translate_query_into_commands, url_to_receiver}; #[global_allocator] static GLOBAL: AccountingAllocator = @@ -90,7 +91,7 @@ impl WebHandle { let Some(mut app) = self.runner.app_mut::() else { return; }; - let rx = url_to_receiver(url, app.re_ui.egui_ctx.clone()); + let rx = url_to_receiver(app.re_ui.egui_ctx.clone(), url); if let Some(rx) = rx.ok_or_log_error() { app.add_receiver(rx); } @@ -130,8 +131,6 @@ fn create_app( }; let re_ui = crate::customize_eframe(cc); - let egui_ctx = cc.egui_ctx.clone(); - let mut app = crate::App::new(build_info, &app_env, startup_options, re_ui, cc.storage); let query_map = &cc.integration_info.web_info.location.query_map; @@ -145,73 +144,37 @@ fn create_app( } if let Some(url) = url { - if let Some(receiver) = url_to_receiver(url, egui_ctx).ok_or_log_error() { + if let Some(receiver) = url_to_receiver(cc.egui_ctx.clone(), url).ok_or_log_error() { app.add_receiver(receiver); } } else { - // NOTE: we support passing in multiple urls to multiple different recorording, blueprints, etc - for url in query_map.get("url").into_iter().flatten() { - if let Some(receiver) = url_to_receiver(url, egui_ctx.clone()).ok_or_log_error() { - app.add_receiver(receiver); - } - } + translate_query_into_commands(&cc.egui_ctx, &app.command_sender); } + install_popstate_listener(cc.egui_ctx.clone(), app.command_sender.clone()); + app } -fn url_to_receiver( - url: &str, - egui_ctx: egui::Context, -) -> anyhow::Result> { - let ui_waker = Box::new(move || { - // Spend a few more milliseconds decoding incoming messages, - // then trigger a repaint (https://github.com/rerun-io/rerun/issues/963): - egui_ctx.request_repaint_after(std::time::Duration::from_millis(10)); - }); - match categorize_uri(url) { - EndpointCategory::HttpRrd(url) => Ok( - re_log_encoding::stream_rrd_from_http::stream_rrd_from_http_to_channel( - url, - Some(ui_waker), - ), - ), - EndpointCategory::WebEventListener => { - // Process an rrd when it's posted via `window.postMessage` - let (tx, rx) = re_smart_channel::smart_channel( - re_smart_channel::SmartMessageSource::RrdWebEventCallback, - re_smart_channel::SmartChannelSource::RrdWebEventListener, - ); - re_log_encoding::stream_rrd_from_http::stream_rrd_from_event_listener(Arc::new({ - move |msg| { - ui_waker(); - use re_log_encoding::stream_rrd_from_http::HttpMessage; - match msg { - HttpMessage::LogMsg(msg) => { - if tx.send(msg).is_ok() { - ControlFlow::Continue(()) - } else { - re_log::info!("Failed to send log message to viewer - closing"); - ControlFlow::Break(()) - } - } - HttpMessage::Success => { - tx.quit(None).warn_on_err_once("failed to send quit marker"); - ControlFlow::Break(()) - } - HttpMessage::Failure(err) => { - tx.quit(Some(err)) - .warn_on_err_once("failed to send quit marker"); - ControlFlow::Break(()) - } - } - } - })); - Ok(rx) - } - EndpointCategory::WebSocket(url) => re_data_source::connect_to_ws_url(&url, Some(ui_waker)) - .with_context(|| format!("Failed to connect to WebSocket server at {url}.")), - } +/// Listen for `popstate` event, which comes when the user hits the back/forward buttons. +/// +/// +fn install_popstate_listener(egui_ctx: egui::Context, command_sender: CommandSender) -> Option<()> { + let window = web_sys::window()?; + let closure = Closure::wrap(Box::new(move |_: web_sys::Event| { + translate_query_into_commands(&egui_ctx, &command_sender); + }) as Box); + window + .add_event_listener_with_callback("popstate", closure.as_ref().unchecked_ref()) + .map_err(|err| { + format!( + "Failed to add popstate event listener: {}", + string_from_js_value(err) + ) + }) + .ok_or_log_error()?; + closure.forget(); + Some(()) } /// Used to set the "email" property in the analytics config, @@ -227,38 +190,6 @@ pub fn set_email(email: String) { config.save().unwrap(); } -enum EndpointCategory { - /// Could be a local path (`/foo.rrd`) or a remote url (`http://foo.com/bar.rrd`). - /// - /// Could be a link to either an `.rrd` recording or a `.rbl` blueprint. - HttpRrd(String), - - /// A remote Rerun server. - WebSocket(String), - - /// An eventListener for rrd posted from containing html - WebEventListener, -} - -fn categorize_uri(uri: &str) -> EndpointCategory { - if uri.starts_with("http") || uri.ends_with(".rrd") || uri.ends_with(".rbl") { - EndpointCategory::HttpRrd(uri.into()) - } else if uri.starts_with("ws:") || uri.starts_with("wss:") { - EndpointCategory::WebSocket(uri.into()) - } else if uri.starts_with("web_event:") { - EndpointCategory::WebEventListener - } else { - // If this is something like `foo.com` we can't know what it is until we connect to it. - // We could/should connect and see what it is, but for now we just take a wild guess instead: - re_log::info!("Assuming WebSocket endpoint"); - if uri.contains("://") { - EndpointCategory::WebSocket(uri.into()) - } else { - EndpointCategory::WebSocket(format!("{}://{uri}", re_ws_comms::PROTOCOL)) - } - } -} - fn is_in_notebook(info: &eframe::IntegrationInfo) -> bool { get_query_bool(info, "notebook", false) } diff --git a/crates/re_viewer/src/web_tools.rs b/crates/re_viewer/src/web_tools.rs index 2575a31a944e..790c56f0b5ac 100644 --- a/crates/re_viewer/src/web_tools.rs +++ b/crates/re_viewer/src/web_tools.rs @@ -1,3 +1,19 @@ +use std::{ops::ControlFlow, sync::Arc}; + +use anyhow::Context as _; +use wasm_bindgen::JsValue; + +use re_log::ResultExt as _; +use re_viewer_context::CommandSender; + +/// Web-specific tools used by various parts of the application. + +/// Useful in error handlers +#[allow(clippy::needless_pass_by_value)] +pub fn string_from_js_value(s: wasm_bindgen::JsValue) -> String { + s.as_string().unwrap_or(format!("{s:#?}")) +} + pub fn set_url_parameter_and_refresh(key: &str, value: &str) -> Result<(), wasm_bindgen::JsValue> { let Some(window) = web_sys::window() else { return Err("Failed to get window".into()); @@ -9,3 +25,173 @@ pub fn set_url_parameter_and_refresh(key: &str, value: &str) -> Result<(), wasm_ location.assign(&url.href()) } + +/// Percent-encode the given string so you can put it in a URL. +pub fn percent_encode(s: &str) -> String { + format!("{}", js_sys::encode_uri_component(s)) +} + +/// Push a relative url on the web `History`, +/// so that the user can use the back button to navigate to it. +/// +/// If this is already the current url, nothing happens. +/// +/// The url must be percent encoded. +/// +/// Example: +/// ``` +/// push_history("foo/bar?baz=qux#fragment"); +/// ``` +pub fn push_history(new_relative_url: &str) -> Option<()> { + let location = web_sys::window()?.location(); + + let search = location.search().unwrap_or_default(); + let hash = location.hash().unwrap_or_default(); + let current_relative_url = format!("{search}{hash}"); + + if current_relative_url == new_relative_url { + re_log::debug!("Ignoring navigation to {new_relative_url:?} as we're already there"); + } else { + re_log::debug!( + "Existing url is {current_relative_url:?}; navigating to {new_relative_url:?}" + ); + + let history = web_sys::window()? + .history() + .map_err(|err| format!("Failed to get History API: {}", string_from_js_value(err))) + .ok_or_log_error()?; + history + .push_state_with_url(&JsValue::NULL, "", Some(new_relative_url)) + .map_err(|err| { + format!( + "Failed to push history state: {}", + string_from_js_value(err) + ) + }) + .ok_or_log_error()?; + } + Some(()) +} + +/// Parse the `?query` parst of the url, and translate it into commands to control the application. +pub fn translate_query_into_commands(egui_ctx: &egui::Context, command_sender: &CommandSender) { + use re_viewer_context::{SystemCommand, SystemCommandSender as _}; + + let location = eframe::web::web_location(); + + // NOTE: it's unclear what to do if we find bout `examples` and `url` in the query. + + if location.query_map.get("examples").is_some() { + command_sender.send_system(SystemCommand::CloseAllRecordings); + } + + // NOTE: we support passing in multiple urls to multiple different recorording, blueprints, etc + let urls: Vec<&String> = location + .query_map + .get("url") + .into_iter() + .flatten() + .collect(); + if !urls.is_empty() { + // Clear out any already open recordings to make room for the new ones. + command_sender.send_system(SystemCommand::CloseAllRecordings); + + for url in urls { + if let Some(receiver) = url_to_receiver(egui_ctx.clone(), url).ok_or_log_error() { + command_sender.send_system(SystemCommand::AddReceiver(receiver)); + } + } + } + + egui_ctx.request_repaint(); // wake up to receive the messages +} + +enum EndpointCategory { + /// Could be a local path (`/foo.rrd`) or a remote url (`http://foo.com/bar.rrd`). + /// + /// Could be a link to either an `.rrd` recording or a `.rbl` blueprint. + HttpRrd(String), + + /// A remote Rerun server. + WebSocket(String), + + /// An eventListener for rrd posted from containing html + WebEventListener, +} + +impl EndpointCategory { + fn categorize_uri(uri: &str) -> Self { + if uri.starts_with("http") || uri.ends_with(".rrd") || uri.ends_with(".rbl") { + Self::HttpRrd(uri.into()) + } else if uri.starts_with("ws:") || uri.starts_with("wss:") { + Self::WebSocket(uri.into()) + } else if uri.starts_with("web_event:") { + Self::WebEventListener + } else { + // If this is something like `foo.com` we can't know what it is until we connect to it. + // We could/should connect and see what it is, but for now we just take a wild guess instead: + re_log::info!("Assuming WebSocket endpoint"); + if uri.contains("://") { + Self::WebSocket(uri.into()) + } else { + Self::WebSocket(format!("{}://{uri}", re_ws_comms::PROTOCOL)) + } + } + } +} + +/// Start receiving from the given url. +pub fn url_to_receiver( + egui_ctx: egui::Context, + url: &str, +) -> anyhow::Result> { + let ui_waker = Box::new(move || { + // Spend a few more milliseconds decoding incoming messages, + // then trigger a repaint (https://github.com/rerun-io/rerun/issues/963): + egui_ctx.request_repaint_after(std::time::Duration::from_millis(10)); + }); + match EndpointCategory::categorize_uri(url) { + EndpointCategory::HttpRrd(url) => Ok( + re_log_encoding::stream_rrd_from_http::stream_rrd_from_http_to_channel( + url, + Some(ui_waker), + ), + ), + EndpointCategory::WebEventListener => { + // Process an rrd when it's posted via `window.postMessage` + let (tx, rx) = re_smart_channel::smart_channel( + re_smart_channel::SmartMessageSource::RrdWebEventCallback, + re_smart_channel::SmartChannelSource::RrdWebEventListener, + ); + let url = url.to_owned(); + re_log_encoding::stream_rrd_from_http::stream_rrd_from_event_listener(Arc::new({ + move |msg| { + ui_waker(); + use re_log_encoding::stream_rrd_from_http::HttpMessage; + match msg { + HttpMessage::LogMsg(msg) => { + if tx.send(msg).is_ok() { + ControlFlow::Continue(()) + } else { + re_log::info_once!("Failed to send log message to viewer - closing connection to {url}"); + ControlFlow::Break(()) + } + } + HttpMessage::Success => { + tx.quit(None).warn_on_err_once("Failed to send quit marker"); + ControlFlow::Break(()) + } + HttpMessage::Failure(err) => { + tx.quit(Some(err)) + .warn_on_err_once("Failed to send quit marker"); + ControlFlow::Break(()) + } + } + } + })); + Ok(rx) + } + EndpointCategory::WebSocket(url) => re_data_source::connect_to_ws_url(&url, Some(ui_waker)) + .with_context(|| format!("Failed to connect to WebSocket server at {url}.")), + } +} diff --git a/crates/re_viewer_context/src/command_sender.rs b/crates/re_viewer_context/src/command_sender.rs index 53f1cc342e0d..e836e288e660 100644 --- a/crates/re_viewer_context/src/command_sender.rs +++ b/crates/re_viewer_context/src/command_sender.rs @@ -10,6 +10,8 @@ pub enum SystemCommand { /// Load some data. LoadDataSource(DataSource), + AddReceiver(re_smart_channel::Receiver), + /// Reset the `Viewer` to the default state ResetViewer, @@ -25,6 +27,9 @@ pub enum SystemCommand { /// Close a recording or blueprint (free its memory). CloseStore(StoreId), + /// Close all stores and show the welcome screen again. + CloseAllRecordings, + /// Update the blueprint with additional data /// /// The [`StoreId`] should generally be the currently selected blueprint @@ -65,6 +70,7 @@ pub trait SystemCommandSender { // ---------------------------------------------------------------------------- /// Sender that queues up the execution of commands. +#[derive(Clone)] pub struct CommandSender { system_sender: std::sync::mpsc::Sender, ui_sender: std::sync::mpsc::Sender, diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 594fffbb3177..782a8ed02c8c 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -100,14 +100,14 @@ impl StoreHub { setup_welcome_screen_blueprint: &dyn Fn(&mut EntityDb), ) -> Self { re_tracing::profile_function!(); - let mut blueprint_by_app_id = HashMap::new(); + let mut active_blueprint_by_app_id = HashMap::new(); let mut store_bundle = StoreBundle::default(); let welcome_screen_store_id = StoreId::from_string( StoreKind::Blueprint, Self::welcome_screen_app_id().to_string(), ); - blueprint_by_app_id.insert( + active_blueprint_by_app_id.insert( Self::welcome_screen_app_id(), welcome_screen_store_id.clone(), ); @@ -121,7 +121,7 @@ impl StoreHub { active_rec_id: None, active_application_id: None, default_blueprint_by_app_id: Default::default(), - active_blueprint_by_app_id: blueprint_by_app_id, + active_blueprint_by_app_id, store_bundle, was_recording_active: false, @@ -213,6 +213,14 @@ impl StoreHub { self.store_bundle.remove(store_id); } + /// Remove all open recordings, and go to the welcome page. + pub fn clear_recordings(&mut self) { + self.store_bundle + .retain(|db| db.store_kind() != StoreKind::Recording); + self.active_rec_id = None; + self.active_application_id = Some(Self::welcome_screen_app_id()); + } + // --------------------- // Active app From 27f3b15839bf91c3ce4c3363c1a6b3c1220de412 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 3 Apr 2024 05:28:53 +0200 Subject: [PATCH 162/508] Improve `re_format` formatting of floats (#5746) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What Some improvements to `re_format`: * Use thousands-separators when formatting floats * Support formatting and parsing negative numbers * Rename `format_number` to `format_uint`, and support any unsigned integer The reason for all this is to be able to use this for the Y axis plot format: Screenshot 2024-04-02 at 16 24 50 Screenshot 2024-04-02 at 16 25 44 …however, that will have to wait for egui 0.27.2 (coming soon!) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5746) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5746?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5746?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5746) - [Docs preview](https://rerun.io/preview/8f2b803cd19ca869e3c7b39d94d76bbfca9ae674/docs) - [Examples preview](https://rerun.io/preview/8f2b803cd19ca869e3c7b39d94d76bbfca9ae674/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 1 + crates/re_data_store/src/store_format.rs | 12 +- crates/re_data_store/src/store_gc.rs | 10 +- crates/re_data_store/src/store_sanity.rs | 4 +- crates/re_data_ui/src/component.rs | 7 +- crates/re_data_ui/src/data.rs | 2 +- crates/re_format/Cargo.toml | 2 + crates/re_format/src/lib.rs | 300 +++++++++++++++++++---- crates/re_viewer/src/ui/memory_panel.rs | 26 +- crates/re_viewer/src/ui/top_panel.rs | 18 +- 10 files changed, 299 insertions(+), 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1da8653b931..e39c15ad4194 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4403,6 +4403,7 @@ name = "re_format" version = "0.15.0-alpha.5" dependencies = [ "comfy-table", + "num-traits", "re_arrow2", "re_tuid", "re_types_core", diff --git a/crates/re_data_store/src/store_format.rs b/crates/re_data_store/src/store_format.rs index 29c9ad1b589d..3867098d8ad3 100644 --- a/crates/re_data_store/src/store_format.rs +++ b/crates/re_data_store/src/store_format.rs @@ -1,4 +1,4 @@ -use re_format::{format_bytes, format_number}; +use re_format::{format_bytes, format_uint}; use re_log_types::TimeInt; use re_types_core::SizeBytes as _; @@ -40,7 +40,7 @@ impl std::fmt::Display for DataStore { "{} timeless indexed tables, for a total of {} across {} total rows\n", timeless_tables.len(), format_bytes(self.timeless_size_bytes() as _), - format_number(self.num_timeless_rows() as _) + format_uint(self.num_timeless_rows()) ), ))?; f.write_str(&indent::indent_all_by(4, "timeless_tables: [\n"))?; @@ -59,7 +59,7 @@ impl std::fmt::Display for DataStore { "{} indexed tables, for a total of {} across {} total rows\n", tables.len(), format_bytes(self.temporal_size_bytes() as _), - format_number(self.num_temporal_rows() as _) + format_uint(self.num_temporal_rows()) ), ))?; f.write_str(&indent::indent_all_by(4, "tables: [\n"))?; @@ -99,7 +99,7 @@ impl std::fmt::Display for IndexedTable { "size: {} buckets for a total of {} across {} total rows\n", self.buckets.len(), format_bytes(self.total_size_bytes() as _), - format_number(self.num_rows() as _), + format_uint(self.num_rows()), ))?; f.write_str("buckets: [\n")?; for (time, bucket) in buckets { @@ -125,7 +125,7 @@ impl std::fmt::Display for IndexedBucket { f.write_fmt(format_args!( "size: {} across {} rows\n", format_bytes(self.total_size_bytes() as _), - format_number(self.num_rows() as _), + format_uint(self.num_rows()), ))?; let time_range = { @@ -166,7 +166,7 @@ impl std::fmt::Display for PersistentIndexedTable { f.write_fmt(format_args!( "size: {} across {} rows\n", format_bytes(self.total_size_bytes() as _), - format_number(self.inner.read().num_rows() as _), + format_uint(self.inner.read().num_rows()), ))?; let (schema, columns) = self.serialize().map_err(|err| { diff --git a/crates/re_data_store/src/store_gc.rs b/crates/re_data_store/src/store_gc.rs index 8013b524f0c9..0aa190f6b5c9 100644 --- a/crates/re_data_store/src/store_gc.rs +++ b/crates/re_data_store/src/store_gc.rs @@ -83,7 +83,7 @@ impl std::fmt::Display for GarbageCollectionTarget { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { GarbageCollectionTarget::DropAtLeastFraction(p) => { - write!(f, "DropAtLeast({:.3}%)", re_format::format_f64(*p * 100.0)) + write!(f, "DropAtLeast({:.3}%)", *p * 100.0) } GarbageCollectionTarget::Everything => write!(f, "Everything"), } @@ -144,7 +144,7 @@ impl DataStore { kind = "gc", id = self.gc_id, %options.target, - initial_num_rows = re_format::format_number(initial_num_rows as _), + initial_num_rows = re_format::format_uint(initial_num_rows), initial_num_bytes = re_format::format_bytes(initial_num_bytes), target_num_bytes = re_format::format_bytes(target_num_bytes), drop_at_least_num_bytes = re_format::format_bytes(num_bytes_to_drop), @@ -158,7 +158,7 @@ impl DataStore { kind = "gc", id = self.gc_id, %options.target, - initial_num_rows = re_format::format_number(initial_num_rows as _), + initial_num_rows = re_format::format_uint(initial_num_rows), initial_num_bytes = re_format::format_bytes(initial_num_bytes), "starting GC" ); @@ -183,9 +183,9 @@ impl DataStore { kind = "gc", id = self.gc_id, %options.target, - initial_num_rows = re_format::format_number(initial_num_rows as _), + initial_num_rows = re_format::format_uint(initial_num_rows), initial_num_bytes = re_format::format_bytes(initial_num_bytes), - new_num_rows = re_format::format_number(new_num_rows as _), + new_num_rows = re_format::format_uint(new_num_rows), new_num_bytes = re_format::format_bytes(new_num_bytes), "GC done" ); diff --git a/crates/re_data_store/src/store_sanity.rs b/crates/re_data_store/src/store_sanity.rs index 028a2f215104..f03c25afbcf1 100644 --- a/crates/re_data_store/src/store_sanity.rs +++ b/crates/re_data_store/src/store_sanity.rs @@ -122,8 +122,8 @@ impl IndexedTable { if num_rows != num_rows_uncached { return Err(SanityError::RowsOutOfSync { origin: std::any::type_name::(), - expected: re_format::format_number(num_rows_uncached as _), - got: re_format::format_number(num_rows as _), + expected: re_format::format_uint(num_rows_uncached), + got: re_format::format_uint(num_rows), }); } } diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index b329896c64fc..f572dcaee7a3 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -94,10 +94,7 @@ impl DataUi for EntityComponentWithInstances { ui.label(ctx.re_ui.error_text("Error: missing instance key")); } } else if one_line { - ui.label(format!( - "{} values", - re_format::format_number(num_instances) - )); + ui.label(format!("{} values", re_format::format_uint(num_instances))); } else { table_for_verbosity(verbosity, ui) .resizable(false) @@ -148,7 +145,7 @@ impl DataUi for EntityComponentWithInstances { if num_instances > displayed_row { ui.label(format!( "…and {} more.", - re_format::format_number(num_instances - displayed_row) + re_format::format_uint(num_instances - displayed_row) )); } } diff --git a/crates/re_data_ui/src/data.rs b/crates/re_data_ui/src/data.rs index 2a74f9fc7d80..5d7751e94586 100644 --- a/crates/re_data_ui/src/data.rs +++ b/crates/re_data_ui/src/data.rs @@ -238,7 +238,7 @@ impl DataUi for MeshProperties { if let Some(indices) = self.indices.as_ref() { ui.label(format!( "{} triangles", - re_format::format_number(indices.len() / 3) + re_format::format_uint(indices.len() / 3) )); } else { ui.weak("(empty)"); diff --git a/crates/re_format/Cargo.toml b/crates/re_format/Cargo.toml index fc0489342f84..ba81b0d51558 100644 --- a/crates/re_format/Cargo.toml +++ b/crates/re_format/Cargo.toml @@ -24,6 +24,8 @@ default = [] [dependencies] +num-traits.workspace = true + arrow2 = { workspace = true, optional = true } comfy-table = { workspace = true, optional = true } re_tuid = { workspace = true, optional = true } diff --git a/crates/re_format/src/lib.rs b/crates/re_format/src/lib.rs index 795e42ca5fd9..4a0ecc78cc8a 100644 --- a/crates/re_format/src/lib.rs +++ b/crates/re_format/src/lib.rs @@ -1,4 +1,6 @@ //! Miscellaneous tools to format and parse numbers, durations, etc. +//! +//! TODO(emilk): move some of this numeric formatting into `emath` so we can use it in `egui_plot`. #[cfg(feature = "arrow")] pub mod arrow; @@ -9,9 +11,38 @@ pub use time::next_grid_tick_magnitude_ns; // --- Numbers --- -/// Pretty format a number by using thousands separators for readability. -pub fn format_number(number: usize) -> String { - let number = number.to_string(); +/// The minus character: +/// +/// Looks slightly different from the normal hyphen `-`. +const MINUS: char = '−'; + +/// Pretty format an unsigned integer by using thousands separators for readability. +/// +/// The returned value is for human eyes only, and can not be parsed +/// by the normal `usize::from_str` function. +pub fn format_uint(number: Uint) -> String +where + Uint: Copy + num_traits::Unsigned + std::fmt::Display, +{ + add_thousands_separators(&number.to_string()) +} + +/// Pretty format a signed number by using thousands separators for readability. +/// +/// The returned value is for human eyes only, and can not be parsed +/// by the normal `usize::from_str` function. +pub fn format_i64(number: i64) -> String { + if number < 0 { + // TODO(rust-num/num-traits#315): generalize this to all signed integers once https://github.com/rust-num/num-traits/issues/315 lands + format!("{MINUS}{}", format_uint(number.unsigned_abs())) + } else { + add_thousands_separators(&number.to_string()) + } +} + +/// Add thousands separators to a number, every three steps, +/// counting from the last character. +fn add_thousands_separators(number: &str) -> String { let mut chars = number.chars().rev().peekable(); let mut result = vec![]; @@ -33,44 +64,225 @@ pub fn format_number(number: usize) -> String { } #[test] -fn test_format_number() { - assert_eq!(format_number(42), "42"); - assert_eq!(format_number(999), "999"); - assert_eq!(format_number(1_000), "1 000"); - assert_eq!(format_number(123_456), "123 456"); - assert_eq!(format_number(1_234_567), "1 234 567"); +fn test_format_uint() { + assert_eq!(format_uint(42_u32), "42"); + assert_eq!(format_uint(999_u32), "999"); + assert_eq!(format_uint(1_000_u32), "1 000"); + assert_eq!(format_uint(123_456_u32), "123 456"); + assert_eq!(format_uint(1_234_567_u32), "1 234 567"); } -/// Format a number with a decent number of decimals. -pub fn format_f64(value: f64) -> String { - let is_integer = value.round() == value; - if is_integer { - return format!("{value:.0}"); +/// Options for how to format a floating point number, e.g. an [`f64`]. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct FloatFormatOptions { + /// Maximum digits of precision to use. + /// + /// This includes both the integer part and the fractional part. + pub precision: usize, + + /// Max number of decimals to show after the decimal point. + /// + /// If not specified, [`Self::precision`] is used instead. + pub num_decimals: Option, + + pub strip_trailing_zeros: bool, +} + +impl FloatFormatOptions { + /// Default options for formatting an [`f32`]. + #[allow(non_upper_case_globals)] + pub const DEFAULT_f32: Self = Self { + precision: 7, + num_decimals: None, + strip_trailing_zeros: true, + }; + + /// Default options for formatting an [`f64`]. + #[allow(non_upper_case_globals)] + pub const DEFAULT_f64: Self = Self { + precision: 15, + num_decimals: None, + strip_trailing_zeros: true, + }; + + /// Show at most this many digits of precision, + /// including both the integer part and the fractional part. + #[inline] + pub fn with_precision(mut self, precision: usize) -> Self { + self.precision = precision; + self + } + + /// Max number of decimals to show after the decimal point. + /// + /// If not specified, [`Self::precision`] is used instead. + #[inline] + pub fn with_decimals(mut self, num_decimals: usize) -> Self { + self.num_decimals = Some(num_decimals); + self + } + + /// The returned value is for human eyes only, and can not be parsed + /// by the normal `f64::from_str` function. + pub fn format(&self, value: impl Into) -> String { + self.format_f64(value.into()) + } + + fn format_f64(&self, value: f64) -> String { + fn reverse(s: &str) -> String { + s.chars().rev().collect() + } + + let Self { + precision, + num_decimals, + strip_trailing_zeros, + } = *self; + + if value.is_nan() { + "NaN".to_owned() + } else if value < 0.0 { + format!("{MINUS}{}", self.format_f64(-value)) + } else if value == f64::INFINITY { + "∞".to_owned() + } else { + let magnitude = value.log10(); + let max_decimals = precision as f64 - magnitude.max(0.0); + + if max_decimals < 0.0 { + // A very large number (more digits than we have precision), + // so use scientific notation. + // TODO(emilk): nice formatting of scientific notation with thousands separators + return format!("{:.*e}", precision.saturating_sub(1), value); + } + + let max_decimals = max_decimals as usize; + + let num_decimals = if let Some(num_decimals) = num_decimals { + num_decimals.min(max_decimals) + } else { + max_decimals + }; + + let mut formatted = format!("{value:.num_decimals$}"); + + if strip_trailing_zeros && formatted.contains('.') { + while formatted.ends_with('0') { + formatted.pop(); + } + if formatted.ends_with('.') { + formatted.pop(); + } + } + + if let Some(dot) = formatted.find('.') { + let integer_part = &formatted[..dot]; + let fractional_part = &formatted[dot + 1..]; + // let fractional_part = &fractional_part[..num_decimals.min(fractional_part.len())]; + + let integer_part = add_thousands_separators(integer_part); + // For the fractional part we should start counting thousand separators from the _front_, so we reverse: + let fractional_part = reverse(&add_thousands_separators(&reverse(fractional_part))); + format!("{integer_part}.{fractional_part}") + } else { + add_thousands_separators(&formatted) // it's an integer + } + } } +} - let magnitude = value.abs().log10(); - let num_decimals = (3.5 - magnitude).round().max(1.0) as usize; - format!("{value:.num_decimals$}") +/// Format a number with about 15 decimals of precision. +/// +/// The returned value is for human eyes only, and can not be parsed +/// by the normal `f64::from_str` function. +pub fn format_f64(value: f64) -> String { + FloatFormatOptions::DEFAULT_f64.format(value) } -/// Format a number with a decent number of decimals. +/// Format a number with about 7 decimals of precision. +/// +/// The returned value is for human eyes only, and can not be parsed +/// by the normal `f64::from_str` function. pub fn format_f32(value: f32) -> String { - format_f64(value as f64) + FloatFormatOptions::DEFAULT_f32.format(value) +} + +#[test] +fn test_format_f32() { + let cases = [ + (f32::NAN, "NaN"), + (f32::INFINITY, "∞"), + (f32::NEG_INFINITY, "−∞"), + (0.0, "0"), + (42.0, "42"), + (10_000.0, "10 000"), + (1_000_000.0, "1 000 000"), + (10_000_000.0, "10 000 000"), + (11_000_000.0, "1.100000e7"), + (-42.0, "−42"), + (-4.20, "−4.2"), + (123_456.78, "123 456.8"), + (78.4321, "78.432 1"), + (-std::f32::consts::PI, "−3.141 593"), + (-std::f32::consts::PI * 1e6, "−3 141 593"), + (-std::f32::consts::PI * 1e20, "−3.141593e20"), // We should switch to scientific notation to now show dummy digits + ]; + for (value, expected) in cases { + let got = format_f32(value); + assert!( + got == expected, + "Expected to format {value} as '{expected}', but got '{got}'" + ); + } +} + +#[test] +fn test_format_f64() { + let cases = [ + (f64::NAN, "NaN"), + (f64::INFINITY, "∞"), + (f64::NEG_INFINITY, "−∞"), + (0.0, "0"), + (42.0, "42"), + (-42.0, "−42"), + (-4.20, "−4.2"), + (123_456_789.0, "123 456 789"), + (123_456_789.123_45, "123 456 789.123 45"), + (0.0000123456789, "0.000 012 345 678 9"), + (0.123456789, "0.123 456 789"), + (1.23456789, "1.234 567 89"), + (12.3456789, "12.345 678 9"), + (123.456789, "123.456 789"), + (1234.56789, "1 234.567 89"), + (12345.6789, "12 345.678 9"), + (78.4321, "78.432 1"), + (-std::f64::consts::PI, "−3.141 592 653 589 79"), + (-std::f64::consts::PI * 1e6, "−3 141 592.653 589 79"), + (-std::f64::consts::PI * 1e20, "−3.14159265358979e20"), // We should switch to scientific notation to now show dummy digits + ]; + for (value, expected) in cases { + let got = format_f64(value); + assert!( + got == expected, + "Expected to format {value} as '{expected}', but got '{got}'" + ); + } } #[test] -fn test_format_float() { - assert_eq!(format_f64(42.0), "42"); - assert_eq!(format_f64(123_456_789.0), "123456789"); - assert_eq!(format_f64(123_456_789.123_45), "123456789.1"); - assert_eq!(format_f64(0.0000123456789), "0.00001235"); - assert_eq!(format_f64(0.123456789), "0.1235"); - assert_eq!(format_f64(1.23456789), "1.235"); - assert_eq!(format_f64(12.3456789), "12.35"); - assert_eq!(format_f64(123.456789), "123.5"); - assert_eq!(format_f64(1234.56789), "1234.6"); - assert_eq!(format_f64(12345.6789), "12345.7"); - assert_eq!(format_f64(78.4321), "78.43"); +fn test_format_f64_custom() { + let cases = [( + FloatFormatOptions::DEFAULT_f64.with_decimals(2), + 123.456789, + "123.46", + )]; + for (options, value, expected) in cases { + let got = options.format(value); + assert!( + got == expected, + "Expected to format {value} as '{expected}', but got '{got}'. Options: {options:#?}" + ); + } } /// Pretty format a large number by using SI notation (base 10), e.g. @@ -83,14 +295,12 @@ fn test_format_float() { /// assert_eq!(approximate_large_number(123_456_789 as _), "123M"); /// ``` /// -/// Prefer to use [`format_number`], which outputs an exact string, +/// Prefer to use [`format_uint`], which outputs an exact string, /// while still being readable thanks to half-width spaces used as thousands-separators. pub fn approximate_large_number(number: f64) -> String { if number < 0.0 { - return format!("-{}", approximate_large_number(-number)); - } - - if number < 1000.0 { + format!("{MINUS}{}", approximate_large_number(-number)) + } else if number < 1000.0 { format!("{number:.0}") } else if number < 1_000_000.0 { let decimals = (number < 10_000.0) as usize; @@ -140,10 +350,8 @@ fn test_format_large_number() { /// ``` pub fn format_bytes(number_of_bytes: f64) -> String { if number_of_bytes < 0.0 { - return format!("-{}", format_bytes(-number_of_bytes)); - } - - if number_of_bytes < 10.0_f64.exp2() { + format!("{MINUS}{}", format_bytes(-number_of_bytes)) + } else if number_of_bytes < 10.0_f64.exp2() { format!("{number_of_bytes:.0} B") } else if number_of_bytes < 20.0_f64.exp2() { let decimals = (10.0 * number_of_bytes < 20.0_f64.exp2()) as usize; @@ -194,7 +402,9 @@ fn test_format_bytes() { pub fn parse_bytes_base10(bytes: &str) -> Option { // Note: intentionally case sensitive so that we don't parse `Mb` (Megabit) as `MB` (Megabyte). - if let Some(kb) = bytes.strip_suffix("kB") { + if let Some(rest) = bytes.strip_prefix(MINUS) { + Some(-parse_bytes_base10(rest)?) + } else if let Some(kb) = bytes.strip_suffix("kB") { Some(kb.parse::().ok()? * 1_000) } else if let Some(mb) = bytes.strip_suffix("MB") { Some(mb.parse::().ok()? * 1_000_000) @@ -225,6 +435,8 @@ fn test_parse_bytes_base10() { ("123B", 123), ("12kB", 12_000), ("123MB", 123_000_000), + ("-10B", -10), // hyphen-minus + ("−10B", -10), // proper minus ]; for (value, expected) in test_cases { assert_eq!(Some(expected), parse_bytes_base10(value)); @@ -233,7 +445,9 @@ fn test_parse_bytes_base10() { pub fn parse_bytes_base2(bytes: &str) -> Option { // Note: intentionally case sensitive so that we don't parse `Mib` (Mebibit) as `MiB` (Mebibyte). - if let Some(kb) = bytes.strip_suffix("KiB") { + if let Some(rest) = bytes.strip_prefix(MINUS) { + Some(-parse_bytes_base2(rest)?) + } else if let Some(kb) = bytes.strip_suffix("KiB") { Some(kb.parse::().ok()? * 1024) } else if let Some(mb) = bytes.strip_suffix("MiB") { Some(mb.parse::().ok()? * 1024 * 1024) @@ -265,6 +479,8 @@ fn test_parse_bytes_base2() { ("123B", 123), ("12KiB", 12 * 1024), ("123MiB", 123 * 1024 * 1024), + ("-10B", -10), // hyphen-minus + ("−10B", -10), // proper minus ]; for (value, expected) in test_cases { assert_eq!(Some(expected), parse_bytes_base2(value)); diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index 47918f38dcd6..16b4e0f2687b 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -1,7 +1,7 @@ use std::sync::atomic::AtomicBool; use re_data_store::{DataStoreConfig, DataStoreRowStats, DataStoreStats}; -use re_format::{format_bytes, format_number}; +use re_format::{format_bytes, format_uint}; use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse}; use re_query_cache::{CachedComponentStats, CachedEntityStats, CachesStats}; use re_renderer::WgpuResourcePoolStatistics; @@ -243,7 +243,7 @@ impl MemoryPanel { if num_rows == u64::MAX { ui.label("+∞") } else { - ui.label(re_format::format_number(num_rows as _)) + ui.label(re_format::format_uint(num_rows)) } }; @@ -283,7 +283,7 @@ impl MemoryPanel { num_bytes, } = row_stats; - ui.label(re_format::format_number(num_rows as _)); + ui.label(re_format::format_uint(num_rows)); ui.label(re_format::format_bytes(num_bytes as _)); } @@ -308,12 +308,12 @@ impl MemoryPanel { ui.end_row(); ui.label("Temporal:"); - ui.label(re_format::format_number(temporal_buckets as _)); + ui.label(re_format::format_uint(temporal_buckets)); label_row_stats(ui, temporal); ui.end_row(); ui.label("Total"); - ui.label(re_format::format_number(temporal_buckets as _)); + ui.label(re_format::format_uint(temporal_buckets)); label_row_stats(ui, total); ui.end_row(); }); @@ -439,8 +439,8 @@ impl MemoryPanel { } = stats; ui.label(component_name.to_string()); - ui.label(re_format::format_number(total_rows as _)); - ui.label(re_format::format_number(total_instances as _)); + ui.label(re_format::format_uint(total_rows)); + ui.label(re_format::format_uint(total_instances)); ui.label(re_format::format_bytes(total_size_bytes as _)); ui.end_row(); } @@ -448,7 +448,7 @@ impl MemoryPanel { }); } - ui.label(re_format::format_number(*total_rows as _)); + ui.label(re_format::format_uint(*total_rows)); ui.label(re_format::format_bytes(*total_size_bytes as _)); } } @@ -461,23 +461,23 @@ impl MemoryPanel { ui.label(format!( "fully_tracked: {} in {} allocs", format_bytes(tracking_stats.fully_tracked.size as _), - format_number(tracking_stats.fully_tracked.count), + format_uint(tracking_stats.fully_tracked.count), )); ui.label(format!( "stochastically_tracked: {} in {} allocs", format_bytes(tracking_stats.stochastically_tracked.size as _), - format_number(tracking_stats.stochastically_tracked.count), + format_uint(tracking_stats.stochastically_tracked.count), )); ui.label(format!( "untracked: {} in {} allocs (all smaller than {})", format_bytes(tracking_stats.untracked.size as _), - format_number(tracking_stats.untracked.count), + format_uint(tracking_stats.untracked.count), format_bytes(tracking_stats.track_size_threshold as _), )); ui.label(format!( "overhead: {} in {} allocs", format_bytes(tracking_stats.overhead.size as _), - format_number(tracking_stats.overhead.count), + format_uint(tracking_stats.overhead.count), )) .on_hover_text("Used for the book-keeping of the allocation tracker"); @@ -496,7 +496,7 @@ impl MemoryPanel { "{}{} in {} allocs (≈{} / alloc){} - {}", if is_stochastic { "≈" } else { "" }, format_bytes((callstack.extant.size * stochastic_rate) as _), - format_number(callstack.extant.count * stochastic_rate), + format_uint(callstack.extant.count * stochastic_rate), format_bytes( callstack.extant.size as f64 / callstack.extant.count as f64 ), diff --git a/crates/re_viewer/src/ui/top_panel.rs b/crates/re_viewer/src/ui/top_panel.rs index ca9165c90ab9..160120e04448 100644 --- a/crates/re_viewer/src/ui/top_panel.rs +++ b/crates/re_viewer/src/ui/top_panel.rs @@ -1,6 +1,6 @@ use egui::NumExt as _; use itertools::Itertools; -use re_format::format_number; +use re_format::format_uint; use re_renderer::WgpuResourcePoolStatistics; use re_smart_channel::{ReceiveSet, SmartChannelSource}; use re_ui::UICommand; @@ -361,10 +361,10 @@ fn memory_use_label_ui(ui: &mut egui::Ui, gpu_resource_stats: &WgpuResourcePoolS "Rerun Viewer is using {} of RAM in {} separate allocations,\n\ plus {} of GPU memory in {} textures and {} buffers.", bytes_used_text, - format_number(count.count), + format_uint(count.count), re_format::format_bytes(gpu_resource_stats.total_bytes() as _), - format_number(gpu_resource_stats.num_textures), - format_number(gpu_resource_stats.num_buffers), + format_uint(gpu_resource_stats.num_textures), + format_uint(gpu_resource_stats.num_buffers), )); } else if let Some(rss) = mem.resident { let bytes_used_text = re_format::format_bytes(rss as _); @@ -374,8 +374,8 @@ fn memory_use_label_ui(ui: &mut egui::Ui, gpu_resource_stats: &WgpuResourcePoolS plus {} of GPU memory in {} textures and {} buffers.", bytes_used_text, re_format::format_bytes(gpu_resource_stats.total_bytes() as _), - format_number(gpu_resource_stats.num_textures), - format_number(gpu_resource_stats.num_buffers), + format_uint(gpu_resource_stats.num_textures), + format_uint(gpu_resource_stats.num_buffers), )); ui.label( "To get more accurate memory reportings, consider configuring your Rerun \n\ @@ -411,7 +411,7 @@ fn latency_ui(ui: &mut egui::Ui, app: &mut App, store_context: Option<&StoreCont ui.label(format!( "Queue latency: {}, length: {}", latency_text(latency_sec), - format_number(queue_len), + format_uint(queue_len), )); ui.label( @@ -474,7 +474,7 @@ fn input_queue_latency_ui(ui: &mut egui::Ui, app: &mut App) { let text = format!( "Queue latency: {}, length: {}", latency_text(latency_sec), - format_number(queue_len), + format_uint(queue_len), ); let hover_text = "When more data is arriving over network than the Rerun Viewer can ingest, a queue starts building up, leading to latency and increased RAM use.\n\ @@ -487,7 +487,7 @@ fn input_queue_latency_ui(ui: &mut egui::Ui, app: &mut App) { .on_hover_text(hover_text); } } else { - ui.weak(format!("Queue: {}", format_number(queue_len))) + ui.weak(format!("Queue: {}", format_uint(queue_len))) .on_hover_text("Number of messages in the inbound queue"); } } From 2434877612d2360c320dc024d159ccfb3537c65c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 3 Apr 2024 09:53:49 +0200 Subject: [PATCH 163/508] Improve formatting of numbers on plot Y axis (#5753) ### What The formatting up numbers on the plot Y axis was really bad before, showing very few digits of precision, and switching to scientific mode really early. Now it use up to 15 digits of precision and uses thousands separators for clairy. Sequence timelines (frames, log_tick, etc) are now also formatted with thousands separators to make them easier to read when large. #### Before Screenshot 2024-04-03 at 05 30 03 #### After Screenshot 2024-04-03 at 05 30 43 Screenshot 2024-04-03 at 05 31 28 Screenshot 2024-04-03 at 05 31 11 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5753) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5753?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5753?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5753) - [Docs preview](https://rerun.io/preview/5b0f69e4f74dfb9cc855ba62d4f1241e8a103c57/docs) - [Examples preview](https://rerun.io/preview/5b0f69e4f74dfb9cc855ba62d4f1241e8a103c57/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_log_types/src/time_point/mod.rs | 2 +- .../src/space_view_class.rs | 18 +++++++++++++----- crates/re_time_panel/src/paint_ticks.rs | 3 ++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/crates/re_log_types/src/time_point/mod.rs b/crates/re_log_types/src/time_point/mod.rs index 63c73a4aa2e1..b6c0ad94eea7 100644 --- a/crates/re_log_types/src/time_point/mod.rs +++ b/crates/re_log_types/src/time_point/mod.rs @@ -139,7 +139,7 @@ impl TimeType { } else { match self { Self::Time => Time::from(time_int).format(time_zone_for_timestamps), - Self::Sequence => format!("#{}", time_int.0), + Self::Sequence => format!("#{}", re_format::format_i64(time_int.0)), } } } diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index cc78f74897c2..06ad0b08b0ee 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -404,6 +404,7 @@ It can greatly improve performance (and readability) in such situations as it pr time_zone_for_timestamps, ) }) + .y_axis_formatter(move |mark, _, _| format_y_axis(mark)) .y_axis_width(3) // in digits .label_formatter(move |name, value| { let name = if name.is_empty() { "y" } else { name }; @@ -412,16 +413,14 @@ It can greatly improve performance (and readability) in such situations as it pr time_zone_for_timestamps, ); - let is_integer = value.y.round() == value.y; - let decimals = if is_integer { 0 } else { 5 }; + let y_value = re_format::format_f64(value.y); if aggregator == TimeSeriesAggregator::Off || aggregation_factor <= 1.0 { - format!("{timeline_name}: {label}\n{name}: {:.decimals$}", value.y) + format!("{timeline_name}: {label}\n{name}: {y_value}") } else { format!( - "{timeline_name}: {label}\n{name}: {:.decimals$}\n\ + "{timeline_name}: {label}\n{name}: {y_value}\n\ {aggregator} aggregation over approx. {aggregation_factor:.1} time points", - value.y, ) } }); @@ -791,6 +790,15 @@ fn format_time(time_type: TimeType, time_int: i64, time_zone_for_timestamps: Tim } } +fn format_y_axis(mark: egui_plot::GridMark) -> String { + // Example: If the step to the next tick is `0.01`, we should use 2 decimals of precision: + let num_decimals = -mark.step_size.log10().round() as usize; + + re_format::FloatFormatOptions::DEFAULT_f64 + .with_decimals(num_decimals) + .format(mark.value) +} + fn ns_grid_spacer( canvas_size: egui::Vec2, input: &egui_plot::GridInput, diff --git a/crates/re_time_panel/src/paint_ticks.rs b/crates/re_time_panel/src/paint_ticks.rs index bc3cb8ae3ac3..1d3e7b778555 100644 --- a/crates/re_time_panel/src/paint_ticks.rs +++ b/crates/re_time_panel/src/paint_ticks.rs @@ -79,6 +79,7 @@ fn paint_time_range_ticks( |ns| Time::from_ns_since_epoch(ns).format_time_compact(time_zone_for_timestamps), ) } + TimeType::Sequence => { fn next_power_of_10(i: i64) -> i64 { i * 10 @@ -91,7 +92,7 @@ fn paint_time_range_ticks( &ui.clip_rect(), time_range, next_power_of_10, - |seq| format!("#{seq}"), + |seq| format!("#{}", re_format::format_i64(seq)), ) } } From 8ee2cdbbdbe363f58c22c5ef509017aceab36f76 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 3 Apr 2024 13:16:42 +0200 Subject: [PATCH 164/508] Make Welcome screen work without internet too (#5756) ### What * Closes https://github.com/rerun-io/rerun/issues/5752 Make sure to show the welcome screen header even while downloading the manifest (slow internet) or failing to do so (no internet). See commit messages for details. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5756) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5756?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5756?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5756) - [Docs preview](https://rerun.io/preview/d22c288d25984b18cd438ccbbd7af1b2e6b80e91/docs) - [Examples preview](https://rerun.io/preview/d22c288d25984b18cd438ccbbd7af1b2e6b80e91/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/ui/welcome_screen/example_section.rs | 18 +++++++++++++++--- crates/re_viewer/src/ui/welcome_screen/mod.rs | 2 -- .../src/ui/welcome_screen/welcome_section.rs | 5 +++-- docs/content/getting-started/what-is-rerun.md | 2 +- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index 066f9ae6af83..adc22e445e8f 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -268,7 +268,7 @@ impl ExampleSection { pub(super) fn ui( &mut self, ui: &mut egui::Ui, - re_ui: &re_ui::ReUi, + _re_ui: &re_ui::ReUi, command_sender: &CommandSender, header_ui: &impl Fn(&mut Ui), ) { @@ -277,14 +277,25 @@ impl ExampleSection { .get_or_insert_with(|| load_manifest(ui.ctx(), self.manifest_url.clone())); let Some(examples) = examples.ready_mut() else { - ui.spinner(); + // Still waiting for example to load + + header_ui(ui); // Always show the header + + ui.separator(); + + ui.spinner(); // Placeholder for the examples return; }; let examples = match examples { Ok(examples) => examples, Err(err) => { - ui.label(re_ui.error_text(format!("Failed to load examples: {err}"))); + // Examples failed to load. + + header_ui(ui); // Always show the header + + re_log::warn_once!("Failed to load examples: {err}"); + return; } }; @@ -550,6 +561,7 @@ fn example_source(ui: &mut Ui, example: &ExampleDesc) { source_url.is_some(), egui::Button::image_and_text(re_ui::icons::GITHUB.as_image(), "Source code"), ) + .on_hover_cursor(egui::CursorIcon::PointingHand) .on_disabled_hover_text("Source code is not available for this example") .clicked() { diff --git a/crates/re_viewer/src/ui/welcome_screen/mod.rs b/crates/re_viewer/src/ui/welcome_screen/mod.rs index d40f9bfcbc83..d4e86a9a8c24 100644 --- a/crates/re_viewer/src/ui/welcome_screen/mod.rs +++ b/crates/re_viewer/src/ui/welcome_screen/mod.rs @@ -41,8 +41,6 @@ impl WelcomeScreen { ..Default::default() } .show(ui, |ui| { - //welcome_section_ui(ui); - self.example_page .ui(ui, re_ui, command_sender, &welcome_section_ui); }); diff --git a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs index 39c111386f60..1724ddf51afd 100644 --- a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs @@ -40,9 +40,9 @@ pub(super) fn welcome_section_ui(ui: &mut egui::Ui) { ui.add_space(4.0); }; - bullet_text(ui, "Log with the Rerun SDK in Python, C++, or Rust"); + bullet_text(ui, "Log with the Rerun SDK in C++, Python, or Rust"); bullet_text(ui, "Visualize and explore live or recorded data"); - bullet_text(ui, "Customize in the UI or through code"); + bullet_text(ui, "Customize using the UI or through code"); ui.add_space(9.0); if ui @@ -51,6 +51,7 @@ pub(super) fn welcome_section_ui(ui: &mut egui::Ui) { .color(egui::Color32::from_hex("#60A0FF").expect("this color is valid")) .text_style(re_ui::ReUi::welcome_screen_body()), ) + .on_hover_cursor(egui::CursorIcon::PointingHand) .clicked() { ui.ctx().open_url(egui::output::OpenUrl { diff --git a/docs/content/getting-started/what-is-rerun.md b/docs/content/getting-started/what-is-rerun.md index 177c5efc2065..7b5546aabf54 100644 --- a/docs/content/getting-started/what-is-rerun.md +++ b/docs/content/getting-started/what-is-rerun.md @@ -13,7 +13,7 @@ Rerun is an SDK and engine for visualizing and interacting with multimodal data Rerun is - Free to use - Simple to integrate and get started with -- Usable from Python, Rust, and C++ +- Usable from C++, Python, and Rust - Powerful, flexible, and extensible - Built in Rust to be cross platform and fast - Open source, dual licensed under MIT and Apache 2 From 7a0218b7fa5fad9c346af108ddd56e2611ee36ee Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 3 Apr 2024 14:16:59 +0200 Subject: [PATCH 165/508] Fix clicking example source code links in example cards (#5758) * Closes https://github.com/rerun-io/rerun/issues/5757 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5758) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5758?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5758?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5758) - [Docs preview](https://rerun.io/preview/216f87ec19b278bcc46f1770f77431703519fe1c/docs) - [Examples preview](https://rerun.io/preview/216f87ec19b278bcc46f1770f77431703519fe1c/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/ui/welcome_screen/example_section.rs | 76 ++++++++++--------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index adc22e445e8f..584f7656fbeb 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -66,21 +66,6 @@ impl ExampleDescLayout { } } - /// Saves the rectangle of the hover/click area for this example. - fn set_rect(&mut self, rect: egui::Rect) { - self.rect = rect; - } - - fn clicked(&self, ui: &egui::Ui, id: egui::Id) -> bool { - ui.interact(self.rect, id.with(&self.desc.name), egui::Sense::click()) - .clicked() - } - - fn hovered(&self, ui: &egui::Ui, id: egui::Id) -> bool { - ui.interact(self.rect, id.with(&self.desc.name), egui::Sense::hover()) - .hovered() - } - /// Move the egui cursor to the bottom of this example card. fn move_cursor_to_bottom(&self, ui: &mut Ui) { let vspace = (self.rect.max.y - ui.cursor().min.y).at_least(0.0); @@ -342,18 +327,27 @@ impl ExampleSection { .min_col_width(column_width) .max_col_width(column_width) .show(ui, |ui| { - for example_layouts in examples.chunks_mut(column_count) { - for example in &mut *example_layouts { + for row_of_examples in examples.chunks_mut(column_count) { + let mut row_example_responses: Vec = vec![]; + + // Background and thumbnail + for example in &mut *row_of_examples { // this is the beginning of the first cell for this example, we can // fully compute its rect now - example.set_rect(egui::Rect::from_min_size( + example.rect = egui::Rect::from_min_size( ui.cursor().min, egui::vec2( column_width, column_width / CARD_THUMBNAIL_ASPECT_RATIO + CARD_DESCRIPTION_HEIGHT, ), - )); + ); + + let response = ui.interact( + example.rect, + self.id.with(&example.desc.name), + egui::Sense::click(), + ); // paint background ui.painter().rect_filled( @@ -363,6 +357,17 @@ impl ExampleSection { egui::Color32::WHITE.gamma_multiply(0.04), ); + if response.clicked() { + // TODO(#5177): This workaround is needed to avoid the click to "leak" + // through the UI, potentially causing some views (e.g. timeseries or time + // panel to quit auto-zoom mode. + ui.input_mut(|i| i.pointer = Default::default()); + + open_example_url(command_sender, &example.desc.rrd_url); + } + + row_example_responses.push(response); + ui.vertical(|ui| { example_thumbnail(ui, &example.desc, column_width); }); @@ -370,7 +375,8 @@ impl ExampleSection { ui.end_row(); - for example in &mut *example_layouts { + // Title + for example in &*row_of_examples { ui.vertical(|ui| { example_title(ui, example); }); @@ -378,7 +384,8 @@ impl ExampleSection { ui.end_row(); - for example in &mut *example_layouts { + // Tags + for example in &*row_of_examples { ui.vertical(|ui| { example_tags(ui, &example.desc); }); @@ -386,7 +393,10 @@ impl ExampleSection { ui.end_row(); - for example in &mut *example_layouts { + // Source code link + for (example, response) in + itertools::izip!(&*row_of_examples, row_example_responses) + { ui.vertical(|ui| { // The previous row (tags) may take one or two lines, depending // on wrapping, so we use the bottom of the example card as @@ -404,7 +414,9 @@ impl ExampleSection { ui.add_space(ROW_VSPACE); }); - if example.hovered(ui, self.id) { + if response.hovered() { + // We do the hover effect here, last, so we can make the whole card, + // including the image, brighter. ui.painter().rect_filled( example.rect, THUMBNAIL_RADIUS, @@ -417,17 +429,6 @@ impl ExampleSection { ui.end_row(); } }); - - for example in examples { - if example.clicked(ui, self.id) { - // TODO(#5177): This workaround is needed to avoid the click to "leak" - // through the UI, potentially causing some views (e.g. timeseries or time - // panel to quit auto-zoom mode. - ui.input_mut(|i| i.pointer = Default::default()); - - open_example_url(command_sender, &example.desc.rrd_url); - } - } }); }); } @@ -504,7 +505,12 @@ fn example_title(ui: &mut Ui, example: &ExampleDescLayout) { } .show(ui, |ui| { ui.horizontal(|ui| { - ui.add(egui::Label::new(title).truncate(true)); + let selectable = false; // Unselectable; otherwise selection steals input from clicking the card. + ui.add( + egui::Label::new(title) + .truncate(true) + .selectable(selectable), + ); if let Some(Some(size)) = example.rrd_byte_size_promise.ready().cloned() { ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { From a6863f750b78d138c32e1ad42c4522b70dfc4b1a Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 3 Apr 2024 17:20:09 +0200 Subject: [PATCH 166/508] Add support for directly copying the HTML tag created by `upload_image.py` (#5763) ### What Currently, `upload_image.py` (aka `just upload`) print debug output and the resulting HTML tag to stderr. Now it will _also_ print the HTML tag to stdout if stdout is not a tty. This enable piping to `pbcopy` or whatever is the equivalent on Linux/Window: So, either: ``` # copy some image to the clipboard just upload --name my_name | pbcopy # paste tag to wherever ``` or: ``` just upload some_file.png | pbcopy # paste tag to wherever ``` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5763) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5763?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5763?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5763) - [Docs preview](https://rerun.io/preview/4459ca2d3a08d4b68147aec77828ad4b887d6588/docs) - [Examples preview](https://rerun.io/preview/4459ca2d3a08d4b68147aec77828ad4b887d6588/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- scripts/upload_image.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/scripts/upload_image.py b/scripts/upload_image.py index bf9a9f95bbe8..7236a25744c4 100755 --- a/scripts/upload_image.py +++ b/scripts/upload_image.py @@ -32,6 +32,12 @@ or the just command: just upload --help + +All info/debug output occurs on stderr. If stdout is not a tty (e.g. piping to `pbcopy`), the resulting HTML tag is also +printed to stdout. For example, this upload the image from the clipboard and copies the resulting HTML tag back to the +clipboard: + + just upload --name some_name | pbcopy """ from __future__ import annotations @@ -131,12 +137,13 @@ def _check_aspect_ratio(self, image: Path | Image) -> None: f"Aspect ratio is {aspect_ratio:.2f} but should be between {ASPECT_RATIO_RANGE[0]} and " f"{ASPECT_RATIO_RANGE[1]}." ) - if ( - input( - "The image aspect ratio is outside the range recommended for example screenshots. Continue? [y/N] " - ).lower() - != "y" - ): + # do not pass prompt to input as this goes to stdout + print( + "The image aspect ratio is outside the range recommended for example screenshots. Continue? [y/N] ", + end="", + file=sys.stderr, + ) + if input().lower() != "y": sys.exit(1) def upload_file(self, path: Path) -> str: @@ -288,7 +295,7 @@ def upload_stack( else: html_str += f' \n' - logging.info(f"uploaded width={width or 'full'} ({index+1}/{len(image_stack)})") + logging.info(f"uploaded width={width or 'full'} ({index + 1}/{len(image_stack)})") html_str += "" return html_str @@ -355,7 +362,7 @@ def run(args: argparse.Namespace) -> None: raise RuntimeError("Path is required when uploading a single image") object_name = uploader.upload_file(args.path) - print(f"\nhttps://static.rerun.io/{object_name}") + html_str = f"https://static.rerun.io/{object_name}" else: if args.path is None: if args.name is None: @@ -364,9 +371,16 @@ def run(args: argparse.Namespace) -> None: html_str = uploader.upload_stack_from_clipboard(args.name) else: html_str = uploader.upload_stack_from_file(args.path, args.name) - print("\n" + html_str) + except RuntimeError as e: print(f"Error: {e.args[0]}", file=sys.stderr) + return + + print(f"\n{html_str}", file=sys.stderr) + + if not sys.stdout.isatty(): + # we might be piping to pbcopy or similar, so we print string again to stdout + print(html_str) DESCRIPTION = """Upload an image to static.rerun.io. From 9d0b0d887af1b8d2b866f8ff8751037b7a9dd80c Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 3 Apr 2024 18:26:26 +0200 Subject: [PATCH 167/508] Use new blueprint id on each sent blueprint (#5760) ### What Previously, successive `send_blueprint` calls would append new blueprints to the existing ones. This fixes this by creating a new blueprint (uu)id every time. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5760) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5760?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5760?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5760) - [Docs preview](https://rerun.io/preview/e8fc79c543c213f190273121d860f75b39d97925/docs) - [Examples preview](https://rerun.io/preview/e8fc79c543c213f190273121d860f75b39d97925/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- rerun_py/rerun_sdk/rerun/blueprint/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 367c0707f32f..fe1c693a571d 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -508,6 +508,8 @@ def create_in_memory_blueprint(*, application_id: str, blueprint: BlueprintLike) blueprint_stream = RecordingStream( bindings.new_blueprint( application_id=application_id, + # Generate a new id every time so we don't append to overwrite previous blueprints. + blueprint_id=str(uuid.uuid4()), make_default=False, make_thread_default=False, default_enabled=True, From 01e5678b22f5faafe177f4076d0c7a43320540c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Birger=20Mo=C3=ABll?= Date: Thu, 4 Apr 2024 09:55:04 +0200 Subject: [PATCH 168/508] Update README and description of `arkit_scenes` example (#5711) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5711/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5711/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5711/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5711) - [Docs preview](https://rerun.io/preview/6dd84524f2d3d2afa66866b33c681830f7534edf/docs) - [Examples preview](https://rerun.io/preview/6dd84524f2d3d2afa66866b33c681830f7534edf/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt --- docs/cspell.json | 2 + examples/python/arkit_scenes/README.md | 84 +++++++++++++++++++++++++- scripts/lint.py | 5 +- 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/docs/cspell.json b/docs/cspell.json index b9a42adfc4d6..02469d15c323 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -36,6 +36,7 @@ "backprojection", "barebone", "Bazel", + "bboxes", "Bgra", "Bhat", "bibtex", @@ -193,6 +194,7 @@ "llvmpipe", "loggable", "logtype", + "lowres", "mainpage", "Malik", "Mathieu", diff --git a/examples/python/arkit_scenes/README.md b/examples/python/arkit_scenes/README.md index 9b230c9584cb..fdb47df64ab5 100644 --- a/examples/python/arkit_scenes/README.md +++ b/examples/python/arkit_scenes/README.md @@ -1,7 +1,7 @@ + + +# Run the Code + +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` + +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/arkit_scenes/requirements.txt +``` + +To run this example use +```bash python examples/python/arkit_scenes/main.py ``` + diff --git a/scripts/lint.py b/scripts/lint.py index 6cce10c4fe70..933d504ec961 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -5,6 +5,7 @@ Adding "NOLINT" to any line makes the linter ignore that line. """ + from __future__ import annotations import argparse @@ -665,8 +666,8 @@ def lint_example_description(filepath: str, fm: Frontmatter) -> list[str]: return [] desc = fm.get("description", "") - if len(desc) > 130: - return [f"Frontmatter: description is too long ({len(desc)} > 130)"] + if len(desc) > 180: + return [f"Frontmatter: description is too long ({len(desc)} > 180)"] else: return [] From 321ccd1b0ebb9f9a9eca0983e3778c5ecf5ac07b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Apr 2024 11:01:53 +0200 Subject: [PATCH 169/508] Use space view icons in the "Add to new space view" menu (#5773) ### What This is an opportunity to teach users what those icons mean! image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5773) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5773?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5773?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5773) - [Docs preview](https://rerun.io/preview/7f455666bb0ddc77a2350094c9835b9e092b2634/docs) - [Examples preview](https://rerun.io/preview/7f455666bb0ddc77a2350094c9835b9e092b2634/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/space_view_class.rs | 2 +- .../src/space_view_class.rs | 2 +- .../src/space_view_class.rs | 2 +- .../src/space_view_class.rs | 2 +- .../actions/add_entities_to_new_space_view.rs | 40 ++++++++++--------- .../src/color_coordinates_space_view.rs | 2 +- 6 files changed, 26 insertions(+), 24 deletions(-) diff --git a/crates/re_space_view_bar_chart/src/space_view_class.rs b/crates/re_space_view_bar_chart/src/space_view_class.rs index 4f9f848182db..9d29fa0a0470 100644 --- a/crates/re_space_view_bar_chart/src/space_view_class.rs +++ b/crates/re_space_view_bar_chart/src/space_view_class.rs @@ -19,7 +19,7 @@ impl SpaceViewClass for BarChartSpaceView { } fn display_name(&self) -> &'static str { - "Bar Chart" + "Bar chart" } fn icon(&self) -> &'static re_ui::Icon { diff --git a/crates/re_space_view_text_document/src/space_view_class.rs b/crates/re_space_view_text_document/src/space_view_class.rs index 5154de039c99..572262aebd18 100644 --- a/crates/re_space_view_text_document/src/space_view_class.rs +++ b/crates/re_space_view_text_document/src/space_view_class.rs @@ -52,7 +52,7 @@ impl SpaceViewClass for TextDocumentSpaceView { } fn display_name(&self) -> &'static str { - "Text Document" + "Text document" } fn icon(&self) -> &'static re_ui::Icon { diff --git a/crates/re_space_view_text_log/src/space_view_class.rs b/crates/re_space_view_text_log/src/space_view_class.rs index 15d5e273731f..8708308cda38 100644 --- a/crates/re_space_view_text_log/src/space_view_class.rs +++ b/crates/re_space_view_text_log/src/space_view_class.rs @@ -45,7 +45,7 @@ impl SpaceViewClass for TextSpaceView { } fn display_name(&self) -> &'static str { - "Text Log" + "Text log" } fn icon(&self) -> &'static re_ui::Icon { diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 06ad0b08b0ee..3c11d5e31583 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -80,7 +80,7 @@ impl SpaceViewClass for TimeSeriesSpaceView { } fn display_name(&self) -> &'static str { - "Time Series" + "Time series" } fn icon(&self) -> &'static re_ui::Icon { diff --git a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs index 005d8ce42d15..ad567045955b 100644 --- a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs +++ b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs @@ -35,26 +35,28 @@ impl ContextMenuAction for AddEntitiesToNewSpaceViewAction { .collect(); ui.menu_button("Add to new space view", |ui| { - let buttons_for_space_view_classes = - |ui: &mut egui::Ui, space_view_classes: &IntSet| { - for (identifier, display_name) in space_view_classes - .iter() - .map(|identifier| { - ( - identifier, - space_view_class_registry - .get_class_or_log_error(identifier) - .display_name(), - ) - }) - .sorted_by_key(|(_, display_name)| display_name.to_owned()) - { - if ui.button(display_name).clicked() { - create_space_view_for_selected_entities(ctx, *identifier); - ui.close_menu(); - } + let buttons_for_space_view_classes = |ui: &mut egui::Ui, + space_view_classes: &IntSet< + SpaceViewClassIdentifier, + >| { + for (identifier, class) in space_view_classes + .iter() + .map(|identifier| { + ( + identifier, + space_view_class_registry.get_class_or_log_error(identifier), + ) + }) + .sorted_by_key(|(_, class)| class.display_name().to_owned()) + { + let btn = + egui::Button::image_and_text(class.icon().as_image(), class.display_name()); + if ui.add(btn).clicked() { + create_space_view_for_selected_entities(ctx, *identifier); + ui.close_menu(); } - }; + } + }; ui.label(egui::WidgetText::from("Recommended:").italics()); if recommended_space_view_classes.is_empty() { diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index 339c0edd97af..622c8927ab90 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -73,7 +73,7 @@ impl SpaceViewClass for ColorCoordinatesSpaceView { } fn display_name(&self) -> &'static str { - "Color Coordinates" + "Color coordinates" } fn icon(&self) -> &'static re_ui::Icon { From e7ed16d8094393f42d851fec285402d62eebb1d5 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Apr 2024 11:02:44 +0200 Subject: [PATCH 170/508] Use consistent `PascalCase` for space view class identifiers (#5774) We used to mix different casing. Using `PascalCase` makes it clear it is an identifier (NOT a name) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5774) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5774?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5774?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5774) - [Docs preview](https://rerun.io/preview/95e556378ad5d0ad093c001ac3420716fb66a925/docs) - [Examples preview](https://rerun.io/preview/95e556378ad5d0ad093c001ac3420716fb66a925/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view_bar_chart/src/space_view_class.rs | 2 +- crates/re_space_view_text_document/src/space_view_class.rs | 2 +- crates/re_space_view_time_series/src/space_view_class.rs | 2 +- crates/re_viewer_context/src/space_view/space_view_class.rs | 3 +-- .../src/space_view/space_view_class_placeholder.rs | 2 +- .../custom_space_view/src/color_coordinates_space_view.rs | 2 +- rerun_py/rerun_sdk/rerun/blueprint/space_views.py | 6 +++--- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/re_space_view_bar_chart/src/space_view_class.rs b/crates/re_space_view_bar_chart/src/space_view_class.rs index 9d29fa0a0470..2ee86651d9e0 100644 --- a/crates/re_space_view_bar_chart/src/space_view_class.rs +++ b/crates/re_space_view_bar_chart/src/space_view_class.rs @@ -15,7 +15,7 @@ pub struct BarChartSpaceView; impl SpaceViewClass for BarChartSpaceView { fn identifier() -> SpaceViewClassIdentifier { - "Bar Chart".into() + "BarChart".into() } fn display_name(&self) -> &'static str { diff --git a/crates/re_space_view_text_document/src/space_view_class.rs b/crates/re_space_view_text_document/src/space_view_class.rs index 572262aebd18..28d1d61642a7 100644 --- a/crates/re_space_view_text_document/src/space_view_class.rs +++ b/crates/re_space_view_text_document/src/space_view_class.rs @@ -48,7 +48,7 @@ pub struct TextDocumentSpaceView; impl SpaceViewClass for TextDocumentSpaceView { fn identifier() -> SpaceViewClassIdentifier { - "Text Document".into() + "TextDocument".into() } fn display_name(&self) -> &'static str { diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 3c11d5e31583..54b5312252d5 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -76,7 +76,7 @@ const DEFAULT_LEGEND_CORNER: egui_plot::Corner = egui_plot::Corner::RightBottom; impl SpaceViewClass for TimeSeriesSpaceView { fn identifier() -> SpaceViewClassIdentifier { - "Time Series".into() + "TimeSeries".into() } fn display_name(&self) -> &'static str { diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index 3aac62c4c441..6a0e899b9931 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -59,8 +59,7 @@ impl VisualizableFilterContext for () { pub trait SpaceViewClass: Send + Sync { /// Identifier string of this space view class. /// - /// This is similar to [`Self::identifier`] but it can be used without an actual instance of the - /// class. + /// By convention we use `PascalCase`. fn identifier() -> SpaceViewClassIdentifier where Self: Sized; diff --git a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs index f60bcea30617..2d64e1f5c31c 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs @@ -11,7 +11,7 @@ pub struct SpaceViewClassPlaceholder; impl SpaceViewClass for SpaceViewClassPlaceholder { fn identifier() -> SpaceViewClassIdentifier { - "Unknown space view class".into() + "UnknownSpaceViewClass".into() } fn display_name(&self) -> &'static str { diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index 622c8927ab90..2c53a75d60b9 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -69,7 +69,7 @@ impl SpaceViewClass for ColorCoordinatesSpaceView { // State type as described above. fn identifier() -> SpaceViewClassIdentifier { - "Color Coordinates".into() + "ColorCoordinates".into() } fn display_name(&self) -> &'static str { diff --git a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py index 6a5c2293ad09..347221e6e46a 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py @@ -29,7 +29,7 @@ def __init__( The name of the view. """ - super().__init__(class_identifier="Bar Chart", origin=origin, contents=contents, name=name) + super().__init__(class_identifier="BarChart", origin=origin, contents=contents, name=name) class Spatial2DView(SpaceView): @@ -141,7 +141,7 @@ def __init__( The name of the view. """ - super().__init__(class_identifier="Text Document", origin=origin, contents=contents, name=name) + super().__init__(class_identifier="TextDocument", origin=origin, contents=contents, name=name) class TextLogView(SpaceView): @@ -197,4 +197,4 @@ def __init__( The name of the view. """ - super().__init__(class_identifier="Time Series", origin=origin, contents=contents, name=name) + super().__init__(class_identifier="TimeSeries", origin=origin, contents=contents, name=name) From 15eecd3ca24ab32245cbba55031fcb994273b08a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Apr 2024 11:04:12 +0200 Subject: [PATCH 171/508] re_format: add general `format_int` function (#5754) ### What Mostly as an experiment to see if this makes sense as a `trait` for `num-traits` (see https://github.com/rust-num/num-traits/issues/315) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5754) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5754?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5754?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5754) - [Docs preview](https://rerun.io/preview/b55246f04976986ca8ffac7b72963eae454e374b/docs) - [Examples preview](https://rerun.io/preview/b55246f04976986ca8ffac7b72963eae454e374b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_format/src/lib.rs | 93 ++++++++++++++++++++--- crates/re_log_types/src/time_point/mod.rs | 2 +- crates/re_time_panel/src/paint_ticks.rs | 2 +- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/crates/re_format/src/lib.rs b/crates/re_format/src/lib.rs index 4a0ecc78cc8a..778fb6beac39 100644 --- a/crates/re_format/src/lib.rs +++ b/crates/re_format/src/lib.rs @@ -7,6 +7,8 @@ pub mod arrow; mod time; +use std::{cmp::PartialOrd, fmt::Display}; + pub use time::next_grid_tick_magnitude_ns; // --- Numbers --- @@ -16,30 +18,97 @@ pub use time::next_grid_tick_magnitude_ns; /// Looks slightly different from the normal hyphen `-`. const MINUS: char = '−'; -/// Pretty format an unsigned integer by using thousands separators for readability. -/// -/// The returned value is for human eyes only, and can not be parsed -/// by the normal `usize::from_str` function. -pub fn format_uint(number: Uint) -> String -where - Uint: Copy + num_traits::Unsigned + std::fmt::Display, -{ - add_thousands_separators(&number.to_string()) +// TODO(rust-num/num-traits#315): waiting for https://github.com/rust-num/num-traits/issues/315 to land +pub trait UnsignedAbs { + /// An unsigned type which is large enough to hold the absolute value of `Self`. + type Unsigned; + + /// Computes the absolute value of `self` without any wrapping or panicking. + fn unsigned_abs(self) -> Self::Unsigned; +} + +impl UnsignedAbs for i8 { + type Unsigned = u8; + + #[inline] + fn unsigned_abs(self) -> Self::Unsigned { + self.unsigned_abs() + } +} + +impl UnsignedAbs for i16 { + type Unsigned = u16; + + #[inline] + fn unsigned_abs(self) -> Self::Unsigned { + self.unsigned_abs() + } +} + +impl UnsignedAbs for i32 { + type Unsigned = u32; + + #[inline] + fn unsigned_abs(self) -> Self::Unsigned { + self.unsigned_abs() + } +} + +impl UnsignedAbs for i64 { + type Unsigned = u64; + + #[inline] + fn unsigned_abs(self) -> Self::Unsigned { + self.unsigned_abs() + } +} + +impl UnsignedAbs for i128 { + type Unsigned = u128; + + #[inline] + fn unsigned_abs(self) -> Self::Unsigned { + self.unsigned_abs() + } +} + +impl UnsignedAbs for isize { + type Unsigned = usize; + + #[inline] + fn unsigned_abs(self) -> Self::Unsigned { + self.unsigned_abs() + } } /// Pretty format a signed number by using thousands separators for readability. /// /// The returned value is for human eyes only, and can not be parsed /// by the normal `usize::from_str` function. -pub fn format_i64(number: i64) -> String { - if number < 0 { - // TODO(rust-num/num-traits#315): generalize this to all signed integers once https://github.com/rust-num/num-traits/issues/315 lands +pub fn format_int(number: Int) -> String +where + Int: Display + PartialOrd + num_traits::Zero + UnsignedAbs, + Int::Unsigned: Display + num_traits::Unsigned, +{ + if number < Int::zero() { format!("{MINUS}{}", format_uint(number.unsigned_abs())) } else { add_thousands_separators(&number.to_string()) } } +/// Pretty format an unsigned integer by using thousands separators for readability. +/// +/// The returned value is for human eyes only, and can not be parsed +/// by the normal `usize::from_str` function. +#[allow(clippy::needless_pass_by_value)] +pub fn format_uint(number: Uint) -> String +where + Uint: Display + num_traits::Unsigned, +{ + add_thousands_separators(&number.to_string()) +} + /// Add thousands separators to a number, every three steps, /// counting from the last character. fn add_thousands_separators(number: &str) -> String { diff --git a/crates/re_log_types/src/time_point/mod.rs b/crates/re_log_types/src/time_point/mod.rs index b6c0ad94eea7..bdd4e8f4081b 100644 --- a/crates/re_log_types/src/time_point/mod.rs +++ b/crates/re_log_types/src/time_point/mod.rs @@ -139,7 +139,7 @@ impl TimeType { } else { match self { Self::Time => Time::from(time_int).format(time_zone_for_timestamps), - Self::Sequence => format!("#{}", re_format::format_i64(time_int.0)), + Self::Sequence => format!("#{}", re_format::format_int(time_int.0)), } } } diff --git a/crates/re_time_panel/src/paint_ticks.rs b/crates/re_time_panel/src/paint_ticks.rs index 1d3e7b778555..a10d4a6702ff 100644 --- a/crates/re_time_panel/src/paint_ticks.rs +++ b/crates/re_time_panel/src/paint_ticks.rs @@ -92,7 +92,7 @@ fn paint_time_range_ticks( &ui.clip_rect(), time_range, next_power_of_10, - |seq| format!("#{}", re_format::format_i64(seq)), + |seq| format!("#{}", re_format::format_int(seq)), ) } } From a1640aad976dd39e6371da17a822acbb6176f157 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Apr 2024 11:04:31 +0200 Subject: [PATCH 172/508] Example page: make sure title and file size don't overlap (#5767) ### What See commit messages Before: Screenshot 2024-04-03 at 20 20 39 After: Screenshot 2024-04-03 at 20 27 34 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5767) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5767?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5767?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5767) - [Docs preview](https://rerun.io/preview/308979f2c251bb268c373da5449712f1fe19bd64/docs) - [Examples preview](https://rerun.io/preview/308979f2c251bb268c373da5449712f1fe19bd64/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../src/ui/welcome_screen/example_section.rs | 262 +++++++++--------- 1 file changed, 132 insertions(+), 130 deletions(-) diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index 584f7656fbeb..3cf9b2364417 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -327,6 +327,9 @@ impl ExampleSection { .min_col_width(column_width) .max_col_width(column_width) .show(ui, |ui| { + // Disable text selection so that hovering the example card only hovers the card + ui.style_mut().interaction.selectable_labels = false; + for row_of_examples in examples.chunks_mut(column_count) { let mut row_example_responses: Vec = vec![]; @@ -368,35 +371,27 @@ impl ExampleSection { row_example_responses.push(response); - ui.vertical(|ui| { - example_thumbnail(ui, &example.desc, column_width); - }); + ui.vertical(|ui| example.image_ui(ui, column_width)); } ui.end_row(); // Title for example in &*row_of_examples { - ui.vertical(|ui| { - example_title(ui, example); - }); + ui.vertical(|ui| example.tile_ui(ui)); } ui.end_row(); // Tags for example in &*row_of_examples { - ui.vertical(|ui| { - example_tags(ui, &example.desc); - }); + ui.vertical(|ui| example.tags_ui(ui)); } ui.end_row(); - // Source code link - for (example, response) in - itertools::izip!(&*row_of_examples, row_example_responses) - { + // Source code link and file size + for example in &*row_of_examples { ui.vertical(|ui| { // The previous row (tags) may take one or two lines, depending // on wrapping, so we use the bottom of the example card as @@ -404,7 +399,7 @@ impl ExampleSection { example.move_cursor_to_bottom(ui); ui.add_space(-DESCRIPTION_INNER_MARGIN - 15.0); - example_source(ui, &example.desc); + example.github_link_and_size_ui(ui); // Ensure the egui cursor is moved according to this card's // geometry. @@ -413,7 +408,12 @@ impl ExampleSection { // Manual spacing between rows. ui.add_space(ROW_VSPACE); }); + } + // Hover effect + for (example, response) in + itertools::izip!(&*row_of_examples, row_example_responses) + { if response.hovered() { // We do the hover effect here, last, so we can make the whole card, // including the image, brighter. @@ -453,130 +453,132 @@ fn open_example_url(command_sender: &CommandSender, rrd_url: &str) { } } -fn example_thumbnail(ui: &mut Ui, example: &ExampleDesc, column_width: f32) { - // dimensions of the source image to use as thumbnail - let image_width = example.thumbnail.width as f32; - let image_height = example.thumbnail.height as f32; - - // the thumbnail rect is determined by the column width and a fixed aspect ratio - let thumbnail_rect = egui::Rect::from_min_size( - ui.cursor().left_top(), - egui::vec2(column_width, column_width / CARD_THUMBNAIL_ASPECT_RATIO), - ); - let thumbnail_width = thumbnail_rect.width(); - let thumbnail_height = thumbnail_rect.height(); - - // compute image UV coordinates implementing a "cropping" scale to fit thumbnail rect - let display_aspect_ratio = thumbnail_width / thumbnail_height; - let image_aspect_ratio = image_width / image_height; - let uv_rect = if image_aspect_ratio > display_aspect_ratio { - let a = - (image_width / image_height * thumbnail_height - thumbnail_width) / 2.0 / image_width; - egui::Rect::from_min_max(egui::Pos2::new(a, 0.0), egui::Pos2::new(1.0 - a, 1.0)) - } else { - let a = - (image_height / image_width * thumbnail_width - thumbnail_height) / 2.0 / image_height; - egui::Rect::from_min_max(egui::Pos2::new(0.0, a), egui::Pos2::new(1.0, 1.0 - a)) - }; +impl ExampleDescLayout { + fn image_ui(&self, ui: &mut Ui, column_width: f32) { + // dimensions of the source image to use as thumbnail + let image_width = self.desc.thumbnail.width as f32; + let image_height = self.desc.thumbnail.height as f32; + + // the thumbnail rect is determined by the column width and a fixed aspect ratio + let thumbnail_rect = egui::Rect::from_min_size( + ui.cursor().left_top(), + egui::vec2(column_width, column_width / CARD_THUMBNAIL_ASPECT_RATIO), + ); + let thumbnail_width = thumbnail_rect.width(); + let thumbnail_height = thumbnail_rect.height(); + + // compute image UV coordinates implementing a "cropping" scale to fit thumbnail rect + let display_aspect_ratio = thumbnail_width / thumbnail_height; + let image_aspect_ratio = image_width / image_height; + let uv_rect = if image_aspect_ratio > display_aspect_ratio { + let a = (image_width / image_height * thumbnail_height - thumbnail_width) + / 2.0 + / image_width; + egui::Rect::from_min_max(egui::Pos2::new(a, 0.0), egui::Pos2::new(1.0 - a, 1.0)) + } else { + let a = (image_height / image_width * thumbnail_width - thumbnail_height) + / 2.0 + / image_height; + egui::Rect::from_min_max(egui::Pos2::new(0.0, a), egui::Pos2::new(1.0, 1.0 - a)) + }; - let rounding = egui::Rounding { - nw: THUMBNAIL_RADIUS, - ne: THUMBNAIL_RADIUS, - sw: 0.0, - se: 0.0, - }; - egui::Image::new(&example.thumbnail.url) - .uv(uv_rect) - .rounding(rounding) - .paint_at(ui, thumbnail_rect); - ui.advance_cursor_after_rect(thumbnail_rect); -} + let rounding = egui::Rounding { + nw: THUMBNAIL_RADIUS, + ne: THUMBNAIL_RADIUS, + sw: 0.0, + se: 0.0, + }; + egui::Image::new(&self.desc.thumbnail.url) + .uv(uv_rect) + .rounding(rounding) + .paint_at(ui, thumbnail_rect); + ui.advance_cursor_after_rect(thumbnail_rect); + } -fn example_title(ui: &mut Ui, example: &ExampleDescLayout) { - let title = egui::RichText::new(example.desc.title.clone()) - .strong() - .line_height(Some(16.0)) - .text_style(re_ui::ReUi::welcome_screen_example_title()); + fn tile_ui(&self, ui: &mut Ui) { + let title = egui::RichText::new(self.desc.title.clone()) + .strong() + .line_height(Some(16.0)) + .text_style(re_ui::ReUi::welcome_screen_example_title()); - ui.add_space(DESCRIPTION_INNER_MARGIN); - egui::Frame { - inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), - ..Default::default() - } - .show(ui, |ui| { - ui.horizontal(|ui| { - let selectable = false; // Unselectable; otherwise selection steals input from clicking the card. - ui.add( - egui::Label::new(title) - .truncate(true) - .selectable(selectable), - ); - - if let Some(Some(size)) = example.rrd_byte_size_promise.ready().cloned() { - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - ui.label(egui::RichText::new(re_format::format_bytes(size as f64)).weak()); - }); - } + ui.add_space(DESCRIPTION_INNER_MARGIN); + egui::Frame { + inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), + ..Default::default() + } + .show(ui, |ui| { + ui.add(egui::Label::new(title).truncate(true)); }); - }); -} + } -fn example_tags(ui: &mut Ui, example: &ExampleDesc) { - ui.add_space(10.0); + fn tags_ui(&self, ui: &mut Ui) { + ui.add_space(10.0); - egui::Frame { - inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), - ..Default::default() - } - .show(ui, |ui| { - ui.horizontal_wrapped(|ui| { - // TODO(ab): use design tokens - ui.style_mut().spacing.button_padding = egui::vec2(4.0, 2.0); - ui.style_mut().spacing.item_spacing = egui::vec2(4.0, 4.0); - for tag in &example.tags { - ui.add( - egui::Button::new( - egui::RichText::new(tag) - .text_style(re_ui::ReUi::welcome_screen_tag()) - .strong(), - ) - .sense(egui::Sense::hover()) - .rounding(6.0) - .fill(egui::Color32::from_rgb(26, 29, 30)) - .stroke(egui::Stroke::new( - 1.0, - egui::Color32::WHITE.gamma_multiply(0.086), - )) - .wrap(false), - ); - } + egui::Frame { + inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), + ..Default::default() + } + .show(ui, |ui| { + ui.horizontal_wrapped(|ui| { + // TODO(ab): use design tokens + ui.style_mut().spacing.button_padding = egui::vec2(4.0, 2.0); + ui.style_mut().spacing.item_spacing = egui::vec2(4.0, 4.0); + for tag in &self.desc.tags { + ui.add( + egui::Button::new( + egui::RichText::new(tag) + .text_style(re_ui::ReUi::welcome_screen_tag()) + .strong(), + ) + .sense(egui::Sense::hover()) + .rounding(6.0) + .fill(egui::Color32::from_rgb(26, 29, 30)) + .stroke(egui::Stroke::new( + 1.0, + egui::Color32::WHITE.gamma_multiply(0.086), + )) + .wrap(false), + ); + } + }); }); - }); -} + } -fn example_source(ui: &mut Ui, example: &ExampleDesc) { - let source_url = example.source_url.as_deref(); + fn github_link_and_size_ui(&self, ui: &mut Ui) { + let source_url = self.desc.source_url.as_deref(); - egui::Frame { - inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), - ..Default::default() - } - .show(ui, |ui| { - if ui - .add_enabled( - source_url.is_some(), - egui::Button::image_and_text(re_ui::icons::GITHUB.as_image(), "Source code"), - ) - .on_hover_cursor(egui::CursorIcon::PointingHand) - .on_disabled_hover_text("Source code is not available for this example") - .clicked() - { - if let Some(source_url) = source_url { - ui.ctx().open_url(egui::output::OpenUrl { - url: source_url.to_owned(), - new_tab: true, - }); - } + egui::Frame { + inner_margin: egui::Margin::symmetric(DESCRIPTION_INNER_MARGIN, 0.0), + ..Default::default() } - }); + .show(ui, |ui| { + ui.horizontal(|ui| { + if ui + .add_enabled( + source_url.is_some(), + egui::Button::image_and_text( + re_ui::icons::GITHUB.as_image(), + "Source code", + ), + ) + .on_hover_cursor(egui::CursorIcon::PointingHand) + .on_disabled_hover_text("Source code is not available for this example") + .clicked() + { + if let Some(source_url) = source_url { + ui.ctx().open_url(egui::output::OpenUrl { + url: source_url.to_owned(), + new_tab: true, + }); + } + } + + if let Some(Some(size)) = self.rrd_byte_size_promise.ready().cloned() { + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + ui.label(egui::RichText::new(re_format::format_bytes(size as f64)).weak()); + }); + } + }); + }); + } } From eb1892e4c8934ea84b15d3e27bae860cb37db99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Birger=20Mo=C3=ABll?= Date: Thu, 4 Apr 2024 11:16:07 +0200 Subject: [PATCH 173/508] Improve readme of `depth_guided_stable_diffusion` example (#5593) ### What * Replaces #5502 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5593/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5593/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5593/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5593) - [Docs preview](https://rerun.io/preview/49584ada6236c9802c2490a106ef20ebedaa6cf3/docs) - [Examples preview](https://rerun.io/preview/49584ada6236c9802c2490a106ef20ebedaa6cf3/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Andreas Reich --- docs/cspell.json | 3 + .../depth_guided_stable_diffusion/README.md | 96 +++++++++++++++++-- scripts/lint.py | 6 +- 3 files changed, 93 insertions(+), 12 deletions(-) diff --git a/docs/cspell.json b/docs/cspell.json index 02469d15c323..abbab567d81c 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -84,6 +84,8 @@ "DCMAKE", "deallocate", "deallocation", + "denoising", + "Denoising", "debuginfo", "dedup", "depgraph", @@ -373,6 +375,7 @@ "UI's", "uncollapsed", "unmultiplied", + "uncond", "Unorm", "unsetting", "upcasting", diff --git a/examples/python/depth_guided_stable_diffusion/README.md b/examples/python/depth_guided_stable_diffusion/README.md index be85cd53c7ad..02e21ce44144 100644 --- a/examples/python/depth_guided_stable_diffusion/README.md +++ b/examples/python/depth_guided_stable_diffusion/README.md @@ -1,25 +1,107 @@ - Depth-guided stable diffusion screenshot + Depth-guided stable diffusion example -A more elaborate example running Depth Guided Stable Diffusion 2.0. +Leverage [Depth Guided Stable Diffusion](https://github.com/Stability-AI/stablediffusion?tab=readme-ov-file#depth-conditional-stable-diffusion) to generate images with enhanced depth perception. This method integrates depth maps to guide the Stable Diffusion model, creating more visually compelling and contextually accurate images. -For more info see [here](https://github.com/Stability-AI/stablediffusion). +## Used Rerun Types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor), [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document),[`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log)[`BarChart`](https://www.rerun.io/docs/reference/types/archetypes/bar_chart) +## Background +Depth Guided Stable Diffusion enriches the image generation process by incorporating depth information, providing a unique way to control the spatial composition of generated images. This approach allows for more nuanced and layered creations, making it especially useful for scenes requiring a sense of three-dimensionality. + +# Logging and Visualizing with Rerun +The visualizations in this example were created with the Rerun SDK, demonstrating the integration of depth information in the Stable Diffusion image generation process. Here is the code for generating the visualization in Rerun. + +## Prompt +Visualizing the prompt and negative prompt +```python +rr.log("prompt/text", rr.TextLog(prompt)) +rr.log("prompt/text_negative", rr.TextLog(negative_prompt)) +``` + +## Text +Visualizing the text input ids, the text attention mask and the unconditional input ids +```python +rr.log("prompt/text_input/ids", rr.BarChart(text_input_ids)) +rr.log("prompt/text_input/attention_mask", rr.BarChart(text_inputs.attention_mask)) +rr.log("prompt/uncond_input/ids", rr.Tensor(uncond_input.input_ids)) +``` + +## Text embeddings +Visualizing the text embeddings. The text embeddings are generated in response to the specific prompts used while the unconditional text embeddings represent a neutral or baseline state without specific input conditions. +```python +rr.log("prompt/text_embeddings", rr.Tensor(text_embeddings)) +rr.log("prompt/uncond_embeddings", rr.Tensor(uncond_embeddings)) +``` + +## Depth map +Visualizing the pixel values of the depth estimation, estimated depth image, interpolated depth image and normalized depth image +```python +rr.log("depth/input_preprocessed", rr.Tensor(pixel_values)) +rr.log("depth/estimated", rr.DepthImage(depth_map)) +rr.log("depth/interpolated", rr.DepthImage(depth_map)) +rr.log("depth/normalized", rr.DepthImage(depth_map)) +``` + +## Latents +Log the latents, the representation of the images in the format used by the diffusion model. +```python +rr.log("diffusion/latents", rr.Tensor(latents, dim_names=["b", "c", "h", "w"])) +``` + +## Denoising loop +For each step in the denoising loop we set a time sequence with step and timestep and log the latent model input, noise predictions, latents and image. This make is possible for us to see all denoising steps in the Rerun viewer. +```python +rr.set_time_sequence("step", i) +rr.set_time_sequence("timestep", t) +rr.log("diffusion/latent_model_input", rr.Tensor(latent_model_input)) +rr.log("diffusion/noise_pred", rr.Tensor(noise_pred, dim_names=["b", "c", "h", "w"])) +rr.log("diffusion/latents", rr.Tensor(latents, dim_names=["b", "c", "h", "w"])) +rr.log("image/diffused", rr.Image(image)) +``` + +## Diffused image +Finally we log the diffused image generated by the model. + +```python +rr.log("image/diffused", rr.Image(image_8)) +``` + +# Run the Code + +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` + +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/depth_guided_stable_diffusion/requirements.txt +``` + +To run this example use +```bash python examples/python/depth_guided_stable_diffusion/main.py ``` +You can specify your own image and prompts using +```bash +python examples/python/depth_guided_stable_diffusion/main.py [--img-path IMG_PATH] [--depth-map-path DEPTH_MAP_PATH] [--prompt PROMPT] +````` diff --git a/scripts/lint.py b/scripts/lint.py index 933d504ec961..2603c41a670c 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -665,11 +665,7 @@ def lint_example_description(filepath: str, fm: Frontmatter) -> list[str]: if not filepath.startswith("./examples/python") or not filepath.endswith("README.md"): return [] - desc = fm.get("description", "") - if len(desc) > 180: - return [f"Frontmatter: description is too long ({len(desc)} > 180)"] - else: - return [] + return [] def lint_frontmatter(filepath: str, content: str) -> list[str]: From 48b3c9e68f45bd3b567cb6bba8d7c3c3eb404438 Mon Sep 17 00:00:00 2001 From: Alexander Berntsson Date: Thu, 4 Apr 2024 11:23:46 +0200 Subject: [PATCH 174/508] Add example visualizing KISS-ICP (#5546) ### What This is a paper visualization of the KISS-ICP algorithm. It consists of both logging from C++ and Python. The source is located at https://github.com/rerun-io/kiss-icp . It requires the prelease version of `rerun` so it might be better to wait with merging until `0.15.0` is released. --- docs/cspell.json | 5 ++++ examples/cpp/kiss-icp/README.md | 42 ++++++++++++++++++++++++++++++ examples/manifest.toml | 1 + examples/python/kiss-icp/README.md | 42 ++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 examples/cpp/kiss-icp/README.md create mode 100644 examples/python/kiss-icp/README.md diff --git a/docs/cspell.json b/docs/cspell.json index abbab567d81c..b595e623e43e 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -89,6 +89,8 @@ "debuginfo", "dedup", "depgraph", + "deskewed", + "deskewing", "devel", "Dhariwal", "dicom", @@ -230,6 +232,7 @@ "nans", "nbconvert", "ncipollo", + "NCLT", "ndarray", "Niantic", "Nichol", @@ -346,6 +349,7 @@ "Struct", "structs", "subdir", + "subsampled", "superquadrics", "tableofcontents", "taplo", @@ -393,6 +397,7 @@ "Viktor", "virtualenv", "visualizability", + "Vizzo", "vstack", "vsuryamurthy", "vulkan", diff --git a/examples/cpp/kiss-icp/README.md b/examples/cpp/kiss-icp/README.md new file mode 100644 index 000000000000..1a425669655e --- /dev/null +++ b/examples/cpp/kiss-icp/README.md @@ -0,0 +1,42 @@ + + +Estimating the odometry is a common problem in robotics and in the [2023, "KISS-ICP: In Defense of Point-to-Point ICP -- Simple, Accurate, and Robust Registration If Done the Right Way" Ignacio Vizzo et al.](https://arxiv.org/abs/2209.15397) they show how one can use an ICP (iterative closest point) algorithm to robustly and accurately estimate poses from LiDAR data. We will demonstrate the KISS-ICP pipeline on the [NCLT dataset](http://robots.engin.umich.edu/nclt/) along with some brief explanations, for a more detailed explanation you should look at the [original paper](https://arxiv.org/abs/2209.15397). + + + + + + + + + +The KISS-ICP odometry pipeline consists of 4 steps. The first step is to compensate for movement of the vehicle during the LiDAR scan which is commonly called deskewing. This is done by creating an estimate of the rotational and translational velocity from previous pose estimates, then calculate the corrected scan under the assumption that the velocity is constant. In the screenshot below the raw scan is shown as green and the corrected scan is shown as the blue. + + + + + + + + + +The second step is to subsample the deskewed point cloud at two different resolutions. The first subsample with the highest resolution iis used to update the map after the pose has been estimated. The second is a subsample of the first subsample but with a lower resolution, this subsample is used during the ICP registration step. In the screenshot below the first subsample is colored pink and the second subsample is colored purple. + + + + + + + + + +The third step is to compute the adaptive threshold which will impose a limit on the distance between correspondences during the ICP. This is done using previously estimated poses to compute a likely limit of the displacement. The final step is to estimate the current pose by doing Point-to-Point ICP. This involves comparing each point in the subsampled scan with the closest point in the constructed map and making incremental updates to the estimated odometry based on these correspondences. + +https://vimeo.com/923395317?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=1920:1080 diff --git a/examples/manifest.toml b/examples/manifest.toml index d3765693960a..16b5dc3454c6 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -82,6 +82,7 @@ examples = [ "tapir", "widebaseline", "arflow", + "kiss-icp", ] [categories.setup] diff --git a/examples/python/kiss-icp/README.md b/examples/python/kiss-icp/README.md new file mode 100644 index 000000000000..1a425669655e --- /dev/null +++ b/examples/python/kiss-icp/README.md @@ -0,0 +1,42 @@ + + +Estimating the odometry is a common problem in robotics and in the [2023, "KISS-ICP: In Defense of Point-to-Point ICP -- Simple, Accurate, and Robust Registration If Done the Right Way" Ignacio Vizzo et al.](https://arxiv.org/abs/2209.15397) they show how one can use an ICP (iterative closest point) algorithm to robustly and accurately estimate poses from LiDAR data. We will demonstrate the KISS-ICP pipeline on the [NCLT dataset](http://robots.engin.umich.edu/nclt/) along with some brief explanations, for a more detailed explanation you should look at the [original paper](https://arxiv.org/abs/2209.15397). + + + + + + + + + +The KISS-ICP odometry pipeline consists of 4 steps. The first step is to compensate for movement of the vehicle during the LiDAR scan which is commonly called deskewing. This is done by creating an estimate of the rotational and translational velocity from previous pose estimates, then calculate the corrected scan under the assumption that the velocity is constant. In the screenshot below the raw scan is shown as green and the corrected scan is shown as the blue. + + + + + + + + + +The second step is to subsample the deskewed point cloud at two different resolutions. The first subsample with the highest resolution iis used to update the map after the pose has been estimated. The second is a subsample of the first subsample but with a lower resolution, this subsample is used during the ICP registration step. In the screenshot below the first subsample is colored pink and the second subsample is colored purple. + + + + + + + + + +The third step is to compute the adaptive threshold which will impose a limit on the distance between correspondences during the ICP. This is done using previously estimated poses to compute a likely limit of the displacement. The final step is to estimate the current pose by doing Point-to-Point ICP. This involves comparing each point in the subsampled scan with the closest point in the constructed map and making incremental updates to the estimated odometry based on these correspondences. + +https://vimeo.com/923395317?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=1920:1080 From a5df6910ca72707d4c6c7f0b3bbeeafa37358ddb Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 4 Apr 2024 11:25:47 +0200 Subject: [PATCH 175/508] Update h2 to 0.3.26 to address RUSTSEC-2024-0332 (#5775) ### What addresses ``` = ID: RUSTSEC-2024-0332 = Advisory: https://rustsec.org/advisories/RUSTSEC-2024-0332 = An attacker can send a flood of CONTINUATION frames, causing `h2` to process them indefinitely. This results in an increase in CPU usage. Tokio task budget helps prevent this from a complete denial-of-service, as the server can still respond to legitimate requests, albeit with increased latency. More details at "https://seanmonstar.com/blog/hyper-http2-continuation-flood/. ``` as flagged by cargo deny ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5775) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5775?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5775?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5775) - [Docs preview](https://rerun.io/preview/d0991aacd4ca9b0e4459d677f90aea68ca39fa33/docs) - [Examples preview](https://rerun.io/preview/d0991aacd4ca9b0e4459d677f90aea68ca39fa33/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e39c15ad4194..5c82c2ac9133 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2381,9 +2381,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", From 0d145ebecfa2a9422b59a4d4c942a67e26d963ba Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 4 Apr 2024 05:34:59 -0400 Subject: [PATCH 176/508] Reorganize getting-started and blueprint tutorials (#5762) ### What Strips out some gratuitous hierarchy. Moves the blueprint guides into getting-started. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5762) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5762?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5762?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5762) - [Docs preview](https://rerun.io/preview/214057272e4b01359946488cd8227e689e94fd70/docs) - [Examples preview](https://rerun.io/preview/214057272e4b01359946488cd8227e689e94fd70/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Antoine Beyeler <49431240+abey79@users.noreply.github.com> --- docs/content/concepts/blueprint.md | 92 ++++++++ .../content/concepts/spaces-and-transforms.md | 52 ++--- .../configure-the-viewer.md | 6 +- .../configure-the-viewer/interactively.md | 158 +++++++++++++ .../navigating-the-viewer-continued.md | 119 ++++++++++ .../configure-the-viewer/save-and-load.md | 2 +- .../through-code-tutorial.md} | 4 +- docs/content/getting-started/data-in.md | 10 +- .../data-in/{streaming => }/cpp.md | 68 +++--- .../getting-started/data-in/open-any-file.md | 66 +----- .../data-in/{streaming => }/python.md | 63 ++--- .../data-in/{streaming => }/rust.md | 68 +++--- .../getting-started/data-in/streaming.md | 10 - ...alkthrough.md => navigating-the-viewer.md} | 217 ++++++------------ .../getting-started/quick-start/cpp.md | 21 +- .../getting-started/quick-start/python.md | 42 ++-- .../getting-started/quick-start/rust.md | 22 +- docs/content/getting-started/visualize.md | 5 - .../add-support-for-arbitrary-file-types.md | 48 ++++ .../configure-the-viewer/interactively.md | 85 ------- ...de.md => configure-viewer-through-code.md} | 19 +- docs/content/howto/ros2-nav-turtlebot.md | 66 ++++-- 22 files changed, 754 insertions(+), 489 deletions(-) create mode 100644 docs/content/concepts/blueprint.md rename docs/content/{howto => getting-started}/configure-the-viewer.md (86%) create mode 100644 docs/content/getting-started/configure-the-viewer/interactively.md create mode 100644 docs/content/getting-started/configure-the-viewer/navigating-the-viewer-continued.md rename docs/content/{howto => getting-started}/configure-the-viewer/save-and-load.md (98%) rename docs/content/{howto/configure-the-viewer/blueprint-api-tutorial.md => getting-started/configure-the-viewer/through-code-tutorial.md} (99%) rename docs/content/getting-started/data-in/{streaming => }/cpp.md (86%) rename docs/content/getting-started/data-in/{streaming => }/python.md (87%) rename docs/content/getting-started/data-in/{streaming => }/rust.md (84%) delete mode 100644 docs/content/getting-started/data-in/streaming.md rename docs/content/getting-started/{visualize/viewer-walkthrough.md => navigating-the-viewer.md} (55%) delete mode 100644 docs/content/getting-started/visualize.md create mode 100644 docs/content/howto/add-support-for-arbitrary-file-types.md delete mode 100644 docs/content/howto/configure-the-viewer/interactively.md rename docs/content/howto/{configure-the-viewer/through-code.md => configure-viewer-through-code.md} (91%) diff --git a/docs/content/concepts/blueprint.md b/docs/content/concepts/blueprint.md new file mode 100644 index 000000000000..28189066c555 --- /dev/null +++ b/docs/content/concepts/blueprint.md @@ -0,0 +1,92 @@ +--- +title: Blueprint +order: 9 +--- + +## Blueprints and Recordings + +When you are working with the Rerun viewer, there are two separate pieces that +combine to produce what you see: the "recording" and the "blueprint." + +- The recording provides the actual data you are visualizing. +- The blueprint is the configuration that determines how the data from the + recording is displayed. + +Both of these pieces are crucial -- without the recording there is nothing to +show, and without the blueprint there is no way to show it. Even if you have +used Rerun before without explicitly loading a blueprint, the viewer was +actually creating one for you. Without a blueprint, there is literally nothing +for the viewer to display. + +## Loose coupling + +The blueprint and the recording are only loosely coupled. Rerun uses the +"application ID" to determine whether a blueprint and a recording should be used +together, but they are not directly linked beyond that. + +This means that either can be changed independently of the other. Keeping the +blueprint constant while changing the recording will allow you to compare +different datasets using a consistent set of views. On the other hand, changing +the blueprint while keeping a recording constant will allow you to view the same +data in different ways. + +## What the blueprint controls + +Every aspect of what the viewer displays is controlled by the blueprint. This +includes the type and content of the different views, the organization and +layout of the different containers, and the configuration and styling properties +of the individual data visualizers. + +In general, if you can modify an aspect of how something looks through the +viewer, you are actually modifying the blueprint. (Note that while there may be +some exceptions to this rule at the moment, the intent is to eventually migrate +all state to the blueprint.) + +## What is a blueprint + +Under the hood, the blueprint is just data. It is represented by a +[time-series ECS](./entity-component.md), just like a recording. The only +difference is that it uses a specific set of blueprint archetypes and a special +blueprint timeline. Note that even though the blueprint may be sent over the +same connection, blueprint data is kept in an isolated store and is not mixed +together with your recording data. + +Although the Rerun APIs for working with blueprint may look different from the +regular logging APIs, they are really just syntactic sugar for logging a +collection of blueprint-specific archetypes to a separate blueprint stream. + +Furthermore, when you make any change to the viewer in the UI, what is actually +happening is the viewer is creating a new blueprint event and adding it to the +end of the blueprint timeline in the blueprint store. + +## Viewer operation + +Outside of caching that exists primarily for performance reasons, the viewer +persists very little state frame-to-frame. The goal is for the output of the +viewer to be a deterministic function of the blueprint and the recording. + +Every frame, the viewer starts with a minimal context of an "active" blueprint, +and an "active" recording. The viewer then uses the current revision on the +blueprint timeline to query the container and space-view archetypes from the +blueprint store. The space-view archetypes, in turn, specify the paths types +that need to be queried from the recording store in order to render the views. + +Any user interactions that modify the blueprint are queued and written back to +the blueprint using the next revision on the blueprint timeline. + +## Blueprint architecture motivation + +Although this architecture adds some complexity and indirection, the fact that +the viewer stores all of its meaningful frame-to-frame state in a structured +blueprint data-store has several advantages: + +- Anything you modify in the viewer can be saved and shared as a blueprint. +- A blueprint can be produced programmatically using just the Rerun SDK without + a dependency on the viewer libraries. +- The blueprint is capable of representing any data that a recording can + represent. This means in the future, blueprint-sourced data overrides will + be just as expressive as any logged data. +- The blueprint is actually stored as a full time-series, simplifying future + implementations of things like snapshots and undo/redo mechanisms. +- Debugging tools for inspecting generic Rerun data can be used to inspect + internal blueprint state. diff --git a/docs/content/concepts/spaces-and-transforms.md b/docs/content/concepts/spaces-and-transforms.md index 1f6fadf807af..0048c9f7b5a8 100644 --- a/docs/content/concepts/spaces-and-transforms.md +++ b/docs/content/concepts/spaces-and-transforms.md @@ -3,22 +3,23 @@ title: Spaces and Transforms order: 2 --- -## The Definition of Spaces +## The definition of a space -Every Entity in Rerun exists in some *space*. This is at the core of how Rerun organizes the visualizations of the data -that you have logged. In the [Rerun Viewer](../reference/viewer.md) you view data by configuring a *space view*, which is a view -of a set of entities *as seen from a particular space.* +Every entity in Rerun exists in some _space_. This is at the core of how Rerun organizes the visualizations of the data +that you have logged. In the [Rerun Viewer](../reference/viewer.md) you view data by configuring a _space view_, which is a view +of a set of entities _as seen from a particular origin._ -A space is, very loosely, a generalization of the idea of a "coordinate system" (sometimes known as a "coordinate frame") to arbitrary data. If a collection of -entities are part of the same space, it means they can be rendered together in the same "coordinate system". +The origin of a space is, very loosely, a generalization of the idea of a "coordinate system" (sometimes known as a "coordinate frame") to arbitrary data. If a collection of +entities are part of the same space, it means they can be rendered together. -For examples: -- For 2D and 3D geometric primitives this means they share the same origin and coordinate system. -- For scalar plots it means they share the same plot axes. -- For text logs, it means they share the same conceptual stream. +For example: -As explained bellow, a space view *may* display data belonging to multiple spaces, but its coordinate system is defined -by a specific space, and the other spaces must have well-defined transforms to that space to be displayed in the same view. +- For 2D and 3D geometric primitives this means they share the same coordinate system. +- For scalar plots it means they share the same plot axes. +- For text logs, it means they share the same conceptual stream. + +As explained below, a space view _may_ display data belonging to multiple spaces, but there must be a well-defined +means of transforming the data from one space to another. Which entities belong to which spaces is a function of the transform system, which uses the following rules to define the space connectivity: @@ -26,9 +27,9 @@ the space connectivity: 1. Every unique entity path defines a potentially unique space. 1. Unless otherwise specified, every path is trivially connected to its parent by the identity transform. 1. Logging a transform to a path defines the relationship between that path and its parent (replacing the identity - connection). + connection). 1. Only paths which are connected by the identity transform are effectively considered to be part of the same - space. All others are considered to be disjoint. + space. All others are considered to be disjoint. Note that in the absence of transforms, all entity paths are fully connected by the identity transform, and therefore share the same space. However, as soon as you begin to log transforms, you can end up with additional spaces. @@ -43,10 +44,10 @@ rr.log("world/robot", rr.Transforms3D(…)) There are 4 parent/child entity relationships represented in this hierarchy. -- `(root)` -> `world` -- `world` -> `world/mapped_keypoints` -- `world` -> `world/robot` -- `world/robot` -> `world/robot/observed_features` +- `(root)` -> `world` +- `world` -> `world/mapped_keypoints` +- `world` -> `world/robot` +- `world/robot` -> `world/robot/observed_features` The call: `rr.log("world/robot", rr.Transforms3D(…))` only applies to the relationship: `world` -> `world/robot` because the logged transform (`world/robot`) describes the relationship between the entity and its _parent_ (`world`). All other @@ -60,7 +61,6 @@ from `world/robot/observed_features` are not directly comparable. If you were to coordinate system the results would be meaningless. As noted above, Rerun can still display these entities in the same space view because it is able to automatically transform data between different spaces. - ## Space Transformations In order to correctly display data from different spaces in the same view, Rerun uses the information from logged @@ -71,15 +71,15 @@ of transformations to the component data when building the scene. Rerun transforms are currently limited to connections between _spatial_ views of 2D or 3D data. There are 3 types of transforms that can be logged: -- Affine 3D transforms, which can define any combination of translation, rotation, and scale relationship between two paths (see - [`rr.Transform3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Transform3D)). -- Pinhole transforms define a 3D -> 2D camera projection (see - [`rr.Pinhole`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Pinhole)). -- A disconnected space specifies that the data cannot be transformed (see [`rr.DisconnectedSpace`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.DisconnectedSpace)). In this case it will not be possible to combine the data into a single view, and you will need to create two separate views to explore the data. +- Affine 3D transforms, which can define any combination of translation, rotation, and scale relationship between two paths (see + [`rr.Transform3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Transform3D)). +- Pinhole transforms define a 3D -> 2D camera projection (see + [`rr.Pinhole`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Pinhole)). +- A disconnected space specifies that the data cannot be transformed (see [`rr.DisconnectedSpace`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.DisconnectedSpace)). In this case it will not be possible to combine the data into a single view, and you will need to create two separate views to explore the data. In the future, Rerun will be adding support for additional types of transforms. - - [#349: Log 2D -> 2D transformations in the transform hierarchy](https://github.com/rerun-io/rerun/issues/349) +- [#349: Log 2D -> 2D transformations in the transform hierarchy](https://github.com/rerun-io/rerun/issues/349) ## Examples @@ -106,8 +106,8 @@ Rerun will from this understand how the `world` space and the two image spaces ( Note that none of the names in the paths are special. - ## View coordinates + You can use [`rr.ViewCoordinates`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.ViewCoordinates) to set your preferred view coordinate systems, giving semantic meaning to the XYZ axes of the space. For 3D spaces it can be used to log what the up-axis is in your coordinate system. This will help Rerun set a good default view of your 3D scene, as well as make the virtual eye interactions more natural. This can be done with `rr.log("world", rr.ViewCoordinates(up="+Z"), timeless=True)`. diff --git a/docs/content/howto/configure-the-viewer.md b/docs/content/getting-started/configure-the-viewer.md similarity index 86% rename from docs/content/howto/configure-the-viewer.md rename to docs/content/getting-started/configure-the-viewer.md index d345a881ef1d..2d47dd5bb0c6 100644 --- a/docs/content/howto/configure-the-viewer.md +++ b/docs/content/getting-started/configure-the-viewer.md @@ -1,6 +1,6 @@ --- title: Configure the Viewer -order: 10 +order: 5 --- Although the Rerun Viewer tries to do a reasonable job of using heuristics to automatically determine @@ -20,6 +20,4 @@ There are a few different ways to work with Blueprints: - [Blueprints can be modified interactively](./configure-the-viewer/interactively.md) - [Blueprint files (.rbl) can be saved and loaded from disk](./configure-the-viewer/save-and-load.md) -- [Blueprints can be controlled directly from code](./configure-the-viewer/through-code.md) - -For a hands on example, you can also follow the [Blueprint API Tutorial](./configure-the-viewer/blueprint-api-tutorial.md). +- [Blueprints can be controlled directly from code](./configure-the-viewer/through-code-tutorial.md) diff --git a/docs/content/getting-started/configure-the-viewer/interactively.md b/docs/content/getting-started/configure-the-viewer/interactively.md new file mode 100644 index 000000000000..e4cab20edd57 --- /dev/null +++ b/docs/content/getting-started/configure-the-viewer/interactively.md @@ -0,0 +1,158 @@ +--- +title: Configure the viewer interactively +order: 1 +--- + +The Rerun Viewer is configurable directly through the UI itself. + +## Viewer overview + + + + + + + + + + +The central part is known as the viewport and contains the various views displaying the data. + +The left panel of the viewer is the "Blueprint Panel". It shows a visual tree view representing +the contents of the current blueprint. + +The right panel of the viewer is the "Selection Panel" this panel allows you to configure +specific blueprint properties of the currently selected element. + +The blueprint defines the structure, the type of views, and their content in the viewport. Changing the content of the viewport is done by editing the blueprint. + +After editing the viewer you may want to [save or share the blueprint](./save-and-load.md). + +## Configuring the view hierarchy + +The viewport is made of various views, laid out hierarchically with nested containers of various kinds: vertical, horizontal, grid, and tabs. This hierarchy is represented in the blueprint panel, with the top container corresponding to the viewport. In this section, we cover the various ways this view hierarchy can be interactively created and modified. + +### Show or hide parts of the blueprint + +Any container or view can be hidden or shown by clicking the "eye" icon. + + + + + + +### Add new Containers or Views + +Adding a container or a view to the view port can be done by clicking the "+" at the top of the blueprint panel. + + + + + + +If a container (or the viewport) is already selected, a "+" button will also be available in the selection panel. + + + + + + + +### Remove a View or Container + +Removing a view or a container can be done by clicking the "-" button next to it: + + + + + + +### Re-arrange existing Containers or Views + +The viewport hierarchy can be reorganized by drag-and-dropping containers or views in the blueprint panel. It ssi also possible to drag views directly in the viewport by using their title tab: + + + + + + + +### Rename a View or Container + +Both views and containers may be assigned a custom name. This can be done by selecting the view or container, and editing the name at the top of the selection panel. + + + + + +### Change a Container kind + +Containers come in four different kinds: vertical, horizontal, grid, and tabs. To change an existing container's kind, select it and change the value from the dropdown menu in the selection panel: + + + + + + + +### Using context menus + +The context menu is accessed by right-clicking on a container or view in the blueprint panel. Many of the previous operations are also available there: + + + + + + +One key advantage of using the context menu is that it enable operations on multiple items at once. For example, you may select several views (ctrl-click, or cmd-click on Mac), and remove them all in a single operation using the context menu. + + +## Configuring the content of a view + +The content of a view is determined by its entity query, which can be manually edited in the selection panel when the view is selected (see [Entity Queries](../../reference/entity-queries.md) for more information). This section covers the interactive means of manipulating the view content (which typically operate by actually modifying the query). + + +### Show or hide view content + +Like containers and views, any entity in a view may be shown and hidden with the "eye" icon or the context menu. + + + + + + +### Remove Data from a View + +Likewise, entities may be removed from a view by clicking the "-" next to it: + + + + + + +### Using the query editor + +A visual query editor is available from the selection panel when a view is selected. Click the "Edit" button next to the entity query: + + + + + + +The query editor allows visually adding and removing entities and entity trees from the query. + +### Adding entities to a new view with context menu + +Like with viewport hierarchy, most operations on view data are available from the context menu. In particular, a new view can be created with custom content by selecting one or more entities (either in existing views in the blueprint panel, or in the time panel's streams), and clicking "Add to new space view" in the context menu: + + + + + + + + +When using one of the recommended views with this method, the view's origin will automatically be set to a sensible default based on the actual data. + + + diff --git a/docs/content/getting-started/configure-the-viewer/navigating-the-viewer-continued.md b/docs/content/getting-started/configure-the-viewer/navigating-the-viewer-continued.md new file mode 100644 index 000000000000..91c60cb97ce7 --- /dev/null +++ b/docs/content/getting-started/configure-the-viewer/navigating-the-viewer-continued.md @@ -0,0 +1,119 @@ +--- +title: Navigating the viewer (continued) +order: 4 +--- + +This guide builds on top of the previous tutorial: +[Navigating the viewer](../navigating-the-viewer.md). Please follow that tutorial first if you haven't already. + +This guide will familiarize you with the basics of using the Rerun Viewer with an example dataset. By the end you should +be comfortable with the following topics: + +- [Configuring views](#configuring-views) +- [Creating new views](#creating-new-views) + +## Configuring views + +Views in Rerun are configured by [Blueprints](../../reference/viewer/blueprint.md). We will now use blueprints to adjust +both an individual entity as well as the contents of a space view itself. + +### Adjusting entity properties + +First, click to select the entity named `points` in the `/ (Spatial)` view in the Blueprint panel. Now, look and the +selection panel -- in addition to the information about the data associated with that entity, you will see a "Blueprint" +section. + +Try toggling "visible" on and off and you will see that the points disappear and reappear. Next, click the control +labeled "visible history" and drag it to the right to increase the value. As you drag farther you will see more points +show up in the view. This is making historical points, from farther back in time visible within the time point of this +view. Because the points are logged in stationary 3D space, aggregating them here gives us a more complete view of the +car. Leave the visible history with a value of 50. + + + + + + + viewer walkthrough adjusting visible history screenshot + + +### Modifying the contents of a space view + +Now select the `/ (Spatial)` view itself. We will start by giving this space view a different name. At the very +top of the selection panel you will see a text box labeled "Space view:". Go ahead and change the name to +`Reconstruction`. The name will also update in the blueprint panel on the left. + +Like with the entity selection, you will see a Blueprint section within the Selection panel. This time, click on the +button labeled "Add/Remove Entities". This pop-up shows all of the entities that were logged as part of this session. +You can click on the "+" or "-" buttons to add or remove entities from this view. Go ahead and remove the entity called +"keypoints," and then add them back again. Unlike hiding an entity, you will notice that as you remove entities they +completely disappear from the blueprint panel on the left. Entities that are incompatible with the selected view will be +grayed out. For example, you cannot add a scalar to a spatial scene. + + + + + + + viewer walkthrough modifying contents of a space view screenshot + + +## Creating new views + +New views & view containers (grid, vertical, etc.) can be created using the "+" button at the top of the Blueprint panel or +from the selection panel when selecting a container. + +After creating a view you usually want to proceed to editing its origin and query (which entities are shown) in the selection panel. + +Your view layout might be feeling a little cluttered now. You can quickly hide views you're +not using from the blueprint panel by hovering over the view and then clicking the icon that looks like an eye. Go ahead +and hide the `image` and `avg_reproj_err` views, and collapse the expanded timeline panel using the button in the upper +right corner. Note that even with the timeline collapsed you still have access to timeline controls, including a slider. + + + + + + + viewer walkthrough toggle visibility screenshot + + +### Reusing what you've learned + +Finally, use what we covered in the previous section to change the contents of this view. Select the new `camera` view, +then choose "Add/remove entities." Remove the 2D "keypoints" and add in the 3D "points." Note that these points do not +have visible history turned on -- that's because the blueprint is part of the view and not part of the entity. +Select the points within this view by clicking on them in the blueprint or the view itself, and then give them visible +history as well. When you are done, your view should look like this: + + + + + + + viewer walkthrough camera view screenshot + + +Now move the slider back and forth and see what happens. Even though they are both views of the same camera and point +entities, they behave quite differently. On the top the camera moves relative to the car, while on the bottom the car +moves relative to the camera. This is because the new views have _different_ space roots, and Rerun uses the transform +system to transform or project all data into the space root for the given view. + +## Conclusion + +That brings us to the end of this walkthrough. To recap, you have learned how to: + +- Configure entity blueprint properties. +- Add and remove entities from views. +- Create and configure new views. +- And some basics of how transforms work. + +Again, if you ran into any issues following this guide, please don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). + +### Up next + +To get started with writing a program to logging data with the Rerun SDK see the [getting started guides](../quick-start). + +To see and explore other data, you can check out the [examples](/examples). + +For deeper context on the ideas covered here, consult the [Concept overview](../../concepts.md). diff --git a/docs/content/howto/configure-the-viewer/save-and-load.md b/docs/content/getting-started/configure-the-viewer/save-and-load.md similarity index 98% rename from docs/content/howto/configure-the-viewer/save-and-load.md rename to docs/content/getting-started/configure-the-viewer/save-and-load.md index ab8aa010b1a5..015800aa8c53 100644 --- a/docs/content/howto/configure-the-viewer/save-and-load.md +++ b/docs/content/getting-started/configure-the-viewer/save-and-load.md @@ -1,6 +1,6 @@ --- title: Save and load viewer configuration files -order: 1 +order: 2 --- If you have made changes to your blueprint and you would like to save or share these changes, diff --git a/docs/content/howto/configure-the-viewer/blueprint-api-tutorial.md b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md similarity index 99% rename from docs/content/howto/configure-the-viewer/blueprint-api-tutorial.md rename to docs/content/getting-started/configure-the-viewer/through-code-tutorial.md index bbc9ec4c52cc..848655738d6e 100644 --- a/docs/content/howto/configure-the-viewer/blueprint-api-tutorial.md +++ b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md @@ -1,6 +1,6 @@ --- -title: Blueprint API Tutorial -order: 4 +title: Configure the viewer through code +order: 3 --- This tutorial will walk you through using the Blueprint APIs to better control the diff --git a/docs/content/getting-started/data-in.md b/docs/content/getting-started/data-in.md index 0f59e61801b0..a7ea02f8b6ed 100644 --- a/docs/content/getting-started/data-in.md +++ b/docs/content/getting-started/data-in.md @@ -5,8 +5,8 @@ order: 3 This section talks about how to get data out of your application into Rerun. -* Streaming data from your code - * [C++](./data-in/streaming/cpp.md) - * [Python](./data-in/streaming/python.md) - * [Rust](./data-in/streaming/rust.md) -* [Opening files](./data-in/open-any-file.md) +- Streaming data from your code + - [C++](./data-in/cpp.md) + - [Python](./data-in/python.md) + - [Rust](./data-in/rust.md) +- [Opening files](./data-in/open-any-file.md) diff --git a/docs/content/getting-started/data-in/streaming/cpp.md b/docs/content/getting-started/data-in/cpp.md similarity index 86% rename from docs/content/getting-started/data-in/streaming/cpp.md rename to docs/content/getting-started/data-in/cpp.md index 06a9b47ea198..4e7364336b9a 100644 --- a/docs/content/getting-started/data-in/streaming/cpp.md +++ b/docs/content/getting-started/data-in/cpp.md @@ -1,13 +1,14 @@ --- -title: C++ -order: 5 +title: Stream from C++ +order: 1 --- In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. @@ -23,24 +24,25 @@ cmake --build build -j ``` And then to run it on Linux/Mac: + ``` ./build/example_dna ``` + and windows respectively: + ``` build\Debug\example_dna.exe ``` - ## Prerequisites -You should have already [installed the viewer](../../installing-viewer.md). +You should have already [installed the viewer](../installing-viewer.md). We assume you have a working C++ toolchain and are using `CMake` to build your project. For this example we will let Rerun download build [Apache Arrow](https://arrow.apache.org/)'s C++ library itself. To learn more about how Rerun's CMake script can be configured, see [CMake Setup in Detail](https://ref.rerun.io/docs/cpp/stable/md__2home_2runner_2work_2rerun_2rerun_2rerun__cpp_2cmake__setup__in__detail.html) in the C++ reference documentation. - ## Setting up your CMakeLists.txt A minimal CMakeLists.txt for this example looks like this: @@ -69,6 +71,7 @@ target_link_libraries(example_dna PRIVATE rerun_sdk) To use Rerun all you need to include is `rerun.hpp`, however for this example we will pull in a few extra headers. Starting our `main.cpp`: + ```cpp #include #include @@ -92,6 +95,7 @@ by setting it's `ApplicationId`. We then use the stream to spawn a new rerun viewer via [`spawn`](https://github.com/rerun-io/rerun/blob/d962b34b07775bbacf14883d683cca6746852b6a/rerun_cpp/src/rerun/recording_stream.hpp#L151). Add our initial `main` to `main.cpp`: + ```cpp int main() { auto rec = rerun::RecordingStream("rerun_example_dna_abacus"); @@ -99,9 +103,9 @@ int main() { } ``` -Among other things, a stable `ApplicationId` will make it so the [Rerun Viewer](../../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. +Among other things, a stable `ApplicationId` will make it so the [Rerun Viewer](../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. -Check out the reference to learn more about how Rerun deals with [applications and recordings](../../../concepts/apps-and-recordings.md). +Check out the reference to learn more about how Rerun deals with [applications and recordings](../../concepts/apps-and-recordings.md). ## Testing our app @@ -115,7 +119,8 @@ cmake --build build -j When everything finishes compiling, an empty Rerun viewer should be spawned: - + + @@ -128,6 +133,7 @@ Now let's add some data to the viewer. The core structure of our DNA looking shape can easily be described using two point clouds shaped like spirals. Add the following to your `main` function: + ```cpp std::vector points1, points2; std::vector colors1, colors2; @@ -145,10 +151,12 @@ rec.log( ``` Re-compile and run your program again: + ```bash cmake --build build -j ./build/example_dna ``` + and now you should now see this scene in the viewer: @@ -160,7 +168,7 @@ and now you should now see this scene in the viewer: _This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ -_Checkout the [Viewer Walkthrough](../../visualize/viewer-walkthrough.md) and [viewer reference](../../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ +_Checkout the [Viewer Walkthrough](../navigating-the-viewer.md) and [viewer reference](../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood @@ -172,28 +180,28 @@ The easiest way to log geometric primitives is the use the [`RecordingStream::lo ### Components -Under the hood, the Rerun C++ SDK logs individual *components* like positions, colors, +Under the hood, the Rerun C++ SDK logs individual _components_ like positions, colors, and radii. Archetypes are just one high-level, convenient way of building such collections of components. For advanced use cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. -For more information on how the rerun data model works, refer to our section on [Entities and Components](../../../concepts/entity-component.md). +For more information on how the rerun data model works, refer to our section on [Entities and Components](../../concepts/entity-component.md). Notably, the [`RecordingStream::log`](https://github.com/rerun-io/rerun/blob/d962b34b07775bbacf14883d683cca6746852b6a/rerun_cpp/src/rerun/recording_stream.hpp#L236) method will handle any data type that implements the [`AsComponents`](https://github.com/rerun-io/rerun/blob/latest/rerun_cpp/src/rerun/as_components.hpp) trait, making it easy to add your own data. -For more information on how to supply your own components see [Use custom data](../../../howto/extend/custom-data.md). +For more information on how to supply your own components see [Use custom data](../../howto/extend/custom-data.md). ### Entities & hierarchies Note the two strings we're passing in: `"dna/structure/left"` and `"dna/structure/right"`. -These are [*entity paths*](../../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. -[Entity paths typically form a hierarchy](../../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). +These are [_entity paths_](../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. +[Entity paths typically form a hierarchy](../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Batches One final observation: notice how we're logging a whole batch of points and colors all at once here. -[Batches of data](../../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. -You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this *splatting*. +[Batches of data](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. +You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _splatting_. --- @@ -203,6 +211,7 @@ Good news is: once you've digested all of the above, logging any other Entity wi ## Adding the missing pieces We can represent the scaffolding using a batch of 3D line segments: + ```cpp std::vector lines; for (size_t i = 0; i < points1.size(); ++i) { @@ -216,6 +225,7 @@ rec.log( ``` Which only leaves the beads: + ```cpp std::default_random_engine gen; std::uniform_real_distribution dist(0.0f, 1.0f); @@ -253,14 +263,13 @@ Once again, although we are getting fancier and fancier with our iterator mappin - ## Animating the beads ### Introducing Time -Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../../concepts/timelines.md). +Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). -Even so, if you look at your [Timeline View](../../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. +Even so, if you look at your [Timeline View](../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. @@ -278,6 +287,7 @@ Rerun has rich support for time: whether you want concurrent or disjoint timelin Let's add our custom timeline. Replace the section that logs the beads with a loop that logs the beads at different timestamps: + ```cpp for (int t = 0; t < 400; t++) { auto time = std::chrono::duration(t) * 0.01f; @@ -306,7 +316,7 @@ for (int t = 0; t < 400; t++) { First we use [`RecordingStream::set_time_seconds`](https://github.com/rerun-io/rerun/blob/d962b34b07775bbacf14883d683cca6746852b6a/rerun_cpp/src/rerun/recording_stream.hpp#L192) to declare our own custom `Timeline` and set the current timestamp. You can add as many timelines and timestamps as you want when logging data. -⚠️ If you run this code as is, the result will be.. surprising: the beads are animating as expected, but everything we've logged until that point is gone! ⚠️ +⚠️ If you run this code as is, the result will be.. surprising: the beads are animating as expected, but everything we've logged until that point is gone! ⚠️ ![logging data - wat](https://static.rerun.io/a396c8aae1cbd717a3f35472594f789e4829b1ae_logging_data7_wat.png) @@ -314,8 +324,9 @@ Enter… ### Latest At semantics -That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the *default* timeline (called `log_time`). -To fix this, go back to the top of your main and initialize your timeline before logging the initial structure: +That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). +To fix this, go back to the top of your main and initialize your timeline before logging the initial structure: + ```cpp rec.set_time_seconds("stable_time", 0.0f); @@ -351,6 +362,7 @@ Now it's just a matter of combining the two: we need to log the transform of the Either expand the previous loop to include logging transforms or simply add a second loop like this: + ```cpp for (int t = 0; t < 400; t++) { float time = static_cast(t) * 0.01f; @@ -371,7 +383,6 @@ Voila! - ## Other ways of logging & visualizing data ### Saving & loading to/from RRD files @@ -379,15 +390,16 @@ Voila! Sometimes, sending the data over the network is not an option. Maybe you'd like to share the data, attach it to a bug report, etc. Rerun has you covered: -- Use [`RecordingStream::save`](https://github.com/rerun-io/rerun/blob/d962b34b07775bbacf14883d683cca6746852b6a/rerun_cpp/src/rerun/recording_stream.hpp#L162) to stream all logging data to disk. -- Visualize it via `rerun path/to/recording.rrd` + +- Use [`RecordingStream::save`](https://github.com/rerun-io/rerun/blob/d962b34b07775bbacf14883d683cca6746852b6a/rerun_cpp/src/rerun/recording_stream.hpp#L162) to stream all logging data to disk. +- Visualize it via `rerun path/to/recording.rrd` You can also save a recording (or a portion of it) as you're visualizing it, directly from the viewer. -⚠️ [RRD files don't yet handle versioning!](https://github.com/rerun-io/rerun/issues/873) ⚠️ +⚠️ [RRD files don't yet handle versioning!](https://github.com/rerun-io/rerun/issues/873) ⚠️ ### Closing This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. -As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../../reference/types.md) section for more simple examples of how to use the main data types. +As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main data types. diff --git a/docs/content/getting-started/data-in/open-any-file.md b/docs/content/getting-started/data-in/open-any-file.md index 3d0755b0a043..c80c94d455b4 100644 --- a/docs/content/getting-started/data-in/open-any-file.md +++ b/docs/content/getting-started/data-in/open-any-file.md @@ -1,25 +1,27 @@ --- title: Opening files -order: 1 +order: 4 --- The Rerun Viewer and SDK have built-in support for opening many kinds of files, and can be extended to support any other file type without needing to modify the Rerun codebase itself. The Viewer can load files in 3 different ways: -- via CLI arguments (e.g. `rerun myfile.jpeg`), -- using drag-and-drop, -- using the open dialog in the Rerun Viewer. + +- via CLI arguments (e.g. `rerun myfile.jpeg`), +- using drag-and-drop, +- using the open dialog in the Rerun Viewer. All these file loading methods support loading a single file, many files at once (e.g. `rerun myfiles/*`), or even folders. ⚠ Drag-and-drop of folders does [not yet work](https://github.com/rerun-io/rerun/issues/4528) on the web version of the Rerun Viewer ⚠ The following file types have built-in support in the Rerun Viewer and SDK: -- Native Rerun files: `rrd` -- 3D models: `gltf`, `glb`, `obj`, `stl` -- Images: `avif`, `bmp`, `dds`, `exr`, `farbfeld`, `ff`, `gif`, `hdr`, `ico`, `jpeg`, `jpg`, `pam`, `pbm`, `pgm`, `png`, `ppm`, `tga`, `tif`, `tiff`, `webp`. -- Point clouds: `ply`. -- Text files: `md`, `txt`. + +- Native Rerun files: `rrd` +- 3D models: `gltf`, `glb`, `obj`, `stl` +- Images: `avif`, `bmp`, `dds`, `exr`, `farbfeld`, `ff`, `gif`, `hdr`, `ico`, `jpeg`, `jpg`, `pam`, `pbm`, `pgm`, `png`, `ppm`, `tga`, `tif`, `tiff`, `webp`. +- Point clouds: `ply`. +- Text files: `md`, `txt`. With the exception of `rrd` files that can be streamed from an HTTP URL (e.g. `rerun https://demo.rerun.io/version/latest/examples/dna/data.rrd`), we only support loading files from the local filesystem for now, with [plans to make this generic over any URI and protocol in the future](https://github.com/rerun-io/rerun/issues/4525). @@ -30,49 +32,3 @@ To log the contents of a file from the SDK you can use the `log_file_from_path` Note: when calling these APIs from the SDK, the data will be loaded by the process running the SDK, not the Viewer! snippet: log-file - -## Adding support for arbitrary filetypes - -Internally, the [`DataLoader`](https://docs.rs/re_data_source/latest/re_data_source/trait.DataLoader.html) trait takes care of loading files into the Viewer and/or SDK. - -There are 3 broad kinds of `DataLoader`s: _builtin_, _external_ and _custom_. -_External_ and _custom_ are the two ways of extending the file loading system that we'll describe below. - -When a user attempts to open a file in the Viewer/SDK, **all** known `DataLoader`s are notified of the path to be opened, unconditionally. -This gives `DataLoader`s maximum flexibility to decide what files they are interested in, as opposed to e.g. only being able to look at a file's extension. - -Once notified, a `DataLoader` can return a [`DataLoaderError::Incompatible`](https://docs.rs/re_data_source/latest/re_data_source/enum.DataLoaderError.html#variant.Incompatible) error to indicate that it doesn't support a given file type. -If, and only if, all loaders known to the Viewer/SDK return an `Incompatible` error code, then an error message is shown to the user indicating that this file type is not (_yet_) supported. - -In these instances of unsupported files, we expose two ways of implementing and registering your `DataLoader`s, explained below. - -### External data-loaders - -The easiest way to create your own `DataLoader` is by implementing what we call an "external loader": a stand alone executable written in any language that the Rerun SDK ships for. Any executable on your `$PATH` with a name that starts with `rerun-loader-` will be treated as a `DataLoader`. - -This executable takes a file path as a command line argument and outputs Rerun logs on `stdout`. -It will be called by the Rerun Viewer/SDK when the user opens a file, and be passed the path to that file. -From there, it can log data as usual, using the [`stdout` logging sink](../../reference/sdk-operating-modes.md#standard-inputoutput). - -The Rerun Viewer/SDK will then automatically load the data streamed to the external loader's standard output. - - - - - - - - - -Like any other `DataLoader`, an external loader will be notified of all file openings, unconditionally. -To indicate that it does not support a given file, the loader has to exit with a [dedicated status code](https://docs.rs/rerun/latest/rerun/constant.EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE.html). - -Check out our examples for [C++](https://github.com/rerun-io/rerun/tree/main/examples/cpp/external_data_loader), [Python](https://github.com/rerun-io/rerun/tree/main/examples/python/external_data_loader) and [Rust](https://github.com/rerun-io/rerun/tree/main/examples/rust/external_data_loader) that cover every steps in details. - -### Custom Rust data-loaders - -Another Rust-specific approach is to implement the `DataLoader` trait yourself and register it in the Rerun Viewer/SDK. - -To do so, you'll need to import `rerun` as a library, register your `DataLoader` and then start the Viewer/SDK from code. - -Check out our [example](https://github.com/rerun-io/rerun/tree/main/examples/rust/custom_data_loader) that cover all these steps in details. diff --git a/docs/content/getting-started/data-in/streaming/python.md b/docs/content/getting-started/data-in/python.md similarity index 87% rename from docs/content/getting-started/data-in/streaming/python.md rename to docs/content/getting-started/data-in/python.md index 19dc1ede4dcb..0ce5014ab85a 100644 --- a/docs/content/getting-started/data-in/streaming/python.md +++ b/docs/content/getting-started/data-in/python.md @@ -1,13 +1,14 @@ --- -title: Python -order: 6 +title: Stream from Python +order: 2 --- In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. @@ -17,7 +18,7 @@ At any time, you can checkout the complete code listing for this tutorial [here] ## Prerequisites -We assume you have working Python and `rerun-sdk` installations. If not, check out the [setup page](../../quick-start/python.md). +We assume you have working Python and `rerun-sdk` installations. If not, check out the [setup page](../quick-start/python.md). ## Initializing the SDK @@ -32,20 +33,22 @@ import rerun as rr rr.init("rerun_example_dna_abacus") ``` -Among other things, a stable [`ApplicationId`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init) will make it so the [Rerun Viewer](../../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. +Among other things, a stable [`ApplicationId`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init) will make it so the [Rerun Viewer](../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. -Check out the reference to learn more about how Rerun deals with [applications and recordings](../../../concepts/apps-and-recordings.md). +Check out the reference to learn more about how Rerun deals with [applications and recordings](../../concepts/apps-and-recordings.md). ## Starting the Viewer -Next up, we want to spawn the [Rerun Viewer](../../../reference/viewer/overview.md) itself. +Next up, we want to spawn the [Rerun Viewer](../../reference/viewer/overview.md) itself. To do this, you can add the line: + ```python rr.spawn() ``` Now you can run your application just as you would any other python script: + ``` (venv) $ python dna_example.py ``` @@ -64,14 +67,17 @@ By default, the SDK will start a viewer in another process and automatically pip There are other means of sending data to a viewer as we'll see at the end of this section, but for now this default will work great as we experiment. --- + The following sections will require importing a few different things to your script. We will do so incrementally, but if you just want to update your imports once and call it a day, feel free to add the following to the top of your script: + ```python from math import tau import numpy as np from rerun.utilities import build_color_spiral from rerun.utilities import bounce_lerp ``` + --- ## Logging our first points @@ -95,7 +101,7 @@ rr.log("dna/structure/right", rr.Points3D(points2, colors=colors2, radii=0.08)) ``` Run your script once again and you should now see this scene in the viewer. -Note that if the viewer was still running, Rerun will simply connect to this existing session and replace the data with this new [_recording_](../../../concepts/apps-and-recordings.md). +Note that if the viewer was still running, Rerun will simply connect to this existing session and replace the data with this new [_recording_](../../concepts/apps-and-recordings.md). @@ -105,10 +111,8 @@ Note that if the viewer was still running, Rerun will simply connect to this exi - - _This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ -_Checkout the [Viewer Walkthrough](../../visualize/viewer-walkthrough.md) and [viewer reference](../../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ +_Checkout the [Viewer Walkthrough](../navigating-the-viewer.md) and [viewer reference](../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood @@ -121,12 +125,12 @@ of components that are recognized and correctly displayed by the Rerun viewer. ### Components -Under the hood, the Rerun [Python SDK](https://ref.rerun.io/docs/python) logs individual *components* like positions, colors, +Under the hood, the Rerun [Python SDK](https://ref.rerun.io/docs/python) logs individual _components_ like positions, colors, and radii. Archetypes are just one high-level, convenient way of building such collections of components. For advanced use cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. -For more information on how the rerun data model works, refer to our section on [Entities and Components](../../../concepts/entity-component.md). +For more information on how the rerun data model works, refer to our section on [Entities and Components](../../concepts/entity-component.md). Our [Python SDK](https://ref.rerun.io/docs/python) integrates with the rest of the Python ecosystem: the points and colors returned by [`build_color_spiral`](https://ref.rerun.io/docs/python/stable/common/demo_utilities/#rerun.utilities.data.build_color_spiral) in this example are vanilla `numpy` arrays. Rerun takes care of mapping those arrays to actual Rerun components depending on the context (e.g. we're calling [`rr.Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points3D) in this case). @@ -135,14 +139,14 @@ Rerun takes care of mapping those arrays to actual Rerun components depending on Note the two strings we're passing in: `"dna/structure/left"` & `"dna/structure/right"`. -These are [*entity paths*](../../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. -[Entity paths typically form a hierarchy](../../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). +These are [_entity paths_](../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. +[Entity paths typically form a hierarchy](../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Batches One final observation: notice how we're logging a whole batch of points and colors all at once here. -[Batches of data](../../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. -You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this *splatting*. +[Batches of data](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. +You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _splatting_. --- @@ -152,6 +156,7 @@ Good news is: once you've digested all of the above, logging any other Entity wi ## Adding the missing pieces We can represent the scaffolding using a batch of 3D line strips: + ```python rr.log( "dna/structure/scaffolding", @@ -160,6 +165,7 @@ rr.log( ``` Which only leaves the beads: + ```python # new imports import numpy as np @@ -185,14 +191,13 @@ there is nothing new here: it's all about building out `numpy` arrays and feedin - ## Animating the beads ### Introducing Time -Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../../concepts/timelines.md). +Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). -Even so, if you look at your [Timeline View](../../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. +Even so, if you look at your [Timeline View](../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. @@ -202,13 +207,13 @@ Even so, if you look at your [Timeline View](../../../reference/viewer/timeline. screenshot of the beads with the timeline - Unfortunately, the logging time isn't particularly helpful to us in this case: we can't have our beads animate depending on the logging time, else they would move at different speeds depending on the performance of the logging process! For that, we need to introduce our own custom timeline that uses a deterministic clock which we control. Rerun has rich support for time: whether you want concurrent or disjoint timelines, out-of-order insertions or even data that lives _outside_ the timeline(s). You will find a lot of flexibility in there. Let's add our custom timeline: + ```python # new imports from rerun.utilities import bounce_lerp @@ -239,13 +244,13 @@ A call to [`set_time_seconds`](https://ref.rerun.io/docs/python/stable/common/lo screenshot of the surprising situation
- Enter… ### Latest At semantics -That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the *default* timeline (called `log_time`). +That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). To fix this, go back to the top of the file and add: + ```python rr.spawn() rr.set_time_seconds("stable_time", 0) @@ -259,7 +264,6 @@ rr.set_time_seconds("stable_time", 0) screenshot after using latest at
- This fix actually introduces yet another very important concept in Rerun: "latest at" semantics. Notice how entities `"dna/structure/left"` & `"dna/structure/right"` have only ever been logged at time zero, and yet they are still visible when querying times far beyond that point. @@ -274,6 +278,7 @@ Now it's just a matter of combining the two: we need to log the transform of the Either expand the previous loop to include logging transforms or simply add a second loop like this: + ```python for i in range(400): time = i * 0.01 @@ -290,7 +295,6 @@ Voila! - ## Other ways of logging & visualizing data [`rr.spawn`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.spawn) is great when you're experimenting on a single machine like we did in this tutorial, but what if the logging happens on, for example, a headless computer? @@ -310,15 +314,16 @@ Checkout `rerun --help` for more options. Sometimes, sending the data over the network is not an option. Maybe you'd like to share the data, attach it to a bug report, etc. Rerun has you covered: -- Use [`rr.save`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.save) to stream all logged data to disk. -- View it with `rerun path/to/recording.rrd` + +- Use [`rr.save`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.save) to stream all logged data to disk. +- View it with `rerun path/to/recording.rrd` You can also save a recording (or a portion of it) as you're visualizing it, directly from the viewer. -⚠️ [RRD files don't yet handle versioning!](https://github.com/rerun-io/rerun/issues/873) ⚠️ +⚠️ [RRD files don't yet handle versioning!](https://github.com/rerun-io/rerun/issues/873) ⚠️ ## Closing This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. -As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../../reference/types.md) section for more simple examples of how to use the main datatypes. +As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. diff --git a/docs/content/getting-started/data-in/streaming/rust.md b/docs/content/getting-started/data-in/rust.md similarity index 84% rename from docs/content/getting-started/data-in/streaming/rust.md rename to docs/content/getting-started/data-in/rust.md index 476da651f710..c0a9f780131b 100644 --- a/docs/content/getting-started/data-in/streaming/rust.md +++ b/docs/content/getting-started/data-in/rust.md @@ -1,13 +1,14 @@ --- -title: Rust -order: 7 +title: Stream from Rust +order: 3 --- In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. @@ -21,6 +22,7 @@ To run the example from the repository, run `cargo run -p dna`. We assume you have a working Rust environment and have started a new project with the `rerun` dependency. If not, check out the [setup page](rust.md). For this example in particular, we're going to need all of these: + ```toml [dependencies] rerun = "0.9" @@ -29,6 +31,7 @@ rand = "0.8" ``` While we're at it, let's get imports out of the way: + ```rust use std::f32::consts::TAU; @@ -41,7 +44,8 @@ use rerun::{ ``` ## Starting the viewer -Just run `rerun` to start the [Rerun Viewer](../../../reference/viewer/overview.md). It will wait for your application to log some data to it. This viewer is in fact a server that's ready to accept data over TCP (it's listening on `0.0.0.0:9876` by default). + +Just run `rerun` to start the [Rerun Viewer](../../reference/viewer/overview.md). It will wait for your application to log some data to it. This viewer is in fact a server that's ready to accept data over TCP (it's listening on `0.0.0.0:9876` by default). Checkout `rerun --help` for more options. @@ -68,15 +72,15 @@ fn main() -> Result<(), Box> { } ``` -Among other things, a stable [`ApplicationId`](https://docs.rs/rerun/latest/rerun/struct.ApplicationId.html) will make it so the [Rerun Viewer](../../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. - -Check out the reference to learn more about how Rerun deals with [applications and recordings](../../../concepts/apps-and-recordings.md). +Among other things, a stable [`ApplicationId`](https://docs.rs/rerun/latest/rerun/struct.ApplicationId.html) will make it so the [Rerun Viewer](../../reference/viewer/overview.md) retains its UI state across runs for this specific dataset, which will make our lives much easier as we iterate. +Check out the reference to learn more about how Rerun deals with [applications and recordings](../../concepts/apps-and-recordings.md). ## Logging our first points The core structure of our DNA looking shape can easily be described using two point clouds shaped like spirals. Add the following to your `main` function: + ```rust const NUM_POINTS: usize = 100; @@ -108,7 +112,7 @@ Run your program with `cargo run` and you should now see this scene in the viewe
_This is a good time to make yourself familiar with the viewer: try interacting with the scene and exploring the different menus._ -_Checkout the [Viewer Walkthrough](../../visualize/viewer-walkthrough.md) and [viewer reference](../../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ +_Checkout the [Viewer Walkthrough](../navigating-the-viewer.md) and [viewer reference](../../reference/viewer/overview.md) for a complete tour of the viewer's capabilities._ ## Under the hood @@ -117,35 +121,37 @@ This tiny snippet of code actually holds much more than meets the eye… ### Archetypes + The easiest way to log geometric primitives is the use the [`RecordingStream::log`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log) method with one of the built-in archetype class, such as [`Points3D`](https://docs.rs/rerun/latest/0.9.0-alpha.10/struct.Points3D.html). Archetypes take care of building batches of components that are recognized and correctly displayed by the Rerun viewer. ### Components -Under the hood, the Rerun [Rust SDK](https://ref.rerun.io/docs/rust) logs individual *components* like positions, colors, +Under the hood, the Rerun [Rust SDK](https://ref.rerun.io/docs/rust) logs individual _components_ like positions, colors, and radii. Archetypes are just one high-level, convenient way of building such collections of components. For advanced use cases, it's possible to add custom components to archetypes, or even log entirely custom sets of components, bypassing archetypes altogether. -For more information on how the rerun data model works, refer to our section on [Entities and Components](../../../concepts/entity-component.md). +For more information on how the rerun data model works, refer to our section on [Entities and Components](../../concepts/entity-component.md). Notably, the [`RecordingStream::log`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log) method + -will handle any data type that implements the [`AsComponents`](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html) trait, making it easy to add your own data. -For more information on how to supply your own components see [Use custom data](../../../howto/extend/custom-data.md). +will handle any data type that implements the [`AsComponents`](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html) trait, making it easy to add your own data. +For more information on how to supply your own components see [Use custom data](../../howto/extend/custom-data.md). ### Entities & hierarchies Note the two strings we're passing in: `"dna/structure/left"` and `"dna/structure/right"`. -These are [*entity paths*](../../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. -[Entity paths typically form a hierarchy](../../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). +These are [_entity paths_](../../concepts/entity-component.md), which uniquely identify each entity in our scene. Every entity is made up of a path and one or more components. +[Entity paths typically form a hierarchy](../../concepts/entity-path.md) which plays an important role in how data is visualized and transformed (as we shall soon see). ### Batches One final observation: notice how we're logging a whole batch of points and colors all at once here. -[Batches of data](../../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. -You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this *splatting*. +[Batches of data](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. +You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _splatting_. --- @@ -155,6 +161,7 @@ Good news is: once you've digested all of the above, logging any other Entity wi ## Adding the missing pieces We can represent the scaffolding using a batch of 3D line segments: + ```rust let points_interleaved: Vec<[glam::Vec3; 2]> = points1 .into_iter() @@ -172,6 +179,7 @@ rec.log( ``` Which only leaves the beads: + ```rust use rand::Rng as _; let mut rng = rand::thread_rng(); @@ -206,14 +214,13 @@ Once again, although we are getting fancier and fancier with our iterator mappin
- ## Animating the beads ### Introducing Time -Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../../concepts/timelines.md). +Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). -Even so, if you look at your [Timeline View](../../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. +Even so, if you look at your [Timeline View](../../reference/viewer/timeline.md) right now, you'll notice that Rerun has kept track of time on your behalf anyway by memorizing when each log call occurred. @@ -229,6 +236,7 @@ For that, we need to introduce our own custom timeline that uses a deterministic Rerun has rich support for time: whether you want concurrent or disjoint timelines, out-of-order insertions or even data that lives _outside_ the timeline(s). You will find a lot of flexibility in there. Let's add our custom timeline: + ```rust for i in 0..400 { let time = i as f32 * 0.01; @@ -260,7 +268,7 @@ for i in 0..400 { First we use [`RecordingStream::set_time_seconds`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.set_time_seconds) to declare our own custom `Timeline` and set the current timestamp. You can add as many timelines and timestamps as you want when logging data. -⚠️ If you run this code as is, the result will be.. surprising: the beads are animating as expected, but everything we've logged until that point is gone! ⚠️ +⚠️ If you run this code as is, the result will be.. surprising: the beads are animating as expected, but everything we've logged until that point is gone! ⚠️ ![logging data - wat](https://static.rerun.io/a396c8aae1cbd717a3f35472594f789e4829b1ae_logging_data7_wat.png) @@ -268,8 +276,9 @@ Enter… ### Latest At semantics -That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the *default* timeline (called `log_time`). +That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). To fix this, add this at the beginning of the main function: + ```rust rec.set_time_seconds("stable_time", 0f64); ``` @@ -296,6 +305,7 @@ Now it's just a matter of combining the two: we need to log the transform of the Either expand the previous loop to include logging transforms or simply add a second loop like this: + ```rust for i in 0..400 { // …everything else… @@ -316,7 +326,6 @@ Voila! - ## Other ways of logging & visualizing data ### Saving & loading to/from RRD files @@ -324,16 +333,17 @@ Voila! Sometimes, sending the data over the network is not an option. Maybe you'd like to share the data, attach it to a bug report, etc. Rerun has you covered: -- Use [`RecordingStream::save`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.save) to stream all logging data to disk. -- Visualize it via `rerun path/to/recording.rrd` + +- Use [`RecordingStream::save`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.save) to stream all logging data to disk. +- Visualize it via `rerun path/to/recording.rrd` You can also save a recording (or a portion of it) as you're visualizing it, directly from the viewer. -⚠️ [RRD files don't yet handle versioning!](https://github.com/rerun-io/rerun/issues/873) ⚠️ +⚠️ [RRD files don't yet handle versioning!](https://github.com/rerun-io/rerun/issues/873) ⚠️ ### Spawning the Viewer from your process -If the Rerun Viewer is [installed](../../installing-viewer.md) and available in your `PATH`, you can use [`RecordingStream::spawn`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.spawn) to automatically start a viewer in a new process and connect to it over TCP. +If the Rerun Viewer is [installed](../installing-viewer.md) and available in your `PATH`, you can use [`RecordingStream::spawn`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.spawn) to automatically start a viewer in a new process and connect to it over TCP. If an external viewer was already running, `spawn` will connect to that one instead of spawning a new one. ```rust @@ -349,12 +359,15 @@ fn main() -> Result<(), Box> { Alternatively, you can use [`rerun::native_viewer::show`](https://docs.rs/rerun/latest/rerun/native_viewer/fn.show.html) to start a viewer on the main thread (for platform-compatibility reasons) and feed it data from memory. This requires the `native_viewer` feature to be enabled in `Cargo.toml`: + ```toml rerun = { version = "0.9", features = ["native_viewer"] } ``` + Doing so means you're building the Rerun Viewer itself as part of your project, meaning compilation will take a bit longer the first time. Unlike `spawn` however, this expects a complete recording instead of being fed in real-time: + ```rust let (rec, storage) = rerun::RecordingStreamBuilder::new("rerun_example_dna_abacus").memory()?; @@ -362,10 +375,11 @@ let (rec, storage) = rerun::RecordingStreamBuilder::new("rerun_example_dna_abacu rerun::native_viewer::show(storage.take())?; ``` + The viewer will block the main thread until it is closed. ### Closing This closes our whirlwind tour of Rerun. We've barely scratched the surface of what's possible, but this should have hopefully given you plenty pointers to start experimenting. -As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../../reference/types.md) section for more simple examples of how to use the main data types. +As a next step, browse through our [example gallery](/examples) for some more realistic example use-cases, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main data types. diff --git a/docs/content/getting-started/data-in/streaming.md b/docs/content/getting-started/data-in/streaming.md deleted file mode 100644 index fc7d7a592025..000000000000 --- a/docs/content/getting-started/data-in/streaming.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Streaming data -order: 0 ---- - -A step by step tutorial for how to stream data from your application to the Rerun viewer. - -* [C++](./streaming/cpp.md) -* [Python](./streaming/python.md) -* [Rust](./streaming/rust.md) diff --git a/docs/content/getting-started/visualize/viewer-walkthrough.md b/docs/content/getting-started/navigating-the-viewer.md similarity index 55% rename from docs/content/getting-started/visualize/viewer-walkthrough.md rename to docs/content/getting-started/navigating-the-viewer.md index 9555deda6260..65b0119856a1 100644 --- a/docs/content/getting-started/visualize/viewer-walkthrough.md +++ b/docs/content/getting-started/navigating-the-viewer.md @@ -1,16 +1,15 @@ --- -title: Viewer walkthrough -order: 0 +title: Navigating the viewer +order: 4 --- This guide will familiarize you with the basics of using the Rerun Viewer with an example dataset. By the end you should be comfortable with the following topics: - * [Launching the demo](#launching-the-demo) - * [The viewer panels](#the-viewer-panels) - * [Exploring data](#exploring-data) - * [Navigating the timeline](#navigating-the-timeline) - * [Configuring views](#configuring-views) - * [Creating new views](#creating-new-views) + +- [Launching the demo](#launching-the-demo) +- [The viewer panels](#the-viewer-panels) +- [Exploring data](#exploring-data) +- [Navigating the timeline](#navigating-the-timeline) Here is a preview of the dataset that we will be working with: @@ -21,7 +20,6 @@ Here is a preview of the dataset that we will be working with: viewer walkthrough dataset preview screenshot - The demo uses the output of the [COLMAP](https://colmap.github.io/) structure-from-motion pipeline on a small dataset. Familiarity with structure-from-motion algorithms is not a prerequisite for following the guide. All you need to know is that at a very high level, COLMAP processes a series of images, and by tracking identifiable "keypoints" from frame to @@ -29,9 +27,10 @@ frame, it is able to reconstruct both a sparse representation of the scene as we to take the images. ## Prerequisites + Although the Rerun SDK is available in both Python and Rust, this walkthrough makes use the Python installation. Even if you plan to use Rerun with Rust, we still recommend having a Rerun Python environment available for quick -experimentation and working with examples. You can either follow the [Python Quickstart](../quick-start/python.md) or simply run: +experimentation and working with examples. You can either follow the [Python Quickstart](./quick-start/python.md) or simply run: ```bash pip install rerun-sdk @@ -49,9 +48,9 @@ Start by running the viewer: $ rerun ``` -*Note: If this is your first time launching Rerun you will see a notification about the Rerun anonymous data usage +_Note: If this is your first time launching Rerun you will see a notification about the Rerun anonymous data usage policy. Rerun collects anonymous usage data to help improve the SDK, though you may choose to opt out if you would -like.* +like._ This will bring you the Rerun viewer's Welcome screen: @@ -73,21 +72,21 @@ Click on the "View Examples" button, and then chose the "Structure from Motion" viewer walkthrough first launch screenshot
- Depending on your display size, the panels may have a different arrangements. This does not yet look like the initial preview, but the remainder of this guide will walk you through how to configure the Viewer to meet your needs. ## The viewer panels There are 4 main parts to this window: -- In the middle of the screen is the [Viewport](../../reference/viewer/viewport.md). This is where you see the rendered - space views for your session. -- On the left is the [Blueprint](../../reference/viewer/blueprint.md) panel. This is where the different space views can be - controlled. -- On the right is the [Selection](../../reference/viewer/selection.md) panel. This is where you see extra information - and configuration information for things that you have selected. -- On the bottom is the [Timeline](../../reference/viewer/timeline.md) panel. This is where you can control the current - point in time that is being viewed. + +- In the middle of the screen is the [Viewport](../reference/viewer/viewport.md). This is where you see the rendered + space views for your session. +- On the left is the [Blueprint](../reference/viewer/blueprint.md) panel. This is where the different space views can be + controlled. +- On the right is the [Selection](../reference/viewer/selection.md) panel. This is where you see extra information + and configuration information for things that you have selected. +- On the bottom is the [Timeline](../reference/viewer/timeline.md) panel. This is where you can control the current + point in time that is being viewed. Each of the 3 side panels has a corresponding button in the upper right corner. Try clicking each of these to hide and show the corresponding panel. @@ -114,23 +113,25 @@ view. viewer walkthrough rearrange panels screenshot
- Feel free to move the views around until you are happy with the layout. ## Exploring data + The space views are where you can see the data that was actually logged. This scene has streams of data for 6 different -primitives, also known as [entities](../../concepts/entity-component.md): -* [images](../../reference/types/archetypes/image.md) that were captured from a camera. -* [2D keypoints](../../reference/types/archetypes/points2d.md) that were detected and tracked in those images. -* a [pinhole](../../reference/types/archetypes/pinhole.md) camera model that describes the relationship between 2D and 3D space. -* [3D points](../../reference/types/archetypes/points3d.md) that were computed by the COLMAP slam pipeline. -* A sequence of [transforms](../../reference/types/archetypes/transform3d.md) describing the 3D location of the camera in space. -* A [scalar](../../reference/types/archetypes/scalar.md) error metric that was computed by the algorithm for each frame. +primitives, also known as [entities](../concepts/entity-component.md): + +- [images](../reference/types/archetypes/image.md) that were captured from a camera. +- [2D keypoints](../reference/types/archetypes/points2d.md) that were detected and tracked in those images. +- a [pinhole](../reference/types/archetypes/pinhole.md) camera model that describes the relationship between 2D and 3D space. +- [3D points](../reference/types/archetypes/points3d.md) that were computed by the COLMAP slam pipeline. +- A sequence of [transforms](../reference/types/archetypes/transform3d.md) describing the 3D location of the camera in space. +- A [scalar](../reference/types/archetypes/scalar.md) error metric that was computed by the algorithm for each frame. ### Hover and selection + You can find out more about these entities by hovering over them in the different views. Hovering will bring up a context popup with additional information. You can also click on entities to select them and see more details in the -[Selection panel](../../reference/viewer/selection.md). +[Selection panel](../reference/viewer/selection.md). @@ -140,18 +141,19 @@ context popup with additional information. You can also click on entities to sel viewer walkthrough hover screenshot - Try each of the following: - * Hover over the image to see a zoomed-in preview - * Click on the point cloud to select the whole cloud - * With the point cloud selected, hover and click individual points + +- Hover over the image to see a zoomed-in preview +- Click on the point cloud to select the whole cloud +- With the point cloud selected, hover and click individual points Note that the views are actually connected. As you hover over points in the `/ (Spatial)` view you will see information about the depth of the projection in the image view. Conversely as you hover over pixels in the `image` you will see the corresponding ray projected into the `/ (Spatial)` view. See the section on -[Spaces and Transforms](../../concepts/spaces-and-transforms.md) for more information on how this linking works. +[Spaces and Transforms](../concepts/spaces-and-transforms.md) for more information on how this linking works. ### Rotate, zoom, and pan + Clicking and dragging the contents of any view will move it. You can rotate 3D views, or pan 2D views and plots. You can also zoom using ctrl+scrollwheel or pinch gestures on a trackpad. Most views can be restored to their default state by double-clicking somewhere in the view. Every view has a "?" icon in the upper right hand corner. You can always mouse @@ -165,20 +167,22 @@ over this icon to find out more information about the specific view. viewer walkthrough rotate zoom and pan screenshot
- Try each of the following: - * Drag the camera image and zoom in on one of the stickers - * Rotate the 3D point cloud - * Right-click and drag a rectangle to see a zoomed-in region of the plot - * Double-click in each of the views to return them to default + +- Drag the camera image and zoom in on one of the stickers +- Rotate the 3D point cloud +- Right-click and drag a rectangle to see a zoomed-in region of the plot +- Double-click in each of the views to return them to default ## Navigating the timeline + So far, we have only been exploring data from a single point in time. However, if you look at the Timeline panel at the bottom of the window, you will see a series of white dots. Each of those dots represents a piece of data that was logged at a different point in time. In fact, if you hover over the dot, the context popup will give you more information about the specific thing that was logged. ### Changing the time slider + To change the position on the timeline, simply grab the time indicator and pull it to the point in time you are interested in seeing. The space views will adjust accordingly. You can also use the play/pause/step/loop controls to playback the Rerun data as you might with a video file. @@ -191,16 +195,17 @@ playback the Rerun data as you might with a video file. viewer walkthrough timeline screenshot
- Try out the following: - * Use the arrow buttons (or arrow keys on your keyboard) to step forward and backwards by a single frame - * Click play to watch the data update on its own - * Hit space bar to stop and start the playback - * Hold shift and drag in the timeline to select a region - * Toggle the loop button to playback on a loop of either the whole recording or just the selection + +- Use the arrow buttons (or arrow keys on your keyboard) to step forward and backwards by a single frame +- Click play to watch the data update on its own +- Hit space bar to stop and start the playback +- Hold shift and drag in the timeline to select a region +- Toggle the loop button to playback on a loop of either the whole recording or just the selection ### Selecting different timelines -The current view of timeline is showing the data organized by the *frame number* at which it was logged. Using frame + +The current view of timeline is showing the data organized by the _frame number_ at which it was logged. Using frame numbers can be a helpful way to synchronize things that may not have been logged at precisely the same time. However, it's possible to also view the data in the specific order that it was logged. Click on the drop-down that says "frame" and switch it to "log_time." If you zoom in on the timeline (using ctrl+scrollwheel), you can see that these events were @@ -214,121 +219,37 @@ all logged at slightly different times. viewer walkthrough change timeline screenshot
- Feel free to spend a bit of time looking at the data across the different timelines. When you are done, switch back to the "frame" timeline and double-click the timeline panel to reset it to the default range. One thing to notice is there is a gap in the timeline in the "frame" view. This dataset is actually missing a few frames, and the timeline view of frames makes this easy to spot. This highlights the importance of applying meaningful timestamps to your data as you log it. You also aren't limited to frame and log_time. Rerun lets you define your own -timelines however you would like. You can read more about timelines [here](../../concepts/timelines.md). - -## Configuring views -Views in Rerun are configured by [Blueprints](../../reference/viewer/blueprint.md). We will now use blueprints to adjust -both an individual entity as well as the contents of a space view itself. - -### Adjusting entity properties -First, click to select the entity named `points` in the `/ (Spatial)` view in the Blueprint panel. Now, look and the -selection panel -- in addition to the information about the data associated with that entity, you will see a "Blueprint" -section. - -Try toggling "visible" on and off and you will see that the points disappear and reappear. Next, click the control -labeled "visible history" and drag it to the right to increase the value. As you drag farther you will see more points -show up in the view. This is making historical points, from farther back in time visible within the time point of this -view. Because the points are logged in stationary 3D space, aggregating them here gives us a more complete view of the -car. Leave the visible history with a value of 50. - - - - - - - viewer walkthrough adjusting visible history screenshot - - -### Modifying the contents of a space view -Now select the `/ (Spatial)` view itself. We will start by giving this space view a different name. At the very -top of the selection panel you will see a text box labeled "Space view:". Go ahead and change the name to -`Reconstruction`. The name will also update in the blueprint panel on the left. - -Like with the entity selection, you will see a Blueprint section within the Selection panel. This time, click on the -button labeled "Add/Remove Entities". This pop-up shows all of the entities that were logged as part of this session. -You can click on the "+" or "-" buttons to add or remove entities from this view. Go ahead and remove the entity called -"keypoints," and then add them back again. Unlike hiding an entity, you will notice that as you remove entities they -completely disappear from the blueprint panel on the left. Entities that are incompatible with the selected view will be -grayed out. For example, you cannot add a scalar to a spatial scene. - - - - - - - viewer walkthrough modifying contents of a space view screenshot - - - -## Creating new views -New views & view containers (grid, vertical, etc.) can be created using the "+" button at the top of the Blueprint panel or -from the selection panel when selecting a container. - -After creating a view you usually want to proceed to editing its origin and query (which entities are shown) in the selection panel. - -Your view layout might be feeling a little cluttered now. You can quickly hide views you're -not using from the blueprint panel by hovering over the view and then clicking the icon that looks like an eye. Go ahead -and hide the `image` and `avg_reproj_err` views, and collapse the expanded timeline panel using the button in the upper -right corner. Note that even with the timeline collapsed you still have access to timeline controls, including a slider. - - - - - - - viewer walkthrough toggle visibility screenshot - - - -### Reusing what you've learned -Finally, use what we covered in the previous section to change the contents of this view. Select the new `camera` view, -then choose "Add/remove entities." Remove the 2D "keypoints" and add in the 3D "points." Note that these points do not -have visible history turned on -- that's because the blueprint is part of the view and not part of the entity. -Select the points within this view by clicking on them in the blueprint or the view itself, and then give them visible -history as well. When you are done, your view should look like this: - - - - - - - viewer walkthrough camera view screenshot - - - -Now move the slider back and forth and see what happens. Even though they are both views of the same camera and point -entities, they behave quite differently. On the top the camera moves relative to the car, while on the bottom the car -moves relative to the camera. This is because the new views have *different* space roots, and Rerun uses the transform -system to transform or project all data into the space root for the given view. +timelines however you would like. You can read more about timelines [here](../concepts/timelines.md). ## Conclusion That brings us to the end of this walkthrough. To recap, you have learned how to: -- Install the `rerun-sdk` pypi package. -- Run the Rerun Viewer using the `rerun` command. -- Open the examples integrated in the viewer. -- Work with the [Blueprint](../../reference/viewer/blueprint.md), [Selection](../../reference/viewer/selection.md) and [Timeline](../../reference/viewer/timeline.md) panels. -- Rearrange space view layouts. -- Explore data through hover and selection. -- Change the time selection. -- Switch between different timelines. -- Configure entity blueprint properties. -- Add and remove entities from views. -- Create and configure new views. -- And some basics of how transforms work. + +- Install the `rerun-sdk` pypi package. +- Run the Rerun Viewer using the `rerun` command. +- Open the examples integrated in the viewer. +- Work with the [Blueprint](../reference/viewer/blueprint.md), [Selection](../reference/viewer/selection.md) and [Timeline](../reference/viewer/timeline.md) panels. +- Rearrange space view layouts. +- Explore data through hover and selection. +- Change the time selection. +- Switch between different timelines. Again, if you ran into any issues following this guide, please don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). ### Up next -To get started with writing a program to logging data with the Rerun SDK see the [getting started guides](../quick-start). + +The followup to this tutorial involves further configuring how the viewer displays the data. + +- See: [Configure the viewer interactively](./configure-the-viewer/interactively.md) + +To get started with writing a program to logging data with the Rerun SDK see the [getting started guides](./quick-start). To see and explore other data, you can check out the [examples](/examples). -For deeper context on the ideas covered here, consult the [Concept overview](../../concepts.md). +For deeper context on the ideas covered here, consult the [Concept overview](../concepts.md). diff --git a/docs/content/getting-started/quick-start/cpp.md b/docs/content/getting-started/quick-start/cpp.md index ba4d52bca8ec..ca6a580ec582 100644 --- a/docs/content/getting-started/quick-start/cpp.md +++ b/docs/content/getting-started/quick-start/cpp.md @@ -4,9 +4,11 @@ order: 1 --- ## Setup + Before adding Rerun to your application, start by [installing the viewer](../installing-viewer.md#installing-the-viewer). ## Learning by example + If you prefer to learn by example, check out our example repository which uses the Rerun C++ SDK to log some data from Eigen and OpenCV: . ## Using Rerun with CMake @@ -28,6 +30,7 @@ FetchContent_Declare(rerun_sdk URL https://github.com/rerun-io/rerun/releases/latest/download/rerun_cpp_sdk.zip) FetchContent_MakeAvailable(rerun_sdk) ``` + This will download a bundle with pre-built Rerun C static libraries for most desktop platforms, all Rerun C++ sources and headers, as well as CMake build instructions for them. By default this will in turn download & build [Apache Arrow](https://arrow.apache.org/)'s C++ library which is required to build the Rerun C++. @@ -67,6 +70,7 @@ target_link_libraries(example_minimal PRIVATE rerun_sdk) ``` ## Logging some data + Add the following code to your `main.cpp` (this example also lives in the `rerun` source tree [example](https://github.com/rerun-io/rerun/blob/latest/examples/cpp/minimal/main.cpp)): @@ -94,6 +98,7 @@ int main() { ## Building and running You can configure cmake, build, and run your application like so: + ```bash cmake -B build cmake --build build -j @@ -111,19 +116,21 @@ Once everything finishes compiling, the application will spawn the rerun viewer
## Using the viewer + Try out the following to interact with the viewer: - * Click and drag in the main view to rotate the cube. - * Zoom in and out with the scroll wheel. - * Mouse over the "?" icons to find out about more controls. - * Click on the cube to select all of the points. - * Hover and select individual points to see more information. + +- Click and drag in the main view to rotate the cube. +- Zoom in and out with the scroll wheel. +- Mouse over the "?" icons to find out about more controls. +- Click on the cube to select all of the points. +- Hover and select individual points to see more information. If you're facing any difficulties, don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose) or [join the Discord server](https://discord.gg/PXtCgFBSmH). ## What's next -If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../visualize/viewer-walkthrough.md) or our -more advanced guide for [Logging Data in C++](../data-in/streaming/cpp.md) where we will explore the core concepts that make +If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../navigating-the-viewer.md) or our +more advanced guide for [Logging Data in C++](../data-in/cpp.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. diff --git a/docs/content/getting-started/quick-start/python.md b/docs/content/getting-started/quick-start/python.md index d0c275929efe..0c051713e209 100644 --- a/docs/content/getting-started/quick-start/python.md +++ b/docs/content/getting-started/quick-start/python.md @@ -8,6 +8,7 @@ order: 2 The Rerun SDK for Python requires a working installation of [Python-3.8+](https://www.python.org/). You can install the Rerun SDK using the [rerun-sdk](https://pypi.org/project/rerun-sdk/) pypi package via pip: + ```bash $ pip3 install rerun-sdk ``` @@ -17,6 +18,7 @@ You are now ready to start logging and visualizing data. ## Trying out the viewer Rerun comes packaged with integrated examples to make it easy to explore the viewer. Launch it with: + ```bash $ rerun ``` @@ -41,32 +43,35 @@ Click on the "View Examples" button, and then on the "Helix" example. This shoul
- Try looping the recording to see the fun animation. -*Note: If this is your first time launching Rerun you will see a notification in the terminal about the Rerun anonymous +_Note: If this is your first time launching Rerun you will see a notification in the terminal about the Rerun anonymous data usage policy. Rerun collects anonymous usage data to help improve the project, though you may choose to opt out if you -would like.* +would like._ ### If you're having problems - * Checkout out our [troubleshooting guide](../troubleshooting.md). - * [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). - * Or [join the Discord server](https://discord.gg/PXtCgFBSmH). + +- Checkout out our [troubleshooting guide](../troubleshooting.md). +- [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). +- Or [join the Discord server](https://discord.gg/PXtCgFBSmH). ## Using the viewer + Try out the following to interact with the viewer: - * Click and drag in the main view to rotate the cube. - * Zoom in and out with the scroll wheel. - * Mouse over the "?" icons to find out about more controls. - * Grab the time-slider and move it to see the cube at different time-points. - * Click the "play" button to animate the cube. - * Click on the cube to select all the points. - * Hover and select individual points to see more information. + +- Click and drag in the main view to rotate the cube. +- Zoom in and out with the scroll wheel. +- Mouse over the "?" icons to find out about more controls. +- Grab the time-slider and move it to see the cube at different time-points. +- Click the "play" button to animate the cube. +- Click on the cube to select all the points. +- Hover and select individual points to see more information. This is just a taste of some of what you can do with the viewer. We will cover other functionality in much -more detail later in the [Viewer Walkthrough](../visualize/viewer-walkthrough.md) +more detail later in the [Viewer Walkthrough](../navigating-the-viewer.md) ## Logging your own data + After exploring a built-in example, let's create some data ourselves. We will start with an extremely simplified version of this dataset that just logs 1 dimension of points instead of 3. @@ -101,14 +106,13 @@ only showing a simple line of red points.
- - The [`rr.log`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log) is the primary way to log data. It's a flexible call that can accept a variety of correctly-formatted data—including your own. The easiest way to use it is to use an instance of -one of the built-in *archetype* class, such as [`rr.Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points3D). Archetypes take care of gathering the various +one of the built-in _archetype_ class, such as [`rr.Points3D`](https://ref.rerun.io/docs/python/stable/common/archetypes/#rerun.archetypes.Points3D). Archetypes take care of gathering the various components representing, in this case, a batch of 3D points such that it is recognized and correctly displayed by the Rerun viewer. The `rr.Points3D` archetype accepts any collection of positions that can be converted to a Nx3 Numpy array, along with other components such as colors, radii, etc. Feel free to modify the code to log a different set of points. For example, this code generates a more elaborate 3D colored cube: + ```python import rerun as rr import numpy as np @@ -139,8 +143,8 @@ rr.log( ## What's next -If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../visualize/viewer-walkthrough.md) or our -more advanced guide for [Logging Data in Python](../data-in/streaming/python.md) where we will explore the core concepts that make +If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../navigating-the-viewer.md) or our +more advanced guide for [Logging Data in Python](../data-in/python.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. diff --git a/docs/content/getting-started/quick-start/rust.md b/docs/content/getting-started/quick-start/rust.md index 9beee14a84be..910d87aaa9ba 100644 --- a/docs/content/getting-started/quick-start/rust.md +++ b/docs/content/getting-started/quick-start/rust.md @@ -4,18 +4,22 @@ order: 3 --- ## Setup + The Rerun SDK for Rust requires a working installation of Rust 1.74+. After you have [installed the viewer](../installing-viewer.md#installing-the-viewer) you can simply add [the rerun crate](https://crates.io/crates/rerun) to your project with `cargo add rerun`. Let's try it out in a brand new Rust project: + ```bash $ cargo init cube && cd cube && cargo add rerun ``` ## Logging some data + Add the following code to your `main.rs` (This example also lives in the `rerun` source tree [example](https://github.com/rerun-io/rerun/tree/latest/examples/rust/minimal/src/main.rs)) + ```rust use rerun::{demo_util::grid, external::glam}; @@ -38,6 +42,7 @@ fn main() -> Result<(), Box> { ``` Now run your application: + ``` cargo run ``` @@ -52,21 +57,22 @@ Once everything finishes compiling, you will see the points in the Rerun Viewer:
- ## Using the viewer + Try out the following to interact with the viewer: - * Click and drag in the main view to rotate the cube. - * Zoom in and out with the scroll wheel. - * Mouse over the "?" icons to find out about more controls. - * Click on the cube to select all of the points. - * Hover and select individual points to see more information. + +- Click and drag in the main view to rotate the cube. +- Zoom in and out with the scroll wheel. +- Mouse over the "?" icons to find out about more controls. +- Click on the cube to select all of the points. +- Hover and select individual points to see more information. If you're facing any difficulties, don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose) or [join the Discord server](https://discord.gg/PXtCgFBSmH). ## What's next -If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../visualize/viewer-walkthrough.md) or our -more advanced guide for [Logging Data in Rust](../data-in/streaming/rust.md) where we will explore the core concepts that make +If you're ready to move on to more advanced topics, check out the [Viewer Walkthrough](../navigating-the-viewer.md) or our +more advanced guide for [Logging Data in Rust](../data-in/rust.md) where we will explore the core concepts that make Rerun tick and log our first non-trivial dataset. If you'd rather learn from examples, check out the [example gallery](/examples) for some more realistic examples, or browse the [Types](../../reference/types.md) section for more simple examples of how to use the main datatypes. diff --git a/docs/content/getting-started/visualize.md b/docs/content/getting-started/visualize.md deleted file mode 100644 index a658f87687c5..000000000000 --- a/docs/content/getting-started/visualize.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Using the viewer -order: 4 -redirect: getting-started/visualize/viewer-walkthrough ---- diff --git a/docs/content/howto/add-support-for-arbitrary-file-types.md b/docs/content/howto/add-support-for-arbitrary-file-types.md new file mode 100644 index 000000000000..fcd223a0c7c3 --- /dev/null +++ b/docs/content/howto/add-support-for-arbitrary-file-types.md @@ -0,0 +1,48 @@ +--- +title: Add support for arbitrary file types +order: 11 +--- + +Internally, the [`DataLoader`](https://docs.rs/re_data_source/latest/re_data_source/trait.DataLoader.html) trait takes care of loading files into the Viewer and/or SDK. + +There are 3 broad kinds of `DataLoader`s: _builtin_, _external_ and _custom_. +_External_ and _custom_ are the two ways of extending the file loading system that we'll describe below. + +When a user attempts to open a file in the Viewer/SDK, **all** known `DataLoader`s are notified of the path to be opened, unconditionally. +This gives `DataLoader`s maximum flexibility to decide what files they are interested in, as opposed to e.g. only being able to look at a file's extension. + +Once notified, a `DataLoader` can return a [`DataLoaderError::Incompatible`](https://docs.rs/re_data_source/latest/re_data_source/enum.DataLoaderError.html#variant.Incompatible) error to indicate that it doesn't support a given file type. +If, and only if, all loaders known to the Viewer/SDK return an `Incompatible` error code, then an error message is shown to the user indicating that this file type is not (_yet_) supported. + +In these instances of unsupported files, we expose two ways of implementing and registering your `DataLoader`s, explained below. + +### External data-loaders + +The easiest way to create your own `DataLoader` is by implementing what we call an "external loader": a stand alone executable written in any language that the Rerun SDK ships for. Any executable on your `$PATH` with a name that starts with `rerun-loader-` will be treated as a `DataLoader`. + +This executable takes a file path as a command line argument and outputs Rerun logs on `stdout`. +It will be called by the Rerun Viewer/SDK when the user opens a file, and be passed the path to that file. +From there, it can log data as usual, using the [`stdout` logging sink](../reference/sdk-operating-modes.md#standard-inputoutput). + +The Rerun Viewer/SDK will then automatically load the data streamed to the external loader's standard output. + + + + + + + + + +Like any other `DataLoader`, an external loader will be notified of all file openings, unconditionally. +To indicate that it does not support a given file, the loader has to exit with a [dedicated status code](https://docs.rs/rerun/latest/rerun/constant.EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE.html). + +Check out our examples for [C++](https://github.com/rerun-io/rerun/tree/main/examples/cpp/external_data_loader), [Python](https://github.com/rerun-io/rerun/tree/main/examples/python/external_data_loader) and [Rust](https://github.com/rerun-io/rerun/tree/main/examples/rust/external_data_loader) that cover every steps in details. + +### Custom Rust data-loaders + +Another Rust-specific approach is to implement the `DataLoader` trait yourself and register it in the Rerun Viewer/SDK. + +To do so, you'll need to import `rerun` as a library, register your `DataLoader` and then start the Viewer/SDK from code. + +Check out our [example](https://github.com/rerun-io/rerun/tree/main/examples/rust/custom_data_loader) that cover all these steps in details. diff --git a/docs/content/howto/configure-the-viewer/interactively.md b/docs/content/howto/configure-the-viewer/interactively.md deleted file mode 100644 index 5f7d885ace81..000000000000 --- a/docs/content/howto/configure-the-viewer/interactively.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Interactively setup up viewer -order: 1 ---- - -The Rerun Viewer is configurable directly through the UI itself. - -## Viewer overview - -TODO(#5636): Screenshot of the viewer, with the blueprint and selection panels highlighted. - -The left panel of the viewer is the "Blueprint Panel" this shows a visual tree view representing -the contents of the current blueprint. - -The right panel of the viewer is the "Selection Panel" this panel allows you to configure -specific blueprint properties of the currently selected element. - -After editing the viewer you may want to [save or share the blueprint](./save-and-load.md). - -## Configuring Layout and Contents - -### Show or hide parts of the blueprint - -Click the "eye" icon next to the container, view, or entity in the blueprint panel. -TODO(#5636): show_hide - -### Add new Containers or Views - -Clicking the "+" at the top of the blueprint panel. -TODO(#5636): add_1 - -Selecting a Container and clicking the "+" in the selection panel. -TODO(#5636): add_2 - -### Remove a View or Container - -Click the "-" button next to the container or view in the blueprint panel. -TODO(#5636): remove - -### Re-arrange existing Containers or Views - -Drag and drop the container or view in the blueprint panel. -TODO(#5636): drag_1 - -Drag and drop containers or views directly in the viewport -TODO(#5636): drag_2 - -### Change the size of Containers or Views - -Click and drag the edge of a view or container to resize it -TODO(#5636): resize - -### Rename a View or Container - -Select the Container or View and enter a name at the top of the selection panel -TODO(#5636): rename - -### Change the type of a Container - -Select the Container and choose a new type from the dropdown in the selection panel -TODO(#5636): change_type - -### Add a new Data to a View - -Select the view and click "edit" to bring up the entity editor -TODO(#5636): add_data_1 - -Select the view and directly edit the entity query -See [Entity Queries](../../reference/entity-queries.md) for more information on how to write queries. - -TODO(#5636): add_data_2 - -### Remove Data from a View - -Click the "-" next to the entity in the blueprint panel -TODO(#5636): remove_data_1 - -### Change the origin of a View - -Select the view, then click the "Space Origin" field and type or select a new origin -TODO(#5636): change_origin - -## Overriding Properties - -TODO(jleibs): do we include this now or wait for generalized component overrides? diff --git a/docs/content/howto/configure-the-viewer/through-code.md b/docs/content/howto/configure-viewer-through-code.md similarity index 91% rename from docs/content/howto/configure-the-viewer/through-code.md rename to docs/content/howto/configure-viewer-through-code.md index 76339ced0db4..501359f92b21 100644 --- a/docs/content/howto/configure-the-viewer/through-code.md +++ b/docs/content/howto/configure-viewer-through-code.md @@ -1,9 +1,9 @@ --- -title: Control the viewer through code -order: 2 +title: Configure the viewer through code +order: 0 --- -As of Rerun 0.15, the state of the [blueprint](../../reference/viewer/blueprint.md) can be directly manipulated using the +As of Rerun 0.15, the state of the [blueprint](../reference/viewer/blueprint.md) can be directly manipulated using the Rerun SDK. In the initial 0.15 release, the APIs are still somewhat limited and only available in the Python SDK. @@ -86,10 +86,8 @@ blueprint" in the viewer. This minimizes the chance that you accidentally overwrite blueprint edits you may have made locally. If you want to start using the new blueprint, after sending it, you will need to -click the reset button in the blueprint panel. This resets the active blueprint to the -current default: - -TODO(#5636): reset_blueprint +click the reset button (reset icon) in the blueprint panel. This resets the active blueprint to the +current default. ## Always activating the blueprint @@ -123,7 +121,7 @@ rrb.Blueprint( ) ``` -Beyond, instantiating the space views, there are 3 parameters you may want to specify: `name`, `origin`, and `contents`. +Beyond instantiating the space views, there are 3 parameters you may want to specify: `name`, `origin`, and `contents`. `name` is simply the name of the view used as a label in the viewer. @@ -141,8 +139,7 @@ Because the data in the space-view is relative to the `origin`, the `origin` wil in the blueprint tree, with all entities under the origin shown using relative paths. For Spatial views such as `Spatial2DView` and `Spatial3DView`, the `origin` plays an additional role with respect -to data transforms. All data in the view will be transformed to the `origin` space before being displayed. See [Spaces and Transforms](../../concepts/spaces-and-transforms.md) for more information. -TODO(jleibs): Re-review spaces-and-transforms for correctness +to data transforms. All data in the view will be transformed to the `origin` space before being displayed. See [Spaces and Transforms](../concepts/spaces-and-transforms.md) for more information. For example: @@ -158,7 +155,7 @@ rrb.Blueprint( ### `contents` If you need to further modify the contents of a space view, you can use the `contents` parameter. This parameter is -a list of [entity query expressions](../../reference/) that are either included or excluded from the +a list of [entity query expressions](../reference/) that are either included or excluded from the view. Each entity expressions starts with "+" for inclusion or "-" for an exclusion. The expressions can either be specific entity paths, or may end in a wildcard `/**` to include all entities under a specific subtree. diff --git a/docs/content/howto/ros2-nav-turtlebot.md b/docs/content/howto/ros2-nav-turtlebot.md index 964e3f9e84ea..8b7769b96749 100644 --- a/docs/content/howto/ros2-nav-turtlebot.md +++ b/docs/content/howto/ros2-nav-turtlebot.md @@ -26,25 +26,29 @@ All of the code for this guide can be found on GitHub in Rerun 3D view of ROS 2 turtlebot3 navigation demo
- ## Prerequisites Other relevant tutorials: - - [Python SDK Tutorial](../getting-started/data-in/streaming/python.md) - - [Viewer Walkthrough](../getting-started/visualize/viewer-walkthrough.md) + +- [Python SDK Tutorial](../getting-started/data-in/python.md) +- [Viewer Walkthrough](../getting-started/navigating-the-viewer.md) ### ROS 2 & navigation + You will need to have installed [ROS 2 Humble Hawksbill](https://docs.ros.org/en/humble/index.html) and the [turtlebot3 navigation getting-started example](https://navigation.ros.org/getting_started/index.html). Installing ROS is outside the scope of this guide, but you will need the equivalent of the following packages: + ```bash $ sudo apt install ros-humble-desktop gazebo ros-humble-navigation2 ros-humble-turtlebot3 ros-humble-turtlebot3-gazebo ``` + If you don't already have ROS installed, we recommend trying [RoboStack](https://robostack.github.io/) for setting up your installation. Before proceeding, you should follow the [navigation example](https://navigation.ros.org/getting_started/index.html) and confirm that you can successfully run: + ```bash $ export TURTLEBOT3_MODEL=waffle $ export GAZEBO_MODEL_PATH=/opt/ros/humble/share/turtlebot3_gazebo/models @@ -58,18 +62,21 @@ running in the background for the remainder of the guide. The code for this guide is in the `rerun` repository. If you do not already have rerun cloned, you should do so now: + ```bash git clone git@github.com:rerun-io/rerun.git cd rerun ``` + The example code can be found in the folder: `examples/python/ros_node`. In addition to the ROS dependencies, the Rerun node makes use of some dependencies specified in [`requirements.txt`](https://github.com/rerun-io/rerun/blob/main/examples/python/ros_node/requirements.txt). Rerun recommends using `venv` (or the equivalent) to create an environment for installing these -dependencies. Note that *after* setting up your virtualenv you will need to activate your ROS2 +dependencies. Note that _after_ setting up your virtualenv you will need to activate your ROS2 environment. + ```bash $ python3 -m venv venv $ source venv/bin/active @@ -80,6 +87,7 @@ $ source venv/bin/active ## Running the example With the previous dependencies installed, and gazebo running, you should now be able to launch the Rerun ROS example: + ```bash (venv) $ python3 examples/python/ros_node/main.py ``` @@ -94,7 +102,6 @@ You should see a window similar to: Initial window layout of Rerun 3D view of ROS 2 turtlebot3 navigation demo
- Use rviz to send a new navigation goal and confirm that rerun updates with new data as turtlebot drives around the environment. @@ -102,18 +109,18 @@ the environment. If you are familiar with the turtlebot nav example and rviz, this view will likely be familiar: - * `map/box` is a placeholder for the map. (This will eventually be a map: [#1531](https://github.com/rerun-io/rerun/issues/1531).) - * `map/robot` is a transform representing the robot pose logged as a rigid [transform3d](../reference/types/archetypes/transform3d.md). - * `map/robot/urdf` contains the `URDF` logged as a [mesh](../reference/types/archetypes/mesh3d.md). - * `map/robot/scan` contains a `LaserScan` msg logged as a [linestrip3d](../reference/types/archetypes/line_strips3d.md). (This will eventually be a - native type: [#1534](https://github.com/rerun-io/rerun/issues/1534).) - * `map/robot/camera` contains a `CameraInfo` msg logged as a [pinhole](../reference/types/archetypes/pinhole.md) transform. - * `map/robot/camera/img` contains an `Image` msg logged as an [image](../reference/types/archetypes/image.md). - * `map/robot/camera/points` contains a `PointCloud2` msg logged as a [point3d](../reference/types/archetypes/points3d.md). - * `map/points` contains a second copy of `PointCloud2` with a different transform. (This is a workaround until Rerun - has support for ROS-style fixed frames [#1522](https://github.com/rerun-io/rerun/issues/1522).) - * `odometry/vel` is a plot of the linear velocity of the robot logged as a [scalar](../reference/types/archetypes/scalar.md). - * `odometry/ang_vel` is a plot of the angular velocity of the robot logged as a [scalar](../reference/types/archetypes/scalar.md). +- `map/box` is a placeholder for the map. (This will eventually be a map: [#1531](https://github.com/rerun-io/rerun/issues/1531).) +- `map/robot` is a transform representing the robot pose logged as a rigid [transform3d](../reference/types/archetypes/transform3d.md). +- `map/robot/urdf` contains the `URDF` logged as a [mesh](../reference/types/archetypes/mesh3d.md). +- `map/robot/scan` contains a `LaserScan` msg logged as a [linestrip3d](../reference/types/archetypes/line_strips3d.md). (This will eventually be a + native type: [#1534](https://github.com/rerun-io/rerun/issues/1534).) +- `map/robot/camera` contains a `CameraInfo` msg logged as a [pinhole](../reference/types/archetypes/pinhole.md) transform. +- `map/robot/camera/img` contains an `Image` msg logged as an [image](../reference/types/archetypes/image.md). +- `map/robot/camera/points` contains a `PointCloud2` msg logged as a [point3d](../reference/types/archetypes/points3d.md). +- `map/points` contains a second copy of `PointCloud2` with a different transform. (This is a workaround until Rerun + has support for ROS-style fixed frames [#1522](https://github.com/rerun-io/rerun/issues/1522).) +- `odometry/vel` is a plot of the linear velocity of the robot logged as a [scalar](../reference/types/archetypes/scalar.md). +- `odometry/ang_vel` is a plot of the angular velocity of the robot logged as a [scalar](../reference/types/archetypes/scalar.md). ## Code Explanation @@ -129,29 +136,32 @@ models and using asynchronous TF lookups are outside the scope of this guide. ### Updating Time -First of all, we want our messages to show up on the timeline based on their *stamped* time rather than the +First of all, we want our messages to show up on the timeline based on their _stamped_ time rather than the time that they were received by the listener, or relayed to Rerun. To do this, we will use a Rerun timeline called `ros_time`. Each callback follows a common pattern of updating `ros_time` based on the stamped time of the message that was received. + ```python def some_msg_callback(self, msg: Msg): time = Time.from_msg(msg.header.stamp) rr.set_time_nanos("ros_time", time.nanoseconds) ``` + This timestamp will apply to all subsequent log calls on in this callback (on this thread) until the time is updated again. - ### TF to rr.Transform3D + Next, we need to map the [ROS TF2](https://docs.ros.org/en/humble/Concepts/About-Tf2.html) transforms to the corresponding [Rerun Transforms](../concepts/spaces-and-transforms.md#space-transformations). In Rerun, each path represents a coordinate frame, so we need to decide which TF frame each path will correspond to. In general, this is the frame_id of the sensor data that will be logged to that path. For consistency, we define this once in `__init__()`. + ```python # Define a mapping for transforms self.path_to_frame = { @@ -172,6 +182,7 @@ of this code to go away. For now, on each incoming log message, we want to use the mapping to update the transform at the timestamp in question: + ```python def log_tf_as_transform3d(self, path: str, time: Time) -> None: """Helper to look up a transform with tf and log using `log_transform3d`.""" @@ -193,6 +204,7 @@ def log_tf_as_transform3d(self, path: str, time: Time) -> None: ``` As an example of logging points in the map frame, we simply call: + ```python rr.log("map/points", rr.Points3D(positions=pts, colors=colors)) self.log_tf_as_transform3d("map/points", time) @@ -203,9 +215,11 @@ be logged to the same point on the timeline as the data, using a timestamp looke matching timepoint. ### Odometry to rr.Scalar and rr.Transform3D + When receiving odometry messages, we log the linear and angular velocities using `rr.Scalar`. Additionally, since we know that odometry will also update the `map/robot` transform, we use this as a cue to look up the corresponding transform and log it. + ```python def odom_callback(self, odom: Odometry) -> None: """Update transforms when odom is updated.""" @@ -221,11 +235,13 @@ def odom_callback(self, odom: Odometry) -> None: ``` ### CameraInfo to rr.Pinhole + Not all Transforms are rigid as defined in TF. The other transform we want to log is the pinhole projection that is stored in the `CameraInfo` msg. Fortunately, the `image_geometry` package has a `PinholeCameraModel` that exposes the intrinsic matrix in the same structure used by Rerun `rr.Pinhole`: + ```python def __init__(self) -> None: # … @@ -248,8 +264,10 @@ def cam_info_callback(self, info: CameraInfo) -> None: ``` ### Image to rr.Image + ROS Images can also be mapped to Rerun very easily, using the `cv_bridge` package. The output of `cv_bridge.imgmsg_to_cv2` can be fed directly into `rr.Image`: + ```python def __init__(self) -> None: # … @@ -265,6 +283,7 @@ def image_callback(self, img: Image) -> None: ``` ### PointCloud2 to rr.Points3D + The ROS [PointCloud2](https://github.com/ros2/common_interfaces/blob/humble/sensor_msgs/msg/PointCloud2.msg) message is stored as a binary blob that needs to be reinterpreted using the details about its fields. Each field is a named collection of offsets into the data buffer, and datatypes. The `sensor_msgs_py` package includes a `point_cloud2` @@ -277,6 +296,7 @@ Color is extracted in a similar way, although the realsense gazebo driver does n the r,g,b channels, requiring us to patch the field values. After extracting the positions and colors as numpy arrays, the entire cloud can be logged as a batch with `rr.Points3D` + ```python def points_callback(self, points: PointCloud2) -> None: """Log a `PointCloud2` with `log_points`.""" @@ -309,6 +329,7 @@ def points_callback(self, points: PointCloud2) -> None: ``` ### LaserScan to rr.LineStrips3D + Rerun does not yet have native support for a `LaserScan` style primitive so we need to do a bit of additional transformation logic (see: [#1534](https://github.com/rerun-io/rerun/issues/1534).) @@ -323,6 +344,7 @@ We generate a second matching set of points for each ray projected out 0.3m from the origin and then interlace the two sets of points using numpy hstack and reshape. This results in a set of alternating points defining rays from the origin to each laser scan result, which is the format expected by `rr.LineStrips3D`: + ```python def __init__(self) -> None: # … @@ -347,6 +369,7 @@ def scan_callback(self, scan: LaserScan) -> None: ``` ### URDF to rr.Mesh3D + The URDF conversion is actually the most complex operation in this example. As such the functionality is split out into a separate [rerun/examples/python/ros_node/rerun_urdf.py](https://github.com/rerun-io/rerun/blob/main/examples/python/ros_node/rerun_urdf.py) helper. @@ -356,6 +379,7 @@ Loading the URDF from the `/robot_description` topic is relatively straightforwa The main complication is that the actual mesh resources in that URDF need to be located via `ament`. Fortunately, `yourdfpy` accepts a filename handler, which we shim together with ament `get_package_share_directory`. + ```python def ament_locate_package(fname: str) -> str: """Helper to locate urdf resources via ament.""" @@ -381,6 +405,7 @@ camera link. Once we have correctly re-scaled the camera component, we can send the whole scene to rerun with `rerun_urdf.log_scene`. + ```python def urdf_callback(self, urdf_msg: String) -> None: """Log a URDF using `log_scene` from `rerun_urdf`.""" @@ -404,6 +429,7 @@ the trimesh scene graph. For each node, it extracts the transform to the parent, which it logs via `rr.Transform3D` before then using `rr.Mesh3D` to send the vertices, indices, and normals from the trimesh geometry. This code is almost entirely URDF-independent and is a good candidate for a future Python API ([#1536](https://github.com/rerun-io/rerun/issues/1536).) + ```python node_data = scene.graph.get(frame_to=node, frame_from=parent) @@ -436,9 +462,11 @@ if node_data: timeless=timeless, ) ``` + Color data is also extracted from the trimesh, but omitted here for brevity. ## In Summary + Although there is a non-trivial amount of code, none of it is overly complicated. Each message callback operates independently of the others, processing an incoming message, adapting it to Rerun and then logging it again. From dd40fa80ed1805f539502f80b104779301c86a21 Mon Sep 17 00:00:00 2001 From: Andreas Naoum <49308613+andreasnaoum@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:47:14 +0200 Subject: [PATCH 177/508] Updated READMEs for examples: LLM Embedding-Based Named Entity Recognition, nuScenes, Objectron, Open Photogrammetry Format, Raw Mesh (#5653) Updated READMEs for the examples: - LLM Embedding-Based Named Entity Recognition - nuScenes - Objectron - Open Photogrammetry Format - Raw Mesh ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5653/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5653/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5653/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5653) - [Docs preview](https://rerun.io/preview/fa36277713991adad32d6dbfc294a02d2c1798b4/docs) - [Examples preview](https://rerun.io/preview/fa36277713991adad32d6dbfc294a02d2c1798b4/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Nikolaus West Co-authored-by: Andreas Reich --- docs/cspell.json | 5 + examples/python/llm_embedding_ner/README.md | 91 ++++++++++++-- examples/python/nuscenes/README.md | 116 +++++++++++++++++- examples/python/objectron/README.md | 103 +++++++++++++++- .../open_photogrammetry_format/README.md | 81 +++++++++++- examples/python/raw_mesh/README.md | 67 +++++++++- examples/python/raw_mesh/main.py | 2 +- 7 files changed, 444 insertions(+), 21 deletions(-) diff --git a/docs/cspell.json b/docs/cspell.json index b595e623e43e..4d7fd48d623d 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -17,6 +17,7 @@ "andreasnaoum", "Angjoo", "Ankush", + "anns", "arflow", "arkit", "arkitscene", @@ -52,6 +53,7 @@ "booktitle", "braindump", "bringup", + "calib", "callstack", "callstacks", "camino", @@ -356,6 +358,7 @@ "Tete", "Tewari", "Texcoord", + "texcoords", "thiserror", "Tian", "timedelta", @@ -385,6 +388,8 @@ "upcasting", "upsampling", "upvote", + "UMAP", + "umap", "urdf", "URDF", "ureq", diff --git a/examples/python/llm_embedding_ner/README.md b/examples/python/llm_embedding_ner/README.md index d6ae8025d0b2..769b0daecc25 100644 --- a/examples/python/llm_embedding_ner/README.md +++ b/examples/python/llm_embedding_ner/README.md @@ -1,10 +1,10 @@ - @@ -13,15 +13,92 @@ thumbnail_dimensions = [480, 480] -This example visualizes [BERT-based named entity recognition (NER)](https://huggingface.co/dslim/bert-base-NER). It works by splitting text into tokens, feeding the token sequence into a large language model (BERT) to retrieve embeddings per token. The embeddings are then classified. +Visualize the [BERT-based named entity recognition (NER)](https://huggingface.co/dslim/bert-base-NER) with UMAP Embeddings. + +# Used Rerun Types +[`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) + +# Background +This example splits text into tokens, feeds the token sequence into a large language model (BERT), which outputs an embedding per token. +The embeddings are then classified into four types of entities: location (LOC), organizations (ORG), person (PER) and Miscellaneous (MISC). The embeddings are projected to a 3D space using [UMAP](https://umap-learn.readthedocs.io/en/latest), and visualized together with all other data in Rerun. + +# Logging and Visualizing with Rerun +The visualizations in this example were created with the following Rerun code: + +## Text +The logging begins with the original text. Following this, the tokenized version is logged for further analysis, and the named entities identified by the NER model are logged separately. +All texts are logged using [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) as a Markdown document to preserves structure and formatting. +### Original Text +```python +rr.log("text", rr.TextDocument(text, media_type=rr.MediaType.MARKDOWN)) +``` + +### Tokenized Text +```python +rr.log("tokenized_text", rr.TextDocument(markdown, media_type=rr.MediaType.MARKDOWN)) +``` + +### Named Entities +```python +rr.log("named_entities", rr.TextDocument(named_entities_str, media_type=rr.MediaType.MARKDOWN)) +``` + +## UMAP Embeddings + +[//]: # (The embeddings to UMAP facilitates the exploration, understanding, and evaluation of the NER model's output in a more interpretable and visually appealing manner.) + +UMAP is used in this example for dimensionality reduction and visualization of the embeddings generated by a Named Entity Recognition (NER) model. +UMAP preserves the essential structure and relationships between data points, and helps in identifying clusters or patterns within the named entities. + +After transforming the embeddings to UMAP, the next step involves defining labels for classes using [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context). +These labels help in interpreting the visualized data. +Subsequently, the UMAP embeddings are logged as [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) and visualized in a three-dimensional space. +The visualization can provide insights into how the NER model is performing and how different types of entities are distributed throughout the text. -To run this example use + +```python +# Define label for classes and set none class color to dark gray +annotation_context = [ + rr.AnnotationInfo(id=0, color=(30, 30, 30)), + rr.AnnotationInfo(id=1, label="Location"), + rr.AnnotationInfo(id=2, label="Person"), + rr.AnnotationInfo(id=3, label="Organization"), + rr.AnnotationInfo(id=4, label="Miscellaneous"), +] +rr.log("/", rr.AnnotationContext(annotation_context)) +``` + +```python +rr.log( + "umap_embeddings", + rr.Points3D(umap_embeddings, class_ids=class_ids), + rr.AnyValues(**{"Token": token_words, "Named Entity": entity_per_token(token_words, ner_results)}), +) +``` + + +# Run the Code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/llm_embedding_ner/requirements.txt -python examples/python/llm_embedding_ner/main.py ``` - -You can specify your own text using +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/llm_embedding_ner/main.py # run the example +``` +You can specify your own text using: +```bash +python examples/python/llm_embedding_ner/main.py [--text TEXT] +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: ```bash -main.py [--text TEXT] +python examples/python/llm_embedding_ner/main.py --help ``` diff --git a/examples/python/nuscenes/README.md b/examples/python/nuscenes/README.md index 8f716c101bb3..4fa6e215ead8 100644 --- a/examples/python/nuscenes/README.md +++ b/examples/python/nuscenes/README.md @@ -16,12 +16,118 @@ build_args = ["--seconds=5"]
-This example visualizes the [nuScenes dataset](https://www.nuscenes.org/) using Rerun. The dataset -contains lidar data, radar data, color images, and labeled bounding boxes. +Visualize the [nuScenes dataset](https://www.nuscenes.org/) including lidar, radar, images, and bounding boxes data. +# Used Rerun Types +[`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Image`](https://ref.rerun.io/docs/python/0.14.1/common/image_helpers/#rerun.ImageEncoded)* + +# Background +This example demonstrates the ability to read and visualize scenes from the nuScenes dataset, which is a public large-scale dataset specifically designed for autonomous driving. +The scenes in this dataset encompass data collected from a comprehensive suite of sensors on autonomous vehicles. +These include 6 cameras, 1 LIDAR, 5 RADAR, GPS and IMU sensors. +Consequently, the dataset provides information about the vehicle's pose, the images captured, the recorded sensor data and the results of object detection at any given moment. + + +# Logging and Visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## Sensor Calibration + +First, pinhole cameras and sensor poses are initialized to offer a 3D view and camera perspective. This is achieved using the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) and [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetypes. + +```python +rr.log( + f"world/ego_vehicle/{sensor_name}", + rr.Transform3D( + translation=calibrated_sensor["translation"], + rotation=rr.Quaternion(xyzw=rotation_xyzw), + from_parent=False, + ), + timeless=True, + ) +``` + +```python +rr.log( + f"world/ego_vehicle/{sensor_name}", + rr.Pinhole( + image_from_camera=calibrated_sensor["camera_intrinsic"], + width=sample_data["width"], + height=sample_data["height"], + ), + timeless=True, + ) +``` + +## Timelines + +All data logged using Rerun in the following sections is initially connected to a specific time. +Rerun assigns a timestamp to each piece of logged data, and these timestamps are associated with [`timelines`](https://www.rerun.io/docs/concepts/timelines). + +```python +rr.set_time_seconds("timestamp", sample_data["timestamp"] * 1e-6) +``` + + +## Vehicle Pose + +As the vehicle is moving, its pose needs to be updated. Consequently, the positions of pinhole cameras and sensors must also be adjusted using [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d). +```python +rr.log( + "world/ego_vehicle", + rr.Transform3D( + translation=ego_pose["translation"], + rotation=rr.Quaternion(xyzw=rotation_xyzw), + from_parent=False, + ), +) +``` + +## LiDAR Data +LiDAR data is logged as [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype. +```python +rr.log(f"world/ego_vehicle/{sensor_name}", rr.Points3D(points, colors=point_colors)) +``` + +## Camera Data +Camera data is logged as encoded images using [`ImageEncoded`](https://ref.rerun.io/docs/python/0.14.1/common/image_helpers/#rerun.ImageEncoded). +```python +rr.log(f"world/ego_vehicle/{sensor_name}", rr.ImageEncoded(path=data_file_path)) +``` + +## Radar Data +Radar data is logged similar to LiDAR data, as [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d). +```python +rr.log(f"world/ego_vehicle/{sensor_name}", rr.Points3D(points, colors=point_colors)) +``` + +## Annotations + +Annotations are logged as [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), containing details such as object positions, sizes, and rotation. +```python +rr.log("world/anns", rr.Boxes3D(sizes=sizes, centers=centers, rotations=rotations, class_ids=class_ids)) +``` + + +# Run the Code +To run this example, make sure you have Python version at least 3.9, the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/nuscenes/requirements.txt -python examples/python/nuscenes/main.py ``` - -Requires at least Python 3.9 to run. +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/nuscenes/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/nuscenes/main.py --help +``` diff --git a/examples/python/objectron/README.md b/examples/python/objectron/README.md index c1bfc41a39f3..ea02f705d6f3 100644 --- a/examples/python/objectron/README.md +++ b/examples/python/objectron/README.md @@ -16,11 +16,108 @@ build_args = ["--frames=150"] Objectron example screenshot
-Example of using the Rerun SDK to log the [Objectron](https://github.com/google-research-datasets/Objectron) dataset. +[//]: # (Visualize the [Google Research Objectron](https://github.com/google-research-datasets/Objectron) dataset, which contains camera poses, sparse point-clouds and characterization of the planar surfaces in the surrounding environment.) -> The Objectron dataset is a collection of short, object-centric video clips, which are accompanied by AR session metadata that includes camera poses, sparse point-clouds and characterization of the planar surfaces in the surrounding environment. +Visualize the [Google Research Objectron](https://github.com/google-research-datasets/Objectron) dataset including camera poses, sparse point-clouds and surfaces characterization. +# Used Rerun Types + [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), [`Image`](https://ref.rerun.io/docs/python/0.14.1/common/image_helpers/#rerun.ImageEncoded)*, [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) + +# Background + +This example visualizes the Objectron database, a rich collection of object-centric video clips accompanied by AR session metadata. +With high-resolution images, object pose, camera pose, point-cloud, and surface plane information available for each sample, the visualization offers a comprehensive view of the object from various angles. +Additionally, the dataset provides manually annotated 3D bounding boxes, enabling precise object localization and orientation. + +# Logging and Visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## Timelines + +For each processed frame, all data sent to Rerun is associated with the two [`timelines`](https://www.rerun.io/docs/concepts/timelines) `time` and `frame_idx`. + +```python +rr.set_time_sequence("frame", sample.index) +rr.set_time_seconds("time", sample.timestamp) +``` + +## Video + +Pinhole camera is utilized for achieving a 3D view and camera perspective through the use of the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) and [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetypes. + +```python +rr.log( + "world/camera", + rr.Transform3D(translation=translation, rotation=rr.Quaternion(xyzw=rot.as_quat())), +) +``` + +```python +rr.log( + "world/camera", + rr.Pinhole( + resolution=[w, h], + image_from_camera=intrinsics, + camera_xyz=rr.ViewCoordinates.RDF, + ), +) +``` +The input video is logged as a sequence of [`ImageEncoded`](https://ref.rerun.io/docs/python/0.14.1/common/image_helpers/#rerun.ImageEncoded) objects to the `world/camera` entity. +```python +rr.log("world/camera", rr.ImageEncoded(path=sample.image_path)) +``` + +## Sparse Point Clouds + +Sparse point clouds from `ARFrame` are logged as [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype to the `world/points` entity. + +```python +rr.log("world/points", rr.Points3D(positions, colors=[255, 255, 255, 255])) +``` + +## Annotated Bounding Boxes + +Bounding boxes annotated from `ARFrame` are logged as [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), containing details such as object position, sizes, center and rotation. + +```python +rr.log( + f"world/annotations/box-{bbox.id}", + rr.Boxes3D( + half_sizes=0.5 * np.array(bbox.scale), + centers=bbox.translation, + rotations=rr.Quaternion(xyzw=rot.as_quat()), + colors=[160, 230, 130, 255], + labels=bbox.category, + ), + timeless=True, +) +``` + +# Run the Code +To run this example, make sure you have Python version at least 3.9, the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/objectron/requirements.txt -python examples/python/objectron/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/objectron/main.py # run the example +``` + +You can specify the objectron recording: +```bash +python examples/python/objectron/main.py --recording {bike,book,bottle,camera,cereal_box,chair,cup,laptop,shoe} +``` + +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/objectron/main.py --help ``` diff --git a/examples/python/open_photogrammetry_format/README.md b/examples/python/open_photogrammetry_format/README.md index 8ee8f926c22e..9d36a9823a4d 100644 --- a/examples/python/open_photogrammetry_format/README.md +++ b/examples/python/open_photogrammetry_format/README.md @@ -19,10 +19,85 @@ build_args = ["--jpeg-quality=50"] Uses [`pyopf`](https://github.com/Pix4D/pyopf) to load and display a photogrammetrically reconstructed 3D point cloud in the [Open Photogrammetry Format (OPF)](https://www.pix4d.com/open-photogrammetry-format/). +# Used Rerun Types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) +# Background + +This example loads an Open Photogrammetry Format (OPF) project and displays the cameras and point cloud data. +OPF, which stands for 'open photogrammetry format,' is a file format used for photogrammetry data. +It contains all the necessary information related to a reconstructed 3D model made with photogrammetry, including calibration, point clouds and dense reconstruction. + +# Logging and Visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## Timelines + + For each processed frame, all data sent to Rerun is associated with specific time using [`timelines`](https://www.rerun.io/docs/concepts/timelines). + +```python +rr.set_time_sequence("image", i) +``` + +## Video + +Pinhole camera is utilized for achieving a 3D view and camera perspective through the use of the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) and [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetypes. + +```python +rr.log( + "world/cameras", + rr.Transform3D(translation=calib_camera.position, mat3x3=rot) +) +``` + +```python +rr.log( + "world/cameras/image", + rr.Pinhole( + resolution=sensor.image_size_px, + focal_length=calib_sensor.internals.focal_length_px, + principal_point=calib_sensor.internals.principal_point_px, + camera_xyz=rr.ViewCoordinates.RUB, + ), +) +``` +The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) objects to the `world/cameras/image/rgb` entity. +```python +rr.log("world/cameras/image/rgb", rr.Image(np.array(img)).compress(jpeg_quality=jpeg_quality)) +``` + +## Point Clouds + +Point clouds from the project are logged as [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype to the `world/points` entity. + +```python +rr.log("world/points", rr.Points3D(points.position, colors=points.color), timeless=True) +``` + + +# Run the Code + + +> This example requires Python 3.10 or higher because of [`pyopf`](https://pypi.org/project/pyopf/). + +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/open_photogrammetry_format/requirements.txt -python examples/python/open_photogrammetry_format/main.py ``` - -Requires Python 3.10 or higher because of [`pyopf`](https://pypi.org/project/pyopf/). +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/open_photogrammetry_format/main.py # run the example +``` +If you wish to customize it or explore additional features, use the CLI with the `--help` option for guidance: +```bash +python examples/python/open_photogrammetry_format/main.py --help +``` diff --git a/examples/python/raw_mesh/README.md b/examples/python/raw_mesh/README.md index f97e05850902..f0d1a6d7d7ac 100644 --- a/examples/python/raw_mesh/README.md +++ b/examples/python/raw_mesh/README.md @@ -15,9 +15,72 @@ channel = "release"
-This example demonstrates how to use the Rerun SDK to log raw 3D meshes (so-called "triangle soups") and their transform hierarchy. Simple material properties are supported. +Demonstrates logging of raw 3D mesh data (so-called "triangle soups") with simple material properties and their transform hierarchy. +# Used Rerun Types +[`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Mesh3D`](https://www.rerun.io/docs/reference/types/archetypes/mesh3d) + +# Background +Raw 3D mesh data refers to the basic geometric representation of a three-dimensional object, typically composed of interconnected triangles. +These triangles collectively form the surface of the object, defining its shape and structure in a digital environment. +Rerun was employed to visualize and manage this raw mesh data, along with its associated simple material properties and transform hierarchy. + + +# Logging and Visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## 3D Mesh Data +The raw 3D mesh data are logged as [`Mesh3D`](https://www.rerun.io/docs/reference/types/archetypes/mesh3d) objects, and includes details about vertex positions, colors, normals, texture coordinates, material properties, and face indices for an accurate reconstruction and visualization. + +```python +rr.log( + path, + rr.Mesh3D( + vertex_positions=mesh.vertices, + vertex_colors=vertex_colors, + vertex_normals=mesh.vertex_normals, + vertex_texcoords=vertex_texcoords, + albedo_texture=albedo_texture, + indices=mesh.faces, + mesh_material=mesh_material, + ), +) +``` +Through Rerun's [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetype, essential details are captured to ensure precise positioning and orientation of meshes within the 3D scene. +```python +rr.log( + path, + rr.Transform3D( + translation=trimesh.transformations.translation_from_matrix(world_from_mesh), + mat3x3=world_from_mesh[0:3, 0:3], + ), +) +``` + + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/raw_mesh/requirements.txt -python examples/python/raw_mesh/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/raw_mesh/main.py # run the example +``` +You can specify scene: +```bash +python examples/python/objectron/main.py --scene {lantern,avocado,buggy,brain_stem} +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/raw_mesh/main.py --help ``` diff --git a/examples/python/raw_mesh/main.py b/examples/python/raw_mesh/main.py index 5ffacf3c9560..7b92e7097fd5 100755 --- a/examples/python/raw_mesh/main.py +++ b/examples/python/raw_mesh/main.py @@ -39,7 +39,7 @@ def log_scene(scene: trimesh.Scene, node: str, path: str | None = None) -> None: if node_data: # Log the transform between this node and its direct parent (if it has one!). if parent: - # TODO(andreas): We should support 4x4 matrices directly + # TODO(#3559): We should support 4x4 matrices directly world_from_mesh = node_data[0] rr.log( path, From df4c13007102aa08f7c1694b06ae9b3789ed718b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Apr 2024 13:11:16 +0200 Subject: [PATCH 178/508] Show all loaded applications in recordings panel (#5766) * Closes #5672 * Closes #5694 ### What * Show all loaded applications in the recordings panel * Even those with no recordings * Even welcome screen * Close application when last recording of that app is closed * Add button to close all recordings in an application * Make applications selectable * When loading a blueprint, switch to its application Being able to quickly select the welcome screen is super useful while exploring examples, and for testing. It is also the natural place to return to to find the links to the docs, and maybe more stuff in the future. ### Demo At the start here I have pulled in a blueprint for arkit, but no recording for it https://github.com/rerun-io/rerun/assets/1148717/8d7d1fdf-73a1-4eed-b074-5f541ce29384 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5766) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5766?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5766?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5766) - [Docs preview](https://rerun.io/preview/de52f74ec9b8a94b4e82abe41dc5c50b9293ee2e/docs) - [Examples preview](https://rerun.io/preview/de52f74ec9b8a94b4e82abe41dc5c50b9293ee2e/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/app_id.rs | 55 +++++ crates/re_data_ui/src/data_source.rs | 37 ++-- crates/re_data_ui/src/editors.rs | 2 +- crates/re_data_ui/src/entity_db.rs | 4 +- crates/re_data_ui/src/item_ui.rs | 53 +++-- crates/re_data_ui/src/lib.rs | 1 + crates/re_entity_db/src/store_bundle.rs | 15 +- crates/re_space_view_spatial/src/ui_3d.rs | 2 +- crates/re_ui/data/icons/application.png | Bin 0 -> 308 bytes crates/re_ui/examples/re_ui_example.rs | 2 +- crates/re_ui/src/drag_and_drop.rs | 2 +- crates/re_ui/src/icons.rs | 4 + crates/re_ui/src/lib.rs | 28 ++- crates/re_viewer/src/app.rs | 16 +- crates/re_viewer/src/app_state.rs | 8 +- crates/re_viewer/src/ui/recordings_panel.rs | 193 ++++++++++++------ crates/re_viewer/src/ui/rerun_menu.rs | 6 + .../re_viewer/src/ui/selection_history_ui.rs | 1 + crates/re_viewer/src/ui/selection_panel.rs | 21 +- .../src/ui/space_view_space_origin_ui.rs | 15 +- crates/re_viewer_context/src/app_options.rs | 5 + .../re_viewer_context/src/command_sender.rs | 6 + .../src/component_ui_registry.rs | 2 +- crates/re_viewer_context/src/item.rs | 16 +- .../re_viewer_context/src/selection_state.rs | 12 +- crates/re_viewer_context/src/store_hub.rs | 67 +++++- .../actions/collapse_expand_all.rs | 5 +- crates/re_viewport/src/context_menu/mod.rs | 4 + .../re_viewport/src/space_view_highlights.rs | 12 +- crates/re_viewport/src/viewport.rs | 8 +- crates/re_viewport/src/viewport_blueprint.rs | 12 +- .../re_viewport/src/viewport_blueprint_ui.rs | 4 +- 32 files changed, 450 insertions(+), 168 deletions(-) create mode 100644 crates/re_data_ui/src/app_id.rs create mode 100644 crates/re_ui/data/icons/application.png diff --git a/crates/re_data_ui/src/app_id.rs b/crates/re_data_ui/src/app_id.rs new file mode 100644 index 000000000000..47330d44ee7f --- /dev/null +++ b/crates/re_data_ui/src/app_id.rs @@ -0,0 +1,55 @@ +use itertools::Itertools as _; + +use re_entity_db::EntityDb; +use re_log_types::ApplicationId; +use re_viewer_context::{UiVerbosity, ViewerContext}; + +use crate::item_ui::entity_db_button_ui; + +impl crate::DataUi for ApplicationId { + fn data_ui( + &self, + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + verbosity: UiVerbosity, + _query: &re_data_store::LatestAtQuery, + _store: &re_data_store::DataStore, + ) { + egui::Grid::new("application_id") + .num_columns(2) + .show(ui, |ui| { + ui.label("Application ID"); + ui.label(self.to_string()); + if self == &ctx.store_context.app_id { + ui.label("(active)"); + } + ui.end_row(); + }); + + if verbosity == UiVerbosity::Small { + return; + } + + // Find all recordings with this app id + let recordings: Vec<&EntityDb> = ctx + .store_context + .bundle + .recordings() + .filter(|db| db.app_id() == Some(self)) + .sorted_by_key(|entity_db| entity_db.store_info().map(|info| info.started)) + .collect(); + + if !recordings.is_empty() { + ui.scope(|ui| { + ui.set_clip_rect(ui.max_rect()); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect. + ui.spacing_mut().item_spacing.y = 0.0; + + ui.add_space(8.0); + ui.strong("Loaded recordings for this app"); + for entity_db in recordings { + entity_db_button_ui(ctx, ui, entity_db, true); + } + }); + } + } +} diff --git a/crates/re_data_ui/src/data_source.rs b/crates/re_data_ui/src/data_source.rs index da731ed2029f..b1e90ccf1977 100644 --- a/crates/re_data_ui/src/data_source.rs +++ b/crates/re_data_ui/src/data_source.rs @@ -28,7 +28,8 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { for other in ctx .store_context .bundle - .entity_dbs_from_channel_source(self) + .entity_dbs() + .filter(|db| db.data_source.as_ref() == Some(self)) { let is_clone = other.cloned_from().is_some(); if is_clone { @@ -46,30 +47,28 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { } } - if !recordings.is_empty() { - ui.add_space(8.0); - ui.strong("Recordings from this data source"); - let max_rect = ui.max_rect(); - ui.indent("recordings", |ui| { - ui.set_clip_rect(max_rect); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect. - ui.spacing_mut().item_spacing.y = 0.0; + recordings.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started)); + blueprints.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started)); + + ui.scope(|ui| { + ui.set_clip_rect(ui.max_rect()); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect. + ui.spacing_mut().item_spacing.y = 0.0; + + if !recordings.is_empty() { + ui.add_space(8.0); + ui.strong("Recordings from this data source"); for entity_db in recordings { entity_db_button_ui(ctx, ui, entity_db, true); } - }); - } + } - if !blueprints.is_empty() { - ui.add_space(8.0); - ui.strong("Blueprints from this data source"); - let max_rect = ui.max_rect(); - ui.indent("blueprints", |ui| { - ui.set_clip_rect(max_rect); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect. - ui.spacing_mut().item_spacing.y = 0.0; + if !blueprints.is_empty() { + ui.add_space(8.0); + ui.strong("Blueprints from this data source"); for entity_db in blueprints { entity_db_button_ui(ctx, ui, entity_db, true); } - }); - } + } + }); } } diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index 2886043d7e3c..f00b01b17bcc 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -270,7 +270,7 @@ fn edit_marker_shape_ui( ); for marker in MarkerShape::ALL { - let list_item = re_ui::list_item::ListItem::new(ctx.re_ui, marker.to_string()) + let list_item = re_ui::ListItem::new(ctx.re_ui, marker.to_string()) .with_icon_fn(|_re_ui, ui, rect, visuals| { paint_marker(ui, marker.into(), rect, visuals.text_color()); }) diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index a47eaf51b2d4..56ae67f0a934 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -3,7 +3,7 @@ use re_log_types::StoreKind; use re_types::SizeBytes; use re_viewer_context::{UiVerbosity, ViewerContext}; -use crate::item_ui::data_source_button_ui; +use crate::item_ui::{app_id_button_ui, data_source_button_ui}; impl crate::DataUi for EntityDb { fn data_ui( @@ -54,7 +54,7 @@ impl crate::DataUi for EntityDb { } re_ui.grid_left_hand_label(ui, "Application ID"); - ui.label(application_id.to_string()); + app_id_button_ui(ctx, ui, application_id); ui.end_row(); re_ui.grid_left_hand_label(ui, "Source"); diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 35faaf4c0206..db25d48b83fb 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -3,7 +3,7 @@ //! TODO(andreas): This is not a `data_ui`, can this go somewhere else, shouldn't be in `re_data_ui`. use re_entity_db::{EntityTree, InstancePath}; -use re_log_types::{ComponentPath, EntityPath, TimeInt, Timeline}; +use re_log_types::{ApplicationId, ComponentPath, EntityPath, TimeInt, Timeline}; use re_ui::{icons, SyntaxHighlighting}; use re_viewer_context::{HoverHighlight, Item, SpaceViewId, UiVerbosity, ViewerContext}; @@ -551,6 +551,34 @@ pub fn entity_hover_card_ui( instance_hover_card_ui(ui, ctx, query, store, &instance_path); } +pub fn app_id_button_ui( + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + app_id: &ApplicationId, +) -> egui::Response { + let item = Item::AppId(app_id.clone()); + + let response = ctx.re_ui.selectable_label_with_icon( + ui, + &icons::APPLICATION, + app_id.to_string(), + ctx.selection().contains_item(&item), + re_ui::LabelStyle::Normal, + ); + + let response = response.on_hover_ui(|ui| { + app_id.data_ui( + ctx, + ui, + re_viewer_context::UiVerbosity::Reduced, + &ctx.current_query(), // unused + ctx.recording_store(), // unused + ); + }); + + cursor_interact_with_selectable(ctx, response, item) +} + pub fn data_source_button_ui( ctx: &ViewerContext<'_>, ui: &mut egui::Ui, @@ -579,6 +607,7 @@ pub fn data_source_button_ui( cursor_interact_with_selectable(ctx, response, item) } +/// This uses [`re_ui::ListItem::show_hierarchical`], meaning it comes with built-in indentation. pub fn store_id_button_ui( ctx: &ViewerContext<'_>, ui: &mut egui::Ui, @@ -594,6 +623,8 @@ pub fn store_id_button_ui( /// Show button for a store (recording or blueprint). /// /// You can set `include_app_id` to hide the App Id, but usually you want to show it. +/// +/// This uses [`re_ui::ListItem::show_hierarchical`], meaning it comes with built-in indentation. pub fn entity_db_button_ui( ctx: &ViewerContext<'_>, ui: &mut egui::Ui, @@ -666,17 +697,15 @@ pub fn entity_db_button_ui( list_item = list_item.force_hovered(true); } - let response = list_item - .show_flat(ui) // never more than one level deep - .on_hover_ui(|ui| { - entity_db.data_ui( - ctx, - ui, - re_viewer_context::UiVerbosity::Reduced, - &ctx.current_query(), - entity_db.store(), - ); - }); + let response = list_item.show_hierarchical(ui).on_hover_ui(|ui| { + entity_db.data_ui( + ctx, + ui, + re_viewer_context::UiVerbosity::Reduced, + &ctx.current_query(), + entity_db.store(), + ); + }); if response.hovered() { ctx.selection_state().set_hovered(item.clone()); diff --git a/crates/re_data_ui/src/lib.rs b/crates/re_data_ui/src/lib.rs index 4a513b8ed30e..24f54eb4fa20 100644 --- a/crates/re_data_ui/src/lib.rs +++ b/crates/re_data_ui/src/lib.rs @@ -9,6 +9,7 @@ use re_types::ComponentName; use re_viewer_context::{UiVerbosity, ViewerContext}; mod annotation_context; +mod app_id; mod blueprint_data; mod component; mod component_path; diff --git a/crates/re_entity_db/src/store_bundle.rs b/crates/re_entity_db/src/store_bundle.rs index 2e4ee2b562ea..79280822ae9b 100644 --- a/crates/re_entity_db/src/store_bundle.rs +++ b/crates/re_entity_db/src/store_bundle.rs @@ -56,8 +56,8 @@ impl StoreBundle { } } - pub fn remove(&mut self, id: &StoreId) { - self.entity_dbs.remove(id); + pub fn remove(&mut self, id: &StoreId) -> Option { + self.entity_dbs.remove(id) } // -- @@ -134,16 +134,6 @@ impl StoreBundle { .filter(|log| log.store_kind() == StoreKind::Blueprint) } - /// All stores that came from the given source - pub fn entity_dbs_from_channel_source<'a>( - &'a self, - source: &'a re_smart_channel::SmartChannelSource, - ) -> impl Iterator + 'a { - self.entity_dbs - .values() - .filter(move |db| db.data_source.as_ref() == Some(source)) - } - // -- pub fn retain(&mut self, mut f: impl FnMut(&EntityDb) -> bool) { @@ -154,6 +144,7 @@ impl StoreBundle { self.entity_dbs.retain(|_, entity_db| !entity_db.is_empty()); } + /// In no particular order. pub fn drain_entity_dbs(&mut self) -> impl Iterator + '_ { self.entity_dbs.drain().map(|(_, store)| store) } diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index d9b9610e7656..4042662fca6c 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -552,7 +552,7 @@ pub fn view_3d( // Track focused entity if any. if let Some(focused_item) = ctx.focused_item { let focused_entity = match focused_item { - Item::DataSource(_) | Item::StoreId(_) | Item::Container(_) => None, + Item::AppId(_) | Item::DataSource(_) | Item::StoreId(_) | Item::Container(_) => None, Item::SpaceView(space_view_id) => { if space_view_id == &query.space_view_id { diff --git a/crates/re_ui/data/icons/application.png b/crates/re_ui/data/icons/application.png new file mode 100644 index 0000000000000000000000000000000000000000..d74874d42938545cb672f9522021e3756521430e GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^vOp}u!3HGfp5L+xNO2Z;L>4nJh^c}wqi2xH2cRHh zage(c!@6@aFM%AEbVpxD28NCO+f5Y_sn#iaaslw_nS?j*ynM zCpKmHuV2cj*paNiWL@U0?rm3iuk_bkoVM=%6{V9OSE?OV`jp|c?2e+gPwtb(iPB>H zxi77sUC9@mztUas-ixQaKMVG%#lBnlpOq_QCJTT3roZKvGd~;!dWyl*)z4*}Q$iB} D&k1}N literal 0 HcmV?d00001 diff --git a/crates/re_ui/examples/re_ui_example.rs b/crates/re_ui/examples/re_ui_example.rs index abdc8c276628..a035b9a5b2de 100644 --- a/crates/re_ui/examples/re_ui_example.rs +++ b/crates/re_ui/examples/re_ui_example.rs @@ -1,4 +1,4 @@ -use re_ui::list_item::ListItem; +use re_ui::ListItem; use re_ui::{toasts, CommandPalette, ReUi, UICommand, UICommandSender}; /// Sender that queues up the execution of a command. diff --git a/crates/re_ui/src/drag_and_drop.rs b/crates/re_ui/src/drag_and_drop.rs index 38577c360d74..c5afaea9dbe7 100644 --- a/crates/re_ui/src/drag_and_drop.rs +++ b/crates/re_ui/src/drag_and_drop.rs @@ -1,6 +1,6 @@ //! Helpers for drag and drop support for reordering hierarchical lists. //! -//! Works well in combination with [`crate::list_item::ListItem`]. +//! Works well in combination with [`crate::ListItem`]. pub enum ItemKind { /// Root container item. diff --git a/crates/re_ui/src/icons.rs b/crates/re_ui/src/icons.rs index 6b00a11fdaff..3cbe39ec496f 100644 --- a/crates/re_ui/src/icons.rs +++ b/crates/re_ui/src/icons.rs @@ -143,6 +143,10 @@ pub const ENTITY_EMPTY: Icon = Icon::new( pub const LINK: Icon = Icon::new("link", include_bytes!("../data/icons/link.png")); pub const COMPONENT: Icon = Icon::new("component", include_bytes!("../data/icons/component.png")); +pub const APPLICATION: Icon = Icon::new( + "application", + include_bytes!("../data/icons/application.png"), +); pub const DATA_SOURCE: Icon = Icon::new( "data_source", include_bytes!("../data/icons/data_source.png"), diff --git a/crates/re_ui/src/lib.rs b/crates/re_ui/src/lib.rs index 6bbe9b05ca7b..88c6d1cec05f 100644 --- a/crates/re_ui/src/lib.rs +++ b/crates/re_ui/src/lib.rs @@ -13,13 +13,16 @@ pub mod list_item; pub mod modal; pub mod toasts; -pub use command::{UICommand, UICommandSender}; -pub use command_palette::CommandPalette; -pub use design_tokens::DesignTokens; -pub use icons::Icon; -pub use layout_job_builder::LayoutJobBuilder; -pub use syntax_highlighting::SyntaxHighlighting; -pub use toggle_switch::toggle_switch; +pub use self::{ + command::{UICommand, UICommandSender}, + command_palette::CommandPalette, + design_tokens::DesignTokens, + icons::Icon, + layout_job_builder::LayoutJobBuilder, + list_item::ListItem, + syntax_highlighting::SyntaxHighlighting, + toggle_switch::toggle_switch, +}; // --------------------------------------------------------------------------- @@ -62,10 +65,11 @@ pub enum LabelStyle { // ---------------------------------------------------------------------------- -use crate::list_item::ListItem; use egui::emath::{Rangef, Rot2}; -use egui::epaint::util::FloatOrd; -use egui::{pos2, Align2, CollapsingResponse, Color32, Mesh, NumExt, Rect, Shape, Vec2, Widget}; +use egui::{ + epaint::util::FloatOrd, pos2, Align2, CollapsingResponse, Color32, Mesh, NumExt, Rect, Shape, + Vec2, Widget, +}; #[derive(Clone)] pub struct ReUi { @@ -538,7 +542,7 @@ impl ReUi { } /// Popup similar to [`egui::popup_below_widget`] but suitable for use with - /// [`crate::list_item::ListItem`]. + /// [`crate::ListItem`]. pub fn list_item_popup( ui: &egui::Ui, popup_id: egui::Id, @@ -931,6 +935,8 @@ impl ReUi { } /// Workaround for putting a label into a grid at the top left of its row. + /// + /// You only need to use this if you expect the right side to have multi-line entries. #[allow(clippy::unused_self)] pub fn grid_left_hand_label(&self, ui: &mut egui::Ui, label: &str) -> egui::Response { ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| { diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index e85cd7ec3896..7587c8128ebe 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -336,6 +336,14 @@ impl App { egui_ctx: &egui::Context, ) { match cmd { + SystemCommand::ActivateApp(app_id) => { + store_hub.set_active_app(app_id); + } + + SystemCommand::CloseApp(app_id) => { + store_hub.close_app(&app_id); + } + SystemCommand::ActivateRecording(store_id) => { store_hub.set_activate_recording(store_id); } @@ -971,6 +979,11 @@ impl App { StoreKind::Recording => { re_log::debug!("Opening a new recording: {store_id}"); store_hub.set_active_recording_id(store_id.clone()); + + // Also select the new recording: + self.command_sender.send_system(SystemCommand::SetSelection( + re_viewer_context::Item::StoreId(store_id.clone()), + )); } StoreKind::Blueprint => { // We wait with activating blueprints until they are fully loaded, @@ -983,7 +996,7 @@ impl App { } LogMsg::ArrowMsg(_, _) => { - // Andled by EntityDb::add + // Handled by `EntityDb::add` } LogMsg::BlueprintActivationCommand(cmd) => match store_id.kind { @@ -1007,6 +1020,7 @@ impl App { .unwrap_or_else(|err| { re_log::warn!("Failed to make blueprint active: {err}"); }); + store_hub.set_active_app(app_id); // Switch to this app, e.g. on drag-and-drop of a blueprint file } } else { re_log::warn!( diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 8d6f72986307..459d1b585721 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -172,7 +172,7 @@ impl AppState { } } - viewport.is_item_valid(item) + viewport.is_item_valid(store_context, item) }, re_viewer_context::Item::StoreId(store_context.recording.store_id().clone()), ); @@ -354,9 +354,11 @@ impl AppState { // before drawing the blueprint panel. ui.spacing_mut().item_spacing.y = 0.0; - let recording_shown = recordings_panel_ui(&ctx, rx, ui); + let pre_cursor = ui.cursor(); + recordings_panel_ui(&ctx, rx, ui); + let any_recording_shows = pre_cursor == ui.cursor(); - if recording_shown { + if any_recording_shows { ui.add_space(4.0); } diff --git a/crates/re_viewer/src/ui/recordings_panel.rs b/crates/re_viewer/src/ui/recordings_panel.rs index 64c96c745cb8..66756c407a58 100644 --- a/crates/re_viewer/src/ui/recordings_panel.rs +++ b/crates/re_viewer/src/ui/recordings_panel.rs @@ -1,24 +1,24 @@ use std::collections::BTreeMap; -use re_data_ui::item_ui::entity_db_button_ui; -use re_log_types::LogMsg; +use re_data_ui::{item_ui::entity_db_button_ui, DataUi}; +use re_entity_db::EntityDb; +use re_log_types::{ApplicationId, LogMsg, StoreKind}; use re_smart_channel::{ReceiveSet, SmartChannelSource}; -use re_viewer_context::ViewerContext; +use re_ui::icons; +use re_viewer_context::{ + Item, StoreHub, SystemCommand, SystemCommandSender, UiVerbosity, ViewerContext, +}; /// Show the currently open Recordings in a selectable list. /// Also shows the currently loading receivers. -/// -/// Returns `true` if any recordings were shown. -pub fn recordings_panel_ui( - ctx: &ViewerContext<'_>, - rx: &ReceiveSet, - ui: &mut egui::Ui, -) -> bool { +pub fn recordings_panel_ui(ctx: &ViewerContext<'_>, rx: &ReceiveSet, ui: &mut egui::Ui) { ctx.re_ui.panel_content(ui, |re_ui, ui| { re_ui.panel_title_bar_with_buttons( ui, "Recordings", - Some("These are the Recordings currently loaded in the Viewer"), + Some( + "These are the Recordings currently loaded in the Viewer, organized by application", + ), |ui| { add_button_ui(ctx, ui); }, @@ -31,24 +31,16 @@ pub fn recordings_panel_ui( .max_height(300.) .show(ui, |ui| { ctx.re_ui.panel_content(ui, |_re_ui, ui| { - let mut any_shown = false; - any_shown |= recording_list_ui(ctx, ui); + recording_list_ui(ctx, ui); // Show currently loading things after. // They will likely end up here as recordings soon. - any_shown |= loading_receivers_ui(ctx, rx, ui); - - any_shown - }) - }) - .inner + loading_receivers_ui(ctx, rx, ui); + }); + }); } -fn loading_receivers_ui( - ctx: &ViewerContext<'_>, - rx: &ReceiveSet, - ui: &mut egui::Ui, -) -> bool { +fn loading_receivers_ui(ctx: &ViewerContext<'_>, rx: &ReceiveSet, ui: &mut egui::Ui) { let sources_with_stores: ahash::HashSet = ctx .store_context .bundle @@ -56,8 +48,6 @@ fn loading_receivers_ui( .filter_map(|store| store.data_source.clone()) .collect(); - let mut any_shown = false; - for source in rx.sources() { let string = match source.as_ref() { // We only show things we know are very-soon-to-be recordings: @@ -79,7 +69,6 @@ fn loading_receivers_ui( // Note that usually there is a one-to-one mapping between a source and a recording, // but it is possible to send multiple recordings over the same channel. if !sources_with_stores.contains(&source) { - any_shown = true; let response = ctx .re_ui .list_item(string) @@ -98,54 +87,130 @@ fn loading_receivers_ui( } } } - - any_shown } /// Draw the recording list. -/// -/// Returns `true` if any recordings were shown. -fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) -> bool { - let mut entity_dbs_map: BTreeMap<_, Vec<_>> = BTreeMap::new(); - for entity_db in ctx.store_context.bundle.recordings() { - let key = entity_db - .store_info() - .map_or("", |info| info.application_id.as_str()); - entity_dbs_map.entry(key).or_default().push(entity_db); - } +fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { + let mut entity_dbs_map: BTreeMap> = BTreeMap::new(); - if entity_dbs_map.is_empty() { - return false; + for entity_db in ctx.store_context.bundle.entity_dbs() { + // We want to show all open applications, even if they have no recordings + let Some(app_id) = entity_db.app_id().cloned() else { + continue; // this only happens if we haven't even started loading it, or if something is really wrong with it. + }; + let recordings = entity_dbs_map.entry(app_id).or_default(); + + if entity_db.store_kind() == StoreKind::Recording { + recordings.push(entity_db); + } } - for entity_dbs in entity_dbs_map.values_mut() { - entity_dbs.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started)); + if let Some(entity_dbs) = entity_dbs_map.remove(&StoreHub::welcome_screen_app_id()) { + // Always show welcome screen first, if at all: + if ctx + .app_options + .include_welcome_screen_button_in_recordings_panel + { + debug_assert!( + entity_dbs.is_empty(), + "There shouldn't be any recording for the welcome screen, but there are!" + ); + app_and_its_recordings_ui( + ctx, + ui, + &StoreHub::welcome_screen_app_id(), + Default::default(), + ); + } } for (app_id, entity_dbs) in entity_dbs_map { - if entity_dbs.len() == 1 { - let entity_db = entity_dbs[0]; - let include_app_id = true; - entity_db_button_ui(ctx, ui, entity_db, include_app_id); - } else { - ctx.re_ui - .list_item(app_id) - .interactive(false) - .show_hierarchical_with_content( - ui, - ui.make_persistent_id(app_id), - true, - |_, ui| { - for entity_db in entity_dbs { - let include_app_id = false; // we already show it in the parent - entity_db_button_ui(ctx, ui, entity_db, include_app_id); - } - }, - ); - } + app_and_its_recordings_ui(ctx, ui, &app_id, entity_dbs); } +} - true +fn app_and_its_recordings_ui( + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + app_id: &ApplicationId, + mut entity_dbs: Vec<&EntityDb>, +) { + entity_dbs.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started)); + + let app_item = Item::AppId(app_id.clone()); + let selected = ctx.selection().contains_item(&app_item); + + let app_list_item = ctx + .re_ui + .list_item(app_id.to_string()) + .selected(selected) + .with_icon_fn(|_re_ui, ui, rect, visuals| { + // Color icon based on whether this is the active application or not: + let color = if &ctx.store_context.app_id == app_id { + visuals.fg_stroke.color + } else { + ui.visuals().widgets.noninteractive.fg_stroke.color + }; + icons::APPLICATION.as_image().tint(color).paint_at(ui, rect); + }); + + let item_response = if app_id == &StoreHub::welcome_screen_app_id() { + // Special case: the welcome screen never has any recordings + debug_assert!( + entity_dbs.is_empty(), + "There shouldn't be any recording for the welcome screen, but there are!" + ); + app_list_item.show_hierarchical(ui) + } else { + // Normal application + let id = ui.make_persistent_id(app_id); + app_list_item + .with_buttons(|re_ui, ui| { + // Close-button: + let resp = re_ui.small_icon_button(ui, &icons::REMOVE).on_hover_text( + "Close this application and all its recordings. This cannot be undone.", + ); + if resp.clicked() { + ctx.command_sender + .send_system(SystemCommand::CloseApp(app_id.clone())); + } + resp + }) + .show_hierarchical_with_content(ui, id, true, |_, ui| { + // Show all the recordings for this application: + if entity_dbs.is_empty() { + ui.weak("(no recordings)").on_hover_ui(|ui| { + ui.label("No recordings loaded for this application"); + }); + } else { + for entity_db in entity_dbs { + let include_app_id = false; // we already show it in the parent + entity_db_button_ui(ctx, ui, entity_db, include_app_id); + } + } + }) + .item_response + }; + + let item_response = item_response.on_hover_ui(|ui| { + app_id.data_ui( + ctx, + ui, + UiVerbosity::Reduced, + &ctx.current_query(), // unused + ctx.recording_store(), // unused + ); + }); + + ctx.select_hovered_on_click(&item_response, app_item); + + if item_response.clicked() { + // Switch to this application: + ctx.command_sender + .send_system(re_viewer_context::SystemCommand::ActivateApp( + app_id.clone(), + )); + } } fn add_button_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index 84356f86840c..e9270b132751 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -335,6 +335,12 @@ fn options_menu_ui( .on_hover_text("Display timestamps in seconds since unix epoch"); }); + re_ui.checkbox( + ui, + &mut app_options.include_welcome_screen_button_in_recordings_panel, + "Show 'Welcome screen' button", + ); + { ui.add_space(SPACING); ui.label("Experimental features:"); diff --git a/crates/re_viewer/src/ui/selection_history_ui.rs b/crates/re_viewer/src/ui/selection_history_ui.rs index 41d8a818e842..5d36df2303f3 100644 --- a/crates/re_viewer/src/ui/selection_history_ui.rs +++ b/crates/re_viewer/src/ui/selection_history_ui.rs @@ -181,6 +181,7 @@ fn selection_to_string(blueprint: &ViewportBlueprint, selection: &ItemCollection fn item_to_string(blueprint: &ViewportBlueprint, item: &Item) -> String { match item { + Item::AppId(app_id) => app_id.to_string(), Item::DataSource(data_source) => data_source.to_string(), Item::StoreId(store_id) => store_id.to_string(), Item::SpaceView(space_view_id) => { diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 4dc22d1553bb..ae24a9c6a684 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -255,6 +255,7 @@ fn container_children( fn data_section_ui(item: &Item) -> Option> { match item { + Item::AppId(app_id) => Some(Box::new(app_id.clone())), Item::DataSource(data_source) => Some(Box::new(data_source.clone())), Item::StoreId(store_id) => Some(Box::new(store_id.clone())), Item::ComponentPath(component_path) => Some(Box::new(component_path.clone())), @@ -298,6 +299,10 @@ fn what_is_selected_ui( item: &Item, ) { match item { + Item::AppId(app_id) => { + let title = app_id.to_string(); + item_title_ui(ctx.re_ui, ui, &title, Some(&icons::APPLICATION), &title); + } Item::DataSource(data_source) => { let title = data_source.to_string(); item_title_ui(ctx.re_ui, ui, &title, Some(&icons::DATA_SOURCE), &title); @@ -804,7 +809,8 @@ fn show_list_item_for_container_child( fn has_blueprint_section(item: &Item) -> bool { match item { - Item::DataSource(_) + Item::AppId(_) + | Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) | Item::Container(_) @@ -822,6 +828,13 @@ fn blueprint_ui( item: &Item, ) { match item { + Item::AppId(_) + | Item::DataSource(_) + | Item::StoreId(_) + | Item::ComponentPath(_) + | Item::Container(_) + | Item::InstancePath(_) => {} + Item::SpaceView(space_view_id) => { blueprint_ui_for_space_view(ui, ctx, viewport, *space_view_id); } @@ -829,12 +842,6 @@ fn blueprint_ui( Item::DataResult(space_view_id, instance_path) => { blueprint_ui_for_data_result(ui, ctx, viewport, *space_view_id, instance_path); } - - Item::DataSource(_) - | Item::StoreId(_) - | Item::ComponentPath(_) - | Item::Container(_) - | Item::InstancePath(_) => {} } } diff --git a/crates/re_viewer/src/ui/space_view_space_origin_ui.rs b/crates/re_viewer/src/ui/space_view_space_origin_ui.rs index a5a920b13ad6..63dbb8c102ee 100644 --- a/crates/re_viewer/src/ui/space_view_space_origin_ui.rs +++ b/crates/re_viewer/src/ui/space_view_space_origin_ui.rs @@ -185,7 +185,7 @@ fn space_view_space_origin_widget_editing_ui( let suggestions_ui = |ui: &mut egui::Ui| { ui.spacing_mut().item_spacing.y = 0.0; for (idx, suggested_space_view) in filtered_space_view_suggestions.iter().enumerate() { - let response = re_ui::list_item::ListItem::new( + let response = re_ui::ListItem::new( ctx.re_ui, suggested_space_view .space_origin @@ -206,14 +206,11 @@ fn space_view_space_origin_widget_editing_ui( let excluded_count = space_view_suggestions.len() - filtered_space_view_suggestions.len(); if excluded_count > 0 { - re_ui::list_item::ListItem::new( - ctx.re_ui, - format!("{excluded_count} hidden suggestions"), - ) - .weak(true) - .italics(true) - .interactive(false) - .show_flat(ui); + re_ui::ListItem::new(ctx.re_ui, format!("{excluded_count} hidden suggestions")) + .weak(true) + .italics(true) + .interactive(false) + .show_flat(ui); } }; diff --git a/crates/re_viewer_context/src/app_options.rs b/crates/re_viewer_context/src/app_options.rs index e374f4ef50aa..15ee53e05492 100644 --- a/crates/re_viewer_context/src/app_options.rs +++ b/crates/re_viewer_context/src/app_options.rs @@ -10,6 +10,9 @@ pub struct AppOptions { /// Show milliseconds, RAM usage, etc. pub show_metrics: bool, + /// Include the "Welcome screen" application in the recordings panel? + pub include_welcome_screen_button_in_recordings_panel: bool, + /// Enable the experimental feature for space view screenshots. #[cfg(not(target_arch = "wasm32"))] pub experimental_space_view_screenshots: bool, @@ -45,6 +48,8 @@ impl Default for AppOptions { show_metrics: cfg!(debug_assertions), + include_welcome_screen_button_in_recordings_panel: true, + #[cfg(not(target_arch = "wasm32"))] experimental_space_view_screenshots: false, diff --git a/crates/re_viewer_context/src/command_sender.rs b/crates/re_viewer_context/src/command_sender.rs index e836e288e660..29921f47c2df 100644 --- a/crates/re_viewer_context/src/command_sender.rs +++ b/crates/re_viewer_context/src/command_sender.rs @@ -7,6 +7,12 @@ use re_ui::{UICommand, UICommandSender}; /// Commands used by internal system components // TODO(jleibs): Is there a better crate for this? pub enum SystemCommand { + /// Make this the active application. + ActivateApp(re_log_types::ApplicationId), + + /// Close this app and all its recordings. + CloseApp(re_log_types::ApplicationId), + /// Load some data. LoadDataSource(DataSource), diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 3392d89fcff8..5ec1e81f08e9 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -14,7 +14,7 @@ pub enum UiVerbosity { /// Keep it small enough to fit on one row. Small, - /// Display a reduced set, used for hovering. + /// Display a reduced set, used for hovering/tooltips. /// /// Keep it under a half-dozen lines. Reduced, diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 27d68d583140..7d71b0878366 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -8,6 +8,9 @@ use crate::{ContainerId, SpaceViewId}; /// This is the granularity of what is selectable and hoverable. #[derive(Clone, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)] pub enum Item { + /// Select a specific application, to see which recordings and blueprints are loaded for it. + AppId(re_log_types::ApplicationId), + /// A place where data comes from, e.g. the path to a .rrd or a TCP port. DataSource(re_smart_channel::SmartChannelSource), @@ -33,9 +36,11 @@ pub enum Item { impl Item { pub fn entity_path(&self) -> Option<&EntityPath> { match self { - Self::DataSource(_) | Self::SpaceView(_) | Self::Container(_) | Self::StoreId(_) => { - None - } + Self::AppId(_) + | Self::DataSource(_) + | Self::SpaceView(_) + | Self::Container(_) + | Self::StoreId(_) => None, Self::ComponentPath(component_path) => Some(&component_path.entity_path), @@ -100,6 +105,7 @@ impl std::str::FromStr for Item { impl std::fmt::Debug for Item { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + Item::AppId(app_id) => app_id.fmt(f), Item::DataSource(data_source) => data_source.fmt(f), Item::StoreId(store_id) => store_id.fmt(f), Item::ComponentPath(s) => s.fmt(f), @@ -116,6 +122,7 @@ impl std::fmt::Debug for Item { impl Item { pub fn kind(self: &Item) -> &'static str { match self { + Item::AppId(_) => "Application", Item::DataSource(_) => "Data source", Item::StoreId(store_id) => match store_id.kind { re_log_types::StoreKind::Recording => "Recording ID", @@ -157,7 +164,8 @@ pub fn resolve_mono_instance_path_item( *space_view_id, resolve_mono_instance_path(query, store, instance_path), ), - Item::DataSource(_) + Item::AppId(_) + | Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) | Item::SpaceView(_) diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index 8f8810af75d4..8a57b8aa0421 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -358,13 +358,15 @@ impl ApplicationSelectionState { .hovered_previous_frame .iter_items() .any(|current| match current { - Item::DataSource(_) + Item::AppId(_) + | Item::DataSource(_) | Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => current == test, Item::ComponentPath(component_path) => match test { - Item::DataSource(_) + Item::AppId(_) + | Item::DataSource(_) | Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => false, @@ -383,7 +385,8 @@ impl ApplicationSelectionState { }, Item::InstancePath(current_instance_path) => match test { - Item::DataSource(_) + Item::AppId(_) + | Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) | Item::SpaceView(_) @@ -400,7 +403,8 @@ impl ApplicationSelectionState { }, Item::DataResult(_current_space_view_id, current_instance_path) => match test { - Item::DataSource(_) + Item::AppId(_) + | Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) | Item::SpaceView(_) diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 782a8ed02c8c..bd539e38d121 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -1,6 +1,7 @@ use ahash::{HashMap, HashMapExt}; use anyhow::Context as _; +use itertools::Itertools as _; use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; @@ -76,7 +77,7 @@ pub struct StoreHubStats { impl StoreHub { /// App ID used as a marker to display the welcome screen. pub fn welcome_screen_app_id() -> ApplicationId { - "".into() + "Welcome screen".into() } /// Used only for tests @@ -201,6 +202,26 @@ impl StoreHub { } pub fn remove(&mut self, store_id: &StoreId) { + let removed_store = self.store_bundle.remove(store_id); + + let Some(removed_store) = removed_store else { + return; + }; + + if removed_store.store_kind() == StoreKind::Recording { + if let Some(app_id) = removed_store.app_id().cloned() { + let any_other_recordings_for_this_app = self + .store_bundle + .recordings() + .any(|rec| rec.app_id() == Some(&app_id)); + + if !any_other_recordings_for_this_app { + re_log::trace!("Removed last recording of {app_id}. Closing app."); + self.close_app(&app_id); + } + } + } + if self.active_rec_id.as_ref() == Some(store_id) { if let Some(new_selection) = self.store_bundle.find_closest_recording(store_id) { self.set_active_recording_id(new_selection.clone()); @@ -209,14 +230,13 @@ impl StoreHub { self.active_rec_id = None; } } - - self.store_bundle.remove(store_id); } - /// Remove all open recordings, and go to the welcome page. + /// Remove all open recordings and applications, and go to the welcome page. pub fn clear_recordings(&mut self) { + // Keep only the welcome screen: self.store_bundle - .retain(|db| db.store_kind() != StoreKind::Recording); + .retain(|db| db.app_id() == Some(&Self::welcome_screen_app_id())); self.active_rec_id = None; self.active_application_id = Some(Self::welcome_screen_app_id()); } @@ -225,6 +245,7 @@ impl StoreHub { // Active app /// Change the active [`ApplicationId`] + #[allow(clippy::needless_pass_by_value)] pub fn set_active_app(&mut self, app_id: ApplicationId) { // If we don't know of a blueprint for this `ApplicationId` yet, // try to load one from the persisted store @@ -234,7 +255,38 @@ impl StoreHub { } } - self.active_application_id = Some(app_id); + if self.active_application_id.as_ref() == Some(&app_id) { + return; + } + + self.active_application_id = Some(app_id.clone()); + self.active_rec_id = None; + + // Find any matching recording and activate it + for rec in self + .store_bundle + .recordings() + .sorted_by_key(|entity_db| entity_db.store_info().map(|info| info.started)) + { + if rec.app_id() == Some(&app_id) { + self.active_rec_id = Some(rec.store_id().clone()); + self.was_recording_active = true; + return; + } + } + } + + /// Close this application and all its recordings. + pub fn close_app(&mut self, app_id: &ApplicationId) { + self.store_bundle.retain(|db| db.app_id() != Some(app_id)); + + if self.active_application_id.as_ref() == Some(app_id) { + self.active_application_id = None; + self.active_rec_id = None; + } + + self.default_blueprint_by_app_id.remove(app_id); + self.active_blueprint_by_app_id.remove(app_id); } #[inline] @@ -279,8 +331,9 @@ impl StoreHub { .get(&recording_id) .as_ref() .and_then(|recording| recording.app_id()) + .cloned() { - self.set_active_app(app_id.clone()); + self.set_active_app(app_id); } self.active_rec_id = Some(recording_id); diff --git a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs index 6e04cb82f41e..1baa7b91f892 100644 --- a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs +++ b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs @@ -20,11 +20,14 @@ impl ContextMenuAction for CollapseExpandAllAction { .any(|(item, _)| self.supports_item(ctx, item)) } + /// Do we have a context menu for this item? fn supports_item(&self, ctx: &ContextMenuContext<'_>, item: &Item) -> bool { // TODO(ab): in an ideal world, we'd check the fully expended/collapsed state of the item to // avoid showing a command that wouldn't have an effect but that's lots of added complexity. match item { - Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) => false, + Item::AppId(_) | Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) => { + false + } Item::SpaceView(_) | Item::Container(_) | Item::InstancePath(_) => true, diff --git a/crates/re_viewport/src/context_menu/mod.rs b/crates/re_viewport/src/context_menu/mod.rs index d3b62368203e..fdeaadf334a2 100644 --- a/crates/re_viewport/src/context_menu/mod.rs +++ b/crates/re_viewport/src/context_menu/mod.rs @@ -301,6 +301,7 @@ trait ContextMenuAction { fn process_selection(&self, ctx: &ContextMenuContext<'_>) { for (item, _) in ctx.selection.iter() { match item { + Item::AppId(app_id) => self.process_app_id(ctx, app_id), Item::DataSource(data_source) => self.process_data_source(ctx, data_source), Item::StoreId(store_id) => self.process_store_id(ctx, store_id), Item::ComponentPath(component_path) => { @@ -316,6 +317,9 @@ trait ContextMenuAction { } } + fn process_app_id(&self, _ctx: &ContextMenuContext<'_>, _app_id: &re_log_types::ApplicationId) { + } + fn process_data_source( &self, _ctx: &ContextMenuContext<'_>, diff --git a/crates/re_viewport/src/space_view_highlights.rs b/crates/re_viewport/src/space_view_highlights.rs index a06e3ebdaf3a..173fed8ac72d 100644 --- a/crates/re_viewport/src/space_view_highlights.rs +++ b/crates/re_viewport/src/space_view_highlights.rs @@ -44,7 +44,11 @@ pub fn highlights_for_space_view( for current_selection in ctx.selection_state().selected_items().iter_items() { match current_selection { - Item::DataSource(_) | Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => {} + Item::AppId(_) + | Item::DataSource(_) + | Item::StoreId(_) + | Item::SpaceView(_) + | Item::Container(_) => {} Item::ComponentPath(component_path) => { let entity_hash = component_path.entity_path.hash(); @@ -80,7 +84,11 @@ pub fn highlights_for_space_view( for current_hover in ctx.selection_state().hovered_items().iter_items() { match current_hover { - Item::DataSource(_) | Item::StoreId(_) | Item::SpaceView(_) | Item::Container(_) => {} + Item::AppId(_) + | Item::DataSource(_) + | Item::StoreId(_) + | Item::SpaceView(_) + | Item::Container(_) => {} Item::ComponentPath(component_path) => { let entity_hash = component_path.entity_path.hash(); diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index ed568402f5f9..c244570f4d17 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -542,8 +542,12 @@ impl<'a, 'b> Viewport<'a, 'b> { /// If `false`, the item is referring to data that is not present in this blueprint. #[inline] - pub fn is_item_valid(&self, item: &Item) -> bool { - self.blueprint.is_item_valid(item) + pub fn is_item_valid( + &self, + store_context: &re_viewer_context::StoreContext<'_>, + item: &Item, + ) -> bool { + self.blueprint.is_item_valid(store_context, item) } } diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index b8072b183c52..55c86acd2a95 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -262,8 +262,18 @@ impl ViewportBlueprint { /// /// TODO(#5742): note that `Item::DataResult` with entity path set to the space origin or some /// of its descendent are always considered valid. - pub fn is_item_valid(&self, item: &Item) -> bool { + pub fn is_item_valid( + &self, + store_context: &re_viewer_context::StoreContext<'_>, + item: &Item, + ) -> bool { match item { + Item::AppId(app_id) => store_context + .hub + .store_bundle() + .entity_dbs() + .any(|db| db.app_id() == Some(app_id)), + Item::DataSource(_) | Item::StoreId(_) | Item::ComponentPath(_) diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 5a122f0dd71d..507326724fae 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -95,6 +95,8 @@ impl Viewport<'_, '_> { focused_item: &Item, ) -> Option { match focused_item { + Item::AppId(_) | Item::DataSource(_) | Item::StoreId(_) => None, + Item::Container(container_id) => { self.expand_all_contents_until(ui.ctx(), &Contents::Container(*container_id)); Some(focused_item.clone()) @@ -142,8 +144,6 @@ impl Viewport<'_, '_> { component_path.entity_path.clone(), )), ), - - Item::DataSource(_) | Item::StoreId(_) => None, } } From 31cc314045e462b3bdad998ca69ca265e561d291 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 4 Apr 2024 15:01:52 +0200 Subject: [PATCH 179/508] Wider selection panel by default (#5777) ### What We _still_ have to be disciplined about how much space we allow things to take up, but this helps a bit: Before: Screenshot 2024-04-04 at 12 21 01 After: Screenshot 2024-04-04 at 12 27 01 Before: Screenshot 2024-04-04 at 12 20 46 After: Screenshot 2024-04-04 at 12 27 15 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5777) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5777?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5777?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5777) - [Docs preview](https://rerun.io/preview/5e515cb7b52ca0c9c53531d17be8735abd25fcc0/docs) - [Examples preview](https://rerun.io/preview/5e515cb7b52ca0c9c53531d17be8735abd25fcc0/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app_state.rs | 12 +++++++++++- crates/re_viewer/src/ui/selection_panel.rs | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 459d1b585721..838572292206 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -336,7 +336,9 @@ impl AppState { ..Default::default() }) .min_width(120.0) - .default_width((0.35 * ui.ctx().screen_rect().width()).min(200.0).round()); + .default_width(default_blueprint_panel_width( + ui.ctx().screen_rect().width(), + )); let show_welcome = store_context.blueprint.app_id() == Some(&StoreHub::welcome_screen_app_id()); @@ -531,3 +533,11 @@ fn check_for_clicked_hyperlinks( } } } + +pub fn default_blueprint_panel_width(screen_width: f32) -> f32 { + (0.35 * screen_width).min(200.0).round() +} + +pub fn default_selection_panel_width(screen_width: f32) -> f32 { + (0.45 * screen_width).min(300.0).round() +} diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index ae24a9c6a684..858c44dfeba4 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -26,8 +26,8 @@ use re_viewport::{ SelectionUpdateBehavior, Viewport, ViewportBlueprint, }; -use crate::ui::override_ui::override_ui; use crate::ui::override_ui::override_visualizer_ui; +use crate::{app_state::default_selection_panel_width, ui::override_ui::override_ui}; use super::{selection_history_ui::SelectionHistoryUi, visible_history::visual_time_range_ui}; @@ -52,7 +52,7 @@ impl SelectionPanel { let panel = egui::SidePanel::right("selection_view") .min_width(120.0) - .default_width((0.45 * screen_width).min(250.0).round()) + .default_width(default_selection_panel_width(screen_width)) .max_width((0.65 * screen_width).round()) .resizable(true) .frame(egui::Frame { From 77d6a2976e3f17f5e20e23f5f8979b13240117a9 Mon Sep 17 00:00:00 2001 From: Nikolaus West Date: Thu, 4 Apr 2024 15:36:40 +0200 Subject: [PATCH 180/508] Example category rehaul (#5599) ### What - WIP rehaul of the example categories to work with the new design where all examples are shown on one big page with groups of examples separated by category title and description. WIP landing page PR: https://github.com/rerun-io/landing/pull/757 - Added some example that weren't previously listed (e.g. blueprint_stock) - Added a script to check that all of our examples are indeed listed in the manifest (or explicitly excluded). * Closes https://github.com/rerun-io/rerun/issues/5665 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5599/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5599/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5599/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5599) - [Docs preview](https://rerun.io/preview/8635155f3afd9eeb2146c0e8f2e05bd4a0eb233e/docs) - [Examples preview](https://rerun.io/preview/8635155f3afd9eeb2146c0e8f2e05bd4a0eb233e/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Emil Ernerfeldt Co-authored-by: Antoine Beyeler Co-authored-by: Antoine Beyeler <49431240+abey79@users.noreply.github.com> --- examples/manifest.toml | 182 +++++++++++------- examples/python/arflow/README.md | 2 +- .../differentiable_blocks_world/README.md | 2 +- examples/python/limap/README.md | 2 +- examples/python/mcc/README.md | 2 +- examples/python/shape_pointe/README.md | 2 +- examples/python/simplerecon/README.md | 2 +- examples/python/slahmr/README.md | 2 +- examples/python/tapir/README.md | 2 +- examples/python/widebaseline/README.md | 2 +- scripts/check_example_manifest_coverage.py | 45 +++++ 11 files changed, 162 insertions(+), 83 deletions(-) create mode 100644 scripts/check_example_manifest_coverage.py diff --git a/examples/manifest.toml b/examples/manifest.toml index 16b5dc3454c6..05bd029ada80 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -6,105 +6,139 @@ # To add examples to the app itself, use the `channel` attribute in the example's readme's frontmatter. # See for more information. -[categories.real-data] +[categories.spatial-computing] order = 1 -title = "Examples with Real Data" +title = "Spatial computing and XR" prelude = """ -The following examples illustrate using the Rerun logging SDK with potential real-world (if toy) use cases. -They all require additional data to be downloaded, so an internet connection is needed at least once. -Each example downloads it's own data, so no additional steps are needed. -For the simplest possible examples showing how to use each api, -check out [Types](/docs/reference/types). - -You can try these examples live at [rerun.io/viewer](/viewer). +Examples related to spatial computing, augmented reality, virtual reality, and mixed reality. """ examples = [ + # display order, most interesting first "arkit_scenes", - "controlnet", - "depth_guided_stable_diffusion", - "detect_and_track_objects", - "dicom_mri", - "face_tracking", - "gesture_detection", - "human_pose_tracking", - "lidar", - "live_camera_edge_detection", - "live_depth_sensor", - "llm_embedding_ner", - "nuscenes", + "limap", "objectron", - "open_photogrammetry_format", - "raw_mesh", - "rgbd", - "ros_node", - "rrt-star", - "segment_anything_model", - "signed_distance_fields", - "structure_from_motion", + "simplerecon", + "slahmr", "vrs", + "widebaseline", + "arflow", ] -[categories.artificial-data] +[categories.robotics] order = 2 -title = "Examples with Artificial Data" +title = "Robotics" prelude = """ -The following examples serve to illustrate various uses of the Rerun logging SDK. -They should not require any additional data downloads, and should run offline. -For the simplest possible examples showing how to use each api, -check out [Types](/docs/reference/types). +Examples related to robotics, autonomous systems, and interfacing with sensor hardware. """ examples = [ - "minimal", - "clock", - "eigen_opencv", - "multithreading", - "multiprocessing", - "plots", + # display order, most interesting first + "ros_node", + "nuscenes", + "kiss-icp", + "live_depth_sensor", + "lidar", + "rrt-star", + "rgbd", + "nv12", ] -[categories.paper-visualizations] +[categories.generative-vision] order = 3 -title = "Paper Visualizations" +title = "Generative computer vision and LLMs" prelude = """ -The following examples use Rerun to create visual walkthroughs of papers. They are typically forks -from the official open-source implementations adding Rerun as the visualizer. -Check out the respective READMEs for installation instructions. -For the simplest possible examples showing how to use each api, -check out [Types](/docs/reference/types). +Examples using generative AI methods like diffusion and LLMs. """ examples = [ - "differentiable_blocks_world", - "limap", + # display order, most interesting first + "controlnet", + "depth_guided_stable_diffusion", "mcc", "shape_pointe", - "simplerecon", - "slahmr", - "tapir", - "widebaseline", - "arflow", - "kiss-icp", + "llm_embedding_ner", ] -[categories.setup] +[categories.video-image] order = 4 -title = "Setup" +title = "Image and video understanding" prelude = """ -### Examples with Real / Artificial Data -To run these examples, make sure you have the Rerun repository checked out -and the latest SDK installed. +Examples related to image and video processing, highlighting Rerun's 2D capabilities. +""" +examples = [ + # display order, most interesting first + "detect_and_track_objects", + "face_tracking", + "human_pose_tracking", + "gesture_detection", + "live_camera_edge_detection", + "segment_anything_model", + "tapir", +] + +[categories.3d-reconstruction] # NOLINT +order = 5 +title = "3D reconstruction and modelling" +prelude = """ +SLAM, photogrammetry and other 3D modelling examples. +""" +examples = [ + # display order, most interesting first + "structure_from_motion", + "open_photogrammetry_format", + "kiss-icp", + "differentiable_blocks_world", + "signed_distance_fields", + "raw_mesh", +] -```bash -pip install --upgrade rerun-sdk # install the latest Rerun SDK -git clone git@github.com:rerun-io/rerun.git # Clone the repository -cd rerun -git checkout latest # Check out the commit matching the latest SDK release -``` -> Note: Make sure your SDK version matches the examples. -For example, if your SDK version is `0.3.1`, check out the matching tag -in the Rerun repository by running `git checkout v0.3.1`. +[categories.integrations] +order = 6 +title = "Integrations" +prelude = """ +Integration with 3rd party tools, formats, libraries, and APIs. +""" +examples = [ + # display order, most interesting first + "ros_node", + "vrs", + "eigen_opencv", + "dicom_mri", + "blueprint_stocks", + "arflow", +] -### Paper Visualizations -To reproduce the paper visualizations check out the README of the respective -Rerun forks. +[categories.feature-showcase] +order = 7 +title = "Feature showcase" +prelude = """ +Showcase basic usage and specific features of Rerun. """ -examples = [] +examples = [ + # display order, most interesting first + "clock", + "dna", + "log_file", + "minimal", + "multiprocessing", + "multithreading", + "plots", + "raw_mesh", +] + +# These are examples that we explicitly exclude from our website. You can check that all examples are either included +# or explicitly excluded by running `python scripts/check_example_manifest_coverage.py`. +[ignored] +examples = [ + "custom_collection_adapter", + "custom_data_loader", + "custom_space_view", + "custom_store_subscriber", + "extend_viewer_ui", + "external_data_loader", + "incremental_logging", + "minimal_serve", + "notebook", + "shared_recording", + "spawn_viewer", + "stdio", + "template", +] diff --git a/examples/python/arflow/README.md b/examples/python/arflow/README.md index 909c020e9a4a..9b563394ee1a 100644 --- a/examples/python/arflow/README.md +++ b/examples/python/arflow/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/differentiable_blocks_world/README.md b/examples/python/differentiable_blocks_world/README.md index 2541ca5ca06a..37089f80af5c 100644 --- a/examples/python/differentiable_blocks_world/README.md +++ b/examples/python/differentiable_blocks_world/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/limap/README.md b/examples/python/limap/README.md index 05b8f021827f..72408f9f93eb 100644 --- a/examples/python/limap/README.md +++ b/examples/python/limap/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/mcc/README.md b/examples/python/mcc/README.md index 1ed1dbf3ff10..f5e1a5a3aaa6 100644 --- a/examples/python/mcc/README.md +++ b/examples/python/mcc/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/shape_pointe/README.md b/examples/python/shape_pointe/README.md index 08ea096db6d6..191fb088364c 100644 --- a/examples/python/shape_pointe/README.md +++ b/examples/python/shape_pointe/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/simplerecon/README.md b/examples/python/simplerecon/README.md index 6c86fd86d69a..323d470a42c2 100644 --- a/examples/python/simplerecon/README.md +++ b/examples/python/simplerecon/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/slahmr/README.md b/examples/python/slahmr/README.md index 696ccb35f1bc..7ba6c345767d 100644 --- a/examples/python/slahmr/README.md +++ b/examples/python/slahmr/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/tapir/README.md b/examples/python/tapir/README.md index dc43111ef7d8..4913cdfd9fa4 100644 --- a/examples/python/tapir/README.md +++ b/examples/python/tapir/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/widebaseline/README.md b/examples/python/widebaseline/README.md index 5c9a6a6e0e98..da3536b6af9b 100644 --- a/examples/python/widebaseline/README.md +++ b/examples/python/widebaseline/README.md @@ -1,7 +1,7 @@ diff --git a/scripts/check_example_manifest_coverage.py b/scripts/check_example_manifest_coverage.py new file mode 100644 index 000000000000..cca6125b6377 --- /dev/null +++ b/scripts/check_example_manifest_coverage.py @@ -0,0 +1,45 @@ +"""Check if all examples are listed (or explicitly ignored) in our example manifest.""" +from __future__ import annotations + +from pathlib import Path +from typing import Iterable + +import tomli + + +def gather_example_in_repo() -> Iterable[Path]: + example_dir = Path(__file__).parent.parent / "examples" + langs = ["c", "cpp", "python", "rust"] + + for lang in langs: + land_dir = example_dir / lang + for child in land_dir.glob("*"): + if child.is_dir() and (child / "README.md").exists(): + yield child + + +def gather_example_in_manifest() -> Iterable[str]: + manifest_path = Path(__file__).parent.parent / "examples" / "manifest.toml" + manifest = tomli.loads(manifest_path.read_text()) + for cat in manifest["categories"].values(): + yield from cat["examples"] + + if "ignored" in manifest and "examples" in manifest["ignored"]: + yield from manifest["ignored"]["examples"] + + +def main(): + listed_examples = set(gather_example_in_manifest()) + + all_examples = list(gather_example_in_repo()) + + print("Unlisted examples:") + for example_path in all_examples: + if example_path.name not in listed_examples: + print(f"- {example_path.parent.name}/{example_path.name}") + + print(f"({len(all_examples)} checked)") + + +if __name__ == "__main__": + main() From f0285b7ef7e56f29b841b1e12979a7b457723083 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 4 Apr 2024 16:36:01 +0200 Subject: [PATCH 181/508] Fix default time range for time series space view (#5786) ### What Recent innocuous changes of space view identifiers caused an old hack to trip up. Removed the hack! ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5786) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5786?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5786?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5786) - [Docs preview](https://rerun.io/preview/f25335cff69d5b42299c061601da1b86e8e642b0/docs) - [Examples preview](https://rerun.io/preview/f25335cff69d5b42299c061601da1b86e8e642b0/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_space_view/src/lib.rs | 2 +- crates/re_space_view/src/visual_time_range.rs | 11 +---------- .../src/space_view_class.rs | 14 ++++++++++++-- crates/re_space_view_time_series/src/util.rs | 8 +++----- crates/re_viewer/src/ui/visible_history.rs | 8 ++++++-- .../src/space_view/space_view_class.rs | 8 +++++++- 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 900e4bf482b8..c94d583d0299 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -22,7 +22,7 @@ pub use sub_archetypes::{ query_space_view_sub_archetype_or_default, }; pub use visual_time_range::{ - default_time_range, query_visual_history, time_range_boundary_to_visible_history_boundary, + query_visual_history, time_range_boundary_to_visible_history_boundary, visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, }; pub use visualizable::determine_visualizable_entities; diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index b07261f7b4f9..49e510f81934 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -13,7 +13,7 @@ use re_types::blueprint::{ components::VisibleTimeRange, datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, }; -use re_viewer_context::{SpaceViewClassIdentifier, ViewerContext}; +use re_viewer_context::ViewerContext; pub fn time_range_boundary_to_visible_history_boundary( boundary: &VisibleTimeRangeBoundary, @@ -103,12 +103,3 @@ pub fn query_visual_history( } } } - -// TODO(#4194): this should come from delegation to the space-view-class -pub fn default_time_range(class_identifier: SpaceViewClassIdentifier) -> VisibleTimeRange { - if class_identifier == "Time Series" { - VisibleTimeRange::EVERYTHING.clone() - } else { - VisibleTimeRange::EMPTY.clone() - } -} diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 54b5312252d5..079891720094 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -6,8 +6,10 @@ use re_data_store::TimeType; use re_format::next_grid_tick_magnitude_ns; use re_log_types::{EntityPath, TimeZone}; use re_space_view::{controls, query_space_view_sub_archetype_or_default}; -use re_types::blueprint::components::Corner2D; -use re_types::components::Range1D; +use re_types::{ + blueprint::components::{Corner2D, VisibleTimeRange}, + components::Range1D, +}; use re_viewer_context::external::re_entity_db::{ EditableAutoValue, EntityProperties, TimeSeriesAggregator, }; @@ -74,6 +76,10 @@ pub struct TimeSeriesSpaceView; const DEFAULT_LEGEND_CORNER: egui_plot::Corner = egui_plot::Corner::RightBottom; +impl TimeSeriesSpaceView { + pub const DEFAULT_TIME_RANGE: VisibleTimeRange = VisibleTimeRange::EVERYTHING; +} + impl SpaceViewClass for TimeSeriesSpaceView { fn identifier() -> SpaceViewClassIdentifier { "TimeSeries".into() @@ -137,6 +143,10 @@ impl SpaceViewClass for TimeSeriesSpaceView { re_viewer_context::SpaceViewClassLayoutPriority::Low } + fn default_visible_time_range(&self) -> VisibleTimeRange { + Self::DEFAULT_TIME_RANGE.clone() + } + fn selection_ui( &self, ctx: &ViewerContext<'_>, diff --git a/crates/re_space_view_time_series/src/util.rs b/crates/re_space_view_time_series/src/util.rs index b703b7d20ae7..b09b78c40c6e 100644 --- a/crates/re_space_view_time_series/src/util.rs +++ b/crates/re_space_view_time_series/src/util.rs @@ -1,9 +1,7 @@ use re_log_types::{EntityPath, TimeInt, TimeRange}; -use re_space_view::{default_time_range, visible_time_range_to_time_range}; +use re_space_view::visible_time_range_to_time_range; use re_types::datatypes::Utf8; -use re_viewer_context::{ - external::re_entity_db::TimeSeriesAggregator, SpaceViewClass, ViewQuery, ViewerContext, -}; +use re_viewer_context::{external::re_entity_db::TimeSeriesAggregator, ViewQuery, ViewerContext}; use crate::{ aggregation::{AverageAggregator, MinMaxAggregator}, @@ -39,7 +37,7 @@ pub fn determine_time_range( ) -> TimeRange { let visible_time_range_override = data_result .lookup_override::(ctx) - .unwrap_or(default_time_range(TimeSeriesSpaceView::identifier())); + .unwrap_or(TimeSeriesSpaceView::DEFAULT_TIME_RANGE); let mut time_range = visible_time_range_to_time_range( &visible_time_range_override, diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index b88a9b7e88cb..2f7483267f3e 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -6,7 +6,7 @@ use egui::{NumExt as _, Response, Ui}; use re_entity_db::{TimeHistogram, VisibleHistory, VisibleHistoryBoundary}; use re_log_types::{TimeType, TimeZone}; use re_space_view::{ - default_time_range, time_range_boundary_to_visible_history_boundary, + time_range_boundary_to_visible_history_boundary, visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, }; use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D}; @@ -55,9 +55,13 @@ pub fn visual_time_range_ui( let mut interacting_with_controls = false; + let space_view_class = ctx + .space_view_class_registry + .get_class_or_log_error(&space_view_class); + let mut resolved_range = data_result .lookup_override::(ctx) - .unwrap_or(default_time_range(space_view_class)); + .unwrap_or(space_view_class.default_visible_time_range()); let mut has_individual_range = if let Some(data_result_tree) = data_result_tree { // If there is a data-tree, we know we have individual settings if we are our own source. data_result diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index 6a0e899b9931..e5ab37b493a6 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -1,7 +1,7 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityProperties, EntityPropertyMap}; use re_log_types::EntityPath; -use re_types::ComponentName; +use re_types::{blueprint::components::VisibleTimeRange, ComponentName}; use crate::{ IndicatedEntities, PerSystemEntities, PerVisualizer, SmallVisualizerSet, @@ -105,6 +105,12 @@ pub trait SpaceViewClass: Send + Sync { /// Controls how likely this space view will get a large tile in the ui. fn layout_priority(&self) -> SpaceViewClassLayoutPriority; + /// Determines the default time range for this space view class. + // TODO(#4194): This should be generalized to allow arbitrary property defaults. + fn default_visible_time_range(&self) -> VisibleTimeRange { + VisibleTimeRange::EMPTY.clone() + } + /// Determines a suitable origin given the provided set of entities. /// /// This function only considers the transform topology, disregarding the actual visualizability From a5a20ea656eb9471c518a5f2fbc07a1af2c4bc1e Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 4 Apr 2024 16:36:52 +0200 Subject: [PATCH 182/508] Shorter selection ui for tensor/annotation-context/view coordinates/recording (#5782) ### What A few before/after screenshots, covers most but not all changes in this pr: Before: Screenshot 2024-04-04 at 14 36 31 After: Screenshot 2024-04-04 at 14 40 19 Before: Screenshot 2024-04-04 at 12 37 22 After: Screenshot 2024-04-04 at 12 50 50 After: Screenshot 2024-04-04 at 12 37 15 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5782) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5782?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5782?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5782) - [Docs preview](https://rerun.io/preview/0b5e0c93df89317e867a5fd169d6944c944bb91d/docs) - [Examples preview](https://rerun.io/preview/0b5e0c93df89317e867a5fd169d6944c944bb91d/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_data_ui/src/annotation_context.rs | 8 +++- crates/re_data_ui/src/data.rs | 3 +- crates/re_data_ui/src/entity_db.rs | 4 +- crates/re_data_ui/src/image.rs | 41 ++++++++++----------- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/crates/re_data_ui/src/annotation_context.rs b/crates/re_data_ui/src/annotation_context.rs index 2ec9e980e353..2e9bdf82f394 100644 --- a/crates/re_data_ui/src/annotation_context.rs +++ b/crates/re_data_ui/src/annotation_context.rs @@ -107,9 +107,13 @@ impl DataUi for AnnotationContext { UiVerbosity::Small | UiVerbosity::Reduced => { if self.0.len() == 1 { let descr = &self.0[0].class_description; - ui.label(format!("AnnotationContext with one class containing {} keypoints and {} connections", descr.keypoint_annotations.len(), descr.keypoint_connections.len())); + ui.label(format!( + "One class containing {} keypoints and {} connections", + descr.keypoint_annotations.len(), + descr.keypoint_connections.len() + )); } else { - ui.label(format!("AnnotationContext with {} classes", self.0.len())); + ui.label(format!("{} classes", self.0.len())); } } UiVerbosity::LimitHeight | UiVerbosity::Full => { diff --git a/crates/re_data_ui/src/data.rs b/crates/re_data_ui/src/data.rs index 5d7751e94586..234a141c2b4f 100644 --- a/crates/re_data_ui/src/data.rs +++ b/crates/re_data_ui/src/data.rs @@ -62,7 +62,8 @@ impl DataUi for ViewCoordinates { ) { match verbosity { UiVerbosity::Small => { - ui.label(format!("ViewCoordinates: {}", self.describe())); + ui.label(self.describe_short()) + .on_hover_text(self.describe()); } UiVerbosity::Full | UiVerbosity::LimitHeight | UiVerbosity::Reduced => { ui.label(self.describe()); diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index 56ae67f0a934..7afdf6ed5e51 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -65,7 +65,7 @@ impl crate::DataUi for EntityDb { ui.label(store_kind.to_string()); ui.end_row(); - re_ui.grid_left_hand_label(ui, "Recording started"); + re_ui.grid_left_hand_label(ui, "Created"); ui.label(started.format(ctx.app_options.time_zone)); ui.end_row(); } @@ -73,7 +73,7 @@ impl crate::DataUi for EntityDb { if let Some(latest_row_id) = self.latest_row_id() { if let Ok(nanos_since_epoch) = i64::try_from(latest_row_id.nanoseconds_since_epoch()) { let time = re_log_types::Time::from_ns_since_epoch(nanos_since_epoch); - re_ui.grid_left_hand_label(ui, "Last modified at"); + re_ui.grid_left_hand_label(ui, "Modified"); ui.label(time.format(ctx.app_options.time_zone)); ui.end_row(); } diff --git a/crates/re_data_ui/src/image.rs b/crates/re_data_ui/src/image.rs index 2e71764b2d83..37268b391dbd 100644 --- a/crates/re_data_ui/src/image.rs +++ b/crates/re_data_ui/src/image.rs @@ -17,7 +17,13 @@ use crate::image_meaning_for_entity; use super::EntityDataUi; pub fn format_tensor_shape_single_line(shape: &[TensorDimension]) -> String { - format!("[{}]", shape.iter().join(", ")) + const MAX_SHOWN: usize = 4; // should be enough for width/height/depth and then some! + let shapes = shape.iter().take(MAX_SHOWN).join(", "); + if shape.len() > MAX_SHOWN { + format!("{shapes}…") + } else { + shapes + } } impl EntityDataUi for re_types::components::TensorData { @@ -149,27 +155,18 @@ pub fn tensor_ui( ], None => tensor.shape.clone(), }; - ui.label(format!( - "{} x {}{}", - tensor.dtype(), - format_tensor_shape_single_line(shape.as_slice()), - if original_tensor.buffer.is_compressed_image() { - " (compressed)" - } else { - "" - } - )) - .on_hover_ui(|ui| { - tensor_summary_ui( - ctx.re_ui, - ui, - original_tensor, - tensor, - meaning, - meter, - &tensor_stats, - ); - }); + ui.add(egui::Label::new(format_tensor_shape_single_line(&shape)).wrap(true)) + .on_hover_ui(|ui| { + tensor_summary_ui( + ctx.re_ui, + ui, + original_tensor, + tensor, + meaning, + meter, + &tensor_stats, + ); + }); }); } From 0d7367a4d59ca4e7c582fd7a365c78b0937e9123 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 4 Apr 2024 17:40:24 +0200 Subject: [PATCH 183/508] Added `ros_bridge` external example (#5785) ### What - Part of ##5666 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5785) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5785?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5785?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5785) - [Docs preview](https://rerun.io/preview/d2b16ddde46cc35b0e0a174688b76ddc84439429/docs) - [Examples preview](https://rerun.io/preview/d2b16ddde46cc35b0e0a174688b76ddc84439429/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/cpp/ros_bridge/README.md | 34 +++++++++++++++++++++++++++++++ examples/manifest.toml | 2 ++ taplo.toml | 10 ++++++++- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 examples/cpp/ros_bridge/README.md diff --git a/examples/cpp/ros_bridge/README.md b/examples/cpp/ros_bridge/README.md new file mode 100644 index 000000000000..c7a8847b264f --- /dev/null +++ b/examples/cpp/ros_bridge/README.md @@ -0,0 +1,34 @@ + + +## Background + +This is an example that shows how to use Rerun's C++ API to log and visualize [ROS](https://www.ros.org/) messages. + +It works by subscribing to all topics with supported types, converting the messages, and logging the data to Rerun. It further allows to remap topic names to specific entity paths, specify additional timeless transforms, and pinhole parameters via an external config file. See the [launch](https://github.com/rerun-io/cpp-example-ros-bridge/tree/main/rerun_bridge/launch) directory for usage examples. + + + + + + + + + + +## Run the code + +This is an external example, check the [repository](https://github.com/rerun-io/cpp-example-ros-bridge) for more information. + +In a nutshell, clone the repo and run a demo with: + +``` +pixi run example +``` + +Note that this example currently supports Linux only. diff --git a/examples/manifest.toml b/examples/manifest.toml index 05bd029ada80..273d461a0cc6 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -34,6 +34,7 @@ examples = [ # display order, most interesting first "ros_node", "nuscenes", + "ros_bridge", "kiss-icp", "live_depth_sensor", "lidar", @@ -99,6 +100,7 @@ Integration with 3rd party tools, formats, libraries, and APIs. examples = [ # display order, most interesting first "ros_node", + "ros_bridge", "vrs", "eigen_opencv", "dicom_mri", diff --git a/taplo.toml b/taplo.toml index 06f6c78532b4..7ad0910f0de1 100644 --- a/taplo.toml +++ b/taplo.toml @@ -1,6 +1,14 @@ # https://github.com/tamasfe/taplo -exclude = [".pixi/**", "build/**", "target/**", "venv/**"] +exclude = [ + ".nox/**", + ".pixi/**", + "build/**", + "target/**", + "target_ra/**", + "target_wasm/**", + "venv/**", +] [formatting] indent_string = " " From 791e4e66104668f741e19998a2be877c7c4a0b01 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:15:29 +0200 Subject: [PATCH 184/508] Add `urdf_loader` external example (#5789) ### What - Part of #5666 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5789) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5789?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5789?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5789) - [Docs preview](https://rerun.io/preview/ee289d8824bb1107f80a9418c756fb83f963fd0e/docs) - [Examples preview](https://rerun.io/preview/ee289d8824bb1107f80a9418c756fb83f963fd0e/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/cspell.json | 2 ++ examples/manifest.toml | 2 ++ examples/python/urdf_loader/README.md | 46 +++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 examples/python/urdf_loader/README.md diff --git a/docs/cspell.json b/docs/cspell.json index 4d7fd48d623d..9e490a316ce8 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -118,6 +118,7 @@ "Eigen", "emilk", "endcond", + "ensurepath", "enumflags", "everytime", "ewebsock", @@ -266,6 +267,7 @@ "PHALP", "photogrammetrically", "Piotr", + "pipx", "pixi", "pngcrush", "pointcloud", diff --git a/examples/manifest.toml b/examples/manifest.toml index 273d461a0cc6..a6bf420c62ca 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -36,6 +36,7 @@ examples = [ "nuscenes", "ros_bridge", "kiss-icp", + "urdf_loader", "live_depth_sensor", "lidar", "rrt-star", @@ -101,6 +102,7 @@ examples = [ # display order, most interesting first "ros_node", "ros_bridge", + "urdf_loader", "vrs", "eigen_opencv", "dicom_mri", diff --git a/examples/python/urdf_loader/README.md b/examples/python/urdf_loader/README.md new file mode 100644 index 000000000000..055b386d652b --- /dev/null +++ b/examples/python/urdf_loader/README.md @@ -0,0 +1,46 @@ + + + + + + + + + + + +## Overview + +This is an example data-loader plugin that lets you view [URDF](https://wiki.ros.org/urdf) files. It uses the [external data loader mechanism](https://www.rerun.io/docs/howto/open-any-file#external-dataloaders) to add this capability to the Rerun viewer without modifying the viewer itself. + +This example is written in Python, and uses [urdf_parser_py](https://github.com/ros/urdf_parser_py/tree/ros2) to read the files. ROS package-relative paths support both ROS 1 and ROS 2-based resolving. + +## Installing the plug-in + +The [repository](https://github.com/rerun-io/rerun-loader-python-example-urdf) has detailed installation instruction. In a nutshell, the easiest is to use `pipx`: + +``` +pipx install git+https://github.com/rerun-io/rerun-loader-python-example-urdf.git +pipx ensurepath +``` + + +## Try it out + +To try the plug-in, first download the provided example URDF: + +```bash +curl -OL https://github.com/rerun-io/rerun-loader-python-example-urdf/raw/main/example.urdf +``` + +Then you can open the viewer and open the file using drag-and-drop or the open dialog, or you can open it directly from the terminal: + +```bash +rerun example.urdf +``` From 211b9f262f3d4d536cf7fa7c809d1bc3dc9ce8b4 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Apr 2024 18:24:16 +0200 Subject: [PATCH 185/508] Improve browser back-button navigation (#5791) ### What Loading an example and pressing back will keep the example loaded, but still get you back to the welcome screen. Loading the example again will clear the old first before continuing. You can open examples in a background tab by holding down a modifier or middle-clicking. And fixed small annoyance that required an extra "Back" press to get back to the original source. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5791) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5791?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5791?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5791) - [Docs preview](https://rerun.io/preview/e00ddd687df18e3455633ae8da9e51c3db78d18f/docs) - [Examples preview](https://rerun.io/preview/e00ddd687df18e3455633ae8da9e51c3db78d18f/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app.rs | 5 ++ .../src/ui/welcome_screen/example_section.rs | 67 +++++++++++++++++-- crates/re_viewer/src/web_tools.rs | 50 ++++++++++---- .../re_viewer_context/src/command_sender.rs | 3 + crates/re_viewer_context/src/store_hub.rs | 8 +++ 5 files changed, 115 insertions(+), 18 deletions(-) diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 7587c8128ebe..afc03349e791 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -371,6 +371,11 @@ impl App { }); } + SystemCommand::ClearSourceAndItsStores(source) => { + self.rx.retain(|r| r.source() != &source); + store_hub.retain(|db| db.data_source.as_ref() != Some(&source)); + } + SystemCommand::AddReceiver(rx) => { re_log::debug!("Received AddReceiver"); self.add_receiver(rx); diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index 3cf9b2364417..1b305d7e2cf6 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -2,7 +2,7 @@ use egui::{NumExt as _, Ui}; use ehttp::{fetch, Request}; use poll_promise::Promise; -use re_viewer_context::{CommandSender, SystemCommandSender as _}; +use re_viewer_context::{CommandSender, SystemCommand, SystemCommandSender as _}; #[derive(Debug, serde::Deserialize)] struct ExampleThumbnail { @@ -366,7 +366,20 @@ impl ExampleSection { // panel to quit auto-zoom mode. ui.input_mut(|i| i.pointer = Default::default()); - open_example_url(command_sender, &example.desc.rrd_url); + let open_in_new_tab = ui.input(|i| i.modifiers.any()); + open_example_url( + ui.ctx(), + command_sender, + &example.desc.rrd_url, + open_in_new_tab, + ); + } else if response.middle_clicked() { + open_example_url( + ui.ctx(), + command_sender, + &example.desc.rrd_url, + true, + ); } row_example_responses.push(response); @@ -434,19 +447,61 @@ impl ExampleSection { } } -fn open_example_url(command_sender: &CommandSender, rrd_url: &str) { +#[cfg(target_arch = "wasm32")] +fn open_in_background_tab(egui_ctx: &egui::Context, rrd_url: &str) { + egui_ctx.open_url(egui::output::OpenUrl { + url: format!("/?url={}", crate::web_tools::percent_encode(rrd_url)), + new_tab: true, + }); +} + +fn open_example_url( + _egui_ctx: &egui::Context, + command_sender: &CommandSender, + rrd_url: &str, + _open_in_new_tab: bool, +) { + #[cfg(target_arch = "wasm32")] + { + if _open_in_new_tab { + open_in_background_tab(_egui_ctx, rrd_url); + return; + } + } + let data_source = re_data_source::DataSource::RrdHttpUrl(rrd_url.to_owned()); - command_sender.send_system(re_viewer_context::SystemCommand::LoadDataSource( - data_source, + + // If the user re-download an already open recording, clear it out first + command_sender.send_system(SystemCommand::ClearSourceAndItsStores( + re_smart_channel::SmartChannelSource::RrdHttpStream { + url: rrd_url.to_owned(), + }, )); + command_sender.send_system(SystemCommand::LoadDataSource(data_source)); + #[cfg(target_arch = "wasm32")] { // Ensure that the user returns to the welcome page after navigating to an example. use crate::web_tools; // So we know where to return to - web_tools::push_history("?examples"); + let welcome_screen_app_id = re_viewer_context::StoreHub::welcome_screen_app_id(); + let welcome_screen_url = format!( + "?app_id={}", + web_tools::percent_encode(&welcome_screen_app_id.to_string()) + ); + + if web_tools::current_url_suffix() + .unwrap_or_default() + .is_empty() + { + // Replace, otherwise the user would need to hit back twice to return to + // whatever linked them to `https://www.rerun.io/viewer` in the first place. + web_tools::replace_history(&welcome_screen_url); + } else { + web_tools::push_history(&welcome_screen_url); + } // Where we're going: web_tools::push_history(&format!("?url={}", web_tools::percent_encode(rrd_url))); diff --git a/crates/re_viewer/src/web_tools.rs b/crates/re_viewer/src/web_tools.rs index 790c56f0b5ac..4d912fbcd23a 100644 --- a/crates/re_viewer/src/web_tools.rs +++ b/crates/re_viewer/src/web_tools.rs @@ -31,6 +31,14 @@ pub fn percent_encode(s: &str) -> String { format!("{}", js_sys::encode_uri_component(s)) } +/// The current percent-encoded URL suffix, e.g. "?foo=bar#baz". +pub fn current_url_suffix() -> Option { + let location = web_sys::window()?.location(); + let search = location.search().unwrap_or_default(); + let hash = location.hash().unwrap_or_default(); + Some(format!("{search}{hash}")) +} + /// Push a relative url on the web `History`, /// so that the user can use the back button to navigate to it. /// @@ -43,11 +51,7 @@ pub fn percent_encode(s: &str) -> String { /// push_history("foo/bar?baz=qux#fragment"); /// ``` pub fn push_history(new_relative_url: &str) -> Option<()> { - let location = web_sys::window()?.location(); - - let search = location.search().unwrap_or_default(); - let hash = location.hash().unwrap_or_default(); - let current_relative_url = format!("{search}{hash}"); + let current_relative_url = current_url_suffix().unwrap_or_default(); if current_relative_url == new_relative_url { re_log::debug!("Ignoring navigation to {new_relative_url:?} as we're already there"); @@ -73,16 +77,35 @@ pub fn push_history(new_relative_url: &str) -> Option<()> { Some(()) } +/// Replace the current relative url with an new one. +pub fn replace_history(new_relative_url: &str) -> Option<()> { + let history = web_sys::window()? + .history() + .map_err(|err| format!("Failed to get History API: {}", string_from_js_value(err))) + .ok_or_log_error()?; + + history + .replace_state_with_url(&JsValue::NULL, "", Some(new_relative_url)) + .map_err(|err| { + format!( + "Failed to push history state: {}", + string_from_js_value(err) + ) + }) + .ok_or_log_error() +} + /// Parse the `?query` parst of the url, and translate it into commands to control the application. pub fn translate_query_into_commands(egui_ctx: &egui::Context, command_sender: &CommandSender) { use re_viewer_context::{SystemCommand, SystemCommandSender as _}; let location = eframe::web::web_location(); - // NOTE: it's unclear what to do if we find bout `examples` and `url` in the query. - - if location.query_map.get("examples").is_some() { - command_sender.send_system(SystemCommand::CloseAllRecordings); + if let Some(app_ids) = location.query_map.get("app_id") { + if let Some(app_id) = app_ids.last() { + let app_id = re_log_types::ApplicationId::from(app_id.as_str()); + command_sender.send_system(SystemCommand::ActivateApp(app_id)); + } } // NOTE: we support passing in multiple urls to multiple different recorording, blueprints, etc @@ -93,11 +116,14 @@ pub fn translate_query_into_commands(egui_ctx: &egui::Context, command_sender: & .flatten() .collect(); if !urls.is_empty() { - // Clear out any already open recordings to make room for the new ones. - command_sender.send_system(SystemCommand::CloseAllRecordings); - for url in urls { if let Some(receiver) = url_to_receiver(egui_ctx.clone(), url).ok_or_log_error() { + // We may be here because the user clicked Back/Forward in the browser while trying + // out examples. If we re-download the same file we should clear out the old data first. + command_sender.send_system(SystemCommand::ClearSourceAndItsStores( + receiver.source().clone(), + )); + command_sender.send_system(SystemCommand::AddReceiver(receiver)); } } diff --git a/crates/re_viewer_context/src/command_sender.rs b/crates/re_viewer_context/src/command_sender.rs index 29921f47c2df..4f18cc74e7f8 100644 --- a/crates/re_viewer_context/src/command_sender.rs +++ b/crates/re_viewer_context/src/command_sender.rs @@ -16,6 +16,9 @@ pub enum SystemCommand { /// Load some data. LoadDataSource(DataSource), + /// Clear everything that came from this source, and close the source. + ClearSourceAndItsStores(re_smart_channel::SmartChannelSource), + AddReceiver(re_smart_channel::Receiver), /// Reset the `Viewer` to the default state diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index bd539e38d121..afcf64a1667a 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -176,6 +176,10 @@ impl StoreHub { .as_ref() .and_then(|id| self.store_bundle.get(id)); + if recording.is_none() { + self.active_rec_id = None; + } + Some(StoreContext { app_id, blueprint, @@ -232,6 +236,10 @@ impl StoreHub { } } + pub fn retain(&mut self, f: impl FnMut(&EntityDb) -> bool) { + self.store_bundle.retain(f); + } + /// Remove all open recordings and applications, and go to the welcome page. pub fn clear_recordings(&mut self) { // Keep only the welcome screen: From 6de5e14be21947c166ffe43b1e1ce9b2ec1d2304 Mon Sep 17 00:00:00 2001 From: Andreas Naoum <49308613+andreasnaoum@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:39:43 +0200 Subject: [PATCH 186/508] Updated READMEs for the examples - Batch 1 (#5620) Updated READMEs for the examples: Detect and Track Objects Dicom MRI Face Tracking Gesture Detection Human Pose Tracking LiDAR Live Camera Edge Detection Live Depth Sensor ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [app.rerun.io](https://app.rerun.io/pr/5620/index.html) * Using examples from latest `main` build: [app.rerun.io](https://app.rerun.io/pr/5620/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [app.rerun.io](https://app.rerun.io/pr/5620/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5620) - [Docs preview](https://rerun.io/preview/53229bd36daf2158b782ef62b9d76bd90befbdee/docs) - [Examples preview](https://rerun.io/preview/53229bd36daf2158b782ef62b9d76bd90befbdee/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Nikolaus West Co-authored-by: Emil Ernerfeldt --- docs/cspell.json | 7 + .../python/detect_and_track_objects/README.md | 159 +++++- examples/python/dicom_mri/README.md | 45 +- examples/python/face_tracking/README.md | 196 +++++-- examples/python/gesture_detection/README.md | 490 ++++-------------- examples/python/human_pose_tracking/README.md | 11 +- examples/python/lidar/README.md | 44 +- .../live_camera_edge_detection/README.md | 63 ++- examples/python/live_depth_sensor/README.md | 103 +++- 9 files changed, 677 insertions(+), 441 deletions(-) diff --git a/docs/cspell.json b/docs/cspell.json index 9e490a316ce8..e8af69834881 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -48,6 +48,8 @@ "binsearching", "binstall", "binutils", + "blendshape", + "blendshapes", "Birger", "Birkl", "booktitle", @@ -124,6 +126,8 @@ "ewebsock", "extrinsics", "farbfeld", + "FACEMESH", + "facemesh", "Farooq", "Feichtenhofer", "fieldname", @@ -177,6 +181,7 @@ "keypointid", "keypoints", "Kirillov", + "klass", "kpreid", "Landmarker", "Larsson", @@ -329,6 +334,7 @@ "scipy", "scrollwheel", "segs", + "Segmentations", "serde", "Shaohui", "Shap", @@ -404,6 +410,7 @@ "Viktor", "virtualenv", "visualizability", + "voxels", "Vizzo", "vstack", "vsuryamurthy", diff --git a/examples/python/detect_and_track_objects/README.md b/examples/python/detect_and_track_objects/README.md index 8dacfd1fbb00..81301692955b 100644 --- a/examples/python/detect_and_track_objects/README.md +++ b/examples/python/detect_and_track_objects/README.md @@ -1,13 +1,14 @@ + @@ -16,11 +17,161 @@ channel = "release" -Another more elaborate example applying simple object detection and segmentation on a video using the Huggingface `transformers` library. Tracking across frames is performed using [CSRT](https://arxiv.org/pdf/1611.08461.pdf) from OpenCV. +Visualize object detection and segmentation using the [Huggingface's Transformers](https://huggingface.co/docs/transformers/index) and [CSRT](https://arxiv.org/pdf/1611.08461.pdf) from OpenCV. + +# Used Rerun Types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d), [`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log) + +# Background +In this example, CSRT (Channel and Spatial Reliability Tracker), a tracking API introduced in OpenCV, is employed for object detection and tracking across frames. +Additionally, the example showcases basic object detection and segmentation on a video using the Huggingface transformers library. + + +# Logging and Visualizing with Rerun +The visualizations in this example were created with the following Rerun code. + + +## Timelines +For each processed video frame, all data sent to Rerun is associated with the [`timelines`](https://www.rerun.io/docs/concepts/timelines) `frame_idx`. + +```python +rr.set_time_sequence("frame", frame_idx) +``` + +## Video +The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) to the `image` entity. + +```python +rr.log( + "image", + rr.Image(rgb).compress(jpeg_quality=85) +) +``` + +Since the detection and segmentation model operates on smaller images the resized images are logged to the separate `segmentation/rgb_scaled` entity. +This allows us to subsequently visualize the segmentation mask on top of the video. + +```python +rr.log( + "segmentation/rgb_scaled", + rr.Image(rgb_scaled).compress(jpeg_quality=85) +) +``` + +## Segmentations +The segmentation results is logged through a combination of two archetypes. +The segmentation image itself is logged as an +[`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) and +contains the id for each pixel. It is logged to the `segmentation` entity. + + +```python +rr.log( + "segmentation", + rr.SegmentationImage(mask) +) +``` + +The color and label for each class is determined by the +[`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is +logged to the root entity using `rr.log("/", …, timeless=True)` as it should apply to the whole sequence and all +entities that have a class id. + +```python +class_descriptions = [ rr.AnnotationInfo(id=cat["id"], color=cat["color"], label=cat["name"]) for cat in coco_categories ] +rr.log( + "/", + rr.AnnotationContext(class_descriptions), + timeless=True +) +``` + +## Detections +The detections and tracked bounding boxes are visualized by logging the [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d) to Rerun. + +### Detections +```python +rr.log( + "segmentation/detections/things", + rr.Boxes2D( + array=thing_boxes, + array_format=rr.Box2DFormat.XYXY, + class_ids=thing_class_ids, + ), +) +``` -For more info see [here](https://huggingface.co/docs/transformers/index) +```python +rr.log( + f"image/tracked/{self.tracking_id}", + rr.Boxes2D( + array=self.tracked.bbox_xywh, + array_format=rr.Box2DFormat.XYWH, + class_ids=self.tracked.class_id, + ), +) +``` +### Tracked bounding boxes +```python +rr.log( + "segmentation/detections/background", + rr.Boxes2D( + array=background_boxes, + array_format=rr.Box2DFormat.XYXY, + class_ids=background_class_ids, + ), +) +``` +The color and label of the bounding boxes is determined by their class id, relying on the same +[`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) as the +segmentation images. This ensures that a bounding box and a segmentation image with the same class id will also have the +same color. + +Note that it is also possible to log multiple annotation contexts should different colors and / or labels be desired. +The annotation context is resolved by seeking up the entity hierarchy. + +## Text Log +Rerun integrates with the [Python logging module](https://docs.python.org/3/library/logging.html). +Through the [`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log#textlogintegration) text at different importance level can be logged. After an initial setup that is described on the +[`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log#textlogintegration), statements +such as `logging.info("…")`, `logging.debug("…")`, etc. will show up in the Rerun viewer. + +```python +def setup_logging() -> None: + logger = logging.getLogger() + rerun_handler = rr.LoggingHandler("logs") + rerun_handler.setLevel(-1) + logger.addHandler(rerun_handler) + +def main() -> None: + # … existing code … + setup_logging() # setup logging + track_objects(video_path, max_frame_count=args.max_frame) # start tracking +``` +In the viewer you can adjust the filter level and look at the messages time-synchronized with respect to other logged data. + +# Run the Code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` + +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/detect_and_track_objects/requirements.txt -python examples/python/detect_and_track_objects/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/detect_and_track_objects/main.py # run the example +``` + +If you wish to customize it for various videos, adjust the maximum frames, explore additional features, or save it use the CLI with the `--help` option for guidance: + +```bash +python examples/python/detect_and_track_objects/main.py --help ``` diff --git a/examples/python/dicom_mri/README.md b/examples/python/dicom_mri/README.md index 2f4477b8af60..067c7a92f83b 100644 --- a/examples/python/dicom_mri/README.md +++ b/examples/python/dicom_mri/README.md @@ -16,9 +16,50 @@ channel = "main"
-Example using a [DICOM](https://en.wikipedia.org/wiki/DICOM) MRI scan. This demonstrates the flexible tensor slicing capabilities of the Rerun viewer. +Visualize a [DICOM](https://en.wikipedia.org/wiki/DICOM) MRI scan. This demonstrates the flexible tensor slicing capabilities of the Rerun viewer. +# Used Rerun Types +[`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) + +# Background +Digital Imaging and Communications in Medicine (DICOM) serves as a technical standard for the digital storage and transmission of medical images. In this instance, an MRI scan is visualized using Rerun. + +# Logging and Visualizing with Rerun + +The visualizations in this example were created with just the following line. +```python +rr.log("tensor", rr.Tensor(voxels_volume_u16, dim_names=["right", "back", "up"])) +``` + +A `numpy.array` named `voxels_volume_u16` representing volumetric MRI intensities with a shape of `(512, 512, 512)`. +To visualize this data effectively in Rerun, we can log the `numpy.array` as [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor) to the `tensor` entity. + +In the Rerun viewer you can also inspect the data in detail. The `dim_names` provided in the above call to `rr.log` help to +give semantic meaning to each axis. After selecting the tensor view, you can adjust various settings in the Blueprint +settings on the right-hand side. For example, you can adjust the color map, the brightness, which dimensions to show as +an image and which to select from, and more. + +# Run the Code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` + +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/dicom_mri/requirements.txt -python examples/python/dicom_mri/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/dicom_mri/main.py # run the example +``` + +If you wish to customize it, explore additional features, or save it, use the CLI with the `--help` option for guidance: + +```bash +python examples/python/dicom_mri/main.py --help ``` diff --git a/examples/python/face_tracking/README.md b/examples/python/face_tracking/README.md index c5c491e65efc..a93bb7255e75 100644 --- a/examples/python/face_tracking/README.md +++ b/examples/python/face_tracking/README.md @@ -1,6 +1,7 @@ @@ -15,44 +16,179 @@ thumbnail_dimensions = [480, 480]
-Use the [MediaPipe](https://google.github.io/mediapipe/) Face Detector and Landmarker solutions to detect and track a human face in image, videos, and camera stream. +Use the [MediaPipe](https://google.github.io/mediapipe/) Face Detector and Landmarker solutions to detect and track a human face in image, video, and camera stream. -```bash -pip install -r examples/python/face_tracking/requirements.txt -python examples/python/face_tracking/main.py +# Used Rerun Types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) + +# Background +The face and face landmark detection technology aims to give the ability of the devices to interpret face movements and facial expressions as commands or inputs. +At the core of this technology, a pre-trained machine-learning model analyses the visual input, locates face and identifies face landmarks and blendshape scores (coefficients representing facial expression). +Human-Computer Interaction, Robotics, Gaming, and Augmented Reality are among the fields where this technology shows significant promise for applications. + +In this example, the [MediaPipe](https://developers.google.com/mediapipe/) Face and Face Landmark Detection solutions were utilized to detect human face, detect face landmarks and identify facial expressions. +Rerun was employed to visualize the output of the Mediapipe solution over time to make it easy to analyze the behavior. + +# Logging and Visualizing with Rerun +The visualizations in this example were created with the following Rerun code. + +## Timelines + +For each processed video frame, all data sent to Rerun is associated with the two [`timelines`](https://www.rerun.io/docs/concepts/timelines) `time` and `frame_idx`. + +```python +rr.set_time_seconds("time", bgr_frame.time) +rr.set_time_sequence("frame_idx", bgr_frame.idx) +``` + +## Video +The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) objects to the 'Video' entity. +```python +rr.log( + "video/image", + rr.Image(frame).compress(jpeg_quality=75) +) +``` + +## Face Landmark Points +Logging the face landmarks involves specifying connections between the points, extracting face landmark points and logging them to the Rerun SDK. +The 2D points are visualized over the video/image for a better understanding and visualization of the face. +The 3D points allows the creation of a 3D model of the face reconstruction for a more comprehensive representation of the face. + +The 2D and 3D points are logged through a combination of two archetypes. First, a timeless +[`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description) is logged, that contains the information which maps keypoint ids to labels and how to connect +the keypoints. Defining these connections automatically renders lines between them. +Second, the actual keypoint positions are logged in 2D and 3D as [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d) and [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetypes, respectively. + +### Label Mapping and Keypoint Connections + +An annotation context is logged with one class ID assigned per facial feature. The class description includes the connections between corresponding keypoints extracted from the MediaPipe face mesh solution. +A class ID array is generated to match the class IDs in the annotation context with keypoint indices (to be utilized as the class_ids argument to rr.log). +```python +# Initialize a list of facial feature classes from MediaPipe face mesh solution +classes = [ + mp.solutions.face_mesh.FACEMESH_LIPS, + mp.solutions.face_mesh.FACEMESH_LEFT_EYE, + mp.solutions.face_mesh.FACEMESH_LEFT_IRIS, + mp.solutions.face_mesh.FACEMESH_LEFT_EYEBROW, + mp.solutions.face_mesh.FACEMESH_RIGHT_EYE, + mp.solutions.face_mesh.FACEMESH_RIGHT_EYEBROW, + mp.solutions.face_mesh.FACEMESH_RIGHT_IRIS, + mp.solutions.face_mesh.FACEMESH_FACE_OVAL, + mp.solutions.face_mesh.FACEMESH_NOSE, +] + +# Initialize class descriptions and class IDs array +self._class_ids = [0] * mp.solutions.face_mesh.FACEMESH_NUM_LANDMARKS_WITH_IRISES +class_descriptions = [] + +# Loop through each facial feature class +for i, klass in enumerate(classes): + # MediaPipe only provides connections for class, not actual class per keypoint. So we have to extract the + # classes from the connections. + ids = set() + for connection in klass: + ids.add(connection[0]) + ids.add(connection[1]) + + for id_ in ids: + self._class_ids[id_] = i + + # Append class description with class ID and keypoint connections + class_descriptions.append( + rr.ClassDescription( + info=rr.AnnotationInfo(id=i), + keypoint_connections=klass, + ) + ) + +# Log annotation context for video/landmarker and reconstruction entities +rr.log("video/landmarker", rr.AnnotationContext(class_descriptions), timeless=True) +rr.log("reconstruction", rr.AnnotationContext(class_descriptions), timeless=True) + +rr.log("reconstruction", rr.ViewCoordinates.RDF, timeless=True) # properly align the 3D face in the viewer +``` + +With the below annotation, the keypoints will be connected with lines to enhance visibility in the `video/detector` entity. +```python +rr.log( + "video/detector", + rr.ClassDescription( + info=rr.AnnotationInfo(id=0), keypoint_connections=[(0, 1), (1, 2), (2, 0), (2, 3), (0, 4), (1, 5)] + ), + timeless=True, +) +``` +### Bounding Box + +```python +rr.log( + f"video/detector/faces/{i}/bbox", + rr.Boxes2D( + array=[bbox.origin_x, bbox.origin_y, bbox.width, bbox.height], array_format=rr.Box2DFormat.XYWH + ), + rr.AnyValues(index=index, score=score), +) ``` -## Usage -CLI usage help is available using the `--help` option: +### 2D Points + +```python +rr.log( + f"video/detector/faces/{i}/keypoints", + rr.Points2D(pts, radii=3, keypoint_ids=list(range(6))) +) +``` +```python +rr.log( + f"video/landmarker/faces/{i}/landmarks", + rr.Points2D(pts, radii=3, keypoint_ids=keypoint_ids, class_ids=self._class_ids), +) ``` -$ python examples/python/face_tracking/main.py --help -usage: main.py [-h] [--demo-image] [--image IMAGE] [--video VIDEO] [--camera CAMERA] [--max-frame MAX_FRAME] [--max-dim MAX_DIM] [--num-faces NUM_FACES] [--headless] [--connect] [--serve] [--addr ADDR] [--save SAVE] -Uses the MediaPipe Face Detection to track a human pose in video. +### 3D Points -options: - -h, --help show this help message and exit - --demo-image Run on a demo image automatically downloaded - --image IMAGE Run on the provided image - --video VIDEO Run on the provided video file. - --camera CAMERA Run from the camera stream (parameter is the camera ID, usually 0 - --max-frame MAX_FRAME - Stop after processing this many frames. If not specified, will run until interrupted. - --max-dim MAX_DIM Resize the image such as its maximum dimension is not larger than this value. - --num-faces NUM_FACES - Max number of faces detected by the landmark model (temporal smoothing is applied only for a value of 1). - --headless Don't show GUI - --connect Connect to an external viewer - --serve Serve a web viewer (WARNING: experimental feature) - --addr ADDR Connect to this ip:port - --save SAVE Save data to a .rrd file at this path +```python +rr.log( + f"reconstruction/faces/{i}", + rr.Points3D( + [(lm.x, lm.y, lm.z) for lm in landmark], + keypoint_ids=keypoint_ids, + class_ids=self._class_ids, + ), +) ``` -Here is an overview of the options specific to this example: +## Scalar +Blendshapes are essentially predefined facial expressions or configurations that can be detected by the face landmark detection model. Each blendshape typically corresponds to a specific facial movement or expression, such as blinking, squinting, smiling, etc. + +The blendshapes are logged along with their corresponding scores. +```python +for blendshape in blendshapes: + if blendshape.category_name in BLENDSHAPES_CATEGORIES: + rr.log(f"blendshapes/{i}/{blendshape.category_name}", rr.Scalar(blendshape.score)) +``` -- *Running modes*: By default, this example streams images from the default webcam. Another webcam can be used by providing a camera index with the `--camera` option. Alternatively, images can be read from a video file (using `--video PATH`) or a single image file (using `--image PATH`). Also, a demo image with two faces can be automatically downloaded and used with `--demo-image`. -- *Max face count*: The maximum face detected by MediaPipe Face Landmarker can be set using `--num-faces NUM`. It defaults to 1, in which case the Landmarker applies temporal smoothing. This parameter doesn't affect MediaPipe Face Detector, which always attempts to detect all faces present in the input images. -- *Image downscaling*: By default, this example logs and runs on the native resolution of the provided images. Input images can be downscaled to a given maximum dimension using `--max-dim DIM`. -- *Limiting frame count*: When running from a webcam or a video file, this example can be set to stop after a given number of frames using `--max-frame MAX_FRAME`. +# Run the Code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/face_tracking/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/face_tracking/main.py # run the example +``` +If you wish to customize it for various videos, adjust the maximum frames, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/face_tracking/main.py --help +``` diff --git a/examples/python/gesture_detection/README.md b/examples/python/gesture_detection/README.md index 58231fe484a0..f717c31a4474 100644 --- a/examples/python/gesture_detection/README.md +++ b/examples/python/gesture_detection/README.md @@ -1,7 +1,7 @@ @@ -15,429 +15,133 @@ thumbnail_dimensions = [480, 480]
-# Run +Use the [MediaPipe](https://google.github.io/mediapipe/) Hand Landmark and Gesture Detection solutions to +track hands and recognize gestures in images, video, and camera stream. -```bash -# Install the required Python packages specified in the requirements file -pip install -r examples/python/gesture_detection/requirements.txt -python examples/python/gesture_detection/main.py -``` - -# Usage - -CLI usage help is available using the `--help` option: - -```bash -$ python examples/python/gesture_detection/main.py --help -usage: main.py [-h] [--demo-image] [--demo-video] [--image IMAGE] - [--video VIDEO] [--camera CAMERA] [--max-frame MAX_FRAME] - [--headless] [--connect] [--serve] [--addr ADDR] [--save SAVE] - [-o] - -Uses the MediaPipe Gesture Recognition to track a hand and recognize gestures -in image or video. - -optional arguments: - -h, --help show this help message and exit - --demo-image Run on a demo image automatically downloaded - --demo-video Run on a demo image automatically downloaded. - --image IMAGE Run on the provided image - --video VIDEO Run on the provided video file. - --camera CAMERA Run from the camera stream (parameter is the camera - ID, usually 0; or maybe 1 on mac) - --max-frame MAX_FRAME - Stop after processing this many frames. If not - specified, will run until interrupted. - --headless Don\'t show GUI - --connect Connect to an external viewer - --serve Serve a web viewer (WARNING: experimental feature) - --addr ADDR Connect to this ip:port - --save SAVE Save data to a .rrd file at this path - -o, --stdout Log data to standard output, to be piped into a Rerun - Viewer -``` - -Here is an overview of the options specific to this example: - -- ***Running modes*:** By default, this example streams images from the default webcam. Another webcam can be used by - providing a camera index with the `--camera` option. Alternatively, images can be read from a video file ( - using `--video PATH`) or a single image file (using `-image PATH`). Also, a demo image can be automatically downloaded - and used with `--demo-image`. Also, a demo video can be automatically downloaded and used with `--demo-video`. -- ***Limiting frame count*:** When running from a webcam or a video file, this example can be set to stop after a given - number of frames using `--max-frame MAX_FRAME`. - -# Overview - -Use the [MediaPipe](https://google.github.io/mediapipe/) Gesture detection and Gesture landmark detection solutions to -track hands and recognize gestures in images and videos. - -Logging Details: - -1. Hand Landmarks as 2D Points: - - - Extracts hand landmark points as normalized 2D coordinates. - - - Utilizes image width and height for conversion into image coordinates. - - - Logs the 2D points to the Rerun SDK. - - -2. Hand Landmarks as 3D Points: - - - Detects hand landmarks using MediaPipe solutions. - - - Converts the detected hand landmarks into 3D coordinates. - - - Logs the 3D points to the Rerun SDK. - - -3. Gesture Detection Results: +# Used Rerun Types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`LineStrips2D`](https://www.rerun.io/docs/reference/types/archetypes/line_strips2d), [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) - - Utilizes the Gesture Detection solution from MediaPipe. +# Background +The hand tracking and gesture recognition technology aims to give the ability of the devices to interpret hand movements and gestures as commands or inputs. +At the core of this technology, a pre-trained machine-learning model analyses the visual input and identifies hand landmarks and hand gestures. +The real applications of such technology vary, as hand movements and gestures can be used to control smart devices. +Human-Computer Interaction, Robotics, Gaming, and Augmented Reality are a few of the fields where the potential applications of this technology appear most promising. - - Logs the results of gesture detection as emoji +In this example, the [MediaPipe](https://developers.google.com/mediapipe/) Gesture and Hand Landmark Detection solutions were utilized to detect and track hand landmarks and recognize gestures. +Rerun was employed to visualize the output of the Mediapipe solution over time to make it easy to analyze the behavior. -# Logging Data +# Logging and Visualizing with Rerun +The visualizations in this example were created with the following Rerun code. -## Timelines for Video +## Timelines -You can utilize Rerun timelines' functions to associate data with one or more timelines. As a result, each frame of the -video can be linked with its corresponding timestamp. +For each processed video frame, all data sent to Rerun is associated with the two [`timelines`](https://www.rerun.io/docs/concepts/timelines) `time` and `frame_idx`. ```python -def run_from_video_capture(vid: int | str, max_frame_count: int | None) -> None: - """ - Run the detector on a video stream. - - Parameters - ---------- - vid: - The video stream to run the detector on. Use 0/1 for the default camera or a path to a video file. - max_frame_count: - The maximum number of frames to process. If None, process all frames. - """ - cap = cv2.VideoCapture(vid) - fps = cap.get(cv2.CAP_PROP_FPS) - - detector = GestureDetectorLogger(video_mode=True) - - try: - it: Iterable[int] = itertools.count() if max_frame_count is None else range(max_frame_count) - - for frame_idx in tqdm.tqdm(it, desc="Processing frames"): - ret, frame = cap.read() - if not ret: - break - - if np.all(frame == 0): - continue - - frame_time_nano = int(cap.get(cv2.CAP_PROP_POS_MSEC) * 1e6) - if frame_time_nano == 0: - frame_time_nano = int(frame_idx * 1000 / fps * 1e6) - - frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) - - rr.set_time_sequence("frame_nr", frame_idx) - rr.set_time_nanos("frame_time", frame_time_nano) - detector.detect_and_log(frame, frame_time_nano) - rr.log( - "Media/Video", - rr.Image(frame) - ) - - except KeyboardInterrupt: - pass - - cap.release() - cv2.destroyAllWindows() +rr.set_time_sequence("frame_nr", frame_idx) +rr.set_time_nanos("frame_time", frame_time_nano) ``` -## Hand Landmarks as 2D Points - -![gesture_recognition_2d_points](https://github.com/rerun-io/rerun/assets/49308613/7e5dd809-be06-4f62-93a8-4fc03e5dfa0e) - -You can extract hand landmark points as normalized values, utilizing the image's width and height for conversion into -image coordinates. These coordinates are then logged as 2D points to the Rerun SDK. Additionally, you can identify -connections between the landmarks and log them as 2D linestrips. - +## Video +The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) objects to the `Media/Video` entity. ```python -class GestureDetectorLogger: - - def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int | None) -> None: - # Recognize gestures in the image - height, width, _ = image.shape - image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image) - - recognition_result = ( - self.recognizer.recognize_for_video(image, int(frame_time_nano / 1e6)) - if self._video_mode - else self.recognizer.recognize(image) - ) - - # Clear the values - for log_key in ["Media/Points", "Media/Connections"]: - rr.log(log_key, rr.Clear(recursive=True)) - - if recognition_result.hand_landmarks: - hand_landmarks = recognition_result.hand_landmarks - - # Convert normalized coordinates to image coordinates - points = self.convert_landmarks_to_image_coordinates(hand_landmarks, width, height) - - # Log points to the image and Hand Entity - rr.log( - "Media/Points", - rr.Points2D(points, radii=10, colors=[255, 0, 0]) - ) - - # Obtain hand connections from MediaPipe - mp_hands_connections = mp.solutions.hands.HAND_CONNECTIONS - points1 = [points[connection[0]] for connection in mp_hands_connections] - points2 = [points[connection[1]] for connection in mp_hands_connections] - - # Log connections to the image and Hand Entity - rr.log( - "Media/Connections", - rr.LineStrips2D( - np.stack((points1, points2), axis=1), - colors=[255, 165, 0] - ) - ) +rr.log( + "Media/Video", + rr.Image(frame).compress(jpeg_quality=75) +) ``` -## Hand Landmarks as 3D Points +## Hand Landmark Points +Logging the hand landmarks involves specifying connections between the points, extracting pose landmark points and logging them to the Rerun SDK. +The 2D points are visualized over the video and at a separate entity. +Meanwhile, the 3D points allows the creation of a 3D model of the hand for a more comprehensive representation of the hand landmarks. -![gesture_recognition_3d_points](https://github.com/rerun-io/rerun/assets/49308613/b24bb0e5-57cc-43f0-948b-3480fe9073a2) +The 2D and 3D points are logged through a combination of two archetypes. +For the 2D points, the Points2D and LineStrips2D archetypes are utilized. These archetypes help visualize the points and connect them with lines, respectively. +As for the 3D points, the logging process involves two steps. First, a timeless [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description) is logged, that contains the information which maps keypoint ids to labels and how to connect +the keypoints. Defining these connections automatically renders lines between them. Mediapipe provides the `HAND_CONNECTIONS` variable which contains the list of `(from, to)` landmark indices that define the connections. +Second, the actual keypoint positions are logged in 3D [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype. -You can first define the connections between the points using keypoints from Annotation Context in the init function, -and then log them as 3D points. +### Label Mapping and Keypoint Connections ```python - -class GestureDetectorLogger: - - def __init__(self, video_mode: bool = False): - # … existing code … - rr.log( - "/", - rr.AnnotationContext( - rr.ClassDescription( - info=rr.AnnotationInfo(id=0, label="Hand3D"), - keypoint_connections=mp.solutions.hands.HAND_CONNECTIONS - ) - ), - timeless=True, +rr.log( + "/", + rr.AnnotationContext( + rr.ClassDescription( + info=rr.AnnotationInfo(id=0, label="Hand3D"), + keypoint_connections=mp.solutions.hands.HAND_CONNECTIONS, ) - rr.log("Hand3D", rr.ViewCoordinates.RIGHT_HAND_X_DOWN, timeless=True) - - -def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int | None) -> None: - # … existing code … - - if recognition_result.hand_landmarks: - hand_landmarks = recognition_result.hand_landmarks + ), + timeless=True, +) - landmark_positions_3d = self.convert_landmarks_to_3d(hand_landmarks) - if landmark_positions_3d is not None: - rr.log( - "Hand3D/Points", - rr.Points3D(landmark_positions_3d, radii=20, class_ids=0, - keypoint_ids=[i for i in range(len(landmark_positions_3d))]), - ) - - # … existing code … +rr.log("Hand3D", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, timeless=True) ``` -## Gesture Detection Presentation - -![Gesture Detection Presentation](https://github.com/rerun-io/rerun/assets/49308613/32cc44f4-28e5-4ed1-b283-f7351a087535) -One effective method to present these results to the viewer is by utilizing a TextDocument along with emojis for -enhanced visual communication. +### 2D Points ```python +# Log points to the image and Hand Entity +for log_key in ["Media/Points", "Hand/Points"]: + rr.log( + log_key, + rr.Points2D(points, radii=10, colors=[255, 0, 0]) + ) -# Emojis from https://github.com/googlefonts/noto-emoji/tree/main -GESTURE_URL = "https://raw.githubusercontent.com/googlefonts/noto-emoji/9cde38ef5ee6f090ce23f9035e494cb390a2b051/png/128/" - -# Mapping of gesture categories to corresponding emojis -GESTURE_PICTURES = { - "None": "emoji_u2754.png", - "Closed_Fist": "emoji_u270a.png", - "Open_Palm": "emoji_u270b.png", - "Pointing_Up": "emoji_u261d.png", - "Thumb_Down": "emoji_u1f44e.png", - "Thumb_Up": "emoji_u1f44d.png", - "Victory": "emoji_u270c.png", - "ILoveYou": "emoji_u1f91f.png" -} - - -class GestureDetectorLogger: - - def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int | None) -> None: - # Recognize gestures in the image - height, width, _ = image.shape - image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image) - - recognition_result = ( - self.recognizer.recognize_for_video(image, int(frame_time_nano / 1e6)) - if self._video_mode - else self.recognizer.recognize(image) - ) - - for log_key in ["Media/Points", "Hand/Points", "Media/Connections", "Hand/Connections", "Hand3D/Points"]: - rr.log(log_key, rr.Clear(recursive=True)) - - for i, gesture in enumerate(recognition_result.gestures): - # Get the top gesture from the recognition result - gesture_category = gesture[0].category_name if recognition_result.gestures else "None" - self.present_detected_gesture(gesture_category) # Log the detected gesture - - def present_detected_gesture(self, category): - # Get the corresponding ulr of the picture for the detected gesture category - gesture_pic = GESTURE_PICTURES.get( - category, - "emoji_u2754.png" # default - ) - - # Log the detection by using the appropriate image - rr.log( - "Detection", - rr.TextDocument( - f'![Image]({GESTURE_URL + gesture_pic})'.strip(), - media_type=rr.MediaType.MARKDOWN - ) - ) - +# Log connections to the image and Hand Entity [128, 128, 128] +for log_key in ["Media/Connections", "Hand/Connections"]: + rr.log( + log_key, + rr.LineStrips2D(np.stack((points1, points2), axis=1), colors=[255, 165, 0]) + ) ``` -# Gesture Detector Logger +### 3D Points ```python +rr.log( + "Hand3D/Points", + rr.Points3D( + landmark_positions_3d, + radii=20, + class_ids=0, + keypoint_ids=[i for i in range(len(landmark_positions_3d))], + ), +) +``` -class GestureDetectorLogger: - """ - Logger for the MediaPipe Gesture Detection solution. - This class provides logging and utility functions for handling gesture recognition. - - For more information on MediaPipe Gesture Detection: - https://developers.google.com/mediapipe/solutions/vision/gesture_recognizer - """ - - # URL to the pre-trained MediaPipe Gesture Detection model - MODEL_DIR: Final = EXAMPLE_DIR / "model" - MODEL_PATH: Final = (MODEL_DIR / "gesture_recognizer.task").resolve() - MODEL_URL: Final = ( - "https://storage.googleapis.com/mediapipe-models/gesture_recognizer/gesture_recognizer/float16/latest/gesture_recognizer.task" - ) - - def __init__(self, video_mode: bool = False): - self._video_mode = video_mode - - if not self.MODEL_PATH.exists(): - download_file(self.MODEL_URL, self.MODEL_PATH) - - base_options = python.BaseOptions( - model_asset_path=str(self.MODEL_PATH) - ) - options = vision.GestureRecognizerOptions( - base_options=base_options, - running_mode=mp.tasks.vision.RunningMode.VIDEO if self._video_mode else mp.tasks.vision.RunningMode.IMAGE - ) - self.recognizer = vision.GestureRecognizer.create_from_options(options) - - rr.log( - "/", - rr.AnnotationContext( - rr.ClassDescription( - info=rr.AnnotationInfo(id=0, label="Hand3D"), - keypoint_connections=mp.solutions.hands.HAND_CONNECTIONS - ) - ), - timeless=True, - ) - # rr.log("Hand3D", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, timeless=True) - rr.log("Hand3D", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, timeless=True) - - @staticmethod - def convert_landmarks_to_image_coordinates(hand_landmarks, width, height): - return [(int(lm.x * width), int(lm.y * height)) for hand_landmark in hand_landmarks for lm in hand_landmark] - - @staticmethod - def convert_landmarks_to_3d(hand_landmarks): - return [(lm.x, lm.y, lm.y) for hand_landmark in hand_landmarks for lm in hand_landmark] - - def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int | None) -> None: - # Recognize gestures in the image - height, width, _ = image.shape - image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image) - - recognition_result = ( - self.recognizer.recognize_for_video(image, int(frame_time_nano / 1e6)) - if self._video_mode - else self.recognizer.recognize(image) - ) - - for log_key in ["Media/Points", "Hand/Points", "Media/Connections", "Hand/Connections", "Hand3D/Points"]: - rr.log(log_key, rr.Clear(recursive=True)) - - for i, gesture in enumerate(recognition_result.gestures): - # Get the top gesture from the recognition result - gesture_category = gesture[0].category_name if recognition_result.gestures else "None" - self.present_detected_gesture(gesture_category) # Log the detected gesture - - if recognition_result.hand_landmarks: - hand_landmarks = recognition_result.hand_landmarks - - landmark_positions_3d = self.convert_landmarks_to_3d(hand_landmarks) - if landmark_positions_3d is not None: - rr.log( - "Hand3D/Points", - rr.Points3D(landmark_positions_3d, radii=20, class_ids=0, - keypoint_ids=[i for i in range(len(landmark_positions_3d))]), - ) - - # Convert normalized coordinates to image coordinates - points = self.convert_landmarks_to_image_coordinates(hand_landmarks, width, height) - - # Log points to the image and Hand Entity - for log_key in ["Media/Points", "Hand/Points"]: - rr.log( - log_key, - rr.Points2D(points, radii=10, colors=[255, 0, 0]) - ) - - # Obtain hand connections from MediaPipe - mp_hands_connections = mp.solutions.hands.HAND_CONNECTIONS - points1 = [points[connection[0]] for connection in mp_hands_connections] - points2 = [points[connection[1]] for connection in mp_hands_connections] +## Detection - # Log connections to the image and Hand Entity [128, 128, 128] - for log_key in ["Media/Connections", "Hand/Connections"]: - rr.log( - log_key, - rr.LineStrips2D( - np.stack((points1, points2), axis=1), - colors=[255, 165, 0] - ) - ) +To showcase gesture recognition, an image of the corresponding gesture emoji is displayed within a `TextDocument` under the `Detection` entity. - def present_detected_gesture(self, category): - # Get the corresponding ulr of the picture for the detected gesture category - gesture_pic = GESTURE_PICTURES.get( - category, - "emoji_u2754.png" # default - ) - - # Log the detection by using the appropriate image - rr.log( - "Detection", - rr.TextDocument( - f'![Image]({GESTURE_URL + gesture_pic})'.strip(), - media_type=rr.MediaType.MARKDOWN - ) - ) +```python +# Log the detection by using the appropriate image +rr.log( + "Detection", + rr.TextDocument(f"![Image]({GESTURE_URL + gesture_pic})".strip(), media_type=rr.MediaType.MARKDOWN), +) +``` +# Run the Code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/gesture_detection/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/gesture_detection/main.py # run the example +``` +If you wish to customize it for various videos, adjust the maximum frames, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +$ python examples/python/gesture_detection/main.py --help ``` diff --git a/examples/python/human_pose_tracking/README.md b/examples/python/human_pose_tracking/README.md index adec70e1b05c..f0730103153f 100644 --- a/examples/python/human_pose_tracking/README.md +++ b/examples/python/human_pose_tracking/README.md @@ -19,11 +19,16 @@ Use the [MediaPipe Pose Landmark Detection](https://developers.google.com/mediap -## Used Rerun Types +# Used Rerun Types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) -## Background -The [MediaPipe Pose Landmark Detection](https://developers.google.com/mediapipe/solutions/vision/pose_landmarker) solution detects and tracks human pose landmarks and produces segmentation masks for humans. The solution targets real-time inference on video streams. In this example we use Rerun to visualize the output of the Mediapipe solution over time to make it easy to analyze the behavior. +# Background +Human pose tracking is a task in computer vision that focuses on identifying key body locations, analyzing posture, and categorizing movements. +At the heart of this technology is a pre-trained machine-learning model to assess the visual input and recognize landmarks on the body in both image coordinates and 3D world coordinates. +The use cases and applications of this technology include but are not limited to Human-Computer Interaction, Sports Analysis, Gaming, Virtual Reality, Augmented Reality, Health, etc. + +In this example, the [MediaPipe Pose Landmark Detection](https://developers.google.com/mediapipe/solutions/vision/pose_landmarker) solution was utilized to detect and track human pose landmarks and produces segmentation masks for humans. +Rerun was employed to visualize the output of the Mediapipe solution over time to make it easy to analyze the behavior. # Logging and Visualizing with Rerun diff --git a/examples/python/lidar/README.md b/examples/python/lidar/README.md index 15feac668d08..b8c572aeb3bc 100644 --- a/examples/python/lidar/README.md +++ b/examples/python/lidar/README.md @@ -15,9 +15,49 @@ thumbnail_dimensions = [480, 480]
-This example visualizes only the lidar data from the [nuScenes dataset](https://www.nuscenes.org/) using Rerun. For a moe extensive example including other sensors and annotations check out the [nuScenes example](https://www.rerun.io/examples/real-data/nuscenes). +Visualize the LiDAR data from the [nuScenes dataset](https://www.nuscenes.org/). +# Used Rerun Types +[`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) + +# Background +This example demonstrates the ability to read and visualize LiDAR data from the nuScenes dataset, which is a public large-scale dataset specifically designed for autonomous driving. +The scenes in this dataset encompass data collected from a comprehensive suite of sensors on autonomous vehicles, including 6 cameras, 1 LIDAR, 5 RADAR, GPS and IMU sensors. + + +It's important to note that in this example, only the LiDAR data is visualized. For a more extensive example including other sensors and annotations check out the [nuScenes example](https://www.rerun.io/examples/real-data/nuscenes). + +# Logging and Visualizing with Rerun + +The visualization in this example was created with just the following lines. + + +```python +rr.set_time_seconds("timestamp", sample_data["timestamp"] * 1e-6) # Setting the time +rr.log("world/lidar", rr.Points3D(points, colors=point_colors)) # Log the 3D data +``` + +When logging data to Rerun, it's possible to associate it with specific time by using the Rerun's [`timelines`](https://www.rerun.io/docs/concepts/timelines). +In the following code, we first establish the desired time frame and then proceed to log the 3D data points. + +# Run the Code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/lidar/requirements.txt -python examples/python/lidar/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/lidar/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/lidar/main.py --help ``` diff --git a/examples/python/live_camera_edge_detection/README.md b/examples/python/live_camera_edge_detection/README.md index 3b404e072867..f480e14c2116 100644 --- a/examples/python/live_camera_edge_detection/README.md +++ b/examples/python/live_camera_edge_detection/README.md @@ -1,6 +1,7 @@ @@ -14,11 +15,65 @@ thumbnail_dimensions = [480, 480] Live Camera Edge Detection example screenshot
-Very simple example of capturing from a live camera. +Visualize the [OpenCV Canny Edge Detection](https://docs.opencv.org/4.x/da/d22/tutorial_py_canny.html) results from a live camera stream. -Runs the opencv canny edge detector on the image stream. +# Used Rerun Types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) -Usage: +# Background +In this example, the results of the [OpenCV Canny Edge Detection](https://docs.opencv.org/4.x/da/d22/tutorial_py_canny.html) algorithm are visualized. +Canny Edge Detection is a popular edge detection algorithm, and can efficiently extract important structural information from visual objects while notably reducing the computational load. +The process in this example involves converting the input image to RGB, then to grayscale, and finally applying the Canny Edge Detector for precise edge detection. + +# Logging and Visualizing with Rerun + +The visualization in this example were created with the following Rerun code: +## RGB Image + +The original image is read and logged in RGB format under the entity "image/rgb". +```python +# Log the original image +rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) +rr.log("image/rgb", rr.Image(rgb)) +``` + +## Grayscale Image + +The input image is converted from BGR color space to grayscale, and the resulting grayscale image is logged under the entity "image/gray". +```python +# Convert to grayscale +gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) +rr.log("image/gray", rr.Image(gray)) +``` + +## Canny Edge Detection Image + +The Canny edge detector is applied to the grayscale image, and the resulting edge-detected image is logged under the entity "image/canny". +```python +# Run the canny edge detector +canny = cv2.Canny(gray, 50, 200) +rr.log("image/canny", rr.Image(canny)) +``` + + +# Run the Code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/live_camera_edge_detection/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/live_camera_edge_detection/main.py # run the example ``` -python examples/python/live_camera_edge_detection/main.py +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/live_camera_edge_detection/main.py --help ``` diff --git a/examples/python/live_depth_sensor/README.md b/examples/python/live_depth_sensor/README.md index 2762fc8ebc92..e085beb0635d 100644 --- a/examples/python/live_depth_sensor/README.md +++ b/examples/python/live_depth_sensor/README.md @@ -1,6 +1,7 @@ @@ -14,10 +15,106 @@ thumbnail_dimensions = [480, 360] Live Depth Sensor example screenshot
+Visualize the live-streaming frames from an Intel RealSense depth sensor. -A minimal example of streaming frames live from an Intel RealSense depth sensor. +This example requires a connected realsense depth sensor. -Usage: +# Used Rerun Types +[`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image) + +# Background +The Intel RealSense depth sensor can stream live depth and color data. To visualize this data output, we utilized Rerun. + +# Logging and Visualizing with Rerun + +The RealSense sensor captures data in both RGB and depth formats, which are logged using the [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) and [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image) archetypes, respectively. +Additionally, to provide a 3D view, the visualization includes a pinhole camera using the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) and [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetypes. + +The visualization in this example were created with the following Rerun code. + +```python +rr.log("realsense", rr.ViewCoordinates.RDF, timeless=True) # Visualize the data as RDF +``` + + + +## Image + +First, the pinhole camera is set using the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) and [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetypes. Then, the images captured by the RealSense sensor are logged as an [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) object, and they're associated with the time they were taken. + + + +```python +rgb_from_depth = depth_profile.get_extrinsics_to(rgb_profile) + rr.log( + "realsense/rgb", + rr.Transform3D( + translation=rgb_from_depth.translation, + mat3x3=np.reshape(rgb_from_depth.rotation, (3, 3)), + from_parent=True, + ), + timeless=True, +) +``` + +```python +rr.log( + "realsense/rgb/image", + rr.Pinhole( + resolution=[rgb_intr.width, rgb_intr.height], + focal_length=[rgb_intr.fx, rgb_intr.fy], + principal_point=[rgb_intr.ppx, rgb_intr.ppy], + ), + timeless=True, +) +``` +```python +rr.set_time_sequence("frame_nr", frame_nr) +rr.log("realsense/rgb/image", rr.Image(color_image)) +``` + +## Depth Image + +Just like the RGB images, the RealSense sensor also captures depth data. The depth images are logged as [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image) objects and are linked with the time they were captured. + +```python +rr.log( + "realsense/depth/image", + rr.Pinhole( + resolution=[depth_intr.width, depth_intr.height], + focal_length=[depth_intr.fx, depth_intr.fy], + principal_point=[depth_intr.ppx, depth_intr.ppy], + ), + timeless=True, +) +``` +```python +rr.set_time_sequence("frame_nr", frame_nr) +rr.log("realsense/depth/image", rr.DepthImage(depth_image, meter=1.0 / depth_units)) +``` + + + + + +# Run the Code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/live_depth_sensor/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/live_depth_sensor/main.py # run the example ``` -examples/python/live_depth_sensor/main.py +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/live_depth_sensor/main.py --help ``` From 464f4fcf99e3a782d45bf4bc276b997a0df68133 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 4 Apr 2024 13:00:44 -0400 Subject: [PATCH 187/508] Prevent gratuitous blueprint saves by not gc'ing when the blueprint hasn't changed (#5793) ### What Whenever we gc the blueprint, it bumps the generation, which in turn causes another save. By tracking the last gc, we never re-gc again if nothing has changed. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5793) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5793?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5793?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5793) - [Docs preview](https://rerun.io/preview/b0543dcc9e0c0d9abd4fe67e940bf101794d0566/docs) - [Examples preview](https://rerun.io/preview/b0543dcc9e0c0d9abd4fe67e940bf101794d0566/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer_context/src/store_hub.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index afcf64a1667a..763f07dbf57f 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -45,8 +45,11 @@ pub struct StoreHub { /// Was a recording ever activated? Used by the heuristic controlling the welcome screen. was_recording_active: bool, - // The [`StoreGeneration`] from when the [`EntityDb`] was last saved + /// The [`StoreGeneration`] from when the [`EntityDb`] was last saved blueprint_last_save: HashMap, + + /// The [`StoreGeneration`] from when the [`EntityDb`] was last garbage collected + blueprint_last_gc: HashMap, } /// Load a blueprint from persisted storage, e.g. disk. @@ -128,6 +131,7 @@ impl StoreHub { was_recording_active: false, blueprint_last_save: Default::default(), + blueprint_last_gc: Default::default(), } } @@ -547,9 +551,16 @@ impl StoreHub { .chain(self.default_blueprint_by_app_id.values()) { if let Some(blueprint) = self.store_bundle.get_mut(blueprint_id) { + if self.blueprint_last_gc.get(blueprint_id) == Some(&blueprint.generation()) { + continue; // no change since last gc + } + // TODO(jleibs): Decide a better tuning for this. Would like to save a // reasonable amount of history, or incremental snapshots. blueprint.gc_everything_but_the_latest_row(); + + self.blueprint_last_gc + .insert(blueprint_id.clone(), blueprint.generation()); } } } @@ -579,6 +590,8 @@ impl StoreHub { if app_options.blueprint_gc { blueprint.gc_everything_but_the_latest_row(); + self.blueprint_last_gc + .insert(blueprint_id.clone(), blueprint.generation()); } if let Some(saver) = &self.persistence.saver { From 3d68b5216e7191064588c846cb89bb7ede172147 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Apr 2024 19:04:22 +0200 Subject: [PATCH 188/508] On Web, implement navigating back/forward with mouse buttons (#5792) ### What By popular request ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5792) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5792?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5792?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5792) - [Docs preview](https://rerun.io/preview/fb21b7fbbebe58182dfe33276e81c59540393683/docs) - [Examples preview](https://rerun.io/preview/fb21b7fbbebe58182dfe33276e81c59540393683/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app.rs | 16 ++++++++++++++++ crates/re_viewer/src/web_tools.rs | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index afc03349e791..a306786b2509 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -1320,6 +1320,22 @@ impl eframe::App for App { .add(egui_ctx.input(|i| i.time), seconds); } + #[cfg(target_arch = "wasm32")] + { + // Handle pressing the back/forward mouse buttons explicitly, since eframe catches those. + let back_pressed = + egui_ctx.input(|i| i.pointer.button_pressed(egui::PointerButton::Extra1)); + let fwd_pressed = + egui_ctx.input(|i| i.pointer.button_pressed(egui::PointerButton::Extra2)); + + if back_pressed { + crate::web_tools::go_back(); + } + if fwd_pressed { + crate::web_tools::go_forward(); + } + } + // Temporarily take the `StoreHub` out of the Viewer so it doesn't interfere with mutability let mut store_hub = self.store_hub.take().unwrap(); diff --git a/crates/re_viewer/src/web_tools.rs b/crates/re_viewer/src/web_tools.rs index 4d912fbcd23a..32f83476cfa5 100644 --- a/crates/re_viewer/src/web_tools.rs +++ b/crates/re_viewer/src/web_tools.rs @@ -31,6 +31,28 @@ pub fn percent_encode(s: &str) -> String { format!("{}", js_sys::encode_uri_component(s)) } +pub fn go_back() -> Option<()> { + let history = web_sys::window()? + .history() + .map_err(|err| format!("Failed to get History API: {}", string_from_js_value(err))) + .ok_or_log_error()?; + history + .back() + .map_err(|err| format!("Failed to go back: {}", string_from_js_value(err))) + .ok_or_log_error() +} + +pub fn go_forward() -> Option<()> { + let history = web_sys::window()? + .history() + .map_err(|err| format!("Failed to get History API: {}", string_from_js_value(err))) + .ok_or_log_error()?; + history + .forward() + .map_err(|err| format!("Failed to go forward: {}", string_from_js_value(err))) + .ok_or_log_error() +} + /// The current percent-encoded URL suffix, e.g. "?foo=bar#baz". pub fn current_url_suffix() -> Option { let location = web_sys::window()?.location(); From 21db99d6a1ab9c9fddab4d6f1848876a0264fc50 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 4 Apr 2024 19:04:35 +0200 Subject: [PATCH 189/508] Switch away from Title Casing in our Markdown headers (#5779) ### What For consistency! This can be fixed with `pixi run lint-rerun --fix --extra`, but because of too many false positives I decided not to run the lint normally (hence the new `--extra` flag) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5779) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5779?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5779?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5779) - [Docs preview](https://rerun.io/preview/af4b618dc75653fc8e47b82f91bd5197730287c9/docs) - [Examples preview](https://rerun.io/preview/af4b618dc75653fc8e47b82f91bd5197730287c9/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/README.md | 4 +- BUILD.md | 2 +- CHANGELOG.md | 150 +++++++++--------- CONTRIBUTING.md | 2 +- README.md | 2 +- RELEASES.md | 2 +- crates/re_data_store/README.md | 2 +- .../definitions/rerun/archetypes/arrows2d.fbs | 2 +- .../definitions/rerun/archetypes/arrows3d.fbs | 2 +- .../definitions/rerun/archetypes/pinhole.fbs | 4 +- .../rerun/archetypes/series_line.fbs | 2 +- .../rerun/archetypes/series_point.fbs | 2 +- .../definitions/rerun/archetypes/tensor.fbs | 2 +- crates/re_types/src/archetypes/arrows2d.rs | 2 +- crates/re_types/src/archetypes/arrows3d.rs | 2 +- crates/re_types/src/archetypes/pinhole.rs | 4 +- crates/re_types/src/archetypes/series_line.rs | 2 +- .../re_types/src/archetypes/series_point.rs | 2 +- crates/re_types/src/archetypes/tensor.rs | 2 +- .../data/quick_start_guides/cpp_connect.md | 2 +- .../data/quick_start_guides/cpp_spawn.md | 2 +- .../data/quick_start_guides/python_connect.md | 2 +- .../data/quick_start_guides/python_spawn.md | 2 +- .../data/quick_start_guides/rust_connect.md | 2 +- .../data/quick_start_guides/rust_spawn.md | 2 +- design/batching.md | 4 +- design/blueprint_store.md | 12 +- design/space_views.md | 22 +-- design/spatial_transforms.md | 2 +- docs/content/concepts/annotation-context.md | 6 +- docs/content/concepts/blueprint.md | 2 +- docs/content/concepts/entity-component.md | 4 +- docs/content/concepts/entity-path.md | 6 +- .../content/concepts/spaces-and-transforms.md | 2 +- .../configure-the-viewer/interactively.md | 12 +- .../through-code-tutorial.md | 2 +- docs/content/getting-started/data-in/cpp.md | 4 +- .../content/getting-started/data-in/python.md | 6 +- docs/content/getting-started/data-in/rust.md | 6 +- .../getting-started/installing-viewer.md | 4 +- .../howto/configure-viewer-through-code.md | 2 +- docs/content/howto/extend/extend-ui.md | 4 +- docs/content/howto/notebook.md | 4 +- docs/content/howto/ros2-nav-turtlebot.md | 8 +- .../reference/migration/migration-0-13.md | 2 +- .../reference/migration/migration-0-9.md | 6 +- docs/content/reference/sdk-operating-modes.md | 2 +- docs/content/reference/types.md | 8 +- .../reference/types/archetypes/arrows2d.md | 2 +- .../reference/types/archetypes/arrows3d.md | 2 +- .../reference/types/archetypes/pinhole.md | 4 +- .../reference/types/archetypes/series_line.md | 2 +- .../types/archetypes/series_point.md | 2 +- .../reference/types/archetypes/tensor.md | 2 +- docs/content/reference/viewer/blueprint.md | 4 +- docs/content/reference/viewer/overview.md | 2 +- docs/content/reference/viewer/selection.md | 2 +- docs/snippets/README.md | 2 +- examples/c/spawn_viewer/README.md | 2 +- examples/cpp/README.md | 2 +- .../cpp/custom_collection_adapter/README.md | 2 +- examples/cpp/eigen_opencv/README.md | 2 +- examples/cpp/incremental_logging/README.md | 2 +- examples/cpp/spawn_viewer/README.md | 2 +- examples/cpp/vrs/README.md | 2 +- examples/python/README.md | 2 +- examples/python/arflow/README.md | 4 +- examples/python/arkit_scenes/README.md | 8 +- examples/python/blueprint_stocks/README.md | 2 +- examples/python/controlnet/README.md | 6 +- .../depth_guided_stable_diffusion/README.md | 8 +- .../python/detect_and_track_objects/README.md | 2 +- .../differentiable_blocks_world/README.md | 2 +- examples/python/face_tracking/README.md | 2 +- examples/python/gesture_detection/README.md | 11 +- examples/python/human_pose_tracking/README.md | 22 +-- examples/python/incremental_logging/README.md | 2 +- examples/python/limap/README.md | 2 +- .../live_camera_edge_detection/README.md | 2 +- examples/python/live_depth_sensor/README.md | 2 +- examples/python/llm_embedding_ner/README.md | 16 +- examples/python/mcc/README.md | 2 +- examples/python/nuscenes/README.md | 16 +- examples/python/objectron/README.md | 10 +- .../open_photogrammetry_format/README.md | 8 +- examples/python/raw_mesh/README.md | 8 +- examples/python/ros_node/README.md | 2 +- .../python/signed_distance_fields/README.md | 2 +- examples/python/simplerecon/README.md | 2 +- examples/python/slahmr/README.md | 2 +- .../python/structure_from_motion/README.md | 2 +- examples/python/tapir/README.md | 2 +- examples/python/widebaseline/README.md | 2 +- examples/rust/README.md | 2 +- examples/rust/extend_viewer_ui/README.md | 2 +- examples/rust/incremental_logging/README.md | 2 +- examples/rust/raw_mesh/README.md | 2 +- examples/rust/spawn_viewer/README.md | 2 +- rerun_cpp/README.md | 6 +- rerun_cpp/arrow_cpp_install.md | 2 +- rerun_cpp/cmake_setup_in_detail.md | 2 +- rerun_cpp/docs/writing_docs.md | 2 +- rerun_cpp/src/rerun/archetypes/arrows2d.hpp | 2 +- rerun_cpp/src/rerun/archetypes/arrows3d.hpp | 2 +- rerun_cpp/src/rerun/archetypes/pinhole.hpp | 4 +- .../src/rerun/archetypes/series_line.hpp | 2 +- .../src/rerun/archetypes/series_point.hpp | 2 +- rerun_cpp/src/rerun/archetypes/tensor.hpp | 2 +- rerun_js/web-viewer-react/README.md | 2 +- rerun_js/web-viewer/README.md | 2 +- rerun_py/ARCHITECTURE.md | 2 +- rerun_py/README.md | 2 +- rerun_py/docs/writing_docs.md | 2 +- .../rerun_sdk/rerun/archetypes/arrows2d.py | 2 +- .../rerun_sdk/rerun/archetypes/arrows3d.py | 2 +- .../rerun_sdk/rerun/archetypes/pinhole.py | 4 +- .../rerun_sdk/rerun/archetypes/series_line.py | 2 +- .../rerun/archetypes/series_point.py | 2 +- rerun_py/rerun_sdk/rerun/archetypes/tensor.py | 2 +- scripts/lint.py | 92 +++++++++++ 120 files changed, 383 insertions(+), 292 deletions(-) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 9e15c804d538..101f9415afb7 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -15,7 +15,7 @@ If you are going to be doing any editing of workflows, the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=cschleiden.vscode-github-actions) for GitHub Actions is highly recommended. -## Reusable Workflows +## Reusable workflows - [reusable_checks.yml](reusable_checks.yml) - These are all the checks that run to ensure the code is formatted, linted, and tested. This job produces no artifacts other than a pass/fail criteria for the build. @@ -66,7 +66,7 @@ for GitHub Actions is highly recommended. - `PR_NUMBER` - The PR number to update. This will generally be set by the `on_pull_request.yml` workflow using: `${{github.event.pull_request.number}}` -## Manual Workflows +## Manual workflows - [manual_dispatch](manual_dispatch.yml) - This workflow is used to manually trigger the assorted reusable workflows for testing. diff --git a/BUILD.md b/BUILD.md index 1a5f3a58c335..a8a72f0c5eec 100644 --- a/BUILD.md +++ b/BUILD.md @@ -117,7 +117,7 @@ High-level documentation for rerun can be found at [http://rerun.io/docs](http:/ - 🐍 [Python API docs](https://ref.rerun.io/docs/python) are built via `mkdocs` and hosted on GitHub. For details on the python doc-system, see [Writing Docs](https://github.com/rerun-io/rerun/blob/main/rerun_py/docs/writing_docs.md). - 🦀 [Rust API docs](https://docs.rs/rerun/) are hosted on . You can build them locally with: `cargo doc --all-features --no-deps --open`. -## Building for the Web +## Building for the web If you want to build a standalone rerun executable that contains the web-viewer and a websocket server, you need to install the `wasm32-unknown-unknown` rust target and ensure the `web_viewer` feature flag is set when building rerun. diff --git a/CHANGELOG.md b/CHANGELOG.md index 284313ca4493..8068250e913c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ This release is identical to 0.14.0 and merely fixes an issue in the build artif ## [0.14.0](https://github.com/rerun-io/rerun/compare/0.13.0...0.14.0) - "Unlimited" point clouds & lines, quality of life improvements, bugfixes -### Overview & Highlights +### Overview & highlights Originally, we planned to do only a bugfix release, but we got an unexpected amount of goodies amassed already. We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy these improvements in 0.14! @@ -35,7 +35,7 @@ We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy #### 🦀 Rust API - Fix using `rerun` crate as a dependency on CI [#5170](https://github.com/rerun-io/rerun/pull/5170) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Enforce the rule: heuristics should never add a new view that would be completely covered by an existing view [#5164](https://github.com/rerun-io/rerun/pull/5164) - Remove log spam when quickly resizing the viewer [#5189](https://github.com/rerun-io/rerun/pull/5189) - Fix incorrect minimum supported rust version mentioned in docs and examples [#5195](https://github.com/rerun-io/rerun/pull/5195) @@ -45,14 +45,14 @@ We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy - Fix non-deterministic redundancy check for space view spawning heuristic [#5266](https://github.com/rerun-io/rerun/pull/5266) - Fix resetting vertical axis when using non-uniform zoom on Time Series [#5287](https://github.com/rerun-io/rerun/pull/5287) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Clear all blueprints in RAM and on disk when clicking "Reset Viewer" [#5199](https://github.com/rerun-io/rerun/pull/5199) - Improve the orbit eye to always maintain an up-axis [#5193](https://github.com/rerun-io/rerun/pull/5193) - Focus on current bounding-box when resetting camera-eye on a 3D space view (double click it) [#5209](https://github.com/rerun-io/rerun/pull/5209) - Add STL mesh support [#5244](https://github.com/rerun-io/rerun/pull/5244) - Add first person 3D eye-camera [#5249](https://github.com/rerun-io/rerun/pull/5249) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - More robust handling of maximum texture size for non-color data, slight perf improvements for large point clouds [#5229](https://github.com/rerun-io/rerun/pull/5229) - Cached transforms & disconnected spaces for faster scenes with many transforms [#5221](https://github.com/rerun-io/rerun/pull/5221) - Optimized cpu time for 3D point clouds (once again!) [#5273](https://github.com/rerun-io/rerun/pull/5273) @@ -66,7 +66,7 @@ We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy #### 📚 Docs - Fix broken link in the installing-viewer documentation [#5236](https://github.com/rerun-io/rerun/pull/5236) (thanks [@BirgerMoell](https://github.com/BirgerMoell)!) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Context Menu 1: Basic scaffolding and simple actions [#5163](https://github.com/rerun-io/rerun/pull/5163) - Context menu 2: add support for multiple selection [#5205](https://github.com/rerun-io/rerun/pull/5205) - Context menu 3: add "Move to new container" context menu action [#5210](https://github.com/rerun-io/rerun/pull/5210) @@ -76,7 +76,7 @@ We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy - Don't show the blueprint section when selecting recordings [#5245](https://github.com/rerun-io/rerun/pull/5245) - Use the same icon for recordings everywhere [#5246](https://github.com/rerun-io/rerun/pull/5246) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - Lift point cloud size limitations [#5192](https://github.com/rerun-io/rerun/pull/5192) - Lift line vertex/strip count limitations [#5207](https://github.com/rerun-io/rerun/pull/5207) - Fix banding artifacts of 3D space view's skybox [#5279](https://github.com/rerun-io/rerun/pull/5279) @@ -89,7 +89,7 @@ We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy ## [0.13.0](https://github.com/rerun-io/rerun/compare/0.12.1...0.13.0) - Fast time series, improved layout editing & UI overrides - 2024-02-12 -### Overview & Highlights +### Overview & highlights This release focuses on scalar time series -- both from a performance and UI perspectives. Check out our [associated blog post](https://www.rerun.io/blog/fast-plots) for more information. @@ -142,7 +142,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi #### 🐍 Python API - Fix support for compressing mono images by respecting mode to determine depth [#4847](https://github.com/rerun-io/rerun/pull/4847) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - External loader: don't do process IO on compute thread-pool [#4942](https://github.com/rerun-io/rerun/pull/4942) - Fix a Visible Time Range UI issue where the summary string would display the wrong data range [#5034](https://github.com/rerun-io/rerun/pull/5034) - Clear empty containers after tile drag-and-drop [#5044](https://github.com/rerun-io/rerun/pull/5044) @@ -151,7 +151,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Fix `RERUN_FLUSH_NUM_BYTES` and data size estimations [#5086](https://github.com/rerun-io/rerun/pull/5086) - Make `rectangle_fs.wgsl` compile on chrome despite angle/mesa bug (#3931) [#5074](https://github.com/rerun-io/rerun/pull/5074) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Introduce Scalar, SeriesLine, and SeriesPoint archetypes with their own visualizers [#4875](https://github.com/rerun-io/rerun/pull/4875) - Support modifying the plot style by introducing a generic framework for overriding components [#4914](https://github.com/rerun-io/rerun/pull/4914) - Introduce a new blueprint archetype for AxisY configuration in a plot [#5028](https://github.com/rerun-io/rerun/pull/5028) @@ -164,7 +164,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Allow selection of entities directly in the plot space view [#4959](https://github.com/rerun-io/rerun/pull/4959) - Texture support for raw `Mesh3D` logging [#4894](https://github.com/rerun-io/rerun/pull/4894) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - Add `--threads` / `-j` to control number of compute threads [#5021](https://github.com/rerun-io/rerun/pull/5021) - Introduce the query cache: - Primary caching 3: bare-bone latest-at caching [#4659](https://github.com/rerun-io/rerun/pull/4659) @@ -200,7 +200,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - `DisconnectedSpace` now only applies to spatial space views [#4935](https://github.com/rerun-io/rerun/pull/4935) - Fill gaps in image encoding documentation, fix how python documents union variants [#4988](https://github.com/rerun-io/rerun/pull/4988) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Improve timeseries Space Views: - Introduce a new component for MarkerShape and use it in SeriesPoint [#5004](https://github.com/rerun-io/rerun/pull/5004) - Introduce a new StrokeWidth component and use it for SeriesLine [#5025](https://github.com/rerun-io/rerun/pull/5025) @@ -241,7 +241,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Unify `web_viewer/index.html` and `index_bundled.html` [#4720](https://github.com/rerun-io/rerun/pull/4720) - Allow forcing WebGPU/WebGL on the web player, new command line argument to force graphics backend [#4981](https://github.com/rerun-io/rerun/pull/4981) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - Update to wgpu 0.19 and latest `egui` trunk [#4885](https://github.com/rerun-io/rerun/pull/4885) - Support YUY2-encoded images [#4877](https://github.com/rerun-io/rerun/pull/4877) (thanks [@oxkitsune](https://github.com/oxkitsune)!) @@ -274,7 +274,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi #### 🦀 Rust API - Fix `entity_path_vec!` and `entity_path!` depending on `ToString` being in scope [#4766](https://github.com/rerun-io/rerun/pull/4766) (thanks [@kpreid](https://github.com/kpreid)!) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix external data loader plugins on Windows [#4840](https://github.com/rerun-io/rerun/pull/4840) - Reduce latency when loading data from external loaders [#4797](https://github.com/rerun-io/rerun/pull/4797) - Always point to versioned manifest when building a versioned binary [#4781](https://github.com/rerun-io/rerun/pull/4781) @@ -289,7 +289,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi ## [0.12.0](https://github.com/rerun-io/rerun/compare/0.11.0...0.12.0) - Data Loaders, Container-editing, Python-3.12 - 2024-01-09 -### Overview & Highlights +### Overview & highlights - 🌁 The Rerun Viewer now supports a plugin system for creating [arbitrary external data loaders](https://www.rerun.io/docs/howto/open-any-file). - 🕸️ More built-in examples are now available in the viewer. - 🐍 The Python SDK now works with Python-3.12. @@ -318,7 +318,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Add `--stdout`/`-o` to our CLI helper library [#4544](https://github.com/rerun-io/rerun/pull/4544) - Document how to construct an entity path for the Rust logging API [#4584](https://github.com/rerun-io/rerun/pull/4584) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Bugfix: show labels on segmentation images with trivial dimensions [#4368](https://github.com/rerun-io/rerun/pull/4368) - Datastore: don't eagerly sort in bucket split routine on ingestion path [#4417](https://github.com/rerun-io/rerun/pull/4417) - Resolve spurious blueprint panel group collapsing [#4548](https://github.com/rerun-io/rerun/pull/4548) @@ -327,7 +327,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Make scroll-to-zoom a lot more responsive in 3D views [#4668](https://github.com/rerun-io/rerun/pull/4668) - Fix heuristic object properties being broken in some cases / fix DepthMeter being ignored sometimes [#4679](https://github.com/rerun-io/rerun/pull/4679) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Make viewer contexts's render context reference non-mutable [#4430](https://github.com/rerun-io/rerun/pull/4430) - The Rerun Viewer can now consume from stdin: - Standard input/output support 1: stream RRD data from stdin [#4511](https://github.com/rerun-io/rerun/pull/4511) @@ -347,7 +347,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - The viewer now supports segmentation images logged natively as floats [#4585](https://github.com/rerun-io/rerun/pull/4585) - Fix incorrect bounding box calculation for camera view parts [#4640](https://github.com/rerun-io/rerun/pull/4640) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - Parallelize Space View system evaluation [#4460](https://github.com/rerun-io/rerun/pull/4460) - Limit server memory [#4636](https://github.com/rerun-io/rerun/pull/4636) @@ -360,7 +360,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Shared recordings 3: add how-to guide [#4385](https://github.com/rerun-io/rerun/pull/4385) - Document our crate organization in ARCHITECTURE.md [#4458](https://github.com/rerun-io/rerun/pull/4458) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Plot legend visibility and position control (part 1): route `EntityProperties` to `SpaceViewClass` methods [#4363](https://github.com/rerun-io/rerun/pull/4363) - Plot legend visibility and position control (part 2): minor UI spacing improvement [#4364](https://github.com/rerun-io/rerun/pull/4364) - Reset accumulated bounding box when resetting camera [#4369](https://github.com/rerun-io/rerun/pull/4369) @@ -390,7 +390,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Remove builds and usage of `demo.rerun.io` [#4418](https://github.com/rerun-io/rerun/pull/4418) - Open all links in a new tab [#4582](https://github.com/rerun-io/rerun/pull/4582) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - Log wgpu adapter on web [#4414](https://github.com/rerun-io/rerun/pull/4414) - Interior mutability for re_renderer's static resource pools (RenderPipeline/Shader/Layouts/etc.) [#4421](https://github.com/rerun-io/rerun/pull/4421) - Make draw data creation no longer require a mutable re_renderer context [#4422](https://github.com/rerun-io/rerun/pull/4422) @@ -430,7 +430,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi ## [0.11.0](https://github.com/rerun-io/rerun/compare/0.10.1...0.11.0) - C++ improvements & better Visible History - 2023-11-28 -### Overview & Highlights +### Overview & highlights - 🌊 C++ SDK improvements - [Reference docs are live!](https://ref.rerun.io/docs/cpp/) @@ -478,17 +478,17 @@ Special thanks to @dvad & @dangush for contributing! - Remove deprecated `rerun_demo` package [#4293](https://github.com/rerun-io/rerun/pull/4293) - Python: don't catch `KeyboardInterrupt` and `SystemExit` [#4333](https://github.com/rerun-io/rerun/pull/4333) (thanks [@Dvad](https://github.com/Dvad)!) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix line & points (& depth clouds points) radii being unaffected by scale & projection via Pinhole [#4199](https://github.com/rerun-io/rerun/pull/4199) - Fix inaccessible entities being incorrectly added to space view [#4226](https://github.com/rerun-io/rerun/pull/4226) - Silence spammy blueprint warnings and validate blueprint on load [#4303](https://github.com/rerun-io/rerun/pull/4303) - Fix markdown heading size [#4178](https://github.com/rerun-io/rerun/pull/4178) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Add command to copy direct link to fully qualified URL [#4165](https://github.com/rerun-io/rerun/pull/4165) - Implement recording/last-modified-at aware garbage collection [#4183](https://github.com/rerun-io/rerun/pull/4183) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Improve Visible History to support more general time queries [#4123](https://github.com/rerun-io/rerun/pull/4123) - Add support for Visible History to time series space views [#4179](https://github.com/rerun-io/rerun/pull/4179) - Make Visible History UI more ergonomic and show inherited values [#4222](https://github.com/rerun-io/rerun/pull/4222) @@ -515,7 +515,7 @@ Special thanks to @dvad & @dangush for contributing! ## [0.10.1](https://github.com/rerun-io/rerun/compare/0.10.0...0.10.1) - 2023-11-02 -### Overview & Highlights +### Overview & highlights This is a small release primarily to tie up some loose ends for our C++ SDK. #### 🌊 C++ SDK @@ -539,7 +539,7 @@ This is a small release primarily to tie up some loose ends for our C++ SDK. Release blog post: -### Overview & Highlights +### Overview & highlights * The C++ SDK is finally here! ```cpp #include @@ -578,12 +578,12 @@ Release blog post: - `RecordingStream`: introduce `connect_opts` [#4042](https://github.com/rerun-io/rerun/pull/4042) - Add `disable_timeline` function [#4068](https://github.com/rerun-io/rerun/pull/4068) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix grayscale images being too dark [#3999](https://github.com/rerun-io/rerun/pull/3999) - Prevent badly sized tensors from crashing the viewer [#4005](https://github.com/rerun-io/rerun/pull/4005) - Fix selection history right-click menu not working [#3819](https://github.com/rerun-io/rerun/pull/3819) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Replace `--strict` flag with `RERUN_PANIC_ON_WARN` env-var [#3872](https://github.com/rerun-io/rerun/pull/3872) - Support NV12-encoded images [#3541](https://github.com/rerun-io/rerun/pull/3541) (thanks [@zrezke](https://github.com/zrezke)!) @@ -595,12 +595,12 @@ Release blog post: - Improve docs for `TextDocument` example [#4008](https://github.com/rerun-io/rerun/pull/4008) - Fix typos in documentation and code comments [#4061](https://github.com/rerun-io/rerun/pull/4061) (thanks [@omahs](https://github.com/omahs)!) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Add basic support for in-app "Quick Start" guides [#3813](https://github.com/rerun-io/rerun/pull/3813) [#3912](https://github.com/rerun-io/rerun/pull/3912) - Add copy-button to markdown code blocks [#3882](https://github.com/rerun-io/rerun/pull/3882) - Add warning in the Quick Start guides about Safari breaking Copy to Clipboard [#3898](https://github.com/rerun-io/rerun/pull/3898) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - Add easy way to dump out final wgsl shader [#3947](https://github.com/rerun-io/rerun/pull/3947) #### 🧑‍💻 Dev-experience @@ -625,7 +625,7 @@ Release blog post: * Rust: `cargo add rerun` and `cargo install rerun-cli` * Online demo: -### Overview & Highlights +### Overview & highlights - A bunch of bug fixes - Fix big performance regression when hovering images - The Rerun Viewer should now be visible to the system accessibility system @@ -641,7 +641,7 @@ Release blog post: - Fix return type of `entity_path!()` and `entity_path_vec!()` on empty input [#3734](https://github.com/rerun-io/rerun/pull/3734) (thanks [@kpreid](https://github.com/kpreid)!) - Export `RecordingStreamError` [#3777](https://github.com/rerun-io/rerun/pull/3777) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix bug when joining cleared optional components [#3726](https://github.com/rerun-io/rerun/pull/3726) - Update `winit` to 0.28.7 to fix UI glitch on macOS Sonoma [#3763](https://github.com/rerun-io/rerun/pull/3763) - Show 1D-tensors as bar charts [#3769](https://github.com/rerun-io/rerun/pull/3769) @@ -649,13 +649,13 @@ Release blog post: - Fix crash when loading huge image [#3775](https://github.com/rerun-io/rerun/pull/3775) - Fix performance regression when viewing images and tensors [#3767](https://github.com/rerun-io/rerun/pull/3767) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Turn on `AccessKit` accessibility integration [#3732](https://github.com/rerun-io/rerun/pull/3732) - Display space views using `ViewCoordinates` from closest ancestor [#3748](https://github.com/rerun-io/rerun/pull/3748) - Improve 3D view bounds handling of camera frustums [#3749](https://github.com/rerun-io/rerun/pull/3749) [#3815](https://github.com/rerun-io/rerun/pull/3815) [#3811](https://github.com/rerun-io/rerun/pull/3811) - Improve heuristics around 2D vs 3D space-view creation [#3822](https://github.com/rerun-io/rerun/pull/3822) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - Optimize gathering of point cloud colors [#3730](https://github.com/rerun-io/rerun/pull/3730) #### 🧑‍🏫 Examples @@ -664,7 +664,7 @@ Release blog post: #### 📚 Docs - Document that entity-path `rerun/` is reserved [#3747](https://github.com/rerun-io/rerun/pull/3747) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Show all entities/components in the Streams UI, even if empty for the selected timeline [#3779](https://github.com/rerun-io/rerun/pull/3779) #### 🧑‍💻 Dev-experience @@ -687,7 +687,7 @@ Release blog post: * Online demo: -### Overview & Highlights +### Overview & highlights Rerun 0.9.0 is a big release, that introduces a brand new logging API. This API is code-generated from a common definition, meaning the Python and Rust SDKs are very similar now. This will let us more easily extend and improve the API going forward. @@ -730,7 +730,7 @@ Other highlights: - Make `FileSink` actually flush its data when asked to [#3525](https://github.com/rerun-io/rerun/pull/3525) - `TextLog` integrations with native loggers [#3522](https://github.com/rerun-io/rerun/pull/3522) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix bug in size estimation of array buffers [#2991](https://github.com/rerun-io/rerun/pull/2991) - Fix the Streams UI when the recording is empty [#3027](https://github.com/rerun-io/rerun/pull/3027) - Clamp time panel height to avoid visual glitches [#3169](https://github.com/rerun-io/rerun/pull/3169) @@ -744,7 +744,7 @@ Other highlights: - Fix infinite recursion when putting a container inside a viewer tab [#3534](https://github.com/rerun-io/rerun/pull/3534) - Fix failing to preview small images [#3520](https://github.com/rerun-io/rerun/pull/3520) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Open image and mesh files with drag-drop and File->Open [#3116](https://github.com/rerun-io/rerun/pull/3116) - Support loading images and meshes on web [#3131](https://github.com/rerun-io/rerun/pull/3131) - Add `rerun reset` command [#3145](https://github.com/rerun-io/rerun/pull/3145) @@ -756,7 +756,7 @@ Other highlights: - Add option to display timestamps in the local system timezone [#3530](https://github.com/rerun-io/rerun/pull/3530) (thanks [@jparismorgan](https://github.com/jparismorgan)!) - Add obj mesh support to viewer [#3670](https://github.com/rerun-io/rerun/pull/3670) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - Pass through strings using arrow2::Buffers [#2931](https://github.com/rerun-io/rerun/pull/2931) - Introduce codegen optimizations for primitives and fixed-sized-arrays [#2970](https://github.com/rerun-io/rerun/pull/2970) - Optimize big point clouds by ~20% [#3108](https://github.com/rerun-io/rerun/pull/3108) @@ -783,7 +783,7 @@ Other highlights: - Update the python API docs site for the new APIs [#3565](https://github.com/rerun-io/rerun/pull/3565) - Add a how-to guide for using Rerun with custom data [#3634](https://github.com/rerun-io/rerun/pull/3634) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Migrate to custom checkbox/radio_value UI [#2851](https://github.com/rerun-io/rerun/pull/2851) - Remove expansion effect from time panel toolbar [#2863](https://github.com/rerun-io/rerun/pull/2863) - Remove expansion effect from the large collapsing headers [#2864](https://github.com/rerun-io/rerun/pull/2864) @@ -866,7 +866,7 @@ Other highlights: ## [0.8.2](https://github.com/rerun-io/rerun/compare/0.8.1...0.8.2) - Bug fixes - 2023-09-05 -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix quadratic slowdown when ingesting data with uniform time [#3088](https://github.com/rerun-io/rerun/pull/3088) - Normalize quaternions [#3094](https://github.com/rerun-io/rerun/pull/3094) - Improve error message in common `re_renderer` crash [#3070](https://github.com/rerun-io/rerun/pull/3070) @@ -877,10 +877,10 @@ Other highlights: #### 🧑‍🏫 Examples - Make `custom_space_view` example more verbose [#3123](https://github.com/rerun-io/rerun/pull/3123) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Change the "slow-down-camera" modifier to Alt on non-Mac [#3051](https://github.com/rerun-io/rerun/pull/3051) (thanks [@h3mosphere](https://github.com/h3mosphere)!) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - Warn if using software rasterizer (lavapipe or llvmpipe) [#3134](https://github.com/rerun-io/rerun/pull/3134) #### 📦 Dependencies @@ -892,11 +892,11 @@ Other highlights: #### 🐍 Python SDK - Add a warning category and stacklevel to rerun warnings.warn calls [#2985](https://github.com/rerun-io/rerun/pull/2985) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix always redrawing in the presence of a 3D space view [#2900](https://github.com/rerun-io/rerun/pull/2900) - Fix unable to set camera spinning until camera has moved [#2990](https://github.com/rerun-io/rerun/pull/2990) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Allow changing plot aspect ratio with scroll + cmd/ctrl + alt [#2742](https://github.com/rerun-io/rerun/pull/2742) - Automatically select user timeline if no timeline was explicitly selected yet [#2986](https://github.com/rerun-io/rerun/pull/2986) @@ -916,7 +916,7 @@ Other highlights: * Online demo: -### Overview & Highlights +### Overview & highlights - `log_pinhole` is now easier to use in simple cases and supports non-RDF camera coordinates. [#2614](https://github.com/rerun-io/rerun/pull/2614) - You only need to set focal length and optional principal point instead of setting the full 3x3 matrix. - There is also a new argument: `camera_xyz` for setting the coordinate system. The default is RDF (the old @@ -975,7 +975,7 @@ for use-cases like real-time video feeds. [#2220](https://github.com/rerun-io/re - Logging SDK: Log warnings if user data is dropped [#2630](https://github.com/rerun-io/rerun/pull/2630) - Add support for `RecordingStream::serve` [#2815](https://github.com/rerun-io/rerun/pull/2815) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Better handle scroll-to-zoom in 3D views [#1764](https://github.com/rerun-io/rerun/pull/1764) - Add command to screenshot the application [#2293](https://github.com/rerun-io/rerun/pull/2293) - Show layout in blueprint tree view [#2465](https://github.com/rerun-io/rerun/pull/2465) @@ -988,12 +988,12 @@ for use-cases like real-time video feeds. [#2220](https://github.com/rerun-io/re - Consistent transform visualization for all entities with transforms [#2577](https://github.com/rerun-io/rerun/pull/2577) - Improve `log_pinhole` and support non-RDF pinholes [#2614](https://github.com/rerun-io/rerun/pull/2614) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - Flush the batches every 8ms instead of 50 ms [#2220](https://github.com/rerun-io/rerun/pull/2220) - Replace `image` crate jpeg decoder with zune-jpeg [#2376](https://github.com/rerun-io/rerun/pull/2376) - Stream `.rrd` files when loading via http [#2412](https://github.com/rerun-io/rerun/pull/2412) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix deadlock when misusing the Caches [#2318](https://github.com/rerun-io/rerun/pull/2318) - Fix unstable order/flickering of "shown in" space view list on selection [#2327](https://github.com/rerun-io/rerun/pull/2327) - Fix transforms not applied to connections from transform context [#2407](https://github.com/rerun-io/rerun/pull/2407) @@ -1031,7 +1031,7 @@ for use-cases like real-time video feeds. [#2220](https://github.com/rerun-io/re - Update docs about transforms [#2496](https://github.com/rerun-io/rerun/pull/2496) - Fixup remaining usages of log_rigid3 in docs [#2831](https://github.com/rerun-io/rerun/pull/2831) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - Expose type erased draw data that can be consumed directly [#2300](https://github.com/rerun-io/rerun/pull/2300) - Use less `mut` when using `RenderContext` [#2312](https://github.com/rerun-io/rerun/pull/2312) @@ -1159,7 +1159,7 @@ for use-cases like real-time video feeds. [#2220](https://github.com/rerun-io/re ## [0.7.0](https://github.com/rerun-io/rerun/compare/0.6.0...0.7.0) - improved transforms, better color mapping, bug & doc fixes - 2023-06-16 -### Overview & Highlights +### Overview & highlights While we're working on significant updates around interfaces and customizability, here's a smaller release packed with useful improvements 🎉 @@ -1182,7 +1182,7 @@ here's a smaller release packed with useful improvements 🎉 - Improved 3D transform ingestion & affine transform support [#2102](https://github.com/rerun-io/rerun/pull/2102) - `impl Copy for Arrow3D`. [#2239](https://github.com/rerun-io/rerun/pull/2239) (thanks [@kpreid](https://github.com/kpreid)!) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Stable image order, fixing flickering [#2191](https://github.com/rerun-io/rerun/pull/2191) - Fix double clicking objects no longer focusing the camera on them [#2227](https://github.com/rerun-io/rerun/pull/2227) - Fix off-by-half pixel error in textured rectangle shader [#2294](https://github.com/rerun-io/rerun/pull/2294) @@ -1190,11 +1190,11 @@ here's a smaller release packed with useful improvements 🎉 - Fix some browsers failing due to 8k texture requirement, pick always highest available now [#2409](https://github.com/rerun-io/rerun/pull/2409) - Fix visibility toggles for time series not working [#2444](https://github.com/rerun-io/rerun/pull/2444) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Time panel now always talks about "events" instead of "messages" [#2247](https://github.com/rerun-io/rerun/pull/2247) - Automatically determine image/tensor color mapping & need for sRGB decoding [#2342](https://github.com/rerun-io/rerun/pull/2342) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - Optimization: avoid a memory allocation when padding RGB u8 to RGBA [#2345](https://github.com/rerun-io/rerun/pull/2345) #### 🧑‍🏫 Examples @@ -1251,7 +1251,7 @@ here's a smaller release packed with useful improvements 🎉 ## [0.6.0](https://github.com/rerun-io/rerun/compare/v0.5.1...0.6.0) - 3D in 2D and SDK batching - 2023-05-26 -### Overview & Highlights +### Overview & highlights - You can now show 3D objects in 2D views connected by Pinhole transforms [#2008](https://github.com/rerun-io/rerun/pull/2008) - You can quickly view images and meshes with `rerun mesh.obj image.png` [#2060](https://github.com/rerun-io/rerun/pull/2060) @@ -1287,7 +1287,7 @@ here's a smaller release packed with useful improvements 🎉 - Add `Tensor::from_image_file` and `Tensor::from_image_bytes` [#2097](https://github.com/rerun-io/rerun/pull/2097) - Redesign multi-recording & multi-threading [#2061](https://github.com/rerun-io/rerun/pull/2061) -#### 🌁 Viewer Improvements +#### 🌁 Viewer improvements - Support projecting 3D entities in 2D views [#2008](https://github.com/rerun-io/rerun/pull/2008) - Set Rerun viewer native app icon using eframe [#1976](https://github.com/rerun-io/rerun/pull/1976) - Use `alt` key again for rolling camera in 3D views [#2066](https://github.com/rerun-io/rerun/pull/2066) @@ -1295,7 +1295,7 @@ here's a smaller release packed with useful improvements 🎉 - Show meshes and images with `rerun foo.obj bar.png` [#2060](https://github.com/rerun-io/rerun/pull/2060) - Don't persist blueprints for unknown apps [#2165](https://github.com/rerun-io/rerun/pull/2165) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix hover/select highlights when picking single points in a scene with multiple point clouds [#1942](https://github.com/rerun-io/rerun/pull/1942) - Fix crash for missing class ids causing zero sized texture [#1947](https://github.com/rerun-io/rerun/pull/1947) - Handle leaking of prerelease into alpha version [#1953](https://github.com/rerun-io/rerun/pull/1953) @@ -1324,7 +1324,7 @@ here's a smaller release packed with useful improvements 🎉 - Fix incorrect 2D camera for scenes with negative 2D coordinates [#2051](https://github.com/rerun-io/rerun/pull/2051) - Fix web depth/projection regression, causing incorrect rendering on all 3D scenes [#2170](https://github.com/rerun-io/rerun/pull/2170) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - SDK batching/revamp 1: impl `DataTableBatcher` [#1980](https://github.com/rerun-io/rerun/pull/1980) - Upgrade arrow2/convert and use native buffers for the tensor u8 types [#1375](https://github.com/rerun-io/rerun/pull/1375) - Use the same RRD encoding for the SDK comms as for everything else [#2065](https://github.com/rerun-io/rerun/pull/2065) @@ -1345,11 +1345,11 @@ here's a smaller release packed with useful improvements 🎉 - Fix glb mesh data set downloads [#2100](https://github.com/rerun-io/rerun/pull/2100) - Add more examples to https://app.rerun.io/ [#2062](https://github.com/rerun-io/rerun/pull/2062) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Update egui to latest and wgpu to 0.16 [#1958](https://github.com/rerun-io/rerun/pull/1958) - Add keyboard shortcut for "Follow", and stop following on "Restart" [#1986](https://github.com/rerun-io/rerun/pull/1986) (thanks [@h3mosphere](https://github.com/h3mosphere)!) - Improve UI for keypoint and class-ids of annotations contexts [#2071](https://github.com/rerun-io/rerun/pull/2071) -- Improvements to memory measurements and reporting [#2069](https://github.com/rerun-io/rerun/pull/2069) +- improvements to memory measurements and reporting [#2069](https://github.com/rerun-io/rerun/pull/2069) - Switch from `egui_dock` to `egui_tiles` [#2082](https://github.com/rerun-io/rerun/pull/2082) - Allow horizontal scrolling in blueprint panel [#2114](https://github.com/rerun-io/rerun/pull/2114) - Nicer (& fixed up) help texts for space views [#2070](https://github.com/rerun-io/rerun/pull/2070) @@ -1361,7 +1361,7 @@ here's a smaller release packed with useful improvements 🎉 - Work around https://github.com/sebcrozet/instant/issues/49 [#2094](https://github.com/rerun-io/rerun/pull/2094) - Update `wasm-bindgen` to 0.2.86 [#2161](https://github.com/rerun-io/rerun/pull/2161) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - Full (experimental) WebGPU support [#1965](https://github.com/rerun-io/rerun/pull/1965) - Depth offset for lines & points [#2052](https://github.com/rerun-io/rerun/pull/2052) - Update to wgpu 0.16.1 [#2205](https://github.com/rerun-io/rerun/pull/2205) @@ -1448,7 +1448,7 @@ here's a smaller release packed with useful improvements 🎉 ## [0.5.1](https://github.com/rerun-io/rerun/compare/v0.5.1...v0.5.0) - Patch Release - 2023-05-01 -### Overview & Highlights +### Overview & highlights This Release fixes a few small bugs on top of the v0.5.0 release. ### In Detail @@ -1461,7 +1461,7 @@ This Release fixes a few small bugs on top of the v0.5.0 release. ## [0.5.0](https://github.com/rerun-io/rerun/compare/v0.4.0...v0.5.0) - Jupyter MVP, GPU-based picking & colormapping, new datastore! - 2023-04-20 -### Overview & Highlights +### Overview & highlights This new release adds MVP support for embedding Rerun in Jupyter notebooks, and brings significant performance improvements across all layers of the stack. @@ -1490,7 +1490,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Always flush when we remove a sink [#1830](https://github.com/rerun-io/rerun/pull/1830) - More robust wait for exit condition during .serve() [#1939](https://github.com/rerun-io/rerun/pull/1939) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - Fix broken outlines (hover/select effect) for lines [#1724](https://github.com/rerun-io/rerun/pull/1724) - Fix logged obb being displayed with half of the requested size [#1749](https://github.com/rerun-io/rerun/pull/1749) (thanks [@BenjaminDev](https://github.com/BenjaminDev)!) - Fix `log_obb` usage [#1761](https://github.com/rerun-io/rerun/pull/1761) @@ -1519,7 +1519,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Fix hover/select highlights when picking single points in a scene with multiple point clouds [#1942](https://github.com/rerun-io/rerun/pull/1942) - Fix hovering depth clouds [#1943](https://github.com/rerun-io/rerun/pull/1943) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - batching 4: retire `MsgBundle` + batching support in transport layer [#1679](https://github.com/rerun-io/rerun/pull/1679) - Optimize the depth-cloud shader when `depth=0` [#1729](https://github.com/rerun-io/rerun/pull/1729) - `arrow2_convert` primitive (de)serialization benchmarks [#1742](https://github.com/rerun-io/rerun/pull/1742) @@ -1547,7 +1547,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Fix typos in notebook readme [#1852](https://github.com/rerun-io/rerun/pull/1852) - Update docs related to notebook [#1915](https://github.com/rerun-io/rerun/pull/1915) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Hover rays for tracked 3D cameras [#1751](https://github.com/rerun-io/rerun/pull/1751) - Collapse space-view by default if there is only one child [#1762](https://github.com/rerun-io/rerun/pull/1762) - Option to show scene bounding box [#1770](https://github.com/rerun-io/rerun/pull/1770) @@ -1557,7 +1557,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Show previews of colormaps when selecting them [#1846](https://github.com/rerun-io/rerun/pull/1846) - Smooth out scroll wheel input for camera zooming [#1920](https://github.com/rerun-io/rerun/pull/1920) -#### 🤷‍♂️ Other Viewer Improvements +#### 🤷‍♂️ Other Viewer improvements - Change `EntityPathHash` to be 64 bit [#1723](https://github.com/rerun-io/rerun/pull/1723) - Central `GpuReadback` handling for re_viewer, experimental space view screenshots [#1717](https://github.com/rerun-io/rerun/pull/1717) - Readback depth from GPU picking [#1752](https://github.com/rerun-io/rerun/pull/1752) @@ -1572,7 +1572,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Notebooks: make `presentation_id` consistent and use data-attribute for rrd [#1881](https://github.com/rerun-io/rerun/pull/1881) - 2.5GB before GC kick in on web [#1944](https://github.com/rerun-io/rerun/pull/1944) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - GPU based picking with points [#1721](https://github.com/rerun-io/rerun/pull/1721) - improved renderer label handling [#1731](https://github.com/rerun-io/rerun/pull/1731) - Improved readback data handling [#1734](https://github.com/rerun-io/rerun/pull/1734) @@ -1586,7 +1586,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Fix filtering artifact for non-color images [#1886](https://github.com/rerun-io/rerun/pull/1886) - Refactor: Add helper functions to `GpuTexture2DHandle` [#1900](https://github.com/rerun-io/rerun/pull/1900) -#### 🛢 Datastore Improvements +#### 🛢 Datastore improvements - Datastore: revamp bench suite [#1733](https://github.com/rerun-io/rerun/pull/1733) - Datastore revamp 1: new indexing model & core datastructures [#1727](https://github.com/rerun-io/rerun/pull/1727) - Datastore revamp 2: serialization & formatting [#1735](https://github.com/rerun-io/rerun/pull/1735) @@ -1633,7 +1633,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and https://user-images.githubusercontent.com/1220815/228241887-03b311e2-80e9-4541-9281-6d334a15ab04.mp4 -### Overview & Highlights +### Overview & highlights * Add support for mesh vertex colors [#1671](https://github.com/rerun-io/rerun/pull/1671) * Lower memory use [#1535](https://github.com/rerun-io/rerun/pull/1535) * Improve garbage collection [#1560](https://github.com/rerun-io/rerun/pull/1560) @@ -1661,7 +1661,7 @@ We now host an experimental and unpolished web-viewer at - ⚠️ `rerun::global_session` is now hidden behind the `global_session` feature flag [#1507](https://github.com/rerun-io/rerun/pull/1507) - Add support for mesh vertex colors [#1671](https://github.com/rerun-io/rerun/pull/1671) -#### 🪳 Bug Fixes +#### 🪳 Bug fixes - datastore: disable compaction (fixes 2x memory issue) [#1535](https://github.com/rerun-io/rerun/pull/1535) - Fix garbage collection [#1560](https://github.com/rerun-io/rerun/pull/1560) - Avoid using undefined extern "C" on windows [#1577](https://github.com/rerun-io/rerun/pull/1577) @@ -1694,7 +1694,7 @@ We now host an experimental and unpolished web-viewer at - Fix CpuWriteGpuReadBelt producing unaligned gpu buffer offsets [#1716](https://github.com/rerun-io/rerun/pull/1716) - Fix arrows requiring a radius to be visible [#1720](https://github.com/rerun-io/rerun/pull/1720) -#### 🚀 Performance Improvements +#### 🚀 Performance improvements - Add re_arrow_store profile scopes [#1546](https://github.com/rerun-io/rerun/pull/1546) - datastore: early exit missing components at table level [#1554](https://github.com/rerun-io/rerun/pull/1554) - datastore: track bucket count in store stats & mem panel [#1555](https://github.com/rerun-io/rerun/pull/1555) @@ -1714,7 +1714,7 @@ We now host an experimental and unpolished web-viewer at #### 📚 Docs - Link to the Python SDK build instructions in `rerun_py/README.md` [#1565](https://github.com/rerun-io/rerun/pull/1565) -#### 🖼 UI Improvements +#### 🖼 UI improvements - Fix combining outline mask for selection & hover [#1552](https://github.com/rerun-io/rerun/pull/1552) - Implement outlines for rectangles & use them for select & hover of image primitives in Viewer [#1559](https://github.com/rerun-io/rerun/pull/1559) - Show log messages in egui toast notifications [#1603](https://github.com/rerun-io/rerun/pull/1603) @@ -1731,7 +1731,7 @@ We now host an experimental and unpolished web-viewer at - Turn on depth cloud backprojection by default [#1710](https://github.com/rerun-io/rerun/pull/1710) - Add radius boost for depth clouds on outline [#1713](https://github.com/rerun-io/rerun/pull/1713) -#### 🤷‍♂️ Other Viewer Improvements +#### 🤷‍♂️ Other Viewer improvements - Fix web feature name in error messages [#1521](https://github.com/rerun-io/rerun/pull/1521) - Use outlines for mesh selections instead of highlight colors [#1540](https://github.com/rerun-io/rerun/pull/1540) - Implement outlines for line renderer & use them for select & hover of "line-like" primitives in Viewer [#1553](https://github.com/rerun-io/rerun/pull/1553) @@ -1759,7 +1759,7 @@ We now host an experimental and unpolished web-viewer at - Show the git commit in the about section in pre-release builds [#1677](https://github.com/rerun-io/rerun/pull/1677) - Update the web icon [#1688](https://github.com/rerun-io/rerun/pull/1688) -#### 🎨 Renderer Improvements +#### 🎨 Renderer improvements - Outlines via masking & postprocessing in `re_renderer` [#1532](https://github.com/rerun-io/rerun/pull/1532) - Add missing profiling scopes in `re_renderer` [#1567](https://github.com/rerun-io/rerun/pull/1567) - Don't call `wgpu::Device::poll` on the web [#1626](https://github.com/rerun-io/rerun/pull/1626) @@ -1809,7 +1809,7 @@ Remove potentially sensitive analytics, including path to rerun source code on p ## [0.3.0](https://github.com/rerun-io/rerun/compare/v0.2.0...v0.3.0) - 2023-03-07 -### Overview & Highlights +### Overview & highlights After a successful launch a couple of weeks ago, we're back with our second release! With a few exceptions this release focuses on internal refactors & improving our processes. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 38cb6ce21e08..9e48da673d62 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ This is written for anyone who wants to contribute to the Rerun repository. You can also look at our [`good first issue` tag](https://github.com/rerun-io/rerun/labels/good%20first%20issue). -## Pull Requests +## Pull requests We use [Trunk Based Development](https://trunkbaseddevelopment.com/), which means we encourage small, short-lived branches. Open draft PR:s to get some early feedback on your work. All PR:s are merged with [`Squash and Merge`](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-commits), meaning they all get squashed to just one commit on the `main` branch. This means you don't need to keep a clean commit history on your feature branches. In fact, it is preferable to add new commits to a branch rather than rebasing or squashing. For one, it makes it easier to track progress on a branch, but rebasing and force-pushing also discourages collaboration on a branch. diff --git a/README.md b/README.md index 84e9600443ab..5181a70c16dc 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ In the future, Rerun will offer a commercial product that builds on top of the c The Rerun open source project targets the needs of individual developers. The commercial product targets the needs specific to teams that build and run computer vision and robotics products. -## How to Cite Rerun +## How to cite Rerun When using Rerun in your research, please cite it to acknowledge its contribution to your work. This can be done by including a reference to Rerun in the software or methods section of your paper. diff --git a/RELEASES.md b/RELEASES.md index 7e29b37c17f2..b5eb0df429f4 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -10,7 +10,7 @@ This document describes the current release and versioning strategy. This strate * [`CONTRIBUTING.md`](CONTRIBUTING.md) -## Release Cadence +## Release cadence New Rerun versions are released every four weeks. Sometimes we do out-of-schedule patch releases. diff --git a/crates/re_data_store/README.md b/crates/re_data_store/README.md index c34907b5c6c9..0cd5f7e98561 100644 --- a/crates/re_data_store/README.md +++ b/crates/re_data_store/README.md @@ -1,4 +1,4 @@ -# Rerun Data Store +# Rerun data store Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. diff --git a/crates/re_types/definitions/rerun/archetypes/arrows2d.fbs b/crates/re_types/definitions/rerun/archetypes/arrows2d.fbs index 301c723e2a21..0b904c0cec74 100644 --- a/crates/re_types/definitions/rerun/archetypes/arrows2d.fbs +++ b/crates/re_types/definitions/rerun/archetypes/arrows2d.fbs @@ -11,7 +11,7 @@ namespace rerun.archetypes; /// 2D arrows with optional colors, radii, labels, etc. /// -/// \example arrow2d_simple title="Simple batch of 2D Arrows" image="https://static.rerun.io/arrow2d_simple/59f044ccc03f7bc66ee802288f75706618b29a6e/1200w.png" +/// \example arrow2d_simple title="Simple batch of 2D arrows" image="https://static.rerun.io/arrow2d_simple/59f044ccc03f7bc66ee802288f75706618b29a6e/1200w.png" table Arrows2D ( "attr.rust.derive": "PartialEq", "attr.rust.new_pub_crate", diff --git a/crates/re_types/definitions/rerun/archetypes/arrows3d.fbs b/crates/re_types/definitions/rerun/archetypes/arrows3d.fbs index 5265d944eafd..47dc8f6fdbd7 100644 --- a/crates/re_types/definitions/rerun/archetypes/arrows3d.fbs +++ b/crates/re_types/definitions/rerun/archetypes/arrows3d.fbs @@ -11,7 +11,7 @@ namespace rerun.archetypes; /// 3D arrows with optional colors, radii, labels, etc. /// -/// \example arrow3d_simple title="Simple batch of 3D Arrows" image="https://static.rerun.io/arrow3d_simple/55e2f794a520bbf7527d7b828b0264732146c5d0/1200w.png" +/// \example arrow3d_simple title="Simple batch of 3D arrows" image="https://static.rerun.io/arrow3d_simple/55e2f794a520bbf7527d7b828b0264732146c5d0/1200w.png" table Arrows3D ( "attr.rust.derive": "PartialEq", "attr.rust.new_pub_crate", diff --git a/crates/re_types/definitions/rerun/archetypes/pinhole.fbs b/crates/re_types/definitions/rerun/archetypes/pinhole.fbs index eed4a770f831..d69b1a475b75 100644 --- a/crates/re_types/definitions/rerun/archetypes/pinhole.fbs +++ b/crates/re_types/definitions/rerun/archetypes/pinhole.fbs @@ -8,8 +8,8 @@ namespace rerun.archetypes; /// Camera perspective projection (a.k.a. intrinsics). /// -/// \example pinhole_simple title="Simple Pinhole Camera" image="https://static.rerun.io/pinhole_simple/9af9441a94bcd9fd54e1fea44fb0c59ff381a7f2/1200w.png" -/// \example pinhole_perspective title="Perspective Pinhole Camera" image="https://static.rerun.io/pinhole_perspective/d0bd02a0cf354a5c8eafb79a84fe8674335cab98/1200w.png" +/// \example pinhole_simple title="Simple pinhole camera" image="https://static.rerun.io/pinhole_simple/9af9441a94bcd9fd54e1fea44fb0c59ff381a7f2/1200w.png" +/// \example pinhole_perspective title="Perspective pinhole camera" image="https://static.rerun.io/pinhole_perspective/d0bd02a0cf354a5c8eafb79a84fe8674335cab98/1200w.png" table Pinhole ( "attr.rust.derive": "PartialEq" ) { diff --git a/crates/re_types/definitions/rerun/archetypes/series_line.fbs b/crates/re_types/definitions/rerun/archetypes/series_line.fbs index 5d5c5acb38bf..d394720413e1 100644 --- a/crates/re_types/definitions/rerun/archetypes/series_line.fbs +++ b/crates/re_types/definitions/rerun/archetypes/series_line.fbs @@ -17,7 +17,7 @@ namespace rerun.archetypes; /// \rs See [`Scalar`][crate::archetypes.Scalar] /// \cpp See `rerun::archetypes::Scalar` /// -/// \example series_line_style title="Series Line" image="https://static.rerun.io/series_line_style/d2616d98b1e46bdb85849b8669154fdf058e3453/1200w.png" +/// \example series_line_style title="Line series" image="https://static.rerun.io/series_line_style/d2616d98b1e46bdb85849b8669154fdf058e3453/1200w.png" table SeriesLine { // --- Required --- diff --git a/crates/re_types/definitions/rerun/archetypes/series_point.fbs b/crates/re_types/definitions/rerun/archetypes/series_point.fbs index 4f4e94a4581e..de1f6f9550e2 100644 --- a/crates/re_types/definitions/rerun/archetypes/series_point.fbs +++ b/crates/re_types/definitions/rerun/archetypes/series_point.fbs @@ -17,7 +17,7 @@ namespace rerun.archetypes; /// \rs See [`Scalar`][crate::archetypes.Scalar] /// \cpp See `rerun::archetypes::Scalar` /// -/// \example series_point_style title="Series Point" image="https://static.rerun.io/series_point_style/82207a705da6c086b28ce161db1db9e8b12258b7/1200w.png" +/// \example series_point_style title="Point series" image="https://static.rerun.io/series_point_style/82207a705da6c086b28ce161db1db9e8b12258b7/1200w.png" table SeriesPoint { // --- Required --- diff --git a/crates/re_types/definitions/rerun/archetypes/tensor.fbs b/crates/re_types/definitions/rerun/archetypes/tensor.fbs index a6f01ffa8be6..c645fdea5a9f 100644 --- a/crates/re_types/definitions/rerun/archetypes/tensor.fbs +++ b/crates/re_types/definitions/rerun/archetypes/tensor.fbs @@ -12,7 +12,7 @@ namespace rerun.archetypes; /// \cpp data can be passed in without a copy from raw pointers or by reference from `std::vector`/`std::array`/c-arrays. /// \cpp If needed, this "borrow-behavior" can be extended by defining your own `rerun::CollectionAdapter`. /// -/// \example tensor_simple title="Simple Tensor" image="https://static.rerun.io/tensor_simple/baacb07712f7b706e3c80e696f70616c6c20b367/1200w.png" +/// \example tensor_simple title="Simple tensor" image="https://static.rerun.io/tensor_simple/baacb07712f7b706e3c80e696f70616c6c20b367/1200w.png" table Tensor ( "attr.rust.derive": "PartialEq" ) { diff --git a/crates/re_types/src/archetypes/arrows2d.rs b/crates/re_types/src/archetypes/arrows2d.rs index 8a3ac5303bee..44c142e18753 100644 --- a/crates/re_types/src/archetypes/arrows2d.rs +++ b/crates/re_types/src/archetypes/arrows2d.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// ## Example /// -/// ### Simple batch of 2D Arrows +/// ### Simple batch of 2D arrows /// ```ignore /// fn main() -> Result<(), Box> { /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_arrow2d").spawn()?; diff --git a/crates/re_types/src/archetypes/arrows3d.rs b/crates/re_types/src/archetypes/arrows3d.rs index 9a4a885ee89f..b2a51267533d 100644 --- a/crates/re_types/src/archetypes/arrows3d.rs +++ b/crates/re_types/src/archetypes/arrows3d.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// ## Example /// -/// ### Simple batch of 3D Arrows +/// ### Simple batch of 3D arrows /// ```ignore /// use std::f32::consts::TAU; /// diff --git a/crates/re_types/src/archetypes/pinhole.rs b/crates/re_types/src/archetypes/pinhole.rs index da24d417417b..aa98656578c6 100644 --- a/crates/re_types/src/archetypes/pinhole.rs +++ b/crates/re_types/src/archetypes/pinhole.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// ## Examples /// -/// ### Simple Pinhole Camera +/// ### Simple pinhole camera /// ```ignore /// use ndarray::{Array, ShapeBuilder}; /// @@ -54,7 +54,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; ///
///
/// -/// ### Perspective Pinhole Camera +/// ### Perspective pinhole camera /// ```ignore /// fn main() -> Result<(), Box> { /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_pinhole_perspective").spawn()?; diff --git a/crates/re_types/src/archetypes/series_line.rs b/crates/re_types/src/archetypes/series_line.rs index 8557bf829e17..b5be62ef2178 100644 --- a/crates/re_types/src/archetypes/series_line.rs +++ b/crates/re_types/src/archetypes/series_line.rs @@ -31,7 +31,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// ## Example /// -/// ### Series Line +/// ### Line series /// ```ignore /// fn main() -> Result<(), Box> { /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_series_line_style").spawn()?; diff --git a/crates/re_types/src/archetypes/series_point.rs b/crates/re_types/src/archetypes/series_point.rs index 9bef4b604185..55acc22f9ba8 100644 --- a/crates/re_types/src/archetypes/series_point.rs +++ b/crates/re_types/src/archetypes/series_point.rs @@ -31,7 +31,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// ## Example /// -/// ### Series Point +/// ### Point series /// ```ignore /// fn main() -> Result<(), Box> { /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_series_point_style").spawn()?; diff --git a/crates/re_types/src/archetypes/tensor.rs b/crates/re_types/src/archetypes/tensor.rs index 376d28584975..1af986eda6c2 100644 --- a/crates/re_types/src/archetypes/tensor.rs +++ b/crates/re_types/src/archetypes/tensor.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// ## Example /// -/// ### Simple Tensor +/// ### Simple tensor /// ```ignore /// use ndarray::{Array, ShapeBuilder}; /// diff --git a/crates/re_viewer/data/quick_start_guides/cpp_connect.md b/crates/re_viewer/data/quick_start_guides/cpp_connect.md index 217a140b8b4d..43eef06297b5 100644 --- a/crates/re_viewer/data/quick_start_guides/cpp_connect.md +++ b/crates/re_viewer/data/quick_start_guides/cpp_connect.md @@ -1,4 +1,4 @@ -# C++ Quick Start +# C++ quick start ## Installing the Rerun viewer The Rerun C++ SDK works by connecting to an awaiting Rerun Viewer over TCP. diff --git a/crates/re_viewer/data/quick_start_guides/cpp_spawn.md b/crates/re_viewer/data/quick_start_guides/cpp_spawn.md index 92a43a7032c8..7063ffe05cb5 100644 --- a/crates/re_viewer/data/quick_start_guides/cpp_spawn.md +++ b/crates/re_viewer/data/quick_start_guides/cpp_spawn.md @@ -1,4 +1,4 @@ -# C++ Quick Start +# C++ quick start ## Installing the Rerun viewer The Rerun C++ SDK works by connecting to an awaiting Rerun Viewer over TCP. diff --git a/crates/re_viewer/data/quick_start_guides/python_connect.md b/crates/re_viewer/data/quick_start_guides/python_connect.md index cf86fbf63a98..af904052a9d9 100644 --- a/crates/re_viewer/data/quick_start_guides/python_connect.md +++ b/crates/re_viewer/data/quick_start_guides/python_connect.md @@ -1,4 +1,4 @@ -# Python Quick Start +# Python quick start ## Installing the Rerun SDK diff --git a/crates/re_viewer/data/quick_start_guides/python_spawn.md b/crates/re_viewer/data/quick_start_guides/python_spawn.md index c457478ffa08..a4dbbc67a909 100644 --- a/crates/re_viewer/data/quick_start_guides/python_spawn.md +++ b/crates/re_viewer/data/quick_start_guides/python_spawn.md @@ -1,4 +1,4 @@ -# Python Quick Start +# Python quick start ## Installing the Rerun SDK diff --git a/crates/re_viewer/data/quick_start_guides/rust_connect.md b/crates/re_viewer/data/quick_start_guides/rust_connect.md index 37aa2b2955c1..fb561ec18781 100644 --- a/crates/re_viewer/data/quick_start_guides/rust_connect.md +++ b/crates/re_viewer/data/quick_start_guides/rust_connect.md @@ -1,4 +1,4 @@ -# Rust Quick Start +# Rust quick start ## Installing Rerun diff --git a/crates/re_viewer/data/quick_start_guides/rust_spawn.md b/crates/re_viewer/data/quick_start_guides/rust_spawn.md index 197a877494df..127eb8bebd85 100644 --- a/crates/re_viewer/data/quick_start_guides/rust_spawn.md +++ b/crates/re_viewer/data/quick_start_guides/rust_spawn.md @@ -1,4 +1,4 @@ -# Rust Quick Start +# Rust quick start ## Installing Rerun diff --git a/design/batching.md b/design/batching.md index 973460a5cb64..7b5d844b560d 100644 --- a/design/batching.md +++ b/design/batching.md @@ -349,7 +349,7 @@ While range queries have some surprisingly tricky semantics (especially around t However, the fact that we return row numbers instead of the actual data itself can have significant performance implications when it comes to range queries. For example, if you need to iterate through 100k values, you would need to run 100k `get` requests, which would require 100k binsearches in the component tables. This can be extremely costly and is a major reason why our ranged query scenes quickly become unusable as the dataset grows. -### Garbage Collection +### Garbage collection The current garbage collection mechanism was put together as a quick fix for the `MsgId`-mismatch issue, and it is largely unreliable. @@ -783,7 +783,7 @@ Nothing specific to add to the above. Nothing specific to add to the above. -### Garbage Collection +### Garbage collection The garbage collector is the system undergoing the most changes. diff --git a/design/blueprint_store.md b/design/blueprint_store.md index 9dc81037d867..077b24aa045a 100644 --- a/design/blueprint_store.md +++ b/design/blueprint_store.md @@ -1,4 +1,4 @@ -# Blueprint Operation: APIs and Datastore +# Blueprint operation: APIs and datastore Status: proposal ## Intro @@ -27,7 +27,7 @@ give users explicit control over the details of how data is displayed in the vie ## Proposal -### Blueprint Lifecycle +### Blueprint lifecycle In order to simplify many edge cases, custom blueprints will only be able to be sent to the viewer in their entirety as part of viewer startup. This limits blueprint control to: `rr.spawn()` (launch a native app), `rr.serve()` (launch a hosted web-app), and `rr.show()` (embed a viewer in a notebook). Additionally a blueprint file will be able to be @@ -131,7 +131,7 @@ particular: This means a trivial expression like: `rr.show(rrb.Points3D("points"))` is still a valid Blueprint. -## Blueprint-Static Data +## Blueprint-Static data As a further simplification, the Blueprint will allow for the direct inclusion of static data, allowing users to bypass the data-logging APIs entirely for simple use-cases that don't require temporal information. This will be accomplished @@ -139,12 +139,12 @@ by allowing `rrb.Data` objects to be constructed from any Rerun-loggable object. Data that is a *query* from the recording store references an entity path used separately by the logging APIs: ```python -# Log Data +# Log data for t in range(100): rr.set_time('step', t) rr.log("world/points", rr.Points3D(points)) … -# Construct Blueprint +# Construct blueprint rrb.Auto("/world/points") ``` While static data skips the logging step all together, but only allows for a single element: @@ -166,7 +166,7 @@ grid = rrd.GridLayout(cols=3, [rr.Image(img) for img in images]) Note the usage of `rr.Image` (the loggable) vs `rrb.Image` (the blueprint template). -## Blueprint Store +## Blueprint store Behind the APIs, the blueprint is implemented using a “blueprint store” that leverages the same code as the existing data-store. We will therefore have both “data entities” and “blueprint entities”. diff --git a/design/space_views.md b/design/space_views.md index 5d973c2beb3f..1cfe8252cbcc 100644 --- a/design/space_views.md +++ b/design/space_views.md @@ -1,14 +1,14 @@ -# Space Views +# Space views Status: Mostly implemented. -## What are Space Views +## What are space views Space Views visualize a Data Blueprint, i.e. a set of entities with given properties. They are represented as freely arrangeable tiles in the Viewport. Most Space Views are interactive, allowing their data to be explored freely. -## Properties of a Space View +## Properties of a space view All properties are saved as part of the blueprint. Changing discards Space View State: @@ -27,7 +27,7 @@ Freely mutable: * available at various stages of ui drawing & system execution build-up (see below) -## Space View State +## Space view state In addition to blueprint stored data, a space view has a class specific `SpaceViewState` which stored ephemeral state that is not persisted as part of the blueprint. This is typically used for animation/transition state. @@ -35,14 +35,14 @@ This is typically used for animation/transition state. ⚠️ As of writing, we're using this also for state that *should* be persisted and needs to be moved to blueprint components. -## Space View Class +## Space view class Each Space View refers to an immutable Space View Class, implemented by `SpaceViewClass`. It defines: * which data it can display and how it is displayed * how it is interacted with * what properties are read from the blueprint store and how they are exposed in the ui -### What Space View Classes are there? +### What space view classes are there? Space View differ only in class when they are **fundamentally different** in the way they display data. Naturally, this means that there are only ever very few distinct Space View classes. @@ -54,7 +54,7 @@ As of writing we have: * Text Document * Time Series -#### Future Space View Class distinction +#### Future space view class distinction The fundamental difference between different space views lies in the kinds of axes a view has. - Data Table (currently text views) have rows and columns with text @@ -64,7 +64,7 @@ The fundamental difference between different space views lies in the kinds of ax - Time Series has one time axis and one numeric axis - Rich Text is a rich text document (linear in top to bottom with wraparound in horizontal) -##### On merging Bar Chart with Spatial 2D +##### On merging bar chart with spatial 2D It might take some time to get the Archetype Queries + defaults expressive and easy to use enough that it makes sense to merge bar chart with spatial 2D. Right now we have the state that the bar chart space view takes a single 1-D tensor and draws a bar chart with x-axis = tensor indices and y-axis = tensor values. It draws boxes with width 1, centered on integers in x, y-min = 0 and y-max = tensor value. With the right set of primitives a user should be able to manually build a bar chart in a spatial 2D view. For example they might want a stacked bar chart. Talking about bringing in 3D into a bar chart doesn't likely make sense since there probably doesn't exist a camera projection that maps between 3D and the tensor indices axis (x). @@ -135,7 +135,7 @@ Registration is done via `SpaceViewSystemRegistry` which `SpaceViewClassRegistry Space view classes can register their built-in systems upon their own registration via their `on_register` method. As with space view classes themselves, new systems may be added at runtime. -### Frame Lifecycle +### Frame lifecycle * `SpaceViewClass::prepare_ui` * default create all registered `ViewContextSystem` into a `ViewContextCollection` * execute all `ViewContextSystem` @@ -147,7 +147,7 @@ As with space view classes themselves, new systems may be added at runtime. * this typically requires iterating over all `ViewPartSystem` and extract some data either in a generic fashion via `ViewPartSystem::data` or with knowledge of the concrete `ViewPartSystem` types * currently, we also pass in all `re_renderer` data since the build up of the `re_renderer` view via `ViewBuilder` is not (yet?) unified -### Space View Class Registry +### Space view class registry Despite being few in numbers, Space Views Classes are registered on startup. This is desirable since: * forces decoupling from other aspects of the Viewer (Viewer should be composable) @@ -157,7 +157,7 @@ This is desirable since: ![Overview diagram of how the basic traits related to each other](https://github.com/rerun-io/rerun/assets/1220815/ffdb1cdf-7efe-47a0-ac38-30262d770e69) -#### User defined Space View Classes +#### User defined space view classes Rust developers can use the Class Registry to register their own Space View types. We do *not* expect this to be a common workflow, but more of a last resort / highest level extensibility hooks. diff --git a/design/spatial_transforms.md b/design/spatial_transforms.md index 93cba6c3267e..fdbddd88f044 100644 --- a/design/spatial_transforms.md +++ b/design/spatial_transforms.md @@ -1,4 +1,4 @@ -# Spatial Transforms +# Spatial transforms Spatial transforms are transforms that apply the spatial 2D & 3D space views. This includes affine 2D/3D transforms as well as camera projections. diff --git a/docs/content/concepts/annotation-context.md b/docs/content/concepts/annotation-context.md index 06d983d1dda9..492f609bd03e 100644 --- a/docs/content/concepts/annotation-context.md +++ b/docs/content/concepts/annotation-context.md @@ -23,7 +23,7 @@ but can be used more generally for any kind of reoccurring categorization within -### Keypoints & Keypoint Connections +### Keypoints & keypoint connections Rerun allows you to define keypoints *within* a class. Each keypoint can define its own properties (colors, labels, etc.) that overwrite its parent class. @@ -44,7 +44,7 @@ Keypoints are currently only applicable to 2D and 3D points. -### Logging an Annotation Context +### Logging an annotation context Annotation Context is typically logged as [timeless](timelines.md#timeless-data) data, but can change over time if needed. @@ -59,7 +59,7 @@ Annotation contexts are logged with: snippet: annotation-context -## Affected Entities +## Affected entities Each entity that uses a Class ID component (and optionally Keypoint ID components) will look for the nearest ancestor that in the [entity path hierarchy](entity-path.md#path-hierarchy-functions) that has an Annotation Context defined. diff --git a/docs/content/concepts/blueprint.md b/docs/content/concepts/blueprint.md index 28189066c555..46f871ad48f3 100644 --- a/docs/content/concepts/blueprint.md +++ b/docs/content/concepts/blueprint.md @@ -3,7 +3,7 @@ title: Blueprint order: 9 --- -## Blueprints and Recordings +## Blueprints and recordings When you are working with the Rerun viewer, there are two separate pieces that combine to produce what you see: the "recording" and the "blueprint." diff --git a/docs/content/concepts/entity-component.md b/docs/content/concepts/entity-component.md index a03c2103fb9b..e3c7925d31d8 100644 --- a/docs/content/concepts/entity-component.md +++ b/docs/content/concepts/entity-component.md @@ -62,13 +62,13 @@ For more complex use-cases, custom objects implementing the `rr.AsComponents` pr snippet: custom_data -### Empty Entities +### Empty entities An entity without components is nothing more than an identity (represented by its entity path). It contains no data, and has no type. When you log a piece of data, all that you are doing is setting the values of one or more components associated with that entity. -## ECS Systems +## ECS systems There is a third concept we haven't touched on: *systems* are processes which operate on the entities based on the components they possess. Rerun is still settling on the exact form of formalized systems and outside of Rust viewer code it is not yet possible to write your own systems. However, space views work under the hood using a variety of systems. For more information see the [Extend the Viewer in Rust](../howto/extend/extend-ui.md) section. diff --git a/docs/content/concepts/entity-path.md b/docs/content/concepts/entity-path.md index 143aba39d8df..e9f1473402c6 100644 --- a/docs/content/concepts/entity-path.md +++ b/docs/content/concepts/entity-path.md @@ -3,7 +3,7 @@ title: The Entity Path Hierarchy order: 1 --- -## Entity Paths +## Entity paths As mentioned in the [Entity Component](entity-component.md) overview, all entities within Rerun have a unique _entity path_. The first argument to the `log()` function is this path. Each time you log to a specific entity path you will update the entity, i.e. log a new instance of it along the timeline. @@ -49,7 +49,7 @@ So for instance, `world/3D/My\ Image.jpg/detection` is a valid path (note the es ⚠️ NOTE: even though entity paths are somewhat analogous to file paths, they are NOT the same. `..` does not mean "parent folder", and you are NOT intended to pass a file path as an entity path (especially not on Windows, which use `\` as a path separator). -### Path Hierarchy Functions +### Path hierarchy functions Path hierarchy plays an important role in a number of different functions within Rerun: * With the [Transform System](spaces-and-transforms.md) the `transform` component logged to any entity always describes @@ -60,7 +60,7 @@ the relationship between that entity and its direct parent. * In the future, it will also be possible to use path-hierarchy to set default-values for descendants ([#1158](https://github.com/rerun-io/rerun/issues/1158)). -### Reserved Paths +### Reserved paths The path prefix `rerun/` is considered reserved for use by the Rerun SDK itself and should not be used for logging user data. This is where Rerun will log additional information such as warnings. diff --git a/docs/content/concepts/spaces-and-transforms.md b/docs/content/concepts/spaces-and-transforms.md index 0048c9f7b5a8..ecd98567c404 100644 --- a/docs/content/concepts/spaces-and-transforms.md +++ b/docs/content/concepts/spaces-and-transforms.md @@ -61,7 +61,7 @@ from `world/robot/observed_features` are not directly comparable. If you were to coordinate system the results would be meaningless. As noted above, Rerun can still display these entities in the same space view because it is able to automatically transform data between different spaces. -## Space Transformations +## Space transformations In order to correctly display data from different spaces in the same view, Rerun uses the information from logged transforms. Since most transforms are invertible, Rerun can usually transform data from a parent space to a child space diff --git a/docs/content/getting-started/configure-the-viewer/interactively.md b/docs/content/getting-started/configure-the-viewer/interactively.md index e4cab20edd57..ae8ea12049ed 100644 --- a/docs/content/getting-started/configure-the-viewer/interactively.md +++ b/docs/content/getting-started/configure-the-viewer/interactively.md @@ -41,7 +41,7 @@ Any container or view can be hidden or shown by clicking the "eye" icon.
-### Add new Containers or Views +### Add new containers or views Adding a container or a view to the view port can be done by clicking the "+" at the top of the blueprint panel. @@ -58,7 +58,7 @@ If a container (or the viewport) is already selected, a "+" button will also be
-### Remove a View or Container +### Remove a view or container Removing a view or a container can be done by clicking the "-" button next to it: @@ -67,7 +67,7 @@ Removing a view or a container can be done by clicking the "-" button next to it
-### Re-arrange existing Containers or Views +### Re-arrange existing containers or views The viewport hierarchy can be reorganized by drag-and-dropping containers or views in the blueprint panel. It ssi also possible to drag views directly in the viewport by using their title tab: @@ -77,7 +77,7 @@ The viewport hierarchy can be reorganized by drag-and-dropping containers or vie
-### Rename a View or Container +### Rename a view or container Both views and containers may be assigned a custom name. This can be done by selecting the view or container, and editing the name at the top of the selection panel. @@ -85,7 +85,7 @@ Both views and containers may be assigned a custom name. This can be done by sel
-### Change a Container kind +### Change a container kind Containers come in four different kinds: vertical, horizontal, grid, and tabs. To change an existing container's kind, select it and change the value from the dropdown menu in the selection panel: @@ -121,7 +121,7 @@ Like containers and views, any entity in a view may be shown and hidden with the
-### Remove Data from a View +### Remove data from a view Likewise, entities may be removed from a view by clicking the "-" next to it: diff --git a/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md index 848655738d6e..cdecb3f7a07b 100644 --- a/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md +++ b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md @@ -168,7 +168,7 @@ layout is far from ideal:
-## Create a Blueprint +## Create a blueprint To improve the layout, we will now use the blueprint APIs to create some custom layouts. diff --git a/docs/content/getting-started/data-in/cpp.md b/docs/content/getting-started/data-in/cpp.md index 4e7364336b9a..b52dfe809b10 100644 --- a/docs/content/getting-started/data-in/cpp.md +++ b/docs/content/getting-started/data-in/cpp.md @@ -265,7 +265,7 @@ Once again, although we are getting fancier and fancier with our iterator mappin ## Animating the beads -### Introducing Time +### Introducing time Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). @@ -322,7 +322,7 @@ You can add as many timelines and timestamps as you want when logging data. Enter… -### Latest At semantics +### Latest at semantics That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). To fix this, go back to the top of your main and initialize your timeline before logging the initial structure: diff --git a/docs/content/getting-started/data-in/python.md b/docs/content/getting-started/data-in/python.md index 0ce5014ab85a..73d73b6e40b5 100644 --- a/docs/content/getting-started/data-in/python.md +++ b/docs/content/getting-started/data-in/python.md @@ -37,7 +37,7 @@ Among other things, a stable [`ApplicationId`](https://ref.rerun.io/docs/python/ Check out the reference to learn more about how Rerun deals with [applications and recordings](../../concepts/apps-and-recordings.md). -## Starting the Viewer +## Starting the viewer Next up, we want to spawn the [Rerun Viewer](../../reference/viewer/overview.md) itself. @@ -193,7 +193,7 @@ there is nothing new here: it's all about building out `numpy` arrays and feedin ## Animating the beads -### Introducing Time +### Introducing time Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). @@ -246,7 +246,7 @@ A call to [`set_time_seconds`](https://ref.rerun.io/docs/python/stable/common/lo Enter… -### Latest At semantics +### Latest at semantics That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). To fix this, go back to the top of the file and add: diff --git a/docs/content/getting-started/data-in/rust.md b/docs/content/getting-started/data-in/rust.md index c0a9f780131b..7ef473309956 100644 --- a/docs/content/getting-started/data-in/rust.md +++ b/docs/content/getting-started/data-in/rust.md @@ -216,7 +216,7 @@ Once again, although we are getting fancier and fancier with our iterator mappin ## Animating the beads -### Introducing Time +### Introducing time Up until this point, we've completely set aside one of the core concepts of Rerun: [Time and Timelines](../../concepts/timelines.md). @@ -274,7 +274,7 @@ You can add as many timelines and timestamps as you want when logging data. Enter… -### Latest At semantics +### Latest at semantics That's because the Rerun Viewer has switched to displaying your custom timeline by default, but the original data was only logged to the _default_ timeline (called `log_time`). To fix this, add this at the beginning of the main function: @@ -341,7 +341,7 @@ You can also save a recording (or a portion of it) as you're visualizing it, dir ⚠️ [RRD files don't yet handle versioning!](https://github.com/rerun-io/rerun/issues/873) ⚠️ -### Spawning the Viewer from your process +### Spawning the viewer from your process If the Rerun Viewer is [installed](../installing-viewer.md) and available in your `PATH`, you can use [`RecordingStream::spawn`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.spawn) to automatically start a viewer in a new process and connect to it over TCP. If an external viewer was already running, `spawn` will connect to that one instead of spawning a new one. diff --git a/docs/content/getting-started/installing-viewer.md b/docs/content/getting-started/installing-viewer.md index 2b4e117409fb..4f02f7f0580d 100644 --- a/docs/content/getting-started/installing-viewer.md +++ b/docs/content/getting-started/installing-viewer.md @@ -30,7 +30,7 @@ Either way this includes both the SDK & the viewer and you're ready to go! Add the [Rerun crate](https://crates.io/crates/rerun) using `cargo add rerun`. You'll additionally need to install the Viewer, see [below](#installing-the-viewer). -## Installing the Viewer +## Installing the viewer The [Viewer](../reference/viewer/overview.md) can be installed independent of the library language you're using. Make sure that your library version matches the version of the Viewer you're using. @@ -52,7 +52,7 @@ If you're facing any difficulties, don't hesitate to [open an issue](https://git The Rerun Viewer has built-in support for opening many kinds of files, and can be [extended to open any other file type](./data-in/open-any-file.md) without needing to modify the Rerun codebase itself. -## Next Steps +## Next steps To start getting your own data streamed to the viewer, check one of the respective getting started guides: diff --git a/docs/content/howto/configure-viewer-through-code.md b/docs/content/howto/configure-viewer-through-code.md index 501359f92b21..a801a5d1b5e8 100644 --- a/docs/content/howto/configure-viewer-through-code.md +++ b/docs/content/howto/configure-viewer-through-code.md @@ -106,7 +106,7 @@ rr.send_blueprint(my_blueprint, make_active=True) ``` -## Customizing Space Views +## Customizing space views Any of the space views (`BarChartView`, `Spatial2DView`, `Spatial3DView`, `TensorView`, `TextDocumentView`, `TextLogView`, or `TimeSeriesView`) can be instantiated with no arguments. diff --git a/docs/content/howto/extend/extend-ui.md b/docs/content/howto/extend/extend-ui.md index 1c686c03ce31..1600cb0a9157 100644 --- a/docs/content/howto/extend/extend-ui.md +++ b/docs/content/howto/extend/extend-ui.md @@ -4,7 +4,7 @@ order: 2 description: How to extend the Rerun Viewer UI using Rust and egui --- -## Custom UI embedding the Viewer +## Custom UI embedding the viewer ![The Rerun Viewer, extended with a custom panel to the right](https://github.com/rerun-io/rerun/assets/1148717/cbbad63e-9b18-4e54-bafe-b6ffd723f63e) @@ -17,7 +17,7 @@ The Rerun Viewer is defined by the crate [`re_viewer`](https://github.com/rerun- The best way to get started is by reading [the source code of the `extend_viewer_ui` example](https://github.com/rerun-io/rerun/tree/main/examples/rust/extend_viewer_ui). -## Custom Space Views classes +## Custom space views classes diff --git a/docs/content/howto/notebook.md b/docs/content/howto/notebook.md index 5e8190a47fe6..98129090ecbc 100644 --- a/docs/content/howto/notebook.md +++ b/docs/content/howto/notebook.md @@ -13,7 +13,7 @@ Rerun has been tested with: - [VSCode](https://code.visualstudio.com/blogs/2021/08/05/notebooks) - [Google Colab](https://colab.research.google.com/) -## Basic Concept +## Basic concept Rather than logging to a file or a remote server, you can also configure the Rerun SDK to store data in a local [MemoryRecording](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.MemoryRecording). @@ -92,7 +92,7 @@ it is not suited to large RRD files. The RRD file is embedded as a base64 encode result in a very large HTML file. This can cause problems in some browsers. If you want to share large datasets, we recommend using the `save()` API to create a separate file and hosting it as a separate standalone asset. -## Future Work +## Future work We are actively working on improving the notebook experience and welcome any feedback or suggestions. The ongoing roadmap is being tracked in [GitHub issue #1815](https://github.com/rerun-io/rerun/issues/1815). diff --git a/docs/content/howto/ros2-nav-turtlebot.md b/docs/content/howto/ros2-nav-turtlebot.md index 8b7769b96749..8cbe4aef2915 100644 --- a/docs/content/howto/ros2-nav-turtlebot.md +++ b/docs/content/howto/ros2-nav-turtlebot.md @@ -58,7 +58,7 @@ $ ros2 launch nav2_bringup tb3_simulation_launch.py headless:=False Make sure that you can set the 2D Pose Estimate and send a Navigation Goal via rviz. You can now leave this running in the background for the remainder of the guide. -### Additional Dependencies +### Additional dependencies The code for this guide is in the `rerun` repository. If you do not already have rerun cloned, you should do so now: @@ -122,7 +122,7 @@ If you are familiar with the turtlebot nav example and rviz, this view will like - `odometry/vel` is a plot of the linear velocity of the robot logged as a [scalar](../reference/types/archetypes/scalar.md). - `odometry/ang_vel` is a plot of the angular velocity of the robot logged as a [scalar](../reference/types/archetypes/scalar.md). -## Code Explanation +## Code explanation It may be helpful to open [rerun/examples/python/ros_node/main.py](https://github.com/rerun-io/rerun/blob/main/examples/python/ros_node/main.py) to follow along. @@ -134,7 +134,7 @@ For simplicity, this example uses the rosclpy `MultiThreadedExecutor` and `Reent allows each callback thread to do TF lookups without blocking the other incoming messages. More advanced ROS execution models and using asynchronous TF lookups are outside the scope of this guide. -### Updating Time +### Updating time First of all, we want our messages to show up on the timeline based on their _stamped_ time rather than the time that they were received by the listener, or relayed to Rerun. @@ -465,7 +465,7 @@ if node_data: Color data is also extracted from the trimesh, but omitted here for brevity. -## In Summary +## In summary Although there is a non-trivial amount of code, none of it is overly complicated. Each message callback operates independently of the others, processing an incoming message, adapting it to Rerun and then diff --git a/docs/content/reference/migration/migration-0-13.md b/docs/content/reference/migration/migration-0-13.md index 28cade6f3aad..26a6908f8f68 100644 --- a/docs/content/reference/migration/migration-0-13.md +++ b/docs/content/reference/migration/migration-0-13.md @@ -14,7 +14,7 @@ line series via [SeriesLine](../types/archetypes/series_line.md). `TimeSeriesScalar` will be removed in a future release. -## Changes in Space View creation heuristics +## Changes in space view creation heuristics The overhaul of automatic Space View creation makes the viewer faster and more predictable but comes with a few changes on how paths are expected to be structured: diff --git a/docs/content/reference/migration/migration-0-9.md b/docs/content/reference/migration/migration-0-9.md index 38c28369a764..f36080950ca8 100644 --- a/docs/content/reference/migration/migration-0-9.md +++ b/docs/content/reference/migration/migration-0-9.md @@ -24,7 +24,7 @@ batch of size 1. For more information on the relationship between Archetypes, Components, and DataTypes, please see our guide to the [Rerun Data Model](../../concepts/entity-component.md). -# Migrating Python Code +# Migrating Python code All of the previous `log_*` functions have been marked as deprecated and will be removed in `0.10`. We have done our best to keep these functions working as thin wrappers on top of the new logging APIs, though there may be subtle @@ -239,7 +239,7 @@ Notes: - Rather than providing `xyz` or `up` as strings, `rr.ViewCoordinates` exposes a large number of constants that can be logged directly. For example: `rr.ViewCoordinates.RDF` or `rr.ViewCoordinates.RIGHT_HAND_Z_DOWN)` -# Migrating Rust Code +# Migrating Rust code Rust already used a more type oriented interface, so the changes are not as drastic as to the Python API. @@ -252,7 +252,7 @@ using its [`log`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html The new `log` function logs time implicitly. `log_time` and `log_tick` are always included, as well as any custom timeline set using [`RecordingStream::set_timepoint`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.set_timepoint), or one of the shorthands [`RecordingStream::set_time_sequence`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.set_time_sequence)/[`RecordingStream::set_time_seconds`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.set_time_seconds)/[`RecordingStream::set_time_nanos`](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.set_time_nanos) -## Components -> Archetypes +## Components -> archetypes The new log messages consume any type that implements the [`AsComponents`](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html) trait which is [implemented by](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html#implementors) all archetypes. diff --git a/docs/content/reference/sdk-operating-modes.md b/docs/content/reference/sdk-operating-modes.md index 1e4f0cdf08a7..e54badaf96c0 100644 --- a/docs/content/reference/sdk-operating-modes.md +++ b/docs/content/reference/sdk-operating-modes.md @@ -8,7 +8,7 @@ There are many different ways of sending data to the Rerun Viewer depending on w In the [official examples](/examples), these different modes of operation are exposed via a standardized set of flags that we'll cover below. We will also demonstrate how you can achieve the same behavior in your own code. -## Operating Modes +## Operating modes The Rerun SDK provides 4 modes of operation: `spawn`, `connect`, `serve` & `save`. diff --git a/docs/content/reference/types.md b/docs/content/reference/types.md index c5711e2bf5e6..a82c7f6094c4 100644 --- a/docs/content/reference/types.md +++ b/docs/content/reference/types.md @@ -11,7 +11,7 @@ The top-level types are called [**archetypes**](types/archetypes.md) to differen For more information on the relationship between **archetypes** and **components**, check out the concept page on [Entities and Components](../concepts/entity-component.md). -## Spatial **Archetypes** +## Spatial **archetypes** The spatial archetypes represent 2D and 3D spatial data. These types have some notion of a coordinate system and generally support spatial transformations. These types can be visualized by 2D and 3D space views. @@ -35,7 +35,7 @@ To visualize a 3D entity in a 2D space view, the 2D's origin must be at a pinhol - [Pinhole](types/archetypes/pinhole.md) - [DisconnectedSpace](types/archetypes/disconnected_space.md): disconnect an entity path from its parent. -## Image & Tensor **Archetypes** +## Image & tensor **archetypes** Image and tensor archetypes all build on top of a common tensor component. The tensor component is a multi-dimensional generic container for arrays of data. Images are restricted to tensors of rank 2 or rank 3; these can be viewed in the @@ -46,13 +46,13 @@ generic container for arrays of data. Images are restricted to tensors of rank 2 - [SegmentationImage](types/archetypes/segmentation_image.md) - [Tensor](types/archetypes/tensor.md) -## Time Series **Archetypes** +## Time series **archetypes** - [Scalar](types/archetypes/scalar.md): a single scalar / metric value. - [SeriesPoint](types/archetypes/series_point.md): define the style properties for a point series in a chart. - [SeriesLine](types/archetypes/series_line.md): define the style properties for a line series in a chart. -## Other **Archetypes** +## Other **archetypes** - [AnnotationContext](types/archetypes/annotation_context.md): not viewed directly, but provides classes, labels, and connectivity information for other entities. - [BarChart](types/archetypes/bar_chart.md): data displayed in a `BarChart` space view. diff --git a/docs/content/reference/types/archetypes/arrows2d.md b/docs/content/reference/types/archetypes/arrows2d.md index ecc3d8aa0a90..1b96f280ae26 100644 --- a/docs/content/reference/types/archetypes/arrows2d.md +++ b/docs/content/reference/types/archetypes/arrows2d.md @@ -19,7 +19,7 @@ title: "Arrows2D" ## Example -### Simple batch of 2D Arrows +### Simple batch of 2D arrows snippet: arrow2d_simple diff --git a/docs/content/reference/types/archetypes/arrows3d.md b/docs/content/reference/types/archetypes/arrows3d.md index 376946187c7d..9cafefc4f4db 100644 --- a/docs/content/reference/types/archetypes/arrows3d.md +++ b/docs/content/reference/types/archetypes/arrows3d.md @@ -19,7 +19,7 @@ title: "Arrows3D" ## Example -### Simple batch of 3D Arrows +### Simple batch of 3D arrows snippet: arrow3d_simple diff --git a/docs/content/reference/types/archetypes/pinhole.md b/docs/content/reference/types/archetypes/pinhole.md index 790df5927231..9a7bbdc46d07 100644 --- a/docs/content/reference/types/archetypes/pinhole.md +++ b/docs/content/reference/types/archetypes/pinhole.md @@ -19,7 +19,7 @@ Camera perspective projection (a.k.a. intrinsics). ## Examples -### Simple Pinhole Camera +### Simple pinhole camera snippet: pinhole_simple @@ -31,7 +31,7 @@ snippet: pinhole_simple -### Perspective Pinhole Camera +### Perspective pinhole camera snippet: pinhole_perspective diff --git a/docs/content/reference/types/archetypes/series_line.md b/docs/content/reference/types/archetypes/series_line.md index 0315fab0f341..8c5cbfe937fd 100644 --- a/docs/content/reference/types/archetypes/series_line.md +++ b/docs/content/reference/types/archetypes/series_line.md @@ -19,7 +19,7 @@ the `Scalar` archetype. ## Example -### Series Line +### Line series snippet: series_line_style diff --git a/docs/content/reference/types/archetypes/series_point.md b/docs/content/reference/types/archetypes/series_point.md index 3d62588e8276..f9bc328d0f27 100644 --- a/docs/content/reference/types/archetypes/series_point.md +++ b/docs/content/reference/types/archetypes/series_point.md @@ -19,7 +19,7 @@ the `Scalar` archetype. ## Example -### Series Point +### Point series snippet: series_point_style diff --git a/docs/content/reference/types/archetypes/tensor.md b/docs/content/reference/types/archetypes/tensor.md index f94c08466489..84155975d724 100644 --- a/docs/content/reference/types/archetypes/tensor.md +++ b/docs/content/reference/types/archetypes/tensor.md @@ -15,7 +15,7 @@ A generic n-dimensional Tensor. ## Example -### Simple Tensor +### Simple tensor snippet: tensor_simple diff --git a/docs/content/reference/viewer/blueprint.md b/docs/content/reference/viewer/blueprint.md index 694efa381a0b..234a1a7bcdee 100644 --- a/docs/content/reference/viewer/blueprint.md +++ b/docs/content/reference/viewer/blueprint.md @@ -22,14 +22,14 @@ Controls The reset button resets the entire Blueprint back to its heuristic-chosen default. This includes all settings for Entities, Groups and Space Views. -### Add Space View +### Add space view With this control you can add new Space Views for arbitrary [Spaces](../../concepts/spaces-and-transforms.md). Contents -------- Upon hovering any line in the Blueprint panel, you'll find shorthands for removing and hide/show. -### Data Blueprints +### Data blueprints All Entities shown in the blueprint panel refer in fact to their Data Blueprints. I.e. the entity plus the associated blueprint settings. As such, all changes made here are only relevant for the Space View in which they reside. diff --git a/docs/content/reference/viewer/overview.md b/docs/content/reference/viewer/overview.md index 2d26fe19d72a..2bc57a519ac0 100644 --- a/docs/content/reference/viewer/overview.md +++ b/docs/content/reference/viewer/overview.md @@ -24,7 +24,7 @@ Additionally, it gives you an overview of all events on a given timeline. ### [Viewport](viewport.md) The viewport is where your visualizations live. It is composed of one or more Space Views that you can arrange freely. -### Top bar & Menu +### Top bar & menu The top bar contains operating system controls and generic information. In the menu you find application wide options and actions. Use the buttons at the top right corner to hide/show parts of the viewer. diff --git a/docs/content/reference/viewer/selection.md b/docs/content/reference/viewer/selection.md index b19c3599c003..5f6a4b8c2894 100644 --- a/docs/content/reference/viewer/selection.md +++ b/docs/content/reference/viewer/selection.md @@ -29,7 +29,7 @@ Here you find what is selected and for some objects in which context. This context not only gives you a convenient way to jump to related objects, but is also important for what the following sections are showing. -### Data & Blueprint sections +### Data & blueprint sections The data section always shows static, raw user logged data for the currently selected time. Some objects, e.g. Space Views, may not have a data section and expose only Blueprint options. diff --git a/docs/snippets/README.md b/docs/snippets/README.md index 510d504a6962..c4d97935d5c3 100644 --- a/docs/snippets/README.md +++ b/docs/snippets/README.md @@ -1,4 +1,4 @@ -# API Examples +# API examples These examples showcase common usage of each individual Rerun `Archetype`s. diff --git a/examples/c/spawn_viewer/README.md b/examples/c/spawn_viewer/README.md index e6f4f4e7bd38..5b9c879a97d9 100644 --- a/examples/c/spawn_viewer/README.md +++ b/examples/c/spawn_viewer/README.md @@ -1,5 +1,5 @@ diff --git a/examples/cpp/README.md b/examples/cpp/README.md index fe32b388a579..904d28f0ef89 100644 --- a/examples/cpp/README.md +++ b/examples/cpp/README.md @@ -1,4 +1,4 @@ -# Rerun C++ Examples +# Rerun C++ examples The simplest example is [`minimal`](minimal/main.cpp). You may want to start there using the accompanying [`C++ Quick Start`](https://www.rerun.io/docs/getting-started/cpp) guide. diff --git a/examples/cpp/custom_collection_adapter/README.md b/examples/cpp/custom_collection_adapter/README.md index 4ae9b47faba1..30e6ebeb6bb8 100644 --- a/examples/cpp/custom_collection_adapter/README.md +++ b/examples/cpp/custom_collection_adapter/README.md @@ -1,4 +1,4 @@ -# Custom Collection Adapter +# Custom collection adapter Especially when dealing with large amounts of data, it can be both slow and inconvenient to convert your data into the components & datatypes provided by the Rerun SDK in order to log it. diff --git a/examples/cpp/eigen_opencv/README.md b/examples/cpp/eigen_opencv/README.md index 0f70b8ee41b7..0498388e78d0 100644 --- a/examples/cpp/eigen_opencv/README.md +++ b/examples/cpp/eigen_opencv/README.md @@ -1,5 +1,5 @@ diff --git a/examples/cpp/vrs/README.md b/examples/cpp/vrs/README.md index 82521c276f0a..0dd3bc263672 100644 --- a/examples/cpp/vrs/README.md +++ b/examples/cpp/vrs/README.md @@ -1,5 +1,5 @@ -# Run the Code +# Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash diff --git a/examples/python/blueprint_stocks/README.md b/examples/python/blueprint_stocks/README.md index 7e8ea96d1ff8..bf066149e24e 100644 --- a/examples/python/blueprint_stocks/README.md +++ b/examples/python/blueprint_stocks/README.md @@ -1,5 +1,5 @@ diff --git a/examples/rust/incremental_logging/README.md b/examples/rust/incremental_logging/README.md index 3da523165c7d..025f2975fb47 100644 --- a/examples/rust/incremental_logging/README.md +++ b/examples/rust/incremental_logging/README.md @@ -1,5 +1,5 @@ diff --git a/rerun_cpp/README.md b/rerun_cpp/README.md index 23a9ddff5094..51ad1b8fd961 100644 --- a/rerun_cpp/README.md +++ b/rerun_cpp/README.md @@ -5,7 +5,7 @@ The Rerun C++ SDK allows logging data to Rerun directly from C++. -## Getting Started +## Getting started Read the [getting started guide](https://www.rerun.io/docs/getting-started/cpp) on how to use the Rerun C++ SDK. @@ -44,7 +44,7 @@ All C++ examples can be found [directly in the Rerun repository](https://github. Additionally, each [archetype's documentation](https://www.rerun.io/docs/reference/types) comes with at least one small self-contained code example. -## Building Blocks +## Building blocks The most important type in the SDK is the `rerun::RecordingStream`. It allows you to connect to the Rerun Viewer and send data. @@ -58,7 +58,7 @@ If you include `rerun.hpp`, all archetypes and most component types become part Check the [general doc page on types](https://www.rerun.io/docs/reference/types) to learn more. -## Build & Distribution +## Build & distribution ### Overview diff --git a/rerun_cpp/arrow_cpp_install.md b/rerun_cpp/arrow_cpp_install.md index 40885f009070..bf483342fc34 100644 --- a/rerun_cpp/arrow_cpp_install.md +++ b/rerun_cpp/arrow_cpp_install.md @@ -68,7 +68,7 @@ cd cpp-example-opencv-eigen pixi run example ``` -### Known Issues +### Known issues ⚠️ [#4050](https://github.com/rerun-io/rerun/issues/4050) `arrow-cpp` needs to be held back to 10.0.1 to avoid conflicts with the `rerun-sdk` package when installed in the same pixi environment. diff --git a/rerun_cpp/cmake_setup_in_detail.md b/rerun_cpp/cmake_setup_in_detail.md index 741dd645b3c1..030acaee1ae1 100644 --- a/rerun_cpp/cmake_setup_in_detail.md +++ b/rerun_cpp/cmake_setup_in_detail.md @@ -1,4 +1,4 @@ -# CMake Setup in Detail +# CMake setup in detail \tableofcontents diff --git a/rerun_cpp/docs/writing_docs.md b/rerun_cpp/docs/writing_docs.md index 491112e5766e..0e29331f03dc 100644 --- a/rerun_cpp/docs/writing_docs.md +++ b/rerun_cpp/docs/writing_docs.md @@ -1,4 +1,4 @@ -# C++ Docs +# C++ docs A high-level overview of writing and previewing the Rerun C++ documentation. diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp index 6c9359eeaf21..e871a78f3522 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp @@ -25,7 +25,7 @@ namespace rerun::archetypes { /// /// ## Example /// - /// ### Simple batch of 2D Arrows + /// ### Simple batch of 2D arrows /// ![image](https://static.rerun.io/arrow2d_simple/59f044ccc03f7bc66ee802288f75706618b29a6e/full.png) /// /// ```cpp diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp index fb10dd9ec725..06857fccfc2c 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp @@ -25,7 +25,7 @@ namespace rerun::archetypes { /// /// ## Example /// - /// ### Simple batch of 3D Arrows + /// ### Simple batch of 3D arrows /// ![image](https://static.rerun.io/arrow3d_simple/55e2f794a520bbf7527d7b828b0264732146c5d0/full.png) /// /// ```cpp diff --git a/rerun_cpp/src/rerun/archetypes/pinhole.hpp b/rerun_cpp/src/rerun/archetypes/pinhole.hpp index 5d2eb0c1eab8..a248d1185043 100644 --- a/rerun_cpp/src/rerun/archetypes/pinhole.hpp +++ b/rerun_cpp/src/rerun/archetypes/pinhole.hpp @@ -24,7 +24,7 @@ namespace rerun::archetypes { /// /// ## Examples /// - /// ### Simple Pinhole Camera + /// ### Simple pinhole camera /// ![image](https://static.rerun.io/pinhole_simple/9af9441a94bcd9fd54e1fea44fb0c59ff381a7f2/full.png) /// /// ```cpp @@ -49,7 +49,7 @@ namespace rerun::archetypes { /// } /// ``` /// - /// ### Perspective Pinhole Camera + /// ### Perspective pinhole camera /// ![image](https://static.rerun.io/pinhole_perspective/d0bd02a0cf354a5c8eafb79a84fe8674335cab98/full.png) /// /// ```cpp diff --git a/rerun_cpp/src/rerun/archetypes/series_line.hpp b/rerun_cpp/src/rerun/archetypes/series_line.hpp index 965c6fc9d5c8..5f814a8fed0a 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.hpp @@ -28,7 +28,7 @@ namespace rerun::archetypes { /// /// ## Example /// - /// ### Series Line + /// ### Line series /// ![image](https://static.rerun.io/series_line_style/d2616d98b1e46bdb85849b8669154fdf058e3453/full.png) /// /// ```cpp diff --git a/rerun_cpp/src/rerun/archetypes/series_point.hpp b/rerun_cpp/src/rerun/archetypes/series_point.hpp index 77923a629764..71a9108d532a 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.hpp @@ -29,7 +29,7 @@ namespace rerun::archetypes { /// /// ## Example /// - /// ### Series Point + /// ### Point series /// ![image](https://static.rerun.io/series_point_style/82207a705da6c086b28ce161db1db9e8b12258b7/full.png) /// /// ```cpp diff --git a/rerun_cpp/src/rerun/archetypes/tensor.hpp b/rerun_cpp/src/rerun/archetypes/tensor.hpp index dd39b3933ca4..09d293b7b7db 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor.hpp +++ b/rerun_cpp/src/rerun/archetypes/tensor.hpp @@ -22,7 +22,7 @@ namespace rerun::archetypes { /// /// ## Example /// - /// ### Simple Tensor + /// ### Simple tensor /// ![image](https://static.rerun.io/tensor_simple/baacb07712f7b706e3c80e696f70616c6c20b367/full.png) /// /// ```cpp diff --git a/rerun_js/web-viewer-react/README.md b/rerun_js/web-viewer-react/README.md index 8420a433f4c5..48269d84a909 100644 --- a/rerun_js/web-viewer-react/README.md +++ b/rerun_js/web-viewer-react/README.md @@ -1,4 +1,4 @@ -# Rerun Web Viewer +# Rerun web viewer Embed the Rerun web viewer within your React app. diff --git a/rerun_js/web-viewer/README.md b/rerun_js/web-viewer/README.md index a2aeda47572e..65d058fa1091 100644 --- a/rerun_js/web-viewer/README.md +++ b/rerun_js/web-viewer/README.md @@ -1,4 +1,4 @@ -# Rerun Web Viewer +# Rerun web viewer Embed the Rerun web viewer within your app. diff --git a/rerun_py/ARCHITECTURE.md b/rerun_py/ARCHITECTURE.md index 4d14b5733765..294f36c6e6a7 100644 --- a/rerun_py/ARCHITECTURE.md +++ b/rerun_py/ARCHITECTURE.md @@ -1,4 +1,4 @@ -# Rerun Python SDK Architecture +# Rerun Python SDK architecture ## Background diff --git a/rerun_py/README.md b/rerun_py/README.md index 6d11703500fc..e04ca13cd2c9 100644 --- a/rerun_py/README.md +++ b/rerun_py/README.md @@ -52,7 +52,7 @@ python3 python examples/python/plots/main.py --connect ------------------------- -# From Source +# From source Setup: diff --git a/rerun_py/docs/writing_docs.md b/rerun_py/docs/writing_docs.md index 9329f1b50238..d87e8b11d330 100644 --- a/rerun_py/docs/writing_docs.md +++ b/rerun_py/docs/writing_docs.md @@ -1,4 +1,4 @@ -# Python Docs +# Python docs A high-level overview of writing and previewing the Rerun python documentation. diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py index 2132a9cee4e9..2ccd1df6768a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py @@ -21,7 +21,7 @@ class Arrows2D(Arrows2DExt, Archetype): Example ------- - ### Simple batch of 2D Arrows: + ### Simple batch of 2D arrows: ```python import rerun as rr diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py index a05de68db173..bd59135e9929 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py @@ -21,7 +21,7 @@ class Arrows3D(Arrows3DExt, Archetype): Example ------- - ### Simple batch of 3D Arrows: + ### Simple batch of 3D arrows: ```python from math import tau diff --git a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py index 6107a10c4e18..4ecb12f9b295 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py @@ -21,7 +21,7 @@ class Pinhole(PinholeExt, Archetype): Examples -------- - ### Simple Pinhole Camera: + ### Simple pinhole camera: ```python import numpy as np import rerun as rr @@ -43,7 +43,7 @@ class Pinhole(PinholeExt, Archetype):
- ### Perspective Pinhole Camera: + ### Perspective pinhole camera: ```python import rerun as rr diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py index 43f7f66119de..a85bacfd8a15 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py @@ -29,7 +29,7 @@ class SeriesLine(Archetype): Example ------- - ### Series Line: + ### Line series: ```python from math import cos, sin, tau diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py index bfc95f9581d2..fcec1b2277bc 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py @@ -29,7 +29,7 @@ class SeriesPoint(Archetype): Example ------- - ### Series Point: + ### Point series: ```python from math import cos, sin, tau diff --git a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py index dc11c7376cdc..c7fa4e04dfda 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py @@ -21,7 +21,7 @@ class Tensor(TensorExt, Archetype): Example ------- - ### Simple Tensor: + ### Simple tensor: ```python import numpy as np import rerun as rr diff --git a/scripts/lint.py b/scripts/lint.py index 2603c41a670c..377be1982f17 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -609,6 +609,80 @@ def test_lint_workspace_deps() -> None: pass +# ----------------------------------------------------------------------------- + + +def fix_header_casing(s: str) -> str: + allowed_title_words = [ + "Apache", + "APIs", + "Arrow", + "C", + "C++", + "Colab", + "Google", + "Jupyter", + "Linux", + "Numpy", + "Pixi", + "Python", + "Rerun", + "Rust", + "Wasm", + "Windows", + ] + + def is_acronym_or_pascal_case(s: str) -> bool: + return sum(1 for c in s if c.isupper()) > 1 + + new_words = [] + + for i, word in enumerate(s.strip().split(" ")): + if word == "": + continue + if word.lower() in ("2d", "3d"): + word = word.upper() + elif is_acronym_or_pascal_case(word) or any(c in ("_", "(", ".") for c in word): + pass # acroym, PascalCase, code, … + elif i == 0: + # First word: + word = word.capitalize() + else: + if word not in allowed_title_words: + word = word.lower() + new_words.append(word) + + return " ".join(new_words) + + +def lint_markdown(lines_in: list[str]) -> tuple[list[str], list[str]]: + """Only for .md files.""" + + errors = [] + lines_out = [] + + for line_nr, line in enumerate(lines_in): + line_nr = line_nr + 1 + + # Check the casing on markdown headers + if m := re.match(r"(\#+ )(.*)", line): + new_header = fix_header_casing(m.group(2)) + if new_header != m.group(2): + errors.append(f"{line_nr}: Markdown headers should NOT be title cased. This should be '{new_header}'.") + line = m.group(1) + new_header + "\n" + + # Check the casing on `title = "…"` frontmatter + if m := re.match(r'title\s*\=\s*"(.*)"', line): + new_title = fix_header_casing(m.group(1)) + if new_title != m.group(1): + errors.append(f"{line_nr}: Titles should NOT be title cased. This should be '{new_title}'.") + line = f'title = "{new_title}"\n' + + lines_out.append(line) + + return errors, lines_out + + # ----------------------------------------------------------------------------- # We may not use egui's widgets for which we have a custom version in re_ui. @@ -790,6 +864,18 @@ def lint_file(filepath: str, args: Any) -> int: if args.fix: source.rewrite(lines_out) + if filepath.endswith(".md") and args.extra: + errors, lines_out = lint_markdown(source.lines) + + for error in errors: + print(source.error(error)) + num_errors += len(errors) + + if args.fix: + source.rewrite(lines_out) + elif 0 < num_errors: + print(f"Run with --fix to automatically fix {num_errors} errors.") + if filepath.startswith("./examples/rust") and filepath.endswith("Cargo.toml"): errors, lines_out = lint_workspace_deps(source.lines) @@ -868,6 +954,12 @@ def main() -> None: action="store_true", help="Automatically fix some problems.", ) + parser.add_argument( + "--extra", + dest="extra", + action="store_true", + help="Run some extra checks.", + ) args = parser.parse_args() From f5dcf0528ebd8bcf303bdcb94da73caa9ea15b0d Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:53:59 +0200 Subject: [PATCH 190/508] Add `tfrecord_loader` external example (#5790) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What - Part of #5666 Also added a linkinator exception as apparently tensorflow.org blocks CI 🤷🏻 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5790) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5790?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5790?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5790) - [Docs preview](https://rerun.io/preview/72ffd3e4937cfa0e6b4ae7ce488eecbaf2a253ca/docs) - [Examples preview](https://rerun.io/preview/72ffd3e4937cfa0e6b4ae7ce488eecbaf2a253ca/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/documentation.yaml | 3 +- docs/cspell.json | 2 + examples/manifest.toml | 2 + examples/python/tfrecord_loader/README.md | 49 +++++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 examples/python/tfrecord_loader/README.md diff --git a/.github/workflows/documentation.yaml b/.github/workflows/documentation.yaml index 1257c67eebad..587c5db6ac09 100644 --- a/.github/workflows/documentation.yaml +++ b/.github/workflows/documentation.yaml @@ -40,9 +40,10 @@ jobs: # * Stackoverflow links are no longer accessible from CI. # * Tuxfamily.org links are down intermittently. # * Nyud links are down every now and then. + # * tensorflow.org apparently blocks CI. # * TODO(#4085): https://rerun-io.github.io/rerun/dev/bench/ often 404:s for unknown reasons # * TODO(#4556): remove the `static.rerun.io` and `github.com` skips - linksToSkip: "https://stackoverflow.com/.*, https://eigen.tuxfamily.org/, https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html, https://static.rerun.io/.*, https://github.com/.*, https://crates.io/crates/.*, https://github.com/rerun-io/rerun/pull/.*, .*?speculative-link, https://rerun-io.github.io/rerun/dev/bench/" + linksToSkip: "https://stackoverflow.com/.*, https://eigen.tuxfamily.org/, https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html, https://static.rerun.io/.*, https://github.com/.*, https://crates.io/crates/.*, https://github.com/rerun-io/rerun/pull/.*, .*?speculative-link, https://rerun-io.github.io/rerun/dev/bench/, https://www.tensorflow.org/" retry: true retryErrors: true retryErrorsCount: 5 diff --git a/docs/cspell.json b/docs/cspell.json index e8af69834881..2509d98df768 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -362,11 +362,13 @@ "subsampled", "superquadrics", "tableofcontents", + "tensorboard", "taplo", "Tete", "Tewari", "Texcoord", "texcoords", + "tfevents", "thiserror", "Tian", "timedelta", diff --git a/examples/manifest.toml b/examples/manifest.toml index a6bf420c62ca..273c57f1a079 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -57,6 +57,7 @@ examples = [ "mcc", "shape_pointe", "llm_embedding_ner", + "tfrecord_loader", ] [categories.video-image] @@ -104,6 +105,7 @@ examples = [ "ros_bridge", "urdf_loader", "vrs", + "tfrecord_loader", "eigen_opencv", "dicom_mri", "blueprint_stocks", diff --git a/examples/python/tfrecord_loader/README.md b/examples/python/tfrecord_loader/README.md new file mode 100644 index 000000000000..cdc2b291e9b6 --- /dev/null +++ b/examples/python/tfrecord_loader/README.md @@ -0,0 +1,49 @@ + + + + + + + + + + + +## Overview + +This is an example data-loader plugin that lets you view a TFRecord of Events (i.e., Tensorboard log files). It uses the [external data loader mechanism](https://www.rerun.io/docs/howto/open-any-file#external-dataloaders) to add this capability to the Rerun viewer without modifying the viewer itself. + +This example is written in Python, and uses [TensorFlow](https://www.tensorflow.org/) to read the files. The events are then logged to Rerun. + +**Note**: Not all events are supported yet. Scalars, images, text, and tensors should work. Unsupported events are skipped. + + +## Installing the plug-in + +The [repository](https://github.com/rerun-io/rerun-loader-python-example-tfrecord) has detailed installation instruction. In a nutshell, the easiest is to use `pipx`: + +``` +pipx install git+https://github.com/rerun-io/rerun-loader-python-example-tfrecord.git +pipx ensurepath +``` + + +## Try it out + +To try the plug-in, first download an example `xxx.tfevents.xxx` file: + +```bash +curl -OL https://github.com/rerun-io/rerun-loader-python-example-tfrecord/raw/main/events.tfevents.example +``` + +Then you can open the viewer and open the file using drag-and-drop or the open dialog, or you can open it directly from the terminal: + +```bash +rerun events.tfevents.example +``` From ac9f767e8fad96d33df68ce73171d4ddc8cdc89c Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 4 Apr 2024 23:17:46 +0200 Subject: [PATCH 191/508] Fix draw order not working (#5794) ### What Draw order was not doing anything on 0.14! The underlying issue was that the depth offset context system which converts draw order to depth offsets didn't iterate any entities since it used a iterator for entities. This means we're now iterating a much larger entity set. I checked with the "many entities" manual test and the context system takes about 0.5ms for me in release there. This is kinda bad but it's not a big dent here (unfortunately) and it runs in parallel to the much slower transform context system. This PR moves the (also broken due to heuristic changes) test from "api_test" to a release check with a description what should be observable. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5794) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5794?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5794?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5794) - [Docs preview](https://rerun.io/preview/a10a84ef97637dd05c615ac65b63b6711edeba44/docs) - [Examples preview](https://rerun.io/preview/a10a84ef97637dd05c615ac65b63b6711edeba44/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Jeremy Leibs --- .../src/contexts/depth_offsets.rs | 8 +- .../src/contexts/transform_context.rs | 2 +- .../src/space_view/view_query.rs | 12 +-- crates/re_viewport/src/system_execution.rs | 6 +- .../release_checklist/check_draw_order.py | 94 +++++++++++++++++++ tests/python/test_api/main.py | 45 --------- tests/rust/test_api/src/main.rs | 80 ---------------- 7 files changed, 111 insertions(+), 136 deletions(-) create mode 100644 tests/python/release_checklist/check_draw_order.py diff --git a/crates/re_space_view_spatial/src/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/contexts/depth_offsets.rs index 1ed969e30649..806bd83827a6 100644 --- a/crates/re_space_view_spatial/src/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/contexts/depth_offsets.rs @@ -48,7 +48,13 @@ impl ViewContextSystem for EntityDepthOffsets { // Use a BTreeSet for entity hashes to get a stable order. let mut entities_per_draw_order = BTreeMap::>::new(); - for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { + for data_result in query.iter_all_data_results() { + // Note that we can't use `query.iter_visible_data_results` here since `EntityDepthOffsets` isn't a visualizer + // and thus not in the list of per system data results. + if !data_result.is_visible(ctx) { + continue; + } + if let Some(draw_order) = store .query_latest_component::(&data_result.entity_path, &ctx.current_query()) { diff --git a/crates/re_space_view_spatial/src/contexts/transform_context.rs b/crates/re_space_view_spatial/src/contexts/transform_context.rs index 1bdc7fcb053d..26c725e57cbb 100644 --- a/crates/re_space_view_spatial/src/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/contexts/transform_context.rs @@ -98,7 +98,7 @@ impl ViewContextSystem for TransformContext { // Build an entity_property_map for just the CamerasParts, where we would expect to find // the image_depth_plane_distance property. let entity_prop_map: EntityPropertyMap = query - .per_system_data_results + .per_visualizer_data_results .get(&CamerasVisualizer::identifier()) .map(|results| { results diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 635ed9d69f62..ea32f49572fd 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -401,10 +401,10 @@ pub struct ViewQuery<'s> { /// The root of the space in which context the query happens. pub space_origin: &'s EntityPath, - /// All queried [`DataResult`]s. + /// All [`DataResult`]s that are queried by active visualizers. /// - /// Contains also invisible objects, use `iter_entities` to iterate over visible ones. - pub per_system_data_results: PerSystemDataResults<'s>, + /// Contains also invisible objects, use `iter_visible_data_results` to iterate over visible ones. + pub per_visualizer_data_results: PerSystemDataResults<'s>, /// The timeline we're on. pub timeline: Timeline, @@ -423,12 +423,12 @@ impl<'s> ViewQuery<'s> { pub fn iter_visible_data_results<'a>( &'a self, ctx: &'a ViewerContext<'a>, - system: ViewSystemIdentifier, + visualizer: ViewSystemIdentifier, ) -> impl Iterator where 's: 'a, { - self.per_system_data_results.get(&system).map_or( + self.per_visualizer_data_results.get(&visualizer).map_or( itertools::Either::Left(std::iter::empty()), |results| { itertools::Either::Right( @@ -443,7 +443,7 @@ impl<'s> ViewQuery<'s> { /// Iterates over all [`DataResult`]s of the [`ViewQuery`]. pub fn iter_all_data_results(&self) -> impl Iterator + '_ { - self.per_system_data_results + self.per_visualizer_data_results .values() .flat_map(|data_results| data_results.iter().copied()) } diff --git a/crates/re_viewport/src/system_execution.rs b/crates/re_viewport/src/system_execution.rs index fb534d7668cc..155be6fec181 100644 --- a/crates/re_viewport/src/system_execution.rs +++ b/crates/re_viewport/src/system_execution.rs @@ -104,13 +104,13 @@ pub fn execute_systems_for_space_view<'a>( let query_result = ctx.lookup_query_result(space_view.id); - let mut per_system_data_results = PerSystemDataResults::default(); + let mut per_visualizer_data_results = PerSystemDataResults::default(); { re_tracing::profile_scope!("per_system_data_results"); query_result.tree.visit(&mut |node| { for system in &node.data_result.visualizers { - per_system_data_results + per_visualizer_data_results .entry(*system) .or_default() .push(&node.data_result); @@ -122,7 +122,7 @@ pub fn execute_systems_for_space_view<'a>( let query = re_viewer_context::ViewQuery { space_view_id: space_view.id, space_origin: &space_view.space_origin, - per_system_data_results, + per_visualizer_data_results, timeline: *ctx.rec_cfg.time_ctrl.read().timeline(), latest_at, highlights, diff --git a/tests/python/release_checklist/check_draw_order.py b/tests/python/release_checklist/check_draw_order.py new file mode 100644 index 000000000000..0404ccb5cd97 --- /dev/null +++ b/tests/python/release_checklist/check_draw_order.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import numpy as np +import rerun as rr +import rerun.blueprint as rrb + +README = """ +# 2D Draw order + +This checks whether the draw order correctly determines the layering of 2D content. + +### Action +You should see a single 2D space view with the following features: +- Gray background image +- On top of the background a green/red gradient image +- On top of that a blue (slightly transparent) blue square +- On top of the blue square a white square. *Nothing* is overlapping the white square! +- Between the gradient and the blue square rectangle (Box2D) +- Lines *behind* the rectangle +- Regular raster of points *in front* of the rectangle (unbroken by the rectangle) +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def run_2d_layering() -> None: + rr.set_time_seconds("sim_time", 1) + + # Large gray background. + img = np.full((512, 512), 64, dtype="uint8") + rr.log("2d_layering/background", rr.Image(img, draw_order=0.0)) + + # Smaller gradient in the middle. + img = np.zeros((256, 256, 3), dtype="uint8") + img[:, :, 0] = np.linspace(0, 255, 256, dtype="uint8") + img[:, :, 1] = np.linspace(0, 255, 256, dtype="uint8") + img[:, :, 1] = img[:, :, 1].transpose() + rr.log("2d_layering/middle_gradient", rr.Image(img, draw_order=1.0)) + + # Slightly smaller blue in the middle, on the same layer as the previous. + img = np.full((192, 192, 3), (0, 0, 255), dtype="uint8") + rr.log("2d_layering/middle_blue", rr.Image(img, draw_order=1.0)) + + # Small white on top. + img = np.full((128, 128), 255, dtype="uint8") + rr.log("2d_layering/top", rr.Image(img, draw_order=2.0)) + + # Rectangle in between the top and the middle. + rr.log( + "2d_layering/rect_between_top_and_middle", + rr.Boxes2D(array=[64, 64, 256, 256], draw_order=1.5, array_format=rr.Box2DFormat.XYWH), + ) + + # Lines behind the rectangle. + rr.log( + "2d_layering/lines_behind_rect", + rr.LineStrips2D([(i * 20, i % 2 * 100 + 100) for i in range(20)], draw_order=1.25), + ) + + # And some points in front of the rectangle. + rr.log( + "2d_layering/points_between_top_and_middle", + rr.Points2D( + [(32.0 + int(i / 16) * 16.0, 64.0 + (i % 16) * 16.0) for i in range(16 * 16)], + draw_order=1.51, + ), + ) + + +def run(args: Namespace) -> None: + rr.script_setup( + args, + f"{os.path.basename(__file__)}", + recording_id=uuid4(), + default_blueprint=rrb.Grid(rrb.Spatial2DView(origin="/"), rrb.TextDocumentView(origin="readme")), + ) + + log_readme() + run_2d_layering() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) diff --git a/tests/python/test_api/main.py b/tests/python/test_api/main.py index 3145cb7adfa9..a73b9eb28e0a 100755 --- a/tests/python/test_api/main.py +++ b/tests/python/test_api/main.py @@ -97,50 +97,6 @@ def small_image() -> None: rr.log("small_image", rr.Image(img)) -def run_2d_layering() -> None: - rr.set_time_seconds("sim_time", 1) - - # Large gray background. - img = np.full((512, 512), 64, dtype="uint8") - rr.log("2d_layering/background", rr.Image(img, draw_order=0.0)) - - # Smaller gradient in the middle. - img = np.zeros((256, 256, 3), dtype="uint8") - img[:, :, 0] = np.linspace(0, 255, 256, dtype="uint8") - img[:, :, 1] = np.linspace(0, 255, 256, dtype="uint8") - img[:, :, 1] = img[:, :, 1].transpose() - rr.log("2d_layering/middle_gradient", rr.Image(img, draw_order=1.0)) - - # Slightly smaller blue in the middle, on the same layer as the previous. - img = np.full((192, 192, 3), (0, 0, 255), dtype="uint8") - rr.log("2d_layering/middle_blue", rr.Image(img, draw_order=1.0)) - - # Small white on top. - img = np.full((128, 128), 255, dtype="uint8") - rr.log("2d_layering/top", rr.Image(img, draw_order=2.0)) - - # Rectangle in between the top and the middle. - rr.log( - "2d_layering/rect_between_top_and_middle", - rr.Boxes2D(array=[64, 64, 256, 256], draw_order=1.5, array_format=rr.Box2DFormat.XYWH), - ) - - # Lines behind the rectangle. - rr.log( - "2d_layering/lines_behind_rect", - rr.LineStrips2D([(i * 20, i % 2 * 100 + 100) for i in range(20)], draw_order=1.25), - ) - - # And some points in front of the rectangle. - rr.log( - "2d_layering/points_between_top_and_middle", - rr.Points2D( - [(32.0 + int(i / 16) * 16.0, 64.0 + (i % 16) * 16.0) for i in range(16 * 16)], - draw_order=1.51, - ), - ) - - def transforms() -> None: rr.log("transforms", rr.ViewCoordinates.RIGHT_HAND_Y_UP, timeless=True) @@ -474,7 +430,6 @@ def spawn_test(test: Callable[[], None], rec: rr.RecordingStream) -> None: def main() -> None: tests = { - "2d_layering": run_2d_layering, "2d_lines": run_2d_lines, "3d_points": run_3d_points, "bbox": run_bounding_box, diff --git a/tests/rust/test_api/src/main.rs b/tests/rust/test_api/src/main.rs index 625b7a5ba78b..cad476a96669 100644 --- a/tests/rust/test_api/src/main.rs +++ b/tests/rust/test_api/src/main.rs @@ -200,82 +200,6 @@ fn test_rects(rec: &RecordingStream) -> anyhow::Result<()> { Ok(()) } -fn colored_tensor [u8; 3]>( - width: usize, - height: usize, - pos_to_color: F, -) -> ndarray::Array3 { - let pos_to_color = &pos_to_color; // lambda borrow workaround. - ndarray::Array3::from_shape_vec( - (height, width, 3), - (0..height) - .flat_map(|y| (0..width).flat_map(move |x| pos_to_color(x, y))) - .collect_vec(), - ) - .unwrap() -} - -fn test_2d_layering(rec: &RecordingStream) -> anyhow::Result<()> { - use ndarray::prelude::*; - - use rerun::archetypes::{Boxes2D, Image, LineStrips2D, Points2D}; - - rec.set_time_seconds("sim_time", 1f64); - - // Add several overlapping images. - // Large dark gray in the background - let img = Array::::from_elem((512, 512, 1).f(), 64) - .as_standard_layout() - .view() - .to_owned(); - rec.log( - "2d_layering/background", - &Image::try_from(img)?.with_draw_order(0.0), - )?; - // Smaller gradient in the middle - let img = colored_tensor(256, 256, |x, y| [x as u8, y as u8, 0]); - rec.log( - "2d_layering/middle_gradient", - &Image::try_from(img)?.with_draw_order(1.0), - )?; - // Slightly smaller blue in the middle, on the same layer as the previous. - let img = colored_tensor(192, 192, |_, _| [0, 0, 255]); - rec.log( - "2d_layering/middle_blue", - &Image::try_from(img)?.with_draw_order(1.0), - )?; - // Small white on top. - let img = Array::::from_elem((128, 128, 1).f(), 255); - rec.log( - "2d_layering/top", - &Image::try_from(img)?.with_draw_order(2.0), - )?; - - // Rectangle in between the top and the middle. - rec.log( - "2d_layering/rect_between_top_and_middle", - &Boxes2D::from_mins_and_sizes([(64.0, 64.0)], [(256.0, 256.0)]).with_draw_order(1.5), - )?; - - // Lines behind the rectangle. - rec.log( - "2d_layering/lines_behind_rect", - &LineStrips2D::new([(0..20).map(|i| ((i * 20) as f32, (i % 2 * 100 + 100) as f32))]) - .with_draw_order(1.25), - )?; - - // And some points in front of the rectangle. - rec.log( - "2d_layering/points_between_top_and_middle", - &Points2D::new( - (0..256).map(|i| (32.0 + (i / 16) as f32 * 16.0, 64.0 + (i % 16) as f32 * 16.0)), - ) - .with_draw_order(1.51), - )?; - - Ok(()) -} - fn test_segmentation(rec: &RecordingStream) -> anyhow::Result<()> { use rerun::{ archetypes::{AnnotationContext, Points2D}, @@ -539,9 +463,6 @@ enum Demo { #[value(name("rects"))] Rects, - #[value(name("2d_ordering"))] - TwoDOrdering, - #[value(name("segmentation"))] Segmentation, @@ -576,7 +497,6 @@ fn run(rec: &RecordingStream, args: &Args) -> anyhow::Result<()> { Demo::LogCleared => test_log_cleared(rec)?, Demo::Points3D => test_3d_points(rec)?, Demo::Rects => test_rects(rec)?, - Demo::TwoDOrdering => test_2d_layering(rec)?, Demo::Segmentation => test_segmentation(rec)?, Demo::TextLogs => test_text_logs(rec)?, Demo::Transforms3D => test_transforms_3d(rec)?, From 39af075dad7c4961ec172887f639a6c9adfd3730 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 5 Apr 2024 06:58:19 +0200 Subject: [PATCH 192/508] Add buttons to reset the blueprint in the app selection panel (#5795) ### What Screenshot 2024-04-04 at 19 03 21 It's better having them than not having them. * Closes https://github.com/rerun-io/rerun/issues/5781 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5795) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5795?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5795?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5795) - [Docs preview](https://rerun.io/preview/4e18583a50594353b17859bd795da4b1bb3a9df2/docs) - [Examples preview](https://rerun.io/preview/4e18583a50594353b17859bd795da4b1bb3a9df2/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Jeremy Leibs --- crates/re_data_ui/src/app_id.rs | 49 ++++++++++++++++++- crates/re_data_ui/src/entity_db.rs | 5 +- crates/re_ui/src/icons.rs | 6 ++- crates/re_viewer/src/ui/recordings_panel.rs | 5 ++ crates/re_viewer/src/ui/top_panel.rs | 3 +- .../src/ui/welcome_screen/example_section.rs | 4 +- crates/re_viewer_context/src/store_hub.rs | 41 +++++++++++++--- 7 files changed, 96 insertions(+), 17 deletions(-) diff --git a/crates/re_data_ui/src/app_id.rs b/crates/re_data_ui/src/app_id.rs index 47330d44ee7f..50c55d0336f6 100644 --- a/crates/re_data_ui/src/app_id.rs +++ b/crates/re_data_ui/src/app_id.rs @@ -2,7 +2,7 @@ use itertools::Itertools as _; use re_entity_db::EntityDb; use re_log_types::ApplicationId; -use re_viewer_context::{UiVerbosity, ViewerContext}; +use re_viewer_context::{SystemCommandSender as _, UiVerbosity, ViewerContext}; use crate::item_ui::entity_db_button_ui; @@ -30,6 +30,8 @@ impl crate::DataUi for ApplicationId { return; } + // --------------------------------------------------------------------- + // Find all recordings with this app id let recordings: Vec<&EntityDb> = ctx .store_context @@ -51,5 +53,50 @@ impl crate::DataUi for ApplicationId { } }); } + + // --------------------------------------------------------------------- + + ui.add_space(8.0); + + // --------------------------------------------------------------------- + + // Blueprint section. + let active_blueprint = ctx.store_context.blueprint; + let default_blueprint = ctx.store_context.hub.default_blueprint_for_app(self); + + let button = egui::Button::image_and_text( + re_ui::icons::RESET.as_image(), + "Reset to default blueprint", + ); + + let is_same_as_default = default_blueprint.map_or(false, |default_blueprint| { + default_blueprint.latest_row_id() == active_blueprint.latest_row_id() + }); + + if is_same_as_default { + ui.add_enabled(false, button) + .on_disabled_hover_text("No modifications has been made"); + } else if default_blueprint.is_none() { + ui.add_enabled(false, button) + .on_disabled_hover_text("There's no default blueprint"); + } else { + // The active blueprint is different from the default blueprint + if ui + .add(button) + .on_hover_text("Reset to the default blueprint for this app") + .clicked() + { + ctx.command_sender + .send_system(re_viewer_context::SystemCommand::ClearActiveBlueprint); + } + } + + if ui.add(egui::Button::image_and_text( + re_ui::icons::RESET.as_image(), + "Reset to heuristic blueprint", + )).on_hover_text("Clear both active and default blueprint, and auto-generate a new blueprint based on heuristics").clicked() { + ctx.command_sender + .send_system(re_viewer_context::SystemCommand::ClearAndGenerateBlueprint); + } } } diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index 7afdf6ed5e51..4faa5b61b30d 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -120,9 +120,8 @@ impl crate::DataUi for EntityDb { ui.add_space(8.0); ui.label("This is the default blueprint for the current application."); - if let Some(active_blueprint) = hub - .active_blueprint_id_for_app(active_app_id) - .and_then(|id| hub.store_bundle().get(id)) + if let Some(active_blueprint) = + hub.active_blueprint_for_app(active_app_id) { if active_blueprint.cloned_from() == Some(self.store_id()) { // The active blueprint is a clone of the selected blueprint. diff --git a/crates/re_ui/src/icons.rs b/crates/re_ui/src/icons.rs index 3cbe39ec496f..bf434de7f3a4 100644 --- a/crates/re_ui/src/icons.rs +++ b/crates/re_ui/src/icons.rs @@ -9,10 +9,12 @@ pub struct Icon { } impl Icon { + #[inline] pub const fn new(id: &'static str, png_bytes: &'static [u8]) -> Self { Self { id, png_bytes } } + #[inline] pub fn as_image(&self) -> Image<'static> { Image::new(ImageSource::Bytes { uri: self.id.into(), @@ -68,8 +70,8 @@ pub const CLOSE: Icon = Icon::new("close", include_bytes!("../data/icons/close.p /// Used for HTTP URLs that leads out of the app. /// -/// Remember to also use `.on_hover_cursor(egui::CursorIcon::PointingHand)` -/// and `.on_hover_text(url)`. +/// Remember to also use `.on_hover_cursor(egui::CursorIcon::PointingHand)`, +/// but don't add `.on_hover_text(url)`. pub const EXTERNAL_LINK: Icon = Icon::new( "external_link", include_bytes!("../data/icons/external_link.png"), diff --git a/crates/re_viewer/src/ui/recordings_panel.rs b/crates/re_viewer/src/ui/recordings_panel.rs index 66756c407a58..880863647912 100644 --- a/crates/re_viewer/src/ui/recordings_panel.rs +++ b/crates/re_viewer/src/ui/recordings_panel.rs @@ -93,6 +93,11 @@ fn loading_receivers_ui(ctx: &ViewerContext<'_>, rx: &ReceiveSet, ui: &m fn recording_list_ui(ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { let mut entity_dbs_map: BTreeMap> = BTreeMap::new(); + // Always have a place for the welcome screen, even if there is no recordings or blueprints associated with it: + entity_dbs_map + .entry(StoreHub::welcome_screen_app_id()) + .or_default(); + for entity_db in ctx.store_context.bundle.entity_dbs() { // We want to show all open applications, even if they have no recordings let Some(app_id) = entity_db.app_id().cloned() else { diff --git a/crates/re_viewer/src/ui/top_panel.rs b/crates/re_viewer/src/ui/top_panel.rs index 160120e04448..5f69ffae2ed1 100644 --- a/crates/re_viewer/src/ui/top_panel.rs +++ b/crates/re_viewer/src/ui/top_panel.rs @@ -289,8 +289,7 @@ fn website_link_ui(ui: &mut egui::Ui) { let url = "https://rerun.io/"; let response = ui .add(egui::ImageButton::new(image)) - .on_hover_cursor(egui::CursorIcon::PointingHand) - .on_hover_text(url); + .on_hover_cursor(egui::CursorIcon::PointingHand); if response.clicked() { ui.ctx().open_url(egui::output::OpenUrl { url: url.to_owned(), diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index 1b305d7e2cf6..52ab28610480 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -581,9 +581,7 @@ impl ExampleDescLayout { for tag in &self.desc.tags { ui.add( egui::Button::new( - egui::RichText::new(tag) - .text_style(re_ui::ReUi::welcome_screen_tag()) - .strong(), + egui::RichText::new(tag).text_style(re_ui::ReUi::welcome_screen_tag()), ) .sense(egui::Sense::hover()) .rounding(6.0) diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 763f07dbf57f..b55f516674c7 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -83,6 +83,14 @@ impl StoreHub { "Welcome screen".into() } + /// Blueprint ID used for the default welcome screen blueprint + fn welcome_screen_blueprint_id() -> StoreId { + StoreId::from_string( + StoreKind::Blueprint, + Self::welcome_screen_app_id().to_string(), + ) + } + /// Used only for tests pub fn test_hub() -> Self { Self::new( @@ -107,16 +115,13 @@ impl StoreHub { let mut active_blueprint_by_app_id = HashMap::new(); let mut store_bundle = StoreBundle::default(); - let welcome_screen_store_id = StoreId::from_string( - StoreKind::Blueprint, - Self::welcome_screen_app_id().to_string(), - ); active_blueprint_by_app_id.insert( Self::welcome_screen_app_id(), - welcome_screen_store_id.clone(), + Self::welcome_screen_blueprint_id(), ); - let welcome_screen_blueprint = store_bundle.blueprint_entry(&welcome_screen_store_id); + let welcome_screen_blueprint = + store_bundle.blueprint_entry(&Self::welcome_screen_blueprint_id()); (setup_welcome_screen_blueprint)(welcome_screen_blueprint); Self { @@ -369,6 +374,11 @@ impl StoreHub { self.default_blueprint_by_app_id.get(app_id) } + pub fn default_blueprint_for_app(&self, app_id: &ApplicationId) -> Option<&EntityDb> { + self.default_blueprint_id_for_app(app_id) + .and_then(|id| self.store_bundle.get(id)) + } + /// Change which blueprint is the default for a given [`ApplicationId`] #[inline] pub fn set_default_blueprint_for_app( @@ -401,6 +411,11 @@ impl StoreHub { self.active_blueprint_by_app_id.get(app_id) } + pub fn active_blueprint_for_app(&self, app_id: &ApplicationId) -> Option<&EntityDb> { + self.active_blueprint_id_for_app(app_id) + .and_then(|id| self.store_bundle.get(id)) + } + /// Make blueprint active for a given [`ApplicationId`] /// /// We never activate a blueprint directly. Instead, we clone it and activate the clone. @@ -458,8 +473,22 @@ impl StoreHub { .drain() .chain(self.default_blueprint_by_app_id.drain()) { + if let Some(entity_db) = self.store_bundle.get(&blueprint_id) { + if entity_db.cloned_from().is_none() + && entity_db.app_id() == Some(&Self::welcome_screen_app_id()) + { + // Don't remove the welcome screen blueprint + continue; + } + } + self.store_bundle.remove(&blueprint_id); } + + self.active_blueprint_by_app_id.insert( + Self::welcome_screen_app_id(), + Self::welcome_screen_blueprint_id(), + ); } /// Remove any empty [`EntityDb`]s from the hub From 95b373c5600cc875ab8c28b0678dd8885e684d5e Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 5 Apr 2024 08:34:45 +0200 Subject: [PATCH 193/508] Always show welcome screen, but fade it in some situations (#5787) ### What * Closes https://github.com/rerun-io/rerun/issues/4317 It used to be that `rerun --web-viewer` didn't show the welcome screen, which is super annoying when testing. It also feels very brittle to sometimes show it, and sometimes not, and to keep track if we've ever seen a recording, etc. It also feel inconsistent with how the welcome screen is now just another app in the recordings panel. So the new design is much simpler. We always show the welcome screen, but if we expect data to come streaming in at any moment, we delay the welcome screen for a a fraction of a second and then fade it in. This prevents the problem of a flashing welcome screen before showing actual user data. This fade-in was proposed during the initial design of the welcome screen, but we never got to it. This replaces `--skip-welcome-screen` with `--fade-in-welcome-screen`. You can test it with `pixi run rerun ----fade-in-welcome-screen` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5787) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5787?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5787?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5787) - [Docs preview](https://rerun.io/preview/e24d4fd0a23d862697fb1dce865adbd6d1c872b5/docs) - [Examples preview](https://rerun.io/preview/e24d4fd0a23d862697fb1dce865adbd6d1c872b5/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Jeremy Leibs --- crates/re_sdk/src/spawn.rs | 2 +- crates/re_smart_channel/src/lib.rs | 1 + crates/re_viewer/src/app.rs | 115 ++++++++++-------- crates/re_viewer/src/app_state.rs | 3 +- crates/re_viewer/src/ui/welcome_screen/mod.rs | 14 ++- crates/re_viewer/src/web.rs | 2 +- crates/re_viewer_context/src/store_hub.rs | 15 --- crates/rerun/src/run.rs | 16 ++- rerun_py/rerun_sdk/rerun/sinks.py | 2 +- 9 files changed, 99 insertions(+), 71 deletions(-) diff --git a/crates/re_sdk/src/spawn.rs b/crates/re_sdk/src/spawn.rs index e462791630c6..384753fcc0e1 100644 --- a/crates/re_sdk/src/spawn.rs +++ b/crates/re_sdk/src/spawn.rs @@ -246,7 +246,7 @@ pub fn spawn(opts: &SpawnOptions) -> Result<(), SpawnError> { .stdin(std::process::Stdio::null()) .arg(format!("--port={port}")) .arg(format!("--memory-limit={memory_limit}")) - .arg("--skip-welcome-screen") + .arg("--expect-data-soon") .args(opts.extra_args.clone()) .spawn() .map_err(map_err)?; diff --git a/crates/re_smart_channel/src/lib.rs b/crates/re_smart_channel/src/lib.rs index 2998d5f561f5..105369329496 100644 --- a/crates/re_smart_channel/src/lib.rs +++ b/crates/re_smart_channel/src/lib.rs @@ -31,6 +31,7 @@ pub enum SmartChannelSource { /// js event. /// /// Only applicable to web browser iframes. + /// Used for the inline web viewer in a notebook. RrdWebEventListener, /// The channel was created in the context of loading data using a Rerun SDK sharing the same diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index a306786b2509..47d7503dc4b0 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -1,6 +1,6 @@ use re_data_source::{DataSource, FileContents}; use re_entity_db::entity_db::EntityDb; -use re_log_types::{FileSource, LogMsg, StoreKind}; +use re_log_types::{ApplicationId, FileSource, LogMsg, StoreKind}; use re_renderer::WgpuResourcePoolStatistics; use re_smart_channel::{ReceiveSet, SmartChannelSource}; use re_ui::{toasts, UICommand, UICommandSender}; @@ -51,7 +51,14 @@ pub struct StartupOptions { #[cfg(not(target_arch = "wasm32"))] pub resolution_in_points: Option<[f32; 2]>, - pub skip_welcome_screen: bool, + /// This is a hint that we expect a recording to stream in very soon. + /// + /// This is set by the `spawn()` method in our logging SDK. + /// + /// The viewer will respond by fading in the welcome screen, + /// instead of showing it directly. + /// This ensures that it won't blink for a few frames before switching to the recording. + pub expect_data_soon: Option, /// Forces wgpu backend to use the specified graphics API. pub force_wgpu_backend: Option, @@ -73,7 +80,7 @@ impl Default for StartupOptions { #[cfg(not(target_arch = "wasm32"))] resolution_in_points: None, - skip_welcome_screen: false, + expect_data_soon: None, force_wgpu_backend: None, } } @@ -90,6 +97,7 @@ const MAX_ZOOM_FACTOR: f32 = 5.0; pub struct App { build_info: re_build_info::BuildInfo, startup_options: StartupOptions, + start_time: web_time::Instant, ram_limit_warner: re_memory::RamLimitWarner, pub(crate) re_ui: re_ui::ReUi, screenshotter: crate::screenshotter::Screenshotter, @@ -217,6 +225,7 @@ impl App { Self { build_info, startup_options, + start_time: web_time::Instant::now(), ram_limit_warner: re_memory::RamLimitWarner::warn_at_fraction_of_max(0.75), re_ui, screenshotter, @@ -906,6 +915,7 @@ impl App { &self.space_view_class_registry, &self.rx, &self.command_sender, + self.welcome_screen_opacity(egui_ctx), ); } render_ctx.before_submit(); @@ -1166,60 +1176,60 @@ impl App { } } - /// This function implements a heuristic which determines when the welcome screen - /// should show up. - /// - /// Why not always show it when no data is loaded? - /// Because sometimes we expect data to arrive at any moment, - /// and showing the wlecome screen for a few frames will just be an annoying flash - /// in the users face. - fn should_show_welcome_screen(&mut self, store_hub: &StoreHub) -> bool { - // Don't show the welcome screen if we have actual data to display. - if store_hub.active_recording().is_some() || store_hub.active_app().is_some() { - return false; - } - - // Don't show the welcome screen if the `--skip-welcome-screen` flag was used (e.g. by the - // Python SDK), until some data has been loaded and shown. This way, we *still* show the - // welcome screen when the user closes all recordings after, e.g., running a Python example. - if self.startup_options.skip_welcome_screen && !store_hub.was_recording_active() { - return false; + fn should_fade_in_welcome_screen(&self) -> bool { + if let Some(expect_data_soon) = self.startup_options.expect_data_soon { + return expect_data_soon; } - let sources = self.rx.sources(); - - if sources.is_empty() { - return true; - } + // The reason for the fade-in is to avoid the welcome screen + // flickering quickly before receiving some data. + // So: if we expect data very soon, we do a fade-in. - // Here, we use the type of Receiver as a proxy for which kind of workflow the viewer is - // being used in. - for source in sources { + for source in self.rx.sources() { + #[allow(clippy::match_same_arms)] match &*source { - // No need for a welcome screen - data is coming soon! SmartChannelSource::File(_) | SmartChannelSource::RrdHttpStream { .. } - | SmartChannelSource::Stdin => { - return false; - } - - // The workflows associated with these sources typically do not require showing the - // welcome screen until after some recording have been loaded and then closed. - SmartChannelSource::RrdWebEventListener + | SmartChannelSource::Stdin + | SmartChannelSource::RrdWebEventListener | SmartChannelSource::Sdk - | SmartChannelSource::WsClient { .. } => {} + | SmartChannelSource::WsClient { .. } => { + return true; // We expect data soon, so fade-in + } - // This might be the trickiest case. When running the bare executable, we want to show - // the welcome screen (default, "new user" workflow). There are other case using Tcp - // where it's not the case, including Python/C++ SDKs and possibly other, advanced used, - // scenarios. In this cases, `--skip-welcome-screen` should be used. SmartChannelSource::TcpServer { .. } => { - return true; + // We start a TCP server by default in native rerun, i.e. when just running `rerun`, + // and in that case fading in the welcome screen would be slightly annoying. + // However, we also use the TCP server for sending data from the logging SDKs + // when they call `spawn()`, and in that case we really want to fade in the welcome screen. + // Therefore `spawn()` uses the special `--expect-data-soon` flag + // (handled earlier in this function), so here we know we are in the other case: + // a user calling `rerun` in their terminal (don't fade in). } } } - false + false // No special sources (or no sources at all), so don't fade in + } + + /// Handle fading in the welcome screen, if we should. + fn welcome_screen_opacity(&self, egui_ctx: &egui::Context) -> f32 { + if self.should_fade_in_welcome_screen() { + // The reason for this delay is to avoid the welcome screen + // flickering quickly before receiving some data. + // The only time it has for that is between the call to `spawn` and sending the recording info, + // which should happen _right away_, so we only need a small delay. + // Why not skip the wlecome screen completely when we expect the data? + // Because maybe the data never comes. + let sec_since_first_shown = self.start_time.elapsed().as_secs_f32(); + let opacity = egui::remap_clamp(sec_since_first_shown, 0.4..=0.6, 0.0..=1.0); + if opacity < 1.0 { + egui_ctx.request_repaint(); + } + opacity + } else { + 1.0 + } } } @@ -1235,7 +1245,6 @@ fn blueprint_loader() -> BlueprintPersistence { #[cfg(not(target_arch = "wasm32"))] fn blueprint_loader() -> BlueprintPersistence { use re_entity_db::StoreBundle; - use re_log_types::ApplicationId; fn load_blueprint_from_disk(app_id: &ApplicationId) -> anyhow::Result> { let blueprint_path = crate::saving::default_blueprint_path(app_id)?; @@ -1415,10 +1424,20 @@ impl eframe::App for App { file_saver_progress_ui(egui_ctx, &mut self.background_tasks); // toasts for background file saver - // Heuristic to set the app_id to the welcome screen blueprint. + // Make sure some app is active // Must be called before `read_context` below. - if self.should_show_welcome_screen(&store_hub) { - store_hub.set_active_app(StoreHub::welcome_screen_app_id()); + if store_hub.active_app().is_none() { + let apps: std::collections::BTreeSet<&ApplicationId> = store_hub + .store_bundle() + .entity_dbs() + .filter_map(|db| db.app_id()) + .filter(|&app_id| app_id != &StoreHub::welcome_screen_app_id()) + .collect(); + if let Some(app_id) = apps.first().cloned() { + store_hub.set_active_app(app_id.clone()); + } else { + store_hub.set_active_app(StoreHub::welcome_screen_app_id()); + } } let store_context = store_hub.read_context(); diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 838572292206..3898c891b12e 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -114,6 +114,7 @@ impl AppState { space_view_class_registry: &SpaceViewClassRegistry, rx: &ReceiveSet, command_sender: &CommandSender, + welcome_screen_opacity: f32, ) { re_tracing::profile_function!(); @@ -379,7 +380,7 @@ impl AppState { .frame(viewport_frame) .show_inside(ui, |ui| { if show_welcome { - welcome_screen.ui(ui, re_ui, command_sender); + welcome_screen.ui(ui, re_ui, command_sender, welcome_screen_opacity); } else { viewport.viewport_ui(ui, &ctx); } diff --git a/crates/re_viewer/src/ui/welcome_screen/mod.rs b/crates/re_viewer/src/ui/welcome_screen/mod.rs index d4e86a9a8c24..19acc93c85b8 100644 --- a/crates/re_viewer/src/ui/welcome_screen/mod.rs +++ b/crates/re_viewer/src/ui/welcome_screen/mod.rs @@ -20,14 +20,19 @@ impl WelcomeScreen { ui: &mut egui::Ui, re_ui: &re_ui::ReUi, command_sender: &re_viewer_context::CommandSender, + welcome_screen_opacity: f32, ) { + if welcome_screen_opacity <= 0.0 { + return; + } + // This is needed otherwise `example_page_ui` bleeds by a few pixels over the timeline panel // TODO(ab): figure out why that happens ui.set_clip_rect(ui.available_rect_before_wrap()); let horizontal_scroll = ui.available_width() < 40.0 * 2.0 + MIN_COLUMN_WIDTH; - egui::ScrollArea::new([horizontal_scroll, true]) + let response = egui::ScrollArea::new([horizontal_scroll, true]) .id_source("welcome_screen_page") .auto_shrink([false, false]) .show(ui, |ui| { @@ -45,5 +50,12 @@ impl WelcomeScreen { .ui(ui, re_ui, command_sender, &welcome_section_ui); }); }); + + if welcome_screen_opacity < 1.0 { + let cover_opacity = 1.0 - welcome_screen_opacity; + let fill_color = ui.visuals().panel_fill.gamma_multiply(cover_opacity); + ui.painter() + .rect_filled(response.inner_rect, 0.0, fill_color); + } } } diff --git a/crates/re_viewer/src/web.rs b/crates/re_viewer/src/web.rs index 85614f686c2a..08d8d1e9d1c4 100644 --- a/crates/re_viewer/src/web.rs +++ b/crates/re_viewer/src/web.rs @@ -126,7 +126,7 @@ fn create_app( location: Some(cc.integration_info.web_info.location.clone()), persist_state: get_persist_state(&cc.integration_info), is_in_notebook: is_in_notebook(&cc.integration_info), - skip_welcome_screen: false, + expect_data_soon: None, force_wgpu_backend: None, }; let re_ui = crate::customize_eframe(cc); diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index b55f516674c7..fad2c209be02 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -42,9 +42,6 @@ pub struct StoreHub { active_blueprint_by_app_id: HashMap, store_bundle: StoreBundle, - /// Was a recording ever activated? Used by the heuristic controlling the welcome screen. - was_recording_active: bool, - /// The [`StoreGeneration`] from when the [`EntityDb`] was last saved blueprint_last_save: HashMap, @@ -133,8 +130,6 @@ impl StoreHub { active_blueprint_by_app_id, store_bundle, - was_recording_active: false, - blueprint_last_save: Default::default(), blueprint_last_gc: Default::default(), } @@ -287,7 +282,6 @@ impl StoreHub { { if rec.app_id() == Some(&app_id) { self.active_rec_id = Some(rec.store_id().clone()); - self.was_recording_active = true; return; } } @@ -314,14 +308,6 @@ impl StoreHub { // --------------------- // Active recording - /// Keeps track if a recording was ever activated. - /// - /// This is useful for the heuristic controlling the welcome screen. - #[inline] - pub fn was_recording_active(&self) -> bool { - self.was_recording_active - } - /// Directly access the [`EntityDb`] for the active recording. #[inline] pub fn active_recording_id(&self) -> Option<&StoreId> { @@ -354,7 +340,6 @@ impl StoreHub { } self.active_rec_id = Some(recording_id); - self.was_recording_active = true; } /// Activate a recording by its [`StoreId`]. diff --git a/crates/rerun/src/run.rs b/crates/rerun/src/run.rs index 956eeaba8b99..9eb1004e21f1 100644 --- a/crates/rerun/src/run.rs +++ b/crates/rerun/src/run.rs @@ -140,9 +140,15 @@ When persisted, the state will be stored at the following locations: #[clap(long)] serve: bool, - /// Do not display the welcome screen. + /// This is a hint that we expect a recording to stream in very soon. + /// + /// This is set by the `spawn()` method in our logging SDK. + /// + /// The viewer will respond by fading in the welcome screen, + /// instead of showing it directly. + /// This ensures that it won't blink for a few frames before switching to the recording. #[clap(long)] - skip_welcome_screen: bool, + expect_data_soon: bool, /// The number of compute threads to use. /// @@ -614,7 +620,11 @@ async fn run_impl( is_in_notebook: false, screenshot_to_path_then_quit: args.screenshot_to.clone(), - skip_welcome_screen: args.skip_welcome_screen, + expect_data_soon: if args.expect_data_soon { + Some(true) + } else { + None + }, // TODO(emilk): make it easy to set this on eframe instead resolution_in_points: if let Some(size) = &args.window_size { diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index 89a99f4fa7f4..55edd03f51e9 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -392,7 +392,7 @@ def spawn( "import rerun_bindings; rerun_bindings.main()", f"--port={port}", f"--memory-limit={memory_limit}", - "--skip-welcome-screen", + "--expect-data-soon", ], env=new_env, start_new_session=True, From 06a476a95116bbedb809e8b106d1b0bd04a9822a Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 5 Apr 2024 10:05:41 +0200 Subject: [PATCH 194/508] Fix syntax highlight in entity-queries.md (#5801) Annoying typo breaks rendering. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5801) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5801?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5801?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5801) - [Docs preview](https://rerun.io/preview/e0fb2953291bded90f9aa294b92fdd0ad60986f5/docs) - [Examples preview](https://rerun.io/preview/e0fb2953291bded90f9aa294b92fdd0ad60986f5/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/content/reference/entity-queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/reference/entity-queries.md b/docs/content/reference/entity-queries.md index 9f9300144321..c25bdee875db 100644 --- a/docs/content/reference/entity-queries.md +++ b/docs/content/reference/entity-queries.md @@ -74,7 +74,7 @@ rrb.Spatial3DView( ), ``` -## 'origin` substitution +## `origin` substitution Query expressions also allow you to use the variable `$origin` to refer to the origin of the space-view that the query belongs to. From 695e195ad83d847655f84dbb221175558405b5d1 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:20:40 +0200 Subject: [PATCH 195/508] Change all example tags to "Human case" (#5802) ### What - Closes #5783 @jprochazk is there some tag formatting code on landing that you could remove? ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5802) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5802?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5802?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5802) - [Docs preview](https://rerun.io/preview/34e4cbca92fdcf792bea86f63ffd10e742f1706b/docs) - [Examples preview](https://rerun.io/preview/34e4cbca92fdcf792bea86f63ffd10e742f1706b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/c/spawn_viewer/README.md | 2 +- examples/cpp/dna/README.md | 2 +- examples/cpp/incremental_logging/README.md | 2 +- examples/cpp/kiss-icp/README.md | 2 +- examples/cpp/ros_bridge/README.md | 2 +- examples/cpp/spawn_viewer/README.md | 2 +- examples/cpp/vrs/README.md | 2 +- examples/python/arflow/README.md | 2 +- examples/python/arkit_scenes/README.md | 2 +- examples/python/blueprint_stocks/README.md | 2 +- examples/python/controlnet/README.md | 2 +- examples/python/depth_guided_stable_diffusion/README.md | 2 +- examples/python/detect_and_track_objects/README.md | 2 +- examples/python/dicom_mri/README.md | 2 +- examples/python/differentiable_blocks_world/README.md | 2 +- examples/python/dna/README.md | 2 +- examples/python/face_tracking/README.md | 2 +- examples/python/gesture_detection/README.md | 2 +- examples/python/human_pose_tracking/README.md | 2 +- examples/python/incremental_logging/README.md | 2 +- examples/python/kiss-icp/README.md | 2 +- examples/python/lidar/README.md | 2 +- examples/python/limap/README.md | 2 +- examples/python/live_camera_edge_detection/README.md | 2 +- examples/python/live_depth_sensor/README.md | 2 +- examples/python/llm_embedding_ner/README.md | 2 +- examples/python/mcc/README.md | 2 +- examples/python/nuscenes/README.md | 2 +- examples/python/nv12/README.md | 2 +- examples/python/objectron/README.md | 2 +- examples/python/open_photogrammetry_format/README.md | 2 +- examples/python/plots/README.md | 2 +- examples/python/raw_mesh/README.md | 2 +- examples/python/rgbd/README.md | 2 +- examples/python/ros_node/README.md | 2 +- examples/python/segment_anything_model/README.md | 2 +- examples/python/shape_pointe/README.md | 2 +- examples/python/signed_distance_fields/README.md | 2 +- examples/python/simplerecon/README.md | 2 +- examples/python/slahmr/README.md | 2 +- examples/python/structure_from_motion/README.md | 2 +- examples/python/tapir/README.md | 2 +- examples/python/template/README.md | 4 ++-- examples/python/tfrecord_loader/README.md | 2 +- examples/python/urdf_loader/README.md | 2 +- examples/python/widebaseline/README.md | 2 +- examples/rust/custom_store_subscriber/README.md | 2 +- examples/rust/dna/README.md | 2 +- examples/rust/incremental_logging/README.md | 2 +- examples/rust/objectron/README.md | 2 +- examples/rust/spawn_viewer/README.md | 2 +- examples/rust/template/README.md | 2 +- 52 files changed, 53 insertions(+), 53 deletions(-) diff --git a/examples/c/spawn_viewer/README.md b/examples/c/spawn_viewer/README.md index 5b9c879a97d9..348e018aee11 100644 --- a/examples/c/spawn_viewer/README.md +++ b/examples/c/spawn_viewer/README.md @@ -1,6 +1,6 @@ diff --git a/examples/cpp/dna/README.md b/examples/cpp/dna/README.md index 6796bcfe5944..0919fea73036 100644 --- a/examples/cpp/dna/README.md +++ b/examples/cpp/dna/README.md @@ -1,6 +1,6 @@ diff --git a/examples/cpp/spawn_viewer/README.md b/examples/cpp/spawn_viewer/README.md index 40f0c0dcc0a9..585ee37133a7 100644 --- a/examples/cpp/spawn_viewer/README.md +++ b/examples/cpp/spawn_viewer/README.md @@ -1,6 +1,6 @@ diff --git a/examples/cpp/vrs/README.md b/examples/cpp/vrs/README.md index 0dd3bc263672..8485252e8353 100644 --- a/examples/cpp/vrs/README.md +++ b/examples/cpp/vrs/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/arflow/README.md b/examples/python/arflow/README.md index df54473f23b1..c9a0cc0935af 100644 --- a/examples/python/arflow/README.md +++ b/examples/python/arflow/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/arkit_scenes/README.md b/examples/python/arkit_scenes/README.md index 2d68f040d6a2..3d2ecbbdcfb7 100644 --- a/examples/python/arkit_scenes/README.md +++ b/examples/python/arkit_scenes/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/controlnet/README.md b/examples/python/controlnet/README.md index 7e1c206bbcde..29710a24ab0c 100644 --- a/examples/python/controlnet/README.md +++ b/examples/python/controlnet/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/dna/README.md b/examples/python/dna/README.md index ea2fcba75c1a..4d0b0ead556a 100644 --- a/examples/python/dna/README.md +++ b/examples/python/dna/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/live_camera_edge_detection/README.md b/examples/python/live_camera_edge_detection/README.md index 95303e0ea930..b197b9c6adca 100644 --- a/examples/python/live_camera_edge_detection/README.md +++ b/examples/python/live_camera_edge_detection/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/nuscenes/README.md b/examples/python/nuscenes/README.md index 5c796edfc462..8c5fc77b0ee5 100644 --- a/examples/python/nuscenes/README.md +++ b/examples/python/nuscenes/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/objectron/README.md b/examples/python/objectron/README.md index 2771cd5220fb..36d3dcec6ed2 100644 --- a/examples/python/objectron/README.md +++ b/examples/python/objectron/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/segment_anything_model/README.md b/examples/python/segment_anything_model/README.md index 3f2629960d80..f4d9a24d0445 100644 --- a/examples/python/segment_anything_model/README.md +++ b/examples/python/segment_anything_model/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/signed_distance_fields/README.md b/examples/python/signed_distance_fields/README.md index e7be6fc96774..b58e942f7529 100644 --- a/examples/python/signed_distance_fields/README.md +++ b/examples/python/signed_distance_fields/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/simplerecon/README.md b/examples/python/simplerecon/README.md index 715b78e0ade6..599cb0f15cf3 100644 --- a/examples/python/simplerecon/README.md +++ b/examples/python/simplerecon/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/slahmr/README.md b/examples/python/slahmr/README.md index 0dfc4b77d2b6..d566f2f311b2 100644 --- a/examples/python/slahmr/README.md +++ b/examples/python/slahmr/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/structure_from_motion/README.md b/examples/python/structure_from_motion/README.md index b288af6c0338..09c3ca223b70 100644 --- a/examples/python/structure_from_motion/README.md +++ b/examples/python/structure_from_motion/README.md @@ -1,6 +1,6 @@ diff --git a/examples/python/template/README.md b/examples/python/template/README.md index 8e48e80801c3..391f11a6e133 100644 --- a/examples/python/template/README.md +++ b/examples/python/template/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/tfrecord_loader/README.md b/examples/python/tfrecord_loader/README.md index cdc2b291e9b6..169c781afd25 100644 --- a/examples/python/tfrecord_loader/README.md +++ b/examples/python/tfrecord_loader/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/urdf_loader/README.md b/examples/python/urdf_loader/README.md index 055b386d652b..75a0cd011de8 100644 --- a/examples/python/urdf_loader/README.md +++ b/examples/python/urdf_loader/README.md @@ -1,7 +1,7 @@ diff --git a/examples/python/widebaseline/README.md b/examples/python/widebaseline/README.md index 1c4a8960579a..1fc66b11676c 100644 --- a/examples/python/widebaseline/README.md +++ b/examples/python/widebaseline/README.md @@ -1,7 +1,7 @@ diff --git a/examples/rust/custom_store_subscriber/README.md b/examples/rust/custom_store_subscriber/README.md index 337543e0dbb3..64f48f7fc690 100644 --- a/examples/rust/custom_store_subscriber/README.md +++ b/examples/rust/custom_store_subscriber/README.md @@ -1,6 +1,6 @@ diff --git a/examples/rust/dna/README.md b/examples/rust/dna/README.md index f9ea1ab4b7e5..3d25f72f56a0 100644 --- a/examples/rust/dna/README.md +++ b/examples/rust/dna/README.md @@ -1,6 +1,6 @@ diff --git a/examples/rust/template/README.md b/examples/rust/template/README.md index 9c73e6678250..790ee89e7342 100644 --- a/examples/rust/template/README.md +++ b/examples/rust/template/README.md @@ -1,6 +1,6 @@ From f3cc5381cf0e05b1edb9fa7b2124b744f8842ec3 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Fri, 5 Apr 2024 10:48:23 +0200 Subject: [PATCH 196/508] Add missing thumbnail to NV12 example (#5804) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What ☝🏻 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) - [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/nv12/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/python/nv12/README.md b/examples/python/nv12/README.md index 734fe458e173..049409941dfd 100644 --- a/examples/python/nv12/README.md +++ b/examples/python/nv12/README.md @@ -2,6 +2,8 @@ title = "NV12" tags = ["2D", "Image encoding", "YUV"] description = "Visualize an NV12 encoded video stream from a webcam." +thumbnail = "https://static.rerun.io/nv12/3bffd358462a453c6358aa3cc4c8555b12fc0d35/480w.png" +thumbnail_dimensions = [480, 480] --> From b5853316f2a274e41090b794a2b860c8eb64702b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 5 Apr 2024 11:29:18 +0200 Subject: [PATCH 197/508] When hitting the "Reset Viewer" button, only clear cloned blueprints (#5798) ### What * Closes https://github.com/rerun-io/rerun/issues/5788 This PR ensures that the blueprint sent with the recording, or drag-dropped into the viewer, is kept when the user hits the "Reset Viewer" button/command. What it actually does: * Drops al cloned blueprints (usually the active ones) * Resets the egui state * Removes all stores state from disk (all stored blueprints etc) What remains is any recordings and "real" blueprints currently loaded. I also fixed a bunch of the book keeping in the StoreHub ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5798) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5798?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5798?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5798) - [Docs preview](https://rerun.io/preview/eede7f5844e81dd84f64f7eb77c61a69004fe1b4/docs) - [Examples preview](https://rerun.io/preview/eede7f5844e81dd84f64f7eb77c61a69004fe1b4/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_entity_db/src/store_bundle.rs | 4 - crates/re_viewer/src/app.rs | 6 +- crates/re_viewer_context/src/store_hub.rs | 161 +++++++++++++--------- 3 files changed, 100 insertions(+), 71 deletions(-) diff --git a/crates/re_entity_db/src/store_bundle.rs b/crates/re_entity_db/src/store_bundle.rs index 79280822ae9b..e1583074f486 100644 --- a/crates/re_entity_db/src/store_bundle.rs +++ b/crates/re_entity_db/src/store_bundle.rs @@ -140,10 +140,6 @@ impl StoreBundle { self.entity_dbs.retain(|_, db| f(db)); } - pub fn purge_empty(&mut self) { - self.entity_dbs.retain(|_, entity_db| !entity_db.is_empty()); - } - /// In no particular order. pub fn drain_entity_dbs(&mut self) -> impl Iterator + '_ { self.entity_dbs.drain().map(|(_, store)| store) diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 47d7503dc4b0..0de606aebbde 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -412,7 +412,7 @@ impl App { } } - SystemCommand::ResetViewer => self.reset(store_hub, egui_ctx), + SystemCommand::ResetViewer => self.reset_viewer(store_hub, egui_ctx), SystemCommand::ClearAndGenerateBlueprint => { re_log::debug!("Clear and generate new blueprint"); // By clearing the default blueprint and the active blueprint @@ -1125,10 +1125,10 @@ impl App { } /// Reset the viewer to how it looked the first time you ran it. - fn reset(&mut self, store_hub: &mut StoreHub, egui_ctx: &egui::Context) { + fn reset_viewer(&mut self, store_hub: &mut StoreHub, egui_ctx: &egui::Context) { self.state = Default::default(); - store_hub.clear_all_blueprints(); + store_hub.clear_all_cloned_blueprints(); // Reset egui, but keep the style: let style = egui_ctx.style(); diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index fad2c209be02..496e0bb07bb4 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -109,10 +109,10 @@ impl StoreHub { setup_welcome_screen_blueprint: &dyn Fn(&mut EntityDb), ) -> Self { re_tracing::profile_function!(); - let mut active_blueprint_by_app_id = HashMap::new(); + let mut default_blueprint_by_app_id = HashMap::new(); let mut store_bundle = StoreBundle::default(); - active_blueprint_by_app_id.insert( + default_blueprint_by_app_id.insert( Self::welcome_screen_app_id(), Self::welcome_screen_blueprint_id(), ); @@ -126,8 +126,8 @@ impl StoreHub { active_rec_id: None, active_application_id: None, - default_blueprint_by_app_id: Default::default(), - active_blueprint_by_app_id, + default_blueprint_by_app_id, + active_blueprint_by_app_id: Default::default(), store_bundle, blueprint_last_save: Default::default(), @@ -155,6 +155,19 @@ impl StoreHub { // If we have an app-id, then use it to look up the blueprint. let app_id = self.active_application_id.clone()?; + // Defensive coding: Check that default and active blueprints exists, + // in case some of our book-keeping is broken. + if let Some(blueprint_id) = self.default_blueprint_by_app_id.get(&app_id) { + if !self.store_bundle.contains(blueprint_id) { + self.default_blueprint_by_app_id.remove(&app_id); + } + } + if let Some(blueprint_id) = self.active_blueprint_by_app_id.get(&app_id) { + if !self.store_bundle.contains(blueprint_id) { + self.active_blueprint_by_app_id.remove(&app_id); + } + } + // If there's no active blueprint for this app, try to make the current default one active. if !self.active_blueprint_by_app_id.contains_key(&app_id) { if let Some(blueprint_id) = self.default_blueprint_by_app_id.get(&app_id).cloned() { @@ -166,14 +179,14 @@ impl StoreHub { } // Get the id is of whatever blueprint is now active, falling back on the "app blueprint" if needed. - let blueprint_id = self + let active_blueprint_id = self .active_blueprint_by_app_id .entry(app_id.clone()) .or_insert_with(|| StoreId::from_string(StoreKind::Blueprint, app_id.clone().0)); // Get or create the blueprint: - self.store_bundle.blueprint_entry(blueprint_id); - let blueprint = self.store_bundle.get(blueprint_id)?; + self.store_bundle.blueprint_entry(active_blueprint_id); + let blueprint = self.store_bundle.get(active_blueprint_id)?; let recording = self .active_rec_id @@ -216,18 +229,26 @@ impl StoreHub { return; }; - if removed_store.store_kind() == StoreKind::Recording { - if let Some(app_id) = removed_store.app_id().cloned() { - let any_other_recordings_for_this_app = self - .store_bundle - .recordings() - .any(|rec| rec.app_id() == Some(&app_id)); - - if !any_other_recordings_for_this_app { - re_log::trace!("Removed last recording of {app_id}. Closing app."); - self.close_app(&app_id); + match removed_store.store_kind() { + StoreKind::Recording => { + if let Some(app_id) = removed_store.app_id().cloned() { + let any_other_recordings_for_this_app = self + .store_bundle + .recordings() + .any(|rec| rec.app_id() == Some(&app_id)); + + if !any_other_recordings_for_this_app { + re_log::trace!("Removed last recording of {app_id}. Closing app."); + self.close_app(&app_id); + } } } + StoreKind::Blueprint => { + self.active_blueprint_by_app_id + .retain(|_, id| id != store_id); + self.default_blueprint_by_app_id + .retain(|_, id| id != store_id); + } } if self.active_rec_id.as_ref() == Some(store_id) { @@ -240,8 +261,21 @@ impl StoreHub { } } - pub fn retain(&mut self, f: impl FnMut(&EntityDb) -> bool) { - self.store_bundle.retain(f); + pub fn retain(&mut self, mut should_retain: impl FnMut(&EntityDb) -> bool) { + let stores_to_remove: Vec = self + .store_bundle + .entity_dbs() + .filter_map(|store| { + if should_retain(store) { + None + } else { + Some(store.store_id().clone()) + } + }) + .collect(); + for store in stores_to_remove { + self.remove(&store); + } } /// Remove all open recordings and applications, and go to the welcome page. @@ -379,7 +413,9 @@ impl StoreHub { /// Clear the current default blueprint pub fn clear_default_blueprint(&mut self) { if let Some(app_id) = &self.active_application_id { - self.default_blueprint_by_app_id.remove(app_id); + if let Some(blueprint_id) = self.default_blueprint_by_app_id.remove(app_id) { + self.remove(&blueprint_id); + } } } @@ -443,7 +479,7 @@ impl StoreHub { if let Some(app_id) = &self.active_application_id { if let Some(blueprint_id) = self.active_blueprint_by_app_id.remove(app_id) { re_log::debug!("Clearing blueprint for {app_id}: {blueprint_id}"); - self.store_bundle.remove(&blueprint_id); + self.remove(&blueprint_id); } } } @@ -451,34 +487,18 @@ impl StoreHub { // --------------------- // Misc operations - /// Forgets all blueprints - pub fn clear_all_blueprints(&mut self) { - for (_app_id, blueprint_id) in self - .active_blueprint_by_app_id - .drain() - .chain(self.default_blueprint_by_app_id.drain()) - { - if let Some(entity_db) = self.store_bundle.get(&blueprint_id) { - if entity_db.cloned_from().is_none() - && entity_db.app_id() == Some(&Self::welcome_screen_app_id()) - { - // Don't remove the welcome screen blueprint - continue; - } - } - - self.store_bundle.remove(&blueprint_id); - } - - self.active_blueprint_by_app_id.insert( - Self::welcome_screen_app_id(), - Self::welcome_screen_blueprint_id(), - ); + /// Cloned blueprints are the ones the user has edited, + /// i.e. NOT sent from the SDK. + pub fn clear_all_cloned_blueprints(&mut self) { + self.retain(|db| match db.store_kind() { + StoreKind::Recording => true, + StoreKind::Blueprint => db.cloned_from().is_none(), + }); } /// Remove any empty [`EntityDb`]s from the hub pub fn purge_empty(&mut self) { - self.store_bundle.purge_empty(); + self.retain(|entity_db| !entity_db.is_empty()); } /// Call [`EntityDb::purge_fraction_of_ram`] on every recording @@ -537,7 +557,7 @@ impl StoreHub { /// Remove any recordings with a network source pointing at this `uri`. pub fn remove_recording_by_uri(&mut self, uri: &str) { - self.store_bundle.retain(|db| { + self.retain(|db| { let Some(data_source) = &db.data_source else { // no data source, keep return true; @@ -608,7 +628,9 @@ impl StoreHub { .insert(blueprint_id.clone(), blueprint.generation()); } - if let Some(saver) = &self.persistence.saver { + if blueprint.app_id() == Some(&Self::welcome_screen_app_id()) { + // Don't save changes to the welcome screen + } else if let Some(saver) = &self.persistence.saver { (saver)(app_id, blueprint)?; self.blueprint_last_save .insert(blueprint_id.clone(), blueprint.generation()); @@ -630,24 +652,35 @@ impl StoreHub { if let Some(mut bundle) = (loader)(app_id)? { for store in bundle.drain_entity_dbs() { - if store.store_kind() == StoreKind::Blueprint && store.app_id() == Some(app_id) { - // We found the blueprint we were looking for; make it active. - // borrow-checker won't let us just call `self.set_blueprint_for_app_id` - re_log::debug!( - "Activating new blueprint {} for {app_id}; loaded from disk", - store.store_id(), - ); - self.active_blueprint_by_app_id - .insert(app_id.clone(), store.store_id().clone()); - self.blueprint_last_save - .insert(store.store_id().clone(), store.generation()); - self.store_bundle.insert(store); - } else { - anyhow::bail!( - "Found unexpected store while loading blueprint: {:?}", - store.store_id() - ); + match store.store_kind() { + StoreKind::Recording => { + anyhow::bail!( + "Found a recording in a blueprint file: {:?}", + store.store_id() + ); + } + StoreKind::Blueprint => {} + } + + if store.app_id() != Some(app_id) { + if let Some(store_app_id) = store.app_id() { + anyhow::bail!("Found app_id {store_app_id}; expected {app_id}"); + } else { + anyhow::bail!("Found store without an app_id"); + } } + + // We found the blueprint we were looking for; make it active. + // borrow-checker won't let us just call `self.set_blueprint_for_app_id` + re_log::debug!( + "Activating new blueprint {} for {app_id}; loaded from disk", + store.store_id(), + ); + self.active_blueprint_by_app_id + .insert(app_id.clone(), store.store_id().clone()); + self.blueprint_last_save + .insert(store.store_id().clone(), store.generation()); + self.store_bundle.insert(store); } } From 914cd41bf335b25c5d70181e98cf6abadc0c35a2 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 5 Apr 2024 11:36:04 +0200 Subject: [PATCH 198/508] Rename ML category to "Diffusion models, LLMs, and Machine Learning" (#5800) --- examples/manifest.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/manifest.toml b/examples/manifest.toml index 273c57f1a079..71873f34f63a 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -46,9 +46,9 @@ examples = [ [categories.generative-vision] order = 3 -title = "Generative computer vision and LLMs" +title = "Diffusion models, LLMs, and machine learning" prelude = """ -Examples using generative AI methods like diffusion and LLMs. +Examples using machine learning and generative AI methods such as diffusion and LLMs. """ examples = [ # display order, most interesting first From 971b63c2609ef7d7d549fc1f924dc16fea3cfb9c Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 5 Apr 2024 08:20:23 -0400 Subject: [PATCH 199/508] Remove TODOs from save-load blueprint doc (#5797) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5797) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5797?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5797?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5797) - [Docs preview](https://rerun.io/preview/c03d4d6e3cf4ece61808c1acb31c0e4add21516b/docs) - [Examples preview](https://rerun.io/preview/c03d4d6e3cf4ece61808c1acb31c0e4add21516b/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../configure-the-viewer/save-and-load.md | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/content/getting-started/configure-the-viewer/save-and-load.md b/docs/content/getting-started/configure-the-viewer/save-and-load.md index 015800aa8c53..8f57af96fff0 100644 --- a/docs/content/getting-started/configure-the-viewer/save-and-load.md +++ b/docs/content/getting-started/configure-the-viewer/save-and-load.md @@ -3,22 +3,23 @@ title: Save and load viewer configuration files order: 2 --- -If you have made changes to your blueprint and you would like to save or share these changes, +If you have made changes to the viewer and you would like to save or share them, you can do so by saving your blueprint to an `.rbl` file. ## Saving a blueprint -To save your blueprint, go to the file-menu and choose "Save blueprint…" -TODO(#5636): save +To save the currently active blueprint, go to the file-menu and choose "Save blueprint…" -## Loading a blueprint - -Once you have saved a blueprint, you can load it again. + + + -When loading a blueprint, it must match the "application_id" used by the recording. +## Loading a blueprint -To load a blueprint, go to the file-menu and choose "Open…" and select the `.rbl` file you would like to load. -TODO(#5636): open_1 +Once you have saved a blueprint, you can later load it in the viewer. The +"Open…" menu item is used to load either recordings (`.rrd`) or blueprints +(`.rbl`). Alternatively, you can drag an `.rbl` file directly into the viewer. -You can also drag and drop an `.rbl` file directly into the viewer -TODO(#5636): open_2 +Note that the application ID of the blueprint must match the application ID of +the recording you wish to use it with. It is not currently possible to change +the application ID of a blueprint to use it with a different type of recording. From c749fd725b312c343be589fd13e512120a9deb22 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:52:00 +0200 Subject: [PATCH 200/508] ARKit example: blueprint info in REAME + minor formatting fixes (#5807) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What ☝🏻 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5807) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5807?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5807?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5807) - [Docs preview](https://rerun.io/preview/2f09ed1272374281393bf04495d84e12322876cf/docs) - [Examples preview](https://rerun.io/preview/2f09ed1272374281393bf04495d84e12322876cf/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/cspell.json | 2 ++ examples/python/arkit_scenes/README.md | 43 +++++++++++++++++++++++--- examples/python/arkit_scenes/main.py | 19 ++++++------ 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/docs/cspell.json b/docs/cspell.json index 2509d98df768..a2e0288db9dc 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -155,6 +155,7 @@ "Hawksbill", "Heewoo", "hickups", + "highres", "HOTMOBILE", "howto", "hstack", @@ -310,6 +311,7 @@ "renamings", "repr", "reproj", + "reproject", "reqwest", "RGBA", "rgbd", diff --git a/examples/python/arkit_scenes/README.md b/examples/python/arkit_scenes/README.md index 3d2ecbbdcfb7..f640d1a2d68d 100644 --- a/examples/python/arkit_scenes/README.md +++ b/examples/python/arkit_scenes/README.md @@ -1,6 +1,6 @@ -# Run the code +### Setting up the default blueprint + +This example benefits at lot from having a custom blueprint defined. This happens with the following code: + +```python +primary_camera_entity = HIGHRES_ENTITY_PATH if args.include_highres else LOWRES_POSED_ENTITY_PATH + +blueprint = rrb.Horizontal( + rrb.Spatial3DView(name="3D"), + rrb.Vertical( + rrb.Tabs( + rrb.Spatial2DView( + name="RGB", + origin=primary_camera_entity, + contents=["$origin/rgb", "/world/annotations/**"], + ), + rrb.Spatial2DView( + name="Depth", + origin=primary_camera_entity, + contents=["$origin/depth", "/world/annotations/**"], + ), + name="2D", + ), + rrb.TextDocumentView(name="Readme"), + ), +) + +rr.script_setup(args, "rerun_example_arkit_scenes", default_blueprint=blueprint) +``` + +In particular, we want to reproject 3D annotations onto the 2D camera views. To configure such a view, two things are necessary: +- The view origin must be set to the entity that contains the pinhole transforms. In this example, the entity path is stored in the `primary_camera_entity` variable. +- The view contents must explicitly include the annotations, which are not logged in the subtree defined by the origin. This is done using the `contents` argument, here set to `["$origin/depth", "/world/annotations/**"]`. + + +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py index f6c3ffcb56d0..ff0cbbda27a9 100755 --- a/examples/python/arkit_scenes/main.py +++ b/examples/python/arkit_scenes/main.py @@ -30,7 +30,6 @@ assert len(ORIENTATION) == len(AVAILABLE_RECORDINGS) assert set(ORIENTATION.keys()) == set(AVAILABLE_RECORDINGS) - DESCRIPTION = """ # ARKit Scenes This example visualizes the [ARKitScenes dataset](https://github.com/apple/ARKitScenes/) using Rerun. The dataset @@ -83,8 +82,8 @@ bounding box is logged as a separate entity to the common [world/annotations](recording://world/annotations) parent. """.strip() -lowres_posed_entity_path = "world/camera_lowres" -highres_entity_path = "world/camera_highres" +LOWRES_POSED_ENTITY_PATH = "world/camera_lowres" +HIGHRES_ENTITY_PATH = "world/camera_highres" def load_json(js_path: Path) -> dict[str, Any]: @@ -282,11 +281,11 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: lowres_intri_path, frame_timestamp, camera_from_world_dict, - lowres_posed_entity_path, + LOWRES_POSED_ENTITY_PATH, ) - rr.log(f"{lowres_posed_entity_path}/rgb", rr.Image(rgb).compress(jpeg_quality=95)) - rr.log(f"{lowres_posed_entity_path}/depth", rr.DepthImage(depth, meter=1000)) + rr.log(f"{LOWRES_POSED_ENTITY_PATH}/rgb", rr.Image(rgb).compress(jpeg_quality=95)) + rr.log(f"{LOWRES_POSED_ENTITY_PATH}/depth", rr.DepthImage(depth, meter=1000)) # log the high res camera if high_res_exists: @@ -298,7 +297,7 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: highres_intri_path, closest_lowres_frame_id, camera_from_world_dict, - highres_entity_path, + HIGHRES_ENTITY_PATH, ) # load the highres image and depth if they exist @@ -307,8 +306,8 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: highres_rgb = cv2.cvtColor(highres_bgr, cv2.COLOR_BGR2RGB) - rr.log(f"{highres_entity_path}/rgb", rr.Image(highres_rgb).compress(jpeg_quality=75)) - rr.log(f"{highres_entity_path}/depth", rr.DepthImage(highres_depth, meter=1000)) + rr.log(f"{HIGHRES_ENTITY_PATH}/rgb", rr.Image(highres_rgb).compress(jpeg_quality=75)) + rr.log(f"{HIGHRES_ENTITY_PATH}/depth", rr.DepthImage(highres_depth, meter=1000)) def main() -> None: @@ -328,7 +327,7 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - primary_camera_entity = highres_entity_path if args.include_highres else lowres_posed_entity_path + primary_camera_entity = HIGHRES_ENTITY_PATH if args.include_highres else LOWRES_POSED_ENTITY_PATH blueprint = rrb.Horizontal( rrb.Spatial3DView(name="3D"), From f5f02bfc533f561b54bf78260a369e27b67abbb7 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 5 Apr 2024 16:17:14 +0200 Subject: [PATCH 201/508] Move dataloader docs to reference + document CLI flags (#5808) :point_up: Also future proofed reference ordering. ![image](https://github.com/rerun-io/rerun/assets/2910679/8d622925-1032-435f-9918-3dea0c466757) --- docs/content/reference.md | 2 +- docs/content/reference/about.md | 2 +- docs/content/reference/cpp.md | 2 +- docs/content/reference/data-loaders.md | 5 +++ docs/content/reference/data-loaders/cpp.md | 5 +++ .../data-loaders/overview.md} | 45 +++++++++++++++++-- docs/content/reference/data-loaders/python.md | 5 +++ docs/content/reference/data-loaders/rust.md | 5 +++ docs/content/reference/entity-queries.md | 2 +- docs/content/reference/migration.md | 2 +- docs/content/reference/python.md | 2 +- docs/content/reference/roadmap.md | 2 +- docs/content/reference/rust.md | 2 +- .../content/reference/sdk-logging-controls.md | 2 +- docs/content/reference/sdk-micro-batching.md | 2 +- docs/content/reference/sdk-operating-modes.md | 2 +- docs/content/reference/types.md | 2 +- docs/content/reference/viewer.md | 2 +- 18 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 docs/content/reference/data-loaders.md create mode 100644 docs/content/reference/data-loaders/cpp.md rename docs/content/{howto/add-support-for-arbitrary-file-types.md => reference/data-loaders/overview.md} (70%) create mode 100644 docs/content/reference/data-loaders/python.md create mode 100644 docs/content/reference/data-loaders/rust.md diff --git a/docs/content/reference.md b/docs/content/reference.md index 8fd7b64b3021..24ba4696d86f 100644 --- a/docs/content/reference.md +++ b/docs/content/reference.md @@ -3,4 +3,4 @@ title: Reference order: 2 --- -The reference docs details how to use the logging APIs and the viewer. +The reference docs detail how to use the logging APIs and the viewer. diff --git a/docs/content/reference/about.md b/docs/content/reference/about.md index 410420679c46..8c3c0abb073f 100644 --- a/docs/content/reference/about.md +++ b/docs/content/reference/about.md @@ -1,6 +1,6 @@ --- title: About -order: 0 +order: 100 --- To learn more about Rerun, the company, visit our Website at [https://www.rerun.io/](https://www.rerun.io/). diff --git a/docs/content/reference/cpp.md b/docs/content/reference/cpp.md index 9ee8c0b93b69..9d61b17b6783 100644 --- a/docs/content/reference/cpp.md +++ b/docs/content/reference/cpp.md @@ -1,5 +1,5 @@ --- title: 🌊 C++ APIs -order: 9 +order: 1000 redirect: https://ref.rerun.io/docs/cpp --- diff --git a/docs/content/reference/data-loaders.md b/docs/content/reference/data-loaders.md new file mode 100644 index 000000000000..680061c51967 --- /dev/null +++ b/docs/content/reference/data-loaders.md @@ -0,0 +1,5 @@ +--- +title: Data-loaders +order: 550 +redirect: reference/data-loaders/overview +--- diff --git a/docs/content/reference/data-loaders/cpp.md b/docs/content/reference/data-loaders/cpp.md new file mode 100644 index 000000000000..b477abb9a480 --- /dev/null +++ b/docs/content/reference/data-loaders/cpp.md @@ -0,0 +1,5 @@ +--- +title: 🌊 C++ example +order: 100 +redirect: https://github.com/rerun-io/rerun/tree/main/examples/cpp/external_data_loader +--- diff --git a/docs/content/howto/add-support-for-arbitrary-file-types.md b/docs/content/reference/data-loaders/overview.md similarity index 70% rename from docs/content/howto/add-support-for-arbitrary-file-types.md rename to docs/content/reference/data-loaders/overview.md index fcd223a0c7c3..3f3758ec18d6 100644 --- a/docs/content/howto/add-support-for-arbitrary-file-types.md +++ b/docs/content/reference/data-loaders/overview.md @@ -1,6 +1,6 @@ --- -title: Add support for arbitrary file types -order: 11 +title: Overview +order: 50 --- Internally, the [`DataLoader`](https://docs.rs/re_data_source/latest/re_data_source/trait.DataLoader.html) trait takes care of loading files into the Viewer and/or SDK. @@ -22,7 +22,7 @@ The easiest way to create your own `DataLoader` is by implementing what we call This executable takes a file path as a command line argument and outputs Rerun logs on `stdout`. It will be called by the Rerun Viewer/SDK when the user opens a file, and be passed the path to that file. -From there, it can log data as usual, using the [`stdout` logging sink](../reference/sdk-operating-modes.md#standard-inputoutput). +From there, it can log data as usual, using the [`stdout` logging sink](../../reference/sdk-operating-modes.md#standard-inputoutput). The Rerun Viewer/SDK will then automatically load the data streamed to the external loader's standard output. @@ -37,6 +37,45 @@ The Rerun Viewer/SDK will then automatically load the data streamed to the exter Like any other `DataLoader`, an external loader will be notified of all file openings, unconditionally. To indicate that it does not support a given file, the loader has to exit with a [dedicated status code](https://docs.rs/rerun/latest/rerun/constant.EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE.html). +When the viewer and/or SDK executes an external loader, it will pass to it a set of recommended settings in the form of CLI parameters (in addition to the file path to be loaded, which is passed as the one and only positional argument): + +* `--application-id ` + + The recommended `ApplicationId` to log the data to. + +* `--opened-application-id ` (optional) + + The `ApplicationId` that is currently opened in the viewer, if any. + +* `--recording-id ` + + The recommended `RecordingId` to log the data to. + + Log data to this recording if you want it to appear in a new recording shared by all + data-loaders for the current loading session. + +* `--opened-recording-id ` (optional) + + The `RecordingId` that is currently opened in the viewer, if any. + +* `--entity-path-prefix ` (optional) + + Recommended prefix to prepend to all entity paths. + +* `--timeless` (optional) + + The data is expected to be logged timelessly. + +* `--time = = ...` (optional) + + The data is expected to be logged at these specific temporal timestamps. + + The timestamps are expected to be in nanoseconds: use `rr.set_time_nanos` (Python) / `RecordingStream::set_time_nanos` (C++, Rust) appropriately. + +* `--sequence = = ...` (optional) + + The data is expected to be logged at these specific sequence timestamps. + Check out our examples for [C++](https://github.com/rerun-io/rerun/tree/main/examples/cpp/external_data_loader), [Python](https://github.com/rerun-io/rerun/tree/main/examples/python/external_data_loader) and [Rust](https://github.com/rerun-io/rerun/tree/main/examples/rust/external_data_loader) that cover every steps in details. ### Custom Rust data-loaders diff --git a/docs/content/reference/data-loaders/python.md b/docs/content/reference/data-loaders/python.md new file mode 100644 index 000000000000..a5a0c9408daa --- /dev/null +++ b/docs/content/reference/data-loaders/python.md @@ -0,0 +1,5 @@ +--- +title: 🐍 Python example +order: 100 +redirect: https://github.com/rerun-io/rerun/tree/main/examples/python/external_data_loader +--- diff --git a/docs/content/reference/data-loaders/rust.md b/docs/content/reference/data-loaders/rust.md new file mode 100644 index 000000000000..310c3cd62ad0 --- /dev/null +++ b/docs/content/reference/data-loaders/rust.md @@ -0,0 +1,5 @@ +--- +title: 🦀 Rust example +order: 120 +redirect: https://github.com/rerun-io/rerun/tree/main/examples/rust/external_data_loader +--- diff --git a/docs/content/reference/entity-queries.md b/docs/content/reference/entity-queries.md index c25bdee875db..925d7721e4cf 100644 --- a/docs/content/reference/entity-queries.md +++ b/docs/content/reference/entity-queries.md @@ -1,6 +1,6 @@ --- title: Entity Queries -order: 4 +order: 500 --- Many space views are made up of visualizations that include more than one diff --git a/docs/content/reference/migration.md b/docs/content/reference/migration.md index d4bf73e4c914..a32edd8a4283 100644 --- a/docs/content/reference/migration.md +++ b/docs/content/reference/migration.md @@ -1,5 +1,5 @@ --- title: Migration Guides -order: 12 +order: 900 redirect: reference/migration/migration-0-13 --- diff --git a/docs/content/reference/python.md b/docs/content/reference/python.md index 6cd1cd170ee5..6123dd0ba701 100644 --- a/docs/content/reference/python.md +++ b/docs/content/reference/python.md @@ -1,5 +1,5 @@ --- title: 🐍 Python APIs -order: 10 +order: 1100 redirect: https://ref.rerun.io/docs/python --- diff --git a/docs/content/reference/roadmap.md b/docs/content/reference/roadmap.md index 18f51e0d8359..da56878ad4bd 100644 --- a/docs/content/reference/roadmap.md +++ b/docs/content/reference/roadmap.md @@ -1,6 +1,6 @@ --- title: Roadmap -order: 1 +order: 200 --- Rerun is building a visualization engine for streams of multimodal data that's easy to use, adapt, and extend. diff --git a/docs/content/reference/rust.md b/docs/content/reference/rust.md index 658b8e5086b8..cc1623a5165b 100644 --- a/docs/content/reference/rust.md +++ b/docs/content/reference/rust.md @@ -1,5 +1,5 @@ --- title: 🦀 Rust APIs -order: 11 +order: 1200 redirect: https://docs.rs/rerun/ --- diff --git a/docs/content/reference/sdk-logging-controls.md b/docs/content/reference/sdk-logging-controls.md index 99d5e5efc03b..feb3659a467e 100644 --- a/docs/content/reference/sdk-logging-controls.md +++ b/docs/content/reference/sdk-logging-controls.md @@ -1,6 +1,6 @@ --- title: SDK Logging Controls -order: 5 +order: 600 --- ## Controlling logging globally diff --git a/docs/content/reference/sdk-micro-batching.md b/docs/content/reference/sdk-micro-batching.md index faaf427c44e9..66a8bda65d36 100644 --- a/docs/content/reference/sdk-micro-batching.md +++ b/docs/content/reference/sdk-micro-batching.md @@ -1,6 +1,6 @@ --- title: SDK Micro Batching -order: 6 +order: 700 --- diff --git a/docs/content/reference/sdk-operating-modes.md b/docs/content/reference/sdk-operating-modes.md index e54badaf96c0..45d048a61e83 100644 --- a/docs/content/reference/sdk-operating-modes.md +++ b/docs/content/reference/sdk-operating-modes.md @@ -1,6 +1,6 @@ --- title: SDK Operating Modes -order: 7 +order: 800 --- There are many different ways of sending data to the Rerun Viewer depending on what you're trying to achieve and whether the viewer is running in the same process as your code, in another process, or even as a separate web application. diff --git a/docs/content/reference/types.md b/docs/content/reference/types.md index a82c7f6094c4..02da158ab288 100644 --- a/docs/content/reference/types.md +++ b/docs/content/reference/types.md @@ -1,6 +1,6 @@ --- title: Types -order: 3 +order: 400 --- Rerun comes with built-in support for a number of different types that can be logged via the Python and Rust Logging diff --git a/docs/content/reference/viewer.md b/docs/content/reference/viewer.md index 379792ff12b4..b8a014bdb5e2 100644 --- a/docs/content/reference/viewer.md +++ b/docs/content/reference/viewer.md @@ -1,5 +1,5 @@ --- title: Viewer -order: 2 +order: 300 redirect: reference/viewer/overview --- From f100637c1ad68e872722211300dd06a10682910b Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 5 Apr 2024 16:19:04 +0200 Subject: [PATCH 202/508] Spring cleaning of `How to` section of docs (#5803) - Update index page - Order guides by decreasing order of importance as much as possible - Rename everything so that it always reads as "How to... do X" - Give space for future ordering changes Note: I haven't touch the dataloader how-to because it's going to move to Reference in an upcoming PR. ![image](https://github.com/rerun-io/rerun/assets/2910679/3b0bc8b4-0662-42ae-8fe3-7fb9fe85c091) --- docs/content/howto.md | 18 +++++++++++------- .../howto/configure-viewer-through-code.md | 2 +- docs/content/howto/extend.md | 2 +- docs/content/howto/extend/custom-data.md | 4 ++-- docs/content/howto/extend/extend-ui.md | 2 +- docs/content/howto/limit-ram.md | 6 +++--- docs/content/howto/notebook.md | 4 ++-- docs/content/howto/ros2-nav-turtlebot.md | 4 ++-- docs/content/howto/shared-recordings.md | 4 ++-- docs/content/howto/short-lived-entities.md | 4 ++-- docs/content/howto/using-native-loggers.md | 4 ++-- .../content/reference/data-loaders/overview.md | 4 ++-- 12 files changed, 31 insertions(+), 27 deletions(-) diff --git a/docs/content/howto.md b/docs/content/howto.md index d5e8c4ca4554..9ec110bd3de6 100644 --- a/docs/content/howto.md +++ b/docs/content/howto.md @@ -1,12 +1,16 @@ --- -title: How-To Guides +title: How-to order: 1 --- Guides for using Rerun in more advanced ways. - - [Limit RAM use](howto/limit-ram.md) - - [Using Rerun with ROS2](howto/ros2-nav-turtlebot.md) - - [Embedding Rerun within a Notebook](howto/notebook.md) - - [Extending Rerun](howto/extend) - - [By using custom data](howto/extend/custom-data.md) - - [By extending the Viewer in Rust](howto/extend/extend-ui.md) + - [Configure the viewer through code](howto/configure-viewer-through-code.md) + - [Limit memory usage](howto/limit-ram.md) + - [Share recordings across multiple processes](howto/shared-recordings.md) + - [Clear out already logged data](howto/short-lived-entities.md) + - [Use Rerun with ROS2](howto/ros2-nav-turtlebot.md) + - [Embed Rerun in notebooks](howto/notebook.md) + - [Integrate Rerun with native loggers](howto/using-native-loggers.md) + - [Extend Rerun](howto/extend) + - [By logging custom data](howto/extend/custom-data.md) + - [By implementing custom visualizations (Rust only)](howto/extend/extend-ui.md) diff --git a/docs/content/howto/configure-viewer-through-code.md b/docs/content/howto/configure-viewer-through-code.md index a801a5d1b5e8..7eb4bfcc5994 100644 --- a/docs/content/howto/configure-viewer-through-code.md +++ b/docs/content/howto/configure-viewer-through-code.md @@ -1,6 +1,6 @@ --- title: Configure the viewer through code -order: 0 +order: 100 --- As of Rerun 0.15, the state of the [blueprint](../reference/viewer/blueprint.md) can be directly manipulated using the diff --git a/docs/content/howto/extend.md b/docs/content/howto/extend.md index 62305569f878..9e76991bc36c 100644 --- a/docs/content/howto/extend.md +++ b/docs/content/howto/extend.md @@ -1,6 +1,6 @@ --- title: Extend Rerun -order: 8 +order: 1000 --- There are currently two major ways of extending Rerun. You can use Rerun with [your own custom data](extend/custom-data.md), or [extend the Rerun Viewer](extend/extend-ui.md) (currently Rust only). diff --git a/docs/content/howto/extend/custom-data.md b/docs/content/howto/extend/custom-data.md index 564bfef1854d..d5bb8d0c9830 100644 --- a/docs/content/howto/extend/custom-data.md +++ b/docs/content/howto/extend/custom-data.md @@ -1,6 +1,6 @@ --- -title: Use custom data -order: 2 +title: By logging custom data +order: 100 description: How to use Rerun with custom data --- Rerun comes with many pre-built [Types](../../reference/types.md) that you can use out of the box. As long as your own data can be decomposed into Rerun [components](../../reference/types/components.md) or can be serialized with [Apache Arrow](https://arrow.apache.org/), you can log it directly without needing to recompile Rerun. diff --git a/docs/content/howto/extend/extend-ui.md b/docs/content/howto/extend/extend-ui.md index 1600cb0a9157..5b3cae728e33 100644 --- a/docs/content/howto/extend/extend-ui.md +++ b/docs/content/howto/extend/extend-ui.md @@ -1,5 +1,5 @@ --- -title: Extend the Viewer in Rust +title: By implementing custom visualizations (Rust only) order: 2 description: How to extend the Rerun Viewer UI using Rust and egui --- diff --git a/docs/content/howto/limit-ram.md b/docs/content/howto/limit-ram.md index c0dd716e5413..52d49df008a9 100644 --- a/docs/content/howto/limit-ram.md +++ b/docs/content/howto/limit-ram.md @@ -1,7 +1,7 @@ --- -title: How To Limit Memory Use -order: 1 -description: How to limit the memory of Rerun so that it doesn't run out of RAM. +title: Limit memory usage +order: 200 +description: How to limit the memory used by the Rerun viewer so that it doesn't run out of RAM. --- ### --memory-limit diff --git a/docs/content/howto/notebook.md b/docs/content/howto/notebook.md index 98129090ecbc..b02328d7c956 100644 --- a/docs/content/howto/notebook.md +++ b/docs/content/howto/notebook.md @@ -1,6 +1,6 @@ --- -title: Using Rerun with Notebooks -order: 3 +title: Embed Rerun in notebooks +order: 600 description: How to embed Rerun in notebooks like Jupyter or Colab --- diff --git a/docs/content/howto/ros2-nav-turtlebot.md b/docs/content/howto/ros2-nav-turtlebot.md index 8cbe4aef2915..48a62329cad0 100644 --- a/docs/content/howto/ros2-nav-turtlebot.md +++ b/docs/content/howto/ros2-nav-turtlebot.md @@ -1,6 +1,6 @@ --- -title: Using Rerun with ROS 2 -order: 4 +title: Use Rerun with ROS 2 +order: 500 ogImageUrl: /docs-media/og-howto-ros.jpg description: Rerun does not yet have native ROS support, but many of the concepts in ROS and Rerun line up fairly well. In this guide, you will learn how to write a simple ROS 2 python node that subscribes to some common ROS topics and logs them to Rerun. --- diff --git a/docs/content/howto/shared-recordings.md b/docs/content/howto/shared-recordings.md index 582f3caaabdf..24282981de24 100644 --- a/docs/content/howto/shared-recordings.md +++ b/docs/content/howto/shared-recordings.md @@ -1,6 +1,6 @@ --- -title: Share a recording across multiple processes -order: 2 +title: Share recordings across multiple processes +order: 300 --- A common need is to log data from multiple processes and then visualize all of that data as part of a single shared recording. diff --git a/docs/content/howto/short-lived-entities.md b/docs/content/howto/short-lived-entities.md index 68987db179ce..b7fbe47dc520 100644 --- a/docs/content/howto/short-lived-entities.md +++ b/docs/content/howto/short-lived-entities.md @@ -1,6 +1,6 @@ --- -title: Log short lived data -order: 5 +title: Clear out already logged data +order: 400 description: How to log data that isn't valid for the whole recording --- In order to create coherent views of streaming data, the Rerun Viewer shows the latest values for each visible entity at the current timepoint. But some data may not be valid for the entire recording even if there are no updated values. How do you tell Rerun that something you've logged should no longer be shown? diff --git a/docs/content/howto/using-native-loggers.md b/docs/content/howto/using-native-loggers.md index 3dcd8b919038..467223b84497 100644 --- a/docs/content/howto/using-native-loggers.md +++ b/docs/content/howto/using-native-loggers.md @@ -1,6 +1,6 @@ --- -title: Using native loggers -order: 5 +title: Integrate Rerun with native loggers +order: 700 description: How to use the Rerun SDK as a native logger for the host language --- diff --git a/docs/content/reference/data-loaders/overview.md b/docs/content/reference/data-loaders/overview.md index 3f3758ec18d6..bb2a720d894d 100644 --- a/docs/content/reference/data-loaders/overview.md +++ b/docs/content/reference/data-loaders/overview.md @@ -66,13 +66,13 @@ When the viewer and/or SDK executes an external loader, it will pass to it a set The data is expected to be logged timelessly. -* `--time = = ...` (optional) +* `--time = = …` (optional) The data is expected to be logged at these specific temporal timestamps. The timestamps are expected to be in nanoseconds: use `rr.set_time_nanos` (Python) / `RecordingStream::set_time_nanos` (C++, Rust) appropriately. -* `--sequence = = ...` (optional) +* `--sequence = = …` (optional) The data is expected to be logged at these specific sequence timestamps. From eb6270d5778b0b34bf8095e07f64abbc01541089 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 5 Apr 2024 16:20:47 +0200 Subject: [PATCH 203/508] Static data 0: revamped `TimeInt` (#5534) _Commits make no sense, review the final changelog directly._ _All the interesting bits happen in `re_log_types/time_point` & `re_sdk` -- everything else is just change propagation._ - `TimeInt` now ranges from `i64:MIN + 1` to `i64::MAX`. - `TimeInt::STATIC`, which takes the place of the now illegal `TimeInt(i64::MIN)`, is now _the only way_ of identifying static data. - It is impossible to create `TimeInt::STATIC` inadvertently -- users of the SDK cannot set the clock to that value. - Similarly, it is impossible to create a `TimeRange`, a `TimePoint`, a `LatestAtQuery` or a `RangeQuery` that includes `TimeInt::STATIC`. If static data exists, that's what will be returned, unconditionally -- there's no such thing as querying for it explicitely. - `TimePoint::timeless` is gone -- we already have `TimePoint::default` that we use all over the place, we don't need two ways of doing the same thing. There still exists a logical mapping between an empty `TimePoint` and static data, as that is how one represents static data on the wire -- terminology wise: "a timeless timepoint results in static data". Similar to the "ensure `RowId`s are unique" refactor from back when, this seemingly tiny change on the surface will vastly simplify downstream code that finally has some invariants to rely on. - Fixes #4832 - Related to #5264 --- Part of a PR series that removes the concept of timeless data in favor of the much simpler concept of static data: - #5534 - #5535 - #5536 - #5537 - #5540 --- Cargo.lock | 1 + .../src/data_loader/loader_archetype.rs | 19 +- crates/re_data_source/src/data_loader/mod.rs | 2 +- crates/re_data_store/benches/arrow2.rs | 4 +- crates/re_data_store/benches/data_store.rs | 8 +- crates/re_data_store/benches/gc.rs | 4 +- crates/re_data_store/src/store.rs | 4 +- crates/re_data_store/src/store_dump.rs | 5 +- crates/re_data_store/src/store_event.rs | 40 ++-- crates/re_data_store/src/store_format.rs | 2 +- crates/re_data_store/src/store_gc.rs | 25 +-- crates/re_data_store/src/store_read.rs | 45 ++-- crates/re_data_store/src/store_sanity.rs | 18 +- crates/re_data_store/src/store_subscriber.rs | 12 +- crates/re_data_store/src/store_write.rs | 24 +-- crates/re_data_store/src/test_util.rs | 10 + crates/re_data_store/tests/correctness.rs | 69 +++--- crates/re_data_store/tests/data_store.rs | 57 +++-- crates/re_data_store/tests/dump.rs | 22 +- crates/re_data_store/tests/internals.rs | 4 +- crates/re_data_ui/src/image_meaning.rs | 2 +- crates/re_data_ui/src/instance_path.rs | 4 +- crates/re_data_ui/src/item_ui.rs | 10 +- crates/re_entity_db/examples/memory_usage.rs | 6 +- .../src/time_histogram_per_timeline.rs | 2 +- crates/re_entity_db/tests/clear.rs | 96 ++------- crates/re_entity_db/tests/time_histograms.rs | 27 +-- .../benches/msg_encode_benchmark.rs | 6 +- crates/re_log_types/Cargo.toml | 1 + crates/re_log_types/src/data_row.rs | 6 +- crates/re_log_types/src/data_table.rs | 42 ++-- crates/re_log_types/src/lib.rs | 16 +- crates/re_log_types/src/time_point/mod.rs | 93 ++++---- .../src/time_point/non_min_i64.rs | 196 +++++++++++++++++ .../re_log_types/src/time_point/time_int.rs | 199 +++++++++++------- .../re_log_types/src/time_point/timeline.rs | 4 +- crates/re_log_types/src/time_range.rs | 70 +++--- crates/re_log_types/src/time_real.rs | 6 +- crates/re_query/benches/query_benchmark.rs | 8 +- crates/re_query/src/query.rs | 14 +- crates/re_query/src/range.rs | 4 +- crates/re_query/src/util.rs | 16 +- .../re_query/tests/archetype_query_tests.rs | 22 +- .../re_query/tests/archetype_range_tests.rs | 70 +++--- crates/re_query/tests/store.rs | 3 +- crates/re_query_cache/benches/latest_at.rs | 8 +- crates/re_query_cache/src/cache.rs | 6 +- crates/re_query_cache/src/latest_at.rs | 14 +- crates/re_query_cache/src/range.rs | 32 +-- crates/re_query_cache/tests/latest_at.rs | 50 ++--- crates/re_query_cache/tests/range.rs | 84 +++++--- crates/re_sdk/src/recording_stream.rs | 55 ++++- crates/re_space_view/src/space_view.rs | 10 +- .../re_space_view/src/space_view_contents.rs | 2 +- crates/re_space_view/src/visual_time_range.rs | 13 +- .../benches/bench_points.rs | 4 +- .../re_space_view_spatial/src/heuristics.rs | 2 +- .../src/visualizers/images.rs | 6 +- .../src/space_view_class.rs | 9 +- crates/re_space_view_time_series/src/util.rs | 18 +- .../re_time_panel/src/data_density_graph.rs | 21 +- crates/re_time_panel/src/lib.rs | 23 +- crates/re_time_panel/src/time_axis.rs | 30 +-- crates/re_time_panel/src/time_ranges_ui.rs | 55 +++-- crates/re_time_panel/src/time_selection_ui.rs | 21 +- crates/re_viewer/src/app_blueprint.rs | 2 +- crates/re_viewer/src/ui/visible_history.rs | 24 ++- .../src/blueprint_helpers.rs | 11 +- crates/re_viewer_context/src/item.rs | 3 +- .../src/space_view/view_query.rs | 8 +- crates/re_viewer_context/src/time_control.rs | 21 +- examples/rust/custom_data_loader/src/main.rs | 2 +- .../rust/external_data_loader/src/main.rs | 4 +- examples/rust/objectron/src/main.rs | 8 +- 74 files changed, 1101 insertions(+), 743 deletions(-) create mode 100644 crates/re_log_types/src/time_point/non_min_i64.rs diff --git a/Cargo.lock b/Cargo.lock index 5c82c2ac9133..555202c33d9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4489,6 +4489,7 @@ dependencies = [ "serde_bytes", "similar-asserts", "smallvec", + "static_assertions", "thiserror", "time", "typenum", diff --git a/crates/re_data_source/src/data_loader/loader_archetype.rs b/crates/re_data_source/src/data_loader/loader_archetype.rs index 4be5f61dee7e..250c34d9e69c 100644 --- a/crates/re_data_source/src/data_loader/loader_archetype.rs +++ b/crates/re_data_source/src/data_loader/loader_archetype.rs @@ -1,4 +1,4 @@ -use re_log_types::{DataRow, EntityPath, RowId, TimePoint}; +use re_log_types::{DataRow, EntityPath, RowId, TimeInt, TimePoint}; use crate::{DataLoader, DataLoaderError, LoadedData}; @@ -54,29 +54,32 @@ impl DataLoader for ArchetypeLoader { let entity_path = EntityPath::from_file_path(&filepath); - let mut timepoint = TimePoint::timeless(); + let mut timepoint = TimePoint::default(); // TODO(cmc): log these once heuristics (I think?) are fixed if false { if let Ok(metadata) = filepath.metadata() { use re_log_types::{Time, Timeline}; - if let Some(created) = metadata.created().ok().and_then(|t| Time::try_from(t).ok()) + if let Some(created) = metadata + .created() + .ok() + .and_then(|t| TimeInt::try_from(Time::try_from(t).ok()?).ok()) { - timepoint.insert(Timeline::new_temporal("created_at"), created.into()); + timepoint.insert(Timeline::new_temporal("created_at"), created); } if let Some(modified) = metadata .modified() .ok() - .and_then(|t| Time::try_from(t).ok()) + .and_then(|t| TimeInt::try_from(Time::try_from(t).ok()?).ok()) { - timepoint.insert(Timeline::new_temporal("modified_at"), modified.into()); + timepoint.insert(Timeline::new_temporal("modified_at"), modified); } if let Some(accessed) = metadata .accessed() .ok() - .and_then(|t| Time::try_from(t).ok()) + .and_then(|t| TimeInt::try_from(Time::try_from(t).ok()?).ok()) { - timepoint.insert(Timeline::new_temporal("accessed_at"), accessed.into()); + timepoint.insert(Timeline::new_temporal("accessed_at"), accessed); } } } diff --git a/crates/re_data_source/src/data_loader/mod.rs b/crates/re_data_source/src/data_loader/mod.rs index 24d2c74bb711..3c9790fb12ee 100644 --- a/crates/re_data_source/src/data_loader/mod.rs +++ b/crates/re_data_source/src/data_loader/mod.rs @@ -99,7 +99,7 @@ impl DataLoaderSettings { } if let Some(timepoint) = timepoint { - if timepoint.is_timeless() { + if timepoint.is_static() { args.push("--timeless".to_owned()); } diff --git a/crates/re_data_store/benches/arrow2.rs b/crates/re_data_store/benches/arrow2.rs index 29e8f7412ad0..b8e972945d14 100644 --- a/crates/re_data_store/benches/arrow2.rs +++ b/crates/re_data_store/benches/arrow2.rs @@ -112,8 +112,10 @@ fn erased_clone(c: &mut Criterion) { .map(|array| array.total_size_bytes()) .sum::(); let expected_total_size_bytes = data.total_size_bytes(); + // NOTE: `+ 1` because the computation is off by one bytes, which is irrelevant for the + // purposes of this benchmark. assert!( - total_size_bytes >= expected_total_size_bytes, + total_size_bytes + 1 >= expected_total_size_bytes, "Size for {} calculated to be {} bytes, but should be at least {} bytes", T::name(), total_size_bytes, diff --git a/crates/re_data_store/benches/data_store.rs b/crates/re_data_store/benches/data_store.rs index d89009ff67f1..a81b9d516438 100644 --- a/crates/re_data_store/benches/data_store.rs +++ b/crates/re_data_store/benches/data_store.rs @@ -115,7 +115,7 @@ fn insert_same_time_point(c: &mut Criterion) { group.throughput(criterion::Throughput::Elements(num_rows * num_instances)); let rows = build_rows_ex(num_rows as _, num_instances as _, shuffled, packed, |_| { - TimePoint::from([build_frame_nr(TimeInt::from(0))]) + TimePoint::from([build_frame_nr(TimeInt::ZERO)]) }); // Default config @@ -385,7 +385,7 @@ fn build_rows_with_packed(packed: bool) -> Vec { NUM_INSTANCES as _, false, packed, - |row_idx| TimePoint::from([build_frame_nr((row_idx as i64).into())]), + |row_idx| TimePoint::from([build_frame_nr(row_idx as i64)]), ) } @@ -453,7 +453,7 @@ fn latest_data_at( secondaries: &[ComponentName; N], ) -> [Option; N] { let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let timeline_query = LatestAtQuery::new(timeline_frame_nr, (NUM_ROWS / 2).into()); + let timeline_query = LatestAtQuery::new(timeline_frame_nr, NUM_ROWS / 2); let ent_path = EntityPath::from("large_structs"); store @@ -466,7 +466,7 @@ fn range_data( components: [ComponentName; N], ) -> impl Iterator, [Option; N])> + '_ { let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = RangeQuery::new(timeline_frame_nr, TimeRange::new(0.into(), NUM_ROWS.into())); + let query = RangeQuery::new(timeline_frame_nr, TimeRange::new(TimeInt::ZERO, NUM_ROWS)); let ent_path = EntityPath::from("large_structs"); store diff --git a/crates/re_data_store/benches/gc.rs b/crates/re_data_store/benches/gc.rs index 14b4481c97bf..4a2a2949b465 100644 --- a/crates/re_data_store/benches/gc.rs +++ b/crates/re_data_store/benches/gc.rs @@ -76,7 +76,7 @@ fn plotting_dashboard(c: &mut Criterion) { let mut timegen = |i| { [ build_log_time(Time::from_seconds_since_epoch(i as _)), - build_frame_nr((i as i64).into()), + build_frame_nr(i as i64), ] .into() }; @@ -160,7 +160,7 @@ fn timeless_logs(c: &mut Criterion) { time_budget: std::time::Duration::MAX, }; - let mut timegen = |_| TimePoint::timeless(); + let mut timegen = |_| TimePoint::default(); let mut datagen = |i: usize| { Box::new(re_types::archetypes::TextLog::new(i.to_string())) as Box diff --git a/crates/re_data_store/src/store.rs b/crates/re_data_store/src/store.rs index 62885548f32c..da0b72535e45 100644 --- a/crates/re_data_store/src/store.rs +++ b/crates/re_data_store/src/store.rs @@ -317,8 +317,8 @@ impl DataStore { let entry = oldest_time_per_timeline .entry(bucket.timeline) .or_insert(TimeInt::MAX); - if let Some(time) = bucket.inner.read().col_time.front() { - *entry = TimeInt::min(*entry, (*time).into()); + if let Some(&time) = bucket.inner.read().col_time.front() { + *entry = TimeInt::min(*entry, TimeInt::new_temporal(time)); } } } diff --git a/crates/re_data_store/src/store_dump.rs b/crates/re_data_store/src/store_dump.rs index e83a72b9e65f..ebb82e6ea9c7 100644 --- a/crates/re_data_store/src/store_dump.rs +++ b/crates/re_data_store/src/store_dump.rs @@ -2,7 +2,8 @@ use std::collections::BTreeMap; use arrow2::Either; use re_log_types::{ - DataCellColumn, DataRow, DataTable, ErasedTimeVec, RowIdVec, TableId, TimeRange, Timeline, + DataCellColumn, DataRow, DataTable, ErasedTimeVec, RowIdVec, TableId, TimeInt, TimeRange, + Timeline, }; use crate::{ @@ -248,6 +249,6 @@ fn filter_column<'a, T: 'a + Clone>( col_time .iter() .zip(column) - .filter(move |(time, _)| time_filter.contains((**time).into())) + .filter(move |(&time, _)| time_filter.contains(TimeInt::new_temporal(time))) .map(|(_, v)| v.clone()) } diff --git a/crates/re_data_store/src/store_event.rs b/crates/re_data_store/src/store_event.rs index 5dd439aa41f4..aa869ab2c6c8 100644 --- a/crates/re_data_store/src/store_event.rs +++ b/crates/re_data_store/src/store_event.rs @@ -297,9 +297,9 @@ mod tests { let row_id1 = RowId::new(); let timepoint1 = TimePoint::from_iter([ - (timeline_frame, 42.into()), // - (timeline_other, 666.into()), // - (timeline_yet_another, 1.into()), // + (timeline_frame, 42), // + (timeline_other, 666), // + (timeline_yet_another, 1), // ]); let entity_path1: EntityPath = "entity_a".into(); let row1 = DataRow::from_component_batches( @@ -328,9 +328,9 @@ mod tests { (InstanceKey::name(), 1), // ], [ - (42.into(), 1), // - (666.into(), 1), - (1.into(), 1), + (42.try_into().unwrap(), 1), // + (666.try_into().unwrap(), 1), + (1.try_into().unwrap(), 1), ], 0, ), @@ -339,8 +339,8 @@ mod tests { let row_id2 = RowId::new(); let timepoint2 = TimePoint::from_iter([ - (timeline_frame, 42.into()), // - (timeline_yet_another, 1.into()), // + (timeline_frame, 42), // + (timeline_yet_another, 1), // ]); let entity_path2: EntityPath = "entity_b".into(); let row2 = { @@ -380,9 +380,9 @@ mod tests { (MyColor::name(), 1), // ], [ - (42.into(), 2), // - (666.into(), 1), - (1.into(), 2), + (42.try_into().unwrap(), 2), // + (666.try_into().unwrap(), 1), + (1.try_into().unwrap(), 2), ], 0, ), @@ -390,7 +390,7 @@ mod tests { ); let row_id3 = RowId::new(); - let timepoint3 = TimePoint::timeless(); + let timepoint3 = TimePoint::default(); let row3 = { let num_instances = 6; let colors = vec![MyColor::from(0x00DD00FF); num_instances]; @@ -429,9 +429,9 @@ mod tests { (MyColor::name(), 2), // ], [ - (42.into(), 2), // - (666.into(), 1), - (1.into(), 2), + (42.try_into().unwrap(), 2), // + (666.try_into().unwrap(), 1), + (1.try_into().unwrap(), 2), ], 1, ), @@ -463,9 +463,9 @@ mod tests { (MyColor::name(), 0), // ], [ - (42.into(), 0), // - (666.into(), 0), - (1.into(), 0), + (42.try_into().unwrap(), 0), // + (666.try_into().unwrap(), 0), + (1.try_into().unwrap(), 0), ], 0, ), @@ -487,7 +487,7 @@ mod tests { let row1 = DataRow::from_component_batches( RowId::new(), - TimePoint::from_iter([(timeline_frame, 42.into())]), + TimePoint::from_iter([(timeline_frame, 42)]), "entity_a".into(), [&InstanceKey::from_iter(0..10) as _], )?; @@ -504,7 +504,7 @@ mod tests { let row2 = DataRow::from_component_batches( RowId::new(), - TimePoint::from_iter([(timeline_frame, 42.into())]), + TimePoint::from_iter([(timeline_frame, 42)]), "entity_b".into(), [&[MyColor::from(0xAABBCCDD)] as _], )?; diff --git a/crates/re_data_store/src/store_format.rs b/crates/re_data_store/src/store_format.rs index 3867098d8ad3..3cf6431e6a8e 100644 --- a/crates/re_data_store/src/store_format.rs +++ b/crates/re_data_store/src/store_format.rs @@ -130,7 +130,7 @@ impl std::fmt::Display for IndexedBucket { let time_range = { let time_range = &self.inner.read().time_range; - if time_range.min != TimeInt::MAX && time_range.max != TimeInt::MIN { + if time_range.min() != TimeInt::MAX && time_range.max() != TimeInt::MIN { format!( " - {}: {}", self.timeline.name(), diff --git a/crates/re_data_store/src/store_gc.rs b/crates/re_data_store/src/store_gc.rs index 0aa190f6b5c9..c8e2c513d692 100644 --- a/crates/re_data_store/src/store_gc.rs +++ b/crates/re_data_store/src/store_gc.rs @@ -5,7 +5,7 @@ use web_time::Instant; use nohash_hasher::IntMap; use re_log_types::{ - DataCell, EntityPath, EntityPathHash, RowId, TimePoint, TimeRange, Timeline, + DataCell, EntityPath, EntityPathHash, RowId, TimeInt, TimePoint, TimeRange, Timeline, VecDequeRemovalExt as _, }; use re_types_core::{ComponentName, SizeBytes as _}; @@ -424,7 +424,7 @@ impl DataStore { for (&timeline, &time) in timepoint { if let Some(table) = tables.get_mut(&(*entity_path_hash, timeline)) { let (removed, num_bytes_removed) = - table.try_drop_row(cluster_cell_cache, *row_id, time.as_i64()); + table.try_drop_row(cluster_cell_cache, *row_id, time); if let Some(inner) = diff.as_mut() { if let Some(removed) = removed { inner.times.extend(removed.times); @@ -438,7 +438,7 @@ impl DataStore { // TODO(jleibs): This is a worst-case removal-order. Would be nice to collect all the rows // first and then remove them in one pass. - if timepoint.is_timeless() && gc_timeless { + if timepoint.is_static() && gc_timeless { for table in timeless_tables.values_mut() { // let deleted_comps = deleted.timeless.entry(ent_path.clone()_hash).or_default(); let (removed, num_bytes_removed) = @@ -642,7 +642,8 @@ impl DataStore { .entry(row_id) .or_insert_with(|| StoreDiff::deletion(row_id, entity_path.clone())); - diff.times.push((bucket.timeline, time.into())); + diff.times + .push((bucket.timeline, TimeInt::new_temporal(time))); for column in &mut inner.columns.values_mut() { let cell = column[i].take(); @@ -702,7 +703,7 @@ impl IndexedTable { let mut diff = StoreDiff::deletion(row_id, ent_path.clone()); if let Some(time) = col_time.pop_front() { - diff.times.push((timeline, time.into())); + diff.times.push((timeline, TimeInt::new_temporal(time))); } for (component_name, column) in &mut columns { @@ -747,7 +748,7 @@ impl IndexedTable { &mut self, cluster_cache: &ClusterCellCache, row_id: RowId, - time: i64, + time: TimeInt, ) -> (Option, u64) { re_tracing::profile_function!(); @@ -757,7 +758,7 @@ impl IndexedTable { let table_has_more_than_one_bucket = self.buckets.len() > 1; - let (bucket_key, bucket) = self.find_bucket_mut(time.into()); + let (bucket_key, bucket) = self.find_bucket_mut(time); let bucket_num_bytes = bucket.total_size_bytes(); let (diff, mut dropped_num_bytes) = { @@ -806,7 +807,7 @@ impl IndexedBucketInner { row_id: RowId, timeline: Timeline, ent_path: &EntityPath, - time: i64, + time: TimeInt, ) -> (Option, u64) { self.sort(); @@ -825,8 +826,8 @@ impl IndexedBucketInner { let mut diff: Option = None; let mut dropped_num_bytes = 0u64; - let mut row_index = col_time.partition_point(|&time2| time2 < time); - while col_time.get(row_index) == Some(&time) { + let mut row_index = col_time.partition_point(|&time2| time2 < time.as_i64()); + while col_time.get(row_index) == Some(&time.as_i64()) { if col_row_id[row_index] != row_id { row_index += 1; continue; @@ -842,11 +843,11 @@ impl IndexedBucketInner { // We have at least two rows, so we can safely [index] here: if row_index == 0 { // We removed the first row, so the second row holds the new min - time_range.min = col_time[1].into(); + time_range.set_min(col_time[1]); } if row_index + 1 == col_time.len() { // We removed the last row, so the penultimate row holds the new max - time_range.max = col_time[row_index - 1].into(); + time_range.set_max(col_time[row_index - 1]); } } diff --git a/crates/re_data_store/src/store_read.rs b/crates/re_data_store/src/store_read.rs index 516fe472c03c..d44d3026021e 100644 --- a/crates/re_data_store/src/store_read.rs +++ b/crates/re_data_store/src/store_read.rs @@ -19,8 +19,8 @@ use crate::{ /// Get the latest version of the data available at this time. #[derive(Clone, PartialEq, Eq, Hash)] pub struct LatestAtQuery { - pub timeline: Timeline, - pub at: TimeInt, + timeline: Timeline, + at: TimeInt, } impl std::fmt::Debug for LatestAtQuery { @@ -34,16 +34,30 @@ impl std::fmt::Debug for LatestAtQuery { } impl LatestAtQuery { - pub const fn new(timeline: Timeline, at: TimeInt) -> Self { + /// The returned query is guaranteed to never include [`TimeInt::STATIC`]. + #[inline] + pub fn new(timeline: Timeline, at: impl TryInto) -> Self { + let at = at.try_into().unwrap_or(TimeInt::MIN); Self { timeline, at } } + #[inline] pub const fn latest(timeline: Timeline) -> Self { Self { timeline, at: TimeInt::MAX, } } + + #[inline] + pub fn timeline(&self) -> Timeline { + self.timeline + } + + #[inline] + pub fn at(&self) -> TimeInt { + self.at + } } /// A query over a time range, for a given timeline. @@ -62,10 +76,10 @@ impl std::fmt::Debug for RangeQuery { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_fmt(format_args!( "", - self.timeline.typ().format_utc(self.range.min), - self.timeline.typ().format_utc(self.range.max), + self.timeline.typ().format_utc(self.range.min()), + self.timeline.typ().format_utc(self.range.max()), self.timeline.name(), - if self.range.min <= TimeInt::MIN { + if self.range.min() <= TimeInt::MIN { "including" } else { "excluding" @@ -75,6 +89,7 @@ impl std::fmt::Debug for RangeQuery { } impl RangeQuery { + /// The returned query is guaranteed to never include [`TimeInt::STATIC`]. pub const fn new(timeline: Timeline, range: TimeRange) -> Self { Self { timeline, range } } @@ -192,7 +207,7 @@ impl DataStore { .inner .read() .time_range - .min; + .min(); // handle case where no data was logged if min_time == TimeInt::MIN { @@ -373,7 +388,7 @@ impl DataStore { .flatten() .map(|(time, row_id, cells)| (Some(time), row_id, cells)); - if query.range.min <= TimeInt::MIN { + if query.range.min() <= TimeInt::MIN { let timeless = self .timeless_tables .get(&ent_path_hash) @@ -480,9 +495,9 @@ impl IndexedTable { let timeline = self.timeline; // We need to find the _indexing time_ that corresponds to this time range's minimum bound! - let (time_range_min, _) = self.find_bucket(time_range.min); + let (time_range_min, _) = self.find_bucket(time_range.min()); - self.range_buckets(time_range_min..=time_range.max) + self.range_buckets(time_range_min..=time_range.max()) .map(|(_, bucket)| bucket) .enumerate() .flat_map(move |(bucket_nr, bucket)| { @@ -717,7 +732,9 @@ impl IndexedBucket { } Some(( - col_time[secondary_row_nr as usize].into(), + col_time[secondary_row_nr as usize] + .try_into() + .unwrap_or(TimeInt::MIN), col_row_id[secondary_row_nr as usize], cells, )) @@ -776,7 +793,7 @@ impl IndexedBucket { "searching for time & component cell numbers…" ); - let time_row_nr = col_time.partition_point(|t| *t < time_range.min.as_i64()) as u64; + let time_row_nr = col_time.partition_point(|t| *t < time_range.min().as_i64()) as u64; trace!( kind = "range", @@ -806,7 +823,7 @@ impl IndexedBucket { .into_iter() .skip(time_row_nr as usize) // don't go beyond the time range we're interested in! - .filter(move |time| time_range.contains((*time).into())) + .filter(move |&time| time_range.contains(TimeInt::new_temporal(time))) .enumerate() .filter_map(move |(time_row_offset, time)| { let row_nr = time_row_nr + time_row_offset as u64; @@ -839,7 +856,7 @@ impl IndexedBucket { "yielding cells", ); - Some((time.into(), row_id, cells)) + Some((TimeInt::new_temporal(time), row_id, cells)) }); itertools::Either::Left(cells) diff --git a/crates/re_data_store/src/store_sanity.rs b/crates/re_data_store/src/store_sanity.rs index f03c25afbcf1..d2770b61598a 100644 --- a/crates/re_data_store/src/store_sanity.rs +++ b/crates/re_data_store/src/store_sanity.rs @@ -104,12 +104,12 @@ impl IndexedTable { let &[t1, t2] = time_ranges else { unreachable!() }; - if t1.max.as_i64() >= t2.min.as_i64() { + if t1.max().as_i64() >= t2.min().as_i64() { return Err(SanityError::OverlappingBuckets { - t1_max: t1.max.as_i64(), - t1_max_formatted: self.timeline.typ().format_utc(t1.max), - t2_max: t2.max.as_i64(), - t2_max_formatted: self.timeline.typ().format_utc(t2.max), + t1_max: t1.max().as_i64(), + t1_max_formatted: self.timeline.typ().format_utc(t1.max()), + t2_max: t2.max().as_i64(), + t2_max_formatted: self.timeline.typ().format_utc(t2.max()), }); } } @@ -184,13 +184,13 @@ impl IndexedBucket { let expected_min = times .front() .copied() - .unwrap_or(TimeInt::MAX.as_i64()) - .into(); + .and_then(|t| TimeInt::try_from(t).ok()) + .unwrap_or(TimeInt::MAX); let expected_max = times .back() .copied() - .unwrap_or(TimeInt::MIN.as_i64()) - .into(); + .and_then(|t| TimeInt::try_from(t).ok()) + .unwrap_or(TimeInt::MIN); let expected_time_range = TimeRange::new(expected_min, expected_max); if expected_time_range != *time_range { diff --git a/crates/re_data_store/src/store_subscriber.rs b/crates/re_data_store/src/store_subscriber.rs index 10af8533ecb0..51bba3528870 100644 --- a/crates/re_data_store/src/store_subscriber.rs +++ b/crates/re_data_store/src/store_subscriber.rs @@ -230,9 +230,9 @@ mod tests { let row = DataRow::from_component_batches( RowId::new(), TimePoint::from_iter([ - (timeline_frame, 42.into()), // - (timeline_other, 666.into()), // - (timeline_yet_another, 1.into()), // + (timeline_frame, 42), // + (timeline_other, 666), // + (timeline_yet_another, 1), // ]), "entity_a".into(), [&InstanceKey::from_iter(0..10) as _], @@ -249,8 +249,8 @@ mod tests { DataRow::from_component_batches( RowId::new(), TimePoint::from_iter([ - (timeline_frame, 42.into()), // - (timeline_yet_another, 1.into()), // + (timeline_frame, 42), // + (timeline_yet_another, 1), // ]), "entity_b".into(), [&points as _, &colors as _], @@ -264,7 +264,7 @@ mod tests { let colors = vec![MyColor::from(0x00DD00FF); num_instances]; DataRow::from_component_batches( RowId::new(), - TimePoint::timeless(), + TimePoint::default(), "entity_b".into(), [ &InstanceKey::from_iter(0..num_instances as _) as _, diff --git a/crates/re_data_store/src/store_write.rs b/crates/re_data_store/src/store_write.rs index 5f3c697fbb83..8d9efb05f6a8 100644 --- a/crates/re_data_store/src/store_write.rs +++ b/crates/re_data_store/src/store_write.rs @@ -162,7 +162,7 @@ impl DataStore { let insert_id = self.config.store_insert_ids.then_some(self.insert_id); - if timepoint.is_timeless() { + if timepoint.is_static() { let index = self .timeless_tables .entry(ent_path_hash) @@ -355,7 +355,7 @@ impl IndexedTable { entity = %ent_path, len_limit = config.indexed_bucket_num_rows, len, len_overflow, - new_time_bound = timeline.typ().format_utc(new_time_bound.into()), + new_time_bound = timeline.typ().format_utc(TimeInt::new_temporal(new_time_bound)), "creating brand new indexed bucket following overflow" ); @@ -368,7 +368,7 @@ impl IndexedTable { (inner, size_bytes) }; self.buckets.insert( - (new_time_bound).into(), + TimeInt::new_temporal(new_time_bound), IndexedBucket { timeline, cluster_key: self.cluster_key, @@ -387,13 +387,13 @@ impl IndexedTable { re_log::debug_once!("Failed to split bucket on timeline {}", timeline.name()); if 1 < config.indexed_bucket_num_rows - && bucket_time_range.min == bucket_time_range.max + && bucket_time_range.min() == bucket_time_range.max() { re_log::warn_once!( "Found over {} rows with the same timepoint {:?}={} - perhaps you forgot to update or remove the timeline?", config.indexed_bucket_num_rows, bucket.timeline.name(), - bucket.timeline.typ().format_utc(bucket_time_range.min) + bucket.timeline.typ().format_utc(bucket_time_range.min()) ); } } @@ -454,7 +454,7 @@ impl IndexedBucket { } col_time.push_back(time.as_i64()); - *time_range = TimeRange::new(time_range.min.min(time), time_range.max.max(time)); + *time_range = TimeRange::new(time_range.min().min(time), time_range.max().max(time)); size_bytes_added += time.as_i64().total_size_bytes(); // update all control columns @@ -649,7 +649,7 @@ impl IndexedBucket { inner: RwLock::new(inner2), }; - (time_range2.min, bucket2) + (time_range2.min(), bucket2) }; inner1.compute_size_bytes(); @@ -775,17 +775,17 @@ fn split_time_range_off( times1: &[i64], time_range1: &mut TimeRange, ) -> TimeRange { - let time_range2 = TimeRange::new(times1[split_idx].into(), time_range1.max); + let time_range2 = TimeRange::new(TimeInt::new_temporal(times1[split_idx]), time_range1.max()); // This can never fail (underflow or OOB) because we never split buckets smaller than 2 // entries. - time_range1.max = times1[split_idx - 1].into(); + time_range1.set_max(times1[split_idx - 1]); debug_assert!( - time_range1.max.as_i64() < time_range2.min.as_i64(), + time_range1.max().as_i64() < time_range2.min().as_i64(), "split resulted in overlapping time ranges: {} <-> {}\n{:#?}", - time_range1.max.as_i64(), - time_range2.min.as_i64(), + time_range1.max().as_i64(), + time_range2.min().as_i64(), (&time_range1, &time_range2), ); diff --git a/crates/re_data_store/src/test_util.rs b/crates/re_data_store/src/test_util.rs index a41961bf1a35..c8730020f5d7 100644 --- a/crates/re_data_store/src/test_util.rs +++ b/crates/re_data_store/src/test_util.rs @@ -7,6 +7,16 @@ use crate::{DataStore, DataStoreConfig, WriteError}; #[doc(hidden)] #[macro_export] macro_rules! test_row { + ($entity:ident => $n:expr; [$c0:expr $(,)*]) => {{ + ::re_log_types::DataRow::from_cells1_sized( + ::re_log_types::RowId::new(), + $entity.clone(), + ::re_log_types::TimePoint::default(), + $n, + $c0, + ) + .unwrap() + }}; ($entity:ident @ $frames:tt => $n:expr; [$c0:expr $(,)*]) => {{ ::re_log_types::DataRow::from_cells1_sized( ::re_log_types::RowId::new(), diff --git a/crates/re_data_store/tests/correctness.rs b/crates/re_data_store/tests/correctness.rs index d1297f9cc565..163e84884126 100644 --- a/crates/re_data_store/tests/correctness.rs +++ b/crates/re_data_store/tests/correctness.rs @@ -24,7 +24,7 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { let entity_path: EntityPath = "some_entity".into(); let timeline_frame = Timeline::new_sequence("frame"); - let timepoint = TimePoint::from_iter([(timeline_frame, 10.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 10)]); let point1 = MyPoint::new(1.0, 1.0); let point2 = MyPoint::new(2.0, 2.0); @@ -59,11 +59,7 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { store.insert_row(&row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); let got_point = store .query_latest_component::(&entity_path, &query) .unwrap() @@ -132,11 +128,7 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { store.insert_row(&row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); let got_point = store .query_latest_component::(&entity_path, &query) .unwrap() @@ -162,7 +154,7 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { let row = DataRow::from_component_batches( row_id2, - TimePoint::timeless(), + TimePoint::default(), entity_path.clone(), [&[point1] as _], )?; @@ -170,7 +162,7 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { let row = DataRow::from_component_batches( row_id1, - TimePoint::timeless(), + TimePoint::default(), entity_path.clone(), [&[point2] as _], )?; @@ -207,7 +199,7 @@ fn write_errors() { Default::default(), ); let row = test_row!(ent_path @ - [build_frame_nr(32.into()), build_log_time(Time::now())] => 3; [ + [build_frame_nr(32), build_log_time(Time::now())] => 3; [ build_sparse_instances(), build_some_positions2d(3) ]); assert!(matches!( @@ -232,7 +224,7 @@ fn write_errors() { ); { let row = test_row!(ent_path @ - [build_frame_nr(32.into()), build_log_time(Time::now())] => 3; [ + [build_frame_nr(32), build_log_time(Time::now())] => 3; [ build_unsorted_instances(), build_some_positions2d(3) ]); assert!(matches!( @@ -242,7 +234,7 @@ fn write_errors() { } { let row = test_row!(ent_path @ - [build_frame_nr(32.into()), build_log_time(Time::now())] => 3; [ + [build_frame_nr(32), build_log_time(Time::now())] => 3; [ build_duped_instances(), build_some_positions2d(3) ]); assert!(matches!( @@ -260,7 +252,7 @@ fn write_errors() { ); let mut row = test_row!(ent_path @ [ - build_frame_nr(1.into()), + build_frame_nr(1), build_log_time(Time::now()), ] => 1; [ build_some_positions2d(1) ]); @@ -303,9 +295,9 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { let ent_path = EntityPath::from("this/that"); let now = Time::now(); let now_minus_1s = now - Duration::from_secs(1.0); - let now_minus_1s_nanos = now_minus_1s.nanos_since_epoch().into(); - let frame39 = 39.into(); - let frame40 = 40.into(); + let now_minus_1s_nanos = now_minus_1s.nanos_since_epoch(); + let frame39 = 39; + let frame40 = 40; let num_instances = 3; store @@ -428,7 +420,7 @@ fn gc_correct() { let ent_path = EntityPath::from(format!("this/that/{i}")); let num_instances = rng.gen_range(0..=1_000); let row = test_row!(ent_path @ [ - build_frame_nr(frame_nr.into()), + build_frame_nr(frame_nr), ] => num_instances; [ build_some_colors(num_instances as _), ]); @@ -488,7 +480,7 @@ fn gc_metadata_size() -> anyhow::Result<()> { for _ in 0..3 { let row = DataRow::from_component_batches( RowId::new(), - TimePoint::timeless(), + TimePoint::default(), "xxx".into(), [&[point] as _], )?; @@ -554,10 +546,9 @@ fn entity_min_time_correct_impl(store: &mut DataStore) -> anyhow::Result<()> { let row = DataRow::from_component_batches( RowId::new(), - TimePoint::from_iter([ - (timeline_log_time, now.into()), - (timeline_frame_nr, 42.into()), - ]), + TimePoint::default() + .with(timeline_log_time, now) + .with(timeline_frame_nr, 42), ent_path.clone(), [&[point] as _], )?; @@ -572,11 +563,11 @@ fn entity_min_time_correct_impl(store: &mut DataStore) -> anyhow::Result<()> { .is_none()); assert_eq!( store.entity_min_time(&timeline_frame_nr, &ent_path), - Some(TimeInt::from(42)) + Some(TimeInt::new_temporal(42)) ); assert_eq!( store.entity_min_time(&timeline_log_time, &ent_path), - Some(TimeInt::from(now)) + Some(TimeInt::try_from(now).unwrap()) ); assert!(store .entity_min_time(&timeline_frame_nr, &wrong_ent_path) @@ -585,10 +576,9 @@ fn entity_min_time_correct_impl(store: &mut DataStore) -> anyhow::Result<()> { // insert row in the future, these shouldn't be visible let row = DataRow::from_component_batches( RowId::new(), - TimePoint::from_iter([ - (timeline_log_time, now_plus_one.into()), - (timeline_frame_nr, 54.into()), - ]), + TimePoint::default() + .with(timeline_log_time, now_plus_one) + .with(timeline_frame_nr, 54), ent_path.clone(), [&[point] as _], )?; @@ -602,11 +592,11 @@ fn entity_min_time_correct_impl(store: &mut DataStore) -> anyhow::Result<()> { .is_none()); assert_eq!( store.entity_min_time(&timeline_frame_nr, &ent_path), - Some(TimeInt::from(42)) + Some(TimeInt::new_temporal(42)) ); assert_eq!( store.entity_min_time(&timeline_log_time, &ent_path), - Some(TimeInt::from(now)) + Some(TimeInt::try_from(now).unwrap()) ); assert!(store .entity_min_time(&timeline_frame_nr, &wrong_ent_path) @@ -615,10 +605,9 @@ fn entity_min_time_correct_impl(store: &mut DataStore) -> anyhow::Result<()> { // insert row in the past, these should be visible let row = DataRow::from_component_batches( RowId::new(), - TimePoint::from_iter([ - (timeline_log_time, now_minus_one.into()), - (timeline_frame_nr, 32.into()), - ]), + TimePoint::default() + .with(timeline_log_time, now_minus_one) + .with(timeline_frame_nr, 32), ent_path.clone(), [&[point] as _], )?; @@ -632,11 +621,11 @@ fn entity_min_time_correct_impl(store: &mut DataStore) -> anyhow::Result<()> { .is_none()); assert_eq!( store.entity_min_time(&timeline_frame_nr, &ent_path), - Some(TimeInt::from(32)) + Some(TimeInt::new_temporal(32)) ); assert_eq!( store.entity_min_time(&timeline_log_time, &ent_path), - Some(TimeInt::from(now_minus_one)) + Some(TimeInt::try_from(now_minus_one).unwrap()) ); assert!(store .entity_min_time(&timeline_frame_nr, &wrong_ent_path) diff --git a/crates/re_data_store/tests/data_store.rs b/crates/re_data_store/tests/data_store.rs index 3409d131e429..7df23824bbe6 100644 --- a/crates/re_data_store/tests/data_store.rs +++ b/crates/re_data_store/tests/data_store.rs @@ -28,11 +28,10 @@ fn all_components() { let ent_path = EntityPath::from("this/that"); - // let frame0= TimeInt::from(0); - let frame1 = TimeInt::from(1); - let frame2 = TimeInt::from(2); - let frame3 = TimeInt::from(3); - let frame4 = TimeInt::from(4); + let frame1 = TimeInt::new_temporal(1); + let frame2 = TimeInt::new_temporal(2); + let frame3 = TimeInt::new_temporal(3); + let frame4 = TimeInt::new_temporal(4); let assert_latest_components_at = |store: &mut DataStore, ent_path: &EntityPath, expected: Option<&[ComponentName]>| { @@ -100,7 +99,7 @@ fn all_components() { cluster_key, // always here ]; - let row = test_row!(ent_path @ [] => 2; [build_some_colors(2)]); + let row = test_row!(ent_path => 2; [build_some_colors(2)]); store.insert_row(&row).unwrap(); let row = @@ -157,7 +156,7 @@ fn all_components() { cluster_key, // always here ]; - let row = test_row!(ent_path @ [] => 2; [build_some_colors(2)]); + let row = test_row!(ent_path => 2; [build_some_colors(2)]); store.insert_row(&row).unwrap(); let row = @@ -220,7 +219,7 @@ fn all_components() { cluster_key, // always here ]; - let row = test_row!(ent_path @ [] => 2; [build_some_colors(2)]); + let row = test_row!(ent_path => 2; [build_some_colors(2)]); store.insert_row(&row).unwrap(); let row = @@ -271,11 +270,11 @@ fn latest_at_impl(store: &mut DataStore) { let ent_path = EntityPath::from("this/that"); - let frame0 = TimeInt::from(0); - let frame1 = TimeInt::from(1); - let frame2 = TimeInt::from(2); - let frame3 = TimeInt::from(3); - let frame4 = TimeInt::from(4); + let frame0 = TimeInt::new_temporal(0); + let frame1 = TimeInt::new_temporal(1); + let frame2 = TimeInt::new_temporal(2); + let frame3 = TimeInt::new_temporal(3); + let frame4 = TimeInt::new_temporal(4); // helper to insert a table both as a temporal and timeless payload let insert_table = |store: &mut DataStore, table: &DataTable| { @@ -397,11 +396,11 @@ fn range_impl(store: &mut DataStore) { let ent_path = EntityPath::from("this/that"); - let frame1 = TimeInt::from(1); - let frame2 = TimeInt::from(2); - let frame3 = TimeInt::from(3); - let frame4 = TimeInt::from(4); - let frame5 = TimeInt::from(5); + let frame1 = TimeInt::new_temporal(1); + let frame2 = TimeInt::new_temporal(2); + let frame3 = TimeInt::new_temporal(3); + let frame4 = TimeInt::new_temporal(4); + let frame5 = TimeInt::new_temporal(5); // helper to insert a row both as a temporal and timeless payload let insert = |store: &mut DataStore, row| { @@ -620,7 +619,7 @@ fn gc_impl(store: &mut DataStore) { for frame_nr in frames { let num_instances = rng.gen_range(0..=1_000); let row = test_row!(ent_path @ [ - build_frame_nr(frame_nr.into()) + build_frame_nr(frame_nr) ] => num_instances; [ build_some_large_structs(num_instances as _), ]); @@ -683,11 +682,11 @@ fn protected_gc_impl(store: &mut DataStore) { let ent_path = EntityPath::from("this/that"); - let frame0 = TimeInt::from(0); - let frame1 = TimeInt::from(1); - let frame2 = TimeInt::from(2); - let frame3 = TimeInt::from(3); - let frame4 = TimeInt::from(4); + let frame0 = TimeInt::new_temporal(0); + let frame1 = TimeInt::new_temporal(1); + let frame2 = TimeInt::new_temporal(2); + let frame3 = TimeInt::new_temporal(3); + let frame4 = TimeInt::new_temporal(4); let (instances1, colors1) = (build_some_instances(3), build_some_colors(3)); let row1 = test_row!(ent_path @ [build_frame_nr(frame1)] => 3; [instances1.clone(), colors1]); @@ -788,11 +787,11 @@ fn protected_gc_clear_impl(store: &mut DataStore) { let ent_path = EntityPath::from("this/that"); - let frame0 = TimeInt::from(0); - let frame1 = TimeInt::from(1); - let frame2 = TimeInt::from(2); - let frame3 = TimeInt::from(3); - let frame4 = TimeInt::from(4); + let frame0 = TimeInt::new_temporal(0); + let frame1 = TimeInt::new_temporal(1); + let frame2 = TimeInt::new_temporal(2); + let frame3 = TimeInt::new_temporal(3); + let frame4 = TimeInt::new_temporal(4); let (instances1, colors1) = (build_some_instances(3), build_some_colors(3)); let row1 = test_row!(ent_path @ [build_frame_nr(frame1)] => 3; [instances1.clone(), colors1]); diff --git a/crates/re_data_store/tests/dump.rs b/crates/re_data_store/tests/dump.rs index e032317b8589..fa59cba94f1f 100644 --- a/crates/re_data_store/tests/dump.rs +++ b/crates/re_data_store/tests/dump.rs @@ -206,10 +206,10 @@ fn data_store_dump_filtered() { fn data_store_dump_filtered_impl(store1: &mut DataStore, store2: &mut DataStore) { let timeline_frame_nr = Timeline::new_sequence("frame_nr"); let timeline_log_time = Timeline::log_time(); - let frame1: TimeInt = 1.into(); - let frame2: TimeInt = 2.into(); - let frame3: TimeInt = 3.into(); - let frame4: TimeInt = 4.into(); + let frame1 = TimeInt::new_temporal(1); + let frame2 = TimeInt::new_temporal(2); + let frame3 = TimeInt::new_temporal(3); + let frame4 = TimeInt::new_temporal(4); let ent_paths = ["this/that", "other", "yet/another/one"]; let tables = ent_paths @@ -276,10 +276,10 @@ fn data_store_dump_filtered_impl(store1: &mut DataStore, store2: &mut DataStore) fn create_insert_table(ent_path: impl Into) -> DataTable { let ent_path = ent_path.into(); - let frame1: TimeInt = 1.into(); - let frame2: TimeInt = 2.into(); - let frame3: TimeInt = 3.into(); - let frame4: TimeInt = 4.into(); + let frame1 = TimeInt::new_temporal(1); + let frame2 = TimeInt::new_temporal(2); + let frame3 = TimeInt::new_temporal(3); + let frame4 = TimeInt::new_temporal(4); let (instances1, colors1) = (build_some_instances(3), build_some_colors(3)); let row1 = test_row!(ent_path @ [ @@ -330,9 +330,9 @@ fn data_store_dump_empty_column() { fn data_store_dump_empty_column_impl(store: &mut DataStore) { let ent_path: EntityPath = "points".into(); - let frame1: TimeInt = 1.into(); - let frame2: TimeInt = 2.into(); - let frame3: TimeInt = 3.into(); + let frame1 = TimeInt::new_temporal(1); + let frame2 = TimeInt::new_temporal(2); + let frame3 = TimeInt::new_temporal(3); // Start by inserting a table with 2 rows, one with colors, and one with points. { diff --git a/crates/re_data_store/tests/internals.rs b/crates/re_data_store/tests/internals.rs index 92d18bcc06b8..17059840d6a6 100644 --- a/crates/re_data_store/tests/internals.rs +++ b/crates/re_data_store/tests/internals.rs @@ -48,7 +48,7 @@ fn pathological_bucket_topology() { let ent_path = EntityPath::from("this/that"); let num_instances = 1; - let timepoint = TimePoint::from([build_frame_nr(frame_nr.into())]); + let timepoint = TimePoint::from([build_frame_nr(frame_nr)]); for _ in 0..num { let row = DataRow::from_cells1_sized( RowId::new(), @@ -82,7 +82,7 @@ fn pathological_bucket_topology() { let rows = range .map(|frame_nr| { - let timepoint = TimePoint::from([build_frame_nr(frame_nr.into())]); + let timepoint = TimePoint::from([build_frame_nr(frame_nr)]); DataRow::from_cells1_sized( RowId::new(), ent_path.clone(), diff --git a/crates/re_data_ui/src/image_meaning.rs b/crates/re_data_ui/src/image_meaning.rs index 48a300ab59e2..b92a0ceff54d 100644 --- a/crates/re_data_ui/src/image_meaning.rs +++ b/crates/re_data_ui/src/image_meaning.rs @@ -10,7 +10,7 @@ pub fn image_meaning_for_entity( query: &re_data_store::LatestAtQuery, store: &re_data_store::DataStore, ) -> TensorDataMeaning { - let timeline = &query.timeline; + let timeline = &query.timeline(); if store.entity_has_component(timeline, entity_path, &DepthImage::indicator().name()) { TensorDataMeaning::Depth } else if store.entity_has_component( diff --git a/crates/re_data_ui/src/instance_path.rs b/crates/re_data_ui/src/instance_path.rs index 3afeaed83944..192c4206d470 100644 --- a/crates/re_data_ui/src/instance_path.rs +++ b/crates/re_data_ui/src/instance_path.rs @@ -20,12 +20,12 @@ impl DataUi for InstancePath { instance_key, } = self; - let Some(components) = store.all_components(&query.timeline, entity_path) else { + let Some(components) = store.all_components(&query.timeline(), entity_path) else { if ctx.recording().is_known_entity(entity_path) { // This is fine - e.g. we're looking at `/world` and the user has only logged to `/world/car`. ui.label(format!( "No components logged on timeline {:?}", - query.timeline.name() + query.timeline().name() )); } else { ui.label( diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index db25d48b83fb..d2a90128ac9b 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -68,7 +68,7 @@ pub fn entity_path_parts_buttons( // Show one single icon up-front instead: let instance_path = InstancePath::entity_splat(entity_path.clone()); - ui.add(instance_path_icon(&query.timeline, store, &instance_path).as_image()); + ui.add(instance_path_icon(&query.timeline(), store, &instance_path).as_image()); let mut accumulated = Vec::new(); for part in entity_path.iter() { @@ -186,7 +186,7 @@ pub fn guess_instance_path_icon( instance_path: &InstancePath, ) -> &'static icons::Icon { let (query, store) = guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); - instance_path_icon(&query.timeline, store, instance_path) + instance_path_icon(&query.timeline(), store, instance_path) } /// Show an instance id and make it selectable. @@ -232,7 +232,7 @@ fn instance_path_button_to_ex( let response = if with_icon { ctx.re_ui.selectable_label_with_icon( ui, - instance_path_icon(&query.timeline, store, instance_path), + instance_path_icon(&query.timeline(), store, instance_path), text, ctx.selection().contains_item(&item), re_ui::LabelStyle::Normal, @@ -263,7 +263,7 @@ pub fn instance_path_parts_buttons( ui.spacing_mut().item_spacing.x = 2.0; // Show one single icon up-front instead: - ui.add(instance_path_icon(&query.timeline, store, instance_path).as_image()); + ui.add(instance_path_icon(&query.timeline(), store, instance_path).as_image()); let mut accumulated = Vec::new(); for part in instance_path.entity_path.iter() { @@ -530,7 +530,7 @@ pub fn instance_hover_card_ui( if instance_path.instance_key.is_splat() { if let Some(subtree) = ctx.recording().tree().subtree(&instance_path.entity_path) { - entity_tree_stats_ui(ui, &query.timeline, subtree); + entity_tree_stats_ui(ui, &query.timeline(), subtree); } } else { // TODO(emilk): per-component stats diff --git a/crates/re_entity_db/examples/memory_usage.rs b/crates/re_entity_db/examples/memory_usage.rs index dd56faf8a728..608ec9d3b0b2 100644 --- a/crates/re_entity_db/examples/memory_usage.rs +++ b/crates/re_entity_db/examples/memory_usage.rs @@ -95,7 +95,7 @@ fn log_messages() { let store_id = StoreId::random(StoreKind::Recording); let timeline = Timeline::new_sequence("frame_nr"); let mut time_point = TimePoint::default(); - time_point.insert(timeline, TimeInt::from(0)); + time_point.insert(timeline, TimeInt::ZERO); { let used_bytes_start = live_bytes(); @@ -111,7 +111,7 @@ fn log_messages() { DataRow::from_cells1( RowId::new(), entity_path!("points"), - [build_frame_nr(0.into())], + [build_frame_nr(TimeInt::ZERO)], 1, build_some_positions2d(1), ) @@ -138,7 +138,7 @@ fn log_messages() { DataRow::from_cells1( RowId::new(), entity_path!("points"), - [build_frame_nr(0.into())], + [build_frame_nr(TimeInt::ZERO)], NUM_POINTS as _, build_some_positions2d(NUM_POINTS), ) diff --git a/crates/re_entity_db/src/time_histogram_per_timeline.rs b/crates/re_entity_db/src/time_histogram_per_timeline.rs index 9fae9df12ba2..ca8d79f900a8 100644 --- a/crates/re_entity_db/src/time_histogram_per_timeline.rs +++ b/crates/re_entity_db/src/time_histogram_per_timeline.rs @@ -75,7 +75,7 @@ impl TimeHistogramPerTimeline { } pub fn remove(&mut self, timepoint: &TimePoint, n: u32) { - if timepoint.is_timeless() { + if timepoint.is_static() { self.num_timeless_messages = self .num_timeless_messages .checked_sub(n as u64) diff --git a/crates/re_entity_db/tests/clear.rs b/crates/re_entity_db/tests/clear.rs index 14371430d2c5..bff46b11cf88 100644 --- a/crates/re_entity_db/tests/clear.rs +++ b/crates/re_entity_db/tests/clear.rs @@ -28,7 +28,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'parent' at frame #11 and make sure we find everything back. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 10.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 10)]); let point = MyPoint::new(1.0, 2.0); let color = MyColor::from(0xFF0000FF); let row = DataRow::from_component_batches( @@ -41,11 +41,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); let got_point = db .store() .query_latest_component::(&entity_path_parent, &query) @@ -66,7 +62,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'child1' at frame #11 and make sure we find everything back. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 10.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 10)]); let point = MyPoint::new(42.0, 43.0); let row = DataRow::from_component_batches( row_id, @@ -78,11 +74,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); let got_point = db .store() .query_latest_component::(&entity_path_child1, &query) @@ -97,7 +89,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'child2' at frame #11 and make sure we find everything back. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 10.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 10)]); let color = MyColor::from(0x00AA00DD); let row = DataRow::from_component_batches( row_id, @@ -109,11 +101,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); let got_color = db .store() .query_latest_component::(&entity_path_child2, &query) @@ -130,7 +118,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'child2' at frame #11 and make sure we find everything back. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 10.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 10)]); let clear = Clear::flat(); let row = DataRow::from_component_batches( row_id, @@ -142,10 +130,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; + let query = LatestAtQuery::new(timeline_frame, 11); // parent assert!(db @@ -184,7 +169,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'child2' at frame #11 and make sure we find nothing. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 10.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 10)]); let clear = Clear::recursive(); let row = DataRow::from_component_batches( row_id, @@ -196,10 +181,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; + let query = LatestAtQuery::new(timeline_frame, 11); // parent assert!(db @@ -237,7 +219,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'parent' at frame #11 and make sure we do _not_ find it. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 9.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 9)]); let instance_key = InstanceKey(0); let row = DataRow::from_component_batches( row_id, @@ -249,11 +231,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 9.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 9); let got_instance_key = db .store() .query_latest_component::(&entity_path_parent, &query) @@ -263,11 +241,7 @@ fn clears() -> anyhow::Result<()> { } { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); assert!(db .store() .query_latest_component::(&entity_path_parent, &query) @@ -281,7 +255,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'child1' at frame #11 and make sure we do _not_ find anything. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 9.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 9)]); let point = MyPoint::new(42.0, 43.0); let color = MyColor::from(0xBBBBBBBB); let row = DataRow::from_component_batches( @@ -294,11 +268,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 9.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 9); let got_point = db .store() .query_latest_component::(&entity_path_child1, &query) @@ -315,11 +285,7 @@ fn clears() -> anyhow::Result<()> { } { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); assert!(db .store() .query_latest_component::(&entity_path_child1, &query) @@ -337,7 +303,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'child2' at frame #11 and make sure we do _not_ find anything. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 9.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 9)]); let color = MyColor::from(0x00AA00DD); let point = MyPoint::new(66.0, 666.0); let row = DataRow::from_component_batches( @@ -350,11 +316,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 9.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 9); let got_color = db .store() .query_latest_component::(&entity_path_child2, &query) @@ -371,11 +333,7 @@ fn clears() -> anyhow::Result<()> { } { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); assert!(db .store() .query_latest_component::(&entity_path_child2, &query) @@ -392,7 +350,7 @@ fn clears() -> anyhow::Result<()> { // * Query 'grandchild' at frame #11 and make sure we do _not_ find anything. { let row_id = RowId::new(); - let timepoint = TimePoint::from_iter([(timeline_frame, 9.into())]); + let timepoint = TimePoint::from_iter([(timeline_frame, 9)]); let color = MyColor::from(0x00AA00DD); let row = DataRow::from_component_batches( row_id, @@ -404,11 +362,7 @@ fn clears() -> anyhow::Result<()> { db.add_data_row(row)?; { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 9.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 9); let got_color = db .store() .query_latest_component::(&entity_path_grandchild, &query) @@ -419,11 +373,7 @@ fn clears() -> anyhow::Result<()> { } { - let query = LatestAtQuery { - timeline: timeline_frame, - at: 11.into(), - }; - + let query = LatestAtQuery::new(timeline_frame, 11); assert!(db .store() .query_latest_component::(&entity_path_grandchild, &query) @@ -441,7 +391,7 @@ fn clear_and_gc() -> anyhow::Result<()> { let mut db = EntityDb::new(StoreId::random(re_log_types::StoreKind::Recording)); - let timepoint = TimePoint::timeless(); + let timepoint = TimePoint::default(); let entity_path: EntityPath = "space_view".into(); // Insert a component, then clear it, then GC. diff --git a/crates/re_entity_db/tests/time_histograms.rs b/crates/re_entity_db/tests/time_histograms.rs index 72621e9ca638..e62aeaabc2fa 100644 --- a/crates/re_entity_db/tests/time_histograms.rs +++ b/crates/re_entity_db/tests/time_histograms.rs @@ -36,9 +36,9 @@ fn time_histograms() -> anyhow::Result<()> { let row = DataRow::from_component_batches( RowId::new(), TimePoint::from_iter([ - (timeline_frame, 42.into()), // - (timeline_other, 666.into()), // - (timeline_yet_another, 1.into()), // + (timeline_frame, 42), // + (timeline_other, 666), // + (timeline_yet_another, 1), // ]), entity_parent.clone(), [&InstanceKey::from_iter(0..10) as _], @@ -92,8 +92,8 @@ fn time_histograms() -> anyhow::Result<()> { DataRow::from_component_batches( RowId::new(), TimePoint::from_iter([ - (timeline_frame, 42.into()), // - (timeline_yet_another, 1.into()), // + (timeline_frame, 42), // + (timeline_yet_another, 1), // ]), entity_grandchild.clone(), [&points as _, &colors as _], @@ -242,7 +242,7 @@ fn time_histograms() -> anyhow::Result<()> { let colors = vec![MyColor::from(0x00DD00FF); num_instances]; DataRow::from_component_batches( RowId::new(), - TimePoint::timeless(), + TimePoint::default(), "entity".into(), [ &InstanceKey::from_iter(0..num_instances as _) as _, @@ -333,9 +333,9 @@ fn time_histograms() -> anyhow::Result<()> { DataRow::from_component_batches( RowId::new(), TimePoint::from_iter([ - (timeline_frame, 1234.into()), // - (timeline_other, 1235.into()), // - (timeline_yet_another, 1236.into()), // + (timeline_frame, 1234), // + (timeline_other, 1235), // + (timeline_yet_another, 1236), // ]), entity_unrelated.clone(), [ @@ -459,7 +459,7 @@ fn time_histograms() -> anyhow::Result<()> { DataRow::from_component_batches( RowId::new(), TimePoint::from_iter([ - (timeline_frame, 1000.into()), // + (timeline_frame, 1000), // ]), entity_parent.clone(), [&[ClearIsRecursive(true)] as _], @@ -644,14 +644,17 @@ fn time_histograms() -> anyhow::Result<()> { /// Checks the state of the global time tracker (at the `EntityDb` level). fn assert_times_per_timeline<'a>( db: &EntityDb, - expected: impl IntoIterator + Copy + 'a]>)>, + expected: impl IntoIterator)>, ) { for (timeline, expected_times) in expected { let times = db.times_per_timeline().get(timeline); if let Some(expected) = expected_times { let times: BTreeSet<_> = times.unwrap().keys().copied().collect(); - let expected: BTreeSet<_> = expected.iter().map(|t| (*t).into()).collect(); + let expected: BTreeSet<_> = expected + .iter() + .map(|&t| TimeInt::try_from(t).unwrap()) + .collect(); similar_asserts::assert_eq!(expected, times); } else { assert!(times.is_none()); diff --git a/crates/re_log_encoding/benches/msg_encode_benchmark.rs b/crates/re_log_encoding/benches/msg_encode_benchmark.rs index 0a617069bd12..df825fffe618 100644 --- a/crates/re_log_encoding/benches/msg_encode_benchmark.rs +++ b/crates/re_log_encoding/benches/msg_encode_benchmark.rs @@ -74,7 +74,7 @@ fn mono_points_arrow(c: &mut Criterion) { [DataRow::from_cells2( RowId::ZERO, entity_path!("points", i.to_string()), - [build_frame_nr(0.into())], + [build_frame_nr(TimeInt::ZERO)], 1, (build_some_positions2d(1), build_some_colors(1)), ) @@ -132,7 +132,7 @@ fn mono_points_arrow_batched(c: &mut Criterion) { DataRow::from_cells2( RowId::ZERO, entity_path!("points", i.to_string()), - [build_frame_nr(0.into())], + [build_frame_nr(TimeInt::ZERO)], 1, (build_some_positions2d(1), build_some_colors(1)), ) @@ -188,7 +188,7 @@ fn batch_points_arrow(c: &mut Criterion) { [DataRow::from_cells2( RowId::ZERO, entity_path!("points"), - [build_frame_nr(0.into())], + [build_frame_nr(TimeInt::ZERO)], NUM_POINTS as _, ( build_some_positions2d(NUM_POINTS), diff --git a/crates/re_log_types/Cargo.toml b/crates/re_log_types/Cargo.toml index d4dcbf9ae9e9..452c7a3d2957 100644 --- a/crates/re_log_types/Cargo.toml +++ b/crates/re_log_types/Cargo.toml @@ -61,6 +61,7 @@ num-derive.workspace = true num-traits.workspace = true similar-asserts.workspace = true smallvec.workspace = true +static_assertions.workspace = true thiserror.workspace = true time = { workspace = true, features = ["formatting", "macros", "local-offset"] } typenum.workspace = true diff --git a/crates/re_log_types/src/data_row.rs b/crates/re_log_types/src/data_row.rs index 7f1b15f969e4..e77f44d651c0 100644 --- a/crates/re_log_types/src/data_row.rs +++ b/crates/re_log_types/src/data_row.rs @@ -265,8 +265,8 @@ re_types_core::delegate_arrow_tuid!(RowId as "rerun.controls.RowId"); /// # /// # let row_id = RowId::ZERO; /// # let timepoint = [ -/// # (Timeline::new_sequence("frame_nr"), 42.into()), // -/// # (Timeline::new_sequence("clock"), 666.into()), // +/// # (Timeline::new_sequence("frame_nr"), 42), // +/// # (Timeline::new_sequence("clock"), 666), // /// # ]; /// # /// let num_instances = 2; @@ -283,6 +283,8 @@ re_types_core::delegate_arrow_tuid!(RowId as "rerun.controls.RowId"); /// ).unwrap(); /// eprintln!("{row}"); /// ``` +// +// TODO(#5303): the Layout part will be outdated in the new key-less model #[derive(Debug, Clone)] pub struct DataRow { /// Auto-generated `TUID`, uniquely identifying this event and keeping track of the client's diff --git a/crates/re_log_types/src/data_table.rs b/crates/re_log_types/src/data_table.rs index 2580327e6436..9cda8014513d 100644 --- a/crates/re_log_types/src/data_table.rs +++ b/crates/re_log_types/src/data_table.rs @@ -71,7 +71,7 @@ pub type DataCellOptVec = VecDeque>; /// underlying type and likely point to shared, contiguous memory. /// /// Each cell in the column corresponds to a different row of the same column. -#[derive(Debug, Clone, PartialEq)] +#[derive(Default, Debug, Clone, PartialEq)] pub struct DataCellColumn(pub DataCellOptVec); impl std::ops::Deref for DataCellColumn { @@ -291,8 +291,8 @@ re_types_core::delegate_arrow_tuid!(TableId as "rerun.controls.TableId"); /// # /// # let timepoint = |frame_nr: i64, clock: i64| { /// # TimePoint::from([ -/// # (Timeline::new_sequence("frame_nr"), frame_nr.into()), -/// # (Timeline::new_sequence("clock"), clock.into()), +/// # (Timeline::new_sequence("frame_nr"), frame_nr), +/// # (Timeline::new_sequence("clock"), clock), /// # ]) /// # }; /// # @@ -344,6 +344,8 @@ re_types_core::delegate_arrow_tuid!(TableId as "rerun.controls.TableId"); /// # /// # assert_eq!(table_in, table_out); /// ``` +// +// TODO(#5303): the Layout part will be outdated in the new key-less model #[derive(Debug, Clone, PartialEq)] pub struct DataTable { /// Auto-generated `TUID`, uniquely identifying this batch of data and keeping track of the @@ -477,9 +479,7 @@ impl DataTable { self.col_row_id.len() as _ } - /// Fails if any row has: - /// - cells that aren't 0, 1 or `num_instances` long - /// - two or more cells share the same component type + /// Fails if any row has two or more cells share the same component type. #[inline] pub fn to_rows(&self) -> impl ExactSizeIterator> + '_ { let num_rows = self.num_rows() as usize; @@ -504,7 +504,7 @@ impl DataTable { col_timelines .iter() .filter_map(|(timeline, times)| { - times[i].map(|time| (*timeline, time.into())) + times[i].map(|time| (*timeline, crate::TimeInt::new_temporal(time))) }) .collect::>(), ), @@ -519,10 +519,17 @@ impl DataTable { /// and returns the corresponding [`TimePoint`]. #[inline] pub fn timepoint_max(&self) -> TimePoint { - let mut timepoint = TimePoint::timeless(); + let mut timepoint = TimePoint::default(); for (timeline, col_time) in &self.col_timelines { - if let Some(time) = col_time.iter().flatten().max().copied() { - timepoint.insert(*timeline, time.into()); + let time = col_time + .iter() + .flatten() + .max() + .copied() + .map(crate::TimeInt::new_temporal); + + if let Some(time) = time { + timepoint.insert(*timeline, time); } } timepoint @@ -1316,15 +1323,12 @@ impl DataTable { let mut tick = 0i64; let mut timepoint = |frame_nr: i64| { - let tp = if timeless { - TimePoint::timeless() - } else { - TimePoint::from([ - (Timeline::log_time(), Time::now().into()), - (Timeline::log_tick(), tick.into()), - (Timeline::new_sequence("frame_nr"), frame_nr.into()), - ]) - }; + let mut tp = TimePoint::default(); + if !timeless { + tp.insert(Timeline::log_time(), Time::now()); + tp.insert(Timeline::log_tick(), tick); + tp.insert(Timeline::new_sequence("frame_nr"), frame_nr); + } tick += 1; tp }; diff --git a/crates/re_log_types/src/lib.rs b/crates/re_log_types/src/lib.rs index 9319952f2bf9..46741fd35f0d 100644 --- a/crates/re_log_types/src/lib.rs +++ b/crates/re_log_types/src/lib.rs @@ -50,7 +50,9 @@ pub use self::data_table::{ pub use self::num_instances::NumInstances; pub use self::path::*; pub use self::time::{Duration, Time, TimeZone}; -pub use self::time_point::{TimeInt, TimePoint, TimeType, Timeline, TimelineName}; +pub use self::time_point::{ + NonMinI64, TimeInt, TimePoint, TimeType, Timeline, TimelineName, TryFromIntError, +}; pub use self::time_range::{TimeRange, TimeRangeF}; pub use self::time_real::TimeReal; pub use self::vec_deque_ext::{VecDequeInsertionExt, VecDequeRemovalExt, VecDequeSortingExt}; @@ -470,11 +472,17 @@ impl std::fmt::Display for StoreSource { /// Build a ([`Timeline`], [`TimeInt`]) tuple from `log_time` suitable for inserting in a [`TimePoint`]. #[inline] pub fn build_log_time(log_time: Time) -> (Timeline, TimeInt) { - (Timeline::log_time(), log_time.into()) + ( + Timeline::log_time(), + TimeInt::new_temporal(log_time.nanos_since_epoch()), + ) } /// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`TimePoint`]. #[inline] -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) +pub fn build_frame_nr(frame_nr: impl TryInto) -> (Timeline, TimeInt) { + ( + Timeline::new("frame_nr", TimeType::Sequence), + frame_nr.try_into().unwrap_or(TimeInt::MIN), + ) } diff --git a/crates/re_log_types/src/time_point/mod.rs b/crates/re_log_types/src/time_point/mod.rs index bdd4e8f4081b..0bb1ef0cd1da 100644 --- a/crates/re_log_types/src/time_point/mod.rs +++ b/crates/re_log_types/src/time_point/mod.rs @@ -1,5 +1,6 @@ use std::collections::{btree_map, BTreeMap}; +mod non_min_i64; mod time_int; mod timeline; @@ -9,6 +10,7 @@ use crate::{ }; // Re-exports +pub use non_min_i64::{NonMinI64, TryFromIntError}; pub use time_int::TimeInt; pub use timeline::{Timeline, TimelineName}; @@ -16,9 +18,9 @@ pub use timeline::{Timeline, TimelineName}; /// /// It can be represented by [`Time`], a sequence index, or a mix of several things. /// -/// If this is empty, the data is _timeless_. -/// Timeless data will show up on all timelines, past and future, -/// and will hit all time queries. In other words, it is always there. +/// If a [`TimePoint`] is empty ([`TimePoint::default`]), the data will be considered _static_. +/// Static data has no time associated with it, exists on all timelines, and unconditionally shadows +/// any temporal data of the same type. #[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct TimePoint(BTreeMap); @@ -30,27 +32,30 @@ impl From> for TimePoint { } impl TimePoint { - /// Logging to this time means the data will show upp in all timelines, - /// past and future. The time will be [`TimeInt::BEGINNING`], meaning it will - /// always be in range for any time query. - pub fn timeless() -> Self { - Self::default() - } - + #[inline] pub fn get(&self, timeline: &Timeline) -> Option<&TimeInt> { self.0.get(timeline) } - pub fn insert(&mut self, timeline: Timeline, time: TimeInt) -> Option { + #[inline] + pub fn insert(&mut self, timeline: Timeline, time: impl TryInto) -> Option { + let time = time.try_into().unwrap_or(TimeInt::MIN).max(TimeInt::MIN); self.0.insert(timeline, time) } + #[inline] + pub fn with(mut self, timeline: Timeline, time: impl TryInto) -> Self { + self.insert(timeline, time); + self + } + + #[inline] pub fn remove(&mut self, timeline: &Timeline) -> Option { self.0.remove(timeline) } #[inline] - pub fn is_timeless(&self) -> bool { + pub fn is_static(&self) -> bool { self.0.is_empty() } @@ -96,17 +101,7 @@ impl TimePoint { impl re_types_core::SizeBytes for TimePoint { #[inline] fn heap_size_bytes(&self) -> u64 { - type K = Timeline; - type V = TimeInt; - - // NOTE: This is only here to make sure this method fails to compile if the inner type - // changes, as the following size computation assumes POD types. - let inner: &BTreeMap = &self.0; - - let keys_size_bytes = std::mem::size_of::() * inner.len(); - let values_size_bytes = std::mem::size_of::() * inner.len(); - - (keys_size_bytes + values_size_bytes) as u64 + self.0.heap_size_bytes() } } @@ -124,6 +119,7 @@ pub enum TimeType { } impl TimeType { + #[inline] fn hash(&self) -> u64 { match self { Self::Time => 0, @@ -131,23 +127,26 @@ impl TimeType { } } + #[inline] pub fn format(&self, time_int: TimeInt, time_zone_for_timestamps: TimeZone) -> String { - if time_int <= TimeInt::BEGINNING { - "-∞".into() - } else if time_int >= TimeInt::MAX { - "+∞".into() - } else { - match self { + match time_int { + TimeInt::STATIC => "".into(), + // TODO(#5264): remove time panel hack once we migrate to the new static UI + TimeInt::MIN | TimeInt::MIN_TIME_PANEL => "-∞".into(), + TimeInt::MAX => "+∞".into(), + _ => match self { Self::Time => Time::from(time_int).format(time_zone_for_timestamps), - Self::Sequence => format!("#{}", re_format::format_int(time_int.0)), - } + Self::Sequence => format!("#{}", re_format::format_int(time_int.as_i64())), + }, } } + #[inline] pub fn format_utc(&self, time_int: TimeInt) -> String { self.format(time_int, TimeZone::Utc) } + #[inline] pub fn format_range( &self, time_range: TimeRange, @@ -155,11 +154,12 @@ impl TimeType { ) -> String { format!( "{}..={}", - self.format(time_range.min, time_zone_for_timestamps), - self.format(time_range.max, time_zone_for_timestamps) + self.format(time_range.min(), time_zone_for_timestamps), + self.format(time_range.max(), time_zone_for_timestamps) ) } + #[inline] pub fn format_range_utc(&self, time_range: TimeRange) -> String { self.format_range(time_range, TimeZone::Utc) } @@ -189,16 +189,31 @@ impl<'a> IntoIterator for &'a TimePoint { } } -impl FromIterator<(Timeline, TimeInt)> for TimePoint { +impl> FromIterator<(Timeline, T)> for TimePoint { #[inline] - fn from_iter>(iter: T) -> Self { - Self(iter.into_iter().collect()) + fn from_iter>(iter: I) -> Self { + Self( + iter.into_iter() + .map(|(timeline, time)| { + let time = time.try_into().unwrap_or(TimeInt::MIN).max(TimeInt::MIN); + (timeline, time) + }) + .collect(), + ) } } -impl From<[(Timeline, TimeInt); N]> for TimePoint { +impl, const N: usize> From<[(Timeline, T); N]> for TimePoint { #[inline] - fn from(timelines: [(Timeline, TimeInt); N]) -> Self { - Self(timelines.into_iter().collect()) + fn from(timelines: [(Timeline, T); N]) -> Self { + Self( + timelines + .into_iter() + .map(|(timeline, time)| { + let time = time.try_into().unwrap_or(TimeInt::MIN).max(TimeInt::MIN); + (timeline, time) + }) + .collect(), + ) } } diff --git a/crates/re_log_types/src/time_point/non_min_i64.rs b/crates/re_log_types/src/time_point/non_min_i64.rs new file mode 100644 index 000000000000..1d0276f82859 --- /dev/null +++ b/crates/re_log_types/src/time_point/non_min_i64.rs @@ -0,0 +1,196 @@ +// Adapted from because we want a `NonMinI64`, while `nonmax` +// only provides `NonMaxI64`. +// +// Copyright (c) 2020 Lucien Greathouse | MIT or Apache 2 + +// We need unsafety in order to hijack `NonZeroI64` for our purposes. +#![allow( + unsafe_code, + clippy::undocumented_unsafe_blocks, + unsafe_op_in_unsafe_fn +)] + +// --- + +/// An error type returned when a checked integral type conversion fails (mimics [`std::num::TryFromIntError`]) +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct TryFromIntError; + +impl std::error::Error for TryFromIntError {} + +impl core::fmt::Display for TryFromIntError { + fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + "out of range integral type conversion attempted".fmt(fmt) + } +} + +impl From for TryFromIntError { + fn from(_: core::num::TryFromIntError) -> Self { + Self + } +} + +impl From for TryFromIntError { + fn from(never: core::convert::Infallible) -> Self { + match never {} + } +} + +/// --- + +/// An integer that is known not to equal its minimum value. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[repr(transparent)] +pub struct NonMinI64(core::num::NonZeroI64); + +impl PartialOrd for NonMinI64 { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for NonMinI64 { + #[inline] + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.get().cmp(&other.get()) + } +} + +impl NonMinI64 { + pub const ZERO: NonMinI64 = unsafe { Self::new_unchecked(0) }; + pub const ONE: NonMinI64 = unsafe { Self::new_unchecked(1) }; + pub const MIN: NonMinI64 = unsafe { Self::new_unchecked(i64::MIN + 1) }; + pub const MAX: NonMinI64 = unsafe { Self::new_unchecked(i64::MAX) }; + + /// Creates a new non-min if the given value is not the minimum value. + #[inline] + pub const fn new(value: i64) -> Option { + match core::num::NonZeroI64::new(value ^ i64::MIN) { + None => None, + Some(value) => Some(Self(value)), + } + } + + /// Creates a new non-min without checking the value. + /// + /// # Safety + /// + /// The value must not equal the minimum representable value for the + /// primitive type. + #[inline] + pub const unsafe fn new_unchecked(value: i64) -> Self { + let inner = core::num::NonZeroI64::new_unchecked(value ^ i64::MIN); + Self(inner) + } + + /// Returns the value as a primitive type. + #[inline] + pub const fn get(&self) -> i64 { + self.0.get() ^ i64::MIN + } +} + +impl Default for NonMinI64 { + #[inline] + fn default() -> Self { + Self::ZERO + } +} + +impl From for i64 { + #[inline] + fn from(value: NonMinI64) -> Self { + value.get() + } +} + +impl core::convert::TryFrom for NonMinI64 { + type Error = TryFromIntError; + + #[inline] + fn try_from(value: i64) -> Result { + Self::new(value).ok_or(TryFromIntError) + } +} + +impl core::ops::BitAnd for NonMinI64 { + type Output = NonMinI64; + + #[inline] + fn bitand(self, rhs: NonMinI64) -> Self::Output { + unsafe { NonMinI64::new_unchecked(self.get() & rhs.get()) } + } +} + +impl core::ops::BitAndAssign for NonMinI64 { + #[inline] + fn bitand_assign(&mut self, rhs: NonMinI64) { + *self = *self & rhs; + } +} + +impl core::fmt::Debug for NonMinI64 { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Debug::fmt(&self.get(), f) + } +} + +impl core::fmt::Display for NonMinI64 { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Display::fmt(&self.get(), f) + } +} + +impl core::fmt::Binary for NonMinI64 { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Binary::fmt(&self.get(), f) + } +} + +impl core::fmt::Octal for NonMinI64 { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::Octal::fmt(&self.get(), f) + } +} + +impl core::fmt::LowerHex for NonMinI64 { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::LowerHex::fmt(&self.get(), f) + } +} + +impl core::fmt::UpperHex for NonMinI64 { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + core::fmt::UpperHex::fmt(&self.get(), f) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for NonMinI64 { + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.get().serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for NonMinI64 { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let value = i64::deserialize(deserializer)?; + Self::try_from(value).map_err(serde::de::Error::custom) + } +} diff --git a/crates/re_log_types/src/time_point/time_int.rs b/crates/re_log_types/src/time_point/time_int.rs index de13e0d624df..3ad4960710cc 100644 --- a/crates/re_log_types/src/time_point/time_int.rs +++ b/crates/re_log_types/src/time_point/time_int.rs @@ -1,15 +1,16 @@ -use crate::time::{Duration, Time}; +use crate::{time::Time, Duration, NonMinI64, TryFromIntError}; -/// A 64-bit number describing either nanoseconds OR sequence numbers. +/// A 64-bit number describing either nanoseconds, sequence numbers or fully static data. /// /// Must be matched with a [`crate::TimeType`] to know what. /// /// Used both for time points and durations. -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -pub struct TimeInt(pub(crate) i64); +pub struct TimeInt(Option); -impl nohash_hasher::IsEnabled for TimeInt {} +static_assertions::assert_eq_size!(TimeInt, i64); +static_assertions::assert_eq_align!(TimeInt, i64); impl re_types_core::SizeBytes for TimeInt { #[inline] @@ -18,84 +19,144 @@ impl re_types_core::SizeBytes for TimeInt { } } +impl std::fmt::Debug for TimeInt { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.0 { + Some(NonMinI64::MIN) => f + .debug_tuple("TimeInt::MIN") + .field(&NonMinI64::MIN) + .finish(), + Some(NonMinI64::MAX) => f + .debug_tuple("TimeInt::MAX") + .field(&NonMinI64::MAX) + .finish(), + Some(t) => f.debug_tuple("TimeInt").field(&t).finish(), + None => f.debug_tuple("TimeInt::STATIC").finish(), + } + } +} + impl TimeInt { - /// The beginning of time. + /// Hack. + /// + /// Special value used to represent timeless data in the time panel. + /// + /// The reason we don't use i64::MIN is because in the time panel we need + /// to be able to pan to before the [`TimeInt::MIN`], and so we need + /// a bit of leeway. + // + // TODO(#5264): remove this once we migrate to the new static UI + #[doc(hidden)] + pub const MIN_TIME_PANEL: Self = Self(NonMinI64::new(i64::MIN / 2)); + + /// Special value used to represent static data. /// - /// Special value used for timeless data. + /// It is illegal to create a [`TimeInt`] with that value in a temporal context. /// - /// NOTE: this is not necessarily [`i64::MIN`]. - // The reason we don't use i64::MIN is because in the time panel we need - // to be able to pan to before the `TimeInt::BEGINNING`, and so we need - // a bit of leeway. - pub const BEGINNING: Self = Self(i64::MIN / 2); + /// SDK users cannot log data at that timestamp explicitly, the only way to do so is to use + /// the timeless APIs. + pub const STATIC: Self = Self(None); - // TODO(#4832): `TimeInt::BEGINNING` vs. `TimeInt::MIN` vs. `Option`… - pub const MIN: Self = Self(i64::MIN); - pub const MAX: Self = Self(i64::MAX); + /// Value used to represent the minimal temporal value a [`TimeInt`] can hold. + /// + /// This is _not_ `i64::MIN`, as that is a special value reserved as a marker for static + /// data (see [`Self::STATIC`]). + pub const MIN: Self = Self(Some(NonMinI64::MIN)); + + /// Value used to represent the maximum temporal value a [`TimeInt`] can hold. + pub const MAX: Self = Self(Some(NonMinI64::MAX)); + + pub const ZERO: Self = Self(Some(NonMinI64::ZERO)); + + pub const ONE: Self = Self(Some(NonMinI64::ONE)); - /// For time timelines. #[inline] - pub fn from_nanos(nanos: i64) -> Self { - Self(nanos) + pub fn is_static(&self) -> bool { + *self == Self::STATIC } - /// For time timelines. + /// Creates a new temporal [`TimeInt`]. + /// + /// If `time` is `i64::MIN`, this will return [`TimeInt::MIN`]. + /// + /// This can't return [`TimeInt::STATIC`], ever. #[inline] - pub fn from_milliseconds(millis: i64) -> Self { - Self::from_nanos(millis * 1_000_000) + pub fn new_temporal(time: i64) -> TimeInt { + NonMinI64::new(time).map_or(Self::MIN, |t| Self(Some(t))) } /// For time timelines. #[inline] - pub fn from_seconds(seconds: i64) -> Self { - Self::from_nanos(seconds.saturating_mul(1_000_000_000)) + pub fn from_nanos(nanos: NonMinI64) -> Self { + Self(Some(nanos)) } - /// For sequence timelines. + /// For time timelines. #[inline] - pub fn from_sequence(sequence: i64) -> Self { - Self(sequence) + pub fn from_milliseconds(millis: NonMinI64) -> Self { + Self::new_temporal(millis.get().saturating_mul(1_000_000)) } + /// For time timelines. #[inline] - pub fn as_i64(&self) -> i64 { - self.0 + pub fn from_seconds(seconds: NonMinI64) -> Self { + Self::new_temporal(seconds.get().saturating_mul(1_000_000_000)) } + /// For sequence timelines. #[inline] - pub fn as_f32(&self) -> f32 { - self.0 as _ + pub fn from_sequence(sequence: NonMinI64) -> Self { + Self(Some(sequence)) } + /// Returns `i64::MIN` for [`Self::STATIC`]. #[inline] - pub fn as_f64(&self) -> f64 { - self.0 as _ + pub fn as_i64(&self) -> i64 { + match self.0 { + Some(t) => t.get(), + None => i64::MIN, + } } + /// Returns `f64::MIN` for [`Self::STATIC`]. #[inline] - pub fn abs(&self) -> Self { - Self(self.0.saturating_abs()) + pub fn as_f64(&self) -> f64 { + match self.0 { + Some(t) => t.get() as _, + None => f64::MIN, + } } } -impl From for TimeInt { +impl TryFrom for TimeInt { + type Error = TryFromIntError; + #[inline] - fn from(seq: i64) -> Self { - Self(seq) + fn try_from(t: i64) -> Result { + let Some(t) = NonMinI64::new(t) else { + return Err(TryFromIntError); + }; + Ok(Self(Some(t))) } } -impl From for TimeInt { +impl From for TimeInt { #[inline] - fn from(duration: Duration) -> Self { - Self(duration.as_nanos()) + fn from(seq: NonMinI64) -> Self { + Self(Some(seq)) } } -impl From
-## Timeless data +## Static data -The [`rr.log()`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log) function has a `timeless=False` default argument. -If `timeless=True` is used instead, the entity become *timeless*. Timeless entities belong to all timelines (existing ones, and ones not yet created) and are shown leftmost in the time panel in the viewer. -This is useful for entities that aren't part of normal data capture, but set the scene for how they are shown. -For instance, if you are logging cars on a street, perhaps you want to always show a street mesh as part of the scenery, and for that it makes sense for that data to be timeless. +The [`rr.log()`](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.log) function has a `static=False` default argument. +If `static=True` is used instead, the data logged becomes *static*. Static data belongs to all timelines (existing ones, and ones not yet created) and shadows any temporal data of the same type on the same entity. +This is useful for data that isn't part of normal data capture, but sets the scene for how it should be shown. +For instance, if you are logging cars on a street, perhaps you want to always show a street mesh as part of the scenery, and for that it makes sense for that data to be static. -Similarly, [coordinate systems](spaces-and-transforms.md) or [annotation context](annotation-context.md) are typically timeless. +Similarly, [coordinate systems](spaces-and-transforms.md) or [annotation context](annotation-context.md) are typically static. diff --git a/docs/content/howto/ros2-nav-turtlebot.md b/docs/content/howto/ros2-nav-turtlebot.md index 48a62329cad0..022deb554c00 100644 --- a/docs/content/howto/ros2-nav-turtlebot.md +++ b/docs/content/howto/ros2-nav-turtlebot.md @@ -421,7 +421,7 @@ def urdf_callback(self, urdf_msg: String) -> None: rerun_urdf.log_scene(scene=scaled, node=urdf.base_link, path="map/robot/urdf", - timeless=True) + static=True) ``` Back in `rerun_urdf.log_scene` all the code is doing is recursively walking through diff --git a/docs/content/reference/data-loaders/overview.md b/docs/content/reference/data-loaders/overview.md index bb2a720d894d..0426c523f132 100644 --- a/docs/content/reference/data-loaders/overview.md +++ b/docs/content/reference/data-loaders/overview.md @@ -62,9 +62,9 @@ When the viewer and/or SDK executes an external loader, it will pass to it a set Recommended prefix to prepend to all entity paths. -* `--timeless` (optional) +* `--static` (optional) - The data is expected to be logged timelessly. + The data is expected to be logged as static. * `--time = = …` (optional) diff --git a/docs/snippets/all/annotation-context/example.py b/docs/snippets/all/annotation-context/example.py index a38613eb6007..4931b28db951 100644 --- a/docs/snippets/all/annotation-context/example.py +++ b/docs/snippets/all/annotation-context/example.py @@ -9,7 +9,7 @@ rr.AnnotationInfo(id=1, label="Person", color=(255, 0, 0)), ], ), - timeless=True, + static=True, ) # Annotation context with simple keypoints & keypoint connections. @@ -20,5 +20,5 @@ keypoint_annotations=[rr.AnnotationInfo(id=i, color=(0, 255 / 9 * i, 0)) for i in range(10)], keypoint_connections=[(i, i + 1) for i in range(9)], ), - timeless=True, + static=True, ) diff --git a/docs/snippets/all/annotation_context_connections.py b/docs/snippets/all/annotation_context_connections.py index fd3554eacef6..96c32c095caf 100644 --- a/docs/snippets/all/annotation_context_connections.py +++ b/docs/snippets/all/annotation_context_connections.py @@ -21,7 +21,7 @@ ) ] ), - timeless=True, + static=True, ) rr.log( diff --git a/docs/snippets/all/annotation_context_rects.py b/docs/snippets/all/annotation_context_rects.py index e3195b583806..1c430116d223 100644 --- a/docs/snippets/all/annotation_context_rects.py +++ b/docs/snippets/all/annotation_context_rects.py @@ -3,7 +3,7 @@ rr.init("rerun_example_annotation_context_rects", spawn=True) # Log an annotation context to assign a label and color to each class -rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), timeless=True) +rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) # Log a batch of 2 rectangles with different `class_ids` rr.log("detections", rr.Boxes2D(mins=[[-2, -2], [0, 0]], sizes=[[3, 3], [2, 2]], class_ids=[1, 2])) diff --git a/docs/snippets/all/annotation_context_segmentation.py b/docs/snippets/all/annotation_context_segmentation.py index dd51ab812d35..80a7d777fec0 100644 --- a/docs/snippets/all/annotation_context_segmentation.py +++ b/docs/snippets/all/annotation_context_segmentation.py @@ -11,6 +11,6 @@ image[100:180, 130:280] = 2 # Log an annotation context to assign a label and color to each class -rr.log("segmentation", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), timeless=True) +rr.log("segmentation", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) rr.log("segmentation/image", rr.SegmentationImage(image)) diff --git a/docs/snippets/all/asset3d_out_of_tree.py b/docs/snippets/all/asset3d_out_of_tree.py index 4187e10516b7..17e92649c781 100644 --- a/docs/snippets/all/asset3d_out_of_tree.py +++ b/docs/snippets/all/asset3d_out_of_tree.py @@ -12,7 +12,7 @@ rr.init("rerun_example_asset3d_out_of_tree", spawn=True) -rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) # Set an up-axis +rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # Set an up-axis rr.set_time_sequence("frame", 0) rr.log("world/asset", rr.Asset3D(path=sys.argv[1])) diff --git a/docs/snippets/all/asset3d_simple.py b/docs/snippets/all/asset3d_simple.py index 3a0ab487251e..6b1e0b473cfd 100644 --- a/docs/snippets/all/asset3d_simple.py +++ b/docs/snippets/all/asset3d_simple.py @@ -9,5 +9,5 @@ rr.init("rerun_example_asset3d", spawn=True) -rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) # Set an up-axis +rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # Set an up-axis rr.log("world/asset", rr.Asset3D(path=sys.argv[1])) diff --git a/docs/snippets/all/scalar_multiple_plots.py b/docs/snippets/all/scalar_multiple_plots.py index 4761c0d526be..1ce342e9e09e 100644 --- a/docs/snippets/all/scalar_multiple_plots.py +++ b/docs/snippets/all/scalar_multiple_plots.py @@ -9,12 +9,12 @@ lcg_state = np.int64(0) # Set up plot styling: -# They are logged timeless as they don't change over time and apply to all timelines. +# They are logged as static as they don't change over time and apply to all timelines. # Log two lines series under a shared root so that they show in the same plot by default. -rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), timeless=True) -rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), timeless=True) +rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) +rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) # Log scattered points under a different root so that they show in a different plot by default. -rr.log("scatter/lcg", rr.SeriesPoint(), timeless=True) +rr.log("scatter/lcg", rr.SeriesPoint(), static=True) # Log the data on a timeline called "step". for t in range(0, int(tau * 2 * 100.0)): diff --git a/docs/snippets/all/segmentation_image_simple.py b/docs/snippets/all/segmentation_image_simple.py index 064abffb44c3..f75d95dd4a06 100644 --- a/docs/snippets/all/segmentation_image_simple.py +++ b/docs/snippets/all/segmentation_image_simple.py @@ -11,6 +11,6 @@ rr.init("rerun_example_segmentation_image", spawn=True) # Assign a label and color to each class -rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), timeless=True) +rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) rr.log("image", rr.SegmentationImage(image)) diff --git a/docs/snippets/all/series_line_style.py b/docs/snippets/all/series_line_style.py index 373cc7a2540b..e4518ac07fe7 100644 --- a/docs/snippets/all/series_line_style.py +++ b/docs/snippets/all/series_line_style.py @@ -7,10 +7,10 @@ rr.init("rerun_example_series_line_style", spawn=True) # Set up plot styling: -# They are logged timeless as they don't change over time and apply to all timelines. +# They are logged as static as they don't change over time and apply to all timelines. # Log two lines series under a shared root so that they show in the same plot by default. -rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)", width=2), timeless=True) -rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)", width=4), timeless=True) +rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)", width=2), static=True) +rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)", width=4), static=True) # Log the data on a timeline called "step". for t in range(0, int(tau * 2 * 100.0)): diff --git a/docs/snippets/all/series_point_style.py b/docs/snippets/all/series_point_style.py index 258445d6e337..c5451adf83ae 100644 --- a/docs/snippets/all/series_point_style.py +++ b/docs/snippets/all/series_point_style.py @@ -7,7 +7,7 @@ rr.init("rerun_example_series_point_style", spawn=True) # Set up plot styling: -# They are logged timeless as they don't change over time and apply to all timelines. +# They are logged as static as they don't change over time and apply to all timelines. # Log two point series under a shared root so that they show in the same plot by default. rr.log( "trig/sin", @@ -17,7 +17,7 @@ marker="circle", marker_size=4, ), - timeless=True, + static=True, ) rr.log( "trig/cos", @@ -27,7 +27,7 @@ marker="cross", marker_size=2, ), - timeless=True, + static=True, ) # Log the data on a timeline called "step". diff --git a/docs/snippets/all/view_coordinates_simple.py b/docs/snippets/all/view_coordinates_simple.py index 5b84d6511177..208efc8499fb 100644 --- a/docs/snippets/all/view_coordinates_simple.py +++ b/docs/snippets/all/view_coordinates_simple.py @@ -4,7 +4,7 @@ rr.init("rerun_example_view_coordinates", spawn=True) -rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) # Set an up-axis +rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # Set an up-axis rr.log( "world/xyz", rr.Arrows3D( diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py index ff0cbbda27a9..39abed19a591 100755 --- a/examples/python/arkit_scenes/main.py +++ b/examples/python/arkit_scenes/main.py @@ -70,10 +70,10 @@ vertex_colors=mesh.visual.vertex_colors, indices=mesh.faces, ), - timeless=True, + static=True, ) ``` -Here, the mesh is logged to the [world/mesh entity](recording://world/mesh) and is marked as timeless, since it does not +Here, the mesh is logged to the [world/mesh entity](recording://world/mesh) and is marked as static, since it does not change in the context of this visualization. ### 3D bounding boxes @@ -121,7 +121,7 @@ def log_annotated_bboxes(annotation: dict[str, Any]) -> None: rotations=rr.Quaternion(xyzw=rot.as_quat()), labels=label, ), - timeless=True, + static=True, ) @@ -213,7 +213,7 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: None """ - rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) video_id = recording_path.stem lowres_image_dir = recording_path / "lowres_wide" @@ -242,7 +242,7 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: timestamp = f"{round(float(timestamp), 3):.3f}" camera_from_world_dict[timestamp] = camera_from_world - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) ply_path = recording_path / f"{recording_path.stem}_3dod_mesh.ply" print(f"Loading {ply_path}…") assert os.path.isfile(ply_path), f"Failed to find {ply_path}" @@ -255,7 +255,7 @@ def log_arkit(recording_path: Path, include_highres: bool) -> None: vertex_colors=mesh.visual.vertex_colors, indices=mesh.faces, ), - timeless=True, + static=True, ) # load the obb annotations and log them in the world frame diff --git a/examples/python/clock/main.py b/examples/python/clock/main.py index cb6a78506286..772ae92a918a 100755 --- a/examples/python/clock/main.py +++ b/examples/python/clock/main.py @@ -30,12 +30,12 @@ def rotate(angle: float, len: float) -> tuple[float, float, float]: 0.0, ) - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, timeless=True) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True) rr.log( "world/frame", rr.Boxes3D(half_sizes=[LENGTH_S, LENGTH_S, 1.0], centers=[0.0, 0.0, 0.0]), - timeless=True, + static=True, ) for step in range(steps): diff --git a/examples/python/controlnet/main.py b/examples/python/controlnet/main.py index 1b2f9f03f79d..650a0bfca42b 100755 --- a/examples/python/controlnet/main.py +++ b/examples/python/controlnet/main.py @@ -74,8 +74,8 @@ def run_canny_controlnet(image_path: str, prompt: str, negative_prompt: str) -> canny_image = np.concatenate([canny_image, canny_image, canny_image], axis=2) canny_image = PIL.Image.fromarray(canny_image) - rr.log("input/raw", rr.Image(image), timeless=True) - rr.log("input/canny", rr.Image(canny_image), timeless=True) + rr.log("input/raw", rr.Image(image), static=True) + rr.log("input/canny", rr.Image(canny_image), static=True) controlnet = ControlNetModel.from_pretrained( "diffusers/controlnet-canny-sdxl-1.0", @@ -95,8 +95,8 @@ def run_canny_controlnet(image_path: str, prompt: str, negative_prompt: str) -> pipeline.enable_model_cpu_offload() - rr.log("positive_prompt", rr.TextDocument(prompt), timeless=True) - rr.log("negative_prompt", rr.TextDocument(negative_prompt), timeless=True) + rr.log("positive_prompt", rr.TextDocument(prompt), static=True) + rr.log("negative_prompt", rr.TextDocument(negative_prompt), static=True) images = pipeline( prompt, diff --git a/examples/python/detect_and_track_objects/main.py b/examples/python/detect_and_track_objects/main.py index f2d386ffc9d6..bca83a637035 100755 --- a/examples/python/detect_and_track_objects/main.py +++ b/examples/python/detect_and_track_objects/main.py @@ -62,7 +62,7 @@ The color and label for each class is determined by the [rr.AnnotationContext archetype](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is -logged to the root entity using `rr.log("/", …, timeless=True` as it should apply to the whole sequence and all +logged to the root entity using `rr.log("/", …, static=True` as it should apply to the whole sequence and all entities that have a class id. ### Detections @@ -369,7 +369,7 @@ def track_objects(video_path: str, *, max_frame_count: int | None) -> None: class_descriptions = [ rr.AnnotationInfo(id=cat["id"], color=cat["color"], label=cat["name"]) for cat in coco_categories ] - rr.log("/", rr.AnnotationContext(class_descriptions), timeless=True) + rr.log("/", rr.AnnotationContext(class_descriptions), static=True) detector = Detector(coco_categories=coco_categories) @@ -460,7 +460,7 @@ def main() -> None: setup_logging() - rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) video_path: str = args.video_path if not video_path: diff --git a/examples/python/dicom_mri/main.py b/examples/python/dicom_mri/main.py index a207ebb4ed07..0d832c0f27f2 100755 --- a/examples/python/dicom_mri/main.py +++ b/examples/python/dicom_mri/main.py @@ -71,7 +71,7 @@ def list_dicom_files(dir: Path) -> Iterable[Path]: def read_and_log_dicom_dataset(dicom_files: Iterable[Path]) -> None: - rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) voxels_volume, _ = extract_voxel_data(dicom_files) diff --git a/examples/python/dna/main.py b/examples/python/dna/main.py index e0168a453b4d..1fab3ae3c3bd 100755 --- a/examples/python/dna/main.py +++ b/examples/python/dna/main.py @@ -47,7 +47,7 @@ def log_data() -> None: - rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) rr.set_time_seconds("stable_time", 0) diff --git a/examples/python/external_data_loader/main.py b/examples/python/external_data_loader/main.py index b9f4621c11e9..c9cf0a7601dc 100755 --- a/examples/python/external_data_loader/main.py +++ b/examples/python/external_data_loader/main.py @@ -34,9 +34,8 @@ parser.add_argument("--application-id", type=str, help="optional recommended ID for the application") parser.add_argument("--recording-id", type=str, help="optional recommended ID for the recording") parser.add_argument("--entity-path-prefix", type=str, help="optional prefix for all entity paths") -parser.add_argument( - "--timeless", action="store_true", default=False, help="optionally mark data to be logged as timeless" -) +parser.add_argument("--timeless", action="store_true", default=False, help="deprecated: alias for `--static`") +parser.add_argument("--static", action="store_true", default=False, help="optionally mark data to be logged as static") parser.add_argument( "--time", type=str, @@ -77,7 +76,9 @@ def main() -> None: with open(args.filepath) as file: body = file.read() text = f"""## Some Python code\n```python\n{body}\n```\n""" - rr.log(entity_path, rr.TextDocument(text, media_type=rr.MediaType.MARKDOWN), timeless=args.timeless) + rr.log( + entity_path, rr.TextDocument(text, media_type=rr.MediaType.MARKDOWN), static=args.static or args.timeless + ) def set_time_from_args() -> None: diff --git a/examples/python/face_tracking/main.py b/examples/python/face_tracking/main.py index e017e90483c6..7f27a0118bb7 100755 --- a/examples/python/face_tracking/main.py +++ b/examples/python/face_tracking/main.py @@ -120,7 +120,7 @@ def __init__(self, video_mode: bool = False): rr.ClassDescription( info=rr.AnnotationInfo(id=0), keypoint_connections=[(0, 1), (1, 2), (2, 0), (2, 3), (0, 4), (1, 5)] ), - timeless=True, + static=True, ) def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> None: @@ -223,11 +223,11 @@ def __init__(self, video_mode: bool = False, num_faces: int = 1): ) ) - rr.log("video/landmarker", rr.AnnotationContext(class_descriptions), timeless=True) - rr.log("reconstruction", rr.AnnotationContext(class_descriptions), timeless=True) + rr.log("video/landmarker", rr.AnnotationContext(class_descriptions), static=True) + rr.log("reconstruction", rr.AnnotationContext(class_descriptions), static=True) # properly align the 3D face in the viewer - rr.log("reconstruction", rr.ViewCoordinates.RDF, timeless=True) + rr.log("reconstruction", rr.ViewCoordinates.RDF, static=True) def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> None: height, width, _ = image.shape diff --git a/examples/python/gesture_detection/README.md b/examples/python/gesture_detection/README.md index d8d6e72d08aa..6f0402292a60 100644 --- a/examples/python/gesture_detection/README.md +++ b/examples/python/gesture_detection/README.md @@ -58,7 +58,7 @@ Meanwhile, the 3D points allows the creation of a 3D model of the hand for a mor The 2D and 3D points are logged through a combination of two archetypes. For the 2D points, the Points2D and LineStrips2D archetypes are utilized. These archetypes help visualize the points and connect them with lines, respectively. -As for the 3D points, the logging process involves two steps. First, a timeless [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description) is logged, that contains the information which maps keypoint ids to labels and how to connect +As for the 3D points, the logging process involves two steps. First, a static [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description) is logged, that contains the information which maps keypoint ids to labels and how to connect the keypoints. Defining these connections automatically renders lines between them. Mediapipe provides the `HAND_CONNECTIONS` variable which contains the list of `(from, to)` landmark indices that define the connections. Second, the actual keypoint positions are logged in 3D [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype. @@ -73,10 +73,10 @@ rr.log( keypoint_connections=mp.solutions.hands.HAND_CONNECTIONS, ) ), - timeless=True, + static=True, ) -rr.log("Hand3D", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, timeless=True) +rr.log("Hand3D", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, static=True) ``` ### 2D Points diff --git a/examples/python/gesture_detection/main.py b/examples/python/gesture_detection/main.py index 5e04ac9e76d5..fd622bd63167 100755 --- a/examples/python/gesture_detection/main.py +++ b/examples/python/gesture_detection/main.py @@ -86,9 +86,9 @@ def __init__(self, video_mode: bool = False): keypoint_connections=mp.solutions.hands.HAND_CONNECTIONS, ) ), - timeless=True, + static=True, ) - rr.log("hand3d", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, timeless=True) + rr.log("hand3d", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, static=True) @staticmethod def convert_landmarks_to_image_coordinates( diff --git a/examples/python/human_pose_tracking/README.md b/examples/python/human_pose_tracking/README.md index 04322df3c82b..96dd9d68aa41 100644 --- a/examples/python/human_pose_tracking/README.md +++ b/examples/python/human_pose_tracking/README.md @@ -60,7 +60,7 @@ image itself is logged as an [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) and contains the id for each pixel. The color is determined by the [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is -logged with `timeless=True` as it should apply to the whole sequence. +logged with `static=True` as it should apply to the whole sequence. ### Label mapping @@ -73,7 +73,7 @@ rr.log( rr.AnnotationInfo(id=1, label="Person", color=(0, 0, 0)), ] ), - timeless=True, + static=True, ) ``` @@ -111,7 +111,7 @@ rr.log( keypoint_connections=mp_pose.POSE_CONNECTIONS, ) ), - timeless=True, + static=True, ) ``` diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py index e10089c0131e..7b0824e26776 100755 --- a/examples/python/human_pose_tracking/main.py +++ b/examples/python/human_pose_tracking/main.py @@ -41,13 +41,13 @@ [rr.SegmentationImage archetype](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) and contains the id for each pixel. The color is determined by the [rr.AnnotationContext archetype](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is -logged with `rr.log(…, timeless=True` as it should apply to the whole sequence. +logged with `rr.log(…, static=True` as it should apply to the whole sequence. ### Skeletons The [2D](recording://video/pose/points) and [3D skeletons](recording://person/pose/points) are also logged through a similar combination of two entities. -First, a timeless +First, a static [rr.ClassDescription](https://www.rerun.io/docs/reference/types/datatypes/class_description) is logged (note, that this is equivalent to logging an [rr.AnnotationContext archetype](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) as in the @@ -63,7 +63,7 @@ def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) -> None: mp_pose = mp.solutions.pose - rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) rr.log( "/", @@ -74,7 +74,7 @@ def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) - keypoint_connections=mp_pose.POSE_CONNECTIONS, ) ), - timeless=True, + static=True, ) # Use a separate annotation context for the segmentation mask. rr.log( @@ -85,9 +85,9 @@ def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) - rr.AnnotationInfo(id=1, label="Person", color=(0, 0, 0)), ] ), - timeless=True, + static=True, ) - rr.log("person", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, timeless=True) + rr.log("person", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, static=True) with closing(VideoSource(video_path)) as video_source, mp_pose.Pose(enable_segmentation=segment) as pose: for idx, bgr_frame in enumerate(video_source.stream_bgr()): diff --git a/examples/python/incremental_logging/main.py b/examples/python/incremental_logging/main.py index 933d24b76750..cd2e67dfc9f0 100755 --- a/examples/python/incremental_logging/main.py +++ b/examples/python/incremental_logging/main.py @@ -44,7 +44,7 @@ rr.script_setup(args, "rerun_example_incremental_logging") -rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) +rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) # TODO(#5264): just log one once clamp-to-edge semantics land. colors = rr.components.ColorBatch(np.repeat(0xFF0000FF, 10)) @@ -53,8 +53,8 @@ # Only log colors and radii once. rr.set_time_sequence("frame_nr", 0) rr.log_components("points", [colors, radii]) -# Logging timelessly would also work. -# rr.log_components("points", [colors, radii], timeless=True) +# Logging as static would also work. +# rr.log_components("points", [colors, radii], static=True) rng = default_rng(12345) diff --git a/examples/python/lidar/main.py b/examples/python/lidar/main.py index 31aeaed0f85d..a61a4662fec2 100755 --- a/examples/python/lidar/main.py +++ b/examples/python/lidar/main.py @@ -52,7 +52,7 @@ def log_nuscenes_lidar(root_dir: pathlib.Path, dataset_version: str, scene_name: scene = next(s for s in nusc.scene if s["name"] == scene_name) - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) first_sample = nusc.get("sample", scene["first_sample_token"]) current_lidar_token = first_sample["data"]["LIDAR_TOP"] diff --git a/examples/python/live_depth_sensor/main.py b/examples/python/live_depth_sensor/main.py index 18bef9c59d71..bfbb7bba8627 100755 --- a/examples/python/live_depth_sensor/main.py +++ b/examples/python/live_depth_sensor/main.py @@ -11,7 +11,7 @@ def run_realsense(num_frames: int | None) -> None: # Visualize the data as RDF - rr.log("realsense", rr.ViewCoordinates.RDF, timeless=True) + rr.log("realsense", rr.ViewCoordinates.RDF, static=True) # Open the pipe pipe = rs.pipeline() @@ -31,7 +31,7 @@ def run_realsense(num_frames: int | None) -> None: focal_length=[depth_intr.fx, depth_intr.fy], principal_point=[depth_intr.ppx, depth_intr.ppy], ), - timeless=True, + static=True, ) # Get and log color extrinsics @@ -45,7 +45,7 @@ def run_realsense(num_frames: int | None) -> None: mat3x3=np.reshape(rgb_from_depth.rotation, (3, 3)), from_parent=True, ), - timeless=True, + static=True, ) # Get and log color intrinsics @@ -58,7 +58,7 @@ def run_realsense(num_frames: int | None) -> None: focal_length=[rgb_intr.fx, rgb_intr.fy], principal_point=[rgb_intr.ppx, rgb_intr.ppy], ), - timeless=True, + static=True, ) # Read frames in a loop diff --git a/examples/python/nuscenes/main.py b/examples/python/nuscenes/main.py index 8072177d3682..cf7ad6ee4df6 100755 --- a/examples/python/nuscenes/main.py +++ b/examples/python/nuscenes/main.py @@ -73,7 +73,7 @@ def log_nuscenes(nusc: nuscenes.NuScenes, scene_name: str, max_time_sec: float) scene = next(s for s in nusc.scene if s["name"] == scene_name) - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) first_sample_token = scene["first_sample_token"] first_sample = nusc.get("sample", scene["first_sample_token"]) @@ -200,7 +200,7 @@ def log_annotations(first_sample_token: str, nusc: nuscenes.NuScenes, max_timest # skipping for now since labels take too much space in 3D view (see https://github.com/rerun-io/rerun/issues/4451) # annotation_context = [(i, label) for label, i in label2id.items()] - # rr.log("world/anns", rr.AnnotationContext(annotation_context), timeless=True) + # rr.log("world/anns", rr.AnnotationContext(annotation_context), static=True) def log_sensor_calibration(sample_data: dict[str, Any], nusc: nuscenes.NuScenes) -> None: @@ -216,7 +216,7 @@ def log_sensor_calibration(sample_data: dict[str, Any], nusc: nuscenes.NuScenes) rotation=rr.Quaternion(xyzw=rotation_xyzw), from_parent=False, ), - timeless=True, + static=True, ) if len(calibrated_sensor["camera_intrinsic"]) != 0: rr.log( @@ -226,7 +226,7 @@ def log_sensor_calibration(sample_data: dict[str, Any], nusc: nuscenes.NuScenes) width=sample_data["width"], height=sample_data["height"], ), - timeless=True, + static=True, ) diff --git a/examples/python/objectron/main.py b/examples/python/objectron/main.py index f07549a59c51..8f3e006f9689 100755 --- a/examples/python/objectron/main.py +++ b/examples/python/objectron/main.py @@ -105,7 +105,7 @@ def read_annotations(dirpath: Path) -> Sequence: def log_ar_frames(samples: Iterable[SampleARFrame], seq: Sequence) -> None: """Logs a stream of `ARFrame` samples and their annotations with the Rerun SDK.""" - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, timeless=True) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True) log_annotated_bboxes(seq.objects) @@ -179,7 +179,7 @@ def log_annotated_bboxes(bboxes: Iterable[Object]) -> None: colors=[160, 230, 130, 255], labels=bbox.category, ), - timeless=True, + static=True, ) diff --git a/examples/python/open_photogrammetry_format/main.py b/examples/python/open_photogrammetry_format/main.py index 70883c4b47a6..740f2bd740f8 100755 --- a/examples/python/open_photogrammetry_format/main.py +++ b/examples/python/open_photogrammetry_format/main.py @@ -113,7 +113,7 @@ def from_dataset(cls, dataset: str, log_as_frames: bool = True) -> OPFProject: def log_point_cloud(self) -> None: """Log the project's point cloud.""" points = self.project.point_cloud_objs[0].nodes[0] - rr.log("world/points", rr.Points3D(points.position, colors=points.color), timeless=True) + rr.log("world/points", rr.Points3D(points.position, colors=points.color), static=True) def log_calibrated_cameras(self, jpeg_quality: int | None) -> None: """ @@ -227,7 +227,7 @@ def main() -> None: # display everything in Rerun rr.script_setup(args, "rerun_example_open_photogrammetry_format") - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) project.log_point_cloud() project.log_calibrated_cameras(jpeg_quality=args.jpeg_quality) rr.script_teardown(args) diff --git a/examples/python/plots/main.py b/examples/python/plots/main.py index 725ea8c2dda3..ff387b32f7e6 100755 --- a/examples/python/plots/main.py +++ b/examples/python/plots/main.py @@ -39,7 +39,7 @@ archetypes respectively. For the [parabola](recording://curves/parabola) the radius and color is changed over time, -the other plots use timeless for their styling properties where possible. +the other plots use static for their styling properties where possible. [sin](recording://trig/sin) and [cos](recording://trig/cos) are logged with the same parent entity (i.e., `trig/{cos,sin}`) which will put them in the same view by default. @@ -63,7 +63,7 @@ def log_bar_chart() -> None: def log_parabola() -> None: # Name never changes, log it only once. - rr.log("curves/parabola", rr.SeriesLine(name="f(t) = (0.01t - 3)³ + 1"), timeless=True) + rr.log("curves/parabola", rr.SeriesLine(name="f(t) = (0.01t - 3)³ + 1"), static=True) # Log a parabola as a time series for t in range(0, 1000, 10): @@ -85,9 +85,9 @@ def log_parabola() -> None: def log_trig() -> None: - # Styling doesn't change over time, log it once with timeless=True. - rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), timeless=True) - rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), timeless=True) + # Styling doesn't change over time, log it once with static=True. + rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True) + rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True) for t in range(0, int(tau * 2 * 100.0)): rr.set_time_sequence("frame_nr", t) @@ -101,7 +101,7 @@ def log_trig() -> None: def log_classification() -> None: # Log components that don't change only once: - rr.log("classification/line", rr.SeriesLine(color=[255, 255, 0], width=3.0), timeless=True) + rr.log("classification/line", rr.SeriesLine(color=[255, 255, 0], width=3.0), static=True) for t in range(0, 1000, 2): rr.set_time_sequence("frame_nr", t) @@ -144,7 +144,7 @@ def main() -> None: rr.script_setup(args, "rerun_example_plot", default_blueprint=blueprint) - rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) log_bar_chart() log_parabola() log_trig() diff --git a/examples/python/raw_mesh/main.py b/examples/python/raw_mesh/main.py index 7b92e7097fd5..29bc271e80ae 100755 --- a/examples/python/raw_mesh/main.py +++ b/examples/python/raw_mesh/main.py @@ -129,7 +129,7 @@ def main() -> None: root = next(iter(scene.graph.nodes)) # glTF always uses a right-handed coordinate system when +Y is up and meshes face +Z. - rr.log(root, rr.ViewCoordinates.RUB, timeless=True) + rr.log(root, rr.ViewCoordinates.RUB, static=True) log_scene(scene, root) rr.script_teardown(args) diff --git a/examples/python/rgbd/main.py b/examples/python/rgbd/main.py index 33bf11f9f959..67e2ef564e49 100755 --- a/examples/python/rgbd/main.py +++ b/examples/python/rgbd/main.py @@ -53,7 +53,7 @@ def read_depth_image(buf: bytes) -> npt.NDArray[Any]: def log_nyud_data(recording_path: Path, subset_idx: int, frames: int) -> None: - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, timeless=True) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, static=True) with zipfile.ZipFile(recording_path, "r") as archive: archive_dirs = [f.filename for f in archive.filelist if f.is_dir()] diff --git a/examples/python/ros_node/main.py b/examples/python/ros_node/main.py index be27c6e5c2d5..2a81b01d9d48 100755 --- a/examples/python/ros_node/main.py +++ b/examples/python/ros_node/main.py @@ -85,7 +85,7 @@ def __init__(self) -> None: rr.log( "map/box", rr.Boxes3D(half_sizes=[3, 3, 1], centers=[0, 0, 1], colors=[255, 255, 255, 255]), - timeless=True, + static=True, ) # Subscriptions @@ -264,7 +264,7 @@ def urdf_callback(self, urdf_msg: String) -> None: urdf.scene.graph.update(frame_to="camera_link", matrix=orig.dot(scale)) scaled = urdf.scene.scaled(1.0) - rerun_urdf.log_scene(scene=scaled, node=urdf.base_link, path="map/robot/urdf", timeless=True) + rerun_urdf.log_scene(scene=scaled, node=urdf.base_link, path="map/robot/urdf", static=True) def main() -> None: diff --git a/examples/python/ros_node/rerun_urdf.py b/examples/python/ros_node/rerun_urdf.py index 5a498a3ecf40..527b488bd58d 100644 --- a/examples/python/ros_node/rerun_urdf.py +++ b/examples/python/ros_node/rerun_urdf.py @@ -27,7 +27,7 @@ def load_urdf_from_msg(msg: String) -> URDF: return URDF.load(f, filename_handler=ament_locate_package) -def log_scene(scene: trimesh.Scene, node: str, path: str | None = None, timeless: bool = False) -> None: +def log_scene(scene: trimesh.Scene, node: str, path: str | None = None, static: bool = False) -> None: """Log a trimesh scene to rerun.""" path = path + "/" + node if path else node @@ -46,7 +46,7 @@ def log_scene(scene: trimesh.Scene, node: str, path: str | None = None, timeless translation=world_from_mesh[3, 0:3], mat3x3=world_from_mesh[0:3, 0:3], ), - timeless=timeless, + static=static, ) # Log this node's mesh, if it has one. @@ -82,9 +82,9 @@ def log_scene(scene: trimesh.Scene, node: str, path: str | None = None, timeless vertex_normals=mesh.vertex_normals, mesh_material=rr.Material(albedo_factor=albedo_factor), ), - timeless=timeless, + static=static, ) if children: for child in children: - log_scene(scene, child, path, timeless) + log_scene(scene, child, path, static) diff --git a/examples/python/signed_distance_fields/main.py b/examples/python/signed_distance_fields/main.py index 572c184fc2db..2d2399aa486c 100755 --- a/examples/python/signed_distance_fields/main.py +++ b/examples/python/signed_distance_fields/main.py @@ -99,8 +99,8 @@ def log_mesh(path: Path, mesh: Trimesh) -> None: def log_sampled_sdf(points: npt.NDArray[np.float32], sdf: npt.NDArray[np.float32]) -> None: - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) - rr.log("world/sdf", rr.AnnotationContext([(0, "inside", (255, 0, 0)), (1, "outside", (0, 255, 0))]), timeless=False) + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) + rr.log("world/sdf", rr.AnnotationContext([(0, "inside", (255, 0, 0)), (1, "outside", (0, 255, 0))]), static=False) rr.log("world/sdf/points", rr.Points3D(points, class_ids=np.array(sdf > 0, dtype=np.uint8))) outside = points[sdf > 0] diff --git a/examples/python/structure_from_motion/main.py b/examples/python/structure_from_motion/main.py index a8f01bbd0ab7..421399afb04a 100755 --- a/examples/python/structure_from_motion/main.py +++ b/examples/python/structure_from_motion/main.py @@ -133,9 +133,9 @@ def read_and_log_sparse_reconstruction(dataset_path: Path, filter_output: bool, # Filter out noisy points points3D = {id: point for id, point in points3D.items() if point.rgb.any() and len(point.image_ids) > 4} - rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) - rr.log("/", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, timeless=True) - rr.log("plot/avg_reproj_err", rr.SeriesLine(color=[240, 45, 58]), timeless=True) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) + rr.log("/", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, static=True) + rr.log("plot/avg_reproj_err", rr.SeriesLine(color=[240, 45, 58]), static=True) # Iterate through images (video frames) logging data related to each frame. for image in sorted(images.values(), key=lambda im: im.name): # type: ignore[no-any-return] @@ -181,7 +181,7 @@ def read_and_log_sparse_reconstruction(dataset_path: Path, filter_output: bool, rr.log( "camera", rr.Transform3D(translation=image.tvec, rotation=rr.Quaternion(xyzw=quat_xyzw), from_parent=True) ) - rr.log("camera", rr.ViewCoordinates.RDF, timeless=True) # X=Right, Y=Down, Z=Forward + rr.log("camera", rr.ViewCoordinates.RDF, static=True) # X=Right, Y=Down, Z=Forward # Log camera intrinsics assert camera.model == "PINHOLE" diff --git a/rerun_py/rerun_sdk/rerun/_log.py b/rerun_py/rerun_sdk/rerun/_log.py index 30a182364a4f..0f541b27bb35 100644 --- a/rerun_py/rerun_sdk/rerun/_log.py +++ b/rerun_py/rerun_sdk/rerun/_log.py @@ -60,6 +60,7 @@ def log( entity: AsComponents | Iterable[ComponentBatchLike], *extra: AsComponents | Iterable[ComponentBatchLike], timeless: bool = False, + static: bool = False, recording: RecordingStream | None = None, strict: bool | None = None, ) -> None: @@ -113,24 +114,45 @@ def log( entity: Anything that implements the [`rerun.AsComponents`][] interface, usually an archetype. + *extra: - An arbitrary number of additional component bundles implementing the [`rerun.AsComponents`][] interface, that are logged to the same entity path. + An arbitrary number of additional component bundles implementing the [`rerun.AsComponents`][] + interface, that are logged to the same entity path. + timeless: - If true, the logged components will be timeless. + Deprecated. Refer to `static` instead. + + static: + If true, the components will be logged as static data. + + Static data has no time associated with it, exists on all timelines, and unconditionally shadows + any temporal data of the same type. Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. Additional timelines set by [`rerun.set_time_sequence`][], [`rerun.set_time_seconds`][] or [`rerun.set_time_nanos`][] will also be included. + recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. + strict: If True, raise exceptions on non-loggable data. If False, warn on non-loggable data. if None, use the global default from `rerun.strict_mode()` """ + + if timeless is True: + import warnings + + warnings.warn( + message=("`timeless` is deprecated as an argument to `log`; prefer `static` instead"), + category=DeprecationWarning, + ) + static = True + # TODO(jleibs): Profile is_instance with runtime_checkable vs has_attr # Note from: https://docs.python.org/3/library/typing.html#typing.runtime_checkable # @@ -168,7 +190,7 @@ def log( entity_path=entity_path, components=components, num_instances=num_instances, - timeless=timeless, + static=static, recording=recording, ) @@ -180,6 +202,7 @@ def log_components( *, num_instances: int | None = None, timeless: bool = False, + static: bool = False, recording: RecordingStream | None = None, strict: bool | None = None, ) -> None: @@ -203,21 +226,45 @@ def log_components( components: A collection of `ComponentBatchLike` objects that + num_instances: Optional. The number of instances in each batch. If not provided, the max of all components will be used instead. + timeless: - If true, the entity will be timeless (default: False). + Deprecated. Refer to `static` instead. + + static: + If true, the components will be logged as static data. + + Static data has no time associated with it, exists on all timelines, and unconditionally shadows + any temporal data of the same type. + + Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. + Additional timelines set by [`rerun.set_time_sequence`][], [`rerun.set_time_seconds`][] or + [`rerun.set_time_nanos`][] will also be included. + recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, defaults to the current active data recording, if there is one. See also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. + strict: If True, raise exceptions on non-loggable data. If False, warn on non-loggable data. if None, use the global default from `rerun.strict_mode()` """ + + if timeless is True: + import warnings + + warnings.warn( + message=("`timeless` is deprecated as an argument to `log`; prefer `static` instead"), + category=DeprecationWarning, + ) + static = True + # Convert to a native recording recording = RecordingStream.to_native(recording) @@ -269,7 +316,7 @@ def log_components( bindings.log_arrow_msg( # pyright: ignore[reportGeneralTypeIssues] entity_path, components=splats, - timeless=timeless, + static_=static, recording=recording, ) @@ -277,7 +324,7 @@ def log_components( bindings.log_arrow_msg( # pyright: ignore[reportGeneralTypeIssues] entity_path, components=instanced, - timeless=timeless, + static_=static, recording=recording, ) @@ -288,6 +335,7 @@ def log_file_from_path( file_path: str | Path, *, entity_path_prefix: str | None = None, + static: bool = False, timeless: bool = False, recording: RecordingStream | None = None, ) -> None: @@ -310,7 +358,17 @@ def log_file_from_path( What should the logged entity paths be prefixed with? timeless: - Should the logged data be timeless? (default: False) + Deprecated. Refer to `static` instead. + + static: + If true, the components will be logged as static data. + + Static data has no time associated with it, exists on all timelines, and unconditionally shadows + any temporal data of the same type. + + Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. + Additional timelines set by [`rerun.set_time_sequence`][], [`rerun.set_time_seconds`][] or + [`rerun.set_time_nanos`][] will also be included. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, @@ -318,11 +376,19 @@ def log_file_from_path( also: [`rerun.init`][], [`rerun.set_global_data_recording`][]. """ + if timeless is True: + import warnings + + warnings.warn( + message=("`timeless` is deprecated as an argument to `log`; prefer `static` instead"), + category=DeprecationWarning, + ) + static = True bindings.log_file_from_path( Path(file_path), entity_path_prefix=entity_path_prefix, - timeless=timeless, + static_=static, recording=recording, ) @@ -334,6 +400,7 @@ def log_file_from_contents( file_contents: bytes, *, entity_path_prefix: str | None = None, + static: bool = False, timeless: bool | None = None, recording: RecordingStream | None = None, ) -> None: @@ -359,7 +426,17 @@ def log_file_from_contents( What should the logged entity paths be prefixed with? timeless: - Should the logged data be timeless? (default: False) + Deprecated. Refer to `static` instead. + + static: + If true, the components will be logged as static data. + + Static data has no time associated with it, exists on all timelines, and unconditionally shadows + any temporal data of the same type. + + Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. + Additional timelines set by [`rerun.set_time_sequence`][], [`rerun.set_time_seconds`][] or + [`rerun.set_time_nanos`][] will also be included. recording: Specifies the [`rerun.RecordingStream`][] to use. If left unspecified, @@ -372,7 +449,7 @@ def log_file_from_contents( Path(file_path), file_contents, entity_path_prefix=entity_path_prefix, - timeless=timeless, + static_=static, recording=recording, ) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py index eb8ca1b1d6d6..45057b60f7d3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py @@ -44,7 +44,7 @@ class AnnotationContext(Archetype): image[100:180, 130:280] = 2 # Log an annotation context to assign a label and color to each class - rr.log("segmentation", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), timeless=True) + rr.log("segmentation", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) rr.log("segmentation/image", rr.SegmentationImage(image)) ``` diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py index 3d7701dd8728..1fedc8674d81 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py @@ -35,7 +35,7 @@ class Asset3D(Asset3DExt, Archetype): rr.init("rerun_example_asset3d", spawn=True) - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) # Set an up-axis + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # Set an up-axis rr.log("world/asset", rr.Asset3D(path=sys.argv[1])) ```
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py index a8af5f053ff5..024273b80c7a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py @@ -48,7 +48,7 @@ class SegmentationImage(SegmentationImageExt, Archetype): rr.init("rerun_example_segmentation_image", spawn=True) # Assign a label and color to each class - rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), timeless=True) + rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) rr.log("image", rr.SegmentationImage(image)) ``` diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py index 04579032d1f5..c51e444f8b21 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py @@ -38,10 +38,10 @@ class SeriesLine(Archetype): rr.init("rerun_example_series_line_style", spawn=True) # Set up plot styling: - # They are logged timeless as they don't change over time and apply to all timelines. + # They are logged as static as they don't change over time and apply to all timelines. # Log two lines series under a shared root so that they show in the same plot by default. - rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)", width=2), timeless=True) - rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)", width=4), timeless=True) + rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)", width=2), static=True) + rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)", width=4), static=True) # Log the data on a timeline called "step". for t in range(0, int(tau * 2 * 100.0)): diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py index 38c2cf0bc9d1..125417918eaa 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py @@ -38,7 +38,7 @@ class SeriesPoint(Archetype): rr.init("rerun_example_series_point_style", spawn=True) # Set up plot styling: - # They are logged timeless as they don't change over time and apply to all timelines. + # They are logged as static as they don't change over time and apply to all timelines. # Log two point series under a shared root so that they show in the same plot by default. rr.log( "trig/sin", @@ -48,7 +48,7 @@ class SeriesPoint(Archetype): marker="circle", marker_size=4, ), - timeless=True, + static=True, ) rr.log( "trig/cos", @@ -58,7 +58,7 @@ class SeriesPoint(Archetype): marker="cross", marker_size=2, ), - timeless=True, + static=True, ) # Log the data on a timeline called "step". diff --git a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py index 7eedfc433b8b..803d9b2490f2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py @@ -37,7 +37,7 @@ class ViewCoordinates(ViewCoordinatesExt, Archetype): rr.init("rerun_example_view_coordinates", spawn=True) - rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) # Set an up-axis + rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # Set an up-axis rr.log( "world/xyz", rr.Arrows3D( diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index 55edd03f51e9..b8d406082f06 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -202,7 +202,7 @@ def serve( The WebSocket server will buffer all log data in memory so that late connecting viewers will get all the data. You can limit the amount of data buffered by the WebSocket server with the `server_memory_limit` argument. Once reached, the earliest logged data will be dropped. - Note that this means that timeless data may be dropped if logged early. + Note that this means that static data may be dropped if logged early (see https://github.com/rerun-io/rerun/issues/5531). This function returns immediately. @@ -214,7 +214,7 @@ def serve( The port to serve the web viewer on (defaults to 9090). ws_port: The port to serve the WebSocket server on (defaults to 9877) - default_blueprint + default_blueprint: Optionally set a default blueprint to use for this application. If the application already has an active blueprint, the new blueprint won't become active until the user clicks the "reset blueprint" button. If you want to activate the new blueprint @@ -247,6 +247,7 @@ def serve( ).storage recording = RecordingStream.to_native(recording) + # TODO(#5531): keep static data around. bindings.serve( open_browser, web_port, diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index 66adc08165b7..338e4d6c6bbb 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -914,14 +914,14 @@ fn reset_time(recording: Option<&PyRecordingStream>) { #[pyo3(signature = ( entity_path, components, - timeless, + static_, recording=None, ))] fn log_arrow_msg( py: Python<'_>, entity_path: &str, components: &PyDict, - timeless: bool, + static_: bool, recording: Option<&PyRecordingStream>, ) -> PyResult<()> { let Some(recording) = get_data_recording(recording) else { @@ -939,7 +939,7 @@ fn log_arrow_msg( &TimePoint::default(), )?; - recording.record_row(row, !timeless); + recording.record_row(row, !static_); py.allow_threads(flush_garbage_queue); @@ -950,17 +950,17 @@ fn log_arrow_msg( #[pyo3(signature = ( file_path, entity_path_prefix = None, - timeless = false, + static_ = false, recording = None, ))] fn log_file_from_path( py: Python<'_>, file_path: std::path::PathBuf, entity_path_prefix: Option, - timeless: bool, + static_: bool, recording: Option<&PyRecordingStream>, ) -> PyResult<()> { - log_file(py, file_path, None, entity_path_prefix, timeless, recording) + log_file(py, file_path, None, entity_path_prefix, static_, recording) } #[pyfunction] @@ -968,7 +968,7 @@ fn log_file_from_path( file_path, file_contents, entity_path_prefix = None, - timeless = false, + static_ = false, recording = None, ))] fn log_file_from_contents( @@ -976,7 +976,7 @@ fn log_file_from_contents( file_path: std::path::PathBuf, file_contents: &[u8], entity_path_prefix: Option, - timeless: bool, + static_: bool, recording: Option<&PyRecordingStream>, ) -> PyResult<()> { log_file( @@ -984,7 +984,7 @@ fn log_file_from_contents( file_path, Some(file_contents), entity_path_prefix, - timeless, + static_, recording, ) } @@ -994,7 +994,7 @@ fn log_file( file_path: std::path::PathBuf, file_contents: Option<&[u8]>, entity_path_prefix: Option, - timeless: bool, + static_: bool, recording: Option<&PyRecordingStream>, ) -> PyResult<()> { let Some(recording) = get_data_recording(recording) else { @@ -1007,12 +1007,12 @@ fn log_file( file_path, std::borrow::Cow::Borrowed(contents), entity_path_prefix.map(Into::into), - timeless, + static_, ) .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; } else { recording - .log_file_from_path(file_path, entity_path_prefix.map(Into::into), timeless) + .log_file_from_path(file_path, entity_path_prefix.map(Into::into), static_) .map_err(|err| PyRuntimeError::new_err(err.to_string()))?; } diff --git a/tests/python/release_checklist/check_annotations.py b/tests/python/release_checklist/check_annotations.py index e701206fb127..c2a065a5a007 100644 --- a/tests/python/release_checklist/check_annotations.py +++ b/tests/python/release_checklist/check_annotations.py @@ -24,12 +24,12 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def log_annotations() -> None: # Log an annotation context to assign a label and color to each class - rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), timeless=True) + rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) # Log a batch of 2 rectangles with different `class_ids` rr.log("detections", rr.Boxes2D(mins=[[200, 50], [75, 150]], sizes=[[30, 30], [20, 20]], class_ids=[1, 2])) diff --git a/tests/python/release_checklist/check_container_hierarchy.py b/tests/python/release_checklist/check_container_hierarchy.py index 3dd9bece9b44..c10bc2c3b2a9 100644 --- a/tests/python/release_checklist/check_container_hierarchy.py +++ b/tests/python/release_checklist/check_container_hierarchy.py @@ -58,7 +58,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def log_some_space_views() -> None: diff --git a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py index 20032eac8879..7dc4fb4aea28 100644 --- a/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py +++ b/tests/python/release_checklist/check_context_menu_add_entity_to_new_space_view.py @@ -26,7 +26,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def blueprint() -> rrb.BlueprintLike: diff --git a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py index a0be96d164be..6b1d9fc6bc40 100644 --- a/tests/python/release_checklist/check_context_menu_collapse_expand_all.py +++ b/tests/python/release_checklist/check_context_menu_collapse_expand_all.py @@ -27,7 +27,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def blueprint() -> rrb.BlueprintLike: diff --git a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py index 1a434cea1486..a6bc92f1871a 100644 --- a/tests/python/release_checklist/check_context_menu_invalid_sub_container.py +++ b/tests/python/release_checklist/check_context_menu_invalid_sub_container.py @@ -19,7 +19,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def blueprint() -> rrb.BlueprintLike: diff --git a/tests/python/release_checklist/check_context_menu_multi_selection.py b/tests/python/release_checklist/check_context_menu_multi_selection.py index a1d03e2be884..b7879fce72cf 100644 --- a/tests/python/release_checklist/check_context_menu_multi_selection.py +++ b/tests/python/release_checklist/check_context_menu_multi_selection.py @@ -61,7 +61,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def blueprint() -> rrb.BlueprintLike: diff --git a/tests/python/release_checklist/check_context_menu_single_selection.py b/tests/python/release_checklist/check_context_menu_single_selection.py index 7f2ba042e92f..ecb9ee87c3c0 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection.py +++ b/tests/python/release_checklist/check_context_menu_single_selection.py @@ -82,7 +82,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def blueprint() -> rrb.BlueprintLike: diff --git a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py index 831b7c76e0bf..caea1f292863 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py +++ b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py @@ -65,7 +65,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def blueprint() -> rrb.BlueprintLike: diff --git a/tests/python/release_checklist/check_context_menu_suggested_origin.py b/tests/python/release_checklist/check_context_menu_suggested_origin.py index dad86853b320..a125a1bf5026 100644 --- a/tests/python/release_checklist/check_context_menu_suggested_origin.py +++ b/tests/python/release_checklist/check_context_menu_suggested_origin.py @@ -41,7 +41,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def blueprint() -> rrb.BlueprintLike: @@ -55,7 +55,7 @@ def blueprint() -> rrb.BlueprintLike: def log_some_space_views() -> None: rr.set_time_sequence("frame_nr", 0) rr.log("/", rr.Boxes3D(centers=[0, 0, 0], half_sizes=[1, 1, 1])) - rr.log("/world", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, timeless=True) + rr.log("/world", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, static=True) rr.log( "/world/camera/image", rr.Pinhole( diff --git a/tests/python/release_checklist/check_focus.py b/tests/python/release_checklist/check_focus.py index 743c46229ec0..c81b3fcd3516 100644 --- a/tests/python/release_checklist/check_focus.py +++ b/tests/python/release_checklist/check_focus.py @@ -18,7 +18,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def blueprint() -> rrb.BlueprintLike: diff --git a/tests/python/release_checklist/check_heuristics_2d.py b/tests/python/release_checklist/check_heuristics_2d.py index e289a8b2ab34..b030b80f1705 100644 --- a/tests/python/release_checklist/check_heuristics_2d.py +++ b/tests/python/release_checklist/check_heuristics_2d.py @@ -39,7 +39,7 @@ def log_image_nested(path: str, height: int, width: int, color: tuple[int, int, def log_annotation_context() -> None: - rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), timeless=True) + rr.log("/", rr.AnnotationContext([(1, "red", (255, 0, 0)), (2, "green", (0, 255, 0))]), static=True) def log_segmentation(path: str, height: int, width: int, class_id: int) -> None: @@ -49,7 +49,7 @@ def log_segmentation(path: str, height: int, width: int, class_id: int) -> None: def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def log_images() -> None: diff --git a/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py b/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py index c0e7dab2d53d..487b9d5df7cb 100644 --- a/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py +++ b/tests/python/release_checklist/check_heuristics_mixed_2d_and_3d.py @@ -34,7 +34,7 @@ def log_image(path: str, height: int, width: int, color: tuple[int, int, int]) - def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def log_images() -> None: diff --git a/tests/python/release_checklist/check_hover_select_reset.py b/tests/python/release_checklist/check_hover_select_reset.py index c58b29b41020..c65f6cadca0e 100644 --- a/tests/python/release_checklist/check_hover_select_reset.py +++ b/tests/python/release_checklist/check_hover_select_reset.py @@ -37,7 +37,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def log_plots() -> None: diff --git a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py index f307060b721b..92c99c278b13 100644 --- a/tests/python/release_checklist/check_parallelism_caching_reentrancy.py +++ b/tests/python/release_checklist/check_parallelism_caching_reentrancy.py @@ -35,7 +35,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def log_text_logs() -> None: diff --git a/tests/python/release_checklist/check_plot_overrides.py b/tests/python/release_checklist/check_plot_overrides.py index 7aecd2460ac3..8cf3f2f0f329 100644 --- a/tests/python/release_checklist/check_plot_overrides.py +++ b/tests/python/release_checklist/check_plot_overrides.py @@ -37,7 +37,7 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def log_plots() -> None: diff --git a/tests/python/release_checklist/check_scalar_clears.py b/tests/python/release_checklist/check_scalar_clears.py index 0a3691d08dad..f8862ba49741 100644 --- a/tests/python/release_checklist/check_scalar_clears.py +++ b/tests/python/release_checklist/check_scalar_clears.py @@ -19,14 +19,14 @@ def log_readme() -> None: - rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) def log_plots() -> None: from math import sin, tau - rr.log("plots/line", rr.SeriesLine(), timeless=True) - rr.log("plots/point", rr.SeriesPoint(), timeless=True) + rr.log("plots/line", rr.SeriesLine(), static=True) + rr.log("plots/point", rr.SeriesPoint(), static=True) for t in range(0, int(tau * 2 * 10.0)): rr.set_time_sequence("frame_nr", t) diff --git a/tests/python/release_checklist/main.py b/tests/python/release_checklist/main.py index 4b8cbba27a0b..9c4ea5199d29 100644 --- a/tests/python/release_checklist/main.py +++ b/tests/python/release_checklist/main.py @@ -20,7 +20,7 @@ def log_checks(args: argparse.Namespace) -> None: def log_readme() -> None: with open(join(dirname(__file__), "README.md")) as f: - rr.log("readme", rr.TextDocument(f.read(), media_type=rr.MediaType.MARKDOWN), timeless=True) + rr.log("readme", rr.TextDocument(f.read(), media_type=rr.MediaType.MARKDOWN), static=True) def main() -> None: diff --git a/tests/python/roundtrips/view_coordinates/main.py b/tests/python/roundtrips/view_coordinates/main.py index d59515252fe7..1ef301811d80 100755 --- a/tests/python/roundtrips/view_coordinates/main.py +++ b/tests/python/roundtrips/view_coordinates/main.py @@ -16,7 +16,7 @@ def main() -> None: rr.script_setup(args, "rerun_example_roundtrip_view_coordinates") - rr.log("/", rr.ViewCoordinates.RDF, timeless=True) + rr.log("/", rr.ViewCoordinates.RDF, static=True) rr.script_teardown(args) diff --git a/tests/python/test_api/main.py b/tests/python/test_api/main.py index a73b9eb28e0a..76e0a09f59f7 100755 --- a/tests/python/test_api/main.py +++ b/tests/python/test_api/main.py @@ -54,7 +54,7 @@ def run_segmentation() -> None: # Log an initial segmentation map with arbitrary colors rr.set_time_seconds("sim_time", 2) - rr.log("seg_test", rr.AnnotationContext([(13, "label1"), (42, "label2"), (99, "label3")]), timeless=False) + rr.log("seg_test", rr.AnnotationContext([(13, "label1"), (42, "label2"), (99, "label3")]), static=False) rr.log( "logs/seg_test_log", @@ -68,7 +68,7 @@ def run_segmentation() -> None: rr.log( "seg_test", rr.AnnotationContext([(13, "label1", (255, 0, 0)), (42, "label2", (0, 255, 0)), (99, "label3", (0, 0, 255))]), - timeless=False, + static=False, ) rr.log("logs/seg_test_log", rr.TextLog("points/rects with user specified colors")) @@ -84,7 +84,7 @@ def run_segmentation() -> None: rr.AnnotationInfo(99, label="label3"), ] ), - timeless=False, + static=False, ) rr.log("logs/seg_test_log", rr.TextLog("label1 disappears and everything with label3 is now default colored again")) @@ -98,7 +98,7 @@ def small_image() -> None: def transforms() -> None: - rr.log("transforms", rr.ViewCoordinates.RIGHT_HAND_Y_UP, timeless=True) + rr.log("transforms", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True) # Log a disconnected space (this doesn't do anything here, but can be used to force a new space) rr.log("transforms/disconnected", rr.DisconnectedSpace()) @@ -218,7 +218,7 @@ def run_rects() -> None: def run_text_logs() -> None: - rr.log("logs", rr.TextLog("Text with explicitly set color", color=[255, 215, 0]), timeless=True) + rr.log("logs", rr.TextLog("Text with explicitly set color", color=[255, 215, 0]), static=True) rr.log("logs", rr.TextLog("this entry has loglevel TRACE", level="TRACE")) logging.getLogger().addHandler(rr.LoggingHandler("logs/handler")) @@ -255,10 +255,10 @@ def transforms_rigid_3d() -> None: rotation_speed_moon = 5.0 # Planetary motion is typically in the XY plane. - rr.log("transforms3d", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) - rr.log("transforms3d/sun", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) - rr.log("transforms3d/sun/planet", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) - rr.log("transforms3d/sun/planet/moon", rr.ViewCoordinates.RIGHT_HAND_Z_UP, timeless=True) + rr.log("transforms3d", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) + rr.log("transforms3d/sun", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) + rr.log("transforms3d/sun/planet", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) + rr.log("transforms3d/sun/planet/moon", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) # All are in the center of their own space: rr.log("transforms3d/sun", rr.Points3D([0.0, 0.0, 0.0], radii=1.0, colors=[255, 200, 10])) diff --git a/tests/python/visible_history_playground/main.py b/tests/python/visible_history_playground/main.py index e2d60b2fe16e..2abdbbb87c6b 100644 --- a/tests/python/visible_history_playground/main.py +++ b/tests/python/visible_history_playground/main.py @@ -13,13 +13,13 @@ args = parser.parse_args() rr.script_setup(args, "rerun_example_visible_history_playground") -rr.log("bbox", rr.Boxes2D(centers=[50, 3.5], half_sizes=[50, 4.5], colors=[255, 0, 0]), timeless=True) +rr.log("bbox", rr.Boxes2D(centers=[50, 3.5], half_sizes=[50, 4.5], colors=[255, 0, 0]), static=True) rr.log("transform", rr.Transform3D(translation=[0, 0, 0])) -rr.log("some/nested/pinhole", rr.Pinhole(focal_length=3, width=3, height=3), timeless=True) +rr.log("some/nested/pinhole", rr.Pinhole(focal_length=3, width=3, height=3), static=True) -rr.log("3dworld/depthimage/pinhole", rr.Pinhole(focal_length=20, width=100, height=10), timeless=True) -rr.log("3dworld/image", rr.Transform3D(translation=[0, 1, 0]), timeless=True) -rr.log("3dworld/image/pinhole", rr.Pinhole(focal_length=20, width=100, height=10), timeless=True) +rr.log("3dworld/depthimage/pinhole", rr.Pinhole(focal_length=20, width=100, height=10), static=True) +rr.log("3dworld/image", rr.Transform3D(translation=[0, 1, 0]), static=True) +rr.log("3dworld/image/pinhole", rr.Pinhole(focal_length=20, width=100, height=10), static=True) date_offset = int(datetime.datetime(year=2023, month=1, day=1).timestamp()) From a8f7a62a4143a4a3e7acea8d91435a42bc80f2a7 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 5 Apr 2024 17:29:06 +0200 Subject: [PATCH 207/508] Static data 3: static-aware C & C++ SDKs (#5537) Just exposing all the new static stuff to the C & C++ SDKs, and trying to kill the "timeless" terminology in the process. --- Part of a PR series that removes the concept of timeless data in favor of the much simpler concept of static data: - #5534 - #5535 - #5536 - #5537 - #5540 --- crates/rerun_c/src/lib.rs | 16 +- crates/rerun_c/src/rerun.h | 8 +- .../all/annotation_context_connections.cpp | 2 +- .../snippets/all/annotation_context_rects.cpp | 2 +- .../all/annotation_context_segmentation.cpp | 2 +- docs/snippets/all/asset3d_out_of_tree.cpp | 2 +- docs/snippets/all/asset3d_simple.cpp | 2 +- docs/snippets/all/scalar_multiple_plots.cpp | 14 +- .../all/segmentation_image_simple.cpp | 2 +- docs/snippets/all/series_line_style.cpp | 6 +- docs/snippets/all/series_point_style.cpp | 6 +- docs/snippets/all/view_coordinates_simple.cpp | 2 +- examples/cpp/clock/main.cpp | 4 +- examples/cpp/external_data_loader/main.cpp | 7 +- examples/cpp/incremental_logging/main.cpp | 6 +- .../rerun/archetypes/annotation_context.hpp | 2 +- rerun_cpp/src/rerun/archetypes/asset3d.hpp | 2 +- .../rerun/archetypes/segmentation_image.hpp | 2 +- .../src/rerun/archetypes/series_line.hpp | 6 +- .../src/rerun/archetypes/series_point.hpp | 6 +- .../src/rerun/archetypes/view_coordinates.hpp | 2 +- rerun_cpp/src/rerun/c/rerun.h | 8 +- rerun_cpp/src/rerun/recording_stream.cpp | 12 +- rerun_cpp/src/rerun/recording_stream.hpp | 165 ++++++++++++------ rerun_cpp/tests/recording_stream.cpp | 14 +- .../cpp/roundtrips/view_coordinates/main.cpp | 2 +- 26 files changed, 175 insertions(+), 127 deletions(-) diff --git a/crates/rerun_c/src/lib.rs b/crates/rerun_c/src/lib.rs index e814a9dd530c..b9420bca3c2b 100644 --- a/crates/rerun_c/src/lib.rs +++ b/crates/rerun_c/src/lib.rs @@ -732,7 +732,7 @@ fn rr_log_file_from_path_impl( stream: CRecordingStream, filepath: CStringView, entity_path_prefix: CStringView, - timeless: bool, + static_: bool, ) -> Result<(), CError> { let stream = recording_stream(stream)?; @@ -740,7 +740,7 @@ fn rr_log_file_from_path_impl( let entity_path_prefix = entity_path_prefix.as_str("entity_path_prefix").ok(); stream - .log_file_from_path(filepath, entity_path_prefix.map(Into::into), timeless) + .log_file_from_path(filepath, entity_path_prefix.map(Into::into), static_) .map_err(|err| { CError::new( CErrorCode::RecordingStreamRuntimeFailure, @@ -757,10 +757,10 @@ pub unsafe extern "C" fn rr_recording_stream_log_file_from_path( stream: CRecordingStream, filepath: CStringView, entity_path_prefix: CStringView, - timeless: bool, + static_: bool, error: *mut CError, ) { - if let Err(err) = rr_log_file_from_path_impl(stream, filepath, entity_path_prefix, timeless) { + if let Err(err) = rr_log_file_from_path_impl(stream, filepath, entity_path_prefix, static_) { err.write_error(error); } } @@ -772,7 +772,7 @@ fn rr_log_file_from_contents_impl( filepath: CStringView, contents: CBytesView, entity_path_prefix: CStringView, - timeless: bool, + static_: bool, ) -> Result<(), CError> { let stream = recording_stream(stream)?; @@ -785,7 +785,7 @@ fn rr_log_file_from_contents_impl( filepath, std::borrow::Cow::Borrowed(contents), entity_path_prefix.map(Into::into), - timeless, + static_, ) .map_err(|err| { CError::new( @@ -804,11 +804,11 @@ pub unsafe extern "C" fn rr_recording_stream_log_file_from_contents( filepath: CStringView, contents: CBytesView, entity_path_prefix: CStringView, - timeless: bool, + static_: bool, error: *mut CError, ) { if let Err(err) = - rr_log_file_from_contents_impl(stream, filepath, contents, entity_path_prefix, timeless) + rr_log_file_from_contents_impl(stream, filepath, contents, entity_path_prefix, static_) { err.write_error(error); } diff --git a/crates/rerun_c/src/rerun.h b/crates/rerun_c/src/rerun.h index fd2b0afd0811..0d23013320e2 100644 --- a/crates/rerun_c/src/rerun.h +++ b/crates/rerun_c/src/rerun.h @@ -159,10 +159,10 @@ typedef struct rr_data_loader_settings { /// Unspecified by default. rr_string entity_path_prefix; - /// Should the logged data be timeless? + /// Should the logged data be static? /// /// Defaults to `false` if not set. - bool timeless; + bool static_; } rr_data_loader_settings; typedef struct rr_store_info { @@ -456,7 +456,7 @@ extern void rr_recording_stream_log( /// /// See for more information. extern void rr_recording_stream_log_file_from_path( - rr_recording_stream stream, rr_string path, rr_string entity_path_prefix, bool timeless, + rr_recording_stream stream, rr_string path, rr_string entity_path_prefix, bool static_, rr_error* error ); @@ -470,7 +470,7 @@ extern void rr_recording_stream_log_file_from_path( /// See for more information. extern void rr_recording_stream_log_file_from_contents( rr_recording_stream stream, rr_string path, rr_bytes contents, rr_string entity_path_prefix, - bool timeless, rr_error* error + bool static_, rr_error* error ); // ---------------------------------------------------------------------------- diff --git a/docs/snippets/all/annotation_context_connections.cpp b/docs/snippets/all/annotation_context_connections.cpp index 6d734213f8e0..20a69a23c124 100644 --- a/docs/snippets/all/annotation_context_connections.cpp +++ b/docs/snippets/all/annotation_context_connections.cpp @@ -9,7 +9,7 @@ int main() { // Log an annotation context to assign a label and color to each class // Create a class description with labels and color for each keypoint ID as well as some // connections between keypoints. - rec.log_timeless( + rec.log_static( "/", rerun::AnnotationContext({rerun::ClassDescription{ 0, diff --git a/docs/snippets/all/annotation_context_rects.cpp b/docs/snippets/all/annotation_context_rects.cpp index cfc94402829b..4ba4c9150708 100644 --- a/docs/snippets/all/annotation_context_rects.cpp +++ b/docs/snippets/all/annotation_context_rects.cpp @@ -7,7 +7,7 @@ int main() { rec.spawn().exit_on_failure(); // Log an annotation context to assign a label and color to each class - rec.log_timeless( + rec.log_static( "/", rerun::AnnotationContext({ rerun::AnnotationInfo(1, "red", rerun::Rgba32(255, 0, 0)), diff --git a/docs/snippets/all/annotation_context_segmentation.cpp b/docs/snippets/all/annotation_context_segmentation.cpp index eb071348e42c..7a0b06dff736 100644 --- a/docs/snippets/all/annotation_context_segmentation.cpp +++ b/docs/snippets/all/annotation_context_segmentation.cpp @@ -10,7 +10,7 @@ int main() { rec.spawn().exit_on_failure(); // create an annotation context to describe the classes - rec.log_timeless( + rec.log_static( "segmentation", rerun::AnnotationContext({ rerun::AnnotationInfo(1, "red", rerun::Rgba32(255, 0, 0)), diff --git a/docs/snippets/all/asset3d_out_of_tree.cpp b/docs/snippets/all/asset3d_out_of_tree.cpp index 86250226238b..4158d9364e8e 100644 --- a/docs/snippets/all/asset3d_out_of_tree.cpp +++ b/docs/snippets/all/asset3d_out_of_tree.cpp @@ -15,7 +15,7 @@ int main(int argc, char** argv) { const auto rec = rerun::RecordingStream("rerun_example_asset3d_out_of_tree"); rec.spawn().exit_on_failure(); - rec.log_timeless("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis + rec.log_static("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis rec.set_time_sequence("frame", 0); rec.log("world/asset", rerun::Asset3D::from_file(path).value_or_throw()); diff --git a/docs/snippets/all/asset3d_simple.cpp b/docs/snippets/all/asset3d_simple.cpp index 036aa254cab3..1689e792ef26 100644 --- a/docs/snippets/all/asset3d_simple.cpp +++ b/docs/snippets/all/asset3d_simple.cpp @@ -17,6 +17,6 @@ int main(int argc, char* argv[]) { const auto rec = rerun::RecordingStream("rerun_example_asset3d"); rec.spawn().exit_on_failure(); - rec.log_timeless("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis + rec.log_static("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis rec.log("world/asset", rerun::Asset3D::from_file(path).value_or_throw()); } diff --git a/docs/snippets/all/scalar_multiple_plots.cpp b/docs/snippets/all/scalar_multiple_plots.cpp index 09ea10091599..48b962c6370e 100644 --- a/docs/snippets/all/scalar_multiple_plots.cpp +++ b/docs/snippets/all/scalar_multiple_plots.cpp @@ -13,18 +13,12 @@ int main() { int64_t lcg_state = 0; // Set up plot styling: - // They are logged timeless as they don't change over time and apply to all timelines. + // They are logged static as they don't change over time and apply to all timelines. // Log two lines series under a shared root so that they show in the same plot by default. - rec.log_timeless( - "trig/sin", - rerun::SeriesLine().with_color({255, 0, 0}).with_name("sin(0.01t)") - ); - rec.log_timeless( - "trig/cos", - rerun::SeriesLine().with_color({0, 255, 0}).with_name("cos(0.01t)") - ); + rec.log_static("trig/sin", rerun::SeriesLine().with_color({255, 0, 0}).with_name("sin(0.01t)")); + rec.log_static("trig/cos", rerun::SeriesLine().with_color({0, 255, 0}).with_name("cos(0.01t)")); // Log scattered points under a different root so that they show in a different plot by default. - rec.log_timeless("scatter/lcg", rerun::SeriesPoint()); + rec.log_static("scatter/lcg", rerun::SeriesPoint()); // Log the data on a timeline called "step". for (int t = 0; t < static_cast(TAU * 2.0 * 100.0); ++t) { diff --git a/docs/snippets/all/segmentation_image_simple.cpp b/docs/snippets/all/segmentation_image_simple.cpp index 4ab8b6e506a6..d879d13e7263 100644 --- a/docs/snippets/all/segmentation_image_simple.cpp +++ b/docs/snippets/all/segmentation_image_simple.cpp @@ -21,7 +21,7 @@ int main() { } // create an annotation context to describe the classes - rec.log_timeless( + rec.log_static( "/", rerun::AnnotationContext({ rerun::AnnotationInfo(1, "red", rerun::Rgba32(255, 0, 0)), diff --git a/docs/snippets/all/series_line_style.cpp b/docs/snippets/all/series_line_style.cpp index 0a5242a150a1..00a0d4a31923 100644 --- a/docs/snippets/all/series_line_style.cpp +++ b/docs/snippets/all/series_line_style.cpp @@ -11,13 +11,13 @@ int main() { rec.spawn().exit_on_failure(); // Set up plot styling: - // They are logged timeless as they don't change over time and apply to all timelines. + // They are logged static as they don't change over time and apply to all timelines. // Log two lines series under a shared root so that they show in the same plot by default. - rec.log_timeless( + rec.log_static( "trig/sin", rerun::SeriesLine().with_color({255, 0, 0}).with_name("sin(0.01t)").with_width(2) ); - rec.log_timeless( + rec.log_static( "trig/cos", rerun::SeriesLine().with_color({0, 255, 0}).with_name("cos(0.01t)").with_width(4) ); diff --git a/docs/snippets/all/series_point_style.cpp b/docs/snippets/all/series_point_style.cpp index b42b334f1690..21914afbfd25 100644 --- a/docs/snippets/all/series_point_style.cpp +++ b/docs/snippets/all/series_point_style.cpp @@ -11,9 +11,9 @@ int main() { rec.spawn().exit_on_failure(); // Set up plot styling: - // They are logged timeless as they don't change over time and apply to all timelines. + // They are logged static as they don't change over time and apply to all timelines. // Log two point series under a shared root so that they show in the same plot by default. - rec.log_timeless( + rec.log_static( "trig/sin", rerun::SeriesPoint() .with_color({255, 0, 0}) @@ -21,7 +21,7 @@ int main() { .with_marker(rerun::components::MarkerShape::Circle) .with_marker_size(4) ); - rec.log_timeless( + rec.log_static( "trig/cos", rerun::SeriesPoint() .with_color({0, 255, 0}) diff --git a/docs/snippets/all/view_coordinates_simple.cpp b/docs/snippets/all/view_coordinates_simple.cpp index 65dac5b8c762..0c5c5a691bcc 100644 --- a/docs/snippets/all/view_coordinates_simple.cpp +++ b/docs/snippets/all/view_coordinates_simple.cpp @@ -6,7 +6,7 @@ int main() { const auto rec = rerun::RecordingStream("rerun_example_view_coordinates"); rec.spawn().exit_on_failure(); - rec.log_timeless("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis + rec.log_static("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis rec.log( "world/xyz", rerun::Arrows3D::from_vectors({{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}} diff --git a/examples/cpp/clock/main.cpp b/examples/cpp/clock/main.cpp index 1c9ebe23fc03..863574aa830f 100644 --- a/examples/cpp/clock/main.cpp +++ b/examples/cpp/clock/main.cpp @@ -45,8 +45,8 @@ int main() { const auto rec = rerun::RecordingStream("rerun_example_clock"); rec.spawn().exit_on_failure(); - rec.log_timeless("world", rerun::ViewCoordinates::RIGHT_HAND_Y_UP); - rec.log_timeless("world/frame", rerun::Boxes3D::from_half_sizes({{LENGTH_S, LENGTH_S, 1.0f}})); + rec.log_static("world", rerun::ViewCoordinates::RIGHT_HAND_Y_UP); + rec.log_static("world/frame", rerun::Boxes3D::from_half_sizes({{LENGTH_S, LENGTH_S, 1.0f}})); for (int step = 0; step < num_steps; step++) { log_hand(rec, "seconds", seconds(step), (step % 60) / 60.0f, LENGTH_S, WIDTH_S, 0); diff --git a/examples/cpp/external_data_loader/main.cpp b/examples/cpp/external_data_loader/main.cpp index 3c9c78a71f83..fb79a9d5e2f9 100644 --- a/examples/cpp/external_data_loader/main.cpp +++ b/examples/cpp/external_data_loader/main.cpp @@ -69,7 +69,8 @@ file with Rerun (`rerun file.cpp`). ("application-id", "Optional recommended ID for the application", cxxopts::value()) ("recording-id", "Optional recommended ID for the recording", cxxopts::value()) ("entity-path-prefix", "Optional prefix for all entity paths", cxxopts::value()) - ("timeless", "Optionally mark data to be logged as timeless", cxxopts::value()->default_value("false")) + ("timeless", "Deprecated: alias for `--static`", cxxopts::value()->default_value("false")) + ("static", "Optionally mark data to be logged as static", cxxopts::value()->default_value("false")) ("time", "Optional timestamps to log at (e.g. `--time sim_time=1709203426`) (repeatable)", cxxopts::value>()) ("sequence", "Optional sequences to log at (e.g. `--sequence sim_frame=42`) (repeatable)", cxxopts::value>()) ; @@ -118,9 +119,9 @@ file with Rerun (`rerun file.cpp`). if (args.count("entity-path-prefix")) { entity_path = args["entity-path-prefix"].as() + "/" + filepath; } - rec.log_with_timeless( + rec.log_with_static( entity_path, - args["timeless"].as(), + args["static"].as() || args["timeless"].as(), rerun::TextDocument(text).with_media_type(rerun::MediaType::markdown()) ); } diff --git a/examples/cpp/incremental_logging/main.cpp b/examples/cpp/incremental_logging/main.cpp index ddd33d96e528..3dbd9f62f984 100644 --- a/examples/cpp/incremental_logging/main.cpp +++ b/examples/cpp/incremental_logging/main.cpp @@ -44,7 +44,7 @@ int main() { const auto rec = rerun::RecordingStream("rerun_example_incremental_logging"); rec.spawn().exit_on_failure(); - rec.log_timeless( + rec.log_static( "readme", rerun::TextDocument(README).with_media_type(rerun::components::MediaType::markdown()) ); @@ -56,8 +56,8 @@ int main() { // Only log colors and radii once. rec.set_time_sequence("frame_nr", 0); rec.log("points", colors, radii); - // Logging timelessly with `RecordingStream::log_timeless` would also work. - // rec.log_timeless("points", colors, radii); + // Logging statically with `RecordingStream::log_static` would also work. + // rec.log_static("points", colors, radii); std::default_random_engine gen; std::uniform_real_distribution dist_pos(-5.0f, 5.0f); diff --git a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp index 5229a475a142..49b8acf083d5 100644 --- a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp +++ b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp @@ -38,7 +38,7 @@ namespace rerun::archetypes { /// rec.spawn().exit_on_failure(); /// /// // create an annotation context to describe the classes - /// rec.log_timeless( + /// rec.log_static( /// "segmentation", /// rerun::AnnotationContext({ /// rerun::AnnotationInfo(1, "red", rerun::Rgba32(255, 0, 0)), diff --git a/rerun_cpp/src/rerun/archetypes/asset3d.hpp b/rerun_cpp/src/rerun/archetypes/asset3d.hpp index d9cda837e762..4aa8fdf7f09b 100644 --- a/rerun_cpp/src/rerun/archetypes/asset3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset3d.hpp @@ -44,7 +44,7 @@ namespace rerun::archetypes { /// const auto rec = rerun::RecordingStream("rerun_example_asset3d"); /// rec.spawn().exit_on_failure(); /// - /// rec.log_timeless("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis + /// rec.log_static("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis /// rec.log("world/asset", rerun::Asset3D::from_file(path).value_or_throw()); /// } /// ``` diff --git a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp index 0e48f4c14485..dd8b33b7b84d 100644 --- a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp @@ -59,7 +59,7 @@ namespace rerun::archetypes { /// } /// /// // create an annotation context to describe the classes - /// rec.log_timeless( + /// rec.log_static( /// "/", /// rerun::AnnotationContext({ /// rerun::AnnotationInfo(1, "red", rerun::Rgba32(255, 0, 0)), diff --git a/rerun_cpp/src/rerun/archetypes/series_line.hpp b/rerun_cpp/src/rerun/archetypes/series_line.hpp index 865a6586f0ac..cfb37e10062d 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.hpp @@ -43,13 +43,13 @@ namespace rerun::archetypes { /// rec.spawn().exit_on_failure(); /// /// // Set up plot styling: - /// // They are logged timeless as they don't change over time and apply to all timelines. + /// // They are logged static as they don't change over time and apply to all timelines. /// // Log two lines series under a shared root so that they show in the same plot by default. - /// rec.log_timeless( + /// rec.log_static( /// "trig/sin", /// rerun::SeriesLine().with_color({255, 0, 0}).with_name("sin(0.01t)").with_width(2) /// ); - /// rec.log_timeless( + /// rec.log_static( /// "trig/cos", /// rerun::SeriesLine().with_color({0, 255, 0}).with_name("cos(0.01t)").with_width(4) /// ); diff --git a/rerun_cpp/src/rerun/archetypes/series_point.hpp b/rerun_cpp/src/rerun/archetypes/series_point.hpp index 1d43def17746..a3c4d81b3ea6 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.hpp @@ -44,9 +44,9 @@ namespace rerun::archetypes { /// rec.spawn().exit_on_failure(); /// /// // Set up plot styling: - /// // They are logged timeless as they don't change over time and apply to all timelines. + /// // They are logged static as they don't change over time and apply to all timelines. /// // Log two point series under a shared root so that they show in the same plot by default. - /// rec.log_timeless( + /// rec.log_static( /// "trig/sin", /// rerun::SeriesPoint() /// .with_color({255, 0, 0}) @@ -54,7 +54,7 @@ namespace rerun::archetypes { /// .with_marker(rerun::components::MarkerShape::Circle) /// .with_marker_size(4) /// ); - /// rec.log_timeless( + /// rec.log_static( /// "trig/cos", /// rerun::SeriesPoint() /// .with_color({0, 255, 0}) diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp index b69580df1cc9..8c014115270f 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp @@ -35,7 +35,7 @@ namespace rerun::archetypes { /// const auto rec = rerun::RecordingStream("rerun_example_view_coordinates"); /// rec.spawn().exit_on_failure(); /// - /// rec.log_timeless("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis + /// rec.log_static("world", rerun::ViewCoordinates::RIGHT_HAND_Z_UP); // Set an up-axis /// rec.log( /// "world/xyz", /// rerun::Arrows3D::from_vectors({{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}} diff --git a/rerun_cpp/src/rerun/c/rerun.h b/rerun_cpp/src/rerun/c/rerun.h index 6d8235c31fa4..984853268c8d 100644 --- a/rerun_cpp/src/rerun/c/rerun.h +++ b/rerun_cpp/src/rerun/c/rerun.h @@ -159,10 +159,10 @@ typedef struct rr_data_loader_settings { /// Unspecified by default. rr_string entity_path_prefix; - /// Should the logged data be timeless? + /// Should the logged data be static? /// /// Defaults to `false` if not set. - bool timeless; + bool static_; } rr_data_loader_settings; typedef struct rr_store_info { @@ -456,7 +456,7 @@ extern void rr_recording_stream_log( /// /// See for more information. extern void rr_recording_stream_log_file_from_path( - rr_recording_stream stream, rr_string path, rr_string entity_path_prefix, bool timeless, + rr_recording_stream stream, rr_string path, rr_string entity_path_prefix, bool static_, rr_error* error ); @@ -470,7 +470,7 @@ extern void rr_recording_stream_log_file_from_path( /// See for more information. extern void rr_recording_stream_log_file_from_contents( rr_recording_stream stream, rr_string path, rr_bytes contents, rr_string entity_path_prefix, - bool timeless, rr_error* error + bool static_, rr_error* error ); // ---------------------------------------------------------------------------- diff --git a/rerun_cpp/src/rerun/recording_stream.cpp b/rerun_cpp/src/rerun/recording_stream.cpp index 9edbea86c4c4..e470d62f1b83 100644 --- a/rerun_cpp/src/rerun/recording_stream.cpp +++ b/rerun_cpp/src/rerun/recording_stream.cpp @@ -189,7 +189,7 @@ namespace rerun { } Error RecordingStream::try_log_serialized_batches( - std::string_view entity_path, bool timeless, std::vector batches + std::string_view entity_path, bool static_, std::vector batches ) const { if (!is_enabled()) { return Error::ok(); @@ -210,7 +210,7 @@ namespace rerun { } } - bool inject_time = !timeless; + bool inject_time = !static_; if (!splatted.empty()) { splatted.push_back( @@ -258,7 +258,7 @@ namespace rerun { } Error RecordingStream::try_log_file_from_path( - const std::filesystem::path& filepath, std::string_view entity_path_prefix, bool timeless + const std::filesystem::path& filepath, std::string_view entity_path_prefix, bool static_ ) const { if (!is_enabled()) { return Error::ok(); @@ -269,7 +269,7 @@ namespace rerun { _id, detail::to_rr_string(filepath.string()), detail::to_rr_string(entity_path_prefix), - timeless, + static_, &status ); @@ -278,7 +278,7 @@ namespace rerun { Error RecordingStream::try_log_file_from_contents( const std::filesystem::path& filepath, const std::byte* contents, size_t contents_size, - std::string_view entity_path_prefix, bool timeless + std::string_view entity_path_prefix, bool static_ ) const { if (!is_enabled()) { return Error::ok(); @@ -294,7 +294,7 @@ namespace rerun { detail::to_rr_string(filepath.string()), data, detail::to_rr_string(entity_path_prefix), - timeless, + static_, &status ); diff --git a/rerun_cpp/src/rerun/recording_stream.hpp b/rerun_cpp/src/rerun/recording_stream.hpp index f0ff6498dea3..410e67df659d 100644 --- a/rerun_cpp/src/rerun/recording_stream.hpp +++ b/rerun_cpp/src/rerun/recording_stream.hpp @@ -330,38 +330,45 @@ namespace rerun { /// Any failures that may occur during serialization are handled with `Error::handle`. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param archetypes_or_collectiones Any type for which the `AsComponents` trait is implemented. + /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. /// - /// @see try_log, log_timeless, try_log_with_timeless + /// @see try_log, log_static, try_log_with_static template - void log(std::string_view entity_path, const Ts&... archetypes_or_collectiones) const { + void log(std::string_view entity_path, const Ts&... archetypes_or_collections) const { if (!is_enabled()) { return; } - try_log_with_timeless(entity_path, false, archetypes_or_collectiones...).handle(); + try_log_with_static(entity_path, false, archetypes_or_collections...).handle(); } - /// Logs one or more archetype and/or component batches as timeless data. + template + [[deprecated("Use `log_static` instead")]] void log_timeless( + std::string_view entity_path, const Ts&... archetypes_or_collections + ) const { + return log_static(entity_path, true, archetypes_or_collections...); + } + + /// Logs one or more archetype and/or component batches as static data. /// - /// Like `log` but logs the data as timeless: - /// Timeless data is present on all timelines and behaves as if it was recorded infinitely - /// far into the past. + /// Like `log` but logs the data as static: + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. /// /// Failures are handled with `Error::handle`. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param archetypes_or_collectiones Any type for which the `AsComponents` trait is implemented. + /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. /// - /// @see log, try_log_timeless, try_log_with_timeless + /// @see log, try_log_static, try_log_with_static template - void log_timeless(std::string_view entity_path, const Ts&... archetypes_or_collectiones) + void log_static(std::string_view entity_path, const Ts&... archetypes_or_collections) const { if (!is_enabled()) { return; } - try_log_with_timeless(entity_path, true, archetypes_or_collectiones...).handle(); + try_log_with_static(entity_path, true, archetypes_or_collections...).handle(); } /// Logs one or more archetype and/or component batches. @@ -370,76 +377,100 @@ namespace rerun { /// Unlike `log` this method returns an error if an error occurs during serialization or logging. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param archetypes_or_collectiones Any type for which the `AsComponents` trait is implemented. + /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. /// - /// @see log, try_log_timeless, try_log_with_timeless + /// @see log, try_log_static, try_log_with_static template - Error try_log(std::string_view entity_path, const Ts&... archetypes_or_collectiones) const { + Error try_log(std::string_view entity_path, const Ts&... archetypes_or_collections) const { if (!is_enabled()) { return Error::ok(); } - return try_log_with_timeless(entity_path, false, archetypes_or_collectiones...); + return try_log_with_static(entity_path, false, archetypes_or_collections...); + } + + template + [[deprecated("Use `try_log_static` instead")]] Error try_log_timeless( + std::string_view entity_path, const Ts&... archetypes_or_collections + ) const { + return try_log_static(entity_path, archetypes_or_collections...); } - /// Logs one or more archetype and/or component batches as timeless data, returning an error. + /// Logs one or more archetype and/or component batches as static data, returning an error. /// - /// See `log`/`log_timeless` for more information. - /// Unlike `log_timeless` this method returns if an error occurs during serialization or logging. + /// See `log`/`log_static` for more information. + /// Unlike `log_static` this method returns if an error occurs during serialization or logging. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param archetypes_or_collectiones Any type for which the `AsComponents` trait is implemented. + /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. /// \returns An error if an error occurs during serialization or logging. /// - /// @see log_timeless, try_log, try_log_with_timeless + /// @see log_static, try_log, try_log_with_static template - Error try_log_timeless( - std::string_view entity_path, const Ts&... archetypes_or_collectiones - ) const { + Error try_log_static(std::string_view entity_path, const Ts&... archetypes_or_collections) + const { if (!is_enabled()) { return Error::ok(); } - return try_log_with_timeless(entity_path, true, archetypes_or_collectiones...); + return try_log_with_static(entity_path, true, archetypes_or_collections...); + } + + template + [[deprecated("Use `log_with_static` instead")]] void log_with_timeless( + std::string_view entity_path, bool timeless, const Ts&... archetypes_or_collections + ) const { + return log_with_static(entity_path, timeless, archetypes_or_collections...); } - /// Logs one or more archetype and/or component batches optionally timeless, returning an error. + /// Logs one or more archetype and/or component batches optionally static, returning an error. /// - /// See `log`/`log_timeless` for more information. + /// See `log`/`log_static` for more information. /// Returns an error if an error occurs during serialization or logging. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param timeless If true, the logged components will be timeless. + /// \param static_ If true, the logged components will be static. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. - /// \param archetypes_or_collectiones Any type for which the `AsComponents` trait is implemented. + /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. /// - /// @see log, try_log, log_timeless, try_log_timeless + /// @see log, try_log, log_static, try_log_static template - void log_with_timeless( - std::string_view entity_path, bool timeless, const Ts&... archetypes_or_collectiones + void log_with_static( + std::string_view entity_path, bool static_, const Ts&... archetypes_or_collections ) const { - try_log_with_timeless(entity_path, timeless, archetypes_or_collectiones...).handle(); + try_log_with_static(entity_path, static_, archetypes_or_collections...).handle(); } - /// Logs one or more archetype and/or component batches optionally timeless, returning an error. + template + [[deprecated("Use `try_log_with_static` instead")]] Error try_log_with_timeless( + std::string_view entity_path, bool static_, const Ts&... archetypes_or_collections + ) const { + return try_log_with_static(entity_path, static_, archetypes_or_collections...); + } + + /// Logs one or more archetype and/or component batches optionally static, returning an error. /// - /// See `log`/`log_timeless` for more information. + /// See `log`/`log_static` for more information. /// Returns an error if an error occurs during serialization or logging. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param timeless If true, the logged components will be timeless. + /// \param static_ If true, the logged components will be static. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. - /// \param archetypes_or_collectiones Any type for which the `AsComponents` trait is implemented. + /// \param archetypes_or_collections Any type for which the `AsComponents` trait is implemented. /// This is the case for any archetype or `std::vector`/`std::array`/C-array of components implements. /// \returns An error if an error occurs during serialization or logging. /// - /// @see log, try_log, log_timeless, try_log_timeless + /// @see log, try_log, log_static, try_log_static template - Error try_log_with_timeless( - std::string_view entity_path, bool timeless, const Ts&... archetypes_or_collectiones + Error try_log_with_static( + std::string_view entity_path, bool static_, const Ts&... archetypes_or_collections ) const { if (!is_enabled()) { return Error::ok(); @@ -453,7 +484,7 @@ namespace rerun { } const Result> serialization_result = - AsComponents().serialize(archetypes_or_collectiones); + AsComponents().serialize(archetypes_or_collections); if (serialization_result.is_err()) { err = serialization_result.error; return; @@ -474,23 +505,29 @@ namespace rerun { ); RR_RETURN_NOT_OK(err); - return try_log_serialized_batches(entity_path, timeless, std::move(serialized_batches)); + return try_log_serialized_batches( + entity_path, + static_, + std::move(serialized_batches) + ); } /// Logs several serialized batches batches, returning an error on failure. /// - /// This is a more low-level API than `log`/`log_timeless\ and requires you to already serialize the data + /// This is a more low-level API than `log`/`log_static\ and requires you to already serialize the data /// ahead of time. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param timeless If true, the logged components will be timeless. + /// \param static_ If true, the logged components will be static. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. /// \param batches The serialized batches to log. /// - /// \see `log`, `try_log`, `log_timeless`, `try_log_timeless`, `try_log_with_timeless` + /// \see `log`, `try_log`, `log_static`, `try_log_static`, `try_log_with_static` Error try_log_serialized_batches( - std::string_view entity_path, bool timeless, std::vector batches + std::string_view entity_path, bool static_, std::vector batches ) const; /// Bottom level API that logs raw data cells to the recording stream. @@ -523,14 +560,18 @@ namespace rerun { /// /// \param filepath Path to the file to be logged. /// \param entity_path_prefix What should the logged entity paths be prefixed with? - /// \param timeless Should the logged data be timeless? + /// \param static_ If true, the logged components will be static. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. + /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. + /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. /// /// \see `try_log_file_from_path` void log_file_from_path( const std::filesystem::path& filepath, - std::string_view entity_path_prefix = std::string_view(), bool timeless = false + std::string_view entity_path_prefix = std::string_view(), bool static_ = false ) const { - try_log_file_from_path(filepath, entity_path_prefix, timeless).handle(); + try_log_file_from_path(filepath, entity_path_prefix, static_).handle(); } /// Logs the file at the given `path` using all `DataLoader`s available. @@ -544,12 +585,16 @@ namespace rerun { /// /// \param filepath Path to the file to be logged. /// \param entity_path_prefix What should the logged entity paths be prefixed with? - /// \param timeless Should the logged data be timeless? + /// \param static_ If true, the logged components will be static. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. + /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. + /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. /// /// \see `log_file_from_path` Error try_log_file_from_path( const std::filesystem::path& filepath, - std::string_view entity_path_prefix = std::string_view(), bool timeless = false + std::string_view entity_path_prefix = std::string_view(), bool static_ = false ) const; /// Logs the given `contents` using all `DataLoader`s available. @@ -565,19 +610,23 @@ namespace rerun { /// \param contents Contents to be logged. /// \param contents_size Size in bytes of the `contents`. /// \param entity_path_prefix What should the logged entity paths be prefixed with? - /// \param timeless Should the logged data be timeless? + /// \param static_ If true, the logged components will be static. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. + /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. + /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. /// /// \see `try_log_file_from_contents` void log_file_from_contents( const std::filesystem::path& filepath, const std::byte* contents, size_t contents_size, - std::string_view entity_path_prefix = std::string_view(), bool timeless = false + std::string_view entity_path_prefix = std::string_view(), bool static_ = false ) const { try_log_file_from_contents( filepath, contents, contents_size, entity_path_prefix, - timeless + static_ ) .handle(); } @@ -595,12 +644,16 @@ namespace rerun { /// \param contents Contents to be logged. /// \param contents_size Size in bytes of the `contents`. /// \param entity_path_prefix What should the logged entity paths be prefixed with? - /// \param timeless Should the logged data be timeless? + /// \param static_ If true, the logged components will be static. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. + /// Otherwise, the data will be timestamped automatically with `log_time` and `log_tick`. + /// Additional timelines set by `set_time_sequence` or `set_time` will also be included. /// /// \see `log_file_from_contents` Error try_log_file_from_contents( const std::filesystem::path& filepath, const std::byte* contents, size_t contents_size, - std::string_view entity_path_prefix = std::string_view(), bool timeless = false + std::string_view entity_path_prefix = std::string_view(), bool static_ = false ) const; /// @} diff --git a/rerun_cpp/tests/recording_stream.cpp b/rerun_cpp/tests/recording_stream.cpp index 0a028e39d1e9..88840e3c9f62 100644 --- a/rerun_cpp/tests/recording_stream.cpp +++ b/rerun_cpp/tests/recording_stream.cpp @@ -164,7 +164,7 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE }; stream.log("as-carray", c_style_array); - stream.log_timeless("as-carray", c_style_array); + stream.log_static("as-carray", c_style_array); } THEN("components as std::initializer_list can be logged") { const auto c_style_array = { @@ -172,7 +172,7 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE rerun::components::Position2D{4.0, 5.0}, }; stream.log("as-initializer-list", c_style_array); - stream.log_timeless("as-initializer-list", c_style_array); + stream.log_static("as-initializer-list", c_style_array); } THEN("components as std::array can be logged") { stream.log( @@ -182,7 +182,7 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE rerun::Vec2D{4.0, 5.0}, } ); - stream.log_timeless( + stream.log_static( "as-array", std::array{ rerun::Vec2D{1.0, 2.0}, @@ -198,7 +198,7 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE rerun::Vec2D{4.0, 5.0}, } ); - stream.log_timeless( + stream.log_static( "as-vector", std::vector{ rerun::Vec2D{1.0, 2.0}, @@ -226,7 +226,7 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE }, c_style_array ); - stream.log_timeless( + stream.log_static( "as-mix", std::vector{ rerun::Position2D(rerun::Vec2D{0.0, 0.0}), @@ -251,7 +251,7 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE }, std::array{rerun::Color(0xFF0000FF)} ); - stream.log_timeless( + stream.log_static( "log-splat", std::vector{ rerun::Position2D(rerun::Vec2D{0.0, 0.0}), @@ -267,7 +267,7 @@ SCENARIO("RecordingStream can be used for logging archetypes and components", TE rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} ).with_colors(rerun::Color(0xFF0000FF)) ); - stream.log_timeless( + stream.log_static( "log_archetype-splat", rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} ).with_colors(rerun::Color(0xFF0000FF)) diff --git a/tests/cpp/roundtrips/view_coordinates/main.cpp b/tests/cpp/roundtrips/view_coordinates/main.cpp index 1841a7fc0b44..84396ecfb395 100644 --- a/tests/cpp/roundtrips/view_coordinates/main.cpp +++ b/tests/cpp/roundtrips/view_coordinates/main.cpp @@ -3,5 +3,5 @@ int main(int, char** argv) { const auto rec = rerun::RecordingStream("rerun_example_roundtrip_view_coordinates"); rec.save(argv[1]).exit_on_failure(); - rec.log_timeless("/", rerun::archetypes::ViewCoordinates::RDF); + rec.log_static("/", rerun::archetypes::ViewCoordinates::RDF); } From acf32fe91c9e75b0743e55f82ceadef4e7791871 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 5 Apr 2024 17:58:58 +0200 Subject: [PATCH 208/508] Static data 4: static-aware Rust SDK (#5540) Just exposing all the new static stuff to the Rust SDK, and trying to kill the "timeless" terminology in the process. --- Part of a PR series that removes the concept of timeless data in favor of the much simpler concept of static data: - #5534 - #5535 - #5536 - #5537 - #5540 --- crates/re_data_source/src/data_loader/mod.rs | 3 +- crates/re_query_cache/tests/latest_at.rs | 2 +- crates/re_query_cache/tests/range.rs | 2 +- crates/re_sdk/src/recording_stream.rs | 82 ++++++++++++------- .../src/archetypes/annotation_context.rs | 2 +- crates/re_types/src/archetypes/asset3d.rs | 2 +- .../src/archetypes/segmentation_image.rs | 2 +- crates/re_types/src/archetypes/series_line.rs | 6 +- .../re_types/src/archetypes/series_point.rs | 6 +- .../src/archetypes/view_coordinates.rs | 2 +- .../all/annotation-context/example.rs | 4 +- .../all/annotation_context_connections.rs | 2 +- docs/snippets/all/annotation_context_rects.rs | 2 +- .../all/annotation_context_segmentation.rs | 2 +- docs/snippets/all/asset3d_out_of_tree.rs | 2 +- docs/snippets/all/asset3d_simple.rs | 2 +- docs/snippets/all/log-file/example.rs | 2 +- docs/snippets/all/scalar_multiple_plots.rs | 8 +- .../snippets/all/segmentation_image_simple.rs | 2 +- docs/snippets/all/series_line_style.rs | 6 +- docs/snippets/all/series_point_style.rs | 6 +- docs/snippets/all/view_coordinates_simple.rs | 2 +- examples/rust/clock/src/main.rs | 4 +- .../rust/external_data_loader/src/main.rs | 10 ++- examples/rust/incremental_logging/src/main.rs | 10 +-- examples/rust/log_file/src/main.rs | 4 +- examples/rust/objectron/src/main.rs | 6 +- examples/rust/raw_mesh/src/main.rs | 2 +- rerun_cpp/src/rerun/recording_stream.hpp | 6 +- .../roundtrips/view_coordinates/src/main.rs | 2 +- tests/rust/test_api/src/main.rs | 2 +- 31 files changed, 109 insertions(+), 86 deletions(-) diff --git a/crates/re_data_source/src/data_loader/mod.rs b/crates/re_data_source/src/data_loader/mod.rs index 559822b78715..4a107bc620cf 100644 --- a/crates/re_data_source/src/data_loader/mod.rs +++ b/crates/re_data_source/src/data_loader/mod.rs @@ -101,7 +101,8 @@ impl DataLoaderSettings { if let Some(timepoint) = timepoint { if timepoint.is_static() { - args.push("--timeless".to_owned()); + args.push("--timeless".to_owned()); // for backwards compatibility + args.push("--static".to_owned()); } for (timeline, time) in timepoint.iter() { diff --git a/crates/re_query_cache/tests/latest_at.rs b/crates/re_query_cache/tests/latest_at.rs index 33cb1bb1245a..e05d07c05adc 100644 --- a/crates/re_query_cache/tests/latest_at.rs +++ b/crates/re_query_cache/tests/latest_at.rs @@ -68,7 +68,7 @@ fn static_query() { DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); insert_and_react(&mut store, &mut caches, &row); - // Assign one of them a color with an explicit instance.. statically! + // Assign one of them a color with an explicit instance.. static_! let color_instances = vec![InstanceKey(1)]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; let row = DataRow::from_cells2_sized( diff --git a/crates/re_query_cache/tests/range.rs b/crates/re_query_cache/tests/range.rs index d2e98b581f56..8dd3a76cbbb8 100644 --- a/crates/re_query_cache/tests/range.rs +++ b/crates/re_query_cache/tests/range.rs @@ -158,7 +158,7 @@ fn static_range() { .unwrap(); insert_and_react(&mut store, &mut caches, &row); - // Insert statically too! + // Insert static_ too! let row = DataRow::from_cells2_sized( RowId::new(), entity_path.clone(), diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs index 5d11f84af239..85b17c6319a6 100644 --- a/crates/re_sdk/src/recording_stream.rs +++ b/crates/re_sdk/src/recording_stream.rs @@ -476,7 +476,7 @@ impl RecordingStreamBuilder { /// The WebSocket server will buffer all log data in memory so that late connecting viewers will get all the data. /// You can limit the amount of data buffered by the WebSocket server with the `server_memory_limit` argument. /// Once reached, the earliest logged data will be dropped. - /// Note that this means that timeless data may be dropped if logged early. + /// Note that this means that static data may be dropped if logged early (see ). /// /// ## Example /// @@ -499,6 +499,8 @@ impl RecordingStreamBuilder { /// true)?; /// # Ok::<(), Box>(()) /// ``` + // + // # TODO(#5531): keep static data around. #[cfg(feature = "web_viewer")] pub fn serve( self, @@ -860,7 +862,7 @@ impl RecordingStream { /// or an [`EntityPath`] constructed with [`crate::entity_path`]. /// See for more on entity paths. /// - /// See also: [`Self::log_timeless`] for logging timeless data. + /// See also: [`Self::log_static`] for logging static data. /// /// Internally, the stream will automatically micro-batch multiple log calls to optimize /// transport. @@ -885,7 +887,18 @@ impl RecordingStream { ent_path: impl Into, arch: &impl AsComponents, ) -> RecordingStreamResult<()> { - self.log_with_timeless(ent_path, false, arch) + self.log_with_static(ent_path, false, arch) + } + + #[deprecated(since = "0.16.0", note = "use `log_static` instead")] + #[doc(hidden)] + #[inline] + pub fn log_timeless( + &self, + ent_path: impl Into, + arch: &impl AsComponents, + ) -> RecordingStreamResult<()> { + self.log_static(ent_path, arch) } /// Log data to Rerun. @@ -893,8 +906,8 @@ impl RecordingStream { /// It can be used to log anything /// that implements the [`AsComponents`], such as any [archetype](https://docs.rs/rerun/latest/rerun/archetypes/index.html). /// - /// Timeless data is present on all timelines and behaves as if it was recorded infinitely far - /// into the past. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. /// All timestamp data associated with this message will be dropped right before sending it to Rerun. /// /// This is most often used for [`rerun::ViewCoordinates`](https://docs.rs/rerun/latest/rerun/archetypes/struct.ViewCoordinates.html) and @@ -909,20 +922,32 @@ impl RecordingStream { /// [SDK Micro Batching]: https://www.rerun.io/docs/reference/sdk-micro-batching /// [component bundle]: [`AsComponents`] #[inline] - pub fn log_timeless( + pub fn log_static( &self, ent_path: impl Into, arch: &impl AsComponents, ) -> RecordingStreamResult<()> { - self.log_with_timeless(ent_path, true, arch) + self.log_with_static(ent_path, true, arch) + } + + #[deprecated(since = "0.16.0", note = "use `log_static` instead")] + #[doc(hidden)] + #[inline] + pub fn log_with_timeless( + &self, + ent_path: impl Into, + static_: bool, + arch: &impl AsComponents, + ) -> RecordingStreamResult<()> { + self.log_with_static(ent_path, static_, arch) } /// Logs the contents of a [component bundle] into Rerun. /// - /// If `timeless` is set to `true`, all timestamp data associated with this message will be + /// If `static_` is set to `true`, all timestamp data associated with this message will be /// dropped right before sending it to Rerun. - /// Timeless data is present on all timelines and behaves as if it was recorded infinitely far - /// into the past. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. /// /// Otherwise, the data will be timestamped automatically based on the [`RecordingStream`]'s /// internal clock. @@ -940,17 +965,17 @@ impl RecordingStream { /// [SDK Micro Batching]: https://www.rerun.io/docs/reference/sdk-micro-batching /// [component bundle]: [`AsComponents`] #[inline] - pub fn log_with_timeless( + pub fn log_with_static( &self, ent_path: impl Into, - timeless: bool, + static_: bool, arch: &impl AsComponents, ) -> RecordingStreamResult<()> { let row_id = RowId::new(); // Create row-id as early as possible. It has a timestamp and is used to estimate e2e latency. self.log_component_batches_impl( row_id, ent_path, - timeless, + static_, arch.as_component_batches() .iter() .map(|any_comp_batch| any_comp_batch.as_ref()), @@ -959,10 +984,10 @@ impl RecordingStream { /// Logs a set of [`ComponentBatch`]es into Rerun. /// - /// If `timeless` is set to `false`, all timestamp data associated with this message will be + /// If `static_` is set to `true`, all timestamp data associated with this message will be /// dropped right before sending it to Rerun. - /// Timeless data is present on all timelines and behaves as if it was recorded infinitely far - /// into the past. + /// Static data has no time associated with it, exists on all timelines, and unconditionally shadows + /// any temporal data of the same type. /// /// Otherwise, the data will be timestamped automatically based on the [`RecordingStream`]'s /// internal clock. @@ -983,18 +1008,18 @@ impl RecordingStream { pub fn log_component_batches<'a>( &self, ent_path: impl Into, - timeless: bool, + static_: bool, comp_batches: impl IntoIterator, ) -> RecordingStreamResult<()> { let row_id = RowId::new(); // Create row-id as early as possible. It has a timestamp and is used to estimate e2e latency. - self.log_component_batches_impl(row_id, ent_path, timeless, comp_batches) + self.log_component_batches_impl(row_id, ent_path, static_, comp_batches) } fn log_component_batches_impl<'a>( &self, row_id: RowId, ent_path: impl Into, - timeless: bool, + static_: bool, comp_batches: impl IntoIterator, ) -> RecordingStreamResult<()> { if !self.is_enabled() { @@ -1071,13 +1096,13 @@ impl RecordingStream { }; if let Some(splatted) = splatted { - self.record_row(splatted, !timeless); + self.record_row(splatted, !static_); } // Always the primary component last so range-based queries will include the other data. // Since the primary component can't be splatted it must be in here, see(#1215). if let Some(instanced) = instanced { - self.record_row(instanced, !timeless); + self.record_row(instanced, !static_); } Ok(()) @@ -1096,9 +1121,9 @@ impl RecordingStream { &self, filepath: impl AsRef, entity_path_prefix: Option, - timeless: bool, + static_: bool, ) -> RecordingStreamResult<()> { - self.log_file(filepath, None, entity_path_prefix, timeless) + self.log_file(filepath, None, entity_path_prefix, static_) } /// Logs the given `contents` using all [`re_data_source::DataLoader`]s available. @@ -1115,9 +1140,9 @@ impl RecordingStream { filepath: impl AsRef, contents: std::borrow::Cow<'_, [u8]>, entity_path_prefix: Option, - timeless: bool, + static_: bool, ) -> RecordingStreamResult<()> { - self.log_file(filepath, Some(contents), entity_path_prefix, timeless) + self.log_file(filepath, Some(contents), entity_path_prefix, static_) } #[cfg(feature = "data_loaders")] @@ -1126,7 +1151,7 @@ impl RecordingStream { filepath: impl AsRef, contents: Option>, entity_path_prefix: Option, - timeless: bool, + static_: bool, ) -> RecordingStreamResult<()> { let Some(store_info) = self.store_info().clone() else { re_log::warn!("Ignored call to log_file() because RecordingStream has not been properly initialized"); @@ -1147,7 +1172,7 @@ impl RecordingStream { store_id: store_info.store_id, opened_store_id: None, entity_path_prefix, - timepoint: (!timeless).then(|| { + timepoint: (!static_).then(|| { self.with(|inner| { // Get the current time on all timelines, for the current recording, on the current // thread… @@ -1383,9 +1408,6 @@ impl RecordingStream { #[inline] pub fn record_row(&self, mut row: DataRow, inject_time: bool) { let f = move |inner: &RecordingStreamInner| { - // TODO(#2074): Adding a timeline to something timeless would suddenly make it not - // timeless… so for now it cannot even have a tick :/ - // // NOTE: We're incrementing the current tick still. let tick = inner .tick diff --git a/crates/re_types/src/archetypes/annotation_context.rs b/crates/re_types/src/archetypes/annotation_context.rs index aa3d9bcc4099..bd76adc91bbc 100644 --- a/crates/re_types/src/archetypes/annotation_context.rs +++ b/crates/re_types/src/archetypes/annotation_context.rs @@ -42,7 +42,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// .spawn()?; /// /// // create an annotation context to describe the classes -/// rec.log_timeless( +/// rec.log_static( /// "segmentation", /// &rerun::AnnotationContext::new([ /// (1, "red", rerun::Rgba32::from_rgb(255, 0, 0)), diff --git a/crates/re_types/src/archetypes/asset3d.rs b/crates/re_types/src/archetypes/asset3d.rs index d8627d3fec2d..4ba0e82e9143 100644 --- a/crates/re_types/src/archetypes/asset3d.rs +++ b/crates/re_types/src/archetypes/asset3d.rs @@ -39,7 +39,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_asset3d").spawn()?; /// -/// rec.log_timeless("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis +/// rec.log_static("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis /// rec.log("world/asset", &rerun::Asset3D::from_file(path)?)?; /// /// Ok(()) diff --git a/crates/re_types/src/archetypes/segmentation_image.rs b/crates/re_types/src/archetypes/segmentation_image.rs index 522865a652f1..0df5e01bd493 100644 --- a/crates/re_types/src/archetypes/segmentation_image.rs +++ b/crates/re_types/src/archetypes/segmentation_image.rs @@ -55,7 +55,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// ]); /// /// // log the annotation and the image -/// rec.log_timeless("/", &annotation)?; +/// rec.log_static("/", &annotation)?; /// /// rec.log("image", &rerun::SegmentationImage::try_from(image)?)?; /// diff --git a/crates/re_types/src/archetypes/series_line.rs b/crates/re_types/src/archetypes/series_line.rs index d7f6223c90ef..84cab72fc374 100644 --- a/crates/re_types/src/archetypes/series_line.rs +++ b/crates/re_types/src/archetypes/series_line.rs @@ -37,16 +37,16 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_series_line_style").spawn()?; /// /// // Set up plot styling: -/// // They are logged timeless as they don't change over time and apply to all timelines. +/// // They are logged static as they don't change over time and apply to all timelines. /// // Log two lines series under a shared root so that they show in the same plot by default. -/// rec.log_timeless( +/// rec.log_static( /// "trig/sin", /// &rerun::SeriesLine::new() /// .with_color([255, 0, 0]) /// .with_name("sin(0.01t)") /// .with_width(2.0), /// )?; -/// rec.log_timeless( +/// rec.log_static( /// "trig/cos", /// &rerun::SeriesLine::new() /// .with_color([0, 255, 0]) diff --git a/crates/re_types/src/archetypes/series_point.rs b/crates/re_types/src/archetypes/series_point.rs index 89b69ef68f75..a91a75cf6aea 100644 --- a/crates/re_types/src/archetypes/series_point.rs +++ b/crates/re_types/src/archetypes/series_point.rs @@ -37,9 +37,9 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_series_point_style").spawn()?; /// /// // Set up plot styling: -/// // They are logged timeless as they don't change over time and apply to all timelines. +/// // They are logged static as they don't change over time and apply to all timelines. /// // Log two point series under a shared root so that they show in the same plot by default. -/// rec.log_timeless( +/// rec.log_static( /// "trig/sin", /// &rerun::SeriesPoint::new() /// .with_color([255, 0, 0]) @@ -47,7 +47,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// .with_marker(rerun::components::MarkerShape::Circle) /// .with_marker_size(4.0), /// )?; -/// rec.log_timeless( +/// rec.log_static( /// "trig/cos", /// &rerun::SeriesPoint::new() /// .with_color([0, 255, 0]) diff --git a/crates/re_types/src/archetypes/view_coordinates.rs b/crates/re_types/src/archetypes/view_coordinates.rs index 233d4b1c0c9a..d1f856304562 100644 --- a/crates/re_types/src/archetypes/view_coordinates.rs +++ b/crates/re_types/src/archetypes/view_coordinates.rs @@ -37,7 +37,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// fn main() -> Result<(), Box> { /// let rec = rerun::RecordingStreamBuilder::new("rerun_example_view_coordinates").spawn()?; /// -/// rec.log_timeless("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis +/// rec.log_static("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis /// rec.log( /// "world/xyz", /// &rerun::Arrows3D::from_vectors( diff --git a/docs/snippets/all/annotation-context/example.rs b/docs/snippets/all/annotation-context/example.rs index 907e4170da3f..fa5bab0a4c96 100644 --- a/docs/snippets/all/annotation-context/example.rs +++ b/docs/snippets/all/annotation-context/example.rs @@ -1,6 +1,6 @@ // Annotation context with two classes, using two labeled classes, of which ones defines a color. MsgSender::new("masks") // Applies to all entities below "masks". - .with_timeless(true) + .with_static(true) .with_component(&[AnnotationContext { class_map: [ ClassDescription { @@ -28,7 +28,7 @@ MsgSender::new("masks") // Applies to all entities below "masks". // Annotation context with simple keypoints & keypoint connections. MsgSender::new("detections") // Applies to all entities below "detections". - .with_timeless(true) + .with_static(true) .with_component(&[AnnotationContext { class_map: std::iter::once(( ClassId(0), diff --git a/docs/snippets/all/annotation_context_connections.rs b/docs/snippets/all/annotation_context_connections.rs index 3ff2bb57c7b5..7cc8f4889fee 100644 --- a/docs/snippets/all/annotation_context_connections.rs +++ b/docs/snippets/all/annotation_context_connections.rs @@ -7,7 +7,7 @@ fn main() -> Result<(), Box> { // Log an annotation context to assign a label and color to each class // Create a class description with labels and color for each keypoint ID as well as some // connections between keypoints. - rec.log_timeless( + rec.log_static( "/", &rerun::AnnotationContext::new([rerun::ClassDescription { info: 0.into(), diff --git a/docs/snippets/all/annotation_context_rects.rs b/docs/snippets/all/annotation_context_rects.rs index fb4befb5a882..344fc1155dbc 100644 --- a/docs/snippets/all/annotation_context_rects.rs +++ b/docs/snippets/all/annotation_context_rects.rs @@ -5,7 +5,7 @@ fn main() -> Result<(), Box> { rerun::RecordingStreamBuilder::new("rerun_example_annotation_context_rects").spawn()?; // Log an annotation context to assign a label and color to each class - rec.log_timeless( + rec.log_static( "/", &rerun::AnnotationContext::new([ (1, "red", rerun::Rgba32::from_rgb(255, 0, 0)), diff --git a/docs/snippets/all/annotation_context_segmentation.rs b/docs/snippets/all/annotation_context_segmentation.rs index 2e33c2db2b16..97f8a47f6fd5 100644 --- a/docs/snippets/all/annotation_context_segmentation.rs +++ b/docs/snippets/all/annotation_context_segmentation.rs @@ -7,7 +7,7 @@ fn main() -> Result<(), Box> { .spawn()?; // create an annotation context to describe the classes - rec.log_timeless( + rec.log_static( "segmentation", &rerun::AnnotationContext::new([ (1, "red", rerun::Rgba32::from_rgb(255, 0, 0)), diff --git a/docs/snippets/all/asset3d_out_of_tree.rs b/docs/snippets/all/asset3d_out_of_tree.rs index 1b70eaf80709..8673eeb4a73d 100644 --- a/docs/snippets/all/asset3d_out_of_tree.rs +++ b/docs/snippets/all/asset3d_out_of_tree.rs @@ -13,7 +13,7 @@ fn main() -> anyhow::Result<()> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_asset3d_out_of_tree").spawn()?; - rec.log_timeless("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis + rec.log_static("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis rec.set_time_sequence("frame", 0); rec.log("world/asset", &rerun::Asset3D::from_file(path)?)?; diff --git a/docs/snippets/all/asset3d_simple.rs b/docs/snippets/all/asset3d_simple.rs index 63b05b2fe9cf..b379271ae2fd 100644 --- a/docs/snippets/all/asset3d_simple.rs +++ b/docs/snippets/all/asset3d_simple.rs @@ -10,7 +10,7 @@ fn main() -> anyhow::Result<()> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_asset3d").spawn()?; - rec.log_timeless("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis + rec.log_static("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis rec.log("world/asset", &rerun::Asset3D::from_file(path)?)?; Ok(()) diff --git a/docs/snippets/all/log-file/example.rs b/docs/snippets/all/log-file/example.rs index 5d8776510fc8..12a340454a3d 100644 --- a/docs/snippets/all/log-file/example.rs +++ b/docs/snippets/all/log-file/example.rs @@ -2,4 +2,4 @@ let rec = rerun::RecordingStreamBuilder::new("rerun_example_log_file").spawn()?; - rec.log_file_from_path(&args[1], None /* prefix */, true /* timeless */)?; + rec.log_file_from_path(&args[1], None /* prefix */, true /* static */)?; diff --git a/docs/snippets/all/scalar_multiple_plots.rs b/docs/snippets/all/scalar_multiple_plots.rs index f7a60c2f647a..6e805aeaddd4 100644 --- a/docs/snippets/all/scalar_multiple_plots.rs +++ b/docs/snippets/all/scalar_multiple_plots.rs @@ -5,22 +5,22 @@ fn main() -> Result<(), Box> { let mut lcg_state = 0_i64; // Set up plot styling: - // They are logged timeless as they don't change over time and apply to all timelines. + // They are logged static as they don't change over time and apply to all timelines. // Log two lines series under a shared root so that they show in the same plot by default. - rec.log_timeless( + rec.log_static( "trig/sin", &rerun::SeriesLine::new() .with_color([255, 0, 0]) .with_name("sin(0.01t)"), )?; - rec.log_timeless( + rec.log_static( "trig/cos", &rerun::SeriesLine::new() .with_color([0, 255, 0]) .with_name("cos(0.01t)"), )?; // Log scattered points under a different root so that they show in a different plot by default. - rec.log_timeless("scatter/lcg", &rerun::SeriesPoint::new())?; + rec.log_static("scatter/lcg", &rerun::SeriesPoint::new())?; for t in 0..((std::f32::consts::TAU * 2.0 * 100.0) as i64) { rec.set_time_sequence("step", t); diff --git a/docs/snippets/all/segmentation_image_simple.rs b/docs/snippets/all/segmentation_image_simple.rs index de50078b86c6..f9a6f2599a3f 100644 --- a/docs/snippets/all/segmentation_image_simple.rs +++ b/docs/snippets/all/segmentation_image_simple.rs @@ -17,7 +17,7 @@ fn main() -> Result<(), Box> { ]); // log the annotation and the image - rec.log_timeless("/", &annotation)?; + rec.log_static("/", &annotation)?; rec.log("image", &rerun::SegmentationImage::try_from(image)?)?; diff --git a/docs/snippets/all/series_line_style.rs b/docs/snippets/all/series_line_style.rs index 7bacf4d3775b..27754cd839aa 100644 --- a/docs/snippets/all/series_line_style.rs +++ b/docs/snippets/all/series_line_style.rs @@ -4,16 +4,16 @@ fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_series_line_style").spawn()?; // Set up plot styling: - // They are logged timeless as they don't change over time and apply to all timelines. + // They are logged static as they don't change over time and apply to all timelines. // Log two lines series under a shared root so that they show in the same plot by default. - rec.log_timeless( + rec.log_static( "trig/sin", &rerun::SeriesLine::new() .with_color([255, 0, 0]) .with_name("sin(0.01t)") .with_width(2.0), )?; - rec.log_timeless( + rec.log_static( "trig/cos", &rerun::SeriesLine::new() .with_color([0, 255, 0]) diff --git a/docs/snippets/all/series_point_style.rs b/docs/snippets/all/series_point_style.rs index b9332ba2b673..6843342c0b76 100644 --- a/docs/snippets/all/series_point_style.rs +++ b/docs/snippets/all/series_point_style.rs @@ -4,9 +4,9 @@ fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_series_point_style").spawn()?; // Set up plot styling: - // They are logged timeless as they don't change over time and apply to all timelines. + // They are logged static as they don't change over time and apply to all timelines. // Log two point series under a shared root so that they show in the same plot by default. - rec.log_timeless( + rec.log_static( "trig/sin", &rerun::SeriesPoint::new() .with_color([255, 0, 0]) @@ -14,7 +14,7 @@ fn main() -> Result<(), Box> { .with_marker(rerun::components::MarkerShape::Circle) .with_marker_size(4.0), )?; - rec.log_timeless( + rec.log_static( "trig/cos", &rerun::SeriesPoint::new() .with_color([0, 255, 0]) diff --git a/docs/snippets/all/view_coordinates_simple.rs b/docs/snippets/all/view_coordinates_simple.rs index a738abcba426..1969b3b839fd 100644 --- a/docs/snippets/all/view_coordinates_simple.rs +++ b/docs/snippets/all/view_coordinates_simple.rs @@ -3,7 +3,7 @@ fn main() -> Result<(), Box> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_view_coordinates").spawn()?; - rec.log_timeless("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis + rec.log_static("world", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?; // Set an up-axis rec.log( "world/xyz", &rerun::Arrows3D::from_vectors( diff --git a/examples/rust/clock/src/main.rs b/examples/rust/clock/src/main.rs index 16322a47a03d..a39cefd79391 100644 --- a/examples/rust/clock/src/main.rs +++ b/examples/rust/clock/src/main.rs @@ -39,9 +39,9 @@ fn run(rec: &rerun::RecordingStream, args: &Args) -> anyhow::Result<()> { const WIDTH_M: f32 = 0.4; const WIDTH_H: f32 = 0.6; - rec.log_timeless("world", &rerun::ViewCoordinates::RIGHT_HAND_Y_UP)?; + rec.log_static("world", &rerun::ViewCoordinates::RIGHT_HAND_Y_UP)?; - rec.log_timeless( + rec.log_static( "world/frame", &rerun::Boxes3D::from_half_sizes([(LENGTH_S, LENGTH_S, 1.0)]), )?; diff --git a/examples/rust/external_data_loader/src/main.rs b/examples/rust/external_data_loader/src/main.rs index dec843c74e24..e6d44ea60433 100644 --- a/examples/rust/external_data_loader/src/main.rs +++ b/examples/rust/external_data_loader/src/main.rs @@ -41,10 +41,14 @@ struct Args { #[argh(option)] entity_path_prefix: Option, - /// optionally mark data to be logged as timeless + /// deprecated: alias for `--static` #[argh(switch)] timeless: bool, + /// optionally mark data to be logged statically + #[argh(arg_name = "static", switch)] + statically: bool, + /// optional timestamps to log at (e.g. `--time sim_time=1709203426`) (repeatable) #[argh(option)] time: Vec, @@ -99,9 +103,9 @@ fn main() -> anyhow::Result<()> { .entity_path_prefix .map_or_else(|| rerun::EntityPath::new(vec![]), rerun::EntityPath::from); - rec.log_with_timeless( + rec.log_with_static( entity_path_prefix.join(&rerun::EntityPath::from_file_path(&args.filepath)), - args.timeless, + args.statically || args.timeless, &rerun::TextDocument::new(text).with_media_type(MediaType::MARKDOWN), )?; diff --git a/examples/rust/incremental_logging/src/main.rs b/examples/rust/incremental_logging/src/main.rs index 68cc926ee197..05a1e8a5a06f 100644 --- a/examples/rust/incremental_logging/src/main.rs +++ b/examples/rust/incremental_logging/src/main.rs @@ -38,7 +38,7 @@ let radii = [rerun::Radius(0.1); 10]; // Only log colors and radii once. rec.set_time_sequence("frame_nr", 0); -rec.log_component_batches("points", false, /* timeless */ [&colors as &dyn rerun::ComponentBatch, &radii])?; +rec.log_component_batches("points", false /* static */, [&colors as &dyn rerun::ComponentBatch, &radii])?; let mut rng = rand::thread_rng(); let dist = Uniform::new(-5., 5.); @@ -56,7 +56,7 @@ Move the time cursor around, and notice how the colors and radii from frame 0 ar "#; fn run(rec: &rerun::RecordingStream) -> anyhow::Result<()> { - rec.log_timeless( + rec.log_static( "readme", &rerun::TextDocument::new(README).with_media_type(rerun::MediaType::MARKDOWN), )?; @@ -69,13 +69,13 @@ fn run(rec: &rerun::RecordingStream) -> anyhow::Result<()> { rec.set_time_sequence("frame_nr", 0); rec.log_component_batches( "points", - false, /* timeless */ + false, /* static */ [&colors as &dyn rerun::ComponentBatch, &radii], )?; - // Logging timelessly would also work. + // Logging statically would also work. // rec.log_component_batches( // "points", - // true, /* timeless */ + // true, /* static */ // [&colors as &dyn rerun::ComponentBatch, &radii], // )?; diff --git a/examples/rust/log_file/src/main.rs b/examples/rust/log_file/src/main.rs index e8479b0b607a..caad40a10371 100644 --- a/examples/rust/log_file/src/main.rs +++ b/examples/rust/log_file/src/main.rs @@ -43,7 +43,7 @@ fn run(rec: &rerun::RecordingStream, args: &Args) -> anyhow::Result<()> { if !args.from_contents { // Either log the file using its path… - rec.log_file_from_path(filepath, prefix.clone(), true /* timeless */)?; + rec.log_file_from_path(filepath, prefix.clone(), true /* static */)?; } else { // …or using its contents if you already have them loaded for some reason. if filepath.is_file() { @@ -52,7 +52,7 @@ fn run(rec: &rerun::RecordingStream, args: &Args) -> anyhow::Result<()> { filepath, std::borrow::Cow::Borrowed(&contents), prefix.clone(), - true, /* timeless */ + true, /* static */ )?; } } diff --git a/examples/rust/objectron/src/main.rs b/examples/rust/objectron/src/main.rs index a7b7b9e04c77..678b70db72d2 100644 --- a/examples/rust/objectron/src/main.rs +++ b/examples/rust/objectron/src/main.rs @@ -115,13 +115,13 @@ fn log_baseline_objects( for (id, bbox_half_size, transform, label) in boxes { let path = format!("world/annotations/box-{id}"); - rec.log_timeless( + rec.log_static( path.clone(), &rerun::Boxes3D::from_half_sizes([bbox_half_size]) .with_labels([label]) .with_colors([rerun::Color::from_rgb(160, 230, 130)]), )?; - rec.log_timeless(path, &rerun::Transform3D::new(transform))?; + rec.log_static(path, &rerun::Transform3D::new(transform))?; } Ok(()) @@ -331,7 +331,7 @@ fn run(rec: &rerun::RecordingStream, args: &Args) -> anyhow::Result<()> { let annotations = read_annotations(&store_info.path_annotations)?; // See https://github.com/google-research-datasets/Objectron/issues/39 for coordinate systems - rec.log_timeless("world", &rerun::ViewCoordinates::RUB)?; + rec.log_static("world", &rerun::ViewCoordinates::RUB)?; log_baseline_objects(rec, &annotations.objects)?; diff --git a/examples/rust/raw_mesh/src/main.rs b/examples/rust/raw_mesh/src/main.rs index dc40f77cd18f..d5781de96501 100644 --- a/examples/rust/raw_mesh/src/main.rs +++ b/examples/rust/raw_mesh/src/main.rs @@ -164,7 +164,7 @@ fn run(rec: &RecordingStream, args: &Args) -> anyhow::Result<()> { // Log raw glTF nodes and their transforms with Rerun for root in nodes { re_log::info!(scene = root.name, "logging glTF scene"); - rec.log_timeless(root.name.as_str(), &rerun::ViewCoordinates::RIGHT_HAND_Y_UP)?; + rec.log_static(root.name.as_str(), &rerun::ViewCoordinates::RIGHT_HAND_Y_UP)?; log_node(rec, root)?; } diff --git a/rerun_cpp/src/rerun/recording_stream.hpp b/rerun_cpp/src/rerun/recording_stream.hpp index 410e67df659d..a25de265d503 100644 --- a/rerun_cpp/src/rerun/recording_stream.hpp +++ b/rerun_cpp/src/rerun/recording_stream.hpp @@ -505,11 +505,7 @@ namespace rerun { ); RR_RETURN_NOT_OK(err); - return try_log_serialized_batches( - entity_path, - static_, - std::move(serialized_batches) - ); + return try_log_serialized_batches(entity_path, static_, std::move(serialized_batches)); } /// Logs several serialized batches batches, returning an error on failure. diff --git a/tests/rust/roundtrips/view_coordinates/src/main.rs b/tests/rust/roundtrips/view_coordinates/src/main.rs index 8d89cf85b582..1fa3e4f7a888 100644 --- a/tests/rust/roundtrips/view_coordinates/src/main.rs +++ b/tests/rust/roundtrips/view_coordinates/src/main.rs @@ -10,7 +10,7 @@ struct Args { } fn run(rec: &RecordingStream, _args: &Args) -> anyhow::Result<()> { - rec.log_timeless("/", &ViewCoordinates::RDF)?; + rec.log_static("/", &ViewCoordinates::RDF)?; Ok(()) } diff --git a/tests/rust/test_api/src/main.rs b/tests/rust/test_api/src/main.rs index cad476a96669..c5d915f4a045 100644 --- a/tests/rust/test_api/src/main.rs +++ b/tests/rust/test_api/src/main.rs @@ -348,7 +348,7 @@ fn test_transforms_3d(rec: &RecordingStream) -> anyhow::Result<()> { rec: &RecordingStream, ent_path: impl Into, ) -> anyhow::Result<()> { - rec.log_timeless(ent_path, &ViewCoordinates::RIGHT_HAND_Z_UP) + rec.log_static(ent_path, &ViewCoordinates::RIGHT_HAND_Z_UP) .map_err(Into::into) } log_coordinate_space(rec, "transforms3d")?; From b0a42cfd5b2dab4a170672b99c0fece4068741ce Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Fri, 5 Apr 2024 20:38:25 +0200 Subject: [PATCH 209/508] nuScenes: add blueprint info + minor cleaning (#5813) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What ☝🏻 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5813) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5813?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5813?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5813) - [Docs preview](https://rerun.io/preview/05296af7fcc64cce31a9a454a07ce0867c8e4915/docs) - [Examples preview](https://rerun.io/preview/05296af7fcc64cce31a9a454a07ce0867c8e4915/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- docs/cspell.json | 2 ++ examples/python/nuscenes/README.md | 47 ++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/docs/cspell.json b/docs/cspell.json index a2e0288db9dc..217fdb207ee3 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -251,6 +251,8 @@ "noqa", "numpages", "numpy", + "nusc", + "nuscene", "nuScenes", "nyud", "obbs", diff --git a/examples/python/nuscenes/README.md b/examples/python/nuscenes/README.md index 8c5fc77b0ee5..7a5430a21401 100644 --- a/examples/python/nuscenes/README.md +++ b/examples/python/nuscenes/README.md @@ -1,6 +1,6 @@ - [Examples preview](https://rerun.io/preview/8b3283ee2b7863ee1d52674a292c188246d2c2ac/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/objectron/README.md | 33 +++++++++++++++++++++-------- examples/python/objectron/main.py | 9 ++++---- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/examples/python/objectron/README.md b/examples/python/objectron/README.md index 36d3dcec6ed2..0747a5443668 100644 --- a/examples/python/objectron/README.md +++ b/examples/python/objectron/README.md @@ -1,6 +1,6 @@ - [Examples preview](https://rerun.io/preview/b5c7f424890c4cb71b9198e46718839da11fdef0/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Jeremy Leibs --- crates/re_viewer/src/ui/welcome_screen/welcome_section.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs index 1724ddf51afd..76bb02cc41cc 100644 --- a/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/welcome_section.rs @@ -40,9 +40,9 @@ pub(super) fn welcome_section_ui(ui: &mut egui::Ui) { ui.add_space(4.0); }; - bullet_text(ui, "Log with the Rerun SDK in C++, Python, or Rust"); + bullet_text(ui, "Log data with the Rerun SDK in C++, Python, or Rust"); bullet_text(ui, "Visualize and explore live or recorded data"); - bullet_text(ui, "Customize using the UI or through code"); + bullet_text(ui, "Configure the viewer interactively or through code"); ui.add_space(9.0); if ui From 453fd67420b7c3d6d2b03ff80bfb54dc7f386471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 5 Apr 2024 21:00:06 +0200 Subject: [PATCH 212/508] Improve documentation previews (#5805) ### What Documentation previews are now built from the latest production deployment on every PR that includes changes to markdown files in `docs` or `examples`. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5805) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5805?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5805?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5805) - [Docs preview](https://rerun.io/preview/35c5f659949fd08ce283f077ea6de6217b38d432/docs) - [Examples preview](https://rerun.io/preview/35c5f659949fd08ce283f077ea6de6217b38d432/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/actions/deploy-vercel/action.yml | 14 +++- .github/actions/deploy-vercel/index.mjs | 77 ++++++------------- .github/actions/deploy-vercel/preview.mjs | 49 ++++++++++++ .github/actions/deploy-vercel/production.mjs | 68 ++++++++++++++++ .github/actions/deploy-vercel/test.mjs | 38 +++++++++ .github/actions/deploy-vercel/util.mjs | 14 +++- .github/actions/deploy-vercel/vercel.mjs | 61 ++++++++++++--- .github/pull_request_template.md | 2 - .github/workflows/on_pull_request.yml | 26 +++++++ .github/workflows/reusable_deploy_docs.yml | 1 + .../reusable_deploy_landing_preview.yml | 60 +++++++++++++++ scripts/ci/update_pr_body.py | 21 ----- 12 files changed, 340 insertions(+), 91 deletions(-) create mode 100644 .github/actions/deploy-vercel/preview.mjs create mode 100644 .github/actions/deploy-vercel/production.mjs create mode 100644 .github/actions/deploy-vercel/test.mjs create mode 100644 .github/workflows/reusable_deploy_landing_preview.yml diff --git a/.github/actions/deploy-vercel/action.yml b/.github/actions/deploy-vercel/action.yml index 9f2d084a0d2c..c33cc346b7e5 100644 --- a/.github/actions/deploy-vercel/action.yml +++ b/.github/actions/deploy-vercel/action.yml @@ -1,6 +1,10 @@ -# This action handles updating the target commit env variable (`RELEASE_COMMIT`) -# which is used as the pointer for `rerun.io/docs` and `rerun.io/examples` -# and triggering a redeploy of `rerun.io`. +# If `target` is set to `production`, this action handles updating the +# target commit env variable (`RELEASE_COMMIT`) which is used as the +# pointer for `rerun.io/docs` and `rerun.io/examples` and triggering +# a redeploy of `rerun.io`. + +# If `target` is set to `preview`, then this instead deploys a fresh preview +# with an override for `release_commit`, and sets the `vercel_preview_url` output. name: "Deploy rerun.io" @@ -25,6 +29,10 @@ inputs: release_version: description: "Which release version to update the deployment to" type: string + required: false + target: + description: "Which Vercel environment to deploy to" + type: string required: true runs: diff --git a/.github/actions/deploy-vercel/index.mjs b/.github/actions/deploy-vercel/index.mjs index 43b8bbb0fe85..b306ef8c2fb3 100644 --- a/.github/actions/deploy-vercel/index.mjs +++ b/.github/actions/deploy-vercel/index.mjs @@ -1,63 +1,32 @@ // @ts-check import { Client } from "./vercel.mjs"; -import { assert, getRequiredInput, info } from "./util.mjs"; +import { assert, getInput, getRequiredInput } from "./util.mjs"; +import { deployToProduction } from "./production.mjs"; +import { deployToPreview } from "./preview.mjs"; // These inputs are defined in `action.yml`, and should be kept in sync const token = getRequiredInput("vercel_token"); -const teamName = getRequiredInput("vercel_team_name"); -const projectName = getRequiredInput("vercel_project_name"); -const releaseCommit = getRequiredInput("release_commit"); -const releaseVersion = getRequiredInput("release_version"); +const team = getRequiredInput("vercel_team_name"); +const project = getRequiredInput("vercel_project_name"); +const commit = getRequiredInput("release_commit"); +const target = getRequiredInput("target"); const client = new Client(token); -info`Fetching team "${teamName}"`; -const availableTeams = await client.teams(); -assert(availableTeams, `failed to get team "${teamName}"`); -const team = availableTeams.find((team) => team.name === teamName); -assert(team, `failed to get team "${teamName}"`); - -info`Fetching project "${projectName}"`; -const projectsInTeam = await client.projects(team.id); -const project = projectsInTeam.find((project) => project.name === projectName); -assert(project, `failed to get project "${projectName}"`); - -info`Fetching latest production deployment`; -const productionDeployments = await client.deployments(team.id, project.id); -const latestProductionDeployment = productionDeployments[0]; -assert( - latestProductionDeployment, - `failed to get latest production deployment`, -); - -const environment = await client.envs(team.id, project.id); -const RELEASE_COMMIT_KEY = "RELEASE_COMMIT"; -const RELEASE_VERSION_KEY = "RELEASE_VERSION"; - -info`Fetching "${RELEASE_COMMIT_KEY}" env var`; -const releaseCommitEnv = environment.find( - (env) => env.key === RELEASE_COMMIT_KEY, -); -assert(releaseCommitEnv, `failed to get "${RELEASE_COMMIT_KEY}" env var`); - -info`Fetching "${RELEASE_VERSION_KEY}" env var`; -const releaseVersionEnv = environment.find( - (env) => env.key === RELEASE_VERSION_KEY, -); -assert(releaseVersionEnv, `failed to get "${RELEASE_VERSION_KEY}" env var`); - -info`Setting "${RELEASE_COMMIT_KEY}" env to "${releaseCommit}"`; -await client.setEnv(team.id, project.id, releaseCommitEnv.id, { - key: RELEASE_COMMIT_KEY, - value: releaseCommit, -}); - -info`Setting "${RELEASE_VERSION_KEY}" env to "${releaseVersion}"`; -await client.setEnv(team.id, project.id, releaseVersionEnv.id, { - key: RELEASE_VERSION_KEY, - value: releaseVersion, -}); - -info`Triggering redeploy`; -await client.redeploy(team.id, latestProductionDeployment.uid, "landing"); +switch (target) { + case "production": { + const version = getRequiredInput("release_version"); + await deployToProduction(client, { team, project, commit, version }); + break; + } + + case "preview": { + await deployToPreview(client, { team, project, commit }); + break; + } + + default: { + throw new Error(`"target" must be one of: production, preview`); + } +} diff --git a/.github/actions/deploy-vercel/preview.mjs b/.github/actions/deploy-vercel/preview.mjs new file mode 100644 index 000000000000..1ff791694d98 --- /dev/null +++ b/.github/actions/deploy-vercel/preview.mjs @@ -0,0 +1,49 @@ +// @ts-check + +import { assert, info, setOutput } from "./util.mjs"; +import { Client } from "./vercel.mjs"; + +/** + * + * @param {Client} client + * @param {{ + * team: string; + * project: string; + * commit: string; + * }} options + */ +export async function deployToPreview(client, options) { + info`Fetching team "${options.team}"`; + const availableTeams = await client.teams(); + assert(availableTeams, `failed to get team "${options.team}"`); + const team = availableTeams.find((team) => team.name === options.team); + assert(team, `failed to get team "${options.team}"`); + + info`Fetching project "${options.project}"`; + const projectsInTeam = await client.projects(team.id); + const project = projectsInTeam.find( + (project) => project.name === options.project, + ); + assert(project, `failed to get project "${options.project}"`); + + info`Fetching latest production deployment`; + const productionDeployments = await client.deployments(team.id, project.id); + const latestProductionDeployment = productionDeployments[0]; + assert( + latestProductionDeployment, + `failed to get latest production deployment`, + ); + + info`Deploying preview with RELEASE_COMMIT=${options.commit}`; + const { url } = await client.deployPreviewFrom( + team.id, + latestProductionDeployment.uid, + "landing-preview", + { + RELEASE_COMMIT: options.commit, + IS_PR_PREVIEW: "true", + }, + ); + + setOutput("vercel_preview_url", url); +} diff --git a/.github/actions/deploy-vercel/production.mjs b/.github/actions/deploy-vercel/production.mjs new file mode 100644 index 000000000000..f73b462850a4 --- /dev/null +++ b/.github/actions/deploy-vercel/production.mjs @@ -0,0 +1,68 @@ +// @ts-check + +import { assert, info } from "./util.mjs"; +import { Client } from "./vercel.mjs"; + +/** + * + * @param {Client} client + * @param {{ + * team: string; + * project: string; + * commit: string; + * version: string; + * }} options + */ +export async function deployToProduction(client, options) { + info`Fetching team "${options.team}"`; + const availableTeams = await client.teams(); + assert(availableTeams, `failed to get team "${options.team}"`); + const team = availableTeams.find((team) => team.name === options.team); + assert(team, `failed to get team "${options.team}"`); + + info`Fetching project "${options.project}"`; + const projectsInTeam = await client.projects(team.id); + const project = projectsInTeam.find( + (project) => project.name === options.project, + ); + assert(project, `failed to get project "${options.project}"`); + + info`Fetching latest production deployment`; + const productionDeployments = await client.deployments(team.id, project.id); + const latestProductionDeployment = productionDeployments[0]; + assert( + latestProductionDeployment, + `failed to get latest production deployment`, + ); + + const environment = await client.envs(team.id, project.id); + const RELEASE_COMMIT_KEY = "RELEASE_COMMIT"; + const RELEASE_VERSION_KEY = "RELEASE_VERSION"; + + info`Fetching "${RELEASE_COMMIT_KEY}" env var`; + const releaseCommitEnv = environment.find( + (env) => env.key === RELEASE_COMMIT_KEY, + ); + assert(releaseCommitEnv, `failed to get "${RELEASE_COMMIT_KEY}" env var`); + + info`Fetching "${RELEASE_VERSION_KEY}" env var`; + const releaseVersionEnv = environment.find( + (env) => env.key === RELEASE_VERSION_KEY, + ); + assert(releaseVersionEnv, `failed to get "${RELEASE_VERSION_KEY}" env var`); + + info`Setting "${RELEASE_COMMIT_KEY}" env to "${options.commit}"`; + await client.setEnv(team.id, project.id, releaseCommitEnv.id, { + key: RELEASE_COMMIT_KEY, + value: options.commit, + }); + + info`Setting "${RELEASE_VERSION_KEY}" env to "${options.version}"`; + await client.setEnv(team.id, project.id, releaseVersionEnv.id, { + key: RELEASE_VERSION_KEY, + value: options.version, + }); + + info`Triggering redeploy`; + await client.redeploy(team.id, latestProductionDeployment.uid, "landing"); +} diff --git a/.github/actions/deploy-vercel/test.mjs b/.github/actions/deploy-vercel/test.mjs new file mode 100644 index 000000000000..a4d63265d3be --- /dev/null +++ b/.github/actions/deploy-vercel/test.mjs @@ -0,0 +1,38 @@ +// @ts-check + +import { Client } from "./vercel.mjs"; +import { assert, info } from "./util.mjs"; + +const client = new Client("NzuZ9WBTnfUGiwHrhd7mit2E"); + +const teamName = "rerun"; +const projectName = "landing"; + +info`Fetching team "${teamName}"`; +const availableTeams = await client.teams(); +assert(availableTeams, `failed to get team "${teamName}"`); +const team = availableTeams.find((team) => team.name === teamName); +assert(team, `failed to get team "${teamName}"`); + +info`Fetching project "${projectName}"`; +const projectsInTeam = await client.projects(team.id); +const project = projectsInTeam.find((project) => project.name === projectName); +assert(project, `failed to get project "${projectName}"`); + +info`Fetching latest production deployment`; +const productionDeployments = await client.deployments(team.id, project.id); +const latestProductionDeployment = productionDeployments[0]; +assert( + latestProductionDeployment, + `failed to get latest production deployment`, +); + +const response = await client.deployPreviewFrom( + team.id, + latestProductionDeployment.uid, + "rerun-custom-preview-test", + { + RELEASE_COMMIT: "main", + }, +); +console.log(response); diff --git a/.github/actions/deploy-vercel/util.mjs b/.github/actions/deploy-vercel/util.mjs index c838307ffce5..24bb3d76db98 100644 --- a/.github/actions/deploy-vercel/util.mjs +++ b/.github/actions/deploy-vercel/util.mjs @@ -1,5 +1,8 @@ // @ts-check +import { appendFileSync } from "fs"; +import os from "os"; + /** * Log a message with level `INFO` * @@ -41,6 +44,16 @@ export function getRequiredInput(name) { return input; } +/** + * Set a GitHub Actions output for other workflows steps to read. + * @param {string} key + * @param {string} value + */ +export function setOutput(key, value) { + const outputFile = /** @type {string} */ (process.env["GITHUB_OUTPUT"]); + appendFileSync(outputFile, `${key}=${value}${os.EOL}`); +} + /** * Assert that `value` is truthy, throwing an error if it is not. * @@ -61,4 +74,3 @@ export function assert(value, message) { throw new Error(error); } } - diff --git a/.github/actions/deploy-vercel/vercel.mjs b/.github/actions/deploy-vercel/vercel.mjs index 454711012343..e69aab2a5fcb 100644 --- a/.github/actions/deploy-vercel/vercel.mjs +++ b/.github/actions/deploy-vercel/vercel.mjs @@ -106,7 +106,10 @@ export class Client { */ async teams() { const response = await this.get("v2/teams"); - assert("teams" in response, () => `failed to get teams: ${JSON.stringify(response)}`); + assert( + "teams" in response, + () => `failed to get teams: ${JSON.stringify(response)}`, + ); return response.teams; } @@ -119,7 +122,10 @@ export class Client { */ async projects(teamId) { const response = await this.get("v9/projects", { teamId }); - assert("projects" in response, () => `failed to get projects: ${JSON.stringify(response)}`); + assert( + "projects" in response, + () => `failed to get projects: ${JSON.stringify(response)}`, + ); return response.projects; } @@ -146,7 +152,7 @@ export class Client { }); assert( "deployments" in response, - () => `failed to get deployments: ${JSON.stringify(response)}` + () => `failed to get deployments: ${JSON.stringify(response)}`, ); return response.deployments; } @@ -162,7 +168,7 @@ export class Client { const response = await this.get(`v9/projects/${projectId}/env`, { teamId }); assert( "envs" in response, - () => `failed to get environment variables: ${JSON.stringify(response)}` + () => `failed to get environment variables: ${JSON.stringify(response)}`, ); return response.envs; } @@ -177,7 +183,10 @@ export class Client { * @returns {Promise} */ async getEnvDecrypted(teamId, projectId, envId) { - return await this.get(`v9/projects/${projectId}/env/${envId}`, { teamId, decrypt: "true" }); + return await this.get(`v9/projects/${projectId}/env/${envId}`, { + teamId, + decrypt: "true", + }); } /** @@ -194,12 +203,17 @@ export class Client { teamId, projectId, envId, - { key, target = ["production", "preview", "development"], type = "encrypted", value } + { + key, + target = ["production", "preview", "development"], + type = "encrypted", + value, + }, ) { return await this.patch( `v9/projects/${projectId}/env/${envId}`, { gitBranch: null, key, target, type, value }, - { teamId } + { teamId }, ); } @@ -217,9 +231,36 @@ export class Client { async redeploy(teamId, deploymentId, name) { return await this.post( `v13/deployments`, - { deploymentId, meta: { action: "redeploy" }, name, target: "production" }, - { teamId, forceNew: "1" } + { + deploymentId, + meta: { action: "redeploy" }, + name, + target: "production", + }, + { teamId, forceNew: "1" }, ); } -} + /** + * Trigger a preview deploy using the files of an existing deployment (`deploymentId`). + * + * @param {string} teamId + * @param {string} deploymentId + * @param {string} name + * @param {Record} [env] + * @returns {Promise} + */ + async deployPreviewFrom(teamId, deploymentId, name, env) { + // `target` not being set means "preview" + const body = { + deploymentId, + meta: { action: "redeploy" }, + name, + }; + if (env) { + body.env = env; + body.build = { env }; + } + return await this.post(`v13/deployments`, body, { teamId, forceNew: "1" }); + } +} diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 5a7ff934a584..0324b1da38a0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -23,7 +23,5 @@ To get an auto-generated PR description you can put "copilot:summary" or "copilo * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) -- [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) -- [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 451fd6a47f43..255617692e8e 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -55,6 +55,23 @@ jobs: - '**/CMakeLists.txt' - '**/*cmake' + docs-paths-filter: + runs-on: ubuntu-latest + outputs: + docs_changes: ${{ steps.filter.outputs.docs_changes }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + docs_changes: + - 'docs/content/**/*.md' + - 'examples/**/*.md' + - 'examples/manifest.toml' + rust-checks: name: "Rust Checks" if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.rust-paths-filter.outputs.rust_changes == 'true' @@ -186,3 +203,12 @@ jobs: CONCURRENCY: pr-${{ github.event.pull_request.number }} PR_NUMBER: ${{ github.event.pull_request.number }} secrets: inherit + + deploy-landing-preview: + name: "Deploy Landing Preview" + if: needs.docs-paths-filter.outputs.docs_changes == 'true' + uses: ./.github/workflows/reusable_deploy_landing_preview.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + PR_NUMBER: ${{ github.event.pull_request.number }} + secrets: inherit diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index 1f251647c174..736c9f089a78 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -262,3 +262,4 @@ jobs: vercel_project_name: ${{ vars.VERCEL_PROJECT_NAME }} release_commit: ${{ inputs.RELEASE_COMMIT }} release_version: ${{ inputs.RELEASE_VERSION }} + target: "production" diff --git a/.github/workflows/reusable_deploy_landing_preview.yml b/.github/workflows/reusable_deploy_landing_preview.yml new file mode 100644 index 000000000000..e1198e3124f5 --- /dev/null +++ b/.github/workflows/reusable_deploy_landing_preview.yml @@ -0,0 +1,60 @@ +name: Reusable Deploy Landing Preview + +on: + workflow_call: + inputs: + CONCURRENCY: + required: true + type: string + PR_NUMBER: + required: true + type: string + +concurrency: + group: ${{ inputs.CONCURRENCY }}-deploy-landing-preview + cancel-in-progress: true + +permissions: + contents: "write" + id-token: "write" + pull-requests: "write" + +jobs: + deploy: + name: Deploy + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.ref) || '' }} + + - name: Get sha + id: get-sha + shell: bash + run: | + full_commit="${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha }}" + echo "sha=$full_commit" >> "$GITHUB_OUTPUT" + + - name: Re-deploy rerun.io + id: deploy-vercel + uses: ./.github/actions/deploy-vercel + with: + vercel_token: ${{ secrets.VERCEL_TOKEN }} + vercel_team_name: ${{ vars.VERCEL_TEAM_NAME }} + vercel_project_name: ${{ vars.VERCEL_PROJECT_NAME }} + release_commit: ${{ steps.get-sha.outputs.sha }} + target: "preview" + + - name: Create PR comment + # https://github.com/mshick/add-pr-comment + uses: mshick/add-pr-comment@v2.8.1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + message: | + ## Deployed docs + + | Commit | Link | + | ------- | ----- | + | ${{ steps.get-sha.outputs.sha }} | https://${{ steps.deploy-vercel.outputs.vercel_preview_url }}/docs | diff --git a/scripts/ci/update_pr_body.py b/scripts/ci/update_pr_body.py index 7dccdd88fbd9..397d571cbb2a 100755 --- a/scripts/ci/update_pr_body.py +++ b/scripts/ci/update_pr_body.py @@ -18,13 +18,6 @@ from jinja2 import DebugUndefined, select_autoescape from jinja2.sandbox import SandboxedEnvironment -DOCS_PREVIEW_MARKER = "" -DOCS_PREVIEW_BARE_LINK = "- [Docs preview](https://rerun.io/preview/{{ pr.commit }}/docs) " -EXAMPLES_PREVIEW_MARKER = "" -EXAMPLES_PREVIEW_BARE_LINK = ( - "- [Examples preview](https://rerun.io/preview/{{ pr.commit }}/examples) " -) - # Need to protect code-blocks in the PR template. # See https://github.com/rerun-io/rerun/issues/3972 # @@ -119,20 +112,6 @@ def main() -> None: new_body = pr.body - docs_preview_link_end = new_body.find(DOCS_PREVIEW_MARKER) - if docs_preview_link_end != -1: - docs_preview_link_end += len(DOCS_PREVIEW_MARKER) - docs_preview_link_start = new_body.rfind("\n", 0, docs_preview_link_end) + 1 - new_body = new_body[:docs_preview_link_start] + DOCS_PREVIEW_BARE_LINK + new_body[docs_preview_link_end:] - - examples_preview_link_end = new_body.find(EXAMPLES_PREVIEW_MARKER) - if examples_preview_link_end != -1: - examples_preview_link_end += len(EXAMPLES_PREVIEW_MARKER) - examples_preview_link_start = new_body.rfind("\n", 0, examples_preview_link_end) + 1 - new_body = ( - new_body[:examples_preview_link_start] + EXAMPLES_PREVIEW_BARE_LINK + new_body[examples_preview_link_end:] - ) - lines = new_body.splitlines() codeblocks = extract_code_blocks(lines) text = "\n".join(lines) From b24f7a4bf81b979a28ec51afd9b697e3bb943498 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 5 Apr 2024 21:44:32 +0200 Subject: [PATCH 213/508] Add changelog for the unreleased 0.15 (#5809) ### What Slightly unconventionally I decided to add the changelog under the `# Unreleased` heading so we can merge this right away, without having to wait for a release. [Rendered](https://github.com/rerun-io/rerun/blob/emilk/0.15.0-changelog/CHANGELOG.md) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5809) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5809?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5809?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5809) - [Docs preview](https://rerun.io/preview/8aed4a43cc19d8f59ea4cad14884c223f14a96fd/docs) - [Examples preview](https://rerun.io/preview/8aed4a43cc19d8f59ea4cad14884c223f14a96fd/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Clement Rey Co-authored-by: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Co-authored-by: Antoine Beyeler Co-authored-by: Jeremy Leibs --- CHANGELOG.md | 264 ++++++++++++++++++++--- docs/cspell.json | 29 +-- scripts/generate_changelog.py | 2 +- tests/python/blueprint/save_blueprint.py | 2 +- 4 files changed, 249 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8068250e913c..c7ccf1aa869f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,213 @@ # Rerun changelog ## [Unreleased](https://github.com/rerun-io/rerun/compare/latest...HEAD) +The biggest news is the ability to create a _blueprint_ via the Python logging API: + +```py +import rerun.blueprint as rrb + +blueprint = rrb.Blueprint( + rrb.Vertical( + rrb.Spatial3DView(name="3D", origin="/"), + rrb.Horizontal( + rrb.TextDocumentView(name="README", origin="/description"), + rrb.Spatial2DView(name="Camera", origin="/camera/image"), + rrb.TimeSeriesView(origin="/plot"), + ), + row_shares=[3, 2], + ) + rrb.BlueprintPanel(expanded=True), + rrb.SelectionPanel(expanded=False), + rrb.TimePanel(expanded=False), +) +``` + +The blueprint can then be sent to the viewer with +```py +rr.send_blueprint(blueprint) +``` + +Or stored to a file, and then later opened in the viewer: +```py +blueprint.save("my_nice_dashboard.rbl") +``` + +In this case, the results looks something like this: -## [0.14.1](https://github.com/rerun-io/rerun/compare/0.14.0...0.14.1) - C++ build artifact fix + + + + + + + + +Blueprints are currently only supported in the Python API, with C++ and Rust support coming later. + + +### ✨ Overview & highlights +- 🟦 Configure the layout and content of space views from Python [(docs)](https://www.rerun.io/docs/howto/configure-viewer-through-code?speculative-link) +- 🖧 More powerful and flexible data loaders [(docs)](https://www.rerun.io/docs/reference/dataloaders?speculative-link) +- 🖵 Improved UI for managing recordings and applications +- 💾 Save and load blueprint files in the viewer +- 🎨 Configurable background color for 3D Space Views [#5443](https://github.com/rerun-io/rerun/pull/5443) +- 💪 Linux ARM64 support [#5489](https://github.com/rerun-io/rerun/pull/5489) [#5503](https://github.com/rerun-io/rerun/pull/5503) [#5511](https://github.com/rerun-io/rerun/pull/5511) +- 🖼️ Show examples in the welcome page +- 🖱️ Improve context-menu when right-clicking items in the blueprint panel and streams tree +- ❌ Remove `InstanceKey` from our logging APIs [#5395](https://github.com/rerun-io/rerun/pull/5395) +- ❌ Remove groups from blueprints panel [#5326](https://github.com/rerun-io/rerun/pull/5326) + +### 🔎 Details + +#### 🪵 Log API +- Replace `MarkerShape` with code-generated `enum` type [#5336](https://github.com/rerun-io/rerun/pull/5336) +- Key-less data model 1: scrap `InstanceKey` from public logging APIs [#5395](https://github.com/rerun-io/rerun/pull/5395) +- Remove the check for `WrongNumberOfInstances` [#5399](https://github.com/rerun-io/rerun/pull/5399) +- Control panel expanded state via blueprint APIs [#5484](https://github.com/rerun-io/rerun/pull/5484) +- Remove deprecated `TimeSeriesScalar` [#5604](https://github.com/rerun-io/rerun/pull/5604) +- Customizable data loaders [#5327](https://github.com/rerun-io/rerun/pull/5327) [#5328](https://github.com/rerun-io/rerun/pull/5328) [#5330](https://github.com/rerun-io/rerun/pull/5330) [#5337](https://github.com/rerun-io/rerun/pull/5337) [#5351](https://github.com/rerun-io/rerun/pull/5351) [#5355](https://github.com/rerun-io/rerun/pull/5355) [#5379](https://github.com/rerun-io/rerun/pull/5379) [#5361](https://github.com/rerun-io/rerun/pull/5361) [#5388](https://github.com/rerun-io/rerun/pull/5388) + +#### 🌊 C++ API +- Fix arrow libraries from download & build not being found in some cases [#5366](https://github.com/rerun-io/rerun/pull/5366) +- CMake: Add `RERUN_INSTALL_RERUN_C` option to disable installation of `rerun_c` library [#5374](https://github.com/rerun-io/rerun/pull/5374) (thanks [@traversaro](https://github.com/traversaro)!) +- CMake: Fix `install` not finding external `arrow` for dynamic linking [#5375](https://github.com/rerun-io/rerun/pull/5375) (thanks [@traversaro](https://github.com/traversaro)!) +- Make `pinhole.hpp` robust against `min/max` preprocessor macros (typically from `windows.h`) [#5432](https://github.com/rerun-io/rerun/pull/5432) +- Build C++ SDK for Linux ARM64 [#5489](https://github.com/rerun-io/rerun/pull/5489) +- Generate fewer `.cpp` files: Inline forward serialization of transparent components to their respective datatypes [#5544](https://github.com/rerun-io/rerun/pull/5544) +- Fix `RERUN_C_BUILD_ARTIFACT` path value if `CARGO_BUILD_TARGET` env variable is set [#5547](https://github.com/rerun-io/rerun/pull/5547) (thanks [@traversaro](https://github.com/traversaro)!) + +#### 🐍 Python API +- All python components that wrap a `bool` now implement `__bool__` [#5400](https://github.com/rerun-io/rerun/pull/5400) +- Add the remaining space views and name them consistently [#5498](https://github.com/rerun-io/rerun/pull/5498) +- Add option to include blueprint in an `.rrd` when calling `.save(…)` [#5572](https://github.com/rerun-io/rerun/pull/5572) +- Allow naming space view containers [#5626](https://github.com/rerun-io/rerun/pull/5626) + +#### 🦀 Rust API + +#### 🪳 Bug Fixes +- Sort text log space view on currently selected timeline [#5348](https://github.com/rerun-io/rerun/pull/5348) +- Fix parents of queried paths getting visualized, fix 2D objects not showing at all in 3D if their camera parent is not included [#5424](https://github.com/rerun-io/rerun/pull/5424) +- Fix: allow creating 3D space views for pinhole-only 3D scenes [#5563](https://github.com/rerun-io/rerun/pull/5563) +- Fix depth cloud bounding boxes for depth cloud visualizations with transforms [#5578](https://github.com/rerun-io/rerun/pull/5578) +- Fix image view not handling images with extra leading dimensions of size `1` [#5579](https://github.com/rerun-io/rerun/pull/5579) +- Fix web viewer crash on invalid url parameter [#5631](https://github.com/rerun-io/rerun/pull/5631) +- Be consistent in how items are removed from selection [#5643](https://github.com/rerun-io/rerun/pull/5643) +- Fix layout issue on welcome screen for narrow window, triggering debug assertion [#5650](https://github.com/rerun-io/rerun/pull/5650) +- Fix broken 2D space view heuristics in Python Notebooks [#5674](https://github.com/rerun-io/rerun/pull/5674) +- Avoid a hang on linux by always create the renderer, even when we have no store_view [#5724](https://github.com/rerun-io/rerun/pull/5724) +- Fix crash/freeze when zooming out too far in a plot [#5737](https://github.com/rerun-io/rerun/pull/5737) +- Fix `draw_order` not working [#5794](https://github.com/rerun-io/rerun/pull/5794) + +#### 🌁 Viewer Improvements +- Remove groups from blueprints panel [#5326](https://github.com/rerun-io/rerun/pull/5326) +- Improved tracking of which space views were generated by a heuristic [#5419](https://github.com/rerun-io/rerun/pull/5419) +- Configurable background color for 3D Space Views [#5443](https://github.com/rerun-io/rerun/pull/5443) +- Save recordings from web viewer [#5488](https://github.com/rerun-io/rerun/pull/5488) +- Support loading `.rbl` blueprint files [#5513](https://github.com/rerun-io/rerun/pull/5513) +- Tensor space view can now show images [#5567](https://github.com/rerun-io/rerun/pull/5567) +- Entity path query now shows simple statistics and warns if nothing is displayed [#5693](https://github.com/rerun-io/rerun/pull/5693) +- Go back to example page with browser Back-button [#5750](https://github.com/rerun-io/rerun/pull/5750) +- On Web, implement navigating back/forward with mouse buttons [#5792](https://github.com/rerun-io/rerun/pull/5792) + +#### 🧑‍🏫 Examples +- New `incremental_logging` example [#5462](https://github.com/rerun-io/rerun/pull/5462) +- New standalone example showing blueprint configuration of some stock [#5603](https://github.com/rerun-io/rerun/pull/5603) +- New example visualizing KISS-ICP [#5546](https://github.com/rerun-io/rerun/pull/5546) (thanks [@02alexander](https://github.com/02alexander)!) +- Remove car example [#5576](https://github.com/rerun-io/rerun/pull/5576) +- Add blueprint to `arkit_scenes` example, leveraging the viewer's ability to re-project 3D->2D [#5510](https://github.com/rerun-io/rerun/pull/5510) +- Add blueprint to `nuscenes` example [#5556](https://github.com/rerun-io/rerun/pull/5556) +- Add blueprint to Face Tracking example [#5616](https://github.com/rerun-io/rerun/pull/5616) +- Add blueprint to Gesture Detection example [#5619](https://github.com/rerun-io/rerun/pull/5619) +- Add blueprint to Human Pose Tracking example [#5612](https://github.com/rerun-io/rerun/pull/5612) +- Add blueprint to Live Camera Edge Detection example [#5613](https://github.com/rerun-io/rerun/pull/5613) +- Add blueprint to LLM Embedding Ner example [#5614](https://github.com/rerun-io/rerun/pull/5614) +- Add blueprint to Objectron example [#5617](https://github.com/rerun-io/rerun/pull/5617) +- Add blueprint to Signed Distance Fields example [#5635](https://github.com/rerun-io/rerun/pull/5635) +- Add blueprint to the RGBD example [#5623](https://github.com/rerun-io/rerun/pull/5623) +- ARFlow Example Page [#5320](https://github.com/rerun-io/rerun/pull/5320) (thanks [@YiqinZhao](https://github.com/YiqinZhao)!) +- Fix controlnet example for current `controlnet` package version and add blueprint [#5634](https://github.com/rerun-io/rerun/pull/5634) +- Fix RRT-Star example not showing up on website or rerun.io/viewer [#5628](https://github.com/rerun-io/rerun/pull/5628) +- Fix not logging 3D gesture z component correctly in Gesture Detection example [#5630](https://github.com/rerun-io/rerun/pull/5630) (thanks [@andreasnaoum](https://github.com/andreasnaoum)!) +- Updated READMEs for examples: LLM Embedding-Based Named Entity Recognition, nuScenes, Objectron, Open Photogrammetry Format, Raw Mesh [#5653](https://github.com/rerun-io/rerun/pull/5653) (thanks [@andreasnaoum](https://github.com/andreasnaoum)!) +- Updated READMEs for the examples - Batch 1 [#5620](https://github.com/rerun-io/rerun/pull/5620) (thanks [@andreasnaoum](https://github.com/andreasnaoum)!) + +#### 📚 Docs +- Docs: improve discoverability of image compression [#5675](https://github.com/rerun-io/rerun/pull/5675) +- Improve getting started doc section [#5689](https://github.com/rerun-io/rerun/pull/5689) +- Update web viewer links [#5738](https://github.com/rerun-io/rerun/pull/5738) +- Update docs with guides and tutorials for blueprint [#5641](https://github.com/rerun-io/rerun/pull/5641) +- Update README and description of `arkit_scenes` example [#5711](https://github.com/rerun-io/rerun/pull/5711) (thanks [@BirgerMoell](https://github.com/BirgerMoell)!) +- Improve readme of `depth_guided_stable_diffusion` example [#5593](https://github.com/rerun-io/rerun/pull/5593) (thanks [@BirgerMoell](https://github.com/BirgerMoell)!) + +#### 🖼 UI Improvements +- New timezone option: seconds since unix epoch [#5450](https://github.com/rerun-io/rerun/pull/5450) (thanks [@murgeljm](https://github.com/murgeljm)!) +- Always enable entity path filter editor [#5331](https://github.com/rerun-io/rerun/pull/5331) +- Add icons for entities and components, and use them everywhere [#5318](https://github.com/rerun-io/rerun/pull/5318) +- Add support for context menu for viewport tab title and selected container's children list [#5321](https://github.com/rerun-io/rerun/pull/5321) +- Fix `ListItem` indentation so icons are properly aligned [#5340](https://github.com/rerun-io/rerun/pull/5340) +- Blueprint tree always starts at the origin now, "projected" paths are called out explicitly [#5342](https://github.com/rerun-io/rerun/pull/5342) +- Merge example page into welcome screen [#5329](https://github.com/rerun-io/rerun/pull/5329) +- `ListItem`'s collapsing triangle is now styled consistently with the rest of the item [#5354](https://github.com/rerun-io/rerun/pull/5354) +- Add helpers to enable stable and controllable collapsed state in hierarchical lists [#5362](https://github.com/rerun-io/rerun/pull/5362) +- Different icon for empty entity paths [#5338](https://github.com/rerun-io/rerun/pull/5338) +- Merge quick start guides [#5378](https://github.com/rerun-io/rerun/pull/5378) +- Update welcome screen panel illustrations [#5394](https://github.com/rerun-io/rerun/pull/5394) +- More context menu in blueprint and streams tree: + - Refactor [#5392](https://github.com/rerun-io/rerun/pull/5392) + - Add support to show/hide `DataResult`s [#5397](https://github.com/rerun-io/rerun/pull/5397) + - Add support for removing `DataResult` from a space view [#5407](https://github.com/rerun-io/rerun/pull/5407) + - Create a new space view with selected entities [#5411](https://github.com/rerun-io/rerun/pull/5411) + - Add context menu to streams tree [#5422](https://github.com/rerun-io/rerun/pull/5422) + - Add "Expand/Collapse all" actions [#5433](https://github.com/rerun-io/rerun/pull/5433) + - Cleanup [#5456](https://github.com/rerun-io/rerun/pull/5456) +- Automatically expand and scroll the blueprint tree when focusing on an item [#5482](https://github.com/rerun-io/rerun/pull/5482) +- Save blueprint to file [#5491](https://github.com/rerun-io/rerun/pull/5491) +- Add new design guidelines for title casing etc [#5501](https://github.com/rerun-io/rerun/pull/5501) +- Automatically expand and scroll the streams tree when focusing on an item [#5494](https://github.com/rerun-io/rerun/pull/5494) +- Reduce the height of the tab bars and side panel titles [#5609](https://github.com/rerun-io/rerun/pull/5609) +- Support toggling item visibility on touch screens [#5624](https://github.com/rerun-io/rerun/pull/5624) +- Select active recording if nothing else is selected [#5627](https://github.com/rerun-io/rerun/pull/5627) +- Enable selecting data sources and blueprints and recordings in them [#5646](https://github.com/rerun-io/rerun/pull/5646) +- Warn user when a software rasterizer is used [#5655](https://github.com/rerun-io/rerun/pull/5655) +- Improve spacing and alignment of menus [#5680](https://github.com/rerun-io/rerun/pull/5680) +- Simplify Welcome Screen and use card-based layout for examples [#5699](https://github.com/rerun-io/rerun/pull/5699) +- Make selection history global instead of per recordings [#5739](https://github.com/rerun-io/rerun/pull/5739) +- Improve formatting of numbers on plot Y axis [#5753](https://github.com/rerun-io/rerun/pull/5753) +- Show all loaded applications in recordings panel [#5766](https://github.com/rerun-io/rerun/pull/5766) +- Wider selection panel by default [#5777](https://github.com/rerun-io/rerun/pull/5777) +- Tighter UI for tensor, annotation-context, view coordinates, recording [#5782](https://github.com/rerun-io/rerun/pull/5782) +- Always show welcome screen, but sometimes fade it in [#5787](https://github.com/rerun-io/rerun/pull/5787) + +#### 🕸️ Web +- Support loading multiple recordings and/or blueprints in web-viewer [#5548](https://github.com/rerun-io/rerun/pull/5548) +- Build release `.wasm` with debug symbols [#5708](https://github.com/rerun-io/rerun/pull/5708) + +#### 🧑‍💻 Dev-experience +- Build wheels for Linux ARM64 [#5511](https://github.com/rerun-io/rerun/pull/5511) + + +#### 📦 Dependencies +- Update wgpu to 0.19.3 [#5409](https://github.com/rerun-io/rerun/pull/5409) +- Update h2 to 0.3.26 to address RUSTSEC-2024-0332 [#5775](https://github.com/rerun-io/rerun/pull/5775) + +#### 🤷‍ Other +- Build CLI for Linux ARM64 [#5503](https://github.com/rerun-io/rerun/pull/5503) +- Allow hiding/showing entity subtrees under shown/hidden parent tree [#5508](https://github.com/rerun-io/rerun/pull/5508) +- Introduce basic support for `$origin` substitution in `EntityPathFilter` [#5517](https://github.com/rerun-io/rerun/pull/5517) +- Introduce `rr.notebook_show()` to simplify notebook experience [#5715](https://github.com/rerun-io/rerun/pull/5715) +- Also remove nested inclusions when removing a subtree [#5720](https://github.com/rerun-io/rerun/pull/5720) +- Prevent gratuitous blueprint saves by not garbage collecting when the blueprint hasn't changed [#5793](https://github.com/rerun-io/rerun/pull/5793) +- Refactor `Selection` using `IndexMap` and make it more encapsulated [#5569](https://github.com/rerun-io/rerun/pull/5569) + + +## [0.14.1](https://github.com/rerun-io/rerun/compare/0.14.0...0.14.1) - C++ build artifact fix - 2024-02-29 This release is identical to 0.14.0 and merely fixes an issue in the build artifacts for C++: 0.14.0 only contained binaries for Linux x64, this release has the full set for Linux x64, Windows x64, Mac x64 & Mac Arm64. -## [0.14.0](https://github.com/rerun-io/rerun/compare/0.13.0...0.14.0) - "Unlimited" point clouds & lines, quality of life improvements, bugfixes +## [0.14.0](https://github.com/rerun-io/rerun/compare/0.13.0...0.14.0) - "Unlimited" point clouds & lines, quality of life improvements, bugfixes - 2024-02-28 -### Overview & highlights +### ✨ Overview & highlights Originally, we planned to do only a bugfix release, but we got an unexpected amount of goodies amassed already. We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy these improvements in 0.14! @@ -22,7 +220,7 @@ We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy - 🐛 Fixes regressions in Space View spawn heuristics from 0.13, and many more bugfixes. - 🧑‍🏫 Two new examples: [Gesture Recognition](https://github.com/rerun-io/rerun/tree/release-0.14.0/examples/python/gesture_detection) & [RRT* Pathfinding](https://github.com/rerun-io/rerun/tree/release-0.14.0/examples/python/rrt-star) -### Details +### 🔎 Details #### 🪵 Log API - Add helpers for perspective cameras [#5238](https://github.com/rerun-io/rerun/pull/5238) @@ -89,7 +287,7 @@ We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy ## [0.13.0](https://github.com/rerun-io/rerun/compare/0.12.1...0.13.0) - Fast time series, improved layout editing & UI overrides - 2024-02-12 -### Overview & highlights +### ✨ Overview & highlights This release focuses on scalar time series -- both from a performance and UI perspectives. Check out our [associated blog post](https://www.rerun.io/blog/fast-plots) for more information. @@ -126,7 +324,7 @@ As well as a lot of miscellaneous bug fixes and usability improvements: see deta Check out our [migration guide](https://www.rerun.io/docs/reference/migration/migration-0-13). -### Details +### 🔎 Details #### 🪵 Log API - Mark TimeSeriesScalar as deprecated in all SDKs and documentation [#5102](https://github.com/rerun-io/rerun/pull/5102) @@ -260,12 +458,12 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Relax pyarrow dependency to `>=14.0.2` [#5054](https://github.com/rerun-io/rerun/pull/5054) - Update egui_tiles to 0.7.2 [#5107](https://github.com/rerun-io/rerun/pull/5107) -#### 🤷‍♂️ Other +#### 🤷 Other - Add `rerun --serve` and improve `--help` [#4834](https://github.com/rerun-io/rerun/pull/4834) - `rerun print`: print just summary, unless given `--verbose` [#5079](https://github.com/rerun-io/rerun/pull/5079) -## [0.12.1](https://github.com/rerun-io/rerun/compare/0.12.0...0.12.1) - 2024-01-17 - Data loader bug fixes +## [0.12.1](https://github.com/rerun-io/rerun/compare/0.12.0...0.12.1) - Data loader bug fixes - 2024-01-17 #### 🌊 C++ API - Fix CMake trying to pick up test folders outside of the Rerun project/zip [#4770](https://github.com/rerun-io/rerun/pull/4770) (thanks [@KevinGliewe](https://github.com/KevinGliewe)!) @@ -282,14 +480,14 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi #### 🧑‍💻 Dev-experience - External loaders: remove warnings on duplicated binary on `$PATH` [#4833](https://github.com/rerun-io/rerun/pull/4833) -#### 🤷‍♂️ Other +#### 🤷 Other - Include `Cargo.lock` in `rerun-cli` crate [#4750](https://github.com/rerun-io/rerun/pull/4750) - Replace `atty` dependency with `std::io::IsTerminal` [#4790](https://github.com/rerun-io/rerun/pull/4790) (thanks [@kpreid](https://github.com/kpreid)!) ## [0.12.0](https://github.com/rerun-io/rerun/compare/0.11.0...0.12.0) - Data Loaders, Container-editing, Python-3.12 - 2024-01-09 -### Overview & highlights +### ✨ Overview & highlights - 🌁 The Rerun Viewer now supports a plugin system for creating [arbitrary external data loaders](https://www.rerun.io/docs/howto/open-any-file). - 🕸️ More built-in examples are now available in the viewer. - 🐍 The Python SDK now works with Python-3.12. @@ -300,7 +498,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - There is no need for " quotes around path parts, instead we now use \ to escape special characters. - You need to escape any character that isn't alphabetical, numeric, ., -, or _. -### Details +### 🔎 Details #### 🌊 C++ API - Exposing `recording_id` in C and C++ SDKs [#4384](https://github.com/rerun-io/rerun/pull/4384) @@ -422,7 +620,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi - Update egui and wgpu [#4111](https://github.com/rerun-io/rerun/pull/4111) - Update Rust to 1.74.0 [#4390](https://github.com/rerun-io/rerun/pull/4390) -#### 🤷‍♂️ Other +#### 🤷 Other - Use `:` instead of `.` as the entity:component separator in paths [#4471](https://github.com/rerun-io/rerun/pull/4471) - File-like entity paths [#4476](https://github.com/rerun-io/rerun/pull/4476) - Make the new container blueprints the default behavior [#4642](https://github.com/rerun-io/rerun/pull/4642) @@ -430,7 +628,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi ## [0.11.0](https://github.com/rerun-io/rerun/compare/0.10.1...0.11.0) - C++ improvements & better Visible History - 2023-11-28 -### Overview & highlights +### ✨ Overview & highlights - 🌊 C++ SDK improvements - [Reference docs are live!](https://ref.rerun.io/docs/cpp/) @@ -451,7 +649,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi Special thanks to @dvad & @dangush for contributing! -### Details +### 🔎 Details #### 🌊 C++ SDK - Support std::chrono types for `set_time` on `rerun::RecordingStream` [#4134](https://github.com/rerun-io/rerun/pull/4134) @@ -515,7 +713,7 @@ Special thanks to @dvad & @dangush for contributing! ## [0.10.1](https://github.com/rerun-io/rerun/compare/0.10.0...0.10.1) - 2023-11-02 -### Overview & highlights +### ✨ Overview & highlights This is a small release primarily to tie up some loose ends for our C++ SDK. #### 🌊 C++ SDK @@ -539,7 +737,7 @@ This is a small release primarily to tie up some loose ends for our C++ SDK. Release blog post: -### Overview & highlights +### ✨ Overview & highlights * The C++ SDK is finally here! ```cpp #include @@ -557,7 +755,7 @@ Release blog post: * Add support for NV12-encoded images [#3541](https://github.com/rerun-io/rerun/pull/3541) (thanks [@zrezke](https://github.com/zrezke)!) * We now publish pre-built binaries for each release at -### Details +### 🔎 Details #### 🌊 C++ SDK - Has all the features of the Python and C++ SDK:s @@ -625,7 +823,7 @@ Release blog post: * Rust: `cargo add rerun` and `cargo install rerun-cli` * Online demo: -### Overview & highlights +### ✨ Overview & highlights - A bunch of bug fixes - Fix big performance regression when hovering images - The Rerun Viewer should now be visible to the system accessibility system @@ -687,7 +885,7 @@ Release blog post: * Online demo: -### Overview & highlights +### ✨ Overview & highlights Rerun 0.9.0 is a big release, that introduces a brand new logging API. This API is code-generated from a common definition, meaning the Python and Rust SDKs are very similar now. This will let us more easily extend and improve the API going forward. @@ -860,7 +1058,7 @@ Other highlights: - Update to egui 0.23 [#3523](https://github.com/rerun-io/rerun/pull/3523) - Update to wgpu 0.17 [#2980](https://github.com/rerun-io/rerun/pull/2980) -#### 🤷‍♂️ Other +#### 🤷 Other - Always protect at least one value on the timeline when running GC [#3357](https://github.com/rerun-io/rerun/pull/3357) @@ -916,7 +1114,7 @@ Other highlights: * Online demo: -### Overview & highlights +### ✨ Overview & highlights - `log_pinhole` is now easier to use in simple cases and supports non-RDF camera coordinates. [#2614](https://github.com/rerun-io/rerun/pull/2614) - You only need to set focal length and optional principal point instead of setting the full 3x3 matrix. - There is also a new argument: `camera_xyz` for setting the coordinate system. The default is RDF (the old @@ -1149,7 +1347,7 @@ for use-cases like real-time video feeds. [#2220](https://github.com/rerun-io/re - C++ codegen of structs and unions [#2707](https://github.com/rerun-io/rerun/pull/2707) - Fix cpp formatter differences [#2773](https://github.com/rerun-io/rerun/pull/2773) -#### 🤷‍♂️ Other +#### 🤷 Other - test_api: set different app_id based on what test is run [#2599](https://github.com/rerun-io/rerun/pull/2599) - Introduce `rerun compare` to check whether 2 rrd files are functionally equivalent [#2597](https://github.com/rerun-io/rerun/pull/2597) - Remove `files.exclude` in vscode settings [#2621](https://github.com/rerun-io/rerun/pull/2621) @@ -1159,7 +1357,7 @@ for use-cases like real-time video feeds. [#2220](https://github.com/rerun-io/re ## [0.7.0](https://github.com/rerun-io/rerun/compare/0.6.0...0.7.0) - improved transforms, better color mapping, bug & doc fixes - 2023-06-16 -### Overview & highlights +### ✨ Overview & highlights While we're working on significant updates around interfaces and customizability, here's a smaller release packed with useful improvements 🎉 @@ -1251,7 +1449,7 @@ here's a smaller release packed with useful improvements 🎉 ## [0.6.0](https://github.com/rerun-io/rerun/compare/v0.5.1...0.6.0) - 3D in 2D and SDK batching - 2023-05-26 -### Overview & highlights +### ✨ Overview & highlights - You can now show 3D objects in 2D views connected by Pinhole transforms [#2008](https://github.com/rerun-io/rerun/pull/2008) - You can quickly view images and meshes with `rerun mesh.obj image.png` [#2060](https://github.com/rerun-io/rerun/pull/2060) @@ -1413,7 +1611,7 @@ here's a smaller release packed with useful improvements 🎉 - Fix `cargo test` [#2199](https://github.com/rerun-io/rerun/pull/2199) - Fix run all for new rust-cli target & add rerun-web alias for quick running of the web player [#2203](https://github.com/rerun-io/rerun/pull/2203) -#### 🤷‍♂️ Other +#### 🤷 Other - Fix secret in dispatch_lint.yml [4848f98f2605a3caf9b7695273e0871efa2d44c8](https://github.com/rerun-io/rerun/commit/4848f98f2605a3caf9b7695273e0871efa2d44c8) - Only maintain a single manual-dispatch job for testing workflows [98f7de3b52b0fea6abe364f9d0ce0bd4c459caf1](https://github.com/rerun-io/rerun/commit/98f7de3b52b0fea6abe364f9d0ce0bd4c459caf1) - Add other build parametrizations to manual_dispatch.yml [dbdf275eaf17220d14811dc34b69b6a76e948e73](https://github.com/rerun-io/rerun/commit/dbdf275eaf17220d14811dc34b69b6a76e948e73) @@ -1448,7 +1646,7 @@ here's a smaller release packed with useful improvements 🎉 ## [0.5.1](https://github.com/rerun-io/rerun/compare/v0.5.1...v0.5.0) - Patch Release - 2023-05-01 -### Overview & highlights +### ✨ Overview & highlights This Release fixes a few small bugs on top of the v0.5.0 release. ### In Detail @@ -1461,7 +1659,7 @@ This Release fixes a few small bugs on top of the v0.5.0 release. ## [0.5.0](https://github.com/rerun-io/rerun/compare/v0.4.0...v0.5.0) - Jupyter MVP, GPU-based picking & colormapping, new datastore! - 2023-04-20 -### Overview & highlights +### ✨ Overview & highlights This new release adds MVP support for embedding Rerun in Jupyter notebooks, and brings significant performance improvements across all layers of the stack. @@ -1557,7 +1755,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Show previews of colormaps when selecting them [#1846](https://github.com/rerun-io/rerun/pull/1846) - Smooth out scroll wheel input for camera zooming [#1920](https://github.com/rerun-io/rerun/pull/1920) -#### 🤷‍♂️ Other Viewer improvements +#### 🤷 Other Viewer improvements - Change `EntityPathHash` to be 64 bit [#1723](https://github.com/rerun-io/rerun/pull/1723) - Central `GpuReadback` handling for re_viewer, experimental space view screenshots [#1717](https://github.com/rerun-io/rerun/pull/1717) - Readback depth from GPU picking [#1752](https://github.com/rerun-io/rerun/pull/1752) @@ -1618,7 +1816,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Improve PR template with better comment, and no copilot by default [#1901](https://github.com/rerun-io/rerun/pull/1901) - Optimize `generate_changelog.py` [#1912](https://github.com/rerun-io/rerun/pull/1912) -#### 🤷‍♂️ Other +#### 🤷 Other - Fix videos for GitHub in `CHANGELOG.md` [af7d3b192157f942e35f64d3561a9a8dbcc18bfa](https://github.com/rerun-io/rerun/commit/af7d3b192157f942e35f64d3561a9a8dbcc18bfa) - Don't run 3rd party bench suites on CI [#1787](https://github.com/rerun-io/rerun/pull/1787) - Remove `TensorTrait` [#1819](https://github.com/rerun-io/rerun/pull/1819) @@ -1633,7 +1831,7 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and https://user-images.githubusercontent.com/1220815/228241887-03b311e2-80e9-4541-9281-6d334a15ab04.mp4 -### Overview & highlights +### ✨ Overview & highlights * Add support for mesh vertex colors [#1671](https://github.com/rerun-io/rerun/pull/1671) * Lower memory use [#1535](https://github.com/rerun-io/rerun/pull/1535) * Improve garbage collection [#1560](https://github.com/rerun-io/rerun/pull/1560) @@ -1731,7 +1929,7 @@ We now host an experimental and unpolished web-viewer at - Turn on depth cloud backprojection by default [#1710](https://github.com/rerun-io/rerun/pull/1710) - Add radius boost for depth clouds on outline [#1713](https://github.com/rerun-io/rerun/pull/1713) -#### 🤷‍♂️ Other Viewer improvements +#### 🤷 Other Viewer improvements - Fix web feature name in error messages [#1521](https://github.com/rerun-io/rerun/pull/1521) - Use outlines for mesh selections instead of highlight colors [#1540](https://github.com/rerun-io/rerun/pull/1540) - Implement outlines for line renderer & use them for select & hover of "line-like" primitives in Viewer [#1553](https://github.com/rerun-io/rerun/pull/1553) @@ -1798,7 +1996,7 @@ We now host an experimental and unpolished web-viewer at - Fix `lint.py` [#1719](https://github.com/rerun-io/rerun/pull/1719) - Add a script that generates a changelog from recent PRs and their labels [#1718](https://github.com/rerun-io/rerun/pull/1718) -#### 🤷‍♂️ Other +#### 🤷 Other - Clean up opencv_canny example slightly [b487e550dcb87225858dc6f76b791a25e938e75e](https://github.com/rerun-io/rerun/commit/b487e550dcb87225858dc6f76b791a25e938e75e) - Lint fixes [9901e7c6735356b1970ddabc926bc5378d82e057](https://github.com/rerun-io/rerun/commit/9901e7c6735356b1970ddabc926bc5378d82e057) @@ -1809,7 +2007,7 @@ Remove potentially sensitive analytics, including path to rerun source code on p ## [0.3.0](https://github.com/rerun-io/rerun/compare/v0.2.0...v0.3.0) - 2023-03-07 -### Overview & highlights +### ✨ Overview & highlights After a successful launch a couple of weeks ago, we're back with our second release! With a few exceptions this release focuses on internal refactors & improving our processes. diff --git a/docs/cspell.json b/docs/cspell.json index 217fdb207ee3..3bdb4536a3b1 100644 --- a/docs/cspell.json +++ b/docs/cspell.json @@ -48,10 +48,10 @@ "binsearching", "binstall", "binutils", - "blendshape", - "blendshapes", "Birger", "Birkl", + "blendshape", + "blendshapes", "booktitle", "braindump", "bringup", @@ -88,10 +88,10 @@ "DCMAKE", "deallocate", "deallocation", - "denoising", - "Denoising", "debuginfo", "dedup", + "denoising", + "Denoising", "depgraph", "deskewed", "deskewing", @@ -99,6 +99,7 @@ "Dhariwal", "dicom", "Dilara", + "discoverability", "docstring", "docstrings", "Doersch", @@ -125,9 +126,9 @@ "everytime", "ewebsock", "extrinsics", - "farbfeld", - "FACEMESH", "facemesh", + "FACEMESH", + "farbfeld", "Farooq", "Feichtenhofer", "fieldname", @@ -233,6 +234,7 @@ "Müller", "multimodal", "multiview", + "murgeljm", "mydata", "myfile", "myfiles", @@ -293,8 +295,8 @@ "pypi", "pyright", "pytest", - "pytz", "Pythonic", + "pytz", "quickstart", "randn", "randr", @@ -337,8 +339,8 @@ "SCCACHE", "scipy", "scrollwheel", - "segs", "Segmentations", + "segs", "serde", "Shaohui", "Shap", @@ -366,8 +368,8 @@ "subsampled", "superquadrics", "tableofcontents", - "tensorboard", "taplo", + "tensorboard", "Tete", "Tewari", "Texcoord", @@ -386,6 +388,7 @@ "Tpng", "tqdm", "trackpad", + "traversaro", "trimesh", "Trimesh", "trimleft", // doxygen command @@ -394,16 +397,16 @@ "turtlebot", "TURTLEBOT", "UI's", + "umap", + "UMAP", "uncollapsed", - "unmultiplied", "uncond", + "unmultiplied", "Unorm", "unsetting", "upcasting", "upsampling", "upvote", - "UMAP", - "umap", "urdf", "URDF", "ureq", @@ -416,8 +419,8 @@ "Viktor", "virtualenv", "visualizability", - "voxels", "Vizzo", + "voxels", "vstack", "vsuryamurthy", "vulkan", diff --git a/scripts/generate_changelog.py b/scripts/generate_changelog.py index 6fcb31488e8a..5dd558f7c48e 100755 --- a/scripts/generate_changelog.py +++ b/scripts/generate_changelog.py @@ -279,7 +279,7 @@ def main() -> None: print_section("🧑‍💻 Dev-experience", dev_experience) print_section("🗣 Refactors", refactor) print_section("📦 Dependencies", dependencies) - print_section("🤷‍♂️ Other", misc) + print_section("🤷‍ Other", misc) print() print_section("Chronological changes (don't include these)", chronological) diff --git a/tests/python/blueprint/save_blueprint.py b/tests/python/blueprint/save_blueprint.py index bb64a3df5614..495ee982305c 100644 --- a/tests/python/blueprint/save_blueprint.py +++ b/tests/python/blueprint/save_blueprint.py @@ -9,4 +9,4 @@ rrb.BlueprintPanel(expanded=False), ) -blueprint.save("rerun_example_blueprint_test") +blueprint.save("rerun_example_blueprint_test.rbl") From 9b1bd475880f1216c36b2a685208e6eb91446337 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 5 Apr 2024 16:41:31 -0400 Subject: [PATCH 214/508] Add dep for docs-path-filter job (#5818) ### What Needed for the filter to work properly. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5818) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5818?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5818?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5818) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/on_pull_request.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 255617692e8e..feb35d6b7c95 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -207,6 +207,7 @@ jobs: deploy-landing-preview: name: "Deploy Landing Preview" if: needs.docs-paths-filter.outputs.docs_changes == 'true' + needs: docs-paths-filter uses: ./.github/workflows/reusable_deploy_landing_preview.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} From 0db0a8e5a32b946bb2f5b3546f509f73c7f89ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Sun, 7 Apr 2024 15:18:53 +0200 Subject: [PATCH 215/508] Fix video elements in docs (#5826) --- docs/content/getting-started/data-in/cpp.md | 3 +-- docs/content/getting-started/data-in/python.md | 3 +-- docs/content/getting-started/data-in/rust.md | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/content/getting-started/data-in/cpp.md b/docs/content/getting-started/data-in/cpp.md index b52dfe809b10..c2d7bbfb8cd1 100644 --- a/docs/content/getting-started/data-in/cpp.md +++ b/docs/content/getting-started/data-in/cpp.md @@ -7,8 +7,7 @@ In this section we'll log and visualize our first non-trivial dataset, putting m In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. diff --git a/docs/content/getting-started/data-in/python.md b/docs/content/getting-started/data-in/python.md index 73d73b6e40b5..17ec0cc5dea2 100644 --- a/docs/content/getting-started/data-in/python.md +++ b/docs/content/getting-started/data-in/python.md @@ -7,8 +7,7 @@ In this section we'll log and visualize our first non-trivial dataset, putting m In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. diff --git a/docs/content/getting-started/data-in/rust.md b/docs/content/getting-started/data-in/rust.md index 7ef473309956..c6c3ee682228 100644 --- a/docs/content/getting-started/data-in/rust.md +++ b/docs/content/getting-started/data-in/rust.md @@ -7,8 +7,7 @@ In this section we'll log and visualize our first non-trivial dataset, putting m In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: This guide aims to go wide instead of deep. From 079490b0171981b6bbc737d276ada1f1df505431 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 7 Apr 2024 19:49:16 +0200 Subject: [PATCH 216/508] Request attention when Rerun Viewer is sent new recording in background (#5780) ### What If the Rerun Viewer does _not_ have focus and the user sends it a new recording or blueprint, the viewer will now gently request attention _once_. On macOS it looks like this (notice the Rerun icon in the bottom left): https://github.com/rerun-io/rerun/assets/1148717/b7f8696c-c674-4db5-ad5d-08c1cc837de0 This does NOT happen if the Rerun Viewer window already has focus (is on top). On native this uses: * https://docs.rs/winit/latest/winit/window/enum.UserAttentionType.html On web this does nothing. ### Testing * [x] Linux * [x] macOS * [x] Windows ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5780) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5780?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5780?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5780) - [Docs preview](https://rerun.io/preview/31cdad871a470b3dab022f8b774f91cc73745457/docs) - [Examples preview](https://rerun.io/preview/31cdad871a470b3dab022f8b774f91cc73745457/examples) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_viewer/src/app.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 0de606aebbde..4562c234eb52 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -999,6 +999,13 @@ impl App { self.command_sender.send_system(SystemCommand::SetSelection( re_viewer_context::Item::StoreId(store_id.clone()), )); + + // If the viewer is in the background, tell the user that it has received something new. + egui_ctx.send_viewport_cmd( + egui::ViewportCommand::RequestUserAttention( + egui::UserAttentionType::Informational, + ), + ); } StoreKind::Blueprint => { // We wait with activating blueprints until they are fully loaded, @@ -1036,6 +1043,13 @@ impl App { re_log::warn!("Failed to make blueprint active: {err}"); }); store_hub.set_active_app(app_id); // Switch to this app, e.g. on drag-and-drop of a blueprint file + + // If the viewer is in the background, tell the user that it has received something new. + egui_ctx.send_viewport_cmd( + egui::ViewportCommand::RequestUserAttention( + egui::UserAttentionType::Informational, + ), + ); } } else { re_log::warn!( From b6b5e28c52f8932cbaa84df2bf1af1270c4c8778 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 8 Apr 2024 09:28:20 +0200 Subject: [PATCH 217/508] Fix/improve UI when viewing all components of an entity (#5831) ### What #### Before image Screenshot 2024-04-07 at 16 58 57 #### After Screenshot 2024-04-07 at 17 01 59 Screenshot 2024-04-07 at 17 02 05 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5831) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5831?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5831?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5831) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 1 + crates/re_data_ui/src/component.rs | 9 ++++++--- crates/re_data_ui/src/item_ui.rs | 3 ++- crates/re_format/Cargo.toml | 1 + .../re_types_core/src/components/instance_key_ext.rs | 1 + crates/re_ui/Cargo.toml | 1 + crates/re_ui/src/syntax_highlighting.rs | 10 +++++++--- 7 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 736c8a0d6758..e61f3f591945 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5030,6 +5030,7 @@ dependencies = [ "parking_lot", "rand", "re_entity_db", + "re_format", "re_log", "re_log_types", "serde", diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index f572dcaee7a3..95976dbf4043 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -1,7 +1,9 @@ use egui::NumExt; + use re_entity_db::{EntityPath, InstancePath}; use re_query::ComponentWithInstances; use re_types::ComponentName; +use re_ui::SyntaxHighlighting as _; use re_viewer_context::{UiVerbosity, ViewerContext}; use super::{table_for_verbosity, DataUi}; @@ -99,11 +101,12 @@ impl DataUi for EntityComponentWithInstances { table_for_verbosity(verbosity, ui) .resizable(false) .cell_layout(egui::Layout::left_to_right(egui::Align::Center)) - .columns(egui_extras::Column::auto(), 2) + .column(egui_extras::Column::auto()) + .column(egui_extras::Column::remainder()) .header(re_ui::ReUi::table_header_height(), |mut header| { re_ui::ReUi::setup_table_header(&mut header); header.col(|ui| { - ui.label("Instance key"); + ui.label("Index"); }); header.col(|ui| { ui.label(self.component_name().short_name()); @@ -124,7 +127,7 @@ impl DataUi for EntityComponentWithInstances { ui, None, &instance_path, - instance_key.to_string(), + instance_key.syntax_highlighted(ui.style()), ); }); row.col(|ui| { diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index d2a90128ac9b..c6c3acb77091 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -283,7 +283,7 @@ pub fn instance_path_parts_buttons( } if !instance_path.instance_key.is_splat() { - ui.strong("/"); + ui.weak("["); instance_path_button_to_ex( ctx, query, @@ -294,6 +294,7 @@ pub fn instance_path_parts_buttons( instance_path.instance_key.syntax_highlighted(ui.style()), with_icon, ); + ui.weak("]"); } }) .response diff --git a/crates/re_format/Cargo.toml b/crates/re_format/Cargo.toml index ba81b0d51558..32a9b4aafef5 100644 --- a/crates/re_format/Cargo.toml +++ b/crates/re_format/Cargo.toml @@ -26,6 +26,7 @@ default = [] [dependencies] num-traits.workspace = true +# TODO(emilk): remove these high-level dependencies, or split this crate into two. arrow2 = { workspace = true, optional = true } comfy-table = { workspace = true, optional = true } re_tuid = { workspace = true, optional = true } diff --git a/crates/re_types_core/src/components/instance_key_ext.rs b/crates/re_types_core/src/components/instance_key_ext.rs index 7ff7d5085e69..1907dcbf0e66 100644 --- a/crates/re_types_core/src/components/instance_key_ext.rs +++ b/crates/re_types_core/src/components/instance_key_ext.rs @@ -53,6 +53,7 @@ impl std::fmt::Display for InstanceKey { if self.is_splat() { "splat".fmt(f) } else { + // TODO(emilk): re_format::uint(self.0).fmt(f) (fix cyclic dependency!) self.0.fmt(f) } } diff --git a/crates/re_ui/Cargo.toml b/crates/re_ui/Cargo.toml index 2ac73a1ca399..c893eaae5ebc 100644 --- a/crates/re_ui/Cargo.toml +++ b/crates/re_ui/Cargo.toml @@ -27,6 +27,7 @@ default = [] [dependencies] re_entity_db.workspace = true # syntax-highlighting for InstancePath. TODO(emilk): move InstancePath +re_format.workspace = true re_log_types.workspace = true # syntax-highlighting for EntityPath egui_commonmark = { workspace = true, features = ["pulldown_cmark"] } diff --git a/crates/re_ui/src/syntax_highlighting.rs b/crates/re_ui/src/syntax_highlighting.rs index 63af7fba5f7b..3e399234002c 100644 --- a/crates/re_ui/src/syntax_highlighting.rs +++ b/crates/re_ui/src/syntax_highlighting.rs @@ -41,9 +41,11 @@ impl SyntaxHighlighting for EntityPathPart { impl SyntaxHighlighting for InstanceKey { fn syntax_highlight_into(&self, style: &Style, job: &mut LayoutJob) { - job.append("[", 0.0, faint_text_format(style)); - job.append(&self.to_string(), 0.0, text_format(style)); - job.append("]", 0.0, faint_text_format(style)); + if self.is_splat() { + job.append("splat", 0.0, text_format(style)); + } else { + job.append(&re_format::format_uint(self.0), 0.0, text_format(style)); + } } } @@ -64,7 +66,9 @@ impl SyntaxHighlighting for InstancePath { fn syntax_highlight_into(&self, style: &Style, job: &mut LayoutJob) { self.entity_path.syntax_highlight_into(style, job); if !self.instance_key.is_splat() { + job.append("[", 0.0, faint_text_format(style)); self.instance_key.syntax_highlight_into(style, job); + job.append("]", 0.0, faint_text_format(style)); } } } From e158114fc7282b88f2ebddadf74dcd42fbaf0ce5 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 14:34:46 +0200 Subject: [PATCH 218/508] New data APIs 0: `ClampedZip` iterator machinery (#5573) This introduces a new temporary `re_query2` crate, which won't ever be published. It will replace the existing `re_query` crate once all the necessary features have been backported. As of this PR, this crate only contains the `ClampedZip` iterator machinery, which is code generated for all the different arities. Since I'm very, _very tired_ of the awful DX of macros, I implemented a very low-tech code generator in the crate itself (`src/bin/clamped_zip.rs`) that just spews the generated code on stdout. That seems like the right complexity-to-maintenance tradeoff, considering that iterator combinators don't really ever change. `ClampedZip` naturally works with more than one required component, finally! - Fixes #4742 - Fixes #2750 Here's an example of one of these combinators: ```rust /// Returns a new [`ClampedZip1x2`] iterator. /// /// The number of elements in a clamped zip iterator corresponds to the number of elements in the /// shortest of its required iterators (`r0`). /// /// Optional iterators (`o0`, `o1`) will repeat their latest values if they happen to be to short /// to be zipped with the shortest of the required iterators. /// /// If an optional iterator is not only too short but actually empty, its associated default function /// (`o0_default_fn`, `o1_default_fn`) will be executed and the resulting value repeated as necessary. pub fn clamped_zip_1x2( r0: R0, o0: O0, o0_default_fn: D0, o1: O1, o1_default_fn: D1, ) -> ClampedZip1x2 where R0: IntoIterator, O0: IntoIterator, O0::Item: Clone, O1: IntoIterator, O1::Item: Clone, D0: Fn() -> O0::Item, D1: Fn() -> O1::Item, { ClampedZip1x2 { r0: r0.into_iter(), o0: o0.into_iter(), o1: o1.into_iter(), o0_default_fn, o1_default_fn, o0_latest_value: None, o1_latest_value: None, } } /// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional /// iterators. /// /// See [`clamped_zip_1x2`] for more information. pub struct ClampedZip1x2 where R0: Iterator, O0: Iterator, O0::Item: Clone, O1: Iterator, O1::Item: Clone, D0: Fn() -> O0::Item, D1: Fn() -> O1::Item, { r0: R0, o0: O0, o1: O1, o0_default_fn: D0, o1_default_fn: D1, o0_latest_value: Option, o1_latest_value: Option, } impl Iterator for ClampedZip1x2 where R0: Iterator, O0: Iterator, O0::Item: Clone, O1: Iterator, O1::Item: Clone, D0: Fn() -> O0::Item, D1: Fn() -> O1::Item, { type Item = (R0::Item, O0::Item, O1::Item); #[inline] fn next(&mut self) -> Option { let r0_next = self.r0.next()?; let o0_next = self.o0.next().or(self.o0_latest_value.take()); let o1_next = self.o1.next().or(self.o1_latest_value.take()); self.o0_latest_value = o0_next.clone(); self.o1_latest_value = o1_next.clone(); Some(( r0_next, o0_next.unwrap_or_else(|| (self.o0_default_fn)()), o1_next.unwrap_or_else(|| (self.o1_default_fn)()), )) } } ``` --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- Cargo.lock | 29 + Cargo.toml | 3 +- crates/re_query2/Cargo.toml | 72 + crates/re_query2/README.md | 5 + crates/re_query2/src/bin/clamped_zip.rs | 354 ++ .../re_query2/src/clamped_zip/.gitattributes | 1 + crates/re_query2/src/clamped_zip/generated.rs | 3124 +++++++++++++++++ crates/re_query2/src/clamped_zip/mod.rs | 64 + crates/re_query2/src/lib.rs | 58 + crates/re_query2/src/visible_history.rs | 126 + scripts/lint.py | 5 +- 11 files changed, 3839 insertions(+), 2 deletions(-) create mode 100644 crates/re_query2/Cargo.toml create mode 100644 crates/re_query2/README.md create mode 100644 crates/re_query2/src/bin/clamped_zip.rs create mode 100644 crates/re_query2/src/clamped_zip/.gitattributes create mode 100644 crates/re_query2/src/clamped_zip/generated.rs create mode 100644 crates/re_query2/src/clamped_zip/mod.rs create mode 100644 crates/re_query2/src/lib.rs create mode 100644 crates/re_query2/src/visible_history.rs diff --git a/Cargo.lock b/Cargo.lock index e61f3f591945..db1751e1cd7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4542,6 +4542,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "re_query2" +version = "0.15.0-alpha.5" +dependencies = [ + "ahash", + "anyhow", + "backtrace", + "criterion", + "document-features", + "itertools 0.12.0", + "mimalloc", + "nohash-hasher", + "rand", + "re_arrow2", + "re_data_store", + "re_format", + "re_log", + "re_log_types", + "re_tracing", + "re_tuid", + "re_types", + "re_types_core", + "serde", + "similar-asserts", + "smallvec", + "thiserror", + "unindent", +] + [[package]] name = "re_query_cache" version = "0.15.0-alpha.5" diff --git a/Cargo.toml b/Cargo.toml index e32cc1205c89..da3f2bc69b4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,9 +28,9 @@ version = "0.15.0-alpha.5" # In particular: if we compile rerun 0.3.0-alpha.0 we only want it to use # re_log_types 0.3.0-alpha.0, NOT 0.3.0-alpha.4 even though it is newer and semver-compatible. re_analytics = { path = "crates/re_analytics", version = "=0.15.0-alpha.5", default-features = false } -re_build_search_index = { path = "crates/re_build_search_index", version = "=0.15.0-alpha.5", default-features = false } re_build_examples = { path = "crates/re_build_examples", version = "=0.15.0-alpha.5", default-features = false } re_build_info = { path = "crates/re_build_info", version = "=0.15.0-alpha.5", default-features = false } +re_build_search_index = { path = "crates/re_build_search_index", version = "=0.15.0-alpha.5", default-features = false } re_build_tools = { path = "crates/re_build_tools", version = "=0.15.0-alpha.5", default-features = false } re_build_web_viewer = { path = "crates/re_build_web_viewer", version = "=0.15.0-alpha.5", default-features = false } re_crash_handler = { path = "crates/re_crash_handler", version = "=0.15.0-alpha.5", default-features = false } @@ -46,6 +46,7 @@ re_log_encoding = { path = "crates/re_log_encoding", version = "=0.15.0-alpha.5" re_log_types = { path = "crates/re_log_types", version = "=0.15.0-alpha.5", default-features = false } re_memory = { path = "crates/re_memory", version = "=0.15.0-alpha.5", default-features = false } re_query = { path = "crates/re_query", version = "=0.15.0-alpha.5", default-features = false } +re_query2 = { path = "crates/re_query2", version = "=0.15.0-alpha.5", default-features = false } re_query_cache = { path = "crates/re_query_cache", version = "=0.15.0-alpha.5", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.15.0-alpha.5", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.15.0-alpha.5", default-features = false } diff --git a/crates/re_query2/Cargo.toml b/crates/re_query2/Cargo.toml new file mode 100644 index 000000000000..6f67f6a8d7dc --- /dev/null +++ b/crates/re_query2/Cargo.toml @@ -0,0 +1,72 @@ +[package] +name = "re_query2" +authors.workspace = true +description = "Temporary crate meant to replace re_query" +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +# TODO(cmc): Replace re_query with this crate. Never publish this one. +publish = false +readme = "README.md" +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[package.metadata.docs.rs] +all-features = true + + +[features] +default = [] + +## Enable (de)serialization using serde. +serde = ["dep:serde"] + +## Enable codegen helper binaries (generates ClampedZip & RangeZip implementations). +codegen = ["unindent"] + + +[dependencies] +# Rerun dependencies: +re_data_store.workspace = true +re_format = { workspace = true, features = ["arrow"] } +re_log_types.workspace = true +re_types_core.workspace = true +re_log.workspace = true +re_tracing.workspace = true +re_tuid.workspace = true + +# External dependencies: +ahash.workspace = true +anyhow.workspace = true +arrow2.workspace = true +backtrace.workspace = true +document-features.workspace = true +itertools = { workspace = true } +nohash-hasher.workspace = true +serde = { workspace = true, features = ["derive", "rc"], optional = true } +smallvec.workspace = true +thiserror.workspace = true + +# Optional: +unindent = { workspace = true, optional = true } + + +[dev-dependencies] +re_types = { workspace = true, features = ["datagen"] } + +criterion.workspace = true +itertools = { workspace = true } +mimalloc.workspace = true +rand = { workspace = true, features = ["std", "std_rng"] } +similar-asserts.workspace = true + + +[lib] +bench = false + + +[[bin]] +name = "clamped_zip" +required-features = ["codegen"] diff --git a/crates/re_query2/README.md b/crates/re_query2/README.md new file mode 100644 index 000000000000..42bcc981d336 --- /dev/null +++ b/crates/re_query2/README.md @@ -0,0 +1,5 @@ +# re_query2 + +Temporary crate for implementing the new data APIs. Not published. + +Will replace `re_query` when ready. diff --git a/crates/re_query2/src/bin/clamped_zip.rs b/crates/re_query2/src/bin/clamped_zip.rs new file mode 100644 index 000000000000..bb4b642f4ac7 --- /dev/null +++ b/crates/re_query2/src/bin/clamped_zip.rs @@ -0,0 +1,354 @@ +//! CLI tool to generate `ClampedZip` implementations of different arities. + +use itertools::{izip, Itertools}; + +struct Params { + num_required: usize, + num_optional: usize, +} + +impl Params { + fn to_num_required(&self) -> String { + self.num_required.to_string() + } + + fn to_num_optional(&self) -> String { + self.num_optional.to_string() + } + + /// `1x3`, `2x2`… + fn to_suffix(&self) -> String { + format!("{}x{}", self.to_num_required(), self.to_num_optional()) + } + + /// `r0, r1, r2…`. + fn to_required_names(&self) -> Vec { + (0..self.num_required) + .map(|n| format!("r{n}")) + .collect_vec() + } + + /// `R0, R1, R2…`. + fn to_required_types(&self) -> Vec { + self.to_required_names() + .into_iter() + .map(|s| s.to_uppercase()) + .collect() + } + + /// `r0: R0, r1: R1, r2: R2…`. + fn to_required_params(&self) -> Vec { + izip!(self.to_required_names(), self.to_required_types()) + .map(|(n, t)| format!("{n}: {t}")) + .collect() + } + + /// `R0: (Into)Iterator, R1: (Into)Iterator, R2: (Into)Iterator…` + fn to_required_clauses(&self, into: bool) -> Vec { + let trait_name = if into { "IntoIterator" } else { "Iterator" }; + self.to_required_types() + .into_iter() + .map(|t| format!("{t}: {trait_name}")) + .collect() + } + + /// `o0, o1, o2…`. + fn to_optional_names(&self) -> Vec { + (0..self.num_optional) + .map(|n| format!("o{n}")) + .collect_vec() + } + + /// `O0, O1, O2…`. + fn to_optional_types(&self) -> Vec { + self.to_optional_names() + .into_iter() + .map(|s| s.to_uppercase()) + .collect() + } + + /// `o0: O0, o1: O1, o2: O2…`. + fn to_optional_params(&self) -> Vec { + izip!(self.to_optional_names(), self.to_optional_types()) + .map(|(n, t)| format!("{n}: {t}")) + .collect() + } + + /// `O0: IntoIterator, O0::Item: Clone, O1: IntoIterator, O1::Item: Clone…` + fn to_optional_clauses(&self, into: bool) -> Vec { + let trait_name = if into { "IntoIterator" } else { "Iterator" }; + self.to_optional_types() + .into_iter() + .map(|t| format!("{t}: {trait_name}, {t}::Item: Clone")) + .collect() + } + + /// `o0_default_fn, o1_default_fn, o2_default_fn…`. + fn to_optional_fn_names(&self) -> Vec { + (0..self.num_optional) + .map(|n| format!("o{n}_default_fn")) + .collect_vec() + } + + /// `D0, D1, D2…`. + fn to_optional_fn_types(&self) -> Vec { + (0..self.num_optional) + .map(|n| format!("D{n}")) + .collect_vec() + } + + /// `o0_default_fn: D0, o1_default_fn: D1…`. + fn to_optional_fn_params(&self) -> Vec { + izip!(self.to_optional_fn_names(), self.to_optional_fn_types()) + .map(|(n, t)| format!("{n}: {t}")) + .collect() + } + + /// `D0: Fn() -> O0::Item, D1: Fn() -> O1::Item…` + fn to_optional_fn_clauses(&self) -> Vec { + izip!(self.to_optional_fn_types(), self.to_optional_types()) + .map(|(tl, tr)| format!("{tl}: Fn() -> {tr}::Item")) + .collect() + } +} + +fn backticked(strs: impl IntoIterator) -> Vec { + strs.into_iter().map(|s| format!("`{s}`")).collect() +} + +fn generate_helper_func(params: &Params) -> String { + let suffix = params.to_suffix(); + let required_names = backticked(params.to_required_names()).join(", "); + let optional_names = backticked(params.to_optional_names()).join(", "); + let optional_fn_names = backticked(params.to_optional_fn_names()).join(", "); + let required_types = params.to_required_types().join(", "); + let optional_types = params.to_optional_types().join(", "); + let optional_fn_types = params.to_optional_fn_types().join(", "); + let required_clauses = params.to_required_clauses(true /* into */).join(", "); + let optional_clauses = params.to_optional_clauses(true /* into */).join(", "); + let optional_fn_clauses = params.to_optional_fn_clauses().join(", "); + let required_params = params.to_required_params().join(", "); + let optional_params = izip!(params.to_optional_params(), params.to_optional_fn_params()) + .map(|(o, d)| format!("{o}, {d}")) + .collect_vec() + .join(",\n"); + + let ret_clause = params + .to_required_types() + .into_iter() + .map(|r| format!("{r}::IntoIter")) + .chain( + params + .to_optional_types() + .into_iter() + .map(|o| format!("{o}::IntoIter")), + ) + .chain(params.to_optional_fn_types()) + .collect_vec() + .join(", "); + + let ret = params + .to_required_names() + .into_iter() + .map(|r| format!("{r}: {r}.into_iter()")) + .chain( + params + .to_optional_names() + .into_iter() + .map(|o| format!("{o}: {o}.into_iter()")), + ) + .chain(params.to_optional_fn_names()) + .chain( + params + .to_optional_names() + .into_iter() + .map(|o| format!("{o}_latest_value: None")), + ) + .collect_vec() + .join(",\n"); + + format!( + r#" + /// Returns a new [`ClampedZip{suffix}`] iterator. + /// + /// The number of elements in a clamped zip iterator corresponds to the number of elements in the + /// shortest of its required iterators ({required_names}). + /// + /// Optional iterators ({optional_names}) will repeat their latest values if they happen to be too short + /// to be zipped with the shortest of the required iterators. + /// + /// If an optional iterator is not only too short but actually empty, its associated default function + /// ({optional_fn_names}) will be executed and the resulting value repeated as necessary. + pub fn clamped_zip_{suffix}<{required_types}, {optional_types}, {optional_fn_types}>( + {required_params}, + {optional_params}, + ) -> ClampedZip{suffix}<{ret_clause}> + where + {required_clauses}, + {optional_clauses}, + {optional_fn_clauses}, + {{ + ClampedZip{suffix} {{ + {ret} + }} + }} + "# + ) +} + +fn generate_struct(params: &Params) -> String { + let suffix = params.to_suffix(); + let required_types = params.to_required_types().join(", "); + let optional_types = params.to_optional_types().join(", "); + let optional_fn_types = params.to_optional_fn_types().join(", "); + let required_clauses = params.to_required_clauses(false /* into */).join(", "); + let optional_clauses = params.to_optional_clauses(false /* into */).join(", "); + let optional_fn_clauses = params.to_optional_fn_clauses().join(", "); + let required_params = params.to_required_params().join(", "); + let optional_params = params.to_optional_params().join(", "); + let optional_fn_params = params.to_optional_fn_params().join(", "); + + let latest_values = izip!(params.to_optional_names(), params.to_optional_types()) + .map(|(n, t)| format!("{n}_latest_value: Option<{t}::Item>")) + .collect_vec() + .join(",\n"); + + format!( + r#" + /// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional + /// iterators. + /// + /// See [`clamped_zip_{suffix}`] for more information. + pub struct ClampedZip{suffix}<{required_types}, {optional_types}, {optional_fn_types}> + where + {required_clauses}, + {optional_clauses}, + {optional_fn_clauses}, + {{ + {required_params}, + {optional_params}, + {optional_fn_params}, + + {latest_values} + }} + "# + ) +} + +fn generate_impl(params: &Params) -> String { + let suffix = params.to_suffix(); + let required_types = params.to_required_types().join(", "); + let optional_types = params.to_optional_types().join(", "); + let optional_fn_types = params.to_optional_fn_types().join(", "); + let required_clauses = params.to_required_clauses(false /* into */).join(", "); + let optional_clauses = params.to_optional_clauses(false /* into */).join(", "); + let optional_fn_clauses = params.to_optional_fn_clauses().join(", "); + + let items = params + .to_required_types() + .into_iter() + .map(|r| format!("{r}::Item")) + .chain( + params + .to_optional_types() + .into_iter() + .map(|o| format!("{o}::Item")), + ) + .collect_vec() + .join(", "); + + let next = + params + .to_required_names() + .into_iter() + .map(|r| format!("let {r}_next = self.{r}.next()?;")) + .chain(params.to_optional_names().into_iter().map(|o| { + format!("let {o}_next = self.{o}.next().or(self.{o}_latest_value.take());") + })) + .collect_vec() + .join("\n"); + + let update_latest = params + .to_optional_names() + .into_iter() + .map(|o| format!("self.{o}_latest_value = {o}_next.clone();")) + .collect_vec() + .join("\n"); + + let ret = params + .to_required_names() + .into_iter() + .map(|r| format!("{r}_next")) + .chain( + params + .to_optional_names() + .into_iter() + .map(|o| format!("{o}_next.unwrap_or_else(|| (self.{o}_default_fn)())")), + ) + .collect_vec() + .join(",\n"); + + format!( + r#" + impl<{required_types}, {optional_types}, {optional_fn_types}> Iterator for ClampedZip{suffix}<{required_types}, {optional_types}, {optional_fn_types}> + where + {required_clauses}, + {optional_clauses}, + {optional_fn_clauses}, + {{ + type Item = ({items}); + + #[inline] + fn next(&mut self) -> Option {{ + {next} + + {update_latest} + + Some(( + {ret} + )) + }} + }} + "# + ) +} + +fn main() { + let num_required = 1..3; + let num_optional = 1..10; + + let output = num_required + .flat_map(|num_required| { + num_optional + .clone() + .map(move |num_optional| (num_required, num_optional)) + }) + .flat_map(|(num_required, num_optional)| { + let params = Params { + num_required, + num_optional, + }; + + [ + generate_helper_func(¶ms), + generate_struct(¶ms), + generate_impl(¶ms), + ] + }) + .collect_vec() + .join("\n"); + + println!( + " + // This file was generated using `cargo r -p re_query2 --all-features --bin clamped_zip`. + // DO NOT EDIT. + + // --- + + #![allow(clippy::too_many_arguments)] + #![allow(clippy::type_complexity)] + + {output} + " + ); +} diff --git a/crates/re_query2/src/clamped_zip/.gitattributes b/crates/re_query2/src/clamped_zip/.gitattributes new file mode 100644 index 000000000000..30d202506064 --- /dev/null +++ b/crates/re_query2/src/clamped_zip/.gitattributes @@ -0,0 +1 @@ +generated.rs linguist-generated=true diff --git a/crates/re_query2/src/clamped_zip/generated.rs b/crates/re_query2/src/clamped_zip/generated.rs new file mode 100644 index 000000000000..7a5c2222b40a --- /dev/null +++ b/crates/re_query2/src/clamped_zip/generated.rs @@ -0,0 +1,3124 @@ +// This file was generated using `cargo r -p re_query2 --all-features --bin clamped_zip`. +// DO NOT EDIT. + +// --- + +#![allow(clippy::too_many_arguments)] +#![allow(clippy::type_complexity)] + +/// Returns a new [`ClampedZip1x1`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x1( + r0: R0, + o0: O0, + o0_default_fn: D0, +) -> ClampedZip1x1 +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + D0: Fn() -> O0::Item, +{ + ClampedZip1x1 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o0_default_fn, + o0_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x1`] for more information. +pub struct ClampedZip1x1 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + D0: Fn() -> O0::Item, +{ + r0: R0, + o0: O0, + o0_default_fn: D0, + + o0_latest_value: Option, +} + +impl Iterator for ClampedZip1x1 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + D0: Fn() -> O0::Item, +{ + type Item = (R0::Item, O0::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + + Some((r0_next, o0_next.unwrap_or_else(|| (self.o0_default_fn)()))) + } +} + +/// Returns a new [`ClampedZip1x2`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`, `o1`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x2( + r0: R0, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, +) -> ClampedZip1x2 +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, +{ + ClampedZip1x2 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o0_default_fn, + o1_default_fn, + o0_latest_value: None, + o1_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x2`] for more information. +pub struct ClampedZip1x2 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, +{ + r0: R0, + o0: O0, + o1: O1, + o0_default_fn: D0, + o1_default_fn: D1, + + o0_latest_value: Option, + o1_latest_value: Option, +} + +impl Iterator for ClampedZip1x2 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, +{ + type Item = (R0::Item, O0::Item, O1::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + + Some(( + r0_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip1x3`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`, `o1`, `o2`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x3( + r0: R0, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, +) -> ClampedZip1x3 +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, +{ + ClampedZip1x3 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x3`] for more information. +pub struct ClampedZip1x3 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, +{ + r0: R0, + o0: O0, + o1: O1, + o2: O2, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, +} + +impl Iterator for ClampedZip1x3 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, +{ + type Item = (R0::Item, O0::Item, O1::Item, O2::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + + Some(( + r0_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip1x4`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x4( + r0: R0, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, +) -> ClampedZip1x4< + R0::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + D0, + D1, + D2, + D3, +> +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, +{ + ClampedZip1x4 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x4`] for more information. +pub struct ClampedZip1x4 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, +{ + r0: R0, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, +} + +impl Iterator + for ClampedZip1x4 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, +{ + type Item = (R0::Item, O0::Item, O1::Item, O2::Item, O3::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + + Some(( + r0_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip1x5`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x5( + r0: R0, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, +) -> ClampedZip1x5< + R0::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + D0, + D1, + D2, + D3, + D4, +> +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, +{ + ClampedZip1x5 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x5`] for more information. +pub struct ClampedZip1x5 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, +{ + r0: R0, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, +} + +impl Iterator + for ClampedZip1x5 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, +{ + type Item = (R0::Item, O0::Item, O1::Item, O2::Item, O3::Item, O4::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + + Some(( + r0_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip1x6`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`, `o5`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`, `o5_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x6( + r0: R0, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, + o5: O5, + o5_default_fn: D5, +) -> ClampedZip1x6< + R0::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + O5::IntoIter, + D0, + D1, + D2, + D3, + D4, + D5, +> +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + O5: IntoIterator, + O5::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, +{ + ClampedZip1x6 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o5: o5.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o5_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + o5_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x6`] for more information. +pub struct ClampedZip1x6 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, +{ + r0: R0, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o5: O5, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + o5_default_fn: D5, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, + o5_latest_value: Option, +} + +impl Iterator + for ClampedZip1x6 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, +{ + type Item = ( + R0::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + O5::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + let o5_next = self.o5.next().or(self.o5_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + self.o5_latest_value = o5_next.clone(); + + Some(( + r0_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + o5_next.unwrap_or_else(|| (self.o5_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip1x7`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`, `o5`, `o6`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`, `o5_default_fn`, `o6_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x7( + r0: R0, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, + o5: O5, + o5_default_fn: D5, + o6: O6, + o6_default_fn: D6, +) -> ClampedZip1x7< + R0::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + O5::IntoIter, + O6::IntoIter, + D0, + D1, + D2, + D3, + D4, + D5, + D6, +> +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + O5: IntoIterator, + O5::Item: Clone, + O6: IntoIterator, + O6::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, +{ + ClampedZip1x7 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o5: o5.into_iter(), + o6: o6.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o5_default_fn, + o6_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + o5_latest_value: None, + o6_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x7`] for more information. +pub struct ClampedZip1x7 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, +{ + r0: R0, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o5: O5, + o6: O6, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + o5_default_fn: D5, + o6_default_fn: D6, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, + o5_latest_value: Option, + o6_latest_value: Option, +} + +impl Iterator + for ClampedZip1x7 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, +{ + type Item = ( + R0::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + O5::Item, + O6::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + let o5_next = self.o5.next().or(self.o5_latest_value.take()); + let o6_next = self.o6.next().or(self.o6_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + self.o5_latest_value = o5_next.clone(); + self.o6_latest_value = o6_next.clone(); + + Some(( + r0_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + o5_next.unwrap_or_else(|| (self.o5_default_fn)()), + o6_next.unwrap_or_else(|| (self.o6_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip1x8`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`, `o5`, `o6`, `o7`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`, `o5_default_fn`, `o6_default_fn`, `o7_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x8( + r0: R0, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, + o5: O5, + o5_default_fn: D5, + o6: O6, + o6_default_fn: D6, + o7: O7, + o7_default_fn: D7, +) -> ClampedZip1x8< + R0::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + O5::IntoIter, + O6::IntoIter, + O7::IntoIter, + D0, + D1, + D2, + D3, + D4, + D5, + D6, + D7, +> +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + O5: IntoIterator, + O5::Item: Clone, + O6: IntoIterator, + O6::Item: Clone, + O7: IntoIterator, + O7::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, +{ + ClampedZip1x8 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o5: o5.into_iter(), + o6: o6.into_iter(), + o7: o7.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o5_default_fn, + o6_default_fn, + o7_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + o5_latest_value: None, + o6_latest_value: None, + o7_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x8`] for more information. +pub struct ClampedZip1x8 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + O7: Iterator, + O7::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, +{ + r0: R0, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o5: O5, + o6: O6, + o7: O7, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + o5_default_fn: D5, + o6_default_fn: D6, + o7_default_fn: D7, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, + o5_latest_value: Option, + o6_latest_value: Option, + o7_latest_value: Option, +} + +impl Iterator + for ClampedZip1x8 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + O7: Iterator, + O7::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, +{ + type Item = ( + R0::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + O5::Item, + O6::Item, + O7::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + let o5_next = self.o5.next().or(self.o5_latest_value.take()); + let o6_next = self.o6.next().or(self.o6_latest_value.take()); + let o7_next = self.o7.next().or(self.o7_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + self.o5_latest_value = o5_next.clone(); + self.o6_latest_value = o6_next.clone(); + self.o7_latest_value = o7_next.clone(); + + Some(( + r0_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + o5_next.unwrap_or_else(|| (self.o5_default_fn)()), + o6_next.unwrap_or_else(|| (self.o6_default_fn)()), + o7_next.unwrap_or_else(|| (self.o7_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip1x9`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`, `o5`, `o6`, `o7`, `o8`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`, `o5_default_fn`, `o6_default_fn`, `o7_default_fn`, `o8_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_1x9( + r0: R0, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, + o5: O5, + o5_default_fn: D5, + o6: O6, + o6_default_fn: D6, + o7: O7, + o7_default_fn: D7, + o8: O8, + o8_default_fn: D8, +) -> ClampedZip1x9< + R0::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + O5::IntoIter, + O6::IntoIter, + O7::IntoIter, + O8::IntoIter, + D0, + D1, + D2, + D3, + D4, + D5, + D6, + D7, + D8, +> +where + R0: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + O5: IntoIterator, + O5::Item: Clone, + O6: IntoIterator, + O6::Item: Clone, + O7: IntoIterator, + O7::Item: Clone, + O8: IntoIterator, + O8::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, + D8: Fn() -> O8::Item, +{ + ClampedZip1x9 { + r0: r0.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o5: o5.into_iter(), + o6: o6.into_iter(), + o7: o7.into_iter(), + o8: o8.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o5_default_fn, + o6_default_fn, + o7_default_fn, + o8_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + o5_latest_value: None, + o6_latest_value: None, + o7_latest_value: None, + o8_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_1x9`] for more information. +pub struct ClampedZip1x9 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + O7: Iterator, + O7::Item: Clone, + O8: Iterator, + O8::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, + D8: Fn() -> O8::Item, +{ + r0: R0, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o5: O5, + o6: O6, + o7: O7, + o8: O8, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + o5_default_fn: D5, + o6_default_fn: D6, + o7_default_fn: D7, + o8_default_fn: D8, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, + o5_latest_value: Option, + o6_latest_value: Option, + o7_latest_value: Option, + o8_latest_value: Option, +} + +impl Iterator + for ClampedZip1x9 +where + R0: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + O7: Iterator, + O7::Item: Clone, + O8: Iterator, + O8::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, + D8: Fn() -> O8::Item, +{ + type Item = ( + R0::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + O5::Item, + O6::Item, + O7::Item, + O8::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + let o5_next = self.o5.next().or(self.o5_latest_value.take()); + let o6_next = self.o6.next().or(self.o6_latest_value.take()); + let o7_next = self.o7.next().or(self.o7_latest_value.take()); + let o8_next = self.o8.next().or(self.o8_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + self.o5_latest_value = o5_next.clone(); + self.o6_latest_value = o6_next.clone(); + self.o7_latest_value = o7_next.clone(); + self.o8_latest_value = o8_next.clone(); + + Some(( + r0_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + o5_next.unwrap_or_else(|| (self.o5_default_fn)()), + o6_next.unwrap_or_else(|| (self.o6_default_fn)()), + o7_next.unwrap_or_else(|| (self.o7_default_fn)()), + o8_next.unwrap_or_else(|| (self.o8_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x1`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x1( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, +) -> ClampedZip2x1 +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + D0: Fn() -> O0::Item, +{ + ClampedZip2x1 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o0_default_fn, + o0_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x1`] for more information. +pub struct ClampedZip2x1 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + D0: Fn() -> O0::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + + o0_latest_value: Option, +} + +impl Iterator for ClampedZip2x1 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + D0: Fn() -> O0::Item, +{ + type Item = (R0::Item, R1::Item, O0::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x2`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`, `o1`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x2( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, +) -> ClampedZip2x2 +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, +{ + ClampedZip2x2 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o0_default_fn, + o1_default_fn, + o0_latest_value: None, + o1_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x2`] for more information. +pub struct ClampedZip2x2 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o1: O1, + o0_default_fn: D0, + o1_default_fn: D1, + + o0_latest_value: Option, + o1_latest_value: Option, +} + +impl Iterator for ClampedZip2x2 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, +{ + type Item = (R0::Item, R1::Item, O0::Item, O1::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x3`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`, `o1`, `o2`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x3( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, +) -> ClampedZip2x3 +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, +{ + ClampedZip2x3 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x3`] for more information. +pub struct ClampedZip2x3 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o1: O1, + o2: O2, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, +} + +impl Iterator for ClampedZip2x3 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, +{ + type Item = (R0::Item, R1::Item, O0::Item, O1::Item, O2::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x4`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x4( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, +) -> ClampedZip2x4< + R0::IntoIter, + R1::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + D0, + D1, + D2, + D3, +> +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, +{ + ClampedZip2x4 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x4`] for more information. +pub struct ClampedZip2x4 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, +} + +impl Iterator + for ClampedZip2x4 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, +{ + type Item = (R0::Item, R1::Item, O0::Item, O1::Item, O2::Item, O3::Item); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x5`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x5( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, +) -> ClampedZip2x5< + R0::IntoIter, + R1::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + D0, + D1, + D2, + D3, + D4, +> +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, +{ + ClampedZip2x5 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x5`] for more information. +pub struct ClampedZip2x5 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, +} + +impl Iterator + for ClampedZip2x5 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, +{ + type Item = ( + R0::Item, + R1::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x6`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`, `o5`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`, `o5_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x6( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, + o5: O5, + o5_default_fn: D5, +) -> ClampedZip2x6< + R0::IntoIter, + R1::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + O5::IntoIter, + D0, + D1, + D2, + D3, + D4, + D5, +> +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + O5: IntoIterator, + O5::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, +{ + ClampedZip2x6 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o5: o5.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o5_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + o5_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x6`] for more information. +pub struct ClampedZip2x6 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o5: O5, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + o5_default_fn: D5, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, + o5_latest_value: Option, +} + +impl Iterator + for ClampedZip2x6 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, +{ + type Item = ( + R0::Item, + R1::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + O5::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + let o5_next = self.o5.next().or(self.o5_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + self.o5_latest_value = o5_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + o5_next.unwrap_or_else(|| (self.o5_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x7`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`, `o5`, `o6`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`, `o5_default_fn`, `o6_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x7( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, + o5: O5, + o5_default_fn: D5, + o6: O6, + o6_default_fn: D6, +) -> ClampedZip2x7< + R0::IntoIter, + R1::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + O5::IntoIter, + O6::IntoIter, + D0, + D1, + D2, + D3, + D4, + D5, + D6, +> +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + O5: IntoIterator, + O5::Item: Clone, + O6: IntoIterator, + O6::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, +{ + ClampedZip2x7 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o5: o5.into_iter(), + o6: o6.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o5_default_fn, + o6_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + o5_latest_value: None, + o6_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x7`] for more information. +pub struct ClampedZip2x7 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o5: O5, + o6: O6, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + o5_default_fn: D5, + o6_default_fn: D6, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, + o5_latest_value: Option, + o6_latest_value: Option, +} + +impl Iterator + for ClampedZip2x7 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, +{ + type Item = ( + R0::Item, + R1::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + O5::Item, + O6::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + let o5_next = self.o5.next().or(self.o5_latest_value.take()); + let o6_next = self.o6.next().or(self.o6_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + self.o5_latest_value = o5_next.clone(); + self.o6_latest_value = o6_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + o5_next.unwrap_or_else(|| (self.o5_default_fn)()), + o6_next.unwrap_or_else(|| (self.o6_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x8`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`, `o5`, `o6`, `o7`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`, `o5_default_fn`, `o6_default_fn`, `o7_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x8( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, + o5: O5, + o5_default_fn: D5, + o6: O6, + o6_default_fn: D6, + o7: O7, + o7_default_fn: D7, +) -> ClampedZip2x8< + R0::IntoIter, + R1::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + O5::IntoIter, + O6::IntoIter, + O7::IntoIter, + D0, + D1, + D2, + D3, + D4, + D5, + D6, + D7, +> +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + O5: IntoIterator, + O5::Item: Clone, + O6: IntoIterator, + O6::Item: Clone, + O7: IntoIterator, + O7::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, +{ + ClampedZip2x8 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o5: o5.into_iter(), + o6: o6.into_iter(), + o7: o7.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o5_default_fn, + o6_default_fn, + o7_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + o5_latest_value: None, + o6_latest_value: None, + o7_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x8`] for more information. +pub struct ClampedZip2x8 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + O7: Iterator, + O7::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o5: O5, + o6: O6, + o7: O7, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + o5_default_fn: D5, + o6_default_fn: D6, + o7_default_fn: D7, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, + o5_latest_value: Option, + o6_latest_value: Option, + o7_latest_value: Option, +} + +impl Iterator + for ClampedZip2x8 +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + O7: Iterator, + O7::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, +{ + type Item = ( + R0::Item, + R1::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + O5::Item, + O6::Item, + O7::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + let o5_next = self.o5.next().or(self.o5_latest_value.take()); + let o6_next = self.o6.next().or(self.o6_latest_value.take()); + let o7_next = self.o7.next().or(self.o7_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + self.o5_latest_value = o5_next.clone(); + self.o6_latest_value = o6_next.clone(); + self.o7_latest_value = o7_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + o5_next.unwrap_or_else(|| (self.o5_default_fn)()), + o6_next.unwrap_or_else(|| (self.o6_default_fn)()), + o7_next.unwrap_or_else(|| (self.o7_default_fn)()), + )) + } +} + +/// Returns a new [`ClampedZip2x9`] iterator. +/// +/// The number of elements in a clamped zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Optional iterators (`o0`, `o1`, `o2`, `o3`, `o4`, `o5`, `o6`, `o7`, `o8`) will repeat their latest values if they happen to be too short +/// to be zipped with the shortest of the required iterators. +/// +/// If an optional iterator is not only too short but actually empty, its associated default function +/// (`o0_default_fn`, `o1_default_fn`, `o2_default_fn`, `o3_default_fn`, `o4_default_fn`, `o5_default_fn`, `o6_default_fn`, `o7_default_fn`, `o8_default_fn`) will be executed and the resulting value repeated as necessary. +pub fn clamped_zip_2x9< + R0, + R1, + O0, + O1, + O2, + O3, + O4, + O5, + O6, + O7, + O8, + D0, + D1, + D2, + D3, + D4, + D5, + D6, + D7, + D8, +>( + r0: R0, + r1: R1, + o0: O0, + o0_default_fn: D0, + o1: O1, + o1_default_fn: D1, + o2: O2, + o2_default_fn: D2, + o3: O3, + o3_default_fn: D3, + o4: O4, + o4_default_fn: D4, + o5: O5, + o5_default_fn: D5, + o6: O6, + o6_default_fn: D6, + o7: O7, + o7_default_fn: D7, + o8: O8, + o8_default_fn: D8, +) -> ClampedZip2x9< + R0::IntoIter, + R1::IntoIter, + O0::IntoIter, + O1::IntoIter, + O2::IntoIter, + O3::IntoIter, + O4::IntoIter, + O5::IntoIter, + O6::IntoIter, + O7::IntoIter, + O8::IntoIter, + D0, + D1, + D2, + D3, + D4, + D5, + D6, + D7, + D8, +> +where + R0: IntoIterator, + R1: IntoIterator, + O0: IntoIterator, + O0::Item: Clone, + O1: IntoIterator, + O1::Item: Clone, + O2: IntoIterator, + O2::Item: Clone, + O3: IntoIterator, + O3::Item: Clone, + O4: IntoIterator, + O4::Item: Clone, + O5: IntoIterator, + O5::Item: Clone, + O6: IntoIterator, + O6::Item: Clone, + O7: IntoIterator, + O7::Item: Clone, + O8: IntoIterator, + O8::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, + D8: Fn() -> O8::Item, +{ + ClampedZip2x9 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter(), + o1: o1.into_iter(), + o2: o2.into_iter(), + o3: o3.into_iter(), + o4: o4.into_iter(), + o5: o5.into_iter(), + o6: o6.into_iter(), + o7: o7.into_iter(), + o8: o8.into_iter(), + o0_default_fn, + o1_default_fn, + o2_default_fn, + o3_default_fn, + o4_default_fn, + o5_default_fn, + o6_default_fn, + o7_default_fn, + o8_default_fn, + o0_latest_value: None, + o1_latest_value: None, + o2_latest_value: None, + o3_latest_value: None, + o4_latest_value: None, + o5_latest_value: None, + o6_latest_value: None, + o7_latest_value: None, + o8_latest_value: None, + } +} + +/// Implements a clamped zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`clamped_zip_2x9`] for more information. +pub struct ClampedZip2x9< + R0, + R1, + O0, + O1, + O2, + O3, + O4, + O5, + O6, + O7, + O8, + D0, + D1, + D2, + D3, + D4, + D5, + D6, + D7, + D8, +> where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + O7: Iterator, + O7::Item: Clone, + O8: Iterator, + O8::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, + D8: Fn() -> O8::Item, +{ + r0: R0, + r1: R1, + o0: O0, + o1: O1, + o2: O2, + o3: O3, + o4: O4, + o5: O5, + o6: O6, + o7: O7, + o8: O8, + o0_default_fn: D0, + o1_default_fn: D1, + o2_default_fn: D2, + o3_default_fn: D3, + o4_default_fn: D4, + o5_default_fn: D5, + o6_default_fn: D6, + o7_default_fn: D7, + o8_default_fn: D8, + + o0_latest_value: Option, + o1_latest_value: Option, + o2_latest_value: Option, + o3_latest_value: Option, + o4_latest_value: Option, + o5_latest_value: Option, + o6_latest_value: Option, + o7_latest_value: Option, + o8_latest_value: Option, +} + +impl Iterator + for ClampedZip2x9< + R0, + R1, + O0, + O1, + O2, + O3, + O4, + O5, + O6, + O7, + O8, + D0, + D1, + D2, + D3, + D4, + D5, + D6, + D7, + D8, + > +where + R0: Iterator, + R1: Iterator, + O0: Iterator, + O0::Item: Clone, + O1: Iterator, + O1::Item: Clone, + O2: Iterator, + O2::Item: Clone, + O3: Iterator, + O3::Item: Clone, + O4: Iterator, + O4::Item: Clone, + O5: Iterator, + O5::Item: Clone, + O6: Iterator, + O6::Item: Clone, + O7: Iterator, + O7::Item: Clone, + O8: Iterator, + O8::Item: Clone, + D0: Fn() -> O0::Item, + D1: Fn() -> O1::Item, + D2: Fn() -> O2::Item, + D3: Fn() -> O3::Item, + D4: Fn() -> O4::Item, + D5: Fn() -> O5::Item, + D6: Fn() -> O6::Item, + D7: Fn() -> O7::Item, + D8: Fn() -> O8::Item, +{ + type Item = ( + R0::Item, + R1::Item, + O0::Item, + O1::Item, + O2::Item, + O3::Item, + O4::Item, + O5::Item, + O6::Item, + O7::Item, + O8::Item, + ); + + #[inline] + fn next(&mut self) -> Option { + let r0_next = self.r0.next()?; + let r1_next = self.r1.next()?; + let o0_next = self.o0.next().or(self.o0_latest_value.take()); + let o1_next = self.o1.next().or(self.o1_latest_value.take()); + let o2_next = self.o2.next().or(self.o2_latest_value.take()); + let o3_next = self.o3.next().or(self.o3_latest_value.take()); + let o4_next = self.o4.next().or(self.o4_latest_value.take()); + let o5_next = self.o5.next().or(self.o5_latest_value.take()); + let o6_next = self.o6.next().or(self.o6_latest_value.take()); + let o7_next = self.o7.next().or(self.o7_latest_value.take()); + let o8_next = self.o8.next().or(self.o8_latest_value.take()); + + self.o0_latest_value = o0_next.clone(); + self.o1_latest_value = o1_next.clone(); + self.o2_latest_value = o2_next.clone(); + self.o3_latest_value = o3_next.clone(); + self.o4_latest_value = o4_next.clone(); + self.o5_latest_value = o5_next.clone(); + self.o6_latest_value = o6_next.clone(); + self.o7_latest_value = o7_next.clone(); + self.o8_latest_value = o8_next.clone(); + + Some(( + r0_next, + r1_next, + o0_next.unwrap_or_else(|| (self.o0_default_fn)()), + o1_next.unwrap_or_else(|| (self.o1_default_fn)()), + o2_next.unwrap_or_else(|| (self.o2_default_fn)()), + o3_next.unwrap_or_else(|| (self.o3_default_fn)()), + o4_next.unwrap_or_else(|| (self.o4_default_fn)()), + o5_next.unwrap_or_else(|| (self.o5_default_fn)()), + o6_next.unwrap_or_else(|| (self.o6_default_fn)()), + o7_next.unwrap_or_else(|| (self.o7_default_fn)()), + o8_next.unwrap_or_else(|| (self.o8_default_fn)()), + )) + } +} diff --git a/crates/re_query2/src/clamped_zip/mod.rs b/crates/re_query2/src/clamped_zip/mod.rs new file mode 100644 index 000000000000..65bd61b05021 --- /dev/null +++ b/crates/re_query2/src/clamped_zip/mod.rs @@ -0,0 +1,64 @@ +mod generated; +pub use self::generated::*; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn r0_is_empty_o0_is_empty() { + let r0 = std::iter::empty::(); + let o0 = (0..).map(|n| n.to_string()); + + let expected: Vec<(u32, String)> = vec![]; + let got = clamped_zip_1x1(r0, o0, String::new).collect::>(); + + similar_asserts::assert_eq!(expected, got); + } + + #[test] + fn r0_and_o0_are_matched() { + let r0 = 0..20u32; + let o0 = (0..20).map(|n| n.to_string()); + + let expected: Vec<(u32, String)> = (0..20u32).map(|n| (n, n.to_string())).collect(); + let got = clamped_zip_1x1(r0, o0, String::new).collect::>(); + + similar_asserts::assert_eq!(expected, got); + } + + #[test] + fn r0_is_shorter() { + let r0 = 0..10u32; + let o0 = (0..20).map(|n| n.to_string()); + + let expected: Vec<(u32, String)> = (0..10u32).map(|n| (n, n.to_string())).collect(); + let got = clamped_zip_1x1(r0, o0, String::new).collect::>(); + + similar_asserts::assert_eq!(expected, got); + } + + #[test] + fn r0_is_longer() { + let r0 = 0..30u32; + let o0 = (0..20).map(|n| n.to_string()); + + let expected: Vec<(u32, String)> = (0..30u32) + .map(|n| (n, u32::min(n, 19).to_string())) + .collect(); + let got = clamped_zip_1x1(r0, o0, String::new).collect::>(); + + similar_asserts::assert_eq!(expected, got); + } + + #[test] + fn r0_is_longer_and_o0_is_empty() { + let r0 = 0..10u32; + let o0 = std::iter::empty(); + + let expected: Vec<(u32, String)> = (0..10u32).map(|n| (n, "hey".to_owned())).collect(); + let got = clamped_zip_1x1(r0, o0, || "hey".to_owned()).collect::>(); + + similar_asserts::assert_eq!(expected, got); + } +} diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs new file mode 100644 index 000000000000..33f05e522514 --- /dev/null +++ b/crates/re_query2/src/lib.rs @@ -0,0 +1,58 @@ +//! Provide query-centric access to the [`re_data_store`]. + +mod clamped_zip; +mod visible_history; + +pub use self::clamped_zip::*; +pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; + +// --- + +#[derive(Debug, Clone, Copy)] +pub struct ComponentNotFoundError(pub re_types_core::ComponentName); + +impl std::fmt::Display for ComponentNotFoundError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("Could not find component: {}", self.0)) + } +} + +impl std::error::Error for ComponentNotFoundError {} + +#[derive(thiserror::Error, Debug)] +pub enum QueryError { + #[error("Tried to access a column that doesn't exist")] + BadAccess, + + #[error("Could not find primary component: {0}")] + PrimaryNotFound(re_types_core::ComponentName), + + #[error(transparent)] + ComponentNotFound(#[from] ComponentNotFoundError), + + #[error("Tried to access component of type '{actual:?}' using component '{requested:?}'")] + TypeMismatch { + actual: re_types_core::ComponentName, + requested: re_types_core::ComponentName, + }, + + #[error("Error with one or more the underlying data cells: {0}")] + DataCell(#[from] re_log_types::DataCellError), + + #[error("Error deserializing: {0}")] + DeserializationError(#[from] re_types_core::DeserializationError), + + #[error("Error serializing: {0}")] + SerializationError(#[from] re_types_core::SerializationError), + + #[error("Error converting arrow data: {0}")] + ArrowError(#[from] arrow2::error::Error), + + #[error("Not implemented")] + NotImplemented, + + #[error(transparent)] + Other(#[from] anyhow::Error), +} + +pub type Result = std::result::Result; diff --git a/crates/re_query2/src/visible_history.rs b/crates/re_query2/src/visible_history.rs new file mode 100644 index 000000000000..f11b29f96baa --- /dev/null +++ b/crates/re_query2/src/visible_history.rs @@ -0,0 +1,126 @@ +use re_data_store::{TimeInt, TimeRange}; + +// --- + +/// One of the boundaries of the visible history. +/// +/// For [`VisibleHistoryBoundary::RelativeToTimeCursor`] and [`VisibleHistoryBoundary::Absolute`], +/// the value are either nanos or frames, depending on the type of timeline. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub enum VisibleHistoryBoundary { + /// Boundary is a value relative to the time cursor + RelativeToTimeCursor(i64), + + /// Boundary is an absolute value + Absolute(i64), + + /// The boundary extends to infinity. + Infinite, +} + +impl VisibleHistoryBoundary { + /// Value when the boundary is set to the current time cursor. + pub const AT_CURSOR: Self = Self::RelativeToTimeCursor(0); +} + +impl Default for VisibleHistoryBoundary { + fn default() -> Self { + Self::AT_CURSOR + } +} + +/// Visible history bounds. +#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub struct VisibleHistory { + /// Low time boundary. + pub from: VisibleHistoryBoundary, + + /// High time boundary. + pub to: VisibleHistoryBoundary, +} + +impl VisibleHistory { + /// Value with the visible history feature is disabled. + pub const OFF: Self = Self { + from: VisibleHistoryBoundary::AT_CURSOR, + to: VisibleHistoryBoundary::AT_CURSOR, + }; + + pub const ALL: Self = Self { + from: VisibleHistoryBoundary::Infinite, + to: VisibleHistoryBoundary::Infinite, + }; + + /// Returns the start boundary of the time range given an input cursor position. + /// + /// This is not guaranteed to be lesser than or equal to [`Self::to`]. + /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. + #[doc(hidden)] + pub fn range_start_from_cursor(&self, cursor: TimeInt) -> TimeInt { + match self.from { + VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), + VisibleHistoryBoundary::RelativeToTimeCursor(value) => { + cursor + TimeInt::new_temporal(value) + } + VisibleHistoryBoundary::Infinite => TimeInt::MIN, + } + } + + /// Returns the end boundary of the time range given an input cursor position. + /// + /// This is not guaranteed to be greater than [`Self::from`]. + /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. + #[doc(hidden)] + pub fn range_end_from_cursor(&self, cursor: TimeInt) -> TimeInt { + match self.to { + VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), + VisibleHistoryBoundary::RelativeToTimeCursor(value) => { + cursor + TimeInt::new_temporal(value) + } + VisibleHistoryBoundary::Infinite => TimeInt::MAX, + } + } + + /// Returns a _sanitized_ [`TimeRange`], i.e. guaranteed to be monotonically increasing. + pub fn time_range(&self, cursor: TimeInt) -> TimeRange { + let mut from = self.range_start_from_cursor(cursor); + let mut to = self.range_end_from_cursor(cursor); + + // TODO(#4993): visible time range UI can yield inverted ranges + if from > to { + std::mem::swap(&mut from, &mut to); + } + + TimeRange::new(from, to) + } +} + +/// When showing an entity in the history view, add this much history to it. +#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", serde(default))] +pub struct ExtraQueryHistory { + /// Is the feature enabled? + pub enabled: bool, + + /// Visible history settings for time timelines + pub nanos: VisibleHistory, + + /// Visible history settings for frame timelines + pub sequences: VisibleHistory, +} + +impl ExtraQueryHistory { + /// Multiply/and these together. + pub fn with_child(&self, child: &Self) -> Self { + if child.enabled { + *child + } else if self.enabled { + *self + } else { + Self::default() + } + } +} diff --git a/scripts/lint.py b/scripts/lint.py index 377be1982f17..b4a83b447535 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -900,6 +900,9 @@ def lint_file(filepath: str, args: Any) -> int: def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: """Make sure ARCHITECTURE.md talks about every single crate we have.""" + # These crates will replace existing ones and won't ever be published as-is. + tmp_crates = ["re_query2", "re_query_cache2"] + crates_dir = Path("crates") architecture_md_file = Path("ARCHITECTURE.md") @@ -920,7 +923,7 @@ def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: if crate_name in listed_crates: del listed_crates[crate_name] - if should_ignore(crate): + if should_ignore(crate) or crate.name in tmp_crates: continue if not re.search(r"\b" + crate_name + r"\b", architecture_md): From f0bbc155135e56faacff673e6529c3b373cd228a Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 14:36:16 +0200 Subject: [PATCH 219/508] New data APIs 1: uncached latest-at queries (#5574) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implements the new uncached latest-at APIs, and introduces some basic types for promises. Tests and benchmarks have been backported from `re_query`. We already get a pretty decent improvement because the join process (clamped-zip) is cheaper and we don't need to query for instance keys at all: ``` group re_query re_query2 ----- -------- --------- arrow_batch_points2/query 1.39 2.5±0.03µs 379.7 MElem/sec 1.00 1810.6±23.62ns 526.7 MElem/sec arrow_mono_points2/query 1.44 1082.7±8.66µs 902.0 KElem/sec 1.00 753.6±9.28µs 1295.9 KElem/sec ``` - Fixes #3379 - Part of #1893 Here's an example/guide of using the new API: ```rust // First, get the raw results for this query. // // Raw here means that these results are neither deserialized, nor resolved/converted. // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. let results: LatestAtResults = re_query2::latest_at( &store, &query, &entity_path.into(), MyPoints::all_components().iter().cloned(), // no generics! ); // Then, grab the raw results for each individual components. // // This is still raw data, but now a choice has been made regarding the nullability of the // _component batch_ itself (that says nothing about its _instances_!). // // * `get_required` returns an error if the component batch is missing // * `get_optional` returns an empty set of results if the component if missing // * `get` returns an option let points: &LatestAtComponentResults = results.get_required::()?; let colors: &LatestAtComponentResults = results.get_optional::(); let labels: &LatestAtComponentResults = results.get_optional::(); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. // // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. // Use `PromiseResult::flatten` to simplify it down to a single result. // // A choice now has to be made regarding the nullability of the _component batch's instances_. // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably // shouldn't be using anything but `iter_dense`. let points = match points.iter_dense::(&mut resolver).flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), }; let colors = match colors.iter_dense::(&mut resolver).flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), }; let labels = match labels.iter_sparse::(&mut resolver).flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), }; // With the data now fully resolved/converted and deserialized, the joining logic can be // applied. // // In most cases this will be either a clamped zip, or no joining at all. let color_default_fn = || MyColor::from(0xFF00FFFF); let label_default_fn = || None; let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn).collect_vec(); ``` --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- Cargo.lock | 1 + crates/re_query2/Cargo.toml | 6 + crates/re_query2/benches/latest_at.rs | 347 ++++++++++++++++++++++ crates/re_query2/examples/latest_at.rs | 128 ++++++++ crates/re_query2/src/latest_at/mod.rs | 5 + crates/re_query2/src/latest_at/query.rs | 40 +++ crates/re_query2/src/latest_at/results.rs | 213 +++++++++++++ crates/re_query2/src/lib.rs | 6 +- crates/re_query2/src/promise.rs | 132 ++++++++ crates/re_query2/tests/latest_at.rs | 217 ++++++++++++++ 10 files changed, 1094 insertions(+), 1 deletion(-) create mode 100644 crates/re_query2/benches/latest_at.rs create mode 100644 crates/re_query2/examples/latest_at.rs create mode 100644 crates/re_query2/src/latest_at/mod.rs create mode 100644 crates/re_query2/src/latest_at/query.rs create mode 100644 crates/re_query2/src/latest_at/results.rs create mode 100644 crates/re_query2/src/promise.rs create mode 100644 crates/re_query2/tests/latest_at.rs diff --git a/Cargo.lock b/Cargo.lock index db1751e1cd7b..9150af80656e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4567,6 +4567,7 @@ dependencies = [ "serde", "similar-asserts", "smallvec", + "static_assertions", "thiserror", "unindent", ] diff --git a/crates/re_query2/Cargo.toml b/crates/re_query2/Cargo.toml index 6f67f6a8d7dc..e6e8ac693ae9 100644 --- a/crates/re_query2/Cargo.toml +++ b/crates/re_query2/Cargo.toml @@ -47,6 +47,7 @@ itertools = { workspace = true } nohash-hasher.workspace = true serde = { workspace = true, features = ["derive", "rc"], optional = true } smallvec.workspace = true +static_assertions.workspace = true thiserror.workspace = true # Optional: @@ -70,3 +71,8 @@ bench = false [[bin]] name = "clamped_zip" required-features = ["codegen"] + + +[[bench]] +name = "latest_at" +harness = false diff --git a/crates/re_query2/benches/latest_at.rs b/crates/re_query2/benches/latest_at.rs new file mode 100644 index 000000000000..fbc5e5959225 --- /dev/null +++ b/crates/re_query2/benches/latest_at.rs @@ -0,0 +1,347 @@ +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + +use criterion::{criterion_group, criterion_main, Criterion}; + +use itertools::Itertools; +use re_data_store::{DataStore, LatestAtQuery}; +use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; +use re_query2::{clamped_zip_1x1, LatestAtResults, PromiseResolver}; +use re_types::{ + archetypes::Points2D, + components::{Color, InstanceKey, Position2D, Text}, + Archetype as _, +}; +use re_types_core::Loggable as _; + +// --- + +#[cfg(not(debug_assertions))] +const NUM_FRAMES_POINTS: u32 = 1_000; +#[cfg(not(debug_assertions))] +const NUM_POINTS: u32 = 1_000; +#[cfg(not(debug_assertions))] +const NUM_FRAMES_STRINGS: u32 = 1_000; +#[cfg(not(debug_assertions))] +const NUM_STRINGS: u32 = 1_000; + +// `cargo test` also runs the benchmark setup code, so make sure they run quickly: +#[cfg(debug_assertions)] +const NUM_FRAMES_POINTS: u32 = 1; +#[cfg(debug_assertions)] +const NUM_POINTS: u32 = 1; +#[cfg(debug_assertions)] +const NUM_FRAMES_STRINGS: u32 = 1; +#[cfg(debug_assertions)] +const NUM_STRINGS: u32 = 1; + +criterion_group!( + benches, + mono_points, + mono_strings, + batch_points, + batch_strings +); +criterion_main!(benches); + +// --- Benchmarks --- + +pub fn build_some_point2d(len: usize) -> Vec { + use rand::Rng as _; + let mut rng = rand::thread_rng(); + + (0..len) + .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) + .collect() +} + +/// Create `len` dummy colors +pub fn build_some_colors(len: usize) -> Vec { + (0..len).map(|i| Color::from(i as u32)).collect() +} + +/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. +pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { + (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) +} + +pub fn build_some_strings(len: usize) -> Vec { + use rand::Rng as _; + let mut rng = rand::thread_rng(); + + (0..len) + .map(|_| { + let ilen: usize = rng.gen_range(0..10000); + let s: String = rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) + .take(ilen) + .map(char::from) + .collect(); + Text::from(s) + }) + .collect() +} + +fn mono_points(c: &mut Criterion) { + // Each mono point gets logged at a different path + let paths = (0..NUM_POINTS) + .map(move |point_idx| entity_path!("points", point_idx.to_string())) + .collect_vec(); + let msgs = build_points_rows(&paths, 1); + + { + let mut group = c.benchmark_group("arrow_mono_points2"); + // Mono-insert is slow -- decrease the sample size + group.sample_size(10); + group.throughput(criterion::Throughput::Elements( + (NUM_POINTS * NUM_FRAMES_POINTS) as _, + )); + group.bench_function("insert", |b| { + b.iter(|| insert_rows(msgs.iter())); + }); + } + + { + let mut group = c.benchmark_group("arrow_mono_points2"); + group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); + let store = insert_rows(msgs.iter()); + group.bench_function("query", |b| { + b.iter(|| query_and_visit_points(&store, &paths)); + }); + } +} + +fn mono_strings(c: &mut Criterion) { + // Each mono string gets logged at a different path + let paths = (0..NUM_STRINGS) + .map(move |string_idx| entity_path!("strings", string_idx.to_string())) + .collect_vec(); + let msgs = build_strings_rows(&paths, 1); + + { + let mut group = c.benchmark_group("arrow_mono_strings2"); + group.sample_size(10); + group.throughput(criterion::Throughput::Elements( + (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, + )); + group.bench_function("insert", |b| { + b.iter(|| insert_rows(msgs.iter())); + }); + } + + { + let mut group = c.benchmark_group("arrow_mono_strings2"); + group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); + let store = insert_rows(msgs.iter()); + group.bench_function("query", |b| { + b.iter(|| query_and_visit_strings(&store, &paths)); + }); + } +} + +fn batch_points(c: &mut Criterion) { + // Batch points are logged together at a single path + let paths = [EntityPath::from("points")]; + let msgs = build_points_rows(&paths, NUM_POINTS as _); + + { + let mut group = c.benchmark_group("arrow_batch_points2"); + group.throughput(criterion::Throughput::Elements( + (NUM_POINTS * NUM_FRAMES_POINTS) as _, + )); + group.bench_function("insert", |b| { + b.iter(|| insert_rows(msgs.iter())); + }); + } + + { + let mut group = c.benchmark_group("arrow_batch_points2"); + group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); + let store = insert_rows(msgs.iter()); + group.bench_function("query", |b| { + b.iter(|| query_and_visit_points(&store, &paths)); + }); + } +} + +fn batch_strings(c: &mut Criterion) { + // Batch strings are logged together at a single path + let paths = [EntityPath::from("points")]; + let msgs = build_strings_rows(&paths, NUM_STRINGS as _); + + { + let mut group = c.benchmark_group("arrow_batch_strings2"); + group.throughput(criterion::Throughput::Elements( + (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, + )); + group.bench_function("insert", |b| { + b.iter(|| insert_rows(msgs.iter())); + }); + } + + { + let mut group = c.benchmark_group("arrow_batch_strings2"); + group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); + let store = insert_rows(msgs.iter()); + group.bench_function("query", |b| { + b.iter(|| query_and_visit_strings(&store, &paths)); + }); + } +} + +// --- Helpers --- + +fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { + (0..NUM_FRAMES_POINTS) + .flat_map(move |frame_idx| { + paths.iter().map(move |path| { + let mut row = DataRow::from_cells2( + RowId::new(), + path.clone(), + [build_frame_nr((frame_idx as i64).try_into().unwrap())], + num_points as _, + ( + build_some_point2d(num_points), + build_some_colors(num_points), + ), + ) + .unwrap(); + // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, + // in debug mode, by the standard test harness. + if cfg!(debug_assertions) { + row.compute_all_size_bytes(); + } + row + }) + }) + .collect() +} + +fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { + (0..NUM_FRAMES_STRINGS) + .flat_map(move |frame_idx| { + paths.iter().map(move |path| { + let mut row = DataRow::from_cells2( + RowId::new(), + path.clone(), + [build_frame_nr((frame_idx as i64).try_into().unwrap())], + num_strings as _, + // We still need to create points because they are the primary for the + // archetype query we want to do. We won't actually deserialize the points + // during the query -- we just need it for the primary keys. + // TODO(jleibs): switch this to use `TextEntry` once the new type has + // landed. + ( + build_some_point2d(num_strings), + build_some_strings(num_strings), + ), + ) + .unwrap(); + // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, + // in debug mode, by the standard test harness. + if cfg!(debug_assertions) { + row.compute_all_size_bytes(); + } + row + }) + }) + .collect() +} + +fn insert_rows<'a>(msgs: impl Iterator) -> DataStore { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + msgs.for_each(|row| { + store.insert_row(row).unwrap(); + }); + store +} + +struct SavePoint { + _pos: Position2D, + _color: Option, +} + +fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec { + let resolver = PromiseResolver::default(); + + let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); + let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); + + let mut ret = Vec::with_capacity(NUM_POINTS as _); + + // TODO(jleibs): Add Radius once we have support for it in field_types + for entity_path in paths { + let results: LatestAtResults = re_query2::latest_at( + store, + &query, + entity_path, + Points2D::all_components().iter().cloned(), // no generics! + ); + + let points = results.get_required::().unwrap(); + let colors = results.get_or_empty::(); + + let points = points + .iter_dense::(&resolver) + .flatten() + .unwrap(); + + let colors = colors.iter_dense::(&resolver).flatten().unwrap(); + let color_default_fn = || Color::from(0xFF00FFFF); + + for (point, color) in clamped_zip_1x1(points, colors, color_default_fn) { + ret.push(SavePoint { + _pos: point, + _color: Some(color), + }); + } + } + assert_eq!(NUM_POINTS as usize, ret.len()); + ret +} + +struct SaveString { + _label: Option, +} + +fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec { + let resolver = PromiseResolver::default(); + + let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); + let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); + + let mut strings = Vec::with_capacity(NUM_STRINGS as _); + + for entity_path in paths { + let results: LatestAtResults = re_query2::latest_at( + store, + &query, + entity_path, + Points2D::all_components().iter().cloned(), // no generics! + ); + + let points = results.get_required::().unwrap(); + let colors = results.get_or_empty::(); + + let points = points + .iter_dense::(&resolver) + .flatten() + .unwrap(); + + let labels = colors.iter_dense::(&resolver).flatten().unwrap(); + let label_default_fn = || Text(String::new().into()); + + for (_point, label) in clamped_zip_1x1(points, labels, label_default_fn) { + strings.push(SaveString { + _label: Some(label), + }); + } + } + assert_eq!(NUM_STRINGS as usize, strings.len()); + + criterion::black_box(strings) +} diff --git a/crates/re_query2/examples/latest_at.rs b/crates/re_query2/examples/latest_at.rs new file mode 100644 index 000000000000..90e44f48d0f9 --- /dev/null +++ b/crates/re_query2/examples/latest_at.rs @@ -0,0 +1,128 @@ +use itertools::Itertools; +use re_data_store::{DataStore, LatestAtQuery}; +use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; +use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; +use re_types_core::{Archetype as _, Loggable as _}; + +use re_query2::{ + clamped_zip_1x2, LatestAtComponentResults, LatestAtResults, PromiseResolver, PromiseResult, +}; + +// --- + +fn main() -> anyhow::Result<()> { + let store = store()?; + eprintln!("store:\n{}", store.to_data_table()?); + + let resolver = PromiseResolver::default(); + + let entity_path = "points"; + let timeline = Timeline::new("frame_nr", TimeType::Sequence); + let query = LatestAtQuery::latest(timeline); + eprintln!("query:{query:?}"); + + // First, get the raw results for this query. + // + // Raw here means that these results are neither deserialized, nor resolved/converted. + // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. + let results: LatestAtResults = re_query2::latest_at( + &store, + &query, + &entity_path.into(), + MyPoints::all_components().iter().cloned(), // no generics! + ); + + // Then, grab the raw results for each individual components. + // + // This is still raw data, but now a choice has been made regarding the nullability of the + // _component batch_ itself (that says nothing about its _instances_!). + // + // * `get_required` returns an error if the component batch is missing + // * `get_or_empty` returns an empty set of results if the component if missing + // * `get` returns an option + let points: &LatestAtComponentResults = results.get_required::()?; + let colors: &LatestAtComponentResults = results.get_or_empty::(); + let labels: &LatestAtComponentResults = results.get_or_empty::(); + + // Then comes the time to resolve/convert and deserialize the data. + // These steps have to be done together for efficiency reasons. + // + // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. + // Use `PromiseResult::flatten` to simplify it down to a single result. + // + // A choice now has to be made regarding the nullability of the _component batch's instances_. + // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably + // shouldn't be using anything but `iter_dense`. + + let points = match points.iter_dense::(&resolver).flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + return Ok(()); + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + }; + + let colors = match colors.iter_dense::(&resolver).flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + return Ok(()); + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + }; + + let labels = match labels.iter_sparse::(&resolver).flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + return Ok(()); + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + }; + + // With the data now fully resolved/converted and deserialized, the joining logic can be + // applied. + // + // In most cases this will be either a clamped zip, or no joining at all. + + let color_default_fn = || MyColor::from(0xFF00FFFF); + let label_default_fn = || None; + + let results = + clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn).collect_vec(); + + eprintln!("results:\n{results:#?}"); + + Ok(()) +} + +// --- + +fn store() -> anyhow::Result { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + re_types::components::InstanceKey::name(), + Default::default(), + ); + + let entity_path = "points"; + + { + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + store.insert_row(&row)?; + } + + Ok(store) +} diff --git a/crates/re_query2/src/latest_at/mod.rs b/crates/re_query2/src/latest_at/mod.rs new file mode 100644 index 000000000000..dd86e3d68e3c --- /dev/null +++ b/crates/re_query2/src/latest_at/mod.rs @@ -0,0 +1,5 @@ +mod query; +mod results; + +pub use self::query::latest_at; +pub use self::results::{LatestAtComponentResults, LatestAtResults}; diff --git a/crates/re_query2/src/latest_at/query.rs b/crates/re_query2/src/latest_at/query.rs new file mode 100644 index 000000000000..a9da12168890 --- /dev/null +++ b/crates/re_query2/src/latest_at/query.rs @@ -0,0 +1,40 @@ +use re_data_store::{DataStore, LatestAtQuery}; +use re_log_types::EntityPath; +use re_types_core::ComponentName; + +use crate::LatestAtResults; + +// --- + +/// Queries for the given `component_names` using latest-at semantics. +/// +/// See [`LatestAtResults`] for more information about how to handle the results. +pub fn latest_at( + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, + component_names: impl IntoIterator, +) -> LatestAtResults { + re_tracing::profile_function!(entity_path.to_string()); + + let mut results = LatestAtResults::default(); + + for component_name in component_names { + let Some((time, row_id, mut cells)) = + store.latest_at(query, entity_path, component_name, &[component_name]) + else { + continue; + }; + + // Soundness: + // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` + // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null + if let Some(cell) = cells[0].take() { + results.add(component_name, (time, row_id), cell); + } else { + debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); + } + } + + results +} diff --git a/crates/re_query2/src/latest_at/results.rs b/crates/re_query2/src/latest_at/results.rs new file mode 100644 index 000000000000..0a2800c153a0 --- /dev/null +++ b/crates/re_query2/src/latest_at/results.rs @@ -0,0 +1,213 @@ +use nohash_hasher::IntMap; +use re_log_types::{DataCell, RowId, TimeInt}; +use re_types_core::ComponentName; +use re_types_core::{Component, DeserializationError, DeserializationResult}; + +use crate::{Promise, PromiseResolver, PromiseResult}; + +// --- + +/// Raw results for a latest-at query. +/// +/// The data is neither deserialized, nor resolved/converted. +/// It it the raw [`DataCell`]s, straight from our datastore. +/// +/// Use [`LatestAtResults::get`], [`LatestAtResults::get_required`] and [`LatestAtResults::get_or_empty`] +/// in order to access the raw results for each individual component. +#[derive(Debug, Clone)] +pub struct LatestAtResults { + /// The compound index of this query result. + /// + /// A latest-at query is a compound operation that gathers data from many different rows. + /// The index of that compound result corresponds to the index of most the recent row in all the + /// sub-results, as defined by time and row-id order. + pub compound_index: (TimeInt, RowId), + + /// Raw results for each individual component. + pub components: IntMap, +} + +impl Default for LatestAtResults { + #[inline] + fn default() -> Self { + Self { + compound_index: (TimeInt::STATIC, RowId::ZERO), + components: Default::default(), + } + } +} + +impl LatestAtResults { + #[inline] + pub fn contains(&self, component_name: impl Into) -> bool { + self.components.contains_key(&component_name.into()) + } + + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + #[inline] + pub fn get(&self) -> Option<&LatestAtComponentResults> { + self.components.get(&C::name()) + } + + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + /// + /// Returns an error if the component is not present. + #[inline] + pub fn get_required(&self) -> crate::Result<&LatestAtComponentResults> { + if let Some(component) = self.components.get(&C::name()) { + Ok(component) + } else { + Err(DeserializationError::MissingComponent { + component: C::name(), + backtrace: ::backtrace::Backtrace::new_unresolved(), + } + .into()) + } + } + + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + /// + /// Returns empty results if the component is not present. + #[inline] + pub fn get_or_empty(&self) -> &LatestAtComponentResults { + if let Some(component) = self.components.get(&C::name()) { + component + } else { + static DEFAULT: LatestAtComponentResults = LatestAtComponentResults::EMPTY; + &DEFAULT + } + } +} + +impl LatestAtResults { + #[doc(hidden)] + #[inline] + pub fn add(&mut self, component_name: ComponentName, index: (TimeInt, RowId), cell: DataCell) { + // NOTE: Since this is a compound API that actually emits multiple queries, the index of the + // final result is the most recent index among all of its components, as defined by time + // and row-id order. + // + // TODO(#5303): We have to ignore the cluster key in this piece of logic for backwards compatibility + // reasons with the legacy instance-key model. This will go away next. + use re_types_core::Loggable as _; + if component_name != re_types_core::components::InstanceKey::name() + && index > self.compound_index + { + self.compound_index = index; + } + + self.components.insert( + component_name, + LatestAtComponentResults { + index, + promise: Some(Promise::new(cell)), + }, + ); + } +} + +// --- + +/// Uncached results for a particular component when using a latest-at query. +#[derive(Debug, Clone)] +pub struct LatestAtComponentResults { + index: (TimeInt, RowId), + + // Option so we can have a constant default value for `Self` for the optional+empty case. + promise: Option, +} + +impl Default for LatestAtComponentResults { + #[inline] + fn default() -> Self { + Self::EMPTY + } +} + +impl LatestAtComponentResults { + const EMPTY: Self = Self { + index: (TimeInt::STATIC, RowId::ZERO), + promise: None, + }; +} + +impl LatestAtComponentResults { + #[inline] + pub fn index(&self) -> &(TimeInt, RowId) { + &self.index + } + + /// Returns the component data as a dense vector. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn to_dense( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult>> { + if let Some(cell) = self.promise.as_ref() { + resolver.resolve(cell).map(|cell| { + cell.try_to_native() + .map_err(|err| DeserializationError::DataCellError(err.to_string())) + }) + } else { + // Manufactured empty result. + PromiseResult::Ready(Ok(vec![])) + } + } + + /// Iterates over the component data, assuming it is dense. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn iter_dense( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult>> { + self.to_dense(resolver) + .map(|data| data.map(|data| data.into_iter())) + } + + /// Returns the component data as a sparse vector. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn to_sparse( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult>>> { + if let Some(cell) = self.promise.as_ref() { + resolver.resolve(cell).map(|cell| { + cell.try_to_native_opt() + .map_err(|err| DeserializationError::DataCellError(err.to_string())) + }) + } else { + // Manufactured empty result. + PromiseResult::Ready(Ok(vec![])) + } + } + + /// Iterates over the component data, assuming it is sparse. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn iter_sparse( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult>>> { + self.to_sparse(resolver) + .map(|data| data.map(|data| data.into_iter())) + } +} diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs index 33f05e522514..531b1a24dfa1 100644 --- a/crates/re_query2/src/lib.rs +++ b/crates/re_query2/src/lib.rs @@ -1,9 +1,13 @@ //! Provide query-centric access to the [`re_data_store`]. -mod clamped_zip; +pub mod clamped_zip; +mod latest_at; +mod promise; mod visible_history; pub use self::clamped_zip::*; +pub use self::latest_at::{latest_at, LatestAtComponentResults, LatestAtResults}; +pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; // --- diff --git a/crates/re_query2/src/promise.rs b/crates/re_query2/src/promise.rs new file mode 100644 index 000000000000..1585f6eb0ba2 --- /dev/null +++ b/crates/re_query2/src/promise.rs @@ -0,0 +1,132 @@ +use std::sync::Arc; + +use re_log_types::DataCell; + +// --- + +/// Uniquely identifies a [`Promise`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PromiseId(pub(crate) re_tuid::Tuid); + +impl std::fmt::Display for PromiseId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl PromiseId { + /// Create a new unique [`PromiseId`] based on the current time. + #[allow(clippy::new_without_default)] + #[inline] + pub fn new() -> Self { + Self(re_tuid::Tuid::new()) + } +} + +// --- + +/// A [`Promise`] turns a source [`DataCell`] into a new [`DataCell`] with the helper of a +/// [`PromiseResolver`]. +/// +/// Each promise is uniquely identified via a [`PromiseId`]. +/// +/// [`Promise`]s can be cloned cheaply. +#[derive(Debug, Clone)] +pub struct Promise { + id: PromiseId, + source: DataCell, +} + +static_assertions::assert_eq_size!(Promise, Option); + +impl Promise { + #[inline] + pub fn new(source: DataCell) -> Self { + Self { + id: PromiseId::new(), + source, + } + } +} + +// --- + +/// Resolves and keeps track of [`Promise`]s. +#[derive(Default)] +pub struct PromiseResolver {} + +impl PromiseResolver { + /// Resolves the given [`Promise`]. + /// + /// If the method returns [`PromiseResult::Pending`], you should call it again with the same + /// [`Promise`] until it either resolves it or fails irrecoverably. + /// + /// Once a [`Promise`] has left the `Pending` state, `resolve`ing it again is cached and + /// idempotent (the [`PromiseResolver`] keeps track of the state of all [`Promise`]s, both + /// pending and already resolved). + #[inline] + pub fn resolve(&self, promise: &Promise) -> PromiseResult { + // NOTE: we're pretending there's gonna be some kind of interior mutability when + // everything's said and done. + _ = self; + _ = promise.id; + PromiseResult::Ready(promise.source.clone()) + } +} + +/// The result of resolving a [`Promise`] through a [`PromiseResolver`]. +#[derive(Clone)] +pub enum PromiseResult { + /// The resolution process is still in progress. + /// + /// Try calling [`PromiseResolver::resolve`] again. + Pending, + + /// The [`Promise`] failed to resolve due to an irrecoverable error. + Error(Arc), + + /// The [`Promise`] has been fully resolved. + Ready(T), +} + +impl PromiseResult { + /// Applies the given transformation to the [`PromiseResult`] iff it's `Ready`. + #[inline] + pub fn map(self, mut f: F) -> PromiseResult + where + F: FnMut(T) -> B, + { + match self { + PromiseResult::Ready(v) => PromiseResult::Ready(f(v)), + PromiseResult::Pending => PromiseResult::Pending, + PromiseResult::Error(err) => PromiseResult::Error(err), + } + } + + /// Unwraps the resolved result if it's `Ready`, panics otherwise. + #[inline] + pub fn unwrap(self) -> T { + match self { + PromiseResult::Ready(v) => v, + PromiseResult::Pending => panic!("tried to unwrap a pending `PromiseResult`"), + PromiseResult::Error(err) => { + panic!("tried to unwrap an errored `PromiseResult`: {err}") + } + } + } +} + +impl PromiseResult> { + /// Given a [`PromiseResult`] of a `Result`, flattens it down to a single layer [`PromiseResult`]. + #[inline] + pub fn flatten(self) -> PromiseResult { + match self { + PromiseResult::Ready(res) => match res { + Ok(v) => PromiseResult::Ready(v), + Err(err) => PromiseResult::Error(Arc::new(err) as _), + }, + PromiseResult::Pending => PromiseResult::Pending, + PromiseResult::Error(err) => PromiseResult::Error(err), + } + } +} diff --git a/crates/re_query2/tests/latest_at.rs b/crates/re_query2/tests/latest_at.rs new file mode 100644 index 000000000000..ad49831db10c --- /dev/null +++ b/crates/re_query2/tests/latest_at.rs @@ -0,0 +1,217 @@ +use re_data_store::DataStore; +use re_log_types::example_components::{MyColor, MyPoint, MyPoints}; +use re_log_types::{build_frame_nr, DataRow, RowId, TimePoint}; +use re_query2::PromiseResolver; +use re_types::components::InstanceKey; +use re_types::{Archetype as _, ComponentNameSet}; +use re_types_core::Loggable as _; + +// --- + +#[test] +fn simple_query() -> anyhow::Result<()> { + let resolver = PromiseResolver::default(); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let results = re_query2::latest_at( + &store, + &timeline_query, + &entity_path.into(), + MyPoints::all_components().iter().cloned(), + ); + + // We expect this to generate the following `DataFrame` + // ┌─────────────┬────────────┐ + // │ point ┆ color │ + // │ --- ┆ --- │ + // │ struct[2] ┆ u32 │ + // ╞═════════════╪════════════╡ + // │ {1.0,2.0} ┆ 4278190080 │ + // ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ {3.0,4.0} ┆ 4278190080 │ + // └─────────────┴────────────┘ + + { + let expected_components: ComponentNameSet = + [MyPoint::name(), MyColor::name()].into_iter().collect(); + let got_components: ComponentNameSet = results.components.keys().copied().collect(); + similar_asserts::assert_eq!(expected_components, got_components); + + let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = results.get_required::()?; + let point_data = points.iter_dense::(&resolver).flatten().unwrap(); + + let colors = results.get_or_empty::(); + let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); + let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + + Ok(()) +} + +#[test] +fn static_query() -> anyhow::Result<()> { + let resolver = PromiseResolver::default(); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions)?; + store.insert_row(&row)?; + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, TimePoint::default(), 2, colors)?; + store.insert_row(&row)?; + + let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let results = re_query2::latest_at( + &store, + &timeline_query, + &entity_path.into(), + MyPoints::all_components().iter().cloned(), + ); + + // We expect this to generate the following `DataFrame` + // ┌───────────┬────────────┐ + // │ point ┆ color │ + // │ --- ┆ --- │ + // │ struct[2] ┆ u32 │ + // ╞═══════════╪════════════╡ + // │ {1.0,2.0} ┆ 4278190080 │ + // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ {3.0,4.0} ┆ 4278190080 │ + // └───────────┴────────────┘ + + { + let expected_components: ComponentNameSet = + [MyPoint::name(), MyColor::name()].into_iter().collect(); + let got_components: ComponentNameSet = results.components.keys().copied().collect(); + similar_asserts::assert_eq!(expected_components, got_components); + + let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = results.get_required::()?; + let point_data = points.iter_dense::(&resolver).flatten().unwrap(); + + let colors = results.get_or_empty::(); + let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); + let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + + Ok(()) +} + +#[test] +fn no_instance_join_query() -> anyhow::Result<()> { + let resolver = PromiseResolver::default(); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions)?; + store.insert_row(&row)?; + + let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors)?; + store.insert_row(&row)?; + + let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let results = re_query2::latest_at( + &store, + &timeline_query, + &entity_path.into(), + MyPoints::all_components().iter().cloned(), + ); + + // We expect this to generate the following `DataFrame` + // ┌───────────┬────────────┐ + // │ point ┆ color │ + // │ --- ┆ --- │ + // │ struct[2] ┆ u32 │ + // ╞═══════════╪════════════╡ + // │ {1.0,2.0} ┆ 4278190080 │ + // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ {3.0,4.0} ┆ 16711680 │ + // └───────────┴────────────┘ + + { + let expected_components: ComponentNameSet = + [MyPoint::name(), MyColor::name()].into_iter().collect(); + let got_components: ComponentNameSet = results.components.keys().copied().collect(); + similar_asserts::assert_eq!(expected_components, got_components); + + let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(0, 255, 0)), + ]; + + let points = results.get_required::()?; + let point_data = points.iter_dense::(&resolver).flatten().unwrap(); + + let colors = results.get_or_empty::(); + let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); + let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + + Ok(()) +} From 20dc298ec07a77cf8ad997e0f5b44f15edbf6a4b Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 14:37:17 +0200 Subject: [PATCH 220/508] New data APIs 2: cached latest-at queries (#5581) Static-aware, key-less, component-based, cached latest-at APIs. The overall structure of this new cache is very similar to what we had before. Effectively it is just an extremely simplified version of `re_query_cache`. This introduces a new temporary `re_query_cache2` crate, which won't ever be published. It will replace the existing `re_query_cache` crate once all the necessary features have been backported. - Fixes #3232 - Fixes #4733 - Fixes #4734 - Part of #3379 - Part of #1893 Example: ```rust let caches = re_query_cache2::Caches::new(&store); // First, get the results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. let results: CachedLatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), MyPoints::all_components().iter().cloned(), // no generics! ); // Then, grab the results for each individual components. // * `get_required` returns an error if the component batch is missing // * `get_optional` returns an empty set of results if the component if missing // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. let points: &CachedLatestAtComponentResults = results.get_required::()?; let colors: &CachedLatestAtComponentResults = results.get_optional::(); let labels: &CachedLatestAtComponentResults = results.get_optional::(); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. // // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. // Use `PromiseResult::flatten` to simplify it down to a single result. // // A choice now has to be made regarding the nullability of the _component batch's instances_. // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably // shouldn't be using anything but `iter_dense`. // // This is the step at which caching comes into play. // // If the data has already been accessed with the same nullability characteristics in the // past, then this will just grab the pre-deserialized, pre-resolved/pre-converted result from // the cache. // // Otherwise, this will trigger a deserialization and cache the result for next time. let points = match points.iter_dense::(&mut resolver).flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), }; let colors = match colors.iter_dense::(&mut resolver).flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), }; let labels = match labels.iter_sparse::(&mut resolver).flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), }; // With the data now fully resolved/converted and deserialized, the joining logic can be // applied. // // In most cases this will be either a clamped zip, or no joining at all. let color_default_fn = || { static DEFAULT: MyColor = MyColor(0xFF00FFFF); &DEFAULT }; let label_default_fn = || None; let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn).collect_vec(); ``` --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- Cargo.lock | 28 + Cargo.toml | 1 + crates/re_query_cache2/Cargo.toml | 65 ++ crates/re_query_cache2/README.md | 5 + .../re_query_cache2/benches/flat_vec_deque.rs | 333 ++++++ crates/re_query_cache2/benches/latest_at.rs | 374 +++++++ crates/re_query_cache2/examples/latest_at.rs | 140 +++ crates/re_query_cache2/src/cache.rs | 176 ++++ crates/re_query_cache2/src/flat_vec_deque.rs | 945 ++++++++++++++++++ crates/re_query_cache2/src/latest_at/mod.rs | 5 + crates/re_query_cache2/src/latest_at/query.rs | 265 +++++ .../re_query_cache2/src/latest_at/results.rs | 343 +++++++ crates/re_query_cache2/src/lib.rs | 22 + crates/re_query_cache2/tests/latest_at.rs | 526 ++++++++++ crates/re_types_core/src/size_bytes.rs | 15 +- 15 files changed, 3242 insertions(+), 1 deletion(-) create mode 100644 crates/re_query_cache2/Cargo.toml create mode 100644 crates/re_query_cache2/README.md create mode 100644 crates/re_query_cache2/benches/flat_vec_deque.rs create mode 100644 crates/re_query_cache2/benches/latest_at.rs create mode 100644 crates/re_query_cache2/examples/latest_at.rs create mode 100644 crates/re_query_cache2/src/cache.rs create mode 100644 crates/re_query_cache2/src/flat_vec_deque.rs create mode 100644 crates/re_query_cache2/src/latest_at/mod.rs create mode 100644 crates/re_query_cache2/src/latest_at/query.rs create mode 100644 crates/re_query_cache2/src/latest_at/results.rs create mode 100644 crates/re_query_cache2/src/lib.rs create mode 100644 crates/re_query_cache2/tests/latest_at.rs diff --git a/Cargo.lock b/Cargo.lock index 9150af80656e..a9b9560d95b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4598,6 +4598,34 @@ dependencies = [ "web-time", ] +[[package]] +name = "re_query_cache2" +version = "0.15.0-alpha.5" +dependencies = [ + "ahash", + "anyhow", + "backtrace", + "criterion", + "indent", + "itertools 0.12.0", + "mimalloc", + "nohash-hasher", + "parking_lot", + "paste", + "rand", + "re_data_store", + "re_format", + "re_log", + "re_log_types", + "re_query2", + "re_tracing", + "re_types", + "re_types_core", + "seq-macro", + "similar-asserts", + "web-time", +] + [[package]] name = "re_renderer" version = "0.15.0-alpha.5" diff --git a/Cargo.toml b/Cargo.toml index da3f2bc69b4b..590fa2589d89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ re_memory = { path = "crates/re_memory", version = "=0.15.0-alpha.5", default-fe re_query = { path = "crates/re_query", version = "=0.15.0-alpha.5", default-features = false } re_query2 = { path = "crates/re_query2", version = "=0.15.0-alpha.5", default-features = false } re_query_cache = { path = "crates/re_query_cache", version = "=0.15.0-alpha.5", default-features = false } +re_query_cache2 = { path = "crates/re_query_cache2", version = "=0.15.0-alpha.5", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.15.0-alpha.5", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.15.0-alpha.5", default-features = false } re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.15.0-alpha.5", default-features = false } diff --git a/crates/re_query_cache2/Cargo.toml b/crates/re_query_cache2/Cargo.toml new file mode 100644 index 000000000000..a2d1918dddae --- /dev/null +++ b/crates/re_query_cache2/Cargo.toml @@ -0,0 +1,65 @@ +[package] +name = "re_query_cache2" +authors.workspace = true +description = "Temporary crate meant to replace re_query_cache" +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +# TODO(cmc): Replace re_query with this crate. Never publish this one. +publish = false +readme = "README.md" +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[package.metadata.docs.rs] +all-features = true + + +[features] +default = [] + +[dependencies] +# Rerun dependencies: +re_data_store.workspace = true +re_format.workspace = true +re_log.workspace = true +re_log_types.workspace = true +re_query2.workspace = true +re_tracing.workspace = true +re_types_core.workspace = true + +# External dependencies: +ahash.workspace = true +anyhow.workspace = true +backtrace.workspace = true +indent.workspace = true +itertools.workspace = true +nohash-hasher.workspace = true +parking_lot.workspace = true +paste.workspace = true +seq-macro.workspace = true +web-time.workspace = true + + +[dev-dependencies] +re_types = { workspace = true, features = ["datagen"] } + +criterion.workspace = true +mimalloc.workspace = true +rand = { workspace = true, features = ["std", "std_rng"] } +similar-asserts.workspace = true + + +[lib] +bench = false + + +[[bench]] +name = "flat_vec_deque" +harness = false + +[[bench]] +name = "latest_at" +harness = false diff --git a/crates/re_query_cache2/README.md b/crates/re_query_cache2/README.md new file mode 100644 index 000000000000..db850d204a04 --- /dev/null +++ b/crates/re_query_cache2/README.md @@ -0,0 +1,5 @@ +# re_query_cache2 + +Temporary crate for implementing the new cached data APIs. Not published. + +Will replace `re_query_cache2` when ready. diff --git a/crates/re_query_cache2/benches/flat_vec_deque.rs b/crates/re_query_cache2/benches/flat_vec_deque.rs new file mode 100644 index 000000000000..f1dec8514b7d --- /dev/null +++ b/crates/re_query_cache2/benches/flat_vec_deque.rs @@ -0,0 +1,333 @@ +use criterion::{criterion_group, criterion_main, Criterion}; + +use itertools::Itertools as _; + +use re_query_cache2::FlatVecDeque; + +// --- + +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + +criterion_group!( + benches, + range, + insert, + insert_many, + insert_deque, + remove, + remove_range +); +criterion_main!(benches); + +// --- + +// `cargo test` also runs the benchmark setup code, so make sure they run quickly: +#[cfg(debug_assertions)] +mod constants { + pub const INITIAL_VALUES_PER_ENTRY: usize = 1; + pub const INITIAL_NUM_ENTRIES: usize = 1; + pub const ADDED_VALUES_PER_ENTRY: usize = 1; + pub const ADDED_NUM_ENTRIES: usize = 1; +} + +#[cfg(not(debug_assertions))] +mod constants { + pub const INITIAL_VALUES_PER_ENTRY: usize = 1000; + pub const INITIAL_NUM_ENTRIES: usize = 100; + pub const ADDED_VALUES_PER_ENTRY: usize = 1000; + pub const ADDED_NUM_ENTRIES: usize = 5; +} + +#[allow(clippy::wildcard_imports)] +use self::constants::*; + +// --- + +fn range(c: &mut Criterion) { + if std::env::var("CI").is_ok() { + return; + } + + let mut group = c.benchmark_group("flat_vec_deque"); + group.throughput(criterion::Throughput::Elements( + (ADDED_NUM_ENTRIES * ADDED_VALUES_PER_ENTRY) as _, + )); + + { + group.bench_function("range/prefilled/front", |b| { + let base = create_prefilled(); + b.iter(|| { + let v: FlatVecDeque = base.clone(); + v.range(0..ADDED_NUM_ENTRIES) + .map(ToOwned::to_owned) + .collect_vec() + }); + }); + group.bench_function("range/prefilled/middle", |b| { + let base = create_prefilled(); + b.iter(|| { + let v: FlatVecDeque = base.clone(); + v.range( + INITIAL_NUM_ENTRIES / 2 - ADDED_NUM_ENTRIES / 2 + ..INITIAL_NUM_ENTRIES / 2 + ADDED_NUM_ENTRIES / 2, + ) + .map(ToOwned::to_owned) + .collect_vec() + }); + }); + group.bench_function("range/prefilled/back", |b| { + let base = create_prefilled(); + b.iter(|| { + let v: FlatVecDeque = base.clone(); + v.range(INITIAL_NUM_ENTRIES - ADDED_NUM_ENTRIES..INITIAL_NUM_ENTRIES) + .map(ToOwned::to_owned) + .collect_vec() + }); + }); + } +} + +fn insert(c: &mut Criterion) { + if std::env::var("CI").is_ok() { + return; + } + + let added = (0..ADDED_VALUES_PER_ENTRY as i64).collect_vec(); + + let mut group = c.benchmark_group("flat_vec_deque"); + group.throughput(criterion::Throughput::Elements(added.len() as _)); + + { + group.bench_function("insert/empty", |b| { + b.iter(|| { + let mut v: FlatVecDeque = FlatVecDeque::new(); + v.insert(0, added.clone()); + v + }); + }); + } + + { + group.bench_function("insert/prefilled/front", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert(0, added.clone()); + v + }); + }); + group.bench_function("insert/prefilled/middle", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert(INITIAL_NUM_ENTRIES / 2, added.clone()); + v + }); + }); + group.bench_function("insert/prefilled/back", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert(INITIAL_NUM_ENTRIES, added.clone()); + v + }); + }); + } +} + +fn insert_many(c: &mut Criterion) { + if std::env::var("CI").is_ok() { + return; + } + + let added = (0..ADDED_NUM_ENTRIES as i64) + .map(|_| (0..ADDED_VALUES_PER_ENTRY as i64).collect_vec()) + .collect_vec(); + + let mut group = c.benchmark_group("flat_vec_deque"); + group.throughput(criterion::Throughput::Elements( + (ADDED_NUM_ENTRIES * ADDED_VALUES_PER_ENTRY) as _, + )); + + { + group.bench_function("insert_many/empty", |b| { + b.iter(|| { + let mut v: FlatVecDeque = FlatVecDeque::new(); + v.insert_many(0, added.clone()); + v + }); + }); + } + + { + group.bench_function("insert_many/prefilled/front", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert_many(0, added.clone()); + v + }); + }); + group.bench_function("insert_many/prefilled/middle", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert_many(INITIAL_NUM_ENTRIES / 2, added.clone()); + v + }); + }); + group.bench_function("insert_many/prefilled/back", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert_many(INITIAL_NUM_ENTRIES, added.clone()); + v + }); + }); + } +} + +fn insert_deque(c: &mut Criterion) { + if std::env::var("CI").is_ok() { + return; + } + + let mut added: FlatVecDeque = FlatVecDeque::new(); + for i in 0..ADDED_NUM_ENTRIES { + added.insert(i, (0..ADDED_VALUES_PER_ENTRY as i64).collect_vec()); + } + + let added = FlatVecDeque::from_vecs( + std::iter::repeat_with(|| (0..ADDED_VALUES_PER_ENTRY as i64).collect_vec()) + .take(ADDED_NUM_ENTRIES), + ); + + let mut group = c.benchmark_group("flat_vec_deque"); + group.throughput(criterion::Throughput::Elements( + (ADDED_NUM_ENTRIES * ADDED_VALUES_PER_ENTRY) as _, + )); + + { + group.bench_function("insert_deque/empty", |b| { + b.iter(|| { + let mut v: FlatVecDeque = FlatVecDeque::new(); + v.insert_deque(0, added.clone()); + v + }); + }); + } + + { + group.bench_function("insert_deque/prefilled/front", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert_deque(0, added.clone()); + v + }); + }); + group.bench_function("insert_deque/prefilled/middle", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert_deque(INITIAL_NUM_ENTRIES / 2, added.clone()); + v + }); + }); + group.bench_function("insert_deque/prefilled/back", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.insert_deque(INITIAL_NUM_ENTRIES, added.clone()); + v + }); + }); + } +} + +fn remove(c: &mut Criterion) { + if std::env::var("CI").is_ok() { + return; + } + + let mut group = c.benchmark_group("flat_vec_deque"); + group.throughput(criterion::Throughput::Elements(1)); + + { + group.bench_function("remove/prefilled/front", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.remove(0); + v + }); + }); + group.bench_function("remove/prefilled/middle", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.remove(INITIAL_NUM_ENTRIES / 2); + v + }); + }); + group.bench_function("remove/prefilled/back", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.remove(INITIAL_NUM_ENTRIES - 1); + v + }); + }); + } +} + +fn remove_range(c: &mut Criterion) { + if std::env::var("CI").is_ok() { + return; + } + + let mut group = c.benchmark_group("flat_vec_deque"); + group.throughput(criterion::Throughput::Elements( + (ADDED_NUM_ENTRIES * ADDED_VALUES_PER_ENTRY) as _, + )); + + { + group.bench_function("remove_range/prefilled/front", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.remove_range(0..ADDED_NUM_ENTRIES); + v + }); + }); + group.bench_function("remove_range/prefilled/middle", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.remove_range( + INITIAL_NUM_ENTRIES / 2 - ADDED_NUM_ENTRIES / 2 + ..INITIAL_NUM_ENTRIES / 2 + ADDED_NUM_ENTRIES / 2, + ); + v + }); + }); + group.bench_function("remove_range/prefilled/back", |b| { + let base = create_prefilled(); + b.iter(|| { + let mut v: FlatVecDeque = base.clone(); + v.remove_range(INITIAL_NUM_ENTRIES - ADDED_NUM_ENTRIES..INITIAL_NUM_ENTRIES); + v + }); + }); + } +} + +// --- + +fn create_prefilled() -> FlatVecDeque { + FlatVecDeque::from_vecs( + std::iter::repeat_with(|| (0..INITIAL_VALUES_PER_ENTRY as i64).collect_vec()) + .take(INITIAL_NUM_ENTRIES), + ) +} diff --git a/crates/re_query_cache2/benches/latest_at.rs b/crates/re_query_cache2/benches/latest_at.rs new file mode 100644 index 000000000000..f7c608209224 --- /dev/null +++ b/crates/re_query_cache2/benches/latest_at.rs @@ -0,0 +1,374 @@ +//! Contains: +//! - A 1:1 port of the benchmarks in `crates/re_query/benches/query_benchmarks.rs`, with caching enabled. + +use criterion::{criterion_group, criterion_main, Criterion}; + +use itertools::Itertools; +use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; +use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; +use re_query2::{clamped_zip_1x1, PromiseResolver}; +use re_query_cache2::{CachedLatestAtResults, Caches}; +use re_types::{ + archetypes::Points2D, + components::{Color, InstanceKey, Position2D, Text}, + Archetype as _, +}; +use re_types_core::Loggable as _; + +// --- + +// `cargo test` also runs the benchmark setup code, so make sure they run quickly: +#[cfg(debug_assertions)] +mod constants { + pub const NUM_FRAMES_POINTS: u32 = 1; + pub const NUM_POINTS: u32 = 1; + pub const NUM_FRAMES_STRINGS: u32 = 1; + pub const NUM_STRINGS: u32 = 1; +} + +#[cfg(not(debug_assertions))] +mod constants { + pub const NUM_FRAMES_POINTS: u32 = 1_000; + pub const NUM_POINTS: u32 = 1_000; + pub const NUM_FRAMES_STRINGS: u32 = 1_000; + pub const NUM_STRINGS: u32 = 1_000; +} + +#[allow(clippy::wildcard_imports)] +use self::constants::*; + +// --- + +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + +criterion_group!( + benches, + mono_points, + mono_strings, + batch_points, + batch_strings +); +criterion_main!(benches); + +// --- + +fn mono_points(c: &mut Criterion) { + // Each mono point gets logged at a different path + let paths = (0..NUM_POINTS) + .map(move |point_idx| entity_path!("points", point_idx)) + .collect_vec(); + let msgs = build_points_rows(&paths, 1); + + { + let mut group = c.benchmark_group("arrow_mono_points2"); + // Mono-insert is slow -- decrease the sample size + group.sample_size(10); + group.throughput(criterion::Throughput::Elements( + (NUM_POINTS * NUM_FRAMES_POINTS) as _, + )); + group.bench_function("insert", |b| { + b.iter(|| insert_rows(msgs.iter())); + }); + } + + { + let mut group = c.benchmark_group("arrow_mono_points2"); + group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); + let (caches, store) = insert_rows(msgs.iter()); + group.bench_function("query", |b| { + b.iter(|| query_and_visit_points(&caches, &store, &paths)); + }); + } +} + +fn mono_strings(c: &mut Criterion) { + // Each mono string gets logged at a different path + let paths = (0..NUM_STRINGS) + .map(move |string_idx| entity_path!("strings", string_idx)) + .collect_vec(); + let msgs = build_strings_rows(&paths, 1); + + { + let mut group = c.benchmark_group("arrow_mono_strings2"); + group.sample_size(10); + group.throughput(criterion::Throughput::Elements( + (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, + )); + group.bench_function("insert", |b| { + b.iter(|| insert_rows(msgs.iter())); + }); + } + + { + let mut group = c.benchmark_group("arrow_mono_strings2"); + group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); + let (caches, store) = insert_rows(msgs.iter()); + group.bench_function("query", |b| { + b.iter(|| query_and_visit_strings(&caches, &store, &paths)); + }); + } +} + +fn batch_points(c: &mut Criterion) { + // Batch points are logged together at a single path + let paths = [EntityPath::from("points")]; + let msgs = build_points_rows(&paths, NUM_POINTS as _); + + { + let mut group = c.benchmark_group("arrow_batch_points2"); + group.throughput(criterion::Throughput::Elements( + (NUM_POINTS * NUM_FRAMES_POINTS) as _, + )); + group.bench_function("insert", |b| { + b.iter(|| insert_rows(msgs.iter())); + }); + } + + { + let mut group = c.benchmark_group("arrow_batch_points2"); + group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); + let (caches, store) = insert_rows(msgs.iter()); + group.bench_function("query", |b| { + b.iter(|| query_and_visit_points(&caches, &store, &paths)); + }); + } +} + +fn batch_strings(c: &mut Criterion) { + // Batch strings are logged together at a single path + let paths = [EntityPath::from("points")]; + let msgs = build_strings_rows(&paths, NUM_STRINGS as _); + + { + let mut group = c.benchmark_group("arrow_batch_strings2"); + group.throughput(criterion::Throughput::Elements( + (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, + )); + group.bench_function("insert", |b| { + b.iter(|| insert_rows(msgs.iter())); + }); + } + + { + let mut group = c.benchmark_group("arrow_batch_strings2"); + group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); + let (caches, store) = insert_rows(msgs.iter()); + group.bench_function("query", |b| { + b.iter(|| query_and_visit_strings(&caches, &store, &paths)); + }); + } +} + +// --- Helpers --- + +pub fn build_some_point2d(len: usize) -> Vec { + use rand::Rng as _; + let mut rng = rand::thread_rng(); + + (0..len) + .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) + .collect() +} + +/// Create `len` dummy colors +pub fn build_some_colors(len: usize) -> Vec { + (0..len).map(|i| Color::from(i as u32)).collect() +} + +/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. +pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { + (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) +} + +pub fn build_some_strings(len: usize) -> Vec { + use rand::Rng as _; + let mut rng = rand::thread_rng(); + + (0..len) + .map(|_| { + let ilen: usize = rng.gen_range(0..10000); + let s: String = rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) + .take(ilen) + .map(char::from) + .collect(); + Text::from(s) + }) + .collect() +} + +fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { + (0..NUM_FRAMES_POINTS) + .flat_map(move |frame_idx| { + paths.iter().map(move |path| { + let mut row = DataRow::from_cells2( + RowId::new(), + path.clone(), + [build_frame_nr((frame_idx as i64).try_into().unwrap())], + num_points as _, + ( + build_some_point2d(num_points), + build_some_colors(num_points), + ), + ) + .unwrap(); + // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, + // in debug mode, by the standard test harness. + if cfg!(debug_assertions) { + row.compute_all_size_bytes(); + } + row + }) + }) + .collect() +} + +fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { + (0..NUM_FRAMES_STRINGS) + .flat_map(move |frame_idx| { + paths.iter().map(move |path| { + let mut row = DataRow::from_cells2( + RowId::new(), + path.clone(), + [build_frame_nr((frame_idx as i64).try_into().unwrap())], + num_strings as _, + // We still need to create points because they are the primary for the + // archetype query we want to do. We won't actually deserialize the points + // during the query -- we just need it for the primary keys. + // TODO(jleibs): switch this to use `TextEntry` once the new type has + // landed. + ( + build_some_point2d(num_strings), + build_some_strings(num_strings), + ), + ) + .unwrap(); + // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, + // in debug mode, by the standard test harness. + if cfg!(debug_assertions) { + row.compute_all_size_bytes(); + } + row + }) + }) + .collect() +} + +fn insert_rows<'a>(msgs: impl Iterator) -> (Caches, DataStore) { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + msgs.for_each(|row| { + caches.on_events(&[store.insert_row(row).unwrap()]); + }); + + (caches, store) +} + +struct SavePoint { + _pos: Position2D, + _color: Option, +} + +fn query_and_visit_points( + caches: &Caches, + store: &DataStore, + paths: &[EntityPath], +) -> Vec { + let resolver = PromiseResolver::default(); + + let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); + let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); + + let mut ret = Vec::with_capacity(NUM_POINTS as _); + + // TODO(jleibs): Add Radius once we have support for it in field_types + for entity_path in paths { + let results: CachedLatestAtResults = caches.latest_at( + store, + &query, + entity_path, + Points2D::all_components().iter().cloned(), // no generics! + ); + + let points = results.get_required::().unwrap(); + let colors = results.get_or_empty::(); + + let points = points + .iter_dense::(&resolver) + .flatten() + .unwrap() + .copied(); + + let colors = colors + .iter_dense::(&resolver) + .flatten() + .unwrap() + .copied(); + let color_default_fn = || Color::from(0xFF00FFFF); + + for (point, color) in clamped_zip_1x1(points, colors, color_default_fn) { + ret.push(SavePoint { + _pos: point, + _color: Some(color), + }); + } + } + assert_eq!(NUM_POINTS as usize, ret.len()); + ret +} + +struct SaveString { + _label: Option, +} + +fn query_and_visit_strings( + caches: &Caches, + store: &DataStore, + paths: &[EntityPath], +) -> Vec { + let resolver = PromiseResolver::default(); + + let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); + let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); + + let mut strings = Vec::with_capacity(NUM_STRINGS as _); + + for entity_path in paths { + let results: CachedLatestAtResults = caches.latest_at( + store, + &query, + entity_path, + Points2D::all_components().iter().cloned(), // no generics! + ); + + let points = results.get_required::().unwrap(); + let colors = results.get_or_empty::(); + + let points = points + .iter_dense::(&resolver) + .flatten() + .unwrap() + .copied(); + + let labels = colors + .iter_dense::(&resolver) + .flatten() + .unwrap() + .cloned(); + let label_default_fn = || Text(String::new().into()); + + for (_point, label) in clamped_zip_1x1(points, labels, label_default_fn) { + strings.push(SaveString { + _label: Some(label), + }); + } + } + assert_eq!(NUM_STRINGS as usize, strings.len()); + criterion::black_box(strings) +} diff --git a/crates/re_query_cache2/examples/latest_at.rs b/crates/re_query_cache2/examples/latest_at.rs new file mode 100644 index 000000000000..160154bf0589 --- /dev/null +++ b/crates/re_query_cache2/examples/latest_at.rs @@ -0,0 +1,140 @@ +use itertools::Itertools; +use re_data_store::{DataStore, LatestAtQuery}; +use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; +use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; +use re_types_core::{Archetype as _, Loggable as _}; + +use re_query_cache2::{ + clamped_zip_1x2, CachedLatestAtComponentResults, CachedLatestAtResults, PromiseResolver, + PromiseResult, +}; + +// --- + +fn main() -> anyhow::Result<()> { + let store = store()?; + eprintln!("store:\n{}", store.to_data_table()?); + + let resolver = PromiseResolver::default(); + + let entity_path = "points"; + let timeline = Timeline::new("frame_nr", TimeType::Sequence); + let query = LatestAtQuery::latest(timeline); + eprintln!("query:{query:?}"); + + let caches = re_query_cache2::Caches::new(&store); + + // First, get the results for this query. + // + // They might or might not already be cached. We won't know for sure until we try to access + // each individual component's data below. + let results: CachedLatestAtResults = caches.latest_at( + &store, + &query, + &entity_path.into(), + MyPoints::all_components().iter().cloned(), // no generics! + ); + + // Then, grab the results for each individual components. + // * `get_required` returns an error if the component batch is missing + // * `get_or_empty` returns an empty set of results if the component if missing + // * `get` returns an option + // + // At this point we still don't know whether they are cached or not. That's the next step. + let points: &CachedLatestAtComponentResults = results.get_required::()?; + let colors: &CachedLatestAtComponentResults = results.get_or_empty::(); + let labels: &CachedLatestAtComponentResults = results.get_or_empty::(); + + // Then comes the time to resolve/convert and deserialize the data. + // These steps have to be done together for efficiency reasons. + // + // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. + // Use `PromiseResult::flatten` to simplify it down to a single result. + // + // A choice now has to be made regarding the nullability of the _component batch's instances_. + // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably + // shouldn't be using anything but `iter_dense`. + // + // This is the step at which caching comes into play. + // + // If the data has already been accessed with the same nullability characteristics in the + // past, then this will just grab the pre-deserialized, pre-resolved/pre-converted result from + // the cache. + // + // Otherwise, this will trigger a deserialization and cache the result for next time. + + let points = match points.iter_dense::(&resolver).flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + return Ok(()); + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + }; + + let colors = match colors.iter_dense::(&resolver).flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + return Ok(()); + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + }; + + let labels = match labels.iter_sparse::(&resolver).flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + return Ok(()); + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + }; + + // With the data now fully resolved/converted and deserialized, the joining logic can be + // applied. + // + // In most cases this will be either a clamped zip, or no joining at all. + + let color_default_fn = || { + static DEFAULT: MyColor = MyColor(0xFF00FFFF); + &DEFAULT + }; + let label_default_fn = || None; + + let results = + clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn).collect_vec(); + + eprintln!("results:\n{results:#?}"); + + Ok(()) +} + +// --- + +fn store() -> anyhow::Result { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + re_types::components::InstanceKey::name(), + Default::default(), + ); + + let entity_path = "points"; + + { + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + store.insert_row(&row)?; + } + + Ok(store) +} diff --git a/crates/re_query_cache2/src/cache.rs b/crates/re_query_cache2/src/cache.rs new file mode 100644 index 000000000000..959707eca1c5 --- /dev/null +++ b/crates/re_query_cache2/src/cache.rs @@ -0,0 +1,176 @@ +use std::{collections::BTreeSet, sync::Arc}; + +use ahash::{HashMap, HashSet}; +use parking_lot::RwLock; + +use re_data_store::{DataStore, StoreDiff, StoreEvent, StoreSubscriber, TimeInt}; +use re_log_types::{EntityPath, StoreId, Timeline}; +use re_types_core::ComponentName; + +use crate::LatestAtCache; + +// --- + +/// Uniquely identifies cached query results in the [`Caches`]. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct CacheKey { + pub entity_path: EntityPath, + pub timeline: Timeline, + pub component_name: ComponentName, +} + +impl std::fmt::Debug for CacheKey { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + entity_path, + timeline, + component_name, + } = self; + f.write_fmt(format_args!( + "{entity_path}:{component_name} on {}", + timeline.name() + )) + } +} + +impl CacheKey { + #[inline] + pub fn new( + entity_path: impl Into, + timeline: impl Into, + component_name: impl Into, + ) -> Self { + Self { + entity_path: entity_path.into(), + timeline: timeline.into(), + component_name: component_name.into(), + } + } +} + +#[derive(Debug)] +pub struct Caches { + /// The [`StoreId`] of the associated [`DataStore`]. + pub(crate) store_id: StoreId, + + // NOTE: `Arc` so we can cheaply free the top-level lock early when needed. + pub(crate) per_cache_key: RwLock>>>, +} + +impl Caches { + #[inline] + pub fn new(store: &DataStore) -> Self { + Self { + store_id: store.id().clone(), + per_cache_key: Default::default(), + } + } +} + +impl StoreSubscriber for Caches { + #[inline] + fn name(&self) -> String { + "rerun.store_subscribers.QueryCache".into() + } + + #[inline] + fn as_any(&self) -> &dyn std::any::Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + fn on_events(&mut self, events: &[StoreEvent]) { + re_tracing::profile_function!(format!("num_events={}", events.len())); + + #[derive(Default, Debug)] + struct CompactedEvents { + static_: HashSet<(EntityPath, ComponentName)>, + temporal: HashMap>, + } + + let mut compacted = CompactedEvents::default(); + + for event in events { + let StoreEvent { + store_id, + store_generation: _, + event_id: _, + diff, + } = event; + + assert!( + self.store_id == *store_id, + "attempted to use a query cache {} with the wrong datastore ({})", + self.store_id, + store_id, + ); + + let StoreDiff { + kind: _, // Don't care: both additions and deletions invalidate query results. + row_id: _, + times, + entity_path, + cells, + } = diff; + + { + re_tracing::profile_scope!("compact events"); + + if times.is_empty() { + for component_name in cells.keys() { + compacted + .static_ + .insert((entity_path.clone(), *component_name)); + } + } + + for &(timeline, data_time) in times { + for component_name in cells.keys() { + let key = CacheKey::new(entity_path.clone(), timeline, *component_name); + let data_times = compacted.temporal.entry(key).or_default(); + data_times.insert(data_time); + } + } + } + } + + let caches = self.per_cache_key.write(); + // NOTE: Don't release the top-level lock -- even though this cannot happen yet with + // our current macro-architecture, we want to prevent queries from concurrently + // running while we're updating the invalidation flags. + + { + re_tracing::profile_scope!("timeless"); + + // TODO(cmc): This is horribly stupid and slow and can easily be made faster by adding + // yet another layer of caching indirection. + // But since this pretty much never happens in practice, let's not go there until we + // have metrics showing that show we need to. + for (entity_path, component_name) in compacted.static_ { + for (key, cache) in caches.iter() { + if key.entity_path == entity_path && key.component_name == component_name { + cache.write().pending_invalidations.insert(TimeInt::STATIC); + } + } + } + } + + { + re_tracing::profile_scope!("temporal"); + + for (key, times) in compacted.temporal { + if let Some(cache) = caches.get(&key) { + cache + .write() + .pending_invalidations + .extend(times.iter().copied()); + } + } + } + } +} diff --git a/crates/re_query_cache2/src/flat_vec_deque.rs b/crates/re_query_cache2/src/flat_vec_deque.rs new file mode 100644 index 000000000000..a5508f0391c1 --- /dev/null +++ b/crates/re_query_cache2/src/flat_vec_deque.rs @@ -0,0 +1,945 @@ +use std::{collections::VecDeque, ops::Range}; + +use itertools::Itertools as _; + +use re_types_core::SizeBytes; + +// --- + +/// A [`FlatVecDeque`] that can be erased into a trait object. +/// +/// Methods that don't require monomorphization over `T` are made dynamically dispatchable. +pub trait ErasedFlatVecDeque: std::any::Any { + fn as_any(&self) -> &dyn std::any::Any; + + fn as_any_mut(&mut self) -> &mut dyn std::any::Any; + + fn into_any(self: Box) -> Box; + + /// Dynamically dispatches to [`FlatVecDeque::num_entries`]. + /// + /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to + /// avoid even with explicit syntax and that silently lead to infinite recursions. + fn dyn_num_entries(&self) -> usize; + + /// Dynamically dispatches to [`FlatVecDeque::num_values`]. + /// + /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to + /// avoid even with explicit syntax and that silently lead to infinite recursions. + fn dyn_num_values(&self) -> usize; + + /// Dynamically dispatches to [`FlatVecDeque::remove`]. + /// + /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to + /// avoid even with explicit syntax and that silently lead to infinite recursions. + fn dyn_remove(&mut self, at: usize); + + /// Dynamically dispatches to [`FlatVecDeque::remove`]. + /// + /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to + /// avoid even with explicit syntax and that silently lead to infinite recursions. + fn dyn_remove_range(&mut self, range: Range); + + /// Dynamically dispatches to [`FlatVecDeque::truncate`]. + /// + /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to + /// avoid even with explicit syntax and that silently lead to infinite recursions. + fn dyn_truncate(&mut self, at: usize); + + /// Dynamically dispatches to [` as SizeBytes>::total_size_bytes(self)`]. + /// + /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to + /// avoid even with explicit syntax and that silently lead to infinite recursions. + fn dyn_total_size_bytes(&self) -> u64; +} + +impl ErasedFlatVecDeque for FlatVecDeque { + #[inline] + fn as_any(&self) -> &dyn std::any::Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { + self + } + + #[inline] + fn into_any(self: Box) -> Box { + self + } + + #[inline] + fn dyn_num_entries(&self) -> usize { + self.num_entries() + } + + #[inline] + fn dyn_num_values(&self) -> usize { + self.num_values() + } + + #[inline] + fn dyn_remove(&mut self, at: usize) { + FlatVecDeque::::remove(self, at); + } + + #[inline] + fn dyn_remove_range(&mut self, range: Range) { + FlatVecDeque::::remove_range(self, range); + } + + #[inline] + fn dyn_truncate(&mut self, at: usize) { + FlatVecDeque::::truncate(self, at); + } + + #[inline] + fn dyn_total_size_bytes(&self) -> u64 { + as SizeBytes>::total_size_bytes(self) + } +} + +// --- + +/// A double-ended queue implemented with a pair of growable ring buffers, where every single +/// entry is a flattened array of values. +/// +/// Logically like a `VecDeque>`, but with a less fragmented memory layout (each `Box<[T]>` +/// gets copied/inlined into the `FlatVecDeque`). +/// `FlatVecDeque` therefore optimizes for reads (cache locality, specifically) while `VecDeque>` +/// optimizes for writes. +/// +/// You can think of this as the native/deserialized version of an Arrow `ListArray`. +/// This is particularly useful when working with many small arrays of data (e.g. Rerun's +/// `TimeSeriesScalar`s). +// +// TODO(cmc): We could even use a bitmap for T=Option, which would bring this that much +// closer to a deserialized version of an Arrow array. +#[derive(Debug, Clone)] +pub struct FlatVecDeque { + /// Stores every value in the `FlatVecDeque` in a flattened `VecDeque`. + /// + /// E.g.: + /// - `FlatVecDeque[]` -> values=`[]`. + /// - `FlatVecDeque[[], [], []]` -> values=`[]`. + /// - `FlatVecDeque[[], [0], [1, 2, 3], [4, 5]]` -> values=`[0, 1, 2, 3, 4, 5]`. + values: VecDeque, + + /// Keeps track of each entry, i.e. logical slices of data. + /// + /// E.g.: + /// - `FlatVecDeque[]` -> offsets=`[]`. + /// - `FlatVecDeque[[], [], []]` -> offsets=`[0, 0, 0]`. + /// - `FlatVecDeque[[], [0], [1, 2, 3], [4, 5]]` -> offsets=`[0, 1, 4, 6]`. + offsets: VecDeque, +} + +impl SizeBytes for FlatVecDeque { + #[inline] + fn heap_size_bytes(&self) -> u64 { + // NOTE: It's all on the heap at this point. + + let values_size_bytes = if T::is_pod() { + (self.num_values() * std::mem::size_of::()) as _ + } else { + self.values + .iter() + .map(SizeBytes::total_size_bytes) + .sum::() + }; + + let offsets_size_bytes = self.num_entries() * std::mem::size_of::(); + + values_size_bytes + offsets_size_bytes as u64 + } +} + +impl From> for FlatVecDeque { + #[inline] + fn from(values: VecDeque) -> Self { + let num_values = values.len(); + Self { + values, + offsets: std::iter::once(num_values).collect(), + } + } +} + +impl From> for FlatVecDeque { + #[inline] + fn from(values: Vec) -> Self { + let num_values = values.len(); + Self { + values: values.into(), + offsets: std::iter::once(num_values).collect(), + } + } +} + +impl Default for FlatVecDeque { + #[inline] + fn default() -> Self { + Self::new() + } +} + +impl FlatVecDeque { + #[inline] + pub const fn new() -> Self { + Self { + values: VecDeque::new(), + offsets: VecDeque::new(), + } + } + + #[inline] + pub fn from_vecs(entries: impl IntoIterator>) -> Self { + let mut this = Self::new(); + + // NOTE: Do not use any of the insertion methods, they rely on `from_vecs` in the first + // place! + let mut value_offset = 0; + for entry in entries { + value_offset += entry.len(); // increment first! + this.offsets.push_back(value_offset); + this.values.extend(entry); + } + + this + } + + /// How many entries are there in the deque? + /// + /// Keep in mind: each entry is itself an array of values. + /// Use [`Self::num_values`] to get the total number of values across all entries. + #[inline] + pub fn num_entries(&self) -> usize { + self.offsets.len() + } + + /// How many values are there in the deque? + /// + /// Keep in mind: each entry in the deque holds an array of values. + /// Use [`Self::num_entries`] to get the total number of entries, irrelevant of how many + /// values each entry holds. + #[inline] + pub fn num_values(&self) -> usize { + self.values.len() + } + + #[inline] + fn value_offset(&self, entry_index: usize) -> usize { + if entry_index == 0 { + 0 + } else { + self.offsets[entry_index - 1] + } + } + + #[inline] + fn iter_offset_ranges(&self) -> impl Iterator> + '_ { + std::iter::once(0) + .chain(self.offsets.iter().copied()) + .tuple_windows::<(_, _)>() + .map(|(start, end)| (start..end)) + } +} + +// --- + +impl FlatVecDeque { + /// Iterates over all the entries in the deque. + /// + /// This is the same as `self.range(0..self.num_entries())`. + /// + /// Keep in mind that each entry is an array of values! + #[inline] + pub fn iter(&self) -> impl Iterator { + self.range(0..self.num_entries()) + } + + /// Iterates over all the entries in the deque in the given `entry_range`. + /// + /// Keep in mind that each entry is an array of values! + #[inline] + pub fn range(&self, entry_range: Range) -> impl Iterator { + let (values_left, values_right) = self.values.as_slices(); + // NOTE: We can't slice into our offsets, we don't even know if they're contiguous in + // memory at this point -> skip() and take(). + self.iter_offset_ranges() + .skip(entry_range.start) + .take(entry_range.len()) + .map(|offsets| { + if offsets.is_empty() { + return &[] as &'_ [T]; + } + + // NOTE: We do not need `make_contiguous` here because we always guarantee + // that a single entry's worth of values is fully contained in either the left or + // right buffer, but never straddling across both. + if offsets.start < values_left.len() { + &values_left[offsets] + } else { + &values_right[offsets] + } + }) + } +} + +#[test] +fn range() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); + + assert_iter_eq(&[&[1, 2, 3]], v.range(0..1)); + assert_iter_eq(&[&[4, 5, 6, 7]], v.range(1..2)); + assert_iter_eq(&[&[8, 9, 10]], v.range(2..3)); + + assert_iter_eq( + &[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], + v.range(0..v.num_entries()), + ); + + assert_iter_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], v.iter()); +} + +// --- + +impl FlatVecDeque { + /// Prepends an entry comprised of `values` to the deque. + /// + /// This is the same as `self.insert(0, values)`. + /// + /// See [`Self::insert`] for more information. + #[inline] + pub fn push_front(&mut self, values: impl IntoIterator) { + self.insert(0, values); + } + + /// Appends an entry comprised of `values` to the deque. + /// + /// This is the same as `self.insert(self.num_entries(), values)`. + /// + /// See [`Self::insert`] for more information. + #[inline] + pub fn push_back(&mut self, values: impl IntoIterator) { + self.insert(self.num_entries(), values); + } + + /// Inserts a single entry at `entry_index`, comprised of the multiple elements given as `values`. + /// + /// This is O(1) if `entry_index` corresponds to either the start or the end of the deque. + /// Otherwise, this requires splitting the deque into two pieces then stitching them back together + /// at both ends of the added data. + /// + /// Panics if `entry_index` is out of bounds. + /// Panics if `values` is empty. + #[inline] + pub fn insert(&mut self, entry_index: usize, values: impl IntoIterator) { + let values: VecDeque = values.into_iter().collect(); + let deque = values.into(); + self.insert_deque(entry_index, deque); + } + + /// Prepends multiple entries, each comprised of the multiple elements given in `entries`, + /// to the deque. + /// + /// This is the same as `self.insert_many(0, entries)`. + /// + /// See [`Self::insert_many`] for more information. + #[inline] + pub fn push_many_front(&mut self, entries: impl IntoIterator>) { + self.insert_many(0, entries); + } + + /// Appends multiple entries, each comprised of the multiple elements given in `entries`, + /// to the deque. + /// + /// This is the same as `self.insert_many(self.num_entries(), entries)`. + /// + /// See [`Self::insert_many`] for more information. + #[inline] + pub fn push_many_back(&mut self, entries: impl IntoIterator>) { + self.insert_many(self.num_entries(), entries); + } + + /// Inserts multiple entries, starting at `entry_index` onwards, each comprised of the multiple elements + /// given in `entries`. + /// + /// This is O(1) if `entry_index` corresponds to either the start or the end of the deque. + /// Otherwise, this requires splitting the deque into two pieces then stitching them back together + /// at both ends of the added data. + /// + /// Panics if `entry_index` is out of bounds. + /// Panics if any of the value arrays in `entries` is empty. + #[inline] + pub fn insert_many(&mut self, entry_index: usize, entries: impl IntoIterator>) { + let deque = Self::from_vecs(entries); + self.insert_deque(entry_index, deque); + } + + /// Prepends another full deque to the deque. + /// + /// This is the same as `self.insert_deque(0, rhs)`. + /// + /// See [`Self::insert_deque`] for more information. + #[inline] + pub fn push_front_deque(&mut self, rhs: FlatVecDeque) { + self.insert_deque(0, rhs); + } + + /// Appends another full deque to the deque. + /// + /// This is the same as `self.insert_deque(0, rhs)`. + /// + /// See [`Self::insert_deque`] for more information. + #[inline] + pub fn push_back_deque(&mut self, rhs: FlatVecDeque) { + self.insert_deque(self.num_entries(), rhs); + } + + /// Inserts another full deque, starting at `entry_index` and onwards. + /// + /// This is O(1) if `entry_index` corresponds to either the start or the end of the deque. + /// Otherwise, this requires splitting the deque into two pieces then stitching them back together + /// at both ends of the added data. + /// + /// Panics if `entry_index` is out of bounds. + /// Panics if any of the value arrays in `entries` is empty. + pub fn insert_deque(&mut self, entry_index: usize, mut rhs: FlatVecDeque) { + // NOTE: We're inserting _beyond_ the last element. + if entry_index == self.num_entries() { + let max_value_offset = self.offsets.back().copied().unwrap_or_default(); + self.offsets + .extend(rhs.offsets.into_iter().map(|o| o + max_value_offset)); + self.values.extend(rhs.values); + return; + } else if entry_index == 0 { + rhs.push_back_deque(std::mem::take(self)); + *self = rhs; + return; + } + + let right = self.split_off(entry_index); + self.push_back_deque(rhs); + self.push_back_deque(right); + + debug_assert!(self.iter_offset_ranges().all(|r| r.start <= r.end)); + } +} + +#[test] +fn insert() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert(0, [1, 2, 3]); + assert_deque_eq(&[&[1, 2, 3]], &v); + + v.insert(0, [4, 5, 6, 7]); + assert_deque_eq(&[&[4, 5, 6, 7], &[1, 2, 3]], &v); + + v.insert(0, [8, 9]); + assert_deque_eq(&[&[8, 9], &[4, 5, 6, 7], &[1, 2, 3]], &v); + + v.insert(2, [10, 11, 12, 13]); + assert_deque_eq(&[&[8, 9], &[4, 5, 6, 7], &[10, 11, 12, 13], &[1, 2, 3]], &v); + + v.insert(v.num_entries(), [14, 15]); + assert_deque_eq( + &[ + &[8, 9], + &[4, 5, 6, 7], + &[10, 11, 12, 13], + &[1, 2, 3], + &[14, 15], + ], + &v, + ); + + v.insert(v.num_entries() - 1, [42]); + assert_deque_eq( + &[ + &[8, 9], + &[4, 5, 6, 7], + &[10, 11, 12, 13], + &[1, 2, 3], + &[42], + &[14, 15], + ], + &v, + ); +} + +#[test] +fn insert_empty() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.push_back([]); + v.push_back([]); + v.push_back([]); + + assert_deque_eq(&[&[], &[], &[]], &v); +} + +// Simulate the bug that was making everything crash on the face tracking example (ultimately +// caused by recursive clears). +#[test] +fn insert_some_and_empty() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.push_back([0]); + v.push_back([]); + + v.push_back([1]); + v.push_back([]); + + v.push_back([2]); + v.push_back([]); + + // That used to crash. + assert_deque_eq(&[&[0], &[], &[1], &[], &[2], &[]], &v); +} + +#[test] +fn insert_many() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); + + v.insert_many(0, [vec![20], vec![21], vec![22]]); + assert_deque_eq( + &[&[20], &[21], &[22], &[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], + &v, + ); + + v.insert_many(4, [vec![41, 42], vec![43]]); + assert_deque_eq( + &[ + &[20], + &[21], + &[22], + &[1, 2, 3], + &[41, 42], + &[43], + &[4, 5, 6, 7], + &[8, 9, 10], + ], + &v, + ); + + v.insert_many(v.num_entries(), [vec![100], vec![200, 300, 400]]); + assert_deque_eq( + &[ + &[20], + &[21], + &[22], + &[1, 2, 3], + &[41, 42], + &[43], + &[4, 5, 6, 7], + &[8, 9, 10], + &[100], + &[200, 300, 400], + ], + &v, + ); +} + +#[test] +fn insert_deque() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert_deque( + 0, + FlatVecDeque::from_vecs([vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]), + ); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); + + v.insert_deque(0, FlatVecDeque::from_vecs([vec![20], vec![21], vec![22]])); + assert_deque_eq( + &[&[20], &[21], &[22], &[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], + &v, + ); + + v.insert_deque(4, FlatVecDeque::from_vecs([vec![41, 42], vec![43]])); + assert_deque_eq( + &[ + &[20], + &[21], + &[22], + &[1, 2, 3], + &[41, 42], + &[43], + &[4, 5, 6, 7], + &[8, 9, 10], + ], + &v, + ); + + v.insert_deque( + v.num_entries(), + FlatVecDeque::from_vecs([vec![100], vec![200, 300, 400]]), + ); + assert_deque_eq( + &[ + &[20], + &[21], + &[22], + &[1, 2, 3], + &[41, 42], + &[43], + &[4, 5, 6, 7], + &[8, 9, 10], + &[100], + &[200, 300, 400], + ], + &v, + ); +} + +// --- + +impl FlatVecDeque { + /// Splits the deque into two at the given index. + /// + /// Returns a newly allocated `FlatVecDeque`. `self` contains entries `[0, entry_index)`, + /// and the returned deque contains entries `[entry_index, num_entries)`. + /// + /// Note that the capacity of `self` does not change. + /// + /// Panics if `entry_index` is out of bounds. + #[inline] + #[must_use = "use `.truncate()` if you don't need the other half"] + pub fn split_off(&mut self, entry_index: usize) -> Self { + let value_offset = self.value_offset(entry_index); + + let mut offsets = self.offsets.split_off(entry_index); + for offset in &mut offsets { + *offset -= value_offset; + } + + Self { + values: self.values.split_off(value_offset), + offsets, + } + } + + /// Shortens the deque, keeping all entries up to `entry_index` (excluded), and + /// dropping the rest. + /// + /// If `entry_index` is greater or equal to [`Self::num_entries`], this has no effect. + #[inline] + pub fn truncate(&mut self, entry_index: usize) { + if entry_index < self.num_entries() { + self.values.truncate(self.value_offset(entry_index)); + self.offsets.truncate(entry_index); + } + } + + /// Removes the entry at `entry_index` from the deque. + /// + /// This is O(1) if `entry_index` corresponds to either the start or the end of the deque. + /// Otherwise, this requires splitting the deque into three pieces, dropping the superfluous + /// one, then stitching the two remaining pices back together. + /// + /// Panics if `entry_index` is out of bounds. + pub fn remove(&mut self, entry_index: usize) { + let (start_offset, end_offset) = ( + self.value_offset(entry_index), + self.value_offset(entry_index + 1), + ); + let offset_count = end_offset - start_offset; + + if entry_index + 1 == self.num_entries() { + self.offsets.truncate(self.num_entries() - 1); + self.values.truncate(self.values.len() - offset_count); + return; + } else if entry_index == 0 { + *self = self.split_off(entry_index + 1); + return; + } + + // NOTE: elegant, but way too slow :) + // let right = self.split_off(entry_index + 1); + // _ = self.split_off(self.num_entries() - 1); + // self.push_back_deque(right); + + _ = self.offsets.remove(entry_index); + for offset in self.offsets.range_mut(entry_index..) { + *offset -= offset_count; + } + + let right = self.values.split_off(end_offset); + self.values.truncate(self.values.len() - offset_count); + self.values.extend(right); + } + + /// Removes all entries within the given `entry_range` from the deque. + /// + /// This is O(1) if `entry_range` either starts at the beginning of the deque, or ends at + /// the end of the deque, or both. + /// Otherwise, this requires splitting the deque into three pieces, dropping the superfluous + /// one, then stitching the two remaining pieces back together. + /// + /// Panics if `entry_range` is either out of bounds or isn't monotonically increasing. + #[inline] + pub fn remove_range(&mut self, entry_range: Range) { + assert!(entry_range.start <= entry_range.end); + + if entry_range.start == entry_range.end { + return; + } + + let (start_offset, end_offset) = ( + self.value_offset(entry_range.start), + self.value_offset(entry_range.end), + ); + let offset_count = end_offset - start_offset; + + // Reminder: `entry_range.end` is exclusive. + if entry_range.end == self.num_entries() { + self.offsets + .truncate(self.num_entries() - entry_range.len()); + self.values.truncate(self.values.len() - offset_count); + return; + } else if entry_range.start == 0 { + *self = self.split_off(entry_range.end); + return; + } + + let right = self.split_off(entry_range.end); + _ = self.split_off(self.num_entries() - entry_range.len()); + self.push_back_deque(right); + } +} + +#[test] +fn truncate() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); + + { + let mut v = v.clone(); + v.truncate(0); + assert_deque_eq(&[], &v); + } + + { + let mut v = v.clone(); + v.truncate(1); + assert_deque_eq(&[&[1, 2, 3]], &v); + } + + { + let mut v = v.clone(); + v.truncate(2); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &v); + } + + { + let mut v = v.clone(); + v.truncate(3); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); + } +} + +#[test] +fn split_off() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); + + { + let mut left = v.clone(); + let right = left.split_off(0); + + assert_deque_eq(&[], &left); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &right); + } + + { + let mut left = v.clone(); + let right = left.split_off(1); + + assert_deque_eq(&[&[1, 2, 3]], &left); + assert_deque_eq(&[&[4, 5, 6, 7], &[8, 9, 10]], &right); + } + + { + let mut left = v.clone(); + let right = left.split_off(2); + + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &left); + assert_deque_eq(&[&[8, 9, 10]], &right); + } + + { + let mut left = v.clone(); + let right = left.split_off(3); + + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &left); + assert_deque_eq(&[], &right); + } +} + +#[test] +fn remove() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert(0, [1, 2, 3]); + assert_deque_eq(&[&[1, 2, 3]], &v); + + v.remove(0); + assert_deque_eq(&[], &v); + + v.insert(0, [1, 2, 3]); + assert_deque_eq(&[&[1, 2, 3]], &v); + + v.insert(1, [4, 5, 6, 7]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &v); + + v.insert(2, [8, 9]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9]], &v); + + v.remove(0); + assert_deque_eq(&[&[4, 5, 6, 7], &[8, 9]], &v); + + v.insert(0, [1, 2, 3]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9]], &v); + + v.remove(1); + assert_deque_eq(&[&[1, 2, 3], &[8, 9]], &v); + + v.insert(1, [4, 5, 6, 7]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9]], &v); + + v.remove(2); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &v); + + v.remove(0); + assert_deque_eq(&[&[4, 5, 6, 7]], &v); + + v.remove(0); + assert_deque_eq(&[], &v); +} + +#[test] +#[should_panic(expected = "Out of bounds access")] +fn remove_empty() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.remove(0); +} + +#[test] +#[should_panic(expected = "Out of bounds access")] +fn remove_oob() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert(0, [1, 2, 3]); + assert_deque_eq(&[&[1, 2, 3]], &v); + + assert_eq!(1, v.num_entries()); + assert_eq!(3, v.num_values()); + + v.remove(1); +} + +#[test] +fn remove_range() { + let mut v: FlatVecDeque = FlatVecDeque::new(); + + assert_eq!(0, v.num_entries()); + assert_eq!(0, v.num_values()); + + v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); + + { + let mut v = v.clone(); + v.remove_range(0..1); + assert_deque_eq(&[&[4, 5, 6, 7], &[8, 9, 10]], &v); + } + + { + let mut v = v.clone(); + v.remove_range(1..2); + assert_deque_eq(&[&[1, 2, 3], &[8, 9, 10]], &v); + } + + { + let mut v = v.clone(); + v.remove_range(2..3); + assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &v); + } + + { + let mut v = v.clone(); + v.remove_range(0..2); + assert_deque_eq(&[&[8, 9, 10]], &v); + } + + { + let mut v = v.clone(); + v.remove_range(1..3); + assert_deque_eq(&[&[1, 2, 3]], &v); + } + + { + let mut v = v.clone(); + v.remove_range(0..3); + assert_deque_eq(&[], &v); + } +} + +// --- + +#[cfg(test)] +fn assert_deque_eq(expected: &[&'_ [i64]], got: &FlatVecDeque) { + similar_asserts::assert_eq!(expected, got.iter().collect_vec()); +} + +#[cfg(test)] +fn assert_iter_eq<'a>(expected: &[&'_ [i64]], got: impl Iterator) { + similar_asserts::assert_eq!(expected, got.collect_vec()); +} diff --git a/crates/re_query_cache2/src/latest_at/mod.rs b/crates/re_query_cache2/src/latest_at/mod.rs new file mode 100644 index 000000000000..30564eb5e2e0 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/mod.rs @@ -0,0 +1,5 @@ +mod query; +mod results; + +pub use self::query::LatestAtCache; +pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; diff --git a/crates/re_query_cache2/src/latest_at/query.rs b/crates/re_query_cache2/src/latest_at/query.rs new file mode 100644 index 000000000000..878dece4f81d --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/query.rs @@ -0,0 +1,265 @@ +use std::collections::BTreeSet; +use std::sync::atomic::AtomicU64; +use std::sync::atomic::Ordering::Relaxed; +use std::{collections::BTreeMap, sync::Arc}; + +use ahash::HashMap; + +use parking_lot::RwLock; +use re_data_store::{DataStore, LatestAtQuery, TimeInt}; +use re_log_types::EntityPath; +use re_query2::Promise; +use re_types_core::ComponentName; +use re_types_core::SizeBytes; + +use crate::{CacheKey, CachedLatestAtComponentResults, CachedLatestAtResults, Caches}; + +// --- + +impl Caches { + /// Queries for the given `component_names` using latest-at semantics. + /// + /// See [`CachedLatestAtResults`] for more information about how to handle the results. + /// + /// This is a cached API -- data will be lazily cached upon access. + pub fn latest_at( + &self, + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, + component_names: impl IntoIterator, + ) -> CachedLatestAtResults { + re_tracing::profile_function!(entity_path.to_string()); + + let mut results = CachedLatestAtResults::default(); + + for component_name in component_names { + let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); + let cache = Arc::clone( + self.per_cache_key + .write() + .entry(key.clone()) + .or_insert_with(|| Arc::new(RwLock::new(LatestAtCache::new(key.clone())))), + ); + + let mut cache = cache.write(); + cache.handle_pending_invalidation(); + if let Some(cached) = cache.latest_at(store, query, entity_path, component_name) { + results.add(component_name, cached); + } + } + + results + } +} + +// --- + +/// Caches the results of `LatestAt` queries for a given [`CacheKey`]. +pub struct LatestAtCache { + /// For debugging purposes. + pub cache_key: CacheKey, + + /// Organized by _query_ time. + /// + /// If the data you're looking for isn't in here, try partially running the query and check + /// if there is any data available for the resulting _data_ time in [`Self::per_data_time`]. + // + // NOTE: `Arc` so we can share buckets across query time & data time. + pub per_query_time: BTreeMap>, + + /// Organized by _data_ time. + /// + /// Due to how our latest-at semantics work, any number of queries at time `T+n` where `n >= 0` + /// can result in a data time of `T`. + // + // NOTE: `Arc` so we can share buckets across query time & data time. + pub per_data_time: BTreeMap>, + + /// These timestamps have been invalidated asynchronously. + /// + /// The next time this cache gets queried, it must remove any invalidated entries accordingly. + /// + /// Invalidation is deferred to query time because it is far more efficient that way: the frame + /// time effectively behaves as a natural micro-batching mechanism. + pub pending_invalidations: BTreeSet, +} + +impl LatestAtCache { + #[inline] + pub fn new(cache_key: CacheKey) -> Self { + Self { + cache_key, + per_query_time: Default::default(), + per_data_time: Default::default(), + pending_invalidations: Default::default(), + } + } +} + +impl std::fmt::Debug for LatestAtCache { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + cache_key, + per_query_time, + per_data_time, + pending_invalidations: _, + } = self; + + let mut strings = Vec::new(); + + let data_times_per_bucket: HashMap<_, _> = per_data_time + .iter() + .map(|(time, bucket)| (Arc::as_ptr(bucket), *time)) + .collect(); + + for (query_time, bucket) in per_query_time { + let query_time = cache_key.timeline.typ().format_utc(*query_time); + let data_time = data_times_per_bucket.get(&Arc::as_ptr(bucket)).map_or_else( + || "MISSING?!".to_owned(), + |t| cache_key.timeline.typ().format_utc(*t), + ); + strings.push(format!( + "query_time={query_time} -> data_time={data_time} ({})", + re_format::format_bytes(bucket.cached_heap_size_bytes.load(Relaxed) as _), + )); + strings.push(indent::indent_all_by(2, format!("{bucket:?}"))); + } + + if strings.is_empty() { + return f.write_str(""); + } + + f.write_str(&strings.join("\n").replace("\n\n", "\n")) + } +} + +impl SizeBytes for LatestAtCache { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self { + cache_key: _, + per_query_time, + per_data_time, + pending_invalidations, + } = self; + + let per_query_time = per_query_time + .keys() + .map(|k| k.total_size_bytes()) + .sum::(); + let per_data_time = per_data_time.total_size_bytes(); + let pending_invalidations = pending_invalidations.total_size_bytes(); + + per_query_time + per_data_time + pending_invalidations + } +} + +impl LatestAtCache { + /// Queries cached latest-at data for a single component. + pub fn latest_at( + &mut self, + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, + component_name: ComponentName, + ) -> Option> { + re_tracing::profile_scope!("latest_at", format!("{query:?}")); + + let LatestAtCache { + cache_key: _, + per_query_time, + per_data_time, + pending_invalidations: _, + } = self; + + let query_time_bucket_at_query_time = match per_query_time.entry(query.at()) { + std::collections::btree_map::Entry::Occupied(entry) => { + // Fastest path: we have an entry for this exact query time, no need to look any + // further. + re_log::trace!(query_time=?query.at(), "cache hit (query time)"); + return Some(Arc::clone(entry.get())); + } + std::collections::btree_map::Entry::Vacant(entry) => entry, + }; + + let result = store.latest_at(query, entity_path, component_name, &[component_name]); + + // NOTE: cannot `result.and_then(...)` or borrowck gets lost. + if let Some((data_time, row_id, mut cells)) = result { + // Fast path: we've run the query and realized that we already have the data for the resulting + // _data_ time, so let's use that to avoid join & deserialization costs. + if let Some(data_time_bucket_at_data_time) = per_data_time.get(&data_time) { + re_log::trace!(query_time=?query.at(), ?data_time, "cache hit (data time)"); + + query_time_bucket_at_query_time.insert(Arc::clone(data_time_bucket_at_data_time)); + + // We now know for a fact that a query at that data time would yield the same + // results: copy the bucket accordingly so that the next cache hit for that query + // time ends up taking the fastest path. + let query_time_bucket_at_data_time = per_query_time.entry(data_time); + query_time_bucket_at_data_time + .and_modify(|v| *v = Arc::clone(data_time_bucket_at_data_time)) + .or_insert(Arc::clone(data_time_bucket_at_data_time)); + + return Some(Arc::clone(data_time_bucket_at_data_time)); + } + + // Soundness: + // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` + // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null + let Some(cell) = cells[0].take() else { + debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); + return None; + }; + + let bucket = Arc::new(CachedLatestAtComponentResults { + index: (data_time, row_id), + promise: Some(Promise::new(cell)), + cached_dense: Default::default(), + cached_sparse: Default::default(), + cached_heap_size_bytes: AtomicU64::new(0), + }); + + // Slowest path: this is a complete cache miss. + { + re_log::trace!(query_time=?query.at(), ?data_time, "cache miss"); + + let query_time_bucket_at_query_time = + query_time_bucket_at_query_time.insert(Arc::clone(&bucket)); + + let data_time_bucket_at_data_time = per_data_time.entry(data_time); + data_time_bucket_at_data_time + .and_modify(|v| *v = Arc::clone(query_time_bucket_at_query_time)) + .or_insert(Arc::clone(query_time_bucket_at_query_time)); + } + + Some(bucket) + } else { + None + } + } + + pub fn handle_pending_invalidation(&mut self) { + let Self { + cache_key: _, + per_query_time, + per_data_time, + pending_invalidations, + } = self; + + let pending_invalidations = std::mem::take(pending_invalidations); + + // First, remove any data indexed by a _query time_ that's more recent than the oldest + // _data time_ that's been invalidated. + // + // Note that this data time might very well be `TimeInt::STATIC`, in which case the entire + // query-time-based index will be dropped. + if let Some(&oldest_data_time) = pending_invalidations.first() { + per_query_time.retain(|&query_time, _| query_time < oldest_data_time); + } + + // Second, remove any data indexed by _data time_, if it's been invalidated. + per_data_time.retain(|data_time, _| !pending_invalidations.contains(data_time)); + } +} diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs new file mode 100644 index 000000000000..0028adcf41f5 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -0,0 +1,343 @@ +use std::sync::{ + atomic::{AtomicU64, Ordering::Relaxed}, + Arc, OnceLock, +}; + +use nohash_hasher::IntMap; + +use re_log_types::{DataCell, RowId, TimeInt}; +use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; + +use crate::{ + ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, PromiseResult, QueryError, +}; + +// --- + +/// Cached results for a latest-at query. +/// +/// The data is both deserialized and resolved/converted. +/// +/// Use [`CachedLatestAtResults::get`], [`CachedLatestAtResults::get_required`] and +/// [`CachedLatestAtResults::get_or_empty`] in order to access the results for each individual component. +#[derive(Debug)] +pub struct CachedLatestAtResults { + /// The compound index of this query result. + /// + /// A latest-at query is a compound operation that gathers data from many different rows. + /// The index of that compound result corresponds to the index of most the recent row in all the + /// sub-results, as defined by time and row-id order. + pub compound_index: (TimeInt, RowId), + + /// Results for each individual component. + pub components: IntMap>, +} + +impl Default for CachedLatestAtResults { + #[inline] + fn default() -> Self { + Self { + compound_index: (TimeInt::STATIC, RowId::ZERO), + components: Default::default(), + } + } +} + +impl CachedLatestAtResults { + #[inline] + pub fn contains(&self, component_name: impl Into) -> bool { + self.components.contains_key(&component_name.into()) + } + + /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + #[inline] + pub fn get(&self) -> Option<&CachedLatestAtComponentResults> { + self.components.get(&C::name()).map(|arc| &**arc) + } + + /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// + /// Returns an error if the component is not present. + #[inline] + pub fn get_required(&self) -> crate::Result<&CachedLatestAtComponentResults> { + if let Some(component) = self.components.get(&C::name()) { + Ok(component) + } else { + Err(DeserializationError::MissingComponent { + component: C::name(), + backtrace: ::backtrace::Backtrace::new_unresolved(), + } + .into()) + } + } + + /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// + /// Returns empty results if the component is not present. + #[inline] + pub fn get_or_empty(&self) -> &CachedLatestAtComponentResults { + if let Some(component) = self.components.get(&C::name()) { + component + } else { + static EMPTY: CachedLatestAtComponentResults = CachedLatestAtComponentResults::empty(); + &EMPTY + } + } +} + +impl CachedLatestAtResults { + #[doc(hidden)] + #[inline] + pub fn add( + &mut self, + component_name: ComponentName, + cached: Arc, + ) { + // NOTE: Since this is a compound API that actually emits multiple queries, the index of the + // final result is the most recent index among all of its components, as defined by time + // and row-id order. + // + // TODO(#5303): We have to ignore the cluster key in this piece of logic for backwards compatibility + // reasons with the legacy instance-key model. This will go away next. + use re_types_core::Loggable as _; + if component_name != re_types_core::components::InstanceKey::name() + && cached.index > self.compound_index + { + self.compound_index = cached.index; + } + + self.components.insert(component_name, cached); + } +} + +// --- + +/// Lazily cached results for a particular component when using a cached latest-at query. +pub struct CachedLatestAtComponentResults { + pub(crate) index: (TimeInt, RowId), + + // Option so we can have a constant default value for `Self`. + pub(crate) promise: Option, + + /// The resolved, converted, deserialized dense data. + pub(crate) cached_dense: OnceLock>, + + /// The resolved, converted, deserialized sparse data. + pub(crate) cached_sparse: OnceLock>, + + pub(crate) cached_heap_size_bytes: AtomicU64, +} + +impl CachedLatestAtComponentResults { + #[inline] + pub const fn empty() -> Self { + Self { + index: (TimeInt::STATIC, RowId::ZERO), + promise: None, + cached_dense: OnceLock::new(), + cached_sparse: OnceLock::new(), + cached_heap_size_bytes: AtomicU64::new(0), + } + } +} + +impl SizeBytes for CachedLatestAtComponentResults { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.cached_heap_size_bytes.load(Relaxed) + } +} + +impl std::fmt::Debug for CachedLatestAtComponentResults { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + index, + promise: _, + cached_dense: _, // we can't, we don't know the type + cached_sparse: _, // we can't, we don't know the type + cached_heap_size_bytes, + } = self; + + f.write_fmt(format_args!( + "[{:?}#{}] {}", + index.0, + index.1, + re_format::format_bytes(cached_heap_size_bytes.load(Relaxed) as _) + )) + } +} + +impl CachedLatestAtComponentResults { + #[inline] + pub fn index(&self) -> &(TimeInt, RowId) { + &self.index + } + + /// Returns the component data as a dense vector. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn to_dense( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + if let Some(cell) = self.promise.as_ref() { + resolver + .resolve(cell) + .map(|cell| self.downcast_dense::(&cell)) + } else { + // Manufactured empty result. + PromiseResult::Ready(Ok(&[])) + } + } + + /// Iterates over the component data, assuming it is dense. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn iter_dense( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult>> { + self.to_dense(resolver) + .map(|data| data.map(|data| data.iter())) + } + + /// Returns the component data as a sparse vector. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn to_sparse( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult]>> { + if let Some(cell) = self.promise.as_ref() { + resolver + .resolve(cell) + .map(|cell| self.downcast_sparse::(&cell)) + } else { + // Manufactured empty result. + PromiseResult::Ready(Ok(&[])) + } + } + + /// Iterates over the component data, assuming it is sparse. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn iter_sparse( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult>>> { + self.to_sparse(resolver) + .map(|data| data.map(|data| data.iter().map(Option::as_ref))) + } +} + +impl CachedLatestAtComponentResults { + fn downcast_dense( + &self, + cell: &DataCell, + ) -> crate::Result<&[C]> { + // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the + // data has already been computed. + // + // See next comment as to why we need this. + if let Some(cached) = self.cached_dense.get() { + return downcast(&**cached); + } + + // We have to do this outside of the callback in order to propagate errors. + // Hence the early exit check above. + let data = cell + .try_to_native::() + .map_err(|err| DeserializationError::DataCellError(err.to_string()))?; + + #[allow(clippy::borrowed_box)] + let cached: &Box = + self.cached_dense.get_or_init(move || { + self.cached_heap_size_bytes + .fetch_add(data.total_size_bytes(), Relaxed); + Box::new(FlatVecDeque::from(data)) + }); + + downcast(&**cached) + } + + fn downcast_sparse( + &self, + cell: &DataCell, + ) -> crate::Result<&[Option]> { + // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the + // data has already been computed. + // + // See next comment as to why we need this. + if let Some(cached) = self.cached_sparse.get() { + return downcast_opt(&**cached); + } + + // We have to do this outside of the callback in order to propagate errors. + // Hence the early exit check above. + let data = cell + .try_to_native_opt::() + .map_err(|err| DeserializationError::DataCellError(err.to_string()))?; + + #[allow(clippy::borrowed_box)] + let cached: &Box = + self.cached_sparse.get_or_init(move || { + self.cached_heap_size_bytes + .fetch_add(data.total_size_bytes(), Relaxed); + Box::new(FlatVecDeque::from(data)) + }); + + downcast_opt(&**cached) + } +} + +fn downcast( + cached: &(dyn ErasedFlatVecDeque + Send + Sync), +) -> crate::Result<&[C]> { + let cached = cached + .as_any() + .downcast_ref::>() + .ok_or_else(|| QueryError::TypeMismatch { + actual: "".into(), + requested: C::name(), + })?; + + if cached.num_entries() != 1 { + return Err(anyhow::anyhow!("latest_at deque must be single entry").into()); + } + // unwrap checked just above ^^^ + Ok(cached.iter().next().unwrap()) +} + +fn downcast_opt( + cached: &(dyn ErasedFlatVecDeque + Send + Sync), +) -> crate::Result<&[Option]> { + let cached = cached + .as_any() + .downcast_ref::>>() + .ok_or_else(|| QueryError::TypeMismatch { + actual: "".into(), + requested: C::name(), + })?; + + if cached.num_entries() != 1 { + return Err(anyhow::anyhow!("latest_at deque must be single entry").into()); + } + // unwrap checked just above ^^^ + Ok(cached.iter().next().unwrap()) +} diff --git a/crates/re_query_cache2/src/lib.rs b/crates/re_query_cache2/src/lib.rs new file mode 100644 index 000000000000..2162bc333b95 --- /dev/null +++ b/crates/re_query_cache2/src/lib.rs @@ -0,0 +1,22 @@ +//! Caching datastructures for `re_query`. + +mod cache; +mod flat_vec_deque; +mod latest_at; + +pub use self::cache::{CacheKey, Caches}; +pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; +pub use self::latest_at::{CachedLatestAtComponentResults, CachedLatestAtResults}; + +pub(crate) use self::latest_at::LatestAtCache; + +pub use re_query2::{ + clamped_zip::*, Promise, PromiseId, PromiseResolver, PromiseResult, QueryError, Result, +}; + +pub mod external { + pub use re_query2; + + pub use paste; + pub use seq_macro; +} diff --git a/crates/re_query_cache2/tests/latest_at.rs b/crates/re_query_cache2/tests/latest_at.rs new file mode 100644 index 000000000000..b87b1bb02da6 --- /dev/null +++ b/crates/re_query_cache2/tests/latest_at.rs @@ -0,0 +1,526 @@ +//! Contains: +//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_query_tests.rs`, with caching enabled. +//! - Invalidation tests. + +use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; +use re_log_types::{ + build_frame_nr, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimePoint, +}; +use re_query2::PromiseResolver; +use re_query_cache2::Caches; +use re_types::Archetype as _; +use re_types_core::{components::InstanceKey, Loggable as _}; + +// --- + +#[test] +fn simple_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + // Create some positions with implicit instances + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + // Assign one of them a color with an explicit instance + let color_instances = vec![InstanceKey(1)]; + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + timepoint, + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +#[test] +fn static_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + // Create some positions with implicit instances + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + // Assign one of them a color with an explicit instance.. statically! + let color_instances = vec![InstanceKey(1)]; + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + TimePoint::default(), + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +#[test] +fn no_instance_join_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + // Create some positions with an implicit instance + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + // Assign them colors with explicit instances + let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +#[test] +fn missing_column_join_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + // Create some positions with an implicit instance + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +#[test] +fn splatted_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + // Create some positions with implicit instances + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + // Assign all of them a color via splat + let color_instances = vec![InstanceKey::SPLAT]; + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + timepoint, + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +#[test] +fn invalidation_xxx() { + let entity_path = "point"; + + let test_invalidation = |query: LatestAtQuery, + present_data_timepoint: TimePoint, + past_data_timepoint: TimePoint, + future_data_timepoint: TimePoint| { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + // Create some positions with implicit instances + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + positions, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + // Assign one of them a color with an explicit instance + let color_instances = vec![InstanceKey(1)]; + let colors = vec![MyColor::from_rgb(1, 2, 3)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // --- Modify present --- + + // Modify the PoV component + let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + positions, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint, + 2, + colors, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // --- Modify past --- + + // Modify the PoV component + let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + positions, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, past_data_timepoint, 2, colors) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // --- Modify future --- + + // Modify the PoV component + let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint.clone(), + 2, + positions, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(16, 17, 18)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + }; + + let timeless = TimePoint::default(); + let frame_122 = build_frame_nr(122); + let frame_123 = build_frame_nr(123); + let frame_124 = build_frame_nr(124); + + test_invalidation( + LatestAtQuery::new(frame_123.0, frame_123.1), + [frame_123].into(), + [frame_122].into(), + [frame_124].into(), + ); + + test_invalidation( + LatestAtQuery::new(frame_123.0, frame_123.1), + [frame_123].into(), + timeless, + [frame_124].into(), + ); +} + +// Test the following scenario: +// ```py +// rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// +// # Do first query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[] +// +// rr.set_time(2) +// rr.log_components("points", rr.components.MyColor(0xFF0000)) +// +// # Do second query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0xFF0000] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x0000FF)) +// +// # Do third query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x0000FF] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x00FF00)) +// +// # Do fourth query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x00FF00] +// ``` +#[test] +fn invalidation_of_future_optionals() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + let frame2 = [build_frame_nr(2)]; + let frame3 = [build_frame_nr(3)]; + + let query_time = [build_frame_nr(9999)]; + + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let color_instances = vec![InstanceKey::SPLAT]; + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + frame2, + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let color_instances = vec![InstanceKey::SPLAT]; + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + frame3, + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let color_instances = vec![InstanceKey::SPLAT]; + let colors = vec![MyColor::from_rgb(0, 255, 0)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + frame3, + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +#[test] +fn static_invalidation() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + + let query_time = [build_frame_nr(9999)]; + + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let color_instances = vec![InstanceKey::SPLAT]; + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + timeless.clone(), + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let color_instances = vec![InstanceKey::SPLAT]; + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path, + timeless, + 1, + (color_instances, colors), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +// --- + +fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { + caches.on_events(&[store.insert_row(row).unwrap()]); +} + +fn query_and_compare( + caches: &Caches, + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, +) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + + for _ in 0..3 { + let cached = caches.latest_at( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_points = cached.get_required::().unwrap(); + let cached_point_data = cached_points + .to_dense::(&resolver) + .flatten() + .unwrap(); + + let cached_colors = cached.get_or_empty::(); + let cached_color_data = cached_colors + .to_sparse::(&resolver) + .flatten() + .unwrap(); + + let expected = re_query2::latest_at( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let expected_points = expected.get_required::().unwrap(); + let expected_point_data = expected_points + .to_dense::(&resolver) + .flatten() + .unwrap(); + + let expected_colors = expected.get_or_empty::(); + let expected_color_data = expected_colors + .to_sparse::(&resolver) + .flatten() + .unwrap(); + + // eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!(expected.compound_index, cached.compound_index); + similar_asserts::assert_eq!(expected_point_data, cached_point_data); + similar_asserts::assert_eq!(expected_color_data, cached_color_data); + } +} diff --git a/crates/re_types_core/src/size_bytes.rs b/crates/re_types_core/src/size_bytes.rs index 49bedcff98d6..1974faf444fe 100644 --- a/crates/re_types_core/src/size_bytes.rs +++ b/crates/re_types_core/src/size_bytes.rs @@ -1,4 +1,4 @@ -use std::collections::{BTreeMap, HashMap, VecDeque}; +use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque}; use std::sync::Arc; use arrow2::datatypes::{DataType, Field}; @@ -70,6 +70,19 @@ impl SizeBytes for BTreeMap { } } +impl SizeBytes for BTreeSet { + #[inline] + fn heap_size_bytes(&self) -> u64 { + // NOTE: It's all on the heap at this point. + + if K::is_pod() { + (self.len() * std::mem::size_of::()) as _ + } else { + self.iter().map(SizeBytes::total_size_bytes).sum::() + } + } +} + impl SizeBytes for HashMap { #[inline] fn heap_size_bytes(&self) -> u64 { From 793c8223665d2bd1b81e0352e76eef319b827699 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 14:38:07 +0200 Subject: [PATCH 221/508] New data APIs 3: Send/Sync/'static `Component`, once and for all (#5605) A trivial PR that essentially just does this: ```diff - pub trait Loggable: Clone + Sized + SizeBytes { + pub trait Loggable: 'static + Send + Sync + Clone + Sized + SizeBytes { ``` because im very tired of carrying these clauses around manually everywhere. --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- crates/re_query_cache/src/cache.rs | 28 ++++++++----------- crates/re_query_cache/src/latest_at.rs | 4 +-- crates/re_query_cache/src/query.rs | 12 ++++---- crates/re_query_cache/src/range.rs | 8 +++--- .../re_query_cache2/src/latest_at/results.rs | 24 ++++++---------- .../src/visualizers/entity_iterator.rs | 4 +-- crates/re_types_core/src/loggable.rs | 2 +- 7 files changed, 34 insertions(+), 48 deletions(-) diff --git a/crates/re_query_cache/src/cache.rs b/crates/re_query_cache/src/cache.rs index 16442e15dfe2..6b03a1b2fe5e 100644 --- a/crates/re_query_cache/src/cache.rs +++ b/crates/re_query_cache/src/cache.rs @@ -734,9 +734,7 @@ impl CacheBucket { /// Iterate over the batches of the specified non-optional component. #[inline] - pub fn iter_component( - &self, - ) -> Option> { + pub fn iter_component(&self) -> Option> { let data = self .components .get(&C::name()) @@ -746,9 +744,7 @@ impl CacheBucket { /// Iterate over the batches of the specified optional component. #[inline] - pub fn iter_component_opt( - &self, - ) -> Option]>> { + pub fn iter_component_opt(&self) -> Option]>> { let data = self .components .get(&C::name()) @@ -823,7 +819,7 @@ impl CacheBucket { /// Get the raw batches for the specified non-optional component. #[inline] - pub fn component(&self) -> Option<&FlatVecDeque> { + pub fn component(&self) -> Option<&FlatVecDeque> { self.components .get(&C::name()) .and_then(|data| data.as_any().downcast_ref::>()) @@ -831,7 +827,7 @@ impl CacheBucket { /// Range over the batches of the specified non-optional component. #[inline] - pub fn range_component( + pub fn range_component( &self, entry_range: Range, ) -> Option> { @@ -844,9 +840,7 @@ impl CacheBucket { /// Get the raw batches for the specified optional component. #[inline] - pub fn component_opt( - &self, - ) -> Option<&FlatVecDeque>> { + pub fn component_opt(&self) -> Option<&FlatVecDeque>> { self.components .get(&C::name()) .and_then(|data| data.as_any().downcast_ref::>>()) @@ -854,7 +848,7 @@ impl CacheBucket { /// Range over the batches of the specified optional component. #[inline] - pub fn range_component_opt( + pub fn range_component_opt( &self, entry_range: Range, ) -> Option]>> { @@ -934,8 +928,8 @@ macro_rules! impl_insert { ) -> ::re_query::Result where A: Archetype, - $($pov: Component + Send + Sync + 'static,)+ - $($comp: Component + Send + Sync + 'static,)* + $($pov: Component,)+ + $($comp: Component,)* { // NOTE: not `profile_function!` because we want them merged together. re_tracing::profile_scope!("CacheBucket::insert", format!("arch={} pov={} comp={}", A::name(), $N, $M)); @@ -992,7 +986,7 @@ impl CacheBucket { ) -> ::re_query::Result where A: Archetype, - R1: Component + Send + Sync + 'static, + R1: Component, { self.insert_pov1_comp0::(query_time, arch_view) } @@ -1002,7 +996,7 @@ impl CacheBucket { }); #[inline] - fn insert_component( + fn insert_component( &mut self, at: usize, arch_view: &ArchetypeView, @@ -1041,7 +1035,7 @@ impl CacheBucket { /// This will insert an empty slice for a missing component (instead of N `None` values). #[inline] - fn insert_component_opt( + fn insert_component_opt( &mut self, at: usize, arch_view: &ArchetypeView, diff --git a/crates/re_query_cache/src/latest_at.rs b/crates/re_query_cache/src/latest_at.rs index c446fb3b8e37..4804b513801d 100644 --- a/crates/re_query_cache/src/latest_at.rs +++ b/crates/re_query_cache/src/latest_at.rs @@ -145,8 +145,8 @@ macro_rules! impl_query_archetype_latest_at { ) -> ::re_query::Result<()> where A: Archetype + 'a, - $($pov: Component + Send + Sync + 'static,)+ - $($comp: Component + Send + Sync + 'static,)* + $($pov: Component,)+ + $($comp: Component,)* F: FnMut( ( (TimeInt, RowId), diff --git a/crates/re_query_cache/src/query.rs b/crates/re_query_cache/src/query.rs index cace18c9041c..50e4036bff32 100644 --- a/crates/re_query_cache/src/query.rs +++ b/crates/re_query_cache/src/query.rs @@ -39,7 +39,7 @@ impl Caches { ) -> ::re_query::Result<()> where A: Archetype + 'a, - R1: Component + Send + Sync + 'static, + R1: Component, F: FnMut(((TimeInt, RowId), &[InstanceKey], &[R1])), { self.query_archetype_pov1_comp0::(store, query, entity_path, f) @@ -60,8 +60,8 @@ macro_rules! impl_query_archetype { ) -> ::re_query::Result<()> where A: Archetype + 'a, - $($pov: Component + Send + Sync + 'static,)+ - $($comp: Component + Send + Sync + 'static,)* + $($pov: Component,)+ + $($comp: Component,)* F: FnMut( ( (TimeInt, RowId), @@ -159,7 +159,7 @@ impl Caches { ) -> ::re_query::Result<()> where A: Archetype + 'a, - R1: Component + Send + Sync + 'static, + R1: Component, F: FnMut(((TimeInt, RowId), &[InstanceKey], &[R1])), { self.query_archetype_with_history_pov1_comp0::( @@ -186,8 +186,8 @@ macro_rules! impl_query_archetype_with_history { ) -> ::re_query::Result<()> where A: Archetype + 'a, - $($pov: Component + Send + Sync + 'static,)+ - $($comp: Component + Send + Sync + 'static,)* + $($pov: Component,)+ + $($comp: Component,)* F: FnMut( ( (TimeInt, RowId), diff --git a/crates/re_query_cache/src/range.rs b/crates/re_query_cache/src/range.rs index 2a44304d8d6b..39ffcc07fd91 100644 --- a/crates/re_query_cache/src/range.rs +++ b/crates/re_query_cache/src/range.rs @@ -165,8 +165,8 @@ macro_rules! impl_query_archetype_range { ) -> ::re_query::Result<()> where A: Archetype + 'a, - $($pov: Component + Send + Sync + 'static,)+ - $($comp: Component + Send + Sync + 'static,)* + $($pov: Component,)+ + $($comp: Component,)* F: FnMut( std::ops::Range, ( @@ -218,8 +218,8 @@ macro_rules! impl_query_archetype_range { ) -> crate::Result where A: Archetype + 'a, - $($pov: Component + Send + Sync + 'static,)+ - $($comp: Component + Send + Sync + 'static,)* + $($pov: Component,)+ + $($comp: Component,)* { re_tracing::profile_scope!("fill"); diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index 0028adcf41f5..3355be18c032 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -180,7 +180,7 @@ impl CachedLatestAtComponentResults { /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of /// deserializing the data into a single one, if you don't need the extra flexibility. #[inline] - pub fn to_dense( + pub fn to_dense( &self, resolver: &PromiseResolver, ) -> PromiseResult> { @@ -201,7 +201,7 @@ impl CachedLatestAtComponentResults { /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of /// deserializing the data into a single one, if you don't need the extra flexibility. #[inline] - pub fn iter_dense( + pub fn iter_dense( &self, resolver: &PromiseResolver, ) -> PromiseResult>> { @@ -216,7 +216,7 @@ impl CachedLatestAtComponentResults { /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of /// deserializing the data into a single one, if you don't need the extra flexibility. #[inline] - pub fn to_sparse( + pub fn to_sparse( &self, resolver: &PromiseResolver, ) -> PromiseResult]>> { @@ -237,7 +237,7 @@ impl CachedLatestAtComponentResults { /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of /// deserializing the data into a single one, if you don't need the extra flexibility. #[inline] - pub fn iter_sparse( + pub fn iter_sparse( &self, resolver: &PromiseResolver, ) -> PromiseResult>>> { @@ -247,10 +247,7 @@ impl CachedLatestAtComponentResults { } impl CachedLatestAtComponentResults { - fn downcast_dense( - &self, - cell: &DataCell, - ) -> crate::Result<&[C]> { + fn downcast_dense(&self, cell: &DataCell) -> crate::Result<&[C]> { // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the // data has already been computed. // @@ -276,10 +273,7 @@ impl CachedLatestAtComponentResults { downcast(&**cached) } - fn downcast_sparse( - &self, - cell: &DataCell, - ) -> crate::Result<&[Option]> { + fn downcast_sparse(&self, cell: &DataCell) -> crate::Result<&[Option]> { // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the // data has already been computed. // @@ -306,9 +300,7 @@ impl CachedLatestAtComponentResults { } } -fn downcast( - cached: &(dyn ErasedFlatVecDeque + Send + Sync), -) -> crate::Result<&[C]> { +fn downcast(cached: &(dyn ErasedFlatVecDeque + Send + Sync)) -> crate::Result<&[C]> { let cached = cached .as_any() .downcast_ref::>() @@ -324,7 +316,7 @@ fn downcast( Ok(cached.iter().next().unwrap()) } -fn downcast_opt( +fn downcast_opt( cached: &(dyn ErasedFlatVecDeque + Send + Sync), ) -> crate::Result<&[Option]> { let cached = cached diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 7ad1205b334b..746f7fa2a313 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -130,8 +130,8 @@ macro_rules! impl_process_archetype { where S: IdentifiedViewSystem, A: Archetype + 'a, - $($pov: Component + Send + Sync + 'static,)+ - $($comp: Component + Send + Sync + 'static,)* + $($pov: Component,)+ + $($comp: Component,)* F: FnMut( &ViewerContext<'_>, &EntityPath, diff --git a/crates/re_types_core/src/loggable.rs b/crates/re_types_core/src/loggable.rs index 899cf522af64..b7c1b7758144 100644 --- a/crates/re_types_core/src/loggable.rs +++ b/crates/re_types_core/src/loggable.rs @@ -21,7 +21,7 @@ use crate::{Archetype, ComponentBatch, DatatypeBatch, LoggableBatch}; /// automatically derives the [`LoggableBatch`] implementation (and by extension /// [`DatatypeBatch`]/[`ComponentBatch`]), which makes it possible to work with lists' worth of data /// in a generic fashion. -pub trait Loggable: Clone + Sized + SizeBytes { +pub trait Loggable: 'static + Send + Sync + Clone + Sized + SizeBytes { type Name: std::fmt::Display; /// The fully-qualified name of this loggable, e.g. `rerun.datatypes.Vec2D`. From efca999bcd731ff576f2ea0dfc0ee568fdbb0c5e Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:38:20 +0200 Subject: [PATCH 222/508] Do not show the remove button when the origin is empty (#5840) ### What - Closes https://github.com/rerun-io/rerun/issues/5835 image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5840) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5840?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5840?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5840) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../re_viewport/src/viewport_blueprint_ui.rs | 53 +++++++++---------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 507326724fae..aa57a27e67b1 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -573,40 +573,38 @@ impl Viewport<'_, '_> { let subdued = !space_view_visible || !visible; - let list_item = ListItem::new(ctx.re_ui, item_label) + let mut list_item = ListItem::new(ctx.re_ui, item_label) .selected(is_selected) .with_icon(guess_instance_path_icon( ctx, &InstancePath::from(entity_path.clone()), )) .subdued(subdued) - .force_hovered(is_item_hovered) - .with_buttons(|re_ui: &_, ui: &mut egui::Ui| { - let vis_response = if !empty_origin { - let mut visible_after = visible; - let vis_response = - visibility_button_ui(re_ui, ui, space_view_visible, &mut visible_after); - if visible_after != visible { - if let Some(data_result_node) = data_result_node { - data_result_node - .data_result - .save_recursive_override_or_clear_if_redundant( - ctx, - &query_result.tree, - &Visible(visible_after), - ); - } + .force_hovered(is_item_hovered); + + // We force the origin to be displayed, even if it's fully empty, in which case it can be + // neither shown/hidden nor removed. + if !empty_origin { + list_item = list_item.with_buttons(|re_ui: &_, ui: &mut egui::Ui| { + let mut visible_after = visible; + let vis_response = + visibility_button_ui(re_ui, ui, space_view_visible, &mut visible_after); + if visible_after != visible { + if let Some(data_result_node) = data_result_node { + data_result_node + .data_result + .save_recursive_override_or_clear_if_redundant( + ctx, + &query_result.tree, + &Visible(visible_after), + ); } + } - Some(vis_response) - } else { - None - }; - - let mut response = remove_button_ui( + let response = remove_button_ui( re_ui, ui, - "Remove group and all its children from the space view", + "Remove this entity and all its children from the space view", ); if response.clicked() { space_view @@ -614,12 +612,9 @@ impl Viewport<'_, '_> { .remove_subtree_and_matching_rules(ctx, entity_path.clone()); } - if let Some(vis_response) = vis_response { - response |= vis_response; - } - - response + response | vis_response }); + } // If there's any children on the data result nodes, show them, otherwise we're good with this list item as is. let has_children = data_result_node.map_or(false, |n| !n.children.is_empty()); From 0b300fbcc03d62a22857cef3659138e3bb74ce30 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 14:38:54 +0200 Subject: [PATCH 223/508] New data APIs 4: cached latest-at mono helpers everywhere (#5606) Now that we have a component-based latest-at cache, we can start replacing legacy uncached helpers with new ones. Commit-by-commit review should be trivial. Because the new APIs are designed with promises in mind, this already highlights a whole bunch of places where we need to think about what to do in case the data is not ready yet. As indicated in #5607, these places have been labeled `TODO(#5607)` in the code. For now, we simply treat a pending promise the same as missing data. This PR also adds the new `Caches` and `PromiseResolver` to the `EntityDb`. To run a cached query, you now need a `DataStore`, a `Caches` and a `PromiseResolver`, i.e. you need an `EntityDb`. --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- Cargo.lock | 3 + crates/re_data_store/src/lib.rs | 1 - crates/re_data_store/src/store_helpers.rs | 206 +--------------- crates/re_data_store/tests/correctness.rs | 37 ++- crates/re_data_ui/src/annotation_context.rs | 7 +- crates/re_data_ui/src/image.rs | 12 +- crates/re_data_ui/src/item_ui.rs | 14 +- crates/re_entity_db/Cargo.toml | 2 + .../entity_properties_component_ext.rs | 5 - crates/re_entity_db/src/entity_db.rs | 67 ++++++ crates/re_entity_db/src/lib.rs | 2 + crates/re_entity_db/tests/clear.rs | 222 ++++++++---------- crates/re_error/src/lib.rs | 21 +- crates/re_query/src/query.rs | 2 +- crates/re_query2/src/promise.rs | 27 ++- crates/re_query_cache2/Cargo.toml | 1 + .../re_query_cache2/src/latest_at/helpers.rs | 170 ++++++++++++++ crates/re_query_cache2/src/latest_at/mod.rs | 2 + crates/re_query_cache2/src/lib.rs | 4 +- crates/re_space_view/src/lib.rs | 4 + crates/re_space_view/src/space_view.rs | 4 +- .../re_space_view/src/space_view_contents.rs | 14 +- .../src/visualizer_system.rs | 24 +- .../src/contexts/depth_offsets.rs | 9 +- .../re_space_view_spatial/src/heuristics.rs | 30 +-- crates/re_space_view_spatial/src/lib.rs | 24 +- .../src/space_view_3d.rs | 5 +- crates/re_space_view_spatial/src/ui.rs | 78 +++--- crates/re_space_view_spatial/src/ui_2d.rs | 3 +- crates/re_space_view_spatial/src/ui_3d.rs | 5 +- .../src/visualizers/cameras.rs | 13 +- .../src/visualizers/images.rs | 8 +- .../src/visualizer_system.rs | 18 +- .../src/line_visualizer_system.rs | 5 +- .../src/point_visualizer_system.rs | 5 +- crates/re_viewer/src/app_blueprint.rs | 4 +- crates/re_viewer/src/ui/selection_panel.rs | 72 ++++-- .../src/space_view/view_query.rs | 17 +- 38 files changed, 620 insertions(+), 527 deletions(-) create mode 100644 crates/re_query_cache2/src/latest_at/helpers.rs diff --git a/Cargo.lock b/Cargo.lock index a9b9560d95b1..eab6fd468f22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4379,7 +4379,9 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_query", + "re_query2", "re_query_cache", + "re_query_cache2", "re_smart_channel", "re_tracing", "re_types", @@ -4614,6 +4616,7 @@ dependencies = [ "paste", "rand", "re_data_store", + "re_error", "re_format", "re_log", "re_log_types", diff --git a/crates/re_data_store/src/lib.rs b/crates/re_data_store/src/lib.rs index 59bcdc1912c9..07227c54a0f1 100644 --- a/crates/re_data_store/src/lib.rs +++ b/crates/re_data_store/src/lib.rs @@ -35,7 +35,6 @@ pub use self::arrow_util::ArrayExt; pub use self::store::{DataStore, DataStoreConfig, StoreGeneration}; pub use self::store_event::{StoreDiff, StoreDiffKind, StoreEvent}; pub use self::store_gc::{GarbageCollectionOptions, GarbageCollectionTarget}; -pub use self::store_helpers::VersionedComponent; pub use self::store_read::{LatestAtQuery, RangeQuery}; pub use self::store_stats::{DataStoreRowStats, DataStoreStats, EntityStats}; pub use self::store_subscriber::{StoreSubscriber, StoreSubscriberHandle}; diff --git a/crates/re_data_store/src/store_helpers.rs b/crates/re_data_store/src/store_helpers.rs index ed57b759a8a7..d8f07b842cd1 100644 --- a/crates/re_data_store/src/store_helpers.rs +++ b/crates/re_data_store/src/store_helpers.rs @@ -1,209 +1,7 @@ -use re_log_types::{DataCell, DataRow, EntityPath, RowId, TimeInt, TimePoint, Timeline}; - +use re_log_types::{DataCell, DataRow, EntityPath, RowId, TimePoint}; use re_types_core::{Component, ComponentName}; -use crate::{DataStore, LatestAtQuery}; - -// --- Read --- - -// TODO(cmc): these helpers have got to go once the new APIs land. - -/// A [`Component`] at a specific _data_ time, versioned with a specific [`RowId`]. -/// -/// This is not enough to globally, uniquely identify an instance of a component. -/// For that you will need to combine the `InstancePath` that was used to query -/// the versioned component with the returned [`RowId`], therefore creating a -/// `VersionedInstancePath`. -#[derive(Debug, Clone)] -pub struct VersionedComponent { - pub data_time: TimeInt, - pub row_id: RowId, - pub value: C, -} - -impl VersionedComponent { - #[inline] - pub fn new(data_time: TimeInt, row_id: RowId, value: C) -> Self { - Self { - data_time, - row_id, - value, - } - } -} - -impl std::ops::Deref for VersionedComponent { - type Target = C; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.value - } -} - -impl DataStore { - /// Get the latest value for a given [`re_types_core::Component`], as well as the associated - /// _data_ time and [`RowId`]. - /// - /// This assumes that the row we get from the store only contains a single instance for this - /// component; it will generate a log message of `level` otherwise. - /// - /// This should only be used for "mono-components" such as `Transform` and `Tensor`. - /// - /// This is a best-effort helper, it will merely log messages on failure. - pub fn query_latest_component_with_log_level( - &self, - entity_path: &EntityPath, - query: &LatestAtQuery, - level: re_log::Level, - ) -> Option> { - re_tracing::profile_function!(); - - let (data_time, row_id, cells) = - self.latest_at(query, entity_path, C::name(), &[C::name()])?; - let cell = cells.first()?.as_ref()?; - - cell.try_to_native_mono::() - .map_err(|err| { - if let re_log_types::DataCellError::LoggableDeserialize(err) = err { - let bt = err.backtrace().map(|mut bt| { - bt.resolve(); - bt - }); - - let err = Box::new(err) as Box; - if let Some(bt) = bt { - re_log::log_once!( - level, - "Couldn't deserialize component at {entity_path}#{}: {}\n{:#?}", - C::name(), - re_error::format(&err), - bt, - ); - } else { - re_log::log_once!( - level, - "Couldn't deserialize component at {entity_path}#{}: {}", - C::name(), - re_error::format(&err) - ); - } - return err; - } - - let err = Box::new(err) as Box; - re_log::log_once!( - level, - "Couldn't deserialize component at {entity_path}#{}: {}", - C::name(), - re_error::format(&err) - ); - - err - }) - .ok()? - .map(|c| VersionedComponent::new(data_time, row_id, c)) - } - - /// Get the latest value for a given [`re_types_core::Component`], as well as the associated - /// _data_ time and [`RowId`]. - /// - /// This assumes that the row we get from the store only contains a single instance for this - /// component; it will log a warning otherwise. - /// - /// This should only be used for "mono-components" such as `Transform` and `Tensor`. - /// - /// This is a best-effort helper, it will merely log errors on failure. - #[inline] - pub fn query_latest_component( - &self, - entity_path: &EntityPath, - query: &LatestAtQuery, - ) -> Option> { - self.query_latest_component_with_log_level(entity_path, query, re_log::Level::Warn) - } - - /// Get the latest value for a given [`re_types_core::Component`], as well as the associated - /// _data_ time and [`RowId`]. - /// - /// This assumes that the row we get from the store only contains a single instance for this - /// component; it will return None and log a debug message otherwise. - /// - /// This should only be used for "mono-components" such as `Transform` and `Tensor`. - /// - /// This is a best-effort helper, it will merely logs debug messages on failure. - #[inline] - pub fn query_latest_component_quiet( - &self, - entity_path: &EntityPath, - query: &LatestAtQuery, - ) -> Option> { - self.query_latest_component_with_log_level(entity_path, query, re_log::Level::Debug) - } - - /// Call [`Self::query_latest_component`] at the given path, walking up the hierarchy until an instance is found. - pub fn query_latest_component_at_closest_ancestor( - &self, - entity_path: &EntityPath, - query: &LatestAtQuery, - ) -> Option<(EntityPath, VersionedComponent)> { - re_tracing::profile_function!(); - - let mut cur_path = Some(entity_path.clone()); - while let Some(path) = cur_path { - if let Some(vc) = self.query_latest_component::(&path, query) { - return Some((path, vc)); - } - cur_path = path.parent(); - } - None - } - - /// Get the latest value for a given [`re_types_core::Component`] and the associated [`RowId`], - /// assuming it is static. - /// - /// This assumes that the row we get from the store only contains a single instance for this - /// component; it will log a warning otherwise. - /// - /// This should only be used for "mono-components" such as `Transform` and `Tensor`. - /// - /// This is a best-effort helper, it will merely log errors on failure. - pub fn query_static_component( - &self, - entity_path: &EntityPath, - ) -> Option> { - re_tracing::profile_function!(); - - let query = LatestAtQuery::latest(Timeline::default()); - self.query_latest_component(entity_path, &query).map(|vc| { - debug_assert!(vc.data_time.is_static()); - vc - }) - } - - /// Get the latest value for a given [`re_types_core::Component`] and the associated [`RowId`], - /// assuming it is static. - /// - /// This assumes that the row we get from the store only contains a single instance for this - /// component; it will return None and log a debug message otherwise. - /// - /// This should only be used for "mono-components" such as `Transform` and `Tensor`. - /// - /// This is a best-effort helper, it will merely log debug on failure. - pub fn query_static_component_quiet( - &self, - entity_path: &EntityPath, - ) -> Option> { - re_tracing::profile_function!(); - - let query = LatestAtQuery::latest(Timeline::default()); - self.query_latest_component_quiet(entity_path, &query) - .map(|vc| { - debug_assert!(vc.data_time.is_static()); - vc - }) - } -} +use crate::DataStore; // --- Write --- diff --git a/crates/re_data_store/tests/correctness.rs b/crates/re_data_store/tests/correctness.rs index 89228d6e5c43..2d75cf1a69c0 100644 --- a/crates/re_data_store/tests/correctness.rs +++ b/crates/re_data_store/tests/correctness.rs @@ -19,6 +19,24 @@ use re_types_core::Loggable as _; // --- +fn query_latest_component( + store: &DataStore, + entity_path: &EntityPath, + query: &LatestAtQuery, +) -> Option<(TimeInt, RowId, C)> { + re_tracing::profile_function!(); + + let (data_time, row_id, cells) = + store.latest_at(query, entity_path, C::name(), &[C::name()])?; + let cell = cells.first()?.as_ref()?; + + cell.try_to_native_mono::() + .ok()? + .map(|c| (data_time, row_id, c)) +} + +// --- + #[test] fn row_id_ordering_semantics() -> anyhow::Result<()> { let entity_path: EntityPath = "some_entity".into(); @@ -60,10 +78,8 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 11); - let got_point = store - .query_latest_component::(&entity_path, &query) - .unwrap() - .value; + let (_, _, got_point) = + query_latest_component::(&store, &entity_path, &query).unwrap(); similar_asserts::assert_eq!(point2, got_point); } } @@ -129,10 +145,8 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 11); - let got_point = store - .query_latest_component::(&entity_path, &query) - .unwrap() - .value; + let (_, _, got_point) = + query_latest_component::(&store, &entity_path, &query).unwrap(); similar_asserts::assert_eq!(point1, got_point); } } @@ -170,10 +184,9 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { store.insert_row(&row)?; { - let got_point = store - .query_static_component::(&entity_path) - .unwrap() - .value; + let query = LatestAtQuery::new(Timeline::new_temporal("doesnt_matter"), TimeInt::MAX); + let (_, _, got_point) = + query_latest_component::(&store, &entity_path, &query).unwrap(); similar_asserts::assert_eq!(point1, got_point); } } diff --git a/crates/re_data_ui/src/annotation_context.rs b/crates/re_data_ui/src/annotation_context.rs index 2e9bdf82f394..843e293cba04 100644 --- a/crates/re_data_ui/src/annotation_context.rs +++ b/crates/re_data_ui/src/annotation_context.rs @@ -86,11 +86,12 @@ fn annotation_info( query: &re_data_store::LatestAtQuery, keypoint_id: KeypointId, ) -> Option { + // TODO(#5607): what should happen if the promise is still pending? let class_id = ctx - .recording_store() - .query_latest_component::(entity_path, query)?; + .recording() + .latest_at_component::(entity_path, query)?; let annotations = crate::annotations(ctx, query, entity_path); - let class = annotations.resolved_class_description(Some(*class_id)); + let class = annotations.resolved_class_description(Some(class_id.value)); class.keypoint_map?.get(&keypoint_id).cloned() } diff --git a/crates/re_data_ui/src/image.rs b/crates/re_data_ui/src/image.rs index 37268b391dbd..0548957b5993 100644 --- a/crates/re_data_ui/src/image.rs +++ b/crates/re_data_ui/src/image.rs @@ -38,10 +38,11 @@ impl EntityDataUi for re_types::components::TensorData { ) { re_tracing::profile_function!(); + // TODO(#5607): what should happen if the promise is still pending? let tensor_data_row_id = ctx - .recording_store() - .query_latest_component::(entity_path, query) - .map_or(RowId::ZERO, |tensor| tensor.row_id); + .recording() + .latest_at_component::(entity_path, query) + .map_or(RowId::ZERO, |tensor| tensor.index.1); let decoded = ctx .cache @@ -92,8 +93,9 @@ pub fn tensor_ui( let meaning = image_meaning_for_entity(entity_path, query, store); let meter = if meaning == TensorDataMeaning::Depth { - ctx.recording_store() - .query_latest_component::(entity_path, query) + // TODO(#5607): what should happen if the promise is still pending? + ctx.recording() + .latest_at_component::(entity_path, query) .map(|meter| meter.value.0) } else { None diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index c6c3acb77091..3d4c60dc58c2 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -162,21 +162,21 @@ pub fn instance_path_icon( /// timeline, then use the blueprint. Otherwise, use the recording. // TODO(jleibs): Ideally this wouldn't be necessary and we could make the assessment // directly from the entity_path. -pub fn guess_query_and_store_for_selected_entity<'a>( +pub fn guess_query_and_db_for_selected_entity<'a>( ctx: &'a ViewerContext<'_>, entity_path: &EntityPath, -) -> (re_data_store::LatestAtQuery, &'a re_data_store::DataStore) { +) -> (re_data_store::LatestAtQuery, &'a re_entity_db::EntityDb) { if ctx.app_options.inspect_blueprint_timeline && ctx.store_context.blueprint.is_logged_entity(entity_path) { ( ctx.blueprint_cfg.time_ctrl.read().current_query(), - ctx.store_context.blueprint.store(), + ctx.store_context.blueprint, ) } else { ( ctx.rec_cfg.time_ctrl.read().current_query(), - ctx.recording_store(), + ctx.recording(), ) } } @@ -184,9 +184,9 @@ pub fn guess_query_and_store_for_selected_entity<'a>( pub fn guess_instance_path_icon( ctx: &ViewerContext<'_>, instance_path: &InstancePath, -) -> &'static icons::Icon { - let (query, store) = guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); - instance_path_icon(&query.timeline(), store, instance_path) +) -> &'static re_ui::icons::Icon { + let (query, db) = guess_query_and_db_for_selected_entity(ctx, &instance_path.entity_path); + instance_path_icon(&query.timeline(), db.store(), instance_path) } /// Show an instance id and make it selectable. diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index 02e5d93cd799..79e4bc740c0f 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -31,7 +31,9 @@ re_log.workspace = true re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true re_query.workspace = true +re_query2.workspace = true re_query_cache.workspace = true +re_query_cache2.workspace = true re_smart_channel.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_entity_db/src/blueprint/components/entity_properties_component_ext.rs b/crates/re_entity_db/src/blueprint/components/entity_properties_component_ext.rs index ebd21182004c..4b9dda9c614d 100644 --- a/crates/re_entity_db/src/blueprint/components/entity_properties_component_ext.rs +++ b/crates/re_entity_db/src/blueprint/components/entity_properties_component_ext.rs @@ -5,11 +5,6 @@ impl re_types_core::SizeBytes for EntityPropertiesComponent { fn heap_size_bytes(&self) -> u64 { // TODO(cmc): Implementing SizeBytes for this type would require a lot of effort, // which would be wasted since this is supposed to go away very soon. - #[allow(clippy::manual_assert)] // readability - if cfg!(debug_assertions) { - panic!("EntityPropertiesComponent does not report its size properly"); - } - 0 } } diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index a0b6e818a3c9..e5dabe66b608 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -118,6 +118,12 @@ pub struct EntityDb { /// Query caches for the data in [`Self::data_store`]. query_caches: re_query_cache::Caches, + /// The active promise resolver for this DB. + resolver: re_query2::PromiseResolver, + + /// Query caches for the data in [`Self::data_store`]. + query_caches2: re_query_cache2::Caches, + stats: IngestionStatistics, } @@ -129,6 +135,7 @@ impl EntityDb { DataStoreConfig::default(), ); let query_caches = re_query_cache::Caches::new(&data_store); + let query_caches2 = re_query_cache2::Caches::new(&data_store); Self { data_source: None, set_store_info: None, @@ -139,6 +146,8 @@ impl EntityDb { tree: crate::EntityTree::root(), data_store, query_caches, + resolver: re_query2::PromiseResolver::default(), + query_caches2, stats: IngestionStatistics::new(store_id), } } @@ -191,6 +200,59 @@ impl EntityDb { &self.query_caches } + #[inline] + pub fn query_caches2(&self) -> &re_query_cache2::Caches { + &self.query_caches2 + } + + #[inline] + pub fn resolver(&self) -> &re_query2::PromiseResolver { + &self.resolver + } + + #[inline] + pub fn latest_at_component( + &self, + entity_path: &EntityPath, + query: &re_data_store::LatestAtQuery, + ) -> Option> { + self.query_caches2().latest_at_component::( + self.store(), + self.resolver(), + entity_path, + query, + ) + } + + #[inline] + pub fn latest_at_component_quiet( + &self, + entity_path: &EntityPath, + query: &re_data_store::LatestAtQuery, + ) -> Option> { + self.query_caches2().latest_at_component_quiet::( + self.store(), + self.resolver(), + entity_path, + query, + ) + } + + #[inline] + pub fn latest_at_component_at_closest_ancestor( + &self, + entity_path: &EntityPath, + query: &re_data_store::LatestAtQuery, + ) -> Option<(EntityPath, re_query_cache2::CachedLatestAtMonoResult)> { + self.query_caches2() + .latest_at_component_at_closest_ancestor::( + self.store(), + self.resolver(), + entity_path, + query, + ) + } + #[inline] pub fn store(&self) -> &DataStore { &self.data_store @@ -369,6 +431,7 @@ impl EntityDb { let original_store_events = &[store_event]; self.times_per_timeline.on_events(original_store_events); self.query_caches.on_events(original_store_events); + self.query_caches2.on_events(original_store_events); let clear_cascade = self.tree.on_store_additions(original_store_events); // Second-pass: update the [`DataStore`] by applying the [`ClearCascade`]. @@ -378,6 +441,7 @@ impl EntityDb { let new_store_events = self.on_clear_cascade(clear_cascade); self.times_per_timeline.on_events(&new_store_events); self.query_caches.on_events(&new_store_events); + self.query_caches2.on_events(&new_store_events); let clear_cascade = self.tree.on_store_additions(&new_store_events); // Clears don't affect `Clear` components themselves, therefore we cannot have recursive @@ -534,11 +598,14 @@ impl EntityDb { tree, data_store: _, query_caches, + resolver: _, + query_caches2, stats: _, } = self; times_per_timeline.on_events(store_events); query_caches.on_events(store_events); + query_caches2.on_events(store_events); let store_events = store_events.iter().collect_vec(); let compacted = CompactedStoreEvents::new(&store_events); diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index af1acbd99217..859e3af45679 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -43,6 +43,8 @@ pub use editable_auto_value::EditableAutoValue; pub mod external { pub use re_data_store; + pub use re_query2; + pub use re_query_cache2; } // ---------------------------------------------------------------------------- diff --git a/crates/re_entity_db/tests/clear.rs b/crates/re_entity_db/tests/clear.rs index 436ec994155d..3172536078d4 100644 --- a/crates/re_entity_db/tests/clear.rs +++ b/crates/re_entity_db/tests/clear.rs @@ -1,8 +1,8 @@ -use re_data_store::LatestAtQuery; +use re_data_store::{DataStore, LatestAtQuery}; use re_entity_db::EntityDb; use re_log_types::{ example_components::{MyColor, MyPoint}, - DataRow, EntityPath, RowId, StoreId, TimePoint, Timeline, + DataRow, EntityPath, RowId, StoreId, TimeInt, TimePoint, Timeline, }; use re_types_core::{ archetypes::Clear, @@ -10,6 +10,24 @@ use re_types_core::{ AsComponents, }; +// --- + +fn query_latest_component( + store: &DataStore, + entity_path: &EntityPath, + query: &LatestAtQuery, +) -> Option<(TimeInt, RowId, C)> { + re_tracing::profile_function!(); + + let (data_time, row_id, cells) = + store.latest_at(query, entity_path, C::name(), &[C::name()])?; + let cell = cells.first()?.as_ref()?; + + cell.try_to_native_mono::() + .ok()? + .map(|c| (data_time, row_id, c)) +} + /// Complete test suite for the clear & pending clear paths. #[test] fn clears() -> anyhow::Result<()> { @@ -42,16 +60,10 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 11); - let got_point = db - .store() - .query_latest_component::(&entity_path_parent, &query) - .unwrap() - .value; - let got_color = db - .store() - .query_latest_component::(&entity_path_parent, &query) - .unwrap() - .value; + let (_, _, got_point) = + query_latest_component::(db.store(), &entity_path_parent, &query).unwrap(); + let (_, _, got_color) = + query_latest_component::(db.store(), &entity_path_parent, &query).unwrap(); similar_asserts::assert_eq!(point, got_point); similar_asserts::assert_eq!(color, got_color); @@ -75,11 +87,8 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 11); - let got_point = db - .store() - .query_latest_component::(&entity_path_child1, &query) - .unwrap() - .value; + let (_, _, got_point) = + query_latest_component::(db.store(), &entity_path_child1, &query).unwrap(); similar_asserts::assert_eq!(point, got_point); } @@ -102,11 +111,8 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 11); - let got_color = db - .store() - .query_latest_component::(&entity_path_child2, &query) - .unwrap() - .value; + let (_, _, got_color) = + query_latest_component::(db.store(), &entity_path_child2, &query).unwrap(); similar_asserts::assert_eq!(color, got_color); } @@ -133,33 +139,31 @@ fn clears() -> anyhow::Result<()> { let query = LatestAtQuery::new(timeline_frame, 11); // parent - assert!(db - .store() - .query_latest_component::(&entity_path_parent, &query) - .is_none()); - assert!(db - .store() - .query_latest_component::(&entity_path_parent, &query) - .is_none()); + assert!( + query_latest_component::(db.store(), &entity_path_parent, &query) + .is_none() + ); + assert!( + query_latest_component::(db.store(), &entity_path_parent, &query) + .is_none() + ); // the `Clear` component itself doesn't get cleared! - let got_clear = db - .store() - .query_latest_component::(&entity_path_parent, &query) - .unwrap() - .value; + let (_, _, got_clear) = + query_latest_component::(db.store(), &entity_path_parent, &query) + .unwrap(); similar_asserts::assert_eq!(clear.is_recursive, got_clear); // child1 - assert!(db - .store() - .query_latest_component::(&entity_path_child1, &query) - .is_some()); + assert!( + query_latest_component::(db.store(), &entity_path_child1, &query) + .is_some() + ); // child2 - assert!(db - .store() - .query_latest_component::(&entity_path_child2, &query) - .is_some()); + assert!( + query_latest_component::(db.store(), &entity_path_child2, &query) + .is_some() + ); } } @@ -184,33 +188,31 @@ fn clears() -> anyhow::Result<()> { let query = LatestAtQuery::new(timeline_frame, 11); // parent - assert!(db - .store() - .query_latest_component::(&entity_path_parent, &query) - .is_none()); - assert!(db - .store() - .query_latest_component::(&entity_path_parent, &query) - .is_none()); + assert!( + query_latest_component::(db.store(), &entity_path_parent, &query) + .is_none() + ); + assert!( + query_latest_component::(db.store(), &entity_path_parent, &query) + .is_none() + ); // the `Clear` component itself doesn't get cleared! - let got_clear = db - .store() - .query_latest_component::(&entity_path_parent, &query) - .unwrap() - .value; + let (_, _, got_clear) = + query_latest_component::(db.store(), &entity_path_parent, &query) + .unwrap(); similar_asserts::assert_eq!(clear.is_recursive, got_clear); // child1 - assert!(db - .store() - .query_latest_component::(&entity_path_child1, &query) - .is_none()); + assert!( + query_latest_component::(db.store(), &entity_path_child1, &query) + .is_none() + ); // child2 - assert!(db - .store() - .query_latest_component::(&entity_path_child2, &query) - .is_none()); + assert!( + query_latest_component::(db.store(), &entity_path_child2, &query) + .is_none() + ); } } @@ -232,20 +234,18 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 9); - let got_instance_key = db - .store() - .query_latest_component::(&entity_path_parent, &query) - .unwrap() - .value; + let (_, _, got_instance_key) = + query_latest_component::(db.store(), &entity_path_parent, &query) + .unwrap(); similar_asserts::assert_eq!(instance_key, got_instance_key); } { let query = LatestAtQuery::new(timeline_frame, 11); - assert!(db - .store() - .query_latest_component::(&entity_path_parent, &query) - .is_none()); + assert!( + query_latest_component::(db.store(), &entity_path_parent, &query) + .is_none() + ); } } @@ -269,16 +269,10 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 9); - let got_point = db - .store() - .query_latest_component::(&entity_path_child1, &query) - .unwrap() - .value; - let got_color = db - .store() - .query_latest_component::(&entity_path_child1, &query) - .unwrap() - .value; + let (_, _, got_point) = + query_latest_component::(db.store(), &entity_path_child1, &query).unwrap(); + let (_, _, got_color) = + query_latest_component::(db.store(), &entity_path_child1, &query).unwrap(); similar_asserts::assert_eq!(point, got_point); similar_asserts::assert_eq!(color, got_color); @@ -286,14 +280,14 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 11); - assert!(db - .store() - .query_latest_component::(&entity_path_child1, &query) - .is_none()); - assert!(db - .store() - .query_latest_component::(&entity_path_child1, &query) - .is_none()); + assert!( + query_latest_component::(db.store(), &entity_path_child1, &query) + .is_none() + ); + assert!( + query_latest_component::(db.store(), &entity_path_child1, &query) + .is_none() + ); } } @@ -317,16 +311,10 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 9); - let got_color = db - .store() - .query_latest_component::(&entity_path_child2, &query) - .unwrap() - .value; - let got_point = db - .store() - .query_latest_component::(&entity_path_child2, &query) - .unwrap() - .value; + let (_, _, got_point) = + query_latest_component::(db.store(), &entity_path_child2, &query).unwrap(); + let (_, _, got_color) = + query_latest_component::(db.store(), &entity_path_child2, &query).unwrap(); similar_asserts::assert_eq!(color, got_color); similar_asserts::assert_eq!(point, got_point); @@ -334,14 +322,14 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 11); - assert!(db - .store() - .query_latest_component::(&entity_path_child2, &query) - .is_none()); - assert!(db - .store() - .query_latest_component::(&entity_path_child2, &query) - .is_none()); + assert!( + query_latest_component::(db.store(), &entity_path_child2, &query) + .is_none() + ); + assert!( + query_latest_component::(db.store(), &entity_path_child2, &query) + .is_none() + ); } } @@ -363,21 +351,19 @@ fn clears() -> anyhow::Result<()> { { let query = LatestAtQuery::new(timeline_frame, 9); - let got_color = db - .store() - .query_latest_component::(&entity_path_grandchild, &query) - .unwrap() - .value; + let (_, _, got_color) = + query_latest_component::(db.store(), &entity_path_grandchild, &query) + .unwrap(); similar_asserts::assert_eq!(color, got_color); } { let query = LatestAtQuery::new(timeline_frame, 11); - assert!(db - .store() - .query_latest_component::(&entity_path_grandchild, &query) - .is_none()); + assert!( + query_latest_component::(db.store(), &entity_path_grandchild, &query) + .is_none() + ); } } diff --git a/crates/re_error/src/lib.rs b/crates/re_error/src/lib.rs index 81f3d82d4629..3be471dd4fd9 100644 --- a/crates/re_error/src/lib.rs +++ b/crates/re_error/src/lib.rs @@ -4,16 +4,19 @@ /// /// Always use this when displaying an error, especially `anyhow::Error`. pub fn format(error: impl AsRef) -> String { - fn format_impl(error: &dyn std::error::Error) -> String { - let mut string = error.to_string(); - for source in std::iter::successors(error.source(), |error| error.source()) { - string.push_str(" -> "); - string.push_str(&source.to_string()); - } - string - } + format_ref(error.as_ref()) +} - format_impl(error.as_ref()) +/// Format an error, including its chain of sources. +/// +/// Always use this when displaying an error, especially `anyhow::Error`. +pub fn format_ref(error: &dyn std::error::Error) -> String { + let mut string = error.to_string(); + for source in std::iter::successors(error.source(), |error| error.source()) { + string.push_str(" -> "); + string.push_str(&source.to_string()); + } + string } #[test] diff --git a/crates/re_query/src/query.rs b/crates/re_query/src/query.rs index cba68e348201..2580ff33c31f 100644 --- a/crates/re_query/src/query.rs +++ b/crates/re_query/src/query.rs @@ -69,7 +69,7 @@ pub fn get_component_with_instances( /// its _most recent component_. /// /// If you expect only one instance (e.g. for mono-components like `Transform` `Tensor`] -/// and have no additional components you can use [`DataStore::query_latest_component`] instead. +/// and have no additional components you can use `Caches::latest_at_component` instead. /// /// ``` /// # use re_data_store::LatestAtQuery; diff --git a/crates/re_query2/src/promise.rs b/crates/re_query2/src/promise.rs index 1585f6eb0ba2..65c44891b3af 100644 --- a/crates/re_query2/src/promise.rs +++ b/crates/re_query2/src/promise.rs @@ -103,6 +103,21 @@ impl PromiseResult { } } + /// Applies the given transformation to the [`PromiseResult`] iff it's `Ready`. + /// + /// Able to modify the result itself, not just the value contained within. + #[inline] + pub fn remap(self, mut f: F) -> PromiseResult + where + F: FnMut(T) -> PromiseResult, + { + match self { + PromiseResult::Ready(v) => f(v), + PromiseResult::Pending => PromiseResult::Pending, + PromiseResult::Error(err) => PromiseResult::Error(err), + } + } + /// Unwraps the resolved result if it's `Ready`, panics otherwise. #[inline] pub fn unwrap(self) -> T { @@ -120,13 +135,9 @@ impl PromiseResult /// Given a [`PromiseResult`] of a `Result`, flattens it down to a single layer [`PromiseResult`]. #[inline] pub fn flatten(self) -> PromiseResult { - match self { - PromiseResult::Ready(res) => match res { - Ok(v) => PromiseResult::Ready(v), - Err(err) => PromiseResult::Error(Arc::new(err) as _), - }, - PromiseResult::Pending => PromiseResult::Pending, - PromiseResult::Error(err) => PromiseResult::Error(err), - } + self.remap(|res| match res { + Ok(v) => PromiseResult::Ready(v), + Err(err) => PromiseResult::Error(Arc::new(err) as _), + }) } } diff --git a/crates/re_query_cache2/Cargo.toml b/crates/re_query_cache2/Cargo.toml index a2d1918dddae..c953b1124bf6 100644 --- a/crates/re_query_cache2/Cargo.toml +++ b/crates/re_query_cache2/Cargo.toml @@ -23,6 +23,7 @@ default = [] [dependencies] # Rerun dependencies: re_data_store.workspace = true +re_error.workspace = true re_format.workspace = true re_log.workspace = true re_log_types.workspace = true diff --git a/crates/re_query_cache2/src/latest_at/helpers.rs b/crates/re_query_cache2/src/latest_at/helpers.rs new file mode 100644 index 000000000000..559bc013336f --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/helpers.rs @@ -0,0 +1,170 @@ +use re_data_store::{DataStore, LatestAtQuery}; +use re_log_types::{EntityPath, RowId, TimeInt}; +use re_types_core::Component; + +use crate::{Caches, PromiseResolver, PromiseResult}; + +// --- + +#[derive(Clone)] +pub struct CachedLatestAtMonoResult { + pub index: (TimeInt, RowId), + pub value: C, +} + +impl CachedLatestAtMonoResult { + #[inline] + pub fn data_time(&self) -> TimeInt { + self.index.0 + } + + #[inline] + pub fn row_id(&self) -> RowId { + self.index.1 + } +} + +impl std::ops::Deref for CachedLatestAtMonoResult { + type Target = C; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.value + } +} + +// --- + +impl Caches { + /// Get the latest index and value for a given dense [`re_types_core::Component`]. + /// + /// Returns `None` if the data is a promise that has yet to be resolved. + /// + /// This assumes that the row we get from the store only contains a single instance for this + /// component; it will generate a log message of `level` otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// This is a best-effort helper, it will merely log messages on failure. + // + // TODO(#5607): what should happen if the promise is still pending? + pub fn latest_at_component_with_log_level( + &self, + store: &DataStore, + resolver: &PromiseResolver, + entity_path: &EntityPath, + query: &LatestAtQuery, + level: re_log::Level, + ) -> Option> { + re_tracing::profile_function!(); + + let results = self.latest_at(store, query, entity_path, [C::name()]); + let result = results.get::()?; + + let index @ (data_time, row_id) = *result.index(); + + match result.to_dense::(resolver).flatten() { + PromiseResult::Pending => { + re_log::debug_once!( + "Couldn't deserialize {entity_path}:{} @ {data_time:?}#{row_id}: promise still pending", + C::name(), + ); + None + } + PromiseResult::Ready(data) if data.len() == 1 => Some(CachedLatestAtMonoResult { + index, + value: data[0].clone(), + }), + PromiseResult::Ready(data) => { + re_log::log_once!( + level, + "Couldn't deserialize {entity_path}:{} @ {data_time:?}#{row_id}: not a mono-batch (length: {})", + C::name(), + data.len(), + ); + None + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't deserialize {entity_path} @ {data_time:?}#{row_id}:{}: {}", + C::name(), + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Get the latest index and value for a given dense [`re_types_core::Component`]. + /// + /// This assumes that the row we get from the store only contains a single instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// This is a best-effort helper, it will merely log errors on failure. + #[inline] + pub fn latest_at_component( + &self, + store: &DataStore, + resolver: &PromiseResolver, + entity_path: &EntityPath, + query: &LatestAtQuery, + ) -> Option> { + self.latest_at_component_with_log_level( + store, + resolver, + entity_path, + query, + re_log::Level::Warn, + ) + } + + /// Get the latest index and value for a given dense [`re_types_core::Component`]. + /// + /// This assumes that the row we get from the store only contains a single instance for this + /// component; it will return None and log a debug message otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// This is a best-effort helper, it will merely logs debug messages on failure. + #[inline] + pub fn latest_at_component_quiet( + &self, + store: &DataStore, + resolver: &PromiseResolver, + entity_path: &EntityPath, + query: &LatestAtQuery, + ) -> Option> { + self.latest_at_component_with_log_level( + store, + resolver, + entity_path, + query, + re_log::Level::Debug, + ) + } + + /// Call [`Self::latest_at_component`] at the given path, walking up the hierarchy until an instance is found. + pub fn latest_at_component_at_closest_ancestor( + &self, + store: &DataStore, + resolver: &PromiseResolver, + entity_path: &EntityPath, + query: &LatestAtQuery, + ) -> Option<(EntityPath, CachedLatestAtMonoResult)> { + re_tracing::profile_function!(); + + let mut cur_entity_path = Some(entity_path.clone()); + while let Some(entity_path) = cur_entity_path { + if let Some(result) = + self.latest_at_component::(store, resolver, &entity_path, query) + { + return Some((entity_path, result)); + } + cur_entity_path = entity_path.parent(); + } + None + } +} diff --git a/crates/re_query_cache2/src/latest_at/mod.rs b/crates/re_query_cache2/src/latest_at/mod.rs index 30564eb5e2e0..4ed943205a5a 100644 --- a/crates/re_query_cache2/src/latest_at/mod.rs +++ b/crates/re_query_cache2/src/latest_at/mod.rs @@ -1,5 +1,7 @@ +mod helpers; mod query; mod results; +pub use self::helpers::CachedLatestAtMonoResult; pub use self::query::LatestAtCache; pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; diff --git a/crates/re_query_cache2/src/lib.rs b/crates/re_query_cache2/src/lib.rs index 2162bc333b95..49e5ce210e3b 100644 --- a/crates/re_query_cache2/src/lib.rs +++ b/crates/re_query_cache2/src/lib.rs @@ -6,7 +6,9 @@ mod latest_at; pub use self::cache::{CacheKey, Caches}; pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; -pub use self::latest_at::{CachedLatestAtComponentResults, CachedLatestAtResults}; +pub use self::latest_at::{ + CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, +}; pub(crate) use self::latest_at::LatestAtCache; diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index c94d583d0299..322894c3ea78 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -27,6 +27,10 @@ pub use visual_time_range::{ }; pub use visualizable::determine_visualizable_entities; +pub mod external { + pub use re_entity_db::external::*; +} + // ----------- use re_entity_db::external::re_data_store; diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 60a343177f5f..8ad6b2d43e10 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -407,10 +407,10 @@ impl SpaceViewBlueprint { let recursive_override_path = base_override_root.join(&DataResult::RECURSIVE_OVERRIDES_PREFIX.into()); + // TODO(#5607): what should happen if the promise is still pending? let individual_properties = ctx .blueprint - .store() - .query_latest_component_quiet::( + .latest_at_component_quiet::( &individual_override_path, query, ) diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index a7866c829df7..d5dba19e6355 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -392,10 +392,10 @@ impl DataQueryPropertyResolver<'_> { .unwrap_or_default(); for prefix in &self.default_stack { + // TODO(#5607): what should happen if the promise is still pending? if let Some(overrides) = ctx .blueprint - .store() - .query_latest_component::(prefix, query) + .latest_at_component::(prefix, query) { root_entity_properties = root_entity_properties.with_child(&overrides.value.0); } @@ -439,9 +439,9 @@ impl DataQueryPropertyResolver<'_> { if let Some(tree) = blueprint.tree().subtree(override_root) { tree.visit_children_recursively(&mut |path: &EntityPath, _| { - if let Some(props) = blueprint - .store() - .query_latest_component_quiet::(path, query) + // TODO(#5607): what should happen if the promise is still pending? + if let Some(props) = + blueprint.latest_at_component_quiet::(path, query) { let overridden_path = EntityPath::from(&path.as_slice()[override_root.len()..path.len()]); @@ -500,10 +500,10 @@ impl DataQueryPropertyResolver<'_> { re_tracing::profile_scope!("Update visualizers from overrides"); // If the user has overridden the visualizers, update which visualizers are used. + // TODO(#5607): what should happen if the promise is still pending? if let Some(viz_override) = ctx .blueprint - .store() - .query_latest_component::( + .latest_at_component::( &individual_override_path, query, ) diff --git a/crates/re_space_view_bar_chart/src/visualizer_system.rs b/crates/re_space_view_bar_chart/src/visualizer_system.rs index fd7ba62be6ca..df862bde1991 100644 --- a/crates/re_space_view_bar_chart/src/visualizer_system.rs +++ b/crates/re_space_view_bar_chart/src/visualizer_system.rs @@ -48,19 +48,23 @@ impl VisualizerSystem for BarChartVisualizerSystem { ) -> Result, SpaceViewSystemExecutionError> { re_tracing::profile_function!(); - let store = ctx.recording_store(); - for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { + // TODO(#5607): what should happen if the promise is still pending? let query = LatestAtQuery::new(query.timeline, query.latest_at); - let tensor = store.query_latest_component::( - &data_result.entity_path, - &query, - ); - let color = store.query_latest_component::( - &data_result.entity_path, - &query, - ); + let tensor = ctx + .recording() + .latest_at_component::( + &data_result.entity_path, + &query, + ); + + let color = ctx + .recording() + .latest_at_component::( + &data_result.entity_path, + &query, + ); if let Some(tensor) = tensor { if tensor.is_vector() { diff --git a/crates/re_space_view_spatial/src/contexts/depth_offsets.rs b/crates/re_space_view_spatial/src/contexts/depth_offsets.rs index 806bd83827a6..258de2b3bacf 100644 --- a/crates/re_space_view_spatial/src/contexts/depth_offsets.rs +++ b/crates/re_space_view_spatial/src/contexts/depth_offsets.rs @@ -44,8 +44,6 @@ impl ViewContextSystem for EntityDepthOffsets { DefaultPoints, } - let store = ctx.recording_store(); - // Use a BTreeSet for entity hashes to get a stable order. let mut entities_per_draw_order = BTreeMap::>::new(); for data_result in query.iter_all_data_results() { @@ -55,8 +53,11 @@ impl ViewContextSystem for EntityDepthOffsets { continue; } - if let Some(draw_order) = store - .query_latest_component::(&data_result.entity_path, &ctx.current_query()) + // TODO(#5607): what should happen if the promise is still pending? + if let Some(draw_order) = ctx + .store_context + .recording + .latest_at_component::(&data_result.entity_path, &ctx.current_query()) { entities_per_draw_order .entry(draw_order.value) diff --git a/crates/re_space_view_spatial/src/heuristics.rs b/crates/re_space_view_spatial/src/heuristics.rs index d6ee19640848..8ff287752a0e 100644 --- a/crates/re_space_view_spatial/src/heuristics.rs +++ b/crates/re_space_view_spatial/src/heuristics.rs @@ -111,17 +111,21 @@ fn update_depth_cloud_property_heuristics( .get(&ImageVisualizer::identifier()) .unwrap_or(&BTreeSet::new()) { - let store = ctx.recording_store(); - let Some(tensor) = - store.query_latest_component::(ent_path, &ctx.current_query()) + // TODO(#5607): what should happen if the promise is still pending? + let Some(tensor) = ctx + .recording() + .latest_at_component::(ent_path, &ctx.current_query()) else { continue; }; - let meaning = image_meaning_for_entity(ent_path, &ctx.current_query(), store); + let meaning = + image_meaning_for_entity(ent_path, &ctx.current_query(), ctx.recording().store()); - let meter = store - .query_latest_component::(ent_path, &ctx.current_query()) + // TODO(#5607): what should happen if the promise is still pending? + let meter = ctx + .recording() + .latest_at_component::(ent_path, &ctx.current_query()) .map(|meter| meter.value.0); let mut properties = entity_properties.get(ent_path); @@ -163,17 +167,18 @@ fn update_transform3d_lines_heuristics( .unwrap_or(&BTreeSet::new()) { fn is_pinhole_extrinsics_of<'a>( - store: &re_data_store::DataStore, ent_path: &'a EntityPath, ctx: &'a ViewerContext<'_>, ) -> Option<&'a EntityPath> { - if query_pinhole(store, &ctx.current_query(), ent_path).is_some() { + if query_pinhole(ctx.recording(), &ctx.current_query(), ent_path).is_some() { return Some(ent_path); } else { // Any direct child has a pinhole camera? if let Some(child_tree) = ctx.recording().tree().subtree(ent_path) { for child in child_tree.children.values() { - if query_pinhole(store, &ctx.current_query(), &child.path).is_some() { + if query_pinhole(ctx.recording(), &ctx.current_query(), &child.path) + .is_some() + { return Some(&child.path); } } @@ -195,15 +200,12 @@ fn update_transform3d_lines_heuristics( .all(|c| re_types::archetypes::Transform3D::all_components().contains(c)) }); properties.transform_3d_visible = EditableAutoValue::Auto( - only_has_transform_components - || is_pinhole_extrinsics_of(ctx.recording_store(), ent_path, ctx).is_some(), + only_has_transform_components || is_pinhole_extrinsics_of(ent_path, ctx).is_some(), ); } if properties.transform_3d_size.is_auto() { - if let Some(pinhole_path) = - is_pinhole_extrinsics_of(ctx.recording_store(), ent_path, ctx) - { + if let Some(pinhole_path) = is_pinhole_extrinsics_of(ent_path, ctx) { // If there's a pinhole, we orient ourselves on its image plane distance let pinhole_path_props = entity_properties.get(pinhole_path); properties.transform_3d_size = EditableAutoValue::Auto( diff --git a/crates/re_space_view_spatial/src/lib.rs b/crates/re_space_view_spatial/src/lib.rs index f7db2a3228de..53ea9688bbdc 100644 --- a/crates/re_space_view_spatial/src/lib.rs +++ b/crates/re_space_view_spatial/src/lib.rs @@ -38,12 +38,13 @@ mod view_kind { } fn resolution_from_tensor( - store: &re_data_store::DataStore, + entity_db: &re_entity_db::EntityDb, query: &re_data_store::LatestAtQuery, entity_path: &re_log_types::EntityPath, ) -> Option { - store - .query_latest_component::(entity_path, query) + // TODO(#5607): what should happen if the promise is still pending? + entity_db + .latest_at_component::(entity_path, query) .and_then(|tensor| { tensor .image_height_width_channels() @@ -56,20 +57,21 @@ fn resolution_from_tensor( /// TODO(andreas): It should be possible to convert [`re_query::ArchetypeView`] to its corresponding Archetype for situations like this. /// TODO(andreas): This is duplicated into `re_viewport` fn query_pinhole( - store: &re_data_store::DataStore, + entity_db: &re_entity_db::EntityDb, query: &re_data_store::LatestAtQuery, entity_path: &re_log_types::EntityPath, ) -> Option { - store - .query_latest_component::(entity_path, query) + // TODO(#5607): what should happen if the promise is still pending? + entity_db + .latest_at_component::(entity_path, query) .map(|image_from_camera| re_types::archetypes::Pinhole { image_from_camera: image_from_camera.value, - resolution: store - .query_latest_component(entity_path, query) + resolution: entity_db + .latest_at_component(entity_path, query) .map(|c| c.value) - .or_else(|| resolution_from_tensor(store, query, entity_path)), - camera_xyz: store - .query_latest_component(entity_path, query) + .or_else(|| resolution_from_tensor(entity_db, query, entity_path)), + camera_xyz: entity_db + .latest_at_component(entity_path, query) .map(|c| c.value), }) } diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 4e5c34bcf4e3..75f02282b50d 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -305,9 +305,10 @@ impl SpaceViewClass for SpatialSpaceView3D { ) -> Result<(), SpaceViewSystemExecutionError> { let state = state.downcast_mut::()?; + // TODO(#5607): what should happen if the promise is still pending? let scene_view_coordinates = ctx - .recording_store() - .query_latest_component::(space_origin, &ctx.current_query()) + .recording() + .latest_at_component::(space_origin, &ctx.current_query()) .map(|c| c.value); ctx.re_ui diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 90239198db90..c7e32c1a09a3 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -496,41 +496,40 @@ pub fn picking( let is_depth_cloud = images .depth_cloud_entities .contains(&instance_path.entity_path.hash()); - let picked_image_with_coords = - if hit.hit_type == PickingHitType::TexturedRect || is_depth_cloud { - let meaning = image_meaning_for_entity( - &instance_path.entity_path, - &query.latest_at_query(), - store, - ); - - store - .query_latest_component::( - &instance_path.entity_path, - &ctx.current_query(), - ) - .and_then(|tensor| { - // If we're here because of back-projection, but this wasn't actually a depth image, drop out. - // (the back-projection property may be true despite this not being a depth image!) - if hit.hit_type != PickingHitType::TexturedRect - && is_depth_cloud - && meaning != TensorDataMeaning::Depth - { - None - } else { - let tensor_path_hash = hit.instance_path_hash.versioned(tensor.row_id); - tensor.image_height_width_channels().map(|[_, w, _]| { - let coordinates = hit - .instance_path_hash - .instance_key - .to_2d_image_coordinate(w); - (tensor_path_hash, tensor, meaning, coordinates) - }) - } - }) - } else { - None - }; + let picked_image_with_coords = if hit.hit_type == PickingHitType::TexturedRect + || is_depth_cloud + { + let meaning = image_meaning_for_entity( + &instance_path.entity_path, + &query.latest_at_query(), + store, + ); + + // TODO(#5607): what should happen if the promise is still pending? + ctx.recording() + .latest_at_component::(&instance_path.entity_path, &ctx.current_query()) + .and_then(|tensor| { + // If we're here because of back-projection, but this wasn't actually a depth image, drop out. + // (the back-projection property may be true despite this not being a depth image!) + if hit.hit_type != PickingHitType::TexturedRect + && is_depth_cloud + && meaning != TensorDataMeaning::Depth + { + None + } else { + let tensor_path_hash = hit.instance_path_hash.versioned(tensor.row_id()); + tensor.image_height_width_channels().map(|[_, w, _]| { + let coordinates = hit + .instance_path_hash + .instance_key + .to_2d_image_coordinate(w); + (tensor_path_hash, tensor, meaning, coordinates) + }) + } + }) + } else { + None + }; if picked_image_with_coords.is_some() { // We don't support selecting pixels yet. instance_path.instance_key = InstanceKey::SPLAT; @@ -541,11 +540,10 @@ pub fn picking( response = if let Some((tensor_path_hash, tensor, meaning, coords)) = picked_image_with_coords { - let meter = store - .query_latest_component::( - &instance_path.entity_path, - &ctx.current_query(), - ) + // TODO(#5607): what should happen if the promise is still pending? + let meter = ctx + .recording() + .latest_at_component::(&instance_path.entity_path, &ctx.current_query()) .map(|meter| meter.value.0); // TODO(jleibs): Querying this here feels weird. Would be nice to do this whole diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index c150d160ef3b..6d3ca26bae21 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -240,7 +240,6 @@ pub fn view_2d( // Save off the available_size since this is used for some of the layout updates later let available_size = ui.available_size(); - let store = ctx.recording_store(); let scene_rect_accum = state.bounding_boxes.accumulated; let scene_rect_accum = egui::Rect::from_min_max( @@ -258,7 +257,7 @@ pub fn view_2d( // For that we need to check if this is defined by a pinhole camera. // Note that we can't rely on the camera being part of scene.space_cameras since that requires // the camera to be added to the scene! - let pinhole = query_pinhole(store, &ctx.current_query(), query.space_origin); + let pinhole = query_pinhole(ctx.recording(), &ctx.current_query(), query.space_origin); let canvas_rect = pinhole .as_ref() .and_then(|p| p.resolution()) diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 4042662fca6c..9affa4568b05 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -444,11 +444,12 @@ pub fn view_3d( let highlights = &query.highlights; let space_cameras = &parts.get::()?.space_cameras; + // TODO(#5607): what should happen if the promise is still pending? let scene_view_coordinates = ctx - .recording_store() + .recording() // Allow logging view-coordinates to `/` and have it apply to `/world` etc. // See https://github.com/rerun-io/rerun/issues/3538 - .query_latest_component_at_closest_ancestor(query.space_origin, &ctx.current_query()) + .latest_at_component_at_closest_ancestor(query.space_origin, &ctx.current_query()) .map(|(_, c)| c.value); let (rect, mut response) = diff --git a/crates/re_space_view_spatial/src/visualizers/cameras.rs b/crates/re_space_view_spatial/src/visualizers/cameras.rs index cf09142e9c5b..737c384a3d64 100644 --- a/crates/re_space_view_spatial/src/visualizers/cameras.rs +++ b/crates/re_space_view_spatial/src/visualizers/cameras.rs @@ -206,7 +206,6 @@ impl VisualizerSystem for CamerasVisualizer { view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { let transforms = view_ctx.get::()?; - let store = ctx.recording_store(); // Counting all cameras ahead of time is a bit wasteful, but we also don't expect a huge amount, // so let re_renderer's allocator internally decide what buffer sizes to pick & grow them as we go. @@ -216,7 +215,9 @@ impl VisualizerSystem for CamerasVisualizer { for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let time_query = re_data_store::LatestAtQuery::new(query.timeline, query.latest_at); - if let Some(pinhole) = query_pinhole(store, &time_query, &data_result.entity_path) { + if let Some(pinhole) = + query_pinhole(ctx.recording(), &time_query, &data_result.entity_path) + { let entity_highlight = query .highlights .entity_outline_mask(data_result.entity_path.hash()); @@ -227,11 +228,9 @@ impl VisualizerSystem for CamerasVisualizer { &data_result.entity_path, data_result.accumulated_properties(), &pinhole, - store - .query_latest_component::( - &data_result.entity_path, - &time_query, - ) + // TODO(#5607): what should happen if the promise is still pending? + ctx.recording() + .latest_at_component::(&data_result.entity_path, &time_query) .map(|c| c.value), pinhole.camera_xyz.unwrap_or(ViewCoordinates::RDF), // TODO(#2641): This should come from archetype entity_highlight, diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index 91a3437528b6..7fc8f9671c0c 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -558,11 +558,9 @@ impl ImageVisualizer { ) -> anyhow::Result { re_tracing::profile_function!(); - let Some(intrinsics) = query_pinhole( - ctx.recording_store(), - &ctx.current_query(), - parent_pinhole_path, - ) else { + let Some(intrinsics) = + query_pinhole(ctx.recording(), &ctx.current_query(), parent_pinhole_path) + else { anyhow::bail!("Couldn't fetch pinhole intrinsics at {parent_pinhole_path:?}"); }; diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index 11807f00afd2..0056cdda362b 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -1,5 +1,5 @@ -use re_data_store::{LatestAtQuery, VersionedComponent}; -use re_entity_db::EntityPath; +use re_data_store::LatestAtQuery; +use re_entity_db::{external::re_query_cache2::CachedLatestAtMonoResult, EntityPath}; use re_log_types::RowId; use re_space_view::diff_component_filter; use re_types::{archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor}; @@ -47,12 +47,13 @@ impl VisualizerSystem for TensorSystem { ) -> Result, SpaceViewSystemExecutionError> { re_tracing::profile_function!(); - let store = ctx.recording_store(); for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { let timeline_query = LatestAtQuery::new(query.timeline, query.latest_at); - if let Some(tensor) = store - .query_latest_component::(&data_result.entity_path, &timeline_query) + // TODO(#5607): what should happen if the promise is still pending? + if let Some(tensor) = ctx + .recording() + .latest_at_component::(&data_result.entity_path, &timeline_query) { self.load_tensor_entity(ctx, &data_result.entity_path, tensor); } @@ -71,15 +72,16 @@ impl TensorSystem { &mut self, ctx: &ViewerContext<'_>, ent_path: &EntityPath, - tensor: VersionedComponent, + tensor: CachedLatestAtMonoResult, ) { + let row_id = tensor.row_id(); match ctx .cache - .entry(|c: &mut TensorDecodeCache| c.entry(tensor.row_id, tensor.value.0)) + .entry(|c: &mut TensorDecodeCache| c.entry(row_id, tensor.value.0)) { Ok(decoded_tensor) => { self.tensors - .insert(ent_path.clone(), (tensor.row_id, decoded_tensor)); + .insert(ent_path.clone(), (row_id, decoded_tensor)); } Err(err) => { re_log::warn_once!("Failed to decode decoding tensor at path {ent_path}: {err}"); diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 5f5f77e6ac7c..43ee7d5049c6 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -282,8 +282,9 @@ fn load_series( let series_name = if let Some(override_name) = override_series_name { Some(override_name) } else { - ctx.recording_store() - .query_latest_component::(&data_result.entity_path, &ctx.current_query()) + // TODO(#5607): what should happen if the promise is still pending? + ctx.recording() + .latest_at_component::(&data_result.entity_path, &ctx.current_query()) .map(|name| name.value.0) }; diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 4ce60e2696f4..ce651cb6f106 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -253,8 +253,9 @@ impl SeriesPointSystem { let series_name = if let Some(override_name) = override_series_name { Some(override_name) } else { - ctx.recording_store() - .query_latest_component::(&data_result.entity_path, &ctx.current_query()) + // TODO(#5607): what should happen if the promise is still pending? + ctx.recording() + .latest_at_component::(&data_result.entity_path, &ctx.current_query()) .map(|name| name.value.0) }; diff --git a/crates/re_viewer/src/app_blueprint.rs b/crates/re_viewer/src/app_blueprint.rs index cc9561f78bc5..987935a1640b 100644 --- a/crates/re_viewer/src/app_blueprint.rs +++ b/crates/re_viewer/src/app_blueprint.rs @@ -134,8 +134,8 @@ fn load_panel_state( query: &LatestAtQuery, ) -> Option { re_tracing::profile_function!(); + // TODO(#5607): what should happen if the promise is still pending? blueprint_db - .store() - .query_latest_component_quiet::(path, query) + .latest_at_component_quiet::(path, query) .map(|p| p.0 .0) } diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 858c44dfeba4..d91d4a65bb44 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -2,7 +2,7 @@ use egui::{NumExt as _, Ui}; use re_data_ui::{ image_meaning_for_entity, item_ui, - item_ui::{guess_instance_path_icon, guess_query_and_store_for_selected_entity}, + item_ui::{guess_instance_path_icon, guess_query_and_db_for_selected_entity}, DataUi, }; use re_entity_db::{ @@ -143,12 +143,18 @@ impl SelectionPanel { if let Some(data_ui_item) = data_section_ui(item) { ctx.re_ui.large_collapsing_header(ui, "Data", true, |ui| { - let (query, store) = if let Some(entity_path) = item.entity_path() { - guess_query_and_store_for_selected_entity(ctx, entity_path) + let (query, db) = if let Some(entity_path) = item.entity_path() { + guess_query_and_db_for_selected_entity(ctx, entity_path) } else { - (ctx.current_query(), ctx.recording_store()) + (ctx.current_query(), ctx.recording()) }; - data_ui_item.data_ui(ctx, ui, multi_selection_verbosity, &query, store); + data_ui_item.data_ui( + ctx, + ui, + multi_selection_verbosity, + &query, + db.store(), + ); }); } @@ -375,11 +381,11 @@ fn what_is_selected_ui( ), ); - let (query, store) = guess_query_and_store_for_selected_entity(ctx, entity_path); + let (query, db) = guess_query_and_db_for_selected_entity(ctx, entity_path); ui.horizontal(|ui| { ui.label("component of"); - item_ui::entity_path_button(ctx, &query, store, ui, None, entity_path); + item_ui::entity_path_button(ctx, &query, db.store(), ui, None, entity_path); }); list_existing_data_blueprints(ui, ctx, &entity_path.clone().into(), viewport); @@ -433,11 +439,18 @@ fn what_is_selected_ui( }; if let Some(parent) = parent { if !parent.is_root() { - let (query, store) = - guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); + let (query, db) = + guess_query_and_db_for_selected_entity(ctx, &instance_path.entity_path); ui.horizontal(|ui| { ui.label("Parent"); - item_ui::entity_path_parts_buttons(ctx, &query, store, ui, None, &parent); + item_ui::entity_path_parts_buttons( + ctx, + &query, + db.store(), + ui, + None, + &parent, + ); }); } } @@ -470,7 +483,7 @@ fn what_is_selected_ui( if let Some(parent) = parent { if !parent.is_root() { ui.horizontal(|ui| { - let (query, store) = guess_query_and_store_for_selected_entity( + let (query, db) = guess_query_and_db_for_selected_entity( ctx, &instance_path.entity_path, ); @@ -479,7 +492,7 @@ fn what_is_selected_ui( item_ui::entity_path_parts_buttons( ctx, &query, - store, + db.store(), ui, Some(*space_view_id), &parent, @@ -526,7 +539,7 @@ fn list_existing_data_blueprints( let space_views_with_path = blueprint.space_views_containing_entity_path(ctx, &instance_path.entity_path); - let (query, store) = guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); + let (query, db) = guess_query_and_db_for_selected_entity(ctx, &instance_path.entity_path); if space_views_with_path.is_empty() { ui.weak("(Not shown in any space view)"); @@ -537,7 +550,7 @@ fn list_existing_data_blueprints( item_ui::instance_path_button_to( ctx, &query, - store, + db.store(), ui, Some(*space_view_id), instance_path, @@ -1235,9 +1248,9 @@ fn pinhole_props_ui( entity_path: &EntityPath, entity_props: &mut EntityProperties, ) { - let (query, store) = guess_query_and_store_for_selected_entity(ctx, entity_path); + let (query, store) = guess_query_and_db_for_selected_entity(ctx, entity_path); if store - .query_latest_component::(entity_path, &query) + .latest_at_component::(entity_path, &query) .is_some() { ui.label("Image plane distance"); @@ -1266,15 +1279,15 @@ fn depth_props_ui( ) -> Option<()> { re_tracing::profile_function!(); - let (query, store) = guess_query_and_store_for_selected_entity(ctx, entity_path); + let (query, db) = guess_query_and_db_for_selected_entity(ctx, entity_path); - let meaning = image_meaning_for_entity(entity_path, &query, store); + let meaning = image_meaning_for_entity(entity_path, &query, db.store()); if meaning != TensorDataMeaning::Depth { return Some(()); } - let image_projection_ent_path = store - .query_latest_component_at_closest_ancestor::(entity_path, &query)? + let image_projection_ent_path = db + .latest_at_component_at_closest_ancestor::(entity_path, &query)? .0; let mut backproject_depth = *entity_props.backproject_depth; @@ -1294,10 +1307,17 @@ fn depth_props_ui( if backproject_depth { ui.label("Pinhole"); - item_ui::entity_path_button(ctx, &query, store, ui, None, &image_projection_ent_path) - .on_hover_text( - "The entity path of the pinhole transform being used to do the backprojection.", - ); + item_ui::entity_path_button( + ctx, + &query, + db.store(), + ui, + None, + &image_projection_ent_path, + ) + .on_hover_text( + "The entity path of the pinhole transform being used to do the backprojection.", + ); ui.end_row(); depth_from_world_scale_ui(ui, &mut entity_props.depth_from_world_scale); @@ -1367,10 +1387,10 @@ fn transform3d_visualization_ui( ) { re_tracing::profile_function!(); - let (query, store) = guess_query_and_store_for_selected_entity(ctx, entity_path); + let (query, store) = guess_query_and_db_for_selected_entity(ctx, entity_path); if store - .query_latest_component::(entity_path, &query) + .latest_at_component::(entity_path, &query) .is_none() { return; diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 37ac7630ba33..f866f772f39e 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -311,19 +311,22 @@ impl DataResult { .and_then(|p| p.individual_properties.as_ref()) } - pub fn lookup_override(&self, ctx: &ViewerContext<'_>) -> Option { + #[inline] + pub fn lookup_override( + &self, + ctx: &ViewerContext<'_>, + ) -> Option { self.property_overrides .as_ref() .and_then(|p| p.resolved_component_overrides.get(&C::name())) .and_then(|OverridePath { store_kind, path }| match store_kind { + // TODO(#5607): what should happen if the promise is still pending? StoreKind::Blueprint => ctx - .store_context - .blueprint - .store() - .query_latest_component::(path, ctx.blueprint_query), + .recording() + .latest_at_component::(path, ctx.blueprint_query), StoreKind::Recording => ctx - .recording_store() - .query_latest_component::(path, &ctx.current_query()), + .recording() + .latest_at_component::(path, &ctx.current_query()), }) .map(|c| c.value) } From b66fb55b77d32a36f29729d8425c28ee98259d2f Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 14:44:49 +0200 Subject: [PATCH 224/508] New data APIs 5: port data UIs to new APIs (#5633) _Trivial commit by commit_ All data UIs are now using cached APIs as much as possible. As a nice side-effect, `EntityDb` is now plumbed through everywhere, giving access to everything you might possibly need in all the places you might need 'em. We're slowly but surely seeing the first sign of instance keys going away, but it's still not the focus of this PR. --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- crates/re_data_ui/src/annotation_context.rs | 6 +- crates/re_data_ui/src/app_id.rs | 2 +- crates/re_data_ui/src/blueprint_data.rs | 4 +- crates/re_data_ui/src/component.rs | 132 +++++------ crates/re_data_ui/src/component_path.rs | 46 ++-- .../re_data_ui/src/component_ui_registry.rs | 32 +-- crates/re_data_ui/src/data.rs | 18 +- crates/re_data_ui/src/data_source.rs | 2 +- crates/re_data_ui/src/editors.rs | 110 ++++----- crates/re_data_ui/src/entity_db.rs | 2 +- crates/re_data_ui/src/entity_path.rs | 4 +- crates/re_data_ui/src/image.rs | 8 +- crates/re_data_ui/src/instance_path.rs | 31 ++- crates/re_data_ui/src/item_ui.rs | 72 +++--- crates/re_data_ui/src/lib.rs | 14 +- crates/re_data_ui/src/log_msg.rs | 16 +- crates/re_data_ui/src/material.rs | 4 +- crates/re_data_ui/src/pinhole.rs | 8 +- crates/re_data_ui/src/rotation3d.rs | 8 +- crates/re_data_ui/src/store_id.rs | 4 +- crates/re_data_ui/src/transform3d.rs | 36 +-- crates/re_query2/src/promise.rs | 9 + .../re_query_cache2/src/latest_at/helpers.rs | 223 +++++++++++++++++- .../re_query_cache2/src/latest_at/results.rs | 19 ++ .../src/space_view_class.rs | 34 +-- crates/re_space_view_spatial/src/ui.rs | 14 +- .../src/space_view_class.rs | 3 +- .../re_time_panel/src/data_density_graph.rs | 12 +- crates/re_time_panel/src/lib.rs | 18 +- crates/re_viewer/src/ui/override_ui.rs | 41 +++- crates/re_viewer/src/ui/recordings_panel.rs | 4 +- crates/re_viewer/src/ui/selection_panel.rs | 38 +-- .../src/component_ui_registry.rs | 55 +++-- crates/re_viewport/src/blueprint/data_ui.rs | 8 +- .../src/space_view_entity_picker.rs | 3 +- .../re_viewport/src/viewport_blueprint_ui.rs | 10 +- .../src/color_coordinates_space_view.rs | 4 +- examples/rust/extend_viewer_ui/src/main.rs | 23 +- 38 files changed, 675 insertions(+), 402 deletions(-) diff --git a/crates/re_data_ui/src/annotation_context.rs b/crates/re_data_ui/src/annotation_context.rs index 843e293cba04..9e8a3c7e3d38 100644 --- a/crates/re_data_ui/src/annotation_context.rs +++ b/crates/re_data_ui/src/annotation_context.rs @@ -17,7 +17,7 @@ impl crate::EntityDataUi for re_types::components::ClassId { verbosity: re_viewer_context::UiVerbosity, entity_path: &re_log_types::EntityPath, query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let annotations = crate::annotations(ctx, query, entity_path); let class = annotations @@ -63,7 +63,7 @@ impl crate::EntityDataUi for re_types::components::KeypointId { _verbosity: re_viewer_context::UiVerbosity, entity_path: &re_log_types::EntityPath, query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { if let Some(info) = annotation_info(ctx, entity_path, query, self.0) { ui.horizontal(|ui| { @@ -102,7 +102,7 @@ impl DataUi for AnnotationContext { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small | UiVerbosity::Reduced => { diff --git a/crates/re_data_ui/src/app_id.rs b/crates/re_data_ui/src/app_id.rs index 50c55d0336f6..31ea2ca0f470 100644 --- a/crates/re_data_ui/src/app_id.rs +++ b/crates/re_data_ui/src/app_id.rs @@ -13,7 +13,7 @@ impl crate::DataUi for ApplicationId { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &EntityDb, ) { egui::Grid::new("application_id") .num_columns(2) diff --git a/crates/re_data_ui/src/blueprint_data.rs b/crates/re_data_ui/src/blueprint_data.rs index 344033d5abbf..5cae1a5ec929 100644 --- a/crates/re_data_ui/src/blueprint_data.rs +++ b/crates/re_data_ui/src/blueprint_data.rs @@ -10,12 +10,12 @@ impl DataUi for BlueprintId { ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { entity_path_button_to( ctx, query, - store, + db, ui, None, &self.as_entity_path(), diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index 95976dbf4043..d7973d302eeb 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -1,7 +1,10 @@ +use std::sync::Arc; + use egui::NumExt; -use re_entity_db::{EntityPath, InstancePath}; -use re_query::ComponentWithInstances; +use re_entity_db::{ + external::re_query_cache2::CachedLatestAtComponentResults, EntityPath, InstancePath, +}; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; use re_viewer_context::{UiVerbosity, ViewerContext}; @@ -9,38 +12,33 @@ use re_viewer_context::{UiVerbosity, ViewerContext}; use super::{table_for_verbosity, DataUi}; use crate::item_ui; -// We do NOT implement `DataUi` for just `ComponentWithInstances` -// because we also want the context of what entity it is part of! - /// All the values of a specific [`re_log_types::ComponentPath`]. -pub struct EntityComponentWithInstances { +pub struct EntityLatestAtResults { pub entity_path: EntityPath, - pub component_data: ComponentWithInstances, -} - -impl EntityComponentWithInstances { - pub fn component_name(&self) -> ComponentName { - self.component_data.name() - } - - pub fn num_instances(&self) -> usize { - self.component_data.len() - } + pub component_name: ComponentName, + pub results: Arc, } -impl DataUi for EntityComponentWithInstances { +impl DataUi for EntityLatestAtResults { fn data_ui( &self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { - re_tracing::profile_function!(self.component_name().full_name()); + re_tracing::profile_function!(self.component_name); - let instance_keys = self.component_data.instance_keys(); - let num_instances = self.num_instances(); + // TODO(#5607): what should happen if the promise is still pending? + let Some(num_instances) = self + .results + .raw(db.resolver(), self.component_name) + .map(|data| data.len()) + else { + ui.weak(""); + return; + }; let one_line = match verbosity { UiVerbosity::Small => true, @@ -71,7 +69,7 @@ impl DataUi for EntityComponentWithInstances { // ├───┼───┼───┼───┤ │ // │ │ x │…+2│…+3│ │ // └───┴───┴───┴───┘ ┘ - let displayed_row = if num_instances <= max_row { + let num_displayed_rows = if num_instances <= max_row { num_instances } else { // this accounts for the "…x more" using a row and handles `num_instances == 0` @@ -81,20 +79,16 @@ impl DataUi for EntityComponentWithInstances { if num_instances == 0 { ui.weak("(empty)"); } else if num_instances == 1 { - if let Some(instance_key) = instance_keys.first() { - ctx.component_ui_registry.ui( - ctx, - ui, - verbosity, - query, - store, - &self.entity_path, - &self.component_data, - instance_key, - ); - } else { - ui.label(ctx.re_ui.error_text("Error: missing instance key")); - } + ctx.component_ui_registry.ui( + ctx, + ui, + verbosity, + query, + db, + &self.entity_path, + &self.results, + &re_types::components::InstanceKey(0), + ); } else if one_line { ui.label(format!("{} values", re_format::format_uint(num_instances))); } else { @@ -106,49 +100,49 @@ impl DataUi for EntityComponentWithInstances { .header(re_ui::ReUi::table_header_height(), |mut header| { re_ui::ReUi::setup_table_header(&mut header); header.col(|ui| { - ui.label("Index"); + ui.label("Instance"); }); header.col(|ui| { - ui.label(self.component_name().short_name()); + ui.label(self.component_name.short_name()); }); }) .body(|mut body| { re_ui::ReUi::setup_table_body(&mut body); let row_height = re_ui::ReUi::table_line_height(); - body.rows(row_height, displayed_row, |mut row| { - if let Some(instance_key) = instance_keys.get(row.index()) { - row.col(|ui| { - let instance_path = - InstancePath::instance(self.entity_path.clone(), *instance_key); - item_ui::instance_path_button_to( - ctx, - query, - store, - ui, - None, - &instance_path, - instance_key.syntax_highlighted(ui.style()), - ); - }); - row.col(|ui| { - ctx.component_ui_registry.ui( - ctx, - ui, - UiVerbosity::Small, - query, - store, - &self.entity_path, - &self.component_data, - instance_key, - ); - }); - } + body.rows(row_height, num_displayed_rows, |mut row| { + let instance_key = re_types::components::InstanceKey(row.index() as _); + row.col(|ui| { + let instance_path = + InstancePath::instance(self.entity_path.clone(), instance_key); + item_ui::instance_path_button_to( + ctx, + query, + db, + ui, + None, + &instance_path, + instance_key.syntax_highlighted(ui.style()), + ); + }); + row.col(|ui| { + ctx.component_ui_registry.ui( + ctx, + ui, + UiVerbosity::Small, + query, + db, + &self.entity_path, + &self.results, + &instance_key, + ); + }); }); }); - if num_instances > displayed_row { + + if num_instances > num_displayed_rows { ui.label(format!( "…and {} more.", - re_format::format_uint(num_instances - displayed_row) + re_format::format_uint(num_instances - num_displayed_rows) )); } } diff --git a/crates/re_data_ui/src/component_path.rs b/crates/re_data_ui/src/component_path.rs index 49496d789fe0..35af64c88430 100644 --- a/crates/re_data_ui/src/component_path.rs +++ b/crates/re_data_ui/src/component_path.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use re_log_types::ComponentPath; use re_viewer_context::{UiVerbosity, ViewerContext}; @@ -10,7 +12,7 @@ impl DataUi for ComponentPath { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let Self { entity_path, @@ -21,27 +23,31 @@ impl DataUi for ComponentPath { ui.label(format!( "Indicator component for the {archetype_name} archetype" )); - } else if let Some((_, _, component_data)) = - re_query::get_component_with_instances(store, query, entity_path, *component_name) - { - super::component::EntityComponentWithInstances { - entity_path: self.entity_path.clone(), - component_data, - } - .data_ui(ctx, ui, verbosity, query, store); - } else if let Some(entity_tree) = ctx.recording().tree().subtree(entity_path) { - if entity_tree.entity.components.contains_key(component_name) { - ui.label(""); + } else { + let results = + db.query_caches2() + .latest_at(db.store(), query, entity_path, [*component_name]); + if let Some(results) = results.components.get(component_name) { + crate::EntityLatestAtResults { + entity_path: entity_path.clone(), + component_name: *component_name, + results: Arc::clone(results), + } + .data_ui(ctx, ui, verbosity, query, db); + } else if let Some(entity_tree) = ctx.recording().tree().subtree(entity_path) { + if entity_tree.entity.components.contains_key(component_name) { + ui.label(""); + } else { + ui.label(format!( + "Entity {entity_path:?} has no component {component_name:?}" + )); + } } else { - ui.label(format!( - "Entity {entity_path:?} has no component {component_name:?}" - )); + ui.label( + ctx.re_ui + .error_text(format!("Unknown component path: {self}")), + ); } - } else { - ui.label( - ctx.re_ui - .error_text(format!("Unknown component path: {self}")), - ); } } } diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 28ed1571b684..e576b76c0b66 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,6 +1,6 @@ -use re_data_store::{DataStore, LatestAtQuery}; +use re_data_store::LatestAtQuery; +use re_entity_db::{external::re_query_cache2::CachedLatestAtComponentResults, EntityDb}; use re_log_types::{external::arrow2, EntityPath}; -use re_query::ComponentWithInstances; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; @@ -39,18 +39,13 @@ pub fn add_to_registry(registry: &mut Com registry.add( C::name(), Box::new( - |ctx, ui, verbosity, query, store, entity_path, component, instance| match component - .lookup::(instance) - { - Ok(component) => { - component.entity_data_ui(ctx, ui, verbosity, entity_path, query, store); - } - Err(re_query::QueryError::ComponentNotFound(_)) => { + |ctx, ui, verbosity, query, db, entity_path, component, instance| { + // TODO(#5607): what should happen if the promise is still pending? + if let Some(component) = component.instance::(db.resolver(), instance.0 as _) { + component.entity_data_ui(ctx, ui, verbosity, entity_path, query, db); + } else { ui.weak("(not found)"); } - Err(err) => { - re_log::warn_once!("Expected component {}, {}", C::name(), err); - } }, ), ); @@ -62,13 +57,20 @@ fn fallback_component_ui( ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &LatestAtQuery, - _store: &DataStore, + db: &EntityDb, _entity_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { + // TODO(#5607): what should happen if the promise is still pending? + let value = component + .component_name(db.resolver()) + .and_then(|component_name| { + component.instance_raw(db.resolver(), component_name, instance_key.0 as _) + }); + // No special ui implementation - use a generic one: - if let Some(value) = component.lookup_arrow(instance_key) { + if let Some(value) = value { arrow_ui(ui, verbosity, &*value); } else { ui.weak("(null)"); diff --git a/crates/re_data_ui/src/data.rs b/crates/re_data_ui/src/data.rs index 234a141c2b4f..ec481568d639 100644 --- a/crates/re_data_ui/src/data.rs +++ b/crates/re_data_ui/src/data.rs @@ -16,7 +16,7 @@ impl DataUi for [u8; 4] { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let [r, g, b, a] = self; let color = egui::Color32::from_rgba_unmultiplied(*r, *g, *b, *a); @@ -37,7 +37,7 @@ impl DataUi for Color { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let [r, g, b, a] = self.to_array(); let color = egui::Color32::from_rgba_unmultiplied(r, g, b, a); @@ -58,7 +58,7 @@ impl DataUi for ViewCoordinates { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small => { @@ -79,7 +79,7 @@ impl DataUi for re_types::datatypes::Mat3x3 { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { egui::Grid::new("mat3").num_columns(3).show(ui, |ui| { ui.monospace(self[0].to_string()); @@ -107,7 +107,7 @@ impl DataUi for re_types::datatypes::Vec2D { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { ui.label(self.to_string()); } @@ -120,7 +120,7 @@ impl DataUi for re_types::datatypes::Vec3D { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { ui.label(self.to_string()); } @@ -133,7 +133,7 @@ impl DataUi for LineStrip2D { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small | UiVerbosity::Reduced => { @@ -180,7 +180,7 @@ impl DataUi for LineStrip3D { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small | UiVerbosity::Reduced => { @@ -233,7 +233,7 @@ impl DataUi for MeshProperties { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let show_optional_indices = |ui: &mut egui::Ui| { if let Some(indices) = self.indices.as_ref() { diff --git a/crates/re_data_ui/src/data_source.rs b/crates/re_data_ui/src/data_source.rs index b1e90ccf1977..bdf3ed05db01 100644 --- a/crates/re_data_ui/src/data_source.rs +++ b/crates/re_data_ui/src/data_source.rs @@ -10,7 +10,7 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { ui.label(self.to_string()); diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index f00b01b17bcc..425cbc28eeca 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -1,9 +1,9 @@ // TODO(jleibs): Turn this into a trait use egui::NumExt as _; -use re_data_store::{DataStore, LatestAtQuery}; +use re_data_store::LatestAtQuery; +use re_entity_db::{external::re_query_cache2::CachedLatestAtComponentResults, EntityDb}; use re_log_types::EntityPath; -use re_query::ComponentWithInstances; use re_types::{ components::{ Color, MarkerShape, MarkerSize, Name, Radius, ScalarScattering, StrokeWidth, Text, @@ -20,16 +20,16 @@ fn edit_color_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_color = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_color(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_color(ctx, query, db, entity_path)); let current_color = current_color.into(); let mut edit_color = current_color; @@ -49,7 +49,7 @@ fn edit_color_ui( fn default_color( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> Color { Color::from_rgb(255, 255, 255) @@ -63,16 +63,16 @@ fn edit_text_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_text(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_text(ctx, query, db, entity_path)); let current_text = current_text.to_string(); let mut edit_text = current_text.clone(); @@ -90,7 +90,7 @@ fn edit_text_ui( fn default_text( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, entity_path: &EntityPath, ) -> Text { Text::from(entity_path.to_string()) @@ -103,16 +103,16 @@ fn edit_name_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_name(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_name(ctx, query, db, entity_path)); let current_text = current_text.to_string(); let mut edit_text = current_text.clone(); @@ -130,7 +130,7 @@ fn edit_name_ui( fn default_name( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, entity_path: &EntityPath, ) -> Name { Name::from(entity_path.to_string()) @@ -144,16 +144,16 @@ fn edit_scatter_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_scatter = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_scatter(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_scatter(ctx, query, db, entity_path)); let current_scatter = current_scatter.0; let mut edit_scatter = current_scatter; @@ -179,7 +179,7 @@ fn edit_scatter_ui( fn default_scatter( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> ScalarScattering { ScalarScattering::from(false) @@ -193,16 +193,16 @@ fn edit_radius_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_radius = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_radius(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_radius(ctx, query, db, entity_path)); let current_radius = current_radius.0; let mut edit_radius = current_radius; @@ -226,7 +226,7 @@ fn edit_radius_ui( fn default_radius( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> Radius { Radius::from(1.0) @@ -240,16 +240,16 @@ fn edit_marker_shape_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_marker_shape(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_marker_shape(ctx, query, db, entity_path)); let mut edit_marker = current_marker; @@ -290,7 +290,7 @@ fn edit_marker_shape_ui( fn default_marker_shape( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> MarkerShape { MarkerShape::default() @@ -326,16 +326,16 @@ fn edit_stroke_width_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_stroke_width = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_stroke_width(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_stroke_width(ctx, query, db, entity_path)); let current_stroke_width = current_stroke_width.0; let mut edit_stroke_width = current_stroke_width; @@ -359,7 +359,7 @@ fn edit_stroke_width_ui( fn default_stroke_width( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> StrokeWidth { StrokeWidth::from(1.0) @@ -373,16 +373,16 @@ fn edit_marker_size_ui( ui: &mut egui::Ui, _verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker_size = component - .lookup::(instance_key) - .ok() - .unwrap_or_else(|| default_marker_size(ctx, query, store, entity_path)); + // TODO(#5607): what should happen if the promise is still pending? + .instance::(db.resolver(), instance_key.0 as _) + .unwrap_or_else(|| default_marker_size(ctx, query, db, entity_path)); let current_marker_size = current_marker_size.0; let mut edit_marker_size = current_marker_size; @@ -406,7 +406,7 @@ fn edit_marker_size_ui( fn default_marker_size( _ctx: &ViewerContext<'_>, _query: &LatestAtQuery, - _store: &DataStore, + _db: &EntityDb, _entity_path: &EntityPath, ) -> MarkerSize { MarkerSize::from(1.0) @@ -416,16 +416,16 @@ fn default_marker_size( fn register_editor<'a, C: Component + Loggable + 'static>( registry: &mut re_viewer_context::ComponentUiRegistry, - default: fn(&ViewerContext<'_>, &LatestAtQuery, &DataStore, &EntityPath) -> C, + default: fn(&ViewerContext<'_>, &LatestAtQuery, &EntityDb, &EntityPath) -> C, edit: fn( &ViewerContext<'_>, &mut egui::Ui, UiVerbosity, &LatestAtQuery, - &DataStore, + &EntityDb, &EntityPath, &EntityPath, - &ComponentWithInstances, + &CachedLatestAtComponentResults, &re_types::components::InstanceKey, ), ) where @@ -433,8 +433,8 @@ fn register_editor<'a, C: Component + Loggable + 'static>( { registry.add_editor( C::name(), - Box::new(move |ctx, query, store, entity_path| { - let c = default(ctx, query, store, entity_path); + Box::new(move |ctx, query, db, entity_path| { + let c = default(ctx, query, db, entity_path); [c].into() }), Box::new(edit), diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index 4faa5b61b30d..57a0007fa6f4 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -12,7 +12,7 @@ impl crate::DataUi for EntityDb { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let re_ui = &ctx.re_ui; diff --git a/crates/re_data_ui/src/entity_path.rs b/crates/re_data_ui/src/entity_path.rs index c4dd7d1df55c..6348b21ddbac 100644 --- a/crates/re_data_ui/src/entity_path.rs +++ b/crates/re_data_ui/src/entity_path.rs @@ -10,8 +10,8 @@ impl DataUi for re_entity_db::EntityPath { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { - InstancePath::entity_splat(self.clone()).data_ui(ctx, ui, verbosity, query, store); + InstancePath::entity_splat(self.clone()).data_ui(ctx, ui, verbosity, query, db); } } diff --git a/crates/re_data_ui/src/image.rs b/crates/re_data_ui/src/image.rs index 0548957b5993..491320baeb82 100644 --- a/crates/re_data_ui/src/image.rs +++ b/crates/re_data_ui/src/image.rs @@ -34,7 +34,7 @@ impl EntityDataUi for re_types::components::TensorData { verbosity: UiVerbosity, entity_path: &re_log_types::EntityPath, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { re_tracing::profile_function!(); @@ -53,7 +53,7 @@ impl EntityDataUi for re_types::components::TensorData { tensor_ui( ctx, query, - store, + db, ui, verbosity, entity_path, @@ -74,7 +74,7 @@ impl EntityDataUi for re_types::components::TensorData { pub fn tensor_ui( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, verbosity: UiVerbosity, entity_path: &re_entity_db::EntityPath, @@ -90,7 +90,7 @@ pub fn tensor_ui( .entry(|c: &mut TensorStatsCache| c.entry(tensor_data_row_id, tensor)); let debug_name = entity_path.to_string(); - let meaning = image_meaning_for_entity(entity_path, query, store); + let meaning = image_meaning_for_entity(entity_path, query, db.store()); let meter = if meaning == TensorDataMeaning::Depth { // TODO(#5607): what should happen if the promise is still pending? diff --git a/crates/re_data_ui/src/instance_path.rs b/crates/re_data_ui/src/instance_path.rs index 192c4206d470..11152fedd6f0 100644 --- a/crates/re_data_ui/src/instance_path.rs +++ b/crates/re_data_ui/src/instance_path.rs @@ -1,6 +1,7 @@ +use std::sync::Arc; + use re_entity_db::InstancePath; use re_log_types::ComponentPath; -use re_query::get_component_with_instances; use re_viewer_context::{UiVerbosity, ViewerContext}; use super::DataUi; @@ -13,14 +14,17 @@ impl DataUi for InstancePath { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let Self { entity_path, instance_key, } = self; - let Some(components) = store.all_components(&query.timeline(), entity_path) else { + let Some(components) = ctx + .recording_store() + .all_components(&query.timeline(), entity_path) + else { if ctx.recording().is_known_entity(entity_path) { // This is fine - e.g. we're looking at `/world` and the user has only logged to `/world/car`. ui.label(format!( @@ -71,9 +75,13 @@ impl DataUi for InstancePath { .num_columns(2) .show(ui, |ui| { for component_name in normal_components { - let Some((_, _, component_data)) = - get_component_with_instances(store, query, entity_path, component_name) - else { + let results = db.query_caches2().latest_at( + db.store(), + query, + entity_path, + [component_name], + ); + let Some(results) = results.components.get(&component_name) else { continue; // no need to show components that are unset at this point in time }; @@ -84,20 +92,21 @@ impl DataUi for InstancePath { ); if instance_key.is_splat() { - super::component::EntityComponentWithInstances { + crate::EntityLatestAtResults { entity_path: entity_path.clone(), - component_data, + component_name, + results: Arc::clone(results), } - .data_ui(ctx, ui, UiVerbosity::Small, query, store); + .data_ui(ctx, ui, UiVerbosity::Small, query, db); } else { ctx.component_ui_registry.ui( ctx, ui, UiVerbosity::Small, query, - store, + db, entity_path, - &component_data, + results, instance_key, ); } diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 3d4c60dc58c2..001c3320297d 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -36,7 +36,7 @@ use super::DataUi; pub fn entity_path_button( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, entity_path: &EntityPath, @@ -44,7 +44,7 @@ pub fn entity_path_button( instance_path_button_to( ctx, query, - store, + db, ui, space_view_id, &InstancePath::entity_splat(entity_path.clone()), @@ -56,7 +56,7 @@ pub fn entity_path_button( pub fn entity_path_parts_buttons( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, entity_path: &EntityPath, @@ -68,7 +68,7 @@ pub fn entity_path_parts_buttons( // Show one single icon up-front instead: let instance_path = InstancePath::entity_splat(entity_path.clone()); - ui.add(instance_path_icon(&query.timeline(), store, &instance_path).as_image()); + ui.add(instance_path_icon(&query.timeline(), db, &instance_path).as_image()); let mut accumulated = Vec::new(); for part in entity_path.iter() { @@ -78,7 +78,7 @@ pub fn entity_path_parts_buttons( instance_path_button_to_ex( ctx, query, - store, + db, ui, space_view_id, &InstancePath::entity_splat(accumulated.clone().into()), @@ -94,7 +94,7 @@ pub fn entity_path_parts_buttons( pub fn entity_path_button_to( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, entity_path: &EntityPath, @@ -103,7 +103,7 @@ pub fn entity_path_button_to( instance_path_button_to( ctx, query, - store, + db, ui, space_view_id, &InstancePath::entity_splat(entity_path.clone()), @@ -115,7 +115,7 @@ pub fn entity_path_button_to( pub fn instance_path_button( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, instance_path: &InstancePath, @@ -123,7 +123,7 @@ pub fn instance_path_button( instance_path_button_to( ctx, query, - store, + db, ui, space_view_id, instance_path, @@ -137,12 +137,13 @@ pub fn instance_path_button( /// _on the current timeline_. pub fn instance_path_icon( timeline: &re_data_store::Timeline, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, instance_path: &InstancePath, ) -> &'static icons::Icon { if instance_path.is_splat() { // It is an entity path - if store + if db + .store() .all_components(timeline, &instance_path.entity_path) .is_some() { @@ -186,29 +187,20 @@ pub fn guess_instance_path_icon( instance_path: &InstancePath, ) -> &'static re_ui::icons::Icon { let (query, db) = guess_query_and_db_for_selected_entity(ctx, &instance_path.entity_path); - instance_path_icon(&query.timeline(), db.store(), instance_path) + instance_path_icon(&query.timeline(), db, instance_path) } /// Show an instance id and make it selectable. pub fn instance_path_button_to( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, instance_path: &InstancePath, text: impl Into, ) -> egui::Response { - instance_path_button_to_ex( - ctx, - query, - store, - ui, - space_view_id, - instance_path, - text, - true, - ) + instance_path_button_to_ex(ctx, query, db, ui, space_view_id, instance_path, text, true) } /// Show an instance id and make it selectable. @@ -216,7 +208,7 @@ pub fn instance_path_button_to( fn instance_path_button_to_ex( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, instance_path: &InstancePath, @@ -232,7 +224,7 @@ fn instance_path_button_to_ex( let response = if with_icon { ctx.re_ui.selectable_label_with_icon( ui, - instance_path_icon(&query.timeline(), store, instance_path), + instance_path_icon(&query.timeline(), db, instance_path), text, ctx.selection().contains_item(&item), re_ui::LabelStyle::Normal, @@ -242,7 +234,7 @@ fn instance_path_button_to_ex( }; let response = response.on_hover_ui(|ui| { - instance_hover_card_ui(ui, ctx, query, store, instance_path); + instance_hover_card_ui(ui, ctx, query, db, instance_path); }); cursor_interact_with_selectable(ctx, response, item) @@ -252,7 +244,7 @@ fn instance_path_button_to_ex( pub fn instance_path_parts_buttons( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, space_view_id: Option, instance_path: &InstancePath, @@ -263,7 +255,7 @@ pub fn instance_path_parts_buttons( ui.spacing_mut().item_spacing.x = 2.0; // Show one single icon up-front instead: - ui.add(instance_path_icon(&query.timeline(), store, instance_path).as_image()); + ui.add(instance_path_icon(&query.timeline(), db, instance_path).as_image()); let mut accumulated = Vec::new(); for part in instance_path.entity_path.iter() { @@ -273,7 +265,7 @@ pub fn instance_path_parts_buttons( instance_path_button_to_ex( ctx, query, - store, + db, ui, space_view_id, &InstancePath::entity_splat(accumulated.clone().into()), @@ -287,7 +279,7 @@ pub fn instance_path_parts_buttons( instance_path_button_to_ex( ctx, query, - store, + db, ui, space_view_id, instance_path, @@ -413,7 +405,7 @@ pub fn component_path_button_to( pub fn data_blueprint_button_to( ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ui: &mut egui::Ui, text: impl Into, space_view_id: SpaceViewId, @@ -426,7 +418,7 @@ pub fn data_blueprint_button_to( let response = ui .selectable_label(ctx.selection().contains_item(&item), text) .on_hover_ui(|ui| { - entity_hover_card_ui(ui, ctx, query, store, entity_path); + entity_hover_card_ui(ui, ctx, query, db, entity_path); }); cursor_interact_with_selectable(ctx, response, item) } @@ -510,7 +502,7 @@ pub fn instance_hover_card_ui( ui: &mut egui::Ui, ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, instance_path: &InstancePath, ) { if !ctx.recording().is_known_entity(&instance_path.entity_path) { @@ -537,7 +529,7 @@ pub fn instance_hover_card_ui( // TODO(emilk): per-component stats } - instance_path.data_ui(ctx, ui, UiVerbosity::Reduced, query, store); + instance_path.data_ui(ctx, ui, UiVerbosity::Reduced, query, db); } /// Displays the "hover card" (i.e. big tooltip) for an entity. @@ -545,11 +537,11 @@ pub fn entity_hover_card_ui( ui: &mut egui::Ui, ctx: &ViewerContext<'_>, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, entity_path: &EntityPath, ) { let instance_path = InstancePath::entity_splat(entity_path.clone()); - instance_hover_card_ui(ui, ctx, query, store, &instance_path); + instance_hover_card_ui(ui, ctx, query, db, &instance_path); } pub fn app_id_button_ui( @@ -572,8 +564,8 @@ pub fn app_id_button_ui( ctx, ui, re_viewer_context::UiVerbosity::Reduced, - &ctx.current_query(), // unused - ctx.recording_store(), // unused + &ctx.current_query(), // unused + ctx.recording(), // unused ); }); @@ -601,7 +593,7 @@ pub fn data_source_button_ui( ui, re_viewer_context::UiVerbosity::Reduced, &ctx.current_query(), - ctx.recording_store(), // unused + ctx.recording(), // unused ); }); @@ -704,7 +696,7 @@ pub fn entity_db_button_ui( ui, re_viewer_context::UiVerbosity::Reduced, &ctx.current_query(), - entity_db.store(), + entity_db, ); }); diff --git a/crates/re_data_ui/src/lib.rs b/crates/re_data_ui/src/lib.rs index 24f54eb4fa20..ab92ba5fd344 100644 --- a/crates/re_data_ui/src/lib.rs +++ b/crates/re_data_ui/src/lib.rs @@ -35,7 +35,7 @@ pub use crate::image::{ show_zoomed_image_region, show_zoomed_image_region_area_outline, tensor_summary_ui_grid_contents, }; -pub use component::EntityComponentWithInstances; +pub use component::EntityLatestAtResults; pub use component_ui_registry::{add_to_registry, create_component_ui_registry}; pub use image_meaning::image_meaning_for_entity; @@ -71,7 +71,7 @@ pub trait DataUi { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ); } @@ -87,7 +87,7 @@ pub trait EntityDataUi { verbosity: UiVerbosity, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ); } @@ -102,12 +102,12 @@ where verbosity: UiVerbosity, entity: &EntityPath, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { // This ensures that UI state is maintained per entity. For example, the collapsed state for // `AnnotationContext` component is not saved by all instances of the component. ui.push_id(entity.hash(), |ui| { - self.data_ui(ctx, ui, verbosity, query, store); + self.data_ui(ctx, ui, verbosity, query, db); }); } } @@ -121,7 +121,7 @@ impl DataUi for TimePoint { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { ui.vertical(|ui| { egui::Grid::new("time_point").num_columns(2).show(ui, |ui| { @@ -143,7 +143,7 @@ impl DataUi for [DataCell] { ui: &mut egui::Ui, verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let mut sorted = self.to_vec(); sorted.sort_by_key(|cb| cb.component_name()); diff --git a/crates/re_data_ui/src/log_msg.rs b/crates/re_data_ui/src/log_msg.rs index a6636b5983e3..86559d0d0e67 100644 --- a/crates/re_data_ui/src/log_msg.rs +++ b/crates/re_data_ui/src/log_msg.rs @@ -13,11 +13,11 @@ impl DataUi for LogMsg { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match self { - LogMsg::SetStoreInfo(msg) => msg.data_ui(ctx, ui, verbosity, query, store), - LogMsg::ArrowMsg(_, msg) => msg.data_ui(ctx, ui, verbosity, query, store), + LogMsg::SetStoreInfo(msg) => msg.data_ui(ctx, ui, verbosity, query, db), + LogMsg::ArrowMsg(_, msg) => msg.data_ui(ctx, ui, verbosity, query, db), LogMsg::BlueprintActivationCommand(BlueprintActivationCommand { blueprint_id, make_active, @@ -38,7 +38,7 @@ impl DataUi for SetStoreInfo { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let SetStoreInfo { row_id: _, info } = self; let StoreInfo { @@ -96,7 +96,7 @@ impl DataUi for ArrowMsg { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let table = match DataTable::from_arrow_msg(self) { Ok(table) => table, @@ -115,15 +115,15 @@ impl DataUi for ArrowMsg { Ok(row) => { egui::Grid::new("fields").num_columns(2).show(ui, |ui| { ui.monospace("entity_path:"); - item_ui::entity_path_button(ctx, query, store, ui, None, row.entity_path()); + item_ui::entity_path_button(ctx, query, db, ui, None, row.entity_path()); ui.end_row(); ui.monospace("time_point:"); - row.timepoint().data_ui(ctx, ui, verbosity, query, store); + row.timepoint().data_ui(ctx, ui, verbosity, query, db); ui.end_row(); ui.monospace("components:"); - row.cells().data_ui(ctx, ui, verbosity, query, store); + row.cells().data_ui(ctx, ui, verbosity, query, db); ui.end_row(); }); } diff --git a/crates/re_data_ui/src/material.rs b/crates/re_data_ui/src/material.rs index d17aba5c17a9..1e39d0197b57 100644 --- a/crates/re_data_ui/src/material.rs +++ b/crates/re_data_ui/src/material.rs @@ -10,11 +10,11 @@ impl DataUi for Material { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let show_optional_albedo_factor = |ui: &mut egui::Ui| { if let Some(albedo_factor) = self.albedo_factor { - Color(albedo_factor).data_ui(ctx, ui, verbosity, query, store); + Color(albedo_factor).data_ui(ctx, ui, verbosity, query, db); } else { ui.weak("(empty)"); } diff --git a/crates/re_data_ui/src/pinhole.rs b/crates/re_data_ui/src/pinhole.rs index 7b8b48b06838..0237e5b25e04 100644 --- a/crates/re_data_ui/src/pinhole.rs +++ b/crates/re_data_ui/src/pinhole.rs @@ -10,7 +10,7 @@ impl DataUi for PinholeProjection { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { if verbosity == UiVerbosity::Small { // See if this is a trivial pinhole, and can be displayed as such: @@ -24,12 +24,12 @@ impl DataUi for PinholeProjection { }; ui.label(format!("Focal length: {fl}\nPrincipal point: {pp}")) - .on_hover_ui(|ui| self.data_ui(ctx, ui, UiVerbosity::Reduced, query, store)); + .on_hover_ui(|ui| self.data_ui(ctx, ui, UiVerbosity::Reduced, query, db)); return; } } - self.0.data_ui(ctx, ui, verbosity, query, store); + self.0.data_ui(ctx, ui, verbosity, query, db); } } @@ -40,7 +40,7 @@ impl DataUi for Resolution { ui: &mut egui::Ui, _verbosity: UiVerbosity, _query: &re_data_store::LatestAtQuery, - _store: &re_data_store::DataStore, + _db: &re_entity_db::EntityDb, ) { let [x, y] = self.0 .0; ui.monospace(format!("{x}x{y}")); diff --git a/crates/re_data_ui/src/rotation3d.rs b/crates/re_data_ui/src/rotation3d.rs index 5a30b308d885..5b17d32cacaf 100644 --- a/crates/re_data_ui/src/rotation3d.rs +++ b/crates/re_data_ui/src/rotation3d.rs @@ -13,9 +13,9 @@ impl DataUi for components::Rotation3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { - self.0.data_ui(ctx, ui, verbosity, query, store); + self.0.data_ui(ctx, ui, verbosity, query, db); } } @@ -26,7 +26,7 @@ impl DataUi for datatypes::Rotation3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match self { datatypes::Rotation3D::Quaternion(q) => { @@ -36,7 +36,7 @@ impl DataUi for datatypes::Rotation3D { datatypes::Rotation3D::AxisAngle(RotationAxisAngle { axis, angle }) => { egui::Grid::new("axis_angle").num_columns(2).show(ui, |ui| { ui.label("axis"); - axis.data_ui(ctx, ui, verbosity, query, store); + axis.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); ui.label("angle"); diff --git a/crates/re_data_ui/src/store_id.rs b/crates/re_data_ui/src/store_id.rs index 3aef5003ed2a..ca173439d8e2 100644 --- a/crates/re_data_ui/src/store_id.rs +++ b/crates/re_data_ui/src/store_id.rs @@ -5,10 +5,10 @@ impl crate::DataUi for re_log_types::StoreId { ui: &mut egui::Ui, verbosity: re_viewer_context::UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { if let Some(entity_db) = ctx.store_context.bundle.get(self) { - entity_db.data_ui(ctx, ui, verbosity, query, store); + entity_db.data_ui(ctx, ui, verbosity, query, db); } else { ui.label(format!("{} ID {} (not found)", self.kind, self.id)); } diff --git a/crates/re_data_ui/src/transform3d.rs b/crates/re_data_ui/src/transform3d.rs index bb81f4b75266..7b334afc9be1 100644 --- a/crates/re_data_ui/src/transform3d.rs +++ b/crates/re_data_ui/src/transform3d.rs @@ -11,13 +11,13 @@ impl DataUi for re_types::components::Transform3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small => { // TODO(andreas): Preview some information instead of just a label with hover ui. ui.label("3D transform").on_hover_ui(|ui| { - self.data_ui(ctx, ui, UiVerbosity::LimitHeight, query, store); + self.data_ui(ctx, ui, UiVerbosity::LimitHeight, query, db); }); } @@ -36,7 +36,7 @@ impl DataUi for re_types::components::Transform3D { ui.label("3D transform"); ui.indent("transform_repr", |ui| { ui.label(dir_string); - self.0.data_ui(ctx, ui, verbosity, query, store); + self.0.data_ui(ctx, ui, verbosity, query, db); }); }); } @@ -52,9 +52,9 @@ impl DataUi for re_types::components::OutOfTreeTransform3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { - re_types::components::Transform3D(self.0).data_ui(ctx, ui, verbosity, query, store); + re_types::components::Transform3D(self.0).data_ui(ctx, ui, verbosity, query, db); } } @@ -66,21 +66,21 @@ impl DataUi for Transform3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match verbosity { UiVerbosity::Small => { ui.label("3D transform").on_hover_ui(|ui| { - self.data_ui(ctx, ui, UiVerbosity::LimitHeight, query, store); + self.data_ui(ctx, ui, UiVerbosity::LimitHeight, query, db); }); } UiVerbosity::Full | UiVerbosity::LimitHeight | UiVerbosity::Reduced => match self { Transform3D::TranslationAndMat3x3(translation_matrix) => { - translation_matrix.data_ui(ctx, ui, verbosity, query, store); + translation_matrix.data_ui(ctx, ui, verbosity, query, db); } Transform3D::TranslationRotationScale(translation_rotation_scale) => { - translation_rotation_scale.data_ui(ctx, ui, verbosity, query, store); + translation_rotation_scale.data_ui(ctx, ui, verbosity, query, db); } }, } @@ -94,7 +94,7 @@ impl DataUi for TranslationRotationScale3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let TranslationRotationScale3D { translation, @@ -110,19 +110,19 @@ impl DataUi for TranslationRotationScale3D { // We still skip zero translations though since they are typically not logged explicitly. if let Some(translation) = translation { ui.label("translation"); - translation.data_ui(ctx, ui, verbosity, query, store); + translation.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } if let Some(rotation) = rotation { ui.label("rotation"); - rotation.data_ui(ctx, ui, verbosity, query, store); + rotation.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } if let Some(scale) = scale { ui.label("scale"); - scale.data_ui(ctx, ui, verbosity, query, store); + scale.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } }); @@ -136,14 +136,14 @@ impl DataUi for Scale3D { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { match self { Scale3D::Uniform(scale) => { ui.label(re_format::format_f32(*scale)); } Scale3D::ThreeD(v) => { - v.data_ui(ctx, ui, verbosity, query, store); + v.data_ui(ctx, ui, verbosity, query, db); } } } @@ -156,7 +156,7 @@ impl DataUi for TranslationAndMat3x3 { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let TranslationAndMat3x3 { translation, @@ -169,13 +169,13 @@ impl DataUi for TranslationAndMat3x3 { .show(ui, |ui| { if let Some(translation) = translation { ui.label("translation"); - translation.data_ui(ctx, ui, verbosity, query, store); + translation.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } if let Some(matrix) = mat3x3 { ui.label("matrix"); - matrix.data_ui(ctx, ui, verbosity, query, store); + matrix.data_ui(ctx, ui, verbosity, query, db); ui.end_row(); } }); diff --git a/crates/re_query2/src/promise.rs b/crates/re_query2/src/promise.rs index 65c44891b3af..a8f473c725a5 100644 --- a/crates/re_query2/src/promise.rs +++ b/crates/re_query2/src/promise.rs @@ -118,6 +118,15 @@ impl PromiseResult { } } + /// Returns the inner value if it's ready. + #[inline] + pub fn ok(self) -> Option { + match self { + PromiseResult::Ready(v) => Some(v), + _ => None, + } + } + /// Unwraps the resolved result if it's `Ready`, panics otherwise. #[inline] pub fn unwrap(self) -> T { diff --git a/crates/re_query_cache2/src/latest_at/helpers.rs b/crates/re_query_cache2/src/latest_at/helpers.rs index 559bc013336f..8ba0bb86d448 100644 --- a/crates/re_query_cache2/src/latest_at/helpers.rs +++ b/crates/re_query_cache2/src/latest_at/helpers.rs @@ -1,8 +1,227 @@ use re_data_store::{DataStore, LatestAtQuery}; use re_log_types::{EntityPath, RowId, TimeInt}; use re_types_core::Component; +use re_types_core::{external::arrow2::array::Array, ComponentName}; -use crate::{Caches, PromiseResolver, PromiseResult}; +use crate::{CachedLatestAtComponentResults, Caches, PromiseResolver, PromiseResult}; + +// --- + +impl CachedLatestAtComponentResults { + /// Returns the component data as a dense vector. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. + #[inline] + pub fn dense(&self, resolver: &PromiseResolver) -> Option<&[C]> { + let component_name = C::name(); + let level = re_log::Level::Warn; + match self.to_dense::(resolver).flatten() { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); + None + } + PromiseResult::Ready(data) => Some(data), + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data as an arrow array. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. + #[inline] + pub fn raw( + &self, + resolver: &PromiseResolver, + component_name: impl Into, + ) -> Option> { + let component_name = component_name.into(); + let level = re_log::Level::Warn; + match self.resolved(resolver) { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't get {component_name}: promise still pending"); + None + } + PromiseResult::Ready(cell) => Some(cell.to_arrow()), + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data of the single instance. + /// + /// This assumes that the row we get from the store only contains a single instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. + #[inline] + pub fn mono(&self, resolver: &PromiseResolver) -> Option { + let component_name = C::name(); + let level = re_log::Level::Warn; + match self.to_dense::(resolver).flatten() { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); + None + } + PromiseResult::Ready(data) if data.len() == 1 => Some(data[0].clone()), + PromiseResult::Ready(data) => { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: not a mono-batch (length: {})", + data.len(), + ); + None + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data of the single instance as an arrow array. + /// + /// This assumes that the row we get from the store only contains a single instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. + #[inline] + pub fn mono_raw( + &self, + resolver: &PromiseResolver, + component_name: impl Into, + ) -> Option> { + let component_name = component_name.into(); + let level = re_log::Level::Warn; + match self.resolved(resolver) { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't get {component_name}: promise still pending"); + None + } + PromiseResult::Ready(cell) if cell.as_arrow_ref().len() == 1 => { + Some(cell.as_arrow_ref().sliced(0, 1)) + } + PromiseResult::Ready(cell) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: not a mono-batch (length: {})", + cell.as_arrow_ref().len(), + ); + None + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data of the specified instance. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized, or + /// the index doesn't exist. + #[inline] + pub fn instance(&self, resolver: &PromiseResolver, index: usize) -> Option { + let component_name = C::name(); + let level = re_log::Level::Warn; + match self.to_dense::(resolver).flatten() { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); + None + } + PromiseResult::Ready(data) => { + // TODO(#5303): Figure out we'd like to integrate clamping semantics into selection panel. + // + // For now, we simply always clamp, which is the closest to the legacy behavior that the UI + // expects. + let index = usize::min(index, data.len().saturating_sub(1)); + + if data.len() > index { + Some(data[index].clone()) + } else { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: index not found (index: {index}, length: {})", + data.len(), + ); + None + } + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } + + /// Returns the component data of the specified instance as an arrow array. + /// + /// Logs a warning and returns `None` if the component is missing or cannot be deserialized, or + /// the index doesn't exist. + #[inline] + pub fn instance_raw( + &self, + resolver: &PromiseResolver, + component_name: impl Into, + index: usize, + ) -> Option> { + let component_name = component_name.into(); + let level = re_log::Level::Warn; + match self.resolved(resolver) { + PromiseResult::Pending => { + re_log::debug_once!("Couldn't get {component_name}: promise still pending"); + None + } + PromiseResult::Ready(cell) if cell.as_arrow_ref().len() > index => { + Some(cell.as_arrow_ref().sliced(index, 1)) + } + PromiseResult::Ready(cell) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: index not found (index: {index}, length: {})", + cell.as_arrow_ref().len(), + ); + None + } + PromiseResult::Error(err) => { + re_log::log_once!( + level, + "Couldn't get {component_name}: {}", + re_error::format_ref(&*err), + ); + None + } + } + } +} // --- @@ -33,8 +252,6 @@ impl std::ops::Deref for CachedLatestAtMonoResult { } } -// --- - impl Caches { /// Get the latest index and value for a given dense [`re_types_core::Component`]. /// diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index 3355be18c032..c8a07e39cbd7 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -139,6 +139,15 @@ impl CachedLatestAtComponentResults { cached_heap_size_bytes: AtomicU64::new(0), } } + + /// Returns the [`ComponentName`] of the resolved data, if available. + #[inline] + pub fn component_name(&self, resolver: &PromiseResolver) -> Option { + match self.resolved(resolver) { + PromiseResult::Ready(cell) => Some(cell.component_name()), + _ => None, + } + } } impl SizeBytes for CachedLatestAtComponentResults { @@ -173,6 +182,16 @@ impl CachedLatestAtComponentResults { &self.index } + /// Returns the raw resolved data, if it's ready. + #[inline] + pub fn resolved(&self, resolver: &PromiseResolver) -> PromiseResult { + if let Some(cell) = self.promise.as_ref() { + resolver.resolve(cell) + } else { + PromiseResult::Pending + } + } + /// Returns the component data as a dense vector. /// /// Returns an error if the component is missing or cannot be deserialized. diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index 05f379c5c714..b6189eb53312 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -86,7 +86,6 @@ impl SpaceViewClass for DataframeSpaceView { .cloned() .collect(); - let store = ctx.recording_store(); let latest_at_query = query.latest_at_query(); let sorted_instance_paths: Vec<_>; @@ -108,7 +107,12 @@ impl SpaceViewClass for DataframeSpaceView { sorted_instance_paths = sorted_entity_paths .iter() .flat_map(|entity_path| { - sorted_instance_paths_for(entity_path, store, &query.timeline, &latest_at_query) + sorted_instance_paths_for( + entity_path, + ctx.recording_store(), + &query.timeline, + &latest_at_query, + ) }) .collect(); @@ -117,7 +121,7 @@ impl SpaceViewClass for DataframeSpaceView { sorted_components = sorted_entity_paths .iter() .flat_map(|entity_path| { - store + ctx.recording_store() .all_components(&query.timeline, entity_path) .unwrap_or_default() }) @@ -148,32 +152,34 @@ impl SpaceViewClass for DataframeSpaceView { // of bounds" (aka cannot be joined to a primary component). row.col(|ui| { - instance_path_button(ctx, &latest_at_query, store, ui, None, instance); + instance_path_button(ctx, &latest_at_query, ctx.recording(), ui, None, instance); }); - for comp in &sorted_components { + for component_name in &sorted_components { row.col(|ui| { // TODO(#4466): make it explicit if that value results // from a splat joint. - if let Some((_, _, comp_inst)) = + let results = ctx.recording().query_caches2().latest_at( + ctx.recording_store(), + &latest_at_query, + &instance.entity_path, + [*component_name], + ); + + if let Some(results) = // This is a duplicate of the one above, but this ok since this codes runs // *only* for visible rows. - get_component_with_instances( - store, - &latest_at_query, - &instance.entity_path, - *comp, - ) + results.components.get(component_name) { ctx.component_ui_registry.ui( ctx, ui, UiVerbosity::Small, &latest_at_query, - store, + ctx.recording(), &instance.entity_path, - &comp_inst, + results, &instance.instance_key, ); } else { diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index c7e32c1a09a3..53e822295b99 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -587,12 +587,18 @@ pub fn picking( item_ui::instance_path_button( ctx, &query.latest_at_query(), - store, + ctx.recording(), ui, Some(query.space_view_id), &instance_path, ); - instance_path.data_ui(ctx, ui, UiVerbosity::Reduced, &ctx.current_query(), store); + instance_path.data_ui( + ctx, + ui, + UiVerbosity::Reduced, + &ctx.current_query(), + ctx.recording(), + ); }) }; } @@ -673,7 +679,7 @@ fn image_hover_ui( ui, UiVerbosity::Small, &ctx.current_query(), - ctx.recording_store(), + ctx.recording(), ); } else { // Show it all, like we do for any other thing we hover @@ -682,7 +688,7 @@ fn image_hover_ui( ui, UiVerbosity::Small, &ctx.current_query(), - ctx.recording_store(), + ctx.recording(), ); } diff --git a/crates/re_space_view_text_log/src/space_view_class.rs b/crates/re_space_view_text_log/src/space_view_class.rs index d7b2ee356ecc..ca5d0ae97848 100644 --- a/crates/re_space_view_text_log/src/space_view_class.rs +++ b/crates/re_space_view_text_log/src/space_view_class.rs @@ -359,7 +359,6 @@ fn table_ui( body_clip_rect = Some(body.max_rect()); let query = ctx.current_query(); - let store = ctx.recording_store(); let row_heights = entries.iter().map(|te| calc_row_height(te)); body.heterogeneous_rows(row_heights, |mut row| { @@ -410,7 +409,7 @@ fn table_ui( item_ui::entity_path_button( ctx, &query, - store, + ctx.recording(), ui, None, &entry.entity_path, diff --git a/crates/re_time_panel/src/data_density_graph.rs b/crates/re_time_panel/src/data_density_graph.rs index 50c4e5896c48..3a73e4c1c224 100644 --- a/crates/re_time_panel/src/data_density_graph.rs +++ b/crates/re_time_panel/src/data_density_graph.rs @@ -371,7 +371,7 @@ pub fn data_density_graph_ui( data_dentity_graph_painter: &mut DataDensityGraphPainter, ctx: &ViewerContext<'_>, time_ctrl: &mut TimeControl, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, time_area_response: &egui::Response, time_area_painter: &egui::Painter, ui: &egui::Ui, @@ -497,7 +497,7 @@ pub fn data_density_graph_ui( show_row_ids_tooltip( ctx, time_ctrl, - store, + db, ui.ctx(), item, hovered_time_range, @@ -529,7 +529,7 @@ fn make_brighter(color: Color32) -> Color32 { fn show_row_ids_tooltip( ctx: &ViewerContext<'_>, time_ctrl: &TimeControl, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, egui_ctx: &egui::Context, item: &TimePanelItem, time_range: TimeRange, @@ -561,12 +561,12 @@ fn show_row_ids_tooltip( let component_path = ComponentPath::new(entity_path.clone(), *component_name); item_ui::component_path_button(ctx, ui, &component_path); ui.add_space(8.0); - component_path.data_ui(ctx, ui, verbosity, &query, store); + component_path.data_ui(ctx, ui, verbosity, &query, db); } else { let instance_path = re_entity_db::InstancePath::entity_splat(entity_path.clone()); - item_ui::instance_path_button(ctx, &query, store, ui, None, &instance_path); + item_ui::instance_path_button(ctx, &query, db, ui, None, &instance_path); ui.add_space(8.0); - instance_path.data_ui(ctx, ui, verbosity, &query, store); + instance_path.data_ui(ctx, ui, verbosity, &query, db); } }); } diff --git a/crates/re_time_panel/src/lib.rs b/crates/re_time_panel/src/lib.rs index 4e5c2e685d3a..6aea8b62c413 100644 --- a/crates/re_time_panel/src/lib.rs +++ b/crates/re_time_panel/src/lib.rs @@ -553,9 +553,9 @@ impl TimePanel { ) { let tree_has_data_in_current_timeline = time_ctrl.tree_has_data_in_current_timeline(tree); - let store = match self.source { - TimePanelSource::Recording => ctx.recording_store(), - TimePanelSource::Blueprint => ctx.store_context.blueprint.store(), + let db = match self.source { + TimePanelSource::Recording => ctx.recording(), + TimePanelSource::Blueprint => ctx.store_context.blueprint, }; // The last part of the path component @@ -632,7 +632,7 @@ impl TimePanel { ui, ctx, &time_ctrl.current_query(), - store, + db, &tree.path, ); }); @@ -689,7 +689,7 @@ impl TimePanel { &mut self.data_density_graph_painter, ctx, time_ctrl, - store, + db, time_area_response, time_area_painter, ui, @@ -807,16 +807,16 @@ impl TimePanel { highlight_timeline_row(ui, ctx, time_area_painter, &item.to_item(), &row_rect); - let store = match self.source { - TimePanelSource::Recording => ctx.recording_store(), - TimePanelSource::Blueprint => ctx.store_context.blueprint.store(), + let db = match self.source { + TimePanelSource::Recording => ctx.recording(), + TimePanelSource::Blueprint => ctx.store_context.blueprint, }; data_density_graph::data_density_graph_ui( &mut self.data_density_graph_painter, ctx, time_ctrl, - store, + db, time_area_response, time_area_painter, ui, diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index b69f46aca3b3..ae6e37ed0594 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -2,11 +2,10 @@ use std::collections::{BTreeMap, BTreeSet}; use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; +use re_data_store::LatestAtQuery; use re_data_ui::is_component_visible_in_ui; use re_entity_db::{EntityDb, InstancePath}; use re_log_types::{DataCell, DataRow, RowId, StoreKind}; -use re_query_cache::external::re_query::get_component_with_instances; use re_space_view::{determine_visualizable_entities, SpaceViewBlueprint}; use re_types_core::{ components::{InstanceKey, VisualizerOverrides}, @@ -33,7 +32,6 @@ pub fn override_ui( // entity from the blueprint-inspector since it isn't "part" of a space-view to provide // the overrides. let query = ctx.current_query(); - let store = ctx.recording_store(); let query_result = ctx.lookup_query_result(space_view.id); let Some(data_result) = query_result @@ -80,7 +78,7 @@ pub fn override_ui( add_new_override( ctx, &query, - store, + ctx.recording(), ui, &view_systems, &component_to_vis, @@ -142,23 +140,39 @@ pub fn override_ui( StoreKind::Blueprint => { let store = ctx.store_context.blueprint.store(); let query = ctx.blueprint_query; - get_component_with_instances(store, query, path, *component_name) + ctx.store_context + .blueprint + .query_caches2() + .latest_at(store, query, entity_path, [*component_name]) + .components + .get(component_name) + .cloned() /* arc */ } StoreKind::Recording => { - get_component_with_instances(store, &query, path, *component_name) + ctx.recording() + .query_caches2() + .latest_at( + ctx.recording_store(), + &query, + entity_path, + [*component_name], + ) + .components + .get(component_name) + .cloned() /* arc */ } }; - if let Some((_, _, component_data)) = component_data { + if let Some(results) = component_data { ctx.component_ui_registry.edit_ui( ctx, ui, UiVerbosity::Small, &query, - store, + ctx.recording(), path, &overrides.individual_override_path, - &component_data, + &results, instance_key, ); } else { @@ -176,7 +190,7 @@ pub fn override_ui( pub fn add_new_override( ctx: &ViewerContext<'_>, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, ui: &mut egui::Ui, view_systems: &re_viewer_context::VisualizerCollection, component_to_vis: &BTreeMap, @@ -228,7 +242,8 @@ pub fn add_new_override( let mut splat_cell: DataCell = [InstanceKey::SPLAT].into(); splat_cell.compute_size_bytes(); - let Some(mut initial_data) = store + let Some(mut initial_data) = db + .store() .latest_at(query, &data_result.entity_path, *component, &components) .and_then(|result| result.2[0].clone()) .and_then(|cell| { @@ -243,7 +258,7 @@ pub fn add_new_override( sys.initial_override_value( ctx, query, - store, + db.store(), &data_result.entity_path, component, ) @@ -253,7 +268,7 @@ pub fn add_new_override( ctx.component_ui_registry.default_value( ctx, query, - store, + db, &data_result.entity_path, component, ) diff --git a/crates/re_viewer/src/ui/recordings_panel.rs b/crates/re_viewer/src/ui/recordings_panel.rs index 880863647912..5f094b276516 100644 --- a/crates/re_viewer/src/ui/recordings_panel.rs +++ b/crates/re_viewer/src/ui/recordings_panel.rs @@ -202,8 +202,8 @@ fn app_and_its_recordings_ui( ctx, ui, UiVerbosity::Reduced, - &ctx.current_query(), // unused - ctx.recording_store(), // unused + &ctx.current_query(), // unused + ctx.recording(), // unused ); }); diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index d91d4a65bb44..b311b38055bd 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -148,13 +148,7 @@ impl SelectionPanel { } else { (ctx.current_query(), ctx.recording()) }; - data_ui_item.data_ui( - ctx, - ui, - multi_selection_verbosity, - &query, - db.store(), - ); + data_ui_item.data_ui(ctx, ui, multi_selection_verbosity, &query, db); }); } @@ -385,7 +379,7 @@ fn what_is_selected_ui( ui.horizontal(|ui| { ui.label("component of"); - item_ui::entity_path_button(ctx, &query, db.store(), ui, None, entity_path); + item_ui::entity_path_button(ctx, &query, db, ui, None, entity_path); }); list_existing_data_blueprints(ui, ctx, &entity_path.clone().into(), viewport); @@ -443,14 +437,7 @@ fn what_is_selected_ui( guess_query_and_db_for_selected_entity(ctx, &instance_path.entity_path); ui.horizontal(|ui| { ui.label("Parent"); - item_ui::entity_path_parts_buttons( - ctx, - &query, - db.store(), - ui, - None, - &parent, - ); + item_ui::entity_path_parts_buttons(ctx, &query, db, ui, None, &parent); }); } } @@ -492,7 +479,7 @@ fn what_is_selected_ui( item_ui::entity_path_parts_buttons( ctx, &query, - db.store(), + db, ui, Some(*space_view_id), &parent, @@ -550,7 +537,7 @@ fn list_existing_data_blueprints( item_ui::instance_path_button_to( ctx, &query, - db.store(), + db, ui, Some(*space_view_id), instance_path, @@ -1307,17 +1294,10 @@ fn depth_props_ui( if backproject_depth { ui.label("Pinhole"); - item_ui::entity_path_button( - ctx, - &query, - db.store(), - ui, - None, - &image_projection_ent_path, - ) - .on_hover_text( - "The entity path of the pinhole transform being used to do the backprojection.", - ); + item_ui::entity_path_button(ctx, &query, db, ui, None, &image_projection_ent_path) + .on_hover_text( + "The entity path of the pinhole transform being used to do the backprojection.", + ); ui.end_row(); depth_from_world_scale_ui(ui, &mut entity_props.depth_from_world_scale); diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 5ec1e81f08e9..f687e5ec6168 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -1,9 +1,10 @@ use std::collections::BTreeMap; -use re_data_store::{DataStore, LatestAtQuery}; -use re_entity_db::EntityPath; +use re_data_store::LatestAtQuery; +use re_entity_db::{ + external::re_query_cache2::CachedLatestAtComponentResults, EntityDb, EntityPath, +}; use re_log_types::DataCell; -use re_query::ComponentWithInstances; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; use crate::ViewerContext; @@ -39,9 +40,9 @@ type ComponentUiCallback = Box< &mut egui::Ui, UiVerbosity, &LatestAtQuery, - &DataStore, + &EntityDb, &EntityPath, - &ComponentWithInstances, + &CachedLatestAtComponentResults, &InstanceKey, ) + Send + Sync, @@ -53,17 +54,17 @@ type ComponentEditCallback = Box< &mut egui::Ui, UiVerbosity, &LatestAtQuery, - &DataStore, + &EntityDb, &EntityPath, &EntityPath, - &ComponentWithInstances, + &CachedLatestAtComponentResults, &InstanceKey, ) + Send + Sync, >; type DefaultValueCallback = Box< - dyn Fn(&ViewerContext<'_>, &LatestAtQuery, &DataStore, &EntityPath) -> DataCell + Send + Sync, + dyn Fn(&ViewerContext<'_>, &LatestAtQuery, &EntityDb, &EntityPath) -> DataCell + Send + Sync, >; /// How to display components in a Ui. @@ -119,14 +120,19 @@ impl ComponentUiRegistry { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &InstanceKey, ) { - re_tracing::profile_function!(component.name().full_name()); + let Some(component_name) = component.component_name(db.resolver()) else { + // TODO(#5607): what should happen if the promise is still pending? + return; + }; + + re_tracing::profile_function!(component_name.full_name()); - if component.name() == InstanceKey::name() { + if component_name == InstanceKey::name() { // The user wants to show a ui for the `InstanceKey` component - well, that's easy: ui.label(instance_key.to_string()); return; @@ -134,14 +140,14 @@ impl ComponentUiRegistry { let ui_callback = self .component_uis - .get(&component.name()) + .get(&component_name) .unwrap_or(&self.fallback_ui); (*ui_callback)( ctx, ui, verbosity, query, - store, + db, entity_path, component, instance_key, @@ -156,21 +162,26 @@ impl ComponentUiRegistry { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &ComponentWithInstances, + component: &CachedLatestAtComponentResults, instance_key: &InstanceKey, ) { - re_tracing::profile_function!(component.name().full_name()); + let Some(component_name) = component.component_name(db.resolver()) else { + // TODO(#5607): what should happen if the promise is still pending? + return; + }; + + re_tracing::profile_function!(component_name.full_name()); - if let Some((_, edit_callback)) = self.component_editors.get(&component.name()) { + if let Some((_, edit_callback)) = self.component_editors.get(&component_name) { (*edit_callback)( ctx, ui, verbosity, query, - store, + db, entity_path, override_path, component, @@ -183,7 +194,7 @@ impl ComponentUiRegistry { ui, verbosity, query, - store, + db, entity_path, component, instance_key, @@ -197,7 +208,7 @@ impl ComponentUiRegistry { &self, ctx: &ViewerContext<'_>, query: &LatestAtQuery, - store: &DataStore, + db: &EntityDb, entity_path: &EntityPath, component: &ComponentName, ) -> Option { @@ -205,6 +216,6 @@ impl ComponentUiRegistry { self.component_editors .get(component) - .map(|(default_value, _)| (*default_value)(ctx, query, store, entity_path)) + .map(|(default_value, _)| (*default_value)(ctx, query, db, entity_path)) } } diff --git a/crates/re_viewport/src/blueprint/data_ui.rs b/crates/re_viewport/src/blueprint/data_ui.rs index ae5010180662..7ed45bc2274a 100644 --- a/crates/re_viewport/src/blueprint/data_ui.rs +++ b/crates/re_viewport/src/blueprint/data_ui.rs @@ -11,10 +11,10 @@ impl DataUi for IncludedSpaceView { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let space_view: SpaceViewId = self.0.into(); - space_view.data_ui(ctx, ui, verbosity, query, store); + space_view.data_ui(ctx, ui, verbosity, query, db); } } @@ -26,10 +26,10 @@ impl DataUi for SpaceViewMaximized { ui: &mut egui::Ui, verbosity: UiVerbosity, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, + db: &re_entity_db::EntityDb, ) { let space_view: SpaceViewId = self.0.into(); - space_view.data_ui(ctx, ui, verbosity, query, store); + space_view.data_ui(ctx, ui, verbosity, query, db); } } diff --git a/crates/re_viewport/src/space_view_entity_picker.rs b/crates/re_viewport/src/space_view_entity_picker.rs index 4b59093a9537..23c268f67d63 100644 --- a/crates/re_viewport/src/space_view_entity_picker.rs +++ b/crates/re_viewport/src/space_view_entity_picker.rs @@ -154,7 +154,6 @@ fn add_entities_line_ui( re_tracing::profile_function!(); let query = ctx.current_query(); - let store = ctx.recording_store(); ui.horizontal(|ui| { let entity_path = &entity_tree.path; @@ -177,7 +176,7 @@ fn add_entities_line_ui( let response = item_ui::instance_path_button_to( ctx, &query, - store, + ctx.recording(), ui, Some(space_view.id), &InstancePath::entity_splat(entity_path.clone()), diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index aa57a27e67b1..602d91c32e0a 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -523,8 +523,6 @@ impl Viewport<'_, '_> { space_view_visible: bool, projection_mode: bool, ) { - let store = ctx.recording_store(); - let entity_path = node_or_path.path(); if projection_mode && entity_path == &space_view.space_origin { @@ -662,7 +660,13 @@ impl Viewport<'_, '_> { let response = response.on_hover_ui(|ui| { let query = ctx.current_query(); - re_data_ui::item_ui::entity_hover_card_ui(ui, ctx, &query, store, entity_path); + re_data_ui::item_ui::entity_hover_card_ui( + ui, + ctx, + &query, + ctx.recording(), + entity_path, + ); if empty_origin { ui.label(ctx.re_ui.warning_text( diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index 2c53a75d60b9..8c4bce111ac9 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -275,7 +275,7 @@ fn color_space_ui( item_ui::instance_path_button( ctx, &ctx.current_query(), - ctx.recording_store(), + ctx.recording(), ui, Some(query.space_view_id), &instance, @@ -285,7 +285,7 @@ fn color_space_ui( ui, UiVerbosity::Reduced, &ctx.current_query(), - ctx.recording_store(), + ctx.recording(), ); }); ctx.select_hovered_on_click(&interact, Item::DataResult(query.space_view_id, instance)); diff --git a/examples/rust/extend_viewer_ui/src/main.rs b/examples/rust/extend_viewer_ui/src/main.rs index d0ac54af050e..fbc37dee872b 100644 --- a/examples/rust/extend_viewer_ui/src/main.rs +++ b/examples/rust/extend_viewer_ui/src/main.rs @@ -1,8 +1,7 @@ //! This example shows how to wrap the Rerun Viewer in your own GUI. use re_viewer::external::{ - arrow2, eframe, egui, re_data_store, re_entity_db, re_log, re_log_types, re_memory, re_query, - re_types, + arrow2, eframe, egui, re_data_store, re_entity_db, re_log, re_log_types, re_memory, re_types, }; // By using `re_memory::AccountingAllocator` Rerun can keep track of exactly how much memory it is using, @@ -153,20 +152,26 @@ fn component_ui( // just show the last value logged for each component: let query = re_data_store::LatestAtQuery::latest(timeline); - if let Some((_, _, component)) = re_query::get_component_with_instances( + let results = entity_db.query_caches2().latest_at( entity_db.store(), &query, entity_path, - component_name, - ) { + [component_name], + ); + let component = results + .components + .get(&component_name) + .and_then(|result| result.raw(entity_db.resolver(), component_name)); + + if let Some(data) = component { egui::ScrollArea::vertical() .auto_shrink([false, true]) .show(ui, |ui| { // Iterate over all the instances (e.g. all the points in the point cloud): - for instance_key in component.instance_keys() { - if let Some(value) = component.lookup_arrow(&instance_key) { - ui.label(format_arrow(&*value)); - } + + let num_instances = data.len(); + for i in 0..num_instances { + ui.label(format_arrow(&*data.sliced(i, 1))); } }); }; From c53d3393aa999bffdd1f34308c8fc9cfe730be84 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 14:48:48 +0200 Subject: [PATCH 225/508] New data APIs 6: cached archetype queries (#5673) Introduce very high-level APIs that make it possible to query, resolve, deserialize and cache an entire archetype all at once. The core trait allowing this is the newly introduced `ToArchetype` trait: ```rust pub trait ToArchetype { fn to_archetype(&self, resolver: &crate::PromiseResolver) -> crate::PromiseResult; } ``` This trait is implemented for all builtins archetypes thanks to a new codegen pass. Implementing such a trait is tricky: one needs to know about this trait, archetypes, queries, caches, etc all in one single place. This is a recipe for a very nasty circular dependency chains. This PR makes it work for all archetypes except archetypes that are generated in `re_viewport`. These will need some special care in a follow-up PR (likely moving them out of there, and only reexporting them in `re_viewport`?). Update: related: - https://github.com/rerun-io/rerun/issues/5421 Here's how it looks in practice: ```rust let caches = re_query_cache2::Caches::new(&store); // First, get the results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. let results: CachedLatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), Points2D::all_components().iter().cloned(), // no generics! ); // Then make use of the `ToArchetype` helper trait in order to query, resolve, deserialize and // cache an entire archetype all at once. use re_query_cache2::ToArchetype as _; let arch: Points2D = match results.to_archetype(&resolver) { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } PromiseResult::Ready(arch) => arch, PromiseResult::Error(err) => return Err(err.into()), }; // With the data now fully resolved/converted and deserialized, some joining logic can be // applied if desired. // // In most cases this will be either a clamped zip, or no joining at all. let color_default_fn = || None; let label_default_fn = || None; let results = clamped_zip_1x2( arch.positions.iter(), arch.colors .iter() .flat_map(|colors| colors.iter().map(Some)), color_default_fn, arch.labels .iter() .flat_map(|labels| labels.iter().map(Some)), label_default_fn, ) .collect_vec(); eprintln!("results:\n{results:?}"); ``` --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- Cargo.lock | 4 +- crates/re_query2/benches/latest_at.rs | 8 +- crates/re_query2/examples/latest_at.rs | 6 +- crates/re_query2/src/latest_at/results.rs | 31 +- crates/re_query2/src/lib.rs | 14 + crates/re_query2/tests/latest_at.rs | 12 +- crates/re_query_cache2/Cargo.toml | 13 +- crates/re_query_cache2/benches/latest_at.rs | 8 +- crates/re_query_cache2/examples/latest_at.rs | 6 +- .../examples/latest_at_archetype.rs | 105 +++++++ .../re_query_cache2/src/latest_at/helpers.rs | 2 +- crates/re_query_cache2/src/latest_at/mod.rs | 3 + .../re_query_cache2/src/latest_at/results.rs | 27 +- .../src/latest_at/to_archetype/.gitattributes | 30 ++ .../to_archetype/annotation_context.rs | 51 ++++ .../src/latest_at/to_archetype/arrows2d.rs | 121 ++++++++ .../src/latest_at/to_archetype/arrows3d.rs | 121 ++++++++ .../src/latest_at/to_archetype/asset3d.rs | 83 ++++++ .../src/latest_at/to_archetype/bar_chart.rs | 65 +++++ .../src/latest_at/to_archetype/boxes2d.rs | 136 +++++++++ .../src/latest_at/to_archetype/boxes3d.rs | 136 +++++++++ .../src/latest_at/to_archetype/clear.rs | 51 ++++ .../src/latest_at/to_archetype/depth_image.rs | 83 ++++++ .../to_archetype/disconnected_space.rs | 51 ++++ .../src/latest_at/to_archetype/image.rs | 65 +++++ .../latest_at/to_archetype/line_strips2d.rs | 121 ++++++++ .../latest_at/to_archetype/line_strips3d.rs | 106 +++++++ .../src/latest_at/to_archetype/mesh3d.rs | 151 ++++++++++ .../src/latest_at/to_archetype/mod.rs | 28 ++ .../src/latest_at/to_archetype/pinhole.rs | 83 ++++++ .../src/latest_at/to_archetype/points2d.rs | 136 +++++++++ .../src/latest_at/to_archetype/points3d.rs | 121 ++++++++ .../src/latest_at/to_archetype/scalar.rs | 51 ++++ .../to_archetype/segmentation_image.rs | 65 +++++ .../src/latest_at/to_archetype/series_line.rs | 72 +++++ .../latest_at/to_archetype/series_point.rs | 91 ++++++ .../src/latest_at/to_archetype/tensor.rs | 51 ++++ .../latest_at/to_archetype/text_document.rs | 65 +++++ .../src/latest_at/to_archetype/text_log.rs | 79 +++++ .../src/latest_at/to_archetype/transform3d.rs | 51 ++++ .../to_archetype/view_coordinates.rs | 51 ++++ crates/re_query_cache2/src/lib.rs | 1 + crates/re_query_cache2/tests/latest_at.rs | 8 +- .../re_types_builder/src/codegen/rust/api.rs | 3 +- .../re_types_builder/src/codegen/rust/mod.rs | 1 + .../src/codegen/rust/to_archetype.rs | 274 ++++++++++++++++++ 46 files changed, 2795 insertions(+), 46 deletions(-) create mode 100644 crates/re_query_cache2/examples/latest_at_archetype.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/clear.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/image.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/mod.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs create mode 100644 crates/re_types_builder/src/codegen/rust/to_archetype.rs diff --git a/Cargo.lock b/Cargo.lock index eab6fd468f22..be632cbe1088 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2669,9 +2669,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "infer" diff --git a/crates/re_query2/benches/latest_at.rs b/crates/re_query2/benches/latest_at.rs index fbc5e5959225..15e41c055b8c 100644 --- a/crates/re_query2/benches/latest_at.rs +++ b/crates/re_query2/benches/latest_at.rs @@ -282,8 +282,8 @@ fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec().unwrap(); - let colors = results.get_or_empty::(); + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Color::name()); let points = points .iter_dense::(&resolver) @@ -324,8 +324,8 @@ fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec().unwrap(); - let colors = results.get_or_empty::(); + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Text::name()); let points = points .iter_dense::(&resolver) diff --git a/crates/re_query2/examples/latest_at.rs b/crates/re_query2/examples/latest_at.rs index 90e44f48d0f9..9fd0c7764e35 100644 --- a/crates/re_query2/examples/latest_at.rs +++ b/crates/re_query2/examples/latest_at.rs @@ -40,9 +40,9 @@ fn main() -> anyhow::Result<()> { // * `get_required` returns an error if the component batch is missing // * `get_or_empty` returns an empty set of results if the component if missing // * `get` returns an option - let points: &LatestAtComponentResults = results.get_required::()?; - let colors: &LatestAtComponentResults = results.get_or_empty::(); - let labels: &LatestAtComponentResults = results.get_or_empty::(); + let points: &LatestAtComponentResults = results.get_required(MyPoint::name())?; + let colors: &LatestAtComponentResults = results.get_or_empty(MyColor::name()); + let labels: &LatestAtComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query2/src/latest_at/results.rs b/crates/re_query2/src/latest_at/results.rs index 0a2800c153a0..aef7167423dc 100644 --- a/crates/re_query2/src/latest_at/results.rs +++ b/crates/re_query2/src/latest_at/results.rs @@ -43,34 +43,45 @@ impl LatestAtResults { self.components.contains_key(&component_name.into()) } - /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. #[inline] - pub fn get(&self) -> Option<&LatestAtComponentResults> { - self.components.get(&C::name()) + pub fn get( + &self, + component_name: impl Into, + ) -> Option<&LatestAtComponentResults> { + self.components.get(&component_name.into()) } - /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. /// /// Returns an error if the component is not present. #[inline] - pub fn get_required(&self) -> crate::Result<&LatestAtComponentResults> { - if let Some(component) = self.components.get(&C::name()) { + pub fn get_required( + &self, + component_name: impl Into, + ) -> crate::Result<&LatestAtComponentResults> { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { Ok(component) } else { Err(DeserializationError::MissingComponent { - component: C::name(), + component: component_name, backtrace: ::backtrace::Backtrace::new_unresolved(), } .into()) } } - /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. /// /// Returns empty results if the component is not present. #[inline] - pub fn get_or_empty(&self) -> &LatestAtComponentResults { - if let Some(component) = self.components.get(&C::name()) { + pub fn get_or_empty( + &self, + component_name: impl Into, + ) -> &LatestAtComponentResults { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { component } else { static DEFAULT: LatestAtComponentResults = LatestAtComponentResults::EMPTY; diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs index 531b1a24dfa1..ac92c6aed7c2 100644 --- a/crates/re_query2/src/lib.rs +++ b/crates/re_query2/src/lib.rs @@ -60,3 +60,17 @@ pub enum QueryError { } pub type Result = std::result::Result; + +// --- + +/// Helper extension trait to convert query results into [`re_types_core::Archetype`]s. +pub trait ToArchetype { + /// Converts the result into an [`re_types_core::Archetype`]. + /// + /// Automatically handles all aspects of the query process: deserialization, caching, promise + /// resolution, etc. + fn to_archetype( + &self, + resolver: &crate::PromiseResolver, + ) -> crate::PromiseResult>; +} diff --git a/crates/re_query2/tests/latest_at.rs b/crates/re_query2/tests/latest_at.rs index ad49831db10c..2ab2a5714302 100644 --- a/crates/re_query2/tests/latest_at.rs +++ b/crates/re_query2/tests/latest_at.rs @@ -60,10 +60,10 @@ fn simple_query() -> anyhow::Result<()> { Some(MyColor::from_rgb(255, 0, 0)), ]; - let points = results.get_required::()?; + let points = results.get_required(MyPoint::name())?; let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - let colors = results.get_or_empty::(); + let colors = results.get_or_empty(MyColor::name()); let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); @@ -130,10 +130,10 @@ fn static_query() -> anyhow::Result<()> { Some(MyColor::from_rgb(255, 0, 0)), ]; - let points = results.get_required::()?; + let points = results.get_required(MyPoint::name())?; let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - let colors = results.get_or_empty::(); + let colors = results.get_or_empty(MyColor::name()); let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); @@ -199,10 +199,10 @@ fn no_instance_join_query() -> anyhow::Result<()> { Some(MyColor::from_rgb(0, 255, 0)), ]; - let points = results.get_required::()?; + let points = results.get_required(MyPoint::name())?; let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - let colors = results.get_or_empty::(); + let colors = results.get_or_empty(MyColor::name()); let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); diff --git a/crates/re_query_cache2/Cargo.toml b/crates/re_query_cache2/Cargo.toml index c953b1124bf6..b87432ff1fb8 100644 --- a/crates/re_query_cache2/Cargo.toml +++ b/crates/re_query_cache2/Cargo.toml @@ -18,7 +18,10 @@ all-features = true [features] -default = [] +default = ["to_archetype"] + +## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. +to_archetype = ["dep:re_types"] [dependencies] # Rerun dependencies: @@ -31,6 +34,9 @@ re_query2.workspace = true re_tracing.workspace = true re_types_core.workspace = true +# Rerun dependencies (optional): +re_types = { workspace = true, optional = true } + # External dependencies: ahash.workspace = true anyhow.workspace = true @@ -57,6 +63,11 @@ similar-asserts.workspace = true bench = false +[[example]] +name = "latest_at_archetype" +required-features = ["to_archetype"] + + [[bench]] name = "flat_vec_deque" harness = false diff --git a/crates/re_query_cache2/benches/latest_at.rs b/crates/re_query_cache2/benches/latest_at.rs index f7c608209224..27e1824a0168 100644 --- a/crates/re_query_cache2/benches/latest_at.rs +++ b/crates/re_query_cache2/benches/latest_at.rs @@ -296,8 +296,8 @@ fn query_and_visit_points( Points2D::all_components().iter().cloned(), // no generics! ); - let points = results.get_required::().unwrap(); - let colors = results.get_or_empty::(); + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Color::name()); let points = points .iter_dense::(&resolver) @@ -347,8 +347,8 @@ fn query_and_visit_strings( Points2D::all_components().iter().cloned(), // no generics! ); - let points = results.get_required::().unwrap(); - let colors = results.get_or_empty::(); + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Text::name()); let points = points .iter_dense::(&resolver) diff --git a/crates/re_query_cache2/examples/latest_at.rs b/crates/re_query_cache2/examples/latest_at.rs index 160154bf0589..bb170472ff2a 100644 --- a/crates/re_query_cache2/examples/latest_at.rs +++ b/crates/re_query_cache2/examples/latest_at.rs @@ -41,9 +41,9 @@ fn main() -> anyhow::Result<()> { // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. - let points: &CachedLatestAtComponentResults = results.get_required::()?; - let colors: &CachedLatestAtComponentResults = results.get_or_empty::(); - let labels: &CachedLatestAtComponentResults = results.get_or_empty::(); + let points: &CachedLatestAtComponentResults = results.get_required(MyPoint::name())?; + let colors: &CachedLatestAtComponentResults = results.get_or_empty(MyColor::name()); + let labels: &CachedLatestAtComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query_cache2/examples/latest_at_archetype.rs b/crates/re_query_cache2/examples/latest_at_archetype.rs new file mode 100644 index 000000000000..f0ae3059e944 --- /dev/null +++ b/crates/re_query_cache2/examples/latest_at_archetype.rs @@ -0,0 +1,105 @@ +use itertools::Itertools; +use re_data_store::{DataStore, LatestAtQuery}; +use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; +use re_types::{ + archetypes::Points2D, + components::{Color, Position2D, Text}, +}; +use re_types_core::{Archetype as _, Loggable as _}; + +use re_query_cache2::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; + +// --- + +fn main() -> anyhow::Result<()> { + let store = store()?; + eprintln!("store:\n{}", store.to_data_table()?); + + let resolver = PromiseResolver::default(); + + let entity_path = "points"; + let timeline = Timeline::new("frame_nr", TimeType::Sequence); + let query = LatestAtQuery::latest(timeline); + eprintln!("query:{query:?}"); + + let caches = re_query_cache2::Caches::new(&store); + + // First, get the results for this query. + // + // They might or might not already be cached. We won't know for sure until we try to access + // each individual component's data below. + let results: CachedLatestAtResults = caches.latest_at( + &store, + &query, + &entity_path.into(), + Points2D::all_components().iter().cloned(), // no generics! + ); + + // Then make use of the `ToArchetype` helper trait in order to query, resolve, deserialize and + // cache an entire archetype all at once. + use re_query_cache2::ToArchetype as _; + + let arch: Points2D = match results.to_archetype(&resolver).flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + return Ok(()); + } + PromiseResult::Ready(arch) => arch, + PromiseResult::Error(err) => return Err(err.into()), + }; + + // With the data now fully resolved/converted and deserialized, some joining logic can be + // applied if desired. + // + // In most cases this will be either a clamped zip, or no joining at all. + + let color_default_fn = || None; + let label_default_fn = || None; + + let results = clamped_zip_1x2( + arch.positions.iter(), + arch.colors + .iter() + .flat_map(|colors| colors.iter().map(Some)), + color_default_fn, + arch.labels + .iter() + .flat_map(|labels| labels.iter().map(Some)), + label_default_fn, + ) + .collect_vec(); + + eprintln!("results:\n{results:?}"); + + Ok(()) +} + +// --- + +fn store() -> anyhow::Result { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + re_types::components::InstanceKey::name(), + Default::default(), + ); + + let entity_path = "points"; + + { + let timepoint = [build_frame_nr(123)]; + + let points = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + + let colors = vec![Color::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let labels = vec![Text("a".into()), Text("b".into())]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + store.insert_row(&row)?; + } + + Ok(store) +} diff --git a/crates/re_query_cache2/src/latest_at/helpers.rs b/crates/re_query_cache2/src/latest_at/helpers.rs index 8ba0bb86d448..9273e12e0fc9 100644 --- a/crates/re_query_cache2/src/latest_at/helpers.rs +++ b/crates/re_query_cache2/src/latest_at/helpers.rs @@ -276,7 +276,7 @@ impl Caches { re_tracing::profile_function!(); let results = self.latest_at(store, query, entity_path, [C::name()]); - let result = results.get::()?; + let result = results.get(C::name())?; let index @ (data_time, row_id) = *result.index(); diff --git a/crates/re_query_cache2/src/latest_at/mod.rs b/crates/re_query_cache2/src/latest_at/mod.rs index 4ed943205a5a..82fd889bce0b 100644 --- a/crates/re_query_cache2/src/latest_at/mod.rs +++ b/crates/re_query_cache2/src/latest_at/mod.rs @@ -2,6 +2,9 @@ mod helpers; mod query; mod results; +#[cfg(feature = "to_archetype")] +mod to_archetype; + pub use self::helpers::CachedLatestAtMonoResult; pub use self::query::LatestAtCache; pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index c8a07e39cbd7..99319de5d4b9 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -51,20 +51,29 @@ impl CachedLatestAtResults { /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. #[inline] - pub fn get(&self) -> Option<&CachedLatestAtComponentResults> { - self.components.get(&C::name()).map(|arc| &**arc) + pub fn get( + &self, + component_name: impl Into, + ) -> Option<&CachedLatestAtComponentResults> { + self.components + .get(&component_name.into()) + .map(|arc| &**arc) } /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] - pub fn get_required(&self) -> crate::Result<&CachedLatestAtComponentResults> { - if let Some(component) = self.components.get(&C::name()) { + pub fn get_required( + &self, + component_name: impl Into, + ) -> crate::Result<&CachedLatestAtComponentResults> { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { Ok(component) } else { Err(DeserializationError::MissingComponent { - component: C::name(), + component: component_name, backtrace: ::backtrace::Backtrace::new_unresolved(), } .into()) @@ -75,8 +84,12 @@ impl CachedLatestAtResults { /// /// Returns empty results if the component is not present. #[inline] - pub fn get_or_empty(&self) -> &CachedLatestAtComponentResults { - if let Some(component) = self.components.get(&C::name()) { + pub fn get_or_empty( + &self, + component_name: impl Into, + ) -> &CachedLatestAtComponentResults { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { component } else { static EMPTY: CachedLatestAtComponentResults = CachedLatestAtComponentResults::empty(); diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes b/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes new file mode 100644 index 000000000000..b074eccb685e --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes @@ -0,0 +1,30 @@ +# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs + +.gitattributes linguist-generated=true +annotation_context.rs linguist-generated=true +arrows2d.rs linguist-generated=true +arrows3d.rs linguist-generated=true +asset3d.rs linguist-generated=true +bar_chart.rs linguist-generated=true +boxes2d.rs linguist-generated=true +boxes3d.rs linguist-generated=true +clear.rs linguist-generated=true +depth_image.rs linguist-generated=true +disconnected_space.rs linguist-generated=true +image.rs linguist-generated=true +line_strips2d.rs linguist-generated=true +line_strips3d.rs linguist-generated=true +mesh3d.rs linguist-generated=true +mod.rs linguist-generated=true +pinhole.rs linguist-generated=true +points2d.rs linguist-generated=true +points3d.rs linguist-generated=true +scalar.rs linguist-generated=true +segmentation_image.rs linguist-generated=true +series_line.rs linguist-generated=true +series_point.rs linguist-generated=true +tensor.rs linguist-generated=true +text_document.rs linguist-generated=true +text_log.rs linguist-generated=true +transform3d.rs linguist-generated=true +view_coordinates.rs linguist-generated=true diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs new file mode 100644 index 000000000000..9b11a29180f6 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::AnnotationContext; + let context = match self.get_required(::name()) { + Ok(context) => context, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let context = match context.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::AnnotationContext { context }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs new file mode 100644 index 000000000000..7f058b601e53 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs @@ -0,0 +1,121 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Vector2D; + let vectors = match self.get_required(::name()) { + Ok(vectors) => vectors, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let vectors = match vectors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Position2D; + let origins = if let Some(origins) = self.get(::name()) { + match origins.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Arrows2D { + vectors, + origins, + radii, + colors, + labels, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs new file mode 100644 index 000000000000..1b8361441273 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs @@ -0,0 +1,121 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Vector3D; + let vectors = match self.get_required(::name()) { + Ok(vectors) => vectors, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let vectors = match vectors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Position3D; + let origins = if let Some(origins) = self.get(::name()) { + match origins.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Arrows3D { + vectors, + origins, + radii, + colors, + labels, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs new file mode 100644 index 000000000000..ea1848353286 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs @@ -0,0 +1,83 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Blob; + let blob = match self.get_required(::name()) { + Ok(blob) => blob, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let blob = match blob.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::MediaType; + let media_type = if let Some(media_type) = self.get(::name()) { + match media_type.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::OutOfTreeTransform3D; + let transform = if let Some(transform) = self.get(::name()) { + match transform.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Asset3D { + blob, + media_type, + transform, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs new file mode 100644 index 000000000000..208250b38c98 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let values = match self.get_required(::name()) { + Ok(values) => values, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let values = match values.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::BarChart { values, color }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs new file mode 100644 index 000000000000..a91d137e3f08 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs @@ -0,0 +1,136 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::HalfSizes2D; + let half_sizes = match self.get_required(::name()) { + Ok(half_sizes) => half_sizes, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let half_sizes = match half_sizes.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Position2D; + let centers = if let Some(centers) = self.get(::name()) { + match centers.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Boxes2D { + half_sizes, + centers, + colors, + radii, + labels, + draw_order, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs new file mode 100644 index 000000000000..eeda7ca0d848 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs @@ -0,0 +1,136 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::HalfSizes3D; + let half_sizes = match self.get_required(::name()) { + Ok(half_sizes) => half_sizes, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let half_sizes = match half_sizes.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Position3D; + let centers = if let Some(centers) = self.get(::name()) { + match centers.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Rotation3D; + let rotations = if let Some(rotations) = self.get(::name()) { + match rotations.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Boxes3D { + half_sizes, + centers, + rotations, + colors, + radii, + labels, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/clear.rs b/crates/re_query_cache2/src/latest_at/to_archetype/clear.rs new file mode 100644 index 000000000000..66f2a4fc0632 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/clear.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types_core::components::ClearIsRecursive; + let is_recursive = match self.get_required(::name()) { + Ok(is_recursive) => is_recursive, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let is_recursive = match is_recursive.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types_core::archetypes::Clear { is_recursive }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs b/crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs new file mode 100644 index 000000000000..72241e116757 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs @@ -0,0 +1,83 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let data = match self.get_required(::name()) { + Ok(data) => data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let data = match data.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::DepthMeter; + let meter = if let Some(meter) = self.get(::name()) { + match meter.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::DepthImage { + data, + meter, + draw_order, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs new file mode 100644 index 000000000000..fb260af9ea10 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::DisconnectedSpace; + let disconnected_space = match self.get_required(::name()) { + Ok(disconnected_space) => disconnected_space, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let disconnected_space = match disconnected_space.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::DisconnectedSpace { disconnected_space }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/image.rs b/crates/re_query_cache2/src/latest_at/to_archetype/image.rs new file mode 100644 index 000000000000..075dbb43ddf4 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/image.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let data = match self.get_required(::name()) { + Ok(data) => data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let data = match data.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Image { data, draw_order }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs new file mode 100644 index 000000000000..76aac8acec22 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs @@ -0,0 +1,121 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::LineStrip2D; + let strips = match self.get_required(::name()) { + Ok(strips) => strips, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let strips = match strips.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::LineStrips2D { + strips, + radii, + colors, + labels, + draw_order, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs new file mode 100644 index 000000000000..dab31b78577a --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs @@ -0,0 +1,106 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::LineStrip3D; + let strips = match self.get_required(::name()) { + Ok(strips) => strips, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let strips = match strips.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::LineStrips3D { + strips, + radii, + colors, + labels, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs new file mode 100644 index 000000000000..6b6ef86c0aef --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs @@ -0,0 +1,151 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Position3D; + let vertex_positions = match self.get_required(::name()) { + Ok(vertex_positions) => vertex_positions, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let vertex_positions = match vertex_positions.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::MeshProperties; + let mesh_properties = if let Some(mesh_properties) = self.get(::name()) { + match mesh_properties.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Vector3D; + let vertex_normals = if let Some(vertex_normals) = self.get(::name()) { + match vertex_normals.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let vertex_colors = if let Some(vertex_colors) = self.get(::name()) { + match vertex_colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Texcoord2D; + let vertex_texcoords = if let Some(vertex_texcoords) = self.get(::name()) { + match vertex_texcoords.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Material; + let mesh_material = if let Some(mesh_material) = self.get(::name()) { + match mesh_material.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::TensorData; + let albedo_texture = if let Some(albedo_texture) = self.get(::name()) { + match albedo_texture.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Mesh3D { + vertex_positions, + mesh_properties, + vertex_normals, + vertex_colors, + vertex_texcoords, + mesh_material, + albedo_texture, + class_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs b/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs new file mode 100644 index 000000000000..a66a21691f82 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs @@ -0,0 +1,28 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +mod annotation_context; +mod arrows2d; +mod arrows3d; +mod asset3d; +mod bar_chart; +mod boxes2d; +mod boxes3d; +mod clear; +mod depth_image; +mod disconnected_space; +mod image; +mod line_strips2d; +mod line_strips3d; +mod mesh3d; +mod pinhole; +mod points2d; +mod points3d; +mod scalar; +mod segmentation_image; +mod series_line; +mod series_point; +mod tensor; +mod text_document; +mod text_log; +mod transform3d; +mod view_coordinates; diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs b/crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs new file mode 100644 index 000000000000..8d7cd53ce764 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs @@ -0,0 +1,83 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::PinholeProjection; + let image_from_camera = match self.get_required(::name()) { + Ok(image_from_camera) => image_from_camera, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let image_from_camera = match image_from_camera.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Resolution; + let resolution = if let Some(resolution) = self.get(::name()) { + match resolution.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ViewCoordinates; + let camera_xyz = if let Some(camera_xyz) = self.get(::name()) { + match camera_xyz.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Pinhole { + image_from_camera, + resolution, + camera_xyz, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs new file mode 100644 index 000000000000..8bd79e0895fb --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs @@ -0,0 +1,136 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Position2D; + let positions = match self.get_required(::name()) { + Ok(positions) => positions, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let positions = match positions.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::KeypointId; + let keypoint_ids = if let Some(keypoint_ids) = self.get(::name()) { + match keypoint_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Points2D { + positions, + radii, + colors, + labels, + draw_order, + class_ids, + keypoint_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs new file mode 100644 index 000000000000..b2bc78bc0760 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs @@ -0,0 +1,121 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Position3D; + let positions = match self.get_required(::name()) { + Ok(positions) => positions, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let positions = match positions.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Radius; + let radii = if let Some(radii) = self.get(::name()) { + match radii.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let colors = if let Some(colors) = self.get(::name()) { + match colors.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Text; + let labels = if let Some(labels) = self.get(::name()) { + match labels.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::ClassId; + let class_ids = if let Some(class_ids) = self.get(::name()) { + match class_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::KeypointId; + let keypoint_ids = if let Some(keypoint_ids) = self.get(::name()) { + match keypoint_ids.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::Points3D { + positions, + radii, + colors, + labels, + class_ids, + keypoint_ids, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs b/crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs new file mode 100644 index 000000000000..89594fd0bd5e --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Scalar; + let scalar = match self.get_required(::name()) { + Ok(scalar) => scalar, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let scalar = match scalar.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::Scalar { scalar }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs new file mode 100644 index 000000000000..5e09d7522f89 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let data = match self.get_required(::name()) { + Ok(data) => data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let data = match data.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::DrawOrder; + let draw_order = if let Some(draw_order) = self.get(::name()) { + match draw_order.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::SegmentationImage { data, draw_order }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs b/crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs new file mode 100644 index 000000000000..83f309cd79ed --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs @@ -0,0 +1,72 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::StrokeWidth; + let width = if let Some(width) = self.get(::name()) { + match width.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Name; + let name = if let Some(name) = self.get(::name()) { + match name.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::SeriesLine { color, width, name }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs b/crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs new file mode 100644 index 000000000000..8e7f5faa6a2c --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs @@ -0,0 +1,91 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::MarkerShape; + let marker = if let Some(marker) = self.get(::name()) { + match marker.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Name; + let name = if let Some(name) = self.get(::name()) { + match name.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::MarkerSize; + let marker_size = if let Some(marker_size) = self.get(::name()) { + match marker_size.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::SeriesPoint { + color, + marker, + name, + marker_size, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs b/crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs new file mode 100644 index 000000000000..8144906d8d73 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::TensorData; + let data = match self.get_required(::name()) { + Ok(data) => data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let data = match data.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::Tensor { data }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs b/crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs new file mode 100644 index 000000000000..c644acbd170b --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Text; + let text = match self.get_required(::name()) { + Ok(text) => text, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let text = match text.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::MediaType; + let media_type = if let Some(media_type) = self.get(::name()) { + match media_type.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::TextDocument { text, media_type }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs b/crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs new file mode 100644 index 000000000000..759cd69501aa --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs @@ -0,0 +1,79 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Text; + let text = match self.get_required(::name()) { + Ok(text) => text, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let text = match text.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::TextLogLevel; + let level = if let Some(level) = self.get(::name()) { + match level.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::archetypes::TextLog { text, level, color }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs new file mode 100644 index 000000000000..16a9cd0cc53a --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::Transform3D; + let transform = match self.get_required(::name()) { + Ok(transform) => transform, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let transform = match transform.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::Transform3D { transform }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs new file mode 100644 index 000000000000..9d4a252d55da --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs @@ -0,0 +1,51 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::components::ViewCoordinates; + let xyz = match self.get_required(::name()) { + Ok(xyz) => xyz, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let xyz = match xyz.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + // --- + + let arch = re_types::archetypes::ViewCoordinates { xyz }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/lib.rs b/crates/re_query_cache2/src/lib.rs index 49e5ce210e3b..58e3f4b46669 100644 --- a/crates/re_query_cache2/src/lib.rs +++ b/crates/re_query_cache2/src/lib.rs @@ -14,6 +14,7 @@ pub(crate) use self::latest_at::LatestAtCache; pub use re_query2::{ clamped_zip::*, Promise, PromiseId, PromiseResolver, PromiseResult, QueryError, Result, + ToArchetype, }; pub mod external { diff --git a/crates/re_query_cache2/tests/latest_at.rs b/crates/re_query_cache2/tests/latest_at.rs index b87b1bb02da6..4af2ba0b8f12 100644 --- a/crates/re_query_cache2/tests/latest_at.rs +++ b/crates/re_query_cache2/tests/latest_at.rs @@ -486,13 +486,13 @@ fn query_and_compare( MyPoints::all_components().iter().copied(), ); - let cached_points = cached.get_required::().unwrap(); + let cached_points = cached.get_required(MyPoint::name()).unwrap(); let cached_point_data = cached_points .to_dense::(&resolver) .flatten() .unwrap(); - let cached_colors = cached.get_or_empty::(); + let cached_colors = cached.get_or_empty(MyColor::name()); let cached_color_data = cached_colors .to_sparse::(&resolver) .flatten() @@ -505,13 +505,13 @@ fn query_and_compare( MyPoints::all_components().iter().copied(), ); - let expected_points = expected.get_required::().unwrap(); + let expected_points = expected.get_required(MyPoint::name()).unwrap(); let expected_point_data = expected_points .to_dense::(&resolver) .flatten() .unwrap(); - let expected_colors = expected.get_or_empty::(); + let expected_colors = expected.get_or_empty(MyColor::name()); let expected_color_data = expected_colors .to_sparse::(&resolver) .flatten() diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index a89613137681..03bef116e80b 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -31,7 +31,7 @@ use crate::{ use super::{ arrow::quote_fqname_as_type_path, blueprint_validation::generate_blueprint_validation, - util::string_from_quoted, + to_archetype::generate_to_archetype_impls, util::string_from_quoted, }; // --- @@ -72,6 +72,7 @@ impl CodeGenerator for RustCodeGenerator { } generate_blueprint_validation(reporter, objects, &mut files_to_write); + generate_to_archetype_impls(reporter, objects, &mut files_to_write); files_to_write } diff --git a/crates/re_types_builder/src/codegen/rust/mod.rs b/crates/re_types_builder/src/codegen/rust/mod.rs index 6179dffcc5dc..33a12cf821d7 100644 --- a/crates/re_types_builder/src/codegen/rust/mod.rs +++ b/crates/re_types_builder/src/codegen/rust/mod.rs @@ -5,6 +5,7 @@ mod arrow; mod blueprint_validation; mod deserializer; mod serializer; +mod to_archetype; mod util; pub use self::api::RustCodeGenerator; diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs new file mode 100644 index 000000000000..9c755a0e7b70 --- /dev/null +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -0,0 +1,274 @@ +//! Generates code in `re_query_cache2` so that cached results can easily be converted to +//! ready-to-use archetypes. +//! +//! That code needs to be generated directly in the caching crates as it needs access to the cached +//! queries and results as well as the promise resolving machinery. +//! Generating such code in the usual places would result in one giant cycle dependency chain. + +use std::collections::BTreeMap; + +use camino::Utf8PathBuf; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; + +use crate::{objects::FieldKind, Object, ObjectKind, Objects, Reporter}; + +// --- + +const NEWLINE_TOKEN: &str = "NEWLINE_TOKEN"; +const COMMENT_SEPARATOR_TOKEN: &str = "COMMENT_SEPARATOR_TOKEN"; +const COMMENT_REQUIRED_TOKEN: &str = "COMMENT_REQUIRED_TOKEN"; +const COMMENT_RECOMMENDED_OPTIONAL_TOKEN: &str = "COMMENT_RECOMMENDED_OPTIONAL_TOKEN"; + +pub fn generate_to_archetype_impls( + reporter: &Reporter, + objects: &Objects, + files_to_write: &mut BTreeMap, +) { + generate_mod(reporter, objects, files_to_write); + generate_impls(reporter, objects, files_to_write); +} + +fn generate_mod( + _reporter: &Reporter, + objects: &Objects, + files_to_write: &mut BTreeMap, +) { + let generated_path = + Utf8PathBuf::from("crates/re_query_cache2/src/latest_at/to_archetype/mod.rs"); + + let mut code = String::new(); + code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); + + let mut mods = Vec::new(); + + for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { + if obj.scope() == Some("blueprint".to_owned()) { + // TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. + continue; + } + + // TODO(#4478): add a 'testing' scope + if obj.fqname.contains("testing") { + continue; + } + + let arch_name = obj.snake_case_name(); + mods.push(format!("mod {arch_name};")); + } + + code.push_str(&mods.join("\n")); + + files_to_write.insert(generated_path, code); +} + +fn generate_impls( + _reporter: &Reporter, + objects: &Objects, + files_to_write: &mut BTreeMap, +) { + let generated_path = Utf8PathBuf::from("crates/re_query_cache2/src/latest_at/to_archetype"); + + let quoted_imports = quote! { + use std::sync::Arc; + + use re_query2::{PromiseResolver, PromiseResult}; + use re_types_core::{Archetype, Loggable as _}; + + use crate::CachedLatestAtResults; + }; + + for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { + if obj.scope() == Some("blueprint".to_owned()) { + // TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. + continue; + } + + if obj + .try_get_attr::(crate::ATTR_RUST_SERDE_TYPE) + .is_some() + { + // NOTE: legacy serde-based hacks. + continue; + } + + // TODO(#4478): add a 'testing' scope + if obj.fqname.contains("testing") { + continue; + } + + let quoted_imports = quoted_imports.to_string(); + let quoted_impl = quote_to_archetype_impl(objects, obj); + + let mut code = String::new(); + code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); + code.push_str("#![allow(unused_imports)]\n"); + code.push_str("#![allow(unused_parens)]\n"); + code.push_str("#![allow(clippy::clone_on_copy)]\n"); + if obj.deprecation_notice().is_some() { + code.push_str("#![allow(deprecated)]\n"); + } + code.push_str(&format!("\n\n{quoted_imports}\n\n")); + code.push_str("ed_impl.to_string()); + + let arch_name = obj.snake_case_name(); + files_to_write.insert( + generated_path.join([arch_name.as_str(), "rs"].join(".")), + code.replace(&format!("{NEWLINE_TOKEN:?}"), "\n\n") + .replace(&format!("{COMMENT_SEPARATOR_TOKEN:?}"), "\n\n// --- \n\n") + .replace( + &format!("{COMMENT_REQUIRED_TOKEN:?}"), + "\n\n// --- Required ---\n\n", + ) + .replace( + &format!("{COMMENT_RECOMMENDED_OPTIONAL_TOKEN:?}"), + "\n\n// --- Recommended/Optional ---\n\n", + ), + ); + } +} + +fn quote_to_archetype_impl(objects: &Objects, obj: &Object) -> TokenStream { + assert!(obj.kind == ObjectKind::Archetype); + + let quoted_arch_fqname = quote_fqname_as_type_path(&obj.crate_name(), &obj.fqname); + + let quoted_required = obj + .fields + .iter() + .filter(|obj_field| obj_field.kind() == Some(FieldKind::Required)) + .filter_map(|obj_field| { + let quoted_name = format_ident!("{}", obj_field.name); + + let type_fqname = obj_field.typ.fqname()?; + let type_name = type_fqname.rsplit_once('.').map(|(_, name)| name)?; + + let quoted_type_name = format_ident!("{type_name}"); + let quoted_type_fqname = + quote_fqname_as_type_path(&objects[type_fqname].crate_name(), type_fqname); + + let quoted_data = if obj_field.typ.is_plural() { + quote!(data.to_vec()) + } else { + quote! {{ + let Some(first) = data.first().cloned() else { + return PromiseResult::Error( + std::sync::Arc::new(re_types_core::DeserializationError::missing_data()) + ); + }; + first + }} + }; + + Some(quote! { + #NEWLINE_TOKEN + + use #quoted_type_fqname; + let #quoted_name = match self.get_required(<#quoted_type_name>::name()) { + Ok(#quoted_name) => #quoted_name, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let #quoted_name = match #quoted_name.to_dense::<#quoted_type_name>(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => #quoted_data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + }) + }); + + let quoted_optional = obj + .fields + .iter() + .filter(|obj_field| obj_field.kind() != Some(FieldKind::Required)) + .filter_map(|obj_field| { + let quoted_name = format_ident!("{}", obj_field.name); + + let type_fqname = obj_field.typ.fqname()?; + let type_name = type_fqname.rsplit_once('.').map(|(_, name)| name)?; + + let quoted_type_name = format_ident!("{type_name}"); + let quoted_type_fqname = + quote_fqname_as_type_path(&objects[type_fqname].crate_name(), type_fqname); + + let quoted_data = if obj_field.typ.is_plural() { + quote!(Some(data.to_vec())) + } else { + quote!(data.first().cloned()) + }; + + Some(quote! { + #NEWLINE_TOKEN + + use #quoted_type_fqname; + let #quoted_name = if let Some(#quoted_name) = self.get(<#quoted_type_name>::name()) { + match #quoted_name.to_dense::<#quoted_type_name>(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => #quoted_data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + }) + }); + + let quoted_fields = obj.fields.iter().map(|obj_field| { + let quoted_name = format_ident!("{}", obj_field.name); + quote!(#quoted_name) + }); + + quote! { + impl crate::ToArchetype<#quoted_arch_fqname> for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + #NEWLINE_TOKEN + re_tracing::profile_function!(<#quoted_arch_fqname>::name()); + #NEWLINE_TOKEN + + // --- Required --- + #COMMENT_REQUIRED_TOKEN + + #(#quoted_required)* + + // --- Recommended/Optional --- + #COMMENT_RECOMMENDED_OPTIONAL_TOKEN + + #(#quoted_optional)* + + // --- + #COMMENT_SEPARATOR_TOKEN + + // TODO(cmc): A lot of useless copying going on since archetypes are fully owned + // types. Probably fine for now since these are very high-level APIs anyhow. + let arch = #quoted_arch_fqname { + #(#quoted_fields),* + }; + + #NEWLINE_TOKEN + + PromiseResult::Ready(Ok(arch)) + } + } + } +} + +// --- + +// TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. +fn quote_fqname_as_type_path(crate_name: &str, fqname: impl AsRef) -> TokenStream { + let fqname = fqname + .as_ref() + .replace('.', "::") + .replace("rerun", crate_name); + let expr: syn::TypePath = syn::parse_str(&fqname).unwrap(); + quote!(#expr) +} From d4c6469d8348b5b203b3211c508c79ac4f5a4787 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 14:59:26 +0200 Subject: [PATCH 226/508] New data APIs 7: `RangeZip` iterator machinery (#5679) Code generator, and code generated, for the new `RangeZip` machinery. Similar to #5573, the code generation is implemented as a very low-tech binary in the crate itself (`src/bin/range_zip.rs`), that just spews the generated code on stdout. That seems like the right complexity-to-maintenance tradeoff, considering that iterator combinators don't really ever change. Here's an example of one of these combinators: ```rust /// Returns a new [`RangeZip2x2`] iterator. /// /// The number of elements in a range zip iterator corresponds to the number of elements in the /// shortest of its required iterators (`r0`, `r1`). /// /// Each call to `next` is guaranteed to yield the next value for each required iterator, /// as well as the most recent index amongst all of them. /// /// Optional iterators accumulate their state and yield their most recent value (if any), /// each time the required iterators fire. pub fn range_zip_2x2( r0: IR0, r1: IR1, o0: IO0, o1: IO1, ) -> RangeZip2x2 where Idx: std::cmp::Ord, IR0: IntoIterator, IR1: IntoIterator, IO0: IntoIterator, IO1: IntoIterator, { RangeZip2x2 { r0: r0.into_iter(), r1: r1.into_iter(), o0: o0.into_iter().peekable(), o1: o1.into_iter().peekable(), o0_data_latest: None, o1_data_latest: None, } } /// Implements a range zip iterator combinator with 2 required iterators and 2 optional /// iterators. /// /// See [`range_zip_2x2`] for more information. pub struct RangeZip2x2 where Idx: std::cmp::Ord, IR0: Iterator, IR1: Iterator, IO0: Iterator, IO1: Iterator, { r0: IR0, r1: IR1, o0: Peekable, o1: Peekable, o0_data_latest: Option, o1_data_latest: Option, } impl Iterator for RangeZip2x2 where Idx: std::cmp::Ord, IR0: Iterator, IR1: Iterator, IO0: Iterator, IO1: Iterator, O0: Clone, O1: Clone, { type Item = (Idx, R0, R1, Option, Option); #[inline] fn next(&mut self) -> Option { let Self { r0, r1, o0, o1, o0_data_latest, o1_data_latest, } = self; let Some((r0_index, r0_data)) = r0.next() else { return None; }; let Some((r1_index, r1_data)) = r1.next() else { return None; }; let max_index = [r0_index, r1_index].into_iter().max().unwrap(); let mut o0_data = None; while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { o0_data = Some(data); } let o0_data = o0_data.or(o0_data_latest.take()); *o0_data_latest = o0_data.clone(); let mut o1_data = None; while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { o1_data = Some(data); } let o1_data = o1_data.or(o1_data_latest.take()); *o1_data_latest = o1_data.clone(); Some((max_index, r0_data, r1_data, o0_data, o1_data)) } } ``` --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- crates/re_query2/Cargo.toml | 5 + crates/re_query2/src/bin/range_zip.rs | 503 +++ crates/re_query2/src/lib.rs | 4 +- crates/re_query2/src/range_zip/.gitattributes | 1 + crates/re_query2/src/range_zip/generated.rs | 3544 +++++++++++++++++ crates/re_query2/src/range_zip/mod.rs | 69 + 6 files changed, 4125 insertions(+), 1 deletion(-) create mode 100644 crates/re_query2/src/bin/range_zip.rs create mode 100644 crates/re_query2/src/range_zip/.gitattributes create mode 100644 crates/re_query2/src/range_zip/generated.rs create mode 100644 crates/re_query2/src/range_zip/mod.rs diff --git a/crates/re_query2/Cargo.toml b/crates/re_query2/Cargo.toml index e6e8ac693ae9..38cb50ac2807 100644 --- a/crates/re_query2/Cargo.toml +++ b/crates/re_query2/Cargo.toml @@ -73,6 +73,11 @@ name = "clamped_zip" required-features = ["codegen"] +[[bin]] +name = "range_zip" +required-features = ["codegen"] + + [[bench]] name = "latest_at" harness = false diff --git a/crates/re_query2/src/bin/range_zip.rs b/crates/re_query2/src/bin/range_zip.rs new file mode 100644 index 000000000000..f4af9aae0276 --- /dev/null +++ b/crates/re_query2/src/bin/range_zip.rs @@ -0,0 +1,503 @@ +//! CLI tool to generate `RangeZip` implementations of different arities. + +#![allow(clippy::tuple_array_conversions)] // false positive + +use itertools::{izip, Itertools}; + +struct Params { + num_required: usize, + num_optional: usize, +} + +impl Params { + fn to_num_required(&self) -> String { + self.num_required.to_string() + } + + fn to_num_optional(&self) -> String { + self.num_optional.to_string() + } + + /// `1x3`, `2x2`… + fn to_suffix(&self) -> String { + format!("{}x{}", self.to_num_required(), self.to_num_optional()) + } + + /// `r0, r1, r2…`. + fn to_required_names(&self) -> Vec { + (0..self.num_required) + .map(|n| format!("r{n}")) + .collect_vec() + } + + /// `R0, R1, R2…`. + fn to_required_types(&self) -> Vec { + self.to_required_names() + .into_iter() + .map(|s| s.to_uppercase()) + .collect() + } + + /// `r0: IR0, r1: IR1, r2: IR2…`. + fn to_required_params(&self) -> Vec { + izip!(self.to_required_names(), self.to_required_types()) + .map(|(n, t)| format!("{n}: I{t}")) + .collect() + } + + /// `IR0: (Into)Iterator, IR1: (Into)Iterator…` + fn to_required_clauses(&self, into: bool) -> Vec { + let trait_name = if into { "IntoIterator" } else { "Iterator" }; + self.to_required_types() + .into_iter() + .map(|t| format!("I{t}: {trait_name}")) + .collect() + } + + /// `o0, o1, o2…`. + fn to_optional_names(&self) -> Vec { + (0..self.num_optional) + .map(|n| format!("o{n}")) + .collect_vec() + } + + /// `O0, O1, O2…`. + fn to_optional_types(&self) -> Vec { + self.to_optional_names() + .into_iter() + .map(|s| s.to_uppercase()) + .collect() + } + + /// `o0: IO0, o1: IO1, o2: IO2…`. + fn to_optional_params(&self) -> Vec { + izip!(self.to_optional_names(), self.to_optional_types()) + .map(|(n, t)| format!("{n}: I{t}")) + .collect() + } + + /// `o0: Peekable, o1: Peekable, o2: Peekable…`. + fn to_optional_peekable_params(&self) -> Vec { + izip!(self.to_optional_names(), self.to_optional_types()) + .map(|(n, t)| format!("{n}: Peekable")) + .collect() + } + + /// `IO0: (Into)Iterator, IO1: (Into)Iterator…` + fn to_optional_clauses(&self, into: bool) -> Vec { + let trait_name = if into { "IntoIterator" } else { "Iterator" }; + self.to_optional_types() + .into_iter() + .map(|t| format!("I{t}: {trait_name}")) + .collect() + } +} + +fn backticked(strs: impl IntoIterator) -> Vec { + strs.into_iter().map(|s| format!("`{s}`")).collect() +} + +/// Output: +/// ```ignore +/// pub fn range_zip_2x2( +/// r0: IR0, +/// r1: IR1, +/// o0: IO0, +/// o1: IO1, +/// ) -> RangeZip2x2 +/// where +/// Idx: std::cmp::Ord, +/// IR0: IntoIterator, +/// IR1: IntoIterator, +/// IO0: IntoIterator, +/// IO1: IntoIterator, +/// { +/// RangeZip2x2 { +/// r0: r0.into_iter(), +/// r1: r1.into_iter(), +/// o0: o0.into_iter().peekable(), +/// o1: o1.into_iter().peekable(), +/// +/// o0_data_latest: None, +/// o1_data_latest: None, +/// } +/// } +/// ``` +fn generate_helper_func(params: &Params) -> String { + let suffix = params.to_suffix(); + let required_names = backticked(params.to_required_names()).join(", "); + let required_types = izip!( + params + .to_required_types() + .into_iter() + .map(|t| format!("I{t}")), + params.to_required_types() + ) + .flat_map(|(tr, r)| [tr, r]) + .collect_vec() + .join(", "); + let optional_types = izip!( + params + .to_optional_types() + .into_iter() + .map(|t| format!("I{t}")), + params.to_optional_types() + ) + .flat_map(|(tr, r)| [tr, r]) + .collect_vec() + .join(", "); + let required_clauses = params.to_required_clauses(true /* into */).join(", "); + let optional_clauses = params.to_optional_clauses(true /* into */).join(", "); + let required_params = params.to_required_params().join(", "); + let optional_params = params.to_optional_params().join(", "); + + let ret_clause = params + .to_required_types() + .into_iter() + .map(|r| format!("I{r}::IntoIter, {r}")) + .chain( + params + .to_optional_types() + .into_iter() + .map(|o| format!("I{o}::IntoIter, {o}")), + ) + .collect_vec() + .join(", "); + + let ret = params + .to_required_names() + .into_iter() + .map(|r| format!("{r}: {r}.into_iter()")) + .chain( + params + .to_optional_names() + .into_iter() + .map(|o| format!("{o}: {o}.into_iter().peekable()")), + ) + .collect_vec() + .join(",\n"); + + let latest = params + .to_optional_names() + .into_iter() + .map(|o| format!("{o}_data_latest: None")) + .collect_vec() + .join(",\n"); + + format!( + r#" + /// Returns a new [`RangeZip{suffix}`] iterator. + /// + /// The number of elements in a range zip iterator corresponds to the number of elements in the + /// shortest of its required iterators ({required_names}). + /// + /// Each call to `next` is guaranteed to yield the next value for each required iterator, + /// as well as the most recent index amongst all of them. + /// + /// Optional iterators accumulate their state and yield their most recent value (if any), + /// each time the required iterators fire. + pub fn range_zip_{suffix}( + {required_params}, + {optional_params}, + ) -> RangeZip{suffix} + where + Idx: std::cmp::Ord, + {required_clauses}, + {optional_clauses}, + {{ + RangeZip{suffix} {{ + {ret}, + + {latest}, + }} + }} + "# + ) +} + +/// Output: +/// ```ignore +/// pub struct RangeZip2x2 +/// where +/// Idx: std::cmp::Ord, +/// IR0: Iterator, +/// IR1: Iterator, +/// IO0: Iterator, +/// IO1: Iterator, +/// { +/// r0: IR0, +/// r1: IR1, +/// o0: Peekable, +/// o1: Peekable, +/// +/// o0_data_latest: Option, +/// o1_data_latest: Option, +/// } +/// ``` +fn generate_struct(params: &Params) -> String { + let suffix = params.to_suffix(); + let required_types = izip!( + params + .to_required_types() + .into_iter() + .map(|t| format!("I{t}")), + params.to_required_types() + ) + .flat_map(|(tr, r)| [tr, r]) + .collect_vec() + .join(", "); + let optional_types = izip!( + params + .to_optional_types() + .into_iter() + .map(|t| format!("I{t}")), + params.to_optional_types() + ) + .flat_map(|(tr, r)| [tr, r]) + .collect_vec() + .join(", "); + let required_clauses = params.to_required_clauses(false /* into */).join(", "); + let optional_clauses = params.to_optional_clauses(false /* into */).join(", "); + let required_params = params.to_required_params().join(", "); + let optional_params = params.to_optional_peekable_params().join(", "); + let optional_latest_params = izip!(params.to_optional_names(), params.to_optional_types()) + .map(|(n, t)| format!("{n}_data_latest: Option<{t}>")) + .join(", "); + + format!( + r#" + /// Implements a range zip iterator combinator with 2 required iterators and 2 optional + /// iterators. + /// + /// See [`range_zip_{suffix}`] for more information. + pub struct RangeZip{suffix} + where + Idx: std::cmp::Ord, + {required_clauses}, + {optional_clauses}, + {{ + {required_params}, + {optional_params}, + + {optional_latest_params}, + }} + "# + ) +} + +/// Output: +/// ```ignore +/// impl Iterator +/// for RangeZip2x2 +/// where +/// Idx: std::cmp::Ord, +/// IR0: Iterator, +/// IR1: Iterator, +/// IO0: Iterator, +/// IO1: Iterator, +/// O0: Clone, +/// O1: Clone, +/// { +/// type Item = (Idx, R0, R1, Option, Option); +/// +/// #[inline] +/// fn next(&mut self) -> Option { +/// let Self { +/// r0, +/// r1, +/// o0, +/// o1, +/// o0_data_latest, +/// o1_data_latest, +/// } = self; +/// +/// let Some((r0_index, r0_data)) = r0.next() else { +/// return None; +/// }; +/// let Some((r1_index, r1_data)) = r1.next() else { +/// return None; +/// }; +/// +/// let max_index = [r0_index, r1_index].into_iter().max().unwrap(); +/// +/// let mut o0_data = None; +/// while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { +/// o0_data = Some(data); +/// } +/// let o0_data = o0_data.or(o0_data_latest.take()); +/// *o0_data_latest = o0_data.clone(); +/// +/// let mut o1_data = None; +/// while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { +/// o1_data = Some(data); +/// } +/// let o1_data = o1_data.or(o1_data_latest.take()); +/// *o1_data_latest = o1_data.clone(); +/// +/// Some((max_index, r0_data, r1_data, o0_data, o1_data)) +/// } +/// } +/// ``` +fn generate_impl(params: &Params) -> String { + let suffix = params.to_suffix(); + let required_types = izip!( + params + .to_required_types() + .into_iter() + .map(|t| format!("I{t}")), + params.to_required_types() + ) + .flat_map(|(tr, r)| [tr, r]) + .collect_vec() + .join(", "); + let optional_types = izip!( + params + .to_optional_types() + .into_iter() + .map(|t| format!("I{t}")), + params.to_optional_types() + ) + .flat_map(|(tr, r)| [tr, r]) + .collect_vec() + .join(", "); + let required_names = params.to_required_names().join(", "); + let optional_names = params.to_optional_names().join(", "); + let optional_latest_names = params + .to_optional_names() + .into_iter() + .map(|n| format!("{n}_data_latest")) + .join(", "); + let required_indices = params + .to_required_names() + .into_iter() + .map(|n| format!("{n}_index")) + .collect_vec() + .join(", "); + let required_data = params + .to_required_names() + .into_iter() + .map(|n| format!("{n}_data")) + .collect_vec() + .join(", "); + let optional_data = params + .to_optional_names() + .into_iter() + .map(|n| format!("{n}_data")) + .collect_vec() + .join(", "); + let required_clauses = params.to_required_clauses(false /* into */).join(", "); + let optional_clauses = params.to_optional_clauses(false /* into */).join(", "); + let optional_clone_clauses = params + .to_optional_types() + .into_iter() + .map(|o| format!("{o}: Clone")) + .collect_vec() + .join(", "); + + let items = params + .to_required_types() + .into_iter() + .chain( + params + .to_optional_types() + .into_iter() + .map(|o| format!("Option<{o}>")), + ) + .collect_vec() + .join(", "); + + let next_required = params + .to_required_names() + .into_iter() + .map(|r| format!("let Some(({r}_index, {r}_data)) = {r}.next() else {{ return None; }};")) + .collect_vec() + .join("\n"); + + let next_optional = params + .to_optional_names() + .into_iter() + .map(|o| { + format!( + " + let mut {o}_data = None; + while let Some((_, data)) = {o}.next_if(|(index, _)| index <= &max_index) {{ + {o}_data = Some(data); + }} + let {o}_data = {o}_data.or({o}_data_latest.take()); + *{o}_data_latest = {o}_data.clone(); + " + ) + }) + .collect_vec() + .join("\n"); + + format!( + r#" + impl Iterator for RangeZip{suffix} + where + Idx: std::cmp::Ord, + {required_clauses}, + {optional_clauses}, + {optional_clone_clauses}, + {{ + type Item = (Idx, {items}); + + #[inline] + fn next(&mut self) -> Option {{ + let Self {{ {required_names}, {optional_names}, {optional_latest_names} }} = self; + + {next_required} + + let max_index = [{required_indices}].into_iter().max().unwrap(); + + {next_optional} + + Some((max_index, {required_data}, {optional_data})) + }} + }} + "# + ) +} + +fn main() { + let num_required = 1..3; + let num_optional = 1..10; + + let output = num_required + .flat_map(|num_required| { + num_optional + .clone() + .map(move |num_optional| (num_required, num_optional)) + }) + .flat_map(|(num_required, num_optional)| { + let params = Params { + num_required, + num_optional, + }; + + [ + generate_helper_func(¶ms), + generate_struct(¶ms), + generate_impl(¶ms), + ] + }) + .collect_vec() + .join("\n"); + + println!( + " + // This file was generated using `cargo r -p re_query2 --all-features --bin range_zip`. + // DO NOT EDIT. + + // --- + + #![allow(clippy::iter_on_single_items)] + #![allow(clippy::too_many_arguments)] + #![allow(clippy::type_complexity)] + + use std::iter::Peekable; + + {output} + " + ); +} diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs index ac92c6aed7c2..944319561404 100644 --- a/crates/re_query2/src/lib.rs +++ b/crates/re_query2/src/lib.rs @@ -1,10 +1,12 @@ //! Provide query-centric access to the [`re_data_store`]. -pub mod clamped_zip; mod latest_at; mod promise; mod visible_history; +pub mod clamped_zip; +pub mod range_zip; + pub use self::clamped_zip::*; pub use self::latest_at::{latest_at, LatestAtComponentResults, LatestAtResults}; pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; diff --git a/crates/re_query2/src/range_zip/.gitattributes b/crates/re_query2/src/range_zip/.gitattributes new file mode 100644 index 000000000000..30d202506064 --- /dev/null +++ b/crates/re_query2/src/range_zip/.gitattributes @@ -0,0 +1 @@ +generated.rs linguist-generated=true diff --git a/crates/re_query2/src/range_zip/generated.rs b/crates/re_query2/src/range_zip/generated.rs new file mode 100644 index 000000000000..c916479d39f2 --- /dev/null +++ b/crates/re_query2/src/range_zip/generated.rs @@ -0,0 +1,3544 @@ +// This file was generated using `cargo r -p re_query2 --all-features --bin range_zip`. +// DO NOT EDIT. + +// --- + +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::type_complexity)] + +use std::iter::Peekable; + +/// Returns a new [`RangeZip1x1`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x1( + r0: IR0, + o0: IO0, +) -> RangeZip1x1 +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, +{ + RangeZip1x1 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + + o0_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x1`] for more information. +pub struct RangeZip1x1 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, +{ + r0: IR0, + o0: Peekable, + + o0_data_latest: Option, +} + +impl Iterator for RangeZip1x1 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + O0: Clone, +{ + type Item = (Idx, R0, Option); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o0_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + Some((max_index, r0_data, o0_data)) + } +} + +/// Returns a new [`RangeZip1x2`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x2( + r0: IR0, + o0: IO0, + o1: IO1, +) -> RangeZip1x2 +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, +{ + RangeZip1x2 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x2`] for more information. +pub struct RangeZip1x2 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, +{ + r0: IR0, + o0: Peekable, + o1: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, +} + +impl Iterator for RangeZip1x2 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + O0: Clone, + O1: Clone, +{ + type Item = (Idx, R0, Option, Option); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o1, + o0_data_latest, + o1_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + Some((max_index, r0_data, o0_data, o1_data)) + } +} + +/// Returns a new [`RangeZip1x3`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x3( + r0: IR0, + o0: IO0, + o1: IO1, + o2: IO2, +) -> RangeZip1x3 +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, +{ + RangeZip1x3 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x3`] for more information. +pub struct RangeZip1x3 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, +{ + r0: IR0, + o0: Peekable, + o1: Peekable, + o2: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, +} + +impl Iterator + for RangeZip1x3 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, +{ + type Item = (Idx, R0, Option, Option, Option); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o1, + o2, + o0_data_latest, + o1_data_latest, + o2_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + Some((max_index, r0_data, o0_data, o1_data, o2_data)) + } +} + +/// Returns a new [`RangeZip1x4`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x4( + r0: IR0, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, +) -> RangeZip1x4< + Idx, + IR0::IntoIter, + R0, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, +{ + RangeZip1x4 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x4`] for more information. +pub struct RangeZip1x4 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, +{ + r0: IR0, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, +} + +impl Iterator + for RangeZip1x4 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, +{ + type Item = (Idx, R0, Option, Option, Option, Option); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o1, + o2, + o3, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + Some((max_index, r0_data, o0_data, o1_data, o2_data, o3_data)) + } +} + +/// Returns a new [`RangeZip1x5`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x5( + r0: IR0, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, +) -> RangeZip1x5< + Idx, + IR0::IntoIter, + R0, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, +{ + RangeZip1x5 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x5`] for more information. +pub struct RangeZip1x5 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, +{ + r0: IR0, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, +} + +impl Iterator + for RangeZip1x5 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, +{ + type Item = ( + Idx, + R0, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o1, + o2, + o3, + o4, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + Some(( + max_index, r0_data, o0_data, o1_data, o2_data, o3_data, o4_data, + )) + } +} + +/// Returns a new [`RangeZip1x6`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x6( + r0: IR0, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, + o5: IO5, +) -> RangeZip1x6< + Idx, + IR0::IntoIter, + R0, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, + IO5::IntoIter, + O5, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, + IO5: IntoIterator, +{ + RangeZip1x6 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + o5: o5.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + o5_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x6`] for more information. +pub struct RangeZip1x6 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, +{ + r0: IR0, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + o5: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, + o5_data_latest: Option, +} + +impl Iterator + for RangeZip1x6 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, + O5: Clone, +{ + type Item = ( + Idx, + R0, + Option, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o1, + o2, + o3, + o4, + o5, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + o5_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + let mut o5_data = None; + while let Some((_, data)) = o5.next_if(|(index, _)| index <= &max_index) { + o5_data = Some(data); + } + let o5_data = o5_data.or(o5_data_latest.take()); + *o5_data_latest = o5_data.clone(); + + Some(( + max_index, r0_data, o0_data, o1_data, o2_data, o3_data, o4_data, o5_data, + )) + } +} + +/// Returns a new [`RangeZip1x7`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x7( + r0: IR0, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, + o5: IO5, + o6: IO6, +) -> RangeZip1x7< + Idx, + IR0::IntoIter, + R0, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, + IO5::IntoIter, + O5, + IO6::IntoIter, + O6, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, + IO5: IntoIterator, + IO6: IntoIterator, +{ + RangeZip1x7 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + o5: o5.into_iter().peekable(), + o6: o6.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + o5_data_latest: None, + o6_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x7`] for more information. +pub struct RangeZip1x7 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, +{ + r0: IR0, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + o5: Peekable, + o6: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, + o5_data_latest: Option, + o6_data_latest: Option, +} + +impl Iterator + for RangeZip1x7 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, + O5: Clone, + O6: Clone, +{ + type Item = ( + Idx, + R0, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o1, + o2, + o3, + o4, + o5, + o6, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + o5_data_latest, + o6_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + let mut o5_data = None; + while let Some((_, data)) = o5.next_if(|(index, _)| index <= &max_index) { + o5_data = Some(data); + } + let o5_data = o5_data.or(o5_data_latest.take()); + *o5_data_latest = o5_data.clone(); + + let mut o6_data = None; + while let Some((_, data)) = o6.next_if(|(index, _)| index <= &max_index) { + o6_data = Some(data); + } + let o6_data = o6_data.or(o6_data_latest.take()); + *o6_data_latest = o6_data.clone(); + + Some(( + max_index, r0_data, o0_data, o1_data, o2_data, o3_data, o4_data, o5_data, o6_data, + )) + } +} + +/// Returns a new [`RangeZip1x8`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x8< + Idx, + IR0, + R0, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, +>( + r0: IR0, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, + o5: IO5, + o6: IO6, + o7: IO7, +) -> RangeZip1x8< + Idx, + IR0::IntoIter, + R0, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, + IO5::IntoIter, + O5, + IO6::IntoIter, + O6, + IO7::IntoIter, + O7, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, + IO5: IntoIterator, + IO6: IntoIterator, + IO7: IntoIterator, +{ + RangeZip1x8 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + o5: o5.into_iter().peekable(), + o6: o6.into_iter().peekable(), + o7: o7.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + o5_data_latest: None, + o6_data_latest: None, + o7_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x8`] for more information. +pub struct RangeZip1x8< + Idx, + IR0, + R0, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, +> where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + IO7: Iterator, +{ + r0: IR0, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + o5: Peekable, + o6: Peekable, + o7: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, + o5_data_latest: Option, + o6_data_latest: Option, + o7_data_latest: Option, +} + +impl Iterator + for RangeZip1x8< + Idx, + IR0, + R0, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + > +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + IO7: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, + O5: Clone, + O6: Clone, + O7: Clone, +{ + type Item = ( + Idx, + R0, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o1, + o2, + o3, + o4, + o5, + o6, + o7, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + o5_data_latest, + o6_data_latest, + o7_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + let mut o5_data = None; + while let Some((_, data)) = o5.next_if(|(index, _)| index <= &max_index) { + o5_data = Some(data); + } + let o5_data = o5_data.or(o5_data_latest.take()); + *o5_data_latest = o5_data.clone(); + + let mut o6_data = None; + while let Some((_, data)) = o6.next_if(|(index, _)| index <= &max_index) { + o6_data = Some(data); + } + let o6_data = o6_data.or(o6_data_latest.take()); + *o6_data_latest = o6_data.clone(); + + let mut o7_data = None; + while let Some((_, data)) = o7.next_if(|(index, _)| index <= &max_index) { + o7_data = Some(data); + } + let o7_data = o7_data.or(o7_data_latest.take()); + *o7_data_latest = o7_data.clone(); + + Some(( + max_index, r0_data, o0_data, o1_data, o2_data, o3_data, o4_data, o5_data, o6_data, + o7_data, + )) + } +} + +/// Returns a new [`RangeZip1x9`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_1x9< + Idx, + IR0, + R0, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + IO8, + O8, +>( + r0: IR0, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, + o5: IO5, + o6: IO6, + o7: IO7, + o8: IO8, +) -> RangeZip1x9< + Idx, + IR0::IntoIter, + R0, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, + IO5::IntoIter, + O5, + IO6::IntoIter, + O6, + IO7::IntoIter, + O7, + IO8::IntoIter, + O8, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, + IO5: IntoIterator, + IO6: IntoIterator, + IO7: IntoIterator, + IO8: IntoIterator, +{ + RangeZip1x9 { + r0: r0.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + o5: o5.into_iter().peekable(), + o6: o6.into_iter().peekable(), + o7: o7.into_iter().peekable(), + o8: o8.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + o5_data_latest: None, + o6_data_latest: None, + o7_data_latest: None, + o8_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_1x9`] for more information. +pub struct RangeZip1x9< + Idx, + IR0, + R0, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + IO8, + O8, +> where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + IO7: Iterator, + IO8: Iterator, +{ + r0: IR0, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + o5: Peekable, + o6: Peekable, + o7: Peekable, + o8: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, + o5_data_latest: Option, + o6_data_latest: Option, + o7_data_latest: Option, + o8_data_latest: Option, +} + +impl< + Idx, + IR0, + R0, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + IO8, + O8, + > Iterator + for RangeZip1x9< + Idx, + IR0, + R0, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + IO8, + O8, + > +where + Idx: std::cmp::Ord, + IR0: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + IO7: Iterator, + IO8: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, + O5: Clone, + O6: Clone, + O7: Clone, + O8: Clone, +{ + type Item = ( + Idx, + R0, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + o0, + o1, + o2, + o3, + o4, + o5, + o6, + o7, + o8, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + o5_data_latest, + o6_data_latest, + o7_data_latest, + o8_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + + let max_index = [r0_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + let mut o5_data = None; + while let Some((_, data)) = o5.next_if(|(index, _)| index <= &max_index) { + o5_data = Some(data); + } + let o5_data = o5_data.or(o5_data_latest.take()); + *o5_data_latest = o5_data.clone(); + + let mut o6_data = None; + while let Some((_, data)) = o6.next_if(|(index, _)| index <= &max_index) { + o6_data = Some(data); + } + let o6_data = o6_data.or(o6_data_latest.take()); + *o6_data_latest = o6_data.clone(); + + let mut o7_data = None; + while let Some((_, data)) = o7.next_if(|(index, _)| index <= &max_index) { + o7_data = Some(data); + } + let o7_data = o7_data.or(o7_data_latest.take()); + *o7_data_latest = o7_data.clone(); + + let mut o8_data = None; + while let Some((_, data)) = o8.next_if(|(index, _)| index <= &max_index) { + o8_data = Some(data); + } + let o8_data = o8_data.or(o8_data_latest.take()); + *o8_data_latest = o8_data.clone(); + + Some(( + max_index, r0_data, o0_data, o1_data, o2_data, o3_data, o4_data, o5_data, o6_data, + o7_data, o8_data, + )) + } +} + +/// Returns a new [`RangeZip2x1`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x1( + r0: IR0, + r1: IR1, + o0: IO0, +) -> RangeZip2x1 +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, +{ + RangeZip2x1 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + + o0_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x1`] for more information. +pub struct RangeZip2x1 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + + o0_data_latest: Option, +} + +impl Iterator for RangeZip2x1 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + O0: Clone, +{ + type Item = (Idx, R0, R1, Option); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o0_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + Some((max_index, r0_data, r1_data, o0_data)) + } +} + +/// Returns a new [`RangeZip2x2`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x2( + r0: IR0, + r1: IR1, + o0: IO0, + o1: IO1, +) -> RangeZip2x2 +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, +{ + RangeZip2x2 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x2`] for more information. +pub struct RangeZip2x2 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + o1: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, +} + +impl Iterator + for RangeZip2x2 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + O0: Clone, + O1: Clone, +{ + type Item = (Idx, R0, R1, Option, Option); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o1, + o0_data_latest, + o1_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + Some((max_index, r0_data, r1_data, o0_data, o1_data)) + } +} + +/// Returns a new [`RangeZip2x3`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x3( + r0: IR0, + r1: IR1, + o0: IO0, + o1: IO1, + o2: IO2, +) -> RangeZip2x3< + Idx, + IR0::IntoIter, + R0, + IR1::IntoIter, + R1, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, +{ + RangeZip2x3 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x3`] for more information. +pub struct RangeZip2x3 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + o1: Peekable, + o2: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, +} + +impl Iterator + for RangeZip2x3 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, +{ + type Item = (Idx, R0, R1, Option, Option, Option); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o1, + o2, + o0_data_latest, + o1_data_latest, + o2_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + Some((max_index, r0_data, r1_data, o0_data, o1_data, o2_data)) + } +} + +/// Returns a new [`RangeZip2x4`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x4( + r0: IR0, + r1: IR1, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, +) -> RangeZip2x4< + Idx, + IR0::IntoIter, + R0, + IR1::IntoIter, + R1, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, +{ + RangeZip2x4 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x4`] for more information. +pub struct RangeZip2x4 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, +} + +impl Iterator + for RangeZip2x4 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, +{ + type Item = (Idx, R0, R1, Option, Option, Option, Option); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o1, + o2, + o3, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + Some(( + max_index, r0_data, r1_data, o0_data, o1_data, o2_data, o3_data, + )) + } +} + +/// Returns a new [`RangeZip2x5`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x5( + r0: IR0, + r1: IR1, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, +) -> RangeZip2x5< + Idx, + IR0::IntoIter, + R0, + IR1::IntoIter, + R1, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, +{ + RangeZip2x5 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x5`] for more information. +pub struct RangeZip2x5 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, +} + +impl Iterator + for RangeZip2x5 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, +{ + type Item = ( + Idx, + R0, + R1, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o1, + o2, + o3, + o4, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + Some(( + max_index, r0_data, r1_data, o0_data, o1_data, o2_data, o3_data, o4_data, + )) + } +} + +/// Returns a new [`RangeZip2x6`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x6( + r0: IR0, + r1: IR1, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, + o5: IO5, +) -> RangeZip2x6< + Idx, + IR0::IntoIter, + R0, + IR1::IntoIter, + R1, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, + IO5::IntoIter, + O5, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, + IO5: IntoIterator, +{ + RangeZip2x6 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + o5: o5.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + o5_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x6`] for more information. +pub struct RangeZip2x6 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + o5: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, + o5_data_latest: Option, +} + +impl Iterator + for RangeZip2x6 +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, + O5: Clone, +{ + type Item = ( + Idx, + R0, + R1, + Option, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o1, + o2, + o3, + o4, + o5, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + o5_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + let mut o5_data = None; + while let Some((_, data)) = o5.next_if(|(index, _)| index <= &max_index) { + o5_data = Some(data); + } + let o5_data = o5_data.or(o5_data_latest.take()); + *o5_data_latest = o5_data.clone(); + + Some(( + max_index, r0_data, r1_data, o0_data, o1_data, o2_data, o3_data, o4_data, o5_data, + )) + } +} + +/// Returns a new [`RangeZip2x7`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x7< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, +>( + r0: IR0, + r1: IR1, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, + o5: IO5, + o6: IO6, +) -> RangeZip2x7< + Idx, + IR0::IntoIter, + R0, + IR1::IntoIter, + R1, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, + IO5::IntoIter, + O5, + IO6::IntoIter, + O6, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, + IO5: IntoIterator, + IO6: IntoIterator, +{ + RangeZip2x7 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + o5: o5.into_iter().peekable(), + o6: o6.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + o5_data_latest: None, + o6_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x7`] for more information. +pub struct RangeZip2x7< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, +> where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + o5: Peekable, + o6: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, + o5_data_latest: Option, + o6_data_latest: Option, +} + +impl Iterator + for RangeZip2x7< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + > +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, + O5: Clone, + O6: Clone, +{ + type Item = ( + Idx, + R0, + R1, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o1, + o2, + o3, + o4, + o5, + o6, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + o5_data_latest, + o6_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + let mut o5_data = None; + while let Some((_, data)) = o5.next_if(|(index, _)| index <= &max_index) { + o5_data = Some(data); + } + let o5_data = o5_data.or(o5_data_latest.take()); + *o5_data_latest = o5_data.clone(); + + let mut o6_data = None; + while let Some((_, data)) = o6.next_if(|(index, _)| index <= &max_index) { + o6_data = Some(data); + } + let o6_data = o6_data.or(o6_data_latest.take()); + *o6_data_latest = o6_data.clone(); + + Some(( + max_index, r0_data, r1_data, o0_data, o1_data, o2_data, o3_data, o4_data, o5_data, + o6_data, + )) + } +} + +/// Returns a new [`RangeZip2x8`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x8< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, +>( + r0: IR0, + r1: IR1, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, + o5: IO5, + o6: IO6, + o7: IO7, +) -> RangeZip2x8< + Idx, + IR0::IntoIter, + R0, + IR1::IntoIter, + R1, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, + IO5::IntoIter, + O5, + IO6::IntoIter, + O6, + IO7::IntoIter, + O7, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, + IO5: IntoIterator, + IO6: IntoIterator, + IO7: IntoIterator, +{ + RangeZip2x8 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + o5: o5.into_iter().peekable(), + o6: o6.into_iter().peekable(), + o7: o7.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + o5_data_latest: None, + o6_data_latest: None, + o7_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x8`] for more information. +pub struct RangeZip2x8< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, +> where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + IO7: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + o5: Peekable, + o6: Peekable, + o7: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, + o5_data_latest: Option, + o6_data_latest: Option, + o7_data_latest: Option, +} + +impl< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + > Iterator + for RangeZip2x8< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + > +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + IO7: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, + O5: Clone, + O6: Clone, + O7: Clone, +{ + type Item = ( + Idx, + R0, + R1, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o1, + o2, + o3, + o4, + o5, + o6, + o7, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + o5_data_latest, + o6_data_latest, + o7_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + let mut o5_data = None; + while let Some((_, data)) = o5.next_if(|(index, _)| index <= &max_index) { + o5_data = Some(data); + } + let o5_data = o5_data.or(o5_data_latest.take()); + *o5_data_latest = o5_data.clone(); + + let mut o6_data = None; + while let Some((_, data)) = o6.next_if(|(index, _)| index <= &max_index) { + o6_data = Some(data); + } + let o6_data = o6_data.or(o6_data_latest.take()); + *o6_data_latest = o6_data.clone(); + + let mut o7_data = None; + while let Some((_, data)) = o7.next_if(|(index, _)| index <= &max_index) { + o7_data = Some(data); + } + let o7_data = o7_data.or(o7_data_latest.take()); + *o7_data_latest = o7_data.clone(); + + Some(( + max_index, r0_data, r1_data, o0_data, o1_data, o2_data, o3_data, o4_data, o5_data, + o6_data, o7_data, + )) + } +} + +/// Returns a new [`RangeZip2x9`] iterator. +/// +/// The number of elements in a range zip iterator corresponds to the number of elements in the +/// shortest of its required iterators (`r0`, `r1`). +/// +/// Each call to `next` is guaranteed to yield the next value for each required iterator, +/// as well as the most recent index amongst all of them. +/// +/// Optional iterators accumulate their state and yield their most recent value (if any), +/// each time the required iterators fire. +pub fn range_zip_2x9< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + IO8, + O8, +>( + r0: IR0, + r1: IR1, + o0: IO0, + o1: IO1, + o2: IO2, + o3: IO3, + o4: IO4, + o5: IO5, + o6: IO6, + o7: IO7, + o8: IO8, +) -> RangeZip2x9< + Idx, + IR0::IntoIter, + R0, + IR1::IntoIter, + R1, + IO0::IntoIter, + O0, + IO1::IntoIter, + O1, + IO2::IntoIter, + O2, + IO3::IntoIter, + O3, + IO4::IntoIter, + O4, + IO5::IntoIter, + O5, + IO6::IntoIter, + O6, + IO7::IntoIter, + O7, + IO8::IntoIter, + O8, +> +where + Idx: std::cmp::Ord, + IR0: IntoIterator, + IR1: IntoIterator, + IO0: IntoIterator, + IO1: IntoIterator, + IO2: IntoIterator, + IO3: IntoIterator, + IO4: IntoIterator, + IO5: IntoIterator, + IO6: IntoIterator, + IO7: IntoIterator, + IO8: IntoIterator, +{ + RangeZip2x9 { + r0: r0.into_iter(), + r1: r1.into_iter(), + o0: o0.into_iter().peekable(), + o1: o1.into_iter().peekable(), + o2: o2.into_iter().peekable(), + o3: o3.into_iter().peekable(), + o4: o4.into_iter().peekable(), + o5: o5.into_iter().peekable(), + o6: o6.into_iter().peekable(), + o7: o7.into_iter().peekable(), + o8: o8.into_iter().peekable(), + + o0_data_latest: None, + o1_data_latest: None, + o2_data_latest: None, + o3_data_latest: None, + o4_data_latest: None, + o5_data_latest: None, + o6_data_latest: None, + o7_data_latest: None, + o8_data_latest: None, + } +} + +/// Implements a range zip iterator combinator with 2 required iterators and 2 optional +/// iterators. +/// +/// See [`range_zip_2x9`] for more information. +pub struct RangeZip2x9< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + IO8, + O8, +> where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + IO7: Iterator, + IO8: Iterator, +{ + r0: IR0, + r1: IR1, + o0: Peekable, + o1: Peekable, + o2: Peekable, + o3: Peekable, + o4: Peekable, + o5: Peekable, + o6: Peekable, + o7: Peekable, + o8: Peekable, + + o0_data_latest: Option, + o1_data_latest: Option, + o2_data_latest: Option, + o3_data_latest: Option, + o4_data_latest: Option, + o5_data_latest: Option, + o6_data_latest: Option, + o7_data_latest: Option, + o8_data_latest: Option, +} + +impl< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + IO8, + O8, + > Iterator + for RangeZip2x9< + Idx, + IR0, + R0, + IR1, + R1, + IO0, + O0, + IO1, + O1, + IO2, + O2, + IO3, + O3, + IO4, + O4, + IO5, + O5, + IO6, + O6, + IO7, + O7, + IO8, + O8, + > +where + Idx: std::cmp::Ord, + IR0: Iterator, + IR1: Iterator, + IO0: Iterator, + IO1: Iterator, + IO2: Iterator, + IO3: Iterator, + IO4: Iterator, + IO5: Iterator, + IO6: Iterator, + IO7: Iterator, + IO8: Iterator, + O0: Clone, + O1: Clone, + O2: Clone, + O3: Clone, + O4: Clone, + O5: Clone, + O6: Clone, + O7: Clone, + O8: Clone, +{ + type Item = ( + Idx, + R0, + R1, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + Option, + ); + + #[inline] + fn next(&mut self) -> Option { + let Self { + r0, + r1, + o0, + o1, + o2, + o3, + o4, + o5, + o6, + o7, + o8, + o0_data_latest, + o1_data_latest, + o2_data_latest, + o3_data_latest, + o4_data_latest, + o5_data_latest, + o6_data_latest, + o7_data_latest, + o8_data_latest, + } = self; + + let Some((r0_index, r0_data)) = r0.next() else { + return None; + }; + let Some((r1_index, r1_data)) = r1.next() else { + return None; + }; + + let max_index = [r0_index, r1_index].into_iter().max().unwrap(); + + let mut o0_data = None; + while let Some((_, data)) = o0.next_if(|(index, _)| index <= &max_index) { + o0_data = Some(data); + } + let o0_data = o0_data.or(o0_data_latest.take()); + *o0_data_latest = o0_data.clone(); + + let mut o1_data = None; + while let Some((_, data)) = o1.next_if(|(index, _)| index <= &max_index) { + o1_data = Some(data); + } + let o1_data = o1_data.or(o1_data_latest.take()); + *o1_data_latest = o1_data.clone(); + + let mut o2_data = None; + while let Some((_, data)) = o2.next_if(|(index, _)| index <= &max_index) { + o2_data = Some(data); + } + let o2_data = o2_data.or(o2_data_latest.take()); + *o2_data_latest = o2_data.clone(); + + let mut o3_data = None; + while let Some((_, data)) = o3.next_if(|(index, _)| index <= &max_index) { + o3_data = Some(data); + } + let o3_data = o3_data.or(o3_data_latest.take()); + *o3_data_latest = o3_data.clone(); + + let mut o4_data = None; + while let Some((_, data)) = o4.next_if(|(index, _)| index <= &max_index) { + o4_data = Some(data); + } + let o4_data = o4_data.or(o4_data_latest.take()); + *o4_data_latest = o4_data.clone(); + + let mut o5_data = None; + while let Some((_, data)) = o5.next_if(|(index, _)| index <= &max_index) { + o5_data = Some(data); + } + let o5_data = o5_data.or(o5_data_latest.take()); + *o5_data_latest = o5_data.clone(); + + let mut o6_data = None; + while let Some((_, data)) = o6.next_if(|(index, _)| index <= &max_index) { + o6_data = Some(data); + } + let o6_data = o6_data.or(o6_data_latest.take()); + *o6_data_latest = o6_data.clone(); + + let mut o7_data = None; + while let Some((_, data)) = o7.next_if(|(index, _)| index <= &max_index) { + o7_data = Some(data); + } + let o7_data = o7_data.or(o7_data_latest.take()); + *o7_data_latest = o7_data.clone(); + + let mut o8_data = None; + while let Some((_, data)) = o8.next_if(|(index, _)| index <= &max_index) { + o8_data = Some(data); + } + let o8_data = o8_data.or(o8_data_latest.take()); + *o8_data_latest = o8_data.clone(); + + Some(( + max_index, r0_data, r1_data, o0_data, o1_data, o2_data, o3_data, o4_data, o5_data, + o6_data, o7_data, o8_data, + )) + } +} diff --git a/crates/re_query2/src/range_zip/mod.rs b/crates/re_query2/src/range_zip/mod.rs new file mode 100644 index 000000000000..60913fef721c --- /dev/null +++ b/crates/re_query2/src/range_zip/mod.rs @@ -0,0 +1,69 @@ +mod generated; +pub use self::generated::*; + +#[cfg(test)] +mod tests { + use itertools::Itertools as _; + + use re_log_types::{RowId, TimeInt}; + + use super::*; + + #[test] + fn overview_1x1() { + let t9 = TimeInt::new_temporal(9); + let t10 = TimeInt::new_temporal(10); + let t11 = TimeInt::new_temporal(11); + let t12 = TimeInt::new_temporal(12); + let t13 = TimeInt::new_temporal(13); + let t14 = TimeInt::new_temporal(14); + + let p0: Vec<((TimeInt, RowId), u32)> = vec![ + ((t9, RowId::ZERO), 90), // + // + ((t10, RowId::ZERO), 100), // + // + ((t13, RowId::ZERO.incremented_by(0)), 130), // + ((t13, RowId::ZERO.incremented_by(0)), 130), // + ((t13, RowId::ZERO.incremented_by(0)), 130), // + ((t13, RowId::ZERO.incremented_by(1)), 131), // + ((t13, RowId::ZERO.incremented_by(2)), 132), // + ((t13, RowId::ZERO.incremented_by(5)), 135), // + // + ((t14, RowId::ZERO), 140), // + ]; + + let c0: Vec<((TimeInt, RowId), &'static str)> = vec![ + ((t10, RowId::ZERO.incremented_by(1)), "101"), // + ((t10, RowId::ZERO.incremented_by(2)), "102"), // + ((t10, RowId::ZERO.incremented_by(3)), "103"), // + // + ((t11, RowId::ZERO), "110"), // + // + ((t12, RowId::ZERO), "120"), // + // + ((t13, RowId::ZERO.incremented_by(1)), "131"), // + ((t13, RowId::ZERO.incremented_by(2)), "132"), // + ((t13, RowId::ZERO.incremented_by(4)), "134"), // + ((t13, RowId::ZERO.incremented_by(6)), "136"), // + ]; + + let expected: Vec<((TimeInt, RowId), u32, Option<&'static str>)> = vec![ + ((t9, RowId::ZERO), 90, None), // + // + ((t10, RowId::ZERO), 100, None), // + // + ((t13, RowId::ZERO.incremented_by(0)), 130, Some("120")), // + ((t13, RowId::ZERO.incremented_by(0)), 130, Some("120")), // + ((t13, RowId::ZERO.incremented_by(0)), 130, Some("120")), // + ((t13, RowId::ZERO.incremented_by(1)), 131, Some("131")), // + ((t13, RowId::ZERO.incremented_by(2)), 132, Some("132")), // + ((t13, RowId::ZERO.incremented_by(5)), 135, Some("134")), // + // + ((t14, RowId::ZERO), 140, Some("136")), // + ]; + let got = range_zip_1x1(p0, c0).collect_vec(); + + similar_asserts::assert_eq!(expected, got); + } +} From a95ce15b6d51ed270c461ef4120d0a97b2ed012d Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 8 Apr 2024 15:11:18 +0200 Subject: [PATCH 227/508] New data APIs 8: uncached range queries (#5687) This implements the new uncached range APIs. Latest-at & range queries are now much more similar than before and share a lot of nice traits. Tests have been backported from `re_query`. Here's an example/guide of using the new API: ```rust // First, get the raw results for this query. // // Raw here means that these results are neither deserialized, nor resolved/converted. // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. let results: RangeResults = re_query2::range( &store, &query, &entity_path.into(), MyPoints::all_components().iter().cloned(), // no generics! ); // Then, grab the raw results for each individual components. // // This is still raw data, but now a choice has been made regarding the nullability of the // _component batch_ itself (that says nothing about its _instances_!). // // * `get_required` returns an error if the component batch is missing // * `get_optional` returns an empty set of results if the component if missing // * `get` returns an option let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; let all_colors: &RangeComponentResults = results.get_optional(MyColor::name()); let all_labels: &RangeComponentResults = results.get_optional(MyLabel::name()); let all_indexed_points = izip!( all_points.iter_indices(), all_points.iter_dense::(&resolver) ); let all_indexed_colors = izip!( all_colors.iter_indices(), all_colors.iter_sparse::(&resolver) ); let all_indexed_labels = izip!( all_labels.iter_indices(), all_labels.iter_sparse::(&resolver) ); let all_frames = range_zip_1x2(all_indexed_points, all_indexed_colors, all_indexed_labels); // Then comes the time to resolve/convert and deserialize the data, _for each timestamp_. // These steps have to be done together for efficiency reasons. // // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. // Use `PromiseResult::flatten` to simplify it down to a single result. // // A choice now has to be made regarding the nullability of the _component batch's instances_. // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably // shouldn't be using anything but `iter_dense`. eprintln!("results:"); for ((data_time, row_id), points, colors, labels) in all_frames { let points = match points.flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. continue; } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), }; let colors = if let Some(colors) = colors { match colors.flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. continue; } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), } } else { vec![] }; let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); let labels = if let Some(labels) = labels { match labels.flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. continue; } PromiseResult::Ready(data) => data, PromiseResult::Error(err) => return Err(err.into()), } } else { vec![] }; let label_default_fn = || None; // With the data now fully resolved/converted and deserialized, the joining logic can be // applied. // // In most cases this will be either a clamped zip, or no joining at all. let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn) .collect_vec(); eprintln!("{data_time:?} @ {row_id}:\n {results:?}"); } ``` - Fixes #3379 - Part of #1893 --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - TODO - TODO Builds on top of the static data PR series: - #5534 --- crates/re_query2/examples/range.rs | 168 +++++++++ crates/re_query2/src/lib.rs | 3 + crates/re_query2/src/range/mod.rs | 5 + crates/re_query2/src/range/query.rs | 38 ++ crates/re_query2/src/range/results.rs | 198 ++++++++++ crates/re_query2/tests/range.rs | 496 ++++++++++++++++++++++++++ 6 files changed, 908 insertions(+) create mode 100644 crates/re_query2/examples/range.rs create mode 100644 crates/re_query2/src/range/mod.rs create mode 100644 crates/re_query2/src/range/query.rs create mode 100644 crates/re_query2/src/range/results.rs create mode 100644 crates/re_query2/tests/range.rs diff --git a/crates/re_query2/examples/range.rs b/crates/re_query2/examples/range.rs new file mode 100644 index 000000000000..8753dac5308d --- /dev/null +++ b/crates/re_query2/examples/range.rs @@ -0,0 +1,168 @@ +use itertools::{izip, Itertools}; +use re_data_store::{DataStore, RangeQuery}; +use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; +use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; +use re_types_core::{Archetype as _, Loggable as _}; + +use re_query2::{ + clamped_zip_1x2, range_zip_1x2, PromiseResolver, PromiseResult, RangeComponentResults, + RangeResults, +}; + +// --- + +fn main() -> anyhow::Result<()> { + let store = store()?; + eprintln!("store:\n{}", store.to_data_table()?); + + let resolver = PromiseResolver::default(); + + let entity_path = "points"; + let timeline = Timeline::new("frame_nr", TimeType::Sequence); + let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); + eprintln!("query:{query:?}"); + + // First, get the raw results for this query. + // + // Raw here means that these results are neither deserialized, nor resolved/converted. + // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. + let results: RangeResults = re_query2::range( + &store, + &query, + &entity_path.into(), + MyPoints::all_components().iter().cloned(), // no generics! + ); + + // Then, grab the raw results for each individual components. + // + // This is still raw data, but now a choice has been made regarding the nullability of the + // _component batch_ itself (that says nothing about its _instances_!). + // + // * `get_required` returns an error if the component batch is missing + // * `get_optional` returns an empty set of results if the component if missing + // * `get` returns an option + let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; + let all_colors: &RangeComponentResults = results.get_optional(MyColor::name()); + let all_labels: &RangeComponentResults = results.get_optional(MyLabel::name()); + + let all_indexed_points = izip!( + all_points.iter_indices(), + all_points.iter_dense::(&resolver) + ); + let all_indexed_colors = izip!( + all_colors.iter_indices(), + all_colors.iter_sparse::(&resolver) + ); + let all_indexed_labels = izip!( + all_labels.iter_indices(), + all_labels.iter_sparse::(&resolver) + ); + + let all_frames = range_zip_1x2(all_indexed_points, all_indexed_colors, all_indexed_labels); + + // Then comes the time to resolve/convert and deserialize the data, _for each timestamp_. + // These steps have to be done together for efficiency reasons. + // + // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. + // Use `PromiseResult::flatten` to simplify it down to a single result. + // + // A choice now has to be made regarding the nullability of the _component batch's instances_. + // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably + // shouldn't be using anything but `iter_dense`. + eprintln!("results:"); + for ((data_time, row_id), points, colors, labels) in all_frames { + let points = match points.flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + continue; + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + }; + + let colors = if let Some(colors) = colors { + match colors.flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + continue; + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + } + } else { + vec![] + }; + let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); + + let labels = if let Some(labels) = labels { + match labels.flatten() { + PromiseResult::Pending => { + // Handle the fact that the data isn't ready appropriately. + continue; + } + PromiseResult::Ready(data) => data, + PromiseResult::Error(err) => return Err(err.into()), + } + } else { + vec![] + }; + let label_default_fn = || None; + + // With the data now fully resolved/converted and deserialized, the joining logic can be + // applied. + // + // In most cases this will be either a clamped zip, or no joining at all. + + let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn) + .collect_vec(); + eprintln!("{data_time:?} @ {row_id}:\n {results:?}"); + } + + Ok(()) +} + +// --- + +fn store() -> anyhow::Result { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + re_types::components::InstanceKey::name(), + Default::default(), + ); + + let entity_path = "points"; + + { + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + store.insert_row(&row)?; + } + + { + let timepoint = [build_frame_nr(456)]; + + let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 0, 255)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let points = vec![ + MyPoint::new(10.0, 20.0), + MyPoint::new(30.0, 40.0), + MyPoint::new(50.0, 60.0), + ]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + } + + Ok(store) +} diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs index 944319561404..94e94a06f803 100644 --- a/crates/re_query2/src/lib.rs +++ b/crates/re_query2/src/lib.rs @@ -2,6 +2,7 @@ mod latest_at; mod promise; +mod range; mod visible_history; pub mod clamped_zip; @@ -10,6 +11,8 @@ pub mod range_zip; pub use self::clamped_zip::*; pub use self::latest_at::{latest_at, LatestAtComponentResults, LatestAtResults}; pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; +pub use self::range::{range, RangeComponentResults, RangeResults}; +pub use self::range_zip::*; pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; // --- diff --git a/crates/re_query2/src/range/mod.rs b/crates/re_query2/src/range/mod.rs new file mode 100644 index 000000000000..e4068c918b48 --- /dev/null +++ b/crates/re_query2/src/range/mod.rs @@ -0,0 +1,5 @@ +mod query; +mod results; + +pub use self::query::range; +pub use self::results::{RangeComponentResults, RangeResults}; diff --git a/crates/re_query2/src/range/query.rs b/crates/re_query2/src/range/query.rs new file mode 100644 index 000000000000..5c2c821bd846 --- /dev/null +++ b/crates/re_query2/src/range/query.rs @@ -0,0 +1,38 @@ +use re_data_store::{DataStore, RangeQuery}; +use re_log_types::EntityPath; +use re_types_core::ComponentName; + +use crate::RangeResults; + +// --- + +/// Queries for the given `component_names` using range semantics. +/// +/// See [`RangeResults`] for more information about how to handle the results. +pub fn range( + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, + component_names: impl IntoIterator, +) -> RangeResults { + re_tracing::profile_function!(entity_path.to_string()); + + let mut results = RangeResults::default(); + + for component_name in component_names { + let data = store.range(query, entity_path, [component_name]).map( + |(data_time, row_id, mut cells)| { + // Unwrap: + // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` + // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null + let cell = cells[0].take().unwrap(); + + ((data_time, row_id), cell) + }, + ); + + results.add(component_name, data); + } + + results +} diff --git a/crates/re_query2/src/range/results.rs b/crates/re_query2/src/range/results.rs new file mode 100644 index 000000000000..883101db0264 --- /dev/null +++ b/crates/re_query2/src/range/results.rs @@ -0,0 +1,198 @@ +use nohash_hasher::IntMap; +use re_log_types::{DataCell, RowId, TimeInt}; +use re_types_core::ComponentName; +use re_types_core::{Component, DeserializationError, DeserializationResult}; + +use crate::{Promise, PromiseResolver, PromiseResult}; + +// --- + +/// Raw results for a range query. +/// +/// The data is neither deserialized, nor resolved/converted. +/// It it the raw [`DataCell`]s, straight from our datastore. +/// +/// Use [`RangeResults::get`], [`RangeResults::get_required`] and [`RangeResults::get_optional`] +/// in order to access the raw results for each individual component. +#[derive(Default, Debug, Clone)] +pub struct RangeResults { + /// Raw results for each individual component. + pub components: IntMap, +} + +impl RangeResults { + #[inline] + pub fn contains(&self, component_name: impl Into) -> bool { + self.components.contains_key(&component_name.into()) + } + + /// Returns the [`RangeComponentResults`] for the specified `component_name`. + #[inline] + pub fn get(&self, component_name: impl Into) -> Option<&RangeComponentResults> { + self.components.get(&component_name.into()) + } + + /// Returns the [`RangeComponentResults`] for the specified `component_name`. + /// + /// Returns an error if the component is not present. + #[inline] + pub fn get_required( + &self, + component_name: impl Into, + ) -> crate::Result<&RangeComponentResults> { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { + Ok(component) + } else { + Err(DeserializationError::MissingComponent { + component: component_name, + backtrace: ::backtrace::Backtrace::new_unresolved(), + } + .into()) + } + } + + /// Returns the [`RangeComponentResults`] for the specified `component_name`. + /// + /// Returns empty results if the component is not present. + #[inline] + pub fn get_optional(&self, component_name: impl Into) -> &RangeComponentResults { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { + component + } else { + static DEFAULT: RangeComponentResults = RangeComponentResults::empty(); + &DEFAULT + } + } +} + +impl RangeResults { + #[doc(hidden)] + #[inline] + pub fn add( + &mut self, + component_name: ComponentName, + data: impl Iterator, + ) { + let (indices, cells): (Vec<_>, Vec<_>) = data + .map(|(index, cell)| (index, Promise::new(cell))) + .unzip(); + + let results = RangeComponentResults { indices, cells }; + results.sanity_check(); + + self.components.insert(component_name, results); + } +} + +// --- + +/// Uncached results for a particular component when using a range query. +#[derive(Debug, Clone)] +pub struct RangeComponentResults { + pub indices: Vec<(TimeInt, RowId)>, + pub cells: Vec, +} + +impl Default for RangeComponentResults { + #[inline] + fn default() -> Self { + Self::empty() + } +} + +impl RangeComponentResults { + #[inline] + pub const fn empty() -> Self { + Self { + indices: Vec::new(), + cells: Vec::new(), + } + } + + /// No-op in release. + #[inline] + pub fn sanity_check(&self) { + let Self { indices, cells } = self; + if cfg!(debug_assertions) { + assert_eq!(indices.len(), cells.len()); + } + } +} + +impl RangeComponentResults { + #[inline] + pub fn indices(&self) -> &[(TimeInt, RowId)] { + &self.indices + } + + #[inline] + pub fn iter_indices(&self) -> impl ExactSizeIterator + '_ { + self.indices.iter().copied() + } + + /// Returns the component data as a vector of dense vectors. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn to_dense( + &self, + resolver: &PromiseResolver, + ) -> Vec>>> { + self.cells + .iter() + .map(|cell| { + resolver.resolve(cell).map(|cell| { + cell.try_to_native() + .map_err(|err| DeserializationError::DataCellError(err.to_string())) + }) + }) + .collect() + } + + /// Returns the component data as an iterator of dense vectors. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn iter_dense( + &self, + resolver: &PromiseResolver, + ) -> impl ExactSizeIterator>>> { + self.to_dense(resolver).into_iter() + } + + /// Returns the component data as a vector of sparse vectors. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn to_sparse( + &self, + resolver: &PromiseResolver, + ) -> Vec>>>> { + self.cells + .iter() + .map(|cell| { + resolver.resolve(cell).map(|cell| { + cell.try_to_native_opt() + .map_err(|err| DeserializationError::DataCellError(err.to_string())) + }) + }) + .collect() + } + + /// Returns the component data as an iterator of sparse vectors. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn iter_sparse( + &self, + resolver: &PromiseResolver, + ) -> impl ExactSizeIterator>>>> { + self.to_sparse(resolver).into_iter() + } +} diff --git a/crates/re_query2/tests/range.rs b/crates/re_query2/tests/range.rs new file mode 100644 index 000000000000..6f47f1fb1184 --- /dev/null +++ b/crates/re_query2/tests/range.rs @@ -0,0 +1,496 @@ +use itertools::izip; +use re_query2::PromiseResolver; +use re_types::{components::InstanceKey, Archetype}; + +use re_data_store::{DataStore, TimeInt, TimeRange}; +use re_log_types::{ + build_frame_nr, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimePoint, +}; +use re_types_core::Loggable as _; + +// --- + +#[test] +fn simple_range() -> anyhow::Result<()> { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + + let resolver = PromiseResolver::default(); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + { + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; + store.insert_row(&row)?; + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; + store.insert_row(&row)?; + } + + let timepoint2 = [build_frame_nr(223)]; + { + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; + store.insert_row(&row)?; + } + + let timepoint3 = [build_frame_nr(323)]; + { + let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; + store.insert_row(&row)?; + } + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + let results = re_query2::range( + &store, + &query, + &entity_path, + MyPoints::all_components().iter().copied(), + ); + + let all_points = results.get_required(MyPoint::name())?; + let all_colors = results.get_optional(MyColor::name()); + + let all_points = izip!( + all_points.iter_indices(), + all_points.iter_dense::(&resolver) + ); + let all_colors = izip!( + all_colors.iter_indices(), + all_colors.iter_sparse::(&resolver) + ); + + let mut results = re_query2::range_zip_1x1(all_points, all_colors); + + // We expect this to generate the following `DataFrame`s: + // + // Frame #323: + // ┌──────────────┬─────────────────┐ + // │ MyPoint ┆ MyColor │ + // ╞══════════════╪═════════════════╡ + // │ {10.0,20.0} ┆ 4278190080 │ + // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ {30.0,40.0} ┆ 4278190080 │ + // └──────────────┴─────────────────┘ + + { + // Frame #323 + + let ((data_time, _row_id), points, colors) = results.next().unwrap(); + assert_eq!(TimeInt::new_temporal(323), data_time); + + let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = points.flatten().unwrap(); + let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(points, colors, || None).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + + assert!(results.next().is_none()); + + // --- Second test: `[timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + let results = re_query2::range( + &store, + &query, + &entity_path, + MyPoints::all_components().iter().copied(), + ); + + let all_points = results.get_required(MyPoint::name())?; + let all_colors = results.get_optional(MyColor::name()); + + let all_points = izip!( + all_points.iter_indices(), + all_points.iter_dense::(&resolver) + ); + let all_colors = izip!( + all_colors.iter_indices(), + all_colors.iter_sparse::(&resolver) + ); + + let mut results = re_query2::range_zip_1x1(all_points, all_colors); + + // We expect this to generate the following `DataFrame`s: + // + // Frame #123: + // ┌───────────────┬─────────────────┐ + // │ MyPoint ┆ MyColor │ + // ╞═══════════════╪═════════════════╡ + // │ {1.0,2.0} ┆ null │ + // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ {3.0,4.0} ┆ null │ + // └───────────────┴─────────────────┘ + // + // Frame #323: + // ┌───────────────┬─────────────────┐ + // │ MyPoint ┆ MyColor │ + // ╞═══════════════╪═════════════════╡ + // │ {10.0,20.0} ┆ 4278190080 │ + // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ {30.0,40.0} ┆ 4278190080 │ + // └───────────────┴─────────────────┘ + + { + // Frame #123 + + let ((data_time, _row_id), points, colors) = results.next().unwrap(); + assert_eq!(TimeInt::new_temporal(123), data_time); + + let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let expected_colors = vec![None, None]; + + let points = points.flatten().unwrap(); + let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(points, colors, || None).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + { + // Frame #323 + + let ((data_time, _row_id), points, colors) = results.next().unwrap(); + assert_eq!(TimeInt::new_temporal(323), data_time); + + let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = points.flatten().unwrap(); + let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(points, colors, || None).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + + assert!(results.next().is_none()); + + Ok(()) +} + +#[test] +fn static_range() -> anyhow::Result<()> { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + + let resolver = PromiseResolver::default(); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + { + // Create some Positions with implicit instances + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let mut row = + DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint1, 2, positions)?; + row.compute_all_size_bytes(); + store.insert_row(&row)?; + + // Assign one of them a color with an explicit instance + let color_instances = vec![InstanceKey(1)]; + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 1, + (color_instances.clone(), colors.clone()), + )?; + store.insert_row(&row)?; + } + + let timepoint2 = [build_frame_nr(223)]; + { + // Assign one of them a color with an explicit instance + let color_instances = vec![InstanceKey(0)]; + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells2_sized( + RowId::new(), + entity_path.clone(), + timepoint2, + 1, + (color_instances.clone(), colors.clone()), + )?; + store.insert_row(&row)?; + + // Insert statically too! + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors, + )?; + store.insert_row(&row)?; + } + + let timepoint3 = [build_frame_nr(323)]; + { + // Create some Positions with implicit instances + let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint3, + 2, + positions, + )?; + store.insert_row(&row)?; + } + + // ┌──────────┬───────────────┬────────────────────────────┐ + // │ frame_nr ┆ MyColor ┆ MyColor │ + // ╞══════════╪═══════════════╪════════════════════════════╡ + // │ null ┆ [4278190080] ┆ null │ + // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ 123 ┆ null ┆ [{1.0,2.0}, {3.0,4.0}] │ + // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ 123 ┆ [4278190080] ┆ null │ + // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ 223 ┆ [4278190080] ┆ null │ + // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ 223 ┆ [4278190080] ┆ null │ + // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + // │ 323 ┆ null ┆ [{10.0,20.0}, {30.0,40.0}] │ + // └──────────┴───────────────┴────────────────────────────┘ + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + let results = re_query2::range( + &store, + &query, + &entity_path, + MyPoints::all_components().iter().copied(), + ); + + let all_points = results.get_required(MyPoint::name())?; + let all_colors = results.get_optional(MyColor::name()); + + let all_points = izip!( + all_points.iter_indices(), + all_points.iter_dense::(&resolver) + ); + let all_colors = izip!( + all_colors.iter_indices(), + all_colors.iter_sparse::(&resolver) + ); + + let mut results = re_query2::range_zip_1x1(all_points, all_colors); + + { + // Frame #323 + + let ((data_time, _row_id), points, colors) = results.next().unwrap(); + assert_eq!(TimeInt::new_temporal(323), data_time); + + let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = points.flatten().unwrap(); + let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(points, colors, || None).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + + // --- Second test: `[timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + let results = re_query2::range( + &store, + &query, + &entity_path, + MyPoints::all_components().iter().copied(), + ); + + let all_points = results.get_required(MyPoint::name())?; + let all_colors = results.get_optional(MyColor::name()); + + let all_points = izip!( + all_points.iter_indices(), + all_points.iter_dense::(&resolver) + ); + let all_colors = izip!( + all_colors.iter_indices(), + all_colors.iter_sparse::(&resolver) + ); + + let mut results = re_query2::range_zip_1x1(all_points, all_colors); + + { + // Frame #123 (partially static) + + let ((data_time, _row_id), points, colors) = results.next().unwrap(); + assert_eq!(TimeInt::new_temporal(123), data_time); + + let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = points.flatten().unwrap(); + let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(points, colors, || None).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + { + // Frame #323 + + let ((data_time, _row_id), points, colors) = results.next().unwrap(); + assert_eq!(TimeInt::new_temporal(323), data_time); + + let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = points.flatten().unwrap(); + let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(points, colors, || None).unzip(); + + eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + + // --- Third test: `[-inf, +inf]` --- + + let query = + re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); + + let results = re_query2::range( + &store, + &query, + &entity_path, + MyPoints::all_components().iter().copied(), + ); + + let all_points = results.get_required(MyPoint::name())?; + let all_colors = results.get_optional(MyColor::name()); + + let all_points = izip!( + all_points.iter_indices(), + all_points.iter_dense::(&resolver) + ); + let all_colors = izip!( + all_colors.iter_indices(), + all_colors.iter_sparse::(&resolver) + ); + + let mut results = re_query2::range_zip_1x1(all_points, all_colors); + + { + // Frame #123 (partially static) + + let ((data_time, _row_id), points, colors) = results.next().unwrap(); + assert_eq!(TimeInt::new_temporal(123), data_time); + + let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = points.flatten().unwrap(); + let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(points, colors, || None).unzip(); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + { + // Frame #323 + + let ((data_time, _row_id), points, colors) = results.next().unwrap(); + assert_eq!(TimeInt::new_temporal(323), data_time); + + let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let expected_colors = vec![ + Some(MyColor::from_rgb(255, 0, 0)), + Some(MyColor::from_rgb(255, 0, 0)), + ]; + + let points = points.flatten().unwrap(); + let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); + + let (got_points, got_colors): (Vec<_>, Vec<_>) = + re_query2::clamped_zip_1x1(points, colors, || None).unzip(); + + eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!(expected_points, got_points); + similar_asserts::assert_eq!(expected_colors, got_colors); + } + + Ok(()) +} From 86da3a5e2919c6d2937d1172ee9fa702a2f6bd9e Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:12:06 +0200 Subject: [PATCH 228/508] Fix argparse deprecation warning in `scripts/ci/crates.py` (#5845) ### What `crates.py` would emit a deprecation warning under python >= 3.11 because of some nested `add_mutually_exclusive_group`. Turns out this nesting wasn't really necessary. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5845) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5845?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5845?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5845) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- scripts/ci/crates.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/ci/crates.py b/scripts/ci/crates.py index 3fed5aa3580a..3ec164b3fc4d 100755 --- a/scripts/ci/crates.py +++ b/scripts/ci/crates.py @@ -46,7 +46,6 @@ DEFAULT_PRE_ID = "alpha" MAX_PUBLISH_WORKERS = 3 - R = Fore.RED G = Fore.GREEN B = Fore.BLUE @@ -569,8 +568,7 @@ def main() -> None: cmds_parser = parser.add_subparsers(title="cmds", dest="cmd") version_parser = cmds_parser.add_parser("version", help="Bump the crate versions") - target_version_parser = version_parser.add_mutually_exclusive_group() - target_version_update_group = target_version_parser.add_mutually_exclusive_group() + target_version_update_group = version_parser.add_mutually_exclusive_group() target_version_update_group.add_argument( "--bump", type=Bump, choices=list(Bump), help="Bump version according to semver" ) From 9cca581f21edd4b2ada898d39b4a7bf546f616d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Tue, 9 Apr 2024 09:27:21 +0200 Subject: [PATCH 229/508] Check release branch format (#5846) ### What - Closes https://github.com/rerun-io/rerun/issues/5844 Adds a check for valid semver string embedded in release branch name to the start of the release workflow. `release-0.15` previously failed, and will now still fail with a better error message. `release-0.15.0` is the correct format. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5846) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5846?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5846?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5846) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/release.yml | 6 ++++-- RELEASES.md | 3 +++ scripts/ci/crates.py | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 83e533dd09e9..c37163d9b52a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -96,13 +96,15 @@ jobs: id: versioning shell: bash run: | - - echo "release_version: $release_version" + echo Check that the release version matches expected format… + python3 scripts/ci/crates.py check-git-branch-name echo Parse the release version from the branch name… # `release-0.8.1-meta.N` -> `0.8.1` release_version=$(python3 scripts/ci/crates.py get-version --from git --finalize) + echo "release_version: $release_version" + echo Store version before the update, so we can later detect if it changed… previous=$(python3 scripts/ci/crates.py get-version) diff --git a/RELEASES.md b/RELEASES.md index b5eb0df429f4..6746a97c0d19 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -51,6 +51,9 @@ If we are doing a patch release, we do a branch off of the latest release tag (e - `release-0.x.y-alpha.N` where `N` is incremented from the previous alpha, or defaulted to `1` if no previous alpha exists. + Note that `release-0.x` is _invalid_. Always specify the `y`, even if it is `0`, + e.g. `release-0.15.0` instead of `release-0.15`. + ![Image showing the branch create UI. You can find the `new branch` button at https://github.com/rerun-io/rerun/branches](https://github.com/rerun-io/rerun/assets/1665677/becaad03-9262-4476-b811-c23d40305aec) Note: you do not need to create a PR for this branch -- the release workflow will do that for you. diff --git a/scripts/ci/crates.py b/scripts/ci/crates.py index 3ec164b3fc4d..6aa20992b0f3 100755 --- a/scripts/ci/crates.py +++ b/scripts/ci/crates.py @@ -526,9 +526,13 @@ def __str__(self) -> str: return self.value +def get_release_version_from_git_branch() -> str: + return git.Repo().active_branch.name.lstrip("release-") + + def get_version(target: Target | None) -> VersionInfo: if target is Target.Git: - branch_name = git.Repo().active_branch.name.lstrip("release-") + branch_name = get_release_version_from_git_branch() try: current_version = VersionInfo.parse(branch_name) # ensures that it is a valid version except ValueError: @@ -547,6 +551,29 @@ def get_version(target: Target | None) -> VersionInfo: return current_version +def is_valid_version_string(version: str) -> bool: + # remove metadata -> split into digits + parts = version.split("-")[0].split(".") + + if len(parts) != 3: + return False + + for part in parts: + if not part.isdigit(): + return False + + return True + + +def check_git_branch_name() -> None: + version = get_release_version_from_git_branch() + + if is_valid_version_string(version): + print(f'"{version}" is a valid version string.') + else: + raise Exception(f'"{version}" is not a valid version string. See RELEASES.md for supported formats') + + def print_version(target: Target | None, finalize: bool = False, pre_id: bool = False) -> None: current_version = get_version(target) @@ -592,6 +619,8 @@ def main() -> None: publish_parser.add_argument("--dry-run", action="store_true", help="Display the execution plan") publish_parser.add_argument("--allow-dirty", action="store_true", help="Allow uncommitted changes") + cmds_parser.add_parser("check-git-branch-name", help="Check if the git branch name uses the correct format") + get_version_parser = cmds_parser.add_parser("get-version", help="Get the current crate version") get_version_parser.add_argument( "--finalize", action="store_true", help="Return version finalized if it is a pre-release" @@ -603,6 +632,8 @@ def main() -> None: args = parser.parse_args() + if args.cmd == "check-git-branch-name": + check_git_branch_name() if args.cmd == "get-version": print_version(args.target, args.finalize, args.pre_id) if args.cmd == "version": From 2c8f66fe43153466b559d5ebfc65d3566a87d467 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 9 Apr 2024 09:55:17 +0200 Subject: [PATCH 230/508] Fix missing clamping semantics for raw instance-based UIs (#5858) I forgot to add the clamping semantics for instance-based UIs that work on the raw arrow data rather than deserialized native types. It's trivial. --- .../re_query_cache2/src/latest_at/helpers.rs | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/crates/re_query_cache2/src/latest_at/helpers.rs b/crates/re_query_cache2/src/latest_at/helpers.rs index 9273e12e0fc9..a941fe7b56bd 100644 --- a/crates/re_query_cache2/src/latest_at/helpers.rs +++ b/crates/re_query_cache2/src/latest_at/helpers.rs @@ -153,8 +153,10 @@ impl CachedLatestAtComponentResults { re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); None } + PromiseResult::Ready(data) => { - // TODO(#5303): Figure out we'd like to integrate clamping semantics into selection panel. + // TODO(#5303): Figure out if/how we'd like to integrate clamping semantics into the + // selection panel. // // For now, we simply always clamp, which is the closest to the legacy behavior that the UI // expects. @@ -171,6 +173,7 @@ impl CachedLatestAtComponentResults { None } } + PromiseResult::Error(err) => { re_log::log_once!( level, @@ -200,17 +203,29 @@ impl CachedLatestAtComponentResults { re_log::debug_once!("Couldn't get {component_name}: promise still pending"); None } - PromiseResult::Ready(cell) if cell.as_arrow_ref().len() > index => { - Some(cell.as_arrow_ref().sliced(index, 1)) - } + PromiseResult::Ready(cell) => { - re_log::log_once!( - level, - "Couldn't get {component_name}: index not found (index: {index}, length: {})", - cell.as_arrow_ref().len(), - ); - None + let len = cell.num_instances() as usize; + + // TODO(#5303): Figure out if/how we'd like to integrate clamping semantics into the + // selection panel. + // + // For now, we simply always clamp, which is the closest to the legacy behavior that the UI + // expects. + let index = usize::min(index, len.saturating_sub(1)); + + if len > index { + Some(cell.as_arrow_ref().sliced(index, 1)) + } else { + re_log::log_once!( + level, + "Couldn't deserialize {component_name}: index not found (index: {index}, length: {})", + len, + ); + None + } } + PromiseResult::Error(err) => { re_log::log_once!( level, From 19c13c4ceb0d3b8dfc3c6e67a641e38619f11429 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 9 Apr 2024 10:12:06 +0200 Subject: [PATCH 231/508] Split `re_viewport`'s codegened types into `re_types_blueprint` (#5853) :point_up: This is a prerequisite in order to implement `ToArchetype for QueryResults` for all blueprint related types without ending up in a dependency cycle of doom. --- - Part of #5421 - Followed by https://github.com/rerun-io/rerun/pull/5860 --- ARCHITECTURE.md | 25 ++-- Cargo.lock | 24 ++++ Cargo.toml | 1 + crates/re_data_ui/Cargo.toml | 1 + .../src/blueprint_types.rs} | 15 +- .../re_data_ui/src/component_ui_registry.rs | 3 + crates/re_data_ui/src/lib.rs | 1 + .../archetypes/container_blueprint.fbs | 2 +- .../blueprint/archetypes/panel_blueprint.fbs | 2 +- .../archetypes/viewport_blueprint.fbs | 2 +- .../blueprint/components/auto_layout.fbs | 2 +- .../blueprint/components/auto_space_views.fbs | 2 +- .../blueprint/components/container_kind.fbs | 2 +- .../blueprint/components/grid_columns.fbs | 2 +- .../components/included_space_view.fbs | 2 +- .../blueprint/components/root_container.fbs | 2 +- .../components/space_view_maximized.fbs | 2 +- crates/re_types_blueprint/.gitattributes | 129 ++++++++++++++++++ crates/re_types_blueprint/Cargo.toml | 46 +++++++ crates/re_types_blueprint/README.md | 10 ++ .../src/blueprint/archetypes/.gitattributes | 0 .../archetypes/container_blueprint.rs | 0 .../src/blueprint/archetypes/mod.rs | 0 .../blueprint/archetypes/panel_blueprint.rs | 0 .../archetypes/viewport_blueprint.rs | 0 .../src/blueprint/components/.gitattributes | 0 .../src/blueprint/components/auto_layout.rs | 0 .../blueprint/components/auto_layout_ext.rs | 0 .../blueprint/components/auto_space_views.rs | 0 .../blueprint/components/container_kind.rs | 0 .../src/blueprint/components/grid_columns.rs | 0 .../components/included_space_view.rs | 0 .../src/blueprint/components/mod.rs | 1 - .../blueprint/components/root_container.rs | 0 .../components/space_view_maximized.rs | 0 .../src/blueprint/mod.rs | 4 - crates/re_types_blueprint/src/lib.rs | 14 ++ crates/re_viewer/Cargo.toml | 1 + crates/re_viewer/src/app.rs | 3 +- .../src/blueprint/validation_gen/mod.rs | 14 +- crates/re_viewport/Cargo.toml | 3 +- .../re_viewport/src/blueprint/.gitattributes | 7 - .../components/container_kind_ext.rs | 23 ---- crates/re_viewport/src/container.rs | 20 +-- crates/re_viewport/src/lib.rs | 60 +++++--- crates/re_viewport/src/viewport_blueprint.rs | 14 +- 46 files changed, 326 insertions(+), 113 deletions(-) rename crates/{re_viewport/src/blueprint/data_ui.rs => re_data_ui/src/blueprint_types.rs} (67%) create mode 100644 crates/re_types_blueprint/.gitattributes create mode 100644 crates/re_types_blueprint/Cargo.toml create mode 100644 crates/re_types_blueprint/README.md rename crates/{re_viewport => re_types_blueprint}/src/blueprint/archetypes/.gitattributes (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/archetypes/container_blueprint.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/archetypes/mod.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/archetypes/panel_blueprint.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/archetypes/viewport_blueprint.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/.gitattributes (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/auto_layout.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/auto_layout_ext.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/auto_space_views.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/container_kind.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/grid_columns.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/included_space_view.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/mod.rs (96%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/root_container.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/components/space_view_maximized.rs (100%) rename crates/{re_viewport => re_types_blueprint}/src/blueprint/mod.rs (76%) create mode 100644 crates/re_types_blueprint/src/lib.rs delete mode 100644 crates/re_viewport/src/blueprint/.gitattributes delete mode 100644 crates/re_viewport/src/blueprint/components/container_kind_ext.rs diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index bfa4b5af5ffe..1174d56a85c6 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -88,11 +88,11 @@ Of course, this will only take us so far. In the future we plan on caching queri Here is an overview of the crates included in the project: - - - - - + + + + + + + When you are working with the Rerun viewer, there are two separate pieces that combine to produce what you see: the "recording" and the "blueprint." @@ -21,8 +24,8 @@ for the viewer to display. ## Loose coupling The blueprint and the recording are only loosely coupled. Rerun uses the -"application ID" to determine whether a blueprint and a recording should be used -together, but they are not directly linked beyond that. +[application ID](apps-and-recordings.md) to determine whether a blueprint and a +recording should be used together, but they are not directly linked beyond that. This means that either can be changed independently of the other. Keeping the blueprint constant while changing the recording will allow you to compare @@ -42,6 +45,17 @@ viewer, you are actually modifying the blueprint. (Note that while there may be some exceptions to this rule at the moment, the intent is to eventually migrate all state to the blueprint.) +## Current, default, and heuristics blueprints + + + + +Blueprints may originate from multiple sources. + +- The "current blueprint" for a given application ID is the one that is used by the viewer to display data at any given time. It is updated for each change made to the visualization within the viewer, and may be saved to a blueprint file at any time. +- The "default blueprint" is a snapshot that is set or updated when a blueprint is received from code or loaded from a file. The current blueprint may be reset to default blueprint at any time by using the "reset" button in the blueprint panel's header. +- The "heuristic blueprint" is an automatically-produced blueprint based on the recording data. When no default blueprint is available, the heuristic blueprint is used when resetting the current blueprint. It is also possible to reset to the heuristic blueprint in the selection panel after selecting an application. + ## What is a blueprint Under the hood, the blueprint is just data. It is represented by a diff --git a/docs/content/concepts/entity-component.md b/docs/content/concepts/entity-component.md index e3c7925d31d8..e91785c4784e 100644 --- a/docs/content/concepts/entity-component.md +++ b/docs/content/concepts/entity-component.md @@ -1,6 +1,6 @@ --- title: Entities and Components -order: 1 +order: 100 --- ## Data model diff --git a/docs/content/concepts/entity-path.md b/docs/content/concepts/entity-path.md index e9f1473402c6..bffb28c6efd7 100644 --- a/docs/content/concepts/entity-path.md +++ b/docs/content/concepts/entity-path.md @@ -1,6 +1,6 @@ --- title: The Entity Path Hierarchy -order: 1 +order: 200 --- ## Entity paths diff --git a/docs/content/concepts/spaces-and-transforms.md b/docs/content/concepts/spaces-and-transforms.md index ff89256b3904..cd20dabf3534 100644 --- a/docs/content/concepts/spaces-and-transforms.md +++ b/docs/content/concepts/spaces-and-transforms.md @@ -1,6 +1,6 @@ --- title: Spaces and Transforms -order: 2 +order: 300 --- ## The definition of a space diff --git a/docs/content/concepts/timelines.md b/docs/content/concepts/timelines.md index bc08ef9d9539..f7eabc6f4d1f 100644 --- a/docs/content/concepts/timelines.md +++ b/docs/content/concepts/timelines.md @@ -1,12 +1,15 @@ --- title: Events and Timelines -order: 3 +order: 400 --- ## Timelines Each piece of logged data is associated with one or more timelines. -By default, each log is added to the `log_time` timeline, with a timestamp assigned by the SDK. + +The logging SDK always creates two timelines for you: +* `log_tick` - a sequence timeline with the sequence number of the log call +* `log_time` - a temporal timeline with the time of the log call You can use the _set time_ functions (Python reference: [set_time_sequence](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_sequence), [set_time_seconds](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_seconds), [set_time_nanos](https://ref.rerun.io/docs/python/stable/common/logging_functions/#rerun.set_time_nanos)) to associate logs with other timestamps on other timelines. For example: diff --git a/docs/content/getting-started/configure-the-viewer.md b/docs/content/getting-started/configure-the-viewer.md index 2d47dd5bb0c6..21fc71ae590d 100644 --- a/docs/content/getting-started/configure-the-viewer.md +++ b/docs/content/getting-started/configure-the-viewer.md @@ -1,11 +1,11 @@ --- -title: Configure the Viewer +title: Configure the viewer order: 5 --- -Although the Rerun Viewer tries to do a reasonable job of using heuristics to automatically determine -an appropriate layout given the data that you provide, there will always be situations where the heuristic -results don't match the needs of a particular use-case. +By default, the Rerun viewer uses heuristics to automatically determine an appropriate +layout given the data that you provide. However, there will always be situations +where the heuristic results don't match the needs of a particular use-case. Fortunately, almost all aspects of the viewer can be configured via the [Blueprint](../reference/viewer/blueprint.md). diff --git a/docs/content/getting-started/configure-the-viewer/navigating-the-viewer-continued.md b/docs/content/getting-started/configure-the-viewer/navigating-the-viewer-continued.md deleted file mode 100644 index 91c60cb97ce7..000000000000 --- a/docs/content/getting-started/configure-the-viewer/navigating-the-viewer-continued.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Navigating the viewer (continued) -order: 4 ---- - -This guide builds on top of the previous tutorial: -[Navigating the viewer](../navigating-the-viewer.md). Please follow that tutorial first if you haven't already. - -This guide will familiarize you with the basics of using the Rerun Viewer with an example dataset. By the end you should -be comfortable with the following topics: - -- [Configuring views](#configuring-views) -- [Creating new views](#creating-new-views) - -## Configuring views - -Views in Rerun are configured by [Blueprints](../../reference/viewer/blueprint.md). We will now use blueprints to adjust -both an individual entity as well as the contents of a space view itself. - -### Adjusting entity properties - -First, click to select the entity named `points` in the `/ (Spatial)` view in the Blueprint panel. Now, look and the -selection panel -- in addition to the information about the data associated with that entity, you will see a "Blueprint" -section. - -Try toggling "visible" on and off and you will see that the points disappear and reappear. Next, click the control -labeled "visible history" and drag it to the right to increase the value. As you drag farther you will see more points -show up in the view. This is making historical points, from farther back in time visible within the time point of this -view. Because the points are logged in stationary 3D space, aggregating them here gives us a more complete view of the -car. Leave the visible history with a value of 50. - - - - - - - viewer walkthrough adjusting visible history screenshot - - -### Modifying the contents of a space view - -Now select the `/ (Spatial)` view itself. We will start by giving this space view a different name. At the very -top of the selection panel you will see a text box labeled "Space view:". Go ahead and change the name to -`Reconstruction`. The name will also update in the blueprint panel on the left. - -Like with the entity selection, you will see a Blueprint section within the Selection panel. This time, click on the -button labeled "Add/Remove Entities". This pop-up shows all of the entities that were logged as part of this session. -You can click on the "+" or "-" buttons to add or remove entities from this view. Go ahead and remove the entity called -"keypoints," and then add them back again. Unlike hiding an entity, you will notice that as you remove entities they -completely disappear from the blueprint panel on the left. Entities that are incompatible with the selected view will be -grayed out. For example, you cannot add a scalar to a spatial scene. - - - - - - - viewer walkthrough modifying contents of a space view screenshot - - -## Creating new views - -New views & view containers (grid, vertical, etc.) can be created using the "+" button at the top of the Blueprint panel or -from the selection panel when selecting a container. - -After creating a view you usually want to proceed to editing its origin and query (which entities are shown) in the selection panel. - -Your view layout might be feeling a little cluttered now. You can quickly hide views you're -not using from the blueprint panel by hovering over the view and then clicking the icon that looks like an eye. Go ahead -and hide the `image` and `avg_reproj_err` views, and collapse the expanded timeline panel using the button in the upper -right corner. Note that even with the timeline collapsed you still have access to timeline controls, including a slider. - - - - - - - viewer walkthrough toggle visibility screenshot - - -### Reusing what you've learned - -Finally, use what we covered in the previous section to change the contents of this view. Select the new `camera` view, -then choose "Add/remove entities." Remove the 2D "keypoints" and add in the 3D "points." Note that these points do not -have visible history turned on -- that's because the blueprint is part of the view and not part of the entity. -Select the points within this view by clicking on them in the blueprint or the view itself, and then give them visible -history as well. When you are done, your view should look like this: - - - - - - - viewer walkthrough camera view screenshot - - -Now move the slider back and forth and see what happens. Even though they are both views of the same camera and point -entities, they behave quite differently. On the top the camera moves relative to the car, while on the bottom the car -moves relative to the camera. This is because the new views have _different_ space roots, and Rerun uses the transform -system to transform or project all data into the space root for the given view. - -## Conclusion - -That brings us to the end of this walkthrough. To recap, you have learned how to: - -- Configure entity blueprint properties. -- Add and remove entities from views. -- Create and configure new views. -- And some basics of how transforms work. - -Again, if you ran into any issues following this guide, please don't hesitate to [open an issue](https://github.com/rerun-io/rerun/issues/new/choose). - -### Up next - -To get started with writing a program to logging data with the Rerun SDK see the [getting started guides](../quick-start). - -To see and explore other data, you can check out the [examples](/examples). - -For deeper context on the ideas covered here, consult the [Concept overview](../../concepts.md). diff --git a/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md index cdecb3f7a07b..0102a7ee4fd4 100644 --- a/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md +++ b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md @@ -3,14 +3,28 @@ title: Configure the viewer through code order: 3 --- -This tutorial will walk you through using the Blueprint APIs to better control the -layout and appearance of your data in the Rerun Viewer in Python. +This tutorial will walk you through using the +[Blueprint APIs](../../howto/configure-viewer-through-code.md) to better control +the layout and appearance of your data in the Rerun Viewer in Python. -This walkthrough is based on the [stock charts](https://github.com/rerun-io/rerun/tree/main/examples/python/blueprint_stocks?speculative-link) example. +This walkthrough is based on the [stock charts](https://github.com/rerun-io/rerun/tree/main/examples/python/blueprint_stocks) example. The main differences between this tutorial and the linked example are related to additional processing of command-line flags, which are omitted here for simplicity. -## Create an environment for you example +All of the examples in this tutorial use the exact same data. However, by changing the blueprint using +small statements such as: +```python +rrb.Blueprint( + rrb.Vertical( + rrb.TextDocumentView(name="Info", origin="/stocks/AAPL/info"), + rrb.TimeSeriesView(name="Chart", origin="/stocks/AAPL"), + row_shares=[1, 4], + ) +) +``` +we will completely change the way the data is presented. + +## Create an environment for the example We start by creating a new virtual environment and installing the Rerun SDK along with the dependencies we will use in this example. diff --git a/docs/content/getting-started/data-in/open-any-file.md b/docs/content/getting-started/data-in/open-any-file.md index c80c94d455b4..fc3df08913ec 100644 --- a/docs/content/getting-started/data-in/open-any-file.md +++ b/docs/content/getting-started/data-in/open-any-file.md @@ -27,7 +27,7 @@ With the exception of `rrd` files that can be streamed from an HTTP URL (e.g. `r ## Logging file contents from the SDK -To log the contents of a file from the SDK you can use the `log_file_from_path` and `log_file_from_contents` methods ([C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#SOME_HASH_TBD?speculative-link), [Python](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.log_file_from_path?speculative-link), [Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path)) and the associated examples ([C++](https://github.com/rerun-io/rerun/blob/main/examples/cpp/log_file/main.cpp), [Python](https://github.com/rerun-io/rerun/blob/main/examples/python/log_file/main.py), [Rust](https://github.com/rerun-io/rerun/blob/main/examples/rust/log_file/src/main.rs)). +To log the contents of a file from the SDK you can use the `log_file_from_path` and `log_file_from_contents` methods ([C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a8f253422a7adc2a19b89d1538c05bcac), [Python](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.log_file_from_path), [Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path)) and the associated examples ([C++](https://github.com/rerun-io/rerun/blob/main/examples/cpp/log_file/main.cpp), [Python](https://github.com/rerun-io/rerun/blob/main/examples/python/log_file/main.py), [Rust](https://github.com/rerun-io/rerun/blob/main/examples/rust/log_file/src/main.rs)). Note: when calling these APIs from the SDK, the data will be loaded by the process running the SDK, not the Viewer! diff --git a/docs/content/getting-started/data-in/python.md b/docs/content/getting-started/data-in/python.md index 17ec0cc5dea2..7b587def3bbe 100644 --- a/docs/content/getting-started/data-in/python.md +++ b/docs/content/getting-started/data-in/python.md @@ -26,9 +26,16 @@ Start by opening your editor of choice and creating a new file called `dna_examp The first thing we need to do is to import `rerun` and initialize the SDK by calling [`rr.init`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.init). This init call is required prior to using any of the global logging calls, and allows us to name our recording using an `ApplicationId`. +We also import some other utilities we will use later in the example. + ```python import rerun as rr +from math import tau +import numpy as np +from rerun.utilities import build_color_spiral +from rerun.utilities import bounce_lerp + rr.init("rerun_example_dna_abacus") ``` @@ -65,30 +72,12 @@ And with that, we're ready to start sending out data: By default, the SDK will start a viewer in another process and automatically pipe the data through. There are other means of sending data to a viewer as we'll see at the end of this section, but for now this default will work great as we experiment. ---- - -The following sections will require importing a few different things to your script. -We will do so incrementally, but if you just want to update your imports once and call it a day, feel free to add the following to the top of your script: - -```python -from math import tau -import numpy as np -from rerun.utilities import build_color_spiral -from rerun.utilities import bounce_lerp -``` - ---- - ## Logging our first points The core structure of our DNA looking shape can easily be described using two point clouds shaped like spirals. Add the following to your file: ```python -# new imports -from rerun.utilities import build_color_spiral -from math import tau - NUM_POINTS = 100 # points and colors are both np.array((NUM_POINTS, 3)) @@ -166,10 +155,6 @@ rr.log( Which only leaves the beads: ```python -# new imports -import numpy as np -from rerun.utilities import bounce_lerp - offsets = np.random.rand(NUM_POINTS) beads = [bounce_lerp(points1[n], points2[n], offsets[n]) for n in range(NUM_POINTS)] colors = [[int(bounce_lerp(80, 230, offsets[n] * 2))] for n in range(NUM_POINTS)] @@ -214,10 +199,8 @@ Rerun has rich support for time: whether you want concurrent or disjoint timelin Let's add our custom timeline: ```python -# new imports -from rerun.utilities import bounce_lerp - time_offsets = np.random.rand(NUM_POINTS) + for i in range(400): time = i * 0.01 rr.set_time_seconds("stable_time", time) diff --git a/docs/content/getting-started/navigating-the-viewer.md b/docs/content/getting-started/navigating-the-viewer.md index 65b0119856a1..f3f7fbfe2390 100644 --- a/docs/content/getting-started/navigating-the-viewer.md +++ b/docs/content/getting-started/navigating-the-viewer.md @@ -244,12 +244,7 @@ Again, if you ran into any issues following this guide, please don't hesitate to ### Up next -The followup to this tutorial involves further configuring how the viewer displays the data. - -- See: [Configure the viewer interactively](./configure-the-viewer/interactively.md) - -To get started with writing a program to logging data with the Rerun SDK see the [getting started guides](./quick-start). - -To see and explore other data, you can check out the [examples](/examples). - -For deeper context on the ideas covered here, consult the [Concept overview](../concepts.md). +- [Get started](./quick-start) by writing a program to log data with the Rerun SDK. +- Learn how to further [configure the viewer](./configure-the-viewer) to suit your data. +- Explore other [examples of using Rerun](/examples). +- Consult the [concept overview](../concepts.md) for more context on the ideas covered here. diff --git a/docs/content/getting-started/quick-start.md b/docs/content/getting-started/quick-start.md index cb8b97e1988e..378e620051bb 100644 --- a/docs/content/getting-started/quick-start.md +++ b/docs/content/getting-started/quick-start.md @@ -3,7 +3,12 @@ title: Quick start order: 1 --- -Dive right into using the Rerun SDK with your favorite programming language! +Rerun is an SDK and engine for visualizing and interacting with multimodal data +streams. + +The primary way to get data into the Rerun viewer is to write code in +one of the supported languages. To learn more about installing Rerun and +the basics of getting started, choose your language: * [C++](./quick-start/cpp.md) * [Python](./quick-start/python.md) diff --git a/docs/content/getting-started/what-is-rerun.md b/docs/content/getting-started/what-is-rerun.md index 7b5546aabf54..bc40a17dd238 100644 --- a/docs/content/getting-started/what-is-rerun.md +++ b/docs/content/getting-started/what-is-rerun.md @@ -2,13 +2,11 @@ title: What is Rerun? order: 0 --- -To get a feeling of what you can do with Rerun -- browse the [example gallery](/examples) or -- try Rerun directly [in your browser](/viewer?speculative-link). -## What is Rerun? - -Rerun is an SDK and engine for visualizing and interacting with multimodal data streams. +Rerun is an SDK and viewer for visualizing and interacting with multimodal data streams. +The SDK lets you send data from anywhere, and the viewer, +which consists of an in-memory database and a visualization engine, +collects the data and aligns it so that you can scroll back and forth in time to understand what happened. Rerun is - Free to use @@ -18,23 +16,21 @@ Rerun is - Built in Rust to be cross platform and fast - Open source, dual licensed under MIT and Apache 2 -Rerun is used by engineers and researchers in fields like computer vision and robotics -to verify, debug, and demo. - -For a list of built-in data types, see the [Types](../reference/types.md) section. +Rerun is used by engineers and researchers in fields like robotics, +spatial computing, 2D/3D simulation, and finance to verify, debug, and demo. ## How do you use it? - - - - - + + + + + 1. Stream multimodal data from your code by logging it with the Rerun SDK 2. Visualize and interact with live or recorded streams, whether local or remote -3. Interactively build layouts and customize visualizations +3. Build layouts and customize visualizations interactively in the UI or through the SDK 4. Extend Rerun when you need to ## How does it work? @@ -43,7 +39,6 @@ Rerun goes to extreme lengths to make handling and visualizing multimodal data streams easy and performant. - ## Can't find what you're looking for? - Join us in the [Rerun Community Discord](https://discord.gg/xwcxHUjD35) diff --git a/docs/content/howto/configure-viewer-through-code.md b/docs/content/howto/configure-viewer-through-code.md index 7eb4bfcc5994..649d17003c19 100644 --- a/docs/content/howto/configure-viewer-through-code.md +++ b/docs/content/howto/configure-viewer-through-code.md @@ -11,7 +11,7 @@ Future releases will add support for the full scope of blueprint. See issues: [# ## Blueprint API overview -All blueprint APIs are in the [`rerun.blueprint`](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/?speculative-link) namespace. In our python examples, we typically import this using the `rrb` alias: +All blueprint APIs are in the [`rerun.blueprint`](https://ref.rerun.io/docs/python/stable/common/blueprint_apis/) namespace. In our python examples, we typically import this using the `rrb` alias: ```python import rerun.blueprint as rrb diff --git a/docs/content/howto/embed-rerun-viewer.md b/docs/content/howto/embed-rerun-viewer.md new file mode 100644 index 000000000000..428af8305a71 --- /dev/null +++ b/docs/content/howto/embed-rerun-viewer.md @@ -0,0 +1,114 @@ +--- +title: Embed a Rerun Viewer +order: 1500 +--- + +Integrating the Rerun Viewer into your web application can be accomplished either by [utilizing an iframe](#embedding-apprerunio-using-an-iframe) or by using our [JavaScript package](#using-the-javascript-package). + +## Embedding `app.rerun.io` using an ` +``` + +To implement this, fill in the placeholders: +- `RRD_URL` - The URL of the recording to display in the viewer. +- `RERUN_VERSION` - The version of the Rerun SDK used to generate the recording. + +For instance: + +```html + +``` + +## Using the JavaScript Package + +We offer JavaScript bindings to the Rerun Viewer via NPM. This method provides control over the viewer but requires a JavaScript web application setup with a bundler. + +Various packages are available: +- [@rerun-io/web-viewer](https://www.npmjs.com/package/@rerun-io/web-viewer): Suitable for JS apps without a framework or frameworks without dedicated packages. +- [@rerun-io/web-viewer-react](https://www.npmjs.com/package/@rerun-io/web-viewer-react): Designed specifically for React apps. + +> ℹ️ Note: The stability of the `rrd` format is still evolving, so the package version corresponds to the supported Rerun SDK version. Therefore, `@rerun-io/web-viewer@0.10.0` can only connect to a data source (`.rrd` file, WebSocket connection, etc.) originating from a Rerun SDK with version `0.10.0`! + +### Basic Example + +To begin, install the package ([@rerun-io/web-viewer](https://www.npmjs.com/package/@rerun-io/web-viewer)) from NPM: + +``` +npm i @rerun-io/web-viewer +``` + +> ℹ Note: This package is compatible only with recent browser versions. If your target browser lacks support for Wasm imports or top-level await, additional plugins may be required for your bundler setup. For instance, if you're using [Vite](https://vitejs.dev/), you'll need to install [vite-plugin-wasm](https://www.npmjs.com/package/vite-plugin-wasm) and [vite-plugin-top-level-await](https://www.npmjs.com/package/vite-plugin-top-level-await) and integrate them into your `vite.config.js`. + +Once installed and configured, import and use it within your application: + +```js +import { WebViewer } from "@rerun-io/web-viewer"; + +const rrdUrl = null; +const parentElement = document.body; + +const viewer = new WebViewer(); +await viewer.start(rrdUrl, parentElement); +``` + +The viewer creates a `` on the provided `parentElement` and executes within it. + +The first argument for `start` determines the recordings to open in the viewer. It can be: +- `null` for an initially empty viewer +- a URL string to open a single recording +- an array of strings to open multiple recordings + +Each URL can be either a file served over `http` or a connection to an SDK using our [serve](https://www.rerun.io/docs/reference/sdk-operating-modes#serve) API. See [web-viewer-serve-example](https://github.com/rerun-io/web-viewer-serve-example) for a full example of how to log data from our Python SDK to an embedded Rerun Viewer. + +### Controlling the canvas + +By default, the web viewer attempts to expand the canvas to occupy all available space. You can customize its dimensions by placing it within a container: + +```html,id=embed-web-viewer-canvas-control-html + +
+ +``` + +```css,id=embed-web-viewer-canvas-control-css +#viewer-container { + position: relative; + height: 640px; + width: 100%; +} +``` + +```js,id=embed-web-viewer-canvas-control-js +const parentElement = document.getElementById("viewer-container"); + +const viewer = new WebViewer(); +await viewer.start(null, parentElement); +``` + +### Viewer API + +The Viewer API supports adding and removing recordings: + +```js,id=embed-web-viewer-api-js-open-close +const rrdUrl = "https://app.rerun.io/version/0.14.1/examples/arkit_scenes.rrd"; + +// Open a recording: +viewer.open(rrdUrl); + +// Later on… +viewer.close(rrdUrl); +``` + +Once finished with the Viewer, you can stop it and release all associated resources: + +```js,id=embed-web-viewer-api-js-stop +viewer.stop(); +``` + +This action also removes the canvas from the page. + +You can `start` and `stop` the same `WebViewer` instance multiple times. diff --git a/docs/content/howto/extend/custom-data.md b/docs/content/howto/extend/custom-data.md index d5bb8d0c9830..bdc0b3df3e6f 100644 --- a/docs/content/howto/extend/custom-data.md +++ b/docs/content/howto/extend/custom-data.md @@ -5,7 +5,18 @@ description: How to use Rerun with custom data --- Rerun comes with many pre-built [Types](../../reference/types.md) that you can use out of the box. As long as your own data can be decomposed into Rerun [components](../../reference/types/components.md) or can be serialized with [Apache Arrow](https://arrow.apache.org/), you can log it directly without needing to recompile Rerun. -All you need to do is implement the `AsComponents` [Python protocol](https://ref.rerun.io/docs/python/0.9.0/common/interfaces/#rerun.AsComponents) or [Rust trait](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html), which means implementing the function, `as_component_batches()`. +For Python we have a helper for this, called [`AnyValues`](https://ref.rerun.io/docs/python/main/common/custom_data/), allowing you to easily attach custom values to any entity instance: + +``` +rr.log( + "my_entity", rr.AnyValues( + confidence=[1.2, 3.4, 5.6], + description="Bla bla bla…", + ), +) +``` + +You can also create your own component by implementing the `AsComponents` [Python protocol](https://ref.rerun.io/docs/python/0.9.0/common/interfaces/#rerun.AsComponents) or [Rust trait](https://docs.rs/rerun/latest/rerun/trait.AsComponents.html), which means implementing the function, `as_component_batches()`. ## Remapping to a Rerun archetype Let's start with a simple example where you have your own point cloud class that is perfectly representable as a Rerun archetype. diff --git a/docs/content/reference/migration.md b/docs/content/reference/migration.md index a32edd8a4283..e5e473e4a2d2 100644 --- a/docs/content/reference/migration.md +++ b/docs/content/reference/migration.md @@ -1,5 +1,5 @@ --- title: Migration Guides order: 900 -redirect: reference/migration/migration-0-13 +redirect: reference/migration/migration-0-15 --- diff --git a/docs/content/reference/migration/migration-0-13.md b/docs/content/reference/migration/migration-0-13.md index 26a6908f8f68..bc1f9ac2b619 100644 --- a/docs/content/reference/migration/migration-0-13.md +++ b/docs/content/reference/migration/migration-0-13.md @@ -1,6 +1,6 @@ --- title: Migrating from 0.12 to 0.13 -order: 11 +order: 130 --- ## `TimeSeriesScalar` deprecated in favor of [Scalar](../types/archetypes/scalar.md) & [SeriesLine](../types/archetypes/series_line.md)/[SeriesPoint](../types/archetypes/series_point.md) diff --git a/docs/content/reference/migration/migration-0-15.md b/docs/content/reference/migration/migration-0-15.md new file mode 100644 index 000000000000..7f08871e6ddd --- /dev/null +++ b/docs/content/reference/migration/migration-0-15.md @@ -0,0 +1,32 @@ +--- +title: Migrating from 0.14 to 0.15 +order: 150 +--- + +## `InstanceKey` removed from our logging APIs +In PR [#5395](https://github.com/rerun-io/rerun/pull/5395) we removed the `InstanceKey` component from all our archetypes. + +What were instance keys? + +In Rerun, each entity can be a batch of _instances_. +For instance, a point cloud is usually logged as one entity where each point is an instance of that entity. +An entity is made up of several components (e.g. position, color, …), and you may log these different components separately. +For example, this lets you update only the colors of a point cloud, keeping the same positions. + +Instance keys were a way to assign identities to these instances so that you could update the components of a specific set of instances. +This was a complicated and little used feature, that caused far more complexity in our code than it was worth. + +For now the `InstanceKey` component as such still remains, but is always assigned the integer index at log time (i.e. `0, 1, 2, 3, …`). +This means that if you first log the positions `A, B, C` and then later log the colors `red, green, blue` to the same entity, they will always be matched as `(A, red), (B, green), (C, blue)`. +We still support _splatting_, where you log one single color for the whole point cloud. + +If you were relying on `InstanceKey` solely to identify your instances when inspecting them in the viewer, then you can replace it with a custom value using [custom data](../../howto/extend/custom-data.md): + +```py +rr.log( + "my/points", + rr.AnyValues(point_id=[17, 42, 103]), +) +``` + +In the future we plan on introducing a better way to identify and track instances over time. diff --git a/docs/content/reference/migration/migration-0-9.md b/docs/content/reference/migration/migration-0-9.md index f36080950ca8..3a65d3bcbde2 100644 --- a/docs/content/reference/migration/migration-0-9.md +++ b/docs/content/reference/migration/migration-0-9.md @@ -1,6 +1,6 @@ --- title: Migrating from 0.8 to 0.9 -order: 12 +order: 90 --- Rerun-0.9 introduces a new set of type-oriented logging APIs built on top of an updated, more concrete, diff --git a/docs/content/reference/npm.md b/docs/content/reference/npm.md new file mode 100644 index 000000000000..19f2ceddb385 --- /dev/null +++ b/docs/content/reference/npm.md @@ -0,0 +1,5 @@ +--- +title: 💻 Web Viewer API +order: 1400 +redirect: https://npmjs.com/package/@rerun-io/web-viewer +--- diff --git a/docs/content/reference/roadmap.md b/docs/content/reference/roadmap.md index da56878ad4bd..24547d74dcb5 100644 --- a/docs/content/reference/roadmap.md +++ b/docs/content/reference/roadmap.md @@ -16,20 +16,22 @@ This page is meant to give an high level overview of ongoing and planned work. ## Roadmap of major feature areas -### Early January 2024: Release 0.12 -- Parallelized rendering and processing for all views -- Plugin system for loading any file into Rerun - -### Near term: Now - Q1 2024 -- End to end performance for high frequency time series logging -- Layout and configuration from code (blueprint) -- Datasets that are bigger than RAM for the native viewer -- CLI for manipulating and exporting data from rrd files - -### Medium term (Q2-3 2024) -- Broader coverage of robotics data types +### Early April 2024: Release 0.15 +- Layout and viewport content from code (blueprint part 1) +- Data-loader plugins callable from the SDK +- Linux ARM64 support in pre-built artifacts + +### Near term: Now - end of Q2 2024 +- Property overrides from code (blueprint part 2) + - Includes setting visible time range from code +- Broader coverage of robotics and spatial computing data types - Extension mechanisms for dynamically reading from external storage - For example files like: VRS, MCAP, or mp4 + - Also brings support for datasets that are bigger than RAM in the native viewer + +### Medium term (Q3-4 2024) +- Make Rerun easier to use when training and evaluating ML models +- Deeper support for modalities like text and audio - Callbacks and the ability to build interactive applications with Rerun - For example: UI for tweaking configs, custom data annotation tools, etc diff --git a/docs/content/reference/types/components/instance_key.md b/docs/content/reference/types/components/instance_key.md index aa626ad7f7ff..099005b47318 100644 --- a/docs/content/reference/types/components/instance_key.md +++ b/docs/content/reference/types/components/instance_key.md @@ -4,6 +4,13 @@ title: "InstanceKey" A unique numeric identifier for each individual instance within a batch. +Instance keys are automatically assigned by the `rerun` library and should not be set manually. + +The instance key is just the index of the instance within the batch, +i.e. the first point in a point cloud has `InstanceKey = 0`, the second `InstanceKey = 1`, and so on. + +We plan to remove the `InstanceKey` component in the near future. + ## Fields * value: `u64` diff --git a/docs/content/reference/types/components/marker_shape.md b/docs/content/reference/types/components/marker_shape.md index 268cc303ed01..d902de3d51a3 100644 --- a/docs/content/reference/types/components/marker_shape.md +++ b/docs/content/reference/types/components/marker_shape.md @@ -18,9 +18,9 @@ Shape of a marker. * Asterisk ## Links - * 🌊 [C++ API docs for `MarkerShape`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1MarkerShape.html?speculative-link) - * 🐍 [Python API docs for `MarkerShape`](https://ref.rerun.io/docs/python/stable/common/components?speculative-link#rerun.components.MarkerShape) - * 🦀 [Rust API docs for `MarkerShape`](https://docs.rs/rerun/latest/rerun/components/enum.MarkerShape.html?speculative-link) + * 🌊 [C++ API docs for `MarkerShape`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1components.html) + * 🐍 [Python API docs for `MarkerShape`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.MarkerShape) + * 🦀 [Rust API docs for `MarkerShape`](https://docs.rs/rerun/latest/rerun/components/enum.MarkerShape.html) ## Used by diff --git a/docs/content/reference/types/datatypes/bool.md b/docs/content/reference/types/datatypes/bool.md index 3326327cc2ae..7d26b9286f60 100644 --- a/docs/content/reference/types/datatypes/bool.md +++ b/docs/content/reference/types/datatypes/bool.md @@ -9,8 +9,8 @@ A single boolean. * value: `bool` ## Links - * 🌊 [C++ API docs for `Bool`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Bool.html?speculative-link) - * 🐍 [Python API docs for `Bool`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.Bool) - * 🦀 [Rust API docs for `Bool`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Bool.html?speculative-link) + * 🌊 [C++ API docs for `Bool`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Bool.html) + * 🐍 [Python API docs for `Bool`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Bool) + * 🦀 [Rust API docs for `Bool`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Bool.html) diff --git a/docs/content/reference/types/datatypes/time_int.md b/docs/content/reference/types/datatypes/time_int.md index de6030538958..83a601840e60 100644 --- a/docs/content/reference/types/datatypes/time_int.md +++ b/docs/content/reference/types/datatypes/time_int.md @@ -9,8 +9,8 @@ A 64-bit number describing either nanoseconds OR sequence numbers. * value: `i64` ## Links - * 🌊 [C++ API docs for `TimeInt`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TimeInt.html?speculative-link) - * 🐍 [Python API docs for `TimeInt`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.TimeInt) - * 🦀 [Rust API docs for `TimeInt`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TimeInt.html?speculative-link) + * 🌊 [C++ API docs for `TimeInt`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1TimeInt.html) + * 🐍 [Python API docs for `TimeInt`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.TimeInt) + * 🦀 [Rust API docs for `TimeInt`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TimeInt.html) diff --git a/docs/content/reference/types/datatypes/uint64.md b/docs/content/reference/types/datatypes/uint64.md index 4984dca79ebc..66ad2a852852 100644 --- a/docs/content/reference/types/datatypes/uint64.md +++ b/docs/content/reference/types/datatypes/uint64.md @@ -9,8 +9,8 @@ A 64bit unsigned integer. * value: `u64` ## Links - * 🌊 [C++ API docs for `UInt64`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1UInt64.html?speculative-link) - * 🐍 [Python API docs for `UInt64`](https://ref.rerun.io/docs/python/stable/common/datatypes?speculative-link#rerun.datatypes.UInt64) - * 🦀 [Rust API docs for `UInt64`](https://docs.rs/rerun/latest/rerun/datatypes/struct.UInt64.html?speculative-link) + * 🌊 [C++ API docs for `UInt64`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1UInt64.html) + * 🐍 [Python API docs for `UInt64`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.UInt64) + * 🦀 [Rust API docs for `UInt64`](https://docs.rs/rerun/latest/rerun/datatypes/struct.UInt64.html) diff --git a/docs/content/reference/viewer/blueprint.md b/docs/content/reference/viewer/blueprint.md index 234a1a7bcdee..e4b1c40593bd 100644 --- a/docs/content/reference/viewer/blueprint.md +++ b/docs/content/reference/viewer/blueprint.md @@ -12,7 +12,8 @@ Everything visible in the [Viewport](viewport.md) has a representation here, making it an easy way to select a Space View and the [Entities](../../concepts/entity-component.md) it shows. - screenshot of the blueprint view + + diff --git a/docs/snippets/all/any_values.py b/docs/snippets/all/any_values.py index 5dc11bef1865..36496ee0d8d0 100644 --- a/docs/snippets/all/any_values.py +++ b/docs/snippets/all/any_values.py @@ -6,7 +6,7 @@ rr.log( "any_values", rr.AnyValues( - foo=[1.2, 3.4, 5.6], - bar="hello world", + confidence=[1.2, 3.4, 5.6], + description="Bla bla bla…", ), ) diff --git a/examples/README.md b/examples/README.md index 2be0e8cdc9eb..a668e06f8c47 100644 --- a/examples/README.md +++ b/examples/README.md @@ -28,26 +28,21 @@ examples/ main.rs ``` -The important part is that each example has a `README.md` file. This file contains a brief description of the example, as well as installation/usage instructions. The `README.md` file also contains metadata in the form of frontmatter: -``` ---- -title: Text Logging -python: https://github.com/rerun-io/rerun/tree/latest/examples/python/detect_and_track_objects/main.py -tags: [2D, huggingface, object-detection, object-tracking, opencv] ---- +The important part is that each example has a `README.md` file. The contents of this `README.md` is used to render the examples in [the documentation](https://rerun.io/examples). +Check out [`examples/python/template/README.md`](python/template/README.md) to see its format. -… +You are also encourage to add a _short_ `DESCRIPTION = """…"""` markdown to the top of the `main.py` and then log it with: +```py +rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) ``` -The contents of this `README.md` file and its frontmatter are used to render the examples in [the documentation](https://rerun.io/examples). Individual examples are currently "stitched together" to form one large markdown file for every category of examples (`artificial-data`, `real-data`). - -The `manifest.toml` file describes the structure of the examples contained in this repository. Only the examples which appear in the manifest are included in the [generated documentation](https://rerun.io/examples). The file contains a description of its own format. - ## Adding a new example You can base your example off of `python/template` or `rust/template`. Once it's ready to be displayed in the docs, add it to the [manifest](./manifest.toml). +The `manifest.toml` file describes the structure of the examples contained in this repository. Only the examples which appear in the manifest are included in the [generated documentation](https://rerun.io/examples). The file contains a description of its own format. + If you want to run the example on CI and include it in the in-viewer example page, add a `channel` entry to its README frontmatter. The available channels right now are: - `main` for simple/fast examples built on each PR and the `main` branch diff --git a/examples/cpp/README.md b/examples/cpp/README.md index 904d28f0ef89..8579db52f807 100644 --- a/examples/cpp/README.md +++ b/examples/cpp/README.md @@ -1,6 +1,6 @@ # Rerun C++ examples The simplest example is [`minimal`](minimal/main.cpp). You may want to start there -using the accompanying [`C++ Quick Start`](https://www.rerun.io/docs/getting-started/cpp) guide. +using the accompanying [`C++ Quick Start`](https://www.rerun.io/docs/getting-started/quick-start/cpp) guide. ## Build all examples The CMake target `examples` is a convenient alias for building all CMake examples in one go. diff --git a/examples/cpp/dna/README.md b/examples/cpp/dna/README.md index 0919fea73036..a9cb282cd91c 100644 --- a/examples/cpp/dna/README.md +++ b/examples/cpp/dna/README.md @@ -1,12 +1,12 @@ +Simple example of logging point and line primitives to draw a 3D helix. @@ -16,9 +16,6 @@ channel = "main" -Simple example of logging point and line primitives to draw a 3D helix. - - To build it from a checkout of the repository (requires a Rust toolchain): ```bash cmake . diff --git a/examples/cpp/eigen_opencv/README.md b/examples/cpp/eigen_opencv/README.md index 0498388e78d0..d13a57e48bc1 100644 --- a/examples/cpp/eigen_opencv/README.md +++ b/examples/cpp/eigen_opencv/README.md @@ -6,9 +6,7 @@ thumbnail = "https://static.rerun.io/eigen-and-opencv-c-integration/5d271725bb92 thumbnail_dimensions = [480, 480] --> -This is a minimal CMake project that shows how to use Rerun in your code in conjunction with [Eigen](https://eigen.tuxfamily.org/) and [OpenCV](https://opencv.org/). -You can find the example at . @@ -17,3 +15,61 @@ You can find the example at + +This is a minimal CMake project that shows how to use Rerun in your code in conjunction with [Eigen](https://eigen.tuxfamily.org/) and [OpenCV](https://opencv.org/). + + +# Used Rerun types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) + +# Background +This C++ example demonstrates the integration of the Rerun with Eigen and OpenCV libraries. +Eigen handles 3D point calculations and camera orientations, while OpenCV assists with image processing tasks like reading and converting images. + +# Logging and visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + + +## 3D points +The positions of 3D points are logged to the "world/points_from_vector" and "world/points_from_matrix" entities using the [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype. +```cpp +rec.log("world/points_from_vector", rerun::Points3D(points3d_vector)); +``` + +```cpp +rec.log("world/points_from_matrix", rerun::Points3D(points3d_matrix)); +``` + +## Pinhole camera +A pinhole camera is logged to "world/camera" using the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) archetype. +Additionally, the 3D transformation of the camera, including its position and orientation, is logged using the [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetype. +```cpp +rec.log( + "world/camera", + rerun::Pinhole::from_focal_length_and_resolution({500.0, 500.0}, {640.0, 480.0}) +); +``` + +```cpp +rec.log( + "world/camera", + rerun::Transform3D( + rerun::Vec3D(camera_position.data()), + rerun::Mat3x3(camera_orientation.data()) + ) +); +``` + +## Images +Images are logged using the [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) archetype. Two methods are demonstrated: logging images with a tensor buffer and logging images by passing a pointer to the image data. +```cpp +// Log image to rerun using the tensor buffer adapter defined in `collection_adapters.hpp`. +rec.log("image0", rerun::Image(tensor_shape(img), rerun::TensorBuffer::u8(img))); + +// Or by passing a pointer to the image data. +rec.log("image1", rerun::Image(tensor_shape(img), reinterpret_cast(img.data))); +``` + +# Run the code +You can find the build instructions here: [C++ Example with OpenCV and Eigen](https://github.com/rerun-io/cpp-example-opencv-eigen/blob/main/README.md) diff --git a/examples/cpp/incremental_logging/README.md b/examples/cpp/incremental_logging/README.md index 90c8dce2bdfa..39db773b8f6b 100644 --- a/examples/cpp/incremental_logging/README.md +++ b/examples/cpp/incremental_logging/README.md @@ -1,11 +1,11 @@ +Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. @@ -15,8 +15,8 @@ thumbnail_dimensions = [480, 301] -Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. +## Run the code To build it from a checkout of the repository (requires a Rust toolchain): ```bash diff --git a/examples/cpp/kiss-icp/README.md b/examples/cpp/kiss-icp/README.md index 9096b859cb5f..cbeb1326bd00 100644 --- a/examples/cpp/kiss-icp/README.md +++ b/examples/cpp/kiss-icp/README.md @@ -2,11 +2,12 @@ title = "KISS-ICP" tags = ["3D", "Point cloud"] source = "https://github.com/rerun-io/kiss-icp" -description = "Visualizes the KISS-ICP LiDAR odometry pipeline on the NCLT dataset." thumbnail = "https://static.rerun.io/kiss-icp-screenshot/881ec7c7c0a0e50ec5d78d82875efaf3bb3c6e01/480w.png" thumbnail_dimensions = [480, 288] --> +Visualizes the KISS-ICP LiDAR odometry pipeline on the NCLT dataset. + Estimating the odometry is a common problem in robotics and in the [2023, "KISS-ICP: In Defense of Point-to-Point ICP -- Simple, Accurate, and Robust Registration If Done the Right Way" Ignacio Vizzo et al.](https://arxiv.org/abs/2209.15397) they show how one can use an ICP (iterative closest point) algorithm to robustly and accurately estimate poses from LiDAR data. We will demonstrate the KISS-ICP pipeline on the [NCLT dataset](http://robots.engin.umich.edu/nclt/) along with some brief explanations, for a more detailed explanation you should look at the [original paper](https://arxiv.org/abs/2209.15397). diff --git a/examples/cpp/log_file/README.md b/examples/cpp/log_file/README.md index 6c0999dae03d..c3cf96e54250 100644 --- a/examples/cpp/log_file/README.md +++ b/examples/cpp/log_file/README.md @@ -2,7 +2,7 @@ title = "Log file example" --> -Demonstrates how to log any file from the SDK using the [`DataLoader`](https://www.rerun.io/docs/howto/open-any-file) machinery. +Demonstrates how to log any file from the SDK using the [`DataLoader`](https://www.rerun.io/docs/reference/data-loaders/overview) machinery. To build it from a checkout of the repository (requires a Rust toolchain): ```bash diff --git a/examples/cpp/minimal/README.md b/examples/cpp/minimal/README.md index fc23daa441c1..cc7705064590 100644 --- a/examples/cpp/minimal/README.md +++ b/examples/cpp/minimal/README.md @@ -14,7 +14,7 @@ thumbnail_dimensions = [480, 480] The simplest example of how to use Rerun, showing how to log a point cloud. -This is part of the [Quick Start guide](https://www.rerun.io/docs/getting-started/cpp). +This is part of the [Quick Start guide](https://www.rerun.io/docs/getting-started/quick-start/cpp). To build it from a checkout of the repository (requires a Rust toolchain): ```bash diff --git a/examples/cpp/ros_bridge/README.md b/examples/cpp/ros_bridge/README.md index 5ed6f6115946..82c4221e1b16 100644 --- a/examples/cpp/ros_bridge/README.md +++ b/examples/cpp/ros_bridge/README.md @@ -1,5 +1,5 @@ - -This is an example that shows how to use [Rerun](https://github.com/rerun-io/rerun)'s C++ API to log and view [VRS](https://github.com/facebookresearch/vrs) files. - -> VRS is a file format optimized to record & playback streams of sensor data, such as images, audio samples, and any other discrete sensors (IMU, temperature, etc), stored in per-device streams of time-stamped records. - -You can find the example at . - + +This is an example that shows how to use Rerun's C++ API to log and view [VRS](https://github.com/facebookresearch/vrs) files. + + +# Used Rerun types + +[`Arrows3D`](https://www.rerun.io/docs/reference/types/archetypes/arrows3d), [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) + +# Background +This C++ example demonstrates how to visualize VRS files with Rerun. +VRS is a file format optimized to record & playback streams of sensor data, such as images, audio samples, and any other discrete sensors (IMU, temperature, etc), stored in per-device streams of time-stamped records. + +# Logging and visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## 3D arrows +```cpp +void IMUPlayer::log_accelerometer(const std::array& accelMSec2) { + _rec->log(_entity_path + "/accelerometer", rerun::Arrows3D::from_vectors({accelMSec2})); + // … existing code for scalars … +} +``` + +## Scalars +```cpp +void IMUPlayer::log_accelerometer(const std::array& accelMSec2) { + // … existing code for Arrows3D … + _rec->log(_entity_path + "/accelerometer/x", rerun::Scalar(accelMSec2[0])); + _rec->log(_entity_path + "/accelerometer/y", rerun::Scalar(accelMSec2[1])); + _rec->log(_entity_path + "/accelerometer/z", rerun::Scalar(accelMSec2[2])); +} +``` + +```cpp +void IMUPlayer::log_gyroscope(const std::array& gyroRadSec) { + _rec->log(_entity_path + "/gyroscope/x", rerun::Scalar(gyroRadSec[0])); + _rec->log(_entity_path + "/gyroscope/y", rerun::Scalar(gyroRadSec[1])); + _rec->log(_entity_path + "/gyroscope/z", rerun::Scalar(gyroRadSec[2])); +} +``` + +```cpp +void IMUPlayer::log_magnetometer(const std::array& magTesla) { + _rec->log(_entity_path + "/magnetometer/x", rerun::Scalar(magTesla[0])); + _rec->log(_entity_path + "/magnetometer/y", rerun::Scalar(magTesla[1])); + _rec->log(_entity_path + "/magnetometer/z", rerun::Scalar(magTesla[2])); +} +``` + +## Images +```cpp +_rec->log( + _entity_path, + rerun::Image({ + frame->getHeight(), + frame->getWidth(), + frame->getSpec().getChannelCountPerPixel()}, + frame->getBuffer() + ) +); +``` + +## Text document +```cpp +_rec->log_timeless(_entity_path + "/configuration", rerun::TextDocument(layout_str)); +``` + +# Run the code +You can find the build instructions here: [C++ Example: VRS Viewer](https://github.com/rerun-io/cpp-example-vrs) diff --git a/examples/manifest.toml b/examples/manifest.toml index 71873f34f63a..6f19820daba1 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -105,6 +105,7 @@ examples = [ "ros_bridge", "urdf_loader", "vrs", + "revy", "tfrecord_loader", "eigen_opencv", "dicom_mri", diff --git a/examples/python/arflow/README.md b/examples/python/arflow/README.md index c9a0cc0935af..a9be17a4c53f 100644 --- a/examples/python/arflow/README.md +++ b/examples/python/arflow/README.md @@ -6,6 +6,10 @@ thumbnail = "https://static.rerun.io/arflow/a6b509af10a42b3c7ad3909d44e972a3cb1a thumbnail_dimensions = [480, 480] --> +This is an external project that uses Rerun as a core component. + +## External project presentation + [Paper](https://doi.org/10.1145/3638550.3643617) | [BibTeX](#bibtex) | [Project Page](https://cake.wpi.edu/ARFlow/) | [Video](https://youtu.be/mml8YrCgfTk) diff --git a/examples/python/arkit_scenes/README.md b/examples/python/arkit_scenes/README.md index f640d1a2d68d..f205e3f193ba 100644 --- a/examples/python/arkit_scenes/README.md +++ b/examples/python/arkit_scenes/README.md @@ -1,12 +1,13 @@ +This example visualizes the [ARKitScenes dataset](https://github.com/apple/ARKitScenes/) using Rerun. +The dataset contains color images, depth images, the reconstructed mesh, and labeled bounding boxes around furniture. @@ -16,9 +17,6 @@ channel = "main" ARKit Scenes screenshot -This example visualizes the [ARKitScenes dataset](https://github.com/apple/ARKitScenes/) using Rerun. The dataset -contains color images, depth images, the reconstructed mesh, and labeled bounding boxes around furniture. - ## Used Rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py index 39abed19a591..27c13ca9a7f9 100755 --- a/examples/python/arkit_scenes/main.py +++ b/examples/python/arkit_scenes/main.py @@ -16,6 +16,15 @@ from scipy.spatial.transform import Rotation as R from tqdm import tqdm +DESCRIPTION = """ +# ARKitScenes +This example visualizes the [ARKitScenes dataset](https://github.com/apple/ARKitScenes/) using Rerun. The dataset +contains color images, depth images, the reconstructed mesh, and labeled bounding boxes around furniture. + +The full source code for this example is available +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/arkit_scenes). +""".strip() + Color = Tuple[float, float, float, float] # hack for now since dataset does not provide orientation information, only known after initial visual inspection @@ -30,58 +39,6 @@ assert len(ORIENTATION) == len(AVAILABLE_RECORDINGS) assert set(ORIENTATION.keys()) == set(AVAILABLE_RECORDINGS) -DESCRIPTION = """ -# ARKit Scenes -This example visualizes the [ARKitScenes dataset](https://github.com/apple/ARKitScenes/) using Rerun. The dataset -contains color images, depth images, the reconstructed mesh, and labeled bounding boxes around furniture. - -## How it was made -The full source code for this example is available -[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/arkit_scenes/main.py). - -### Moving RGB-D camera -To log a moving RGB-D camera we need to log four objects: the pinhole camera (intrinsics), the camera pose -(extrinsics), the color image and the depth image. - -The [rr.Pinhole archetype](https://www.rerun.io/docs/reference/types/archetypes/pinhole) is logged to -[world/camera_lowres](recording://world/camera_lowres) to define the intrinsics of the camera. This -determines how to go from the 3D camera frame to the 2D image plane. The extrinsics are logged as an -[rr.Transform3D archetype](https://www.rerun.io/docs/reference/types/archetypes/transform3d) to the -[same entity world/camera_lowres](recording://world/camera_lowres). Note that we could also log the extrinsics to -`world/camera` and the intrinsics to `world/camera/image` instead. Here, we log both on the same entity path to keep -the paths shorter. - -The RGB image is logged as an -[rr.Image archetype](https://www.rerun.io/docs/reference/types/archetypes/image) to the -[world/camera_lowres/rgb entity](recording://world/camera_lowres/rgb) as a child of the intrinsics + extrinsics -entity described in the previous paragraph. Similarly the depth image is logged as an -[rr.DepthImage archetype](https://www.rerun.io/docs/reference/types/archetypes/depth_image) to -[world/camera_lowres/depth](recording://world/camera_lowres/depth). - -### Ground-truth mesh -The mesh is logged as an [rr.Mesh3D archetype](https://www.rerun.io/docs/reference/types/archetypes/mesh3d). -In this case the mesh is composed of mesh vertices, indices (i.e., which vertices belong to the same face), and vertex -colors. Given a `trimesh.Trimesh` the following call is used to log it to Rerun -```python -rr.log( - "world/mesh", - rr.Mesh3D( - vertex_positions=mesh.vertices, - vertex_colors=mesh.visual.vertex_colors, - indices=mesh.faces, - ), - static=True, -) -``` -Here, the mesh is logged to the [world/mesh entity](recording://world/mesh) and is marked as static, since it does not -change in the context of this visualization. - -### 3D bounding boxes -The bounding boxes around the furniture is visualized by logging the -[rr.Boxes3D archetype](https://www.rerun.io/docs/reference/types/archetypes/boxes3d). In this example, each -bounding box is logged as a separate entity to the common [world/annotations](recording://world/annotations) parent. -""".strip() - LOWRES_POSED_ENTITY_PATH = "world/camera_lowres" HIGHRES_ENTITY_PATH = "world/camera_highres" @@ -349,6 +306,7 @@ def main() -> None: name="2D", ), rrb.TextDocumentView(name="Readme"), + row_shares=[2, 1], ), ) diff --git a/examples/python/blueprint_stocks/README.md b/examples/python/blueprint_stocks/README.md index e4f296fb2a2e..094026f4572d 100644 --- a/examples/python/blueprint_stocks/README.md +++ b/examples/python/blueprint_stocks/README.md @@ -1,11 +1,13 @@ +This example fetches the last 5 days of stock data for a few different stocks. +We show how Rerun blueprints can then be used to present many different views of the same data. + @@ -14,8 +16,6 @@ thumbnail_dimensions = [480, 270] -This example fetches the last 5 days of stock data for a few different stocks. -We show how Rerun blueprints can then be used to present many different views of the same data. ```bash pip install -r examples/python/blueprint_stocks/requirements.txt diff --git a/examples/python/clock/README.md b/examples/python/clock/README.md index d3a4b5c189d2..de59a6e27af6 100644 --- a/examples/python/clock/README.md +++ b/examples/python/clock/README.md @@ -1,5 +1,6 @@ @@ -15,6 +16,62 @@ thumbnail_dimensions = [480, 480] An example visualizing an analog clock with hour, minute and seconds hands using Rerun Arrow3D primitives. +# Used Rerun types + +[`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Arrows3D`](https://www.rerun.io/docs/reference/types/archetypes/arrows3d) + +# Logging and visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +The clock's frame is logged as a 3D box using [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d) archetype. + ```python +rr.log( + "world/frame", + rr.Boxes3D(half_sizes=[LENGTH_S, LENGTH_S, 1.0], centers=[0.0, 0.0, 0.0]), + timeless=True, +) + ``` + +Then, the positions and colors of points and arrows representing the hands of a clock for seconds, minutes, and hours are logged in each simulation time. +It first sets the simulation time using [`timelines`](https://www.rerun.io/docs/concepts/timelines), calculates the data for each hand, and logs it using [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) and [`Arrows3D`](https://www.rerun.io/docs/reference/types/archetypes/arrows3d) archetypes. +This enables the visualization of the clock's movement over time. + + ```python +for step in range(steps): + rr.set_time_seconds("sim_time", t_secs) + + # … calculating seconds … + rr.log("world/seconds_pt", rr.Points3D(positions=point_s, colors=color_s)) + rr.log("world/seconds_hand", rr.Arrows3D(vectors=point_s, colors=color_s, radii=WIDTH_S)) + + # … calculating minutes … + rr.log("world/minutes_pt", rr.Points3D(positions=point_m, colors=color_m)) + rr.log("world/minutes_hand", rr.Arrows3D(vectors=point_m, colors=color_m, radii=WIDTH_M)) + + # … calculating hours … + rr.log("world/hours_pt", rr.Points3D(positions=point_h, colors=color_h)) + rr.log("world/hours_hand", rr.Arrows3D(vectors=point_h, colors=color_h, radii=WIDTH_H)) + ``` + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/clock/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/clock/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: ```bash -python examples/python/clock/main.py +python examples/python/clock/main.py --help ``` diff --git a/examples/python/controlnet/README.md b/examples/python/controlnet/README.md index 29710a24ab0c..c4e5d9d3c38c 100644 --- a/examples/python/controlnet/README.md +++ b/examples/python/controlnet/README.md @@ -1,11 +1,12 @@ +Use [Hugging Face's ControlNet](https://huggingface.co/docs/diffusers/using-diffusers/controlnet#controlnet) to generate an image from text, conditioned on detected edges from another image. + @@ -14,9 +15,6 @@ thumbnail_dimensions = [480, 480] -Use [Hugging Face's ControlNet](https://huggingface.co/docs/diffusers/using-diffusers/controlnet#controlnet) to generate an image from text, conditioned on detected edges from another image. - - ## Used Rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) @@ -27,10 +25,10 @@ Use [Hugging Face's ControlNet](https://huggingface.co/docs/diffusers/using-diff https://vimeo.com/870289439?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=1440:1080 -# Logging and visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the following Rerun code. -## Images +### Images ```python rr.log("input/raw", rr.Image(image), timeless=True) rr.log("input/canny", rr.Image(canny_image), timeless=True) @@ -41,14 +39,14 @@ Timeless entities belong to all timelines (existing ones, and ones not yet creat This designation ensures their constant availability across all timelines in Rerun, aiding in consistent comparison and documentation. -## Prompts +### Prompts ```python rr.log("positive_prompt", rr.TextDocument(prompt), timeless=True) rr.log("negative_prompt", rr.TextDocument(negative_prompt), timeless=True) ``` The positive and negative prompt used for generation is logged to Rerun. -## Custom diffusion step callback +### Custom diffusion step callback We use a custom callback function for ControlNet that logs the output and the latent values at each timestep, which makes it possible for us to view all timesteps of the generation in Rerun. ```python def controlnet_callback( @@ -60,13 +58,13 @@ def controlnet_callback( rr.log("latent", rr.Tensor(latents.squeeze(), dim_names=["channel", "height", "width"])) ``` -## Output image +### Output image ```python rr.log("output", rr.Image(images)) ``` Finally we log the output image generated by ControlNet. -# Run the code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash diff --git a/examples/python/depth_guided_stable_diffusion/README.md b/examples/python/depth_guided_stable_diffusion/README.md index b3761753f2ca..ac014c2628b1 100644 --- a/examples/python/depth_guided_stable_diffusion/README.md +++ b/examples/python/depth_guided_stable_diffusion/README.md @@ -1,11 +1,12 @@ +Leverage [Depth Guided Stable Diffusion](https://github.com/Stability-AI/stablediffusion?tab=readme-ov-file#depth-conditional-stable-diffusion) to generate images with enhanced depth perception. This method integrates depth maps to guide the Stable Diffusion model, creating more visually compelling and contextually accurate images. + @@ -14,25 +15,23 @@ thumbnail_dimensions = [480, 266] Depth-guided stable diffusion example -Leverage [Depth Guided Stable Diffusion](https://github.com/Stability-AI/stablediffusion?tab=readme-ov-file#depth-conditional-stable-diffusion) to generate images with enhanced depth perception. This method integrates depth maps to guide the Stable Diffusion model, creating more visually compelling and contextually accurate images. - ## Used Rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor), [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document),[`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log)[`BarChart`](https://www.rerun.io/docs/reference/types/archetypes/bar_chart) ## Background Depth Guided Stable Diffusion enriches the image generation process by incorporating depth information, providing a unique way to control the spatial composition of generated images. This approach allows for more nuanced and layered creations, making it especially useful for scenes requiring a sense of three-dimensionality. -# Logging and visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the Rerun SDK, demonstrating the integration of depth information in the Stable Diffusion image generation process. Here is the code for generating the visualization in Rerun. -## Prompt +### Prompt Visualizing the prompt and negative prompt ```python rr.log("prompt/text", rr.TextLog(prompt)) rr.log("prompt/text_negative", rr.TextLog(negative_prompt)) ``` -## Text +### Text Visualizing the text input ids, the text attention mask and the unconditional input ids ```python rr.log("prompt/text_input/ids", rr.BarChart(text_input_ids)) @@ -40,14 +39,14 @@ rr.log("prompt/text_input/attention_mask", rr.BarChart(text_inputs.attention_mas rr.log("prompt/uncond_input/ids", rr.Tensor(uncond_input.input_ids)) ``` -## Text embeddings +### Text embeddings Visualizing the text embeddings. The text embeddings are generated in response to the specific prompts used while the unconditional text embeddings represent a neutral or baseline state without specific input conditions. ```python rr.log("prompt/text_embeddings", rr.Tensor(text_embeddings)) rr.log("prompt/uncond_embeddings", rr.Tensor(uncond_embeddings)) ``` -## Depth map +### Depth map Visualizing the pixel values of the depth estimation, estimated depth image, interpolated depth image and normalized depth image ```python rr.log("depth/input_preprocessed", rr.Tensor(pixel_values)) @@ -56,13 +55,13 @@ rr.log("depth/interpolated", rr.DepthImage(depth_map)) rr.log("depth/normalized", rr.DepthImage(depth_map)) ``` -## Latents +### Latents Log the latents, the representation of the images in the format used by the diffusion model. ```python rr.log("diffusion/latents", rr.Tensor(latents, dim_names=["b", "c", "h", "w"])) ``` -## Denoising loop +### Denoising loop For each step in the denoising loop we set a time sequence with step and timestep and log the latent model input, noise predictions, latents and image. This make is possible for us to see all denoising steps in the Rerun viewer. ```python rr.set_time_sequence("step", i) @@ -73,14 +72,14 @@ rr.log("diffusion/latents", rr.Tensor(latents, dim_names=["b", "c", "h", "w"])) rr.log("image/diffused", rr.Image(image)) ``` -## Diffused image +### Diffused image Finally we log the diffused image generated by the model. ```python rr.log("image/diffused", rr.Image(image_8)) ``` -# Run the code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash diff --git a/examples/python/detect_and_track_objects/README.md b/examples/python/detect_and_track_objects/README.md index 664dc1991bb7..26db52356a92 100644 --- a/examples/python/detect_and_track_objects/README.md +++ b/examples/python/detect_and_track_objects/README.md @@ -1,13 +1,12 @@ - +Visualize object detection and segmentation using the [Huggingface's Transformers](https://huggingface.co/docs/transformers/index) and [CSRT](https://arxiv.org/pdf/1611.08461.pdf) from OpenCV. @@ -17,28 +16,26 @@ channel = "release" -Visualize object detection and segmentation using the [Huggingface's Transformers](https://huggingface.co/docs/transformers/index) and [CSRT](https://arxiv.org/pdf/1611.08461.pdf) from OpenCV. - -# Used Rerun Types +## Used Rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d), [`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log) -# Background +## Background In this example, CSRT (Channel and Spatial Reliability Tracker), a tracking API introduced in OpenCV, is employed for object detection and tracking across frames. Additionally, the example showcases basic object detection and segmentation on a video using the Huggingface transformers library. -# Logging and Visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the following Rerun code. -## Timelines +### Timelines For each processed video frame, all data sent to Rerun is associated with the [`timelines`](https://www.rerun.io/docs/concepts/timelines) `frame_idx`. ```python rr.set_time_sequence("frame", frame_idx) ``` -## Video +### Video The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) to the `image` entity. ```python @@ -58,7 +55,7 @@ rr.log( ) ``` -## Segmentations +### Segmentations The segmentation results is logged through a combination of two archetypes. The segmentation image itself is logged as an [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) and @@ -86,10 +83,10 @@ rr.log( ) ``` -## Detections +### Detections The detections and tracked bounding boxes are visualized by logging the [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d) to Rerun. -### Detections +#### Detections ```python rr.log( "segmentation/detections/things", @@ -111,7 +108,7 @@ rr.log( ), ) ``` -### Tracked bounding boxes +#### Tracked bounding boxes ```python rr.log( "segmentation/detections/background", @@ -131,7 +128,7 @@ same color. Note that it is also possible to log multiple annotation contexts should different colors and / or labels be desired. The annotation context is resolved by seeking up the entity hierarchy. -## Text Log +### Text log Rerun integrates with the [Python logging module](https://docs.python.org/3/library/logging.html). Through the [`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log#textlogintegration) text at different importance level can be logged. After an initial setup that is described on the [`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log#textlogintegration), statements @@ -151,7 +148,7 @@ def main() -> None: ``` In the viewer you can adjust the filter level and look at the messages time-synchronized with respect to other logged data. -# Run the Code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/detect_and_track_objects/main.py b/examples/python/detect_and_track_objects/main.py index bca83a637035..5930cc266455 100755 --- a/examples/python/detect_and_track_objects/main.py +++ b/examples/python/detect_and_track_objects/main.py @@ -17,6 +17,18 @@ import rerun as rr # pip install rerun-sdk from PIL import Image +DESCRIPTION = """ +# Detect and track objects + +This is a more elaborate example applying simple object detection and segmentation on a video using the Huggingface +`transformers` library. Tracking across frames is performed using [CSRT](https://arxiv.org/abs/1611.08461) from +OpenCV. The results are visualized using Rerun. + +The full source code for this example is available +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/detect_and_track_objects). +""".strip() + + EXAMPLE_DIR: Final = Path(os.path.dirname(__file__)) DATASET_DIR: Final = EXAMPLE_DIR / "dataset" / "tracking_sequences" DATASET_URL_BASE: Final = "https://storage.googleapis.com/rerun-example-datasets/tracking_sequences" @@ -36,55 +48,6 @@ DetrForSegmentation, ) -DESCRIPTION = """ -# Detect and Track Objects - -This is a more elaborate example applying simple object detection and segmentation on a video using the Huggingface -`transformers` library. Tracking across frames is performed using [CSRT](https://arxiv.org/abs/1611.08461) from -OpenCV. The results are visualized using Rerun. - -## How it was made -The full source code for this example is available -[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/detect_and_track_objects/main.py). - -### Input Video -The input video is logged as a sequence of -[rr.Image objects](https://www.rerun.io/docs/reference/types/archetypes/image) to the -[image entity](recording://image). Since the detection and segmentation model operates on smaller images the -resized images are logged to the separate [segmentation/rgb_scaled entity](recording://segmentation/rgb_scaled). This allows us to -subsequently visualize the segmentation mask on top of the video. - -### Segmentations -The [segmentation result](recording://image_segmentation/segmentation) is logged through a combination of two archetypes. -The segmentation image itself is logged as an -[rr.SegmentationImage archetype](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) and -contains the id for each pixel. It is logged to the [segmentation entity](recording://segmentation). - -The color and label for each class is determined by the -[rr.AnnotationContext archetype](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is -logged to the root entity using `rr.log("/", …, static=True` as it should apply to the whole sequence and all -entities that have a class id. - -### Detections -The detections and tracked bounding boxes are visualized by logging the -[rr.Boxes2D archetype](https://www.rerun.io/docs/reference/types/archetypes/boxes2d) to Rerun. - -The color and label of the bounding boxes is determined by their class id, relying on the same -[rr.AnnotationContext archetype](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) as the -segmentation images. This ensures that a bounding box and a segmentation image with the same class id will also have the -same color. - -Note that it is also possible to log multiple annotation contexts should different colors and / or labels be desired. -The annotation context is resolved by seeking up the entity hierarchy. - -### Text Log -Through the [rr.TextLog archetype] text at different importance level can be logged. Rerun integrates with the -[Python logging module](https://docs.python.org/3/library/logging.html). After an initial setup that is described on the -[rr.TextLog page](https://www.rerun.io/docs/reference/types/archetypes/text_log#textlogintegration), statements -such as `logging.info("...")`, `logging.debug("...")`, etc. will show up in the Rerun viewer. In the viewer you can -adjust the filter level and look at the messages time-synchronized with respect to other logged data. -""".strip() - @dataclass class Detection: diff --git a/examples/python/dicom_mri/README.md b/examples/python/dicom_mri/README.md index cf7fc26b35ee..4f4c6b3f56ae 100644 --- a/examples/python/dicom_mri/README.md +++ b/examples/python/dicom_mri/README.md @@ -1,12 +1,12 @@ +Visualize a [DICOM](https://en.wikipedia.org/wiki/DICOM) MRI scan. This demonstrates the flexible tensor slicing capabilities of the Rerun viewer. @@ -16,15 +16,13 @@ channel = "main" -Visualize a [DICOM](https://en.wikipedia.org/wiki/DICOM) MRI scan. This demonstrates the flexible tensor slicing capabilities of the Rerun viewer. - -# Used Rerun Types +## Used Rerun types [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) -# Background +## Background Digital Imaging and Communications in Medicine (DICOM) serves as a technical standard for the digital storage and transmission of medical images. In this instance, an MRI scan is visualized using Rerun. -# Logging and Visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with just the following line. ```python @@ -39,7 +37,7 @@ give semantic meaning to each axis. After selecting the tensor view, you can adj settings on the right-hand side. For example, you can adjust the color map, the brightness, which dimensions to show as an image and which to select from, and more. -# Run the Code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/dicom_mri/main.py b/examples/python/dicom_mri/main.py index 0d832c0f27f2..9b36728ee0c1 100755 --- a/examples/python/dicom_mri/main.py +++ b/examples/python/dicom_mri/main.py @@ -23,33 +23,22 @@ import requests import rerun as rr # pip install rerun-sdk -DATASET_DIR: Final = Path(os.path.dirname(__file__)) / "dataset" -DATASET_URL: Final = "https://storage.googleapis.com/rerun-example-datasets/dicom.zip" - DESCRIPTION = """ # Dicom MRI This example visualizes an MRI scan using Rerun. -## How it was made -The full source code for this example is available -[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/dicom_mri/main.py). - The visualization of the data consists of just the following line ```python rr.log("tensor", rr.Tensor(voxels_volume_u16, dim_names=["right", "back", "up"])) ``` -`voxels_volume_u16` is a `numpy.array` of shape `(512, 512, 512)` containing volumetric MRI intensities. We can -visualize such information in Rerun by logging the `numpy.array` as an -[rr.Tensor archetype](https://www.rerun.io/docs/reference/types/archetypes/tensor). Here the tensor is logged to -the [tensor entity](recording://tensor), however any other name for the entity could have been chosen. - -In the Rerun viewer you can inspect the data in detail. The `dim_names` provided in the above call to `rr.log` help to -give semantic meaning to each axis. After selecting the tensor view, you can adjust various settings in the Blueprint -settings on the right-hand side. For example, you can adjust the color map, the brightness, which dimensions to show as -an image and which to select from, and more. +The full source code for this example is available +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/dicom_mri). """ +DATASET_DIR: Final = Path(os.path.dirname(__file__)) / "dataset" +DATASET_URL: Final = "https://storage.googleapis.com/rerun-example-datasets/dicom.zip" + def extract_voxel_data( dicom_files: Iterable[Path], diff --git a/examples/python/differentiable_blocks_world/README.md b/examples/python/differentiable_blocks_world/README.md index bca0aafbbb51..2b6f4b2472af 100644 --- a/examples/python/differentiable_blocks_world/README.md +++ b/examples/python/differentiable_blocks_world/README.md @@ -6,6 +6,10 @@ thumbnail = "https://static.rerun.io/differentiable-blocks/42f3a5481162a0e75f1c5 thumbnail_dimensions = [480, 480] --> +This example is a visual walkthrough of the paper "Differentiable Block Worlds". +All the visualizations were created by editing the original source code to log data with the Rerun SDK. + +## Visual paper walkthrough Finding a textured mesh decomposition from a collection of posed images is a very challenging optimization problem. "Differentiable Block Worlds" by Tom Monnier et al. shows impressive results using differentiable rendering. Here we visualize how this optimization works using the Rerun SDK. diff --git a/examples/python/dna/README.md b/examples/python/dna/README.md index 4d0b0ead556a..6ef9d77836ad 100644 --- a/examples/python/dna/README.md +++ b/examples/python/dna/README.md @@ -1,12 +1,13 @@ +Simple example of logging point and line primitives to draw a 3D helix. + @@ -15,8 +16,6 @@ channel = "main" -Simple example of logging point and line primitives to draw a 3D helix. - ```bash python examples/python/dna/main.py ``` diff --git a/examples/python/dna/main.py b/examples/python/dna/main.py index 1fab3ae3c3bd..158d1efb2f52 100755 --- a/examples/python/dna/main.py +++ b/examples/python/dna/main.py @@ -18,31 +18,8 @@ This is a minimal example that logs synthetic 3D data in the shape of a double helix. The underlying data is generated using numpy and visualized using Rerun. -## How it was made The full source code for this example is available -[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/dna/main.py). - -### Colored 3D points -The colored 3D points were added to the scene by logging the -[rr.Points3D archetype](https://www.rerun.io/docs/reference/types/archetypes/points3d) to the -[helix/structure/left](recording://helix/structure/left) and [helix/structure/right](recording://helix/structure/right) -entities. - -### 3D line strips -The 3D line strips connecting the 3D point pairs are logged as an -[rr.LineStrips3D archetype](https://www.rerun.io/docs/reference/types/archetypes/line_strips3d) to the -[helix/structure/scaffolding entity](recording://helix/structure/scaffolding). - -### Rotation -The whole structure is rotated over time by logging a -[rr.Transform3D archetype](https://www.rerun.io/docs/reference/types/archetypes/transform3d) to the -[helix/structure entity](recording://helix/structure:Transform3D) that changes over time. This transform determines the rotation of -the [structure entity](recording://helix/structure) relative to the [helix](recording://helix) entity. Since all other -entities are children of [helix/structure](recording://helix/structure) they will also rotate based on this transform. - -You can visualize this rotation by selecting the two entities on the left-hand side and activating `Show transform` in -the Blueprint settings on the right-hand side. You will see one static frame (i.e., the frame of -[helix](recording://helix)) and the rotating frame (i.e., the frame of [structure](recording://helix/structure)). +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/dna). """.strip() diff --git a/examples/python/face_tracking/README.md b/examples/python/face_tracking/README.md index 33549e5e3b0f..ead37fd1dd5d 100644 --- a/examples/python/face_tracking/README.md +++ b/examples/python/face_tracking/README.md @@ -1,11 +1,12 @@ +Use the [MediaPipe](https://google.github.io/mediapipe/) Face Detector and Landmarker solutions to detect and track a human face in image, video, and camera stream. + @@ -15,13 +16,10 @@ thumbnail_dimensions = [480, 480] screenshot of the Rerun visualization of the MediaPipe Face Detector and Landmarker - -Use the [MediaPipe](https://google.github.io/mediapipe/) Face Detector and Landmarker solutions to detect and track a human face in image, video, and camera stream. - -# Used Rerun Types +## Used Rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) -# Background +## Background The face and face landmark detection technology aims to give the ability of the devices to interpret face movements and facial expressions as commands or inputs. At the core of this technology, a pre-trained machine-learning model analyses the visual input, locates face and identifies face landmarks and blendshape scores (coefficients representing facial expression). Human-Computer Interaction, Robotics, Gaming, and Augmented Reality are among the fields where this technology shows significant promise for applications. @@ -29,10 +27,10 @@ Human-Computer Interaction, Robotics, Gaming, and Augmented Reality are among th In this example, the [MediaPipe](https://developers.google.com/mediapipe/) Face and Face Landmark Detection solutions were utilized to detect human face, detect face landmarks and identify facial expressions. Rerun was employed to visualize the output of the Mediapipe solution over time to make it easy to analyze the behavior. -# Logging and Visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the following Rerun code. -## Timelines +### Timelines For each processed video frame, all data sent to Rerun is associated with the two [`timelines`](https://www.rerun.io/docs/concepts/timelines) `time` and `frame_idx`. @@ -41,7 +39,7 @@ rr.set_time_seconds("time", bgr_frame.time) rr.set_time_sequence("frame_idx", bgr_frame.idx) ``` -## Video +### Video The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) objects to the 'Video' entity. ```python rr.log( @@ -50,7 +48,7 @@ rr.log( ) ``` -## Face Landmark Points +### Face landmark points Logging the face landmarks involves specifying connections between the points, extracting face landmark points and logging them to the Rerun SDK. The 2D points are visualized over the video/image for a better understanding and visualization of the face. The 3D points allows the creation of a 3D model of the face reconstruction for a more comprehensive representation of the face. @@ -60,7 +58,7 @@ The 2D and 3D points are logged through a combination of two archetypes. First, the keypoints. Defining these connections automatically renders lines between them. Second, the actual keypoint positions are logged in 2D and 3D as [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d) and [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetypes, respectively. -### Label Mapping and Keypoint Connections +#### Label mapping and keypoint connections An annotation context is logged with one class ID assigned per facial feature. The class description includes the connections between corresponding keypoints extracted from the MediaPipe face mesh solution. A class ID array is generated to match the class IDs in the annotation context with keypoint indices (to be utilized as the class_ids argument to rr.log). @@ -119,7 +117,7 @@ rr.log( timeless=True, ) ``` -### Bounding Box +#### Bounding box ```python rr.log( @@ -132,7 +130,7 @@ rr.log( ``` -### 2D Points +#### 2D points ```python rr.log( @@ -148,7 +146,7 @@ rr.log( ) ``` -### 3D Points +#### 3D points ```python rr.log( @@ -161,7 +159,7 @@ rr.log( ) ``` -## Scalar +### Scalar Blendshapes are essentially predefined facial expressions or configurations that can be detected by the face landmark detection model. Each blendshape typically corresponds to a specific facial movement or expression, such as blinking, squinting, smiling, etc. The blendshapes are logged along with their corresponding scores. @@ -171,7 +169,7 @@ for blendshape in blendshapes: rr.log(f"blendshapes/{i}/{blendshape.category_name}", rr.Scalar(blendshape.score)) ``` -# Run the Code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/face_tracking/requirements.txt b/examples/python/face_tracking/requirements.txt index 03268960a288..c018d69ff2e2 100644 --- a/examples/python/face_tracking/requirements.txt +++ b/examples/python/face_tracking/requirements.txt @@ -1,4 +1,7 @@ -mediapipe>=0.10.1 ; python_version <= '3.11' # no 3.12 version yet (https://pypi.org/project/mediapipe/) +# no 3.12 version yet (https://pypi.org/project/mediapipe/) +# 0.10.10 no longer supports the legacy Pose model: https://github.com/rerun-io/rerun/issues/5859 +mediapipe==0.10.9 ; python_version <= '3.11' + numpy opencv-python>4.6 # Avoid opencv-4.6 since it rotates images incorrectly (https://github.com/opencv/opencv/issues/22088) requests diff --git a/examples/python/gesture_detection/README.md b/examples/python/gesture_detection/README.md index 6f0402292a60..c8132d471098 100644 --- a/examples/python/gesture_detection/README.md +++ b/examples/python/gesture_detection/README.md @@ -1,11 +1,12 @@ +Use the [MediaPipe](https://google.github.io/mediapipe/) Hand Landmark and Gesture Detection solutions to +track hands and recognize gestures in images, video, and camera stream. @@ -15,13 +16,10 @@ thumbnail_dimensions = [480, 480] -Use the [MediaPipe](https://google.github.io/mediapipe/) Hand Landmark and Gesture Detection solutions to -track hands and recognize gestures in images, video, and camera stream. - -# Used rerun types +## Used rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`LineStrips2D`](https://www.rerun.io/docs/reference/types/archetypes/line_strips2d), [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) -# Background +## Background The hand tracking and gesture recognition technology aims to give the ability of the devices to interpret hand movements and gestures as commands or inputs. At the core of this technology, a pre-trained machine-learning model analyses the visual input and identifies hand landmarks and hand gestures. The real applications of such technology vary, as hand movements and gestures can be used to control smart devices. @@ -30,10 +28,10 @@ Human-Computer Interaction, Robotics, Gaming, and Augmented Reality are a few of In this example, the [MediaPipe](https://developers.google.com/mediapipe/) Gesture and Hand Landmark Detection solutions were utilized to detect and track hand landmarks and recognize gestures. Rerun was employed to visualize the output of the Mediapipe solution over time to make it easy to analyze the behavior. -# Logging and visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the following Rerun code. -## Timelines +### Timelines For each processed video frame, all data sent to Rerun is associated with the two [`timelines`](https://www.rerun.io/docs/concepts/timelines) `time` and `frame_idx`. @@ -42,7 +40,7 @@ rr.set_time_sequence("frame_nr", frame_idx) rr.set_time_nanos("frame_time", frame_time_nano) ``` -## Video +### Video The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) objects to the `Media/Video` entity. ```python rr.log( @@ -51,7 +49,7 @@ rr.log( ) ``` -## Hand landmark points +### Hand landmark points Logging the hand landmarks involves specifying connections between the points, extracting pose landmark points and logging them to the Rerun SDK. The 2D points are visualized over the video and at a separate entity. Meanwhile, the 3D points allows the creation of a 3D model of the hand for a more comprehensive representation of the hand landmarks. @@ -62,7 +60,7 @@ As for the 3D points, the logging process involves two steps. First, a static [` the keypoints. Defining these connections automatically renders lines between them. Mediapipe provides the `HAND_CONNECTIONS` variable which contains the list of `(from, to)` landmark indices that define the connections. Second, the actual keypoint positions are logged in 3D [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype. -### Label Mapping and Keypoint Connections +#### Label mapping and keypoint connections ```python rr.log( @@ -79,7 +77,7 @@ rr.log( rr.log("Hand3D", rr.ViewCoordinates.LEFT_HAND_Y_DOWN, static=True) ``` -### 2D Points +#### 2D points ```python # Log points to the image and Hand Entity @@ -97,7 +95,7 @@ for log_key in ["Media/Connections", "Hand/Connections"]: ) ``` -### 3D points +#### 3D points ```python rr.log( @@ -111,7 +109,7 @@ rr.log( ) ``` -## Detection +### Detection To showcase gesture recognition, an image of the corresponding gesture emoji is displayed within a `TextDocument` under the `Detection` entity. @@ -123,7 +121,7 @@ rr.log( ) ``` -# Run the Code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/gesture_detection/requirements.txt b/examples/python/gesture_detection/requirements.txt index 23d673c2f837..aecc4bce71e3 100644 --- a/examples/python/gesture_detection/requirements.txt +++ b/examples/python/gesture_detection/requirements.txt @@ -1,4 +1,7 @@ -mediapipe==0.10.9 ; python_version <= '3.11' # no 3.12 version yet (https://pypi.org/project/mediapipe/) # For mac also you may need to run this: export SYSTEM_VERSION_COMPAT=0 +# no 3.12 version yet (https://pypi.org/project/mediapipe/) +# 0.10.10 no longer supports the legacy Pose model: https://github.com/rerun-io/rerun/issues/5859 +mediapipe==0.10.9 ; python_version <= '3.11' + numpy opencv-python>4.9 requests>=2.31,<3 diff --git a/examples/python/human_pose_tracking/README.md b/examples/python/human_pose_tracking/README.md index 96dd9d68aa41..e439d7fb3cda 100644 --- a/examples/python/human_pose_tracking/README.md +++ b/examples/python/human_pose_tracking/README.md @@ -1,12 +1,13 @@ +Use the [MediaPipe Pose Landmark Detection](https://developers.google.com/mediapipe/solutions/vision/pose_landmarker) solution to detect and track a human pose in video. + @@ -15,14 +16,10 @@ channel = "main" -Use the [MediaPipe Pose Landmark Detection](https://developers.google.com/mediapipe/solutions/vision/pose_landmarker) solution to detect and track a human pose in video. - - - -# Used Rerun types +## Used Rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) -# Background +## Background Human pose tracking is a task in computer vision that focuses on identifying key body locations, analyzing posture, and categorizing movements. At the heart of this technology is a pre-trained machine-learning model to assess the visual input and recognize landmarks on the body in both image coordinates and 3D world coordinates. The use cases and applications of this technology include but are not limited to Human-Computer Interaction, Sports Analysis, Gaming, Virtual Reality, Augmented Reality, Health, etc. @@ -31,10 +28,10 @@ In this example, the [MediaPipe Pose Landmark Detection](https://developers.goog Rerun was employed to visualize the output of the Mediapipe solution over time to make it easy to analyze the behavior. -# Logging and visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the following Rerun code. -## Timelines +### Timelines For each processed video frame, all data sent to Rerun is associated with the two [`timelines`](https://www.rerun.io/docs/concepts/timelines) `time` and `frame_idx`. @@ -43,7 +40,7 @@ rr.set_time_seconds("time", bgr_frame.time) rr.set_time_sequence("frame_idx", bgr_frame.idx) ``` -## Video +### Video The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) objects to the 'Video' entity. ```python @@ -53,7 +50,7 @@ rr.log( ) ``` -## Segmentation mask +### Segmentation mask The segmentation result is logged through a combination of two archetypes. The segmentation image itself is logged as an @@ -62,22 +59,22 @@ contains the id for each pixel. The color is determined by the [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is logged with `static=True` as it should apply to the whole sequence. -### Label mapping +#### Label mapping ```python rr.log( - "video/mask", - rr.AnnotationContext( - [ - rr.AnnotationInfo(id=0, label="Background"), - rr.AnnotationInfo(id=1, label="Person", color=(0, 0, 0)), - ] - ), - static=True, - ) + "video/mask", + rr.AnnotationContext( + [ + rr.AnnotationInfo(id=0, label="Background"), + rr.AnnotationInfo(id=1, label="Person", color=(0, 0, 0)), + ] + ), + static=True, +) ``` -### Segmentation image +#### Segmentation image ```python rr.log( @@ -86,7 +83,7 @@ rr.log( ) ``` -## Body pose points +### Body pose points Logging the body pose landmarks involves specifying connections between the points, extracting pose landmark points and logging them to the Rerun SDK. The 2D points are visualized over the image/video for a better understanding and visualization of the body pose. The 3D points allows the creation of a 3D model of the body posture for a more comprehensive representation of the human pose. @@ -99,7 +96,7 @@ Defining these connections automatically renders lines between them. Mediapipe p and 3D as [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d) and [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetypes, respectively. -### Label mapping and keypoint connections +#### Label mapping and keypoint connections ```python rr.log( @@ -115,7 +112,7 @@ rr.log( ) ``` -### 2D points +#### 2D points ```python rr.log( @@ -124,7 +121,7 @@ rr.log( ) ``` -### 3D points +#### 3D points ```python rr.log( @@ -133,7 +130,7 @@ rr.log( ) ``` -# Run the code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py index 7b0824e26776..a7e619824a2e 100755 --- a/examples/python/human_pose_tracking/main.py +++ b/examples/python/human_pose_tracking/main.py @@ -18,47 +18,19 @@ import rerun as rr # pip install rerun-sdk import rerun.blueprint as rrb -EXAMPLE_DIR: Final = Path(os.path.dirname(__file__)) -DATASET_DIR: Final = EXAMPLE_DIR / "dataset" / "pose_movement" -DATASET_URL_BASE: Final = "https://storage.googleapis.com/rerun-example-datasets/pose_movement" - DESCRIPTION = """ -# Human Pose Tracking +# Human pose tracking This example uses Rerun to visualize the output of [MediaPipe](https://developers.google.com/mediapipe)-based tracking of a human pose in 2D and 3D. -## How it was made The full source code for this example is available -[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/human_pose_tracking/main.py). - -### Input Video -The input video is logged as a sequence of -[rr.Image objects](https://www.rerun.io/docs/reference/types/archetypes/image) to the [video entity](recording://video). - -### Segmentation -The [segmentation result](recording://video/mask) is logged through a combination of two archetypes. The segmentation -image itself is logged as an -[rr.SegmentationImage archetype](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) and -contains the id for each pixel. The color is determined by the -[rr.AnnotationContext archetype](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is -logged with `rr.log(…, static=True` as it should apply to the whole sequence. - -### Skeletons -The [2D](recording://video/pose/points) and [3D skeletons](recording://person/pose/points) are also logged through a -similar combination of two entities. - -First, a static -[rr.ClassDescription](https://www.rerun.io/docs/reference/types/datatypes/class_description) is logged (note, that -this is equivalent to logging an -[rr.AnnotationContext archetype](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) as in the -segmentation case). The class description contains the information which maps keypoint ids to labels and how to connect -the keypoints to a skeleton. - -Second, the actual keypoint positions are logged in 2D -nd 3D as [rr.Points2D](https://www.rerun.io/docs/reference/types/archetypes/points2d) and -[rr.Points3D](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetypes, respectively. +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/human_pose_tracking). """.strip() +EXAMPLE_DIR: Final = Path(os.path.dirname(__file__)) +DATASET_DIR: Final = EXAMPLE_DIR / "dataset" / "pose_movement" +DATASET_URL_BASE: Final = "https://storage.googleapis.com/rerun-example-datasets/pose_movement" + def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) -> None: mp_pose = mp.solutions.pose diff --git a/examples/python/human_pose_tracking/requirements.txt b/examples/python/human_pose_tracking/requirements.txt index b5a9a535e2eb..5bec67ecf1ad 100644 --- a/examples/python/human_pose_tracking/requirements.txt +++ b/examples/python/human_pose_tracking/requirements.txt @@ -1,4 +1,7 @@ -mediapipe>=0.10.9 ; python_version <= '3.11' # no 3.12 version yet (https://pypi.org/project/mediapipe/) +# no 3.12 version yet (https://pypi.org/project/mediapipe/) +# 0.10.10 no longer supports the legacy Pose model: https://github.com/rerun-io/rerun/issues/5859 +mediapipe==0.10.9 ; python_version <= '3.11' + numpy opencv-python>4.6 # Avoid opencv-4.6 since it rotates images incorrectly (https://github.com/opencv/opencv/issues/22088) requests>=2.31,<3 diff --git a/examples/python/incremental_logging/README.md b/examples/python/incremental_logging/README.md index c0c5d61f74e1..cb4333b32773 100644 --- a/examples/python/incremental_logging/README.md +++ b/examples/python/incremental_logging/README.md @@ -1,11 +1,11 @@ +Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. @@ -15,9 +15,6 @@ thumbnail_dimensions = [480, 301] -Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. - - To build it from a checkout of the repository (requires a Rust toolchain): ```bash python examples/python/incremental_logging/main.py diff --git a/examples/python/kiss-icp/README.md b/examples/python/kiss-icp/README.md index 9096b859cb5f..a5f345da8bcf 100644 --- a/examples/python/kiss-icp/README.md +++ b/examples/python/kiss-icp/README.md @@ -1,13 +1,14 @@ -Estimating the odometry is a common problem in robotics and in the [2023, "KISS-ICP: In Defense of Point-to-Point ICP -- Simple, Accurate, and Robust Registration If Done the Right Way" Ignacio Vizzo et al.](https://arxiv.org/abs/2209.15397) they show how one can use an ICP (iterative closest point) algorithm to robustly and accurately estimate poses from LiDAR data. We will demonstrate the KISS-ICP pipeline on the [NCLT dataset](http://robots.engin.umich.edu/nclt/) along with some brief explanations, for a more detailed explanation you should look at the [original paper](https://arxiv.org/abs/2209.15397). +Visualizes the KISS-ICP LiDAR odometry pipeline on the [NCLT dataset](http://robots.engin.umich.edu/nclt/). + +Estimating the odometry is a common problem in robotics and in the [2023, "KISS-ICP: In Defense of Point-to-Point ICP -- Simple, Accurate, and Robust Registration If Done the Right Way" Ignacio Vizzo et al.](https://arxiv.org/abs/2209.15397) they show how one can use an ICP (iterative closest point) algorithm to robustly and accurately estimate poses from LiDAR data. We will demonstrate the KISS-ICP pipeline on the NCLT dataset along with some brief explanations, for a more detailed explanation you should look at the [original paper](https://arxiv.org/abs/2209.15397). diff --git a/examples/python/lidar/README.md b/examples/python/lidar/README.md index 390da060f579..283fcc34a83f 100644 --- a/examples/python/lidar/README.md +++ b/examples/python/lidar/README.md @@ -1,11 +1,11 @@ +Visualize the LiDAR data from the [nuScenes dataset](https://www.nuscenes.org/). @@ -15,19 +15,17 @@ thumbnail_dimensions = [480, 480] -Visualize the LiDAR data from the [nuScenes dataset](https://www.nuscenes.org/). - -# Used Rerun Types +## Used Rerun types [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) -# Background +## Background This example demonstrates the ability to read and visualize LiDAR data from the nuScenes dataset, which is a public large-scale dataset specifically designed for autonomous driving. The scenes in this dataset encompass data collected from a comprehensive suite of sensors on autonomous vehicles, including 6 cameras, 1 LIDAR, 5 RADAR, GPS and IMU sensors. It's important to note that in this example, only the LiDAR data is visualized. For a more extensive example including other sensors and annotations check out the [nuScenes example](https://www.rerun.io/examples/real-data/nuscenes). -# Logging and Visualizing with Rerun +## Logging and visualizing with Rerun The visualization in this example was created with just the following lines. @@ -40,7 +38,7 @@ rr.log("world/lidar", rr.Points3D(points, colors=point_colors)) # Log the 3D dat When logging data to Rerun, it's possible to associate it with specific time by using the Rerun's [`timelines`](https://www.rerun.io/docs/concepts/timelines). In the following code, we first establish the desired time frame and then proceed to log the 3D data points. -# Run the Code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/limap/README.md b/examples/python/limap/README.md index 795bd4b73253..ee8918b40a6f 100644 --- a/examples/python/limap/README.md +++ b/examples/python/limap/README.md @@ -6,6 +6,10 @@ thumbnail = "https://static.rerun.io/3d-line-mapping-revisited/be0a3b8ac08360368 thumbnail_dimensions = [480, 480] --> +This example is a visual walkthrough of the paper "3D Line Mapping Revisited". +All the visualizations were created by editing the original source code to log data with the Rerun SDK. + +## Visual paper walkthrough Human-made environments contain a lot of straight lines, which are currently not exploited by most mapping approaches. With their recent work "3D Line Mapping Revisited" Shaohui Liu et al. take steps towards changing that. diff --git a/examples/python/live_camera_edge_detection/README.md b/examples/python/live_camera_edge_detection/README.md index b197b9c6adca..dff535f818d8 100644 --- a/examples/python/live_camera_edge_detection/README.md +++ b/examples/python/live_camera_edge_detection/README.md @@ -1,11 +1,11 @@ +Visualize the [OpenCV Canny Edge Detection](https://docs.opencv.org/4.x/da/d22/tutorial_py_canny.html) results from a live camera stream. @@ -15,20 +15,18 @@ thumbnail_dimensions = [480, 480] Live Camera Edge Detection example screenshot -Visualize the [OpenCV Canny Edge Detection](https://docs.opencv.org/4.x/da/d22/tutorial_py_canny.html) results from a live camera stream. - -# Used Rerun Types +## Used Rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) -# Background +## Background In this example, the results of the [OpenCV Canny Edge Detection](https://docs.opencv.org/4.x/da/d22/tutorial_py_canny.html) algorithm are visualized. Canny Edge Detection is a popular edge detection algorithm, and can efficiently extract important structural information from visual objects while notably reducing the computational load. The process in this example involves converting the input image to RGB, then to grayscale, and finally applying the Canny Edge Detector for precise edge detection. -# Logging and Visualizing with Rerun +## Logging and visualizing with Rerun The visualization in this example were created with the following Rerun code: -## RGB Image +### RGB image The original image is read and logged in RGB format under the entity "image/rgb". ```python @@ -37,7 +35,7 @@ rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) rr.log("image/rgb", rr.Image(rgb)) ``` -## Grayscale Image +### Grayscale image The input image is converted from BGR color space to grayscale, and the resulting grayscale image is logged under the entity "image/gray". ```python @@ -46,7 +44,7 @@ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) rr.log("image/gray", rr.Image(gray)) ``` -## Canny Edge Detection Image +### Canny edge detection image The Canny edge detector is applied to the grayscale image, and the resulting edge-detected image is logged under the entity "image/canny". ```python @@ -56,7 +54,7 @@ rr.log("image/canny", rr.Image(canny)) ``` -# Run the Code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/live_depth_sensor/README.md b/examples/python/live_depth_sensor/README.md index f5d0acb76272..9d564d34c501 100644 --- a/examples/python/live_depth_sensor/README.md +++ b/examples/python/live_depth_sensor/README.md @@ -1,11 +1,11 @@ +Visualize the live-streaming frames from an Intel RealSense depth sensor. @@ -15,17 +15,15 @@ thumbnail_dimensions = [480, 360] Live Depth Sensor example screenshot -Visualize the live-streaming frames from an Intel RealSense depth sensor. - This example requires a connected realsense depth sensor. -# Used Rerun Types +## Used Rerun types [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image) -# Background +## Background The Intel RealSense depth sensor can stream live depth and color data. To visualize this data output, we utilized Rerun. -# Logging and Visualizing with Rerun +## Logging and visualizing with Rerun The RealSense sensor captures data in both RGB and depth formats, which are logged using the [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) and [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image) archetypes, respectively. Additionally, to provide a 3D view, the visualization includes a pinhole camera using the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) and [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetypes. @@ -38,7 +36,7 @@ rr.log("realsense", rr.ViewCoordinates.RDF, timeless=True) # Visualize the data -## Image +### Image First, the pinhole camera is set using the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) and [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetypes. Then, the images captured by the RealSense sensor are logged as an [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) object, and they're associated with the time they were taken. @@ -46,26 +44,26 @@ First, the pinhole camera is set using the [`Pinhole`](https://www.rerun.io/docs ```python rgb_from_depth = depth_profile.get_extrinsics_to(rgb_profile) - rr.log( - "realsense/rgb", - rr.Transform3D( - translation=rgb_from_depth.translation, - mat3x3=np.reshape(rgb_from_depth.rotation, (3, 3)), - from_parent=True, - ), - timeless=True, +rr.log( + "realsense/rgb", + rr.Transform3D( + translation=rgb_from_depth.translation, + mat3x3=np.reshape(rgb_from_depth.rotation, (3, 3)), + from_parent=True, + ), + timeless=True, ) ``` ```python rr.log( - "realsense/rgb/image", - rr.Pinhole( - resolution=[rgb_intr.width, rgb_intr.height], - focal_length=[rgb_intr.fx, rgb_intr.fy], - principal_point=[rgb_intr.ppx, rgb_intr.ppy], - ), - timeless=True, + "realsense/rgb/image", + rr.Pinhole( + resolution=[rgb_intr.width, rgb_intr.height], + focal_length=[rgb_intr.fx, rgb_intr.fy], + principal_point=[rgb_intr.ppx, rgb_intr.ppy], + ), + timeless=True, ) ``` ```python @@ -73,19 +71,19 @@ rr.set_time_sequence("frame_nr", frame_nr) rr.log("realsense/rgb/image", rr.Image(color_image)) ``` -## Depth Image +### Depth image Just like the RGB images, the RealSense sensor also captures depth data. The depth images are logged as [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image) objects and are linked with the time they were captured. ```python rr.log( - "realsense/depth/image", - rr.Pinhole( - resolution=[depth_intr.width, depth_intr.height], - focal_length=[depth_intr.fx, depth_intr.fy], - principal_point=[depth_intr.ppx, depth_intr.ppy], - ), - timeless=True, + "realsense/depth/image", + rr.Pinhole( + resolution=[depth_intr.width, depth_intr.height], + focal_length=[depth_intr.fx, depth_intr.fy], + principal_point=[depth_intr.ppx, depth_intr.ppy], + ), + timeless=True, ) ``` ```python @@ -93,11 +91,7 @@ rr.set_time_sequence("frame_nr", frame_nr) rr.log("realsense/depth/image", rr.DepthImage(depth_image, meter=1.0 / depth_units)) ``` - - - - -# Run the Code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/llm_embedding_ner/README.md b/examples/python/llm_embedding_ner/README.md index d36dcf8d7ab5..7451237c2969 100644 --- a/examples/python/llm_embedding_ner/README.md +++ b/examples/python/llm_embedding_ner/README.md @@ -1,10 +1,12 @@ + +Visualize the [BERT-based named entity recognition (NER)](https://huggingface.co/dslim/bert-base-NER) with UMAP Embeddings. + @@ -13,39 +15,36 @@ thumbnail_dimensions = [480, 480] -Visualize the [BERT-based named entity recognition (NER)](https://huggingface.co/dslim/bert-base-NER) with UMAP Embeddings. - -# Used Rerun types +## Used Rerun types [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) -# Background +## Background This example splits text into tokens, feeds the token sequence into a large language model (BERT), which outputs an embedding per token. The embeddings are then classified into four types of entities: location (LOC), organizations (ORG), person (PER) and Miscellaneous (MISC). The embeddings are projected to a 3D space using [UMAP](https://umap-learn.readthedocs.io/en/latest), and visualized together with all other data in Rerun. -# Logging and visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the following Rerun code: -## Text +### Text The logging begins with the original text. Following this, the tokenized version is logged for further analysis, and the named entities identified by the NER model are logged separately. All texts are logged using [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) as a Markdown document to preserves structure and formatting. -### Original text + +#### Original text ```python rr.log("text", rr.TextDocument(text, media_type=rr.MediaType.MARKDOWN)) ``` -### Tokenized text +#### Tokenized text ```python rr.log("tokenized_text", rr.TextDocument(markdown, media_type=rr.MediaType.MARKDOWN)) ``` -### Named entities +#### Named entities ```python rr.log("named_entities", rr.TextDocument(named_entities_str, media_type=rr.MediaType.MARKDOWN)) ``` -## UMAP embeddings - -[//]: # (The embeddings to UMAP facilitates the exploration, understanding, and evaluation of the NER model's output in a more interpretable and visually appealing manner.) +### UMAP embeddings UMAP is used in this example for dimensionality reduction and visualization of the embeddings generated by a Named Entity Recognition (NER) model. UMAP preserves the essential structure and relationships between data points, and helps in identifying clusters or patterns within the named entities. @@ -70,14 +69,14 @@ rr.log("/", rr.AnnotationContext(annotation_context)) ```python rr.log( - "umap_embeddings", - rr.Points3D(umap_embeddings, class_ids=class_ids), - rr.AnyValues(**{"Token": token_words, "Named Entity": entity_per_token(token_words, ner_results)}), + "umap_embeddings", + rr.Points3D(umap_embeddings, class_ids=class_ids), + rr.AnyValues(**{"Token": token_words, "Named Entity": entity_per_token(token_words, ner_results)}), ) ``` -# Run the code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/log_file/README.md b/examples/python/log_file/README.md index 95bdce41785f..57465d94e605 100644 --- a/examples/python/log_file/README.md +++ b/examples/python/log_file/README.md @@ -1,8 +1,11 @@ -Demonstrates how to log any file from the SDK using the [`DataLoader`](https://www.rerun.io/docs/howto/open-any-file) machinery. +Demonstrates how to log any file from the SDK using the [`DataLoader`](https://www.rerun.io/docs/reference/data-loaders/overview) machinery. Usage: ```bash diff --git a/examples/python/log_file/main.py b/examples/python/log_file/main.py index 113567a1a132..81764ad8299d 100755 --- a/examples/python/log_file/main.py +++ b/examples/python/log_file/main.py @@ -2,13 +2,14 @@ """ Demonstrates how to log any file from the SDK using the `DataLoader` machinery. -See for more information. +See for more information. Usage: ``` python examples/python/log_file/main.py -- examples/assets ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/mcc/README.md b/examples/python/mcc/README.md index d7bb9e8c4a68..977be02d7d38 100644 --- a/examples/python/mcc/README.md +++ b/examples/python/mcc/README.md @@ -6,6 +6,9 @@ thumbnail = "https://static.rerun.io/single-image-3D-reconstruction/c54498053d53 thumbnail_dimensions = [480, 480] --> +This example project combines several popular computer vision methods and uses Rerun to visualize the results and how the pieces fit together. + +# Visual project walkthrough By combining MetaAI's [Segment Anything Model (SAM)](https://github.com/facebookresearch/segment-anything) and [Multiview Compressive Coding (MCC)](https://github.com/facebookresearch/MCC) we can get a 3D object from a single image. @@ -32,7 +35,7 @@ MCC encodes the colored points and then creates a reconstruction by sweeping thr https://vimeo.com/865973880?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=1:1 -This is a really great example of how a lot of cool solutions are built these days; by stringing together more targeted pre-trained models.The details of the three building blocks can be found in the respective papers: +This is a really great example of how a lot of cool solutions are built these days; by stringing together more targeted pre-trained models. The details of the three building blocks can be found in the respective papers: - [Segment Anything](https://arxiv.org/abs/2304.02643) by Alexander Kirillov, Eric Mintun, Nikhila Ravi, Hanzi Mao, Chloe Rolland, Laura Gustafson, Tete Xiao, Spencer Whitehead, Alexander C. Berg, Wan-Yen Lo, Piotr Dollár, and Ross Girshick - [Multiview Compressive Coding for 3D Reconstruction](https://arxiv.org/abs/2301.08247) by Chao-Yuan Wu, Justin Johnson, Jitendra Malik, Christoph Feichtenhofer, and Georgia Gkioxari - [ZoeDepth: Zero-shot Transfer by Combining Relative and Metric Depth](https://arxiv.org/abs/2302.12288) by Shariq Farooq Bhat, Reiner Birkl, Diana Wofk, Peter Wonka, and Matthias Müller diff --git a/examples/python/minimal/README.md b/examples/python/minimal/README.md index 388248e9d268..308889ff43a1 100644 --- a/examples/python/minimal/README.md +++ b/examples/python/minimal/README.md @@ -2,8 +2,10 @@ title = "Minimal example" thumbnail = "https://static.rerun.io/minimal-example/9e694c0689f20323ed0053506a7a099f7391afca/480w.png" thumbnail_dimensions = [480, 480] +tags = ["3D", "API example"] --> +Generates a 3D colored cube and demonstrates how to log a point cloud. @@ -13,9 +15,55 @@ thumbnail_dimensions = [480, 480] Minimal example screenshot -The simplest example of how to use Rerun, showing how to log a point cloud. -This is part of the [Quick Start guide](https://www.rerun.io/docs/getting-started/python). +Straightforward example from the [Quick Start guide](https://www.rerun.io/docs/getting-started/quick-start/python) to generate a 3D colored cube and demonstrate how to log a point cloud. +# Used Rerun types + +[`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) + +# Logging and visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +It logs 3D points, each associated with a specific color, forming a grid pattern using [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype. +```python +import rerun as rr +import numpy as np + +rr.init("rerun_example_my_data", spawn=True) + +SIZE = 10 + +pos_grid = np.meshgrid(*[np.linspace(-10, 10, SIZE)]*3) +positions = np.vstack([d.reshape(-1) for d in pos_grid]).T + +col_grid = np.meshgrid(*[np.linspace(0, 255, SIZE)]*3) +colors = np.vstack([c.reshape(-1) for c in col_grid]).astype(np.uint8).T + +rr.log( + "my_points", + rr.Points3D(positions, colors=colors, radii=0.5) +) + ``` + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/minimal/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/minimal/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: ```bash -python examples/python/minimal/main.py +python examples/python/minimal/main.py --help ``` diff --git a/examples/python/multiprocessing/README.md b/examples/python/multiprocessing/README.md index 9448190c965c..306e041df973 100644 --- a/examples/python/multiprocessing/README.md +++ b/examples/python/multiprocessing/README.md @@ -2,8 +2,10 @@ title = "Multiprocessing" thumbnail = "https://static.rerun.io/multiprocessing/959e2c675f52a7ca83e11e5170903e8f0f53f5ed/480w.png" thumbnail_dimensions = [480, 480] +tags = ["API example"] --> +Demonstrates how rerun can work with the python `multiprocessing` library. @@ -13,8 +15,78 @@ thumbnail_dimensions = [480, 480] -Demonstrates how rerun can work with the python `multiprocessing` library. +# Used Rerun types +[`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d), [`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log) + +# Logging and visualizing with Rerun +This example demonstrates how to use the rerun with `multiprocessing` to log data from multiple processes to the same Rerun viewer. +It starts with the definition of the function for logging, the `task`, followed by typical usage of Python's `multiprocessing` library. + +The function `task` is decorated with `@rr.shutdown_at_exit`. This decorator ensures that data is flushed when the task completes, even if the normal `atexit`-handlers are not called at the termination of a multiprocessing process. + +```python +@rr.shutdown_at_exit +def task(child_index: int) -> None: + rr.init("rerun_example_multiprocessing") + + rr.connect() + + title = f"task_{child_index}" + rr.log( + "log", + rr.TextLog( + f"Logging from pid={os.getpid()}, thread={threading.get_ident()} using the Rerun recording id {rr.get_recording_id()}" + ) + ) + if child_index == 0: + rr.log(title, rr.Boxes2D(array=[5, 5, 80, 80], array_format=rr.Box2DFormat.XYWH, labels=title)) + else: + rr.log( + title, + rr.Boxes2D( + array=[10 + child_index * 10, 20 + child_index * 5, 30, 40], + array_format=rr.Box2DFormat.XYWH, + labels=title, + ), + ) +``` + +The main function initializes rerun with a specific application ID and manages the multiprocessing processes for logging data to the Rerun viewer. + +> Caution: Ensure that the `recording id` specified in the main function matches the one used in the logging functions + ```python +def main() -> None: + # … existing code … + rr.init("rerun_example_multiprocessing") + rr.spawn(connect=False) # this is the viewer that each child process will connect to + + task(0) + + for i in [1, 2, 3]: + p = multiprocessing.Process(target=task, args=(i,)) + p.start() + p.join() + ``` + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/multiprocessing/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/multiprocessing/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: ```bash -python examples/python/multiprocessing/main.py +python examples/python/multiprocessing/main.py --help ``` diff --git a/examples/python/multithreading/README.md b/examples/python/multithreading/README.md index 730090633cc6..2a4fc0ee76f2 100644 --- a/examples/python/multithreading/README.md +++ b/examples/python/multithreading/README.md @@ -2,8 +2,10 @@ title = "Multithreading" thumbnail = "https://static.rerun.io/multithreading/80a3e566d6d9f8f17b04c839cd0ae2380c2baf02/480w.png" thumbnail_dimensions = [480, 480] +tags = ["API example"] --> +Demonstration of logging to Rerun from multiple threads. @@ -13,8 +15,57 @@ thumbnail_dimensions = [480, 480] Multithreading example screenshot -Demonstration of logging to Rerun from multiple threads. +# Used Rerun types +[`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d) + +# Logging and visualizing with Rerun +This example showcases logging from multiple threads, starting with the definition of the function for logging, the `rect_logger`, followed by typical usage of Python's `threading` module in the main function. + + ```python +def rect_logger(path: str, color: npt.NDArray[np.float32]) -> None: + for _ in range(1000): + rects_xy = np.random.rand(5, 2) * 1024 + rects_wh = np.random.rand(5, 2) * (1024 - rects_xy + 1) + rects = np.hstack((rects_xy, rects_wh)) + rr.log(path, rr.Boxes2D(array=rects, array_format=rr.Box2DFormat.XYWH, colors=color)) # Log the rectangles using Rerun + ``` + +The main function manages the multiple threads for logging data to the Rerun viewer. + ```python +def main() -> None: + # … existing code … + + threads = [] + + for i in range(10): # Create 10 threads to run the rect_logger function with different paths and colors. + t = threading.Thread(target=rect_logger, args=(f"thread/{i}", [random.randrange(255) for _ in range(3)])) + t.start() + threads.append(t) + + for t in threads: # Wait for all threads to complete before proceeding. + t.join() + # … existing code … +``` + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/multithreading/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/multithreading/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: ```bash -python examples/python/multithreading/main.py +python examples/python/multithreading/main.py --help ``` diff --git a/examples/python/nuscenes/README.md b/examples/python/nuscenes/README.md index 7a5430a21401..5976e0303da4 100644 --- a/examples/python/nuscenes/README.md +++ b/examples/python/nuscenes/README.md @@ -1,13 +1,14 @@ +Visualize the [nuScenes dataset](https://www.nuscenes.org/) including lidar, radar, images, and bounding boxes data. + @@ -16,8 +17,6 @@ build_args = ["--seconds=5"] -Visualize the [nuScenes dataset](https://www.nuscenes.org/) including lidar, radar, images, and bounding boxes data. - ## Used Rerun types [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Image`](https://ref.rerun.io/docs/python/0.14.1/common/image_helpers/#rerun.ImageEncoded)* @@ -38,26 +37,26 @@ First, pinhole cameras and sensor poses are initialized to offer a 3D view and c ```python rr.log( - f"world/ego_vehicle/{sensor_name}", - rr.Transform3D( - translation=calibrated_sensor["translation"], - rotation=rr.Quaternion(xyzw=rotation_xyzw), - from_parent=False, - ), - timeless=True, - ) + f"world/ego_vehicle/{sensor_name}", + rr.Transform3D( + translation=calibrated_sensor["translation"], + rotation=rr.Quaternion(xyzw=rotation_xyzw), + from_parent=False, + ), + timeless=True, +) ``` ```python rr.log( - f"world/ego_vehicle/{sensor_name}", - rr.Pinhole( - image_from_camera=calibrated_sensor["camera_intrinsic"], - width=sample_data["width"], - height=sample_data["height"], - ), - timeless=True, - ) + f"world/ego_vehicle/{sensor_name}", + rr.Pinhole( + image_from_camera=calibrated_sensor["camera_intrinsic"], + width=sample_data["width"], + height=sample_data["height"], + ), + timeless=True, +) ``` ### Timelines diff --git a/examples/python/nuscenes/main.py b/examples/python/nuscenes/main.py index cf7ad6ee4df6..3843fd890221 100755 --- a/examples/python/nuscenes/main.py +++ b/examples/python/nuscenes/main.py @@ -13,6 +13,15 @@ from download_dataset import MINISPLIT_SCENES, download_minisplit from nuscenes import nuscenes +DESCRIPTION = """ +# nuScenes + +Visualize the [nuScenes dataset](https://www.nuscenes.org/) including lidar, radar, images, and bounding boxes data. + +The full source code for this example is available +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/nuscenes). +""" + EXAMPLE_DIR: Final = pathlib.Path(os.path.dirname(__file__)) DATASET_DIR: Final = EXAMPLE_DIR / "dataset" @@ -264,13 +273,19 @@ def main() -> None: for sensor_name in nuscene_sensor_names(nusc, args.scene_name) ] blueprint = rrb.Vertical( - rrb.Spatial3DView(name="3D", origin="world"), + rrb.Horizontal( + rrb.Spatial3DView(name="3D", origin="world"), + rrb.TextDocumentView(origin="description", name="Description"), + column_shares=[3, 1], + ), rrb.Grid(*sensor_space_views), - row_shares=[3, 2], + row_shares=[4, 2], ) rr.script_setup(args, "rerun_example_nuscenes", default_blueprint=blueprint) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + log_nuscenes(nusc, args.scene_name, max_time_sec=args.seconds) rr.script_teardown(args) diff --git a/examples/python/nv12/README.md b/examples/python/nv12/README.md index 049409941dfd..aa615390c2d5 100644 --- a/examples/python/nv12/README.md +++ b/examples/python/nv12/README.md @@ -1,18 +1,16 @@ +This example displays an NV12 encoded video stream from a webcam in rerun. - + -This example displays an NV12 encoded video stream from a webcam in rerun. + +## Run the code ```bash pip install -r examples/python/nv12/requirements.txt diff --git a/examples/python/objectron/README.md b/examples/python/objectron/README.md index 0747a5443668..22fc8a0f56bf 100644 --- a/examples/python/objectron/README.md +++ b/examples/python/objectron/README.md @@ -1,13 +1,14 @@ +Visualize the [Google Research Objectron](https://github.com/google-research-datasets/Objectron) dataset including camera poses, sparse point-clouds and surfaces characterization. + @@ -16,10 +17,6 @@ build_args = ["--frames=150"] Objectron example screenshot -[//]: # (Visualize the [Google Research Objectron](https://github.com/google-research-datasets/Objectron) dataset, which contains camera poses, sparse point-clouds and characterization of the planar surfaces in the surrounding environment.) - -Visualize the [Google Research Objectron](https://github.com/google-research-datasets/Objectron) dataset including camera poses, sparse point-clouds and surfaces characterization. - ## Used Rerun types [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), [`Image`](https://ref.rerun.io/docs/python/0.14.1/common/image_helpers/#rerun.ImageEncoded)*, [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) diff --git a/examples/python/open_photogrammetry_format/README.md b/examples/python/open_photogrammetry_format/README.md index 456b01c06b9a..0bc19932441f 100644 --- a/examples/python/open_photogrammetry_format/README.md +++ b/examples/python/open_photogrammetry_format/README.md @@ -1,13 +1,14 @@ +Uses [`pyopf`](https://github.com/Pix4D/pyopf) to load and display a photogrammetrically reconstructed 3D point cloud in the [Open Photogrammetry Format (OPF)](https://www.pix4d.com/open-photogrammetry-format/). + @@ -16,23 +17,20 @@ build_args = ["--jpeg-quality=50"] - -Uses [`pyopf`](https://github.com/Pix4D/pyopf) to load and display a photogrammetrically reconstructed 3D point cloud in the [Open Photogrammetry Format (OPF)](https://www.pix4d.com/open-photogrammetry-format/). - -# Used Rerun types +## Used Rerun types [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) -# Background +## Background This example loads an Open Photogrammetry Format (OPF) project and displays the cameras and point cloud data. OPF, which stands for 'open photogrammetry format,' is a file format used for photogrammetry data. It contains all the necessary information related to a reconstructed 3D model made with photogrammetry, including calibration, point clouds and dense reconstruction. -# Logging and visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the following Rerun code: -## Timelines +### Timelines For each processed frame, all data sent to Rerun is associated with specific time using [`timelines`](https://www.rerun.io/docs/concepts/timelines). @@ -40,7 +38,7 @@ The visualizations in this example were created with the following Rerun code: rr.set_time_sequence("image", i) ``` -## Video +### Video Pinhole camera is utilized for achieving a 3D view and camera perspective through the use of the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) and [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetypes. @@ -67,7 +65,7 @@ The input video is logged as a sequence of [`Image`](https://www.rerun.io/docs/r rr.log("world/cameras/image/rgb", rr.Image(np.array(img)).compress(jpeg_quality=jpeg_quality)) ``` -## Point clouds +### Point clouds Point clouds from the project are logged as [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype to the `world/points` entity. @@ -76,7 +74,7 @@ rr.log("world/points", rr.Points3D(points.position, colors=points.color), timele ``` -# Run the code +## Run the code > This example requires Python 3.10 or higher because of [`pyopf`](https://pypi.org/project/pyopf/). diff --git a/examples/python/open_photogrammetry_format/main.py b/examples/python/open_photogrammetry_format/main.py index 740f2bd740f8..182ba4e30f6f 100755 --- a/examples/python/open_photogrammetry_format/main.py +++ b/examples/python/open_photogrammetry_format/main.py @@ -2,10 +2,6 @@ """ Load an Open Photogrammetry Format (OPF) project and display the cameras and point cloud. -OPF specification: https://pix4d.github.io/opf-spec/index.html -Dataset source: https://support.pix4d.com/hc/en-us/articles/360000235126-Example-projects-real-photogrammetry-data#OPF1 -pyopf: https://github.com/Pix4D/pyopf - Requires Python 3.10 or higher because of [pyopf](https://pypi.org/project/pyopf/). """ from __future__ import annotations @@ -25,6 +21,20 @@ from pyopf.io import load from pyopf.resolve import resolve +DESCRIPTION = """ +# Open Photogrammetry Format + +Visualizes an Open Photogrammetry Format (OPF) project, displaying the cameras and point cloud. + +The full source code for this example is available +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/open_photogrammetry_format). + +### Links +* [OPF specification](https://pix4d.github.io/opf-spec/index.html) +* [Dataset source](https://support.pix4d.com/hc/en-us/articles/360000235126-Example-projects-real-photogrammetry-data#OPF1) +* [pyopf](https://github.com/Pix4D/pyopf) +""" + @dataclass class DatasetSpec: @@ -227,6 +237,7 @@ def main() -> None: # display everything in Rerun rr.script_setup(args, "rerun_example_open_photogrammetry_format") + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True) project.log_point_cloud() project.log_calibrated_cameras(jpeg_quality=args.jpeg_quality) diff --git a/examples/python/plots/README.md b/examples/python/plots/README.md index 33e38699bc30..6c9a888bf49d 100644 --- a/examples/python/plots/README.md +++ b/examples/python/plots/README.md @@ -1,12 +1,12 @@ +This example demonstrates how to log simple plots with the Rerun SDK. Charts can be created from 1-dimensional tensors, or from time-varying scalars. @@ -16,8 +16,122 @@ channel = "main" Plots example screenshot -This example demonstrates how to log simple plots with the Rerun SDK. Charts can be created from 1-dimensional tensors, or from time-varying scalars. +# Used Rerun types + +[`BarChart`](https://www.rerun.io/docs/reference/types/archetypes/bar_chart), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar), [`SeriesPoint`](https://www.rerun.io/docs/reference/types/archetypes/series_point), [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) + +# Logging and visualizing with Rerun + +This example shows various plot types that you can create using Rerun. Common usecases for such plots would be logging +losses or metrics over time, histograms, or general function plots. + +The bar chart is created by logging the [`BarChart`](https://www.rerun.io/docs/reference/types/archetypes/bar_chart) archetype. +All other plots are created using the [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype. +Each plot is created by logging scalars at different time steps (i.e., the x-axis). +Additionally, the plots are styled using the [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line) and +[`SeriesPoint`](https://www.rerun.io/docs/reference/types/archetypes/series_point) archetypes respectively. + +The visualizations in this example were created with the following Rerun code: + +## Bar chart + +The `log_bar_chart` function logs a bar chat. +It generates data for a Gaussian bell curve and logs it using [`BarChart`](https://www.rerun.io/docs/reference/types/archetypes/bar_chart) archetype. +```python +def log_bar_chart() -> None: + # … existing code … + rr.log("bar_chart", rr.BarChart(y)) +``` + +## Curves +The `log_parabola` function logs a parabola curve (sine and cosine functions) as a time series. + +It first sets up a time sequence using [`timelines`](https://www.rerun.io/docs/concepts/timelines), then calculates the y-value of the parabola at each time step, and logs it using [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype. +It also adjusts the width and color of the plotted line based on the calculated y value using [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line) archetype. + +```python +def log_parabola() -> None: + # Name never changes, log it only once. + rr.log("curves/parabola", rr.SeriesLine(name="f(t) = (0.01t - 3)³ + 1"), timeless=True) + + # Log a parabola as a time series + for t in range(0, 1000, 10): + rr.set_time_sequence("frame_nr", t) + + # … existing code … + + rr.log( + "curves/parabola", + rr.Scalar(f_of_t), + rr.SeriesLine(width=width, color=color), + ) +``` + +## Trig + +The `log_trig` function logs sin and cos functions as time series. Sin and cos are logged with the same parent entity (i.e.,`trig/{cos,sin}`) which will put them in the same view by default. +It first logs the styling properties of the sin and cos plots using [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line) archetype. +Then, it iterates over a range of time steps, calculates the sin and cos values at each time step, and logs them using [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype. + + ```python +def log_trig() -> None: + # Styling doesn't change over time, log it once with timeless=True. + rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), timeless=True) + rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), timeless=True) + + for t in range(0, int(tau * 2 * 100.0)): + rr.set_time_sequence("frame_nr", t) + + sin_of_t = sin(float(t) / 100.0) + rr.log("trig/sin", rr.Scalar(sin_of_t)) + + cos_of_t = cos(float(t) / 100.0) + rr.log("trig/cos", rr.Scalar(cos_of_t)) + ``` + +## Classification + +The `log_classification` function simulates a classification problem by logging a line function and randomly generated samples around that line. + +It first logs the styling properties of the line plot using [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line) archetype. +Then, it iterates over a range of time steps, calculates the y value of the line function at each time step, and logs it as a scalar using [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype. +Additionally, it generates random samples around the line function and logs them using [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) and [`SeriesPoint`](https://www.rerun.io/docs/reference/types/archetypes/series_point) archetypes. + + ```python +def log_classification() -> None: + # Log components that don't change only once: + rr.log("classification/line", rr.SeriesLine(color=[255, 255, 0], width=3.0), timeless=True) + + for t in range(0, 1000, 2): + rr.set_time_sequence("frame_nr", t) + + # … existing code … + rr.log("classification/line", rr.Scalar(f_of_t)) + + # … existing code … + rr.log("classification/samples", rr.Scalar(g_of_t), rr.SeriesPoint(color=color, marker_size=marker_size)) + ``` + + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/plots/requirements.txt +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/plots/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: ```bash -python examples/python/plots/main.py +python examples/python/plots/main.py --help ``` diff --git a/examples/python/plots/main.py b/examples/python/plots/main.py index ff387b32f7e6..40a4e2245373 100755 --- a/examples/python/plots/main.py +++ b/examples/python/plots/main.py @@ -22,27 +22,7 @@ This example shows various plot types that you can create using Rerun. Common usecases for such plots would be logging losses or metrics over time, histograms, or general function plots. -## How it was made -The full source code for this example is available [on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/plots/main.py). - -### Bar charts -The [bar chart](recording://bar_chart) is created by logging the [rr.BarChart archetype](https://www.rerun.io/docs/reference/types/archetypes/bar_chart). - -### Time series -All other plots are created using the -[rr.Scalar archetype](https://www.rerun.io/docs/reference/types/archetypes/scalar) -archetype. -Each plot is created by logging scalars at different time steps (i.e., the x-axis). -Additionally, the plots are styled using the -[rr.SeriesLine](https://www.rerun.io/docs/reference/types/archetypes/series_line) and -[rr.SeriesPoint](https://www.rerun.io/docs/reference/types/archetypes/series_point) -archetypes respectively. - -For the [parabola](recording://curves/parabola) the radius and color is changed over time, -the other plots use static for their styling properties where possible. - -[sin](recording://trig/sin) and [cos](recording://trig/cos) are logged with the same parent entity (i.e., -`trig/{cos,sin}`) which will put them in the same view by default. +The full source code for this example is available [on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/plots). """.strip() @@ -136,7 +116,7 @@ def main() -> None: rrb.TimeSeriesView(name="Classification", origin="/classification"), ), rrb.TextDocumentView(name="Description", origin="/description"), - column_shares=[2, 1], + column_shares=[3, 1], ), rrb.SelectionPanel(expanded=False), rrb.TimePanel(expanded=False), diff --git a/examples/python/raw_mesh/README.md b/examples/python/raw_mesh/README.md index c30762f765fa..f4a2071147da 100644 --- a/examples/python/raw_mesh/README.md +++ b/examples/python/raw_mesh/README.md @@ -1,12 +1,13 @@ +Demonstrates logging of raw 3D mesh data (so-called "triangle soups") with simple material properties and their transform hierarchy. + @@ -15,22 +16,20 @@ channel = "release" -Demonstrates logging of raw 3D mesh data (so-called "triangle soups") with simple material properties and their transform hierarchy. - -# Used Rerun types +## Used Rerun types [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Mesh3D`](https://www.rerun.io/docs/reference/types/archetypes/mesh3d) -# Background +## Background Raw 3D mesh data refers to the basic geometric representation of a three-dimensional object, typically composed of interconnected triangles. These triangles collectively form the surface of the object, defining its shape and structure in a digital environment. Rerun was employed to visualize and manage this raw mesh data, along with its associated simple material properties and transform hierarchy. -# Logging and visualizing with Rerun +## Logging and visualizing with Rerun The visualizations in this example were created with the following Rerun code: -## 3D mesh data +### 3D mesh data The raw 3D mesh data are logged as [`Mesh3D`](https://www.rerun.io/docs/reference/types/archetypes/mesh3d) objects, and includes details about vertex positions, colors, normals, texture coordinates, material properties, and face indices for an accurate reconstruction and visualization. ```python @@ -59,7 +58,7 @@ rr.log( ``` -# Run the code +## Run the code To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: ```bash # Setup diff --git a/examples/python/raw_mesh/main.py b/examples/python/raw_mesh/main.py index 29bc271e80ae..3dc682d1abcf 100755 --- a/examples/python/raw_mesh/main.py +++ b/examples/python/raw_mesh/main.py @@ -16,10 +16,18 @@ import numpy as np import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb import trimesh from download_dataset import AVAILABLE_MESHES, ensure_mesh_downloaded from rerun.components import Material +DESCRIPTION = """ +# Raw meshes +This example shows how you can log a hierarchial 3D mesh, including its transform hierarchy. + +The full source code for this example is available [on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/raw_mesh). +""" + def load_scene(path: Path) -> trimesh.Scene: print(f"loading scene {path}…") @@ -119,8 +127,6 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_raw_mesh") - scene_path = args.scene_path if scene_path is None: scene_path = ensure_mesh_downloaded(args.scene) @@ -128,6 +134,15 @@ def main() -> None: root = next(iter(scene.graph.nodes)) + blueprint = rrb.Horizontal( + rrb.Spatial3DView(name="Mesh", origin="/world"), + rrb.TextDocumentView(name="Description", origin="/description"), + column_shares=[3, 1], + ) + + rr.script_setup(args, "rerun_example_raw_mesh", default_blueprint=blueprint) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + # glTF always uses a right-handed coordinate system when +Y is up and meshes face +Z. rr.log(root, rr.ViewCoordinates.RUB, static=True) log_scene(scene, root) diff --git a/examples/python/rgbd/README.md b/examples/python/rgbd/README.md index 08d5b018178b..7e5429cfc591 100644 --- a/examples/python/rgbd/README.md +++ b/examples/python/rgbd/README.md @@ -1,13 +1,14 @@ +Visualizes an example recording from [the NYUD dataset](https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html) with RGB and Depth channels. + @@ -16,9 +17,74 @@ build_args = ["--frames=300"] RGBD example screenshot -Example using an [example dataset](https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html) from New York University with RGB and Depth channels. +# Used Rerun types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image) + +# Background +The dataset, known as the NYU Depth V2 dataset, consists of synchronized pairs of RGB and depth frames recorded by the Microsoft Kinect in various indoor scenes. +This example visualizes one scene of this dataset, and offers a rich source of data for object recognition, scene understanding, depth estimation, and more. + +# Logging and visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## Timelines + +All data logged using Rerun in the following sections is connected to a specific time. +Rerun assigns a timestamp to each piece of logged data, and these timestamps are associated with a [`timeline`](https://www.rerun.io/docs/concepts/timelines). + + ```python +rr.set_time_seconds("time", time.timestamp()) + ``` + +## Image +The example image is logged as [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) to the `world/camera/image/rgb` entity. +```python +rr.log("world/camera/image/rgb", rr.Image(img_rgb).compress(jpeg_quality=95)) +``` + +## Depth image + +Pinhole camera is utilized for achieving a 3D view and camera perspective through the use of the [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole). + +```python +rr.log( + "world/camera/image", + rr.Pinhole( + resolution=[img_depth.shape[1], img_depth.shape[0]], + focal_length=0.7 * img_depth.shape[1], + ), +) +``` + +Then, the depth image is logged as an [`DepthImage`](https://www.rerun.io/docs/reference/types/archetypes/depth_image) to the `world/camera/image/depth` entity. + +```python +rr.log("world/camera/image/depth", rr.DepthImage(img_depth, meter=DEPTH_IMAGE_SCALING)) +``` +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/rgbd/requirements.txt -python examples/python/rgbd/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/rgbd/main.py # run the example +``` +You can specify the recording: +```bash +python examples/python/rgbd/main.py --recording {cafe,basements,studies,office_kitchens,playroooms} +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/rgbd/main.py --help ``` diff --git a/examples/python/rgbd/main.py b/examples/python/rgbd/main.py index 67e2ef564e49..b63a499ed305 100755 --- a/examples/python/rgbd/main.py +++ b/examples/python/rgbd/main.py @@ -22,6 +22,13 @@ import rerun.blueprint as rrb from tqdm import tqdm +DESCRIPTION = """ +# RGBD +Visualizes an example recording from [the NYUD dataset](https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html) with RGB and Depth channels. + +The full source code for this example is available [on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/rgbd). +""" + DEPTH_IMAGE_SCALING: Final = 1e4 DATASET_DIR: Final = Path(os.path.dirname(__file__)) / "dataset" DATASET_URL_BASE: Final = "https://static.rerun.io/rgbd_dataset" @@ -169,15 +176,22 @@ def main() -> None: rrb.Vertical( # Put the origin for both 2D spaces where the pinhole is logged. Doing so allows them to understand how they're connected to the 3D space. # This enables interactions like clicking on a point in the 3D space to show the corresponding point in the 2D spaces and vice versa. - rrb.Spatial2DView(name="Depth & RGB", origin="world/camera/image"), - rrb.Spatial2DView(name="RGB", origin="world/camera/image", contents="world/camera/image/rgb"), + rrb.Spatial2DView(name="RGB & Depth", origin="world/camera/image"), + rrb.Tabs( + rrb.Spatial2DView(name="RGB", origin="world/camera/image", contents="world/camera/image/rgb"), + rrb.Spatial2DView(name="Depth", origin="world/camera/image", contents="world/camera/image/depth"), + ), + rrb.TextDocumentView(name="Description", origin="/description"), name="2D", + row_shares=[3, 3, 2], ), column_shares=[2, 1], ), ) recording_path = ensure_recording_downloaded(args.recording) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + log_nyud_data( recording_path=recording_path, subset_idx=args.subset_idx, diff --git a/examples/python/ros_node/README.md b/examples/python/ros_node/README.md index db4cb217f185..8174a5d3250c 100644 --- a/examples/python/ros_node/README.md +++ b/examples/python/ros_node/README.md @@ -1,10 +1,13 @@ +A minimal example of creating a ROS node that subscribes to topics and converts the messages to rerun log calls. + +The solution here is mostly a toy example to show how ROS concepts can be mapped to Rerun. @@ -14,17 +17,26 @@ thumbnail_dimensions = [480, 480] -# Overview +# Used Rerun types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Boxes3D`](https://www.rerun.io/docs/reference/types/archetypes/boxes3d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`LineStrips3D`](https://www.rerun.io/docs/reference/types/archetypes/line_strips3d), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) -A minimal example of creating a ROS node that subscribes to topics and converts the messages to rerun log calls. +# Background +The [Robot Operating System (ROS)](https://www.ros.org) helps build robot applications through software libraries and tools. +Although Rerun doesn't have native ROS support, you can easily create a basic ROS 2 Python node to subscribe to common ROS topics and log them to Rerun. +In this example, Rerun visualizes simulation data, including robot pose, images, camera position, laser scans, point clouds, and velocities, as the [Turtlebot](http://wiki.ros.org/turtlebot3) navigates the environment. -The solution here is mostly a toy example to show how ROS concepts can be mapped to Rerun. Fore more information on -future improved ROS support, see the tracking issue: [#1527](https://github.com/rerun-io/rerun/issues/1537) +# Logging and visualizing with Rerun -NOTE: Unlike many of the other examples, this example requires a system installation of ROS -in addition to the packages from requirements.txt. +Find the detailed code walkthrough and explanation for visualizing this example here: [Using Rerun with ROS 2](https://www.rerun.io/docs/howto/ros2-nav-turtlebot). -# Dependencies +For more information on future improved ROS support, see tracking issue: [#1527](https://github.com/rerun-io/rerun/issues/1537) + +# Run the code + +## Dependencies + +> NOTE: Unlike many of the other examples, this example requires a system installation of ROS +in addition to the packages from requirements.txt. This example was developed and tested on top of [ROS2 Humble Hawksbill](https://docs.ros.org/en/humble/index.html) and the [turtlebot3 navigation example](https://navigation.ros.org/getting_started/index.html). @@ -34,6 +46,19 @@ Installing ROS is outside the scope of this example, but you will need the equiv sudo apt install ros-humble-desktop gazebo ros-humble-navigation2 ros-humble-turtlebot3 ros-humble-turtlebot3-gazebo ``` +Make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: +```bash +pip install -r examples/python/ros_node/requirements.txt +``` + In addition to installing the dependencies from `requirements.txt` into a venv you will also need to source the ROS setup script: ``` @@ -41,8 +66,7 @@ source venv/bin/active source /opt/ros/humble/setup.bash ``` - -# Running +## Run the code First, in one terminal launch the nav2 turtlebot demo: ``` @@ -56,6 +80,11 @@ ros2 launch nav2_bringup tb3_simulation_launch.py headless:=False As described in the nav demo, use the rviz window to initialize the pose estimate and set a navigation goal. You can now connect to the running ROS system by running: +```bash +python examples/python/ros_node/main.py # run the example ``` -python3 examples/python/ros_node/main.py + +If you wish to customize it, or explore additional features, use the CLI with the `--help` option for guidance: +```bash +python examples/python/ros_node/main.py --help ``` diff --git a/examples/python/rrt-star/README.md b/examples/python/rrt-star/README.md index 005caff1aa86..f57f256ff030 100644 --- a/examples/python/rrt-star/README.md +++ b/examples/python/rrt-star/README.md @@ -1,12 +1,13 @@ +This example visualizes the path finding algorithm RRT\* in a simple environment. + RRT* example screenshot @@ -15,13 +16,104 @@ channel = "main" -This example visualizes the path finding algorithm RRT\* in a simple environment. +# Used Rerun types +[`LineStrips2D`](https://www.rerun.io/docs/reference/types/archetypes/line_strips2d), [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) + +# Background +The algorithm finds a path between two points by randomly expanding a tree from the start point. +After it has added a random edge to the tree it looks at nearby nodes to check if it's faster to reach them through this new edge instead, +and if so it changes the parent of these nodes. This ensures that the algorithm will converge to the optimal path given enough time. A detailed explanation can be found in the original paper Karaman, S. Frazzoli, S. 2011. "Sampling-based algorithms for optimal motion planning". or in [this medium article](https://theclassytim.medium.com/robotic-path-planning-rrt-and-rrt-212319121378) + +# Logging and visualizing with Rerun + +All points are logged using the [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d) archetype, while the lines are logged using the LineStrips2D [`LineStrips2D`](https://www.rerun.io/docs/reference/types/archetypes/line_strips2d). + +The visualizations in this example were created with the following Rerun code: + +## Map + +### Starting point +```python +rr.log("map/start", rr.Points2D([start_point], radii=0.02, colors=[[255, 255, 255, 255]])) +``` + +### Destination point +```python +rr.log("map/destination", rr.Points2D([end_point], radii=0.02, colors=[[255, 255, 0, 255]])) +``` + +### Obstacles +```python +rr.log("map/obstacles", rr.LineStrips2D(self.obstacles)) +``` + + +## RRT tree + +### Edges +```python +rr.log("map/tree/edges", rr.LineStrips2D(tree.segments(), radii=0.0005, colors=[0, 0, 255, 128])) +``` + +### New edges +```python +rr.log("map/new/new_edge", rr.LineStrips2D([(closest_node.pos, new_point)], colors=[color], radii=0.001)) +``` + +### Vertices +```python +rr.log("map/tree/vertices", rr.Points2D([node.pos for node in tree], radii=0.002), rr.AnyValues(cost=[float(node.cost) for node in tree])) +``` + +### Close nodes +```python +rr.log("map/new/close_nodes", rr.Points2D([node.pos for node in close_nodes])) +``` + +### Closest node +```python +rr.log("map/new/closest_node", rr.Points2D([closest_node.pos], radii=0.008)) +``` + +### Random points +```python +rr.log("map/new/random_point", rr.Points2D([random_point], radii=0.008)) +``` + +### New points +```python +rr.log("map/new/new_point", rr.Points2D([new_point], radii=0.008)) +``` + +### Path +```python +rr.log("map/path", rr.LineStrips2D(segments, radii=0.002, colors=[0, 255, 255, 255])) +``` + + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/rrt-star/requirements.txt -python examples/python/rrt-star/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/rrt-star/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/rrt-star/main.py --help ``` diff --git a/examples/python/rrt-star/main.py b/examples/python/rrt-star/main.py index 1438640d1392..36a90e6158b2 100755 --- a/examples/python/rrt-star/main.py +++ b/examples/python/rrt-star/main.py @@ -26,6 +26,21 @@ import numpy as np import numpy.typing as npt import rerun as rr +import rerun.blueprint as rrb + +DESCRIPTION = """ +Visualizes the path finding algorithm RRT* in a simple environment. + +The algorithm finds a [path](recording://map/path) between two points by randomly expanding a [tree](recording://map/tree/edges) from the [start point](recording://map/start). +After it has added a [random edge](recording://map/new/new_edge) to the tree it looks at [nearby nodes](recording://map/new/close_nodes) to check if it's faster to reach them through this [new edge](recording://map/new/new_edge) instead, and if so it changes the parent of these nodes. +This ensures that the algorithm will converge to the optimal path given enough time. + +A more detailed explanation can be found in the original paper +Karaman, S. Frazzoli, S. 2011. "Sampling-based algorithms for optimal motion planning". +or in [this medium article](https://theclassytim.medium.com/robotic-path-planning-rrt-and-rrt-212319121378). + +The full source code for this example is available [on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/rrt-star). +""".strip() Point2D = Annotated[npt.NDArray[np.float64], Literal[2]] @@ -259,7 +274,13 @@ def main() -> None: parser.add_argument("--max-step-size", type=float, default=0.1) parser.add_argument("--iterations", type=int, help="How many iterations it should do") args = parser.parse_args() - rr.script_setup(args, "rerun_example_rrt_star") + + blueprint = rrb.Horizontal( + rrb.Spatial2DView(name="Map", origin="/map"), + rrb.TextDocumentView(name="Description", origin="/description"), + column_shares=[3, 1], + ) + rr.script_setup(args, "rerun_example_rrt_star", default_blueprint=blueprint) max_step_size = args.max_step_size neighborhood_size = max_step_size * 1.5 @@ -268,23 +289,7 @@ def main() -> None: end_point = np.array([1.8, 0.5]) rr.set_time_sequence("step", 0) - rr.log( - "description", - rr.TextDocument( - """ -Visualizes the path finding algorithm RRT* in a simple environment. - -The algorithm finds a [path](recording://map/path) between two points by randomly expanding a [tree](recording://map/tree/edges) from the [start point](recording://map/start). -After it has added a [random edge](recording://map/new/new_edge) to the tree it looks at [nearby nodes](recording://map/new/close_nodes) to check if it's faster to reach them through this [new edge](recording://map/new/new_edge) instead, and if so it changes the parent of these nodes. -This ensures that the algorithm will converge to the optimal path given enough time. - -A more detailed explanation can be found in the original paper -Karaman, S. Frazzoli, S. 2011. "Sampling-based algorithms for optimal motion planning". -or in [this medium article](https://theclassytim.medium.com/robotic-path-planning-rrt-and-rrt-212319121378) - """.strip(), - media_type=rr.MediaType.MARKDOWN, - ), - ) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) rr.log( "map/start", rr.Points2D([start_point], radii=0.02, colors=[[255, 255, 255, 255]]), diff --git a/examples/python/segment_anything_model/README.md b/examples/python/segment_anything_model/README.md index f4d9a24d0445..ba2b5b7974d7 100644 --- a/examples/python/segment_anything_model/README.md +++ b/examples/python/segment_anything_model/README.md @@ -1,12 +1,12 @@ +Example of using Rerun to log and visualize the output of [Meta AI's Segment Anything model](https://segment-anything.com/). @@ -16,11 +16,69 @@ channel = "release" Segment Anything Model example screenshot -Example of using Rerun to log and visualize the output of Meta AI's Segment Anything model. +# Used Rerun types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor), [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image), [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d) -For more info see [here](https://segment-anything.com/). +# Background +This example showcases the visualization capabilities of [Meta AI's Segment Anything model](https://segment-anything.com/). +The visualization provided in this example demonstrates the precise and accurate segmentation capabilities of the model, effectively distinguishing each object from the background and creating a transparent mask around them. +# Logging and visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## Timelines + +All data logged using Rerun in the following sections is connected to a specific frame. +Rerun assigns a frame to each piece of logged data, and these timestamps are associated with a [`timeline`](https://www.rerun.io/docs/concepts/timelines). + + ```python +for n, image_uri in enumerate(args.images): + rr.set_time_sequence("image", n) + image = load_image(image_uri) + run_segmentation(mask_generator, image) + ``` + +## Image +The input image is logged as [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) to the `image` entity. +```python +rr.log("image", rr.Image(image)) +``` +## Segmentation +All masks are stacked together and logged using the [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor) archetype. +```python +rr.log("mask_tensor", rr.Tensor(mask_tensor)) +``` +Then, all the masks are layered together and the result is logged as a [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) to the `image/masks` entity. +```python +rr.log("image/masks", rr.SegmentationImage(segmentation_img.astype(np.uint8))) +``` +For object localization, bounding boxes of segmentations are logged as [`Boxes2D`](https://www.rerun.io/docs/reference/types/archetypes/boxes2d). +```python +rr.log( + "image/boxes", + rr.Boxes2D(array=mask_bbox, array_format=rr.Box2DFormat.XYWH, class_ids=[id for id, _ in masks_with_ids]), +) +``` + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/segment_anything_model/requirements.txt -python examples/python/segment_anything_model/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/segment_anything_model/main.py # run the example +``` +If you wish to customize it or explore additional features, use the CLI with the `--help` option for guidance: +```bash +python examples/python/segment_anything_model/main.py --help ``` diff --git a/examples/python/segment_anything_model/main.py b/examples/python/segment_anything_model/main.py index 5124182d4658..cbd8f7597543 100755 --- a/examples/python/segment_anything_model/main.py +++ b/examples/python/segment_anything_model/main.py @@ -1,8 +1,6 @@ #!/usr/bin/env python3 """ -Example of using Rerun to log and visualize the output of segment-anything. - -See: [segment_anything](https://segment-anything.com/). +Example of using Rerun to log and visualize the output of [Segment Anything](https://segment-anything.com/). Can be used to test mask-generation on one or more images. Images can be local file-paths or remote urls. @@ -29,6 +27,7 @@ import numpy as np import requests import rerun as rr # pip install rerun-sdk +import rerun.blueprint as rrb import torch import torchvision from cv2 import Mat @@ -36,6 +35,12 @@ from segment_anything.modeling import Sam from tqdm import tqdm +DESCRIPTION = """ +Example of using Rerun to log and visualize the output of [Segment Anything](https://segment-anything.com/). + +The full source code for this example is available [on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/segment_anything_model). +""".strip() + MODEL_DIR: Final = Path(os.path.dirname(__file__)) / "model" MODEL_URLS: Final = { "vit_h": "https://dl.fbaipublicfiles.com/segment_anything/sam_vit_h_4b8939.pth", @@ -177,10 +182,22 @@ def main() -> None: rr.script_add_args(parser) args = parser.parse_args() - rr.script_setup(args, "rerun_example_segment_anything_model") + blueprint = rrb.Vertical( + rrb.Spatial2DView(name="Image and segmentation mask", origin="/image"), + rrb.Horizontal( + rrb.TextLogView(name="Log", origin="/logs"), + rrb.TextDocumentView(name="Description", origin="/description"), + column_shares=[2, 1], + ), + row_shares=[3, 1], + ) + + rr.script_setup(args, "rerun_example_segment_anything_model", default_blueprint=blueprint) logging.getLogger().addHandler(rr.LoggingHandler("logs")) logging.getLogger().setLevel(logging.INFO) + rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), timeless=True) + sam = create_sam(args.model, args.device) mask_config = {"points_per_batch": args.points_per_batch} diff --git a/examples/python/shape_pointe/README.md b/examples/python/shape_pointe/README.md index dedf923e73bd..d4df5865718c 100644 --- a/examples/python/shape_pointe/README.md +++ b/examples/python/shape_pointe/README.md @@ -6,6 +6,9 @@ thumbnail = "https://static.rerun.io/point-e/5b5beb36dce77d2dac7123b197b825421af thumbnail_dimensions = [480, 480] --> +This example is a visual comparison of two popular text-to-3D methods that uses Rerun to compare the generation process and results. + +## Visual paper comparison OpenAI has released two models for text-to-3D generation: Point-E and Shape-E. Both of these methods are fast and interesting but still low fidelity for now. diff --git a/examples/python/signed_distance_fields/README.md b/examples/python/signed_distance_fields/README.md index b58e942f7529..6100fa9fadbe 100644 --- a/examples/python/signed_distance_fields/README.md +++ b/examples/python/signed_distance_fields/README.md @@ -1,23 +1,96 @@ +Visualize the results of the Generate Signed Distance Fields for arbitrary meshes using both traditional methods and the one described in the [DeepSDF paper](https://arxiv.org/abs/1901.05103) + - Signed Distance Fields example screenshot - - - - + + + + + Signed Distance Fields example screenshot -Generate Signed Distance Fields for arbitrary meshes using both traditional methods and the one described in the [DeepSDF paper](https://arxiv.org/abs/1901.05103), and visualize the results using the Rerun SDK. +# Used Rerun types +[`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor), [`Asset3D`](https://www.rerun.io/docs/reference/types/archetypes/asset3d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context), [`TextLog`](https://www.rerun.io/docs/reference/types/archetypes/text_log) + +# Background + +This example illustrates the visualization of the results obtained from generating Signed Distance Fields (SDFs) for arbitrary meshes using both traditional methods and the approach described in the [DeepSDF paper](https://arxiv.org/abs/1901.05103). +DeepSDF introduces a learned continuous representation of shapes using SDFs, enabling high-quality shape representation, interpolation, and completion from partial and noisy 3D input data. +This novel approach offers improved performance and reduced model size compared to previous methods. +The generated SDFs help with accurate 3D reconstruction and visualization. + +# Logging and visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## 3D asset + +```python +# Internally, `mesh_to_sdf` will normalize everything to a unit sphere centered around the center of mass. +bs1 = mesh.bounding_sphere +bs2 = mesh_to_sdf.scale_to_unit_sphere(mesh).bounding_sphere +scale = bs2.scale / bs1.scale +center = bs2.center - bs1.center * scale +``` + +```python +# Logging the 3D asset with the unit sphere +mesh3d = rr.Asset3D(path=path) +mesh3d.transform = rr.OutOfTreeTransform3DBatch(rr.TranslationRotationScale3D(translation=center, scale=scale)) +rr.log("world/mesh", mesh3d) +``` + +## Sample SDF + +The sampled points and their corresponding signed distances are visualized using the [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype within the `world/sdf/points` entity. + +```python +# Points inside the object are highlighted in red, while those outside are marked in green. +rr.log("world/sdf", rr.AnnotationContext([(0, "inside", (255, 0, 0)), (1, "outside", (0, 255, 0))]), timeless=False) +``` + +```python +rr.log("world/sdf/points", rr.Points3D(points, class_ids=np.array(sdf > 0, dtype=np.uint8))) # Visualizing Sample SDF +``` + +## Volumetric SDF + +The computed distances for each voxel are visualized using the [`Tensor`](https://www.rerun.io/docs/reference/types/archetypes/tensor) archetype to the `tensor` entity, which represents a 3D grid with dimensions for width, height, and depth. + +```python +rr.log("tensor", rr.Tensor(voxvol, dim_names=["width", "height", "depth"])) # Visualizing Volumetric SDF +``` + +# Run the code +> _Known issue_: On macOS, this example may present artefacts in the SDF and/or fail. +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/signed_distance_fields/requirements.txt -python examples/python/signed_distance_fields/main.py ``` - -_Known issue_: On macOS, this example may present artefacts in the SDF and/or fail. +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/signed_distance_fields/main.py # run the example +``` +You can specify the mesh: +```bash +python examples/python/signed_distance_fields/main.py --mesh {lantern,avocado,buggy,brain_stem} +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/signed_distance_fields/main.py --help +``` diff --git a/examples/python/simplerecon/README.md b/examples/python/simplerecon/README.md index 599cb0f15cf3..18fd078584db 100644 --- a/examples/python/simplerecon/README.md +++ b/examples/python/simplerecon/README.md @@ -6,6 +6,11 @@ thumbnail = "https://static.rerun.io/simplecon/e0f234159cc0f934e6d4a26886b751579 thumbnail_dimensions = [480, 480] --> +This example is a visual walkthrough of the paper "SimpleRecon: 3D reconstruction without 3D convolutions". +All the visualizations were created by editing the original source code to log data with the Rerun SDK. + +## Visual paper walkthrough + SimpleRecon is a back-to-basics approach for 3D scene reconstruction from posed monocular images by Niantic Labs. It offers state-of-the-art depth accuracy and competitive 3D scene reconstruction which makes it perfect for resource-constrained environments. diff --git a/examples/python/slahmr/README.md b/examples/python/slahmr/README.md index d566f2f311b2..a0ed3aced25f 100644 --- a/examples/python/slahmr/README.md +++ b/examples/python/slahmr/README.md @@ -7,6 +7,11 @@ thumbnail_dimensions = [480, 480] --> +This example is a visual walkthrough of the paper “Decoupling Human and Camera Motion from Videos in the Wild”. +All the visualizations were created by editing the original source code to log data with the Rerun SDK. + +## Visual paper walkthrough + SLAHMR robustly tracks the motion of multiple moving people filmed with a moving camera and works well on “in-the-wild” videos. It’s a great showcase of how to build working computer vision systems by intelligently combining several single purpose models. https://vimeo.com/865974657?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=10000:6835 diff --git a/examples/python/structure_from_motion/README.md b/examples/python/structure_from_motion/README.md index 09c3ca223b70..7c3ce6a61263 100644 --- a/examples/python/structure_from_motion/README.md +++ b/examples/python/structure_from_motion/README.md @@ -1,13 +1,13 @@ +Visualize a sparse reconstruction by [COLMAP](https://colmap.github.io/index.html), a general-purpose Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline with a graphical and command-line interface @@ -17,14 +17,102 @@ build_args = ["--dataset=colmap_fiat", "--resize=800x600"] Structure From Motion example screenshot -An example using Rerun to log and visualize the output of COLMAP's sparse reconstruction. +# Background -[COLMAP](https://colmap.github.io/index.html) is a general-purpose Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline with a graphical and command-line interface. +COLMAP is a general-purpose Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline. +In this example, a short video clip has been processed offline using the COLMAP pipeline. +The processed data was then visualized using Rerun, which allowed for the visualization of individual camera frames, estimation of camera poses, and creation of point clouds over time. +By using COLMAP in combination with Rerun, a highly-detailed reconstruction of the scene depicted in the video was generated. -In this example a short video clip has been processed offline by the COLMAP pipeline, and we use Rerun to visualize the individual camera frames, estimated camera poses, and resulting point clouds over time. +# Used Rerun types +[`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d), [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d), [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`SeriesLine`](https://www.rerun.io/docs/reference/types/archetypes/series_line), [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar), [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole), [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), [`TextDocument`](https://www.rerun.io/docs/reference/types/archetypes/text_document) +# Logging and visualizing with Rerun + +The visualizations in this example were created with the following Rerun code: + +## Timelines + +All data logged using Rerun in the following sections is connected to a specific frame. +Rerun assigns a frame id to each piece of logged data, and these frame ids are associated with a [`timeline`](https://www.rerun.io/docs/concepts/timelines). + + ```python +rr.set_time_sequence("frame", frame_idx) + ``` + +## Images +The images are logged through the [`Image`](https://www.rerun.io/docs/reference/types/archetypes/image) to the `camera/image` entity. + +```python +rr.log("camera/image", rr.Image(rgb).compress(jpeg_quality=75)) +``` + +## Cameras +The images stem from pinhole cameras located in the 3D world. To visualize the images in 3D, the pinhole projection has +to be logged and the camera pose (this is often referred to as the intrinsics and extrinsics of the camera, +respectively). + +The [`Pinhole`](https://www.rerun.io/docs/reference/types/archetypes/pinhole) is logged to the `camera/image` entity and defines the intrinsics of the camera. +This defines how to go from the 3D camera frame to the 2D image plane. The extrinsics are logged as an +[`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) to the `camera` entity. + +```python +rr.log("camera", rr.Transform3D(translation=image.tvec, rotation=rr.Quaternion(xyzw=quat_xyzw), from_parent=True)) +``` + +```python +rr.log( + "camera/image", + rr.Pinhole( + resolution=[camera.width, camera.height], + focal_length=camera.params[:2], + principal_point=camera.params[2:], + ), +) +``` + +## Reprojection error +For each image a [`Scalar`](https://www.rerun.io/docs/reference/types/archetypes/scalar) archetype containing the average reprojection error of the keypoints is logged to the +`plot/avg_reproj_err` entity. + +```python +rr.log("plot/avg_reproj_err", rr.Scalar(np.mean(point_errors))) +``` + +## 2D points +The 2D image points that are used to triangulate the 3D points are visualized by logging as [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d) +to the `camera/image/keypoints` entity. Note that these keypoints are a child of the +`camera/image` entity, since the points should show in the image plane. + +```python +rr.log("camera/image/keypoints", rr.Points2D(visible_xys, colors=[34, 138, 167])) +``` + +## 3D points +The colored 3D points were added to the visualization by logging the [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetype to the `points` entity. +```python +rr.log("points", rr.Points3D(points, colors=point_colors), rr.AnyValues(error=point_errors)) +``` + +# Run the code +To run this example, make sure you have the Rerun repository checked out and the latest SDK installed: +```bash +# Setup +pip install --upgrade rerun-sdk # install the latest Rerun SDK +git clone git@github.com:rerun-io/rerun.git # Clone the repository +cd rerun +git checkout latest # Check out the commit matching the latest SDK release +``` +Install the necessary libraries specified in the requirements file: ```bash pip install -r examples/python/structure_from_motion/requirements.txt -python examples/python/structure_from_motion/main.py +``` +To experiment with the provided example, simply execute the main Python script: +```bash +python examples/python/structure_from_motion/main.py # run the example +``` +If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance: +```bash +python examples/python/structure_from_motion/main.py --help ``` diff --git a/examples/python/structure_from_motion/main.py b/examples/python/structure_from_motion/main.py index 421399afb04a..975beb22c385 100755 --- a/examples/python/structure_from_motion/main.py +++ b/examples/python/structure_from_motion/main.py @@ -19,13 +19,8 @@ from read_write_model import Camera, read_model from tqdm import tqdm -DATASET_DIR: Final = Path(os.path.dirname(__file__)) / "dataset" -DATASET_URL_BASE: Final = "https://storage.googleapis.com/rerun-example-datasets/colmap" -# When dataset filtering is turned on, drop views with less than this many valid points. -FILTER_MIN_VISIBLE: Final = 500 - DESCRIPTION = """ -# Sparse Reconstruction by COLMAP +# Sparse reconstruction by COLMAP This example was generated from the output of a sparse reconstruction done with COLMAP. [COLMAP](https://colmap.github.io/index.html) is a general-purpose Structure-from-Motion (SfM) and Multi-View Stereo @@ -34,47 +29,15 @@ In this example a short video clip has been processed offline by the COLMAP pipeline, and we use Rerun to visualize the individual camera frames, estimated camera poses, and resulting point clouds over time. -## How it was made The full source code for this example is available -[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/structure_from_motion/main.py). - -### Images -The images are logged through the [rr.Image archetype](https://www.rerun.io/docs/reference/types/archetypes/image) -to the [camera/image entity](recording://camera/image). - -### Cameras -The images stem from pinhole cameras located in the 3D world. To visualize the images in 3D, the pinhole projection has -to be logged and the camera pose (this is often referred to as the intrinsics and extrinsics of the camera, -respectively). - -The [rr.Pinhole archetype](https://www.rerun.io/docs/reference/types/archetypes/pinhole) is logged to -the [camera/image entity](recording://camera/image) and defines the intrinsics of the camera. This defines how to go -from the 3D camera frame to the 2D image plane. The extrinsics are logged as an -[rr.Transform3D archetype](https://www.rerun.io/docs/reference/types/archetypes/transform3d) to the -[camera entity](recording://camera). - -### Reprojection error -For each image a [rr.Scalar archetype](https://www.rerun.io/docs/reference/types/archetypes/scalar) -containing the average reprojection error of the keypoints is logged to the -[plot/avg_reproj_err entity](recording://plot/avg_reproj_err). - -### 2D points -The 2D image points that are used to triangulate the 3D points are visualized by logging -[rr.Points3D archetype](https://www.rerun.io/docs/reference/types/archetypes/points2d) -to the [camera/image/keypoints entity](recording://camera/image/keypoints). Note that these keypoints are a child of the -[camera/image entity](recording://camera/image), since the points should show in the image plane. - -### Colored 3D points -The colored 3D points were added to the scene by logging the -[rr.Points3D archetype](https://www.rerun.io/docs/reference/types/archetypes/points3d) -to the [points entity](recording://points): -```python -rr.log("points", rr.Points3D(points, colors=point_colors), rr.AnyValues(error=point_errors)) -``` -**Note:** we added some [custom per-point errors](recording://points) that you can see when you -hover over the points in the 3D view. +[on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/structure_from_motion). """.strip() +DATASET_DIR: Final = Path(os.path.dirname(__file__)) / "dataset" +DATASET_URL_BASE: Final = "https://storage.googleapis.com/rerun-example-datasets/colmap" +# When dataset filtering is turned on, drop views with less than this many valid points. +FILTER_MIN_VISIBLE: Final = 500 + def scale_camera(camera: Camera, resize: tuple[int, int]) -> tuple[Camera, npt.NDArray[np.float_]]: """Scale the camera intrinsics to match the resized image.""" diff --git a/examples/python/template/README.md b/examples/python/template/README.md index 391f11a6e133..ad0a63f0978e 100644 --- a/examples/python/template/README.md +++ b/examples/python/template/README.md @@ -1,16 +1,27 @@ +This is an example template. It is not a real example. You can duplicate the directory and use it as a starting point for writing a real example. +Put a short description at the top, like this. -This is an example template. It is not a real example. You can duplicate the directory and use it as a starting point for writing a real example. +## Used Rerun types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), … + +## Optional details here +… + +## Run the code ```bash pip install -r examples/python/template/requirements.txt diff --git a/examples/python/tfrecord_loader/README.md b/examples/python/tfrecord_loader/README.md index 169c781afd25..8d7ffe487943 100644 --- a/examples/python/tfrecord_loader/README.md +++ b/examples/python/tfrecord_loader/README.md @@ -1,5 +1,5 @@ +This example is a visual walkthrough of the paper "Learning to render novel views from wide-baseline stereo pairs". +All the visualizations were created by editing the original source code to log data with the Rerun SDK. + +## Visual paper walkthrough Novel view synthesis has made remarkable progress in recent years, but most methods require per-scene optimization on many images. In their [CVPR 2023 paper](https://openaccess.thecvf.com/content/CVPR2023/html/Du_Learning_To_Render_Novel_Views_From_Wide-Baseline_Stereo_Pairs_CVPR_2023_paper.html) Yilun Du et al. propose a method that works with just 2 views. I created a visual walkthrough of the work using the Rerun SDK. diff --git a/examples/rust/README.md b/examples/rust/README.md index 193e6e18b0ab..2d1e54cbc2f8 100644 --- a/examples/rust/README.md +++ b/examples/rust/README.md @@ -70,4 +70,4 @@ Demonstrates how to log: `cargo run -p dna` -This is what you'll build when following our [Getting Started guide](https://www.rerun.io/docs/getting-started/logging-rust). +This is what you'll build when following our [Getting Started guide](https://www.rerun.io/docs/getting-started/quick-start/rust). diff --git a/examples/rust/clock/Cargo.toml b/examples/rust/clock/Cargo.toml index d8d010536180..0846228b7e3c 100644 --- a/examples/rust/clock/Cargo.toml +++ b/examples/rust/clock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clock" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_data_loader/Cargo.toml b/examples/rust/custom_data_loader/Cargo.toml index ac5f22c5234d..c806cfc33c78 100644 --- a/examples/rust/custom_data_loader/Cargo.toml +++ b/examples/rust/custom_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_data_loader" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index acdca2beaa81..ac26a16f34a6 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_space_view" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_store_subscriber/Cargo.toml b/examples/rust/custom_store_subscriber/Cargo.toml index 541745d2e86f..c7a9caf5421e 100644 --- a/examples/rust/custom_store_subscriber/Cargo.toml +++ b/examples/rust/custom_store_subscriber/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_store_subscriber" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml index 66f92f5b5a2e..f82568b67453 100644 --- a/examples/rust/dna/Cargo.toml +++ b/examples/rust/dna/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dna" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/dna/README.md b/examples/rust/dna/README.md index 3d25f72f56a0..3b74b8c97db8 100644 --- a/examples/rust/dna/README.md +++ b/examples/rust/dna/README.md @@ -1,12 +1,12 @@ +Simple example of logging point and line primitives to draw a 3D helix. @@ -16,8 +16,6 @@ channel = "main" -Simple example of logging point and line primitives to draw a 3D helix. - ```bash cargo run --release ``` diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml index e8b37eae7596..d3e0eb7dc5ac 100644 --- a/examples/rust/extend_viewer_ui/Cargo.toml +++ b/examples/rust/extend_viewer_ui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extend_viewer_ui" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/external_data_loader/Cargo.toml b/examples/rust/external_data_loader/Cargo.toml index 7ee3d4e7565a..25c1e9b923cc 100644 --- a/examples/rust/external_data_loader/Cargo.toml +++ b/examples/rust/external_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rerun-loader-rust-file" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml index 3dea27f2945e..8961b27b5051 100644 --- a/examples/rust/incremental_logging/Cargo.toml +++ b/examples/rust/incremental_logging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "incremental_logging" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/incremental_logging/README.md b/examples/rust/incremental_logging/README.md index 143ab0b9d1f7..aed1e97ee619 100644 --- a/examples/rust/incremental_logging/README.md +++ b/examples/rust/incremental_logging/README.md @@ -1,11 +1,11 @@ +Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. @@ -15,8 +15,6 @@ thumbnail_dimensions = [480, 301] -Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames. - ```bash cargo run --release diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml index 0b81f4632c78..b899ff577f90 100644 --- a/examples/rust/log_file/Cargo.toml +++ b/examples/rust/log_file/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "log_file" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/log_file/README.md b/examples/rust/log_file/README.md index f07e5ca78459..fa09ccef67f0 100644 --- a/examples/rust/log_file/README.md +++ b/examples/rust/log_file/README.md @@ -2,7 +2,7 @@ title = "Log file example" --> -Demonstrates how to log any file from the SDK using the [`DataLoader`](https://www.rerun.io/docs/howto/open-any-file) machinery. +Demonstrates how to log any file from the SDK using the [`DataLoader`](https://www.rerun.io/docs/reference/data-loaders/overview) machinery. Usage: ```bash diff --git a/examples/rust/log_file/src/main.rs b/examples/rust/log_file/src/main.rs index caad40a10371..0ad21d312f5a 100644 --- a/examples/rust/log_file/src/main.rs +++ b/examples/rust/log_file/src/main.rs @@ -1,6 +1,6 @@ //! Demonstrates how to log any file from the SDK using the `DataLoader` machinery. //! -//! See for more information. +//! See for more information. //! //! Usage: //! ``` diff --git a/examples/rust/minimal/Cargo.toml b/examples/rust/minimal/Cargo.toml index 08ccde4af01a..775150905de4 100644 --- a/examples/rust/minimal/Cargo.toml +++ b/examples/rust/minimal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal/README.md b/examples/rust/minimal/README.md index a9bee0fd09a5..831536ed548d 100644 --- a/examples/rust/minimal/README.md +++ b/examples/rust/minimal/README.md @@ -14,7 +14,7 @@ thumbnail_dimensions = [480, 480] The simplest example of how to use Rerun, showing how to log a point cloud. -This is part of the [Quick Start guide](https://www.rerun.io/docs/getting-started/rust). +This is part of the [Quick Start guide](https://www.rerun.io/docs/getting-started/quick-start/rust). ```bash cargo run --release diff --git a/examples/rust/minimal_options/Cargo.toml b/examples/rust/minimal_options/Cargo.toml index f91c036bb215..53e96a6fbdfa 100644 --- a/examples/rust/minimal_options/Cargo.toml +++ b/examples/rust/minimal_options/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_options" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml index 7f1b6d795c99..5964192611e6 100644 --- a/examples/rust/minimal_serve/Cargo.toml +++ b/examples/rust/minimal_serve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_serve" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/objectron/Cargo.toml b/examples/rust/objectron/Cargo.toml index 331b7d51f225..ebc9e71124a8 100644 --- a/examples/rust/objectron/Cargo.toml +++ b/examples/rust/objectron/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "objectron" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/objectron/README.md b/examples/rust/objectron/README.md index ee7bd1b31f66..bcb8b327a422 100644 --- a/examples/rust/objectron/README.md +++ b/examples/rust/objectron/README.md @@ -1,12 +1,13 @@ +Example of using the Rerun SDK to log the [Objectron](https://github.com/google-research-datasets/Objectron) dataset. + @@ -15,8 +16,6 @@ build_args = ["--frames=100"] Objectron example screenshot -Example of using the Rerun SDK to log the [Objectron](https://github.com/google-research-datasets/Objectron) dataset. - > The Objectron dataset is a collection of short, object-centric video clips, which are accompanied by AR session metadata that includes camera poses, sparse point-clouds and characterization of the planar surfaces in the surrounding environment. ```bash diff --git a/examples/rust/raw_mesh/Cargo.toml b/examples/rust/raw_mesh/Cargo.toml index c9be9caa5ddb..4f0aac6254ee 100644 --- a/examples/rust/raw_mesh/Cargo.toml +++ b/examples/rust/raw_mesh/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "raw_mesh" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/raw_mesh/README.md b/examples/rust/raw_mesh/README.md index b59fbdbba380..8c7463598b74 100644 --- a/examples/rust/raw_mesh/README.md +++ b/examples/rust/raw_mesh/README.md @@ -1,10 +1,11 @@ +This example demonstrates how to use the Rerun SDK to log raw 3D meshes (so-called "triangle soups") and their transform hierarchy. Simple material properties are supported. + @@ -13,8 +14,6 @@ thumbnail_dimensions = [480, 480] -This example demonstrates how to use the Rerun SDK to log raw 3D meshes (so-called "triangle soups") and their transform hierarchy. Simple material properties are supported. - ```bash cargo run --release ``` diff --git a/examples/rust/revy/README.md b/examples/rust/revy/README.md new file mode 100644 index 000000000000..8caa95218dfe --- /dev/null +++ b/examples/rust/revy/README.md @@ -0,0 +1,91 @@ + + + + + + + + + + + +## Overview + +Revy is a proof-of-concept time-travel debugger for the [Bevy](https://github.com/bevyengine/bevy) game engine, built using [Rerun](https://github.com/rerun-io/rerun). + +Revy works by snapshotting diffs of the Bevy database every frame that are then logged into the Rerun database.\ +This allows you to inspect and visualize the state of the engine at any point in time, either in real-time or after the fact.\ +These recordings can then be shared to be replayed or e.g. attached to bug reports. + +For more information, check out the [Revy repository](https://github.com/rerun-io/revy). + +## Examples + + + + + + + + + + + + + + + + +
Breakout3D shapes Alien Cake Addict
+ Live demo + + + + + + + + + Live demo + + + + + + + + + Live demo + + + + + + + +
+ +## Usage + +1. [Install the Rerun Viewer](https://www.rerun.io/docs/getting-started/installing-viewer) (`0.15`). + +2. Add `revy` to your dependencies: + ```toml + revy = "0.15" # always matches the rerun version + ``` + +3. Initialize the `rerun` plugin: + ```rust + .add_plugins({ + let rec = revy::RecordingStreamBuilder::new("").spawn().unwrap(); + revy::RerunPlugin { rec } + }) + ``` + This will start a Rerun Viewer in the background and stream the recording data to it.\ + Check out the [`RecordingStreamBuilder`](https://docs.rs/rerun/latest/rerun/struct.RecordingStreamBuilder.html) docs for other options (saving to file, connecting to a remote viewer, etc). diff --git a/examples/rust/shared_recording/Cargo.toml b/examples/rust/shared_recording/Cargo.toml index 1110239a5e0a..ecc1e20b1e5a 100644 --- a/examples/rust/shared_recording/Cargo.toml +++ b/examples/rust/shared_recording/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared_recording" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/spawn_viewer/Cargo.toml b/examples/rust/spawn_viewer/Cargo.toml index 140a8c77f043..e83ba44db66d 100644 --- a/examples/rust/spawn_viewer/Cargo.toml +++ b/examples/rust/spawn_viewer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spawn_viewer" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/stdio/Cargo.toml b/examples/rust/stdio/Cargo.toml index 5379a7585c7c..fca0eb86e408 100644 --- a/examples/rust/stdio/Cargo.toml +++ b/examples/rust/stdio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stdio" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/template/Cargo.toml b/examples/rust/template/Cargo.toml index a83e38fbca9a..ece83f24a4c5 100644 --- a/examples/rust/template/Cargo.toml +++ b/examples/rust/template/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "template" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" diff --git a/examples/rust/template/README.md b/examples/rust/template/README.md index 790ee89e7342..76f87bda681b 100644 --- a/examples/rust/template/README.md +++ b/examples/rust/template/README.md @@ -1,15 +1,27 @@ +This is an example template. It is not a real example. You can duplicate the directory and use it as a starting point for writing a real example. +Put a short description at the top, like this. -This is an example template. It is not a real example. You can duplicate the directory and use it as a starting point for writing a real example. +## Used Rerun types +[`Image`](https://www.rerun.io/docs/reference/types/archetypes/image), … + +## More details here +… + +## Run the code ```bash cargo run --release -p template diff --git a/rerun_cpp/README.md b/rerun_cpp/README.md index 51ad1b8fd961..872b0520ac6c 100644 --- a/rerun_cpp/README.md +++ b/rerun_cpp/README.md @@ -7,7 +7,7 @@ The Rerun C++ SDK allows logging data to Rerun directly from C++. ## Getting started -Read the [getting started guide](https://www.rerun.io/docs/getting-started/cpp) on how to use the Rerun C++ SDK. +Read the [getting started guide](https://www.rerun.io/docs/getting-started/quick-start/cpp) on how to use the Rerun C++ SDK. ### Logging diff --git a/rerun_cpp/src/rerun/c/rerun.h b/rerun_cpp/src/rerun/c/rerun.h index 984853268c8d..b00e92bff746 100644 --- a/rerun_cpp/src/rerun/c/rerun.h +++ b/rerun_cpp/src/rerun/c/rerun.h @@ -268,7 +268,7 @@ typedef struct rr_error { /// /// This should match the string returned by `rr_version_string`. /// If not, the SDK's binary and the C header are out of sync. -#define RERUN_SDK_HEADER_VERSION "0.15.0-alpha.5" +#define RERUN_SDK_HEADER_VERSION "0.15.0" /// Returns a human-readable version string of the Rerun C SDK. /// diff --git a/rerun_cpp/src/rerun/components/instance_key.hpp b/rerun_cpp/src/rerun/components/instance_key.hpp index c3d92a4bcf82..c7593674b9c1 100644 --- a/rerun_cpp/src/rerun/components/instance_key.hpp +++ b/rerun_cpp/src/rerun/components/instance_key.hpp @@ -21,6 +21,13 @@ namespace arrow { namespace rerun::components { /// **Component**: A unique numeric identifier for each individual instance within a batch. + /// + /// Instance keys are automatically assigned by the `rerun` library and should not be set manually. + /// + /// The instance key is just the index of the instance within the batch, + /// i.e. the first point in a point cloud has `InstanceKey = 0`, the second `InstanceKey = 1`, and so on. + /// + /// We plan to remove the `InstanceKey` component in the near future. struct InstanceKey { uint64_t value; diff --git a/rerun_cpp/src/rerun/recording_stream.hpp b/rerun_cpp/src/rerun/recording_stream.hpp index a25de265d503..4646b44ebdcf 100644 --- a/rerun_cpp/src/rerun/recording_stream.hpp +++ b/rerun_cpp/src/rerun/recording_stream.hpp @@ -552,7 +552,7 @@ namespace rerun { /// This method blocks until either at least one `DataLoader` starts streaming data in /// or all of them fail. /// - /// See for more information. + /// See for more information. /// /// \param filepath Path to the file to be logged. /// \param entity_path_prefix What should the logged entity paths be prefixed with? @@ -577,7 +577,7 @@ namespace rerun { /// This method blocks until either at least one `DataLoader` starts streaming data in /// or all of them fail. /// - /// See for more information. + /// See for more information. /// /// \param filepath Path to the file to be logged. /// \param entity_path_prefix What should the logged entity paths be prefixed with? @@ -600,7 +600,7 @@ namespace rerun { /// This method blocks until either at least one `DataLoader` starts streaming data in /// or all of them fail. /// - /// See for more information. + /// See for more information. /// /// \param filepath Path to the file that the `contents` belong to. /// \param contents Contents to be logged. @@ -634,7 +634,7 @@ namespace rerun { /// This method blocks until either at least one `DataLoader` starts streaming data in /// or all of them fail. /// - /// See for more information. + /// See for more information. /// /// \param filepath Path to the file that the `contents` belong to. /// \param contents Contents to be logged. diff --git a/rerun_js/web-viewer-react/README.md b/rerun_js/web-viewer-react/README.md index 48269d84a909..e889006674b7 100644 --- a/rerun_js/web-viewer-react/README.md +++ b/rerun_js/web-viewer-react/README.md @@ -35,7 +35,7 @@ export default function App() { ``` The `rrd` in the snippet above should be a URL pointing to either: -- A hosted `.rrd` file, such as +- A hosted `.rrd` file, such as - A WebSocket connection to the SDK opened via the [`serve`](https://www.rerun.io/docs/reference/sdk-operating-modes#serve) API If `rrd` is not set, the viewer will display the same welcome screen as . diff --git a/rerun_js/web-viewer-react/package.json b/rerun_js/web-viewer-react/package.json index 06ce069a1df8..bad25ded3af3 100644 --- a/rerun_js/web-viewer-react/package.json +++ b/rerun_js/web-viewer-react/package.json @@ -1,6 +1,6 @@ { "name": "@rerun-io/web-viewer-react", - "version": "0.15.0-alpha.5", + "version": "0.15.0", "description": "Embed the Rerun web viewer in your React app", "licenses": [ { @@ -39,7 +39,7 @@ "tsconfig.json" ], "dependencies": { - "@rerun-io/web-viewer": "0.15.0-alpha.5", + "@rerun-io/web-viewer": "0.15.0", "@types/react": "^18.2.33", "react": "^18.2.0" }, diff --git a/rerun_js/web-viewer/README.md b/rerun_js/web-viewer/README.md index 65d058fa1091..0cd316290892 100644 --- a/rerun_js/web-viewer/README.md +++ b/rerun_js/web-viewer/README.md @@ -41,7 +41,7 @@ viewer.stop(); ``` The `rrd` in the snippet above should be a URL pointing to either: -- A hosted `.rrd` file, such as +- A hosted `.rrd` file, such as - A WebSocket connection to the SDK opened via the [`serve`](https://www.rerun.io/docs/reference/sdk-operating-modes#serve) API If `rrd` is not set, the viewer will display the same welcome screen as . diff --git a/rerun_js/web-viewer/index.js b/rerun_js/web-viewer/index.js index 4d23b0d07f0d..a16117d7c313 100644 --- a/rerun_js/web-viewer/index.js +++ b/rerun_js/web-viewer/index.js @@ -121,7 +121,7 @@ export class WebViewer { * The same viewer instance may be started multiple times. */ stop() { - if (this.#state !== "stopped") return; + if (this.#state === "stopped") return; this.#state = "stopped"; this.#canvas?.remove(); diff --git a/rerun_js/web-viewer/package.json b/rerun_js/web-viewer/package.json index c3841b2223c2..534416d3eca3 100644 --- a/rerun_js/web-viewer/package.json +++ b/rerun_js/web-viewer/package.json @@ -1,6 +1,6 @@ { "name": "@rerun-io/web-viewer", - "version": "0.15.0-alpha.5", + "version": "0.15.0", "description": "Embed the Rerun web viewer in your app", "licenses": [ { diff --git a/rerun_py/README.md b/rerun_py/README.md index e04ca13cd2c9..a212f095f9e6 100644 --- a/rerun_py/README.md +++ b/rerun_py/README.md @@ -31,8 +31,8 @@ rr.log("points3d", rr.Points3D(positions, colors=colors)) ## Resources * [Examples](https://www.rerun.io/examples) * [Python API docs](https://ref.rerun.io/docs/python) -* [Quick start](https://www.rerun.io/docs/getting-started/python) -* [Tutorial](https://www.rerun.io/docs/getting-started/logging-python) +* [Quick start](https://www.rerun.io/docs/getting-started/quick-start/python) +* [Tutorial](https://www.rerun.io/docs/getting-started/data-in/python) * [Troubleshooting](https://www.rerun.io/docs/getting-started/troubleshooting) * [Discord Server](https://discord.com/invite/Gcm8BbTaAj) diff --git a/rerun_py/rerun_sdk/rerun/_spawn.py b/rerun_py/rerun_sdk/rerun/_spawn.py new file mode 100644 index 000000000000..1d3b9b2979d0 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/_spawn.py @@ -0,0 +1,93 @@ +from __future__ import annotations + +import socket + + +# TODO(#4019): application-level handshake +def _check_for_existing_viewer(port: int) -> bool: + try: + # Try opening a connection to the port to see if something is there + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(1) + s.connect(("127.0.0.1", port)) + return True + except Exception: + # If the connection times out or is refused, the port is not open + return False + finally: + # Always close the socket to release resources + s.close() + + +def _spawn_viewer( + *, + port: int = 9876, + memory_limit: str = "75%", +) -> None: + """ + Internal helper to spawn a Rerun Viewer, listening on the given port. + + Blocks until the viewer is ready to accept connections. + + Used by [rerun.spawn][] + + Parameters + ---------- + port: + The port to listen on. + memory_limit: + An upper limit on how much memory the Rerun Viewer should use. + When this limit is reached, Rerun will drop the oldest data. + Example: `16GB` or `50%` (of system total). + + """ + + import os + import subprocess + import sys + from time import sleep + + # Let the spawned rerun process know it's just an app + new_env = os.environ.copy() + # NOTE: If `_RERUN_TEST_FORCE_SAVE` is set, all recording streams will write to disk no matter + # what, thus spawning a viewer is pointless (and probably not intended). + if os.environ.get("_RERUN_TEST_FORCE_SAVE") is not None: + return + new_env["RERUN_APP_ONLY"] = "true" + + # sys.executable: the absolute path of the executable binary for the Python interpreter + python_executable = sys.executable + if python_executable is None: + python_executable = "python3" + + # TODO(jleibs): More options to opt out of this behavior. + if _check_for_existing_viewer(port): + # Using print here for now rather than `logging.info` because logging.info isn't + # visible by default. + # + # If we spawn a process it's going to send a bunch of stuff to stdout anyways. + print(f"Found existing process on port {port}. Trying to connect.") + else: + # start_new_session=True ensures the spawned process does NOT die when + # we hit ctrl-c in the terminal running the parent Python process. + subprocess.Popen( + [ + python_executable, + "-c", + "import rerun_bindings; rerun_bindings.main()", + f"--port={port}", + f"--memory-limit={memory_limit}", + "--expect-data-soon", + ], + env=new_env, + start_new_session=True, + ) + + # Give the newly spawned Rerun Viewer some time to bind. + # + # NOTE: The timeout only covers the TCP handshake: if no process is bound to that address + # at all, the connection will fail immediately, irrelevant of the timeout configuration. + # For that reason we use an extra loop. + for _ in range(0, 5): + _check_for_existing_viewer(port) + sleep(0.1) diff --git a/rerun_py/rerun_sdk/rerun/any_value.py b/rerun_py/rerun_sdk/rerun/any_value.py index 8bd445081dd9..75396f74eed7 100644 --- a/rerun_py/rerun_sdk/rerun/any_value.py +++ b/rerun_py/rerun_sdk/rerun/any_value.py @@ -102,7 +102,8 @@ class AnyValues(AsComponents): ```python rr.log( "any_values", rr.AnyValues( - foo=[1.2, 3.4, 5.6], bar="hello world", + confidence=[1.2, 3.4, 5.6], + description="Bla bla bla…", ), ) ``` diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index fe1c693a571d..281b28ae9792 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -5,6 +5,7 @@ import rerun_bindings as bindings +from .._spawn import _spawn_viewer from ..datatypes import EntityPathLike, Utf8ArrayLike, Utf8Like from ..memory import MemoryRecording from ..notebook import as_html @@ -456,6 +457,49 @@ def _repr_html_(self) -> Any: """IPython interface to conversion to html.""" return as_html(blueprint=self) + def connect( + self, + application_id: str, + *, + addr: str | None = None, + make_active: bool = True, + make_default: bool = True, + ) -> None: + """ + Connect to a remote Rerun Viewer on the given ip:port and send this blueprint. + + Parameters + ---------- + application_id: + The application ID to use for this blueprint. This must match the application ID used + when initiating rerun for any data logging you wish to associate with this blueprint. + addr: + The ip:port to connect to + make_active: + Immediately make this the active blueprint for the associated `app_id`. + Note that setting this to `false` does not mean the blueprint may not still end + up becoming active. In particular, if `make_default` is true and there is no other + currently active blueprint. + make_default: + Make this the default blueprint for the `app_id`. + The default blueprint will be used as the template when the user resets the + blueprint for the app. It will also become the active blueprint if no other + blueprint is currently active. + + """ + blueprint_stream = RecordingStream( + bindings.new_blueprint( + application_id=application_id, + make_default=False, + make_thread_default=False, + default_enabled=True, + ) + ) + blueprint_stream.set_time_sequence("blueprint", 0) # type: ignore[attr-defined] + self._log_to_stream(blueprint_stream) + + bindings.connect_blueprint(addr, make_active, make_default, blueprint_stream.to_native()) + def save(self, application_id: str, path: str | None = None) -> None: """ Save this blueprint to a file. Rerun recommends the `.rbl` suffix. @@ -473,7 +517,7 @@ def save(self, application_id: str, path: str | None = None) -> None: if path is None: path = f"{application_id}.rbl" - blueprint_file = RecordingStream( + blueprint_stream = RecordingStream( bindings.new_blueprint( application_id=application_id, make_default=False, @@ -481,10 +525,30 @@ def save(self, application_id: str, path: str | None = None) -> None: default_enabled=True, ) ) - blueprint_file.set_time_sequence("blueprint", 0) # type: ignore[attr-defined] - self._log_to_stream(blueprint_file) + blueprint_stream.set_time_sequence("blueprint", 0) # type: ignore[attr-defined] + self._log_to_stream(blueprint_stream) + + bindings.save_blueprint(path, blueprint_stream.to_native()) + + def spawn(self, application_id: str, port: int = 9876, memory_limit: str = "75%") -> None: + """ + Spawn a Rerun viewer with this blueprint. - bindings.save_blueprint(path, blueprint_file.to_native()) + Parameters + ---------- + application_id: + The application ID to use for this blueprint. This must match the application ID used + when initiating rerun for any data logging you wish to associate with this blueprint. + port: + The port to listen on. + memory_limit: + An upper limit on how much memory the Rerun Viewer should use. + When this limit is reached, Rerun will drop the oldest data. + Example: `16GB` or `50%` (of system total). + + """ + _spawn_viewer(port=port, memory_limit=memory_limit) + self.connect(application_id=application_id, addr=f"127.0.0.1:{port}") BlueprintLike = Union[Blueprint, SpaceView, Container] @@ -508,8 +572,6 @@ def create_in_memory_blueprint(*, application_id: str, blueprint: BlueprintLike) blueprint_stream = RecordingStream( bindings.new_blueprint( application_id=application_id, - # Generate a new id every time so we don't append to overwrite previous blueprints. - blueprint_id=str(uuid.uuid4()), make_default=False, make_thread_default=False, default_enabled=True, diff --git a/rerun_py/rerun_sdk/rerun/components/instance_key.py b/rerun_py/rerun_sdk/rerun/components/instance_key.py index 7fc6df0e43fc..edb361d45a58 100644 --- a/rerun_py/rerun_sdk/rerun/components/instance_key.py +++ b/rerun_py/rerun_sdk/rerun/components/instance_key.py @@ -20,7 +20,16 @@ @define(init=False) class InstanceKey(InstanceKeyExt): - """**Component**: A unique numeric identifier for each individual instance within a batch.""" + """ + **Component**: A unique numeric identifier for each individual instance within a batch. + + Instance keys are automatically assigned by the `rerun` library and should not be set manually. + + The instance key is just the index of the instance within the batch, + i.e. the first point in a point cloud has `InstanceKey = 0`, the second `InstanceKey = 1`, and so on. + + We plan to remove the `InstanceKey` component in the near future. + """ def __init__(self: Any, value: InstanceKeyLike): """Create a new instance of the InstanceKey component.""" diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index b8d406082f06..7d3c728e8957 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -2,13 +2,14 @@ import logging import pathlib -import socket import rerun_bindings as bindings # type: ignore[attr-defined] from rerun.blueprint.api import BlueprintLike, create_in_memory_blueprint from rerun.recording_stream import RecordingStream, get_application_id +from ._spawn import _spawn_viewer + # --- Sinks --- @@ -300,22 +301,6 @@ def send_blueprint( bindings.send_blueprint(blueprint_storage, make_active, make_default, recording=recording) -# TODO(#4019): application-level handshake -def _check_for_existing_viewer(port: int) -> bool: - try: - # Try opening a connection to the port to see if something is there - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(1) - s.connect(("127.0.0.1", port)) - return True - except Exception: - # If the connection times out or is refused, the port is not open - return False - finally: - # Always close the socket to release resources - s.close() - - def spawn( *, port: int = 9876, @@ -358,55 +343,7 @@ def spawn( logging.warning("Rerun is disabled - spawn() call ignored.") return - import os - import subprocess - import sys - from time import sleep - - # Let the spawned rerun process know it's just an app - new_env = os.environ.copy() - # NOTE: If `_RERUN_TEST_FORCE_SAVE` is set, all recording streams will write to disk no matter - # what, thus spawning a viewer is pointless (and probably not intended). - if os.environ.get("_RERUN_TEST_FORCE_SAVE") is not None: - return - new_env["RERUN_APP_ONLY"] = "true" - - # sys.executable: the absolute path of the executable binary for the Python interpreter - python_executable = sys.executable - if python_executable is None: - python_executable = "python3" - - # TODO(jleibs): More options to opt out of this behavior. - if _check_for_existing_viewer(port): - # Using print here for now rather than `logging.info` because logging.info isn't - # visible by default. - # - # If we spawn a process it's going to send a bunch of stuff to stdout anyways. - print(f"Found existing process on port {port}. Trying to connect.") - else: - # start_new_session=True ensures the spawned process does NOT die when - # we hit ctrl-c in the terminal running the parent Python process. - subprocess.Popen( - [ - python_executable, - "-c", - "import rerun_bindings; rerun_bindings.main()", - f"--port={port}", - f"--memory-limit={memory_limit}", - "--expect-data-soon", - ], - env=new_env, - start_new_session=True, - ) - - # Give the newly spawned Rerun Viewer some time to bind. - # - # NOTE: The timeout only covers the TCP handshake: if no process is bound to that address - # at all, the connection will fail immediately, irrelevant of the timeout configuration. - # For that reason we use an extra loop. - for _ in range(0, 5): - _check_for_existing_viewer(port) - sleep(0.1) + _spawn_viewer(port=port, memory_limit=memory_limit) if connect: _connect(f"127.0.0.1:{port}", recording=recording, default_blueprint=default_blueprint) diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index 338e4d6c6bbb..8dd6e1f64ef3 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -163,6 +163,7 @@ fn rerun_bindings(_py: Python<'_>, m: &PyModule) -> PyResult<()> { // sinks m.add_function(wrap_pyfunction!(is_enabled, m)?)?; m.add_function(wrap_pyfunction!(connect, m)?)?; + m.add_function(wrap_pyfunction!(connect_blueprint, m)?)?; m.add_function(wrap_pyfunction!(save, m)?)?; m.add_function(wrap_pyfunction!(save_blueprint, m)?)?; m.add_function(wrap_pyfunction!(stdout, m)?)?; @@ -274,7 +275,6 @@ fn new_recording( #[pyfunction] #[pyo3(signature = ( application_id, - blueprint_id=None, make_default=true, make_thread_default=true, default_enabled=true, @@ -282,16 +282,13 @@ fn new_recording( fn new_blueprint( py: Python<'_>, application_id: String, - blueprint_id: Option, make_default: bool, make_thread_default: bool, default_enabled: bool, ) -> PyResult { - let blueprint_id = if let Some(blueprint_id) = blueprint_id { - StoreId::from_string(StoreKind::Blueprint, blueprint_id) - } else { - default_store_id(py, StoreKind::Blueprint, &application_id) - }; + // We don't currently support additive blueprints, so we should always be generating a new, unique + // blueprint id to avoid collisions. + let blueprint_id = StoreId::random(StoreKind::Blueprint); let mut batcher_config = re_log_types::DataTableBatcherConfig::from_env().unwrap_or_default(); let on_release = |chunk| { @@ -588,6 +585,48 @@ fn connect( Ok(()) } +#[pyfunction] +#[pyo3(signature = (addr, make_active, make_default, blueprint_stream))] +/// Special binding for directly sending a blueprint stream to a connection. +fn connect_blueprint( + addr: Option, + make_active: bool, + make_default: bool, + blueprint_stream: &PyRecordingStream, + py: Python<'_>, +) -> PyResult<()> { + let addr = if let Some(addr) = addr { + addr.parse()? + } else { + rerun::default_server_addr() + }; + + if let Some(blueprint_id) = (*blueprint_stream).store_info().map(|info| info.store_id) { + // The call to save, needs to flush. + // Release the GIL in case any flushing behavior needs to cleanup a python object. + py.allow_threads(|| { + // Flush all the pending blueprint messages before we include the Ready message + blueprint_stream.flush_blocking(); + + let activation_cmd = BlueprintActivationCommand { + blueprint_id, + make_active, + make_default, + }; + + blueprint_stream.record_msg(activation_cmd.into()); + + blueprint_stream.connect_opts(addr, None); + flush_garbage_queue(); + }); + Ok(()) + } else { + Err(PyRuntimeError::new_err( + "Blueprint stream has no store info".to_owned(), + )) + } +} + #[pyfunction] #[pyo3(signature = (path, default_blueprint = None, recording = None))] fn save( @@ -633,14 +672,14 @@ fn save_blueprint( blueprint_stream: &PyRecordingStream, py: Python<'_>, ) -> PyResult<()> { - if let Some(recording_id) = (*blueprint_stream).store_info().map(|info| info.store_id) { + if let Some(blueprint_id) = (*blueprint_stream).store_info().map(|info| info.store_id) { // The call to save, needs to flush. // Release the GIL in case any flushing behavior needs to cleanup a python object. py.allow_threads(|| { // Flush all the pending blueprint messages before we include the Ready message blueprint_stream.flush_blocking(); - let activation_cmd = BlueprintActivationCommand::make_active(recording_id.clone()); + let activation_cmd = BlueprintActivationCommand::make_active(blueprint_id.clone()); blueprint_stream.record_msg(activation_cmd.into()); diff --git a/scripts/ci/crates.py b/scripts/ci/crates.py index 6aa20992b0f3..c994adea6e34 100755 --- a/scripts/ci/crates.py +++ b/scripts/ci/crates.py @@ -88,6 +88,8 @@ def get_workspace_crates(root: dict[str, Any]) -> dict[str, Crate]: for pattern in root["workspace"]["members"]: for crate in [member for member in glob(pattern) if os.path.isdir(member)]: crate_path = Path(crate) + if not os.path.exists(crate_path / "Cargo.toml"): + continue manifest_text = (crate_path / "Cargo.toml").read_text() manifest: dict[str, Any] = tomlkit.parse(manifest_text) crates[manifest["package"]["name"]] = Crate(manifest, crate_path) diff --git a/scripts/lint.py b/scripts/lint.py index b4a83b447535..ed64f4002d56 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -38,7 +38,6 @@ double_the = re.compile(r"\bthe the\b") double_word = re.compile(r" ([a-z]+) \1[ \.]") - Frontmatter = Dict[str, Any] @@ -191,14 +190,14 @@ def lint_line( if not is_in_docstring: if m := re.search( - r'(RecordingStreamBuilder::new|\.init|RecordingStream)\("(\w*)', + r'(RecordingStreamBuilder::new|\.init|RecordingStream)\("([^"]*)', line, ) or re.search( r'(rr.script_setup)\(args, "(\w*)', line, ): app_id = m.group(2) - if not app_id.startswith("rerun_example_"): + if not app_id.startswith("rerun_example_") and not app_id == "": return f"All examples should have an app_id starting with 'rerun_example_'. Found '{app_id}'" # Methods that return Self should usually be marked #[inline] or #[inline(always)] since they indicate a builder. @@ -655,15 +654,27 @@ def is_acronym_or_pascal_case(s: str) -> bool: return " ".join(new_words) -def lint_markdown(lines_in: list[str]) -> tuple[list[str], list[str]]: +def lint_markdown(filepath: str, lines_in: list[str]) -> tuple[list[str], list[str]]: """Only for .md files.""" errors = [] lines_out = [] + in_example_readme = "/examples/python/" in filepath and filepath.endswith("README.md") + + in_code_block = False + in_frontmatter = False for line_nr, line in enumerate(lines_in): line_nr = line_nr + 1 + if line.startswith("```"): + in_code_block = not in_code_block + + if line.startswith(""): + in_frontmatter = False + # Check the casing on markdown headers if m := re.match(r"(\#+ )(.*)", line): new_header = fix_header_casing(m.group(2)) @@ -678,6 +689,13 @@ def lint_markdown(lines_in: list[str]) -> tuple[list[str], list[str]]: errors.append(f"{line_nr}: Titles should NOT be title cased. This should be '{new_title}'.") line = f'title = "{new_title}"\n' + if in_example_readme and not in_code_block and not in_frontmatter: + # Check that

is not used in example READMEs + if line.startswith("#") and not line.startswith("##"): + errors.append( + f"{line_nr}: Do not use top-level headers in example READMEs, they are reserved for page title." + ) + lines_out.append(line) return errors, lines_out @@ -749,14 +767,17 @@ def lint_frontmatter(filepath: str, content: str) -> list[str]: if not filepath.endswith(".md"): return errors - fm = load_frontmatter(content) + try: + fm = load_frontmatter(content) + except Exception as e: + errors.append(f"Error parsing frontmatter: {e}") + return errors + if fm is None: return [] errors += lint_example_description(filepath, fm) - # TODO(ab): check for missing fields (when descriptions are populated everywhere) - return errors @@ -819,7 +840,7 @@ def error(self, message: str, *, line_nr: int | None = None, index: int | None = if line_nr is None: return f"{self.path}:{message}" else: - return f"{self.path}:{line_nr+1}: {message}" + return f"{self.path}:{line_nr + 1}: {message}" def lint_file(filepath: str, args: Any) -> int: @@ -865,7 +886,7 @@ def lint_file(filepath: str, args: Any) -> int: source.rewrite(lines_out) if filepath.endswith(".md") and args.extra: - errors, lines_out = lint_markdown(source.lines) + errors, lines_out = lint_markdown(filepath, source.lines) for error in errors: print(source.error(error)) diff --git a/tests/python/blueprint/spawn_blueprint.py b/tests/python/blueprint/spawn_blueprint.py new file mode 100644 index 000000000000..8c08a60d1910 --- /dev/null +++ b/tests/python/blueprint/spawn_blueprint.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +import rerun.blueprint as rrb + +blueprint = rrb.Blueprint( + rrb.Spatial3DView(origin="/test1"), + rrb.TimePanel(expanded=False), + rrb.SelectionPanel(expanded=False), + rrb.BlueprintPanel(expanded=False), +) + +blueprint.spawn("rerun_example_blueprint_test") diff --git a/tests/python/release_checklist/check_1d_tensor_data.py b/tests/python/release_checklist/check_1d_tensor_data.py new file mode 100644 index 000000000000..ed334dede2b9 --- /dev/null +++ b/tests/python/release_checklist/check_1d_tensor_data.py @@ -0,0 +1,56 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import numpy as np +import rerun as rr + +README = """ +# 1D Image/Tensor/BarChart + +This checks the different ways 1D arrays can be visualized. + +### Actions + +You should see: +* a tensor view with 1D data +* an image view with a 1D image +* a bar chart + +Bonus actions: +* use the ui to create a tensor/bar-chart with each of the entities no matter how it was logged + * TODO(#5847): Right now tensors & bar charts can not be reinterpreted as 2D images. + In this example, image is correctly not suggested for the `tensor` and `image` entities, + since they are of 1D shape, but this would be relevant if they were 1xN or Nx1. + +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def log_1d_data() -> None: + x = np.linspace(0.0, 100.0, 100) + rr.log("tensor", rr.Tensor(x)) + rr.log("barchart", rr.BarChart(x)) + # We're not allowing "real" 1D here and force users to be explicit about width/height + rr.log("image", rr.Image(np.reshape(x, (1, 100)))) + + +def run(args: Namespace) -> None: + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + log_readme() + log_1d_data() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) diff --git a/tests/python/release_checklist/check_context_menu_multi_selection.py b/tests/python/release_checklist/check_context_menu_multi_selection.py index b7879fce72cf..4fb1f86d5859 100644 --- a/tests/python/release_checklist/check_context_menu_multi_selection.py +++ b/tests/python/release_checklist/check_context_menu_multi_selection.py @@ -23,7 +23,7 @@ Expand all Collapse all - Move to new Container + Move to new container ---------------------------------------------------------- + Vertical container Hide all Remove @@ -31,7 +31,7 @@ Expand all Collapse all - Move to new Container + Move to new container ---------------------------------------------------------- + Viewport Hide all @@ -49,7 +49,7 @@ Expand all Collapse all - Add to new Space View + Add to new space view ---------------------------------------------------------- + some component Hide all diff --git a/tests/python/release_checklist/check_context_menu_single_selection.py b/tests/python/release_checklist/check_context_menu_single_selection.py index ecb9ee87c3c0..0408aef472b6 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection.py +++ b/tests/python/release_checklist/check_context_menu_single_selection.py @@ -24,13 +24,13 @@ 'group/' entity Expand all Collapse all - Add to new Space View + Add to new space view ------------------------------------------------- Component ================================================= ``` -#### Tile Title UI +#### Tile title UI - Multi-select the 3D space view and the Vertical container in the Blueprint tree. - Right-click on the 3D space view tab title: @@ -50,12 +50,12 @@ Clone - Move to new Container + Move to new container ================================================= ``` -#### Container Selection Panel child list +#### Container selection panel child list - Select the Vertical container. - In the selection panel, right-click on the 3D space view, and check that: diff --git a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py index caea1f292863..56e079154468 100644 --- a/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py +++ b/tests/python/release_checklist/check_context_menu_single_selection_blueprint_tree.py @@ -23,8 +23,8 @@ Viewport Expand all Collapse all - Add Container - Add Space View + Add container + Add space view ------------------------------------------------------------------ Container Hide (or Show, depending on visibility) Remove @@ -32,12 +32,12 @@ Expand all Collapse all - Add Container - Add Space View + Add container + Add space view - Move to new Container + Move to new container ------------------------------------------------------------------ -Space View Hide (or Show, depending on visibility) +Space view Hide (or Show, depending on visibility) Remove Expand all @@ -45,20 +45,20 @@ Clone - Move to new Container + Move to new container ------------------------------------------------------------------ -'group' Data Result Hide (or Show, depending on visibility) +'group' data result Hide (or Show, depending on visibility) Remove Expand all Collapse all - Add to new Space View + Add to new space view ------------------------------------------------------------------ -'boxes3d' Data Result Hide (or Show, depending on visibility) +'boxes3d' data result Hide (or Show, depending on visibility) Remove - Add to new Space View + Add to new space view ``` """ diff --git a/tests/python/release_checklist/check_draw_order.py b/tests/python/release_checklist/check_draw_order.py index 0404ccb5cd97..2150e17c7497 100644 --- a/tests/python/release_checklist/check_draw_order.py +++ b/tests/python/release_checklist/check_draw_order.py @@ -14,14 +14,14 @@ This checks whether the draw order correctly determines the layering of 2D content. ### Action -You should see a single 2D space view with the following features: +You should see a single 2D view with the following elements overdrawing each other back to front: - Gray background image -- On top of the background a green/red gradient image -- On top of that a blue (slightly transparent) blue square -- On top of the blue square a white square. *Nothing* is overlapping the white square! -- Between the gradient and the blue square rectangle (Box2D) -- Lines *behind* the rectangle -- Regular raster of points *in front* of the rectangle (unbroken by the rectangle) +- Green to red gradient image +- Blue (slightly transparent) square +- Red line strip (zig-zagging) +- Black Rectangle (Box2D) +- Raster of points (visibly overlaps the rectangle!) +- White square """ @@ -33,7 +33,7 @@ def run_2d_layering() -> None: rr.set_time_seconds("sim_time", 1) # Large gray background. - img = np.full((512, 512), 64, dtype="uint8") + img = np.full((256, 512), 64, dtype="uint8") rr.log("2d_layering/background", rr.Image(img, draw_order=0.0)) # Smaller gradient in the middle. @@ -47,31 +47,28 @@ def run_2d_layering() -> None: img = np.full((192, 192, 3), (0, 0, 255), dtype="uint8") rr.log("2d_layering/middle_blue", rr.Image(img, draw_order=1.0)) - # Small white on top. - img = np.full((128, 128), 255, dtype="uint8") - rr.log("2d_layering/top", rr.Image(img, draw_order=2.0)) - - # Rectangle in between the top and the middle. rr.log( - "2d_layering/rect_between_top_and_middle", - rr.Boxes2D(array=[64, 64, 256, 256], draw_order=1.5, array_format=rr.Box2DFormat.XYWH), + "2d_layering/lines_behind_rect", + rr.LineStrips2D([(i * 20, i % 2 * 100 + 70) for i in range(20)], draw_order=1.25, colors=0xFF0000FF), ) - # Lines behind the rectangle. rr.log( - "2d_layering/lines_behind_rect", - rr.LineStrips2D([(i * 20, i % 2 * 100 + 100) for i in range(20)], draw_order=1.25), + "2d_layering/rect_between_top_and_middle", + rr.Boxes2D(array=[64, 32, 256, 128], draw_order=1.5, array_format=rr.Box2DFormat.XYWH, colors=0), ) - # And some points in front of the rectangle. rr.log( "2d_layering/points_between_top_and_middle", rr.Points2D( - [(32.0 + int(i / 16) * 16.0, 64.0 + (i % 16) * 16.0) for i in range(16 * 16)], + [(32.0 + int(i / 16) * 16.0, 32.0 + (i % 16) * 16.0) for i in range(16 * 16)], draw_order=1.51, ), ) + # Small white square on top. + img = np.full((128, 128), 255, dtype="uint8") + rr.log("2d_layering/top", rr.Image(img, draw_order=2.0)) + def run(args: Namespace) -> None: rr.script_setup( diff --git a/tests/python/release_checklist/main.py b/tests/python/release_checklist/main.py old mode 100644 new mode 100755 index 9c4ea5199d29..b34ba2a7605a --- a/tests/python/release_checklist/main.py +++ b/tests/python/release_checklist/main.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 from __future__ import annotations import argparse diff --git a/tests/rust/plot_dashboard_stress/Cargo.toml b/tests/rust/plot_dashboard_stress/Cargo.toml index c939b36f9c51..87b30691b2a9 100644 --- a/tests/rust/plot_dashboard_stress/Cargo.toml +++ b/tests/rust/plot_dashboard_stress/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "plot_dashboard_stress" -version = "0.15.0-alpha.5" +version = "0.16.0-alpha.1+dev" edition = "2021" rust-version = "1.74" license = "MIT OR Apache-2.0" From e6c116b126b29aea70158d21d72a2ef2ad4480d1 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Wed, 10 Apr 2024 08:11:29 +0200 Subject: [PATCH 236/508] Allow to call find_package(rerun_sdk) two or more times (#5886) Fix https://github.com/rerun-io/rerun/issues/5885 . ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5886) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5886?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5886?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5886) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- rerun_cpp/Config.cmake.in | 50 +++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/rerun_cpp/Config.cmake.in b/rerun_cpp/Config.cmake.in index d1cac77cd438..c093c4432b0b 100644 --- a/rerun_cpp/Config.cmake.in +++ b/rerun_cpp/Config.cmake.in @@ -5,16 +5,18 @@ include("${CMAKE_CURRENT_LIST_DIR}/rerun_sdkTargets.cmake") set(RERUN_LIB_DIR "${CMAKE_CURRENT_LIST_DIR}/../..") if(@RERUN_INSTALL_RERUN_C@) - # Setup `rerun_c` (imported libraries can't be exported!) - add_library(rerun_c STATIC IMPORTED GLOBAL) - get_filename_component(RERUN_C_LIB_NAME "@RERUN_C_LIB_LOCATION@" NAME) - set_target_properties(rerun_c PROPERTIES IMPORTED_LOCATION "${RERUN_LIB_DIR}/${RERUN_C_LIB_NAME}") - if(APPLE) - target_link_libraries(rerun_c INTERFACE "-framework CoreFoundation" "-framework IOKit") - elseif(UNIX) # if(LINUX) # CMake 3.25 - target_link_libraries(rerun_c INTERFACE "-lm -ldl -pthread") - elseif(WIN32) - target_link_libraries(rerun_c INTERFACE ws2_32.dll Bcrypt.dll Userenv.dll ntdll.dll) + if(NOT TARGET rerun_c) + # Setup `rerun_c` (imported libraries can't be exported!) + add_library(rerun_c STATIC IMPORTED GLOBAL) + get_filename_component(RERUN_C_LIB_NAME "@RERUN_C_LIB_LOCATION@" NAME) + set_target_properties(rerun_c PROPERTIES IMPORTED_LOCATION "${RERUN_LIB_DIR}/${RERUN_C_LIB_NAME}") + if(APPLE) + target_link_libraries(rerun_c INTERFACE "-framework CoreFoundation" "-framework IOKit") + elseif(UNIX) # if(LINUX) # CMake 3.25 + target_link_libraries(rerun_c INTERFACE "-lm -ldl -pthread") + elseif(WIN32) + target_link_libraries(rerun_c INTERFACE ws2_32.dll Bcrypt.dll Userenv.dll ntdll.dll) + endif() endif() endif() @@ -23,15 +25,19 @@ endif() if(@RERUN_DOWNLOAD_AND_BUILD_ARROW@ AND NOT @RERUN_ARROW_LINK_SHARED@) message(STATUS "Rerun is using bundled arrow library.") - add_library(rerun_arrow_target STATIC IMPORTED GLOBAL) - get_filename_component(RERUN_ARROW_LIB_NAME "@RERUN_ARROW_LIBRARY_FILE@" NAME) - set_target_properties(rerun_arrow_target PROPERTIES IMPORTED_LOCATION "${RERUN_LIB_DIR}/${RERUN_ARROW_LIB_NAME}") + if(NOT TARGET rerun_arrow_target) + add_library(rerun_arrow_target STATIC IMPORTED GLOBAL) + get_filename_component(RERUN_ARROW_LIB_NAME "@RERUN_ARROW_LIBRARY_FILE@" NAME) + set_target_properties(rerun_arrow_target PROPERTIES IMPORTED_LOCATION "${RERUN_LIB_DIR}/${RERUN_ARROW_LIB_NAME}") + endif() # We have to explicitly opt in the arrow bundled dependencies, otherwise we're missing the symbols for mimalloc. - add_library(arrow_targetBundledDeps STATIC IMPORTED) - get_filename_component(RERUN_ARROW_DEPS_LIB_NAME "@RERUN_ARROW_BUNDLED_DEPENDENCIES_FILE@" NAME) - set_target_properties(arrow_targetBundledDeps PROPERTIES IMPORTED_LOCATION "${RERUN_LIB_DIR}/${RERUN_ARROW_DEPS_LIB_NAME}") - target_link_libraries(rerun_arrow_target INTERFACE arrow_targetBundledDeps) + if(NOT TARGET arrow_targetBundledDeps) + add_library(arrow_targetBundledDeps STATIC IMPORTED) + get_filename_component(RERUN_ARROW_DEPS_LIB_NAME "@RERUN_ARROW_BUNDLED_DEPENDENCIES_FILE@" NAME) + set_target_properties(arrow_targetBundledDeps PROPERTIES IMPORTED_LOCATION "${RERUN_LIB_DIR}/${RERUN_ARROW_DEPS_LIB_NAME}") + target_link_libraries(rerun_arrow_target INTERFACE arrow_targetBundledDeps) + endif() else() if(@RERUN_DOWNLOAD_AND_BUILD_ARROW@ AND @RERUN_ARROW_LINK_SHARED@) message(WARNING @@ -45,9 +51,11 @@ else() message(STATUS "Rerun is using a system installed libArrow.") - if(@RERUN_ARROW_LINK_SHARED@) - add_library(rerun_arrow_target ALIAS Arrow::arrow_shared) - else() - add_library(rerun_arrow_target ALIAS Arrow::arrow_static) + if(NOT TARGET rerun_arrow_target) + if(@RERUN_ARROW_LINK_SHARED@) + add_library(rerun_arrow_target ALIAS Arrow::arrow_shared) + else() + add_library(rerun_arrow_target ALIAS Arrow::arrow_static) + endif() endif() endif() From 1c01b687194c4ad87db836cf9da5d4757282194a Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 10 Apr 2024 08:25:23 +0200 Subject: [PATCH 237/508] Add notebook fake-check to checklist (#5881) Never be bitten again... maybe ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5881) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5881?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5881?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5881) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../release_checklist/check_notebook.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/python/release_checklist/check_notebook.py diff --git a/tests/python/release_checklist/check_notebook.py b/tests/python/release_checklist/check_notebook.py new file mode 100644 index 000000000000..2de6f879ed29 --- /dev/null +++ b/tests/python/release_checklist/check_notebook.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr +import rerun.blueprint as rrb + +README = """ +# Notebook + +Make sure to check that notebooks (both local and Google Colab) work properly with the latest release candidate. +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def run(args: Namespace) -> None: + rr.script_setup( + args, + f"{os.path.basename(__file__)}", + recording_id=uuid4(), + default_blueprint=rrb.Grid(rrb.Spatial2DView(origin="/"), rrb.TextDocumentView(origin="readme")), + ) + + log_readme() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) From 82993da837c0e47be4997fdd924897f4e1d69d93 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 10 Apr 2024 10:15:22 +0200 Subject: [PATCH 238/508] Update `egui_commonmark` (#5864) ### What Seems pretty safe - i tested a handful of examples, and all their inline markdown looks as good or better. https://github.com/lampsitter/egui_commonmark/blob/master/CHANGELOG.md ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5864) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5864?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5864?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5864) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 426481291c1a..4174723ef13b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1655,9 +1655,9 @@ dependencies = [ [[package]] name = "egui_commonmark" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e30fc4d40a8ef399a8debfbdae0462ca45912d81b9e81b24373337669e961201" +checksum = "013480797931a2649e03069613ed35514569372d6f79df70fc3653ae18a75c6c" dependencies = [ "egui", "egui_extras", diff --git a/Cargo.toml b/Cargo.toml index c7fe68857bf6..eceb581b10fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,7 +94,7 @@ egui = { version = "0.27.2", features = [ "puffin", "rayon", ] } -egui_commonmark = { version = "0.14", default-features = false } +egui_commonmark = { version = "0.15", default-features = false } egui_extras = { version = "0.27.2", features = ["http", "image", "puffin"] } egui_plot = "0.27.2" egui_tiles = "0.8.0" From 3624586e2f42427c736fb644c2b108f456c4920f Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 10 Apr 2024 13:55:29 +0200 Subject: [PATCH 239/508] Fix visible range not working (#5891) Typo during the great rebase that resulted in a massive never-ending conflict with the store hub changes :sob: I might do a follow-up to try and protect against it somehow -- whether at compile time or run time. --- crates/re_viewer_context/src/space_view/view_query.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index f866f772f39e..98c3ef7dc4a9 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -322,7 +322,8 @@ impl DataResult { .and_then(|OverridePath { store_kind, path }| match store_kind { // TODO(#5607): what should happen if the promise is still pending? StoreKind::Blueprint => ctx - .recording() + .store_context + .blueprint .latest_at_component::(path, ctx.blueprint_query), StoreKind::Recording => ctx .recording() From 5d5749d6a81355cb912b992cbf8fb03bf3193aba Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 10 Apr 2024 16:53:16 +0200 Subject: [PATCH 240/508] Remove justfile & fully replace remaining commands with pixi (#5892) ### What * Fixes #5595 Has a few judgment calls on what is no longer needed, but preserves most of what we had. Notably removes `py-requirements` command for the time being - the hope is that #5890 will fix things. (porting it proved difficult) See * https://github.com/rerun-io/rerun/issues/5894 Other things in here: * taplo (toml formatting) was very slow since despite extensive 'exclude' list it looked at too many files. Turned it around to 'include' things and it's a LOT faster now * Updated Ruff & removed last use of blackdoc. The only thing we're not properly catching with this now is too long lines, I figured it's not worth keeping it around just for that. * various cleanups of pixi.toml file: trying to make commands a bit more consistent overall Tested on: * [x] mac * [x] windows ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5892) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5892?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5892?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5892) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_checks.yml | 33 +- .github/workflows/reusable_checks.yml | 25 +- .github/workflows/reusable_checks_rust.yml | 19 - BUILD.md | 37 +- CONTRIBUTING.md | 7 +- docs/snippets/all/any_values.py | 1 + docs/snippets/all/arrow2d_simple.py | 1 + docs/snippets/all/arrow3d_simple.py | 1 + docs/snippets/all/asset3d_out_of_tree.py | 1 + docs/snippets/all/asset3d_simple.py | 1 + docs/snippets/all/box2d_simple.py | 1 + docs/snippets/all/box3d_batch.py | 1 + docs/snippets/all/box3d_simple.py | 1 + docs/snippets/all/custom_data.py | 1 + docs/snippets/all/disconnected_space.py | 1 + docs/snippets/all/extra_values.py | 1 + docs/snippets/all/line_segments2d_simple.py | 1 + docs/snippets/all/line_segments3d_simple.py | 1 + docs/snippets/all/line_strip2d_batch.py | 1 + docs/snippets/all/line_strip2d_simple.py | 1 + docs/snippets/all/line_strip3d_batch.py | 1 + docs/snippets/all/line_strip3d_simple.py | 1 + docs/snippets/all/manual_indicator.py | 1 + docs/snippets/all/mesh3d_indexed.py | 1 + docs/snippets/all/mesh3d_partial_updates.py | 1 + docs/snippets/all/mesh3d_simple.py | 1 + docs/snippets/all/pinhole_perspective.py | 1 + docs/snippets/all/pinhole_simple.py | 1 + docs/snippets/all/point2d_random.py | 1 + docs/snippets/all/point2d_simple.py | 1 + docs/snippets/all/point3d_random.py | 1 + docs/snippets/all/point3d_simple.py | 1 + docs/snippets/all/scalar_simple.py | 1 + docs/snippets/all/tensor_simple.py | 1 + docs/snippets/all/text_log_integration.py | 1 + docs/snippets/all/transform3d_simple.py | 1 + examples/python/blueprint/main.py | 1 + examples/python/blueprint_stocks/main.py | 1 + examples/python/clock/main.py | 1 + examples/python/controlnet/main.py | 1 + .../depth_guided_stable_diffusion/main.py | 1 + .../python/detect_and_track_objects/main.py | 1 + examples/python/dicom_mri/main.py | 1 + examples/python/dna/main.py | 1 + examples/python/external_data_loader/main.py | 1 + examples/python/face_tracking/main.py | 1 + examples/python/gesture_detection/main.py | 1 + examples/python/human_pose_tracking/main.py | 1 + examples/python/incremental_logging/main.py | 1 + examples/python/lidar/download_dataset.py | 1 + .../python/live_camera_edge_detection/main.py | 1 + examples/python/live_depth_sensor/main.py | 1 + examples/python/llm_embedding_ner/main.py | 1 + examples/python/minimal/main.py | 1 + examples/python/minimal_options/main.py | 1 + examples/python/multiprocessing/main.py | 1 + examples/python/multithreading/main.py | 1 + examples/python/nuscenes/download_dataset.py | 1 + examples/python/nv12/main.py | 1 + examples/python/objectron/main.py | 1 + .../python/open_photogrammetry_format/main.py | 1 + examples/python/plots/main.py | 1 + examples/python/raw_mesh/main.py | 1 + examples/python/rgbd/main.py | 1 + examples/python/ros_node/main.py | 1 + .../python/segment_anything_model/main.py | 1 + examples/python/shared_recording/main.py | 1 + .../python/signed_distance_fields/main.py | 1 + examples/python/stdio/main.py | 1 + examples/python/structure_from_motion/main.py | 1 + examples/python/template/main.py | 1 + justfile | 248 --- pixi.lock | 1850 +++++++---------- pixi.toml | 78 +- rerun_cpp/src/rerun/c/rerun.h | 6 +- rerun_py/docs/gen_common_index.py | 1 + rerun_py/pyproject.toml | 9 +- rerun_py/rerun/__init__.py | 1 + rerun_py/rerun_sdk/rerun/__main__.py | 1 + rerun_py/rerun_sdk/rerun/_converters.py | 24 +- rerun_py/rerun_sdk/rerun/color_conversion.py | 1 + .../rerun/datatypes/tensor_buffer.py | 6 +- .../rerun/datatypes/tensor_data_ext.py | 3 +- .../rerun_sdk/rerun/experimental/__init__.py | 1 + rerun_py/rerun_sdk/rerun/memory.py | 1 + rerun_py/rerun_sdk/rerun/notebook.py | 1 + rerun_py/rerun_sdk/rerun/script_helpers.py | 1 + rerun_py/rerun_sdk/rerun/utilities/data.py | 1 + rerun_py/rerun_sdk/rerun/utilities/util.py | 1 + rerun_py/tests/unit/test_color_conversion.py | 1 + scripts/check_example_manifest_coverage.py | 1 + scripts/ci/approve_workflow_runs.py | 1 + scripts/ci/build_and_upload_wheels.py | 1 + scripts/ci/compare.py | 1 + scripts/ci/count_bytes.py | 1 + scripts/ci/count_dependencies.py | 1 + scripts/ci/crates.py | 1 + scripts/ci/generate_pr_summary.py | 1 + scripts/ci/generate_prerelease_pip_index.py | 1 + scripts/ci/publish_wheels.py | 1 + scripts/ci/render_bench.py | 1 + scripts/ci/sync_release_assets.py | 1 + scripts/ci/thumbnails.py | 1 + scripts/ci/update_pr_body.py | 1 + scripts/fast_lint.py | 9 +- scripts/fetch_crashes.py | 1 + scripts/generate_changelog.py | 1 + scripts/highlight_issues.py | 1 + scripts/lint.py | 1 + scripts/run_all.py | 1 + scripts/run_python_e2e_test.py | 1 + taplo.toml | 14 +- tests/python/chroma_downsample_image/main.py | 1 + .../many_large_many_rows_recordings.py | 1 + .../many_large_single_row_recordings.py | 1 + .../many_medium_sized_many_rows_recordings.py | 1 + ...many_medium_sized_single_row_recordings.py | 1 + tests/python/gil_stress/main.py | 1 + .../log_benchmark/test_log_benchmark.py | 2 +- tests/python/plot_dashboard_stress/main.py | 1 + tests/python/test_api/main.py | 1 + tests/python/view_coordinates/main.py | 1 + .../python/visible_history_playground/main.py | 1 + 123 files changed, 992 insertions(+), 1485 deletions(-) delete mode 100644 justfile diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 9f90076c3b44..a087841b4876 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -35,10 +35,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: extractions/setup-just@v1 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - just-version: 1.5 - + pixi-version: v0.16.1 - name: Set up Python uses: actions/setup-python@v4 with: @@ -50,15 +49,15 @@ jobs: pip install --upgrade pip pip install -r rerun_py/requirements-lint.txt - - name: Lint Python + - name: Python format check shell: bash run: | - just py-lint + pixi run py-fmt-check - - name: Check requirements + - name: Lint Python shell: bash run: | - just py-requirements + pixi run py-lint py-test-docs: name: Test Python Docs @@ -204,8 +203,8 @@ jobs: # We build in release so that we can reuse the results for actual publishing, if necessary args: --locked -p re_build_web_viewer -- --release -g - toml-lints: - name: Lint TOML files + misc-rerun-lints: + name: Rerun lints runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -214,15 +213,6 @@ jobs: with: pixi-version: v0.16.1 - - run: pixi run lint-taplo - shell: bash - - misc-rerun-lints: - name: Rerun lints - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up Python uses: actions/setup-python@v4 with: @@ -235,9 +225,10 @@ jobs: pip install -r ./scripts/ci/requirements.txt - name: Rerun lints - shell: bash - run: | - ./scripts/lint.py + run: pixi run lint-rerun + + - name: Toml format check + run: pixi run toml-fmt-check - name: Check for too large files shell: bash diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 823dc755da7c..16823a23228d 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -39,11 +39,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: extractions/setup-just@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - uses: prefix-dev/setup-pixi@v0.4.1 with: - just-version: 1.5 + pixi-version: v0.16.1 - name: Set up Python uses: actions/setup-python@v4 @@ -58,15 +56,15 @@ jobs: pip install --upgrade pip pip install -r rerun_py/requirements-lint.txt - - name: Lint Python + - name: Python format check shell: bash run: | - just py-lint + pixi run py-fmt-check - - name: Check requirements + - name: Lint Python shell: bash run: | - just py-requirements + pixi run py-lint # --------------------------------------------------------------------------- @@ -144,6 +142,10 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + - uses: prefix-dev/setup-pixi@v0.4.1 + with: + pixi-version: v0.16.1 + - name: Set up Python uses: actions/setup-python@v4 with: @@ -156,9 +158,10 @@ jobs: pip install -r ./scripts/ci/requirements.txt - name: Rerun lints - shell: bash - run: | - ./scripts/lint.py + run: pixi run lint-rerun + + - name: Toml format check + run: pixi run toml-fmt-check # NOTE: We don't want spurious failures caused by issues being closed, so this does not run on CI, # at least for the time being. diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index b23c31b79a81..45b126234d16 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -118,25 +118,6 @@ jobs: # --------------------------------------------------------------------------- - toml-lints: - name: Lint TOML files - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - - uses: prefix-dev/setup-pixi@v0.4.1 - with: - pixi-version: v0.16.1 - - - name: Taplo check - shell: bash - run: | - pixi run lint-taplo - - # --------------------------------------------------------------------------- - rs-cargo-deny: name: Cargo Deny runs-on: ubuntu-latest diff --git a/BUILD.md b/BUILD.md index a8a72f0c5eec..62632d00abd4 100644 --- a/BUILD.md +++ b/BUILD.md @@ -65,36 +65,9 @@ Rerun is available as a package on PyPi and can be installed with `pip install r Additionally, prebuilt dev wheels from head of main are available at . -If you want to build from source, use the following instructions. - -### Mac/Linux - -First, a local virtual environment must be created and the necessary dependencies installed (this needs to be done only once): - -Linux/Mac: -```sh -just py-dev-env -source venv/bin/activate -``` -Windows (powershell): -```ps1 -just py-dev-env -.\venv\Scripts\Activate.ps1 -``` - - -Then, the SDK can be compiled and installed in the virtual environment using the following command: - -```sh -just py-build -``` - -This needs to be repeated each time the Rust source code is updated, for example after updating your clone using `git pull`. - -Now you can run the python examples from the repository, given that you're still in the virtual environment. -```sh -python examples/python/minimal/main.py -``` +If you want to build from source, you can do so easily in the pixi environment: +* Run `pixi run py-build-release` to build SDK & viewer for python (or `pixi run py-build` for a debug build) +* Then you can run examples from the repository, either by making the pixi shell active with `pixi shell` and then running python or by using `pixi run`, e.g. `pixi run python examples/python/minimal/main.py` ## Building and installing the Rerun C++ SDK @@ -102,11 +75,11 @@ On Windows you have to have a system install of Visual Studio 2022 in order to c All other dependencies are downloaded by Pixi! You can run tests with: ```sh -just cpp-test +pixi run cpp-test ``` and build all C++ artifacts with: ```sh -just cpp-build-all +pixi run cpp-build-all ``` ## Building the docs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e48da673d62..8c5ab569f285 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -113,7 +113,8 @@ cargo run -p rerun -- --help ## Tools -We use the [`just`](https://github.com/casey/just) command runner tool for repository automation. See [here](https://github.com/casey/just#installation) for installation instructions. To see available automation, use `just --list`. +We use the [`pixi`](https://prefix.dev/) for managing dev-tool versioning, download and task running. See [here](https://github.com/casey/just#installation) for installation instructions. To see available tasks, use `pixi task list`. +# TODO(andreas): This doesn't list tasks from the different environments. Asked [here](https://discord.com/channels/1082332781146800168/1227563080934756475/1227563080934756475) if there's a way to do that. We use [cargo cranky](https://github.com/ericseppanen/cargo-cranky) and specify our clippy lints in [`Cranky.toml`](Cranky.toml). Usage: `cargo cranky`. @@ -124,12 +125,12 @@ Configure your editor to run `cargo fmt` on save. Also configure it to strip tra To check everything in one go, run `./scripts/check.sh`. `check.sh` should ideally check approximately the same things as our CI. ### Linting -Prior to pushing changes to a PR, at a minimum, you should always run `just fast-lint`. This is designed to run +Prior to pushing changes to a PR, at a minimum, you should always run `pixi run fast-lint`. This is designed to run in a few seconds and should catch the more trivial issues to avoid wasting CI time. ### Hooks We recommend adding the rerun pre-push hook to your local checkout, which among other-things will run -`just fast-lint` for you. +`pixi run fast-lint` for you. To install the hooks, simply copy them into the `.git/hooks` directory of your local checkout. ``` diff --git a/docs/snippets/all/any_values.py b/docs/snippets/all/any_values.py index 36496ee0d8d0..156cc56f1d69 100644 --- a/docs/snippets/all/any_values.py +++ b/docs/snippets/all/any_values.py @@ -1,4 +1,5 @@ """Log arbitrary data.""" + import rerun as rr rr.init("rerun_example_any_values", spawn=True) diff --git a/docs/snippets/all/arrow2d_simple.py b/docs/snippets/all/arrow2d_simple.py index 3b1874ccbdaa..1f7d63a179fa 100644 --- a/docs/snippets/all/arrow2d_simple.py +++ b/docs/snippets/all/arrow2d_simple.py @@ -1,4 +1,5 @@ """Log a batch of 2D arrows.""" + import rerun as rr rr.init("rerun_example_arrow2d", spawn=True) diff --git a/docs/snippets/all/arrow3d_simple.py b/docs/snippets/all/arrow3d_simple.py index 808fd63db651..e645e7dba279 100644 --- a/docs/snippets/all/arrow3d_simple.py +++ b/docs/snippets/all/arrow3d_simple.py @@ -1,4 +1,5 @@ """Log a batch of 3D arrows.""" + from math import tau import numpy as np diff --git a/docs/snippets/all/asset3d_out_of_tree.py b/docs/snippets/all/asset3d_out_of_tree.py index 17e92649c781..35dd272dfcb6 100644 --- a/docs/snippets/all/asset3d_out_of_tree.py +++ b/docs/snippets/all/asset3d_out_of_tree.py @@ -1,4 +1,5 @@ """Log a simple 3D asset with an out-of-tree transform which will not affect its children.""" + import sys import numpy as np diff --git a/docs/snippets/all/asset3d_simple.py b/docs/snippets/all/asset3d_simple.py index 6b1e0b473cfd..b203e343f8c6 100644 --- a/docs/snippets/all/asset3d_simple.py +++ b/docs/snippets/all/asset3d_simple.py @@ -1,4 +1,5 @@ """Log a simple 3D asset.""" + import sys import rerun as rr diff --git a/docs/snippets/all/box2d_simple.py b/docs/snippets/all/box2d_simple.py index 241242a51a23..864dbcddb75f 100644 --- a/docs/snippets/all/box2d_simple.py +++ b/docs/snippets/all/box2d_simple.py @@ -1,4 +1,5 @@ """Log a simple 2D Box.""" + import rerun as rr rr.init("rerun_example_box2d", spawn=True) diff --git a/docs/snippets/all/box3d_batch.py b/docs/snippets/all/box3d_batch.py index fe7f74439453..272d895b371a 100644 --- a/docs/snippets/all/box3d_batch.py +++ b/docs/snippets/all/box3d_batch.py @@ -1,4 +1,5 @@ """Log a batch of oriented bounding boxes.""" + import rerun as rr from rerun.datatypes import Angle, Quaternion, Rotation3D, RotationAxisAngle diff --git a/docs/snippets/all/box3d_simple.py b/docs/snippets/all/box3d_simple.py index c1bb546fb0c0..d8973dce6139 100644 --- a/docs/snippets/all/box3d_simple.py +++ b/docs/snippets/all/box3d_simple.py @@ -1,4 +1,5 @@ """Log a single 3D Box.""" + import rerun as rr rr.init("rerun_example_box3d", spawn=True) diff --git a/docs/snippets/all/custom_data.py b/docs/snippets/all/custom_data.py index 09dddbd2c426..22becf1551d5 100755 --- a/docs/snippets/all/custom_data.py +++ b/docs/snippets/all/custom_data.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Shows how to implement custom archetypes and components.""" + from __future__ import annotations import argparse diff --git a/docs/snippets/all/disconnected_space.py b/docs/snippets/all/disconnected_space.py index 43197b7a6152..cde7a732e846 100644 --- a/docs/snippets/all/disconnected_space.py +++ b/docs/snippets/all/disconnected_space.py @@ -1,4 +1,5 @@ """Disconnect two spaces.""" + import rerun as rr rr.init("rerun_example_disconnected_space", spawn=True) diff --git a/docs/snippets/all/extra_values.py b/docs/snippets/all/extra_values.py index 6a50d9f72fe9..0d477be1c892 100644 --- a/docs/snippets/all/extra_values.py +++ b/docs/snippets/all/extra_values.py @@ -1,4 +1,5 @@ """Log extra values with a Points2D.""" + import rerun as rr rr.init("rerun_example_extra_values", spawn=True) diff --git a/docs/snippets/all/line_segments2d_simple.py b/docs/snippets/all/line_segments2d_simple.py index 01deae5c9a2c..1700bdaced31 100644 --- a/docs/snippets/all/line_segments2d_simple.py +++ b/docs/snippets/all/line_segments2d_simple.py @@ -1,4 +1,5 @@ """Log a couple 2D line segments using 2D line strips.""" + import numpy as np import rerun as rr diff --git a/docs/snippets/all/line_segments3d_simple.py b/docs/snippets/all/line_segments3d_simple.py index c04125749a7f..9d70db37f973 100644 --- a/docs/snippets/all/line_segments3d_simple.py +++ b/docs/snippets/all/line_segments3d_simple.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Log a simple set of line segments.""" + import numpy as np import rerun as rr diff --git a/docs/snippets/all/line_strip2d_batch.py b/docs/snippets/all/line_strip2d_batch.py index 7ff5ab60377f..a71c43f0bbb7 100644 --- a/docs/snippets/all/line_strip2d_batch.py +++ b/docs/snippets/all/line_strip2d_batch.py @@ -1,4 +1,5 @@ """Log a batch of 2D line strips.""" + import rerun as rr rr.init("rerun_example_line_strip2d_batch", spawn=True) diff --git a/docs/snippets/all/line_strip2d_simple.py b/docs/snippets/all/line_strip2d_simple.py index bdd1cb813114..67ca4296e80a 100644 --- a/docs/snippets/all/line_strip2d_simple.py +++ b/docs/snippets/all/line_strip2d_simple.py @@ -1,4 +1,5 @@ """Log a simple line strip.""" + import rerun as rr rr.init("rerun_example_line_strip2d", spawn=True) diff --git a/docs/snippets/all/line_strip3d_batch.py b/docs/snippets/all/line_strip3d_batch.py index 94c96024f82c..2349cdc30149 100644 --- a/docs/snippets/all/line_strip3d_batch.py +++ b/docs/snippets/all/line_strip3d_batch.py @@ -1,4 +1,5 @@ """Log a batch of 3D line strips.""" + import rerun as rr rr.init("rerun_example_line_strip3d_batch", spawn=True) diff --git a/docs/snippets/all/line_strip3d_simple.py b/docs/snippets/all/line_strip3d_simple.py index 6a22721a062c..7c775897f2aa 100644 --- a/docs/snippets/all/line_strip3d_simple.py +++ b/docs/snippets/all/line_strip3d_simple.py @@ -1,4 +1,5 @@ """Log a simple line strip.""" + import rerun as rr rr.init("rerun_example_line_strip3d", spawn=True) diff --git a/docs/snippets/all/manual_indicator.py b/docs/snippets/all/manual_indicator.py index 368bd9eb0022..86e4970e8dea 100644 --- a/docs/snippets/all/manual_indicator.py +++ b/docs/snippets/all/manual_indicator.py @@ -1,4 +1,5 @@ """Shows how to manually associate one or more indicator components with arbitrary data.""" + import rerun as rr rr.init("rerun_example_manual_indicator", spawn=True) diff --git a/docs/snippets/all/mesh3d_indexed.py b/docs/snippets/all/mesh3d_indexed.py index 695275ab7ec4..e5241e1ac3d7 100644 --- a/docs/snippets/all/mesh3d_indexed.py +++ b/docs/snippets/all/mesh3d_indexed.py @@ -1,4 +1,5 @@ """Log a simple colored triangle.""" + import rerun as rr rr.init("rerun_example_mesh3d_indexed", spawn=True) diff --git a/docs/snippets/all/mesh3d_partial_updates.py b/docs/snippets/all/mesh3d_partial_updates.py index 0d1f73b66d14..64b2dd77e546 100644 --- a/docs/snippets/all/mesh3d_partial_updates.py +++ b/docs/snippets/all/mesh3d_partial_updates.py @@ -1,4 +1,5 @@ """Log a simple colored triangle, then update its vertices' positions each frame.""" + import numpy as np import rerun as rr from rerun.components import Position3DBatch diff --git a/docs/snippets/all/mesh3d_simple.py b/docs/snippets/all/mesh3d_simple.py index e88b9cee5b53..8f90bd2ec277 100644 --- a/docs/snippets/all/mesh3d_simple.py +++ b/docs/snippets/all/mesh3d_simple.py @@ -1,4 +1,5 @@ """Log a simple colored triangle.""" + import rerun as rr rr.init("rerun_example_mesh3d", spawn=True) diff --git a/docs/snippets/all/pinhole_perspective.py b/docs/snippets/all/pinhole_perspective.py index 32155d0fdc8f..5d99b82a3526 100644 --- a/docs/snippets/all/pinhole_perspective.py +++ b/docs/snippets/all/pinhole_perspective.py @@ -1,4 +1,5 @@ """Logs a point cloud and a perspective camera looking at it.""" + import rerun as rr rr.init("rerun_example_pinhole_perspective", spawn=True) diff --git a/docs/snippets/all/pinhole_simple.py b/docs/snippets/all/pinhole_simple.py index d83aae079296..0357efdcf4fe 100644 --- a/docs/snippets/all/pinhole_simple.py +++ b/docs/snippets/all/pinhole_simple.py @@ -1,4 +1,5 @@ """Log a pinhole and a random image.""" + import numpy as np import rerun as rr diff --git a/docs/snippets/all/point2d_random.py b/docs/snippets/all/point2d_random.py index 81fbf09bea02..f4c4fb423be6 100644 --- a/docs/snippets/all/point2d_random.py +++ b/docs/snippets/all/point2d_random.py @@ -1,4 +1,5 @@ """Log some random points with color and radii.""" + import rerun as rr from numpy.random import default_rng diff --git a/docs/snippets/all/point2d_simple.py b/docs/snippets/all/point2d_simple.py index 827f896b4b22..86d791ee0675 100644 --- a/docs/snippets/all/point2d_simple.py +++ b/docs/snippets/all/point2d_simple.py @@ -1,4 +1,5 @@ """Log some very simple points.""" + import rerun as rr rr.init("rerun_example_points2d", spawn=True) diff --git a/docs/snippets/all/point3d_random.py b/docs/snippets/all/point3d_random.py index dbbedc098fc2..49bd390ed7a2 100644 --- a/docs/snippets/all/point3d_random.py +++ b/docs/snippets/all/point3d_random.py @@ -1,4 +1,5 @@ """Log some random points with color and radii.""" + import rerun as rr from numpy.random import default_rng diff --git a/docs/snippets/all/point3d_simple.py b/docs/snippets/all/point3d_simple.py index aaa98a40d3c3..db435548d8c2 100644 --- a/docs/snippets/all/point3d_simple.py +++ b/docs/snippets/all/point3d_simple.py @@ -1,4 +1,5 @@ """Log some very simple points.""" + import rerun as rr rr.init("rerun_example_points3d", spawn=True) diff --git a/docs/snippets/all/scalar_simple.py b/docs/snippets/all/scalar_simple.py index b8c5e3fae323..87e96a763e20 100644 --- a/docs/snippets/all/scalar_simple.py +++ b/docs/snippets/all/scalar_simple.py @@ -1,4 +1,5 @@ """Log a scalar over time.""" + import math import rerun as rr diff --git a/docs/snippets/all/tensor_simple.py b/docs/snippets/all/tensor_simple.py index 727744253f14..fb3b6f0539ec 100644 --- a/docs/snippets/all/tensor_simple.py +++ b/docs/snippets/all/tensor_simple.py @@ -1,4 +1,5 @@ """Create and log a tensor.""" + import numpy as np import rerun as rr diff --git a/docs/snippets/all/text_log_integration.py b/docs/snippets/all/text_log_integration.py index e7b91758fc8e..93025b1d6502 100644 --- a/docs/snippets/all/text_log_integration.py +++ b/docs/snippets/all/text_log_integration.py @@ -1,4 +1,5 @@ """Shows integration of Rerun's `TextLog` with the native logging interface.""" + import logging import rerun as rr diff --git a/docs/snippets/all/transform3d_simple.py b/docs/snippets/all/transform3d_simple.py index 511e7407576f..894c3cb11524 100644 --- a/docs/snippets/all/transform3d_simple.py +++ b/docs/snippets/all/transform3d_simple.py @@ -1,4 +1,5 @@ """Log different transforms between three arrows.""" + from math import pi import rerun as rr diff --git a/examples/python/blueprint/main.py b/examples/python/blueprint/main.py index ef100b2c5eed..e9e3f7fc8c1c 100755 --- a/examples/python/blueprint/main.py +++ b/examples/python/blueprint/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Example of using the blueprint APIs to configure Rerun.""" + from __future__ import annotations import argparse diff --git a/examples/python/blueprint_stocks/main.py b/examples/python/blueprint_stocks/main.py index 17805e04442c..e250829f1aba 100755 --- a/examples/python/blueprint_stocks/main.py +++ b/examples/python/blueprint_stocks/main.py @@ -4,6 +4,7 @@ The main focus of this example is using blueprints to control how the data is displayed in the viewer. """ + from __future__ import annotations import argparse diff --git a/examples/python/clock/main.py b/examples/python/clock/main.py index 772ae92a918a..a1dccef90c51 100755 --- a/examples/python/clock/main.py +++ b/examples/python/clock/main.py @@ -4,6 +4,7 @@ An analog clock is built with Rerun Arrow3D primitives. """ + from __future__ import annotations import argparse diff --git a/examples/python/controlnet/main.py b/examples/python/controlnet/main.py index 650a0bfca42b..1ecadd9e3d4a 100755 --- a/examples/python/controlnet/main.py +++ b/examples/python/controlnet/main.py @@ -9,6 +9,7 @@ examples/python/controlnet/main.py ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/depth_guided_stable_diffusion/main.py b/examples/python/depth_guided_stable_diffusion/main.py index abe0316d3fd5..370573ce2413 100755 --- a/examples/python/depth_guided_stable_diffusion/main.py +++ b/examples/python/depth_guided_stable_diffusion/main.py @@ -4,6 +4,7 @@ For more info see: https://github.com/Stability-AI/stablediffusion """ + from __future__ import annotations import argparse diff --git a/examples/python/detect_and_track_objects/main.py b/examples/python/detect_and_track_objects/main.py index 5930cc266455..51ed28a90e4e 100755 --- a/examples/python/detect_and_track_objects/main.py +++ b/examples/python/detect_and_track_objects/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Example applying simple object detection and tracking on a video.""" + from __future__ import annotations import argparse diff --git a/examples/python/dicom_mri/main.py b/examples/python/dicom_mri/main.py index 9b36728ee0c1..078569c215fd 100755 --- a/examples/python/dicom_mri/main.py +++ b/examples/python/dicom_mri/main.py @@ -7,6 +7,7 @@ python3 examples/python/dicom/main.py ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/dna/main.py b/examples/python/dna/main.py index 158d1efb2f52..8cacc502ba3f 100755 --- a/examples/python/dna/main.py +++ b/examples/python/dna/main.py @@ -4,6 +4,7 @@ `examples/python/dna/main.py` """ + from __future__ import annotations import argparse diff --git a/examples/python/external_data_loader/main.py b/examples/python/external_data_loader/main.py index c9cf0a7601dc..39c057b2f96f 100755 --- a/examples/python/external_data_loader/main.py +++ b/examples/python/external_data_loader/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Example of an executable data-loader plugin for the Rerun Viewer.""" + from __future__ import annotations import argparse diff --git a/examples/python/face_tracking/main.py b/examples/python/face_tracking/main.py index 7f27a0118bb7..586865671c44 100755 --- a/examples/python/face_tracking/main.py +++ b/examples/python/face_tracking/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Use the MediaPipe Face detection and Face landmark detection solutions to track human faces in images and videos.""" + from __future__ import annotations import argparse diff --git a/examples/python/gesture_detection/main.py b/examples/python/gesture_detection/main.py index fd622bd63167..fe8f043f042e 100755 --- a/examples/python/gesture_detection/main.py +++ b/examples/python/gesture_detection/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Use the MediaPipe Gesture detection and Gesture landmark detection solutions to track hands and recognize gestures in images and videos.""" + from __future__ import annotations import argparse diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py index a7e619824a2e..b46492dc82fb 100755 --- a/examples/python/human_pose_tracking/main.py +++ b/examples/python/human_pose_tracking/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Use the MediaPipe Pose solution to detect and track a human pose in video.""" + from __future__ import annotations import argparse diff --git a/examples/python/incremental_logging/main.py b/examples/python/incremental_logging/main.py index cd2e67dfc9f0..cf631dfe6991 100755 --- a/examples/python/incremental_logging/main.py +++ b/examples/python/incremental_logging/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Showcases how to incrementally log data belonging to the same archetype, and re-use some or all of it across frames.""" + from __future__ import annotations import argparse diff --git a/examples/python/lidar/download_dataset.py b/examples/python/lidar/download_dataset.py index fbb384643ffe..277baec5e3ac 100644 --- a/examples/python/lidar/download_dataset.py +++ b/examples/python/lidar/download_dataset.py @@ -1,4 +1,5 @@ """Module to download nuScenes minisplit.""" + from __future__ import annotations import os diff --git a/examples/python/live_camera_edge_detection/main.py b/examples/python/live_camera_edge_detection/main.py index 86373d6006dd..4d3206d6c21b 100755 --- a/examples/python/live_camera_edge_detection/main.py +++ b/examples/python/live_camera_edge_detection/main.py @@ -4,6 +4,7 @@ Runs the opencv canny edge detector on the image stream. """ + from __future__ import annotations import argparse diff --git a/examples/python/live_depth_sensor/main.py b/examples/python/live_depth_sensor/main.py index bfbb7bba8627..7ababef6a042 100755 --- a/examples/python/live_depth_sensor/main.py +++ b/examples/python/live_depth_sensor/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """A minimal example of streaming frames live from an Intel RealSense depth sensor.""" + from __future__ import annotations import argparse diff --git a/examples/python/llm_embedding_ner/main.py b/examples/python/llm_embedding_ner/main.py index 363383999020..dab018fe1f77 100755 --- a/examples/python/llm_embedding_ner/main.py +++ b/examples/python/llm_embedding_ner/main.py @@ -7,6 +7,7 @@ examples/python/llm_embedding_ner/main.py ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/minimal/main.py b/examples/python/minimal/main.py index 7be4546043f6..5f1fe2dce7b7 100755 --- a/examples/python/minimal/main.py +++ b/examples/python/minimal/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Demonstrates the most barebone usage of the Rerun SDK.""" + from __future__ import annotations import sys diff --git a/examples/python/minimal_options/main.py b/examples/python/minimal_options/main.py index 2d2b7e27c5b3..30e86af8ea13 100755 --- a/examples/python/minimal_options/main.py +++ b/examples/python/minimal_options/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Demonstrates the most barebone usage of the Rerun SDK, with standard options.""" + from __future__ import annotations import argparse diff --git a/examples/python/multiprocessing/main.py b/examples/python/multiprocessing/main.py index 7c6ce96d2ed1..a1a61ba312ce 100755 --- a/examples/python/multiprocessing/main.py +++ b/examples/python/multiprocessing/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Shows how rerun can work with multiprocessing.""" + from __future__ import annotations import argparse diff --git a/examples/python/multithreading/main.py b/examples/python/multithreading/main.py index 08eb3536f753..61098b663686 100755 --- a/examples/python/multithreading/main.py +++ b/examples/python/multithreading/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Demonstration of using rerun from multiple threads.""" + from __future__ import annotations import argparse diff --git a/examples/python/nuscenes/download_dataset.py b/examples/python/nuscenes/download_dataset.py index fbb384643ffe..277baec5e3ac 100644 --- a/examples/python/nuscenes/download_dataset.py +++ b/examples/python/nuscenes/download_dataset.py @@ -1,4 +1,5 @@ """Module to download nuScenes minisplit.""" + from __future__ import annotations import os diff --git a/examples/python/nv12/main.py b/examples/python/nv12/main.py index 16833e8c2dde..0d96a66b9c82 100755 --- a/examples/python/nv12/main.py +++ b/examples/python/nv12/main.py @@ -8,6 +8,7 @@ python examples/python/nv12/main.py ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/objectron/main.py b/examples/python/objectron/main.py index 4fa27b3ed3b2..f806df275571 100755 --- a/examples/python/objectron/main.py +++ b/examples/python/objectron/main.py @@ -4,6 +4,7 @@ Example: `examples/python/objectron/main.py --recording chair` """ + from __future__ import annotations import argparse diff --git a/examples/python/open_photogrammetry_format/main.py b/examples/python/open_photogrammetry_format/main.py index 182ba4e30f6f..d09409cceb13 100755 --- a/examples/python/open_photogrammetry_format/main.py +++ b/examples/python/open_photogrammetry_format/main.py @@ -4,6 +4,7 @@ Requires Python 3.10 or higher because of [pyopf](https://pypi.org/project/pyopf/). """ + from __future__ import annotations import argparse diff --git a/examples/python/plots/main.py b/examples/python/plots/main.py index 40a4e2245373..7aff7e7881f0 100755 --- a/examples/python/plots/main.py +++ b/examples/python/plots/main.py @@ -7,6 +7,7 @@ ./examples/python/plot/main.py ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/raw_mesh/main.py b/examples/python/raw_mesh/main.py index 3dc682d1abcf..d8608272c985 100755 --- a/examples/python/raw_mesh/main.py +++ b/examples/python/raw_mesh/main.py @@ -8,6 +8,7 @@ examples/python/raw_mesh/main.py ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/rgbd/main.py b/examples/python/rgbd/main.py index b63a499ed305..0c575f3a0569 100755 --- a/examples/python/rgbd/main.py +++ b/examples/python/rgbd/main.py @@ -4,6 +4,7 @@ https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html """ + from __future__ import annotations import argparse diff --git a/examples/python/ros_node/main.py b/examples/python/ros_node/main.py index 2a81b01d9d48..4645066f6825 100755 --- a/examples/python/ros_node/main.py +++ b/examples/python/ros_node/main.py @@ -9,6 +9,7 @@ NOTE: Unlike many of the other examples, this example requires a system installation of ROS in addition to the packages from requirements.txt. """ + from __future__ import annotations import argparse diff --git a/examples/python/segment_anything_model/main.py b/examples/python/segment_anything_model/main.py index cbd8f7597543..4eb278ecc724 100755 --- a/examples/python/segment_anything_model/main.py +++ b/examples/python/segment_anything_model/main.py @@ -14,6 +14,7 @@ python main.py --device cuda --model vit_h /path/to/my_image.jpg ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/shared_recording/main.py b/examples/python/shared_recording/main.py index a951792d3ed9..57b0ffa61ab7 100755 --- a/examples/python/shared_recording/main.py +++ b/examples/python/shared_recording/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Demonstrates how to use `RecordingId`s to build a single recording from multiple processes.""" + from __future__ import annotations import os diff --git a/examples/python/signed_distance_fields/main.py b/examples/python/signed_distance_fields/main.py index 2d2399aa486c..1024f589a46b 100755 --- a/examples/python/signed_distance_fields/main.py +++ b/examples/python/signed_distance_fields/main.py @@ -25,6 +25,7 @@ examples/python/signed_distance_fields/main.py ``` """ + from __future__ import annotations import argparse diff --git a/examples/python/stdio/main.py b/examples/python/stdio/main.py index 9a9e57cbd342..d1400c5d55b1 100755 --- a/examples/python/stdio/main.py +++ b/examples/python/stdio/main.py @@ -4,6 +4,7 @@ Usage: `echo 'hello from stdin!' | python main.py | rerun -` """ + from __future__ import annotations import sys diff --git a/examples/python/structure_from_motion/main.py b/examples/python/structure_from_motion/main.py index 975beb22c385..e7377e45e9fa 100755 --- a/examples/python/structure_from_motion/main.py +++ b/examples/python/structure_from_motion/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Example of using Rerun to log and visualize the output of COLMAP's sparse reconstruction.""" + from __future__ import annotations import io diff --git a/examples/python/template/main.py b/examples/python/template/main.py index f688d32a4a6b..856d490b18bc 100755 --- a/examples/python/template/main.py +++ b/examples/python/template/main.py @@ -8,6 +8,7 @@ python examples/python/template/main.py ``` """ + from __future__ import annotations import argparse diff --git a/justfile b/justfile deleted file mode 100644 index d69e6d958176..000000000000 --- a/justfile +++ /dev/null @@ -1,248 +0,0 @@ -# Install just: https://github.com/casey/just -# -# Then run `just --list` to see the available commands - -export RUSTDOCFLAGS := "--deny warnings --deny rustdoc::missing_crate_level_docs" -set windows-shell := ["powershell.exe", "-NoLogo", "-Command"] - -default: - @just --list - - -### Common -# Format all of our code -format: cpp-format toml-format py-format - cargo fmt --all - -# Lint all of our code -lint: toml-lint py-lint rs-lint - -# Run the fast versions of our linters -fast-lint *ARGS: - pixi run fast-lint {{ARGS}} - -### C and C++ - -# Clear the C++ build directories -cpp-clean: - rm -rf build CMakeCache.txt CMakeFiles - -cpp-format: - #!/usr/bin/env bash - fd --extension h --exec clang-format -i - fd --extension hpp --exec clang-format -i - fd --extension c --exec clang-format -i - fd --extension cpp --exec clang-format -i - -# Build our C++ SDK, and all our tests and examples -cpp-build-all: - pixi run cpp-build-all - -# Build our C++ SDK and tests -cpp-build: - pixi run cpp-build-all - -# Build all our C++ examples. -cpp-build-examples: - pixi run cpp-build-examples - -# Build all our C++ snippets. -cpp-build-snippets: - pixi run cpp-build-snippets - -# Run our C++ tests -cpp-test: - pixi run cpp-test - -cpp-plot-dashboard *ARGS: - pixi run cpp-plot-dashboard {{ARGS}} - - -### Python - -py_folders := "." - -# Set up a Python virtual environment for development -py-dev-env: - #!/usr/bin/env bash - echo "Setting up Python virtual environment in venv" - set -euxo pipefail - python3 -m venv venv - venv/bin/pip install --upgrade pip - venv/bin/pip install -r scripts/requirements-dev.txt - echo "Do 'source venv/bin/activate' to use the virtual environment!" - -# Set up a Python 3.10 virtual environment for development -py-dev-env-3-10: - #!/usr/bin/env bash - echo "Setting up Python 3.10 virtual environment in venv3.10" - set -euxo pipefail - python3.10 -m venv venv3.10 - venv3.10/bin/pip install --upgrade pip - venv3.10/bin/pip install -r scripts/requirements-dev.txt - echo "Do 'source venv3.10/bin/activate' to use the virtual environment!" - -# Run all examples with the specified args -py-run-all *ARGS: - python3 "scripts/run_all.py" {{ARGS}} - -# Run all examples in the native viewer -py-run-all-native: py-run-all - -# Run all examples in the web viewer -py-run-all-web: - just py-run-all --web - -# Run all examples, save them to disk as rrd, then view them natively -py-run-all-rrd *ARGS: - just py-run-all --save {{ARGS}} - -# Run all examples with all supported Python versions (through nox) -py-run-all-allpy *ARGS: - nox -s run_all -- {{ARGS}} - -# Build and install the package into the venv -py-build *ARGS: - #!/usr/bin/env bash - set -euo pipefail - unset CONDA_PREFIX && \ - maturin develop \ - --manifest-path rerun_py/Cargo.toml \ - --extras="tests" \ - {{ARGS}} - -# Run autoformatting -py-format: - #!/usr/bin/env bash - set -euo pipefail - # NOTE: we need both `ruff check --fix` and `ruff format` in that order: https://twitter.com/charliermarsh/status/1717229721954799727 - ruff check --fix --config rerun_py/pyproject.toml {{py_folders}} - ruff format --config rerun_py/pyproject.toml {{py_folders}} - blackdoc {{py_folders}} # Format snippets in docstring. Hopefully `ruff` can do this soon: https://github.com/astral-sh/ruff/issues/7146 - -# Check that all the requirements.txt files for all the examples are correct -py-requirements: - #!/usr/bin/env bash - set -euo pipefail - find examples/python/ -name main.py | xargs -I _ sh -c 'cd $(dirname _) && echo $(pwd) && pip-missing-reqs . || exit 255' - -# Run linting -py-lint: - #!/usr/bin/env bash - set -euxo pipefail - ruff check --config rerun_py/pyproject.toml {{py_folders}} - ruff format --check --config rerun_py/pyproject.toml {{py_folders}} - blackdoc --check {{py_folders}} - mypy --install-types --non-interactive --no-warn-unused-ignore - -# Run fast unittests -py-test: - python -m pytest -vv -c rerun_py/pyproject.toml rerun_py/tests/unit/ - -# Run tests on all supported Python versions (through nox) -py-test-allpy: - nox -s tests - -# Run all Python benchmarks -py-bench *ARGS: - python -m pytest -c rerun_py/pyproject.toml --benchmark-only {{ARGS}} - - -# Serve the python docs locally -py-docs-serve: - mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py - -py-plot-dashboard *ARGS: - pixi run py-plot-dashboard {{ARGS}} - -### Rust - -# Generate and open the documentation for Rerun and all of its Rust dependencies. -# -# `--keep-going` makes sure we don't to abort the build process in case of errors. -# This is an unstable flag, available only on nightly. -rs-doc: - cargo +nightly doc --all --open --keep-going --all-features -Zunstable-options - -# `just rerun` is short a convenient shorthand, skipping the web viewer. -rerun *ARGS: - cargo run --package rerun-cli --no-default-features --features native_viewer -- {{ARGS}} - -# like `just rerun`, but with --release -rerun-release *ARGS: - cargo run --package rerun-cli --no-default-features --features native_viewer --release -- {{ARGS}} - -# `just rerun-web` is short a convenient shorthand for building & starting the web viewer. -rerun-web *ARGS: - cargo run --package rerun-cli --no-default-features --features web_viewer -- --web-viewer {{ARGS}} - -# like `rerun-web-release`, but with --release -rerun-web-release *ARGS: - cargo run --package rerun-cli --no-default-features --features web_viewer --release -- --web-viewer {{ARGS}} - -# Run the codegen. Optionally pass `--profile` argument if you want. -codegen *ARGS: - pixi run codegen {{ARGS}} - -# Print the contents of an .rrd file -print *ARGS: - just rerun print {{ARGS}} - -# To easily run examples on the web, see https://github.com/rukai/cargo-run-wasm. -# Temporary solution while we wait for our own xtasks! -run-wasm *ARGS: - cargo run --release --package run_wasm -- {{ARGS}} - -# Lint all of Rust code -rs-lint: - #!/usr/bin/env bash - set -euxo pipefail - cargo cranky --quiet --all-features -- --deny warnings - typos - scripts/lint.py - cargo doc --quiet --no-deps --all-features - cargo doc --quiet --document-private-items --no-deps --all-features - cargo test --quiet --doc --all-features # runs all doc-tests - -# Lint Rust code for the wasm target -rs-lint-wasm: - scripts/clippy_wasm.sh - -# Run all examples with the specified args -rs-run-all *ARGS: - #!/usr/bin/env bash - set -euo pipefail - find examples/rust/ -name main.rs | xargs -I _ sh -c 'cd $(dirname _) && echo $(pwd) && cargo r' - -rs-plot-dashboard *ARGS: - pixi run rs-plot-dashboard {{ARGS}} - -### TOML - -# Format .toml files -toml-format: - pixi run toml-fmt - -# Lint .toml files -toml-lint: - pixi run lint-taplo - - -### Misc - -# Update the design_tokens.json used to style the GUI. -# See https://rerun-design-guidelines.netlify.app/tokens for their meanings. -# To update the upstream `design_tokens.json`, modify -# https://github.com/rerun-io/documentation/blob/main/src/utils/tokens.ts and push to main. -download-design-tokens: - curl --fail https://rerun-docs.netlify.app/api/tokens | jq > crates/re_ui/data/design_tokens.json - -# Update the results of `insta` snapshot regression tests -update-insta-tests: - cargo test; cargo insta review - -upload *ARGS: - python3 "scripts/upload_image.py" {{ARGS}} - -crates *ARGS: - python3 "scripts/ci/crates.py" {{ARGS}} diff --git a/pixi.lock b/pixi.lock index 175f0d5dc038..1e634cad920b 100644 --- a/pixi.lock +++ b/pixi.lock @@ -7,6 +7,7 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.16-h79b3bcb_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.10-hb29e0c7_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.13-hd590300_0.conda @@ -24,7 +25,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.40-hdd6e379_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-hf600244_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.40-hbdbef99_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.26.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.6.0-hd590300_0.conda @@ -35,19 +35,25 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/cxx-compiler-1.6.0-h00ab1b0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-23.5.26-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-12.3.0-h8d2909c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-12.3.0-he2b93b0_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-12.3.0-h76fc315_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx-12.3.0-h8d2909c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-12.3.0-he2b93b0_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-12.3.0-h8a814eb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/just-1.22.1-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_16.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda @@ -73,6 +79,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.5.0-hcb278e6_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h8bca6fd_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_5.conda @@ -96,6 +103,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libsanitizer-12.3.0-h0f45ef3_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.1-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h8bca6fd_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.19.0-hb90f79a_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.8.0-h166bdaf_0.tar.bz2 @@ -108,75 +116,59 @@ 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/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-h59595ed_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.18.2-hb753e55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.2-h00e871a_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-50.0-hd3aeb46_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.5-h06160fa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.18.1-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h75e419f_3.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_16.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-64-12.3.0-h8bca6fd_105.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-64-12.3.0-h8bca6fd_105.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-64-2.12-he073ed8_16.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.18.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h75e419f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/_sysroot_linux-aarch64_curr_repodata_hack-4-h57d6b7b_14.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.13-h31becfc_0.conda @@ -191,20 +183,38 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.2-h07bb24a_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/black-24.2.0-py311hec3470c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.40-h64c2a2e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.40-h870a726_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.40-h95d2017_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.6.0-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-16-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-16.0.6-h250cd41_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.6.0-h2a328a1_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-12.3.0-he80d746_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-12.3.0-hcde2664_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-12.3.0-h9622932_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-12.3.0-he80d746_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-12.3.0-hcde2664_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-12.3.0-h3d1e521_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/just-1.24.0-h1d8f897_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h5b4a56d_14.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda @@ -221,7 +231,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.1.0-h31becfc_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.1.0-h31becfc_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-21_linuxaarch64_openblas.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp16-16.0.6-default_hb368394_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp16-16.0.6-default_hb368394_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-18.1.1-default_hf9b4efe_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcrc32c-1.1.2-h01db608_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.5.0-h4e8248e_0.conda @@ -230,6 +240,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-12.3.0-h8b5ab12_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-13.2.0-hf8544c7_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-ng-13.2.0-he9431aa_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-13.2.0-h582850c_5.conda @@ -249,8 +260,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libparquet-14.0.2-hb18b541_12_cpu.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-4.25.3-h648ac29_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libre2-11-2023.09.01-h9d008c2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-12.3.0-h8ebda82_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.0-h492db2e_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-12.3.0-h8b5ab12_105.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-13.2.0-h9a76618_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libthrift-0.19.0-h043aeee_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libutf8proc-2.8.0-h4e544f5_0.tar.bz2 @@ -262,101 +275,56 @@ 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/maturin-1.5.1-py311h06e5ef9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4-h0425590_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-h75d905f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.2.2-py311he69e3a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.17-h5b4a56d_14.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-16.0.6-ha38d28d_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.16-h79cb451_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.10-h7beb4c2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.13-h10d778d_0.conda @@ -371,7 +339,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.2-h56a5195_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h4da54b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.26.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.6.0-h282daa2_0.conda @@ -389,14 +356,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_impl_osx-64-16.0.6-h6d92fbe_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clangxx_osx-64-16.0.6-hb91bd55_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/compiler-rt-16.0.6-ha38d28d_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-64-16.0.6-ha38d28d_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cxx-compiler-1.6.0-h7728843_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-23.5.26-he965462_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/just-1.22.1-h63b85fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-609-ha02d983_16.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-609-ha20a434_16.conda @@ -450,69 +423,54 @@ 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/maturin-1.5.1-py311h24bb903_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4-h93d8f39_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.18.2-h2713218_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h3758fe2_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/sigtool-0.1.3-h88f4db0_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tapi-1100.0.11-h9ce4665_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.18.1-h11a7dfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-16.0.6-h3808999_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.16-h51b92d1_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.10-hf888d4c_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.13-h93a5062_0.conda @@ -527,7 +485,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.2-h06549c9_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h73c0887_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.26.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.6.0-h6aa9301_0.conda @@ -545,14 +502,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_impl_osx-arm64-16.0.6-hcd7bac0_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clangxx_osx-arm64-16.0.6-h54d7cd3_9.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/compiler-rt-16.0.6-h3808999_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/compiler-rt_osx-arm64-16.0.6-h3808999_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cxx-compiler-1.6.0-h2ffa867_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-23.5.26-h13dd4ca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.22.1-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-609-h634c8be_16.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-609-ha4bd21c_16.conda @@ -606,68 +569,54 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - 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/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h463b476_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.18.2-h7ed3092_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h798d188_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/sigtool-0.1.3-h44b9a77_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tapi-1100.0.11-he4954df_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.18.1-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.13-hcfcfb64_0.conda @@ -682,17 +631,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.0.0-h57928b3_49841.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.22.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-hd01637b_10_cpu.conda @@ -739,38 +692,54 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.0.0-h66d3029_49657.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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.11.0-h91493d7_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.18.1-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.37.32822-h0123c8e_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vswhere-3.1.4-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl default: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -778,6 +747,7 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.10-h0100c56_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.9-h5d48c4d_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.10-hd590300_0.conda @@ -792,7 +762,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.0-h3b5eec7_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.210-hac0d6e5_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h7f98852_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.24.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.7.22-hbcca054_0.conda @@ -800,12 +769,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-23.5.26-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.6.0-h6f12383_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/just-1.15.0-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda @@ -863,72 +837,57 @@ 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/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-hcb278e6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.18.2-hb753e55_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.2-h4b38347_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-28.9-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.06.02-h2873b5e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.1-h06160fa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-h2797004_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.1.10-h9fff704_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.13-h31becfc_0.conda @@ -943,7 +902,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.2-h07bb24a_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/black-24.2.0-py311hec3470c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda @@ -951,12 +909,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/just-1.24.0-h1d8f897_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda @@ -1014,101 +977,55 @@ 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/maturin-1.5.1-py311h06e5ef9_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4-h0425590_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-h75d905f_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.2.2-py311he69e3a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_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/noarch/packaging-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.1.10-he8610fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.10-h5ed86db_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.9-had988b7_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.10-h10d778d_0.conda @@ -1123,7 +1040,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.0-h88f2ebf_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.210-heeba50e_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h0d85af4_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.24.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2023.7.22-h8857fd0_0.conda @@ -1131,12 +1047,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-23.5.26-he965462_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.6.0-h8ac2a54_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/just-1.15.0-h63b85fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20230802.1-cxx17_h048a20a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-h1aaacd4_3_cpu.conda @@ -1186,67 +1107,52 @@ 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/maturin-1.5.1-py311h24bb903_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4-hf0c8a7f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.18.2-h2713218_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h9ab30d4_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.06.02-hd34609a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.1.10-h225ccf5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hef22860_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.16.20-h63b85fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.10-h8e8137d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.9-hb1772db_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.10-h93a5062_0.conda @@ -1261,7 +1167,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.0-hcc526ff_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.210-ha042220_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h3422bc3_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.24.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2023.7.22-hf0a4a13_0.conda @@ -1269,12 +1174,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-23.5.26-h13dd4ca_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.6.0-h6da1cb0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.15.0-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20230802.1-cxx17_h13dd4ca_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h4ce3932_3_cpu.conda @@ -1324,67 +1234,52 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - 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/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h7ea286d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.18.2-h7ed3092_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h7c018df_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.06.02-h6135d0a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.1.10-h17c5cce_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hb31c410_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.16.20-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_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/noarch/packaging-23.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.13-hcfcfb64_0.conda @@ -1399,17 +1294,21 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h8ffe710_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2023.7.22-h56e8100_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2023.2.0-h57928b3_50496.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/just-1.15.0-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-hd01637b_10_cpu.conda @@ -1456,36 +1355,52 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2022.1.0-h6a75c08_874.tar.bz2 - 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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.1.10-hfb803bf_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.10.0-h91493d7_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.16.20-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h64f974e_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.36.32532-hdcecf7f_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.36.32532-h05e6639_17.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a - - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c - - pypi: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be - - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl packages: - kind: conda name: _libgcc_mutex @@ -1533,10 +1448,24 @@ packages: license_family: BSD size: 23712 timestamp: 1650670790230 +- kind: conda + name: _sysroot_linux-aarch64_curr_repodata_hack + version: '4' + build: h57d6b7b_14 + build_number: 14 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/_sysroot_linux-aarch64_curr_repodata_hack-4-h57d6b7b_14.conda + sha256: edac93a8e3beb9383abf508f66085505950bc89962116ef149558350a6213749 + md5: 18f0bdf689b6f345fecddbebaed945d6 + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0 + license_family: GPL + size: 21238 + timestamp: 1708000885951 - kind: pypi name: argcomplete version: 3.2.3 - url: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl#sha256=c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c + url: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl sha256: c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c requires_dist: - coverage ; extra == 'test' @@ -3613,6 +3542,20 @@ packages: license_family: APACHE size: 3466426 timestamp: 1709092708128 +- kind: conda + name: binutils + version: '2.40' + build: h64c2a2e_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.40-h64c2a2e_0.conda + sha256: 624f6e9dd9cf651d9fd6ed3a7c1af38ea60aaa3213b35f14c088d8de37ffda5e + md5: 50083e4c6e024fcb0b0dd195204276a3 + depends: + - binutils_impl_linux-aarch64 >=2.40,<2.41.0a0 + license: GPL-3.0-only + license_family: GPL + size: 30742 + timestamp: 1674833883570 - kind: conda name: binutils version: '2.40' @@ -3636,12 +3579,27 @@ packages: sha256: a7e0ea2b71a5b03d82e5a58fb6b612ab1c44d72ce161f9aa441f7ba467cd4c8d md5: 33084421a8c0af6aef1b439707f7662a depends: - - ld_impl_linux-64 2.40 h41732ed_0 - - sysroot_linux-64 + - ld_impl_linux-64 2.40 h41732ed_0 + - sysroot_linux-64 + license: GPL-3.0-only + license_family: GPL + size: 5414922 + timestamp: 1674833958334 +- kind: conda + name: binutils_impl_linux-aarch64 + version: '2.40' + build: h870a726_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.40-h870a726_0.conda + sha256: 43a69e65a7d66fe9f6f17f71814eef807c94f2bc60c7892e6658498cb3759e13 + md5: 1945203dbddc28b0080c5129a3a704b1 + depends: + - ld_impl_linux-aarch64 2.40 h2d8c526_0 + - sysroot_linux-aarch64 license: GPL-3.0-only license_family: GPL - size: 5414922 - timestamp: 1674833958334 + size: 5535072 + timestamp: 1674833858298 - kind: conda name: binutils_linux-64 version: '2.40' @@ -3659,131 +3617,21 @@ packages: size: 28178 timestamp: 1694604071236 - kind: conda - name: black - version: 24.2.0 - build: py311h1ea47a8_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/black-24.2.0-py311h1ea47a8_0.conda - sha256: b87464ade65b64177d73c63f16f2ec8f04b46ee4851db366b36e6c23383fd6d1 - md5: bace117309e02f00843794f9d7eebca2 - depends: - - click >=8.0.0 - - mypy_extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9 - - platformdirs >=2 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 402645 - timestamp: 1708248678003 -- kind: conda - name: black - version: 24.2.0 - build: py311h267d04e_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/black-24.2.0-py311h267d04e_0.conda - sha256: 5be58d2bd471adf44c3ef37f7909b2c27538a9ab63ee465f0b67652f42ea89cb - md5: 50648218d4ca9f1728c93f72f659a7a3 - depends: - - click >=8.0.0 - - mypy_extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9 - - platformdirs >=2 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 385007 - timestamp: 1708251716849 -- kind: conda - name: black - version: 24.2.0 - build: py311h38be061_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/black-24.2.0-py311h38be061_0.conda - sha256: a8f4dca5689162914c76d6c798d43c346ea6d0c567ee3b83278d7c602fcc334e - md5: da18066416bcacf1ff2f644f4c4ec90d - depends: - - click >=8.0.0 - - mypy_extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9 - - platformdirs >=2 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 385178 - timestamp: 1708248412394 -- kind: conda - name: black - version: 24.2.0 - build: py311h6eed73b_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/black-24.2.0-py311h6eed73b_0.conda - sha256: 2fd6b25d8d3f0bc3e91715bafcd0c38121974b61248b7b812fd850abfa41c7ed - md5: 816ffba077c301e7b2710a1dd76e6e63 - depends: - - click >=8.0.0 - - mypy_extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9 - - platformdirs >=2 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 386618 - timestamp: 1708248490085 -- kind: conda - name: black - version: 24.2.0 - build: py311hec3470c_0 + name: binutils_linux-aarch64 + version: '2.40' + build: h95d2017_3 + build_number: 3 subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/black-24.2.0-py311hec3470c_0.conda - sha256: 44600ae70a8fca4ea1fda9c86818e2a5a58c23b3b03a27b1de9079f5f022c193 - md5: 5f1d486090d858df5fd90f2137b27e53 - depends: - - click >=8.0.0 - - mypy_extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9 - - platformdirs >=2 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - size: 386639 - timestamp: 1708248423560 -- kind: conda - name: blackdoc - version: 0.3.8 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/blackdoc-0.3.8-pyhd8ed1ab_0.tar.bz2 - sha256: ec7b75c0f88db3e8c8b506ec48fa4fa210b0c1d09b0969df726a68b5563d151d - md5: c03749cb0d5874fd5b9c1620a3d230c4 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.40-h95d2017_3.conda + sha256: cd839ad41a573ebd84552b9ed946ea99ae48f8a07f4e38b8725022ff881f767c + md5: 561a4c45334781c962db079457e6f0f0 depends: - - black * - - importlib-metadata * - - more-itertools * - - python >=3.7 - - rich * - - tomli * - arch: x86_64 - platform: win - license: MIT - license_family: MIT - purls: - - pkg:pypi/blackdoc - size: 30092 - timestamp: 1667565048643 + - binutils_impl_linux-aarch64 2.40.* + - sysroot_linux-aarch64 + license: BSD-3-Clause + license_family: BSD + size: 28888 + timestamp: 1710259827989 - kind: conda name: bzip2 version: 1.0.8 @@ -4050,6 +3898,21 @@ packages: license: BSD size: 6375 timestamp: 1701504699534 +- kind: conda + name: c-compiler + version: 1.6.0 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.6.0-h31becfc_0.conda + sha256: 36bc9d1673939980e7692ccce27e677dd4477d4c727ea173ec4210605b73927d + md5: b98866e63b17433ea5921a826c93cb97 + depends: + - binutils + - gcc + - gcc_linux-aarch64 12.* + license: BSD + size: 6213 + timestamp: 1689097449087 - kind: conda name: c-compiler version: 1.6.0 @@ -4268,6 +4131,29 @@ packages: license_family: Other size: 1124537 timestamp: 1706798177156 +- kind: conda + name: clang + version: 16.0.6 + build: h250cd41_6 + build_number: 6 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-16.0.6-h250cd41_6.conda + sha256: d9e6dac05b9a81297c238223dd8cc455056fe6fff63569e78e662805f39cc3dc + md5: a9943555a36406f13c3b4d700bd42513 + depends: + - binutils_impl_linux-aarch64 + - clang-16 16.0.6 default_hb368394_6 + - libgcc-devel_linux-aarch64 + - sysroot_linux-aarch64 + constrains: + - clang-tools 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22054 + timestamp: 1711067413789 - kind: conda name: clang version: 16.0.6 @@ -4376,6 +4262,29 @@ packages: license_family: Apache size: 712582 timestamp: 1704262190912 +- kind: conda + name: clang-16 + version: 16.0.6 + build: default_hb368394_6 + build_number: 6 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-16-16.0.6-default_hb368394_6.conda + sha256: bf9d113e63372632c51847c2f1e97e01d75ea9a3ef4ded7812e46e1176533871 + md5: 840768da10bb31e766556f198e111e42 + depends: + - libclang-cpp16 16.0.6 default_hb368394_6 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + constrains: + - clangxx 16.0.6 + - clang-tools 16.0.6 + - clangdev 16.0.6 + - llvm-tools 16.0.6 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 709685 + timestamp: 1711067335599 - kind: conda name: clang-16 version: 16.0.6 @@ -4855,47 +4764,6 @@ packages: license_family: BSD size: 19330 timestamp: 1706832814124 -- kind: conda - name: click - version: 8.1.7 - build: unix_pyh707e725_0 - subdir: osx-arm64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-unix_pyh707e725_0.conda - sha256: f0016cbab6ac4138a429e28dbcb904a90305b34b3fe41a9b89d697c90401caec - md5: f3ad426304898027fc619827ff428eca - depends: - - __unix * - - python >=3.8 - arch: aarch64 - platform: osx - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/click - size: 84437 - timestamp: 1692311973840 -- kind: conda - name: click - version: 8.1.7 - build: win_pyh7428d3b_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/click-8.1.7-win_pyh7428d3b_0.conda - sha256: 90236b113b9a20041736e80b80ee965167f9aac0468315c55e2bad902d673fb0 - md5: 3549ecbceb6cd77b91a105511b7d0786 - depends: - - __win * - - colorama * - - python >=3.8 - arch: x86_64 - platform: win - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/click - size: 85051 - timestamp: 1692312207348 - kind: conda name: cmake version: 3.27.6 @@ -5034,7 +4902,7 @@ packages: - kind: pypi name: colorlog version: 6.8.2 - url: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl#sha256=4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 + url: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl sha256: 4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33 requires_dist: - colorama ; sys_platform == 'win32' @@ -5131,6 +4999,21 @@ packages: license: BSD size: 6179 timestamp: 1689097484095 +- kind: conda + name: cxx-compiler + version: 1.6.0 + build: h2a328a1_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/cxx-compiler-1.6.0-h2a328a1_0.conda + sha256: aebe297f355fb3a5101eb11a5233d94c3445d2f1bbf4c0d7e3ff88b98d399694 + md5: 3847c922cacfe5a3d7ee663ffde014a4 + depends: + - c-compiler 1.6.0 h31becfc_0 + - gxx + - gxx_linux-aarch64 12.* + license: BSD + size: 6220 + timestamp: 1689097451413 - kind: conda name: cxx-compiler version: 1.6.0 @@ -5162,7 +5045,7 @@ packages: - kind: pypi name: distlib version: 0.3.8 - url: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl#sha256=034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 + url: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl sha256: 034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 - kind: conda name: doxygen @@ -5286,9 +5169,9 @@ packages: timestamp: 1704921321122 - kind: pypi name: filelock - version: 3.13.3 - url: https://files.pythonhosted.org/packages/8b/69/acdf492db27dea7be5c63053230130e0574fd8a376de3555d5f8bbc3d3ad/filelock-3.13.3-py3-none-any.whl#sha256=5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb - sha256: 5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb + version: 3.13.4 + url: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + sha256: 404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f requires_dist: - furo >=2023.9.10 ; extra == 'docs' - sphinx-autodoc-typehints !=1.23.4, >=1.25.2 ; extra == 'docs' @@ -5395,6 +5278,21 @@ packages: license_family: BSD size: 27086 timestamp: 1694604171830 +- kind: conda + name: gcc + version: 12.3.0 + build: he80d746_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-12.3.0-he80d746_3.conda + sha256: b85e2482a76145f01932513304ee1eca58115f48a4d02107035272c2a2c4bed2 + md5: fe4071326b5c555a0c87081bb0427724 + depends: + - gcc_impl_linux-aarch64 12.3.0.* + license: BSD-3-Clause + license_family: BSD + size: 27793 + timestamp: 1710259900584 - kind: conda name: gcc_impl_linux-64 version: 12.3.0 @@ -5416,6 +5314,27 @@ packages: license_family: GPL size: 51856676 timestamp: 1706820019081 +- kind: conda + name: gcc_impl_linux-aarch64 + version: 12.3.0 + build: hcde2664_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-12.3.0-hcde2664_5.conda + sha256: c9d333af50695a002173fbfd906278b7709993139e65523c484853a70e769d06 + md5: 07e2aacd52ad96db11f72558be9ad6ab + depends: + - binutils_impl_linux-aarch64 >=2.39 + - libgcc-devel_linux-aarch64 12.3.0 h8b5ab12_105 + - libgcc-ng >=12.3.0 + - libgomp >=12.3.0 + - libsanitizer 12.3.0 h8ebda82_5 + - libstdcxx-ng >=12.3.0 + - sysroot_linux-aarch64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 47107717 + timestamp: 1706820306980 - kind: conda name: gcc_linux-64 version: 12.3.0 @@ -5433,6 +5352,23 @@ packages: license_family: BSD size: 30351 timestamp: 1694604476800 +- kind: conda + name: gcc_linux-aarch64 + version: 12.3.0 + build: h9622932_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-12.3.0-h9622932_3.conda + sha256: fabd666508f2c814d9372a46e5abb19bd5f53b66e67c9fee0d577fc0bdc292f2 + md5: 0f77e0c3b8902a8c44b9814701e6f0a5 + depends: + - binutils_linux-aarch64 2.40 h95d2017_3 + - gcc_impl_linux-aarch64 12.3.0.* + - sysroot_linux-aarch64 + license: BSD-3-Clause + license_family: BSD + size: 30943 + timestamp: 1710260225977 - kind: conda name: gflags version: 2.2.2 @@ -5735,6 +5671,22 @@ packages: license_family: BSD size: 26539 timestamp: 1694604501713 +- kind: conda + name: gxx + version: 12.3.0 + build: he80d746_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx-12.3.0-he80d746_3.conda + sha256: b26da37112ab50b8a7ae316ccd19451c486e6f4042011fa0292b97baa4140d2a + md5: 73d7d6aaf1c41cefe3585ddd89eb4035 + depends: + - gcc 12.3.0.* + - gxx_impl_linux-aarch64 12.3.0.* + license: BSD-3-Clause + license_family: BSD + size: 27304 + timestamp: 1710260259320 - kind: conda name: gxx_impl_linux-64 version: 12.3.0 @@ -5752,6 +5704,23 @@ packages: license_family: GPL size: 12742481 timestamp: 1706820327015 +- kind: conda + name: gxx_impl_linux-aarch64 + version: 12.3.0 + build: hcde2664_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-12.3.0-hcde2664_5.conda + sha256: 0efcc3ecf96692c08a9158b2b28a70b13e1c0ec5f301c026a302fe47b74f8b3c + md5: 88d365e3c078988887fc92e58228a5b4 + depends: + - gcc_impl_linux-aarch64 12.3.0 hcde2664_5 + - libstdcxx-devel_linux-aarch64 12.3.0 h8b5ab12_105 + - sysroot_linux-aarch64 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 11490051 + timestamp: 1706820597770 - kind: conda name: gxx_linux-64 version: 12.3.0 @@ -5770,6 +5739,24 @@ packages: license_family: BSD size: 28640 timestamp: 1694604524890 +- kind: conda + name: gxx_linux-aarch64 + version: 12.3.0 + build: h3d1e521_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-12.3.0-h3d1e521_3.conda + sha256: 9d2c7649e9341ed218aef701e1db15d8cea4e70d19c4dbf8f9efe06d2c5a0b14 + md5: f1ac1d0d0b1afcbe3a8ad3a0b33aeaf4 + depends: + - binutils_linux-aarch64 2.40 h95d2017_3 + - gcc_linux-aarch64 12.3.0 h9622932_3 + - gxx_impl_linux-aarch64 12.3.0.* + - sysroot_linux-aarch64 + license: BSD-3-Clause + license_family: BSD + size: 29283 + timestamp: 1710260291746 - kind: conda name: icu version: '73.2' @@ -5824,40 +5811,6 @@ packages: license_family: MIT size: 11787527 timestamp: 1692901622519 -- kind: conda - name: importlib-metadata - version: 4.13.0 - build: pyha770c72_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-4.13.0-pyha770c72_0.conda - sha256: 81c149c12dc6dadc9836873282fa51a9c16507da94e89ccc6f3bdeb870b1cb73 - md5: 80d2ed5fd22d7eb804f70c03f0d40b45 - depends: - - python >=3.8 - - zipp >=0.5 - arch: x86_64 - platform: win - license: Apache-2.0 - license_family: APACHE - size: 25527 - timestamp: 1676330831614 -- kind: conda - name: importlib-metadata - version: 7.0.2 - build: pyha770c72_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-7.0.2-pyha770c72_0.conda - sha256: 9a26136d2cc81ccac209d6ae24281ceba3365fe34e34b2c45570f2a96e9d9c1b - md5: b050a4bb0e90ebd6e7fa4093d6346867 - depends: - - python >=3.8 - - zipp >=0.5 - license: Apache-2.0 - license_family: APACHE - size: 26900 - timestamp: 1709821273570 - kind: conda name: iniconfig version: 2.0.0 @@ -5876,154 +5829,35 @@ packages: purls: - pkg:pypi/iniconfig size: 11101 - timestamp: 1673103208955 -- kind: conda - name: intel-openmp - version: 2023.2.0 - build: h57928b3_50496 - build_number: 50496 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2023.2.0-h57928b3_50496.conda - sha256: 38367c264bace64d6f939c1170cda3aba2eb0fb2300570c16a8c63aff9ca8031 - md5: 519f9c42672f1e8a334ec9471e93f4fe - arch: x86_64 - platform: win - license: LicenseRef-ProprietaryIntel - license_family: Proprietary - size: 2520627 - timestamp: 1695994411378 -- kind: conda - name: intel-openmp - version: 2024.0.0 - build: h57928b3_49841 - build_number: 49841 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.0.0-h57928b3_49841.conda - sha256: 6ee8eb9080bb3268654e015dd17ad79d0c1ea98b2eee6b928ecd27f01d6b38e8 - md5: e3255c8cdaf1d52f15816d1970f9c77a - license: LicenseRef-ProprietaryIntel - license_family: Proprietary - size: 2325424 - timestamp: 1706182537883 -- kind: conda - name: just - version: 1.15.0 - build: h5ef7bb8_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.15.0-h5ef7bb8_0.conda - sha256: 457c259b027cd035aa9fa11d9eeedfbe2298e6cfcebe6c2e1f4cdfce47cc5fc9 - md5: a283dd994c0181833cd289e1a0d374e5 - arch: aarch64 - platform: osx - license: CC0-1.0 - size: 967137 - timestamp: 1697287585467 -- kind: conda - name: just - version: 1.15.0 - build: h63b85fc_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/just-1.15.0-h63b85fc_0.conda - sha256: 32cfa40bed1c71342488e02c4c984c7e7c515645ac7286b2e866afbd017e2234 - md5: 9d17474a2fd0286a95e472369a27f4a0 - arch: x86_64 - platform: osx - license: CC0-1.0 - size: 1045840 - timestamp: 1697287468425 -- kind: conda - name: just - version: 1.15.0 - build: h7f3b576_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/just-1.15.0-h7f3b576_0.conda - sha256: c70bc660ef68da0a7128a133ac3d41b1aa4a6f8ace1894b11b691ae2464ad3ab - md5: c99de86aee5b1280526e717881fb31f4 - depends: - - m2w64-gcc-libs * - - m2w64-gcc-libs-core * - arch: x86_64 - platform: win - license: CC0-1.0 - size: 1075396 - timestamp: 1697288439231 -- kind: conda - name: just - version: 1.15.0 - build: he8a937b_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/just-1.15.0-he8a937b_0.conda - sha256: 3df9d0c1674c41699533211dc43b6f85a5650a987746faad659eb3c222cd6168 - md5: 7e60e76dd956032a16543773f1488955 - depends: - - libgcc-ng >=12 - arch: x86_64 - platform: linux - license: CC0-1.0 - size: 1119533 - timestamp: 1697287198405 -- kind: conda - name: just - version: 1.22.1 - build: h5ef7bb8_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/just-1.22.1-h5ef7bb8_0.conda - sha256: a2ba21abf4f759e11df357b730e9d5759ba27bce923567b352967821cf22353d - md5: d6b29d5e3c1d331f5776cfdcea3dd435 - license: CC0-1.0 - size: 1028938 - timestamp: 1704893781124 -- kind: conda - name: just - version: 1.22.1 - build: h63b85fc_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/just-1.22.1-h63b85fc_0.conda - sha256: 445e451166af113535941c7fdc4f923a32f4c41f08aa019dd9e4e44f415abf09 - md5: 70268351f5a226d550b599947bf5629a - license: CC0-1.0 - size: 1103475 - timestamp: 1704893343411 -- kind: conda - name: just - version: 1.22.1 - build: h7f3b576_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/just-1.22.1-h7f3b576_0.conda - sha256: c6e5e5281753f0f4db195b614e2448bbfbe0efcc9e5746eb332894e3e8d90478 - md5: d2fa27c35c5648f9f3845956ec3baf7b - depends: - - m2w64-gcc-libs - - m2w64-gcc-libs-core - license: CC0-1.0 - size: 1138631 - timestamp: 1704894003304 + timestamp: 1673103208955 - kind: conda - name: just - version: 1.22.1 - build: he8a937b_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/just-1.22.1-he8a937b_0.conda - sha256: 759ded3ce474a1fdb68534edeb2eefd5646903de80220a01ca92f7e7226c6bd4 - md5: 0b30315c6c3f61e48f6a71609ded6a96 - depends: - - libgcc-ng >=12 - license: CC0-1.0 - size: 1178083 - timestamp: 1704893025811 + name: intel-openmp + version: 2023.2.0 + build: h57928b3_50496 + build_number: 50496 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2023.2.0-h57928b3_50496.conda + sha256: 38367c264bace64d6f939c1170cda3aba2eb0fb2300570c16a8c63aff9ca8031 + md5: 519f9c42672f1e8a334ec9471e93f4fe + arch: x86_64 + platform: win + license: LicenseRef-ProprietaryIntel + license_family: Proprietary + size: 2520627 + timestamp: 1695994411378 - kind: conda - name: just - version: 1.24.0 - build: h1d8f897_0 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/just-1.24.0-h1d8f897_0.conda - sha256: 581e83c4f9aa9663244b767e49a857374019d71f589567611be2870a95a05f52 - md5: 0a0e604e2ff4c1a207f5a2fbc2df154c - depends: - - libgcc-ng >=12 - license: CC0-1.0 - size: 1104293 - timestamp: 1708246328468 + name: intel-openmp + version: 2024.0.0 + build: h57928b3_49841 + build_number: 49841 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.0.0-h57928b3_49841.conda + sha256: 6ee8eb9080bb3268654e015dd17ad79d0c1ea98b2eee6b928ecd27f01d6b38e8 + md5: e3255c8cdaf1d52f15816d1970f9c77a + license: LicenseRef-ProprietaryIntel + license_family: Proprietary + size: 2325424 + timestamp: 1706182537883 - kind: conda name: kernel-headers_linux-64 version: 2.6.32 @@ -6040,6 +5874,24 @@ packages: license_family: GPL size: 709007 timestamp: 1689214970644 +- kind: conda + name: kernel-headers_linux-aarch64 + version: 4.18.0 + build: h5b4a56d_14 + build_number: 14 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h5b4a56d_14.conda + sha256: c44b178b38de4126d50a71501ac9e1c49119bb7aba9d09ab861ba12bc8d4e21c + md5: 9b0446ad203105e5bbdda273a78d1d0f + depends: + - _sysroot_linux-aarch64_curr_repodata_hack 4.* + constrains: + - sysroot_linux-aarch64 ==2.17 + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0 + license_family: GPL + size: 1114567 + timestamp: 1708000894708 - kind: conda name: keyutils version: 1.6.1 @@ -8319,6 +8171,23 @@ packages: license_family: Apache size: 17600643 timestamp: 1706895662107 +- kind: conda + name: libclang-cpp16 + version: 16.0.6 + build: default_hb368394_6 + build_number: 6 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp16-16.0.6-default_hb368394_6.conda + sha256: fff382cd97b0188d4c093a6f3362901735c32be97cb91436de737336f359d4ec + md5: 6f5c339e6522967a32f608620e0424a3 + depends: + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 17589928 + timestamp: 1711067170200 - kind: conda name: libclang-cpp16 version: 16.0.6 @@ -9068,6 +8937,20 @@ packages: license_family: GPL size: 2568967 timestamp: 1706819720613 +- kind: conda + name: libgcc-devel_linux-aarch64 + version: 12.3.0 + build: h8b5ab12_105 + build_number: 105 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/libgcc-devel_linux-aarch64-12.3.0-h8b5ab12_105.conda + sha256: 1ff691733d28774c8f56e0159fe0fffc56b1cf4de64630501f6c3b8438aa893f + md5: cb2ce837146463f83f24f52face3ca9d + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 285097 + timestamp: 1706819953671 - kind: conda name: libgcc-ng version: 13.2.0 @@ -11395,6 +11278,21 @@ packages: license_family: GPL size: 3890717 timestamp: 1706819904612 +- kind: conda + name: libsanitizer + version: 12.3.0 + build: h8ebda82_5 + build_number: 5 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libsanitizer-12.3.0-h8ebda82_5.conda + sha256: a30e1e297218c097ee715cc52bf4711e3f21d6f4fcf2a7e3e1ebae9a65903d04 + md5: b23f5de2b160df4b83a5b16f4deab34a + depends: + - libgcc-ng >=12.3.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 3912550 + timestamp: 1706820192702 - kind: conda name: libsqlite version: 3.45.1 @@ -11558,6 +11456,20 @@ packages: license_family: GPL size: 11597918 timestamp: 1706819775415 +- kind: conda + name: libstdcxx-devel_linux-aarch64 + version: 12.3.0 + build: h8b5ab12_105 + build_number: 105 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/libstdcxx-devel_linux-aarch64-12.3.0-h8b5ab12_105.conda + sha256: f38714920c850eac02b4b8175146188a3657c7ea5a3be22ae644b9d5e2356663 + md5: 47f23759d39c3d993dc189ce4ab7f79c + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 10380824 + timestamp: 1706820045043 - kind: conda name: libstdcxx-ng version: 13.2.0 @@ -12375,26 +12287,6 @@ packages: license: MIT, BSD size: 31928 timestamp: 1608166099896 -- kind: conda - name: markdown-it-py - version: 3.0.0 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_0.conda - sha256: c041b0eaf7a6af3344d5dd452815cdc148d6284fec25a4fa3f4263b3a021e962 - md5: 93a8e71256479c62074356ef6ebf501b - depends: - - mdurl >=0.1,<1 - - python >=3.8 - arch: x86_64 - platform: win - license: MIT - license_family: MIT - purls: - - pkg:pypi/markdown-it-py - size: 64356 - timestamp: 1686175179621 - kind: conda name: maturin version: 1.5.1 @@ -12488,42 +12380,6 @@ packages: license_family: MIT size: 4498445 timestamp: 1711044494832 -- kind: conda - name: mdurl - version: 0.1.0 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.0-pyhd8ed1ab_0.tar.bz2 - sha256: c678b9194e025b1fb665bec30ee20aab93399203583875b1dcc0a3b52a8f5523 - md5: f8dab71fdc13b1bf29a01248b156d268 - depends: - - python >=3.6 - arch: x86_64 - platform: win - license: MIT - license_family: MIT - purls: - - pkg:pypi/mdurl - size: 13707 - timestamp: 1639515992326 -- kind: conda - name: mdurl - version: 0.1.2 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/mdurl-0.1.2-pyhd8ed1ab_0.conda - sha256: 64073dfb6bb429d52fff30891877b48c7ec0f89625b1bf844905b66a81cce6e1 - md5: 776a8dd9e824f77abac30e6ef43a8f7a - depends: - - python >=3.6 - license: MIT - license_family: MIT - purls: - - pkg:pypi/mdurl - size: 14680 - timestamp: 1704317789138 - kind: conda name: meilisearch version: 1.5.1 @@ -12572,42 +12428,6 @@ packages: license_family: Proprietary size: 108505947 timestamp: 1701973497498 -- kind: conda - name: more-itertools - version: 10.1.0 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.1.0-pyhd8ed1ab_0.conda - sha256: 07ce65497dec537e490992758934ddbc4fb5ed9285b41387a7cca966f1a98a0f - md5: 8549fafed0351bbfaa1ddaa15fdf9b4e - depends: - - python >=3.8 - arch: x86_64 - platform: win - license: MIT - license_family: MIT - purls: - - pkg:pypi/more-itertools - size: 53654 - timestamp: 1691087125209 -- kind: conda - name: more-itertools - version: 10.2.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/more-itertools-10.2.0-pyhd8ed1ab_0.conda - sha256: 9e49e9484ff279453f0b55323a3f0c7cb97440c74f69eecda1f4ad29fae5cd3c - md5: d5c98e9706fdc5328d49a9bf2ce5fb42 - depends: - - python >=3.8 - license: MIT - license_family: MIT - purls: - - pkg:pypi/more-itertools - size: 54469 - timestamp: 1704738585811 - kind: conda name: msys2-conda-epoch version: '20160418' @@ -13008,7 +12828,7 @@ packages: - kind: pypi name: nox version: 2024.3.2 - url: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl#sha256=e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be + url: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl sha256: e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be requires_dist: - argcomplete <4.0, >=1.9.4 @@ -13449,42 +13269,6 @@ packages: license_family: GPL size: 94048 timestamp: 1673473024463 -- kind: conda - name: pathspec - version: 0.11.2 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.11.2-pyhd8ed1ab_0.conda - sha256: 7bcfa6d86359d45572ba9ccaeaedc04b0452e2654fe44b6fe378d0d37b8745e1 - md5: e41debb259e68490e3ab81e46b639ab6 - depends: - - python >=3.7 - arch: x86_64 - platform: win - license: MPL-2.0 - license_family: MOZILLA - purls: - - pkg:pypi/pathspec - size: 38649 - timestamp: 1690598108100 -- kind: conda - name: pathspec - version: 0.12.1 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pathspec-0.12.1-pyhd8ed1ab_0.conda - sha256: 4e534e66bfe8b1e035d2169d0e5b185450546b17e36764272863e22e0370be4d - md5: 17064acba08d3686f1135b5ec1b32b12 - depends: - - python >=3.7 - license: MPL-2.0 - license_family: MOZILLA - purls: - - pkg:pypi/pathspec - size: 41173 - timestamp: 1702250135032 - kind: conda name: pip version: 23.2.1 @@ -13525,43 +13309,22 @@ packages: - pkg:pypi/pip size: 1398245 timestamp: 1706960660581 -- kind: conda - name: platformdirs - version: 3.11.0 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/platformdirs-3.11.0-pyhd8ed1ab_0.conda - sha256: b3d809ff5a18ee8514bba8bc05a23b4cdf1758090a18a2cf742af38aed405144 - md5: 8f567c0a74aa44cf732f15773b4083b0 - depends: - - python >=3.7 - - typing-extensions >=4.6.3 - arch: x86_64 - platform: win - license: MIT - license_family: MIT - purls: - - pkg:pypi/platformdirs - size: 19985 - timestamp: 1696272419779 -- kind: conda +- kind: pypi name: platformdirs version: 4.2.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/platformdirs-4.2.0-pyhd8ed1ab_0.conda - sha256: 2ebfb971236ab825dd79dd6086ea742a9901008ffb9c6222c1f2b5172a8039d3 - md5: a0bc3eec34b0fab84be6b2da94e98e20 - depends: - - python >=3.8 - license: MIT - license_family: MIT - purls: - - pkg:pypi/platformdirs - size: 20210 - timestamp: 1706713564353 + url: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + sha256: 0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068 + requires_dist: + - furo >=2023.9.10 ; extra == 'docs' + - proselint >=0.13 ; extra == 'docs' + - sphinx-autodoc-typehints >=1.25.2 ; extra == 'docs' + - sphinx >=7.2.6 ; extra == 'docs' + - appdirs ==1.4.4 ; extra == 'test' + - covdefaults >=2.3 ; extra == 'test' + - pytest-cov >=4.1 ; extra == 'test' + - pytest-mock >=3.12 ; extra == 'test' + - pytest >=7.4.3 ; extra == 'test' + requires_python: '>=3.8' - kind: conda name: pluggy version: 1.3.0 @@ -13780,6 +13543,23 @@ packages: license: LGPL 2 size: 144301 timestamp: 1537755684331 +- kind: conda + name: py-cpuinfo + version: 9.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + sha256: 1bb0459fdebf2f3155ee511e99097c5506ef206acbdd871b74ae9fc4b0c4a019 + md5: 6f6d42b894118f8378fce11887ccdaff + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/py-cpuinfo + size: 24947 + timestamp: 1666774595872 - kind: conda name: pyarrow version: 14.0.2 @@ -14012,42 +13792,6 @@ packages: license_family: APACHE size: 4074654 timestamp: 1706611920192 -- kind: conda - name: pygments - version: 2.16.1 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pygments-2.16.1-pyhd8ed1ab_0.conda - sha256: 3f0f0fadc6084960ec8cc00a32a03529c562ffea3b527eb73b1653183daad389 - md5: 40e5cb18165466773619e5c963f00a7b - depends: - - python >=3.7 - arch: x86_64 - platform: win - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/pygments - size: 853439 - timestamp: 1691408777841 -- kind: conda - name: pygments - version: 2.17.2 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pygments-2.17.2-pyhd8ed1ab_0.conda - sha256: af5f8867450dc292f98ea387d4d8945fc574284677c8f60eaa9846ede7387257 - md5: 140a7f159396547e9799aa98f9f0742e - depends: - - python >=3.7 - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/pygments - size: 860425 - timestamp: 1700608076927 - kind: conda name: pytest version: 7.4.2 @@ -14125,6 +13869,25 @@ packages: - pkg:pypi/pytest size: 255523 timestamp: 1709992719691 +- kind: conda + name: pytest-benchmark + version: 4.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + sha256: e08bba57295c6ca9cbc265347c312aaab1f0cf66f4e8ff53a2461f32c397536f + md5: 8c3168375e2ac100c17b133f4e2eb536 + depends: + - py-cpuinfo + - pytest >=3.8 + - python >=3.5 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/pytest-benchmark + size: 39571 + timestamp: 1666782598879 - kind: conda name: python version: 3.11.8 @@ -14620,70 +14383,14 @@ packages: license_family: MIT size: 185144 timestamp: 1693455923632 -- kind: conda - name: rich - version: 13.6.0 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/rich-13.6.0-pyhd8ed1ab_0.conda - sha256: a2f8838a75ab8c2c1da0a813c7569d4f6efba0d2b5dc3a7659e2cb6d96bd8e19 - md5: 3ca4829f40710f581ca1d76bc907e99f - depends: - - markdown-it-py >=2.2.0 - - pygments >=2.13.0,<3.0.0 - - python >=3.7.0 - - typing_extensions >=4.0.0,<5.0.0 - arch: x86_64 - platform: win - license: MIT - license_family: MIT - size: 183200 - timestamp: 1696096819794 -- kind: conda - name: rich - version: 13.7.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.0-pyhd8ed1ab_0.conda - sha256: 4bb25bf1f5664772b2c4c2e3878aa6e7dc2695f97e3da4ee8e47c51e179913bb - md5: d7a11d4f3024b2f4a6e0ae7377dd61e9 - depends: - - markdown-it-py >=2.2.0 - - pygments >=2.13.0,<3.0.0 - - python >=3.7.0 - - typing_extensions >=4.0.0,<5.0.0 - license: MIT - license_family: MIT - size: 184071 - timestamp: 1700160247583 -- kind: conda - name: rich - version: 13.7.1 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/rich-13.7.1-pyhd8ed1ab_0.conda - sha256: 2b26d58aa59e46f933c3126367348651b0dab6e0bf88014e857415bb184a4667 - md5: ba445bf767ae6f0d959ff2b40c20912b - depends: - - markdown-it-py >=2.2.0 - - pygments >=2.13.0,<3.0.0 - - python >=3.7.0 - - typing_extensions >=4.0.0,<5.0.0 - license: MIT - license_family: MIT - size: 184347 - timestamp: 1709150578093 - kind: conda name: ruff - version: 0.2.2 + version: 0.3.5 build: py311h7145743_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.2.2-py311h7145743_0.conda - sha256: 9d532179c68e2151bcf7314e51614316869150ea046b34696d9097f6e853e909 - md5: 155dd63afed91c0e5591b5942544c361 + url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda + sha256: 21d492a207c88672288668018ff931eea06c65625f2660fc4e4985e52243f4e8 + md5: 476ec3ffa92e3178463c666a221b401b depends: - libgcc-ng >=12 - libstdcxx-ng >=12 @@ -14693,16 +14400,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 5717696 - timestamp: 1708223090811 + size: 6286425 + timestamp: 1711999691593 - kind: conda name: ruff - version: 0.2.2 + version: 0.3.5 build: py311h8c97afb_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.2.2-py311h8c97afb_0.conda - sha256: 8bde1e4a82a22376eb3a233cd401a0b3937859f6ff462556f0a69b8daa3e7507 - md5: e74f44bc27321f5cc4a3c628b32e5c67 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda + sha256: 1af91e59adc5bf40a8b5b0e1a2c369286c3e9388179dc76fc2760498a6f2c48c + md5: 8e1fe4c5e7bb5c9a585c57e8cec44d1a depends: - libcxx >=16 - python >=3.11,<3.12.0a0 @@ -14714,16 +14421,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 5280983 - timestamp: 1708223865116 + size: 5764786 + timestamp: 1712000852408 - kind: conda name: ruff - version: 0.2.2 + version: 0.3.5 build: py311hc14472d_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.2.2-py311hc14472d_0.conda - sha256: 0dc322a254ad082f26efdfdc01757f3ae69d1ce30e52149557719dd16d6ba5b1 - md5: 8090ecc1caf5c94bde0dd0966785fc48 + url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda + sha256: 7800532c6daeb465b5847d532cd1244ae86dd1eb95878c28f378d3b0c85d5d47 + md5: d0c971d5173e4d2400ab21f7674d8055 depends: - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 @@ -14734,16 +14441,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 5662517 - timestamp: 1708224151838 + size: 6257429 + timestamp: 1712000640263 - kind: conda name: ruff - version: 0.2.2 + version: 0.3.5 build: py311he69e3a7_0 subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.2.2-py311he69e3a7_0.conda - sha256: 79692d93fd01d2600aad350d34efa4faae33b87f35acce1560de61b4f14cc597 - md5: d43da3e0a735527d540d7f8947ee179b + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda + sha256: db0e13ff550e1afd405487d3aeb14dc534bca8bf62c297323e83a13fb67e92a8 + md5: c3dc02c8cc9a80ca0b34fc86b083e284 depends: - libgcc-ng >=12 - libstdcxx-ng >=12 @@ -14754,16 +14461,16 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 5439861 - timestamp: 1708223383662 + size: 5937629 + timestamp: 1711999839570 - kind: conda name: ruff - version: 0.2.2 + version: 0.3.5 build: py311hfff7943_0 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.2.2-py311hfff7943_0.conda - sha256: 688b47940043c3e9263bf11e0fded7088df7c5bb74d18b8c06c201d2b892d01e - md5: 783e767120acfb225c33c5805f76278d + url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda + sha256: 576c9a798ac3a78e8ea4cddd914f45aa7f1615a0e4393bf4cead8d9808ac97b6 + md5: b5410e0ebf58e4444b4659b1f3ee21fc depends: - libcxx >=16 - python >=3.11,<3.12.0a0 @@ -14774,8 +14481,8 @@ packages: license_family: MIT purls: - pkg:pypi/ruff - size: 5540591 - timestamp: 1708224008985 + size: 6083087 + timestamp: 1712000648440 - kind: conda name: s2n version: 1.4.1 @@ -15032,6 +14739,23 @@ packages: license_family: GPL size: 15277813 timestamp: 1689214980563 +- kind: conda + name: sysroot_linux-aarch64 + version: '2.17' + build: h5b4a56d_14 + build_number: 14 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/sysroot_linux-aarch64-2.17-h5b4a56d_14.conda + sha256: d239232cff55b45a1fbdea9fc660492afca16ba950785d9da3504f16de8fe765 + md5: ba47875acf57f2717bcd55b26f4c3e00 + depends: + - _sysroot_linux-aarch64_curr_repodata_hack 4.* + - kernel-headers_linux-aarch64 4.18.0 h5b4a56d_14 + license: LGPL-2.0-or-later AND LGPL-2.0-or-later WITH exceptions AND GPL-2.0-or-later AND MPL-2.0 + license_family: GPL + size: 16253097 + timestamp: 1708000911838 - kind: conda name: tapi version: 1100.0.11 @@ -15358,23 +15082,6 @@ packages: - pkg:pypi/tomlkit size: 37132 timestamp: 1700046842169 -- kind: conda - name: typing-extensions - version: 4.8.0 - build: hd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.8.0-hd8ed1ab_0.conda - sha256: d6e1dddd0c372218ef15912383d351ac8c73465cbf16238017f0269813cafe2d - md5: 384462e63262a527bda564fa2d9126c0 - depends: - - typing_extensions ==4.8.0 pyha770c72_0 - arch: x86_64 - platform: win - license: PSF-2.0 - license_family: PSF - size: 10104 - timestamp: 1695040958008 - kind: conda name: typing_extensions version: 4.8.0 @@ -15721,7 +15428,7 @@ packages: - kind: pypi name: virtualenv version: 20.25.1 - url: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl#sha256=961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a + url: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl sha256: 961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a requires_dist: - distlib <1, >=0.3.7 @@ -15890,25 +15597,6 @@ packages: license: LGPL-2.1 and GPL-2.0 size: 440555 timestamp: 1660348056328 -- kind: conda - name: zipp - version: 3.17.0 - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/zipp-3.17.0-pyhd8ed1ab_0.conda - sha256: bced1423fdbf77bca0a735187d05d9b9812d2163f60ab426fc10f11f92ecbe26 - md5: 2e4d6bc0b14e10f895fc6791a7d9b26a - depends: - - python >=3.8 - arch: x86_64 - platform: win - license: MIT - license_family: MIT - purls: - - pkg:pypi/zipp - size: 18954 - timestamp: 1695255262261 - kind: conda name: zlib version: 1.2.13 diff --git a/pixi.toml b/pixi.toml index 16a69c46e545..9cc0ef04d145 100644 --- a/pixi.toml +++ b/pixi.toml @@ -56,6 +56,12 @@ rerun-web = { cmd = "cargo run --package rerun-cli --no-default-features --featu # (this looks heavy but takes typically below 0.1s!) rerun-build-web = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --debug" +# Compile the web-viewer wasm and the cli. +# +# This installs the `wasm32-unknown-unknown` rust target if it's not already installed. +# (this looks heavy but takes typically below 0.1s!) +rerun-build-web-cli = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --debug && cargo build --package rerun-cli --no-default-features --features web_viewer" + # Compile and run the web-viewer in release mode via rerun-cli. # # You can also give an argument for what to view (e.g. an .rrd file). @@ -72,41 +78,59 @@ rerun-web-release = { cmd = "cargo run --package rerun-cli --no-default-features # (this looks heavy but takes typically below 0.1s!) rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --release -g" - build-examples = "cargo run -q --locked -p re_build_examples --" +# Code formatting for all languages. +format = { depends_on = ["py-fmt", "cpp-fmt", "toml-fmt", "misc-fmt"] } +fmt = { depends_on = ["format"] } + # Assorted linting tasks fast-lint = "python scripts/fast_lint.py" lint-codegen = "cargo run --package re_types_builder -- --check" # TODO(jleibs): implement lint-cpp-all -lint-cpp-files = "clang-format --dry-run -Werror" lint-rerun = "python scripts/lint.py" lint-rs-files = "rustfmt --edition 2021 --check" lint-rs-all = "cargo fmt --check" -lint-py-fmt-check = "ruff format --check --config rerun_py/pyproject.toml" -lint-py-blackdoc = "blackdoc --check" -lint-py-mypy = "mypy --install-types --non-interactive --no-warn-unused-ignore" -lint-py-ruff = "ruff format --check --config rerun_py/pyproject.toml" -lint-taplo = "taplo fmt --check --diff" + lint-typos = "typos" +# Toml tasks +toml-fmt-check = "taplo fmt --check --diff" +toml-fmt = "taplo fmt" + +# Misc formatting tasks. misc-fmt = "prettier --write '**/*.{yml,yaml,js,css,html}'" misc-fmt-check = "prettier --check '**/*.{yml,yaml,js,css,html}'" -ruff-fmt = "ruff format --config rerun_py/pyproject.toml ." -ruff-fix = "ruff --fix --config rerun_py/pyproject.toml ." -toml-fmt = "taplo fmt" + +# Run first ruff fix, then ruff format, order is important see also https://twitter.com/charliermarsh/status/1717229721954799727 +py-fmt = "ruff check --fix --config rerun_py/pyproject.toml . && ruff format --config rerun_py/pyproject.toml ." +py-fmt-check = "ruff format --check --config rerun_py/pyproject.toml" +py-lint = "mypy --install-types --non-interactive --no-warn-unused-ignore" py-build = "maturin develop --manifest-path rerun_py/Cargo.toml --extras=tests" +py-build-release = "maturin develop --release --manifest-path rerun_py/Cargo.toml --extras=tests" # Run the Python tests. # Don't call this on CI - use `nox` to run tests on all supported Python versions instead. py-test = { cmd = "python -m pytest -vv rerun_py/tests/unit", depends_on = [ "py-build", ] } -py-plot-dashboard = { cmd = "python tests/python/plot_dashboard_stress/main.py", depends_on = [ +py-bench = { cmd = "python -m pytest -c rerun_py/pyproject.toml --benchmark-only", depends_on = [ "py-build", ] } +# Python example utilities +py-run-all-examples = { cmd = "python scripts/run_all.py --skip-build", depends_on = [ + "py-build", +] } +py-run-all-examples-web = { cmd = "python scripts/run_all.py --web --skip-build", depends_on = [ + "rerun-build-web-cli", + "py-build", +] } + +py-plot-dashboard = { cmd = "python tests/python/plot_dashboard_stress/main.py", depends_on = [ + "py-build", +] } rs-plot-dashboard = { cmd = "cargo r -p plot_dashboard_stress --release --" } # Build the documentation search index. @@ -118,6 +142,14 @@ search-index = "cargo run -p re_build_search_index --release --" # Files are stored in the `meilisearch` directory, so you can fully wipe it via `rm -rf meilisearch`. meilisearch = "meilisearch --db-path=./meilisearch/data.ms --dump-dir=./meilisearch/dumps/ --snapshot-dir=./meilisearch/snapshots/ --env=development --no-analytics --experimental-reduce-indexing-memory-usage --master-key=test" +# Update the design_tokens.json used to style the GUI. +# See https://rerun-design-guidelines.netlify.app/tokens for their meanings. +# To update the upstream `design_tokens.json`, modify +# https://github.com/rerun-io/documentation/blob/main/src/utils/tokens.ts and push to main. +download-design-tokens = "curl --fail https://rerun-docs.netlify.app/api/tokens | jq > crates/re_ui/data/design_tokens.json" + +# Update the results of `insta` snapshot regression tests +rs-update-insta-tests = "cargo test && cargo insta review" [feature.cpp.tasks] # All the cpp-* tasks can be configured with environment variables, e.g.: RERUN_WERROR=ON CXX=clang++ @@ -156,6 +188,7 @@ cpp-plot-dashboard = { cmd = "export RERUN_STRICT=1 && ./build/release/tests/cpp ] } cpp-build-and-test-all = { depends_on = ["cpp-build-all", "cpp-test"] } cpp-docs = { cmd = "doxygen docs/Doxyfile && echo '***************\nSuccess!\nOpen ./rerun_cpp/docs/html/index.html in your browser.'", cwd = "rerun_cpp" } +cpp-fmt = "fd --extension h --extension hpp --extension c --extension cpp --exec clang-format -i" [feature.cpp.target.win-64.tasks] cpp-prepare-msvc = "cmake -G 'Visual Studio 17 2022' -B build-msvc -S ." @@ -175,21 +208,20 @@ cpp-prepare-msvc = "cmake -G 'Visual Studio 17 2022' -B build-msvc -S ." # - Last resort, use a feature to conditionally include a dependency (e.g. `taplo`). attrs = ">=23.1.0" -blackdoc = "0.3.8" -clang-tools = "16.0.6" # clang-format +clang-tools = "16.0.6" # clang-format cmake = "3.27.6" flatbuffers = ">=23" gitignore-parser = ">=0.1.9" gitpython = ">=3.1.40" -just = ">=1.15.0" maturin = "1.5.1" mypy = "1.8.0" numpy = ">=1.23,<2" pip = ">=23" pyarrow = "14.0.2" pytest = ">=7" -python = "=3.11" # We use the latest Python version here, so we get the latest mypy etc, EXCEPT 3.12 is too new for some of our examples. We run our CI tests on ALL supported versions though. -ruff = "0.2.2" +pytest-benchmark = ">=4.0.0,<4.1" +python = "=3.11" # We use the latest Python version here, so we get the latest mypy etc, EXCEPT 3.12 is too new for some of our examples. We run our CI tests on ALL supported versions though. +ruff = "0.3.5" semver = ">=2.13,<2.14" typing_extensions = ">4.5" typos = ">=1.16.20" @@ -210,19 +242,7 @@ nox = ">=2024.3.2" # the conda-forge package is (wrongly) tagged as platform-spe patchelf = ">=0.17" meilisearch = "1.5.1.*" # not available for linux-aarch64 -[feature.cpp.target.linux-64.dependencies] -clang = "16.0.6" -ninja = "1.11.1" -c-compiler = "1.6.0.*" -cxx-compiler = "1.6.0.*" - -[feature.cpp.target.osx-64.dependencies] -clang = "16.0.6" -ninja = "1.11.1" -c-compiler = "1.6.0.*" -cxx-compiler = "1.6.0.*" - -[feature.cpp.target.osx-arm64.dependencies] +[feature.cpp.target.unix.dependencies] clang = "16.0.6" ninja = "1.11.1" c-compiler = "1.6.0.*" diff --git a/rerun_cpp/src/rerun/c/rerun.h b/rerun_cpp/src/rerun/c/rerun.h index b00e92bff746..614f3f5c3d41 100644 --- a/rerun_cpp/src/rerun/c/rerun.h +++ b/rerun_cpp/src/rerun/c/rerun.h @@ -268,7 +268,7 @@ typedef struct rr_error { /// /// This should match the string returned by `rr_version_string`. /// If not, the SDK's binary and the C header are out of sync. -#define RERUN_SDK_HEADER_VERSION "0.15.0" +#define RERUN_SDK_HEADER_VERSION "0.16.0-alpha.1+dev" /// Returns a human-readable version string of the Rerun C SDK. /// @@ -454,7 +454,7 @@ extern void rr_recording_stream_log( /// This method blocks until either at least one `DataLoader` starts streaming data in /// or all of them fail. /// -/// See for more information. +/// See for more information. extern void rr_recording_stream_log_file_from_path( rr_recording_stream stream, rr_string path, rr_string entity_path_prefix, bool static_, rr_error* error @@ -467,7 +467,7 @@ extern void rr_recording_stream_log_file_from_path( /// This method blocks until either at least one `DataLoader` starts streaming data in /// or all of them fail. /// -/// See for more information. +/// See for more information. extern void rr_recording_stream_log_file_from_contents( rr_recording_stream stream, rr_string path, rr_bytes contents, rr_string entity_path_prefix, bool static_, rr_error* error diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index daeccdaa0376..e2272d1a3fb8 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -27,6 +27,7 @@ * [Helpers](helpers.md) ``` """ + from __future__ import annotations import re diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index 6b3c0bfb44d3..0b0066f1ebe5 100644 --- a/rerun_py/pyproject.toml +++ b/rerun_py/pyproject.toml @@ -47,6 +47,10 @@ rerun = "rerun_bindings:main" # target-version = "py38" # inferred from requires-python, see https://beta.ruff.rs/docs/settings/#target-version +# Enable unsafe fixes to allow ruff to apply fixes that may change the behavior of the code. +# This is needed because otherwise ruff will not be able to trim whitespaces in (codegened) docstrings. +unsafe-fixes = true + extend-exclude = [ # Automatically generated test artifacts "venv/", @@ -85,9 +89,8 @@ lint.ignore = [ "D415", "D416", - # Black is going to handle this for us, and ruff can't fix this error on its own (yet) - # Having ruff check this causes errors that prevent the code-formatting process from - # completing. + # Ruff can't fix this error on its own (yet) + # Having ruff check this causes errors that prevent the code-formatting process from completing. "E501", # allow relative imports diff --git a/rerun_py/rerun/__init__.py b/rerun_py/rerun/__init__.py index feedd2553ce0..be05e3b1f63c 100644 --- a/rerun_py/rerun/__init__.py +++ b/rerun_py/rerun/__init__.py @@ -11,6 +11,7 @@ real rerun module by adding it to the path and then, and then replacing our own module content with it. """ + from __future__ import annotations import pathlib diff --git a/rerun_py/rerun_sdk/rerun/__main__.py b/rerun_py/rerun_sdk/rerun/__main__.py index 739555494e5f..9fc0a594394a 100644 --- a/rerun_py/rerun_sdk/rerun/__main__.py +++ b/rerun_py/rerun_sdk/rerun/__main__.py @@ -1,4 +1,5 @@ """See `python3 -m rerun --help`.""" + from __future__ import annotations import rerun_bindings as bindings diff --git a/rerun_py/rerun_sdk/rerun/_converters.py b/rerun_py/rerun_sdk/rerun/_converters.py index a234006f322c..e951032373ea 100644 --- a/rerun_py/rerun_sdk/rerun/_converters.py +++ b/rerun_py/rerun_sdk/rerun/_converters.py @@ -48,13 +48,11 @@ class ClassA: @overload -def int_or_none(data: None) -> None: - ... +def int_or_none(data: None) -> None: ... @overload -def int_or_none(data: SupportsInt) -> int: - ... +def int_or_none(data: SupportsInt) -> int: ... def int_or_none(data: SupportsInt | None) -> int | None: @@ -64,13 +62,11 @@ def int_or_none(data: SupportsInt | None) -> int | None: @overload -def float_or_none(data: None) -> None: - ... +def float_or_none(data: None) -> None: ... @overload -def float_or_none(data: SupportsFloat) -> float: - ... +def float_or_none(data: SupportsFloat) -> float: ... def float_or_none(data: SupportsFloat | None) -> float | None: @@ -80,13 +76,11 @@ def float_or_none(data: SupportsFloat | None) -> float | None: @overload -def bool_or_none(data: None) -> None: - ... +def bool_or_none(data: None) -> None: ... @overload -def bool_or_none(data: bool) -> bool: - ... +def bool_or_none(data: bool) -> bool: ... def bool_or_none(data: bool | None) -> bool | None: @@ -96,13 +90,11 @@ def bool_or_none(data: bool | None) -> bool | None: @overload -def str_or_none(data: None) -> None: - ... +def str_or_none(data: None) -> None: ... @overload -def str_or_none(data: str) -> str: - ... +def str_or_none(data: str) -> str: ... def str_or_none(data: str | None) -> str | None: diff --git a/rerun_py/rerun_sdk/rerun/color_conversion.py b/rerun_py/rerun_sdk/rerun/color_conversion.py index 8d0cf599d363..fece2007e653 100644 --- a/rerun_py/rerun_sdk/rerun/color_conversion.py +++ b/rerun_py/rerun_sdk/rerun/color_conversion.py @@ -1,4 +1,5 @@ """Color conversion utilities.""" + from __future__ import annotations import numpy as np diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py index 34cd5165a0be..36ae3c1e1c76 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py @@ -93,9 +93,9 @@ class TensorBuffer(TensorBufferExt): The order of the channels is Y0, U0, Y1, V0. """ - kind: Literal[ - "u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f16", "f32", "f64", "jpeg", "nv12", "yuy2" - ] = field(default="u8") + kind: Literal["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f16", "f32", "f64", "jpeg", "nv12", "yuy2"] = ( + field(default="u8") + ) """ Possible values: diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py index 43b717d2231c..ace5947e0637 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data_ext.py @@ -16,8 +16,7 @@ class TorchTensorLike(Protocol): """Describes what is need from a Torch Tensor to be loggable to Rerun.""" - def numpy(self, force: bool) -> npt.NDArray[Any]: - ... + def numpy(self, force: bool) -> npt.NDArray[Any]: ... if TYPE_CHECKING: diff --git a/rerun_py/rerun_sdk/rerun/experimental/__init__.py b/rerun_py/rerun_sdk/rerun/experimental/__init__.py index 485bcf3c66a0..844bd63eb849 100644 --- a/rerun_py/rerun_sdk/rerun/experimental/__init__.py +++ b/rerun_py/rerun_sdk/rerun/experimental/__init__.py @@ -4,6 +4,7 @@ These features are not yet stable and may change in future releases without going through the normal deprecation cycle. """ + from __future__ import annotations # __all__ = [] diff --git a/rerun_py/rerun_sdk/rerun/memory.py b/rerun_py/rerun_sdk/rerun/memory.py index e01c3f5d8fb1..3b4330517bf1 100644 --- a/rerun_py/rerun_sdk/rerun/memory.py +++ b/rerun_py/rerun_sdk/rerun/memory.py @@ -1,4 +1,5 @@ """Helper functions for directly working with recordings.""" + from __future__ import annotations import base64 diff --git a/rerun_py/rerun_sdk/rerun/notebook.py b/rerun_py/rerun_sdk/rerun/notebook.py index 0b54dbb2e7f5..f4284875b7e9 100644 --- a/rerun_py/rerun_sdk/rerun/notebook.py +++ b/rerun_py/rerun_sdk/rerun/notebook.py @@ -1,4 +1,5 @@ """Helper functions for converting streams to inline html.""" + from __future__ import annotations import base64 diff --git a/rerun_py/rerun_sdk/rerun/script_helpers.py b/rerun_py/rerun_sdk/rerun/script_helpers.py index 0a9062ac7127..f3e5f26b9305 100644 --- a/rerun_py/rerun_sdk/rerun/script_helpers.py +++ b/rerun_py/rerun_sdk/rerun/script_helpers.py @@ -18,6 +18,7 @@ ``` """ + from __future__ import annotations from argparse import ArgumentParser, Namespace diff --git a/rerun_py/rerun_sdk/rerun/utilities/data.py b/rerun_py/rerun_sdk/rerun/utilities/data.py index cb5812377b4f..d8419f5370bd 100644 --- a/rerun_py/rerun_sdk/rerun/utilities/data.py +++ b/rerun_py/rerun_sdk/rerun/utilities/data.py @@ -1,4 +1,5 @@ """Simple data to be used for Rerun demos.""" + from __future__ import annotations from collections import namedtuple diff --git a/rerun_py/rerun_sdk/rerun/utilities/util.py b/rerun_py/rerun_sdk/rerun/utilities/util.py index 95c20c6a2912..293fcbffb006 100644 --- a/rerun_py/rerun_sdk/rerun/utilities/util.py +++ b/rerun_py/rerun_sdk/rerun/utilities/util.py @@ -1,4 +1,5 @@ """Simple utilities to be used for Rerun demos.""" + from __future__ import annotations from typing import Any diff --git a/rerun_py/tests/unit/test_color_conversion.py b/rerun_py/tests/unit/test_color_conversion.py index ff0e743e4de0..8273ae674038 100644 --- a/rerun_py/tests/unit/test_color_conversion.py +++ b/rerun_py/tests/unit/test_color_conversion.py @@ -1,4 +1,5 @@ """Test for color_conversion module.""" + from __future__ import annotations import numpy as np diff --git a/scripts/check_example_manifest_coverage.py b/scripts/check_example_manifest_coverage.py index cca6125b6377..8d29a8819af0 100644 --- a/scripts/check_example_manifest_coverage.py +++ b/scripts/check_example_manifest_coverage.py @@ -1,4 +1,5 @@ """Check if all examples are listed (or explicitly ignored) in our example manifest.""" + from __future__ import annotations from pathlib import Path diff --git a/scripts/ci/approve_workflow_runs.py b/scripts/ci/approve_workflow_runs.py index fd35f8b9c224..bb781ffebfdf 100755 --- a/scripts/ci/approve_workflow_runs.py +++ b/scripts/ci/approve_workflow_runs.py @@ -11,6 +11,7 @@ Requires the following packages: pip install PyGithub==1.59.0 requests>=2.31,<3 """ + from __future__ import annotations import argparse diff --git a/scripts/ci/build_and_upload_wheels.py b/scripts/ci/build_and_upload_wheels.py index 1916d56d9812..932f9a672b54 100755 --- a/scripts/ci/build_and_upload_wheels.py +++ b/scripts/ci/build_and_upload_wheels.py @@ -9,6 +9,7 @@ Use the script: python3 scripts/ci/release.py --help """ + from __future__ import annotations import argparse diff --git a/scripts/ci/compare.py b/scripts/ci/compare.py index 282bdffc80b0..ca040ab97cab 100755 --- a/scripts/ci/compare.py +++ b/scripts/ci/compare.py @@ -10,6 +10,7 @@ python3 scripts/ci/compare.py --threshold=20 previous.json current.json """ + from __future__ import annotations import argparse diff --git a/scripts/ci/count_bytes.py b/scripts/ci/count_bytes.py index e840fc25b164..71f188ab3bb4 100755 --- a/scripts/ci/count_bytes.py +++ b/scripts/ci/count_bytes.py @@ -14,6 +14,7 @@ python3 scripts/ci/count_bytes.py --format=github \ "Wasm":web_viewer/re_viewer_bg.wasm """ + from __future__ import annotations import argparse diff --git a/scripts/ci/count_dependencies.py b/scripts/ci/count_dependencies.py index f1c316bb6eab..379b1926f819 100755 --- a/scripts/ci/count_dependencies.py +++ b/scripts/ci/count_dependencies.py @@ -19,6 +19,7 @@ So this script is more of a heurristic than an exact count. """ + from __future__ import annotations import argparse diff --git a/scripts/ci/crates.py b/scripts/ci/crates.py index c994adea6e34..0a38b522e7dc 100755 --- a/scripts/ci/crates.py +++ b/scripts/ci/crates.py @@ -19,6 +19,7 @@ # Publish all crates in topological order python3 scripts/ci/publish.py --token """ + from __future__ import annotations import argparse diff --git a/scripts/ci/generate_pr_summary.py b/scripts/ci/generate_pr_summary.py index cfea39ee1528..c1f4cbf69ba5 100644 --- a/scripts/ci/generate_pr_summary.py +++ b/scripts/ci/generate_pr_summary.py @@ -9,6 +9,7 @@ Requires the following packages: pip install google-cloud-storage Jinja2 PyGithub """ + from __future__ import annotations import argparse diff --git a/scripts/ci/generate_prerelease_pip_index.py b/scripts/ci/generate_prerelease_pip_index.py index b2d1e48e4d62..6d4d752f2284 100755 --- a/scripts/ci/generate_prerelease_pip_index.py +++ b/scripts/ci/generate_prerelease_pip_index.py @@ -11,6 +11,7 @@ Requires the following packages: pip install google-cloud-storage Jinja2 """ + from __future__ import annotations import argparse diff --git a/scripts/ci/publish_wheels.py b/scripts/ci/publish_wheels.py index d6d152f4ea1f..943a5e870dff 100755 --- a/scripts/ci/publish_wheels.py +++ b/scripts/ci/publish_wheels.py @@ -9,6 +9,7 @@ Use the script: python3 scripts/ci/verify_wheels.py --help """ + from __future__ import annotations import argparse diff --git a/scripts/ci/render_bench.py b/scripts/ci/render_bench.py index df5c0390464e..a76f51967f32 100755 --- a/scripts/ci/render_bench.py +++ b/scripts/ci/render_bench.py @@ -20,6 +20,7 @@ sizes \ --output gs://rerun-builds/graphs """ + from __future__ import annotations import argparse diff --git a/scripts/ci/sync_release_assets.py b/scripts/ci/sync_release_assets.py index d75f262a5d4f..60da0b3eab30 100644 --- a/scripts/ci/sync_release_assets.py +++ b/scripts/ci/sync_release_assets.py @@ -13,6 +13,7 @@ Requires the following packages: pip install google-cloud-storage PyGithub """ + from __future__ import annotations import argparse diff --git a/scripts/ci/thumbnails.py b/scripts/ci/thumbnails.py index 968a9d5676de..13bcb9aaf41d 100755 --- a/scripts/ci/thumbnails.py +++ b/scripts/ci/thumbnails.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 """Checks or updates cached thumbnail dimensions in example READMEs.""" + from __future__ import annotations import argparse diff --git a/scripts/ci/update_pr_body.py b/scripts/ci/update_pr_body.py index 397d571cbb2a..697b15191fc0 100755 --- a/scripts/ci/update_pr_body.py +++ b/scripts/ci/update_pr_body.py @@ -8,6 +8,7 @@ Requires the following packages: pip install Jinja2 PyGithub """ + from __future__ import annotations import argparse diff --git a/scripts/fast_lint.py b/scripts/fast_lint.py index 3f4a8cc414d1..7bca3b325c72 100755 --- a/scripts/fast_lint.py +++ b/scripts/fast_lint.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 """Runs the common linters on any files that have changed relative to the main branch.""" + from __future__ import annotations import argparse @@ -149,13 +150,11 @@ def main() -> None: extensions=[".rs"], no_filter_cmd="lint-rs-all", ), - LintJob("lint-py-fmt-check", extensions=[".py"], no_filter_args=PY_FOLDERS), - LintJob("lint-py-blackdoc", extensions=[".py"], no_filter_args=PY_FOLDERS), + LintJob("py-fmt-check", extensions=[".py"], no_filter_args=PY_FOLDERS), # Even though mypy will accept a list of files, the results it generates are inconsistent # with running on the full project. - LintJob("lint-py-mypy", extensions=[".py"], accepts_files=False), - LintJob("lint-py-ruff", extensions=[".py"], no_filter_args=PY_FOLDERS), - LintJob("lint-taplo", extensions=[".toml"]), + LintJob("py-lint", extensions=[".py"], accepts_files=False), + LintJob("toml-fmt-check", extensions=[".toml"]), LintJob("lint-typos"), ] diff --git a/scripts/fetch_crashes.py b/scripts/fetch_crashes.py index 577d6beac4ba..4cb5b9576188 100755 --- a/scripts/fetch_crashes.py +++ b/scripts/fetch_crashes.py @@ -22,6 +22,7 @@ ``` """ + from __future__ import annotations import argparse diff --git a/scripts/generate_changelog.py b/scripts/generate_changelog.py index 5dd558f7c48e..4bdb8cda6f54 100755 --- a/scripts/generate_changelog.py +++ b/scripts/generate_changelog.py @@ -8,6 +8,7 @@ Finally, copy-paste the output into `CHANGELOG.md` and add a high-level summary to the top. """ + from __future__ import annotations import argparse diff --git a/scripts/highlight_issues.py b/scripts/highlight_issues.py index a3d1362ab9c7..79b69fc2db64 100755 --- a/scripts/highlight_issues.py +++ b/scripts/highlight_issues.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 """Generate a list of GitHub issues that needs attention.""" + from __future__ import annotations import multiprocessing diff --git a/scripts/lint.py b/scripts/lint.py index ed64f4002d56..89b69ada30c1 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -123,6 +123,7 @@ def lint_line( and not ellipsis_import.search(line) and not ellipsis_bare.search(line) and not ellipsis_reference.search(line) + and not (file_extension == "py" and line.strip().startswith("def")) ): return "Use … instead of ..." diff --git a/scripts/run_all.py b/scripts/run_all.py index 48b36acf0868..e27d8f9e726c 100755 --- a/scripts/run_all.py +++ b/scripts/run_all.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 """Run all examples.""" + from __future__ import annotations import argparse diff --git a/scripts/run_python_e2e_test.py b/scripts/run_python_e2e_test.py index b3ab62996b76..d825f95492b3 100755 --- a/scripts/run_python_e2e_test.py +++ b/scripts/run_python_e2e_test.py @@ -10,6 +10,7 @@ * TCP connection * Data store ingestion """ + from __future__ import annotations import argparse diff --git a/taplo.toml b/taplo.toml index 7ad0910f0de1..bf7d6e80a3e6 100644 --- a/taplo.toml +++ b/taplo.toml @@ -1,13 +1,11 @@ # https://github.com/tamasfe/taplo -exclude = [ - ".nox/**", - ".pixi/**", - "build/**", - "target/**", - "target_ra/**", - "target_wasm/**", - "venv/**", +# As of writing, taplo is really slow to gather files, so we help it out a bit. +include = [ + "*.toml", + "crates/**/*.toml", + "examples/rust/**/*.toml", + "tests/rust/**/*.toml", ] [formatting] diff --git a/tests/python/chroma_downsample_image/main.py b/tests/python/chroma_downsample_image/main.py index 0b314d6eced3..ac3c0205cfd8 100755 --- a/tests/python/chroma_downsample_image/main.py +++ b/tests/python/chroma_downsample_image/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """Testing NV12 image encoding.""" + from __future__ import annotations import argparse diff --git a/tests/python/gc_stress/many_large_many_rows_recordings.py b/tests/python/gc_stress/many_large_many_rows_recordings.py index ca535ae45626..00a1ee5ecfa7 100644 --- a/tests/python/gc_stress/many_large_many_rows_recordings.py +++ b/tests/python/gc_stress/many_large_many_rows_recordings.py @@ -10,6 +10,7 @@ - Run this script. - You should see recordings coming in and going out in a ringbuffer-like rolling fashion. """ + from __future__ import annotations import rerun as rr diff --git a/tests/python/gc_stress/many_large_single_row_recordings.py b/tests/python/gc_stress/many_large_single_row_recordings.py index 90a64faba84f..77cb386768a5 100644 --- a/tests/python/gc_stress/many_large_single_row_recordings.py +++ b/tests/python/gc_stress/many_large_single_row_recordings.py @@ -10,6 +10,7 @@ - Run this script. - You should see recordings coming in and going out in a ringbuffer-like rolling fashion. """ + from __future__ import annotations import time diff --git a/tests/python/gc_stress/many_medium_sized_many_rows_recordings.py b/tests/python/gc_stress/many_medium_sized_many_rows_recordings.py index bae6acfefa1b..56f99d9d2f9e 100644 --- a/tests/python/gc_stress/many_medium_sized_many_rows_recordings.py +++ b/tests/python/gc_stress/many_medium_sized_many_rows_recordings.py @@ -10,6 +10,7 @@ - Run this script. - You should see recordings coming in and going out in a ringbuffer-like rolling fashion. """ + from __future__ import annotations import rerun as rr diff --git a/tests/python/gc_stress/many_medium_sized_single_row_recordings.py b/tests/python/gc_stress/many_medium_sized_single_row_recordings.py index 8109dd857494..a53d947e5db1 100644 --- a/tests/python/gc_stress/many_medium_sized_single_row_recordings.py +++ b/tests/python/gc_stress/many_medium_sized_single_row_recordings.py @@ -10,6 +10,7 @@ - Run this script. - You should see recordings coming in and going out in a ringbuffer-like rolling fashion. """ + from __future__ import annotations import time diff --git a/tests/python/gil_stress/main.py b/tests/python/gil_stress/main.py index 14e266ed5abd..0b58410074e4 100644 --- a/tests/python/gil_stress/main.py +++ b/tests/python/gil_stress/main.py @@ -7,6 +7,7 @@ ``` python main.py """ + from __future__ import annotations import rerun as rr diff --git a/tests/python/log_benchmark/test_log_benchmark.py b/tests/python/log_benchmark/test_log_benchmark.py index 5a26d0426169..64536bd446d1 100644 --- a/tests/python/log_benchmark/test_log_benchmark.py +++ b/tests/python/log_benchmark/test_log_benchmark.py @@ -1,4 +1,4 @@ -"""Python logging benchmarks. Use `just py-bench` to run.""" +"""Python logging benchmarks. Use `pixi run py-bench` to run.""" from __future__ import annotations diff --git a/tests/python/plot_dashboard_stress/main.py b/tests/python/plot_dashboard_stress/main.py index 2a8c036d04f1..2e0f9f1021af 100755 --- a/tests/python/plot_dashboard_stress/main.py +++ b/tests/python/plot_dashboard_stress/main.py @@ -15,6 +15,7 @@ ``` """ + from __future__ import annotations import argparse diff --git a/tests/python/test_api/main.py b/tests/python/test_api/main.py index 76e0a09f59f7..e59aa39ea953 100755 --- a/tests/python/test_api/main.py +++ b/tests/python/test_api/main.py @@ -8,6 +8,7 @@ * Run all tests: `examples/python/test_api/main.py` * Run specific test: `examples/python/test_api/main.py --test rects` """ + from __future__ import annotations import argparse diff --git a/tests/python/view_coordinates/main.py b/tests/python/view_coordinates/main.py index 349785e33737..172222062bbb 100755 --- a/tests/python/view_coordinates/main.py +++ b/tests/python/view_coordinates/main.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 """A test series for view coordinates.""" + from __future__ import annotations import argparse diff --git a/tests/python/visible_history_playground/main.py b/tests/python/visible_history_playground/main.py index 2abdbbb87c6b..07325a77d192 100644 --- a/tests/python/visible_history_playground/main.py +++ b/tests/python/visible_history_playground/main.py @@ -1,4 +1,5 @@ """Playground to test the visible history feature.""" + from __future__ import annotations import argparse From bc47678d6980587983e2218d3bfb479504ff405d Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 10 Apr 2024 17:14:40 +0200 Subject: [PATCH 241/508] Fix python lints, make python lint ci conditional (#5897) ### What * related to #3033 -- * Turned out most of the python lints issues I had locally (and did not see on ci) are about opencv-python missmatches. The way I fixed it should work fine with either though now! * Various python lints on ci now use pixi and run only when py files change. * update pixi version used on ci ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5897) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5897?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5897?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5897) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/auto_release_crates.yml | 2 +- .github/workflows/contrib_checks.yml | 8 +-- .github/workflows/contrib_rerun_py.yml | 2 +- .github/workflows/nightly.yml | 7 ++ .github/workflows/on_pull_request.yml | 27 ++++++++ .github/workflows/on_push_main.yml | 7 ++ .github/workflows/release.yml | 4 +- .../reusable_build_and_upload_rerun_cli.yml | 2 +- .../reusable_build_and_upload_wheels.yml | 2 +- .github/workflows/reusable_build_examples.yml | 2 +- .github/workflows/reusable_build_js.yml | 2 +- .github/workflows/reusable_build_web.yml | 2 +- .github/workflows/reusable_checks.yml | 29 ++------ .github/workflows/reusable_checks_cpp.yml | 2 +- .github/workflows/reusable_checks_python.yml | 68 +++++++++++++++++++ .github/workflows/reusable_checks_rust.yml | 6 +- .github/workflows/reusable_deploy_docs.yml | 2 +- .github/workflows/reusable_publish_js.yml | 2 +- .github/workflows/reusable_publish_web.yml | 2 +- .github/workflows/reusable_release_crates.yml | 2 +- .github/workflows/reusable_test_wheels.yml | 2 +- examples/python/controlnet/main.py | 4 +- examples/python/controlnet/requirements.txt | 2 +- examples/python/face_tracking/main.py | 2 +- examples/python/gesture_detection/main.py | 2 +- examples/python/human_pose_tracking/main.py | 2 +- examples/python/nv12/main.py | 5 +- 27 files changed, 145 insertions(+), 54 deletions(-) create mode 100644 .github/workflows/reusable_checks_python.yml diff --git a/.github/workflows/auto_release_crates.yml b/.github/workflows/auto_release_crates.yml index a1b7d814ff89..c68b0e991601 100644 --- a/.github/workflows/auto_release_crates.yml +++ b/.github/workflows/auto_release_crates.yml @@ -22,7 +22,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Install dependencies shell: bash diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index a087841b4876..3898830c1c73 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -37,7 +37,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Set up Python uses: actions/setup-python@v4 with: @@ -100,7 +100,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Codegen check shell: bash @@ -211,7 +211,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Set up Python uses: actions/setup-python@v4 @@ -291,7 +291,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 # TODO(emilk): make this work somehow. Right now this just results in # > Compiler: GNU 12.3.0 (/__w/rerun/rerun/.pixi/env/bin/x86_64-conda-linux-gnu-c++) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 4b5da77f58d2..29d2f43c08bc 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -42,7 +42,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 # These should already be in the docker container, but run for good measure. A no-op install # should be fast, and this way things don't break if we add new packages without rebuilding diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5e25573628e2..8675978859ca 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -31,6 +31,13 @@ jobs: ALL_CHECKS: true secrets: inherit + checks-python: + name: Checks + uses: ./.github/workflows/reusable_checks_python.yml + with: + CONCURRENCY: nightly + secrets: inherit + build-web: name: "Build Web" uses: ./.github/workflows/reusable_build_web.yml diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index feb35d6b7c95..53662bb8e559 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -55,6 +55,23 @@ jobs: - '**/CMakeLists.txt' - '**/*cmake' + python-paths-filter: + runs-on: ubuntu-latest + outputs: + python_changes: ${{ steps.filter.outputs.python_changes }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + python_changes: + - '**/*.py' + - '**/requirements.txt' + - '**/pyproject.toml' + docs-paths-filter: runs-on: ubuntu-latest outputs: @@ -82,6 +99,16 @@ jobs: CONCURRENCY: pr-${{ github.event.pull_request.number }} secrets: inherit + python-checks: + name: "Python Checks" + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.python-paths-filter.outputs.python_changes == 'true' + # Wait for the python-paths-filter to be completed before starting. + needs: python-paths-filter + uses: ./.github/workflows/reusable_checks_python.yml + with: + CONCURRENCY: pr-${{ github.event.pull_request.number }} + secrets: inherit + cpp-tests: name: "C++ tests" if: needs.cpp-paths-filter.outputs.cpp_changes == 'true' diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 922aa2dd73f6..7172cbe435a6 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -28,6 +28,13 @@ jobs: CONCURRENCY: push-${{ github.ref_name }} secrets: inherit + python_checks: + name: Checks + uses: ./.github/workflows/reusable_checks_python.yml + with: + CONCURRENCY: push-${{ github.ref_name }} + secrets: inherit + # Check that a CLEAN container with just `cargo` on it can build rerun: clean-build: name: cargo build on clean container diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c37163d9b52a..ef2edd90fbd8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Update crate versions id: versioning @@ -392,7 +392,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Install dependencies shell: bash diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index 975405c3bcbc..ff51bd370213 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -152,7 +152,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Build web-viewer (release) shell: bash diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index b112dba1b864..47d3b1c27f46 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -179,7 +179,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Install dependencies shell: bash diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 108dde0ed807..2c2411057738 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -50,7 +50,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Download Wheel uses: actions/download-artifact@v3 diff --git a/.github/workflows/reusable_build_js.yml b/.github/workflows/reusable_build_js.yml index b64f2e356a5b..71debee78fed 100644 --- a/.github/workflows/reusable_build_js.yml +++ b/.github/workflows/reusable_build_js.yml @@ -55,7 +55,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.3.0 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Install dependencies shell: bash diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 1e1adbf50573..82272e917908 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -55,7 +55,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Build web-viewer (release) shell: bash diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 16823a23228d..636ed9abb37b 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -41,30 +41,13 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.11" - cache: "pip" - cache-dependency-path: "rerun_py/requirements-lint.txt" - - - name: Install Python dependencies - shell: bash - run: | - pip install --upgrade pip - pip install -r rerun_py/requirements-lint.txt + pixi-version: v0.18.0 - name: Python format check - shell: bash - run: | - pixi run py-fmt-check + run: pixi run py-fmt-check - name: Lint Python - shell: bash - run: | - pixi run py-lint + run: pixi run py-lint # --------------------------------------------------------------------------- @@ -125,7 +108,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Codegen check shell: bash @@ -144,7 +127,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Set up Python uses: actions/setup-python@v4 @@ -211,7 +194,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: prettier --check run: pixi run misc-fmt-check diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index faa590f9eff9..406ac548cca8 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -73,7 +73,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Set up Rust uses: ./.github/actions/setup-rust diff --git a/.github/workflows/reusable_checks_python.yml b/.github/workflows/reusable_checks_python.yml new file mode 100644 index 000000000000..5e9cac76d0f8 --- /dev/null +++ b/.github/workflows/reusable_checks_python.yml @@ -0,0 +1,68 @@ +name: "Python Checks: Lints & Docs" + +on: + workflow_call: + inputs: + CONCURRENCY: + required: true + type: string + +concurrency: + group: ${{ inputs.CONCURRENCY }}-checks_python + cancel-in-progress: true + +env: + PYTHON_VERSION: "3.8" + +permissions: + contents: "read" + id-token: "write" + +jobs: + # --------------------------------------------------------------------------- + + py-lints: + name: Python lints (ruff, mypy, …) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + + - uses: prefix-dev/setup-pixi@v0.4.1 + with: + pixi-version: v0.18.0 + + - name: Python format check + run: pixi run py-fmt-check + + - name: Lint Python + run: pixi run py-lint + + # --------------------------------------------------------------------------- + + py-test-docs: + name: Test Python Docs + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.8" + cache: "pip" + cache-dependency-path: "rerun_py/requirements-doc.txt" + + - name: Install Python dependencies + shell: bash + run: | + pip install --upgrade pip + pip install -r rerun_py/requirements-doc.txt + + - name: Build via mkdocs + shell: bash + run: | + mkdocs build --strict -f rerun_py/mkdocs.yml diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 45b126234d16..4994d066b565 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -1,4 +1,4 @@ -name: "Rust & toml Checks: Lints, Tests, Docs" +name: "Rust Checks: Lints, Tests, Docs" on: workflow_call: @@ -57,7 +57,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 # We need to build the web viewer for `rust_checks.py` to succeed. # We build in release so that we can reuse the results for actual publishing, if necessary @@ -108,7 +108,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 # We build in release so that we can reuse the results for actual publishing, if necessary - name: Build web-viewer (release) diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index 736c9f089a78..984a8bd2ea5d 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -206,7 +206,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Doxygen C++ docs shell: bash diff --git a/.github/workflows/reusable_publish_js.yml b/.github/workflows/reusable_publish_js.yml index 711f5c923225..d75cc9d84259 100644 --- a/.github/workflows/reusable_publish_js.yml +++ b/.github/workflows/reusable_publish_js.yml @@ -63,7 +63,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.3.0 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Publish packages env: diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index f7d480a56b81..8230e3513e9d 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -74,7 +74,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 # built by `reusable_build_and_publish_wheels` - name: Download Wheel diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml index ca769ed0a13c..dabc0b001afb 100644 --- a/.github/workflows/reusable_release_crates.yml +++ b/.github/workflows/reusable_release_crates.yml @@ -26,7 +26,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 - name: Build web-viewer (release) shell: bash diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 0a16a5fb7733..160271a83567 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -133,7 +133,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.16.1 + pixi-version: v0.18.0 # The pip-cache setup logic doesn't work in the ubuntu docker container # That's probably fine since we bake these deps into the container already diff --git a/examples/python/controlnet/main.py b/examples/python/controlnet/main.py index 1ecadd9e3d4a..72406f356d1e 100755 --- a/examples/python/controlnet/main.py +++ b/examples/python/controlnet/main.py @@ -39,8 +39,8 @@ def controlnet_callback( rr.set_time_seconds("timestep", timestep) latents = callback_kwargs["latents"] - image = pipe.vae.decode(latents / pipe.vae.config.scaling_factor, return_dict=False)[0] - image = pipe.image_processor.postprocess(image, output_type="np").squeeze() + image = pipe.vae.decode(latents / pipe.vae.config.scaling_factor, return_dict=False)[0] # type: ignore[attr-defined] + image = pipe.image_processor.postprocess(image, output_type="np").squeeze() # type: ignore[attr-defined] rr.log("output", rr.Image(image)) rr.log("latent", rr.Tensor(latents.squeeze(), dim_names=["channel", "height", "width"])) diff --git a/examples/python/controlnet/requirements.txt b/examples/python/controlnet/requirements.txt index 59a05f75f682..d7dc8b29f056 100644 --- a/examples/python/controlnet/requirements.txt +++ b/examples/python/controlnet/requirements.txt @@ -1,7 +1,7 @@ accelerate opencv-python pillow -diffusers +diffusers==0.27.2 numpy #TODO(#4704): clean that up when pytorch is available for 3.12 torch ; python_version < "3.12" diff --git a/examples/python/face_tracking/main.py b/examples/python/face_tracking/main.py index 586865671c44..4448270f8c8d 100755 --- a/examples/python/face_tracking/main.py +++ b/examples/python/face_tracking/main.py @@ -302,7 +302,7 @@ def download_file(url: str, path: Path) -> None: f.write(chunk) -def resize_image(image: npt.NDArray[np.uint8], max_dim: int | None) -> npt.NDArray[np.uint8]: +def resize_image(image: cv2.typing.MatLike, max_dim: int | None) -> cv2.typing.MatLike: """Resize an image if it is larger than max_dim.""" if max_dim is None: return image diff --git a/examples/python/gesture_detection/main.py b/examples/python/gesture_detection/main.py index fe8f043f042e..3f284315c296 100755 --- a/examples/python/gesture_detection/main.py +++ b/examples/python/gesture_detection/main.py @@ -178,7 +178,7 @@ def download_file(url: str, path: Path) -> None: f.write(chunk) -def resize_image(image: npt.NDArray[np.uint8], max_dim: int | None) -> npt.NDArray[np.uint8]: +def resize_image(image: cv2.typing.MatLike, max_dim: int | None) -> cv2.typing.MatLike: """Resize an image if it is larger than max_dim.""" if max_dim is None: return image diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py index b46492dc82fb..b7927e11ac90 100755 --- a/examples/python/human_pose_tracking/main.py +++ b/examples/python/human_pose_tracking/main.py @@ -117,7 +117,7 @@ def read_landmark_positions_3d( @dataclass class VideoFrame: - data: npt.NDArray[np.uint8] + data: cv2.typing.MatLike time: float idx: int diff --git a/examples/python/nv12/main.py b/examples/python/nv12/main.py index 0d96a66b9c82..d841edd7ab9e 100755 --- a/examples/python/nv12/main.py +++ b/examples/python/nv12/main.py @@ -16,12 +16,11 @@ import cv2 import numpy as np -import numpy.typing as npt import rerun as rr # pip install rerun-sdk -def bgr2nv12(bgr: npt.NDArray[np.uint8]) -> npt.NDArray[np.uint8]: - yuv: npt.NDArray[np.uint8] = cv2.cvtColor(bgr, cv2.COLOR_BGR2YUV_I420) +def bgr2nv12(bgr: cv2.typing.MatLike) -> cv2.typing.MatLike: + yuv = cv2.cvtColor(bgr, cv2.COLOR_BGR2YUV_I420) uv_row_cnt = yuv.shape[0] // 3 uv_plane = np.transpose(yuv[uv_row_cnt * 2 :].reshape(2, -1), [1, 0]) yuv[uv_row_cnt * 2 :] = uv_plane.reshape(uv_row_cnt, -1) From a838a2e56093f348cc6ea983f6657052ab429f07 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:13:59 +0200 Subject: [PATCH 242/508] Don't gate `torch` behind python<3.12 (#5899) ### What - closes #4704 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5899) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5899?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5899?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5899) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- examples/python/controlnet/requirements.txt | 3 +-- .../requirements.txt | 3 +-- .../detect_and_track_objects/requirements.txt | 3 +-- .../python/llm_embedding_ner/requirements.txt | 3 +-- .../segment_anything_model/requirements.txt | 5 ++--- noxfile.py | 19 ------------------- rerun_py/requirements-build.txt | 3 +-- rerun_py/requirements-lint.txt | 3 +-- scripts/requirements-dev.txt | 3 +-- 9 files changed, 9 insertions(+), 36 deletions(-) diff --git a/examples/python/controlnet/requirements.txt b/examples/python/controlnet/requirements.txt index d7dc8b29f056..94d2d4c124a3 100644 --- a/examples/python/controlnet/requirements.txt +++ b/examples/python/controlnet/requirements.txt @@ -3,7 +3,6 @@ opencv-python pillow diffusers==0.27.2 numpy -#TODO(#4704): clean that up when pytorch is available for 3.12 -torch ; python_version < "3.12" +torch transformers rerun-sdk diff --git a/examples/python/depth_guided_stable_diffusion/requirements.txt b/examples/python/depth_guided_stable_diffusion/requirements.txt index 4841ec4dc2e0..f48c42477775 100644 --- a/examples/python/depth_guided_stable_diffusion/requirements.txt +++ b/examples/python/depth_guided_stable_diffusion/requirements.txt @@ -7,6 +7,5 @@ pillow requests>=2.31,<3 rerun-sdk scipy -#TODO(#4704): clean that up when pytorch is available for 3.12 -torch>1.13.0 ; python_version < "3.12" +torch>1.13.0 transformers>=4.26.0 diff --git a/examples/python/detect_and_track_objects/requirements.txt b/examples/python/detect_and_track_objects/requirements.txt index 2faba41baaa3..78cafec6c5e9 100644 --- a/examples/python/detect_and_track_objects/requirements.txt +++ b/examples/python/detect_and_track_objects/requirements.txt @@ -5,6 +5,5 @@ pillow requests>=2.31,<3 rerun-sdk timm==0.9.11 -#TODO(#4704): clean that up when pytorch is available for 3.12 -torch>=1.13.0 ; python_version < "3.12" +torch>=1.13.0 transformers diff --git a/examples/python/llm_embedding_ner/requirements.txt b/examples/python/llm_embedding_ner/requirements.txt index 9d989c80c142..554464f3669e 100644 --- a/examples/python/llm_embedding_ner/requirements.txt +++ b/examples/python/llm_embedding_ner/requirements.txt @@ -1,5 +1,4 @@ rerun-sdk -#TODO(#4704): clean that up when pytorch is available for 3.12 -torch ; python_version < "3.12" +torch transformers umap-learn diff --git a/examples/python/segment_anything_model/requirements.txt b/examples/python/segment_anything_model/requirements.txt index 9ee553729732..90181c6cb02f 100644 --- a/examples/python/segment_anything_model/requirements.txt +++ b/examples/python/segment_anything_model/requirements.txt @@ -3,7 +3,6 @@ numpy opencv-python requests>=2.31,<3 rerun-sdk -#TODO(#4704): clean that up when pytorch is available for 3.12 -torch ; python_version < "3.12" -torchvision ; python_version < "3.12" +torch +torchvision tqdm diff --git a/noxfile.py b/noxfile.py index 2bfc7935a701..8ad7fc0b8d05 100644 --- a/noxfile.py +++ b/noxfile.py @@ -17,13 +17,6 @@ def tests(session: nox.Session) -> None: """Run the Python test suite.""" session.install("-r", "rerun_py/requirements-build.txt") - - # TODO(#4704): clean that up when torch is 3.12 compatible - if session.python == "3.12": - session.run( - "pip", "install", "torch", "torchvision", "--pre", "--index-url", "https://download.pytorch.org/whl/nightly" - ) - session.install("./rerun_py") session.run("just", "py-test", external=True) @@ -32,12 +25,6 @@ def tests(session: nox.Session) -> None: def run_all(session: nox.Session) -> None: """Run all examples through the run_all.py script (pass args with: "-- ").""" - # TODO(#4704): clean that up when torch is 3.12 compatible - if session.python == "3.12": - session.run( - "pip", "install", "torch", "torchvision", "--pre", "--index-url", "https://download.pytorch.org/whl/nightly" - ) - # Note: the run_all.py scripts installs all dependencies itself. In particular, we can install from # examples/python/requirements.txt because it includes pyrealsense2, which is not available for mac. session.run("python", "scripts/run_all.py", "--install-requirements", *session.posargs) @@ -54,12 +41,6 @@ def roundtrips(session: nox.Session) -> None: session.install("-r", "rerun_py/requirements-build.txt") session.install("opencv-python") - - # TODO(#4704): clean that up when torch is 3.12 compatible - if session.python == "3.12": - session.run( - "pip", "install", "torch", "torchvision", "--pre", "--index-url", "https://download.pytorch.org/whl/nightly" - ) session.install("./rerun_py") extra_args = [] diff --git a/rerun_py/requirements-build.txt b/rerun_py/requirements-build.txt index ae41c64d3506..4eeb5d293455 100644 --- a/rerun_py/requirements-build.txt +++ b/rerun_py/requirements-build.txt @@ -3,5 +3,4 @@ maturin>=1.5.1 semver wheel pytest -#TODO(#4704): clean that up when pytorch is available for 3.12 -torch>=2.0.1 ; python_version < "3.12" +torch>=2.0.1 diff --git a/rerun_py/requirements-lint.txt b/rerun_py/requirements-lint.txt index 6a3bc50f7b1e..001d44d5eaac 100644 --- a/rerun_py/requirements-lint.txt +++ b/rerun_py/requirements-lint.txt @@ -2,8 +2,7 @@ attrs>=23.1.0 # for mypy to work blackdoc==0.3.8 mypy==1.8.0 numpy>=1.23,<2 # For mypy plugin -#TODO(#4704): clean that up when pytorch is available for 3.12 -torch>=2.0.1 ; python_version < "3.12" +torch>=2.0.1 pip-check-reqs==2.4.4 # Checks for missing deps in requirements.txt files pytest # For mypy to work ruff==0.2.2 diff --git a/scripts/requirements-dev.txt b/scripts/requirements-dev.txt index 6a74004947b0..3d8840a76ef4 100644 --- a/scripts/requirements-dev.txt +++ b/scripts/requirements-dev.txt @@ -8,8 +8,7 @@ cryptography==38.0.4 # for scripts/upload_image.py google-cloud-storage==2.9.0 # for scripts/upload_image.py PyGithub==1.58.2 # for scripts/ci/generate_pr_summary.py and scripts/ci/update_pr_body.py Pillow # for scripts/upload_image.py -#TODO(#4704): clean that up when pytorch is available for 3.12 -torch ; python_version < "3.12" +torch tqdm requests gitignore_parser # handle .gitignore From e3c4fdeb1e598025bb671c1e717ae4a9721bd24e Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Wed, 10 Apr 2024 18:29:45 +0200 Subject: [PATCH 243/508] Port `re_viewport`-related queries to new data APIs (#5860) **Trivial commit by commit** Implements `ToArchetype for QueryResults` for all blueprint-related types, and then use the new cached APIs for all blueprint UI stuff. With this PR, everything in the UI besides the space views should now be powered by the new data APIs. --- - Requires #5853 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5860) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5860?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5860?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5860) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- Cargo.lock | 1 + crates/re_entity_db/Cargo.toml | 2 +- crates/re_entity_db/src/entity_db.rs | 33 ++++ crates/re_query_cache2/Cargo.toml | 3 +- .../re_query_cache2/src/latest_at/results.rs | 6 +- .../src/latest_at/to_archetype/.gitattributes | 8 + .../latest_at/to_archetype/background3d.rs | 65 +++++++ .../to_archetype/container_blueprint.rs | 163 ++++++++++++++++++ .../src/latest_at/to_archetype/mod.rs | 8 + .../latest_at/to_archetype/panel_blueprint.rs | 49 ++++++ .../src/latest_at/to_archetype/plot_legend.rs | 58 +++++++ .../src/latest_at/to_archetype/scalar_axis.rs | 62 +++++++ .../to_archetype/space_view_blueprint.rs | 100 +++++++++++ .../to_archetype/space_view_contents.rs | 45 +++++ .../to_archetype/viewport_blueprint.rs | 113 ++++++++++++ crates/re_space_view/src/space_view.rs | 27 +-- .../re_space_view/src/space_view_contents.rs | 37 ++-- crates/re_space_view/src/sub_archetypes.rs | 31 ++-- .../src/space_view_3d.rs | 2 +- .../src/codegen/rust/to_archetype.rs | 75 ++++---- crates/re_viewport/src/container.rs | 28 +-- crates/re_viewport/src/viewport_blueprint.rs | 14 +- 22 files changed, 834 insertions(+), 96 deletions(-) create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/background3d.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/container_blueprint.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/panel_blueprint.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/plot_legend.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/scalar_axis.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/space_view_blueprint.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/space_view_contents.rs create mode 100644 crates/re_query_cache2/src/latest_at/to_archetype/viewport_blueprint.rs diff --git a/Cargo.lock b/Cargo.lock index 4174723ef13b..5eddcb0ff171 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4624,6 +4624,7 @@ dependencies = [ "re_query2", "re_tracing", "re_types", + "re_types_blueprint", "re_types_core", "seq-macro", "similar-asserts", diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index 79e4bc740c0f..c4d703bfd23b 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -33,7 +33,7 @@ re_log_types.workspace = true re_query.workspace = true re_query2.workspace = true re_query_cache.workspace = true -re_query_cache2.workspace = true +re_query_cache2 = { workspace = true, features = ["to_archetype"] } re_smart_channel.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index e5dabe66b608..eb31fe3406b1 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -12,6 +12,7 @@ use re_log_types::{ LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, TimeRange, TimeRangeF, Timeline, }; +use re_query2::PromiseResult; use re_types_core::{components::InstanceKey, Archetype, Loggable}; use crate::{ClearCascade, CompactedStoreEvents, Error, TimesPerTimeline}; @@ -210,6 +211,38 @@ impl EntityDb { &self.resolver } + /// Returns `Ok(None)` if any of the required components are missing. + #[inline] + pub fn latest_at_archetype( + &self, + entity_path: &EntityPath, + query: &re_data_store::LatestAtQuery, + ) -> PromiseResult> + where + re_query_cache2::CachedLatestAtResults: re_query_cache2::ToArchetype, + { + let results = self.query_caches2().latest_at( + self.store(), + query, + entity_path, + A::all_components().iter().cloned(), // no generics! + ); + + use re_query_cache2::ToArchetype as _; + match results.to_archetype(self.resolver()).flatten() { + PromiseResult::Pending => PromiseResult::Pending, + PromiseResult::Error(err) => { + if let Some(err) = err.downcast_ref::() { + if matches!(err, re_query_cache2::QueryError::PrimaryNotFound(_)) { + return PromiseResult::Ready(None); + } + } + PromiseResult::Error(err) + } + PromiseResult::Ready(arch) => PromiseResult::Ready(Some(arch)), + } + } + #[inline] pub fn latest_at_component( &self, diff --git a/crates/re_query_cache2/Cargo.toml b/crates/re_query_cache2/Cargo.toml index b87432ff1fb8..47f6e0db6485 100644 --- a/crates/re_query_cache2/Cargo.toml +++ b/crates/re_query_cache2/Cargo.toml @@ -21,7 +21,7 @@ all-features = true default = ["to_archetype"] ## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. -to_archetype = ["dep:re_types"] +to_archetype = ["dep:re_types", "dep:re_types_blueprint"] [dependencies] # Rerun dependencies: @@ -36,6 +36,7 @@ re_types_core.workspace = true # Rerun dependencies (optional): re_types = { workspace = true, optional = true } +re_types_blueprint = { workspace = true, optional = true } # External dependencies: ahash.workspace = true diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index 99319de5d4b9..909c16916dd9 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -72,11 +72,7 @@ impl CachedLatestAtResults { if let Some(component) = self.components.get(&component_name) { Ok(component) } else { - Err(DeserializationError::MissingComponent { - component: component_name, - backtrace: ::backtrace::Backtrace::new_unresolved(), - } - .into()) + Err(QueryError::PrimaryNotFound(component_name)) } } diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes b/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes index b074eccb685e..b258bf0350f5 100644 --- a/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes +++ b/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes @@ -5,10 +5,12 @@ annotation_context.rs linguist-generated=true arrows2d.rs linguist-generated=true arrows3d.rs linguist-generated=true asset3d.rs linguist-generated=true +background3d.rs linguist-generated=true bar_chart.rs linguist-generated=true boxes2d.rs linguist-generated=true boxes3d.rs linguist-generated=true clear.rs linguist-generated=true +container_blueprint.rs linguist-generated=true depth_image.rs linguist-generated=true disconnected_space.rs linguist-generated=true image.rs linguist-generated=true @@ -16,15 +18,21 @@ line_strips2d.rs linguist-generated=true line_strips3d.rs linguist-generated=true mesh3d.rs linguist-generated=true mod.rs linguist-generated=true +panel_blueprint.rs linguist-generated=true pinhole.rs linguist-generated=true +plot_legend.rs linguist-generated=true points2d.rs linguist-generated=true points3d.rs linguist-generated=true scalar.rs linguist-generated=true +scalar_axis.rs linguist-generated=true segmentation_image.rs linguist-generated=true series_line.rs linguist-generated=true series_point.rs linguist-generated=true +space_view_blueprint.rs linguist-generated=true +space_view_contents.rs linguist-generated=true tensor.rs linguist-generated=true text_document.rs linguist-generated=true text_log.rs linguist-generated=true transform3d.rs linguist-generated=true view_coordinates.rs linguist-generated=true +viewport_blueprint.rs linguist-generated=true diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/background3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/background3d.rs new file mode 100644 index 000000000000..4ad631f419b9 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/background3d.rs @@ -0,0 +1,65 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::blueprint::components::Background3DKind; + let kind = match self.get_required(::name()) { + Ok(kind) => kind, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let kind = match kind.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Color; + let color = if let Some(color) = self.get(::name()) { + match color.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::blueprint::archetypes::Background3D { kind, color }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/container_blueprint.rs b/crates/re_query_cache2/src/latest_at/to_archetype/container_blueprint.rs new file mode 100644 index 000000000000..e49749d7b5e2 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/container_blueprint.rs @@ -0,0 +1,163 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype + for CachedLatestAtResults +{ + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> + { + re_tracing::profile_function!( + ::name() + ); + + // --- Required --- + + use re_types_blueprint::blueprint::components::ContainerKind; + let container_kind = match self.get_required(::name()) { + Ok(container_kind) => container_kind, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let container_kind = match container_kind.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Name; + let display_name = if let Some(display_name) = self.get(::name()) { + match display_name.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::IncludedContent; + let contents = if let Some(contents) = self.get(::name()) { + match contents.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::ColumnShare; + let col_shares = if let Some(col_shares) = self.get(::name()) { + match col_shares.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::RowShare; + let row_shares = if let Some(row_shares) = self.get(::name()) { + match row_shares.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::ActiveTab; + let active_tab = if let Some(active_tab) = self.get(::name()) { + match active_tab.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::Visible; + let visible = if let Some(visible) = self.get(::name()) { + match visible.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types_blueprint::blueprint::components::GridColumns; + let grid_columns = if let Some(grid_columns) = self.get(::name()) { + match grid_columns.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types_blueprint::blueprint::archetypes::ContainerBlueprint { + container_kind, + display_name, + contents, + col_shares, + row_shares, + active_tab, + visible, + grid_columns, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs b/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs index a66a21691f82..b4e4e8b5a695 100644 --- a/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs +++ b/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs @@ -4,25 +4,33 @@ mod annotation_context; mod arrows2d; mod arrows3d; mod asset3d; +mod background3d; mod bar_chart; mod boxes2d; mod boxes3d; mod clear; +mod container_blueprint; mod depth_image; mod disconnected_space; mod image; mod line_strips2d; mod line_strips3d; mod mesh3d; +mod panel_blueprint; mod pinhole; +mod plot_legend; mod points2d; mod points3d; mod scalar; +mod scalar_axis; mod segmentation_image; mod series_line; mod series_point; +mod space_view_blueprint; +mod space_view_contents; mod tensor; mod text_document; mod text_log; mod transform3d; mod view_coordinates; +mod viewport_blueprint; diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/panel_blueprint.rs b/crates/re_query_cache2/src/latest_at/to_archetype/panel_blueprint.rs new file mode 100644 index 000000000000..df25768d3573 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/panel_blueprint.rs @@ -0,0 +1,49 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype + for CachedLatestAtResults +{ + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> + { + re_tracing::profile_function!( + ::name() + ); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::blueprint::components::PanelExpanded; + let expanded = if let Some(expanded) = self.get(::name()) { + match expanded.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types_blueprint::blueprint::archetypes::PanelBlueprint { expanded }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/plot_legend.rs b/crates/re_query_cache2/src/latest_at/to_archetype/plot_legend.rs new file mode 100644 index 000000000000..33e5bbe1c8ca --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/plot_legend.rs @@ -0,0 +1,58 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::blueprint::components::Corner2D; + let corner = if let Some(corner) = self.get(::name()) { + match corner.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::Visible; + let visible = if let Some(visible) = self.get(::name()) { + match visible.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::blueprint::archetypes::PlotLegend { corner, visible }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/scalar_axis.rs b/crates/re_query_cache2/src/latest_at/to_archetype/scalar_axis.rs new file mode 100644 index 000000000000..066a0e4c7cdb --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/scalar_axis.rs @@ -0,0 +1,62 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::components::Range1D; + let range = if let Some(range) = self.get(::name()) { + match range.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::LockRangeDuringZoom; + let lock_range_during_zoom = + if let Some(lock_range_during_zoom) = self.get(::name()) { + match lock_range_during_zoom.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::blueprint::archetypes::ScalarAxis { + range, + lock_range_during_zoom, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/space_view_blueprint.rs b/crates/re_query_cache2/src/latest_at/to_archetype/space_view_blueprint.rs new file mode 100644 index 000000000000..550867169c71 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/space_view_blueprint.rs @@ -0,0 +1,100 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype + for CachedLatestAtResults +{ + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + use re_types::blueprint::components::SpaceViewClass; + let class_identifier = match self.get_required(::name()) { + Ok(class_identifier) => class_identifier, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }; + let class_identifier = match class_identifier.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => { + let Some(first) = data.first().cloned() else { + return PromiseResult::Error(std::sync::Arc::new( + re_types_core::DeserializationError::missing_data(), + )); + }; + first + } + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- Recommended/Optional --- + + use re_types::components::Name; + let display_name = if let Some(display_name) = self.get(::name()) { + match display_name.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::SpaceViewOrigin; + let space_origin = if let Some(space_origin) = self.get(::name()) { + match space_origin.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::Visible; + let visible = if let Some(visible) = self.get(::name()) { + match visible.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::blueprint::archetypes::SpaceViewBlueprint { + class_identifier, + display_name, + space_origin, + visible, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/space_view_contents.rs b/crates/re_query_cache2/src/latest_at/to_archetype/space_view_contents.rs new file mode 100644 index 000000000000..94b7181ddf6b --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/space_view_contents.rs @@ -0,0 +1,45 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype + for CachedLatestAtResults +{ + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::blueprint::components::QueryExpression; + let query = match self + .get_or_empty(::name()) + .to_dense::(resolver) + { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.to_vec(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + + // --- + + let arch = re_types::blueprint::archetypes::SpaceViewContents { query }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/viewport_blueprint.rs b/crates/re_query_cache2/src/latest_at/to_archetype/viewport_blueprint.rs new file mode 100644 index 000000000000..40beb2b65262 --- /dev/null +++ b/crates/re_query_cache2/src/latest_at/to_archetype/viewport_blueprint.rs @@ -0,0 +1,113 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] + +use crate::CachedLatestAtResults; +use re_query2::{PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype + for CachedLatestAtResults +{ + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> + { + re_tracing::profile_function!( + ::name() + ); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types_blueprint::blueprint::components::RootContainer; + let root_container = if let Some(root_container) = self.get(::name()) { + match root_container.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types_blueprint::blueprint::components::SpaceViewMaximized; + let maximized = if let Some(maximized) = self.get(::name()) { + match maximized.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types_blueprint::blueprint::components::AutoLayout; + let auto_layout = if let Some(auto_layout) = self.get(::name()) { + match auto_layout.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types_blueprint::blueprint::components::AutoSpaceViews; + let auto_space_views = if let Some(auto_space_views) = self.get(::name()) { + match auto_space_views.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::ViewerRecommendationHash; + let past_viewer_recommendations = if let Some(past_viewer_recommendations) = + self.get(::name()) + { + match past_viewer_recommendations.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => Some(data.to_vec()), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types_blueprint::blueprint::archetypes::ViewportBlueprint { + root_container, + maximized, + auto_layout, + auto_space_views, + past_viewer_recommendations, + }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 8ad6b2d43e10..a590f96203c7 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,11 +1,11 @@ use itertools::{FoldWhile, Itertools}; use nohash_hasher::IntMap; +use re_entity_db::external::re_query2::PromiseResult; use crate::SpaceViewContents; use re_data_store::LatestAtQuery; use re_entity_db::{EntityDb, EntityPath, EntityPropertiesComponent, EntityPropertyMap}; use re_log_types::{DataRow, EntityPathSubs, RowId}; -use re_query::query_archetype; use re_types::blueprint::archetypes as blueprint_archetypes; use re_types::{ blueprint::components::{SpaceViewOrigin, Visible}, @@ -122,18 +122,21 @@ impl SpaceViewBlueprint { class_identifier, space_origin, visible, - } = query_archetype(blueprint_db.store(), query, &id.as_entity_path()) - .and_then(|arch| arch.to_archetype()) - .map_err(|err| { - if !matches!(err, re_query::QueryError::PrimaryNotFound(_)) { - if cfg!(debug_assertions) { - re_log::error!("Failed to load SpaceView blueprint: {err}."); - } else { - re_log::debug!("Failed to load SpaceView blueprint: {err}."); - } + } = match blueprint_db.latest_at_archetype(&id.as_entity_path(), query) { + PromiseResult::Pending => { + // TODO(#5607): what should happen if the promise is still pending? + None + } + PromiseResult::Ready(arch) => arch, + PromiseResult::Error(err) => { + if cfg!(debug_assertions) { + re_log::error!("Failed to load SpaceView blueprint: {err}."); + } else { + re_log::debug!("Failed to load SpaceView blueprint: {err}."); } - }) - .ok()?; + None + } + }?; let space_origin = space_origin.map_or_else(EntityPath::root, |origin| origin.0.into()); let class_identifier: SpaceViewClassIdentifier = class_identifier.0.as_str().into(); diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index d5dba19e6355..4ed247703593 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -3,8 +3,8 @@ use slotmap::SlotMap; use smallvec::SmallVec; use re_entity_db::{ - external::re_data_store::LatestAtQuery, EntityDb, EntityProperties, EntityPropertiesComponent, - EntityPropertyMap, EntityTree, + external::{re_data_store::LatestAtQuery, re_query2::PromiseResult}, + EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, }; use re_log_types::{ path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule, EntityPathSubs, @@ -105,15 +105,30 @@ impl SpaceViewContents { blueprint_archetypes::SpaceViewContents, >(id, blueprint_db, query); - let blueprint_archetypes::SpaceViewContents { query } = contents.unwrap_or_else(|err| { - re_log::warn_once!( - "Failed to load SpaceViewContents for {:?} from blueprint store at {:?}: {}", - id, - blueprint_entity_path, - err - ); - Default::default() - }); + let blueprint_archetypes::SpaceViewContents { query } = match contents { + PromiseResult::Pending => { + // TODO(#5607): what should happen if the promise is still pending? + Default::default() + } + PromiseResult::Ready(Some(arch)) => arch, + PromiseResult::Ready(None) => { + re_log::warn_once!( + "Failed to load SpaceViewContents for {:?} from blueprint store at {:?}: not found", + id, + blueprint_entity_path, + ); + Default::default() + } + PromiseResult::Error(err) => { + re_log::warn_once!( + "Failed to load SpaceViewContents for {:?} from blueprint store at {:?}: {}", + id, + blueprint_entity_path, + err + ); + Default::default() + } + }; let query = query.iter().map(|qe| qe.0.as_str()); diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 5098e2bbee1c..1da0a8d04ab3 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -1,7 +1,9 @@ use re_data_store::LatestAtQuery; -use re_entity_db::EntityDb; +use re_entity_db::{ + external::re_query_cache2::{CachedLatestAtResults, PromiseResult, ToArchetype}, + EntityDb, +}; use re_log_types::EntityPath; -use re_query::query_archetype; use re_types::Archetype; use re_viewer_context::{external::re_entity_db::EntityTree, SpaceViewId}; @@ -20,24 +22,27 @@ pub fn entity_path_for_space_view_sub_archetype( space_view_blueprint_path.join(&EntityPath::from_single_string(T::name().short_name())) } -pub fn query_space_view_sub_archetype( +/// Returns `Ok(None)` if any of the required components are missing. +pub fn query_space_view_sub_archetype( space_view_id: SpaceViewId, blueprint_db: &EntityDb, query: &LatestAtQuery, -) -> (Result, EntityPath) { - let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); - - ( - query_archetype(blueprint_db.store(), query, &path).and_then(|arch| arch.to_archetype()), - path, - ) +) -> (PromiseResult>, EntityPath) +where + CachedLatestAtResults: ToArchetype, +{ + let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); + (blueprint_db.latest_at_archetype(&path, query), path) } -pub fn query_space_view_sub_archetype_or_default( +pub fn query_space_view_sub_archetype_or_default( space_view_id: SpaceViewId, blueprint_db: &EntityDb, query: &LatestAtQuery, -) -> (T, EntityPath) { +) -> (A, EntityPath) +where + CachedLatestAtResults: ToArchetype, +{ let (arch, path) = query_space_view_sub_archetype(space_view_id, blueprint_db, query); - (arch.unwrap_or_default(), path) + (arch.ok().flatten().unwrap_or_default(), path) } diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 75f02282b50d..47dd77d59172 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -407,7 +407,7 @@ fn background_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mut e let (archetype, blueprint_path) = query_space_view_sub_archetype(space_view_id, blueprint_db, blueprint_query); - let Background3D { color, mut kind } = archetype.unwrap_or_default(); + let Background3D { color, mut kind } = archetype.ok().flatten().unwrap_or_default(); ctx.re_ui.grid_left_hand_label(ui, "Background"); diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs index 9c755a0e7b70..476b8bae9c93 100644 --- a/crates/re_types_builder/src/codegen/rust/to_archetype.rs +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -43,11 +43,6 @@ fn generate_mod( let mut mods = Vec::new(); for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { - if obj.scope() == Some("blueprint".to_owned()) { - // TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. - continue; - } - // TODO(#4478): add a 'testing' scope if obj.fqname.contains("testing") { continue; @@ -79,11 +74,6 @@ fn generate_impls( }; for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { - if obj.scope() == Some("blueprint".to_owned()) { - // TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. - continue; - } - if obj .try_get_attr::(crate::ATTR_RUST_SERDE_TYPE) .is_some() @@ -193,29 +183,53 @@ fn quote_to_archetype_impl(objects: &Objects, obj: &Object) -> TokenStream { let quoted_type_fqname = quote_fqname_as_type_path(&objects[type_fqname].crate_name(), type_fqname); - let quoted_data = if obj_field.typ.is_plural() { - quote!(Some(data.to_vec())) - } else { - quote!(data.first().cloned()) - }; - - Some(quote! { - #NEWLINE_TOKEN + if obj_field.is_nullable { + let quoted_data = if obj_field.typ.is_plural() { + quote!(Some(data.to_vec())) + } else { + quote!(data.first().cloned()) + }; - use #quoted_type_fqname; - let #quoted_name = if let Some(#quoted_name) = self.get(<#quoted_type_name>::name()) { - match #quoted_name.to_dense::<#quoted_type_name>(resolver) { - PromiseResult::Pending => return PromiseResult::Pending, - PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), - PromiseResult::Ready(query_res) => match query_res { - Ok(data) => #quoted_data, - Err(query_err) => return PromiseResult::Ready(Err(query_err)), - }, - } + Some(quote! { + #NEWLINE_TOKEN + + use #quoted_type_fqname; + let #quoted_name = if let Some(#quoted_name) = self.get(<#quoted_type_name>::name()) { + match #quoted_name.to_dense::<#quoted_type_name>(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => #quoted_data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + }) + } else { + let quoted_data = if obj_field.typ.is_plural() { + quote!(data.to_vec()) } else { - None + panic!("optional, non-nullable, non-plural data is not representable"); }; - }) + + Some(quote! { + #NEWLINE_TOKEN + + use #quoted_type_fqname; + let #quoted_name = + match self.get_or_empty(<#quoted_type_name>::name()).to_dense::<#quoted_type_name>(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => #quoted_data, + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + }; + }) + } + }); let quoted_fields = obj.fields.iter().map(|obj_field| { @@ -263,7 +277,6 @@ fn quote_to_archetype_impl(objects: &Objects, obj: &Object) -> TokenStream { // --- -// TODO(cmc): support types in re_viewport and somehow manage the dep-cycle of doom. fn quote_fqname_as_type_path(crate_name: &str, fqname: impl AsRef) -> TokenStream { let fqname = fqname .as_ref() diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index 213213cca614..65f53e480bd8 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -2,10 +2,9 @@ use ahash::HashMap; use egui_tiles::TileId; use re_data_store::LatestAtQuery; -use re_entity_db::EntityDb; +use re_entity_db::{external::re_query2::PromiseResult, EntityDb}; use re_log::ResultExt; use re_log_types::{DataRow, EntityPath, RowId}; -use re_query::query_archetype; use re_types::blueprint::components::Visible; use re_types::components::Name; use re_types_core::archetypes::Clear; @@ -55,18 +54,21 @@ impl ContainerBlueprint { active_tab, visible, grid_columns, - } = query_archetype(blueprint_db.store(), query, &id.as_entity_path()) - .and_then(|arch| arch.to_archetype()) - .map_err(|err| { - if !matches!(err, re_query::QueryError::PrimaryNotFound(_)) { - if cfg!(debug_assertions) { - re_log::error!("Failed to load container blueprint: {err}."); - } else { - re_log::debug!("Failed to load container blueprint: {err}."); - } + } = match blueprint_db.latest_at_archetype(&id.as_entity_path(), query) { + PromiseResult::Pending => { + // TODO(#5607): what should happen if the promise is still pending? + None + } + PromiseResult::Ready(arch) => arch, + PromiseResult::Error(err) => { + if cfg!(debug_assertions) { + re_log::error!("Failed to load container blueprint: {err}."); + } else { + re_log::debug!("Failed to load container blueprint: {err}."); } - }) - .ok()?; + None + } + }?; let container_kind = crate::container_kind_to_egui(container_kind); let display_name = display_name.map(|v| v.0.to_string()); diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 5c27b3463275..241092034d29 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -4,11 +4,11 @@ use std::sync::atomic::{AtomicBool, Ordering}; use ahash::HashMap; use egui_tiles::{SimplificationOptions, TileId}; use nohash_hasher::IntSet; +use re_entity_db::external::re_query2::PromiseResult; use smallvec::SmallVec; use re_data_store::LatestAtQuery; use re_entity_db::EntityPath; -use re_query::query_archetype; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::ViewerRecommendationHash; use re_types_blueprint::blueprint::components::{ @@ -75,15 +75,13 @@ impl ViewportBlueprint { auto_layout, auto_space_views, past_viewer_recommendations, - } = match query_archetype(blueprint_db.store(), query, &VIEWPORT_PATH.into()) - .and_then(|arch| arch.to_archetype()) - { - Ok(arch) => arch, - Err(re_query::QueryError::PrimaryNotFound(_)) => { - // Empty Store + } = match blueprint_db.latest_at_archetype(&VIEWPORT_PATH.into(), query) { + PromiseResult::Pending => { + // TODO(#5607): what should happen if the promise is still pending? Default::default() } - Err(err) => { + PromiseResult::Ready(arch) => arch.unwrap_or_default(), + PromiseResult::Error(err) => { if cfg!(debug_assertions) { re_log::error!("Failed to load viewport blueprint: {err}."); } else { From 62ff2d535cb71b2d754d45edfc24625c4aa3a04d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 10 Apr 2024 18:55:15 +0200 Subject: [PATCH 244/508] Run all jobs if any CI job changes (#5900) ### What If we change the any GitHub action `.yml` file, then run all jobs ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5900) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5900?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5900?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5900) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/on_pull_request.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 53662bb8e559..80a7c6cba429 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -34,6 +34,7 @@ jobs: with: filters: | rust_changes: + - .github/**/*.yml # CI changes should always trigger all jobs - "**/*.rs" - "**/*.toml" @@ -50,6 +51,7 @@ jobs: with: filters: | cpp_changes: + - .github/**/*.yml # CI changes should always trigger all jobs - '**/*.hpp' - '**/*.cpp' - '**/CMakeLists.txt' @@ -68,6 +70,7 @@ jobs: with: filters: | python_changes: + - .github/**/*.yml # CI changes should always trigger all jobs - '**/*.py' - '**/requirements.txt' - '**/pyproject.toml' @@ -85,6 +88,7 @@ jobs: with: filters: | docs_changes: + - .github/**/*.yml # CI changes should always trigger all jobs - 'docs/content/**/*.md' - 'examples/**/*.md' - 'examples/manifest.toml' From bc1becfd396c786570e168c5be134dec4a7ffb23 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Wed, 10 Apr 2024 18:58:20 +0200 Subject: [PATCH 245/508] Speed up CI: less use of `ci_docker` (#5896) ### What * Use less of `ci_docker` (it takes a minute to start!) * Smaller tweaks Saves around 5min of billable time (1h20m -> 1h15m) ### Checklist * [x] I've checked this checkbox - [PR Build Summary](https://build.rerun.io/pr/5896) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_checks.yml | 15 +++----------- .github/workflows/nightly.yml | 2 +- .github/workflows/on_pull_request.yml | 4 ++-- .github/workflows/on_push_main.yml | 2 +- .../reusable_build_and_upload_wheels.yml | 4 ++-- .github/workflows/reusable_build_js.yml | 11 ++++------ .github/workflows/reusable_build_web.yml | 9 +++------ .github/workflows/reusable_checks.yml | 8 -------- .github/workflows/reusable_checks_rust.yml | 20 +++++++++++++------ pixi.toml | 4 ++-- scripts/ci/cargo_deny.sh | 3 ++- scripts/clippy_wasm.sh | 2 ++ 12 files changed, 36 insertions(+), 48 deletions(-) diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 3898830c1c73..0f9b34ec8c28 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -84,20 +84,12 @@ jobs: no-codegen-changes: name: Check if running codegen would produce any changes runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 steps: # Note: We explicitly don't override `ref` here. We need to see if changes would be made # in a context where we have merged with main. Otherwise we might miss changes such as one # PR introduces a new type and another PR changes the codegen. - uses: actions/checkout@v4 - # So we can format the Python code - - name: Set up Python - shell: bash - run: | - pip install -r rerun_py/requirements-lint.txt - - uses: prefix-dev/setup-pixi@v0.4.1 with: pixi-version: v0.18.0 @@ -181,8 +173,6 @@ jobs: rs-check-wasm: name: Check Rust web build (wasm32 + wasm-bindgen) runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 @@ -258,11 +248,12 @@ jobs: rs-cargo-deny: name: Cargo Deny runs-on: ubuntu-latest - container: - image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 + - name: Install cargo-deny + run: cargo install --locked --quiet cargo-deny + - name: Cargo Deny shell: bash id: expected_version diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 8675978859ca..dcef8cb59ec9 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -39,7 +39,7 @@ jobs: secrets: inherit build-web: - name: "Build Web" + name: "Build and upload web viewer" uses: ./.github/workflows/reusable_build_web.yml with: CONCURRENCY: nightly diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 80a7c6cba429..c48ef2425361 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -149,7 +149,7 @@ jobs: secrets: inherit build-js: - name: "Build JS" + name: "Build rerun_js" if: github.event.pull_request.head.repo.owner.login == 'rerun-io' uses: ./.github/workflows/reusable_build_js.yml with: @@ -157,7 +157,7 @@ jobs: secrets: inherit build-web: - name: "Build Web" + name: "Build and upload web viewer" if: github.event.pull_request.head.repo.owner.login == 'rerun-io' uses: ./.github/workflows/reusable_build_web.yml with: diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 7172cbe435a6..3f1dc46ea2d3 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -77,7 +77,7 @@ jobs: secrets: inherit build-web: - name: "Build Web" + name: "Build and upload web viewer" uses: ./.github/workflows/reusable_build_web.yml with: CONCURRENCY: push-${{ github.ref_name }} diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 47d3b1c27f46..ef58f4557b82 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -101,14 +101,14 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.12.0'" + container="'rerunio/ci_docker:0.12.0'" # Required to be manylinux compatible compat="manylinux_2_31" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" compat="manylinux_2_31" - container="'rerunio/ci_docker:0.12.0'" + container="'rerunio/ci_docker:0.12.0'" # Required to be manylinux compatible ;; windows-x64) runner="windows-latest-8-cores" diff --git a/.github/workflows/reusable_build_js.yml b/.github/workflows/reusable_build_js.yml index 71debee78fed..3d7eb6b63772 100644 --- a/.github/workflows/reusable_build_js.yml +++ b/.github/workflows/reusable_build_js.yml @@ -1,4 +1,4 @@ -name: Reusable Build JS +name: Reusable Build rerun_js on: workflow_call: @@ -22,16 +22,13 @@ env: jobs: build: - name: Build + name: Build rerun_js permissions: contents: "read" id-token: "write" runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 - steps: - uses: actions/checkout@v4 with: @@ -57,10 +54,10 @@ jobs: with: pixi-version: v0.18.0 - - name: Install dependencies + - name: Install yarn dependencies shell: bash run: pixi run yarn --cwd rerun_js install - - name: Build package + - name: Build rerun_js package shell: bash run: pixi run yarn --cwd rerun_js workspaces run build diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 82272e917908..7c3e571623b8 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -1,4 +1,4 @@ -name: Reusable Build Web +name: Reusable Build and upload web viewer on: workflow_call: @@ -29,16 +29,13 @@ env: jobs: rs-build-web-viewer: - name: Build Web (wasm32 + wasm-bindgen) + name: Build and upload web viewer permissions: contents: "read" id-token: "write" runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 - steps: - uses: actions/checkout@v4 with: @@ -78,7 +75,7 @@ jobs: --channel "${{ inputs.CHANNEL }}" \ web_viewer/examples_manifest.json - - name: Upload web assets + - name: Upload web viewer uses: actions/upload-artifact@v3 with: name: web_viewer diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 636ed9abb37b..8d26e917d41b 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -82,8 +82,6 @@ jobs: no-codegen-changes: name: Check if running codegen would produce any changes runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 env: RUSTC_WRAPPER: "sccache" steps: @@ -100,12 +98,6 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - # So we can format the Python code - - name: Set up Python - shell: bash - run: | - pip install -r rerun_py/requirements-lint.txt - - uses: prefix-dev/setup-pixi@v0.4.1 with: pixi-version: v0.18.0 diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 4994d066b565..89c6a7d4f3a2 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -38,8 +38,6 @@ jobs: rs-lints: name: Rust lints (fmt, check, cranky, tests, doc) runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 env: RUSTC_WRAPPER: "sccache" steps: @@ -66,6 +64,9 @@ jobs: run: | pixi run cargo run --locked -p re_build_web_viewer -- --release -g + - name: install cargo cranky + run: cargo install --locked --quiet cargo-cranky + - name: Rust checks & tests if: ${{ !inputs.ALL_CHECKS }} run: ./scripts/ci/rust_checks.py --skip-check-individual-crates @@ -79,8 +80,6 @@ jobs: rs-check-wasm: name: Check Rust web build (wasm32 + wasm-bindgen) runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 env: RUSTC_WRAPPER: "sccache" steps: @@ -121,13 +120,22 @@ jobs: rs-cargo-deny: name: Cargo Deny runs-on: ubuntu-latest - container: - image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + - name: Set up Rust + uses: ./.github/actions/setup-rust + with: + cache_key: "rs-cargo-deny" + save_cache: true + workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} + service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} + + - name: Install cargo-deny + run: cargo install --locked --quiet cargo-deny + - name: Cargo Deny shell: bash id: expected_version diff --git a/pixi.toml b/pixi.toml index 9cc0ef04d145..a22399982bda 100644 --- a/pixi.toml +++ b/pixi.toml @@ -28,7 +28,7 @@ cpp = ["cpp"] # Note: extra CLI argument after `pixi run TASK` are passed to the task cmd. # Run the codegen. Optionally pass `--profile` argument if you want. -codegen = "cargo run --package re_types_builder -- " +codegen = "cargo --quiet run --package re_types_builder -- " # Compile and run the rerun viewer. # @@ -86,7 +86,7 @@ fmt = { depends_on = ["format"] } # Assorted linting tasks fast-lint = "python scripts/fast_lint.py" -lint-codegen = "cargo run --package re_types_builder -- --check" +lint-codegen = "cargo --quiet run --package re_types_builder -- --check" # TODO(jleibs): implement lint-cpp-all lint-rerun = "python scripts/lint.py" lint-rs-files = "rustfmt --edition 2021 --check" diff --git a/scripts/ci/cargo_deny.sh b/scripts/ci/cargo_deny.sh index 68fae4c98eb4..6cf700132b8c 100755 --- a/scripts/ci/cargo_deny.sh +++ b/scripts/ci/cargo_deny.sh @@ -5,7 +5,8 @@ script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) cd "$script_path/../.." set -x -# cargo install cargo-deny +cargo install --locked --quiet cargo-deny + cargo deny --all-features --log-level error --target aarch64-apple-darwin check cargo deny --all-features --log-level error --target i686-pc-windows-gnu check cargo deny --all-features --log-level error --target i686-pc-windows-msvc check diff --git a/scripts/clippy_wasm.sh b/scripts/clippy_wasm.sh index 107a6c96049a..0b320a2ecaab 100755 --- a/scripts/clippy_wasm.sh +++ b/scripts/clippy_wasm.sh @@ -10,4 +10,6 @@ set -x # Use scripts/clippy_wasm/clippy.toml export CLIPPY_CONF_DIR="scripts/clippy_wasm" +cargo install --locked --quiet cargo-cranky + cargo cranky --all-features --target wasm32-unknown-unknown --target-dir target_wasm -p re_viewer -- --deny warnings From 13a2193421d5bb94000b6aa1d6d163b21793f549 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 07:19:37 +0200 Subject: [PATCH 246/508] CI: update misc actions (#5902) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What We get a lot of these warnings on CI: > Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: … This attempts to fix those ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5902) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5902?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5902?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5902) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/actions/setup-rust/action.yml | 2 +- .github/workflows/checkboxes.yml | 2 +- .github/workflows/on_pull_request.yml | 8 ++++---- .../on_pull_request_target_contrib.yml | 2 +- .github/workflows/release.yml | 4 ++-- .github/workflows/reusable_bench.yml | 8 ++++---- .../reusable_build_and_upload_rerun_c.yml | 4 ++-- .../reusable_build_and_upload_rerun_cli.yml | 4 ++-- .../reusable_build_and_upload_wheels.yml | 2 +- .github/workflows/reusable_build_examples.yml | 4 ++-- .github/workflows/reusable_build_web.yml | 2 +- .../reusable_bundle_and_upload_rerun_cpp.yml | 4 ++-- .../reusable_deploy_landing_preview.yml | 2 +- .github/workflows/reusable_pip_index.yml | 6 +++--- .github/workflows/reusable_pr_summary.yml | 6 +++--- .github/workflows/reusable_publish_web.yml | 10 +++++----- .github/workflows/reusable_publish_wheels.yml | 4 ++-- .github/workflows/reusable_run_notebook.yml | 6 +++--- .../workflows/reusable_sync_release_assets.yml | 4 ++-- .github/workflows/reusable_test_wheels.yml | 2 +- .github/workflows/reusable_track_size.yml | 14 +++++++------- .github/workflows/reusable_update_pr_body.yml | 2 +- .github/workflows/reusable_upload_examples.yml | 18 +++++++++--------- .github/workflows/reusable_upload_web.yml | 18 +++++++++--------- 24 files changed, 69 insertions(+), 69 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index 0478952e2f0c..04b26ad20532 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -35,7 +35,7 @@ runs: using: "composite" steps: - name: Set up GCP credentials - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ inputs.workload_identity_provider }} service_account: ${{ inputs.service_account }} diff --git a/.github/workflows/checkboxes.yml b/.github/workflows/checkboxes.yml index 3e258ae3f703..6dd1be1ec9b5 100644 --- a/.github/workflows/checkboxes.yml +++ b/.github/workflows/checkboxes.yml @@ -29,7 +29,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index c48ef2425361..84b57e5803a3 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -29,7 +29,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: dorny/paths-filter@v2 + - uses: dorny/paths-filter@v3 id: filter with: filters: | @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: dorny/paths-filter@v2 + - uses: dorny/paths-filter@v3 id: filter with: filters: | @@ -65,7 +65,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: dorny/paths-filter@v2 + - uses: dorny/paths-filter@v3 id: filter with: filters: | @@ -83,7 +83,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: dorny/paths-filter@v2 + - uses: dorny/paths-filter@v3 id: filter with: filters: | diff --git a/.github/workflows/on_pull_request_target_contrib.yml b/.github/workflows/on_pull_request_target_contrib.yml index 6f8a08de8a24..eb2e950e5006 100644 --- a/.github/workflows/on_pull_request_target_contrib.yml +++ b/.github/workflows/on_pull_request_target_contrib.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef2edd90fbd8..ee3f98c6bcce 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,7 +79,7 @@ jobs: node-version: 18 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 @@ -386,7 +386,7 @@ jobs: node-version: 18 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 diff --git a/.github/workflows/reusable_bench.yml b/.github/workflows/reusable_bench.yml index 7c6885a4c65b..5f1c05da69e2 100644 --- a/.github/workflows/reusable_bench.yml +++ b/.github/workflows/reusable_bench.yml @@ -87,13 +87,13 @@ jobs: -- --output-format=bencher | tee /tmp/${{ env.SHORT_SHA }} - name: "Set up Cloud SDK" - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 363.0.0" # TODO(jleibs) make this whole thing a python script - name: "Upload bench to GCS based on SHA" - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: /tmp/${{ env.SHORT_SHA }} destination: "rerun-builds/benches/" @@ -112,7 +112,7 @@ jobs: - name: "Upload bench-results to GCS" if: ${{ inputs.COMPARE_TO != '' }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: /tmp/bench_results.txt destination: "rerun-builds/commit/${{env.SHORT_SHA}}/" @@ -125,7 +125,7 @@ jobs: # Don't upload the new named bench until the end in case the names are the same - name: "Upload named bench to GCS" if: ${{ inputs.BENCH_NAME != '' }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: /tmp/${{ inputs.BENCH_NAME }} destination: "rerun-builds/benches/" diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml index 79a1958a806d..751a934e5237 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_c.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml @@ -163,7 +163,7 @@ jobs: echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT" - name: "Upload rerun_c (commit)" - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "./target/${{ needs.set-config.outputs.TARGET }}/release/${{ needs.set-config.outputs.LIB_NAME }}" destination: "rerun-builds/commit/${{ steps.get-sha.outputs.sha }}/rerun_c/${{ inputs.PLATFORM }}" @@ -171,7 +171,7 @@ jobs: - name: "Upload rerun_c (adhoc)" if: ${{ inputs.ADHOC_NAME != '' }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "./target/${{ needs.set-config.outputs.TARGET }}/release/${{ needs.set-config.outputs.LIB_NAME }}" destination: "rerun-builds/adhoc/${{inputs.ADHOC_NAME}}/rerun_c/${{ inputs.PLATFORM }}" diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index ff51bd370213..98fd400f0537 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -183,7 +183,7 @@ jobs: echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT" - name: "Upload rerun-cli (commit)" - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "./target/${{ needs.set-config.outputs.TARGET }}/release/${{ needs.set-config.outputs.BIN_NAME }}" destination: "rerun-builds/commit/${{ steps.get-sha.outputs.sha }}/rerun-cli/${{ inputs.PLATFORM }}" @@ -191,7 +191,7 @@ jobs: - name: "Upload rerun-cli (adhoc)" if: ${{ inputs.ADHOC_NAME != '' }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "./target/${{ needs.set-config.outputs.TARGET }}/release/${{ needs.set-config.outputs.BIN_NAME }}" destination: "rerun-builds/adhoc/${{inputs.ADHOC_NAME}}/rerun-cli/${{ inputs.PLATFORM }}" diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index ef58f4557b82..d81790146a3c 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -206,7 +206,7 @@ jobs: - name: Save wheel artifact if: ${{ inputs.WHEEL_ARTIFACT_NAME != '' }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{inputs.WHEEL_ARTIFACT_NAME}} path: dist/${{ needs.set-config.outputs.TARGET }} diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 2c2411057738..24f5918d9cbd 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -53,7 +53,7 @@ jobs: pixi-version: v0.18.0 - name: Download Wheel - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ inputs.WHEEL_ARTIFACT_NAME }} path: wheel @@ -100,7 +100,7 @@ jobs: example_data/snippets - name: Upload assets - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: example_data path: example_data diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 7c3e571623b8..5393401340fa 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -76,7 +76,7 @@ jobs: web_viewer/examples_manifest.json - name: Upload web viewer - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: web_viewer path: web_viewer diff --git a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml index 33df3acec442..83d9d6df4ba5 100644 --- a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml +++ b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml @@ -31,13 +31,13 @@ jobs: ref: ${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.ref) || '') }} - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - name: "Set up Cloud SDK" - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 363.0.0" diff --git a/.github/workflows/reusable_deploy_landing_preview.yml b/.github/workflows/reusable_deploy_landing_preview.yml index e1198e3124f5..e5e9abe85d17 100644 --- a/.github/workflows/reusable_deploy_landing_preview.yml +++ b/.github/workflows/reusable_deploy_landing_preview.yml @@ -49,7 +49,7 @@ jobs: - name: Create PR comment # https://github.com/mshick/add-pr-comment - uses: mshick/add-pr-comment@v2.8.1 + uses: mshick/add-pr-comment@v2.8.2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} message: | diff --git a/.github/workflows/reusable_pip_index.yml b/.github/workflows/reusable_pip_index.yml index 2179d0613414..6c177a18b781 100644 --- a/.github/workflows/reusable_pip_index.yml +++ b/.github/workflows/reusable_pip_index.yml @@ -32,18 +32,18 @@ jobs: ref: ${{ inputs.COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || '') }} - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - name: "Set up Cloud SDK" - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 363.0.0" diff --git a/.github/workflows/reusable_pr_summary.yml b/.github/workflows/reusable_pr_summary.yml index cccc509e6173..b0e5c3a5bb9f 100644 --- a/.github/workflows/reusable_pr_summary.yml +++ b/.github/workflows/reusable_pr_summary.yml @@ -32,18 +32,18 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - name: "Set up Cloud SDK" - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 363.0.0" diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index 8230e3513e9d..7c925bcc9177 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -54,13 +54,13 @@ jobs: ref: ${{ inputs.release-commit }} - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - name: "Set up Cloud SDK" - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 363.0.0" @@ -78,7 +78,7 @@ jobs: # built by `reusable_build_and_publish_wheels` - name: Download Wheel - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ inputs.wheel-artifact-name }} path: wheel @@ -126,14 +126,14 @@ jobs: web_viewer/examples_manifest.json - name: Upload app.rerun.io (versioned) - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/version/${{ inputs.release-version }}" parent: false - name: Upload app.rerun.io (commit) - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/commit/${{ needs.get-commit-sha.outputs.short-sha }}" diff --git a/.github/workflows/reusable_publish_wheels.yml b/.github/workflows/reusable_publish_wheels.yml index 274b72c406dd..ed8b5e3afa30 100644 --- a/.github/workflows/reusable_publish_wheels.yml +++ b/.github/workflows/reusable_publish_wheels.yml @@ -152,13 +152,13 @@ jobs: ref: ${{ inputs.release-commit }} - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - name: "Set up Cloud SDK" - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 363.0.0" diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml index b741ad6750e2..c10ff10df916 100644 --- a/.github/workflows/reusable_run_notebook.yml +++ b/.github/workflows/reusable_run_notebook.yml @@ -34,7 +34,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - name: Download Wheel Artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ inputs.WHEEL_ARTIFACT_NAME }} path: wheel_artifact @@ -66,7 +66,7 @@ jobs: jupyter nbconvert --to=html --ExecutePreprocessor.enabled=True examples/python/notebook/cube.ipynb --output /tmp/cube.html - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} @@ -79,7 +79,7 @@ jobs: echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT" - name: "Upload Notebook" - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "/tmp/cube.html" destination: "rerun-builds/commit/${{ steps.get-sha.outputs.sha }}/notebooks" diff --git a/.github/workflows/reusable_sync_release_assets.yml b/.github/workflows/reusable_sync_release_assets.yml index fea9ddb54604..b94288ccda20 100644 --- a/.github/workflows/reusable_sync_release_assets.yml +++ b/.github/workflows/reusable_sync_release_assets.yml @@ -45,13 +45,13 @@ jobs: run: pip install google-cloud-storage "PyGithub==1.59.0" "requests>=2.31,<3" - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - name: "Set up Cloud SDK" - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 363.0.0" diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 160271a83567..dc82c73621ff 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -152,7 +152,7 @@ jobs: shell: bash - name: Download Wheel - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: ${{ inputs.WHEEL_ARTIFACT_NAME }} path: wheel diff --git a/.github/workflows/reusable_track_size.yml b/.github/workflows/reusable_track_size.yml index 4df28e81bd85..0dc0ce530c32 100644 --- a/.github/workflows/reusable_track_size.yml +++ b/.github/workflows/reusable_track_size.yml @@ -33,24 +33,24 @@ jobs: echo "short_sha=$(echo ${{ github.sha }} | cut -c1-7)" >> "$GITHUB_OUTPUT" - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - name: "Set up Cloud SDK" - uses: "google-github-actions/setup-gcloud@v1" + uses: "google-github-actions/setup-gcloud@v2" with: version: ">= 363.0.0" - name: Download web_viewer - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: web_viewer path: web_viewer - name: Download examples - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: example_data path: example_data @@ -132,7 +132,7 @@ jobs: echo "is comparison set: $is_comparison_set" - name: Upload data to GCS (commit) - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: /tmp/data.json destination: "rerun-builds/sizes/commit/${{ steps.context.outputs.short_sha }}" @@ -145,7 +145,7 @@ jobs: - name: Upload index if: github.ref == 'refs/heads/main' - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: /tmp/index destination: "rerun-builds/sizes" @@ -153,7 +153,7 @@ jobs: - name: Create PR comment if: inputs.PR_NUMBER != '' && steps.measure.outputs.is_comparison_set == 'true' # https://github.com/mshick/add-pr-comment - uses: mshick/add-pr-comment@v2.8.1 + uses: mshick/add-pr-comment@v2.8.2 with: repo-token: ${{ secrets.GITHUB_TOKEN }} message: | diff --git a/.github/workflows/reusable_update_pr_body.yml b/.github/workflows/reusable_update_pr_body.yml index 9e45202eb980..927bd03026d1 100644 --- a/.github/workflows/reusable_update_pr_body.yml +++ b/.github/workflows/reusable_update_pr_body.yml @@ -32,7 +32,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 diff --git a/.github/workflows/reusable_upload_examples.yml b/.github/workflows/reusable_upload_examples.yml index cfbd28f8e29c..22a0bbf3a506 100644 --- a/.github/workflows/reusable_upload_examples.yml +++ b/.github/workflows/reusable_upload_examples.yml @@ -45,14 +45,14 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - name: Download assets - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: example_data path: example_data # Upload the wasm, html etc to a Google cloud bucket: - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} @@ -66,7 +66,7 @@ jobs: - name: "Upload examples (commit)" if: ${{ !inputs.NIGHTLY }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "example_data" destination: "rerun-web-viewer/commit/${{ steps.get-sha.outputs.sha }}/examples" @@ -74,7 +74,7 @@ jobs: - name: "Upload examples (tagged)" if: inputs.MARK_TAGGED_VERSION - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "example_data" destination: "rerun-web-viewer/version/${{ inputs.RELEASE_VERSION }}/examples" @@ -82,7 +82,7 @@ jobs: - name: "Upload examples (adhoc)" if: ${{ inputs.ADHOC_NAME != '' }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "example_data" destination: "rerun-web-viewer/adhoc/${{ inputs.ADHOC_NAME }}/examples" @@ -90,7 +90,7 @@ jobs: - name: "Upload examples (prerelease)" if: github.ref == 'refs/heads/main' - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "example_data" destination: "rerun-web-viewer/prerelease/examples" @@ -100,7 +100,7 @@ jobs: - name: "Upload examples (main)" if: github.ref == 'refs/heads/main' - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "example_data" destination: "rerun-web-viewer/version/main/examples" @@ -110,7 +110,7 @@ jobs: - name: "Upload examples (pr)" if: ${{ inputs.PR_NUMBER != '' }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "example_data" destination: "rerun-web-viewer/pr/${{ inputs.PR_NUMBER }}/examples" @@ -120,7 +120,7 @@ jobs: - name: "Upload examples (nightly)" if: ${{ inputs.NIGHTLY }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "example_data" destination: "rerun-web-viewer/version/nightly/examples" diff --git a/.github/workflows/reusable_upload_web.yml b/.github/workflows/reusable_upload_web.yml index b2a43a745611..97da0f4c50b8 100644 --- a/.github/workflows/reusable_upload_web.yml +++ b/.github/workflows/reusable_upload_web.yml @@ -46,14 +46,14 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - name: Download Web Viewer - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: web_viewer path: web_viewer # Upload the wasm, html etc to a Google cloud bucket: - id: "auth" - uses: google-github-actions/auth@v1 + uses: google-github-actions/auth@v2 with: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} @@ -67,7 +67,7 @@ jobs: - name: "Upload web-viewer (commit)" if: ${{ !inputs.NIGHTLY }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/commit/${{ steps.get-sha.outputs.sha }}" @@ -75,7 +75,7 @@ jobs: - name: "Upload web-viewer (tagged)" if: inputs.MARK_TAGGED_VERSION - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/version/${{inputs.RELEASE_VERSION}}" @@ -83,7 +83,7 @@ jobs: - name: "Upload web-viewer (adhoc)" if: ${{ inputs.ADHOC_NAME != '' }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/adhoc/${{inputs.ADHOC_NAME}}" @@ -91,7 +91,7 @@ jobs: - name: "Upload web-viewer (prerelease)" if: github.ref == 'refs/heads/main' - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/prerelease" @@ -101,7 +101,7 @@ jobs: - name: "Upload web-viewer (main)" if: github.ref == 'refs/heads/main' - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/version/main" @@ -111,7 +111,7 @@ jobs: - name: "Upload web-viewer (pr)" if: ${{ inputs.PR_NUMBER != '' }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/pr/${{ inputs.PR_NUMBER }}" @@ -121,7 +121,7 @@ jobs: - name: "Upload web-viewer (nightly)" if: ${{ inputs.NIGHTLY }} - uses: google-github-actions/upload-cloud-storage@v1 + uses: google-github-actions/upload-cloud-storage@v2 with: path: "web_viewer" destination: "rerun-web-viewer/version/nightly" From 60cf846aff504c7747013c2655b09089019ca399 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 07:54:23 +0200 Subject: [PATCH 247/508] Speed up CI: Skip a few steps (#5901) * Part of https://github.com/rerun-io/rerun/issues/3033 ### What For PRs, skip: * Building a notebook (moved to `nightly`) * `cargo test` * `roundtrips.py` * `compare_snippet_output.py` ### Effect Total duration: 17m59s -> 12m39s Billable time: 1h15m -> 1h9m ### Checklist * [x] A box was cheked - [PR Build Summary](https://build.rerun.io/pr/5901) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_checks.yml | 16 +- .github/workflows/nightly.yml | 13 +- .github/workflows/on_pull_request.yml | 16 +- .github/workflows/on_push_main.yml | 5 +- .github/workflows/reusable_bench.yml | 3 - .github/workflows/reusable_build_web.yml | 4 +- .../reusable_bundle_and_upload_rerun_cpp.yml | 4 +- .github/workflows/reusable_checks.yml | 12 +- .github/workflows/reusable_checks_rust.yml | 13 +- .github/workflows/reusable_deploy_docs.yml | 2 - .github/workflows/reusable_run_notebook.yml | 2 +- .github/workflows/reusable_test_wheels.yml | 8 +- pixi.lock | 247 ++++++++++++++++++ pixi.toml | 5 +- scripts/ci/rust_checks.py | 19 +- tests/roundtrips.py | 12 +- 16 files changed, 316 insertions(+), 65 deletions(-) diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 0f9b34ec8c28..359e9860c7e3 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -102,8 +102,6 @@ jobs: rs-lints: name: Rust lints (fmt, check, cranky, tests, doc) runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 @@ -208,12 +206,6 @@ jobs: with: python-version: "3.8" - - name: Install dependencies - shell: bash - run: | - pip install gitignore_parser - pip install -r ./scripts/ci/requirements.txt - - name: Rerun lints run: pixi run lint-rerun @@ -223,17 +215,17 @@ jobs: - name: Check for too large files shell: bash run: | - ./scripts/ci/check_large_files.sh + pixi run ./scripts/ci/check_large_files.sh - name: Check Python example requirements shell: bash run: | - ./scripts/ci/check_requirements.py + pixi run ./scripts/ci/check_requirements.py - name: Check Python example thumbnails shell: bash run: | - ./scripts/ci/thumbnails.py check + pixi run ./scripts/ci/thumbnails.py check spell-check: name: Spell Check @@ -275,8 +267,6 @@ jobs: cpp-tests: name: C++ tests runs-on: ubuntu-latest - container: - image: rerunio/ci_docker:0.12.0 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index dcef8cb59ec9..e1f80b61454f 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -28,7 +28,7 @@ jobs: uses: ./.github/workflows/reusable_checks_rust.yml with: CONCURRENCY: nightly - ALL_CHECKS: true + CHANNEL: nightly secrets: inherit checks-python: @@ -39,7 +39,7 @@ jobs: secrets: inherit build-web: - name: "Build and upload web viewer" + name: "Build web viewer" uses: ./.github/workflows/reusable_build_web.yml with: CONCURRENCY: nightly @@ -65,6 +65,15 @@ jobs: MODE: "pr" secrets: inherit + run-notebook: + name: "Run Notebook" + needs: [build-wheel-linux] + uses: ./.github/workflows/reusable_run_notebook.yml + with: + CONCURRENCY: push-linux-x64-${{ github.ref_name }} + WHEEL_ARTIFACT_NAME: linux-x64-wheel + secrets: inherit + build-examples: name: "Build Examples" needs: [build-wheel-linux] diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 84b57e5803a3..eceafc31a78e 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -101,6 +101,7 @@ jobs: uses: ./.github/workflows/reusable_checks_rust.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} + CHANNEL: pr secrets: inherit python-checks: @@ -146,6 +147,7 @@ jobs: CONCURRENCY: pr-${{ github.event.pull_request.number }} PLATFORM: linux-x64 WHEEL_ARTIFACT_NAME: "linux-x64-wheel-fast" + FAST: true secrets: inherit build-js: @@ -157,7 +159,7 @@ jobs: secrets: inherit build-web: - name: "Build and upload web viewer" + name: "Build web viewer" if: github.event.pull_request.head.repo.owner.login == 'rerun-io' uses: ./.github/workflows/reusable_build_web.yml with: @@ -206,20 +208,10 @@ jobs: PR_NUMBER: ${{ github.event.pull_request.number }} secrets: inherit - run-notebook: - name: "Run Notebook" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' - needs: [min-wheel-build] - uses: ./.github/workflows/reusable_run_notebook.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - WHEEL_ARTIFACT_NAME: linux-x64-wheel-fast - secrets: inherit - save-pr-summary: name: "Save PR Summary" if: github.event.pull_request.head.repo.owner.login == 'rerun-io' - needs: [upload-web, run-notebook] + needs: [upload-web] uses: ./.github/workflows/reusable_pr_summary.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 3f1dc46ea2d3..bdd9beeb0a24 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -26,6 +26,7 @@ jobs: uses: ./.github/workflows/reusable_checks_rust.yml with: CONCURRENCY: push-${{ github.ref_name }} + CHANNEL: main secrets: inherit python_checks: @@ -77,7 +78,7 @@ jobs: secrets: inherit build-web: - name: "Build and upload web viewer" + name: "Build web viewer" uses: ./.github/workflows/reusable_build_web.yml with: CONCURRENCY: push-${{ github.ref_name }} @@ -291,6 +292,8 @@ jobs: WHEEL_ARTIFACT_NAME: windows-x64-wheel secrets: inherit + # -------------------------------------------------------------------------- + generate-pip-index: name: "Generate Pip Index" needs: diff --git a/.github/workflows/reusable_bench.yml b/.github/workflows/reusable_bench.yml index 5f1c05da69e2..3180a9c11337 100644 --- a/.github/workflows/reusable_bench.yml +++ b/.github/workflows/reusable_bench.yml @@ -51,9 +51,6 @@ jobs: runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 - steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 5393401340fa..af4a8865fce1 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -1,4 +1,4 @@ -name: Reusable Build and upload web viewer +name: Reusable Build web viewer on: workflow_call: @@ -29,7 +29,7 @@ env: jobs: rs-build-web-viewer: - name: Build and upload web viewer + name: Build web viewer permissions: contents: "read" id-token: "write" diff --git a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml index 83d9d6df4ba5..652bee8ae942 100644 --- a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml +++ b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml @@ -20,9 +20,9 @@ jobs: id-token: "write" runs-on: ubuntu-latest - # Need container for arrow dependency. + container: - image: rerunio/ci_docker:0.12.0 + image: rerunio/ci_docker:0.12.0 # Need container for arrow dependency. steps: - name: Checkout repository diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 8d26e917d41b..d54dde1dfef8 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -126,12 +126,6 @@ jobs: with: python-version: "3.8" - - name: Install dependencies - shell: bash - run: | - pip install gitignore_parser - pip install -r ./scripts/ci/requirements.txt - - name: Rerun lints run: pixi run lint-rerun @@ -143,7 +137,7 @@ jobs: # - name: Check for zombie TODOs # shell: bash # run: | - # ./scripts/zombie_todos.py --token ${{ secrets.GITHUB_TOKEN }} + # pixi run ./scripts/zombie_todos.py --token ${{ secrets.GITHUB_TOKEN }} - name: Check for too large files shell: bash @@ -153,12 +147,12 @@ jobs: - name: Check Python example requirements shell: bash run: | - ./scripts/ci/check_requirements.py + pixi run ./scripts/ci/check_requirements.py - name: Check Python example thumbnails shell: bash run: | - ./scripts/ci/thumbnails.py check + pixi run ./scripts/ci/thumbnails.py check # --------------------------------------------------------------------------- diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 89c6a7d4f3a2..3b766f2e91ac 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -6,10 +6,9 @@ on: CONCURRENCY: required: true type: string - ALL_CHECKS: + CHANNEL: required: false - type: boolean - default: false + type: string # enum: 'nightly', 'main', or 'pr' concurrency: group: ${{ inputs.CONCURRENCY }}-checks_rust @@ -68,11 +67,15 @@ jobs: run: cargo install --locked --quiet cargo-cranky - name: Rust checks & tests - if: ${{ !inputs.ALL_CHECKS }} + if: ${{ inputs.CHANNEL == 'pr' }} + run: ./scripts/ci/rust_checks.py --skip-check-individual-crates --skip-test + + - name: Rust checks & tests + if: ${{ inputs.CHANNEL == 'main' }} run: ./scripts/ci/rust_checks.py --skip-check-individual-crates - name: Rust all checks & tests - if: inputs.ALL_CHECKS + if: ${{ inputs.CHANNEL == 'nightly' }} run: ./scripts/ci/rust_checks.py # --------------------------------------------------------------------------- diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index 984a8bd2ea5d..7d4a332a9b2f 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -115,8 +115,6 @@ jobs: name: Rust needs: [py-deploy-docs] runs-on: ubuntu-latest-16-cores - container: - image: rerunio/ci_docker:0.12.0 steps: - name: Show context shell: bash diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml index c10ff10df916..577b2e1385c8 100644 --- a/.github/workflows/reusable_run_notebook.yml +++ b/.github/workflows/reusable_run_notebook.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.12.0 + image: rerunio/ci_docker:0.12.0 # Required to run the wheel or we get "No matching distribution found for attrs>=23.1.0" during `pip install rerun-sdk` steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index dc82c73621ff..2a7b7e21f015 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -17,6 +17,10 @@ on: required: false type: string default: "" + FAST: + required: false + type: boolean + default: false concurrency: group: ${{ inputs.CONCURRENCY }}-build-wheels @@ -197,7 +201,7 @@ jobs: run: RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed - name: Run tests/roundtrips.py - if: ${{ inputs.PLATFORM != 'windows-x64' }} + if: ${{ inputs.PLATFORM != 'windows-x64' && !inputs.FAST }} shell: bash # --release so we can inherit from some of the artifacts that maturin has just built before # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… @@ -206,7 +210,7 @@ jobs: RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build - name: Run docs/snippets/compare_snippet_output.py - if: ${{ inputs.PLATFORM != 'windows-x64' }} + if: ${{ inputs.PLATFORM != 'windows-x64' && !inputs.FAST }} shell: bash # --release so we can inherit from some of the artifacts that maturin has just built before # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… diff --git a/pixi.lock b/pixi.lock index 1e634cad920b..829d8c401aa6 100644 --- a/pixi.lock +++ b/pixi.lock @@ -159,11 +159,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 @@ -317,11 +323,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda @@ -463,11 +475,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda @@ -609,11 +627,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda @@ -734,11 +758,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl default: channels: @@ -879,11 +909,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 @@ -1018,11 +1054,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda @@ -1145,11 +1187,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-arm64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda @@ -1272,11 +1320,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl win-64: - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda @@ -1395,11 +1449,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl packages: - kind: conda @@ -4131,6 +4191,42 @@ packages: license_family: Other size: 1124537 timestamp: 1706798177156 +- kind: pypi + name: certifi + version: 2024.2.2 + url: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + sha256: dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 + requires_python: '>=3.6' +- kind: pypi + name: charset-normalizer + version: 3.3.2 + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 + requires_python: '>=3.7.0' +- kind: pypi + name: charset-normalizer + version: 3.3.2 + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + requires_python: '>=3.7.0' +- kind: pypi + name: charset-normalizer + version: 3.3.2 + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + requires_python: '>=3.7.0' +- kind: pypi + name: charset-normalizer + version: 3.3.2 + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + requires_python: '>=3.7.0' +- kind: pypi + name: charset-normalizer + version: 3.3.2 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + requires_python: '>=3.7.0' - kind: conda name: clang version: 16.0.6 @@ -5811,6 +5907,12 @@ packages: license_family: MIT size: 11787527 timestamp: 1692901622519 +- kind: pypi + name: idna + version: '3.6' + url: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + sha256: c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f + requires_python: '>=3.5' - kind: conda name: iniconfig version: 2.0.0 @@ -13269,6 +13371,126 @@ packages: license_family: GPL size: 94048 timestamp: 1673473024463 +- kind: pypi + name: pillow + version: 10.0.0 + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinx-removed-in ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - check-manifest ; extra == 'tests' + - coverage ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + requires_python: '>=3.8' +- kind: pypi + name: pillow + version: 10.0.0 + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinx-removed-in ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - check-manifest ; extra == 'tests' + - coverage ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + requires_python: '>=3.8' +- kind: pypi + name: pillow + version: 10.0.0 + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinx-removed-in ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - check-manifest ; extra == 'tests' + - coverage ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + requires_python: '>=3.8' +- kind: pypi + name: pillow + version: 10.0.0 + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinx-removed-in ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - check-manifest ; extra == 'tests' + - coverage ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + requires_python: '>=3.8' +- kind: pypi + name: pillow + version: 10.0.0 + url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 + requires_dist: + - furo ; extra == 'docs' + - olefile ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' + - sphinx-copybutton ; extra == 'docs' + - sphinx-inline-tabs ; extra == 'docs' + - sphinx-removed-in ; extra == 'docs' + - sphinxext-opengraph ; extra == 'docs' + - check-manifest ; extra == 'tests' + - coverage ; extra == 'tests' + - defusedxml ; extra == 'tests' + - markdown2 ; extra == 'tests' + - olefile ; extra == 'tests' + - packaging ; extra == 'tests' + - pyroma ; extra == 'tests' + - pytest ; extra == 'tests' + - pytest-cov ; extra == 'tests' + - pytest-timeout ; extra == 'tests' + requires_python: '>=3.8' - kind: conda name: pip version: 23.2.1 @@ -14331,6 +14553,19 @@ packages: license_family: GPL size: 255870 timestamp: 1679532707590 +- kind: pypi + name: requests + version: 2.31.0 + url: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + sha256: 58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f + requires_dist: + - charset-normalizer <4, >=2 + - idna <4, >=2.5 + - urllib3 <3, >=1.21.1 + - certifi >=2017.4.17 + - pysocks !=1.5.7, >=1.5.6 ; extra == 'socks' + - chardet <6, >=3.0.2 ; extra == 'use_chardet_on_py3' + requires_python: '>=3.7' - kind: conda name: rhash version: 1.4.4 @@ -15353,6 +15588,18 @@ packages: license_family: BSD size: 6868398 timestamp: 1710357060520 +- kind: pypi + name: urllib3 + version: 2.2.1 + url: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + sha256: 450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d + requires_dist: + - brotli >=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2 <5, >=4 ; extra == 'h2' + - pysocks !=1.5.7, <2.0, >=1.5.6 ; extra == 'socks' + - zstandard >=0.18.0 ; extra == 'zstd' + requires_python: '>=3.8' - kind: conda name: vc version: '14.3' diff --git a/pixi.toml b/pixi.toml index a22399982bda..c99fa717a9d2 100644 --- a/pixi.toml +++ b/pixi.toml @@ -236,7 +236,10 @@ taplo = "=0.9.1" tomlkit = "0.12.3.*" [pypi-dependencies] -nox = ">=2024.3.2" # the conda-forge package is (wrongly) tagged as platform-specific +nox = ">=2024.3.2" # the conda-forge package is (wrongly) tagged as platform-specific +Pillow = "==10.0.0" # For `thumbnails.py` +requests = ">=2.31,<3" # For `thumbnails.py` +tomlkit = ">=0.11.8" # For `thumbnails.py` [target.linux-64.dependencies] patchelf = ">=0.17" diff --git a/scripts/ci/rust_checks.py b/scripts/ci/rust_checks.py index 14cbef9d5d7e..f75abec3a5ae 100755 --- a/scripts/ci/rust_checks.py +++ b/scripts/ci/rust_checks.py @@ -13,21 +13,21 @@ class Timing: - def __init__(self, cwd: str, start_time: float) -> None: - self.cwd = cwd + def __init__(self, command: str, start_time: float) -> None: + self.command = command self.duration = time.time() - start_time def run_cargo(command: str, args: str) -> Timing: - cwd = f"cargo {command} --quiet {args}" - print(f"Running '{cwd}'") + command = f"cargo {command} --quiet {args}" + print(f"> {command}") start = time.time() - result = subprocess.call(cwd, shell=True) - - if result != 0: + result = subprocess.run(command, check=False, capture_output=True, text=True, shell=True) + if result.returncode != 0: + print(f"'{command}' failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}") sys.exit(result) - return Timing(cwd, start) + return Timing(command, start) def package_name_from_cargo_toml(cargo_toml_path: str) -> str: @@ -99,8 +99,9 @@ def main() -> None: # Print timings overview print("-----------------") print("Timings:") + timings.sort(key=lambda timing: timing.duration, reverse=True) for timing in timings: - print(f"{timing.duration:.2f}s \t {timing.cwd}") + print(f"{timing.duration:.2f}s \t {timing.command}") if __name__ == "__main__": diff --git a/tests/roundtrips.py b/tests/roundtrips.py index ba8c8e43f7d9..fbdfa6c4a41c 100755 --- a/tests/roundtrips.py +++ b/tests/roundtrips.py @@ -95,13 +95,17 @@ def main() -> None: # Running CMake in parallel causes failures during rerun_sdk & arrow build. # TODO(andreas): Tell cmake in a single command to build everything at once. if not args.no_cpp_build: + start_time = time.time() for arch in archetypes: arch_opt_out = opt_out.get(arch, []) if "cpp" in arch_opt_out: continue build(arch, "cpp", args) + elapsed = time.time() - start_time + print(f"C++ examples compiled and ran in {elapsed:.1f} seconds") with multiprocessing.Pool() as pool: + start_time = time.time() jobs = [] for arch in archetypes: arch_opt_out = opt_out.get(arch, []) @@ -113,9 +117,12 @@ def main() -> None: print(f"Waiting for {len(jobs)} build jobs to finish…") for job in jobs: job.get() + elapsed = time.time() - start_time + print(f"Python and Rust examples ran in {elapsed:.1f} seconds") print("----------------------------------------------------------") - print(f"Comparing {len(archetypes)} archetypes…") + print(f"Comparing recordings for{len(archetypes)} archetypes…") + start_time = time.time() for arch in archetypes: print() @@ -135,6 +142,9 @@ def main() -> None: if "cpp" not in arch_opt_out: run_comparison(cpp_output_path, rust_output_path, args.full_dump) + print() + elapsed = time.time() - start_time + print(f"Comparisons ran in {elapsed:.1f} seconds") print() print("----------------------------------------------------------") print("All tests passed!") From d884026124efa2d201160870b5d3d67bd918337f Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 10:47:13 +0200 Subject: [PATCH 248/508] Misc CI improvements (#5905) ### What ### Checklist * [x] I checked a box - [PR Build Summary](https://build.rerun.io/pr/5905) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_checks.yml | 2 +- .github/workflows/reusable_bench.yml | 3 ++ .github/workflows/reusable_checks_rust.yml | 2 +- scripts/ci/rust_checks.py | 36 ++++++++++++++++------ 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 359e9860c7e3..6d7082c03301 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -238,7 +238,7 @@ jobs: uses: crate-ci/typos@v1.18.0 rs-cargo-deny: - name: Cargo Deny + name: cargo-deny runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/reusable_bench.yml b/.github/workflows/reusable_bench.yml index 3180a9c11337..27bb88638884 100644 --- a/.github/workflows/reusable_bench.yml +++ b/.github/workflows/reusable_bench.yml @@ -102,6 +102,9 @@ jobs: mkdir /tmp/compare/ gsutil cp gs://rerun-builds/benches/${{inputs.COMPARE_TO}} /tmp/compare/${{ inputs.COMPARE_TO }} + - name: Install cargo-benchcmp + run: cargo install --quiet cargo-benchcmp + - name: Compare results with benchcmp if: ${{ inputs.COMPARE_TO != '' }} shell: bash diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 3b766f2e91ac..b003473a25e6 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -121,7 +121,7 @@ jobs: # --------------------------------------------------------------------------- rs-cargo-deny: - name: Cargo Deny + name: cargo-deny runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/scripts/ci/rust_checks.py b/scripts/ci/rust_checks.py index f75abec3a5ae..2936bc4dd48b 100755 --- a/scripts/ci/rust_checks.py +++ b/scripts/ci/rust_checks.py @@ -5,6 +5,7 @@ from __future__ import annotations import argparse +import os import re import subprocess import sys @@ -13,21 +14,27 @@ class Timing: - def __init__(self, command: str, start_time: float) -> None: + def __init__(self, command: str, duration: float) -> None: self.command = command - self.duration = time.time() - start_time + self.duration = duration -def run_cargo(command: str, args: str) -> Timing: - command = f"cargo {command} --quiet {args}" - print(f"> {command}") - start = time.time() - result = subprocess.run(command, check=False, capture_output=True, text=True, shell=True) +def run_cargo(cargo_cmd, cargo_args: str) -> Timing: + args = ["cargo", cargo_cmd, "--quiet"] + cargo_args.split(" ") + cmd_str = subprocess.list2cmdline(args) + print(f"> {cmd_str}") + start_time = time.time() + + env = os.environ.copy() + env["RUSTFLAGS"] = "--deny warnings" + env["RUSTDOCFLAGS"] = "--deny warnings --deny rustdoc::missing_crate_level_docs" + + result = subprocess.run(args, env=env, check=False, capture_output=True, text=True) if result.returncode != 0: - print(f"'{command}' failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}") - sys.exit(result) + print(f"'{cmd_str}' failed with exit-code {result.returncode}. Output:\n{result.stdout}\n{result.stderr}") + sys.exit(result.returncode) - return Timing(command, start) + return Timing(cmd_str, time.time() - start_time) def package_name_from_cargo_toml(cargo_toml_path: str) -> str: @@ -58,6 +65,8 @@ def main() -> None: # ---------------------- + # NOTE: a lot of these jobs use very little CPU, but we csannot parallelize them because they all take a lock on the `target` directory. + timings = [] # First check with --locked to make sure Cargo.lock is up to date. @@ -87,13 +96,20 @@ def main() -> None: if args.skip_docs is not True: # Full doc build takes prohibitively long (over 17min as of writing), so we skip it: # timings.append(run_cargo("doc", "--all-features")) + + # These take around 3m40s each on CI, but very useful for catching broken doclinks: timings.append(run_cargo("doc", "--no-deps --all-features --workspace")) timings.append(run_cargo("doc", "--document-private-items --no-deps --all-features --workspace")) if args.skip_tests is not True: + # We first use `--no-run` to measure the time of compiling vs actually running + # Just a normal `cargo test` should always work: + timings.append(run_cargo("test", "--all-targets --no-run")) timings.append(run_cargo("test", "--all-targets")) + # Full test of everything: + timings.append(run_cargo("test", "--all-targets --all-features --no-run")) timings.append(run_cargo("test", "--all-targets --all-features")) # Print timings overview From 9d584c7a4446221b6b0e59ca33d8ca707909c5bd Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 11 Apr 2024 11:49:45 +0200 Subject: [PATCH 249/508] Replace requirements-docs.txt with a python doc pixi environment (#5909) ### What * Part of #5895 requirements-docs is still mentioned in python readme, this is handled in * #5911 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5909) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5909?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5909?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5909) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_checks.yml | 13 +- .github/workflows/reusable_checks.yml | 17 +- .github/workflows/reusable_checks_python.yml | 15 +- .github/workflows/reusable_deploy_docs.yml | 17 +- crates/re_build_search_index/README.md | 5 - .../src/ingest/python.rs | 4 +- pixi.lock | 6333 ++++++++++++++++- pixi.toml | 21 + rerun_py/docs/writing_docs.md | 27 +- rerun_py/requirements-doc.txt | 12 - scripts/ci/requirements.txt | 1 - scripts/requirements-dev.txt | 1 - 12 files changed, 6198 insertions(+), 268 deletions(-) delete mode 100644 rerun_py/requirements-doc.txt diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 6d7082c03301..3a1eeb01f4e9 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -65,21 +65,14 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v4 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: "3.8" - - - name: Install Python dependencies - shell: bash - run: | - pip install --upgrade pip - pip install -r rerun_py/requirements-doc.txt + pixi-version: v0.18.0 - name: Build via mkdocs shell: bash run: | - mkdocs build --strict -f rerun_py/mkdocs.yml + pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml no-codegen-changes: name: Check if running codegen would produce any changes diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index d54dde1dfef8..dc50790faa3a 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -59,23 +59,12 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - name: Set up Python - uses: actions/setup-python@v4 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: "3.8" - cache: "pip" - cache-dependency-path: "rerun_py/requirements-doc.txt" - - - name: Install Python dependencies - shell: bash - run: | - pip install --upgrade pip - pip install -r rerun_py/requirements-doc.txt + pixi-version: v0.18.0 - name: Build via mkdocs - shell: bash - run: | - mkdocs build --strict -f rerun_py/mkdocs.yml + run: pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml # --------------------------------------------------------------------------- diff --git a/.github/workflows/reusable_checks_python.yml b/.github/workflows/reusable_checks_python.yml index 5e9cac76d0f8..b394dcf53d4e 100644 --- a/.github/workflows/reusable_checks_python.yml +++ b/.github/workflows/reusable_checks_python.yml @@ -49,20 +49,11 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - name: Set up Python - uses: actions/setup-python@v4 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: "3.8" - cache: "pip" - cache-dependency-path: "rerun_py/requirements-doc.txt" - - - name: Install Python dependencies - shell: bash - run: | - pip install --upgrade pip - pip install -r rerun_py/requirements-doc.txt + pixi-version: v0.18.0 - name: Build via mkdocs shell: bash run: | - mkdocs build --strict -f rerun_py/mkdocs.yml + pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index 7d4a332a9b2f..aadaa701e7b6 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -59,18 +59,9 @@ jobs: fetch-depth: 0 # Don't do a shallow clone ref: ${{ inputs.RELEASE_COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || '') }} - - name: Set up Python - uses: actions/setup-python@v4 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: "3.8" - cache: "pip" - cache-dependency-path: "rerun_py/requirements-doc.txt" - - - name: Install Python dependencies - shell: bash - run: | - pip install --upgrade pip - pip install -r rerun_py/requirements-doc.txt + pixi-version: v0.18.0 - name: Set up git author shell: bash @@ -89,7 +80,7 @@ jobs: shell: bash run: | git fetch - mike deploy -F rerun_py/mkdocs.yml --rebase -b gh-pages --prefix docs/python -u ${{inputs.PY_DOCS_VERSION_NAME}} stable + pixi run -e py-docs mike deploy -F rerun_py/mkdocs.yml --rebase -b gh-pages --prefix docs/python -u ${{inputs.PY_DOCS_VERSION_NAME}} stable git checkout gh-pages git checkout --orphan gh-pages-orphan git commit -m "Update docs for ${GITHUB_SHA}" @@ -103,7 +94,7 @@ jobs: shell: bash run: | git fetch - mike deploy -F rerun_py/mkdocs.yml --rebase -b gh-pages --prefix docs/python ${{inputs.PY_DOCS_VERSION_NAME}} + pixi run -e py-docs mike deploy -F rerun_py/mkdocs.yml --rebase -b gh-pages --prefix docs/python ${{inputs.PY_DOCS_VERSION_NAME}} git checkout gh-pages git checkout --orphan gh-pages-orphan git commit -m "Update docs for ${GITHUB_SHA}" diff --git a/crates/re_build_search_index/README.md b/crates/re_build_search_index/README.md index f0c084c2d3aa..cd86fc1b4cff 100644 --- a/crates/re_build_search_index/README.md +++ b/crates/re_build_search_index/README.md @@ -10,11 +10,6 @@ Builds a Meilisearch index from our documentation. rustup install nightly rustup +nightly target add wasm32-unknown-unknown ``` -- A local installation of `rerun_sdk` and `rerun_py/requirements-doc.txt` - ``` - pixi run py-build - pixi run pip install -r rerun_py/requirements-doc.txt - ``` ### Usage diff --git a/crates/re_build_search_index/src/ingest/python.rs b/crates/re_build_search_index/src/ingest/python.rs index 94635422b63a..bdbd6f863187 100644 --- a/crates/re_build_search_index/src/ingest/python.rs +++ b/crates/re_build_search_index/src/ingest/python.rs @@ -33,7 +33,9 @@ pub fn ingest(ctx: &Context) -> anyhow::Result<()> { .with_arg("rerun_py/site/objects.inv") .with_arg("-") .parse_json::() - .context("sphobjinv may not be installed, install rerun_py/requirements-doc.txt")? + .context( + "sphobjinv may not be installed, are you running in the py-docs pixi environment?", + )? .objects .into_values() .map(|o| (o.name.clone(), o)) diff --git a/pixi.lock b/pixi.lock index 829d8c401aa6..66fbe4405f09 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1461,6 +1461,870 @@ environments: - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + py-docs: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.17-he0b1f16_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.11-heb1d5e4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.15-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.2.18-hce8ee76_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.4.2-h01f5eca_8.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.8.1-hdb68c23_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.14.7-h76a7424_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.10.3-h50844eb_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.5.7-hb7bd14b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.1.15-hce8ee76_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.18-hce8ee76_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.6-hf567797_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-hbf3e495_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.28.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.25-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20240116.1-cxx17_h59595ed_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-he70291f_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-14.0.2-hac33072_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-14.0.2-hac33072_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-14.0.2-hd42f311_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-sql-14.0.2-h9241762_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hd4ab825_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-14.0.2-h9241762_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-22_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-22_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp16-16.0.6-default_h127d8a8_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-18.1.3-default_h5d6823c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.7.1-hca28451_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.22.0-h9be4e54_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.22.0-hc7a4891_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.62.1-h15f2491_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-22_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm15-15.0.7-hb3ce162_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm16-16.0.6-hb3ce162_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.3-h2448989_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnl-3.9.0-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.27-pthreads_h413a1c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-14.0.2-h6a7eafb_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.25.3-h08a7969_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libre2-11-2023.09.01-h5a48ba9_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.19.0-hb90f79a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.8.0-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.46.0-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda + - 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/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4.20240210-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.19.0-hb753e55_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.0.0-h17fec99_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h78dcc79_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-51.0-hd3aeb46_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.9-h06160fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.0-hdb0a2a9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.20.7-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-ha691c75_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl + - pypi: git+https://github.com/rerun-io/mkdocs-redirects.git@fb6b074554975ba7729d68d04957ce7c7dfd5003 + - pypi: https://files.pythonhosted.org/packages/f6/01/d413c98335ed75d8c211afb91320811366d55fb0ef7f4b01b9ab19630eac/mkdocs_autorefs-1.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/3b/e00d839d3242844c77e248f9572dd34644a04300839a60fe7d6bf652ab19/mkdocs_literate_nav-0.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/ca/e72f41f1f94eae8a45de6b247ed90c868b9af107cd3b2182c6c6e944fe06/mkdocs_material-9.4.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.17-h43c0ec5_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.11-hd75f5ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.15-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-compression-0.2.18-he771c36_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-event-stream-0.4.2-h0aa0982_8.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-http-0.8.1-h505357e_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-io-0.14.7-h2e28a7b_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-mqtt-0.10.3-h3321c0c_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-s3-0.5.7-hb8e3a89_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-sdkutils-0.1.15-he771c36_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-checksums-0.1.18-he771c36_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.6-h497fec5_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hc40fc56_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.28.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.25-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20240116.1-cxx17_h2f0025b_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-14.0.2-h520d24b_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-acero-14.0.2-h0a1ffab_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-dataset-14.0.2-h0a1ffab_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-14.0.2-hbf3f4d3_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-sql-14.0.2-h7624240_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-gandiva-14.0.2-h1eebba3_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-substrait-14.0.2-h9b67ed8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.9.0-22_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-22_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp16-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-18.1.3-default_hf9b4efe_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcrc32c-1.1.2-h01db608_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.7.1-h4e8248e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-13.2.0-hf8544c7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-ng-13.2.0-he9431aa_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-13.2.0-h582850c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-13.2.0-hf8544c7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-2.22.0-hd739bbb_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-storage-2.22.0-hdb39181_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgrpc-1.62.1-h98a9317_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.17-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.9.0-22_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm15-15.0.7-hb4f23b0_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm16-16.0.6-h0b931ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm18-18.1.3-hbfe100b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.58.0-hb0e430d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnl-3.9.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.27-pthreads_h5a5ec62_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libparquet-14.0.2-h70b04f6_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-4.25.3-h648ac29_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libre2-11-2023.09.01-h9d008c2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.0-h492db2e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-13.2.0-h9a76618_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libthrift-0.19.0-h043aeee_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libutf8proc-2.8.0-h4e544f5_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.38.1-hb4cce97_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.46.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.6-h3091e33_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda + - 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/maturin-1.5.1-py311h06e5ef9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4.20240210-h0425590_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-hd7aaf90_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311hf60b7a8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-51.0-h0425590_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.9-h5a25046_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.2.0-h8d0c38d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.20.7-h1d8f897_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hb4872d8_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl + - pypi: git+https://github.com/rerun-io/mkdocs-redirects.git@fb6b074554975ba7729d68d04957ce7c7dfd5003 + - pypi: https://files.pythonhosted.org/packages/f6/01/d413c98335ed75d8c211afb91320811366d55fb0ef7f4b01b9ab19630eac/mkdocs_autorefs-1.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/3b/e00d839d3242844c77e248f9572dd34644a04300839a60fe7d6bf652ab19/mkdocs_literate_nav-0.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/ca/e72f41f1f94eae8a45de6b247ed90c868b9af107cd3b2182c6c6e944fe06/mkdocs_material-9.4.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.17-hb47d15a_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.11-hbce485b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.15-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.18-h53e3db5_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.2-he461af8_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.1-h0afc28a_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.7-h6254544_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.3-hd66502f_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.5.7-h4907f8a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.15-h53e3db5_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.18-h53e3db5_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.6-hfb53d2e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h01edc24_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.25-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20240116.1-cxx17_hc1bcbd7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-hf13115f_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-hcdcf8f8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-hcdcf8f8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-hcd10e87_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-hd7485ff_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-h1359b85_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-hd7485ff_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp16-16.0.6-default_h7151d67_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-18.1.3-default_h0edc4dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.7.1-h726d00d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-16.0.6-hd57cbcb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-5.0.0-13_2_0_h97931a8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-13.2.0-h2873a65_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.22.0-h651e89d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.22.0-ha67e85c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.1-h384b2fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm15-15.0.7-hbedff68_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm16-16.0.6-hbedff68_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.3-hbcf5fad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.27-openmp_hfef2a42_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h4aea69c_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-h4e4d658_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2023.09.01-h81f5012_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.19.0-h064b379_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.8.0-hb7f2c08_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.47.0-h67532ce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda + - 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/maturin-1.5.1-py311h24bb903_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4.20240210-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.19.0-h119ffd7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.0-hf146577_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311hb0c4a44_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.0-h6dc393e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.20.7-h11a7dfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl + - pypi: git+https://github.com/rerun-io/mkdocs-redirects.git@fb6b074554975ba7729d68d04957ce7c7dfd5003 + - pypi: https://files.pythonhosted.org/packages/f6/01/d413c98335ed75d8c211afb91320811366d55fb0ef7f4b01b9ab19630eac/mkdocs_autorefs-1.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/3b/e00d839d3242844c77e248f9572dd34644a04300839a60fe7d6bf652ab19/mkdocs_literate_nav-0.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/ca/e72f41f1f94eae8a45de6b247ed90c868b9af107cd3b2182c6c6e944fe06/mkdocs_material-9.4.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.17-h382b9c6_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.11-hd34e5fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.15-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.2.18-hd34e5fa_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.4.2-h247c08a_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.8.1-hf9e830b_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.14.7-h33d81b3_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.10.3-h5f4abda_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.5.7-h606a3d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.1.15-hd34e5fa_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.18-hd34e5fa_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.6-h13f0230_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h134aaec_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.25-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20240116.1-cxx17_hebf3989_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h3fc723a_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-14.0.2-h43a2c78_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-14.0.2-h43a2c78_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-14.0.2-h161034a_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-sql-14.0.2-h32643e2_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-gandiva-14.0.2-ha803c60_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-14.0.2-h7a0fec1_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-22_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-22_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp16-16.0.6-default_he012953_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-18.1.3-default_h83d0a53_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.7.1-h2d989ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-16.0.6-h4653b0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-13_2_0_hd922786_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-13.2.0-hf226fd6_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.22.0-hbebe991_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-2.22.0-h8a76758_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.62.1-h9c18a4f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-22_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm15-15.0.7-h2621b3d_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm16-16.0.6-haab561b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.3-h30cc82d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.27-openmp_h6c19121_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-14.0.2-he0622da_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-4.25.3-hbfab5d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2023.09.01-h7b2c953_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.19.0-h026a170_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.8.0-h1a8c8d9_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.47.0-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda + - 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/mypy-1.8.0-py311h05b510d_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/ncurses-6.4.20240210-h078ce10_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.19.0-h5f47a4d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.0.0-h4aad248_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311h4c23913_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.0-hd04f947_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.20.7-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl + - pypi: git+https://github.com/rerun-io/mkdocs-redirects.git@fb6b074554975ba7729d68d04957ce7c7dfd5003 + - pypi: https://files.pythonhosted.org/packages/f6/01/d413c98335ed75d8c211afb91320811366d55fb0ef7f4b01b9ab19630eac/mkdocs_autorefs-1.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/3b/e00d839d3242844c77e248f9572dd34644a04300839a60fe7d6bf652ab19/mkdocs_literate_nav-0.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/ca/e72f41f1f94eae8a45de6b247ed90c868b9af107cd3b2182c6c6e944fe06/mkdocs_material-9.4.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.17-hb40cdec_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.11-ha21e00f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.15-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-ha21e00f_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-hf668b60_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-hd704247_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.7-h14865c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.3-h748201e_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.7-h5da7064_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-ha21e00f_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-ha21e00f_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.6-h5bc0ceb_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h5d77392_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.28.1-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.25-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.1.0-h57928b3_964.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h45212c0_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h8681a6d_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h8681a6d_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-h83a3238_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h21569af_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-h4e6a3a4_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-hea7f8fd_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-22_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlicommon-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlidec-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlienc-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-22_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libclang13-18.1.3-default_hf64faad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.7.1-hd5e4a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.22.0-h9cad5c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.22.0-hb581fae_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.62.1-h5273850_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.9.3-default_haede6df_1009.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.17-hcfcfb64_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-22_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h39135fc_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.3-h503648d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libre2-11-2023.09.01-hf8d8778_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libthrift-0.19.0-ha2b3283_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libutf8proc-2.8.0-h82a8f57_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.4-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libgfortran-5.3.0-6.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-5.3.0-7.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_692.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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.19.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/orc-2.0.0-h7e885a9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h05400ba_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.2.0-hfb803bf_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.11.0-h91493d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.20.7-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl + - pypi: git+https://github.com/rerun-io/mkdocs-redirects.git@fb6b074554975ba7729d68d04957ce7c7dfd5003 + - pypi: https://files.pythonhosted.org/packages/f6/01/d413c98335ed75d8c211afb91320811366d55fb0ef7f4b01b9ab19630eac/mkdocs_autorefs-1.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/51/3b/e00d839d3242844c77e248f9572dd34644a04300839a60fe7d6bf652ab19/mkdocs_literate_nav-0.6.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a6/ca/e72f41f1f94eae8a45de6b247ed90c868b9af107cd3b2182c6c6e944fe06/mkdocs_material-9.4.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz + - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl packages: - kind: conda name: _libgcc_mutex @@ -1735,6 +2599,108 @@ packages: license_family: Apache size: 99251 timestamp: 1708633468680 +- kind: conda + name: aws-c-auth + version: 0.7.17 + build: h382b9c6_2 + build_number: 2 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.17-h382b9c6_2.conda + sha256: 50c87bf0fa68b5a6b9d2fbde5a17b1cf8c5f81ddbf659d78452de779598b1177 + md5: f38724f2e96212bf6c5c96861dc887f1 + depends: + - __osx >=11.0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 89585 + timestamp: 1712670760388 +- kind: conda + name: aws-c-auth + version: 0.7.17 + build: h43c0ec5_2 + build_number: 2 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.17-h43c0ec5_2.conda + sha256: 3cdf6d4dd402842148756655a9117a3bc7d5e27c5dc3166f3c466c3efdb93caa + md5: 2f5347aa7884bc265ebf6d92ba2f1b80 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 108723 + timestamp: 1712670573058 +- kind: conda + name: aws-c-auth + version: 0.7.17 + build: hb40cdec_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.17-hb40cdec_2.conda + sha256: 3a86263b08f8a454ebbc21ffa9f71a3daa86e32e2605e125878bec2d46147c32 + md5: 1d8527b98fbf4a803e92c2ee3d241ed8 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 100109 + timestamp: 1712671026674 +- kind: conda + name: aws-c-auth + version: 0.7.17 + build: hb47d15a_2 + build_number: 2 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.17-hb47d15a_2.conda + sha256: b3bada3f35ae0b60b6ae575e2aeae3d7c828f362161dfbe3ebcf469f2f7ac73a + md5: 0152c8670d2459a170019a59985b8a88 + depends: + - __osx >=10.9 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 91309 + timestamp: 1712670722676 +- kind: conda + name: aws-c-auth + version: 0.7.17 + build: he0b1f16_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.17-he0b1f16_2.conda + sha256: 607755dd09088b0d7898733edbe91aea979c599dc8d710b0d267b71424673032 + md5: ea6d998135d5f8932cffc91381104690 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 104450 + timestamp: 1712670541560 - kind: conda name: aws-c-cal version: 0.6.9 @@ -1870,6 +2836,83 @@ packages: license_family: Apache size: 39206 timestamp: 1708003965707 +- kind: conda + name: aws-c-cal + version: 0.6.11 + build: ha21e00f_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.11-ha21e00f_0.conda + sha256: 3925aa37d9cbceb4cceb10ac1f602ca9e86bbea53ebbc2f560b97f51989c56bc + md5: 683d416db152019f181c34e74a3fd0a2 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 45832 + timestamp: 1712495134572 +- kind: conda + name: aws-c-cal + version: 0.6.11 + build: hbce485b_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.11-hbce485b_0.conda + sha256: a390f2c964408e9215046220351498bc80ca551be9dfac95702ce1be1dcfa436 + md5: a7b19e98d30d51fdf0546e048cc0a262 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 38803 + timestamp: 1712495186044 +- kind: conda + name: aws-c-cal + version: 0.6.11 + build: hd34e5fa_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.11-hd34e5fa_0.conda + sha256: 8296f9ad5415f6e640862116c4c3f4c1bc555ea05eab2ec32e112073cd697d79 + md5: 92d0e6abc836c1c00facbd08d3b01ce9 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 39697 + timestamp: 1712495118765 +- kind: conda + name: aws-c-cal + version: 0.6.11 + build: hd75f5ff_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.11-hd75f5ff_0.conda + sha256: 3e088fc93a58bfdaf30e87664df21feab552aaa5e93d54cb13d28fdee03feafb + md5: 25ee0226e8d8971eec470c9a6e1caff8 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 48398 + timestamp: 1712494883031 +- kind: conda + name: aws-c-cal + version: 0.6.11 + build: heb1d5e4_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.11-heb1d5e4_0.conda + sha256: f1b40106a70cc294aab350daa97c760a9875073f58a5b7a25370c31fed8a2c15 + md5: 98784bb35b316e2ba8698f4a75326e9a + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 46257 + timestamp: 1712494861919 - kind: conda name: aws-c-common version: 0.9.10 @@ -1982,6 +3025,74 @@ packages: license_family: Apache size: 225560 timestamp: 1707964559211 +- kind: conda + name: aws-c-common + version: 0.9.15 + build: h10d778d_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.15-h10d778d_0.conda + sha256: fed4405a55bce4dc7e947d8604d853ac46b17cf09712f1253932e9cc0fe70f92 + md5: be6037c84d354c0303fdb077967f6048 + license: Apache-2.0 + license_family: Apache + size: 209383 + timestamp: 1712101871696 +- kind: conda + name: aws-c-common + version: 0.9.15 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.15-h31becfc_0.conda + sha256: 9583b3bc8e501958eaeb9b9b43c2c5ca49a783af71de441b876dd69b3d22e983 + md5: f3296fd840dcc6dda5c2245f0d4a2a40 + depends: + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 234027 + timestamp: 1712101733022 +- kind: conda + name: aws-c-common + version: 0.9.15 + build: h93a5062_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.15-h93a5062_0.conda + sha256: ae4a47f032886a7175fe6e7ccbf1233cbe06bdfc747fc707afd83d2bdff43dff + md5: 4ca05bd64cc4decc54089fcd0cc69082 + license: Apache-2.0 + license_family: Apache + size: 204504 + timestamp: 1712101989588 +- kind: conda + name: aws-c-common + version: 0.9.15 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.15-hcfcfb64_0.conda + sha256: 038e4c01a81ac7807e9942009e2db88dea977754f4d2f35f822367132d9a8abf + md5: 6e02bac6dfcf279e2b0b2a3602d7b49b + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 223866 + timestamp: 1712102088444 +- kind: conda + name: aws-c-common + version: 0.9.15 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.15-hd590300_0.conda + sha256: e4251e5fa2656140628f40b74e61cf5048dfd4346f6d81517d346b371113496e + md5: ad8955a300fd09e97e76c38638ac7157 + depends: + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 226559 + timestamp: 1712101677803 - kind: conda name: aws-c-compression version: 0.2.17 @@ -2050,6 +3161,70 @@ packages: license_family: Apache size: 19873 timestamp: 1708003535938 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: h53e3db5_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.18-h53e3db5_3.conda + sha256: b35df886c7a8751fb5d1204510335241ddc9115fb4970c65ac12bbb307f6f8ad + md5: b4341460c51c457c6e5ac58d76f44d17 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 17976 + timestamp: 1712138779036 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: ha21e00f_3 + build_number: 3 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-ha21e00f_3.conda + sha256: c0e05c48a2420bf1e192ba61d9f41fad075186fa12f9018fef4a52f31883f0ee + md5: 15ff0ff5c09bd7c0c6dea51e5ef427b4 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 22479 + timestamp: 1712139181716 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: hce8ee76_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.2.18-hce8ee76_3.conda + sha256: ab0617f2d66d5d88fc6c7edb6ecd4589e0a744ccaeff95765371c9cabdb29722 + md5: b19224a5179ecb512c4aac9f8a6d57a7 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 19134 + timestamp: 1712138634166 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: hd34e5fa_3 + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.2.18-hd34e5fa_3.conda + sha256: c501b4f00d1518956aa3fb45378e0dacdec941cca5d78e8d8ba07b46674fa877 + md5: 194b36e2ac364c12c7fa89e84391722d + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 18089 + timestamp: 1712138821785 - kind: conda name: aws-c-compression version: 0.2.18 @@ -2066,8 +3241,24 @@ packages: - vc14_runtime >=14.29.30139 license: Apache-2.0 license_family: Apache - size: 22347 - timestamp: 1708004038019 + size: 22347 + timestamp: 1708004038019 +- kind: conda + name: aws-c-compression + version: 0.2.18 + build: he771c36_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-compression-0.2.18-he771c36_3.conda + sha256: c3e53f16d0a012e4ed47c6454176bd23f4ac09f81edcd292dfa239dd448a70ca + md5: d3b53a7361f8387894375f71151a5161 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 19788 + timestamp: 1712138757513 - kind: conda name: aws-c-compression version: 0.2.18 @@ -2172,6 +3363,44 @@ packages: license_family: Apache size: 46862 timestamp: 1703907246896 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: h01f5eca_8 + build_number: 8 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.4.2-h01f5eca_8.conda + sha256: 688b81ed93151868df2717556d3b93dcfaf6bf129a1474f14e0c993095816d3f + md5: afb85fc0f01032d115c57c961950e7d8 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 53700 + timestamp: 1712507243610 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: h0aa0982_8 + build_number: 8 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-event-stream-0.4.2-h0aa0982_8.conda + sha256: 21a9ca9ce1d77b041c1935aa472273d59d77e3fb73e8d4f920ab4191d41e5c65 + md5: 08b9fd6dbb0c3d5dba56da5d0aa93cf9 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 55126 + timestamp: 1712507287110 - kind: conda name: aws-c-event-stream version: 0.4.2 @@ -2229,6 +3458,24 @@ packages: license_family: Apache size: 46870 timestamp: 1708602815747 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: h247c08a_8 + build_number: 8 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.4.2-h247c08a_8.conda + sha256: f4a8ee85ed51793bdfaa5ff863db5fa02eb1935e25857109b8650af2c66f46c5 + md5: 47912c9d76ebf3146dc5c5358fe94a97 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 46788 + timestamp: 1712507379999 - kind: conda name: aws-c-event-stream version: 0.4.2 @@ -2247,6 +3494,44 @@ packages: license_family: Apache size: 46676 timestamp: 1708602620909 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: he461af8_8 + build_number: 8 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.2-he461af8_8.conda + sha256: 6a795f72cf2cbf50900cd167942db0361b33e19af4735a36de848b16efa01108 + md5: e06f07aca12555762e986004e013c0e6 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 46574 + timestamp: 1712507348124 +- kind: conda + name: aws-c-event-stream + version: 0.4.2 + build: hf668b60_8 + build_number: 8 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-hf668b60_8.conda + sha256: cc2b8b8338b51b1c05827532e22902005fb68cbb7c85b3e8c6917531721923cd + md5: 61ff0e83fdad92ccf13812b54c447507 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 54179 + timestamp: 1712507805607 - kind: conda name: aws-c-event-stream version: 0.4.2 @@ -2324,6 +3609,25 @@ packages: license_family: Apache size: 151658 timestamp: 1703907442170 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: h0afc28a_10 + build_number: 10 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.1-h0afc28a_10.conda + sha256: 1418ec0dc04e9f00fbd2931f079c6e758b5b7fa7bff65d55eb5d585a60d162b4 + md5: 012d9d06c0b4a37f711a8f905a0f4fd8 + depends: + - __osx >=10.9 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + license: Apache-2.0 + license_family: Apache + size: 162863 + timestamp: 1712654842013 - kind: conda name: aws-c-http version: 0.8.1 @@ -2342,6 +3646,25 @@ packages: license_family: Apache size: 163076 timestamp: 1708602693889 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: h505357e_10 + build_number: 10 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-http-0.8.1-h505357e_10.conda + sha256: 8f51c98dd34096bf25e85ca78534a9a0b2f846ebd7f3b0dac65a68755a0193a7 + md5: 1b2a041d3eba43d117e78c3679ea5dc3 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 188116 + timestamp: 1712654596786 - kind: conda name: aws-c-http version: 0.8.1 @@ -2361,6 +3684,29 @@ packages: license_family: Apache size: 195024 timestamp: 1708602547845 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: hd704247_10 + build_number: 10 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-hd704247_10.conda + sha256: 8a869b0f15bd85eb46b4faa14cadb691d756f8a74279edede1d769fea62d0acc + md5: 6abc1e3bdf18f682c7f42a08669b5662 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc >=14.3,<15 + - vc14_runtime >=14.29.30139 + - vc14_runtime >=14.38.33130 + license: Apache-2.0 + license_family: Apache + size: 180594 + timestamp: 1712655088873 - kind: conda name: aws-c-http version: 0.8.1 @@ -2382,6 +3728,25 @@ packages: license_family: Apache size: 180105 timestamp: 1708603146126 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: hdb68c23_10 + build_number: 10 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.8.1-hdb68c23_10.conda + sha256: a13e77f6b40de79b33711f70b8180943053cc162efdb357bc9cd577f0ac69818 + md5: cb6065938167da2d2f078c2f08473b84 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 195362 + timestamp: 1712654535499 - kind: conda name: aws-c-http version: 0.8.1 @@ -2419,6 +3784,25 @@ packages: license_family: Apache size: 151481 timestamp: 1708602772972 +- kind: conda + name: aws-c-http + version: 0.8.1 + build: hf9e830b_10 + build_number: 10 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.8.1-hf9e830b_10.conda + sha256: 6c06720a8700f65e68ad740b5dd0e559242f62a179067c029792d226b3b065fc + md5: 532e961f28b3c8fcdcb0ecb1e017961d + depends: + - __osx >=11.0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-compression >=0.2.18,<0.2.19.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + license: Apache-2.0 + license_family: Apache + size: 151666 + timestamp: 1712654734379 - kind: conda name: aws-c-io version: 0.13.36 @@ -2562,6 +3946,97 @@ packages: license_family: Apache size: 136989 timestamp: 1708687976415 +- kind: conda + name: aws-c-io + version: 0.14.7 + build: h14865c8_3 + build_number: 3 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.7-h14865c8_3.conda + sha256: 42b46959427374549be06821a2262f0c330df4e9f49c501c84d3fda43c98e3a3 + md5: 4fececd62cac216d5e4e76a094a394a4 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc >=14.3,<15 + - vc14_runtime >=14.29.30139 + - vc14_runtime >=14.38.33130 + license: Apache-2.0 + license_family: Apache + size: 160700 + timestamp: 1712593227384 +- kind: conda + name: aws-c-io + version: 0.14.7 + build: h2e28a7b_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-io-0.14.7-h2e28a7b_3.conda + sha256: ef32a021ebf8d913dc979719fc99551f25159f7345c4190af5f60082d22595e0 + md5: 7dd5bb042847c8ad2dd3a595184f91c9 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + - s2n >=1.4.9,<1.4.10.0a0 + license: Apache-2.0 + license_family: Apache + size: 160593 + timestamp: 1712592986336 +- kind: conda + name: aws-c-io + version: 0.14.7 + build: h33d81b3_3 + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.14.7-h33d81b3_3.conda + sha256: 78e29bcf2b2f13a4da534bd433893767470fee7f89f9c70173586931ef9a9885 + md5: df4dd21ab3e327bafbfe8d9842130dc2 + depends: + - __osx >=11.0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 136983 + timestamp: 1712593152214 +- kind: conda + name: aws-c-io + version: 0.14.7 + build: h6254544_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.7-h6254544_3.conda + sha256: 1f5fcb2d59e2d2a1755495d49d7e5d0404b3e87741b7063b748782c99b1a76e5 + md5: 566a515873a312fc3a97c8028072312c + depends: + - __osx >=10.9 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 138408 + timestamp: 1712593378751 +- kind: conda + name: aws-c-io + version: 0.14.7 + build: h76a7424_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.14.7-h76a7424_3.conda + sha256: d2583f1daeb85dc174dd396651f922ee848247c10dc8411bc8acbc07cd9a896d + md5: d6ff74a0389f7129f7d7a5f94c050776 + depends: + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + - s2n >=1.4.9,<1.4.10.0a0 + license: Apache-2.0 + license_family: Apache + size: 158032 + timestamp: 1712593016853 - kind: conda name: aws-c-mqtt version: 0.10.0 @@ -2710,6 +4185,100 @@ packages: license_family: Apache size: 157819 timestamp: 1708621381498 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: h3321c0c_4 + build_number: 4 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-mqtt-0.10.3-h3321c0c_4.conda + sha256: 2495ddb3ab112f22eb7f96f5f0be6bb7237e93f68b77016afe5bf07b5501f4fb + md5: edb8c254f2a280ba78d2488e28935778 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 146924 + timestamp: 1712547308954 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: h50844eb_4 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.10.3-h50844eb_4.conda + sha256: e80a6cea0a3d954cdb63b49d80a62f1982bb13722c0c99ba83b15820e61d4760 + md5: e72fdd8942f266ea79c70ec085661d6c + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 163794 + timestamp: 1712547607752 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: h5f4abda_4 + build_number: 4 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.10.3-h5f4abda_4.conda + sha256: ee1296c91f1624a67199b4885f79d3123a9bbc5b7def6de056f0d8c1c4525d0d + md5: 49dfa5667f57d5a7f9716ff06f80d28f + depends: + - __osx >=11.0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + license: Apache-2.0 + license_family: Apache + size: 118034 + timestamp: 1712547383899 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: h748201e_4 + build_number: 4 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.3-h748201e_4.conda + sha256: eeec7e222cb8ecf0df2e5d5c17a511ba8b16af22b12bdf6d6a9540b6e6aeb3bd + md5: 235f22fb6ae78c9807273f7726021465 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc >=14.3,<15 + - vc14_runtime >=14.29.30139 + - vc14_runtime >=14.38.33130 + license: Apache-2.0 + license_family: Apache + size: 158520 + timestamp: 1712547856285 +- kind: conda + name: aws-c-mqtt + version: 0.10.3 + build: hd66502f_4 + build_number: 4 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.3-hd66502f_4.conda + sha256: 7c1f640276ad3be6095bf12c1debecde3458321d18eedca40daec6d0036ef0f9 + md5: 89e656a48d3c1e094366648d33320ff0 + depends: + - __osx >=10.9 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + license: Apache-2.0 + license_family: Apache + size: 139268 + timestamp: 1712547737430 - kind: conda name: aws-c-s3 version: 0.4.7 @@ -2880,6 +4449,115 @@ packages: license_family: Apache size: 90798 timestamp: 1709172968839 +- kind: conda + name: aws-c-s3 + version: 0.5.7 + build: h4907f8a_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.5.7-h4907f8a_1.conda + sha256: 1a6b336545f635702c4113272a413b8509762cf3572abe7e3854bdbf9807a9ed + md5: 7591a42fcec5b6ccf27247f66782687f + depends: + - __osx >=10.9 + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + license: Apache-2.0 + license_family: Apache + size: 93544 + timestamp: 1712685831186 +- kind: conda + name: aws-c-s3 + version: 0.5.7 + build: h5da7064_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.7-h5da7064_1.conda + sha256: 0da7ee2d40bd6ed559a4aa52430dd71c8abde10c193f7ea8799a221cb1ceeef0 + md5: 4b80f4d4191132572fe83b622442918a + depends: + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 104398 + timestamp: 1712686192455 +- kind: conda + name: aws-c-s3 + version: 0.5.7 + build: h606a3d2_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.5.7-h606a3d2_1.conda + sha256: 7365e76ad87e39bf58eea10515001007e275bbd270981f3a1641c840f052017a + md5: 9bd413b520a8768af02e3a5810e9a42a + depends: + - __osx >=11.0 + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + license: Apache-2.0 + license_family: Apache + size: 93368 + timestamp: 1712686042460 +- kind: conda + name: aws-c-s3 + version: 0.5.7 + build: hb7bd14b_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.5.7-hb7bd14b_1.conda + sha256: 94e2d5174ba344357801a44c303f513ae40f37c2defcc3d3747809ac11be1e27 + md5: 82bd3d7da86d969c62ff541bab19526a + depends: + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 108249 + timestamp: 1712685968385 +- kind: conda + name: aws-c-s3 + version: 0.5.7 + build: hb8e3a89_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-s3-0.5.7-hb8e3a89_1.conda + sha256: de140ffe2261cd906c4712506605e4be346fafd4a7130a3b7d1e31af108c43f4 + md5: 911e1712416713967239097272c8c336 + depends: + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 112653 + timestamp: 1712686784716 - kind: conda name: aws-c-sdkutils version: 0.1.13 @@ -2945,6 +4623,70 @@ packages: license_family: Apache size: 57857 timestamp: 1708014280193 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: h53e3db5_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.15-h53e3db5_3.conda + sha256: 6b6b1652ede11c5ba4b6458b1fb88760658bb024ac5f06d2adf7130aa5550376 + md5: 569179357460c6f2acd2c3507c77c4c2 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 49610 + timestamp: 1712146120263 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: ha21e00f_3 + build_number: 3 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-ha21e00f_3.conda + sha256: 1c72977356cbac9e805c0325692628edf4d30c3bb09fbe5ddd91d709f410bcc5 + md5: 7b10fea2a5418a3ad31507a8e3019019 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 53883 + timestamp: 1712146320267 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: hce8ee76_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.1.15-hce8ee76_3.conda + sha256: 72fd73a5de0730997a36bf20ac1cb8cf7c67e40225c280b3dc5e46bc61c7d157 + md5: 0c4f0205a1ae4ca6c89af922ec54271c + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 55146 + timestamp: 1712145768196 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: hd34e5fa_3 + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.1.15-hd34e5fa_3.conda + sha256: e128818c57f6273df6dc64d7c3868eb179011766d790a8a93ad152fa26be4b9d + md5: d4afb2c3ed05bf792183ffdbc723aaeb + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 49627 + timestamp: 1712146003862 - kind: conda name: aws-c-sdkutils version: 0.1.15 @@ -2963,6 +4705,22 @@ packages: license_family: Apache size: 54410 timestamp: 1708014886501 +- kind: conda + name: aws-c-sdkutils + version: 0.1.15 + build: he771c36_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-sdkutils-0.1.15-he771c36_3.conda + sha256: 2de4fcab1b3c8a7213dc829cd33fbcebc74e7e75e22ee063eff6ae6101b0d4b9 + md5: fdd738c0212f6ffe582f19b71817e230 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 57954 + timestamp: 1712145913974 - kind: conda name: aws-c-sdkutils version: 0.1.15 @@ -3077,6 +4835,70 @@ packages: license_family: Apache size: 50114 timestamp: 1708017850698 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: h53e3db5_3 + build_number: 3 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.18-h53e3db5_3.conda + sha256: b62bcee0d6accf5b9e790cdb6171678ac6c865acc9df46249f36e554654f218b + md5: 2e78e8a3675a597ff8deaf118c7b714b + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 48730 + timestamp: 1712146097053 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: ha21e00f_3 + build_number: 3 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-ha21e00f_3.conda + sha256: c7759b8b3c163916ab47ae0f65549ce7c4e78d54bf9daadd5fa035b4b04500bb + md5: a593ee36f55e9af14d7a7f9f8f854fcc + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 52267 + timestamp: 1712145968515 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: hce8ee76_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.18-hce8ee76_3.conda + sha256: de0ba47fc8feaaa087d9128e4b5402af72bd46af52b885dee87adfb9e285a816 + md5: 9aa734a17b9b0b793c7696435fe7789a + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 50068 + timestamp: 1712145648515 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: hd34e5fa_3 + build_number: 3 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.18-hd34e5fa_3.conda + sha256: d91ba44e14b31c5fe13fd78a567fc6cf76c62ad8bfaba250e317b354a75c64dd + md5: 69f9b2281805ff1e0c87962d74de1360 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + license: Apache-2.0 + license_family: Apache + size: 48999 + timestamp: 1712145929885 - kind: conda name: aws-checksums version: 0.1.18 @@ -3095,6 +4917,22 @@ packages: license_family: Apache size: 52242 timestamp: 1708018159164 +- kind: conda + name: aws-checksums + version: 0.1.18 + build: he771c36_3 + build_number: 3 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-checksums-0.1.18-he771c36_3.conda + sha256: 325243d15c071e47880fdb940cfc44f7ca514d847e1805517a568c5c71ea8aa1 + md5: 469c1cd8a140da3d1f45e002176e05e0 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - libgcc-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 49898 + timestamp: 1712145734119 - kind: conda name: aws-checksums version: 0.1.18 @@ -3344,6 +5182,132 @@ packages: license_family: Apache size: 242812 timestamp: 1709208518468 +- kind: conda + name: aws-crt-cpp + version: 0.26.6 + build: h13f0230_4 + build_number: 4 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.6-h13f0230_4.conda + sha256: abf4618412f03fad2f3a1d4dd15200237afce54e1d1eff5eb17f834aa7acd32d + md5: 4e2b2d2f1ae778ed49d542974403fb60 + depends: + - __osx >=11.0 + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 + - aws-c-s3 >=0.5.7,<0.5.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 220730 + timestamp: 1712752845989 +- kind: conda + name: aws-crt-cpp + version: 0.26.6 + build: h497fec5_4 + build_number: 4 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.6-h497fec5_4.conda + sha256: dd70eeb5c3a0faf657f608d5dbd391b596037e09bcf6cf002a9ef113be6fd43f + md5: c1936a5794e212e1b98d7c71a60d4bdb + depends: + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 + - aws-c-s3 >=0.5.7,<0.5.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 263673 + timestamp: 1712752511297 +- kind: conda + name: aws-crt-cpp + version: 0.26.6 + build: h5bc0ceb_4 + build_number: 4 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.6-h5bc0ceb_4.conda + sha256: 901ec0e31aa75ae80935a051a1387f55e2b3e0e4a97b31635b88310505e4afa2 + md5: 056f3eaae2910ed8aca0f17cb2378f6f + depends: + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 + - aws-c-s3 >=0.5.7,<0.5.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 246123 + timestamp: 1712753024280 +- kind: conda + name: aws-crt-cpp + version: 0.26.6 + build: hf567797_4 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.6-hf567797_4.conda + sha256: 45007f9367f9f41185a5b274a1dc6c44ceae9fb0a4e44eae3542deaab53559fb + md5: ffb662b31aef333e68a00dd17fda2027 + depends: + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 + - aws-c-s3 >=0.5.7,<0.5.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: Apache + size: 335145 + timestamp: 1712752545390 +- kind: conda + name: aws-crt-cpp + version: 0.26.6 + build: hfb53d2e_4 + build_number: 4 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.6-hfb53d2e_4.conda + sha256: bcb8587d5c1689009badefc13320ba161479aab9affa8d205583059dabe576bd + md5: a4491c9681a6bf71a226c544990c9112 + depends: + - __osx >=10.9 + - aws-c-auth >=0.7.17,<0.7.18.0a0 + - aws-c-cal >=0.6.11,<0.6.12.0a0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-c-http >=0.8.1,<0.8.2.0a0 + - aws-c-io >=0.14.7,<0.14.8.0a0 + - aws-c-mqtt >=0.10.3,<0.10.4.0a0 + - aws-c-s3 >=0.5.7,<0.5.8.0a0 + - aws-c-sdkutils >=0.1.15,<0.1.16.0a0 + - libcxx >=16 + license: Apache-2.0 + license_family: Apache + size: 283365 + timestamp: 1712752909519 - kind: conda name: aws-sdk-cpp version: 1.11.210 @@ -3417,6 +5381,52 @@ packages: license_family: Apache size: 3267017 timestamp: 1704353210503 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: h01edc24_6 + build_number: 6 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h01edc24_6.conda + sha256: a406e26d63b84615e7a9924ae02f609e2a2b1abc201278ddd840787352902353 + md5: bb12f6114bfc032af2e689e0e1eae1c7 + depends: + - __osx >=10.9 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 + - libcurl >=8.7.1,<9.0a0 + - libcxx >=16 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 3394339 + timestamp: 1712754051179 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: h134aaec_6 + build_number: 6 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h134aaec_6.conda + sha256: 5eff7b834368f9e710cded2e7c0a56f1595b5b617f310547874df10c275cd6a0 + md5: 25727bad6dc72a38c856c3e9a578ebc7 + depends: + - __osx >=11.0 + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 + - libcurl >=8.7.1,<9.0a0 + - libcxx >=16 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 3411167 + timestamp: 1712754307571 - kind: conda name: aws-sdk-cpp version: 1.11.267 @@ -3462,6 +5472,28 @@ packages: license_family: Apache size: 3614539 timestamp: 1708527061409 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: h5d77392_6 + build_number: 6 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h5d77392_6.conda + sha256: 9f21b50aaf0eecdc885151dc754fdc5902194e82850629686a0f2f2572b95760 + md5: 1d1a457905f69984e81e541d1ede18e7 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 3435756 + timestamp: 1712754553202 - kind: conda name: aws-sdk-cpp version: 1.11.267 @@ -3506,6 +5538,52 @@ packages: license_family: Apache size: 3413748 timestamp: 1708528552370 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: hbf3e495_6 + build_number: 6 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-hbf3e495_6.conda + sha256: f9cc828d2eba6a0490e0e79795360dfd744e5042f7105311ab0e5927b56121eb + md5: a6caf5a0d9ca940d95f21d40afe8f857 + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 + - libcurl >=8.7.1,<9.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 3643894 + timestamp: 1712753061178 +- kind: conda + name: aws-sdk-cpp + version: 1.11.267 + build: hc40fc56_6 + build_number: 6 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hc40fc56_6.conda + sha256: f7c626469e342c9bf10787d425c8864cb8267cf6d8f0302599bc1cab8d32b8b7 + md5: 43046b3b911da5fae07a5831d5ecb78d + depends: + - aws-c-common >=0.9.15,<0.9.16.0a0 + - aws-c-event-stream >=0.4.2,<0.4.3.0a0 + - aws-checksums >=0.1.18,<0.1.19.0a0 + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 + - libcurl >=8.7.1,<9.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 3427110 + timestamp: 1712753133948 - kind: conda name: aws-sdk-cpp version: 1.11.267 @@ -3529,6 +5607,17 @@ packages: license_family: Apache size: 3409636 timestamp: 1708527387032 +- kind: pypi + name: babel + version: 2.14.0 + url: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + sha256: efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287 + requires_dist: + - pytz >=2015.7 ; python_version < '3.9' + - pytest >=6.0 ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - freezegun ~=1.0 ; extra == 'dev' + requires_python: '>=3.7' - kind: conda name: binaryen version: '117' @@ -3541,6 +5630,7 @@ packages: - libgcc-ng >=12 - libstdcxx-ng >=12 license: Apache-2.0 + license_family: APACHE size: 5372762 timestamp: 1710444374732 - kind: conda @@ -3910,38 +6000,106 @@ packages: - libgcc-ng >=12 license: MIT license_family: MIT - size: 162725 - timestamp: 1706299899438 + size: 162725 + timestamp: 1706299899438 +- kind: conda + name: c-ares + version: 1.27.0 + build: h31becfc_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda + sha256: 4152e674377179b35d59ddd9218411477a206ecff5f5939dfc963f997cf3b8b8 + md5: f03f76a77d690f2d31ce12e7b4e12ae4 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 170421 + timestamp: 1708684764494 +- kind: conda + name: c-ares + version: 1.27.0 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda + sha256: 1ab77396e0aaffc6e02508994983c7c6e3bc57019f4a13ac4fda6ee274e30bda + md5: 387d3a2f8fc0ec02f48cee4cd79ec7e0 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + size: 153934 + timestamp: 1708685329364 +- kind: conda + name: c-ares + version: 1.28.1 + build: h10d778d_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda + sha256: fccd7ad7e3dfa6b19352705b33eb738c4c55f79f398e106e6cf03bab9415595a + md5: d5eb7992227254c0e9a0ce71151f0079 + license: MIT + license_family: MIT + size: 152607 + timestamp: 1711819681694 - kind: conda name: c-ares - version: 1.27.0 + version: 1.28.1 build: h31becfc_0 subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda - sha256: 4152e674377179b35d59ddd9218411477a206ecff5f5939dfc963f997cf3b8b8 - md5: f03f76a77d690f2d31ce12e7b4e12ae4 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.28.1-h31becfc_0.conda + sha256: 0d7b310411f069975053ee5ce750fc6d8c368607164ce2a921a7a1a068dc137b + md5: a8da75795c853c5fe6d8d1947e16eea8 depends: - libgcc-ng >=12 license: MIT license_family: MIT - size: 170421 - timestamp: 1708684764494 + size: 176103 + timestamp: 1711819570996 - kind: conda name: c-ares - version: 1.27.0 + version: 1.28.1 + build: h93a5062_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda + sha256: 2fc553d7a75e912efbdd6b82cd7916cc9cb2773e6cd873b77e02d631dd7be698 + md5: 04f776a6139f7eafc2f38668570eb7db + license: MIT + license_family: MIT + size: 150488 + timestamp: 1711819630164 +- kind: conda + name: c-ares + version: 1.28.1 build: hcfcfb64_0 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - sha256: 1ab77396e0aaffc6e02508994983c7c6e3bc57019f4a13ac4fda6ee274e30bda - md5: 387d3a2f8fc0ec02f48cee4cd79ec7e0 + url: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.28.1-hcfcfb64_0.conda + sha256: 44ded34fdac46d4a37942c1cae3fc871dc6ecb13e0408442c6f8797671b332e6 + md5: 3b2a518680f790a79a7e77bad1861c3a depends: - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 license: MIT license_family: MIT - size: 153934 - timestamp: 1708685329364 + size: 159060 + timestamp: 1711820066438 +- kind: conda + name: c-ares + version: 1.28.1 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.28.1-hd590300_0.conda + sha256: cb25063f3342149c7924b21544109696197a9d774f1407567477d4f3026bf38a + md5: dcde58ff9a1f30b0037a2315d1846d1f + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 168875 + timestamp: 1711819445938 - kind: conda name: c-compiler version: 1.6.0 @@ -4200,14 +6358,8 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 - requires_python: '>=3.7.0' -- kind: pypi - name: charset-normalizer - version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer @@ -4218,8 +6370,8 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer @@ -4227,6 +6379,12 @@ packages: url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' +- kind: pypi + name: charset-normalizer + version: 3.3.2 + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + requires_python: '>=3.7.0' - kind: conda name: clang version: 16.0.6 @@ -4403,6 +6561,25 @@ packages: license_family: Apache size: 692537 timestamp: 1706894104516 +- kind: conda + name: clang-format + version: 16.0.6 + build: default_h127d8a8_6 + build_number: 6 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_6.conda + sha256: 47df5a49b498e21ccfa4fd39765fbbde74a20be92868b68fde106c3c48d8bc66 + md5: cae7d2d4f2b29a87a39da58424cc95b9 + depends: + - clang-format-16 16.0.6 default_h127d8a8_6 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22102 + timestamp: 1711068383801 - kind: conda name: clang-format version: 16.0.6 @@ -4420,6 +6597,23 @@ packages: license_family: Apache size: 1131165 timestamp: 1706895787433 +- kind: conda + name: clang-format + version: 16.0.6 + build: default_h3a3e6c3_6 + build_number: 6 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_6.conda + sha256: df1adc16b66b948854ed4fe872201f5671a3c782f3f1be919f95f9d28f994c33 + md5: a213fcc62200e15b698951088c8d43a7 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 1131387 + timestamp: 1711073515672 - kind: conda name: clang-format version: 16.0.6 @@ -4438,6 +6632,24 @@ packages: license_family: Apache size: 21806 timestamp: 1706894696246 +- kind: conda + name: clang-format + version: 16.0.6 + build: default_h7151d67_6 + build_number: 6 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_6.conda + sha256: 83321fa2efe78de1c13836487d8d2f60dafd31a53ab7660beb39fc311c02c752 + md5: 5cdb7876b0b7e159734e1767f23700da + depends: + - clang-format-16 16.0.6 default_h7151d67_6 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22190 + timestamp: 1711068476939 - kind: conda name: clang-format version: 16.0.6 @@ -4476,6 +6688,25 @@ packages: license_family: Apache size: 21892 timestamp: 1706896136958 +- kind: conda + name: clang-format + version: 16.0.6 + build: default_hb368394_6 + build_number: 6 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_6.conda + sha256: 6f166ee8a6354c12329f515a72fb2494878de5ddeb3a917600c52179a86cd9c4 + md5: cc51a3280d15b92c17ffce9a14e1c2e0 + depends: + - clang-format-16 16.0.6 default_hb368394_6 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22211 + timestamp: 1711067700135 - kind: conda name: clang-format version: 16.0.6 @@ -4494,6 +6725,42 @@ packages: license_family: Apache size: 21914 timestamp: 1706894694897 +- kind: conda + name: clang-format + version: 16.0.6 + build: default_he012953_6 + build_number: 6 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_6.conda + sha256: d2e5fe929b1d3d16fe488997b6ed2c5bf7a654ff95be1aef778cdc2fb0981a29 + md5: 8b520107c3a46be699e81c0ec8a3e5ac + depends: + - clang-format-16 16.0.6 default_he012953_6 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 22305 + timestamp: 1711067661122 +- kind: conda + name: clang-format-16 + version: 16.0.6 + build: default_h127d8a8_6 + build_number: 6 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_6.conda + sha256: 3b0d7ee0dc358cb4509dd55eb7cf1306f43fc58fee3b136ed6ef229f51b49c6c + md5: c88b3af16ca49c02c6dd32c7f81e4c33 + depends: + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 62400 + timestamp: 1711068298945 - kind: conda name: clang-format-16 version: 16.0.6 @@ -4511,6 +6778,23 @@ packages: license_family: Apache size: 58542 timestamp: 1706894600420 +- kind: conda + name: clang-format-16 + version: 16.0.6 + build: default_h7151d67_6 + build_number: 6 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_6.conda + sha256: c0cbb956c1bbf0b5bd1472a0abba5cb150f50970af1826f7af9946b3b3fafcac + md5: 7dcab575fa02c87fcce273888dfcb7e2 + depends: + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 58730 + timestamp: 1711068369836 - kind: conda name: clang-format-16 version: 16.0.6 @@ -4547,6 +6831,24 @@ packages: license_family: Apache size: 63067 timestamp: 1706896079312 +- kind: conda + name: clang-format-16 + version: 16.0.6 + build: default_hb368394_6 + build_number: 6 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_6.conda + sha256: 9e2ddedcaaf03023148824206fd1140b8771b2fac2d2c133192a41057c3f8aed + md5: c7d2345cfa374879ffaf5561904802f1 + depends: + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 63394 + timestamp: 1711067643687 - kind: conda name: clang-format-16 version: 16.0.6 @@ -4564,6 +6866,49 @@ packages: license_family: Apache size: 56848 timestamp: 1706894594045 +- kind: conda + name: clang-format-16 + version: 16.0.6 + build: default_he012953_6 + build_number: 6 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_6.conda + sha256: 0bb88aa14b89b6197666434e92a16dbcd866c11bc4b46fddee464ee79bd443f9 + md5: 3a5eb119f499bc58837e394559a5faf7 + depends: + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 56875 + timestamp: 1711067556812 +- kind: conda + name: clang-tools + version: 16.0.6 + build: default_h127d8a8_6 + build_number: 6 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_6.conda + sha256: f286ff0745c14f7c538f617cb94a62664a8390af8e2df83b8121630b4e1cce0b + md5: 98c22eeaac9b3144e47948d28ae6bc6a + depends: + - clang-format 16.0.6 default_h127d8a8_6 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libclang13 >=16.0.6 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + constrains: + - clangdev 16.0.6 + - clang 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 26787539 + timestamp: 1711068451374 - kind: conda name: clang-tools version: 16.0.6 @@ -4592,6 +6937,34 @@ packages: license_family: Apache size: 227348179 timestamp: 1706896190792 +- kind: conda + name: clang-tools + version: 16.0.6 + build: default_h3a3e6c3_6 + build_number: 6 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_6.conda + sha256: c33605f18fdfbc867ef92086e163d1325ebab0b4bb344b55ecfaaba5fc19c39d + md5: 09383e17b04b0faf0b89850f620efeba + depends: + - clang-format 16.0.6 default_h3a3e6c3_6 + - libclang13 >=16.0.6 + - libxml2 >=2.12.6,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - clangdev 16.0.6 + - clang 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 225794097 + timestamp: 1711074018681 - kind: conda name: clang-tools version: 16.0.6 @@ -4617,6 +6990,31 @@ packages: license_family: Apache size: 17982262 timestamp: 1706894817029 +- kind: conda + name: clang-tools + version: 16.0.6 + build: default_h7151d67_6 + build_number: 6 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_6.conda + sha256: 192c1b7aa1a40b736bceb6c8d37794d25bf1b19b0d6ccc83ddd4ff2ccb5b4207 + md5: 647fab0a5e01c0c9f026465f3c47e725 + depends: + - clang-format 16.0.6 default_h7151d67_6 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libclang13 >=16.0.6 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + constrains: + - clangdev 16.0.6 + - clang 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 17968983 + timestamp: 1711068607365 - kind: conda name: clang-tools version: 16.0.6 @@ -4669,6 +7067,32 @@ packages: license_family: Apache size: 26926170 timestamp: 1706896230135 +- kind: conda + name: clang-tools + version: 16.0.6 + build: default_hb368394_6 + build_number: 6 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_6.conda + sha256: baed51d6b8f84efd5bca692ba0646eb7c2992500318c3b09291070271ecfc4c6 + md5: 3b8393019d34558cf6befab106f5332d + depends: + - clang-format 16.0.6 default_hb368394_6 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libclang13 >=16.0.6 + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + constrains: + - clangdev 16.0.6 + - clang 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 26854313 + timestamp: 1711067761610 - kind: conda name: clang-tools version: 16.0.6 @@ -4679,7 +7103,32 @@ packages: sha256: 1a86cf1334fefb6a4463ed281d57e8826408ada2c06b4367d8b68aa06a5c78da md5: 112fbb989f5a2e82fef7d78e84cb4e8a depends: - - clang-format 16.0.6 default_he012953_5 + - clang-format 16.0.6 default_he012953_5 + - libclang-cpp16 >=16.0.6,<16.1.0a0 + - libclang13 >=16.0.6 + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + constrains: + - clangdev 16.0.6 + - clang 16.0.6.* + - llvm 16.0.6.* + - llvm-tools 16.0.6.* + - llvmdev 16.0.6.* + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 16957978 + timestamp: 1706894821989 +- kind: conda + name: clang-tools + version: 16.0.6 + build: default_he012953_6 + build_number: 6 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_6.conda + sha256: 66c301dd820bce84290fabdf5e90d4663166d2126883b95ac6756b68bc3da7fc + md5: 2cf1b4ddd92abc04814f0ce740aee7a5 + depends: + - clang-format 16.0.6 default_he012953_6 - libclang-cpp16 >=16.0.6,<16.1.0a0 - libclang13 >=16.0.6 - libcxx >=16.0.6 @@ -4692,8 +7141,8 @@ packages: - llvmdev 16.0.6.* license: Apache-2.0 WITH LLVM-exception license_family: Apache - size: 16957978 - timestamp: 1706894821989 + size: 16984505 + timestamp: 1711067792464 - kind: conda name: clang_impl_osx-64 version: 16.0.6 @@ -4860,6 +7309,15 @@ packages: license_family: BSD size: 19330 timestamp: 1706832814124 +- kind: pypi + name: click + version: 8.1.7 + url: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl + sha256: ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 + requires_dist: + - colorama ; platform_system == 'Windows' + - importlib-metadata ; python_version < '3.8' + requires_python: '>=3.7' - kind: conda name: cmake version: 3.27.6 @@ -5359,6 +7817,80 @@ packages: license_family: APACHE size: 1298784 timestamp: 1710058440028 +- kind: conda + name: flatbuffers + version: 24.3.25 + build: h2f0025b_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.25-h2f0025b_0.conda + sha256: e359e3982a316dc0daf6e9b4efbe93efc1a255f15c97694c0abee8f90b13d4a8 + md5: 773218124ef65e2dde011525c6952196 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 1301897 + timestamp: 1711467117 +- kind: conda + name: flatbuffers + version: 24.3.25 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.25-h59595ed_0.conda + sha256: 0f3b8d6a958d40d5b2ac105ba0ec09f61dd4ce78cafdf99ab2d0fc298dc54d75 + md5: 2941a8c4e4871cdfa738c8c1a7611533 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 1459911 + timestamp: 1711467009850 +- kind: conda + name: flatbuffers + version: 24.3.25 + build: h63175ca_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.25-h63175ca_0.conda + sha256: 2535ad2f65afe3764113ecd129a8674bd162b54a78e429a4d324443b1aa5d104 + md5: ee24499f9b776dba2600029209acb64d + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + size: 1734162 + timestamp: 1711467411953 +- kind: conda + name: flatbuffers + version: 24.3.25 + build: h73e2aa4_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.25-h73e2aa4_0.conda + sha256: 3648f1822b69a4212b368b0cfa266a77accaeb60794af2b90e4178c263b2abda + md5: 728a9638664ac180b3d970b3d04cf218 + depends: + - libcxx >=16 + license: Apache-2.0 + license_family: APACHE + size: 1330937 + timestamp: 1711467455228 +- kind: conda + name: flatbuffers + version: 24.3.25 + build: hebf3989_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.25-hebf3989_0.conda + sha256: c95467f1ef83f358518cea13de8e00e3998427fc7f0dad5885f47c18aeb95ad4 + md5: f23852b1b71bc82768a6a33f6122efff + depends: + - libcxx >=16 + license: Apache-2.0 + license_family: APACHE + size: 1280038 + timestamp: 1711467768202 - kind: conda name: gcc version: 12.3.0 @@ -5527,6 +8059,17 @@ packages: license_family: BSD size: 116549 timestamp: 1594303828933 +- kind: pypi + name: ghp-import + version: 2.1.0 + url: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + sha256: 8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 + requires_dist: + - python-dateutil >=2.8.1 + - twine ; extra == 'dev' + - markdown ; extra == 'dev' + - flake8 ; extra == 'dev' + - wheel ; extra == 'dev' - kind: conda name: gitdb version: 4.0.11 @@ -5642,6 +8185,25 @@ packages: - pkg:pypi/gitpython size: 149604 timestamp: 1708069389374 +- kind: conda + name: gitpython + version: 3.1.43 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + sha256: cbb2802641a009ce9bcc2a047e817fd8816f9c842036a42f4730398d8e4cda2a + md5: 0b2154c1818111e17381b1df5b4b0176 + depends: + - gitdb >=4.0.1,<5 + - python >=3.7 + - typing_extensions >=3.7.4.3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/gitpython + size: 156827 + timestamp: 1711991122366 - kind: conda name: glog version: 0.6.0 @@ -5751,6 +8313,14 @@ packages: license_family: BSD size: 143596 timestamp: 1708260910243 +- kind: pypi + name: griffe + version: 0.39.0 + url: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl + sha256: b5e2f249d86feaad1d3068b33b1c8c2ecf39cb870bf292f2af3a4311891a4835 + requires_dist: + - colorama >=0.4 + requires_python: '>=3.8' - kind: conda name: gxx version: 12.3.0 @@ -5913,6 +8483,12 @@ packages: url: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl sha256: c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f requires_python: '>=3.5' +- kind: pypi + name: idna + version: '3.7' + url: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + sha256: 82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 + requires_python: '>=3.5' - kind: conda name: iniconfig version: 2.0.0 @@ -5960,6 +8536,66 @@ packages: license_family: Proprietary size: 2325424 timestamp: 1706182537883 +- kind: conda + name: intel-openmp + version: 2024.1.0 + build: h57928b3_964 + build_number: 964 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.1.0-h57928b3_964.conda + sha256: bea54e995cd79b0961ded5f0d6d1b8a55513283ccda74cedb3421a3764f7d679 + md5: 30ebb9fd99666d8b8675fcee541a09f3 + license: LicenseRef-ProprietaryIntel + license_family: Proprietary + size: 1616281 + timestamp: 1712153179165 +- kind: pypi + name: jinja2 + version: 3.1.3 + url: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + sha256: 7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa + requires_dist: + - markupsafe >=2.0 + - babel >=2.7 ; extra == 'i18n' + requires_python: '>=3.7' +- kind: pypi + name: jsonschema + version: 4.21.1 + url: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl + sha256: 7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f + requires_dist: + - attrs >=22.2.0 + - importlib-resources >=1.4.0 ; python_version < '3.9' + - jsonschema-specifications >=2023.3.6 + - pkgutil-resolve-name >=1.3.10 ; python_version < '3.9' + - referencing >=0.28.4 + - rpds-py >=0.7.1 + - fqdn ; extra == 'format' + - idna ; extra == 'format' + - isoduration ; extra == 'format' + - jsonpointer >1.13 ; extra == 'format' + - rfc3339-validator ; extra == 'format' + - rfc3987 ; extra == 'format' + - uri-template ; extra == 'format' + - webcolors >=1.11 ; extra == 'format' + - fqdn ; extra == 'format-nongpl' + - idna ; extra == 'format-nongpl' + - isoduration ; extra == 'format-nongpl' + - jsonpointer >1.13 ; extra == 'format-nongpl' + - rfc3339-validator ; extra == 'format-nongpl' + - rfc3986-validator >0.1.0 ; extra == 'format-nongpl' + - uri-template ; extra == 'format-nongpl' + - webcolors >=1.11 ; extra == 'format-nongpl' + requires_python: '>=3.8' +- kind: pypi + name: jsonschema-specifications + version: 2023.12.1 + url: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl + sha256: 87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c + requires_dist: + - importlib-resources >=1.4.0 ; python_version < '3.9' + - referencing >=0.31.0 + requires_python: '>=3.8' - kind: conda name: kernel-headers_linux-64 version: 2.6.32 @@ -6444,6 +9080,84 @@ packages: license_family: APACHE size: 7385058 timestamp: 1710292910535 +- kind: conda + name: libarrow + version: 14.0.2 + build: h3fc723a_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h3fc723a_16_cpu.conda + sha256: 634b0af57b962c7aa409b225cd63c9ba15e2d4dd5822ad0ae3bb2ba1e1aecb3c + md5: 6740dd07b1d1b2973a4122ebe48ffcb6 + depends: + - __osx >=11.0 + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.0,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libcxx >=14 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - orc >=2.0.0,<2.0.1.0a0 + - re2 + - snappy >=1.2.0,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - parquet-cpp <0.0a0 + - apache-arrow-proc =*=cpu + - arrow-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + size: 5339852 + timestamp: 1712757441142 +- kind: conda + name: libarrow + version: 14.0.2 + build: h45212c0_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h45212c0_16_cpu.conda + sha256: f34fa38ff5ecbc3c669ca793b9170d3e14d78a04144bdafbcedf0a6a01bb3090 + md5: d9e117ea79c0da1b58684d384c58ec6e + depends: + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl >=8.7.1,<9.0a0 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - openssl >=3.2.1,<4.0a0 + - orc >=2.0.0,<2.0.1.0a0 + - re2 + - snappy >=1.2.0,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - apache-arrow-proc =*=cpu + - parquet-cpp <0.0a0 + - arrow-cpp <0.0a0 + license: Apache-2.0 + size: 4973735 + timestamp: 1712757360391 - kind: conda name: libarrow version: 14.0.2 @@ -6555,6 +9269,43 @@ packages: license_family: APACHE size: 8080771 timestamp: 1708689749260 +- kind: conda + name: libarrow + version: 14.0.2 + build: h520d24b_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-14.0.2-h520d24b_16_cpu.conda + sha256: c2806c04bb4a6cddcc9a3d74a457b0d48c411df32f31f65629956e189edc3e47 + md5: 6157a431296d16c6aea5c24f26c8ebf7 + depends: + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.0,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libgcc-ng >=12 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - orc >=2.0.0,<2.0.1.0a0 + - re2 + - snappy >=1.2.0,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - parquet-cpp <0.0a0 + - arrow-cpp <0.0a0 + - apache-arrow-proc =*=cpu + license: Apache-2.0 + size: 7385901 + timestamp: 1712756380577 - kind: conda name: libarrow version: 14.0.2 @@ -6595,56 +9346,132 @@ packages: - kind: conda name: libarrow version: 14.0.2 - build: hd01637b_10_cpu - build_number: 10 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-hd01637b_10_cpu.conda - sha256: c1c2a596b9248d42c555f1d1834f26b42bf2f3ca65fa2aab3e5746ab3f523126 - md5: f52069d499e82121648fc64aa1d40e0d + build: hd01637b_10_cpu + build_number: 10 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-hd01637b_10_cpu.conda + sha256: c1c2a596b9248d42c555f1d1834f26b42bf2f3ca65fa2aab3e5746ab3f523126 + md5: f52069d499e82121648fc64aa1d40e0d + depends: + - aws-crt-cpp >=0.26.2,<0.26.3.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgoogle-cloud >=2.21.0,<2.22.0a0 + - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 + - libre2-11 >=2023.6.2,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - openssl >=3.2.1,<4.0a0 + - orc >=1.9.2,<1.9.3.0a0 + - re2 + - snappy >=1.1.10,<2.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - apache-arrow-proc =*=cpu + - arrow-cpp <0.0a0 + - parquet-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + size: 4943273 + timestamp: 1708690059642 +- kind: conda + name: libarrow + version: 14.0.2 + build: hd2c9378_10_cpu + build_number: 10 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-hd2c9378_10_cpu.conda + sha256: 37dcb0fe1b56c27567ad83328c203995d284533e1df1e12ad6890aa6806b252b + md5: 9e008589cc46d067b7e4e8f023627743 + depends: + - __osx >=10.13 + - aws-crt-cpp >=0.26.2,<0.26.3.0a0 + - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 + - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.0,<0.8.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libbrotlidec >=1.1.0,<1.2.0a0 + - libbrotlienc >=1.1.0,<1.2.0a0 + - libcxx >=14 + - libgoogle-cloud >=2.21.0,<2.22.0a0 + - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 + - libre2-11 >=2023.6.2,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - orc >=1.9.2,<1.9.3.0a0 + - re2 + - snappy >=1.1.10,<2.0a0 + - zstd >=1.5.5,<1.6.0a0 + constrains: + - apache-arrow-proc =*=cpu + - parquet-cpp <0.0a0 + - arrow-cpp <0.0a0 + license: Apache-2.0 + license_family: APACHE + size: 5696868 + timestamp: 1708690271784 +- kind: conda + name: libarrow + version: 14.0.2 + build: he70291f_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-he70291f_16_cpu.conda + sha256: 62623e8c1c8ac494db18969dc4b10981b6ef168a6bda34ac3cc0540f051fb89b + md5: e788309ce6710ed0b8e79ed48394df32 depends: - - aws-crt-cpp >=0.26.2,<0.26.3.0a0 + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 - bzip2 >=1.0.8,<2.0a0 + - glog >=0.7.0,<0.8.0a0 - libabseil * cxx17* - libabseil >=20240116.1,<20240117.0a0 - libbrotlidec >=1.1.0,<1.2.0a0 - libbrotlienc >=1.1.0,<1.2.0a0 - - libcrc32c >=1.1.2,<1.2.0a0 - - libcurl >=8.5.0,<9.0a0 - - libgoogle-cloud >=2.21.0,<2.22.0a0 - - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 - - libre2-11 >=2023.6.2,<2024.0a0 + - libgcc-ng >=12 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 - libutf8proc >=2.8.0,<3.0a0 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - - openssl >=3.2.1,<4.0a0 - - orc >=1.9.2,<1.9.3.0a0 + - orc >=2.0.0,<2.0.1.0a0 - re2 - - snappy >=1.1.10,<2.0a0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - snappy >=1.2.0,<1.3.0a0 - zstd >=1.5.5,<1.6.0a0 constrains: - - apache-arrow-proc =*=cpu - arrow-cpp <0.0a0 - parquet-cpp <0.0a0 + - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE - size: 4943273 - timestamp: 1708690059642 + size: 8080035 + timestamp: 1712756067076 - kind: conda name: libarrow version: 14.0.2 - build: hd2c9378_10_cpu - build_number: 10 + build: hf13115f_16_cpu + build_number: 16 subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-hd2c9378_10_cpu.conda - sha256: 37dcb0fe1b56c27567ad83328c203995d284533e1df1e12ad6890aa6806b252b - md5: 9e008589cc46d067b7e4e8f023627743 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-hf13115f_16_cpu.conda + sha256: 6088fc74b624eb43ccb9f2c0439ac74036cb0989c788b3bea32bbc47fcdcdd65 + md5: ac262e0996665a32830bd4686ad58305 depends: - __osx >=10.13 - - aws-crt-cpp >=0.26.2,<0.26.3.0a0 + - aws-crt-cpp >=0.26.6,<0.26.7.0a0 - aws-sdk-cpp >=1.11.267,<1.11.268.0a0 - bzip2 >=1.0.8,<2.0a0 - glog >=0.7.0,<0.8.0a0 @@ -6653,24 +9480,23 @@ packages: - libbrotlidec >=1.1.0,<1.2.0a0 - libbrotlienc >=1.1.0,<1.2.0a0 - libcxx >=14 - - libgoogle-cloud >=2.21.0,<2.22.0a0 - - libgoogle-cloud-storage >=2.21.0,<2.22.0a0 - - libre2-11 >=2023.6.2,<2024.0a0 + - libgoogle-cloud >=2.22.0,<2.23.0a0 + - libgoogle-cloud-storage >=2.22.0,<2.23.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 - libutf8proc >=2.8.0,<3.0a0 - libzlib >=1.2.13,<1.3.0a0 - lz4-c >=1.9.3,<1.10.0a0 - - orc >=1.9.2,<1.9.3.0a0 + - orc >=2.0.0,<2.0.1.0a0 - re2 - - snappy >=1.1.10,<2.0a0 + - snappy >=1.2.0,<1.3.0a0 - zstd >=1.5.5,<1.6.0a0 constrains: - - apache-arrow-proc =*=cpu - - parquet-cpp <0.0a0 - arrow-cpp <0.0a0 + - parquet-cpp <0.0a0 + - apache-arrow-proc =*=cpu license: Apache-2.0 - license_family: APACHE - size: 5696868 - timestamp: 1708690271784 + size: 5698170 + timestamp: 1712757727827 - kind: conda name: libarrow-acero version: 14.0.2 @@ -6703,6 +9529,22 @@ packages: license_family: APACHE size: 511565 timestamp: 1706610895374 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: h0a1ffab_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-acero-14.0.2-h0a1ffab_16_cpu.conda + sha256: 227e4780febf20263aa27ff2a4e94454081ad12e7c7d008331dd8ed7dae3fe96 + md5: 35560acadb9ea4e4827a65748cbbfd38 + depends: + - libarrow 14.0.2 h520d24b_16_cpu + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + size: 543042 + timestamp: 1712756415053 - kind: conda name: libarrow-acero version: 14.0.2 @@ -6752,6 +9594,23 @@ packages: license_family: APACHE size: 542198 timestamp: 1710292954892 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: h43a2c78_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-14.0.2-h43a2c78_16_cpu.conda + sha256: a2c9bf9bffdda271241132704eccb980441338b5f112869cadd6b026c94ea64d + md5: dc75687da2e778b20fde2fbc826fa305 + depends: + - __osx >=11.0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libcxx >=14 + license: Apache-2.0 + license_family: APACHE + size: 495529 + timestamp: 1712757569509 - kind: conda name: libarrow-acero version: 14.0.2 @@ -6804,6 +9663,56 @@ packages: license_family: APACHE size: 430548 timestamp: 1708690137226 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: h8681a6d_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h8681a6d_16_cpu.conda + sha256: ef3ee1329d01ecf9d3fce9d71bb8d992047159e74ad6f8e6888f3b9167299c58 + md5: 962174049b3f016ec8c094c11c0e4b59 + depends: + - libarrow 14.0.2 h45212c0_16_cpu + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + size: 431209 + timestamp: 1712757444547 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: hac33072_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-14.0.2-hac33072_16_cpu.conda + sha256: af941fc5cbcd2dfbd469961b63bde52f43201bfaa014cda3685bf9088f037b55 + md5: dcaea1851956026dd7c796fac5b5aca3 + depends: + - libarrow 14.0.2 he70291f_16_cpu + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 578186 + timestamp: 1712756104658 +- kind: conda + name: libarrow-acero + version: 14.0.2 + build: hcdcf8f8_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-hcdcf8f8_16_cpu.conda + sha256: f1b21b04890e4dd315fd3c30eb3e131f7a9a0bca4175486885db9692b5c3f07e + md5: 5d6cf60ee555213f81706f58542d478c + depends: + - __osx >=10.13 + - libarrow 14.0.2 hf13115f_16_cpu + - libcxx >=14 + license: Apache-2.0 + size: 513336 + timestamp: 1712757880486 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -6840,6 +9749,24 @@ packages: license_family: APACHE size: 510602 timestamp: 1706611131325 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: h0a1ffab_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-dataset-14.0.2-h0a1ffab_16_cpu.conda + sha256: b20004cfe6ff83f5f8b28885b816b462247263aca3884acefbd99088dca1c2b6 + md5: cbddba39227ce47bcdd4cd5e9f2a64ce + depends: + - libarrow 14.0.2 h520d24b_16_cpu + - libarrow-acero 14.0.2 h0a1ffab_16_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 h70b04f6_16_cpu + - libstdcxx-ng >=12 + license: Apache-2.0 + size: 551480 + timestamp: 1712756500734 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -6895,6 +9822,25 @@ packages: license_family: APACHE size: 551283 timestamp: 1710293072163 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: h43a2c78_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-14.0.2-h43a2c78_16_cpu.conda + sha256: 73498818bdf3273bbe860fe3a85fb5e22e680e58e4be3caad6afeb4ece65cb14 + md5: 0e8c658a3c86f18d4fbf892fffd27ccf + depends: + - __osx >=11.0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libarrow-acero 14.0.2 h43a2c78_16_cpu + - libcxx >=14 + - libparquet 14.0.2 he0622da_16_cpu + license: Apache-2.0 + license_family: APACHE + size: 527563 + timestamp: 1712758813036 - kind: conda name: libarrow-dataset version: 14.0.2 @@ -6953,6 +9899,62 @@ packages: license_family: APACHE size: 429115 timestamp: 1708690422907 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: h8681a6d_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h8681a6d_16_cpu.conda + sha256: 18db3fceb2166ca245464fb924af2705a5a2be819cb82132f0549ae7ab0ac040 + md5: cee87a68e0745dfb82387d89296bb851 + depends: + - libarrow 14.0.2 h45212c0_16_cpu + - libarrow-acero 14.0.2 h8681a6d_16_cpu + - libparquet 14.0.2 h39135fc_16_cpu + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + size: 429999 + timestamp: 1712757753246 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: hac33072_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-14.0.2-hac33072_16_cpu.conda + sha256: ec28a71554fa47803c8cf10a690478e40deb12243e7187ecca9edb3c4834e3cb + md5: 58277cd6a5d64ea26e8ddeb0874a644e + depends: + - libarrow 14.0.2 he70291f_16_cpu + - libarrow-acero 14.0.2 hac33072_16_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 h6a7eafb_16_cpu + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 582131 + timestamp: 1712756178872 +- kind: conda + name: libarrow-dataset + version: 14.0.2 + build: hcdcf8f8_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-hcdcf8f8_16_cpu.conda + sha256: 1cf903af6fd9cbce9b6c61756cfbc392e7f26af93c7f67a5b12d20195f2c47fb + md5: 041880d9fdb9826b97d3de5a214ca398 + depends: + - __osx >=10.13 + - libarrow 14.0.2 hf13115f_16_cpu + - libarrow-acero 14.0.2 hcdcf8f8_16_cpu + - libcxx >=14 + - libparquet 14.0.2 h4aea69c_16_cpu + license: Apache-2.0 + size: 513459 + timestamp: 1712758757865 - kind: conda name: libarrow-flight version: 14.0.2 @@ -6975,6 +9977,27 @@ packages: license_family: APACHE size: 501085 timestamp: 1706609649937 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: h161034a_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-14.0.2-h161034a_16_cpu.conda + sha256: 2efd3f51f0d48f46f44d163c4dfdee668f47709232609a661e89e3a5cbe25e1f + md5: 2b72d4609b7b76d40d2b7cc44bb9acfe + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libcxx >=14 + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 333618 + timestamp: 1712757848944 - kind: conda name: libarrow-flight version: 14.0.2 @@ -7018,6 +10041,27 @@ packages: license_family: APACHE size: 321632 timestamp: 1708690401993 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: h83a3238_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-h83a3238_16_cpu.conda + sha256: 2af9e238c6e1c8ed111410a6e42551e8557ca31e46cf6eb37f14dbb862bddf52 + md5: 89a3f67b5fbae6d35ab6549370ba0d7e + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h45212c0_16_cpu + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + size: 286693 + timestamp: 1712757528915 - kind: conda name: libarrow-flight version: 14.0.2 @@ -7059,6 +10103,27 @@ packages: license_family: APACHE size: 332020 timestamp: 1706610826254 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: hbf3f4d3_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-14.0.2-hbf3f4d3_16_cpu.conda + sha256: 32623ea3856781c6b81550fa2c41512b623e0a527a67193bf7416c522b74d894 + md5: 9466b7a462c71ea0c3895fefee496fa8 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h520d24b_16_cpu + - libgcc-ng >=12 + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + - ucx >=1.15.0,<1.16.0a0 + license: Apache-2.0 + size: 475210 + timestamp: 1712756440661 - kind: conda name: libarrow-flight version: 14.0.2 @@ -7101,6 +10166,48 @@ packages: license_family: APACHE size: 286419 timestamp: 1708690211648 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: hcd10e87_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-hcd10e87_16_cpu.conda + sha256: c33f969d8f84f5ffc9b9a491bfce16c2a53c2351a166566f963c62a0038c5bbc + md5: 2689eb35fd8ff218770ff142b8b45f6a + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 hf13115f_16_cpu + - libcxx >=14 + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + size: 322515 + timestamp: 1712758072747 +- kind: conda + name: libarrow-flight + version: 14.0.2 + build: hd42f311_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-14.0.2-hd42f311_16_cpu.conda + sha256: dbd6159f762ce672b4bb283193bfe63311c2f7e7be04376e4e96d1eef7b055b4 + md5: 8f6059c0c2f0eecab3ee533f555ce75f + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 he70291f_16_cpu + - libgcc-ng >=12 + - libgrpc >=1.62.1,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + - ucx >=1.15.0,<1.16.0a0 + license: Apache-2.0 + license_family: APACHE + size: 503890 + timestamp: 1712756122474 - kind: conda name: libarrow-flight version: 14.0.2 @@ -7143,6 +10250,44 @@ packages: license_family: APACHE size: 233697 timestamp: 1708690485765 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: h21569af_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h21569af_16_cpu.conda + sha256: c87b9bff34980bcc8fd1f1d22088a16795c98539a43e16fa71e1370ef03bfc39 + md5: 9bf97c805e1b7d1c7ad7b2dcc24b88b3 + depends: + - libarrow 14.0.2 h45212c0_16_cpu + - libarrow-flight 14.0.2 h83a3238_16_cpu + - libprotobuf >=4.25.3,<4.25.4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + size: 234852 + timestamp: 1712757820439 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: h32643e2_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-sql-14.0.2-h32643e2_16_cpu.conda + sha256: c2b9263cd47b2881658db07f504d230d7ab6f8cc44829ce20004b5be0f13380a + md5: 2e1bbbc3e8028a533da5955bf48e77f1 + depends: + - __osx >=11.0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libarrow-flight 14.0.2 h161034a_16_cpu + - libcxx >=14 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 162629 + timestamp: 1712758912725 - kind: conda name: libarrow-flight-sql version: 14.0.2 @@ -7230,12 +10375,30 @@ packages: - libarrow 14.0.2 h84dd17c_3_cpu - libarrow-flight 14.0.2 h120cb0d_3_cpu - libgcc-ng >=12 - - libprotobuf >=4.24.4,<4.24.5.0a0 + - libprotobuf >=4.24.4,<4.24.5.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 195809 + timestamp: 1706609745191 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: h7624240_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-sql-14.0.2-h7624240_16_cpu.conda + sha256: 5732516365fbae3c4c82fb1dfb1fb0735050581f670d3a2ef2a67578008f0ab7 + md5: ef90e03d685f7f3aa862b91a80e15d02 + depends: + - libarrow 14.0.2 h520d24b_16_cpu + - libarrow-flight 14.0.2 hbf3f4d3_16_cpu + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 - libstdcxx-ng >=12 license: Apache-2.0 - license_family: APACHE - size: 195809 - timestamp: 1706609745191 + size: 183457 + timestamp: 1712756519546 - kind: conda name: libarrow-flight-sql version: 14.0.2 @@ -7255,6 +10418,25 @@ packages: license_family: APACHE size: 153818 timestamp: 1706611190988 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: h9241762_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-sql-14.0.2-h9241762_16_cpu.conda + sha256: c4193b7e1d5a336c8efc1baa01da4936d614e8f360eed6c007e9bd0c76c0b271 + md5: e31db1ac943508d6ab5ee9851d832d7b + depends: + - libarrow 14.0.2 he70291f_16_cpu + - libarrow-flight 14.0.2 hd42f311_16_cpu + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 195687 + timestamp: 1712756195998 - kind: conda name: libarrow-flight-sql version: 14.0.2 @@ -7274,6 +10456,24 @@ packages: license_family: APACHE size: 182885 timestamp: 1710293099163 +- kind: conda + name: libarrow-flight-sql + version: 14.0.2 + build: hd7485ff_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-hd7485ff_16_cpu.conda + sha256: 5c919f4ecb30c4687c3fd3dc4de4bb0fad235d1ed6db28e2c01aed9dc93a56a5 + md5: 47c4dca34b774f228c37d50d1842497a + depends: + - __osx >=10.13 + - libarrow 14.0.2 hf13115f_16_cpu + - libarrow-flight 14.0.2 hcd10e87_16_cpu + - libcxx >=14 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + size: 156068 + timestamp: 1712758843218 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -7295,6 +10495,52 @@ packages: license_family: APACHE size: 698984 timestamp: 1706611013722 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: h1359b85_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-h1359b85_16_cpu.conda + sha256: 642d36e43291dc1df22d7e4fbcde504b88837c39c9818af1b8c89526a2b64410 + md5: d633d1af2ed4eec13b5bdbd17c3af585 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 hf13115f_16_cpu + - libcxx >=14 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + license: Apache-2.0 + size: 699454 + timestamp: 1712758521155 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: h1eebba3_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-gandiva-14.0.2-h1eebba3_16_cpu.conda + sha256: f5304d1653d417ea7f2a8f9a64fcb2740621b90781bb5fe06ffd95a664e05194 + md5: 3b8c7702be190432547dfdc966a6b543 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h520d24b_16_cpu + - libgcc-ng >=12 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + license: Apache-2.0 + size: 855549 + timestamp: 1712756461086 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -7366,6 +10612,30 @@ packages: license_family: APACHE size: 688217 timestamp: 1708691367293 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: h4e6a3a4_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-h4e6a3a4_16_cpu.conda + sha256: a4ae102b5f5fd5f8ae1febb710a135ea193a7b547547f6409295e1e8b6b4bdb6 + md5: 53c272d16c048ed38f5ca0136698a7fa + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h45212c0_16_cpu + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + size: 10165793 + timestamp: 1712757600278 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -7391,6 +10661,30 @@ packages: license_family: APACHE size: 10170570 timestamp: 1708690279861 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: ha803c60_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-gandiva-14.0.2-ha803c60_16_cpu.conda + sha256: 4a4c3fb74f08c3c571576a46b043402448f692062889e645087e6fb820ecb961 + md5: d6c4908ca595386164178ddf3fbd8f9e + depends: + - __osx >=11.0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libcxx >=14 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + size: 688419 + timestamp: 1712758588011 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -7413,6 +10707,30 @@ packages: license_family: APACHE size: 895232 timestamp: 1706609674431 +- kind: conda + name: libarrow-gandiva + version: 14.0.2 + build: hd4ab825_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hd4ab825_16_cpu.conda + sha256: dbf3b157ad0ae4aca7434c28fb04b0e09949d148e0a89f7cfacc13dccd1b0614 + md5: c5c3ac312e41717423e45be1d21367bc + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 he70291f_16_cpu + - libgcc-ng >=12 + - libllvm15 >=15.0.7,<15.1.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libutf8proc >=2.8.0,<3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + license: Apache-2.0 + license_family: APACHE + size: 894401 + timestamp: 1712756141884 - kind: conda name: libarrow-gandiva version: 14.0.2 @@ -7537,6 +10855,26 @@ packages: license_family: APACHE size: 509163 timestamp: 1706609767216 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: h7a0fec1_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-14.0.2-h7a0fec1_16_cpu.conda + sha256: 189bcd6d96df8834d3e7a1b31c9d7c7437962e35bfbc10b211a2711488e0fff5 + md5: de6e30968e9d6b464338f9ff22cd92d2 + depends: + - __osx >=11.0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libarrow-acero 14.0.2 h43a2c78_16_cpu + - libarrow-dataset 14.0.2 h43a2c78_16_cpu + - libcxx >=14 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 472492 + timestamp: 1712759048456 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -7576,6 +10914,45 @@ packages: license_family: APACHE size: 452971 timestamp: 1706611246525 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: h9241762_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-14.0.2-h9241762_16_cpu.conda + sha256: fdeac590c716fc10ac611b872860088200a57ca775c2431247c2c2851e27656e + md5: 5922ba88e5a196bae61b5b7c2a917821 + depends: + - libarrow 14.0.2 he70291f_16_cpu + - libarrow-acero 14.0.2 hac33072_16_cpu + - libarrow-dataset 14.0.2 hac33072_16_cpu + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + size: 518899 + timestamp: 1712756213866 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: h9b67ed8_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-substrait-14.0.2-h9b67ed8_16_cpu.conda + sha256: b3875481ea61f2bf1ac95d9d567183c969af83a764ee4d498000e169755524c2 + md5: 1cef1b6de6f02ba53ad9e948430489bd + depends: + - libarrow 14.0.2 h520d24b_16_cpu + - libarrow-acero 14.0.2 h0a1ffab_16_cpu + - libarrow-dataset 14.0.2 h0a1ffab_16_cpu + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + size: 502299 + timestamp: 1712756540657 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -7596,6 +10973,47 @@ packages: license_family: APACHE size: 503549 timestamp: 1710293136119 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: hd7485ff_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-hd7485ff_16_cpu.conda + sha256: c2c58ca8988c2d417bbfc8a57564fe96c0b097776dda5e03b66d08303228afaf + md5: 0e36b94ca24a0d94a55c22fb6b65d105 + depends: + - __osx >=10.13 + - libarrow 14.0.2 hf13115f_16_cpu + - libarrow-acero 14.0.2 hcdcf8f8_16_cpu + - libarrow-dataset 14.0.2 hcdcf8f8_16_cpu + - libcxx >=14 + - libprotobuf >=4.25.3,<4.25.4.0a0 + license: Apache-2.0 + size: 453872 + timestamp: 1712758979673 +- kind: conda + name: libarrow-substrait + version: 14.0.2 + build: hea7f8fd_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-hea7f8fd_16_cpu.conda + sha256: d24acc89eb614cea0619363024a71a0d0cb1906120507f006e5aa471e5f9eb4e + md5: 8072cfedd228428ac4185b900fe369d1 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libarrow 14.0.2 h45212c0_16_cpu + - libarrow-acero 14.0.2 h8681a6d_16_cpu + - libarrow-dataset 14.0.2 h8681a6d_16_cpu + - libprotobuf >=4.25.3,<4.25.4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + size: 360873 + timestamp: 1712757886053 - kind: conda name: libarrow-substrait version: 14.0.2 @@ -7811,6 +11229,110 @@ packages: license_family: BSD size: 5017135 timestamp: 1705980415163 +- kind: conda + name: libblas + version: 3.9.0 + build: 22_linux64_openblas + build_number: 22 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-22_linux64_openblas.conda + sha256: 082b8ac20d43a7bbcdc28b3b1cd40e4df3a8b5daf0a2d23d68953a44d2d12c1b + md5: 1a2a0cd3153464fee6646f3dd6dad9b8 + depends: + - libopenblas >=0.3.27,<0.3.28.0a0 + - libopenblas >=0.3.27,<1.0a0 + constrains: + - libcblas 3.9.0 22_linux64_openblas + - blas * openblas + - liblapacke 3.9.0 22_linux64_openblas + - liblapack 3.9.0 22_linux64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14537 + timestamp: 1712542250081 +- kind: conda + name: libblas + version: 3.9.0 + build: 22_linuxaarch64_openblas + build_number: 22 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.9.0-22_linuxaarch64_openblas.conda + sha256: eb4398566a601e68b21ceab9a905a619b94d4d6c8242fffd9ed57cc26d29e278 + md5: 068ab33f2382cda4dd0b72a715ad33b5 + depends: + - libopenblas >=0.3.27,<0.3.28.0a0 + - libopenblas >=0.3.27,<1.0a0 + constrains: + - blas * openblas + - libcblas 3.9.0 22_linuxaarch64_openblas + - liblapacke 3.9.0 22_linuxaarch64_openblas + - liblapack 3.9.0 22_linuxaarch64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14612 + timestamp: 1712542041279 +- kind: conda + name: libblas + version: 3.9.0 + build: 22_osx64_openblas + build_number: 22 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-22_osx64_openblas.conda + sha256: d72060239f904b3a81d2329efcf84dc62c2dfd66dbc4efc8dcae1afdf8f02b59 + md5: b80966a8c8dd0b531f8e65f709d732e8 + depends: + - libopenblas >=0.3.27,<0.3.28.0a0 + - libopenblas >=0.3.27,<1.0a0 + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - libcblas 3.9.0 22_osx64_openblas + - liblapack 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14749 + timestamp: 1712542279018 +- kind: conda + name: libblas + version: 3.9.0 + build: 22_osxarm64_openblas + build_number: 22 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-22_osxarm64_openblas.conda + sha256: 8620e13366076011cfcc6b2565c7a2d362c5d3f0423f54b9ef9bfc17b1a012a4 + md5: aeaf35355ef0f37c7c1ba35b7b7db55f + depends: + - libopenblas >=0.3.27,<0.3.28.0a0 + - libopenblas >=0.3.27,<1.0a0 + constrains: + - blas * openblas + - liblapack 3.9.0 22_osxarm64_openblas + - liblapacke 3.9.0 22_osxarm64_openblas + - libcblas 3.9.0 22_osxarm64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14824 + timestamp: 1712542396471 +- kind: conda + name: libblas + version: 3.9.0 + build: 22_win64_mkl + build_number: 22 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-22_win64_mkl.conda + sha256: 4faab445cbd9a13736a206b98fde962d0a9fa80dcbd38300951a8b2863e7c35c + md5: 65c56ecdeceffd6c32d3d54db7e02c6e + depends: + - mkl 2024.1.0 h66d3029_692 + constrains: + - liblapacke 3.9.0 22_win64_mkl + - blas * mkl + - libcblas 3.9.0 22_win64_mkl + - liblapack 3.9.0 22_win64_mkl + license: BSD-3-Clause + license_family: BSD + size: 5182602 + timestamp: 1712542984136 - kind: conda name: libbrotlicommon version: 1.1.0 @@ -8223,6 +11745,118 @@ packages: license_family: BSD size: 5017024 timestamp: 1705980469944 +- kind: conda + name: libcblas + version: 3.9.0 + build: 22_linux64_openblas + build_number: 22 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-22_linux64_openblas.conda + sha256: da1b2faa017663c8f5555c1c5518e96ac4cd8e0be2a673c1c9e2cb8507c8fe46 + md5: 4b31699e0ec5de64d5896e580389c9a1 + depends: + - libblas 3.9.0 22_linux64_openblas + constrains: + - liblapack 3.9.0 22_linux64_openblas + - blas * openblas + - liblapacke 3.9.0 22_linux64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14438 + timestamp: 1712542270166 +- kind: conda + name: libcblas + version: 3.9.0 + build: 22_linuxaarch64_openblas + build_number: 22 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-22_linuxaarch64_openblas.conda + sha256: 04e31c5f3a3b345a8fcdfa6f5c75909688a134bf9ee93c367c6e5affca501068 + md5: fbe7fe553f2cc78a0311e009b26f180d + depends: + - libblas 3.9.0 22_linuxaarch64_openblas + constrains: + - blas * openblas + - liblapack 3.9.0 22_linuxaarch64_openblas + - liblapacke 3.9.0 22_linuxaarch64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14514 + timestamp: 1712542053335 +- kind: conda + name: libcblas + version: 3.9.0 + build: 22_osx64_openblas + build_number: 22 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-22_osx64_openblas.conda + sha256: 6a2ba9198e2320c3e22fe3d121310cf8a8ac663e94100c5693b34523fcb3cc04 + md5: b9fef82772330f61b2b0201c72d2c29b + depends: + - libblas 3.9.0 22_osx64_openblas + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - liblapack 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14636 + timestamp: 1712542311437 +- kind: conda + name: libcblas + version: 3.9.0 + build: 22_osxarm64_openblas + build_number: 22 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-22_osxarm64_openblas.conda + sha256: 2c7902985dc77db1d7252b4e838d92a34b1729799ae402988d62d077868f6cca + md5: 37b3682240a69874a22658dedbca37d9 + depends: + - libblas 3.9.0 22_osxarm64_openblas + constrains: + - blas * openblas + - liblapack 3.9.0 22_osxarm64_openblas + - liblapacke 3.9.0 22_osxarm64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14741 + timestamp: 1712542420590 +- kind: conda + name: libcblas + version: 3.9.0 + build: 22_win64_mkl + build_number: 22 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-22_win64_mkl.conda + sha256: 5503273924650330dc03edd1eb01ec4020b9967b5a4cafc377ba20b976d15590 + md5: 336c93ab102846c6131cf68e722a68f1 + depends: + - libblas 3.9.0 22_win64_mkl + constrains: + - liblapacke 3.9.0 22_win64_mkl + - blas * mkl + - liblapack 3.9.0 22_win64_mkl + license: BSD-3-Clause + license_family: BSD + size: 5191513 + timestamp: 1712543043641 +- kind: conda + name: libclang-cpp16 + version: 16.0.6 + build: default_h127d8a8_6 + build_number: 6 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp16-16.0.6-default_h127d8a8_6.conda + sha256: 559c132f09ca826a9d7b1d1654099ee03e05d2188127b9450d3935a5fe4147a5 + md5: d691b1aab9c92b0f7f58d74543414265 + depends: + - libgcc-ng >=12 + - libllvm16 >=16.0.6,<16.1.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 17927619 + timestamp: 1711067862506 - kind: conda name: libclang-cpp16 version: 16.0.6 @@ -8239,6 +11873,22 @@ packages: license_family: Apache size: 12713468 timestamp: 1706894023056 +- kind: conda + name: libclang-cpp16 + version: 16.0.6 + build: default_h7151d67_6 + build_number: 6 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp16-16.0.6-default_h7151d67_6.conda + sha256: 8d77bf8bb12e4dff0bdc0d6dbc9ec674a46470c4e51a1fc8ffec16ed7da3365f + md5: 7eaad118ab797d1427f8745c861d1925 + depends: + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 12714864 + timestamp: 1711067666274 - kind: conda name: libclang-cpp16 version: 16.0.6 @@ -8306,6 +11956,22 @@ packages: license_family: Apache size: 11813500 timestamp: 1706893965706 +- kind: conda + name: libclang-cpp16 + version: 16.0.6 + build: default_he012953_6 + build_number: 6 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp16-16.0.6-default_he012953_6.conda + sha256: 83ebaab5779a592de1b349d29a0f633ec0d7ed2722746c616f89ecf43c7a6675 + md5: 4562ed88b0429ac497603df91cdd4f5c + depends: + - libcxx >=16.0.6 + - libllvm16 >=16.0.6,<16.1.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 11762505 + timestamp: 1711066876125 - kind: conda name: libclang13 version: 17.0.5 @@ -8436,6 +12102,86 @@ packages: license_family: Apache size: 10874336 timestamp: 1710473662256 +- kind: conda + name: libclang13 + version: 18.1.3 + build: default_h0edc4dd_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libclang13-18.1.3-default_h0edc4dd_0.conda + sha256: 78db753270dd46c69b5141ee21401b7576ffb9a93feeffa30772cac0130cc94c + md5: 3d13ec4c6c87d0d1af87ae921220ddee + depends: + - libcxx >=16.0.6 + - libllvm18 >=18.1.3,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 8056521 + timestamp: 1712569388477 +- kind: conda + name: libclang13 + version: 18.1.3 + build: default_h5d6823c_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libclang13-18.1.3-default_h5d6823c_0.conda + sha256: 8490f8ca051e80d0f79279d75dabb93e0cadf046984b96bfaeb4c9d6146857fb + md5: 5fff487759736b275dc3e4a263cac666 + depends: + - libgcc-ng >=12 + - libllvm18 >=18.1.3,<18.2.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 11054286 + timestamp: 1712569057776 +- kind: conda + name: libclang13 + version: 18.1.3 + build: default_h83d0a53_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-18.1.3-default_h83d0a53_0.conda + sha256: 42c79469222ea6aa4762c1d82d61445795c90f983b1e3a0e89c8010f5e7442f0 + md5: 6bf79ee12dcf397bcec1b7ffef3cda4f + depends: + - libcxx >=16.0.6 + - libllvm18 >=18.1.3,<18.2.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 7511967 + timestamp: 1712569840902 +- kind: conda + name: libclang13 + version: 18.1.3 + build: default_hf64faad_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libclang13-18.1.3-default_hf64faad_0.conda + sha256: 7ccb5fefe1ca2c8341e402fa726e5b9cea1939feb87b5335b3c4581589ba86d5 + md5: 9217c37b478ec601af909aafc954a6fc + depends: + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 25293651 + timestamp: 1712568643856 +- kind: conda + name: libclang13 + version: 18.1.3 + build: default_hf9b4efe_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-18.1.3-default_hf9b4efe_0.conda + sha256: df4e70597d29b266a5c6957cac9ed741e62602af8548cb10cf746dc3e0a9b880 + md5: e28b34440fa91b0cf931b00980ba2af2 + depends: + - libgcc-ng >=12 + - libllvm18 >=18.1.3,<18.2.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 10890700 + timestamp: 1712566528476 - kind: conda name: libcrc32c version: 1.1.2 @@ -8606,6 +12352,103 @@ packages: license_family: MIT size: 323619 timestamp: 1701860670113 +- kind: conda + name: libcurl + version: 8.7.1 + build: h2d989ff_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.7.1-h2d989ff_0.conda + sha256: 973ac9368efca712a8fd19fe68524d7d9a3087fd88ad6b7fcdf60c3d2e19a498 + md5: 34b9171710f0d9bf093d55bdc36ff355 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: curl + license_family: MIT + size: 358080 + timestamp: 1711548548174 +- kind: conda + name: libcurl + version: 8.7.1 + build: h4e8248e_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.7.1-h4e8248e_0.conda + sha256: 2e2c716875ee48947e4e7a56823c810b5a3d98013ae44d0b55cdfd337f77d693 + md5: 4e38af63e8603414534bbebdd9885021 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libgcc-ng >=12 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: curl + license_family: MIT + size: 409751 + timestamp: 1711548134067 +- kind: conda + name: libcurl + version: 8.7.1 + build: h726d00d_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.7.1-h726d00d_0.conda + sha256: 06cb1bd3bbaf905213777d6ade190ac4c7fb7a20dfe0cf901c977dbbc6cec265 + md5: fa58e5eaa12006bc3289a71357bef167 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: curl + license_family: MIT + size: 378176 + timestamp: 1711548390530 +- kind: conda + name: libcurl + version: 8.7.1 + build: hca28451_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.7.1-hca28451_0.conda + sha256: 82a75e9a5d9ee5b2f487d850ec5d4edc18a56eb9527608a95a916c40baae3843 + md5: 755c7f876815003337d2c61ff5d047e5 + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libgcc-ng >=12 + - libnghttp2 >=1.58.0,<2.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: curl + license_family: MIT + size: 398293 + timestamp: 1711548114077 +- kind: conda + name: libcurl + version: 8.7.1 + build: hd5e4a3a_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.7.1-hd5e4a3a_0.conda + sha256: 8dd272362e2aeb1d4f49333ff57e07eb4da2bbabce20110a2416df9152ba03e0 + md5: 3396aff340d0903e8814c2852d631e4e + depends: + - krb5 >=1.21.2,<1.22.0a0 + - libssh2 >=1.11.0,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: curl + license_family: MIT + size: 331262 + timestamp: 1711548608132 - kind: conda name: libcxx version: 16.0.6 @@ -8953,6 +12796,64 @@ packages: license_family: MIT size: 72544 timestamp: 1710362309065 +- kind: conda + name: libexpat + version: 2.6.2 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + sha256: 331bb7c7c05025343ebd79f86ae612b9e1e74d2687b8f3179faec234f986ce19 + md5: e7ba12deb7020dd080c6c70e7b6f6a3d + depends: + - libgcc-ng >=12 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 73730 + timestamp: 1710362120304 +- kind: conda + name: libexpat + version: 2.6.2 + build: h63175ca_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + sha256: 79f612f75108f3e16bbdc127d4885bb74729cf66a8702fca0373dad89d40c4b7 + md5: bc592d03f62779511d392c175dcece64 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 139224 + timestamp: 1710362609641 +- kind: conda + name: libexpat + version: 2.6.2 + build: h73e2aa4_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + sha256: a188a77b275d61159a32ab547f7d17892226e7dac4518d2c6ac3ac8fc8dfde92 + md5: 3d1d51c8f716d97c864d12f7af329526 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 69246 + timestamp: 1710362566073 +- kind: conda + name: libexpat + version: 2.6.2 + build: hebf3989_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + sha256: ba7173ac30064ea901a4c9fb5a51846dcc25512ceb565759be7d18cbf3e5415e + md5: e3cde7cfa87f82f7cb13d482d5e0ad09 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + size: 63655 + timestamp: 1710362424980 - kind: conda name: libffi version: 3.4.2 @@ -9508,65 +13409,161 @@ packages: - libabseil * cxx17* - libabseil >=20240116.1,<20240117.0a0 - libcurl >=8.5.0,<9.0a0 - - libcxx >=16 - - libgrpc >=1.61.1,<1.62.0a0 - - libprotobuf >=4.25.2,<4.25.3.0a0 + - libcxx >=16 + - libgrpc >=1.61.1,<1.62.0a0 + - libprotobuf >=4.25.2,<4.25.3.0a0 + - openssl >=3.2.1,<4.0a0 + constrains: + - libgoogle-cloud 2.21.0 *_2 + license: Apache-2.0 + license_family: Apache + size: 839546 + timestamp: 1708639487970 +- kind: conda + name: libgoogle-cloud + version: 2.21.0 + build: h2b62511_2 + build_number: 2 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.21.0-h2b62511_2.conda + sha256: d7ad7f35aa5abdbcd9a3c576a23ed2fc1906b83aaf24acfafb768496a0330f41 + md5: 73c00d021383065be34ed4d7efc2c94c + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgrpc >=1.61.1,<1.62.0a0 + - libprotobuf >=4.25.2,<4.25.3.0a0 + - openssl >=3.2.1,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - libgoogle-cloud 2.21.0 *_2 + license: Apache-2.0 + license_family: Apache + size: 14562 + timestamp: 1708637250255 +- kind: conda + name: libgoogle-cloud + version: 2.21.0 + build: h72bcb37_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.21.0-h72bcb37_2.conda + sha256: 055f17ab4621fbcbe68c0656b4811c1a18d8e564fb10287024c67c8d244e7771 + md5: 14b15b923b9e45038f4193d06ecf5ae1 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgcc-ng >=12 + - libgrpc >=1.61.1,<1.62.0a0 + - libprotobuf >=4.25.2,<4.25.3.0a0 + - libstdcxx-ng >=12 + - openssl >=3.2.1,<4.0a0 + constrains: + - libgoogle-cloud 2.21.0 *_2 + license: Apache-2.0 + license_family: Apache + size: 1209079 + timestamp: 1708638321316 +- kind: conda + name: libgoogle-cloud + version: 2.22.0 + build: h651e89d_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.22.0-h651e89d_1.conda + sha256: 39f2f50202e50e41ee8581c99a0b3023c2c21cab80ba597f8c5be7c8c8c6a059 + md5: 3f2faf53ecb3b51b92b3eee155b50233 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libcxx >=16 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - openssl >=3.2.1,<4.0a0 + constrains: + - libgoogle-cloud 2.22.0 *_1 + license: Apache-2.0 + license_family: Apache + size: 849198 + timestamp: 1709738549021 +- kind: conda + name: libgoogle-cloud + version: 2.22.0 + build: h9be4e54_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.22.0-h9be4e54_1.conda + sha256: b9980209438b22113f4352df2b260bf43b2eb63a7b6325192ec5ae3a562872ed + md5: 4b4e36a91e7dabf7345b82d85767a7c3 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcurl >=8.5.0,<9.0a0 + - libgcc-ng >=12 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 - openssl >=3.2.1,<4.0a0 constrains: - - libgoogle-cloud 2.21.0 *_2 + - libgoogle-cloud 2.22.0 *_1 license: Apache-2.0 license_family: Apache - size: 839546 - timestamp: 1708639487970 + size: 1209816 + timestamp: 1709737846418 - kind: conda name: libgoogle-cloud - version: 2.21.0 - build: h2b62511_2 - build_number: 2 + version: 2.22.0 + build: h9cad5c0_1 + build_number: 1 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.21.0-h2b62511_2.conda - sha256: d7ad7f35aa5abdbcd9a3c576a23ed2fc1906b83aaf24acfafb768496a0330f41 - md5: 73c00d021383065be34ed4d7efc2c94c + url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.22.0-h9cad5c0_1.conda + sha256: f76e892d13e1db405777c968787678d8ba912b7e4eef7f950fcdcca185e06e71 + md5: 63cd44a71f00d4e72844bf0e8be56be4 depends: - libabseil * cxx17* - libabseil >=20240116.1,<20240117.0a0 - libcurl >=8.5.0,<9.0a0 - - libgrpc >=1.61.1,<1.62.0a0 - - libprotobuf >=4.25.2,<4.25.3.0a0 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 - openssl >=3.2.1,<4.0a0 - ucrt >=10.0.20348.0 - vc >=14.2,<15 - vc14_runtime >=14.29.30139 constrains: - - libgoogle-cloud 2.21.0 *_2 + - libgoogle-cloud 2.22.0 *_1 license: Apache-2.0 license_family: Apache - size: 14562 - timestamp: 1708637250255 + size: 14420 + timestamp: 1709737037941 - kind: conda name: libgoogle-cloud - version: 2.21.0 - build: h72bcb37_2 - build_number: 2 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.21.0-h72bcb37_2.conda - sha256: 055f17ab4621fbcbe68c0656b4811c1a18d8e564fb10287024c67c8d244e7771 - md5: 14b15b923b9e45038f4193d06ecf5ae1 + version: 2.22.0 + build: hbebe991_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.22.0-hbebe991_1.conda + sha256: a114b4d46eebede7e514abaf9203ea8c952a6382c5c57d1b989da062e3899bd7 + md5: ec7ea95b08e8cbc39fa16b6eafee36e6 depends: - libabseil * cxx17* - libabseil >=20240116.1,<20240117.0a0 - libcurl >=8.5.0,<9.0a0 - - libgcc-ng >=12 - - libgrpc >=1.61.1,<1.62.0a0 - - libprotobuf >=4.25.2,<4.25.3.0a0 - - libstdcxx-ng >=12 + - libcxx >=16 + - libgrpc >=1.62.0,<1.63.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 - openssl >=3.2.1,<4.0a0 constrains: - - libgoogle-cloud 2.21.0 *_2 + - libgoogle-cloud 2.22.0 *_1 license: Apache-2.0 license_family: Apache - size: 1209079 - timestamp: 1708638321316 + size: 836916 + timestamp: 1709739767863 - kind: conda name: libgoogle-cloud version: 2.22.0 @@ -9678,6 +13675,93 @@ packages: license_family: Apache size: 749865 timestamp: 1708638542903 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: h8a76758_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-2.22.0-h8a76758_1.conda + sha256: e23be5896fd78e0e8b1098aab8803192f0c4a328d3d30a57d20d80194045d793 + md5: a89fb5b36b08efaae128d4933e593315 + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libcxx >=16 + - libgoogle-cloud 2.22.0 hbebe991_1 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + size: 507478 + timestamp: 1709740510222 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: ha67e85c_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.22.0-ha67e85c_1.conda + sha256: e4f351e55fe7c0656cb608eba8690063e3b407d25a855c9d1fd832486d4a1244 + md5: 0c25180c34b1a58d309b28386698fb6e + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libcxx >=16 + - libgoogle-cloud 2.22.0 h651e89d_1 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + size: 523045 + timestamp: 1709739227970 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: hb581fae_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.22.0-hb581fae_1.conda + sha256: 5ee34f168948211db14874f521e6edf9b4032d533c61fd429caaa282be1d0e7b + md5: f63348292dea55cf834e631cf26e2669 + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libgoogle-cloud 2.22.0 h9cad5c0_1 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + size: 14330 + timestamp: 1709737542249 +- kind: conda + name: libgoogle-cloud-storage + version: 2.22.0 + build: hc7a4891_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.22.0-hc7a4891_1.conda + sha256: 0e00e1ca2a981db1c96071edf266bc29fd6f13ac484225de1736fc4dac5c64a8 + md5: 7811f043944e010e54640918ea82cecd + depends: + - libabseil + - libcrc32c >=1.1.2,<1.2.0a0 + - libcurl + - libgcc-ng >=12 + - libgoogle-cloud 2.22.0 h9be4e54_1 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl + license: Apache-2.0 + license_family: Apache + size: 748818 + timestamp: 1709738181078 - kind: conda name: libgoogle-cloud-storage version: 2.22.0 @@ -9883,6 +13967,82 @@ packages: license_family: APACHE size: 4975767 timestamp: 1707807808364 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h15f2491_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.62.1-h15f2491_0.conda + sha256: 1d4ece94dfef73d904dcba0fd9d56098796f5fdc62ea5f9edff60c71be7a3d63 + md5: 564517a8cbd095cff75eb996d33d2b7e + depends: + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 7667664 + timestamp: 1709938059287 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h384b2fc_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.1-h384b2fc_0.conda + sha256: 8c9898d259e2343df52259b599ec342c386679e1c420df603cba6f06078fcdd6 + md5: 2ac05daca7276a4d6ca4465707670380 + depends: + - __osx >=10.13 + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 4432823 + timestamp: 1709938959215 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h5273850_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.62.1-h5273850_0.conda + sha256: 338cb58d1095ee651acd168af9636834b41908f7a94e613088e284dc53d2947c + md5: 99ac2f772591801641ec692fee843796 + depends: + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 15963245 + timestamp: 1709939262816 - kind: conda name: libgrpc version: 1.62.1 @@ -9908,6 +14068,30 @@ packages: license_family: APACHE size: 6820015 timestamp: 1709938779780 +- kind: conda + name: libgrpc + version: 1.62.1 + build: h9c18a4f_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.62.1-h9c18a4f_0.conda + sha256: b8c6b48430d0778e9452df88fa7c07fc7828aac87291372ac42dbe78be4078d5 + md5: 24f15c1a9e111825d39bf77881430107 + depends: + - c-ares >=1.27.0,<2.0a0 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libre2-11 >=2023.9.1,<2024.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - re2 + constrains: + - grpc-cpp =1.62.1 + license: Apache-2.0 + license_family: APACHE + size: 4753906 + timestamp: 1709939281511 - kind: conda name: libhwloc version: 2.9.3 @@ -10191,46 +14375,141 @@ packages: - blas * openblas license: BSD-3-Clause license_family: BSD - size: 14738 - timestamp: 1705979734819 + size: 14738 + timestamp: 1705979734819 +- kind: conda + name: liblapack + version: 3.9.0 + build: 21_osxarm64_openblas + build_number: 21 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-21_osxarm64_openblas.conda + sha256: a917e99f26d205df1ec22d7a9fff0d2f2f3c7ba06ea2be886dc220a8340d5917 + md5: a4510e3913ef552d69ab2080a0048523 + depends: + - libblas 3.9.0 21_osxarm64_openblas + constrains: + - libcblas 3.9.0 21_osxarm64_openblas + - blas * openblas + - liblapacke 3.9.0 21_osxarm64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14829 + timestamp: 1705980215575 +- kind: conda + name: liblapack + version: 3.9.0 + build: 21_win64_mkl + build_number: 21 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-21_win64_mkl.conda + sha256: 3fa7c08dd4edf59cb0907d2e5b74e6be890e0671f845e1bae892d212d118a7e9 + md5: c4740f091cb75987390087934354a621 + depends: + - libblas 3.9.0 21_win64_mkl + constrains: + - blas * mkl + - libcblas 3.9.0 21_win64_mkl + - liblapacke 3.9.0 21_win64_mkl + license: BSD-3-Clause + license_family: BSD + size: 5017043 + timestamp: 1705980523462 +- kind: conda + name: liblapack + version: 3.9.0 + build: 22_linux64_openblas + build_number: 22 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-22_linux64_openblas.conda + sha256: db246341d42f9100d45adeb1a7ba8b1ef5b51ceb9056fd643e98046a3259fde6 + md5: b083767b6c877e24ee597d93b87ab838 + depends: + - libblas 3.9.0 22_linux64_openblas + constrains: + - libcblas 3.9.0 22_linux64_openblas + - blas * openblas + - liblapacke 3.9.0 22_linux64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14471 + timestamp: 1712542277696 +- kind: conda + name: liblapack + version: 3.9.0 + build: 22_linuxaarch64_openblas + build_number: 22 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.9.0-22_linuxaarch64_openblas.conda + sha256: a7cb3fd83fdd6eca14adbe3d0cbba6e6246683d39af783f5c05852ed2a9e16a5 + md5: 8c709d281609792c39b1d5c0241f90f1 + depends: + - libblas 3.9.0 22_linuxaarch64_openblas + constrains: + - blas * openblas + - libcblas 3.9.0 22_linuxaarch64_openblas + - liblapacke 3.9.0 22_linuxaarch64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14451 + timestamp: 1712542059832 +- kind: conda + name: liblapack + version: 3.9.0 + build: 22_osx64_openblas + build_number: 22 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-22_osx64_openblas.conda + sha256: e36744f3e780564d6748b5dd05e15ad6a1af9184cf32ab9d1304c13a6bc3e16b + md5: f21b282ff7ba14df6134a0fe6ab42b1b + depends: + - libblas 3.9.0 22_osx64_openblas + constrains: + - liblapacke 3.9.0 22_osx64_openblas + - blas * openblas + - libcblas 3.9.0 22_osx64_openblas + license: BSD-3-Clause + license_family: BSD + size: 14657 + timestamp: 1712542322711 - kind: conda name: liblapack version: 3.9.0 - build: 21_osxarm64_openblas - build_number: 21 + build: 22_osxarm64_openblas + build_number: 22 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-21_osxarm64_openblas.conda - sha256: a917e99f26d205df1ec22d7a9fff0d2f2f3c7ba06ea2be886dc220a8340d5917 - md5: a4510e3913ef552d69ab2080a0048523 + url: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-22_osxarm64_openblas.conda + sha256: 2b1b24c98d15a6a3ad54cf7c8fef1ddccf84b7c557cde08235aaeffd1ff50ee8 + md5: f2794950bc005e123b2c21f7fa3d7a6e depends: - - libblas 3.9.0 21_osxarm64_openblas + - libblas 3.9.0 22_osxarm64_openblas constrains: - - libcblas 3.9.0 21_osxarm64_openblas - blas * openblas - - liblapacke 3.9.0 21_osxarm64_openblas + - liblapacke 3.9.0 22_osxarm64_openblas + - libcblas 3.9.0 22_osxarm64_openblas license: BSD-3-Clause license_family: BSD - size: 14829 - timestamp: 1705980215575 + size: 14730 + timestamp: 1712542435551 - kind: conda name: liblapack version: 3.9.0 - build: 21_win64_mkl - build_number: 21 + build: 22_win64_mkl + build_number: 22 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-21_win64_mkl.conda - sha256: 3fa7c08dd4edf59cb0907d2e5b74e6be890e0671f845e1bae892d212d118a7e9 - md5: c4740f091cb75987390087934354a621 + url: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-22_win64_mkl.conda + sha256: 8b28b361a13819ed83a67d3bfdde750a13bc8b50b9af26d94fd61616d0f2d703 + md5: c752cc2af9f3d8d7b2fdebb915a33ef7 depends: - - libblas 3.9.0 21_win64_mkl + - libblas 3.9.0 22_win64_mkl constrains: + - liblapacke 3.9.0 22_win64_mkl - blas * mkl - - libcblas 3.9.0 21_win64_mkl - - liblapacke 3.9.0 21_win64_mkl + - libcblas 3.9.0 22_win64_mkl license: BSD-3-Clause license_family: BSD - size: 5017043 - timestamp: 1705980523462 + size: 5182500 + timestamp: 1712543085027 - kind: conda name: libllvm15 version: 15.0.7 @@ -10300,7 +14579,7 @@ packages: depends: - libgcc-ng >=12 - libstdcxx-ng >=12 - - libxml2 >=2.12.1,<3.0.0a0 + - libxml2 >=2.12.1,<2.13.0a0 - libzlib >=1.2.13,<1.3.0a0 - zstd >=1.5.5,<1.6.0a0 license: Apache-2.0 WITH LLVM-exception @@ -10431,7 +14710,7 @@ packages: depends: - libgcc-ng >=12 - libstdcxx-ng >=12 - - libxml2 >=2.12.1,<3.0.0a0 + - libxml2 >=2.12.1,<2.13.0a0 - libzlib >=1.2.13,<1.3.0a0 - zstd >=1.5.5,<1.6.0a0 license: Apache-2.0 WITH LLVM-exception @@ -10617,6 +14896,76 @@ packages: license_family: Apache size: 37702614 timestamp: 1710430191630 +- kind: conda + name: libllvm18 + version: 18.1.3 + build: h2448989_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.3-h2448989_0.conda + sha256: 4f213da12c893451b21db33ab9eb7637378b79da3747e4ba70db482f7310c5ae + md5: 927b6d6e80b2c0d4405a58b61ca248a3 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.6,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 38422113 + timestamp: 1712517638355 +- kind: conda + name: libllvm18 + version: 18.1.3 + build: h30cc82d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.3-h30cc82d_0.conda + sha256: 5a8781ab13b163fd028916d050bb209718b14de85493bb7a4b93ea798998b9fe + md5: fad73e8421bcd0de381d172c2224d3a5 + depends: + - libcxx >=16 + - libxml2 >=2.12.6,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 25782519 + timestamp: 1712517407600 +- kind: conda + name: libllvm18 + version: 18.1.3 + build: hbcf5fad_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.3-hbcf5fad_0.conda + sha256: bc42a9999c8846f50f5b3bb9a2338caeab34f2d7de8202e3fad7f929f38e3287 + md5: f286e87d892273a1ef3059744c833f91 + depends: + - libcxx >=16 + - libxml2 >=2.12.6,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 27580830 + timestamp: 1712517566570 +- kind: conda + name: libllvm18 + version: 18.1.3 + build: hbfe100b_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm18-18.1.3-hbfe100b_0.conda + sha256: b4400ca773fad60cc990496da6093871e125646c9ace40f8230fdd30e2c9eb29 + md5: 1476f32da056d05db6704490603f66ad + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.6,<3.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 37761077 + timestamp: 1712512884265 - kind: conda name: libnghttp2 version: 1.58.0 @@ -10903,6 +15252,78 @@ packages: license_family: BSD size: 4306237 timestamp: 1704951018697 +- kind: conda + name: libopenblas + version: 0.3.27 + build: openmp_h6c19121_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.27-openmp_h6c19121_0.conda + sha256: feb2662444fc98a4842fe54cc70b1f109b2146108e7bac2b3bbad1f219cede90 + md5: 82eba59f4eca26a9fc904d584f8761c0 + depends: + - libgfortran 5.* + - libgfortran5 >=12.3.0 + - llvm-openmp >=16.0.6 + constrains: + - openblas >=0.3.27,<0.3.28.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2925015 + timestamp: 1712364212874 +- kind: conda + name: libopenblas + version: 0.3.27 + build: openmp_hfef2a42_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.27-openmp_hfef2a42_0.conda + sha256: 45519189c0295296268cb7eabeeaa03ef54d780416c9a24be1d2a21db63a7848 + md5: 00237c9c7f2cb6725fe2960680a6e225 + depends: + - libgfortran 5.* + - libgfortran5 >=12.3.0 + - llvm-openmp >=16.0.6 + constrains: + - openblas >=0.3.27,<0.3.28.0a0 + license: BSD-3-Clause + license_family: BSD + size: 6047531 + timestamp: 1712366254156 +- kind: conda + name: libopenblas + version: 0.3.27 + build: pthreads_h413a1c8_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.27-pthreads_h413a1c8_0.conda + sha256: 2ae7559aed0705deb3f716c7b247c74fd1b5e35b64e39834ce8b95f7564d4a3e + md5: a356024784da6dfd4683dc5ecf45b155 + depends: + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + constrains: + - openblas >=0.3.27,<0.3.28.0a0 + license: BSD-3-Clause + license_family: BSD + size: 5598747 + timestamp: 1712364444346 +- kind: conda + name: libopenblas + version: 0.3.27 + build: pthreads_h5a5ec62_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.27-pthreads_h5a5ec62_0.conda + sha256: 8a898c64f769c03217fee45d2df9faaee6c1a24349e21ba3569bc7a2ed8dfd1e + md5: ffecca8f4f31cd50b92c0e6e6bfe4416 + depends: + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + constrains: + - openblas >=0.3.27,<0.3.28.0a0 + license: BSD-3-Clause + license_family: BSD + size: 4300345 + timestamp: 1712492725507 - kind: conda name: libparquet version: 14.0.2 @@ -10977,6 +15398,80 @@ packages: license_family: APACHE size: 929650 timestamp: 1706611072859 +- kind: conda + name: libparquet + version: 14.0.2 + build: h39135fc_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h39135fc_16_cpu.conda + sha256: f99dbd6dac57563d2606964be39f6ace92313aef66af9215cb621b58d214b07e + md5: 6b8852b6ba95a4821fb3196f64aaf791 + depends: + - libarrow 14.0.2 h45212c0_16_cpu + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + size: 783069 + timestamp: 1712757687971 +- kind: conda + name: libparquet + version: 14.0.2 + build: h4aea69c_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h4aea69c_16_cpu.conda + sha256: 621f4fdc8d65178145330096d05f008da2bc621875919b3b0585b074ce0f09b6 + md5: 4afe2d9c5b51b93e6a139916db4676d7 + depends: + - __osx >=10.13 + - libarrow 14.0.2 hf13115f_16_cpu + - libcxx >=14 + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + size: 925452 + timestamp: 1712758644383 +- kind: conda + name: libparquet + version: 14.0.2 + build: h6a7eafb_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libparquet-14.0.2-h6a7eafb_16_cpu.conda + sha256: cf7173defb0b018aede7f93f9edcff4eab6505bb88316d1a5589dc374e870b28 + md5: 04122dc41cd99cb5e198fdeb1ce1f801 + depends: + - libarrow 14.0.2 he70291f_16_cpu + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 1159643 + timestamp: 1712756160703 +- kind: conda + name: libparquet + version: 14.0.2 + build: h70b04f6_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libparquet-14.0.2-h70b04f6_16_cpu.conda + sha256: bcfce2e2fc0a2688a71858d9fd6dba9f9b1bb9e996f92d54fe7dc18f2720e4b3 + md5: 464ff28ba1324693e6dc48a2f25ce587 + depends: + - libarrow 14.0.2 h520d24b_16_cpu + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + size: 1074623 + timestamp: 1712756481269 - kind: conda name: libparquet version: 14.0.2 @@ -11016,6 +15511,25 @@ packages: license_family: APACHE size: 1074395 timestamp: 1710293046583 +- kind: conda + name: libparquet + version: 14.0.2 + build: he0622da_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-14.0.2-he0622da_16_cpu.conda + sha256: 05ddc382b4596501cd839666b2bcbe08afe1cdb3a435c7cbab6214ae51388387 + md5: 87156b3a5a1217fb59fb2a382ae97eaa + depends: + - __osx >=11.0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libcxx >=14 + - libthrift >=0.19.0,<0.19.1.0a0 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: APACHE + size: 909622 + timestamp: 1712758719161 - kind: conda name: libparquet version: 14.0.2 @@ -11189,6 +15703,61 @@ packages: license_family: BSD size: 2163244 timestamp: 1708436969402 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: h08a7969_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.25.3-h08a7969_0.conda + sha256: 70e0eef046033af2e8d21251a785563ad738ed5281c74e21c31c457780845dcd + md5: 6945825cebd2aeb16af4c69d97c32c13 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2811207 + timestamp: 1709514552541 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: h4e4d658_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-h4e4d658_0.conda + sha256: 3f126769fb5820387d436370ad48600e05d038a28689fdf9988b64e1059947a8 + md5: 57b7ee4f1fd8573781cfdabaec4a7782 + depends: + - __osx >=10.13 + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libzlib >=1.2.13,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2216001 + timestamp: 1709514908146 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: h503648d_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.3-h503648d_0.conda + sha256: 5d4c5592be3994657ebf47e52f26b734cc50b0ea9db007d920e2e31762aac216 + md5: 4da7de0ba35777742edf67bf7a1075df + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + size: 5650604 + timestamp: 1709514804631 - kind: conda name: libprotobuf version: 4.25.3 @@ -11207,6 +15776,23 @@ packages: license_family: BSD size: 2576197 timestamp: 1709513627963 +- kind: conda + name: libprotobuf + version: 4.25.3 + build: hbfab5d5_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-4.25.3-hbfab5d5_0.conda + sha256: d754519abc3ddbdedab2a38d0639170f5347c1573eef80c707f3a8dc5dff706a + md5: 5f70b2b945a9741cba7e6dfe735a02a7 + depends: + - libabseil * cxx17* + - libabseil >=20240116.1,<20240117.0a0 + - libcxx >=16 + - libzlib >=1.2.13,<1.3.0a0 + license: BSD-3-Clause + license_family: BSD + size: 2154402 + timestamp: 1709514097574 - kind: conda name: libre2-11 version: 2023.06.02 @@ -11444,26 +16030,81 @@ packages: sha256: e1010f4ac7b056d85d91e6cb6137ef118f920eba88059261689e543780b230df md5: c583c1d6999b7aa148eff3089e13c44b depends: - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Unlicense + size: 870045 + timestamp: 1707495642340 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h091b4b1_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + sha256: 7c234320a1a2132b9cc972aaa06bb215bb220a5b1addb0bed7a5a321c805920e + md5: 9d07427ee5bd9afd1e11ce14368a48d6 + depends: + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 825300 + timestamp: 1710255078823 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h194ca79_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda + sha256: 0ce6de6369c04386cfc8696b1f795f425843789609ae2e04e7a1eb7deae62a8b + md5: bf4c96a21fbfc6a6ef6a7781a534a4e0 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 1038462 + timestamp: 1710253998432 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h2797004_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + sha256: 8cdbeb7902729e319510a82d7c642402981818702b58812af265ef55d1315473 + md5: 866983a220e27a80cb75e85cb30466a1 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + license: Unlicense + size: 857489 + timestamp: 1710254744982 +- kind: conda + name: libsqlite + version: 3.45.2 + build: h92b6c6a_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda + sha256: 320ec73a4e3dd377757a2595770b8137ec4583df4d7782472d76377cdbdc4543 + md5: 086f56e13a96a6cfb1bf640505ae6b70 + depends: + - libzlib >=1.2.13,<1.3.0a0 license: Unlicense - size: 870045 - timestamp: 1707495642340 + size: 902355 + timestamp: 1710254991672 - kind: conda name: libsqlite version: 3.45.2 - build: h194ca79_0 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda - sha256: 0ce6de6369c04386cfc8696b1f795f425843789609ae2e04e7a1eb7deae62a8b - md5: bf4c96a21fbfc6a6ef6a7781a534a4e0 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda + sha256: 4bb24b986550275a6d02835150d943c4c675808d05c0efc5c2a22154d007a69f + md5: f95359f8dc5abf7da7776ece9ef10bc5 depends: - - libgcc-ng >=12 - - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 license: Unlicense - size: 1038462 - timestamp: 1710253998432 + size: 869606 + timestamp: 1710255095740 - kind: conda name: libssh2 version: 1.11.0 @@ -11872,6 +16513,46 @@ packages: license_family: MIT size: 893348 timestamp: 1693539405436 +- kind: conda + name: libuv + version: 1.47.0 + build: h67532ce_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.47.0-h67532ce_0.conda + sha256: a452b8fbb906e72d6c633ed133413f6a604471597f4c80dc73b4e81d2ef56b32 + md5: c2c8307836ecebc2799400a4eca27b37 + license: MIT + license_family: MIT + size: 404907 + timestamp: 1707450430194 +- kind: conda + name: libuv + version: 1.47.0 + build: h93a5062_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.47.0-h93a5062_0.conda + sha256: 802da3ad57041480f15fe0581d6fcd421d9cdae17d796d2b126b0a12aa2d3d44 + md5: b586a09ba87849e37634cbaf9ea0e60f + license: MIT + license_family: MIT + size: 404350 + timestamp: 1707450365805 +- kind: conda + name: libuv + version: 1.48.0 + build: hcfcfb64_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda + sha256: 6151c51857c2407139ce22fdc956022353e675b2bc96991a9201d51cceaa90b4 + md5: 485e49e1d500d996844df14cabf64d73 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + size: 289753 + timestamp: 1709913743184 - kind: conda name: libxcrypt version: 4.4.36 @@ -12049,6 +16730,99 @@ packages: license_family: MIT size: 1567894 timestamp: 1707084720091 +- kind: conda + name: libxml2 + version: 2.12.6 + build: h0d0cfa8_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_1.conda + sha256: f18775ca8494ead5451d4acfc53fa7ebf7a8b5ed04c43bcc50fab847c9780cb3 + md5: c08526c957192192e1e7b4f622761144 + depends: + - icu >=73.2,<74.0a0 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 588539 + timestamp: 1711318256840 +- kind: conda + name: libxml2 + version: 2.12.6 + build: h232c23b_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_1.conda + sha256: c0bd693bb1a7e5aba388a0c79be16ff92e2411e03aaa920f94b4b33bf099e254 + md5: 6853448e9ca1cfd5f15382afd2a6d123 + depends: + - icu >=73.2,<74.0a0 + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 705994 + timestamp: 1711318087106 +- kind: conda + name: libxml2 + version: 2.12.6 + build: h3091e33_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.6-h3091e33_1.conda + sha256: 109031dbe6ff873fb5e5617b27e774d8e465a4e82aa9a2967b18d4afacb4314d + md5: d39c279ae11d5574ec893dd3c173328e + depends: + - icu >=73.2,<74.0a0 + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 750797 + timestamp: 1711318216186 +- kind: conda + name: libxml2 + version: 2.12.6 + build: hc0ae0f7_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_1.conda + sha256: 07a5dc7316d4c1ff3d924df6a76e6a13380d702fa5b3b1889e56d0672e5b8201 + md5: bd85e0ca9e1ffaadc3b56079fd956035 + depends: + - icu >=73.2,<74.0a0 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + size: 620164 + timestamp: 1711318305209 +- kind: conda + name: libxml2 + version: 2.12.6 + build: hc3477c8_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_1.conda + sha256: 1846c1318a5987e7315ca3648b55b38e5cfd9853370803a0f5159bc0071609c1 + md5: eb9f59dd51f50f5aa369813fa63ba569 + depends: + - libiconv >=1.17,<2.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + size: 1640801 + timestamp: 1711318467301 - kind: conda name: libzlib version: 1.2.13 @@ -12192,6 +16966,34 @@ packages: license_family: APACHE size: 274631 timestamp: 1701222947083 +- kind: conda + name: llvm-openmp + version: 18.1.3 + build: hb6ac08f_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda + sha256: 997e4169ea474a7bc137fed3b5f4d94b1175162b3318e8cb3943003e460fe458 + md5: 506f270f4f00980d27cc1fc127e0ed37 + constrains: + - openmp 18.1.3|18.1.3.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 300597 + timestamp: 1712603382363 +- kind: conda + name: llvm-openmp + version: 18.1.3 + build: hcd81f8e_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda + sha256: 4cb4eadd633669496ed70c580c965f5f2ed29336890636c61a53e9c1c1541073 + md5: 24cbf1fb1b83056f8ba1beaac0619bf8 + constrains: + - openmp 18.1.3|18.1.3.* + license: Apache-2.0 WITH LLVM-exception + license_family: APACHE + size: 276320 + timestamp: 1712603367897 - kind: conda name: llvm-tools version: 16.0.6 @@ -12389,6 +17191,53 @@ packages: license: MIT, BSD size: 31928 timestamp: 1608166099896 +- kind: pypi + name: markdown + version: '3.6' + url: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl + sha256: 48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f + requires_dist: + - importlib-metadata >=4.4 ; python_version < '3.10' + - mkdocs >=1.5 ; extra == 'docs' + - mkdocs-nature >=0.6 ; extra == 'docs' + - mdx-gh-links >=0.2 ; extra == 'docs' + - mkdocstrings[python] ; extra == 'docs' + - mkdocs-gen-files ; extra == 'docs' + - mkdocs-section-index ; extra == 'docs' + - mkdocs-literate-nav ; extra == 'docs' + - coverage ; extra == 'testing' + - pyyaml ; extra == 'testing' + requires_python: '>=3.8' +- kind: pypi + name: markupsafe + version: 2.1.5 + url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f + requires_python: '>=3.7' +- kind: pypi + name: markupsafe + version: 2.1.5 + url: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced + requires_python: '>=3.7' +- kind: pypi + name: markupsafe + version: 2.1.5 + url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 + requires_python: '>=3.7' +- kind: pypi + name: markupsafe + version: 2.1.5 + url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 + requires_python: '>=3.7' +- kind: pypi + name: markupsafe + version: 2.1.5 + url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl + sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 + requires_python: '>=3.7' - kind: conda name: maturin version: 1.5.1 @@ -12496,6 +17345,168 @@ packages: license_family: MIT size: 83512382 timestamp: 1702682895721 +- kind: pypi + name: mergedeep + version: 1.3.4 + url: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl + sha256: 70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + requires_python: '>=3.6' +- kind: pypi + name: mike + version: 1.1.2 + url: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl + sha256: 4c307c28769834d78df10f834f57f810f04ca27d248f80a75f49c6fa2d1527ca + requires_dist: + - jinja2 + - mkdocs >=1.0 + - pyyaml >=5.1 + - verspec + - coverage ; extra == 'dev' + - flake8 >=3.0 ; extra == 'dev' + - shtab ; extra == 'dev' + - coverage ; extra == 'test' + - flake8 >=3.0 ; extra == 'test' + - shtab ; extra == 'test' +- kind: pypi + name: mkdocs + version: 1.5.3 + url: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl + sha256: 3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1 + requires_dist: + - click >=7.0 + - colorama >=0.4 ; platform_system == 'Windows' + - ghp-import >=1.0 + - importlib-metadata >=4.3 ; python_version < '3.10' + - jinja2 >=2.11.1 + - markdown >=3.2.1 + - markupsafe >=2.0.1 + - mergedeep >=1.3.4 + - packaging >=20.5 + - pathspec >=0.11.1 + - platformdirs >=2.2.0 + - pyyaml-env-tag >=0.1 + - pyyaml >=5.1 + - typing-extensions >=3.10 ; python_version < '3.8' + - watchdog >=2.0 + - babel >=2.9.0 ; extra == 'i18n' + - babel ==2.9.0 ; extra == 'min-versions' + - click ==7.0 ; extra == 'min-versions' + - colorama ==0.4 ; platform_system == 'Windows' and extra == 'min-versions' + - ghp-import ==1.0 ; extra == 'min-versions' + - importlib-metadata ==4.3 ; python_version < '3.10' and extra == 'min-versions' + - jinja2 ==2.11.1 ; extra == 'min-versions' + - markdown ==3.2.1 ; extra == 'min-versions' + - markupsafe ==2.0.1 ; extra == 'min-versions' + - mergedeep ==1.3.4 ; extra == 'min-versions' + - packaging ==20.5 ; extra == 'min-versions' + - pathspec ==0.11.1 ; extra == 'min-versions' + - platformdirs ==2.2.0 ; extra == 'min-versions' + - pyyaml-env-tag ==0.1 ; extra == 'min-versions' + - pyyaml ==5.1 ; extra == 'min-versions' + - typing-extensions ==3.10 ; python_version < '3.8' and extra == 'min-versions' + - watchdog ==2.0 ; extra == 'min-versions' + requires_python: '>=3.7' +- kind: pypi + name: mkdocs-autorefs + version: 1.0.1 + url: https://files.pythonhosted.org/packages/f6/01/d413c98335ed75d8c211afb91320811366d55fb0ef7f4b01b9ab19630eac/mkdocs_autorefs-1.0.1-py3-none-any.whl + sha256: aacdfae1ab197780fb7a2dac92ad8a3d8f7ca8049a9cbe56a4218cd52e8da570 + requires_dist: + - markdown >=3.3 + - markupsafe >=2.0.1 + - mkdocs >=1.1 + requires_python: '>=3.8' +- kind: pypi + name: mkdocs-gen-files + version: 0.5.0 + url: https://files.pythonhosted.org/packages/e7/0f/1e55b3fd490ad2cecb6e7b31892d27cb9fc4218ec1dab780440ba8579e74/mkdocs_gen_files-0.5.0-py3-none-any.whl + sha256: 7ac060096f3f40bd19039e7277dd3050be9a453c8ac578645844d4d91d7978ea + requires_dist: + - mkdocs >=1.0.3 + requires_python: '>=3.7' +- kind: pypi + name: mkdocs-literate-nav + version: 0.6.1 + url: https://files.pythonhosted.org/packages/51/3b/e00d839d3242844c77e248f9572dd34644a04300839a60fe7d6bf652ab19/mkdocs_literate_nav-0.6.1-py3-none-any.whl + sha256: e70bdc4a07050d32da79c0b697bd88e9a104cf3294282e9cb20eec94c6b0f401 + requires_dist: + - mkdocs >=1.0.3 + requires_python: '>=3.7' +- kind: pypi + name: mkdocs-material + version: 9.4.7 + url: https://files.pythonhosted.org/packages/a6/ca/e72f41f1f94eae8a45de6b247ed90c868b9af107cd3b2182c6c6e944fe06/mkdocs_material-9.4.7-py3-none-any.whl + sha256: 4d698d52bb6a6a3c452ab854481c4cdb68453a0420956a6aee2de55fe15fe610 + requires_dist: + - babel ~=2.10 + - colorama ~=0.4 + - jinja2 ~=3.0 + - markdown ~=3.2 + - mkdocs-material-extensions ~=1.3 + - mkdocs >=1.5.3, ~=1.5 + - paginate ~=0.5 + - pygments ~=2.16 + - pymdown-extensions ~=10.2 + - regex >=2022.4 + - requests ~=2.26 + - mkdocs-git-committers-plugin-2 ~=1.1 ; extra == 'git' + - mkdocs-git-revision-date-localized-plugin ~=1.2 ; extra == 'git' + - cairosvg ~=2.6 ; extra == 'imaging' + - pillow ~=9.4 ; extra == 'imaging' + - mkdocs-minify-plugin ~=0.7 ; extra == 'recommended' + - mkdocs-redirects ~=1.2 ; extra == 'recommended' + - mkdocs-rss-plugin ~=1.6 ; extra == 'recommended' + requires_python: '>=3.8' +- kind: pypi + name: mkdocs-material-extensions + version: '1.3' + url: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl + sha256: 0297cc48ba68a9fdd1ef3780a3b41b534b0d0df1d1181a44676fda5f464eeadc + requires_python: '>=3.8' +- kind: pypi + name: mkdocs-redirects + version: 1.3.1 + url: git+https://github.com/rerun-io/mkdocs-redirects.git@fb6b074554975ba7729d68d04957ce7c7dfd5003 + requires_dist: + - mkdocs >=1.1.1 + - pytest ; extra == 'dev' + - black ; extra == 'dev' + - isort ; extra == 'dev' + - autoflake ; extra == 'dev' + - twine >=1.13.0 ; extra == 'dev' + - twine >=1.13.0 ; extra == 'release' + - pytest ; extra == 'test' + - black ; extra == 'test' + - isort ; extra == 'test' + - autoflake ; extra == 'test' + requires_python: '>=3.6' +- kind: pypi + name: mkdocstrings + version: 0.23.0 + url: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl + sha256: 051fa4014dfcd9ed90254ae91de2dbb4f24e166347dae7be9a997fe16316c65e + requires_dist: + - jinja2 >=2.11.1 + - markdown >=3.3 + - markupsafe >=1.1 + - mkdocs >=1.2 + - mkdocs-autorefs >=0.3.1 + - pymdown-extensions >=6.3 + - importlib-metadata >=4.6 ; python_version < '3.10' + - typing-extensions >=4.1 ; python_version < '3.10' + - mkdocstrings-crystal >=0.3.4 ; extra == 'crystal' + - mkdocstrings-python-legacy >=0.2.1 ; extra == 'python-legacy' + - mkdocstrings-python >=0.5.2 ; extra == 'python' + requires_python: '>=3.8' +- kind: pypi + name: mkdocstrings-python + version: 1.7.3 + url: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl + sha256: 2439d6ad3e34f0bb4c643b845fb3c06ae9233499a1736f9fa273424b75cc5894 + requires_dist: + - mkdocstrings >=0.20 + - griffe >=0.35 + requires_python: '>=3.8' - kind: conda name: mkl version: 2022.1.0 @@ -12530,6 +17541,22 @@ packages: license_family: Proprietary size: 108505947 timestamp: 1701973497498 +- kind: conda + name: mkl + version: 2024.1.0 + build: h66d3029_692 + build_number: 692 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_692.conda + sha256: abfdb5eb3a17af59a827ea49fcb4d2bf18e70b62498bf3720351962e636cb5b7 + md5: b43ec7ed045323edeff31e348eea8652 + depends: + - intel-openmp 2024.* + - tbb 2021.* + license: LicenseRef-ProprietaryIntel + license_family: Proprietary + size: 109491063 + timestamp: 1712153746272 - kind: conda name: msys2-conda-epoch version: '20160418' @@ -12754,6 +17781,54 @@ packages: license: X11 AND BSD-3-Clause size: 828118 timestamp: 1686077056765 +- kind: conda + name: ncurses + version: 6.4.20240210 + build: h0425590_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ncurses-6.4.20240210-h0425590_0.conda + sha256: 4223dc34e2bddd37bf995158ae481e00be375b287d539bc7a0532634c0fc63b7 + md5: c1a1612ddaee95c83abfa0b2ec858626 + depends: + - libgcc-ng >=12 + license: X11 AND BSD-3-Clause + size: 926594 + timestamp: 1710866633409 +- kind: conda + name: ncurses + version: 6.4.20240210 + build: h078ce10_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.4.20240210-h078ce10_0.conda + sha256: 06f0905791575e2cd3aa961493c56e490b3d82ad9eb49f1c332bd338b0216911 + md5: 616ae8691e6608527d0071e6766dcb81 + license: X11 AND BSD-3-Clause + size: 820249 + timestamp: 1710866874348 +- kind: conda + name: ncurses + version: 6.4.20240210 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.4.20240210-h59595ed_0.conda + sha256: aa0f005b6727aac6507317ed490f0904430584fa8ca722657e7f0fb94741de81 + md5: 97da8860a0da5413c7c98a3b3838a645 + depends: + - libgcc-ng >=12 + license: X11 AND BSD-3-Clause + size: 895669 + timestamp: 1710866638986 +- kind: conda + name: ncurses + version: 6.4.20240210 + build: h73e2aa4_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.4.20240210-h73e2aa4_0.conda + sha256: 50b72acf08acbc4e5332807653e2ca6b26d4326e8af16fad1fd3f2ce9ea55503 + md5: 50f28c512e9ad78589e3eab34833f762 + license: X11 AND BSD-3-Clause + size: 823010 + timestamp: 1710866856626 - kind: conda name: ninja version: 1.11.1 @@ -12857,43 +17932,116 @@ packages: build: h57928b3_1 build_number: 1 subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda - sha256: 3121574f788fef2e11269a0e77dff71f4dea586d1d8da5a9c36911afa20c0480 - md5: 83569101477048efb6dd12086ef0ba08 + url: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.18.2-h57928b3_1.conda + sha256: 3121574f788fef2e11269a0e77dff71f4dea586d1d8da5a9c36911afa20c0480 + md5: 83569101477048efb6dd12086ef0ba08 + license: MIT + license_family: MIT + size: 22438481 + timestamp: 1700384983430 +- kind: conda + name: nodejs + version: 18.18.2 + build: h7ed3092_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.18.2-h7ed3092_1.conda + sha256: cc52406588c489c1fcccd37148b714e14ae71205c554064abdf07db06394ca07 + md5: 2e8ae468a6ecaa076bc6acc7d796761e + depends: + - __osx >=10.9 + - icu >=73.2,<74.0a0 + - libcxx >=15.0.7 + - libuv >=1.46.0,<1.47.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.1.4,<4.0a0 + - zlib + license: MIT + license_family: MIT + size: 10718633 + timestamp: 1700399218159 +- kind: conda + name: nodejs + version: 18.18.2 + build: hb753e55_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.18.2-hb753e55_1.conda + sha256: 89a88ef9b8d6d138b64bcd95d7edcee42e4c0012bde0665a8d66f812bf5c13be + md5: d3aceb714a24e2bd2655cc9948d23bc9 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=73.2,<74.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libuv >=1.46.0,<1.47.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.1.4,<4.0a0 + - zlib + license: MIT + license_family: MIT + size: 15614862 + timestamp: 1700389549489 +- kind: conda + name: nodejs + version: 18.19.0 + build: h119ffd7_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.19.0-h119ffd7_0.conda + sha256: 896ca8a8683f7d6c3402364f6d28bd00b9d3cb9acb88c85d2fc9ecefbbf4f7db + md5: 022ff05e89afedc3db2decb77a8af207 + depends: + - icu >=73.2,<74.0a0 + - libcxx >=14 + - libuv >=1.47.0,<1.48.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - openssl >=3.2.1,<4.0a0 + - zlib + constrains: + - __osx >=10.15 + license: MIT + license_family: MIT + size: 11439181 + timestamp: 1707771884027 +- kind: conda + name: nodejs + version: 18.19.0 + build: h57928b3_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.19.0-h57928b3_0.conda + sha256: de01dd21f413e0e230b62082d5ee7f25b19b3c7296e1172c7cef94c9d36b8c38 + md5: 41ce77dc534e5bc71b0fc1687a89dcfd license: MIT license_family: MIT - size: 22438481 - timestamp: 1700384983430 + size: 22479049 + timestamp: 1707403072267 - kind: conda name: nodejs - version: 18.18.2 - build: h7ed3092_1 - build_number: 1 + version: 18.19.0 + build: h5f47a4d_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.18.2-h7ed3092_1.conda - sha256: cc52406588c489c1fcccd37148b714e14ae71205c554064abdf07db06394ca07 - md5: 2e8ae468a6ecaa076bc6acc7d796761e + url: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.19.0-h5f47a4d_0.conda + sha256: 1263d3c8aa9adaf4e11616dc05fb28cfdb761d70f2298959728f847688073240 + md5: 7798b881265f448c752fbae08e221b10 depends: - - __osx >=10.9 - icu >=73.2,<74.0a0 - - libcxx >=15.0.7 - - libuv >=1.46.0,<1.47.0a0 + - libcxx >=14 + - libuv >=1.47.0,<1.48.0a0 - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.1.4,<4.0a0 + - openssl >=3.2.1,<4.0a0 - zlib license: MIT license_family: MIT - size: 10718633 - timestamp: 1700399218159 + size: 10879191 + timestamp: 1707778803050 - kind: conda name: nodejs - version: 18.18.2 - build: hb753e55_1 - build_number: 1 + version: 18.19.0 + build: hb753e55_0 subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.18.2-hb753e55_1.conda - sha256: 89a88ef9b8d6d138b64bcd95d7edcee42e4c0012bde0665a8d66f812bf5c13be - md5: d3aceb714a24e2bd2655cc9948d23bc9 + url: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.19.0-hb753e55_0.conda + sha256: d233fe4da686125c2b89d588349eccc78cdcb5a75a2b5b5bc9dc4d0c8c23eda1 + md5: 0b4a67051e3b3812818ccf2f4ee2fd4e depends: - __glibc >=2.17,<3.0.a0 - icu >=73.2,<74.0a0 @@ -12901,12 +18049,12 @@ packages: - libstdcxx-ng >=12 - libuv >=1.46.0,<1.47.0a0 - libzlib >=1.2.13,<1.3.0a0 - - openssl >=3.1.4,<4.0a0 + - openssl >=3.2.1,<4.0a0 - zlib license: MIT license_family: MIT - size: 15614862 - timestamp: 1700389549489 + size: 15917143 + timestamp: 1707407233064 - kind: conda name: nodejs version: 18.19.0 @@ -13080,6 +18228,23 @@ packages: license_family: Apache size: 2862719 timestamp: 1706635779319 +- kind: conda + name: openssl + version: 3.2.1 + build: h0d3ecfb_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_1.conda + sha256: 519dc941d7ab0ebf31a2878d85c2f444450e7c5f6f41c4d07252c6bb3417b78b + md5: eb580fb888d93d5d550c557323ac5cee + depends: + - ca-certificates + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 2855250 + timestamp: 1710793435903 - kind: conda name: openssl version: 3.2.1 @@ -13097,6 +18262,24 @@ packages: license_family: Apache size: 3382700 timestamp: 1706635800272 +- kind: conda + name: openssl + version: 3.2.1 + build: h31becfc_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_1.conda + sha256: 055a26e99ebc12ae0cf23266a0e62e71b59b8ce8cafb1ebb87e375ef9c758d7b + md5: e95eb18d256edc72058e0dc9be5338a0 + depends: + - ca-certificates + - libgcc-ng >=12 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 3380844 + timestamp: 1710793424665 - kind: conda name: openssl version: 3.2.1 @@ -13116,6 +18299,26 @@ packages: license_family: Apache size: 8229619 timestamp: 1706638014697 +- kind: conda + name: openssl + version: 3.2.1 + build: hcfcfb64_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_1.conda + sha256: 61ce4e11c3c26ed4e4d9b7e7e2483121a1741ad0f9c8db0a91a28b6e05182ce6 + md5: 958e0418e93e50c575bff70fbcaa12d8 + depends: + - ca-certificates + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 8230112 + timestamp: 1710796158475 - kind: conda name: openssl version: 3.2.1 @@ -13133,6 +18336,24 @@ packages: license_family: Apache size: 2863069 timestamp: 1706635653339 +- kind: conda + name: openssl + version: 3.2.1 + build: hd590300_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda + sha256: 2c689444ed19a603be457284cf2115ee728a3fafb7527326e96054dee7cdc1a7 + md5: 9d731343cff6ee2e5a25c4a091bf8e2a + depends: + - ca-certificates + - libgcc-ng >=12 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 2865379 + timestamp: 1710793235846 - kind: conda name: openssl version: 3.2.1 @@ -13149,6 +18370,23 @@ packages: license_family: Apache size: 2509168 timestamp: 1706636810736 +- kind: conda + name: openssl + version: 3.2.1 + build: hd75f5a5_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_1.conda + sha256: 7ae0ac6a1673584a8a380c2ff3d46eca48ed53bc7174c0d4eaa0dd2f247a0984 + md5: 570a6f04802df580be529f3a72d2bbf7 + depends: + - ca-certificates + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + size: 2506344 + timestamp: 1710793930515 - kind: conda name: orc version: 1.9.2 @@ -13300,6 +18538,48 @@ packages: license_family: Apache size: 423917 timestamp: 1700373043647 +- kind: conda + name: orc + version: 2.0.0 + build: h17fec99_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/orc-2.0.0-h17fec99_1.conda + sha256: ccbfb6c2a01259c2c95b5b8139a0c3a8d4ec6240228ad1ac454b41f5fbcfd082 + md5: d2e0ffa6c3452f0a723a0ef1b96fd1cb + depends: + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.2.0,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 1029252 + timestamp: 1712616110941 +- kind: conda + name: orc + version: 2.0.0 + build: h4aad248_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.0.0-h4aad248_1.conda + sha256: 1706ed2e71929f5a2bba0e1041c7ecb064031e7b4ab5862777682c8bdc970bd6 + md5: b89ff040a46c45fba6687243e09b8509 + depends: + - __osx >=11.0 + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.2.0,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 414513 + timestamp: 1712616646377 - kind: conda name: orc version: 2.0.0 @@ -13320,6 +18600,72 @@ packages: license_family: Apache size: 999580 timestamp: 1710232876736 +- kind: conda + name: orc + version: 2.0.0 + build: h7e885a9_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/orc-2.0.0-h7e885a9_1.conda + sha256: eb8ba5b2c500b990dc75f468dffaf4ba5eca53a8c021b38900247df988d14e4b + md5: f61ae80fe162b09c627473932d5dc8c3 + depends: + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.2.0,<1.3.0a0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc >=14.3,<15 + - vc14_runtime >=14.29.30139 + - vc14_runtime >=14.38.33130 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 925936 + timestamp: 1712616706879 +- kind: conda + name: orc + version: 2.0.0 + build: hd7aaf90_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-hd7aaf90_1.conda + sha256: 27725756b444000f81ef2c2d132d03b1a67e89ab00dec944c89ef072061f9705 + md5: 95d5a76acc60426348cdf900f5b8d1f2 + depends: + - libgcc-ng >=12 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.2.0,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 1002468 + timestamp: 1712616308423 +- kind: conda + name: orc + version: 2.0.0 + build: hf146577_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.0-hf146577_1.conda + sha256: 801367a030bf6eaf10603c575dbaca439283e449e9cd5bb586b600fb591f5221 + md5: 7979dbaf686485e12d48e7ca9fcb5a56 + depends: + - __osx >=10.13 + - libcxx >=16 + - libprotobuf >=4.25.3,<4.25.4.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - lz4-c >=1.9.3,<1.10.0a0 + - snappy >=1.2.0,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 + license_family: Apache + size: 433233 + timestamp: 1712616573866 - kind: conda name: packaging version: '23.2' @@ -13356,6 +18702,11 @@ packages: - pkg:pypi/packaging size: 49832 timestamp: 1710076089469 +- kind: pypi + name: paginate + version: 0.5.6 + url: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz + sha256: 5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d - kind: conda name: patchelf version: 0.17.2 @@ -13371,11 +18722,17 @@ packages: license_family: GPL size: 94048 timestamp: 1673473024463 +- kind: pypi + name: pathspec + version: 0.12.1 + url: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl + sha256: a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 + requires_python: '>=3.8' - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -13398,8 +18755,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -13422,8 +18779,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -13446,8 +18803,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -13470,8 +18827,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -13782,6 +19139,35 @@ packages: - pkg:pypi/py-cpuinfo size: 24947 timestamp: 1666774595872 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h05400ba_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h05400ba_16_cpu.conda + sha256: e7ae2e78a52e7c986fd8260ab9cbb33c483f0997bf24f8c2cdc24c28c49428c7 + md5: 13eea94cd11c751009580c32ce6056cc + depends: + - libarrow 14.0.2 h45212c0_16_cpu + - libarrow-acero 14.0.2 h8681a6d_16_cpu + - libarrow-dataset 14.0.2 h8681a6d_16_cpu + - libarrow-flight 14.0.2 h83a3238_16_cpu + - libarrow-flight-sql 14.0.2 h21569af_16_cpu + - libarrow-gandiva 14.0.2 h4e6a3a4_16_cpu + - libarrow-substrait 14.0.2 hea7f8fd_16_cpu + - libparquet 14.0.2 h39135fc_16_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + size: 3469033 + timestamp: 1712761753340 - kind: conda name: pyarrow version: 14.0.2 @@ -13870,6 +19256,36 @@ packages: license_family: APACHE size: 4511688 timestamp: 1706611416247 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h4c23913_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311h4c23913_16_cpu.conda + sha256: 166d22fcb756ae4b627d6c11a7539bba6513982bea03e1f5101575ac486fdf22 + md5: 72676f83b15af074051028a3d87f2dd7 + depends: + - __osx >=11.0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libarrow-acero 14.0.2 h43a2c78_16_cpu + - libarrow-dataset 14.0.2 h43a2c78_16_cpu + - libarrow-flight 14.0.2 h161034a_16_cpu + - libarrow-flight-sql 14.0.2 h32643e2_16_cpu + - libarrow-gandiva 14.0.2 ha803c60_16_cpu + - libarrow-substrait 14.0.2 h7a0fec1_16_cpu + - libcxx >=14 + - libparquet 14.0.2 he0622da_16_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 4085287 + timestamp: 1712761619928 - kind: conda name: pyarrow version: 14.0.2 @@ -13947,15 +19363,72 @@ packages: - numpy >=1.23.5,<2.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 3465525 + timestamp: 1708693288111 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h78dcc79_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h78dcc79_16_cpu.conda + sha256: b1902c06a4269496fe4e5b1d93167df5de7a63e4cc17148fb363a0769f458036 + md5: d2c07999b8658fa0052c41ffbe85e3a0 + depends: + - libarrow 14.0.2 he70291f_16_cpu + - libarrow-acero 14.0.2 hac33072_16_cpu + - libarrow-dataset 14.0.2 hac33072_16_cpu + - libarrow-flight 14.0.2 hd42f311_16_cpu + - libarrow-flight-sql 14.0.2 h9241762_16_cpu + - libarrow-gandiva 14.0.2 hd4ab825_16_cpu + - libarrow-substrait 14.0.2 h9241762_16_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 h6a7eafb_16_cpu + - libstdcxx-ng >=12 + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + size: 4497078 + timestamp: 1712756648356 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311hb0c4a44_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311hb0c4a44_16_cpu.conda + sha256: fdf91161069ef925975a4706da24185d62b45d702c7e3e954e2c3851ce31eea0 + md5: 63c818d925da4ce74da9ff6e4ebaea94 + depends: + - __osx >=10.13 + - libarrow 14.0.2 hf13115f_16_cpu + - libarrow-acero 14.0.2 hcdcf8f8_16_cpu + - libarrow-dataset 14.0.2 hcdcf8f8_16_cpu + - libarrow-flight 14.0.2 hcd10e87_16_cpu + - libarrow-flight-sql 14.0.2 hd7485ff_16_cpu + - libarrow-gandiva 14.0.2 h1359b85_16_cpu + - libarrow-substrait 14.0.2 hd7485ff_16_cpu + - libcxx >=14 + - libparquet 14.0.2 h4aea69c_16_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 constrains: - apache-arrow-proc =*=cpu license: Apache-2.0 - license_family: APACHE - size: 3465525 - timestamp: 1708693288111 + size: 4011396 + timestamp: 1712760246531 - kind: conda name: pyarrow version: 14.0.2 @@ -14014,6 +19487,54 @@ packages: license_family: APACHE size: 4074654 timestamp: 1706611920192 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311hf60b7a8_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311hf60b7a8_16_cpu.conda + sha256: cfe2988de02922323fea070d1a520a07fc5626db58f908e6f531d763a4802941 + md5: 92eebc9a1f517898d5c1d82ceee0978e + depends: + - libarrow 14.0.2 h520d24b_16_cpu + - libarrow-acero 14.0.2 h0a1ffab_16_cpu + - libarrow-dataset 14.0.2 h0a1ffab_16_cpu + - libarrow-flight 14.0.2 hbf3f4d3_16_cpu + - libarrow-flight-sql 14.0.2 h7624240_16_cpu + - libarrow-gandiva 14.0.2 h1eebba3_16_cpu + - libarrow-substrait 14.0.2 h9b67ed8_16_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 h70b04f6_16_cpu + - libstdcxx-ng >=12 + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + size: 4395299 + timestamp: 1712757143110 +- kind: pypi + name: pygments + version: 2.17.2 + url: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + sha256: b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c + requires_dist: + - importlib-metadata ; python_version < '3.8' and extra == 'plugins' + - colorama >=0.4.6 ; extra == 'windows-terminal' + requires_python: '>=3.7' +- kind: pypi + name: pymdown-extensions + version: 10.7.1 + url: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + sha256: f5cc7000d7ff0d1ce9395d216017fa4df3dde800afb1fb72d1c7d3fd35e710f4 + requires_dist: + - markdown >=3.5 + - pyyaml + - pygments >=2.12 ; extra == 'extra' + requires_python: '>=3.8' - kind: conda name: pytest version: 7.4.2 @@ -14246,6 +19767,14 @@ packages: license: Python-2.0 size: 14623079 timestamp: 1708116925163 +- kind: pypi + name: python-dateutil + version: 2.9.0.post0 + url: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl + sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + requires_dist: + - six >=1.5 + requires_python: '!=3.0.*,!=3.1.*,!=3.2.*,>=2.7' - kind: conda name: python_abi version: '3.11' @@ -14321,6 +19850,44 @@ packages: license_family: BSD size: 6755 timestamp: 1695147711935 +- kind: pypi + name: pyyaml + version: 6.0.1 + url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab + requires_python: '>=3.6' +- kind: pypi + name: pyyaml + version: 6.0.1 + url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d + requires_python: '>=3.6' +- kind: pypi + name: pyyaml + version: 6.0.1 + url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 + requires_python: '>=3.6' +- kind: pypi + name: pyyaml + version: 6.0.1 + url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 + requires_python: '>=3.6' +- kind: pypi + name: pyyaml + version: 6.0.1 + url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl + sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 + requires_python: '>=3.6' +- kind: pypi + name: pyyaml-env-tag + version: '0.1' + url: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl + sha256: af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069 + requires_dist: + - pyyaml + requires_python: '>=3.6' - kind: conda name: rdma-core version: '28.9' @@ -14374,6 +19941,39 @@ packages: license_family: BSD size: 4724921 timestamp: 1706524445013 +- kind: conda + name: rdma-core + version: '51.0' + build: h0425590_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-51.0-h0425590_0.conda + sha256: 62e19f121c1975a159a5ddd160fa482cd58a474710e260671778dc2401b6d42b + md5: eb55f197626b3df10eff0b1bacafd760 + depends: + - libgcc-ng >=12 + - libnl >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + license: Linux-OpenIB + license_family: BSD + size: 4745994 + timestamp: 1711958372271 +- kind: conda + name: rdma-core + version: '51.0' + build: hd3aeb46_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-51.0-hd3aeb46_0.conda + sha256: bcc774b60605b09701cfad41b2d6d9c3f052dd4adfc1f02bf1c929076f48fe30 + md5: 493598e1f28c01e316fda127715593aa + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libnl >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + license: Linux-OpenIB + license_family: BSD + size: 4734659 + timestamp: 1711958296706 - kind: conda name: re2 version: 2023.06.02 @@ -14553,6 +20153,45 @@ packages: license_family: GPL size: 255870 timestamp: 1679532707590 +- kind: pypi + name: referencing + version: 0.34.0 + url: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl + sha256: d53ae300ceddd3169f1ffa9caf2cb7b769e92657e4fafb23d34b93679116dfd4 + requires_dist: + - attrs >=22.2.0 + - rpds-py >=0.7.0 + requires_python: '>=3.8' +- kind: pypi + name: regex + version: 2023.12.25 + url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl + sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 + requires_python: '>=3.7' +- kind: pypi + name: regex + version: 2023.12.25 + url: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb + requires_python: '>=3.7' +- kind: pypi + name: regex + version: 2023.12.25 + url: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa + requires_python: '>=3.7' +- kind: pypi + name: regex + version: 2023.12.25 + url: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl + sha256: d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97 + requires_python: '>=3.7' +- kind: pypi + name: regex + version: 2023.12.25 + url: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl + sha256: 7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f + requires_python: '>=3.7' - kind: pypi name: requests version: 2.31.0 @@ -14618,6 +20257,36 @@ packages: license_family: MIT size: 185144 timestamp: 1693455923632 +- kind: pypi + name: rpds-py + version: 0.18.0 + url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 + requires_python: '>=3.8' +- kind: pypi + name: rpds-py + version: 0.18.0 + url: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 + requires_python: '>=3.8' +- kind: pypi + name: rpds-py + version: 0.18.0 + url: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5 + requires_python: '>=3.8' +- kind: pypi + name: rpds-py + version: 0.18.0 + url: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4 + requires_python: '>=3.8' +- kind: pypi + name: rpds-py + version: 0.18.0 + url: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl + sha256: 998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa + requires_python: '>=3.8' - kind: conda name: ruff version: 0.3.5 @@ -14765,6 +20434,36 @@ packages: license_family: Apache size: 333810 timestamp: 1708664562153 +- kind: conda + name: s2n + version: 1.4.9 + build: h06160fa_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.9-h06160fa_0.conda + sha256: b362a2663a64806ddfa65672647526e0c08a24dc8ecc9365e85d6f971378e2c7 + md5: ffc686f7f4b7eb48910602b8e147250e + depends: + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 341275 + timestamp: 1712101692146 +- kind: conda + name: s2n + version: 1.4.9 + build: h5a25046_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.9-h5a25046_0.conda + sha256: f40732795f2bf2a7a5388ee723b63ab88fdcb26e8506e7214adcffa3106bbf3c + md5: c4e90602214e63865064f4ab1942a24a + depends: + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + license: Apache-2.0 + license_family: Apache + size: 339709 + timestamp: 1712101772538 - kind: conda name: semver version: 2.13.0 @@ -14865,6 +20564,12 @@ packages: license_family: MIT size: 213817 timestamp: 1643442169866 +- kind: pypi + name: six + version: 1.16.0 + url: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl + sha256: 8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*' - kind: conda name: smmap version: 5.0.0 @@ -14958,6 +20663,95 @@ packages: license_family: BSD size: 57065 timestamp: 1678534804734 +- kind: conda + name: snappy + version: 1.2.0 + build: h6dc393e_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.0-h6dc393e_1.conda + sha256: dc2abe5f45859263c36d287d0d6212e83a3552ef19faf98194d32e70d755d648 + md5: 9c322ec36340610fcf213b72999b049e + depends: + - libcxx >=16 + license: BSD-3-Clause + license_family: BSD + size: 36881 + timestamp: 1712591355487 +- kind: conda + name: snappy + version: 1.2.0 + build: h8d0c38d_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.2.0-h8d0c38d_1.conda + sha256: d02c479500a72d0d79891dac6ae0f564f7c5cd8aad7c2c7168cb48f0a1aee14a + md5: 7875fcea9277713d1744d188ececb767 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: BSD-3-Clause + license_family: BSD + size: 43307 + timestamp: 1712591095967 +- kind: conda + name: snappy + version: 1.2.0 + build: hd04f947_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.0-hd04f947_1.conda + sha256: 88afe00f550e1e2d66326516e5372aa1834c51fb6b53afa7a3636c65cd75ce42 + md5: 32cf833d440ee18d3c4c04ec38cf2b01 + depends: + - libcxx >=16 + license: BSD-3-Clause + license_family: BSD + size: 35655 + timestamp: 1712591484831 +- kind: conda + name: snappy + version: 1.2.0 + build: hdb0a2a9_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.0-hdb0a2a9_1.conda + sha256: bb87116b8c6198f6979b3d212e9af12e08e12f2bf09970d0f9b4582607648b22 + md5: 843bbb8ace1d64ac50d64639ff38b014 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: BSD-3-Clause + license_family: BSD + size: 42334 + timestamp: 1712591084054 +- kind: conda + name: snappy + version: 1.2.0 + build: hfb803bf_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/snappy-1.2.0-hfb803bf_1.conda + sha256: de02a222071d6a832ad3b790c8c977725161ad430ec694fd7b35769b6e1104b4 + md5: a419bf04a7c76a46639e315ac1b8bf72 + depends: + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + size: 59510 + timestamp: 1712591680669 +- kind: pypi + name: sphobjinv + version: 2.3.1 + url: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + sha256: f3efe68bb0ba6e32cb50df064fe6349b8f94681589b400dea753a2860dd576b5 + requires_dist: + - attrs >=19.2 + - certifi + - jsonschema >=3.0 + requires_python: '>=3.6' - kind: conda name: sysroot_linux-64 version: '2.12' @@ -15370,6 +21164,23 @@ packages: - pkg:pypi/typing-extensions size: 37018 timestamp: 1708904796013 +- kind: conda + name: typing_extensions + version: 4.11.0 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + sha256: a7e8714d14f854058e971a6ed44f18cc37cc685f98ddefb2e6b7899a0cc4d1a2 + md5: 6ef2fc37559256cf682d8b3375e89b80 + depends: + - python >=3.8 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions + size: 37583 + timestamp: 1712330089194 - kind: conda name: typos version: 1.16.20 @@ -15502,6 +21313,77 @@ packages: license_family: MIT size: 3607084 timestamp: 1709332306391 +- kind: conda + name: typos + version: 1.20.7 + build: h11a7dfb_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/typos-1.20.7-h11a7dfb_0.conda + sha256: a4de400c80172ce7f100cd3d8fe19943e7dd4c0fa75f6e9a50dbd186a66e73aa + md5: 9b2115e71e00296f11689ecf0df9224a + constrains: + - __osx >=10.12 + license: MIT + license_family: MIT + size: 3342096 + timestamp: 1712710826635 +- kind: conda + name: typos + version: 1.20.7 + build: h1d8f897_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.20.7-h1d8f897_0.conda + sha256: 836ae2a2266f02ebd5edd157079c5b2d08a28c4e370669beb1fe3c5ecaa5a0c6 + md5: e7f3bbd5dd6548dbc1be5d34ed61144b + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 3616005 + timestamp: 1712710058497 +- kind: conda + name: typos + version: 1.20.7 + build: h5ef7bb8_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.20.7-h5ef7bb8_0.conda + sha256: c1f1516d2e335337851ac7b546e004f799a42e14b583e0f5e13592a2cd781004 + md5: 8d515ea542d427bf30b2a39e9f1ad288 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 3342866 + timestamp: 1712710918246 +- kind: conda + name: typos + version: 1.20.7 + build: h7f3b576_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/typos-1.20.7-h7f3b576_0.conda + sha256: 38b16d4c1828b4beab55883788b327947ec301b6f933178d27a15e12bb421aed + md5: eb6d6cffe69958f533801a7e5ac27219 + depends: + - m2w64-gcc-libs + - m2w64-gcc-libs-core + license: MIT + license_family: MIT + size: 2592225 + timestamp: 1712711322837 +- kind: conda + name: typos + version: 1.20.7 + build: he8a937b_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/typos-1.20.7-he8a937b_0.conda + sha256: 1741094e0fb1dd3a264868c900964afe5a5a6efed0e751e563b8cb98cb57f0a9 + md5: e9d28760759e3771a106fc30bc259591 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 3769604 + timestamp: 1712709868814 - kind: conda name: tzdata version: 2024a @@ -15569,6 +21451,44 @@ packages: license_family: BSD size: 15172395 timestamp: 1705978902381 +- kind: conda + name: ucx + version: 1.15.0 + build: ha691c75_8 + build_number: 8 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-ha691c75_8.conda + sha256: 85b40ac6607c9e4e32bcb13e95da41ff48a10f813df0c1e74ff32412e1f7da35 + md5: 3f9bc6137b240642504a6c9b07a10c25 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - rdma-core >=51.0 + constrains: + - cuda-version >=11.2,<12 + license: BSD-3-Clause + license_family: BSD + size: 6842006 + timestamp: 1712025621683 +- kind: conda + name: ucx + version: 1.15.0 + build: hb4872d8_8 + build_number: 8 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hb4872d8_8.conda + sha256: 6d1a9d9acc71a6ec2b9e47f27c1a0de26897227024e54da4da17721e9c97a5d7 + md5: 1274eb3c2d2a374de8004c1e2d7886b1 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - rdma-core >=51.0 + constrains: + - cuda-version >=11.2,<12 + license: BSD-3-Clause + license_family: BSD + size: 6865940 + timestamp: 1712025533832 - kind: conda name: ucx version: 1.15.0 @@ -15672,6 +21592,17 @@ packages: license_family: Proprietary size: 749868 timestamp: 1702511239004 +- kind: pypi + name: verspec + version: 0.1.0 + url: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl + sha256: 741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31 + requires_dist: + - coverage ; extra == 'test' + - flake8 >=3.7 ; extra == 'test' + - mypy ; extra == 'test' + - pretend ; extra == 'test' + - pytest ; extra == 'test' - kind: pypi name: virtualenv version: 20.25.1 @@ -15763,6 +21694,46 @@ packages: license_family: MIT size: 218421 timestamp: 1682376911339 +- kind: pypi + name: watchdog + version: 4.0.0 + url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b + requires_dist: + - pyyaml >=3.10 ; extra == 'watchmedo' + requires_python: '>=3.8' +- kind: pypi + name: watchdog + version: 4.0.0 + url: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl + sha256: 8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3 + requires_dist: + - pyyaml >=3.10 ; extra == 'watchmedo' + requires_python: '>=3.8' +- kind: pypi + name: watchdog + version: 4.0.0 + url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl + sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269 + requires_dist: + - pyyaml >=3.10 ; extra == 'watchmedo' + requires_python: '>=3.8' +- kind: pypi + name: watchdog + version: 4.0.0 + url: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935 + requires_dist: + - pyyaml >=3.10 ; extra == 'watchmedo' + requires_python: '>=3.8' +- kind: pypi + name: watchdog + version: 4.0.0 + url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl + sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245 + requires_dist: + - pyyaml >=3.10 ; extra == 'watchmedo' + requires_python: '>=3.8' - kind: conda name: wheel version: 0.38.4 diff --git a/pixi.toml b/pixi.toml index c99fa717a9d2..5c2b562aceca 100644 --- a/pixi.toml +++ b/pixi.toml @@ -23,6 +23,7 @@ version = "0.1.0" # [environments] cpp = ["cpp"] +py-docs = ["py-docs"] [tasks] # Note: extra CLI argument after `pixi run TASK` are passed to the task cmd. @@ -151,6 +152,26 @@ download-design-tokens = "curl --fail https://rerun-docs.netlify.app/api/tokens # Update the results of `insta` snapshot regression tests rs-update-insta-tests = "cargo test && cargo insta review" + +[feature.py-docs.tasks] +# Serve python docs locally +py-docs-serve = "mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py" + +[feature.py-docs.pypi-dependencies] +griffe = "==0.39.0" +# forked mkdocs-redirects with https://github.com/rerun-io/mkdocs-redirects/commit/d367a0847928438b66f73508e49852be1190409bmkdocs = "==1.5.3" +mkdocs-redirects = { git = "https://github.com/rerun-io/mkdocs-redirects.git", rev = "fb6b074554975ba7729d68d04957ce7c7dfd5003" } +mkdocs-gen-files = "==0.5.0" +mkdocs-literate-nav = "==0.6.1" +mkdocs-material = "==9.4.7" +mkdocs-material-extensions = "==1.3" +mkdocstrings = "==0.23.0" +mkdocstrings-python = "==1.7.3" +mike = "==1.1.2" +sphobjinv = "==2.3.1" +typing_extensions = "==4.11.0" # uncaptured dep for mkdocstrings (https://github.com/mkdocstrings/mkdocstrings/issues/548) + + [feature.cpp.tasks] # All the cpp-* tasks can be configured with environment variables, e.g.: RERUN_WERROR=ON CXX=clang++ cpp-prepare-release = "cmake -G 'Ninja' -B build/release -S . -DCMAKE_BUILD_TYPE=Release" diff --git a/rerun_py/docs/writing_docs.md b/rerun_py/docs/writing_docs.md index d87e8b11d330..39f5ef45869a 100644 --- a/rerun_py/docs/writing_docs.md +++ b/rerun_py/docs/writing_docs.md @@ -5,21 +5,12 @@ A high-level overview of writing and previewing the Rerun python documentation. ## Getting started with docs ### Dependencies -All of the dependencies for documentation generation are captured in the requirements file: -``` -pip install -r rerun_py/requirements-doc.txt -``` +All necessary dependencies are included in the `py-docs` pixi environment. You can activate it with `pixi shell --env py-docs`. ### Serving the docs locally -The docs can be previewed locally using `mkdocs` - This will watch the contents of the `rerun_py` folder and refresh documentation live as files are changed. -``` -mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py -``` -or -``` -just py-docs-serve +```sh +pixi run py-docs-serve ``` ### How versioned docs are generated and served @@ -32,18 +23,18 @@ contents of the `gh-pages` branch. Every commit that lands to main will generate bleeding edge documentation as HEAD. Behind the scenes, a GitHub action is just running: -``` -mike deploy -F rerun_py/mkdocs.yml HEAD +```sh +pixi run -e py-docs mike deploy -F rerun_py/mkdocs.yml HEAD ``` On release, when GitHub sees a new tag: `X.Y.Z`, the GitHub action will instead deploy with a version tag: -``` -mike deploy -F rerun_py/mkdocs.yml X.Y.Z latest +```sh +pixi run -e py-docs mike deploy -F rerun_py/mkdocs.yml X.Y.Z latest ``` You can also locally preview the publicly hosted site with all versions, using mike: -``` -mike serve -F rerun_py/mkdocs.yml +```sh +pixi run -e py-docs mike serve -F rerun_py/mkdocs.yml ``` though when locally developing docs you are better off using `mkdocs serve` as described above since it will handle hot-reloading for you as you edit. diff --git a/rerun_py/requirements-doc.txt b/rerun_py/requirements-doc.txt deleted file mode 100644 index 5b1377c0024c..000000000000 --- a/rerun_py/requirements-doc.txt +++ /dev/null @@ -1,12 +0,0 @@ -griffe==0.39.0 -mkdocs==1.5.3 -mkdocs-gen-files==0.5.0 -mkdocs-literate-nav==0.6.1 -mkdocs-material==9.4.7 -mkdocs-material-extensions==1.3 -git+https://github.com/rerun-io/mkdocs-redirects.git@v1.3.1 # forked mkdocs-redirects with https://github.com/rerun-io/mkdocs-redirects/commit/d367a0847928438b66f73508e49852be1190409b -mkdocstrings==0.23.0 -mkdocstrings-python==1.7.3 -mike==1.1.2 -sphobjinv==2.3.1 -typing_extensions==4.8.0 # uncaptured dep for mkdocstrings (https://github.com/mkdocstrings/mkdocstrings/issues/548) diff --git a/scripts/ci/requirements.txt b/scripts/ci/requirements.txt index 04034a678d8a..de54cb955f88 100644 --- a/scripts/ci/requirements.txt +++ b/scripts/ci/requirements.txt @@ -1,6 +1,5 @@ -r ../../rerun_py/requirements-build.txt --r ../../rerun_py/requirements-doc.txt -r ../../rerun_py/requirements-lint.txt -r ./requirements-crates.txt diff --git a/scripts/requirements-dev.txt b/scripts/requirements-dev.txt index 3d8840a76ef4..6647272241df 100644 --- a/scripts/requirements-dev.txt +++ b/scripts/requirements-dev.txt @@ -1,7 +1,6 @@ # Pip packages all developers need -r ../rerun_py/requirements-build.txt --r ../rerun_py/requirements-doc.txt -r ../rerun_py/requirements-lint.txt cryptography==38.0.4 # for scripts/upload_image.py From fe326a2a0817d068d9dca8a61e9c0cede15855df Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 11 Apr 2024 12:13:55 +0200 Subject: [PATCH 250/508] Fix remaining just mentions (#5914) ### What Fixes a few remaining usages & mentions of `just`. Adds a `upload-image` command to pixi. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5914) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5914?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5914?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5914) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- ARCHITECTURE.md | 2 +- CHANGELOG.md | 1 - CONTRIBUTING.md | 2 +- docs/snippets/compare_snippet_output.py | 2 +- examples/python/template/README.md | 2 +- examples/rust/template/README.md | 2 +- noxfile.py | 2 +- pixi.lock | 726 ++++++++++++++++-- pixi.toml | 13 +- scripts/requirements-dev.txt | 3 - scripts/run_python_e2e_test.py | 2 +- .../build_screenshot_compare.py | 2 +- scripts/upload_image.py | 8 +- tests/cpp/plot_dashboard_stress/main.cpp | 4 +- tests/python/plot_dashboard_stress/main.py | 4 +- tests/roundtrips.py | 2 +- tests/rust/plot_dashboard_stress/src/main.rs | 4 +- 17 files changed, 692 insertions(+), 89 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 1174d56a85c6..3c2f5a8511bd 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -104,7 +104,7 @@ FigJam document: https://www.figma.com/file/Umob8ztK1HmYKLUMSq8aPb/Crates-org Update instructions: 1) Update the FigJam document 2) Select all -> right-click -> Copy as PNG -3) `just upload --name crates` +3) `pixi run upload-image --name crates` 4) Copy/paste the resulting HTML --> diff --git a/CHANGELOG.md b/CHANGELOG.md index 08accaf6dee2..cf8d3751c554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1847,7 +1847,6 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and - Improve PR template with better comment, and no copilot by default [#1901](https://github.com/rerun-io/rerun/pull/1901) - Optimize `generate_changelog.py` [#1912](https://github.com/rerun-io/rerun/pull/1912) -#### 🤷 Other #### 🤷 Other - Fix videos for GitHub in `CHANGELOG.md` [af7d3b192157f942e35f64d3561a9a8dbcc18bfa](https://github.com/rerun-io/rerun/commit/af7d3b192157f942e35f64d3561a9a8dbcc18bfa) - Don't run 3rd party bench suites on CI [#1787](https://github.com/rerun-io/rerun/pull/1787) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8c5ab569f285..6742ff586f19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -113,7 +113,7 @@ cargo run -p rerun -- --help ## Tools -We use the [`pixi`](https://prefix.dev/) for managing dev-tool versioning, download and task running. See [here](https://github.com/casey/just#installation) for installation instructions. To see available tasks, use `pixi task list`. +We use the [`pixi`](https://prefix.dev/) for managing dev-tool versioning, download and task running. To see available tasks, use `pixi task list`. # TODO(andreas): This doesn't list tasks from the different environments. Asked [here](https://discord.com/channels/1082332781146800168/1227563080934756475/1227563080934756475) if there's a way to do that. We use [cargo cranky](https://github.com/ericseppanen/cargo-cranky) and specify our clippy lints in [`Cranky.toml`](Cranky.toml). Usage: `cargo cranky`. diff --git a/docs/snippets/compare_snippet_output.py b/docs/snippets/compare_snippet_output.py index 87636afe74a8..3e822756be3a 100755 --- a/docs/snippets/compare_snippet_output.py +++ b/docs/snippets/compare_snippet_output.py @@ -68,7 +68,7 @@ def main() -> None: print("----------------------------------------------------------") print("Building rerun-sdk for Python…") start_time = time.time() - run(["just", "py-build", "--quiet"], env=build_env) + run(["pixi", "run", "py-build", "--quiet"], env=build_env) elapsed = time.time() - start_time print(f"rerun-sdk for Python built in {elapsed:.1f} seconds") print("") diff --git a/examples/python/template/README.md b/examples/python/template/README.md index ad0a63f0978e..4dd28f29abc5 100644 --- a/examples/python/template/README.md +++ b/examples/python/template/README.md @@ -11,7 +11,7 @@ Put a short description at the top, like this. diff --git a/examples/rust/template/README.md b/examples/rust/template/README.md index 76f87bda681b..27bd60d1854d 100644 --- a/examples/rust/template/README.md +++ b/examples/rust/template/README.md @@ -11,7 +11,7 @@ Put a short description at the top, like this. diff --git a/noxfile.py b/noxfile.py index 8ad7fc0b8d05..fe396a3a3278 100644 --- a/noxfile.py +++ b/noxfile.py @@ -18,7 +18,7 @@ def tests(session: nox.Session) -> None: """Run the Python test suite.""" session.install("-r", "rerun_py/requirements-build.txt") session.install("./rerun_py") - session.run("just", "py-test", external=True) + session.run("pixi", "run", "py-test", external=True) @nox.session(python=PYTHON_VERSIONS) diff --git a/pixi.lock b/pixi.lock index 66fbe4405f09..ba169b101ea0 100644 --- a/pixi.lock +++ b/pixi.lock @@ -159,16 +159,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl linux-aarch64: @@ -323,16 +339,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-64: @@ -475,16 +507,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-arm64: @@ -627,16 +675,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl win-64: @@ -758,16 +822,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl default: @@ -909,16 +989,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl linux-aarch64: @@ -1054,16 +1150,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-64: @@ -1187,16 +1299,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl osx-arm64: @@ -1320,16 +1448,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl win-64: @@ -1449,16 +1593,32 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl py-docs: @@ -1602,13 +1762,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl @@ -1632,6 +1802,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl @@ -1641,6 +1816,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -1781,13 +1957,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl @@ -1811,6 +1997,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl @@ -1820,6 +2011,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -1949,13 +2141,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl @@ -1979,6 +2181,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl @@ -1988,6 +2195,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -2117,13 +2325,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl @@ -2147,6 +2365,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl @@ -2156,6 +2379,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -2280,13 +2504,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl @@ -2310,6 +2544,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl @@ -2319,6 +2558,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl @@ -6269,6 +6509,12 @@ packages: license: ISC size: 155725 timestamp: 1706844034242 +- kind: pypi + name: cachetools + version: 5.3.3 + url: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + sha256: 0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945 + requires_python: '>=3.7' - kind: conda name: cctools version: 973.0.1 @@ -6355,23 +6601,63 @@ packages: url: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl sha256: dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 requires_python: '>=3.6' +- kind: pypi + name: cffi + version: 1.16.0 + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + requires_dist: + - pycparser + requires_python: '>=3.8' +- kind: pypi + name: cffi + version: 1.16.0 + url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 + requires_dist: + - pycparser + requires_python: '>=3.8' +- kind: pypi + name: cffi + version: 1.16.0 + url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 + requires_dist: + - pycparser + requires_python: '>=3.8' +- kind: pypi + name: cffi + version: 1.16.0 + url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 + requires_dist: + - pycparser + requires_python: '>=3.8' +- kind: pypi + name: cffi + version: 1.16.0 + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + requires_dist: + - pycparser + requires_python: '>=3.8' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer @@ -6382,8 +6668,8 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 requires_python: '>=3.7.0' - kind: conda name: clang @@ -7538,6 +7824,146 @@ packages: license_family: APACHE size: 9829914 timestamp: 1701467293179 +- kind: pypi + name: cryptography + version: 38.0.4 + url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d + requires_dist: + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - black ; extra == 'pep8test' + - flake8 ; extra == 'pep8test' + - flake8-import-order ; extra == 'pep8test' + - pep8-naming ; extra == 'pep8test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-subtests ; extra == 'test' + - pytest-xdist ; extra == 'test' + - pretend ; extra == 'test' + - iso8601 ; extra == 'test' + - pytz ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + requires_python: '>=3.6' +- kind: pypi + name: cryptography + version: 38.0.4 + url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb + requires_dist: + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - black ; extra == 'pep8test' + - flake8 ; extra == 'pep8test' + - flake8-import-order ; extra == 'pep8test' + - pep8-naming ; extra == 'pep8test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-subtests ; extra == 'test' + - pytest-xdist ; extra == 'test' + - pretend ; extra == 'test' + - iso8601 ; extra == 'test' + - pytz ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + requires_python: '>=3.6' +- kind: pypi + name: cryptography + version: 38.0.4 + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 + requires_dist: + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - black ; extra == 'pep8test' + - flake8 ; extra == 'pep8test' + - flake8-import-order ; extra == 'pep8test' + - pep8-naming ; extra == 'pep8test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-subtests ; extra == 'test' + - pytest-xdist ; extra == 'test' + - pretend ; extra == 'test' + - iso8601 ; extra == 'test' + - pytz ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + requires_python: '>=3.6' +- kind: pypi + name: cryptography + version: 38.0.4 + url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d + requires_dist: + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - black ; extra == 'pep8test' + - flake8 ; extra == 'pep8test' + - flake8-import-order ; extra == 'pep8test' + - pep8-naming ; extra == 'pep8test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-subtests ; extra == 'test' + - pytest-xdist ; extra == 'test' + - pretend ; extra == 'test' + - iso8601 ; extra == 'test' + - pytz ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + requires_python: '>=3.6' +- kind: pypi + name: cryptography + version: 38.0.4 + url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 + requires_dist: + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - black ; extra == 'pep8test' + - flake8 ; extra == 'pep8test' + - flake8-import-order ; extra == 'pep8test' + - pep8-naming ; extra == 'pep8test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-subtests ; extra == 'test' + - pytest-xdist ; extra == 'test' + - pretend ; extra == 'test' + - iso8601 ; extra == 'test' + - pytz ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + requires_python: '>=3.6' - kind: conda name: cxx-compiler version: 1.6.0 @@ -8313,6 +8739,127 @@ packages: license_family: BSD size: 143596 timestamp: 1708260910243 +- kind: pypi + name: google-api-core + version: 2.18.0 + url: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + sha256: 5a63aa102e0049abe85b5b88cb9409234c1f70afcda21ce1e40b285b9629c1d6 + requires_dist: + - googleapis-common-protos <2.0.dev0, >=1.56.2 + - protobuf !=3.20.0, !=3.20.1, !=4.21.0, !=4.21.1, !=4.21.2, !=4.21.3, !=4.21.4, !=4.21.5, <5.0.0.dev0, >=3.19.5 + - proto-plus <2.0.0.dev0, >=1.22.3 + - google-auth <3.0.dev0, >=2.14.1 + - requests <3.0.0.dev0, >=2.18.0 + - grpcio <2.0.dev0, >=1.33.2 ; extra == 'grpc' + - grpcio-status <2.0.dev0, >=1.33.2 ; extra == 'grpc' + - grpcio <2.0.dev0, >=1.49.1 ; python_version >= '3.11' and extra == 'grpc' + - grpcio-status <2.0.dev0, >=1.49.1 ; python_version >= '3.11' and extra == 'grpc' + - grpcio-gcp <1.0.dev0, >=0.2.2 ; extra == 'grpcgcp' + - grpcio-gcp <1.0.dev0, >=0.2.2 ; extra == 'grpcio-gcp' + requires_python: '>=3.7' +- kind: pypi + name: google-auth + version: 2.29.0 + url: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + sha256: d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415 + requires_dist: + - cachetools <6.0, >=2.0.0 + - pyasn1-modules >=0.2.1 + - rsa <5, >=3.1.4 + - aiohttp <4.0.0.dev0, >=3.6.2 ; extra == 'aiohttp' + - requests <3.0.0.dev0, >=2.20.0 ; extra == 'aiohttp' + - cryptography ==36.0.2 ; extra == 'enterprise_cert' + - pyopenssl ==22.0.0 ; extra == 'enterprise_cert' + - pyopenssl >=20.0.0 ; extra == 'pyopenssl' + - cryptography >=38.0.3 ; extra == 'pyopenssl' + - pyu2f >=0.1.5 ; extra == 'reauth' + - requests <3.0.0.dev0, >=2.20.0 ; extra == 'requests' + requires_python: '>=3.7' +- kind: pypi + name: google-cloud-core + version: 2.4.1 + url: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + sha256: a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61 + requires_dist: + - google-api-core !=2.0.*, !=2.1.*, !=2.2.*, !=2.3.0, <3.0.0.dev0, >=1.31.6 + - google-auth <3.0.dev0, >=1.25.0 + - importlib-metadata >1.0.0 ; python_version < '3.8' + - grpcio <2.0.dev0, >=1.38.0 ; extra == 'grpc' + - grpcio-status <2.0.dev0, >=1.38.0 ; extra == 'grpc' + requires_python: '>=3.7' +- kind: pypi + name: google-cloud-storage + version: 2.9.0 + url: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + sha256: 83a90447f23d5edd045e0037982c270302e3aeb45fc1288d2c2ca713d27bad94 + requires_dist: + - google-auth <3.0.dev0, >=1.25.0 + - google-api-core !=2.0.*, !=2.1.*, !=2.2.*, !=2.3.0, <3.0.0.dev0, >=1.31.5 + - google-cloud-core <3.0.dev0, >=2.3.0 + - google-resumable-media >=2.3.2 + - requests <3.0.0.dev0, >=2.18.0 + - protobuf <5.0.0.dev0 ; extra == 'protobuf' + requires_python: '>=3.7' +- kind: pypi + name: google-crc32c + version: 1.5.0 + url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 + requires_dist: + - pytest ; extra == 'testing' + requires_python: '>=3.7' +- kind: pypi + name: google-crc32c + version: 1.5.0 + url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 + requires_dist: + - pytest ; extra == 'testing' + requires_python: '>=3.7' +- kind: pypi + name: google-crc32c + version: 1.5.0 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + requires_dist: + - pytest ; extra == 'testing' + requires_python: '>=3.7' +- kind: pypi + name: google-crc32c + version: 1.5.0 + url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 + requires_dist: + - pytest ; extra == 'testing' + requires_python: '>=3.7' +- kind: pypi + name: google-crc32c + version: 1.5.0 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + requires_dist: + - pytest ; extra == 'testing' + requires_python: '>=3.7' +- kind: pypi + name: google-resumable-media + version: 2.7.0 + url: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + sha256: 79543cfe433b63fd81c0844b7803aba1bb8950b47bedf7d980c38fa123937e08 + requires_dist: + - google-crc32c <2.0.dev0, >=1.0 + - aiohttp <4.0.0.dev0, >=3.6.2 ; extra == 'aiohttp' + - google-auth <2.0.dev0, >=1.22.0 ; extra == 'aiohttp' + - requests <3.0.0.dev0, >=2.18.0 ; extra == 'requests' + requires_python: '>=3.7' +- kind: pypi + name: googleapis-common-protos + version: 1.63.0 + url: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + sha256: ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632 + requires_dist: + - protobuf !=3.20.0, !=3.20.1, !=4.21.1, !=4.21.2, !=4.21.3, !=4.21.4, !=4.21.5, <5.0.0.dev0, >=3.19.5 + - grpcio <2.0.0.dev0, >=1.44.0 ; extra == 'grpc' + requires_python: '>=3.7' - kind: pypi name: griffe version: 0.39.0 @@ -8477,12 +9024,6 @@ packages: license_family: MIT size: 11787527 timestamp: 1692901622519 -- kind: pypi - name: idna - version: '3.6' - url: https://files.pythonhosted.org/packages/c2/e7/a82b05cf63a603df6e68d59ae6a68bf5064484a0718ea5033660af4b54a9/idna-3.6-py3-none-any.whl - sha256: c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f - requires_python: '>=3.5' - kind: pypi name: idna version: '3.7' @@ -17211,8 +17752,8 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f + url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl + sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 requires_python: '>=3.7' - kind: pypi name: markupsafe @@ -17223,8 +17764,8 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 + url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f requires_python: '>=3.7' - kind: pypi name: markupsafe @@ -17235,8 +17776,8 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl - sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 + url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 requires_python: '>=3.7' - kind: conda name: maturin @@ -18731,8 +19272,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -18755,8 +19296,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -18779,8 +19320,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -18827,8 +19368,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -19016,6 +19557,39 @@ packages: license_family: MIT size: 1398331 timestamp: 1691677409088 +- kind: pypi + name: proto-plus + version: 1.23.0 + url: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + sha256: a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c + requires_dist: + - protobuf <5.0.0.dev0, >=3.19.0 + - google-api-core[grpc] >=1.31.5 ; extra == 'testing' + requires_python: '>=3.6' +- kind: pypi + name: protobuf + version: 4.25.3 + url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 + requires_python: '>=3.8' +- kind: pypi + name: protobuf + version: 4.25.3 + url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c + requires_python: '>=3.8' +- kind: pypi + name: protobuf + version: 4.25.3 + url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 + requires_python: '>=3.8' +- kind: pypi + name: protobuf + version: 4.25.3 + url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d + requires_python: '>=3.8' - kind: conda name: psutil version: 5.9.8 @@ -19516,6 +20090,26 @@ packages: license: Apache-2.0 size: 4395299 timestamp: 1712757143110 +- kind: pypi + name: pyasn1 + version: 0.6.0 + url: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + sha256: cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473 + requires_python: '>=3.8' +- kind: pypi + name: pyasn1-modules + version: 0.4.0 + url: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + sha256: be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b + requires_dist: + - pyasn1 <0.7.0, >=0.4.6 + requires_python: '>=3.8' +- kind: pypi + name: pycparser + version: '2.22' + url: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + sha256: c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc + requires_python: '>=3.8' - kind: pypi name: pygments version: 2.17.2 @@ -19853,8 +20447,8 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab + url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl + sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 requires_python: '>=3.6' - kind: pypi name: pyyaml @@ -19865,8 +20459,8 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 + url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab requires_python: '>=3.6' - kind: pypi name: pyyaml @@ -19877,8 +20471,8 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl - sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 + url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 requires_python: '>=3.6' - kind: pypi name: pyyaml-env-tag @@ -20165,8 +20759,8 @@ packages: - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl - sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 + url: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl + sha256: 7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f requires_python: '>=3.7' - kind: pypi name: regex @@ -20177,8 +20771,8 @@ packages: - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa + url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl + sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 requires_python: '>=3.7' - kind: pypi name: regex @@ -20189,8 +20783,8 @@ packages: - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl - sha256: 7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f + url: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa requires_python: '>=3.7' - kind: pypi name: requests @@ -20260,8 +20854,8 @@ packages: - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 + url: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl + sha256: 998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa requires_python: '>=3.8' - kind: pypi name: rpds-py @@ -20272,8 +20866,8 @@ packages: - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5 + url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 requires_python: '>=3.8' - kind: pypi name: rpds-py @@ -20284,9 +20878,17 @@ packages: - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl - sha256: 998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa + url: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5 requires_python: '>=3.8' +- kind: pypi + name: rsa + version: '4.9' + url: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + sha256: 90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 + requires_dist: + - pyasn1 >=0.1.3 + requires_python: '>=3.6,<4' - kind: conda name: ruff version: 0.3.5 @@ -21697,8 +22299,8 @@ packages: - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b + url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl + sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' @@ -21713,8 +22315,8 @@ packages: - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl - sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269 + url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' @@ -21729,8 +22331,8 @@ packages: - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl - sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245 + url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl + sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' diff --git a/pixi.toml b/pixi.toml index 5c2b562aceca..771d6fbaec66 100644 --- a/pixi.toml +++ b/pixi.toml @@ -152,6 +152,9 @@ download-design-tokens = "curl --fail https://rerun-docs.netlify.app/api/tokens # Update the results of `insta` snapshot regression tests rs-update-insta-tests = "cargo test && cargo insta review" +# Upload image to gcloud storage. +upload-image = "python scripts/upload_image.py" + [feature.py-docs.tasks] # Serve python docs locally @@ -257,10 +260,12 @@ taplo = "=0.9.1" tomlkit = "0.12.3.*" [pypi-dependencies] -nox = ">=2024.3.2" # the conda-forge package is (wrongly) tagged as platform-specific -Pillow = "==10.0.0" # For `thumbnails.py` -requests = ">=2.31,<3" # For `thumbnails.py` -tomlkit = ">=0.11.8" # For `thumbnails.py` +cryptography = "==38.0.4" # For `upload_image.py` +google-cloud-storage = "==2.9.0" # For `upload_image.py` +nox = ">=2024.3.2" # the conda-forge package is (wrongly) tagged as platform-specific +Pillow = "==10.0.0" # For `thumbnails.py` +requests = ">=2.31,<3" # For `thumbnails.py` & `upload_image.py` +tomlkit = ">=0.11.8" # For `thumbnails.py` [target.linux-64.dependencies] patchelf = ">=0.17" diff --git a/scripts/requirements-dev.txt b/scripts/requirements-dev.txt index 6647272241df..a31dbf2ae238 100644 --- a/scripts/requirements-dev.txt +++ b/scripts/requirements-dev.txt @@ -3,10 +3,7 @@ -r ../rerun_py/requirements-build.txt -r ../rerun_py/requirements-lint.txt -cryptography==38.0.4 # for scripts/upload_image.py -google-cloud-storage==2.9.0 # for scripts/upload_image.py PyGithub==1.58.2 # for scripts/ci/generate_pr_summary.py and scripts/ci/update_pr_body.py -Pillow # for scripts/upload_image.py torch tqdm requests diff --git a/scripts/run_python_e2e_test.py b/scripts/run_python_e2e_test.py index d825f95492b3..6080e1a1a5e8 100755 --- a/scripts/run_python_e2e_test.py +++ b/scripts/run_python_e2e_test.py @@ -37,7 +37,7 @@ def main() -> None: print("----------------------------------------------------------") print("Building rerun-sdk…") start_time = time.time() - subprocess.Popen(["just", "py-build", "--quiet"], env=build_env).wait() + subprocess.Popen(["pixi", "run", "py-build", "--quiet"], env=build_env).wait() elapsed = time.time() - start_time print(f"rerun-sdk built in {elapsed:.1f} seconds") print("") diff --git a/scripts/screenshot_compare/build_screenshot_compare.py b/scripts/screenshot_compare/build_screenshot_compare.py index 5a25c7f5e9c2..9a485efaa81b 100755 --- a/scripts/screenshot_compare/build_screenshot_compare.py +++ b/scripts/screenshot_compare/build_screenshot_compare.py @@ -91,7 +91,7 @@ def copy_static_assets(examples: list[Example]) -> None: def build_python_sdk() -> None: print("Building Python SDK…") - run(["just", "py-build", "--features", "web_viewer"]) + run(["pixi", "run", "py-build", "--features", "web_viewer"]) # ==================================================================================================== diff --git a/scripts/upload_image.py b/scripts/upload_image.py index ec357db78138..001c6d1256a1 100755 --- a/scripts/upload_image.py +++ b/scripts/upload_image.py @@ -31,13 +31,13 @@ or the just command: - just upload --help + pixi run upload-image --help All info/debug output occurs on stderr. If stdout is not a tty (e.g. piping to `pbcopy`), the resulting HTML tag is also printed to stdout. For example, this upload the image from the clipboard and copies the resulting HTML tag back to the clipboard: - just upload --name some_name | pbcopy + pixi run upload-image --name some_name | pbcopy """ from __future__ import annotations @@ -374,7 +374,7 @@ def run(args: argparse.Namespace) -> None: Note: you will get a warning and a confirmation prompt if the aspect ratio is not within ~10% of 16:9. 3. Groom the blueprints and panel visibility to your liking. 4. Take a screenshot using the command palette. -5. Run: just upload --name +5. Run: pixi run upload-image --name 6. Copy the output HTML tag and paste it into the README.md file. Other uses @@ -382,7 +382,7 @@ def run(args: argparse.Namespace) -> None: Download an image, optimize it and create a multi-resolution stack: - just upload --name https://example.com/path/to/image.png + pixi run upload-image --name https://example.com/path/to/image.png """ diff --git a/tests/cpp/plot_dashboard_stress/main.cpp b/tests/cpp/plot_dashboard_stress/main.cpp index 417f0f2f9603..08f19cccde81 100644 --- a/tests/cpp/plot_dashboard_stress/main.cpp +++ b/tests/cpp/plot_dashboard_stress/main.cpp @@ -2,12 +2,12 @@ // // Usage: // ```text -// just cpp-plot-dashboard --help +// pixi run cpp-plot-dashboard --help // ``` // // Example: // ```text -// just cpp-plot-dashboard --num-plots 10 --num-series-per-plot 5 --num-points-per-series 5000 --freq 1000 +// pixi run cpp-plot-dashboard --num-plots 10 --num-series-per-plot 5 --num-points-per-series 5000 --freq 1000 // ``` #include diff --git a/tests/python/plot_dashboard_stress/main.py b/tests/python/plot_dashboard_stress/main.py index 2e0f9f1021af..26f230f7997a 100755 --- a/tests/python/plot_dashboard_stress/main.py +++ b/tests/python/plot_dashboard_stress/main.py @@ -5,13 +5,13 @@ Usage: ----- ``` -just py-plot-dashboard --help +pixi run py-plot-dashboard --help ``` Example: ------- ``` -just py-plot-dashboard --num-plots 10 --num-series-per-plot 5 --num-points-per-series 5000 --freq 1000 +pixi run py-plot-dashboard --num-plots 10 --num-series-per-plot 5 --num-points-per-series 5000 --freq 1000 ``` """ diff --git a/tests/roundtrips.py b/tests/roundtrips.py index fbdfa6c4a41c..66730d0ac01a 100755 --- a/tests/roundtrips.py +++ b/tests/roundtrips.py @@ -63,7 +63,7 @@ def main() -> None: print("----------------------------------------------------------") print("Building rerun-sdk for Python…") start_time = time.time() - run(["just", "py-build", "--quiet"], env=build_env) + run(["pixi", "run", "py-build", "--quiet"], env=build_env) elapsed = time.time() - start_time print(f"rerun-sdk for Python built in {elapsed:.1f} seconds") print("") diff --git a/tests/rust/plot_dashboard_stress/src/main.rs b/tests/rust/plot_dashboard_stress/src/main.rs index 9c800343f29a..dc1b5bfce172 100644 --- a/tests/rust/plot_dashboard_stress/src/main.rs +++ b/tests/rust/plot_dashboard_stress/src/main.rs @@ -2,12 +2,12 @@ //! //! Usage: //! ```text -//! just rs-plot-dashboard --help +//! pixi run rs-plot-dashboard --help //! ``` //! //! Example: //! ```text -//! just rs-plot-dashboard --num-plots 10 --num-series-per-plot 5 --num-points-per-series 5000 --freq 1000 +//! pixi run rs-plot-dashboard --num-plots 10 --num-series-per-plot 5 --num-points-per-series 5000 --freq 1000 //! ``` use rerun::external::re_log; From 53116cf6c493f2ebfc7597e1d76c545d97a3dcd2 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 12:14:11 +0200 Subject: [PATCH 251/508] Improve output of `re_build_web_viewer` (#5913) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What …and catch failure to run wasm-opt Review ignoring whitespace changes ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5913) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5913?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5913?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5913) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- crates/re_build_web_viewer/src/lib.rs | 171 +++++++++++++++----------- 1 file changed, 96 insertions(+), 75 deletions(-) diff --git a/crates/re_build_web_viewer/src/lib.rs b/crates/re_build_web_viewer/src/lib.rs index 589e728b7b8e..ce34f7a9c114 100644 --- a/crates/re_build_web_viewer/src/lib.rs +++ b/crates/re_build_web_viewer/src/lib.rs @@ -2,6 +2,8 @@ //! Build the Rerun web-viewer .wasm and generate the .js bindings for it. +use std::time::Instant; + use anyhow::Context as _; use cargo_metadata::camino::{Utf8Path, Utf8PathBuf}; @@ -61,7 +63,7 @@ pub fn build( ) -> anyhow::Result<()> { std::env::set_current_dir(workspace_root())?; - eprintln!("Building web viewer wasm…"); + eprintln!("Building web viewer…\n"); let crate_name = "re_viewer"; @@ -89,72 +91,81 @@ pub fn build( std::fs::remove_file(wasm_path.clone()).ok(); std::fs::remove_file(js_path).ok(); - // -------------------------------------------------------------------------------- - eprintln!("Compiling rust to wasm in {target_wasm_dir}…"); - - let mut cmd = std::process::Command::new("cargo"); - cmd.args([ - "build", - "--quiet", - "--package", - crate_name, - "--lib", - "--target", - "wasm32-unknown-unknown", - "--target-dir", - target_wasm_dir.as_str(), - "--no-default-features", - "--features=analytics", - ]); - if profile == Profile::Release { - cmd.arg("--release"); - } + { + eprintln!("Compiling Rust to wasm in {target_wasm_dir}…"); + let start_time = Instant::now(); + + let mut cmd = std::process::Command::new("cargo"); + cmd.args([ + "build", + "--quiet", + "--package", + crate_name, + "--lib", + "--target", + "wasm32-unknown-unknown", + "--target-dir", + target_wasm_dir.as_str(), + "--no-default-features", + "--features=analytics", + ]); + if profile == Profile::Release { + cmd.arg("--release"); + } - // This is required to enable the web_sys clipboard API which egui_web uses - // https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html - // https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html - // Furthermore, it's necessary for unstable WebGPU apis to work. - cmd.env("RUSTFLAGS", "--cfg=web_sys_unstable_apis"); - - // When executing this script from a Rust build script, do _not_, under any circumstances, - // allow pre-encoded `RUSTFLAGS` to leak into the current environment. - // These pre-encoded flags are generally generated by Cargo itself when loading its - // configuration from e.g. `$CARGO_HOME/config.toml`; which means they will contain - // values that only make sense for the native target host, not for a wasm build. - cmd.env("CARGO_ENCODED_RUSTFLAGS", "--cfg=web_sys_unstable_apis"); - - eprintln!("{root_dir}> {cmd:?}"); - let status = cmd - .current_dir(root_dir) - .status() - .context("Failed to build Wasm")?; - assert!(status.success(), "Failed to build Wasm"); + // This is required to enable the web_sys clipboard API which egui_web uses + // https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html + // https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html + // Furthermore, it's necessary for unstable WebGPU apis to work. + cmd.env("RUSTFLAGS", "--cfg=web_sys_unstable_apis"); - // -------------------------------------------------------------------------------- - eprintln!("Generating JS bindings for wasm…"); - - let build = profile.as_str(); - - let target_wasm_path = target_wasm_dir - .join("wasm32-unknown-unknown") - .join(build) - .join(format!("{crate_name}.wasm")); - - let mut bindgen_cmd = wasm_bindgen_cli_support::Bindgen::new(); - bindgen_cmd - .input_path(target_wasm_path.as_str()) - .out_name(crate_name); - match target { - Target::Browser => bindgen_cmd.no_modules(true)?.typescript(false), - Target::Module => bindgen_cmd.no_modules(false)?.typescript(true), - }; - if let Err(err) = bindgen_cmd.generate(build_dir.as_str()) { - if err - .to_string() - .starts_with("cannot import from modules (`env`") - { - // Very common error: "cannot import from modules (`env`) with `--no-modules`" - anyhow::bail!( + // When executing this script from a Rust build script, do _not_, under any circumstances, + // allow pre-encoded `RUSTFLAGS` to leak into the current environment. + // These pre-encoded flags are generally generated by Cargo itself when loading its + // configuration from e.g. `$CARGO_HOME/config.toml`; which means they will contain + // values that only make sense for the native target host, not for a wasm build. + cmd.env("CARGO_ENCODED_RUSTFLAGS", "--cfg=web_sys_unstable_apis"); + + eprintln!("{root_dir}> {cmd:?}"); + let status = cmd + .current_dir(root_dir) + .status() + .context("Failed to build Wasm")?; + + anyhow::ensure!(status.success(), "Failed to build Wasm"); + + eprintln!( + "Web viewer .wasm built in {:.1}s\n", + start_time.elapsed().as_secs_f32() + ); + } + + { + eprintln!("Generating JS bindings for wasm…"); + let start_time = Instant::now(); + + let build = profile.as_str(); + + let target_wasm_path = target_wasm_dir + .join("wasm32-unknown-unknown") + .join(build) + .join(format!("{crate_name}.wasm")); + + let mut bindgen_cmd = wasm_bindgen_cli_support::Bindgen::new(); + bindgen_cmd + .input_path(target_wasm_path.as_str()) + .out_name(crate_name); + match target { + Target::Browser => bindgen_cmd.no_modules(true)?.typescript(false), + Target::Module => bindgen_cmd.no_modules(false)?.typescript(true), + }; + if let Err(err) = bindgen_cmd.generate(build_dir.as_str()) { + if err + .to_string() + .starts_with("cannot import from modules (`env`") + { + // Very common error: "cannot import from modules (`env`) with `--no-modules`" + anyhow::bail!( "Failed to run wasm-bindgen: {err}. This is often because some dependency is calling `std::time::Instant::now()` or similar. You can try diagnosing this with:\n\ wasm2wat {target_wasm_path} | rg '\"env\"'\n\ wasm2wat {target_wasm_path} | rg 'call .now\\b' -B 20\n\ @@ -162,15 +173,20 @@ pub fn build( You can also try https://rustwasm.github.io/twiggy/usage/command-line-interface/paths.html#twiggy-paths " ); - } else { - return Err(err.context("Failed to run wasm-bindgen")); + } else { + return Err(err.context("Failed to run wasm-bindgen")); + } } - } - // -------------------------------------------------------------------------------- + eprintln!( + "Generated JS bindings in {:.1}s\n", + start_time.elapsed().as_secs_f32() + ); + } if profile == Profile::Release { eprintln!("Optimizing wasm with wasm-opt…"); + let start_time = Instant::now(); // to get wasm-opt: apt/brew/dnf install binaryen let mut cmd = std::process::Command::new("wasm-opt"); @@ -186,12 +202,17 @@ pub fn build( .current_dir(root_dir) .output() .context("Failed to run wasm-opt, it may not be installed")?; - if !output.status.success() { - eprintln!( - "Failed to run wasm-opt:\n{}", - String::from_utf8_lossy(&output.stderr) - ); - } + + anyhow::ensure!( + output.status.success(), + "Failed to run wasm-opt:\n{}", + String::from_utf8_lossy(&output.stderr), + ); + + eprintln!( + "Optimized wasm in {:.1}s\n", + start_time.elapsed().as_secs_f32() + ); } // -------------------------------------------------------------------------------- From b1f6f93fa2a17417338ac458b167127d5f4dcccb Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 11 Apr 2024 12:15:40 +0200 Subject: [PATCH 252/508] Update python readme and add `py-wheel` command (#5912) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5912) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5912?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5912?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5912) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- BUILD.md | 26 ++++++++++- pixi.toml | 2 +- rerun_py/README.md | 114 +++++++-------------------------------------- 3 files changed, 43 insertions(+), 99 deletions(-) diff --git a/BUILD.md b/BUILD.md index 62632d00abd4..5341c53d5c0e 100644 --- a/BUILD.md +++ b/BUILD.md @@ -66,9 +66,33 @@ Rerun is available as a package on PyPi and can be installed with `pip install r Additionally, prebuilt dev wheels from head of main are available at . If you want to build from source, you can do so easily in the pixi environment: -* Run `pixi run py-build-release` to build SDK & viewer for python (or `pixi run py-build` for a debug build) +* Run `pixi run py-build --release` to build SDK & viewer for python (or `pixi run py-build` for a debug build) * Then you can run examples from the repository, either by making the pixi shell active with `pixi shell` and then running python or by using `pixi run`, e.g. `pixi run python examples/python/minimal/main.py` + +### Tests & Tooling + +```sh +# Run the unit tests +pixi run py-test + +# Run the linting checks +pixi run py-lint + +# Run the formatter +pixi run py-fmt +``` + +### Building an installable Python Wheel +The `py-wheel` command builds a whl file: +```sh +pixi run py-wheel --release +``` +Which you can then install in your own python environment: +```sh +pip install ./target/wheels/*.whl +``` + ## Building and installing the Rerun C++ SDK On Windows you have to have a system install of Visual Studio 2022 in order to compile the SDK and samples. diff --git a/pixi.toml b/pixi.toml index 771d6fbaec66..cf53d0ba2abc 100644 --- a/pixi.toml +++ b/pixi.toml @@ -109,7 +109,7 @@ py-fmt-check = "ruff format --check --config rerun_py/pyproject.toml" py-lint = "mypy --install-types --non-interactive --no-warn-unused-ignore" py-build = "maturin develop --manifest-path rerun_py/Cargo.toml --extras=tests" -py-build-release = "maturin develop --release --manifest-path rerun_py/Cargo.toml --extras=tests" +py-wheel = "maturin build --manifest-path rerun_py/Cargo.toml" # Run the Python tests. # Don't call this on CI - use `nox` to run tests on all supported Python versions instead. diff --git a/rerun_py/README.md b/rerun_py/README.md index a212f095f9e6..c3ffb5cbb727 100644 --- a/rerun_py/README.md +++ b/rerun_py/README.md @@ -1,6 +1,6 @@ -# The Rerun Python Log SDK +# The Rerun Python SDK -Use the Rerun SDK to log data like images, tensors, point clouds, and text. Logs are streamed to the Rerun Viewer for live visualization or to file for later use. +Use the Rerun SDK to record data like images, tensors, point clouds, and text. Data is streamed to the Rerun Viewer for live visualization or to file for later use.

Rerun Viewer @@ -15,6 +15,8 @@ pip3 install rerun-sdk ℹ️ Note: The Python module is called `rerun`, while the package published on PyPI is `rerun-sdk`. +For other SDK languages see [Installing Rerun](https://www.rerun.io/docs/getting-started/installing-viewer). + ## Example ```py import rerun as rr @@ -47,114 +49,32 @@ python3 -m rerun In a second terminal, run the example with the `--connect` option: ```sh -python3 python examples/python/plots/main.py --connect +python3 examples/python/plots/main.py --connect ``` +Note that SDK and Viewer can run on different machines! -------------------------- - -# From source - -Setup: -* Install the Rust toolchain: -* `git clone git@github.com:rerun-io/rerun.git && cd rerun` -* Run `./scripts/setup_dev.sh`. -* Make sure `cargo --version` prints `1.74.0` once you are done +# Building Rerun from source -## Building -To build from source and install Rerun into your *current* Python environment run: +We use the [`pixi`](https://prefix.dev/) for managing dev-tool versioning, download and task running. See [here](https://github.com/casey/just#installation) for installation instructions. ```sh -python3 -m pip install --upgrade pip -pip3 install -r rerun_py/requirements-build.txt -pip3 install "./rerun_py" +pixi run py-build --release ``` +To build SDK & viewer for python (or `pixi run py-build` for a debug build) and install it in the pixi environment. -ℹ️ Note: -If you are unable to upgrade pip to version `>=21.3`, you need to pass `--use-feature=in-tree-build` to the `pip3 install` command. - -## Development - -To set up a new virtualenv for development: +You can then run examples from the repository, either by making the pixi shell active with `pixi shell` and then running python or by using `pixi run`, e.g. `pixi run python examples/python/minimal/main.py`. +Respectively, to build a wheel instead for manual install use: ```sh -just py-dev-env -# For bash/zsh users: -source venv/bin/activate -# Or if you're using fish: -source venv/bin/activate.fish +pixi run py-wheel --release ``` -## Build, test, and run +Refer to [BUILD.md](../BUILD.md) for details on the various different build options of the Rerun Viewer and SDKs for all target languages. -For ease of development you can build and install in "editable" mode. This means you can edit the `rerun` Python code without having to re-build and install to see changes. -```sh -# Build the SDK and install in develop mode into the virtualenv -# Re-run this if the Rust code has changed! -source venv/bin/activate -just py-build -``` - -### Test -```sh -# Run the unit tests -just py-test +# Installing a pre-release -# Run the linting checks -just py-lint +Prebuilt dev wheels from head of main are available at . -# Run an example -python examples/python/minimal/main.py -``` - -## Building an installable Python Wheel -The Python bindings to the core Rust library are built using https://github.com/PyO3/pyo3. - -To build an installable Python wheel run: -``` -pip install -r rerun_py/requirements-build.txt -maturin build -m rerun_py/Cargo.toml --release -``` - -By default the wheels will be built to `target/wheels` (use the `-o` flag to set a different output directory). - -Now you can install `rerun` in any Python3 environment using: - -```sh -pip3 install target/wheels/*.whl -``` - -## Viewing the docs locally -The rerun python docs are generated using `mkdocs` - -Install the doc requirements: -``` -pip install -r rerun_py/requirements-doc.txt -``` - -Serve the docs: -```sh -mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py -``` -or -```sh -just py-docs-serve -``` - -For information on how the docs system works, see: [docs/writing_docs.md](docs/writing_docs.md) - - -## Troubleshooting -You can run with `RUST_LOG=debug` to get more output out of the rerun SDK. - -If you are using an Apple-silicon Mac, make sure `rustc -vV` outputs `host: aarch64-apple-darwin`. If not, this should fix it: - -``` sh -rustup set default-host aarch64-apple-darwin && rustup install 1.74 -``` - -If you want to switch back, this is how: -``` sh -rustup set default-host x86_64-apple-darwin && rustup install 1.74 -``` +While we try to keep the main branch usable at all times, it may be unstable occasionally. Use at your own risk. From 1dee2da985aa3fa803b53e28fc6fbff58cd8218c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 12:36:33 +0200 Subject: [PATCH 253/508] Re-run all of CI if `pixi.toml` changes (#5915) ### What pixi has our build commands ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5915) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5915?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5915?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5915) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/on_pull_request.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index eceafc31a78e..980c54402080 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -35,6 +35,8 @@ jobs: filters: | rust_changes: - .github/**/*.yml # CI changes should always trigger all jobs + - pixi.lock # maybe out build commands have changed + - pixi.toml # maybe out build commands have changed - "**/*.rs" - "**/*.toml" @@ -52,6 +54,8 @@ jobs: filters: | cpp_changes: - .github/**/*.yml # CI changes should always trigger all jobs + - pixi.lock # maybe out build commands have changed + - pixi.toml # maybe out build commands have changed - '**/*.hpp' - '**/*.cpp' - '**/CMakeLists.txt' @@ -71,6 +75,8 @@ jobs: filters: | python_changes: - .github/**/*.yml # CI changes should always trigger all jobs + - pixi.lock # maybe out build commands have changed + - pixi.toml # maybe out build commands have changed - '**/*.py' - '**/requirements.txt' - '**/pyproject.toml' @@ -89,6 +95,8 @@ jobs: filters: | docs_changes: - .github/**/*.yml # CI changes should always trigger all jobs + - pixi.lock # maybe out build commands have changed + - pixi.toml # maybe out build commands have changed - 'docs/content/**/*.md' - 'examples/**/*.md' - 'examples/manifest.toml' From eecfdb441972887f8f8741ac91adf443478c9830 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 12:43:52 +0200 Subject: [PATCH 254/508] Update to Rust 1.76 (#5908) * Part of https://github.com/rerun-io/rerun/issues/3033 --------- Co-authored-by: Clement Rey --- .github/actions/setup-rust/action.yml | 2 +- .github/workflows/contrib_rerun_py.yml | 2 +- .github/workflows/on_push_main.yml | 2 +- .../workflows/reusable_build_and_upload_rerun_c.yml | 4 ++-- .../workflows/reusable_build_and_upload_rerun_cli.yml | 4 ++-- .github/workflows/reusable_build_and_upload_wheels.yml | 4 ++-- .../workflows/reusable_bundle_and_upload_rerun_cpp.yml | 2 +- .github/workflows/reusable_checks_rust.yml | 7 ++++--- .github/workflows/reusable_run_notebook.yml | 2 +- .github/workflows/reusable_test_wheels.yml | 4 ++-- BUILD.md | 4 ++-- CHANGELOG.md | 2 +- Cargo.toml | 2 +- Cranky.toml | 5 +++++ RELEASES.md | 8 +++++++- ci_docker/Dockerfile | 6 +++--- ci_docker/publish.sh | 2 +- clippy.toml | 2 +- crates/re_analytics/examples/end_to_end.rs | 2 +- crates/re_build_info/src/build_info.rs | 2 +- crates/re_data_store/src/store_read.rs | 3 +-- crates/re_renderer/src/file_resolver.rs | 2 +- crates/re_sdk_comms/src/server.rs | 1 + .../src/visualizers/entity_iterator.rs | 5 +++-- .../re_space_view_time_series/src/space_view_class.rs | 10 ++-------- .../re_viewer/data/quick_start_guides/rust_connect.md | 2 +- crates/re_viewer/data/quick_start_guides/rust_spawn.md | 2 +- crates/re_viewer/src/ui/top_panel.rs | 2 +- crates/re_viewport/src/viewport.rs | 2 +- docs/content/getting-started/installing-viewer.md | 2 +- docs/content/getting-started/quick-start/rust.md | 2 +- examples/rust/clock/Cargo.toml | 2 +- examples/rust/custom_data_loader/Cargo.toml | 2 +- examples/rust/custom_space_view/Cargo.toml | 2 +- examples/rust/custom_store_subscriber/Cargo.toml | 2 +- examples/rust/dna/Cargo.toml | 2 +- examples/rust/extend_viewer_ui/Cargo.toml | 2 +- examples/rust/external_data_loader/Cargo.toml | 2 +- examples/rust/incremental_logging/Cargo.toml | 2 +- examples/rust/log_file/Cargo.toml | 2 +- examples/rust/minimal/Cargo.toml | 2 +- examples/rust/minimal_options/Cargo.toml | 2 +- examples/rust/minimal_serve/Cargo.toml | 2 +- examples/rust/objectron/Cargo.toml | 2 +- examples/rust/raw_mesh/Cargo.toml | 2 +- examples/rust/shared_recording/Cargo.toml | 2 +- examples/rust/spawn_viewer/Cargo.toml | 2 +- examples/rust/stdio/Cargo.toml | 2 +- examples/rust/template/Cargo.toml | 2 +- rust-toolchain | 2 +- scripts/clippy_wasm/clippy.toml | 2 +- scripts/lint.py | 2 +- tests/rust/plot_dashboard_stress/Cargo.toml | 2 +- 53 files changed, 76 insertions(+), 69 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index 04b26ad20532..c03212566dc7 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -67,7 +67,7 @@ runs: - name: Set up sccache uses: rerun-io/sccache-action@v0.7.0 with: - version: "v0.5.2" + version: "v0.7.7" use_gcs: true gcs_bucket: rerun-sccache gcs_read_only: false diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 29d2f43c08bc..7dd1f11879c7 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -36,7 +36,7 @@ jobs: name: Build Wheels runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.12.0 + image: rerunio/ci_docker:0.13.0 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index bdd9beeb0a24..8221e7c741c4 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.74.0 + toolchain: 1.76.0 - name: Set up cargo cache uses: Swatinem/rust-cache@v2 diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml index 751a934e5237..b817245809ed 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_c.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml @@ -76,13 +76,13 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.12.0'" + container="'rerunio/ci_docker:0.13.0'" lib_name="librerun_c.a" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.12.0'" + container="'rerunio/ci_docker:0.13.0'" lib_name="librerun_c.a" ;; windows-x64) diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index 98fd400f0537..b5efe599dd73 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -77,13 +77,13 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.12.0'" + container="'rerunio/ci_docker:0.13.0'" bin_name="rerun" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.12.0'" + container="'rerunio/ci_docker:0.13.0'" bin_name="rerun" ;; windows-x64) diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index d81790146a3c..532049233707 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -101,14 +101,14 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.12.0'" # Required to be manylinux compatible + container="'rerunio/ci_docker:0.13.0'" # Required to be manylinux compatible compat="manylinux_2_31" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" compat="manylinux_2_31" - container="'rerunio/ci_docker:0.12.0'" # Required to be manylinux compatible + container="'rerunio/ci_docker:0.13.0'" # Required to be manylinux compatible ;; windows-x64) runner="windows-latest-8-cores" diff --git a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml index 652bee8ae942..7a80b267f68f 100644 --- a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml +++ b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.12.0 # Need container for arrow dependency. + image: rerunio/ci_docker:0.13.0 # Need container for arrow dependency. steps: - name: Checkout repository diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index b003473a25e6..f2f53b2771bc 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -98,9 +98,10 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - name: clippy check re_viewer wasm32 - shell: bash - run: ./scripts/clippy_wasm.sh + # NOTE: Fails with sccache -- refactor incoming in a follow-up PR. + # - name: clippy check re_viewer wasm32 + # shell: bash + # run: ./scripts/clippy_wasm.sh - name: Check re_renderer examples wasm32 uses: actions-rs/cargo@v1 diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml index 577b2e1385c8..4481c61653e8 100644 --- a/.github/workflows/reusable_run_notebook.yml +++ b/.github/workflows/reusable_run_notebook.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.12.0 # Required to run the wheel or we get "No matching distribution found for attrs>=23.1.0" during `pip install rerun-sdk` + image: rerunio/ci_docker:0.13.0 # Required to run the wheel or we get "No matching distribution found for attrs>=23.1.0" during `pip install rerun-sdk` steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 2a7b7e21f015..a45e76e9efd7 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -66,12 +66,12 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.12.0'" + container="'rerunio/ci_docker:0.13.0'" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.12.0'" + container="'rerunio/ci_docker:0.13.0'" ;; windows-x64) runner="windows-latest-8-cores" diff --git a/BUILD.md b/BUILD.md index 5341c53d5c0e..fc25752a7942 100644 --- a/BUILD.md +++ b/BUILD.md @@ -23,12 +23,12 @@ cd rerun Now install the `pixi` package manager: -Make sure `cargo --version` prints `1.74.0` once you are done. +Make sure `cargo --version` prints `1.76.0` once you are done. If you are using an Apple-silicon Mac (M1, M2), make sure `rustc -vV` outputs `host: aarch64-apple-darwin`. If not, this should fix it: ```sh -rustup set default-host aarch64-apple-darwin && rustup install 1.74.0 +rustup set default-host aarch64-apple-darwin && rustup install 1.76.0 ``` Additionally, we use [cargo-cranky](https://github.com/ericseppanen/cargo-cranky) for defining which Clippy lints are active and [cargo-deny](https://github.com/EmbarkStudios/cargo-deny) for linting crate versions. diff --git a/CHANGELOG.md b/CHANGELOG.md index cf8d3751c554..08e8efbfbc22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -632,7 +632,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi #### 📦 Dependencies - Update egui and wgpu [#4111](https://github.com/rerun-io/rerun/pull/4111) -- Update Rust to 1.74.0 [#4390](https://github.com/rerun-io/rerun/pull/4390) +- Update Rust to 1.76.0 [#4390](https://github.com/rerun-io/rerun/pull/4390) #### 🤷 Other #### 🤷 Other diff --git a/Cargo.toml b/Cargo.toml index eceb581b10fa..3fc940776264 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ homepage = "https://rerun.io" include = ["../../LICENSE-APACHE", "../../LICENSE-MIT", "**/*.rs", "Cargo.toml"] license = "MIT OR Apache-2.0" repository = "https://github.com/rerun-io/rerun" -rust-version = "1.74" +rust-version = "1.76" version = "0.16.0-alpha.1+dev" [workspace.dependencies] diff --git a/Cranky.toml b/Cranky.toml index a9438d5b41c4..af489d16a438 100644 --- a/Cranky.toml +++ b/Cranky.toml @@ -48,10 +48,13 @@ warn = [ "clippy::imprecise_flops", "clippy::index_refutable_slice", "clippy::inefficient_to_string", + "clippy::infinite_loop", + "clippy::into_iter_without_iter", "clippy::invalid_upcast_comparisons", "clippy::iter_not_returning_iterator", "clippy::iter_on_empty_collections", "clippy::iter_on_single_items", + "clippy::iter_without_into_iter", "clippy::large_digit_groups", "clippy::large_include_file", "clippy::large_stack_arrays", @@ -119,6 +122,7 @@ warn = [ "clippy::unchecked_duration_subtraction", "clippy::undocumented_unsafe_blocks", "clippy::unimplemented", + "clippy::uninhabited_references", "clippy::uninlined_format_args", "clippy::unnecessary_box_returns", "clippy::unnecessary_safety_doc", @@ -152,6 +156,7 @@ allow = [ # TODO(emilk): enable more of these lints: "clippy::cloned_instead_of_copied", + "clippy::iter_over_hash_type", "clippy::let_underscore_untyped", "clippy::missing_assert_message", "clippy::missing_errors_doc", diff --git a/RELEASES.md b/RELEASES.md index 6746a97c0d19..749582aefec7 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -11,7 +11,7 @@ This document describes the current release and versioning strategy. This strate ## Release cadence -New Rerun versions are released every four weeks. Sometimes we do out-of-schedule patch releases. +New Rerun versions are released approximately once every month. Sometimes we do out-of-schedule patch releases. ## Library versioning and release cadence @@ -30,6 +30,12 @@ In rare cases we will do patch releases, e.g. `0.3.1`, when there is a critical We sometimes do pre-releases. Then we use the versioning `0.2.0-alpha.0` etc. +## Rust version policy +Our Minimum Supported Rust Version (MSRV) is always _at least_ one minor release behind the latest Rust version, and ideally two releases. +* This means users of our libraries aren't forced to update to the very latest Rust version +* This lets us sometimes avoid new bugs in the newly released Rust compiler + + ## Data and communication versioning We have not yet committed to any backwards or forwards compatibility. diff --git a/ci_docker/Dockerfile b/ci_docker/Dockerfile index 300ba04c48bf..dd522d2f9f7d 100644 --- a/ci_docker/Dockerfile +++ b/ci_docker/Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu:20.04 LABEL maintainer="opensource@rerun.io" # Remember to update the version in publish.sh # TODO(jleibs) use this version in the publish.sh script and below in the CACHE_KEY -LABEL version="0.12.0" +LABEL version="0.13.0" LABEL description="Docker image used for the CI of https://github.com/rerun-io/rerun" # Install the ubuntu package dependencies @@ -68,7 +68,7 @@ RUN arch=$(if [ "$TARGETARCH" = "arm64" ]; then echo "aarch64"; else echo "x86_6 ENV RUSTUP_HOME=/usr/local/rustup \ CARGO_HOME=/usr/local/cargo \ PATH=/usr/local/cargo/bin:$PATH \ - RUST_VERSION=1.74.0 \ + RUST_VERSION=1.76.0 \ RUSTUP_VERSION=1.26.0 # Install Rust @@ -108,7 +108,7 @@ ADD rerun_py/requirements-lint.txt requirements-lint.txt RUN pip install -r requirements-lint.txt # Increment this to invalidate cache -ENV CACHE_KEY=rerun_docker_v0.12.0 +ENV CACHE_KEY=rerun_docker_v0.13.0 # See: https://github.com/actions/runner-images/issues/6775#issuecomment-1410270956 RUN git config --system --add safe.directory '*' diff --git a/ci_docker/publish.sh b/ci_docker/publish.sh index 31d3d9b57d10..296ba5c50eee 100755 --- a/ci_docker/publish.sh +++ b/ci_docker/publish.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eux -VERSION=0.12.0 # Bump on each new version. Remember to update the version in the Dockerfile too. +VERSION=0.13.0 # Bump on each new version. Remember to update the version in the Dockerfile too. # The build needs to run from top of repo to access the requirements.txt cd `git rev-parse --show-toplevel` diff --git a/clippy.toml b/clippy.toml index 927abf6296cc..1a16dbf77e78 100644 --- a/clippy.toml +++ b/clippy.toml @@ -3,7 +3,7 @@ # ----------------------------------------------------------------------------- # Section identical to the main scripts/clippy_wasm/clippy.toml: -msrv = "1.74" +msrv = "1.76" allow-unwrap-in-tests = true diff --git a/crates/re_analytics/examples/end_to_end.rs b/crates/re_analytics/examples/end_to_end.rs index 525e3f7b5feb..631d783208db 100644 --- a/crates/re_analytics/examples/end_to_end.rs +++ b/crates/re_analytics/examples/end_to_end.rs @@ -4,7 +4,7 @@ use re_analytics::Event; use re_analytics::Properties; use re_analytics::{Analytics, AnalyticsEvent}; -fn main() { +fn main() -> ! { re_log::setup_logging(); let analytics = Analytics::new(Duration::from_secs(3)).unwrap(); diff --git a/crates/re_build_info/src/build_info.rs b/crates/re_build_info/src/build_info.rs index 511d06197a89..28f39a3d87b5 100644 --- a/crates/re_build_info/src/build_info.rs +++ b/crates/re_build_info/src/build_info.rs @@ -153,7 +153,7 @@ fn crate_version_from_build_info_string() { patch: 0, meta: Some(crate::crate_version::Meta::DevAlpha(7)), }, - rustc_version: "1.74.0 (d5c2e9c34 2023-09-13)", + rustc_version: "1.76.0 (d5c2e9c34 2023-09-13)", llvm_version: "16.0.5", git_hash: "", git_branch: "", diff --git a/crates/re_data_store/src/store_read.rs b/crates/re_data_store/src/store_read.rs index e23387a2d8ff..6700163ff668 100644 --- a/crates/re_data_store/src/store_read.rs +++ b/crates/re_data_store/src/store_read.rs @@ -346,8 +346,7 @@ impl DataStore { .get(&(entity_path_hash, query.timeline)) .map(|index| index.range(query.range, component_names_opt)) .into_iter() - .flatten() - .map(|(data_time, row_id, cells)| (data_time, row_id, cells)), + .flatten(), ) } diff --git a/crates/re_renderer/src/file_resolver.rs b/crates/re_renderer/src/file_resolver.rs index 2a65f3743706..c307f83f3006 100644 --- a/crates/re_renderer/src/file_resolver.rs +++ b/crates/re_renderer/src/file_resolver.rs @@ -149,7 +149,7 @@ //! Normalization (not available in `std`) on the other hand is purely lexicographical: it //! normalizes paths as best as it can without ever touching the filesystem. //! -//! See also ["Getting Dot-Dot Right"](https://9p.io/sys/doc/lexnames.html). +//! See also "[Getting Dot-Dot Right](https://9p.io/sys/doc/lexnames.html)". //! //! ### Hermeticism //! diff --git a/crates/re_sdk_comms/src/server.rs b/crates/re_sdk_comms/src/server.rs index 3cfe096dfd79..3ad74cbbe93b 100644 --- a/crates/re_sdk_comms/src/server.rs +++ b/crates/re_sdk_comms/src/server.rs @@ -109,6 +109,7 @@ pub async fn serve( } async fn listen_for_new_clients(listener: TcpListener, options: ServerOptions, tx: Sender) { + #[allow(clippy::infinite_loop)] // TODO(emilk): some way of aborting this loop loop { match listener.accept().await { Ok((stream, _)) => { diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 746f7fa2a313..3c213cdeff57 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -74,7 +74,7 @@ where let extra_history = query_visual_history(ctx, data_result); - match query_archetype_with_history::( + let result = query_archetype_with_history::( ctx.recording_store(), &query.timeline, &query.latest_at, @@ -97,7 +97,8 @@ where )?; } Ok(()) - }) { + }); + match result { Ok(_) | Err(QueryError::PrimaryNotFound(_)) => {} Err(err) => { re_log::error_once!( diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 85c3c0b725e2..4395005fd4e1 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -436,14 +436,8 @@ It can greatly improve performance (and readability) in such situations as it pr }); if legend_visible.unwrap_or(true.into()).0 { - plot = plot.legend( - Legend::default().position( - legend_corner - .unwrap_or_default() - .try_into() - .unwrap_or(DEFAULT_LEGEND_CORNER), - ), - ); + plot = + plot.legend(Legend::default().position(legend_corner.unwrap_or_default().into())); } if timeline.typ() == TimeType::Time { diff --git a/crates/re_viewer/data/quick_start_guides/rust_connect.md b/crates/re_viewer/data/quick_start_guides/rust_connect.md index fb561ec18781..7e59d6afa0a5 100644 --- a/crates/re_viewer/data/quick_start_guides/rust_connect.md +++ b/crates/re_viewer/data/quick_start_guides/rust_connect.md @@ -10,7 +10,7 @@ Let's try it out in a brand-new Rust project: cargo init cube && cd cube && cargo add rerun --features native_viewer ``` -Note that the Rerun SDK requires a working installation of Rust 1.74+. +Note that the Rerun SDK requires a working installation of Rust 1.76+. ## Logging your own data diff --git a/crates/re_viewer/data/quick_start_guides/rust_spawn.md b/crates/re_viewer/data/quick_start_guides/rust_spawn.md index 127eb8bebd85..a59fb322c5d0 100644 --- a/crates/re_viewer/data/quick_start_guides/rust_spawn.md +++ b/crates/re_viewer/data/quick_start_guides/rust_spawn.md @@ -10,7 +10,7 @@ Let's try it out in a brand-new Rust project: cargo init cube && cd cube && cargo add rerun ``` -Note that the Rerun SDK requires a working installation of Rust 1.74+. +Note that the Rerun SDK requires a working installation of Rust 1.76+. ## Logging your own data diff --git a/crates/re_viewer/src/ui/top_panel.rs b/crates/re_viewer/src/ui/top_panel.rs index 5f69ffae2ed1..2db6cfb8086e 100644 --- a/crates/re_viewer/src/ui/top_panel.rs +++ b/crates/re_viewer/src/ui/top_panel.rs @@ -327,7 +327,7 @@ fn memory_use_label_ui(ui: &mut egui::Ui, gpu_resource_stats: &WgpuResourcePoolS text: impl Into, add_contents_on_hover: impl FnOnce(&mut egui::Ui), ) { - #[allow(clippy::blocks_in_if_conditions)] + #[allow(clippy::blocks_in_conditions)] let text = text.into(); if ui .add( diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index 64a0462e0d97..7b74062efd99 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -322,7 +322,7 @@ impl<'a, 'b> Viewport<'a, 'b> { space_view.class_identifier(), ); - #[allow(clippy::blocks_in_if_conditions)] + #[allow(clippy::blocks_in_conditions)] while ScreenshotProcessor::next_readback_result( ctx.render_ctx, space_view.id.gpu_readback_id(), diff --git a/docs/content/getting-started/installing-viewer.md b/docs/content/getting-started/installing-viewer.md index 4f02f7f0580d..807dba0f026c 100644 --- a/docs/content/getting-started/installing-viewer.md +++ b/docs/content/getting-started/installing-viewer.md @@ -40,7 +40,7 @@ There are many ways to install the viewer. Please pick whatever works best for y - Download it from the [GitHub Release artifacts](https://github.com/rerun-io/rerun/releases/latest/) - Via Cargo - `cargo binstall rerun-cli` - download binaries via [`cargo binstall`](https://github.com/cargo-bins/cargo-binstall) - - `cargo install rerun-cli` - build it from source (this requires Rust 1.74+) + - `cargo install rerun-cli` - build it from source (this requires Rust 1.76+) - Together with the Rerun [Python SDK](./quick-start/python.md): - `pip3 install rerun-sdk` - download it via pip - `conda install -c conda-forge rerun-sdk` - download via Conda diff --git a/docs/content/getting-started/quick-start/rust.md b/docs/content/getting-started/quick-start/rust.md index 910d87aaa9ba..217ae3674c34 100644 --- a/docs/content/getting-started/quick-start/rust.md +++ b/docs/content/getting-started/quick-start/rust.md @@ -5,7 +5,7 @@ order: 3 ## Setup -The Rerun SDK for Rust requires a working installation of Rust 1.74+. +The Rerun SDK for Rust requires a working installation of Rust 1.76+. After you have [installed the viewer](../installing-viewer.md#installing-the-viewer) you can simply add [the rerun crate](https://crates.io/crates/rerun) to your project with `cargo add rerun`. diff --git a/examples/rust/clock/Cargo.toml b/examples/rust/clock/Cargo.toml index 0846228b7e3c..ba5c87353b23 100644 --- a/examples/rust/clock/Cargo.toml +++ b/examples/rust/clock/Cargo.toml @@ -2,7 +2,7 @@ name = "clock" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/custom_data_loader/Cargo.toml b/examples/rust/custom_data_loader/Cargo.toml index c806cfc33c78..20523c8cf6d8 100644 --- a/examples/rust/custom_data_loader/Cargo.toml +++ b/examples/rust/custom_data_loader/Cargo.toml @@ -2,7 +2,7 @@ name = "custom_data_loader" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index ac26a16f34a6..952646cfa948 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -2,7 +2,7 @@ name = "custom_space_view" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/custom_store_subscriber/Cargo.toml b/examples/rust/custom_store_subscriber/Cargo.toml index c7a9caf5421e..4cdd909aba29 100644 --- a/examples/rust/custom_store_subscriber/Cargo.toml +++ b/examples/rust/custom_store_subscriber/Cargo.toml @@ -2,7 +2,7 @@ name = "custom_store_subscriber" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml index f82568b67453..6e2a2f64c07c 100644 --- a/examples/rust/dna/Cargo.toml +++ b/examples/rust/dna/Cargo.toml @@ -2,7 +2,7 @@ name = "dna" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml index d3e0eb7dc5ac..78f480231f97 100644 --- a/examples/rust/extend_viewer_ui/Cargo.toml +++ b/examples/rust/extend_viewer_ui/Cargo.toml @@ -2,7 +2,7 @@ name = "extend_viewer_ui" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/external_data_loader/Cargo.toml b/examples/rust/external_data_loader/Cargo.toml index 25c1e9b923cc..4fc476291a69 100644 --- a/examples/rust/external_data_loader/Cargo.toml +++ b/examples/rust/external_data_loader/Cargo.toml @@ -2,7 +2,7 @@ name = "rerun-loader-rust-file" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml index 8961b27b5051..0c835299899b 100644 --- a/examples/rust/incremental_logging/Cargo.toml +++ b/examples/rust/incremental_logging/Cargo.toml @@ -2,7 +2,7 @@ name = "incremental_logging" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml index b899ff577f90..c7ae23912ee1 100644 --- a/examples/rust/log_file/Cargo.toml +++ b/examples/rust/log_file/Cargo.toml @@ -2,7 +2,7 @@ name = "log_file" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/minimal/Cargo.toml b/examples/rust/minimal/Cargo.toml index 775150905de4..e1bb2fedda46 100644 --- a/examples/rust/minimal/Cargo.toml +++ b/examples/rust/minimal/Cargo.toml @@ -2,7 +2,7 @@ name = "minimal" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/minimal_options/Cargo.toml b/examples/rust/minimal_options/Cargo.toml index 53e96a6fbdfa..f16187b9720f 100644 --- a/examples/rust/minimal_options/Cargo.toml +++ b/examples/rust/minimal_options/Cargo.toml @@ -2,7 +2,7 @@ name = "minimal_options" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml index 5964192611e6..f7f69125513a 100644 --- a/examples/rust/minimal_serve/Cargo.toml +++ b/examples/rust/minimal_serve/Cargo.toml @@ -2,7 +2,7 @@ name = "minimal_serve" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/objectron/Cargo.toml b/examples/rust/objectron/Cargo.toml index ebc9e71124a8..bcf6dfc1fa84 100644 --- a/examples/rust/objectron/Cargo.toml +++ b/examples/rust/objectron/Cargo.toml @@ -2,7 +2,7 @@ name = "objectron" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/raw_mesh/Cargo.toml b/examples/rust/raw_mesh/Cargo.toml index 4f0aac6254ee..63ecc0b96ce0 100644 --- a/examples/rust/raw_mesh/Cargo.toml +++ b/examples/rust/raw_mesh/Cargo.toml @@ -2,7 +2,7 @@ name = "raw_mesh" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/shared_recording/Cargo.toml b/examples/rust/shared_recording/Cargo.toml index ecc1e20b1e5a..3ae2cbd51edd 100644 --- a/examples/rust/shared_recording/Cargo.toml +++ b/examples/rust/shared_recording/Cargo.toml @@ -2,7 +2,7 @@ name = "shared_recording" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/spawn_viewer/Cargo.toml b/examples/rust/spawn_viewer/Cargo.toml index e83ba44db66d..2b50de7a3369 100644 --- a/examples/rust/spawn_viewer/Cargo.toml +++ b/examples/rust/spawn_viewer/Cargo.toml @@ -2,7 +2,7 @@ name = "spawn_viewer" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/stdio/Cargo.toml b/examples/rust/stdio/Cargo.toml index fca0eb86e408..0369c6ed3b5d 100644 --- a/examples/rust/stdio/Cargo.toml +++ b/examples/rust/stdio/Cargo.toml @@ -2,7 +2,7 @@ name = "stdio" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/examples/rust/template/Cargo.toml b/examples/rust/template/Cargo.toml index ece83f24a4c5..27f63350ee67 100644 --- a/examples/rust/template/Cargo.toml +++ b/examples/rust/template/Cargo.toml @@ -2,7 +2,7 @@ name = "template" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/rust-toolchain b/rust-toolchain index 8c37a023c1e3..871f562485d6 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -5,6 +5,6 @@ # to the user in the error, instead of "error: invalid channel name '[toolchain]'". [toolchain] -channel = "1.74.0" +channel = "1.76.0" components = ["rustfmt", "clippy"] targets = ["wasm32-unknown-unknown"] diff --git a/scripts/clippy_wasm/clippy.toml b/scripts/clippy_wasm/clippy.toml index b061d1e92816..c475058e4748 100644 --- a/scripts/clippy_wasm/clippy.toml +++ b/scripts/clippy_wasm/clippy.toml @@ -6,7 +6,7 @@ # ----------------------------------------------------------------------------- # Section identical to the main clippy.toml: -msrv = "1.74" +msrv = "1.76" allow-unwrap-in-tests = true diff --git a/scripts/lint.py b/scripts/lint.py index 89b69ada30c1..452449c4acd4 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -562,7 +562,7 @@ def test_lint_workspace_deps() -> None: name = "clock" version = "0.6.0-alpha.0" edition = "2021" - rust-version = "1.74" + rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false diff --git a/tests/rust/plot_dashboard_stress/Cargo.toml b/tests/rust/plot_dashboard_stress/Cargo.toml index 87b30691b2a9..c48ac7f85300 100644 --- a/tests/rust/plot_dashboard_stress/Cargo.toml +++ b/tests/rust/plot_dashboard_stress/Cargo.toml @@ -2,7 +2,7 @@ name = "plot_dashboard_stress" version = "0.16.0-alpha.1+dev" edition = "2021" -rust-version = "1.74" +rust-version = "1.76" license = "MIT OR Apache-2.0" publish = false From 171aad760cf7e738b076dcb8c869954915d7af1d Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Thu, 11 Apr 2024 13:15:36 +0200 Subject: [PATCH 255/508] Fix cell size test now that the overhead has shrunk (#5917) Updated Rust and/or deps have reduced the overhead of `DataCell` (probably better alignment/packing order, I haven't checked in detail). - Fixes https://github.com/rerun-io/rerun/issues/5732 --- crates/re_log_types/src/data_cell.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/re_log_types/src/data_cell.rs b/crates/re_log_types/src/data_cell.rs index a1e4bb94e568..b20d4f166fa1 100644 --- a/crates/re_log_types/src/data_cell.rs +++ b/crates/re_log_types/src/data_cell.rs @@ -689,8 +689,8 @@ fn data_cell_sizes() { DataCell::from_arrow(InstanceKey::name(), UInt64Array::from_vec(vec![]).boxed()); cell.compute_size_bytes(); - assert_eq!(184, cell.heap_size_bytes()); - assert_eq!(184, cell.heap_size_bytes()); + assert_eq!(168, cell.heap_size_bytes()); + assert_eq!(168, cell.heap_size_bytes()); } // anything else @@ -702,7 +702,7 @@ fn data_cell_sizes() { cell.compute_size_bytes(); // zero-sized + 3x u64s - assert_eq!(208, cell.heap_size_bytes()); - assert_eq!(208, cell.heap_size_bytes()); + assert_eq!(192, cell.heap_size_bytes()); + assert_eq!(192, cell.heap_size_bytes()); } } From a8cf9ecc8381c6bb2718aa89744153efe6e98c8c Mon Sep 17 00:00:00 2001 From: Leonard Bruns Date: Thu, 11 Apr 2024 13:19:17 +0200 Subject: [PATCH 256/508] Use new Mediapipe API in human pose tracking example (#5903) ### What Closes #5859. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/5903) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5903?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5903?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5903) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .../python/face_tracking/requirements.txt | 2 +- .../python/gesture_detection/requirements.txt | 2 +- examples/python/human_pose_tracking/README.md | 21 ++--- examples/python/human_pose_tracking/main.py | 81 +++++++++++++++---- .../human_pose_tracking/requirements.txt | 3 +- 5 files changed, 75 insertions(+), 34 deletions(-) diff --git a/examples/python/face_tracking/requirements.txt b/examples/python/face_tracking/requirements.txt index c018d69ff2e2..4a2edb0d4671 100644 --- a/examples/python/face_tracking/requirements.txt +++ b/examples/python/face_tracking/requirements.txt @@ -1,6 +1,6 @@ # no 3.12 version yet (https://pypi.org/project/mediapipe/) # 0.10.10 no longer supports the legacy Pose model: https://github.com/rerun-io/rerun/issues/5859 -mediapipe==0.10.9 ; python_version <= '3.11' +mediapipe==0.10.11 ; python_version <= '3.11' numpy opencv-python>4.6 # Avoid opencv-4.6 since it rotates images incorrectly (https://github.com/opencv/opencv/issues/22088) diff --git a/examples/python/gesture_detection/requirements.txt b/examples/python/gesture_detection/requirements.txt index aecc4bce71e3..ecabeb52bcee 100644 --- a/examples/python/gesture_detection/requirements.txt +++ b/examples/python/gesture_detection/requirements.txt @@ -1,6 +1,6 @@ # no 3.12 version yet (https://pypi.org/project/mediapipe/) # 0.10.10 no longer supports the legacy Pose model: https://github.com/rerun-io/rerun/issues/5859 -mediapipe==0.10.9 ; python_version <= '3.11' +mediapipe==0.10.11 ; python_version <= '3.11' numpy opencv-python>4.9 diff --git a/examples/python/human_pose_tracking/README.md b/examples/python/human_pose_tracking/README.md index e439d7fb3cda..ffbc17de7452 100644 --- a/examples/python/human_pose_tracking/README.md +++ b/examples/python/human_pose_tracking/README.md @@ -53,7 +53,7 @@ rr.log( ### Segmentation mask The segmentation result is logged through a combination of two archetypes. The segmentation -image itself is logged as an +image itself is logged as a [`SegmentationImage`](https://www.rerun.io/docs/reference/types/archetypes/segmentation_image) and contains the id for each pixel. The color is determined by the [`AnnotationContext`](https://www.rerun.io/docs/reference/types/archetypes/annotation_context) which is @@ -77,22 +77,15 @@ rr.log( #### Segmentation image ```python -rr.log( - "video/mask", - rr.SegmentationImage(segmentation_mask.astype(np.uint8)) -) +rr.log("video/mask", rr.SegmentationImage(binary_segmentation_mask.astype(np.uint8))) ``` ### Body pose points -Logging the body pose landmarks involves specifying connections between the points, extracting pose landmark points and logging them to the Rerun SDK. -The 2D points are visualized over the image/video for a better understanding and visualization of the body pose. The 3D points allows the creation of a 3D model of the body posture for a more comprehensive representation of the human pose. - - +Logging the body pose as a skeleton involves specifying the connectivity of its keypoints (i.e., pose landmarks), extracting the pose landmarks, and logging them as points to Rerun. In this example, both the 2D and 3D estimates from Mediapipe are visualized. -The 2D and 3D points are logged through a combination of two archetypes. First, a timeless +The skeletons are logged through a combination of two archetypes. First, a timeless [`ClassDescription`](https://www.rerun.io/docs/reference/types/datatypes/class_description) is logged, that contains the information which maps keypoint ids to labels and how to connect -the keypoints. -Defining these connections automatically renders lines between them. Mediapipe provides the `POSE_CONNECTIONS` variable which contains the list of `(from, to)` landmark indices that define the connections. Second, the actual keypoint positions are logged in 2D +the keypoints. By defining these connections Rerun will automatically add lines between them. Mediapipe provides the `POSE_CONNECTIONS` variable which contains the list of `(from, to)` landmark indices that define the connections. Second, the actual keypoint positions are logged in 2D and 3D as [`Points2D`](https://www.rerun.io/docs/reference/types/archetypes/points2d) and [`Points3D`](https://www.rerun.io/docs/reference/types/archetypes/points3d) archetypes, respectively. @@ -104,7 +97,9 @@ rr.log( rr.AnnotationContext( rr.ClassDescription( info=rr.AnnotationInfo(id=1, label="Person"), - keypoint_annotations=[rr.AnnotationInfo(id=lm.value, label=lm.name) for lm in mp_pose.PoseLandmark], + keypoint_annotations=[ + rr.AnnotationInfo(id=lm.value, label=lm.name) for lm in mp_pose.PoseLandmark + ], keypoint_connections=mp_pose.POSE_CONNECTIONS, ) ), diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py index b7927e11ac90..b3c8ff5b798c 100755 --- a/examples/python/human_pose_tracking/main.py +++ b/examples/python/human_pose_tracking/main.py @@ -13,6 +13,7 @@ import cv2 import mediapipe as mp +import mediapipe.python.solutions.pose as mp_pose import numpy as np import numpy.typing as npt import requests @@ -30,11 +31,19 @@ EXAMPLE_DIR: Final = Path(os.path.dirname(__file__)) DATASET_DIR: Final = EXAMPLE_DIR / "dataset" / "pose_movement" +MODEL_DIR: Final = EXAMPLE_DIR / "model" / "pose_movement" DATASET_URL_BASE: Final = "https://storage.googleapis.com/rerun-example-datasets/pose_movement" +MODEL_URL_TEMPLATE: Final = "https://storage.googleapis.com/mediapipe-models/pose_landmarker/pose_landmarker_{model_name}/float16/latest/pose_landmarker_{model_name}.task" -def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) -> None: - mp_pose = mp.solutions.pose +def track_pose(video_path: str, model_path: str, *, segment: bool, max_frame_count: int | None) -> None: + options = mp.tasks.vision.PoseLandmarkerOptions( + base_options=mp.tasks.BaseOptions( + model_asset_path=model_path, + ), + running_mode=mp.tasks.vision.RunningMode.VIDEO, + output_segmentation_masks=True, + ) rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True) @@ -62,19 +71,23 @@ def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) - ) rr.log("person", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, static=True) - with closing(VideoSource(video_path)) as video_source, mp_pose.Pose(enable_segmentation=segment) as pose: + pose_landmarker = mp.tasks.vision.PoseLandmarker.create_from_options(options) + + with closing(VideoSource(video_path)) as video_source: for idx, bgr_frame in enumerate(video_source.stream_bgr()): if max_frame_count is not None and idx >= max_frame_count: break + mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=bgr_frame.data) rgb = cv2.cvtColor(bgr_frame.data, cv2.COLOR_BGR2RGB) rr.set_time_seconds("time", bgr_frame.time) rr.set_time_sequence("frame_idx", bgr_frame.idx) - rr.log("video/rgb", rr.Image(rgb).compress(jpeg_quality=75)) - results = pose.process(rgb) + results = pose_landmarker.detect_for_video(mp_image, int(bgr_frame.time * 1000)) h, w, _ = rgb.shape landmark_positions_2d = read_landmark_positions_2d(results, w, h) + + rr.log("video/rgb", rr.Image(rgb).compress(jpeg_quality=75)) if landmark_positions_2d is not None: rr.log( "video/pose/points", @@ -88,9 +101,10 @@ def track_pose(video_path: str, *, segment: bool, max_frame_count: int | None) - rr.Points3D(landmark_positions_3d, class_ids=1, keypoint_ids=mp_pose.PoseLandmark), ) - segmentation_mask = results.segmentation_mask - if segmentation_mask is not None: - rr.log("video/mask", rr.SegmentationImage(segmentation_mask.astype(np.uint8))) + if results.segmentation_masks is not None: + segmentation_mask = results.segmentation_masks[0].numpy_view() + binary_segmentation_mask = segmentation_mask > 0.5 + rr.log("video/mask", rr.SegmentationImage(binary_segmentation_mask.astype(np.uint8))) def read_landmark_positions_2d( @@ -98,20 +112,22 @@ def read_landmark_positions_2d( image_width: int, image_height: int, ) -> npt.NDArray[np.float32] | None: - if results.pose_landmarks is None: + if results.pose_landmarks is None or len(results.pose_landmarks) == 0: return None else: - normalized_landmarks = [results.pose_landmarks.landmark[lm] for lm in mp.solutions.pose.PoseLandmark] + pose_landmarks = results.pose_landmarks[0] + normalized_landmarks = [pose_landmarks[lm] for lm in mp_pose.PoseLandmark] return np.array([(image_width * lm.x, image_height * lm.y) for lm in normalized_landmarks]) def read_landmark_positions_3d( results: Any, ) -> npt.NDArray[np.float32] | None: - if results.pose_landmarks is None: + if results.pose_landmarks is None or len(results.pose_landmarks) == 0: return None else: - landmarks = [results.pose_world_landmarks.landmark[lm] for lm in mp.solutions.pose.PoseLandmark] + pose_landmarks = results.pose_landmarks[0] + landmarks = [pose_landmarks[lm] for lm in mp_pose.PoseLandmark] return np.array([(lm.x, lm.y, lm.z) for lm in landmarks]) @@ -144,7 +160,7 @@ def stream_bgr(self) -> Iterator[VideoFrame]: yield VideoFrame(data=bgr, time=time_ms * 1e-3, idx=idx) -def get_downloaded_path(dataset_dir: Path, video_name: str) -> str: +def get_downloaded_video_path(dataset_dir: Path, video_name: str) -> str: video_file_name = f"{video_name}.mp4" destination_path = dataset_dir / video_file_name if destination_path.exists(): @@ -155,12 +171,30 @@ def get_downloaded_path(dataset_dir: Path, video_name: str) -> str: logging.info("Downloading video from %s to %s", source_path, destination_path) os.makedirs(dataset_dir.absolute(), exist_ok=True) - with requests.get(source_path, stream=True) as req: + download(source_path, destination_path) + return str(destination_path) + + +def get_downloaded_model_path(model_dir: Path, model_name: str) -> str: + model_file_name = f"{model_name}.task" + destination_path = model_dir / model_file_name + if destination_path.exists(): + logging.info("%s already exists. No need to download", destination_path) + return str(destination_path) + + model_url = MODEL_URL_TEMPLATE.format(model_name=model_name) + logging.info("Downloading model from %s to %s", model_url, destination_path) + download(model_url, destination_path) + return str(destination_path) + + +def download(url: str, destination_path: Path) -> None: + os.makedirs(destination_path.parent, exist_ok=True) + with requests.get(url, stream=True) as req: req.raise_for_status() with open(destination_path, "wb") as f: for chunk in req.iter_content(chunk_size=8192): f.write(chunk) - return str(destination_path) def main() -> None: @@ -179,6 +213,15 @@ def main() -> None: parser.add_argument("--dataset-dir", type=Path, default=DATASET_DIR, help="Directory to save example videos to.") parser.add_argument("--video-path", type=str, default="", help="Full path to video to run on. Overrides `--video`.") parser.add_argument("--no-segment", action="store_true", help="Don't run person segmentation.") + parser.add_argument( + "--model", + type=str, + default="heavy", + choices=["lite", "full", "heavy"], + help="The mediapipe model to use (see https://developers.google.com/mediapipe/solutions/vision/pose_landmarker).", + ) + parser.add_argument("--model-dir", type=Path, default=MODEL_DIR, help="Directory to save downloaded model to.") + parser.add_argument("--model-path", type=str, default="", help="Full path of mediapipe model. Overrides `--model`.") parser.add_argument( "--max-frame", type=int, @@ -206,9 +249,13 @@ def main() -> None: video_path = args.video_path # type: str if not video_path: - video_path = get_downloaded_path(args.dataset_dir, args.video) + video_path = get_downloaded_video_path(args.dataset_dir, args.video) + + model_path = args.model_path # type: str + if not args.model_path: + model_path = get_downloaded_model_path(args.model_dir, args.model) - track_pose(video_path, segment=not args.no_segment, max_frame_count=args.max_frame) + track_pose(video_path, model_path, segment=not args.no_segment, max_frame_count=args.max_frame) rr.script_teardown(args) diff --git a/examples/python/human_pose_tracking/requirements.txt b/examples/python/human_pose_tracking/requirements.txt index 5bec67ecf1ad..1e5ae4bfa766 100644 --- a/examples/python/human_pose_tracking/requirements.txt +++ b/examples/python/human_pose_tracking/requirements.txt @@ -1,6 +1,5 @@ # no 3.12 version yet (https://pypi.org/project/mediapipe/) -# 0.10.10 no longer supports the legacy Pose model: https://github.com/rerun-io/rerun/issues/5859 -mediapipe==0.10.9 ; python_version <= '3.11' +mediapipe==0.10.11 ; python_version <= '3.11' numpy opencv-python>4.6 # Avoid opencv-4.6 since it rotates images incorrectly (https://github.com/opencv/opencv/issues/22088) From 6ad276691052f9fafeb3cae9364f856764a2733e Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 14:29:43 +0200 Subject: [PATCH 257/508] Don't build examples on each PR (#5910) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Part of https://github.com/rerun-io/rerun/issues/3033 ### What It takes almost 3 minutes per PR. Pro: * I don't remember it ever catching a bug * I usually test the latest examples from `main` or `nightly` anyway Con: * No example size diff comparisons per PR * This breaks the url, unless I also update the default manifest 🤔 Total duration: 12m -> 8m Billable time: 51m -> 43m ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using default manifest (nightly): [rerun.io/viewer](https://rerun.io/viewer/pr/5910) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5910?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5910?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5910) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/pull_request_template.md | 1 - .github/workflows/on_pull_request.yml | 31 ------------------- .github/workflows/on_push_main.yml | 1 + .github/workflows/reusable_checks_cpp.yml | 20 ++++++++---- .github/workflows/reusable_track_size.yml | 14 ++++++--- .../src/ui/welcome_screen/example_section.rs | 13 +------- 6 files changed, 26 insertions(+), 54 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 0324b1da38a0..ceda6c04134c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -16,7 +16,6 @@ To get an auto-generated PR description you can put "copilot:summary" or "copilo * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): - * Using newly built examples: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}) * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 980c54402080..61cd0097cc28 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -185,37 +185,6 @@ jobs: PR_NUMBER: ${{ github.event.pull_request.number }} secrets: inherit - build-examples: - name: "Build Examples" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' - needs: [min-wheel-build] - uses: ./.github/workflows/reusable_build_examples.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - CHANNEL: main - WHEEL_ARTIFACT_NAME: linux-x64-wheel-fast - secrets: inherit - - track-sizes: - name: "Track Sizes" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' - needs: [build-web, build-examples] - uses: ./.github/workflows/reusable_track_size.yml - with: - CONCURRENCY: push-${{ github.ref_name }} - PR_NUMBER: ${{ github.event.pull_request.number }} - secrets: inherit - - upload-examples: - name: "Upload Examples" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' - needs: [build-examples] - uses: ./.github/workflows/reusable_upload_examples.yml - with: - CONCURRENCY: pr-${{ github.event.pull_request.number }} - PR_NUMBER: ${{ github.event.pull_request.number }} - secrets: inherit - save-pr-summary: name: "Save PR Summary" if: github.event.pull_request.head.repo.owner.login == 'rerun-io' diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 8221e7c741c4..630f8f5204b6 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -109,6 +109,7 @@ jobs: uses: ./.github/workflows/reusable_track_size.yml with: CONCURRENCY: push-${{ github.ref_name }} + WITH_EXAMPLES: true secrets: inherit upload-examples: diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index 406ac548cca8..8bfde9212e56 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -92,13 +92,21 @@ jobs: # using leading to random crashes: https://reviews.llvm.org/D148280 run: sudo sysctl vm.mmap_rnd_bits=28 - - name: Build and run C++ tests + - name: pixi run cpp-clean shell: bash - run: | - pixi run cpp-clean - ${{ matrix.extra_env_vars }} RERUN_WERROR=ON pixi run cpp-build-all - ${{ matrix.extra_env_vars }} RERUN_WERROR=ON pixi run cpp-test - ${{ matrix.additional_commands }} + run: pixi run cpp-clean + + - name: pixi run cpp-build-all + shell: bash + run: ${{ matrix.extra_env_vars }} RERUN_WERROR=ON pixi run cpp-build-all + + - name: pixi run cpp-test + shell: bash + run: ${{ matrix.extra_env_vars }} RERUN_WERROR=ON pixi run cpp-test + + - name: additional_commands + shell: bash + run: ${{ matrix.additional_commands }} cpp-formatting: name: C++ formatting check diff --git a/.github/workflows/reusable_track_size.yml b/.github/workflows/reusable_track_size.yml index 0dc0ce530c32..522768353b97 100644 --- a/.github/workflows/reusable_track_size.yml +++ b/.github/workflows/reusable_track_size.yml @@ -9,6 +9,9 @@ on: PR_NUMBER: required: false type: number + WITH_EXAMPLES: + required: true + type: boolean permissions: contents: write @@ -50,6 +53,7 @@ jobs: path: web_viewer - name: Download examples + if: ${{ inputs.WITH_EXAMPLES }} uses: actions/download-artifact@v4 with: name: example_data @@ -92,10 +96,12 @@ jobs: entries+=("Wasm:web_viewer/re_viewer_bg.wasm:MiB") entries+=("JS:web_viewer/re_viewer.js:kiB") - for file in example_data/*.rrd; do - name=$(basename "$file") - entries+=("$name:$file:MiB") - done + if [ -n ${{ inputs.WITH_EXAMPLES }} = "true" ]; then + for file in example_data/*.rrd; do + name=$(basename "$file") + entries+=("$name:$file:MiB") + done + fi python3 scripts/ci/count_bytes.py "${entries[@]}" > /tmp/sizes.json diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index 52ab28610480..d0280e5e9144 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -173,7 +173,6 @@ fn default_manifest_url() -> String { } let build_info = re_build_info::build_info!(); - let short_sha = build_info.short_git_hash(); if build_info.version.is_rc() || build_info.version.is_release() { // If this is versioned as a release or rc, always point to the versioned @@ -182,19 +181,9 @@ fn default_manifest_url() -> String { "https://app.rerun.io/version/{version}/examples_manifest.json", version = build_info.version, ) - } else if build_info.is_in_rerun_workspace { - // Otherwise, always point to `version/nightly` for rerun devs, - // because the current commit's manifest is unlikely to be uploaded to GCS. - // We could point to the main branch, but it's not always finished building, and so doesn't always work. - "https://app.rerun.io/version/nightly/examples_manifest.json".into() - } else if !short_sha.is_empty() { - // If we have a sha, try to point at it. - format!("https://app.rerun.io/commit/{short_sha}/examples_manifest.json") } else { - // If all else fails, point to the nightly branch + // We don't build examples on each PR, so we don't have much to point to except for the nightly examples // We could point to the main branch, but it's not always finished building, and so doesn't always work. - // TODO(#4729): this is better than nothing but still likely to have version - // compatibility issues. "https://app.rerun.io/version/nightly/examples_manifest.json".into() } } From 07e1a4a9360569e16e86f2ba9da5eeb8dd37c5a8 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 16:24:24 +0200 Subject: [PATCH 258/508] Improve the "What is Rerun?" documentation (#5920) ### What [Rendered](https://github.com/rerun-io/rerun/blob/emilk/what-is-rerun/docs/content/getting-started/what-is-rerun.md#what-is-rerun-for) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5920?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5920?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5920) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- README.md | 4 +++ docs/content/getting-started/what-is-rerun.md | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/README.md b/README.md index 192e0a67f09d..02e832749897 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ Use the Rerun SDK (available for C++, Python and Rust) to log data like images, tensors, point clouds, and text. Logs are streamed to the Rerun Viewer for live visualization or to file for later use. +* [Run the Rerun Viewer in your browser](https://www.rerun.io/viewer) +* [Read about what Rerun is and who it is for](https://www.rerun.io/docs/getting-started/what-is-rerun) + +### A short taste ```py import rerun as rr # pip install rerun-sdk diff --git a/docs/content/getting-started/what-is-rerun.md b/docs/content/getting-started/what-is-rerun.md index bc40a17dd238..ddda4cd3c52b 100644 --- a/docs/content/getting-started/what-is-rerun.md +++ b/docs/content/getting-started/what-is-rerun.md @@ -38,6 +38,32 @@ That's a big question for a welcome page. The short answer is that Rerun goes to extreme lengths to make handling and visualizing multimodal data streams easy and performant. +## What is Rerun for? +Rerun is built to help you understand complex processes that include rich multimodal data, including 2D, 3D, text, time series, tensors, etc. +It is used in many industries, including robotics, simulation, computer vision, or anything that involves a lot of sensors. +Let's look at a more concrete example: + +### Example use case +Say you're building a vacuum cleaning robot and it keeps running into walls. Why is it doing that? You need some tool to debug it, but a normal debugger isn't gonna be helpful. Similarly, just logging text won't be very helpful either. The robot may log "Going through doorway" but that won't explain why it thinks the wall is a door. + +What you need is a visual and temporal debugger, that can log all the different representations of the world the robots holds in its little head, such as: + +* RGB camera feed +* depth images +* lidar scan +* segmentation image (how the robot interprets what it sees) +* its 3D map of the apartment +* all the objects the robot has detected (or thinks it has detected), as 3D shapes in the 3D map +* its confidence in its prediction +* etc + +You also want to see how all these streams of data evolve over time so you can go back and pinpoint exactly what went wrong, when and why. + +Maybe it turns out that a glare from the sun hit one of the sensors in the wrong way, confusing the segmentation network leading to bad object detection. Or maybe it was a bug in the lidar scanning code. Or maybe the robot thought it were somewhere else in the apartment, because its odometry was broken. Or it could be one of a thousand other things. Rerun will help you find out! + +But seeing the world from the point of the view of the robot is not just for debugging - it will also give you ideas on how to improve the algorithms. It will also let you explain the brains of the robot to your colleagues, boss, and customers. And so on. Seeing is believing, and an image is worth a thousand words, and multimodal temporal logging is worth a thousand images :) + +Of course, Rerun is useful for much more than just robots. Any time you have any for of sensors, or 2D or 3D state evolving over time, Rerun would be a great tool. ## Can't find what you're looking for? From b572c1163071e0e4d7c451363d6c91ead1693520 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Thu, 11 Apr 2024 17:22:09 +0200 Subject: [PATCH 259/508] Rust: no incremental compilation on CI (#5921) Make sure to disable incremental compilation everywhere to ease sccache's job. --- .github/actions/setup-rust/action.yml | 12 ------------ .github/workflows/contrib_checks.yml | 11 +++++++++++ .github/workflows/contrib_rerun_py.yml | 12 ++++++++++++ .github/workflows/on_push_main.yml | 3 --- .github/workflows/reusable_bench.yml | 8 ++++++++ .../workflows/reusable_build_and_upload_rerun_c.yml | 11 +++++++++++ .../reusable_build_and_upload_rerun_cli.yml | 11 +++++++++++ .../workflows/reusable_build_and_upload_wheels.yml | 9 +++++++++ .github/workflows/reusable_build_examples.yml | 11 +++++++++++ .github/workflows/reusable_build_js.yml | 11 +++++++++++ .github/workflows/reusable_build_web.yml | 11 +++++++++++ .github/workflows/reusable_checks.yml | 10 ++++++++-- .github/workflows/reusable_checks_cpp.yml | 8 ++++++-- .github/workflows/reusable_checks_rust.yml | 12 ++++++++---- .github/workflows/reusable_deploy_docs.yml | 11 ++++++++++- .github/workflows/reusable_test_wheels.yml | 8 ++++++++ 16 files changed, 135 insertions(+), 24 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index c03212566dc7..b069bcd20ba1 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -1,7 +1,6 @@ # This action sets up: # - The correct version of Rust based on the `rust-toolchain` file # - All components + targets specified in `rust-toolchain` -# - Caching of dependencies via `Swatinem/rust-cache` # - Caching of individual compilation requests via `sccache` and GCS # - Uses our own `rerun-io/sccache-action` which supports GCS # @@ -53,17 +52,6 @@ runs: run: rustup target add ${{ inputs.targets }} shell: bash - # Rust-cache will cache our dependencies, which is a large chunk of the build - # See: https://github.com/Swatinem/rust-cache - - name: Set up rust-cache - uses: Swatinem/rust-cache@v2 - with: - # Only save the cache when on the main branch. - # The cache is quite limited in size (~10 GB), and the - # individual rust-cache entries are as much as 2 GB. - save-if: ${{ inputs.save_cache && github.ref == 'refs/heads/main' }} - shared-key: ${{ inputs.cache_key }} - - name: Set up sccache uses: rerun-io/sccache-action@v0.7.0 with: diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 3a1eeb01f4e9..fdcd7a3206cb 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -25,6 +25,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. + # See: https://github.com/marketplace/actions/sccache-action + SCCACHE_GHA_ENABLED: "false" + + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 7dd1f11879c7..bc510f9ba993 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -17,6 +17,7 @@ concurrency: env: PYTHON_VERSION: "3.8" + # web_sys_unstable_apis is required to enable the web_sys clipboard API which egui_web uses # https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html # https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html @@ -28,6 +29,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. + # See: https://github.com/marketplace/actions/sccache-action + SCCACHE_GHA_ENABLED: "false" + + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 630f8f5204b6..2b84fa2c8df3 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -49,9 +49,6 @@ jobs: with: toolchain: 1.76.0 - - name: Set up cargo cache - uses: Swatinem/rust-cache@v2 - - run: cargo build -p rerun shell: bash diff --git a/.github/workflows/reusable_bench.yml b/.github/workflows/reusable_bench.yml index 27bb88638884..751132abe5ae 100644 --- a/.github/workflows/reusable_bench.yml +++ b/.github/workflows/reusable_bench.yml @@ -33,9 +33,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. # See: https://github.com/marketplace/actions/sccache-action SCCACHE_GHA_ENABLED: "false" + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + jobs: # --------------------------------------------------------------------------- diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml index b817245809ed..3b0a33d6d637 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_c.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml @@ -54,6 +54,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. + # See: https://github.com/marketplace/actions/sccache-action + SCCACHE_GHA_ENABLED: "false" + + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" id-token: "write" diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index b5efe599dd73..c64afb3c53e1 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -55,6 +55,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. + # See: https://github.com/marketplace/actions/sccache-action + SCCACHE_GHA_ENABLED: "false" + + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" id-token: "write" diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 532049233707..433d7337798f 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -63,6 +63,7 @@ concurrency: env: PYTHON_VERSION: "3.8" + # web_sys_unstable_apis is required to enable the web_sys clipboard API which egui_web uses # https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html # https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html @@ -74,9 +75,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. # See: https://github.com/marketplace/actions/sccache-action SCCACHE_GHA_ENABLED: "false" + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" id-token: "write" diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 24f5918d9cbd..8833bb30bb8c 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -26,6 +26,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. + # See: https://github.com/marketplace/actions/sccache-action + SCCACHE_GHA_ENABLED: "false" + + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + jobs: rs-build-examples: name: Build Examples diff --git a/.github/workflows/reusable_build_js.yml b/.github/workflows/reusable_build_js.yml index 3d7eb6b63772..ac02d36e95ac 100644 --- a/.github/workflows/reusable_build_js.yml +++ b/.github/workflows/reusable_build_js.yml @@ -20,6 +20,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. + # See: https://github.com/marketplace/actions/sccache-action + SCCACHE_GHA_ENABLED: "false" + + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + jobs: build: name: Build rerun_js diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index af4a8865fce1..9ab4919adc11 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -27,6 +27,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. + # See: https://github.com/marketplace/actions/sccache-action + SCCACHE_GHA_ENABLED: "false" + + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + jobs: rs-build-web-viewer: name: Build web viewer diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index dc50790faa3a..9c4c4867c17e 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -21,9 +21,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. # See: https://github.com/marketplace/actions/sccache-action SCCACHE_GHA_ENABLED: "false" + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" id-token: "write" @@ -71,8 +79,6 @@ jobs: no-codegen-changes: name: Check if running codegen would produce any changes runs-on: ubuntu-latest-16-cores - env: - RUSTC_WRAPPER: "sccache" steps: # Note: We explicitly don't override `ref` here. We need to see if changes would be made # in a context where we have merged with main. Otherwise we might miss changes such as one diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index 8bfde9212e56..a39c5909e8c8 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -34,6 +34,12 @@ env: # See: https://github.com/marketplace/actions/sccache-action SCCACHE_GHA_ENABLED: "false" + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" id-token: "write" @@ -64,8 +70,6 @@ jobs: strategy: matrix: ${{ fromJson(needs.matrix_prep.outputs.MATRIX) }} runs-on: ${{ matrix.runs_on }} - env: - RUSTC_WRAPPER: "sccache" steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index f2f53b2771bc..0f9a4cb0b4aa 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -24,9 +24,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. # See: https://github.com/marketplace/actions/sccache-action SCCACHE_GHA_ENABLED: "false" + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" id-token: "write" @@ -37,8 +45,6 @@ jobs: rs-lints: name: Rust lints (fmt, check, cranky, tests, doc) runs-on: ubuntu-latest-16-cores - env: - RUSTC_WRAPPER: "sccache" steps: - uses: actions/checkout@v4 with: @@ -83,8 +89,6 @@ jobs: rs-check-wasm: name: Check Rust web build (wasm32 + wasm-bindgen) runs-on: ubuntu-latest-16-cores - env: - RUSTC_WRAPPER: "sccache" steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index aadaa701e7b6..b451baf0a884 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -36,6 +36,7 @@ permissions: env: PYTHON_VERSION: "3.8" + # web_sys_unstable_apis is required to enable the web_sys clipboard API which egui_web uses # https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html # https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html @@ -44,8 +45,16 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. # See: https://github.com/marketplace/actions/sccache-action - SCCACHE_GHA_ENABLED: "true" + SCCACHE_GHA_ENABLED: "false" + + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" jobs: # --------------------------------------------------------------------------- diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index a45e76e9efd7..c4e3efdef7ef 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -39,9 +39,17 @@ env: # See https://github.com/ericseppanen/cargo-cranky/issues/8 RUSTDOCFLAGS: --deny warnings --deny rustdoc::missing_crate_level_docs + # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. # See: https://github.com/marketplace/actions/sccache-action SCCACHE_GHA_ENABLED: "false" + # Wrap every `rustc` invocation in `sccache`. + RUSTC_WRAPPER: "sccache" + + # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all + # these incremental artifacts when running on CI. + CARGO_INCREMENTAL: "0" + permissions: contents: "read" id-token: "write" From 4ab977556ccab3346f5456254afad8379a69cdc1 Mon Sep 17 00:00:00 2001 From: Maxim Bonnaerens Date: Thu, 11 Apr 2024 17:22:50 +0200 Subject: [PATCH 260/508] Update Python API links to getting-started and tutorial (#5923) Links to tutorial and getting started on https://ref.rerun.io/docs/python/0.15.0/common/ are broken, I believe this should fix it. --- rerun_py/docs/gen_common_index.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index e2272d1a3fb8..2c1cca4fbaf8 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -370,8 +370,8 @@ def make_slug(s: str) -> str: index_file.write( """ ## Getting Started -* [Quick start](https://www.rerun.io/docs/getting-started/python) -* [Tutorial](https://www.rerun.io/docs/getting-started/logging-python) +* [Quick start](https://www.rerun.io/docs/getting-started/quick-start/python) +* [Tutorial](https://www.rerun.io/docs/getting-started/data-in/python) * [Examples on GitHub](https://github.com/rerun-io/rerun/tree/latest/examples/python) * [Troubleshooting](https://www.rerun.io/docs/getting-started/troubleshooting) From 69ce7d4ffd8999ebb2c77d5649e6822dd6e7290f Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 17:29:04 +0200 Subject: [PATCH 261/508] Add 0.15.1 to changelog (#5926) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) - [PR Build Summary](https://build.rerun.io/pr/5926) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08e8efbfbc22..ccc0352f5389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,12 @@ ## [Unreleased](https://github.com/rerun-io/rerun/compare/latest...HEAD) -## [0.15.0](https://github.com/rerun-io/rerun/compare/0.14.1...0.15.0) - Blueprints from Python - 2024-04-**09** +## [0.15.1](https://github.com/rerun-io/rerun/compare/0.15.1...0.15.0) - Bug fix for notebooks - 2024-04-11 +- Fix timeout in notebooks by making the `app_url` correctly point to `app.rerun.io` [#5877](https://github.com/rerun-io/rerun/pull/5877) +- CMake: Allow to call `find_package(rerun_sdk)` two or more times [#5886](https://github.com/rerun-io/rerun/pull/5886) (thanks [@traversaro](https://github.com/traversaro)!) + + +## [0.15.0](https://github.com/rerun-io/rerun/compare/0.14.1...0.15.0) - Blueprints from Python - 2024-04-09 The biggest news is the ability to create a _blueprint_ via the Python logging API. Check out our [associated blog post](https://www.rerun.io/blog/blueprint-part-one) for more information. ```py From c45073b8e88d06a5f460a9ba3192973ab6283cee Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 11 Apr 2024 18:01:33 +0200 Subject: [PATCH 262/508] Merge 0.15.1 notebook fix to `main` (#5928) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) - [PR Build Summary](https://build.rerun.io/pr/5928) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --------- Co-authored-by: Andreas Reich Co-authored-by: Clement Rey Co-authored-by: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Co-authored-by: Jeremy Leibs --- CHANGELOG.md | 1 - examples/python/ros_node/README.md | 2 +- rerun_py/src/python_bridge.rs | 17 ++++++++++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccc0352f5389..cb61acae9cd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -504,7 +504,6 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi ## [0.12.0](https://github.com/rerun-io/rerun/compare/0.11.0...0.12.0) - Data Loaders, Container-editing, Python-3.12 - 2024-01-09 -### ✨ Overview & highlights ### ✨ Overview & highlights - 🌁 The Rerun Viewer now supports a plugin system for creating [arbitrary external data loaders](https://www.rerun.io/docs/reference/data-loaders/overview). - 🕸️ More built-in examples are now available in the viewer. diff --git a/examples/python/ros_node/README.md b/examples/python/ros_node/README.md index 8174a5d3250c..c9041402daac 100644 --- a/examples/python/ros_node/README.md +++ b/examples/python/ros_node/README.md @@ -1,6 +1,6 @@ diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index 8dd6e1f64ef3..2cdf41bd8fe3 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -1096,7 +1096,7 @@ fn version() -> String { /// Get a url to an instance of the web-viewer /// -/// This may point to rerun.io/viewer or localhost depending on +/// This may point to app.rerun.io or localhost depending on /// whether [`start_web_viewer_server()`] was called. #[pyfunction] fn get_app_url() -> String { @@ -1106,13 +1106,20 @@ fn get_app_url() -> String { } let build_info = re_build_info::build_info!(); - if let Some(short_git_hash) = build_info.git_hash.get(..7) { - format!("https://rerun.io/viewer/commit/{short_git_hash}") + + // Note that it is important to us `app.rerun.io` directly here. The version hosted + // at `rerun.io/viewer` is not designed to be embedded in a notebook and interferes + // with the startup sequencing. Do not switch to `rerun.io/viewer` without considering + // the implications. + if build_info.is_final() { + format!("https://app.rerun.io/version/{}", build_info.version) + } else if let Some(short_git_hash) = build_info.git_hash.get(..7) { + format!("https://app.rerun.io/commit/{short_git_hash}") } else { re_log::warn_once!( - "No valid git hash found in build info. Defaulting to rerun.io/viewer for app url." + "No valid git hash found in build info. Defaulting to app.rerun.io for app url." ); - "https://rerun.io/viewer".to_owned() + "https://app.rerun.io".to_owned() } } From 1a61e9812034d5ed783fc45e2f21b61a7842795f Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Thu, 11 Apr 2024 18:20:24 +0200 Subject: [PATCH 263/508] Don't redeploy rerun.io before the web artifacts have shipped (#5929) - Fixes #5924, I hope. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5929?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5929?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5929) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ee3f98c6bcce..b823995203f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -212,7 +212,7 @@ jobs: update-docs: name: "Update Docs" - needs: [version] + needs: [version, publish-web] uses: ./.github/workflows/reusable_deploy_docs.yml with: CONCURRENCY: ${{ github.ref_name }} From 6861093531687d5c0a3cbac6e02c1f569ef66a8e Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 11 Apr 2024 20:00:27 +0200 Subject: [PATCH 264/508] Remove remaining shell scripts, fix rust wasm checks for ci (#5922) ### What Part of * #3717 After this PR, the only .sh files in the repo are `ci_docker/publish.sh` and `pre-push.sh`. The former is hopefully going away together with the docker, the later can stay. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5922?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5922?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5922) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_checks.yml | 105 +-------------------- .github/workflows/reusable_checks.yml | 34 +------ .github/workflows/reusable_checks_rust.yml | 74 +-------------- CONTRIBUTING.md | 2 +- pixi.toml | 4 + scripts/check.sh | 50 ---------- scripts/ci/cargo_deny.sh | 20 ---- scripts/ci/check_large_files.py | 35 +++++++ scripts/ci/check_large_files.sh | 24 ----- scripts/ci/rust_checks.py | 50 ++++++++-- scripts/clippy_wasm.sh | 15 --- 11 files changed, 93 insertions(+), 320 deletions(-) delete mode 100755 scripts/check.sh delete mode 100755 scripts/ci/cargo_deny.sh create mode 100755 scripts/ci/check_large_files.py delete mode 100755 scripts/ci/check_large_files.sh delete mode 100755 scripts/clippy_wasm.sh diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index fdcd7a3206cb..880fb5849c26 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -109,91 +109,8 @@ jobs: steps: - uses: actions/checkout@v4 - # First do our check with --locked to make sure `Cargo.lock` is up to date - - name: Check all features - uses: actions-rs/cargo@v1 - with: - command: check - args: --locked --all-features - - - name: Rustfmt - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check - - - name: Cranky - uses: actions-rs/cargo@v1 - with: - command: cranky - args: --all-targets --all-features -- --deny warnings - - # Check a few important permutations of the feature flags for our `rerun` library: - - name: Check rerun with `--no-default-features`` - uses: actions-rs/cargo@v1 - with: - command: cranky - args: --locked -p rerun --no-default-features - - - name: Check rerun with `--features sdk` - uses: actions-rs/cargo@v1 - with: - command: cranky - args: --locked -p rerun --no-default-features --features sdk - - - name: Test doc-tests - uses: actions-rs/cargo@v1 - with: - command: test - args: --doc --all-features - - - name: cargo doc - uses: actions-rs/cargo@v1 - with: - command: doc - args: --no-deps --all-features --workspace - - - name: cargo doc --document-private-items - uses: actions-rs/cargo@v1 - with: - command: doc - args: --document-private-items --no-deps --all-features --workspace - - # Just a normal `cargo test` should always work: - - name: cargo test --all-targets - uses: actions-rs/cargo@v1 - with: - command: test - - # Full test of everything: - - name: cargo test --all-targets --all-features - uses: actions-rs/cargo@v1 - with: - command: test - args: --all-targets --all-features - - rs-check-wasm: - name: Check Rust web build (wasm32 + wasm-bindgen) - runs-on: ubuntu-latest-16-cores - steps: - - uses: actions/checkout@v4 - - - name: clippy check re_viewer wasm32 - shell: bash - run: ./scripts/clippy_wasm.sh - - - name: Check re_renderer examples wasm32 - uses: actions-rs/cargo@v1 - with: - command: check - args: --locked --target wasm32-unknown-unknown --target-dir target_wasm -p re_renderer --examples - - - name: Build web-viewer (release) - uses: actions-rs/cargo@v1 - with: - command: run - # We build in release so that we can reuse the results for actual publishing, if necessary - args: --locked -p re_build_web_viewer -- --release -g + - name: Rust checks & tests + run: pixi run rs-check --skip-check-individual-crates misc-rerun-lints: name: Rerun lints @@ -217,9 +134,7 @@ jobs: run: pixi run toml-fmt-check - name: Check for too large files - shell: bash - run: | - pixi run ./scripts/ci/check_large_files.sh + run: pixi run check-large-files - name: Check Python example requirements shell: bash @@ -241,20 +156,6 @@ jobs: - name: Check spelling of entire workspace uses: crate-ci/typos@v1.18.0 - rs-cargo-deny: - name: cargo-deny - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install cargo-deny - run: cargo install --locked --quiet cargo-deny - - - name: Cargo Deny - shell: bash - id: expected_version - run: ./scripts/ci/cargo_deny.sh - cpp-formatting: name: C++ formatting check runs-on: ubuntu-latest diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 9c4c4867c17e..b7a751d9987f 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -37,28 +37,6 @@ permissions: id-token: "write" jobs: - # --------------------------------------------------------------------------- - - py-lints: - name: Python lints (ruff, mypy, …) - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - - uses: prefix-dev/setup-pixi@v0.4.1 - with: - pixi-version: v0.18.0 - - - name: Python format check - run: pixi run py-fmt-check - - - name: Lint Python - run: pixi run py-lint - - # --------------------------------------------------------------------------- - py-test-docs: name: Test Python Docs runs-on: ubuntu-latest @@ -135,19 +113,13 @@ jobs: # pixi run ./scripts/zombie_todos.py --token ${{ secrets.GITHUB_TOKEN }} - name: Check for too large files - shell: bash - run: | - ./scripts/ci/check_large_files.sh + run: pixi run check-large-files - name: Check Python example requirements - shell: bash - run: | - pixi run ./scripts/ci/check_requirements.py + run: pixi run ./scripts/ci/check_requirements.py - name: Check Python example thumbnails - shell: bash - run: | - pixi run ./scripts/ci/thumbnails.py check + run: pixi run ./scripts/ci/thumbnails.py check # --------------------------------------------------------------------------- diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 0f9a4cb0b4aa..a18c167cb6ee 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -69,82 +69,14 @@ jobs: run: | pixi run cargo run --locked -p re_build_web_viewer -- --release -g - - name: install cargo cranky - run: cargo install --locked --quiet cargo-cranky - - name: Rust checks & tests if: ${{ inputs.CHANNEL == 'pr' }} - run: ./scripts/ci/rust_checks.py --skip-check-individual-crates --skip-test + run: pixi run rs-check --skip-check-individual-crates --skip-wasm-checks --skip-test - name: Rust checks & tests if: ${{ inputs.CHANNEL == 'main' }} - run: ./scripts/ci/rust_checks.py --skip-check-individual-crates + run: pixi run rs-check --skip-check-individual-crates - name: Rust all checks & tests if: ${{ inputs.CHANNEL == 'nightly' }} - run: ./scripts/ci/rust_checks.py - - # --------------------------------------------------------------------------- - - rs-check-wasm: - name: Check Rust web build (wasm32 + wasm-bindgen) - runs-on: ubuntu-latest-16-cores - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - - name: Set up Rust - uses: ./.github/actions/setup-rust - with: - cache_key: "build-web" - save_cache: true - workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - # NOTE: Fails with sccache -- refactor incoming in a follow-up PR. - # - name: clippy check re_viewer wasm32 - # shell: bash - # run: ./scripts/clippy_wasm.sh - - - name: Check re_renderer examples wasm32 - uses: actions-rs/cargo@v1 - with: - command: check - args: --locked --target wasm32-unknown-unknown --target-dir target_wasm -p re_renderer --examples - - - uses: prefix-dev/setup-pixi@v0.4.1 - with: - pixi-version: v0.18.0 - - # We build in release so that we can reuse the results for actual publishing, if necessary - - name: Build web-viewer (release) - shell: bash - run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release -g - - # --------------------------------------------------------------------------- - - rs-cargo-deny: - name: cargo-deny - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - - name: Set up Rust - uses: ./.github/actions/setup-rust - with: - cache_key: "rs-cargo-deny" - save_cache: true - workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - - name: Install cargo-deny - run: cargo install --locked --quiet cargo-deny - - - name: Cargo Deny - shell: bash - id: expected_version - run: ./scripts/ci/cargo_deny.sh + run: pixi run rs-check diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6742ff586f19..4f51c579b1d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,7 +122,7 @@ We use [cargo deny](https://github.com/EmbarkStudios/cargo-deny) to check our de Configure your editor to run `cargo fmt` on save. Also configure it to strip trailing whitespace, and to end each file with a newline. Settings for VSCode can be found in the `.vscode` folder and should be applied automatically. If you are using another editor, consider adding good setting to this repository! -To check everything in one go, run `./scripts/check.sh`. `check.sh` should ideally check approximately the same things as our CI. +Depending on the changes you made run `cargo test --all-targets --all-features`, `pixi run py-test` and `pixi run cpp-test` locally. ### Linting Prior to pushing changes to a PR, at a minimum, you should always run `pixi run fast-lint`. This is designed to run diff --git a/pixi.toml b/pixi.toml index cf53d0ba2abc..00eddd2dd152 100644 --- a/pixi.toml +++ b/pixi.toml @@ -79,6 +79,8 @@ rerun-web-release = { cmd = "cargo run --package rerun-cli --no-default-features # (this looks heavy but takes typically below 0.1s!) rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --release -g" +rs-check = "rustup target add wasm32-unknown-unknown && python scripts/ci/rust_checks.py" + build-examples = "cargo run -q --locked -p re_build_examples --" # Code formatting for all languages. @@ -155,6 +157,8 @@ rs-update-insta-tests = "cargo test && cargo insta review" # Upload image to gcloud storage. upload-image = "python scripts/upload_image.py" +# Check whether there's too large files in the repository. +check-large-files = "python scripts/ci/check_large_files.py" [feature.py-docs.tasks] # Serve python docs locally diff --git a/scripts/check.sh b/scripts/check.sh deleted file mode 100755 index e52bc922b731..000000000000 --- a/scripts/check.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash -# This scripts runs various CI-like checks in a convenient way. -# This is likely outdated, but can still be useful. - -set -eu -script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -cd "$script_path/.." -set -x - -export RUSTFLAGS="--deny warnings" - -# https://github.com/ericseppanen/cargo-cranky/issues/8 -export RUSTDOCFLAGS="--deny warnings --deny rustdoc::missing_crate_level_docs" - -export RERUN_WERROR=ON - -# Fast things first: -typos -cargo fmt --all -- --check -pixi run lint-rerun -./scripts/ci/cargo_deny.sh -pixi run cpp-test -just py-lint - -cargo check --all-targets --all-features -cargo check -p re_viewer --all-features --target wasm32-unknown-unknown --target-dir target_wasm -cargo cranky --all-targets --all-features -- --deny warnings -cargo test --all-targets --all-features -cargo test --doc --all-features # checks all doc-tests - -cargo doc --no-deps --all-features -cargo doc --document-private-items --no-deps --all-features - -(cd crates/re_log_types && cargo check --no-default-features) -(cd crates/re_viewer && cargo check --no-default-features) -(cd crates/re_web_viewer_server && cargo check --no-default-features) -(cd crates/re_ws_comms && cargo check --no-default-features) -(cd crates/rerun && cargo check --no-default-features) -(cd examples/rust/objectron && cargo check --no-default-features) - -(cd crates/re_log_types && cargo check --all-features) -(cd crates/re_viewer && cargo check --all-features) -(cd crates/re_web_viewer_server && cargo check --all-features) -(cd crates/re_ws_comms && cargo check --all-features) -(cd crates/rerun && cargo check --all-features) -(cd examples/rust/objectron && cargo check --all-features) - -cargo run -p re_build_web_viewer -- --debug - -echo "All checks passed!" diff --git a/scripts/ci/cargo_deny.sh b/scripts/ci/cargo_deny.sh deleted file mode 100755 index 6cf700132b8c..000000000000 --- a/scripts/ci/cargo_deny.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -set -eu -script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -cd "$script_path/../.." -set -x - -cargo install --locked --quiet cargo-deny - -cargo deny --all-features --log-level error --target aarch64-apple-darwin check -cargo deny --all-features --log-level error --target i686-pc-windows-gnu check -cargo deny --all-features --log-level error --target i686-pc-windows-msvc check -cargo deny --all-features --log-level error --target i686-unknown-linux-gnu check -cargo deny --all-features --log-level error --target wasm32-unknown-unknown check -cargo deny --all-features --log-level error --target x86_64-apple-darwin check -cargo deny --all-features --log-level error --target x86_64-pc-windows-gnu check -cargo deny --all-features --log-level error --target x86_64-pc-windows-msvc check -cargo deny --all-features --log-level error --target x86_64-unknown-linux-gnu check -cargo deny --all-features --log-level error --target x86_64-unknown-linux-musl check -cargo deny --all-features --log-level error --target x86_64-unknown-redox check diff --git a/scripts/ci/check_large_files.py b/scripts/ci/check_large_files.py new file mode 100755 index 000000000000..78d772cb877e --- /dev/null +++ b/scripts/ci/check_large_files.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import os +import subprocess + +#!/usr/bin/env python3 + +# Check for files that are too large to be checked into the repository. +# Whenever we want to make an exception, we add it to `check_large_files_allow_list.txt` + +# Maximum file size, unless found in `check_large_files_allow_list.txt` +maximum_size = 100 * 1024 + +result = 0 +script_path = os.path.dirname(os.path.realpath(__file__)) +os.chdir(os.path.join(script_path, "../..")) + +# Get the list of tracked files using git ls-files command +tracked_files = subprocess.check_output(["git", "ls-files"]).decode().splitlines() + +for file_path in tracked_files: + actual_size = os.path.getsize(file_path) + + if actual_size >= maximum_size: + allow_list_path = os.path.join(script_path, "check_large_files_allow_list.txt") + + with open(allow_list_path) as allow_list_file: + allow_list = allow_list_file.read().splitlines() + + if file_path not in allow_list: + print(f"{file_path} is {actual_size} bytes (max allowed is {maximum_size} bytes)") + result = 1 + +print(f"checked {len(tracked_files)} files") +exit(result) diff --git a/scripts/ci/check_large_files.sh b/scripts/ci/check_large_files.sh deleted file mode 100755 index abe080ee5441..000000000000 --- a/scripts/ci/check_large_files.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash -# Check for files that are too large to be checked into the repository. -# Whenever we want to make an exception, we add it to `check_large_files_allow_list.txt` -set -eu -script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -cd "$script_path/../.." - -# Maximum file size, unless found in `check_large_files_allow_list.txt` -maximum_size=$((100 * 1024)) - -result=0 -while read -d '' -r file; do - if [[ -f "$file" ]]; then - actualsize=$(wc -c <"$file") - if [ $actualsize -ge $maximum_size ]; then - if ! grep -qx "$file" ./scripts/ci/check_large_files_allow_list.txt; then - echo "$file is $actualsize byte (max allowed is $maximum_size bytes)" - result=1 - fi - fi - fi -done < <(git ls-files -z --empty-directory) - -exit $result diff --git a/scripts/ci/rust_checks.py b/scripts/ci/rust_checks.py index 2936bc4dd48b..ff5305b182c3 100755 --- a/scripts/ci/rust_checks.py +++ b/scripts/ci/rust_checks.py @@ -20,7 +20,11 @@ def __init__(self, command: str, duration: float) -> None: def run_cargo(cargo_cmd, cargo_args: str) -> Timing: - args = ["cargo", cargo_cmd, "--quiet"] + cargo_args.split(" ") + args = ["cargo", cargo_cmd] + if cargo_cmd != "deny": + args.append("--quiet") + args += cargo_args.split(" ") + cmd_str = subprocess.list2cmdline(args) print(f"> {cmd_str}") start_time = time.time() @@ -59,6 +63,7 @@ def main() -> None: help="If true, don't check individual examples in /examples/rust/.", action="store_true", ) + parser.add_argument("--skip-wasm-checks", help="If true, don't run explicit wasm32 checks.", action="store_true") parser.add_argument("--skip-docs", help="If true, don't run doc generation.", action="store_true") parser.add_argument("--skip-tests", help="If true, don't run tests.", action="store_true") args = parser.parse_args() @@ -73,27 +78,60 @@ def main() -> None: timings.append(run_cargo("check", "--locked --all-features")) timings.append(run_cargo("fmt", "--all -- --check")) + + # Installing is quite quick if it's already installed. + timings.append(run_cargo("install", "--locked cargo-cranky")) timings.append(run_cargo("cranky", "--all-targets --all-features -- --deny warnings")) # Check a few important permutations of the feature flags for our `rerun` library: timings.append(run_cargo("check", "-p rerun --no-default-features")) timings.append(run_cargo("check", "-p rerun --no-default-features --features sdk")) - # Since features are additive, check crates individually. - if args.skip_check_individual_examples is not True: + # Cargo deny + # Note: running just `cargo deny check` without a `--target` can result in + # false positives due to https://github.com/EmbarkStudios/cargo-deny/issues/324 + # Installing is quite quick if it's already installed. + timings.append(run_cargo("install", "--locked cargo-deny")) + timings.append(run_cargo("deny", "--all-features --log-level error --target aarch64-apple-darwin check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target i686-pc-windows-gnu check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target i686-pc-windows-msvc check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target i686-unknown-linux-gnu check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target wasm32-unknown-unknown check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target x86_64-apple-darwin check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target x86_64-pc-windows-gnu check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target x86_64-pc-windows-msvc check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target x86_64-unknown-linux-gnu check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target x86_64-unknown-linux-musl check")) + timings.append(run_cargo("deny", "--all-features --log-level error --target x86_64-unknown-redox check")) + + if not args.skip_wasm_checks: + # Check viewer for wasm32 + timings.append( + run_cargo( + "cranky", + "--all-features --target wasm32-unknown-unknown --target-dir target_wasm -p re_viewer -- --deny warnings", + ) + ) + # Check re_renderer examples for wasm32. + timings.append( + run_cargo("check", "--target wasm32-unknown-unknown --target-dir target_wasm -p re_renderer --examples") + ) + + # Since features are additive, check examples & crates individually unless opted out. + if not args.skip_check_individual_examples: for cargo_toml_path in glob("./examples/rust/**/Cargo.toml", recursive=True): package_name = package_name_from_cargo_toml(cargo_toml_path) timings.append(run_cargo("check", f"--no-default-features -p {package_name}")) timings.append(run_cargo("check", f"--all-features -p {package_name}")) - if args.skip_check_individual_crates is not True: + if not args.skip_check_individual_crates: for cargo_toml_path in glob("./crates/**/Cargo.toml", recursive=True): package_name = package_name_from_cargo_toml(cargo_toml_path) timings.append(run_cargo("check", f"--no-default-features -p {package_name}")) timings.append(run_cargo("check", f"--all-features -p {package_name}")) # Doc tests - if args.skip_docs is not True: + if not args.skip_docs: # Full doc build takes prohibitively long (over 17min as of writing), so we skip it: # timings.append(run_cargo("doc", "--all-features")) @@ -101,7 +139,7 @@ def main() -> None: timings.append(run_cargo("doc", "--no-deps --all-features --workspace")) timings.append(run_cargo("doc", "--document-private-items --no-deps --all-features --workspace")) - if args.skip_tests is not True: + if not args.skip_tests: # We first use `--no-run` to measure the time of compiling vs actually running # Just a normal `cargo test` should always work: diff --git a/scripts/clippy_wasm.sh b/scripts/clippy_wasm.sh deleted file mode 100755 index 0b320a2ecaab..000000000000 --- a/scripts/clippy_wasm.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -# This scripts run clippy on the wasm32-unknown-unknown target, -# using a special clippy.toml config file which forbids a few more things. - -set -eu -script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) -cd "$script_path/.." -set -x - -# Use scripts/clippy_wasm/clippy.toml -export CLIPPY_CONF_DIR="scripts/clippy_wasm" - -cargo install --locked --quiet cargo-cranky - -cargo cranky --all-features --target wasm32-unknown-unknown --target-dir target_wasm -p re_viewer -- --deny warnings From 1b432d29b6ccc7774b835c098c64b2ee51e653c6 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 12 Apr 2024 08:20:32 +0200 Subject: [PATCH 265/508] Simplify docker image to only include rustup and essential system libs (#5932) ### What - Resolves: https://github.com/rerun-io/rerun/issues/5906 A lot of stuff in the docker container is now in pixi or managed via other explicit configuration steps. The wheel-testing job was the only one that had issues. I moved the job invocations over to pixi and introduced a new `wheel-test` pixi env to avoid needing to pull torch into the normal pixi env. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5932?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5932?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5932) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_rerun_py.yml | 2 +- .../reusable_build_and_upload_rerun_c.yml | 4 +- .../reusable_build_and_upload_rerun_cli.yml | 4 +- .../reusable_build_and_upload_wheels.yml | 4 +- .../reusable_bundle_and_upload_rerun_cpp.yml | 2 +- .github/workflows/reusable_run_notebook.yml | 2 +- .github/workflows/reusable_test_wheels.yml | 49 +- ci_docker/Dockerfile | 73 +- ci_docker/publish.sh | 2 +- pixi.lock | 2419 ++++++++++++++++- pixi.toml | 9 + 11 files changed, 2368 insertions(+), 202 deletions(-) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index bc510f9ba993..d172ba01e415 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -48,7 +48,7 @@ jobs: name: Build Wheels runs-on: ubuntu-latest-16-cores container: - image: rerunio/ci_docker:0.13.0 + image: rerunio/ci_docker:0.14.0 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml index 3b0a33d6d637..df0c75dcae91 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_c.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml @@ -87,13 +87,13 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.13.0'" + container="'rerunio/ci_docker:0.14.0'" lib_name="librerun_c.a" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.13.0'" + container="'rerunio/ci_docker:0.14.0'" lib_name="librerun_c.a" ;; windows-x64) diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index c64afb3c53e1..d4e01d3e2ba7 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -88,13 +88,13 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.13.0'" + container="'rerunio/ci_docker:0.14.0'" bin_name="rerun" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.13.0'" + container="'rerunio/ci_docker:0.14.0'" bin_name="rerun" ;; windows-x64) diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 433d7337798f..51460e953fe6 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -110,14 +110,14 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.13.0'" # Required to be manylinux compatible + container="'rerunio/ci_docker:0.14.0'" # Required to be manylinux compatible compat="manylinux_2_31" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" compat="manylinux_2_31" - container="'rerunio/ci_docker:0.13.0'" # Required to be manylinux compatible + container="'rerunio/ci_docker:0.14.0'" # Required to be manylinux compatible ;; windows-x64) runner="windows-latest-8-cores" diff --git a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml index 7a80b267f68f..9040104db517 100644 --- a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml +++ b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.13.0 # Need container for arrow dependency. + image: rerunio/ci_docker:0.14.0 # Need container for arrow dependency. steps: - name: Checkout repository diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml index 4481c61653e8..e54512d6e3c7 100644 --- a/.github/workflows/reusable_run_notebook.yml +++ b/.github/workflows/reusable_run_notebook.yml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest container: - image: rerunio/ci_docker:0.13.0 # Required to run the wheel or we get "No matching distribution found for attrs>=23.1.0" during `pip install rerun-sdk` + image: rerunio/ci_docker:0.14.0 # Required to run the wheel or we get "No matching distribution found for attrs>=23.1.0" during `pip install rerun-sdk` steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index c4e3efdef7ef..2c74ba422fe7 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -74,12 +74,12 @@ jobs: linux-arm64) runner="buildjet-8vcpu-ubuntu-2204-arm" target="aarch64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.13.0'" + container="'rerunio/ci_docker:0.14.0'" ;; linux-x64) runner="ubuntu-latest-16-cores" target="x86_64-unknown-linux-gnu" - container="'rerunio/ci_docker:0.13.0'" + container="'rerunio/ci_docker:0.14.0'" ;; windows-x64) runner="windows-latest-8-cores" @@ -147,42 +147,17 @@ jobs: with: pixi-version: v0.18.0 - # The pip-cache setup logic doesn't work in the ubuntu docker container - # That's probably fine since we bake these deps into the container already - - name: Setup python - if: ${{ inputs.PLATFORM != 'linux-x64' }} - uses: actions/setup-python@v4 - with: - python-version: ${{ env.PYTHON_VERSION }} - cache: "pip" - cache-dependency-path: "scripts/ci/requirements.txt" - - # These should already be in the docker container, but run for good measure. A no-op install - # should be fast, and this way things don't break if we add new packages without rebuilding - # docker - - run: pip install -r scripts/ci/requirements.txt - shell: bash - - name: Download Wheel uses: actions/download-artifact@v4 with: name: ${{ inputs.WHEEL_ARTIFACT_NAME }} path: wheel - - name: Install wheel dependencies - # First we install the dependencies manually so we can use `--no-index` when installing the wheel. - # This needs to be a separate step for some reason or the following step fails - # TODO(jleibs): pull these deps from pyproject.toml - # TODO(jleibs): understand why deps can't be installed in the same step as the wheel - shell: bash - run: | - pip install attrs>=23.1.0 'numpy>=1.23,<2' pillow pyarrow>=14.0.2 pytest==7.1.2 torch==2.1.0 typing_extensions>=4.5 - - name: Get version id: get-version shell: bash run: | - echo "wheel_version=$(python3 scripts/ci/crates.py get-version)" >> "$GITHUB_OUTPUT" + echo "wheel_version=$(pixi run scripts/ci/crates.py get-version)" >> "$GITHUB_OUTPUT" - name: Install built wheel # Now install the wheel using a specific version and --no-index to guarantee we get the version from @@ -190,23 +165,23 @@ jobs: # find the dependencies to reinstall them. shell: bash run: | - pip uninstall rerun-sdk - pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links wheel + pixi run -e wheel-test pip uninstall rerun-sdk + pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links wheel - name: Verify built wheel version shell: bash run: | - python3 -m rerun --version - which rerun - rerun --version + pixi run -e wheel-test python -m rerun --version + pixi run -e wheel-test which rerun + pixi run -e wheel-test rerun --version - name: Run unit tests shell: bash - run: cd rerun_py/tests && pytest -c ../pyproject.toml + run: cd rerun_py/tests && pixi run -e wheel-test pytest -c ../pyproject.toml - name: Run e2e test shell: bash - run: RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed + run: pixi run -e wheel-test RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed - name: Run tests/roundtrips.py if: ${{ inputs.PLATFORM != 'windows-x64' && !inputs.FAST }} @@ -215,7 +190,7 @@ jobs: # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… # --no-py-build because rerun-sdk is already built and installed run: | - RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build + pixi run -e wheel-test RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build - name: Run docs/snippets/compare_snippet_output.py if: ${{ inputs.PLATFORM != 'windows-x64' && !inputs.FAST }} @@ -224,4 +199,4 @@ jobs: # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… # --no-py-build because rerun-sdk is already built and installed run: | - RUST_LOG=debug docs/snippets/compare_snippet_output.py --release --target x86_64-unknown-linux-gnu --no-py-build + pixi run -e wheel-test RUST_LOG=debug docs/snippets/compare_snippet_output.py --release --target x86_64-unknown-linux-gnu --no-py-build diff --git a/ci_docker/Dockerfile b/ci_docker/Dockerfile index dd522d2f9f7d..d2739e562bdb 100644 --- a/ci_docker/Dockerfile +++ b/ci_docker/Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu:20.04 LABEL maintainer="opensource@rerun.io" # Remember to update the version in publish.sh # TODO(jleibs) use this version in the publish.sh script and below in the CACHE_KEY -LABEL version="0.13.0" +LABEL version="0.14.0" LABEL description="Docker image used for the CI of https://github.com/rerun-io/rerun" # Install the ubuntu package dependencies @@ -37,78 +37,15 @@ RUN set -eux; \ sudo; \ rm -rf /var/lib/apt/lists/*; -# Need a more recent pip for manylinux packages to work properly -RUN python3 -m pip install -U pip - -# Need a more recent clang-format for codegen -RUN add-apt-repository ppa:ubuntu-toolchain-r/test && \ - apt update -y && \ - apt upgrade -y && \ - wget https://apt.llvm.org/llvm.sh && \ - chmod +x llvm.sh && \ - ./llvm.sh 15 && \ - apt-get install clang-format-15 && \ - ln -sf clang-format-15 /usr/bin/clang-format && \ - rm -rf /var/lib/apt/lists/*; - -# Need a more recent flatbuffers for codegen -RUN git clone --depth 1 --branch v23.5.9 https://github.com/google/flatbuffers.git && \ - cd flatbuffers && \ - cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release && \ - make -j4 && \ - make install && \ - cd .. && rm -rf flatbuffers - - -# We need a more modern patchelf than ships on ubuntu-20.04 -RUN arch=$(if [ "$TARGETARCH" = "arm64" ]; then echo "aarch64"; else echo "x86_64"; fi) && \ - curl --fail -L https://github.com/NixOS/patchelf/releases/download/0.17.2/patchelf-0.17.2-${arch}.tar.gz | tar -xz ./bin/patchelf - -# TODO(andreas): Update cargo-deny below when updating rust version to 1.70.0 or above! ENV RUSTUP_HOME=/usr/local/rustup \ CARGO_HOME=/usr/local/cargo \ - PATH=/usr/local/cargo/bin:$PATH \ - RUST_VERSION=1.76.0 \ - RUSTUP_VERSION=1.26.0 - -# Install Rust -# Borrowed from: https://github.com/rust-lang/docker-rust/blob/a8a2a9d/1.71.0/bookworm/Dockerfile -RUN arch=$(if [ "$TARGETARCH" = "arm64" ]; then echo "aarch64"; else echo "x86_64"; fi) && \ - set -eux; \ - rustArch="${arch}-unknown-linux-gnu"; \ - rustupSha256=$(if [ "$TARGETARCH" = "arm64" ]; then echo "673e336c81c65e6b16dcdede33f4cc9ed0f08bde1dbe7a935f113605292dc800"; else echo "0b2f6c8f85a3d02fde2efc0ced4657869d73fccfce59defb4e8d29233116e6db"; fi); \ - url="https://static.rust-lang.org/rustup/archive/${RUSTUP_VERSION}/${rustArch}/rustup-init"; \ - wget "$url"; \ - echo "${rustupSha256} *rustup-init" | sha256sum -c -; \ - chmod +x rustup-init; \ - ./rustup-init -y --no-modify-path --profile default --default-toolchain $RUST_VERSION --default-host ${rustArch}; \ - rm rustup-init; \ - chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \ - rustup --version; \ - cargo --version; \ - rustc --version; - -# Install stuff from `rust-toolchain` -ADD rust-toolchain rust-toolchain -# `show` is currently the only way to install whatever is in `rust-toolchain` -# This is subject to change, but there is no alternative: https://github.com/rust-lang/rustup/issues/1397 -RUN rustup show - -# Install some cargo tools we know we'll always need -# We can't do this until after we've installed rust / cargo above -# Latest cargo-deny requires a rust update! -RUN cargo install cargo-deny@0.13.9 -RUN cargo install cargo-cranky -RUN cargo install cargo-benchcmp + PATH=/usr/local/cargo/bin:$PATH -# Install the python build dependencies -ADD rerun_py/requirements-build.txt requirements-build.txt -RUN pip install -r requirements-build.txt -ADD rerun_py/requirements-lint.txt requirements-lint.txt -RUN pip install -r requirements-lint.txt +# Install Rustup +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y # Increment this to invalidate cache -ENV CACHE_KEY=rerun_docker_v0.13.0 +ENV CACHE_KEY=rerun_docker_v0.14.0 # See: https://github.com/actions/runner-images/issues/6775#issuecomment-1410270956 RUN git config --system --add safe.directory '*' diff --git a/ci_docker/publish.sh b/ci_docker/publish.sh index 296ba5c50eee..25f7fe1dc348 100755 --- a/ci_docker/publish.sh +++ b/ci_docker/publish.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eux -VERSION=0.13.0 # Bump on each new version. Remember to update the version in the Dockerfile too. +VERSION=0.14.0 # Bump on each new version. Remember to update the version in the Dockerfile too. # The build needs to run from top of repo to access the requirements.txt cd `git rev-parse --show-toplevel` diff --git a/pixi.lock b/pixi.lock index ba169b101ea0..5665373a5a6c 100644 --- a/pixi.lock +++ b/pixi.lock @@ -2565,6 +2565,828 @@ environments: - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl + wheel-test: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.17-he0b1f16_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.11-heb1d5e4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-common-0.9.15-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-compression-0.2.18-hce8ee76_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-event-stream-0.4.2-h01f5eca_8.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-http-0.8.1-hdb68c23_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-io-0.14.7-h76a7424_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-mqtt-0.10.3-h50844eb_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-s3-0.5.7-hb7bd14b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-sdkutils-0.1.15-hce8ee76_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-checksums-0.1.18-hce8ee76_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.6-hf567797_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-hbf3e495_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.28.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/cmake-3.27.6-hcfe8598_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.25-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libabseil-20240116.1-cxx17_h59595ed_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-14.0.2-he70291f_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-acero-14.0.2-hac33072_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-dataset-14.0.2-hac33072_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-14.0.2-hd42f311_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-flight-sql-14.0.2-h9241762_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-gandiva-14.0.2-hd4ab825_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libarrow-substrait-14.0.2-h9241762_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-22_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.1.0-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-22_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp16-16.0.6-default_h127d8a8_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang13-18.1.3-default_h5d6823c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcrc32c-1.1.2-h9c3ff4c_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcurl-8.7.1-hca28451_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libev-4.33-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libevent-2.1.12-hf998b51_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-13.2.0-h807b86a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-13.2.0-h69a702a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-13.2.0-ha4646dd_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-13.2.0-h807b86a_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-2.22.0-h9be4e54_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgoogle-cloud-storage-2.22.0-hc7a4891_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgrpc-1.62.1-h15f2491_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-22_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm15-15.0.7-hb3ce162_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm16-16.0.6-hb3ce162_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm18-18.1.3-h2448989_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.58.0-h47da74e_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnl-3.9.0-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.27-pthreads_h413a1c8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libparquet-14.0.2-h6a7eafb_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libprotobuf-4.25.3-h08a7969_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libre2-11-2023.09.01-h5a48ba9_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.45.2-h2797004_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libssh2-1.11.0-h0841786_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-13.2.0-h7e041cc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libthrift-0.19.0-hb90f79a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libutf8proc-2.8.0-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuv-1.46.0-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda + - 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/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4.20240210-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ninja-1.11.1-h924138e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-18.19.0-hb753e55_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-2.0.0-h17fec99_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/prettier-2.8.8-h75cfd52_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h78dcc79_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-51.0-hd3aeb46_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.9-h06160fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/snappy-1.2.0-hdb0a2a9_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/taplo-0.9.1-h1ff36dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.20.7-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-ha691c75_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/37/6d/121efd7382d5b0284239f4ab1fc1590d86d34ed4a4a2fdb13b30ca8e5740/nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/7e/00/6b218edd739ecfc60524e585ba8e6b00554dd908de2c9c66c1af3e44e18d/nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b6/9f/c64c03f49d6fbc56196664d05dba14e3a561038a81a638eeb47f4d4cfd48/nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/eb/d5/c68b1d2cdfcc59e72e8a5949a37ddb22ae6cade80cd4a57a84d4c8b55472/nvidia_cuda_runtime_cu12-12.1.105-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ff/74/a2e2be7fb83aaedec84f391f082cf765dfb635e7caa9b49065f73e4835d8/nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/86/94/eb540db023ce1d162e7bea9f8f5aa781d57c65aed513c33ee9a5123ead4d/nvidia_cufft_cu12-11.0.2.54-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/44/31/4890b1c9abc496303412947fc7dcea3d14861720642b49e8ceed89636705/nvidia_curand_cu12-10.3.2.106-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/bc/1d/8de1e5c67099015c834315e333911273a8c6aaba78923dd1d1e25fc5f217/nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/65/5b/cfaeebf25cd9fdec14338ccb16f6b2c4c7fa9163aefcf057d86b9cc248bb/nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/38/00/d0d4e48aef772ad5aebcf70b73028f88db6e5640b36c38e90445b7a57c45/nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/ff/ff/847841bacfbefc97a00036e0fce5a0f086b640756dc38caea5e1bb002655/nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/da/d3/8057f0587683ed2fcd4dbfbdfdfa807b9160b809976099d36b8f60d08f03/nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/bd/ac/3974caaa459bf2c3a244a84be8d17561f631f7d42af370fc311defeca2fb/triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + linux-aarch64: + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.17-h43c0ec5_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.11-hd75f5ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-common-0.9.15-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-compression-0.2.18-he771c36_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-event-stream-0.4.2-h0aa0982_8.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-http-0.8.1-h505357e_10.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-io-0.14.7-h2e28a7b_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-mqtt-0.10.3-h3321c0c_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-s3-0.5.7-hb8e3a89_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-sdkutils-0.1.15-he771c36_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-checksums-0.1.18-he771c36_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.6-h497fec5_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hc40fc56_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.28.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/cmake-3.27.6-hef020d8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.25-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libabseil-20240116.1-cxx17_h2f0025b_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-14.0.2-h520d24b_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-acero-14.0.2-h0a1ffab_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-dataset-14.0.2-h0a1ffab_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-14.0.2-hbf3f4d3_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-flight-sql-14.0.2-h7624240_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-gandiva-14.0.2-h1eebba3_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libarrow-substrait-14.0.2-h9b67ed8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libblas-3.9.0-22_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlicommon-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlidec-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libbrotlienc-1.1.0-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcblas-3.9.0-22_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang-cpp16-16.0.6-default_hb368394_6.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libclang13-18.1.3-default_hf9b4efe_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcrc32c-1.1.2-h01db608_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libcurl-8.7.1-h4e8248e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libev-4.33-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libevent-2.1.12-h4ba1bb4_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libexpat-2.6.2-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libffi-3.4.2-h3557bc0_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgcc-ng-13.2.0-hf8544c7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran-ng-13.2.0-he9431aa_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgfortran5-13.2.0-h582850c_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgomp-13.2.0-hf8544c7_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-2.22.0-hd739bbb_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgoogle-cloud-storage-2.22.0-hdb39181_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libgrpc-1.62.1-h98a9317_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libiconv-1.17-h31becfc_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/liblapack-3.9.0-22_linuxaarch64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm15-15.0.7-hb4f23b0_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm16-16.0.6-h0b931ab_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libllvm18-18.1.3-hbfe100b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnghttp2-1.58.0-hb0e430d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnl-3.9.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libnsl-2.0.1-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libopenblas-0.3.27-pthreads_h5a5ec62_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libparquet-14.0.2-h70b04f6_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libprotobuf-4.25.3-h648ac29_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libre2-11-2023.09.01-h9d008c2_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libsqlite-3.45.2-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libssh2-1.11.0-h492db2e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libstdcxx-ng-13.2.0-h9a76618_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libthrift-0.19.0-h043aeee_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libutf8proc-2.8.0-h4e544f5_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuuid-2.38.1-hb4cce97_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libuv-1.46.0-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxcrypt-4.4.36-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.6-h3091e33_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda + - 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/maturin-1.5.1-py311h06e5ef9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4.20240210-h0425590_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ninja-1.11.1-hdd96247_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/nodejs-18.19.0-hc1f8a26_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/openssl-3.2.1-h31becfc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/orc-2.0.0-hd7aaf90_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/prettier-2.8.8-hc2da131_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311hf60b7a8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-51.0-h0425590_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.9-h5a25046_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/snappy-1.2.0-h8d0c38d_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/taplo-0.9.1-hb8f9562_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.20.7-h1d8f897_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hb4872d8_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + osx-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.17-hb47d15a_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.11-hbce485b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-common-0.9.15-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-compression-0.2.18-h53e3db5_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-event-stream-0.4.2-he461af8_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-http-0.8.1-h0afc28a_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-io-0.14.7-h6254544_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-mqtt-0.10.3-hd66502f_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-s3-0.5.7-h4907f8a_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-sdkutils-0.1.15-h53e3db5_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-checksums-0.1.18-h53e3db5_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.6-hfb53d2e_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h01edc24_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/cmake-3.27.6-hf40c264_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.25-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20240116.1-cxx17_hc1bcbd7_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-hf13115f_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-acero-14.0.2-hcdcf8f8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-dataset-14.0.2-hcdcf8f8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-14.0.2-hcd10e87_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-flight-sql-14.0.2-hd7485ff_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-gandiva-14.0.2-h1359b85_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-substrait-14.0.2-hd7485ff_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlicommon-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlidec-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libbrotlienc-1.1.0-h0dc2134_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcblas-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang-cpp16-16.0.6-default_h7151d67_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libclang13-18.1.3-default_h0edc4dd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcrc32c-1.1.2-he49afe7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcurl-8.7.1-h726d00d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libcxx-16.0.6-hd57cbcb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libedit-3.1.20191231-h0678c8f_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libev-4.33-h10d778d_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libevent-2.1.12-ha90c15b_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libexpat-2.6.2-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libffi-3.4.2-h0d85af4_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran-5.0.0-13_2_0_h97931a8_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgfortran5-13.2.0-h2873a65_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-2.22.0-h651e89d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgoogle-cloud-storage-2.22.0-ha67e85c_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libgrpc-1.62.1-h384b2fc_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hd75f5a5_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/liblapack-3.9.0-22_osx64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm15-15.0.7-hbedff68_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm16-16.0.6-hbedff68_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libllvm18-18.1.3-hbcf5fad_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.58.0-h64cf6d3_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libopenblas-0.3.27-openmp_hfef2a42_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libparquet-14.0.2-h4aea69c_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libprotobuf-4.25.3-h4e4d658_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libre2-11-2023.09.01-h81f5012_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libsqlite-3.45.2-h92b6c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libssh2-1.11.0-hd019ec5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libthrift-0.19.0-h064b379_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libutf8proc-2.8.0-hb7f2c08_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/libuv-1.47.0-h67532ce_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libxml2-2.12.6-hc0ae0f7_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda + - 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/maturin-1.5.1-py311h24bb903_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4.20240210-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ninja-1.11.1-hb8565cd_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/nodejs-18.19.0-h119ffd7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-2.0.0-hf146577_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311hb0c4a44_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/snappy-1.2.0-h6dc393e_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/taplo-0.9.1-h236d3af_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.20.7-h11a7dfb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.17-h382b9c6_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.11-hd34e5fa_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-common-0.9.15-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-compression-0.2.18-hd34e5fa_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-event-stream-0.4.2-h247c08a_8.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-http-0.8.1-hf9e830b_10.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-io-0.14.7-h33d81b3_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-mqtt-0.10.3-h5f4abda_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-s3-0.5.7-h606a3d2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-sdkutils-0.1.15-hd34e5fa_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-checksums-0.1.18-hd34e5fa_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.6-h13f0230_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h134aaec_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cmake-3.27.6-h1c59155_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.25-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20240116.1-cxx17_hebf3989_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h3fc723a_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-acero-14.0.2-h43a2c78_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-dataset-14.0.2-h43a2c78_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-14.0.2-h161034a_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-flight-sql-14.0.2-h32643e2_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-gandiva-14.0.2-ha803c60_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-substrait-14.0.2-h7a0fec1_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.9.0-22_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlicommon-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlidec-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libbrotlienc-1.1.0-hb547adb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.9.0-22_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang-cpp16-16.0.6-default_he012953_6.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libclang13-18.1.3-default_h83d0a53_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcrc32c-1.1.2-hbdafb3b_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcurl-8.7.1-h2d989ff_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcxx-16.0.6-h4653b0c_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libedit-3.1.20191231-hc8eb9b7_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libev-4.33-h93a5062_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libevent-2.1.12-h2757513_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.6.2-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.4.2-h3422bc3_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran-5.0.0-13_2_0_hd922786_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgfortran5-13.2.0-hf226fd6_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-2.22.0-hbebe991_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgoogle-cloud-storage-2.22.0-h8a76758_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libgrpc-1.62.1-h9c18a4f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libiconv-1.17-h0d3ecfb_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.9.0-22_osxarm64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm15-15.0.7-h2621b3d_4.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm16-16.0.6-haab561b_3.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libllvm18-18.1.3-h30cc82d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libnghttp2-1.58.0-ha4dd798_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.27-openmp_h6c19121_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libparquet-14.0.2-he0622da_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libprotobuf-4.25.3-hbfab5d5_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libre2-11-2023.09.01-h7b2c953_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libsqlite-3.45.2-h091b4b1_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libssh2-1.11.0-h7a5bd25_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libthrift-0.19.0-h026a170_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libutf8proc-2.8.0-h1a8c8d9_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libuv-1.47.0-h93a5062_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libxml2-2.12.6-h0d0cfa8_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda + - 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/mypy-1.8.0-py311h05b510d_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/ncurses-6.4.20240210-h078ce10_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ninja-1.11.1-hffc8910_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-18.19.0-h5f47a4d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-2.0.0-h4aad248_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311h4c23913_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/snappy-1.2.0-hd04f947_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/taplo-0.9.1-h16c8c8b_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.20.7-h5ef7bb8_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + win-64: + - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.17-hb40cdec_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.11-ha21e00f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-common-0.9.15-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-compression-0.2.18-ha21e00f_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-event-stream-0.4.2-hf668b60_8.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-http-0.8.1-hd704247_10.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-io-0.14.7-h14865c8_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-mqtt-0.10.3-h748201e_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-s3-0.5.7-h5da7064_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-sdkutils-0.1.15-ha21e00f_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-checksums-0.1.18-ha21e00f_3.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.6-h5bc0ceb_4.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h5d77392_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.28.1-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_6.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.25-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.1.0-h57928b3_964.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h45212c0_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-acero-14.0.2-h8681a6d_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-dataset-14.0.2-h8681a6d_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-14.0.2-h83a3238_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-flight-sql-14.0.2-h21569af_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-gandiva-14.0.2-h4e6a3a4_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-substrait-14.0.2-hea7f8fd_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libblas-3.9.0-22_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlicommon-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlidec-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libbrotlienc-1.1.0-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcblas-3.9.0-22_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libclang13-18.1.3-default_hf64faad_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libcrc32c-1.1.2-h0e60522_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libcurl-8.7.1-hd5e4a3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libevent-2.1.12-h3671451_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libexpat-2.6.2-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libffi-3.4.2-h8ffe710_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-2.22.0-h9cad5c0_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgoogle-cloud-storage-2.22.0-hb581fae_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libgrpc-1.62.1-h5273850_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libhwloc-2.9.3-default_haede6df_1009.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.17-hcfcfb64_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/liblapack-3.9.0-22_win64_mkl.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libparquet-14.0.2-h39135fc_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libprotobuf-4.25.3-h503648d_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libre2-11-2023.09.01-hf8d8778_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libsqlite-3.45.2-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libssh2-1.11.0-h7dfc565_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libthrift-0.19.0-ha2b3283_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libutf8proc-2.8.0-h82a8f57_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/libuv-1.48.0-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libxml2-2.12.6-hc3477c8_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/libzlib-1.2.13-hcfcfb64_5.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/lz4-c-1.9.4-hcfcfb64_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libgfortran-5.3.0-6.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-5.3.0-7.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_692.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/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/nodejs-18.19.0-h57928b3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/orc-2.0.0-h7e885a9_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h05400ba_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/snappy-1.2.0-hfb803bf_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/taplo-0.9.1-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tbb-2021.11.0-h91493d7_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.20.7-h7f3b576_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda + - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl packages: - kind: conda name: _libgcc_mutex @@ -2675,6 +3497,23 @@ packages: - pkg:pypi/attrs size: 54582 timestamp: 1704011393776 +- kind: conda + name: attrs + version: 23.2.0 + build: pyh71513ae_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda + sha256: 77c7d03bdb243a048fff398cedc74327b7dc79169ebe3b4c8448b0331ea55fea + md5: 5e4c0743c70186509d1412e03c2d8dfa + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/attrs@23.2.0 + size: 54582 + timestamp: 1704011393776 - kind: conda name: aws-c-auth version: 0.7.10 @@ -6612,8 +7451,8 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' @@ -6628,16 +7467,16 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 + url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 requires_dist: - pycparser requires_python: '>=3.8' @@ -6650,8 +7489,8 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer @@ -6662,14 +7501,14 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' - kind: conda name: clang @@ -7720,6 +8559,23 @@ packages: license_family: BSD size: 16525734 timestamp: 1695270838345 +- kind: conda + name: colorama + version: 0.4.6 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 + sha256: 2c1b2e9755ce3102bca8d69e8f26e4f087ece73f50418186aee7c74bef8e1698 + md5: 3faab06a954c2a04039983f2c4a50d99 + depends: + - python >=3.7 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/colorama@0.4.6 + size: 25170 + timestamp: 1666700778190 - kind: conda name: colorama version: 0.4.6 @@ -7855,8 +8711,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb + url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -7911,8 +8767,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d + url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -7939,8 +8795,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 + url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -8147,6 +9003,23 @@ packages: - pkg:pypi/exceptiongroup size: 20551 timestamp: 1704921321122 +- kind: conda + name: exceptiongroup + version: 1.2.0 + build: pyhd8ed1ab_2 + build_number: 2 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda + sha256: a6ae416383bda0e3ed14eaa187c653e22bec94ff2aa3b56970cdf0032761e80d + md5: 8d652ea2ee8eaee02ed8dc820bc794aa + depends: + - python >=3.7 + license: MIT and PSF-2.0 + purls: + - pkg:pypi/exceptiongroup@1.2.0 + size: 20551 + timestamp: 1704921321122 - kind: pypi name: filelock version: 3.13.4 @@ -8317,6 +9190,56 @@ packages: license_family: APACHE size: 1280038 timestamp: 1711467768202 +- kind: pypi + name: fsspec + version: 2024.3.1 + url: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl + sha256: 918d18d41bf73f0e2b261824baeb1b124bcf771767e3a26425cd7dec3332f512 + requires_dist: + - adlfs ; extra == 'abfs' + - adlfs ; extra == 'adl' + - pyarrow >=1 ; extra == 'arrow' + - dask ; extra == 'dask' + - distributed ; extra == 'dask' + - pytest ; extra == 'devel' + - pytest-cov ; extra == 'devel' + - dropboxdrivefs ; extra == 'dropbox' + - requests ; extra == 'dropbox' + - dropbox ; extra == 'dropbox' + - adlfs ; extra == 'full' + - aiohttp !=4.0.0a0, !=4.0.0a1 ; extra == 'full' + - dask ; extra == 'full' + - distributed ; extra == 'full' + - dropbox ; extra == 'full' + - dropboxdrivefs ; extra == 'full' + - fusepy ; extra == 'full' + - gcsfs ; extra == 'full' + - libarchive-c ; extra == 'full' + - ocifs ; extra == 'full' + - panel ; extra == 'full' + - paramiko ; extra == 'full' + - pyarrow >=1 ; extra == 'full' + - pygit2 ; extra == 'full' + - requests ; extra == 'full' + - s3fs ; extra == 'full' + - smbprotocol ; extra == 'full' + - tqdm ; extra == 'full' + - fusepy ; extra == 'fuse' + - gcsfs ; extra == 'gcs' + - pygit2 ; extra == 'git' + - requests ; extra == 'github' + - gcsfs ; extra == 'gs' + - panel ; extra == 'gui' + - pyarrow >=1 ; extra == 'hdfs' + - aiohttp !=4.0.0a0, !=4.0.0a1 ; extra == 'http' + - libarchive-c ; extra == 'libarchive' + - ocifs ; extra == 'oci' + - s3fs ; extra == 's3' + - paramiko ; extra == 'sftp' + - smbprotocol ; extra == 'smb' + - paramiko ; extra == 'ssh' + - tqdm ; extra == 'tqdm' + requires_python: '>=3.8' - kind: conda name: gcc version: 12.3.0 @@ -8496,6 +9419,24 @@ packages: - markdown ; extra == 'dev' - flake8 ; extra == 'dev' - wheel ; extra == 'dev' +- kind: conda + name: gitdb + version: 4.0.11 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda + sha256: 52ab2798be31b8f509eeec458712f447ced4f96ecb672c6c9a42778f47e07b1b + md5: 623b19f616f2ca0c261441067e18ae40 + depends: + - python >=3.7 + - smmap >=3.0.1,<6 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/gitdb@4.0.11 + size: 52872 + timestamp: 1697791718749 - kind: conda name: gitdb version: 4.0.11 @@ -8552,6 +9493,23 @@ packages: - pkg:pypi/gitignore-parser size: 11460 timestamp: 1705776957779 +- kind: conda + name: gitignore-parser + version: 0.1.11 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda + sha256: 10b3621e508e6c647eae4c52d48ff2659f4f0b426d6dd5979ccc7475d5383eb6 + md5: 251ce4bb7b478eacf297b1fb8eb838bb + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/gitignore-parser@0.1.11 + size: 11460 + timestamp: 1705776957779 - kind: conda name: gitpython version: 3.1.40 @@ -8630,6 +9588,25 @@ packages: - pkg:pypi/gitpython size: 156827 timestamp: 1711991122366 +- kind: conda + name: gitpython + version: 3.1.43 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + sha256: cbb2802641a009ce9bcc2a047e817fd8816f9c842036a42f4730398d8e4cda2a + md5: 0b2154c1818111e17381b1df5b4b0176 + depends: + - gitdb >=4.0.1,<5 + - python >=3.7 + - typing_extensions >=3.7.4.3 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/gitpython@3.1.43 + size: 156827 + timestamp: 1711991122366 - kind: conda name: glog version: 0.6.0 @@ -8811,8 +9788,8 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -8827,16 +9804,16 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 + url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -9030,6 +10007,23 @@ packages: url: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl sha256: 82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 requires_python: '>=3.5' +- kind: conda + name: iniconfig + version: 2.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + sha256: 38740c939b668b36a50ef455b077e8015b8c9cf89860d421b3fff86048f49666 + md5: f800d2da156d08e289b14e87e43c1ae5 + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/iniconfig@2.0.0 + size: 11101 + timestamp: 1673103208955 - kind: conda name: iniconfig version: 2.0.0 @@ -15127,6 +16121,25 @@ packages: license_family: Apache size: 33321457 timestamp: 1701375836233 +- kind: conda + name: libllvm15 + version: 15.0.7 + build: hb3ce162_4 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libllvm15-15.0.7-hb3ce162_4.conda + sha256: e71584c0f910140630580fdd0a013029a52fd31e435192aea2aa8d29005262d1 + md5: 8a35df3cbc0c8b12cc8af9473ae75eef + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 33321457 + timestamp: 1701375836233 - kind: conda name: libllvm15 version: 15.0.7 @@ -15258,6 +16271,25 @@ packages: license_family: Apache size: 35359734 timestamp: 1701375139881 +- kind: conda + name: libllvm16 + version: 16.0.6 + build: hb3ce162_3 + build_number: 3 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libllvm16-16.0.6-hb3ce162_3.conda + sha256: 624fa4012397bc5a8c9269247bf9baa7d907eb59079aefc6f6fa6a40f10fd0ba + md5: a4d48c40dd5c60edbab7fd69c9a88967 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.1,<3.0.0a0 + - libzlib >=1.2.13,<1.3.0a0 + - zstd >=1.5.5,<1.6.0a0 + license: Apache-2.0 WITH LLVM-exception + license_family: Apache + size: 35359734 + timestamp: 1701375139881 - kind: conda name: libllvm16 version: 16.0.6 @@ -17758,26 +18790,26 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced + url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f + url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 + url: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 + url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f requires_python: '>=3.7' - kind: conda name: maturin @@ -17797,6 +18829,45 @@ packages: license_family: MIT size: 5883670 timestamp: 1711053175449 +- kind: conda + name: maturin + version: 1.5.1 + build: py311h06e5ef9_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.5.1-py311h06e5ef9_0.conda + sha256: ec876128344c775817ce6c64a979c5570236fe4091eee96cf6547b72fb760736 + md5: f0abfc82e48c4179c8ebecdfc1ce7a59 + depends: + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - tomli >=1.1.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/maturin@1.5.1 + size: 5883670 + timestamp: 1711053175449 +- kind: conda + name: maturin + version: 1.5.1 + build: py311h24bb903_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.5.1-py311h24bb903_0.conda + sha256: 52f9e9e54d36ef40cd5c2fa171613750ee56d722e5ac718e5d71d5e4696e559c + md5: 0ffabfb12f4fbb545781a385744ae75a + depends: + - openssl >=3.2.1,<4.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - tomli >=1.1.0 + constrains: + - __osx >=10.12 + license: MIT + license_family: MIT + size: 4746594 + timestamp: 1711043864724 - kind: conda name: maturin version: 1.5.1 @@ -17814,6 +18885,8 @@ packages: - __osx >=10.12 license: MIT license_family: MIT + purls: + - pkg:pypi/maturin@1.5.1 size: 4746594 timestamp: 1711043864724 - kind: conda @@ -17834,6 +18907,46 @@ packages: license_family: MIT size: 5875793 timestamp: 1711042912603 +- kind: conda + name: maturin + version: 1.5.1 + build: py311h63ff55d_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.5.1-py311h63ff55d_0.conda + sha256: c16ac56fb748e39ae52387395f98c79d031b15d763c1877226bfe8b970690fdb + md5: b988008c60e0ffda52e533668a298c6f + depends: + - libgcc-ng >=12 + - openssl >=3.2.1,<4.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - tomli >=1.1.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/maturin@1.5.1 + size: 5875793 + timestamp: 1711042912603 +- kind: conda + name: maturin + version: 1.5.1 + build: py311h71175c2_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.5.1-py311h71175c2_0.conda + sha256: 5e508cb34bf0f2cfc1f06635d3cceefbe679d3fb81ce64d7d2dc0b4bf8af4584 + md5: 50560d0477396cebcaffc864bad10e42 + depends: + - openssl >=3.2.1,<4.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - tomli >=1.1.0 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + size: 4579808 + timestamp: 1711043620752 - kind: conda name: maturin version: 1.5.1 @@ -17852,6 +18965,8 @@ packages: - __osx >=11.0 license: MIT license_family: MIT + purls: + - pkg:pypi/maturin@1.5.1 size: 4579808 timestamp: 1711043620752 - kind: conda @@ -17872,6 +18987,26 @@ packages: license_family: MIT size: 4498445 timestamp: 1711044494832 +- kind: conda + name: maturin + version: 1.5.1 + build: py311h9a9e57f_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda + sha256: 5307c7955e2a4da23b6a593c715edd8b9e2abe802c1056a225e757ef35eb3356 + md5: 9eeaf6831c4f0a721385e2e9d10c52a7 + depends: + - m2w64-gcc-libs + - m2w64-gcc-libs-core + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - tomli >=1.1.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/maturin@1.5.1 + size: 4498445 + timestamp: 1711044494832 - kind: conda name: meilisearch version: 1.5.1 @@ -18098,6 +19233,20 @@ packages: license_family: Proprietary size: 109491063 timestamp: 1712153746272 +- kind: pypi + name: mpmath + version: 1.3.0 + url: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl + sha256: a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c + requires_dist: + - pytest >=4.6 ; extra == 'develop' + - pycodestyle ; extra == 'develop' + - pytest-cov ; extra == 'develop' + - codecov ; extra == 'develop' + - wheel ; extra == 'develop' + - sphinx ; extra == 'docs' + - gmpy2 >=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' + - pytest >=4.6 ; extra == 'tests' - kind: conda name: msys2-conda-epoch version: '20160418' @@ -18128,6 +19277,46 @@ packages: license_family: MIT size: 9655583 timestamp: 1703185105616 +- kind: conda + name: mypy + version: 1.8.0 + build: py311h05b510d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda + sha256: e31c811f99b842020350f9df6c6e4b5e2bf07353fee3cc0029c655e8980d9431 + md5: 93010b2e72e263002f6c60dc1c1f7e1d + depends: + - 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 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy@1.8.0 + size: 9655583 + timestamp: 1703185105616 +- kind: conda + name: mypy + version: 1.8.0 + build: py311h459d7ec_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda + sha256: 943c43f2d68a6d4e8fa8a3a4e62538e090f5f0afe551f50092ea024850f5cccb + md5: 93b7b2391a045cea0d97772f550f1d77 + depends: + - libgcc-ng >=12 + - mypy_extensions >=1.0.0 + - psutil >=4.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - typing_extensions >=4.1.0 + license: MIT + license_family: MIT + size: 17719191 + timestamp: 1703185056003 - kind: conda name: mypy version: 1.8.0 @@ -18145,6 +19334,8 @@ packages: - typing_extensions >=4.1.0 license: MIT license_family: MIT + purls: + - pkg:pypi/mypy@1.8.0 size: 17719191 timestamp: 1703185056003 - kind: conda @@ -18168,6 +19359,49 @@ packages: license_family: MIT size: 9963457 timestamp: 1703184979309 +- kind: conda + name: mypy + version: 1.8.0 + build: py311ha68e1ae_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda + sha256: cebfab3f247a752be06e945a3a2a1281195d6917fa09906a9618dbc7b2cf734e + md5: 9a949cc91276bf313755857a11ce1ec3 + depends: + - mypy_extensions >=1.0.0 + - psutil >=4.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - typing_extensions >=4.1.0 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy@1.8.0 + size: 9963457 + timestamp: 1703184979309 +- kind: conda + name: mypy + version: 1.8.0 + build: py311hcd402e7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda + sha256: 2a1d84dc94a02ed3cae2fad6dfea0fab4a9504649c1a009d1fff7bfbd9d48e57 + md5: 22b4d0e0a591e6dba331d95f8a702517 + depends: + - libgcc-ng >=12 + - 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 + license: MIT + license_family: MIT + size: 15129179 + timestamp: 1703185374507 - kind: conda name: mypy version: 1.8.0 @@ -18186,6 +19420,8 @@ packages: - typing_extensions >=4.1.0 license: MIT license_family: MIT + purls: + - pkg:pypi/mypy@1.8.0 size: 15129179 timestamp: 1703185374507 - kind: conda @@ -18206,6 +19442,43 @@ packages: license_family: MIT size: 11969071 timestamp: 1703184938293 +- kind: conda + name: mypy + version: 1.8.0 + build: py311he705e18_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda + sha256: affdf64692efcf05888cc42fc2c4159fe5bade7d610847b5610e5b2cc621cd3a + md5: c32cbc41e84a67f1b30b3f157b46996b + depends: + - mypy_extensions >=1.0.0 + - psutil >=4.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - typing_extensions >=4.1.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy@1.8.0 + size: 11969071 + timestamp: 1703184938293 +- kind: conda + name: mypy_extensions + version: 1.0.0 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda + sha256: f240217476e148e825420c6bc3a0c0efb08c0718b7042fae960400c02af858a3 + md5: 4eccaeba205f0aed9ac3a9ea58568ca3 + depends: + - python >=3.5 + license: MIT + license_family: MIT + purls: + - pkg:pypi/mypy-extensions@1.0.0 + size: 10492 + timestamp: 1675543414256 - kind: conda name: mypy_extensions version: 1.0.0 @@ -18370,6 +19643,34 @@ packages: license: X11 AND BSD-3-Clause size: 823010 timestamp: 1710866856626 +- kind: pypi + name: networkx + version: '3.3' + url: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl + sha256: 28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2 + requires_dist: + - numpy >=1.23 ; extra == 'default' + - scipy !=1.11.0, !=1.11.1, >=1.9 ; extra == 'default' + - matplotlib >=3.6 ; extra == 'default' + - pandas >=1.4 ; extra == 'default' + - changelist ==0.5 ; extra == 'developer' + - pre-commit >=3.2 ; extra == 'developer' + - mypy >=1.1 ; extra == 'developer' + - rtoml ; extra == 'developer' + - sphinx >=7 ; extra == 'doc' + - pydata-sphinx-theme >=0.14 ; extra == 'doc' + - sphinx-gallery >=0.14 ; extra == 'doc' + - numpydoc >=1.7 ; extra == 'doc' + - pillow >=9.4 ; extra == 'doc' + - texext >=0.6.7 ; extra == 'doc' + - myst-nb >=1.0 ; extra == 'doc' + - lxml >=4.6 ; extra == 'extra' + - pygraphviz >=1.12 ; extra == 'extra' + - pydot >=2.0 ; extra == 'extra' + - sympy >=1.10 ; extra == 'extra' + - pytest >=7.2 ; extra == 'test' + - pytest-cov >=4.0 ; extra == 'test' + requires_python: '>=3.10' - kind: conda name: ninja version: 1.11.1 @@ -18646,17 +19947,66 @@ packages: - liblapack >=3.9.0,<4.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy + size: 7104093 + timestamp: 1707226459646 +- kind: conda + name: numpy + version: 1.26.4 + build: py311h0b4df5a_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda + sha256: 14116e72107de3089cc58119a5ce5905c22abf9a715c9fe41f8ac14db0992326 + md5: 7b240edd44fd7a0991aa409b07cee776 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - liblapack >=3.9.0,<4.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy@1.26.4 + size: 7104093 + timestamp: 1707226459646 +- kind: conda + name: numpy + version: 1.26.4 + build: py311h64a7726_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda + sha256: 3f4365e11b28e244c95ba8579942b0802761ba7bb31c026f50d1a9ea9c728149 + md5: a502d7aad449a1206efb366d6a12c52d + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy - size: 7104093 - timestamp: 1707226459646 + size: 8065890 + timestamp: 1707225944355 - kind: conda name: numpy version: 1.26.4 @@ -18678,7 +20028,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/numpy + - pkg:pypi/numpy@1.26.4 size: 8065890 timestamp: 1707225944355 - kind: conda @@ -18706,6 +20056,31 @@ packages: - pkg:pypi/numpy size: 7234391 timestamp: 1707225781489 +- kind: conda + name: numpy + version: 1.26.4 + build: py311h69ead2a_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda + sha256: 88800a1d9d11c2fccab09d40d36f7001616f5119eaf0ec86186562f33564e651 + md5: 3fd00dd400c8d3f9da12bf33061dd28d + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy@1.26.4 + size: 7234391 + timestamp: 1707225781489 - kind: conda name: numpy version: 1.26.4 @@ -18730,6 +20105,30 @@ packages: - pkg:pypi/numpy size: 6652352 timestamp: 1707226297967 +- kind: conda + name: numpy + version: 1.26.4 + build: py311h7125741_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda + sha256: 160a52a01fea44fe9753a2ed22cf13d7b55c8a89ea0b8738546fdbf4795d6514 + md5: 3160b93669a0def35a7a8158ebb33816 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=16 + - liblapack >=3.9.0,<4.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy@1.26.4 + size: 6652352 + timestamp: 1707226297967 - kind: conda name: numpy version: 1.26.4 @@ -18753,6 +20152,109 @@ packages: - pkg:pypi/numpy size: 7504319 timestamp: 1707226235372 +- kind: conda + name: numpy + version: 1.26.4 + build: py311hc43a94b_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda + sha256: dc9628197125ee1d02b2e7a859a769d26291d747ed79337309b8a9e67a8b8e00 + md5: bb02b8801d17265160e466cf8bbf28da + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libcxx >=16 + - liblapack >=3.9.0,<4.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy@1.26.4 + size: 7504319 + timestamp: 1707226235372 +- kind: pypi + name: nvidia-cublas-cu12 + version: 12.1.3.1 + url: https://files.pythonhosted.org/packages/37/6d/121efd7382d5b0284239f4ab1fc1590d86d34ed4a4a2fdb13b30ca8e5740/nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl + sha256: ee53ccca76a6fc08fb9701aa95b6ceb242cdaab118c3bb152af4e579af792728 + requires_python: '>=3' +- kind: pypi + name: nvidia-cuda-cupti-cu12 + version: 12.1.105 + url: https://files.pythonhosted.org/packages/7e/00/6b218edd739ecfc60524e585ba8e6b00554dd908de2c9c66c1af3e44e18d/nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl + sha256: e54fde3983165c624cb79254ae9818a456eb6e87a7fd4d56a2352c24ee542d7e + requires_python: '>=3' +- kind: pypi + name: nvidia-cuda-nvrtc-cu12 + version: 12.1.105 + url: https://files.pythonhosted.org/packages/b6/9f/c64c03f49d6fbc56196664d05dba14e3a561038a81a638eeb47f4d4cfd48/nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl + sha256: 339b385f50c309763ca65456ec75e17bbefcbbf2893f462cb8b90584cd27a1c2 + requires_python: '>=3' +- kind: pypi + name: nvidia-cuda-runtime-cu12 + version: 12.1.105 + url: https://files.pythonhosted.org/packages/eb/d5/c68b1d2cdfcc59e72e8a5949a37ddb22ae6cade80cd4a57a84d4c8b55472/nvidia_cuda_runtime_cu12-12.1.105-py3-none-manylinux1_x86_64.whl + sha256: 6e258468ddf5796e25f1dc591a31029fa317d97a0a94ed93468fc86301d61e40 + requires_python: '>=3' +- kind: pypi + name: nvidia-cudnn-cu12 + version: 8.9.2.26 + url: https://files.pythonhosted.org/packages/ff/74/a2e2be7fb83aaedec84f391f082cf765dfb635e7caa9b49065f73e4835d8/nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl + sha256: 5ccb288774fdfb07a7e7025ffec286971c06d8d7b4fb162525334616d7629ff9 + requires_dist: + - nvidia-cublas-cu12 + requires_python: '>=3' +- kind: pypi + name: nvidia-cufft-cu12 + version: 11.0.2.54 + url: https://files.pythonhosted.org/packages/86/94/eb540db023ce1d162e7bea9f8f5aa781d57c65aed513c33ee9a5123ead4d/nvidia_cufft_cu12-11.0.2.54-py3-none-manylinux1_x86_64.whl + sha256: 794e3948a1aa71fd817c3775866943936774d1c14e7628c74f6f7417224cdf56 + requires_python: '>=3' +- kind: pypi + name: nvidia-curand-cu12 + version: 10.3.2.106 + url: https://files.pythonhosted.org/packages/44/31/4890b1c9abc496303412947fc7dcea3d14861720642b49e8ceed89636705/nvidia_curand_cu12-10.3.2.106-py3-none-manylinux1_x86_64.whl + sha256: 9d264c5036dde4e64f1de8c50ae753237c12e0b1348738169cd0f8a536c0e1e0 + requires_python: '>=3' +- kind: pypi + name: nvidia-cusolver-cu12 + version: 11.4.5.107 + url: https://files.pythonhosted.org/packages/bc/1d/8de1e5c67099015c834315e333911273a8c6aaba78923dd1d1e25fc5f217/nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl + sha256: 8a7ec542f0412294b15072fa7dab71d31334014a69f953004ea7a118206fe0dd + requires_dist: + - nvidia-cublas-cu12 + - nvidia-nvjitlink-cu12 + - nvidia-cusparse-cu12 + requires_python: '>=3' +- kind: pypi + name: nvidia-cusparse-cu12 + version: 12.1.0.106 + url: https://files.pythonhosted.org/packages/65/5b/cfaeebf25cd9fdec14338ccb16f6b2c4c7fa9163aefcf057d86b9cc248bb/nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl + sha256: f3b50f42cf363f86ab21f720998517a659a48131e8d538dc02f8768237bd884c + requires_dist: + - nvidia-nvjitlink-cu12 + requires_python: '>=3' +- kind: pypi + name: nvidia-nccl-cu12 + version: 2.19.3 + url: https://files.pythonhosted.org/packages/38/00/d0d4e48aef772ad5aebcf70b73028f88db6e5640b36c38e90445b7a57c45/nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl + sha256: a9734707a2c96443331c1e48c717024aa6678a0e2a4cb66b2c364d18cee6b48d + requires_python: '>=3' +- kind: pypi + name: nvidia-nvjitlink-cu12 + version: 12.4.127 + url: https://files.pythonhosted.org/packages/ff/ff/847841bacfbefc97a00036e0fce5a0f086b640756dc38caea5e1bb002655/nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl + sha256: 06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57 + requires_python: '>=3' +- kind: pypi + name: nvidia-nvtx-cu12 + version: 12.1.105 + url: https://files.pythonhosted.org/packages/da/d3/8057f0587683ed2fcd4dbfbdfdfa807b9160b809976099d36b8f60d08f03/nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl + sha256: dc21cf308ca5691e7c04d962e213f8a4aa9bbfa23d95412f452254c2caeb09e5 + requires_python: '>=3' - kind: conda name: openssl version: 3.2.1 @@ -19243,6 +20745,23 @@ packages: - pkg:pypi/packaging size: 49832 timestamp: 1710076089469 +- kind: conda + name: packaging + version: '24.0' + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda + sha256: a390182d74c31dfd713c16db888c92c277feeb6d1fe96ff9d9c105f9564be48a + md5: 248f521b64ce055e7feae3105e7abeb8 + depends: + - python >=3.8 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/packaging@24.0 + size: 49832 + timestamp: 1710076089469 - kind: pypi name: paginate version: 0.5.6 @@ -19296,8 +20815,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -19344,8 +20863,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -19368,8 +20887,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -19429,6 +20948,25 @@ packages: - pkg:pypi/pip size: 1398245 timestamp: 1706960660581 +- kind: conda + name: pip + version: '24.0' + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda + sha256: b7c1c5d8f13e8cb491c4bd1d0d1896a4cf80fc47de01059ad77509112b664a4a + md5: f586ac1e56c8638b64f9c8122a7b8a67 + depends: + - python >=3.7 + - setuptools + - wheel + license: MIT + license_family: MIT + purls: + - pkg:pypi/pip@24.0 + size: 1398245 + timestamp: 1706960660581 - kind: pypi name: platformdirs version: 4.2.0 @@ -19481,6 +21019,23 @@ packages: - pkg:pypi/pluggy size: 23384 timestamp: 1706116931972 +- kind: conda + name: pluggy + version: 1.4.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda + sha256: 6edfd2c41938ea772096c674809bfcf2ebb9bef7e82de6c7ea0b966b86bfb4d0 + md5: 139e9feb65187e916162917bb2484976 + depends: + - python >=3.8 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pluggy@1.4.0 + size: 23384 + timestamp: 1706116931972 - kind: conda name: prettier version: 2.8.8 @@ -19575,20 +21130,20 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c + url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl - sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 + url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d + url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 requires_python: '>=3.8' - kind: conda name: psutil @@ -19608,6 +21163,24 @@ packages: - pkg:pypi/psutil size: 513415 timestamp: 1705722847446 +- kind: conda + name: psutil + version: 5.9.8 + build: py311h05b510d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda + sha256: 2b6e485c761fa3e7271c44a070c0d08e79a6758ac4d7a660eaff0ed0a60c6f2b + md5: 970ef0edddc6c2cfeb16b7225a28a1f4 + depends: + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil@5.9.8 + size: 513415 + timestamp: 1705722847446 - kind: conda name: psutil version: 5.9.8 @@ -19626,6 +21199,24 @@ packages: - pkg:pypi/psutil size: 505516 timestamp: 1705722586221 +- kind: conda + name: psutil + version: 5.9.8 + build: py311h459d7ec_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda + sha256: 467788418a2c71fb3df9ac0a6282ae693d1070a6cb47cb59bdb529b53acaee1c + md5: 9bc62d25dcf64eec484974a3123c9d57 + depends: + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil@5.9.8 + size: 505516 + timestamp: 1705722586221 - kind: conda name: psutil version: 5.9.8 @@ -19646,6 +21237,45 @@ packages: - pkg:pypi/psutil size: 520242 timestamp: 1705723070638 +- kind: conda + name: psutil + version: 5.9.8 + build: py311ha68e1ae_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda + sha256: 77760f2ce0d2be9339d94d0fb5b3d102659355563f5b6471a1231525e63ff581 + md5: 17e48538806e7c682d2ffcbd5c9f9aa0 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil@5.9.8 + size: 520242 + timestamp: 1705723070638 +- kind: conda + name: psutil + version: 5.9.8 + build: py311hcd402e7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda + sha256: d04efc76d734ac2f1e00f52e3385ba80b089becf60aaae52f0edf185ca9f69e0 + md5: 858767f880caa447ae640a991ec5ba9e + depends: + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil + size: 506604 + timestamp: 1705722743163 - kind: conda name: psutil version: 5.9.8 @@ -19655,16 +21285,33 @@ packages: sha256: d04efc76d734ac2f1e00f52e3385ba80b089becf60aaae52f0edf185ca9f69e0 md5: 858767f880caa447ae640a991ec5ba9e depends: - - libgcc-ng >=12 + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/psutil@5.9.8 + size: 506604 + timestamp: 1705722743163 +- kind: conda + name: psutil + version: 5.9.8 + build: py311he705e18_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda + sha256: fcff83f4d265294b54821656a10be62421da377885ab2e9811a80eb76419b3fe + md5: 31aa294c58b3058c179a7a9593e99e18 + depends: - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/psutil - size: 506604 - timestamp: 1705722743163 + size: 513371 + timestamp: 1705722716862 - kind: conda name: psutil version: 5.9.8 @@ -19679,7 +21326,7 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/psutil + - pkg:pypi/psutil@5.9.8 size: 513371 timestamp: 1705722716862 - kind: conda @@ -19713,6 +21360,52 @@ packages: - pkg:pypi/py-cpuinfo size: 24947 timestamp: 1666774595872 +- kind: conda + name: py-cpuinfo + version: 9.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 + sha256: 1bb0459fdebf2f3155ee511e99097c5506ef206acbdd871b74ae9fc4b0c4a019 + md5: 6f6d42b894118f8378fce11887ccdaff + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/py-cpuinfo@9.0.0 + size: 24947 + timestamp: 1666774595872 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h05400ba_16_cpu + build_number: 16 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h05400ba_16_cpu.conda + sha256: e7ae2e78a52e7c986fd8260ab9cbb33c483f0997bf24f8c2cdc24c28c49428c7 + md5: 13eea94cd11c751009580c32ce6056cc + depends: + - libarrow 14.0.2 h45212c0_16_cpu + - libarrow-acero 14.0.2 h8681a6d_16_cpu + - libarrow-dataset 14.0.2 h8681a6d_16_cpu + - libarrow-flight 14.0.2 h83a3238_16_cpu + - libarrow-flight-sql 14.0.2 h21569af_16_cpu + - libarrow-gandiva 14.0.2 h4e6a3a4_16_cpu + - libarrow-substrait 14.0.2 hea7f8fd_16_cpu + - libparquet 14.0.2 h39135fc_16_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + size: 3469033 + timestamp: 1712761753340 - kind: conda name: pyarrow version: 14.0.2 @@ -19740,6 +21433,8 @@ packages: constrains: - apache-arrow-proc =*=cpu license: Apache-2.0 + purls: + - pkg:pypi/pyarrow@14.0.2 size: 3469033 timestamp: 1712761753340 - kind: conda @@ -19860,6 +21555,38 @@ packages: license_family: APACHE size: 4085287 timestamp: 1712761619928 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h4c23913_16_cpu + build_number: 16 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311h4c23913_16_cpu.conda + sha256: 166d22fcb756ae4b627d6c11a7539bba6513982bea03e1f5101575ac486fdf22 + md5: 72676f83b15af074051028a3d87f2dd7 + depends: + - __osx >=11.0 + - libarrow 14.0.2 h3fc723a_16_cpu + - libarrow-acero 14.0.2 h43a2c78_16_cpu + - libarrow-dataset 14.0.2 h43a2c78_16_cpu + - libarrow-flight 14.0.2 h161034a_16_cpu + - libarrow-flight-sql 14.0.2 h32643e2_16_cpu + - libarrow-gandiva 14.0.2 ha803c60_16_cpu + - libarrow-substrait 14.0.2 h7a0fec1_16_cpu + - libcxx >=14 + - libparquet 14.0.2 he0622da_16_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/pyarrow@14.0.2 + size: 4085287 + timestamp: 1712761619928 - kind: conda name: pyarrow version: 14.0.2 @@ -19975,6 +21702,65 @@ packages: license_family: APACHE size: 4497078 timestamp: 1712756648356 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311h78dcc79_16_cpu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h78dcc79_16_cpu.conda + sha256: b1902c06a4269496fe4e5b1d93167df5de7a63e4cc17148fb363a0769f458036 + md5: d2c07999b8658fa0052c41ffbe85e3a0 + depends: + - libarrow 14.0.2 he70291f_16_cpu + - libarrow-acero 14.0.2 hac33072_16_cpu + - libarrow-dataset 14.0.2 hac33072_16_cpu + - libarrow-flight 14.0.2 hd42f311_16_cpu + - libarrow-flight-sql 14.0.2 h9241762_16_cpu + - libarrow-gandiva 14.0.2 hd4ab825_16_cpu + - libarrow-substrait 14.0.2 h9241762_16_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 h6a7eafb_16_cpu + - libstdcxx-ng >=12 + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/pyarrow@14.0.2 + size: 4497078 + timestamp: 1712756648356 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311hb0c4a44_16_cpu + build_number: 16 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311hb0c4a44_16_cpu.conda + sha256: fdf91161069ef925975a4706da24185d62b45d702c7e3e954e2c3851ce31eea0 + md5: 63c818d925da4ce74da9ff6e4ebaea94 + depends: + - __osx >=10.13 + - libarrow 14.0.2 hf13115f_16_cpu + - libarrow-acero 14.0.2 hcdcf8f8_16_cpu + - libarrow-dataset 14.0.2 hcdcf8f8_16_cpu + - libarrow-flight 14.0.2 hcd10e87_16_cpu + - libarrow-flight-sql 14.0.2 hd7485ff_16_cpu + - libarrow-gandiva 14.0.2 h1359b85_16_cpu + - libarrow-substrait 14.0.2 hd7485ff_16_cpu + - libcxx >=14 + - libparquet 14.0.2 h4aea69c_16_cpu + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + size: 4011396 + timestamp: 1712760246531 - kind: conda name: pyarrow version: 14.0.2 @@ -20001,6 +21787,8 @@ packages: constrains: - apache-arrow-proc =*=cpu license: Apache-2.0 + purls: + - pkg:pypi/pyarrow@14.0.2 size: 4011396 timestamp: 1712760246531 - kind: conda @@ -20090,6 +21878,37 @@ packages: license: Apache-2.0 size: 4395299 timestamp: 1712757143110 +- kind: conda + name: pyarrow + version: 14.0.2 + build: py311hf60b7a8_16_cpu + build_number: 16 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311hf60b7a8_16_cpu.conda + sha256: cfe2988de02922323fea070d1a520a07fc5626db58f908e6f531d763a4802941 + md5: 92eebc9a1f517898d5c1d82ceee0978e + depends: + - libarrow 14.0.2 h520d24b_16_cpu + - libarrow-acero 14.0.2 h0a1ffab_16_cpu + - libarrow-dataset 14.0.2 h0a1ffab_16_cpu + - libarrow-flight 14.0.2 hbf3f4d3_16_cpu + - libarrow-flight-sql 14.0.2 h7624240_16_cpu + - libarrow-gandiva 14.0.2 h1eebba3_16_cpu + - libarrow-substrait 14.0.2 h9b67ed8_16_cpu + - libgcc-ng >=12 + - libparquet 14.0.2 h70b04f6_16_cpu + - libstdcxx-ng >=12 + - numpy >=1.23.5,<2.0a0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - apache-arrow-proc =*=cpu + license: Apache-2.0 + purls: + - pkg:pypi/pyarrow@14.0.2 + size: 4395299 + timestamp: 1712757143110 - kind: pypi name: pyasn1 version: 0.6.0 @@ -20206,6 +22025,31 @@ packages: - pkg:pypi/pytest size: 255523 timestamp: 1709992719691 +- kind: conda + name: pytest + version: 8.1.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda + sha256: 3c481d6b54af1a33c32a3f3eaa3e0971955431e7023db55808740cd062271c73 + md5: 94ff09cdedcb7b17e9cd5097ee2cfcff + depends: + - colorama + - exceptiongroup >=1.0.0rc8 + - iniconfig + - packaging + - pluggy <2.0,>=1.4 + - python >=3.8 + - tomli >=1 + constrains: + - pytest-faulthandler >=2 + license: MIT + license_family: MIT + purls: + - pkg:pypi/pytest@8.1.1 + size: 255523 + timestamp: 1709992719691 - kind: conda name: pytest-benchmark version: 4.0.0 @@ -20225,6 +22069,25 @@ packages: - pkg:pypi/pytest-benchmark size: 39571 timestamp: 1666782598879 +- kind: conda + name: pytest-benchmark + version: 4.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 + sha256: e08bba57295c6ca9cbc265347c312aaab1f0cf66f4e8ff53a2461f32c397536f + md5: 8c3168375e2ac100c17b133f4e2eb536 + depends: + - py-cpuinfo + - pytest >=3.8 + - python >=3.5 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/pytest-benchmark@4.0.0 + size: 39571 + timestamp: 1666782598879 - kind: conda name: python version: 3.11.8 @@ -20453,26 +22316,26 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d + url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab + url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 + url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 + url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab requires_python: '>=3.6' - kind: pypi name: pyyaml-env-tag @@ -20765,26 +22628,26 @@ packages: - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb + url: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl + sha256: d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97 requires_python: '>=3.7' - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl - sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 + url: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa requires_python: '>=3.7' - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl - sha256: d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97 + url: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb requires_python: '>=3.7' - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa + url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl + sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 requires_python: '>=3.7' - kind: pypi name: requests @@ -20860,26 +22723,26 @@ packages: - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 + url: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4 requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 + url: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5 requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4 + url: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5 + url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 requires_python: '>=3.8' - kind: pypi name: rsa @@ -20908,6 +22771,25 @@ packages: - pkg:pypi/ruff size: 6286425 timestamp: 1711999691593 +- kind: conda + name: ruff + version: 0.3.5 + build: py311h7145743_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda + sha256: 21d492a207c88672288668018ff931eea06c65625f2660fc4e4985e52243f4e8 + md5: 476ec3ffa92e3178463c666a221b401b + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruff@0.3.5 + size: 6286425 + timestamp: 1711999691593 - kind: conda name: ruff version: 0.3.5 @@ -20929,6 +22811,27 @@ packages: - pkg:pypi/ruff size: 5764786 timestamp: 1712000852408 +- kind: conda + name: ruff + version: 0.3.5 + build: py311h8c97afb_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda + sha256: 1af91e59adc5bf40a8b5b0e1a2c369286c3e9388179dc76fc2760498a6f2c48c + md5: 8e1fe4c5e7bb5c9a585c57e8cec44d1a + depends: + - libcxx >=16 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruff@0.3.5 + size: 5764786 + timestamp: 1712000852408 - kind: conda name: ruff version: 0.3.5 @@ -20949,6 +22852,26 @@ packages: - pkg:pypi/ruff size: 6257429 timestamp: 1712000640263 +- kind: conda + name: ruff + version: 0.3.5 + build: py311hc14472d_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda + sha256: 7800532c6daeb465b5847d532cd1244ae86dd1eb95878c28f378d3b0c85d5d47 + md5: d0c971d5173e4d2400ab21f7674d8055 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruff@0.3.5 + size: 6257429 + timestamp: 1712000640263 - kind: conda name: ruff version: 0.3.5 @@ -20969,6 +22892,26 @@ packages: - pkg:pypi/ruff size: 5937629 timestamp: 1711999839570 +- kind: conda + name: ruff + version: 0.3.5 + build: py311he69e3a7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda + sha256: db0e13ff550e1afd405487d3aeb14dc534bca8bf62c297323e83a13fb67e92a8 + md5: c3dc02c8cc9a80ca0b34fc86b083e284 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruff@0.3.5 + size: 5937629 + timestamp: 1711999839570 - kind: conda name: ruff version: 0.3.5 @@ -20989,6 +22932,26 @@ packages: - pkg:pypi/ruff size: 6083087 timestamp: 1712000648440 +- kind: conda + name: ruff + version: 0.3.5 + build: py311hfff7943_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda + sha256: 576c9a798ac3a78e8ea4cddd914f45aa7f1615a0e4393bf4cead8d9808ac97b6 + md5: b5410e0ebf58e4444b4659b1f3ee21fc + depends: + - libcxx >=16 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - __osx >=10.12 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ruff@0.3.5 + size: 6083087 + timestamp: 1712000648440 - kind: conda name: s2n version: 1.4.1 @@ -21066,6 +23029,23 @@ packages: license_family: Apache size: 339709 timestamp: 1712101772538 +- kind: conda + name: semver + version: 2.13.0 + build: pyh9f0ad1d_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 + sha256: 673ef5ef04cef60c3584b1d9b81024646b9d9a4c50749356c7ba5cede755e61d + md5: 2cab9f3a9683cb40a2176ccaf76e66c6 + depends: + - python + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/semver@2.13.0 + size: 15712 + timestamp: 1603697876069 - kind: conda name: semver version: 2.13.0 @@ -21138,6 +23118,23 @@ packages: - pkg:pypi/setuptools size: 471183 timestamp: 1710344615844 +- kind: conda + name: setuptools + version: 69.2.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda + sha256: 78a75c75a5dacda6de5f4056c9c990141bdaf4f64245673a590594d00bc63713 + md5: da214ecd521a720a9d521c68047682dc + depends: + - python >=3.8 + license: MIT + license_family: MIT + purls: + - pkg:pypi/setuptools@69.2.0 + size: 471183 + timestamp: 1710344615844 - kind: conda name: sigtool version: 0.1.3 @@ -21172,6 +23169,23 @@ packages: url: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl sha256: 8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*' +- kind: conda + name: smmap + version: 5.0.0 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 + sha256: 23011cb3e064525bdb8787c75126a2e78d2344a72cd6773922006d1da1f2af16 + md5: 62f26a3d1387acee31322208f0cfa3e0 + depends: + - python >=3.5 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/smmap@5.0.0 + size: 22483 + timestamp: 1634310465482 - kind: conda name: smmap version: 5.0.0 @@ -21354,6 +23368,14 @@ packages: - certifi - jsonschema >=3.0 requires_python: '>=3.6' +- kind: pypi + name: sympy + version: '1.12' + url: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl + sha256: c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5 + requires_dist: + - mpmath >=0.19 + requires_python: '>=3.8' - kind: conda name: sysroot_linux-64 version: '2.12' @@ -21675,6 +23697,23 @@ packages: license_family: BSD size: 3318875 timestamp: 1699202167581 +- kind: conda + name: tomli + version: 2.0.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 + sha256: 4cd48aba7cd026d17e86886af48d0d2ebc67ed36f87f6534f4b67138f5a5a58f + md5: 5844808ffab9ebdb694585b50ba02a96 + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomli@2.0.1 + size: 15940 + timestamp: 1644342331069 - kind: conda name: tomli version: 2.0.1 @@ -21694,6 +23733,23 @@ packages: - pkg:pypi/tomli size: 15940 timestamp: 1644342331069 +- kind: conda + name: tomlkit + version: 0.12.3 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + sha256: 53cc436ab92d38683df1320e4468a8b978428e800195bf1c8c2460e90b0bc117 + md5: 074d0ce7a6261ab8b497c3518796ef3e + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/tomlkit@0.12.3 + size: 37132 + timestamp: 1700046842169 - kind: conda name: tomlkit version: 0.12.3 @@ -21713,6 +23769,161 @@ packages: - pkg:pypi/tomlkit size: 37132 timestamp: 1700046842169 +- kind: pypi + name: torch + version: 2.2.2 + url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl + sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb + requires_dist: + - filelock + - typing-extensions >=4.8.0 + - sympy + - networkx + - jinja2 + - fsspec + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' + requires_python: '>=3.8.0' +- kind: pypi + name: torch + version: 2.2.2 + url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 + requires_dist: + - filelock + - typing-extensions >=4.8.0 + - sympy + - networkx + - jinja2 + - fsspec + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' + requires_python: '>=3.8.0' +- kind: pypi + name: torch + version: 2.2.2 + url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 + requires_dist: + - filelock + - typing-extensions >=4.8.0 + - sympy + - networkx + - jinja2 + - fsspec + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' + requires_python: '>=3.8.0' +- kind: pypi + name: torch + version: 2.2.2 + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + requires_dist: + - filelock + - typing-extensions >=4.8.0 + - sympy + - networkx + - jinja2 + - fsspec + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' + requires_python: '>=3.8.0' +- kind: pypi + name: torch + version: 2.2.2 + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + requires_dist: + - filelock + - typing-extensions >=4.8.0 + - sympy + - networkx + - jinja2 + - fsspec + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' + requires_python: '>=3.8.0' +- kind: pypi + name: triton + version: 2.2.0 + url: https://files.pythonhosted.org/packages/bd/ac/3974caaa459bf2c3a244a84be8d17561f631f7d42af370fc311defeca2fb/triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: da58a152bddb62cafa9a857dd2bc1f886dbf9f9c90a2b5da82157cd2b34392b0 + requires_dist: + - filelock + - cmake >=3.20 ; extra == 'build' + - lit ; extra == 'build' + - autopep8 ; extra == 'tests' + - flake8 ; extra == 'tests' + - isort ; extra == 'tests' + - numpy ; extra == 'tests' + - pytest ; extra == 'tests' + - scipy >=1.7.1 ; extra == 'tests' + - torch ; extra == 'tests' + - matplotlib ; extra == 'tutorials' + - pandas ; extra == 'tutorials' + - tabulate ; extra == 'tutorials' + - torch ; extra == 'tutorials' - kind: conda name: typing_extensions version: 4.8.0 @@ -21783,6 +23994,23 @@ packages: - pkg:pypi/typing-extensions size: 37583 timestamp: 1712330089194 +- kind: conda + name: typing_extensions + version: 4.11.0 + build: pyha770c72_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda + sha256: a7e8714d14f854058e971a6ed44f18cc37cc685f98ddefb2e6b7899a0cc4d1a2 + md5: 6ef2fc37559256cf682d8b3375e89b80 + depends: + - python >=3.8 + license: PSF-2.0 + license_family: PSF + purls: + - pkg:pypi/typing-extensions@4.11.0 + size: 37583 + timestamp: 1712330089194 - kind: conda name: typos version: 1.16.20 @@ -22307,35 +24535,52 @@ packages: - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl - sha256: 8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3 + url: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b + url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl + sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935 + url: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl + sha256: 8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl - sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269 + url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' +- kind: conda + name: wheel + version: 0.38.4 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + sha256: bd4f11ff075ff251ade9f57686f31473e25be46ab282d9603f551401250f9f44 + md5: c829cfb8cb826acb9de0ac1a2df0a940 + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/wheel@0.38.4 + size: 32521 + timestamp: 1668051714265 - kind: conda name: wheel version: 0.38.4 diff --git a/pixi.toml b/pixi.toml index 00eddd2dd152..3f158737047b 100644 --- a/pixi.toml +++ b/pixi.toml @@ -24,6 +24,7 @@ version = "0.1.0" # [environments] cpp = ["cpp"] py-docs = ["py-docs"] +wheel-test = ["wheel-test"] [tasks] # Note: extra CLI argument after `pixi run TASK` are passed to the task cmd. @@ -221,6 +222,14 @@ cpp-fmt = "fd --extension h --extension hpp --extension c --extension cpp --exe [feature.cpp.target.win-64.tasks] cpp-prepare-msvc = "cmake -G 'Visual Studio 17 2022' -B build-msvc -S ." +[feature.wheel-test.pypi-dependencies] +torch = ">=2.0.1" + + +[feature.wheel-test.tasks] +# In the wheel-test environment we want to use the wheel-installed `rerun` binary on the path. +# This overrides the `rerun` task from the default env which otherwise executes via cargo. +rerun = "rerun" [dependencies] # IMPORTANT: do not add any dependencies here that may break CI. All dependencies should be available on all supported From b8360bfa23ac5bc1d01cc584c5b6c44774d97b6a Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 12 Apr 2024 08:21:49 +0200 Subject: [PATCH 266/508] Only build web viewer if any rust or web stuff has changed (#5916) ### What For instance: Don't build web viewer when editing docs ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5916?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5916?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5916) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/on_pull_request.yml | 95 +++++++++++++++++---------- 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 61cd0097cc28..f4b3feb7614a 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -21,10 +21,10 @@ jobs: CONCURRENCY: pr-${{ github.event.pull_request.number }} secrets: inherit - rust-paths-filter: + cpp-paths-filter: runs-on: ubuntu-latest outputs: - rust_changes: ${{ steps.filter.outputs.rust_changes }} + cpp_changes: ${{ steps.filter.outputs.cpp_changes }} steps: - uses: actions/checkout@v4 with: @@ -33,17 +33,20 @@ jobs: id: filter with: filters: | - rust_changes: - - .github/**/*.yml # CI changes should always trigger all jobs + cpp_changes: + # - .github/**/*.yml - this is tempting, but leads to constant rebuilds - pixi.lock # maybe out build commands have changed - pixi.toml # maybe out build commands have changed - - "**/*.rs" - - "**/*.toml" + - scripts/ci/* + - '**/*.hpp' + - '**/*.cpp' + - '**/CMakeLists.txt' + - '**/*cmake' - cpp-paths-filter: + docs-paths-filter: runs-on: ubuntu-latest outputs: - cpp_changes: ${{ steps.filter.outputs.cpp_changes }} + docs_changes: ${{ steps.filter.outputs.docs_changes }} steps: - uses: actions/checkout@v4 with: @@ -52,14 +55,14 @@ jobs: id: filter with: filters: | - cpp_changes: - - .github/**/*.yml # CI changes should always trigger all jobs + docs_changes: + # - .github/**/*.yml - this is tempting, but leads to constant rebuilds - pixi.lock # maybe out build commands have changed - pixi.toml # maybe out build commands have changed - - '**/*.hpp' - - '**/*.cpp' - - '**/CMakeLists.txt' - - '**/*cmake' + - scripts/ci/* + - 'docs/content/**/*.md' + - 'examples/**/*.md' + - 'examples/manifest.toml' python-paths-filter: runs-on: ubuntu-latest @@ -74,17 +77,18 @@ jobs: with: filters: | python_changes: - - .github/**/*.yml # CI changes should always trigger all jobs + # - .github/**/*.yml - this is tempting, but leads to constant rebuilds - pixi.lock # maybe out build commands have changed - pixi.toml # maybe out build commands have changed + - scripts/ci/* - '**/*.py' - '**/requirements.txt' - '**/pyproject.toml' - docs-paths-filter: + rust-paths-filter: runs-on: ubuntu-latest outputs: - docs_changes: ${{ steps.filter.outputs.docs_changes }} + rust_changes: ${{ steps.filter.outputs.rust_changes }} steps: - uses: actions/checkout@v4 with: @@ -93,19 +97,43 @@ jobs: id: filter with: filters: | - docs_changes: - - .github/**/*.yml # CI changes should always trigger all jobs + rust_changes: + # - .github/**/*.yml - this is tempting, but leads to constant rebuilds - pixi.lock # maybe out build commands have changed - pixi.toml # maybe out build commands have changed - - 'docs/content/**/*.md' - - 'examples/**/*.md' - - 'examples/manifest.toml' + - scripts/ci/* + - "**/*.rs" + - "**/*.toml" + + web-paths-filter: + runs-on: ubuntu-latest + outputs: + web_changes: ${{ steps.filter.outputs.web_changes }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + web_changes: + # - .github/**/*.yml - this is tempting, but leads to constant rebuilds + - pixi.lock # maybe out build commands have changed + - pixi.toml # maybe out build commands have changed + - scripts/ci/* + - "**/*.html" + - "**/*.js" + - "**/*.json" + - "**/*.rs" + - "**/*.toml" + - "**/yarn.lock" + - "crates/re_ui/data/**" rust-checks: name: "Rust Checks" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.rust-paths-filter.outputs.rust_changes == 'true' - # Wait for the rust-paths-filter to be completed before starting. needs: rust-paths-filter + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.rust-paths-filter.outputs.rust_changes == 'true' uses: ./.github/workflows/reusable_checks_rust.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} @@ -114,9 +142,8 @@ jobs: python-checks: name: "Python Checks" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.python-paths-filter.outputs.python_changes == 'true' - # Wait for the python-paths-filter to be completed before starting. needs: python-paths-filter + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.python-paths-filter.outputs.python_changes == 'true' uses: ./.github/workflows/reusable_checks_python.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} @@ -124,9 +151,8 @@ jobs: cpp-tests: name: "C++ tests" - if: needs.cpp-paths-filter.outputs.cpp_changes == 'true' - # Wait for the cpp-paths-filter to be completed before starting. needs: cpp-paths-filter + if: needs.cpp-paths-filter.outputs.cpp_changes == 'true' uses: ./.github/workflows/reusable_checks_cpp.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} @@ -137,7 +163,8 @@ jobs: # choice, but reusable_test_wheels.yml is broken for that target (https://github.com/rerun-io/rerun/issues/5525) min-wheel-build: name: "Minimum Wheel Build" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' + needs: [python-paths-filter, rust-paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.python-paths-filter.outputs.python_changes == 'true' || needs.rust-paths-filter.outputs.rust_changes == 'true') uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} @@ -148,8 +175,8 @@ jobs: min-wheel-test: name: "Minimum Wheel Test" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' - needs: [min-wheel-build] + needs: [min-wheel-build, python-paths-filter, rust-paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.python-paths-filter.outputs.python_changes == 'true' || needs.rust-paths-filter.outputs.rust_changes == 'true') uses: ./.github/workflows/reusable_test_wheels.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} @@ -160,7 +187,8 @@ jobs: build-js: name: "Build rerun_js" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' + needs: [web-paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.web-paths-filter.outputs.web_changes == 'true' uses: ./.github/workflows/reusable_build_js.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} @@ -168,7 +196,8 @@ jobs: build-web: name: "Build web viewer" - if: github.event.pull_request.head.repo.owner.login == 'rerun-io' + needs: [web-paths-filter] + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.web-paths-filter.outputs.web_changes == 'true' uses: ./.github/workflows/reusable_build_web.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} From 41986fa9a05702892fe4eaeaf631f8cc4de44c30 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 12 Apr 2024 08:51:05 +0200 Subject: [PATCH 267/508] Update to pixi 0.19 (#5935) ### What Should remove some warnings we see on CI ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5935?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5935?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5935) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/auto_release_crates.yml | 2 +- .github/workflows/contrib_checks.yml | 10 +++++----- .github/workflows/contrib_rerun_py.yml | 2 +- .github/workflows/release.yml | 4 ++-- .../workflows/reusable_build_and_upload_rerun_cli.yml | 2 +- .github/workflows/reusable_build_and_upload_wheels.yml | 2 +- .github/workflows/reusable_build_examples.yml | 2 +- .github/workflows/reusable_build_js.yml | 2 +- .github/workflows/reusable_build_web.yml | 2 +- .github/workflows/reusable_checks.yml | 8 ++++---- .github/workflows/reusable_checks_cpp.yml | 2 +- .github/workflows/reusable_checks_python.yml | 4 ++-- .github/workflows/reusable_checks_rust.yml | 2 +- .github/workflows/reusable_deploy_docs.yml | 4 ++-- .github/workflows/reusable_publish_js.yml | 2 +- .github/workflows/reusable_publish_web.yml | 2 +- .github/workflows/reusable_release_crates.yml | 2 +- .github/workflows/reusable_test_wheels.yml | 2 +- 18 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/auto_release_crates.yml b/.github/workflows/auto_release_crates.yml index c68b0e991601..c3547c8d9ad8 100644 --- a/.github/workflows/auto_release_crates.yml +++ b/.github/workflows/auto_release_crates.yml @@ -22,7 +22,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Install dependencies shell: bash diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 880fb5849c26..63b4c8b947b4 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -48,7 +48,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Set up Python uses: actions/setup-python@v4 with: @@ -78,7 +78,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Build via mkdocs shell: bash @@ -96,7 +96,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Codegen check shell: bash @@ -120,7 +120,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Set up Python uses: actions/setup-python@v4 @@ -177,7 +177,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 # TODO(emilk): make this work somehow. Right now this just results in # > Compiler: GNU 12.3.0 (/__w/rerun/rerun/.pixi/env/bin/x86_64-conda-linux-gnu-c++) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index d172ba01e415..1c24ecf3822a 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -54,7 +54,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 # These should already be in the docker container, but run for good measure. A no-op install # should be fast, and this way things don't break if we add new packages without rebuilding diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b823995203f1..423633405f42 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,7 +90,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Update crate versions id: versioning @@ -392,7 +392,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Install dependencies shell: bash diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index d4e01d3e2ba7..89113325da81 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -163,7 +163,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Build web-viewer (release) shell: bash diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 51460e953fe6..8f54a8421230 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -188,7 +188,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Install dependencies shell: bash diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 8833bb30bb8c..712391f16f64 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -61,7 +61,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Download Wheel uses: actions/download-artifact@v4 diff --git a/.github/workflows/reusable_build_js.yml b/.github/workflows/reusable_build_js.yml index ac02d36e95ac..774c1c9e99ef 100644 --- a/.github/workflows/reusable_build_js.yml +++ b/.github/workflows/reusable_build_js.yml @@ -63,7 +63,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.3.0 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Install yarn dependencies shell: bash diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 9ab4919adc11..78072007e8b6 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -63,7 +63,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Build web-viewer (release) shell: bash diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index b7a751d9987f..a7938760cfc3 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -47,7 +47,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Build via mkdocs run: pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml @@ -73,7 +73,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Codegen check shell: bash @@ -92,7 +92,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Set up Python uses: actions/setup-python@v4 @@ -147,7 +147,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: prettier --check run: pixi run misc-fmt-check diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index a39c5909e8c8..3359358776bc 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -77,7 +77,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Set up Rust uses: ./.github/actions/setup-rust diff --git a/.github/workflows/reusable_checks_python.yml b/.github/workflows/reusable_checks_python.yml index b394dcf53d4e..1b5e232d4d87 100644 --- a/.github/workflows/reusable_checks_python.yml +++ b/.github/workflows/reusable_checks_python.yml @@ -31,7 +31,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Python format check run: pixi run py-fmt-check @@ -51,7 +51,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Build via mkdocs shell: bash diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index a18c167cb6ee..0e11da44adab 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -60,7 +60,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 # We need to build the web viewer for `rust_checks.py` to succeed. # We build in release so that we can reuse the results for actual publishing, if necessary diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index b451baf0a884..5948e0636ec8 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -70,7 +70,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Set up git author shell: bash @@ -204,7 +204,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Doxygen C++ docs shell: bash diff --git a/.github/workflows/reusable_publish_js.yml b/.github/workflows/reusable_publish_js.yml index d75cc9d84259..e98a96214413 100644 --- a/.github/workflows/reusable_publish_js.yml +++ b/.github/workflows/reusable_publish_js.yml @@ -63,7 +63,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.3.0 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Publish packages env: diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index 7c925bcc9177..7f75b97b08a5 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -74,7 +74,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 # built by `reusable_build_and_publish_wheels` - name: Download Wheel diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml index dabc0b001afb..e5c9fccc82f9 100644 --- a/.github/workflows/reusable_release_crates.yml +++ b/.github/workflows/reusable_release_crates.yml @@ -26,7 +26,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Build web-viewer (release) shell: bash diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 2c74ba422fe7..0042137f453c 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -145,7 +145,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: - pixi-version: v0.18.0 + pixi-version: v0.19.0 - name: Download Wheel uses: actions/download-artifact@v4 From 78d46da42829bf0dc9d4b76f829caab0de89ede5 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 12 Apr 2024 11:10:40 +0200 Subject: [PATCH 268/508] Move many CI jobs from `main` to `nightly` (#5937) ### What * A huge part of https://github.com/rerun-io/rerun/issues/5332 This moves _a lot_ of jobs from `main` to nightly: * Building and testing wheels, `rerun_c` and `rerun-cli` for all platforms (keeping just linux-x86 on `main`) * Doing a pre-release * Benchmarks * Clean build This should reduce the billable time on `main` significantly. I've mostly just moved the jobs (leaving a few behind) and changing `CONCURRENCY:` to `nightly` everywhere. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5937?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5937?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5937) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/nightly.yml | 358 ++++++++++++++++++++++++++++- .github/workflows/on_push_main.yml | 278 +--------------------- BUILD.md | 2 +- 3 files changed, 356 insertions(+), 282 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index e1f80b61454f..ebe2131654e7 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -38,6 +38,22 @@ jobs: CONCURRENCY: nightly secrets: inherit + # Check that a CLEAN container with just `cargo` on it can build rerun: + clean-build: + name: cargo build on clean container + strategy: + matrix: + os: [ubuntu-latest-16-cores, macos-latest, windows-latest-8-cores] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: 1.76.0 + + - run: cargo build -p rerun + shell: bash + build-web: name: "Build web viewer" uses: ./.github/workflows/reusable_build_web.yml @@ -55,28 +71,228 @@ jobs: NIGHTLY: true secrets: inherit - build-wheel-linux: - name: "Build & Upload Wheels" + # --------------------------------------------------------------------------- + # Build wheels: + + build-wheel-linux-arm64: + needs: [checks] + name: "Linux-arm64: Build & Upload Wheels" + uses: ./.github/workflows/reusable_build_and_upload_wheels.yml + with: + CONCURRENCY: nightly + PLATFORM: linux-arm64 + WHEEL_ARTIFACT_NAME: linux-arm64-wheel + MODE: "pypi" + secrets: inherit + + build-wheel-linux-x64: + needs: [checks] + name: "Linux-x64: Build & Upload Wheels" + uses: ./.github/workflows/reusable_build_and_upload_wheels.yml + with: + CONCURRENCY: nightly + PLATFORM: linux-x64 + WHEEL_ARTIFACT_NAME: linux-x64-wheel + MODE: "pypi" + secrets: inherit + + build-wheel-macos-arm64: + needs: [checks] + name: "Macos-arm64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: nightly-linux + CONCURRENCY: nightly + PLATFORM: macos-arm64 + WHEEL_ARTIFACT_NAME: macos-arm64-wheel + MODE: "pypi" + secrets: inherit + + build-wheel-macos-x64: + needs: [checks] + name: "Macos-x64: Build & Upload Wheels" + uses: ./.github/workflows/reusable_build_and_upload_wheels.yml + with: + CONCURRENCY: nightly + PLATFORM: macos-x64 + WHEEL_ARTIFACT_NAME: "macos-x64-wheel" + MODE: "pypi" + secrets: inherit + + build-wheel-windows-x64: + needs: [checks] + name: "Windows-x64: Build & Upload Wheels" + uses: ./.github/workflows/reusable_build_and_upload_wheels.yml + with: + CONCURRENCY: nightly + PLATFORM: windows-x64 + WHEEL_ARTIFACT_NAME: windows-x64-wheel + MODE: "pypi" + secrets: inherit + + # --------------------------------------------------------------------------- + # Test wheels: + + test-wheel-linux-arm64: + needs: [checks, build-wheel-linux-arm64] + name: "linux-arm64: Test Wheels" + uses: ./.github/workflows/reusable_test_wheels.yml + with: + CONCURRENCY: nightly + PLATFORM: linux-arm64 + WHEEL_ARTIFACT_NAME: linux-arm64-wheel + secrets: inherit + + test-wheel-linux-x64: + needs: [checks, build-wheel-linux-x64] + name: "Linux-x64: Test Wheels" + uses: ./.github/workflows/reusable_test_wheels.yml + with: + CONCURRENCY: nightly PLATFORM: linux-x64 WHEEL_ARTIFACT_NAME: linux-x64-wheel - MODE: "pr" secrets: inherit + test-wheel-macos-arm64: + needs: [checks, build-wheel-macos-arm64] + name: "macos-arm64: Test Wheels" + uses: ./.github/workflows/reusable_test_wheels.yml + with: + CONCURRENCY: nightly + PLATFORM: macos-arm64 + WHEEL_ARTIFACT_NAME: macos-arm64-wheel + secrets: inherit + + test-wheel-macos-x64: + needs: [checks, build-wheel-macos-x64] + name: "macos-x64: Test Wheels" + uses: ./.github/workflows/reusable_test_wheels.yml + with: + CONCURRENCY: nightly + PLATFORM: macos-x64 + WHEEL_ARTIFACT_NAME: macos-x64-wheel + secrets: inherit + + test-wheel-windows-x64: + needs: [checks, build-wheel-windows-x64] + name: "Windows-x64: Test Wheels" + uses: ./.github/workflows/reusable_test_wheels.yml + with: + CONCURRENCY: nightly + PLATFORM: windows-x64 + WHEEL_ARTIFACT_NAME: windows-x64-wheel + secrets: inherit + + # ----------------------------------------------------------------------------------- + # Build rerun_c library binaries: + + build-rerun_c-and-upload-linux-arm64: + needs: [checks] + name: "Linux-Arm64: Build & Upload rerun_c" + uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml + with: + CONCURRENCY: nightly + PLATFORM: linux-arm64 + secrets: inherit + + build-rerun_c-and-upload-linux-x64: + needs: [checks] + name: "Linux-x64: Build & Upload rerun_c" + uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml + with: + CONCURRENCY: nightly + PLATFORM: linux-x64 + secrets: inherit + + build-rerun_c-and-upload-macos-x64: + needs: [checks] + name: "Mac-Intel: Build & Upload rerun_c" + uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml + with: + CONCURRENCY: nightly + PLATFORM: macos-x64 + secrets: inherit + + build-rerun_c-and-upload-macos-arm64: + needs: [checks] + name: "Mac-Arm64: Build & Upload rerun_c" + uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml + with: + CONCURRENCY: nightly + PLATFORM: macos-arm64 + secrets: inherit + + build-rerun_c-and-upload-windows-x64: + needs: [checks] + name: "Windows-x64: Build & Upload rerun_c" + uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml + with: + CONCURRENCY: nightly + PLATFORM: windows-x64 + secrets: inherit + + # ----------------------------------------------------------------------------------- + # TODO(emilk): build and test one additional platorm, picked at random + # Build rerun-cli (rerun binaries): + + build-rerun-cli-and-upload-linux-arm64: + needs: [checks] + name: "Linux-arm64: Build & Upload rerun-cli" + uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + with: + CONCURRENCY: nightly + PLATFORM: linux-arm64 + secrets: inherit + + build-rerun-cli-and-upload-linux-x64: + needs: [checks] + name: "Linux-x64: Build & Upload rerun-cli" + uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + with: + CONCURRENCY: nightly + PLATFORM: linux-x64 + secrets: inherit + + build-rerun-cli-and-upload-macos-x64: + needs: [checks] + name: "Mac-x64: Build & Upload rerun-cli" + uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + with: + CONCURRENCY: nightly + PLATFORM: macos-x64 + secrets: inherit + + build-rerun-cli-and-upload-macos-arm64: + needs: [checks] + name: "Mac-arm64: Build & Upload rerun-cli" + uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + with: + CONCURRENCY: nightly + PLATFORM: macos-arm64 + secrets: inherit + + build-rerun-cli-and-upload-windows-x64: + needs: [checks] + name: "Windows-x64: Build & Upload rerun-cli" + uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml + with: + CONCURRENCY: nightly + PLATFORM: windows-x64 + secrets: inherit + + # --------------------------------------------------------------------------- + run-notebook: name: "Run Notebook" - needs: [build-wheel-linux] + needs: [build-wheel-linux-x64] uses: ./.github/workflows/reusable_run_notebook.yml with: - CONCURRENCY: push-linux-x64-${{ github.ref_name }} + CONCURRENCY: nightly WHEEL_ARTIFACT_NAME: linux-x64-wheel secrets: inherit build-examples: name: "Build Examples" - needs: [build-wheel-linux] + needs: [build-wheel-linux-x64] uses: ./.github/workflows/reusable_build_examples.yml with: CONCURRENCY: nightly @@ -92,3 +308,131 @@ jobs: CONCURRENCY: nightly NIGHTLY: true secrets: inherit + + benches: + name: Benchmarks + uses: ./.github/workflows/reusable_bench.yml + with: + CONCURRENCY: nightly + SAVE_BENCHES: true + BENCH_NAME: main # We currently only run benches nightly, but we used to run them on main + COMPARE_TO: main # We currently only run benches nightly, but we used to run them on main + secrets: inherit + + # -------------------------------------------------------------------------- + # Release: + + generate-pip-index: + name: "Generate Pip Index" + needs: + [ + build-wheel-linux-arm64, + build-wheel-linux-x64, + build-wheel-macos-arm64, + build-wheel-macos-x64, + build-wheel-windows-x64, + ] + uses: ./.github/workflows/reusable_pip_index.yml + with: + CONCURRENCY: nightly + secrets: inherit + + bundle-and-upload-rerun_cpp: + name: "Bundle and upload rerun_cpp_sdk.zip" + needs: + [ + build-rerun_c-and-upload-linux-arm64, + build-rerun_c-and-upload-linux-x64, + build-rerun_c-and-upload-macos-arm64, + build-rerun_c-and-upload-macos-x64, + build-rerun_c-and-upload-windows-x64, + ] + uses: ./.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml + secrets: inherit + + pre-release: + name: Pre Release + concurrency: NIGHTLY + needs: + [ + build-rerun-cli-and-upload-linux-arm64, + build-rerun-cli-and-upload-linux-x64, + build-rerun-cli-and-upload-macos-arm64, + build-rerun-cli-and-upload-macos-x64, + build-rerun-cli-and-upload-windows-x64, + build-rerun_c-and-upload-linux-arm64, + build-rerun_c-and-upload-linux-x64, + build-rerun_c-and-upload-macos-arm64, + build-rerun_c-and-upload-macos-x64, + build-rerun_c-and-upload-windows-x64, + bundle-and-upload-rerun_cpp, + generate-pip-index, + upload-web, + ] + runs-on: "ubuntu-latest" + steps: + - name: Add SHORT_SHA env property with commit short sha + shell: bash + run: echo "SHORT_SHA=`echo ${{github.sha}} | cut -c1-7`" >> $GITHUB_ENV + + # First delete the old prerelease. If we don't do this, we don't get things like + # proper source-archives and changelog info. + # https://github.com/dev-drprasad/delete-tag-and-release + - uses: dev-drprasad/delete-tag-and-release@v0.2.1 + with: + tag_name: prerelease + delete_release: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Create the actual prerelease + # https://github.com/ncipollo/release-action + - name: GitHub Release + uses: ncipollo/release-action@v1.12.0 + with: + body: | + This is a prerelease. It is not intended for production use. + Please report any issues you find. + + ## Example Hosted App + https://rerun.io/viewer/commit/${{ env.SHORT_SHA }} + + ## Wheels can be installed with: + ``` + pip install --pre -f https://build.rerun.io/commit/${{ env.SHORT_SHA }}/wheels --upgrade rerun-sdk + ``` + or + ``` + pip install --pre -f https://github.com/rerun-io/rerun/releases/download/prerelease --upgrade rerun-sdk + ``` + + ## CMake fetch-content for C++ SDK + ``` + include(FetchContent) + FetchContent_Declare(rerun_sdk URL https://build.rerun.io/commit/${{ env.SHORT_SHA }}/rerun_cpp_sdk.zip) + FetchContent_MakeAvailable(rerun_sdk) + ``` + or + ``` + include(FetchContent) + FetchContent_Declare(rerun_sdk URL https://github.com/rerun-io/rerun/releases/download/prerelease/rerun_cpp_sdk.zip) + FetchContent_MakeAvailable(rerun_sdk) + ``` + + prerelease: true + name: "Development Build" + tag: "prerelease" + token: ${{ secrets.GITHUB_TOKEN }} + generateReleaseNotes: false + allowUpdates: true + removeArtifacts: true + replacesArtifacts: true + + sync-release-assets: + needs: [pre-release] + name: "Sync pre-release assets & build.rerun.io" + uses: ./.github/workflows/reusable_sync_release_assets.yml + with: + CONCURRENCY: nightly + RELEASE_VERSION: prerelease + secrets: inherit diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 2b84fa2c8df3..d3bcc75bf7e1 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -36,34 +36,8 @@ jobs: CONCURRENCY: push-${{ github.ref_name }} secrets: inherit - # Check that a CLEAN container with just `cargo` on it can build rerun: - clean-build: - name: cargo build on clean container - strategy: - matrix: - os: [ubuntu-latest-16-cores, macos-latest, windows-latest-8-cores] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@master - with: - toolchain: 1.76.0 - - - run: cargo build -p rerun - shell: bash - - benches: - name: Benchmarks - uses: ./.github/workflows/reusable_bench.yml - with: - CONCURRENCY: push-${{ github.ref_name }} - SAVE_BENCHES: true - BENCH_NAME: main - COMPARE_TO: main - secrets: inherit - deploy-docs: - needs: [checks, benches] + needs: [checks] name: Deploy Docs uses: ./.github/workflows/reusable_deploy_docs.yml with: @@ -118,16 +92,7 @@ jobs: secrets: inherit # ----------------------------------------------------------------------------------- - # Build rerun_c library binaries: - - build-rerun_c-and-upload-linux-arm64: - needs: [checks] - name: "Linux-Arm64: Build & Upload rerun_c" - uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml - with: - CONCURRENCY: push-linux-arm64-${{ github.ref_name }} - PLATFORM: linux-arm64 - secrets: inherit + # TODO(emilk): build and test one additional platorm, picked at random build-rerun_c-and-upload-linux-x64: needs: [checks] @@ -138,44 +103,8 @@ jobs: PLATFORM: linux-x64 secrets: inherit - build-rerun_c-and-upload-macos-x64: - needs: [checks] - name: "Mac-Intel: Build & Upload rerun_c" - uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml - with: - CONCURRENCY: push-macos-x64-${{ github.ref_name }} - PLATFORM: macos-x64 - secrets: inherit - - build-rerun_c-and-upload-macos-arm64: - needs: [checks] - name: "Mac-Arm64: Build & Upload rerun_c" - uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml - with: - CONCURRENCY: push-macos-arm64-${{ github.ref_name }} - PLATFORM: macos-arm64 - secrets: inherit - - build-rerun_c-and-upload-windows-x64: - needs: [checks] - name: "Windows-x64: Build & Upload rerun_c" - uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml - with: - CONCURRENCY: push-windows-x64-${{ github.ref_name }} - PLATFORM: windows-x64 - secrets: inherit - # ----------------------------------------------------------------------------------- - # Build rerun-cli (rerun binaries): - - build-rerun-cli-and-upload-linux-arm64: - needs: [checks] - name: "Linux-arm64: Build & Upload rerun-cli" - uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml - with: - CONCURRENCY: push-linux-arm64-${{ github.ref_name }} - PLATFORM: linux-arm64 - secrets: inherit + # TODO(emilk): build and test one additional platorm, picked at random build-rerun-cli-and-upload-linux-x64: needs: [checks] @@ -186,45 +115,8 @@ jobs: PLATFORM: linux-x64 secrets: inherit - build-rerun-cli-and-upload-macos-x64: - needs: [checks] - name: "Mac-x64: Build & Upload rerun-cli" - uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml - with: - CONCURRENCY: push-macos-x64-${{ github.ref_name }} - PLATFORM: macos-x64 - secrets: inherit - - build-rerun-cli-and-upload-macos-arm64: - needs: [checks] - name: "Mac-arm64: Build & Upload rerun-cli" - uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml - with: - CONCURRENCY: push-macos-arm64-${{ github.ref_name }} - PLATFORM: macos-arm64 - secrets: inherit - - build-rerun-cli-and-upload-windows-x64: - needs: [checks] - name: "Windows-x64: Build & Upload rerun-cli" - uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml - with: - CONCURRENCY: push-windows-x64-${{ github.ref_name }} - PLATFORM: windows-x64 - secrets: inherit - # ----------------------------------------------------------------------------------- - - build-wheel-linux-arm64: - needs: [checks] - name: "Linux-arm64: Build & Upload Wheels" - uses: ./.github/workflows/reusable_build_and_upload_wheels.yml - with: - CONCURRENCY: push-linux-arm64-${{ github.ref_name }} - PLATFORM: linux-arm64 - WHEEL_ARTIFACT_NAME: linux-arm64-wheel - MODE: "pypi" - secrets: inherit + # TODO(emilk): build and test one additional platorm, picked at random build-wheel-linux-x64: needs: [checks] @@ -237,39 +129,6 @@ jobs: MODE: "pypi" secrets: inherit - build-wheel-windows-x64: - needs: [checks] - name: "Windows-x64: Build & Upload Wheels" - uses: ./.github/workflows/reusable_build_and_upload_wheels.yml - with: - CONCURRENCY: push-windows-x64-${{ github.ref_name }} - PLATFORM: windows-x64 - WHEEL_ARTIFACT_NAME: windows-x64-wheel - MODE: "pypi" - secrets: inherit - - build-wheel-macos-arm64: - needs: [checks] - name: "Macos-arm64: Build & Upload Wheels" - uses: ./.github/workflows/reusable_build_and_upload_wheels.yml - with: - CONCURRENCY: push-macos-arm64-${{ github.ref_name }} - PLATFORM: macos-arm64 - WHEEL_ARTIFACT_NAME: macos-arm64-wheel - MODE: "pypi" - secrets: inherit - - build-wheel-macos-x64: - needs: [checks] - name: "Macos-x64: Build & Upload Wheels" - uses: ./.github/workflows/reusable_build_and_upload_wheels.yml - with: - CONCURRENCY: push-macos-x64-${{ github.ref_name }} - PLATFORM: macos-x64 - WHEEL_ARTIFACT_NAME: "macos-x64-wheel" - MODE: "pypi" - secrets: inherit - test-wheel-linux-x64: needs: [checks, build-wheel-linux-x64] name: "Linux-x64: Test Wheels" @@ -279,132 +138,3 @@ jobs: PLATFORM: linux-x64 WHEEL_ARTIFACT_NAME: linux-x64-wheel secrets: inherit - - test-wheel-windows-x64: - needs: [checks, build-wheel-windows-x64] - name: "Windows-x64: Test Wheels" - uses: ./.github/workflows/reusable_test_wheels.yml - with: - CONCURRENCY: push-windows-x64-${{ github.ref_name }} - PLATFORM: windows-x64 - WHEEL_ARTIFACT_NAME: windows-x64-wheel - secrets: inherit - - # -------------------------------------------------------------------------- - - generate-pip-index: - name: "Generate Pip Index" - needs: - [ - build-wheel-linux-arm64, - build-wheel-linux-x64, - build-wheel-macos-arm64, - build-wheel-macos-x64, - build-wheel-windows-x64, - ] - uses: ./.github/workflows/reusable_pip_index.yml - with: - CONCURRENCY: push-${{ github.ref_name }} - secrets: inherit - - bundle-and-upload-rerun_cpp: - name: "Bundle and upload rerun_cpp_sdk.zip" - needs: - [ - build-rerun_c-and-upload-linux-arm64, - build-rerun_c-and-upload-linux-x64, - build-rerun_c-and-upload-macos-arm64, - build-rerun_c-and-upload-macos-x64, - build-rerun_c-and-upload-windows-x64, - ] - uses: ./.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml - secrets: inherit - - pre-release: - name: Pre Release - concurrency: - group: push-${{ github.ref_name }}-prerelease - cancel-in-progress: true - needs: - [ - build-rerun-cli-and-upload-linux-arm64, - build-rerun-cli-and-upload-linux-x64, - build-rerun-cli-and-upload-macos-arm64, - build-rerun-cli-and-upload-macos-x64, - build-rerun-cli-and-upload-windows-x64, - build-rerun_c-and-upload-linux-arm64, - build-rerun_c-and-upload-linux-x64, - build-rerun_c-and-upload-macos-arm64, - build-rerun_c-and-upload-macos-x64, - build-rerun_c-and-upload-windows-x64, - bundle-and-upload-rerun_cpp, - generate-pip-index, - upload-web, - ] - runs-on: "ubuntu-latest" - steps: - - name: Add SHORT_SHA env property with commit short sha - shell: bash - run: echo "SHORT_SHA=`echo ${{github.sha}} | cut -c1-7`" >> $GITHUB_ENV - - # First delete the old prerelease. If we don't do this, we don't get things like - # proper source-archives and changelog info. - # https://github.com/dev-drprasad/delete-tag-and-release - - uses: dev-drprasad/delete-tag-and-release@v0.2.1 - with: - tag_name: prerelease - delete_release: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # Create the actual prerelease - # https://github.com/ncipollo/release-action - - name: GitHub Release - uses: ncipollo/release-action@v1.12.0 - with: - body: | - This is a prerelease. It is not intended for production use. - Please report any issues you find. - - ## Example Hosted App - https://rerun.io/viewer/commit/${{ env.SHORT_SHA }} - - ## Wheels can be installed with: - ``` - pip install --pre -f https://build.rerun.io/commit/${{ env.SHORT_SHA }}/wheels --upgrade rerun-sdk - ``` - or - ``` - pip install --pre -f https://github.com/rerun-io/rerun/releases/download/prerelease --upgrade rerun-sdk - ``` - - ## CMake fetch-content for C++ SDK - ``` - include(FetchContent) - FetchContent_Declare(rerun_sdk URL https://build.rerun.io/commit/${{ env.SHORT_SHA }}/rerun_cpp_sdk.zip) - FetchContent_MakeAvailable(rerun_sdk) - ``` - or - ``` - include(FetchContent) - FetchContent_Declare(rerun_sdk URL https://github.com/rerun-io/rerun/releases/download/prerelease/rerun_cpp_sdk.zip) - FetchContent_MakeAvailable(rerun_sdk) - ``` - - prerelease: true - name: "Development Build" - tag: "prerelease" - token: ${{ secrets.GITHUB_TOKEN }} - generateReleaseNotes: false - allowUpdates: true - removeArtifacts: true - replacesArtifacts: true - - sync-release-assets: - needs: [pre-release] - name: "Sync pre-release assets & build.rerun.io" - uses: ./.github/workflows/reusable_sync_release_assets.yml - with: - CONCURRENCY: push-${{ github.ref_name }} - RELEASE_VERSION: prerelease - secrets: inherit diff --git a/BUILD.md b/BUILD.md index fc25752a7942..959978130ff8 100644 --- a/BUILD.md +++ b/BUILD.md @@ -63,7 +63,7 @@ cargo run -p dna Rerun is available as a package on PyPi and can be installed with `pip install rerun-sdk`. -Additionally, prebuilt dev wheels from head of main are available at . +Additionally, nightly dev wheels from head of `main` are available at . If you want to build from source, you can do so easily in the pixi environment: * Run `pixi run py-build --release` to build SDK & viewer for python (or `pixi run py-build` for a debug build) From fa1202cd4c835460255e336eea810848b25d97bb Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 12 Apr 2024 11:36:13 +0200 Subject: [PATCH 269/508] Fix wheel version verification (#5938) ### What It broke in https://github.com/rerun-io/rerun/pull/5932 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_rerun_py.yml | 6 +++--- .github/workflows/reusable_build_examples.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 1c24ecf3822a..88282f1b2927 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -104,9 +104,9 @@ jobs: - name: Verify built wheel version shell: bash run: | - python3 -m rerun --version - which rerun - rerun --version + pixi run -e wheel-test python -m rerun --version + pixi run -e wheel-test which rerun + pixi run -e wheel-test rerun --version - name: Run Python unit-tests shell: bash diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 712391f16f64..10bb775663c7 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -86,9 +86,9 @@ jobs: - name: Verify built wheel version shell: bash run: | - pixi run python3 -m rerun --version - pixi run which rerun - pixi run rerun --version + pixi run -e wheel-test python -m rerun --version + pixi run -e wheel-test which rerun + pixi run -e wheel-test rerun --version - name: Get sha id: get-sha From fc4eb52c37c957339eca52d932dd8aa828f433c5 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 12 Apr 2024 12:05:56 +0200 Subject: [PATCH 270/508] Try fix main CI again (#5941) Follow-up to: * #5932 * https://github.com/rerun-io/rerun/pull/5938 Make these steps identical --- .github/workflows/contrib_rerun_py.yml | 4 ++-- .github/workflows/reusable_build_examples.yml | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 88282f1b2927..78dbc845dfa7 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -98,8 +98,8 @@ jobs: # find the dependencies to reinstall them. shell: bash run: | - pip uninstall rerun-sdk - pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links dist + pixi run -e wheel-test pip uninstall rerun-sdk + pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links dist - name: Verify built wheel version shell: bash diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 10bb775663c7..62be700b1f01 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -76,12 +76,11 @@ jobs: -r scripts/ci/requirements-examples-${{ inputs.CHANNEL }}.txt \ --no-input - - name: Install Python dependencies and wheel + - name: Install built wheel shell: bash run: | - pixi run pip uninstall rerun-sdk -y - pixi run pip install deprecated '"numpy>=1.23,<2"' pyarrow>=14.0.2 pytest==7.1.2 - pixi run pip install rerun-sdk --no-index --find-links wheel + pixi run -e wheel-test pip uninstall rerun-sdk -y + pixi run -e wheel-test pip install rerun-sdk --no-index --find-links wheel - name: Verify built wheel version shell: bash From 834ec49d314078c7e26a2eb9aaa57ed846f3712d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 12 Apr 2024 12:22:48 +0200 Subject: [PATCH 271/508] Fix CI: Use the correct `wheel-test` pixi env (#5942) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) --- .github/workflows/reusable_build_examples.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 62be700b1f01..9050186db95e 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -99,14 +99,14 @@ jobs: - name: Build examples shell: bash run: | - pixi run build-examples rrd \ + pixi run -e wheel-test build-examples rrd \ --channel ${{ inputs.CHANNEL }} \ example_data - name: Build snippets shell: bash run: | - pixi run build-examples snippets \ + pixi run -e wheel-test build-examples snippets \ example_data/snippets - name: Upload assets From 9b8172dba9bf72905bc1f0e3086bc8447cb911d4 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 12 Apr 2024 13:03:46 +0200 Subject: [PATCH 272/508] CI: Install example pip deps into the correct pixi env (#5943) --- .github/workflows/reusable_build_examples.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 9050186db95e..b41b19b813c2 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -72,7 +72,7 @@ jobs: - name: Install example dependencies shell: bash run: | - pixi run pip install \ + pixi run -e wheel-test pip install \ -r scripts/ci/requirements-examples-${{ inputs.CHANNEL }}.txt \ --no-input From 4c6369ded905c3b02ac72e75d873985d045e3f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 13:25:34 +0200 Subject: [PATCH 273/508] Add `@rerun-bot full-check` command (#5940) ### What The `full-check` command triggers the full `main` workflow on the PR ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5940?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5940?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5940) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/pull_request_template.md | 2 + .github/workflows/on_pr_comment.yml | 101 ++++++++++++++++++++++++++++ .github/workflows/on_push_main.yml | 4 ++ 3 files changed, 107 insertions(+) create mode 100644 .github/workflows/on_pr_comment.yml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ceda6c04134c..30c0224982e0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -24,3 +24,5 @@ To get an auto-generated PR description you can put "copilot:summary" or "copilo - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) + +To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml new file mode 100644 index 000000000000..d26b4628f073 --- /dev/null +++ b/.github/workflows/on_pr_comment.yml @@ -0,0 +1,101 @@ +# This workflow is triggered on any PR comment, and tries to find a `@rerun-bot` mention in it. +# If the mention is a command, such as `@rerun-bot full-check`, then it runs the command. +# +# Available commands: +# full-check Triggers a run of `on_push_main.yml` on the PR. + +name: "PR Comment" + +on: + issue_comment: + types: [created, edited] + +jobs: + parse-command: + if: | + contains(github.event.comment.html_url, '/pull/') && + contains(github.event.comment.body, '@rerun-bot') + runs-on: ubuntu-latest + outputs: + command: ${{ steps.parse.outputs.command }} + steps: + - name: Parse comment + id: parse + shell: bash + run: | + # Parse `@rerun-bot ` + command=$(echo "${{ github.event.comment.body }}" | sed -n 's/.*@rerun-bot[[:space:]]\+\([a-zA-Z\-]*\).*/\1/p') + echo "command=$command" >> "$GITHUB_OUTPUT" + + full-check: + needs: [parse-command] + if: needs.parse-command.outputs.command == 'full-check' + runs-on: ubuntu-latest + steps: + - name: Dispatch main workflow + id: dispatch + shell: bash + env: + # NOTE: This uses `RERUN_BOT_TOKEN` instead of `GITHUB_TOKEN`, + # otherwise the recursive workflow protection prevents us from + # starting the `on_push_main` run. + # https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow + GH_TOKEN: ${{ secrets.RERUN_BOT_TOKEN }} + run: | + get_latest_workflow_run_id () { + local workflow_name=$1 + local ref_name=$2 + local created_after=$3 + echo $( + # https://cli.github.com/manual/gh_run_list + gh run list \ + --workflow $workflow_name \ + --event workflow_dispatch \ + --branch $ref_name \ + # https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates + --created ">$created_after" \ + --json databaseId \ + --jq '.[0].databaseId' + ) + } + + dispatch_workflow () { + local workflow_name=$1 + local ref_name=$2 + # https://cli.github.com/manual/gh_workflow_run + gh workflow run $workflow_name --ref $ref_name + } + + workflow_name='on_push_main.yml' + ref_name='${{ github.ref_name }}' + now=$(date --utc --iso-8601=seconds) + + echo "Dispatching workflow $workflow_name on branch $ref_name" + dispatch_workflow $workflow_name $ref_name $input + + # `gh workflow run` does NOT return the ID. + # In fact, it returns absolutely nothing: https://github.com/cli/cli/issues/4001 + # Instead, we have to wait for the workflow to start, and hope that nobody has + # started a workflow in parallel with us on the same branch. + + echo "Fetching workflow run id…" + run_id=$(get_latest_workflow_run_id $workflow_name $ref_name $now) + while [ -z $run_id ] + do + run_id=$(get_latest_workflow_run_id $workflow_name $ref_name $now) + sleep 1 + done + echo "Workflow run: https://github.com/rerun-io/rerun/actions/runs/$run_id" + + echo "workflow_run_url=https://github.com/rerun-io/rerun/actions/runs/$run_id" >> "$GITHUB_OUTPUT" + + - name: Create PR comment + # https://github.com/mshick/add-pr-comment + uses: mshick/add-pr-comment@v2.8.2 + with: + # We use `GITHUB_TOKEN` here so there is no chance that we'll trigger another run of this workflow. + # https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow + repo-token: ${{ secrets.GITHUB_TOKEN }} + message-id: "pr-${{ github.event.issue.number }}-${{ github.run_id }}" + message: | + Started a full build: ${{ steps.dispatch.outputs.workflow_run_url }} diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index d3bcc75bf7e1..9d39be4101b1 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -5,6 +5,10 @@ on: branches: - "main" + # Can be triggered manually from within the UI or using the GH CLI, + # e.g. `gh workflow run on_push_main.yml --ref main` + workflow_dispatch: + jobs: checks: name: Checks From 97a45d38c9ad7a446c7aee3a002b54fbf69cf834 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 12 Apr 2024 13:25:50 +0200 Subject: [PATCH 274/508] Remove all dev/ci requirements.txt and fully replace with pixi (#5939) ### What * Fixes #5895 In the process cleans up quite a bit more ci to use the pixi environment consequently. Note that the process I followed here was essentially: * pick a requirements.txt file * check for each of its package if it's already in pixi * if not, try adding it as conda package to pixi * if not add it as pypi package to pixi * try documenting who uses it * repeat until requirements.txt file is empty * remove mentions of the requirements.txt file, ensure that python invocations below are using pixi ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5939?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5939?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5939) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/auto_approve.yml | 13 +- .github/workflows/auto_release_crates.yml | 10 +- .github/workflows/checkboxes.yml | 12 +- .github/workflows/contrib_checks.yml | 27 +- .github/workflows/contrib_rerun_py.yml | 26 +- .../on_pull_request_target_contrib.yml | 12 +- .github/workflows/release.yml | 44 +- .../reusable_build_and_upload_wheels.yml | 9 +- .github/workflows/reusable_pr_summary.yml | 11 +- .github/workflows/reusable_publish_web.yml | 19 +- .github/workflows/reusable_publish_wheels.yml | 11 +- .github/workflows/reusable_release_crates.yml | 9 +- .../reusable_sync_release_assets.yml | 11 +- .github/workflows/reusable_update_pr_body.yml | 12 +- noxfile.py | 2 - pixi.lock | 2407 ++++++++--------- pixi.toml | 32 +- rerun_py/requirements-build.txt | 6 - rerun_py/requirements-lint.txt | 10 - scripts/ci/approve_workflow_runs.py | 3 - scripts/ci/build_and_upload_wheels.py | 8 - scripts/ci/crates.py | 11 +- scripts/ci/generate_pr_summary.py | 3 - scripts/ci/publish_wheels.py | 3 - scripts/ci/requirements-crates.txt | 6 - scripts/ci/requirements.txt | 16 - scripts/ci/sync_release_assets.py | 3 - scripts/ci/update_pr_body.py | 3 - scripts/requirements-dev.txt | 10 - 29 files changed, 1227 insertions(+), 1522 deletions(-) delete mode 100644 rerun_py/requirements-build.txt delete mode 100644 rerun_py/requirements-lint.txt delete mode 100644 scripts/ci/requirements-crates.txt delete mode 100644 scripts/ci/requirements.txt delete mode 100644 scripts/requirements-dev.txt diff --git a/.github/workflows/auto_approve.yml b/.github/workflows/auto_approve.yml index d1c4a5a76e36..d02aef9751fc 100644 --- a/.github/workflows/auto_approve.yml +++ b/.github/workflows/auto_approve.yml @@ -20,16 +20,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v4 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: 3.11 - - - name: Install dependencies - shell: bash - run: | - python3 -m pip install --upgrade pip - python3 -m pip install "PyGithub==1.59.0" "requests>=2.31,<3" + pixi-version: v0.18.0 - name: Wait a few seconds shell: bash @@ -40,7 +33,7 @@ jobs: - name: Approve workflow runs shell: bash run: | - python3 scripts/ci/approve_workflow_runs.py \ + pixi run python scripts/ci/approve_workflow_runs.py \ --github-token "${{ secrets.GITHUB_TOKEN }}" \ --github-repository "rerun-io/rerun" \ --pr-number "${{ github.event.pull_request.number || github.event.issue.number }}" diff --git a/.github/workflows/auto_release_crates.yml b/.github/workflows/auto_release_crates.yml index c3547c8d9ad8..506f748f84af 100644 --- a/.github/workflows/auto_release_crates.yml +++ b/.github/workflows/auto_release_crates.yml @@ -24,18 +24,10 @@ jobs: with: pixi-version: v0.19.0 - - name: Install dependencies - shell: bash - run: | - python3 -m pip install -r scripts/ci/requirements-crates.txt - - name: Update crate versions - shell: bash - run: | - python3 scripts/ci/crates.py version --bump prerelease + run: pixi run python scripts/ci/crates.py version --bump prerelease - run: pixi run toml-fmt - shell: bash - name: Get bumped version id: versioning diff --git a/.github/workflows/checkboxes.yml b/.github/workflows/checkboxes.yml index 6dd1be1ec9b5..75af8364585f 100644 --- a/.github/workflows/checkboxes.yml +++ b/.github/workflows/checkboxes.yml @@ -28,20 +28,14 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - name: Set up Python - uses: actions/setup-python@v5 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: 3.11 - - - name: Install deps - shell: bash - run: | - python3 -m pip install PyGithub==1.59.0 + pixi-version: v0.18.0 - name: Check PR checkboxes shell: bash run: | - ./scripts/ci/check_pr_checkboxes.py \ + pixi run ./scripts/ci/check_pr_checkboxes.py \ --github-token ${{ secrets.GITHUB_TOKEN }} \ --github-repository ${{ github.repository }} \ --pr-number ${{ github.event.pull_request.number }} diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 63b4c8b947b4..06cd6b8fd4ed 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -49,26 +49,12 @@ jobs: - uses: prefix-dev/setup-pixi@v0.4.1 with: pixi-version: v0.19.0 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - - name: Install Python dependencies - shell: bash - run: | - pip install --upgrade pip - pip install -r rerun_py/requirements-lint.txt - name: Python format check - shell: bash - run: | - pixi run py-fmt-check + run: pixi run py-fmt-check - name: Lint Python - shell: bash - run: | - pixi run py-lint + run: pixi run py-lint py-test-docs: name: Test Python Docs @@ -81,9 +67,7 @@ jobs: pixi-version: v0.19.0 - name: Build via mkdocs - shell: bash - run: | - pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml + run: pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml no-codegen-changes: name: Check if running codegen would produce any changes @@ -122,11 +106,6 @@ jobs: with: pixi-version: v0.19.0 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.8" - - name: Rerun lints run: pixi run lint-rerun diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 78dbc845dfa7..688b5c7c410e 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -56,12 +56,6 @@ jobs: with: pixi-version: v0.19.0 - # These should already be in the docker container, but run for good measure. A no-op install - # should be fast, and this way things don't break if we add new packages without rebuilding - # docker - - run: pip install -r scripts/ci/requirements.txt - shell: bash - - name: Build Wheel uses: PyO3/maturin-action@v1 with: @@ -76,16 +70,6 @@ jobs: ${{ inputs.MATURIN_FEATURE_FLAGS }} --out dist - # Test the wheel - - name: Install wheel dependencies - # First we install the dependencies manually so we can use `--no-index` when installing the wheel. - # This needs to be a separate step for some reason or the following step fails - # TODO(jleibs): pull these deps from pyproject.toml - # TODO(jleibs): understand why deps can't be installed in the same step as the wheel - shell: bash - run: | - pip install attrs>=23.1.0 'numpy>=1.23,<2' pillow pyarrow>=14.0.2 pytest==7.1.2 torch==2.1.0 typing_extensions>=4.5 - - name: Get version id: get-version shell: bash @@ -110,11 +94,11 @@ jobs: - name: Run Python unit-tests shell: bash - run: cd rerun_py/tests && pytest -c ../pyproject.toml + run: pixi run -e wheel-test cd rerun_py/tests && pixi run -e wheel-test pytest -c ../pyproject.toml - name: Run e2e test shell: bash - run: RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed + run: pixi run -e wheel-test RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed - name: Run tests/roundtrips.py shell: bash @@ -122,7 +106,7 @@ jobs: # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… # --no-py-build because rerun-sdk is already built and installed run: | - RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build + pixi run -e wheel-test RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build - name: Run docs/snippets/compare_snippet_output.py shell: bash @@ -130,7 +114,7 @@ jobs: # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow… # --no-py-build because rerun-sdk is already built and installed run: | - RUST_LOG=debug docs/snippets/compare_snippet_output.py --release --target x86_64-unknown-linux-gnu --no-py-build + pixi run -e wheel-test RUST_LOG=debug docs/snippets/compare_snippet_output.py --release --target x86_64-unknown-linux-gnu --no-py-build - name: Cache RRD dataset id: dataset @@ -146,4 +130,4 @@ jobs: run: | mkdir rrd pip install -r examples/python/structure_from_motion/requirements.txt - python3 examples/python/structure_from_motion/main.py --dataset colmap_fiat --resize 800x600 --save rrd/colmap_fiat.rrd + pixi run -e wheel-test python examples/python/structure_from_motion/main.py --dataset colmap_fiat --resize 800x600 --save rrd/colmap_fiat.rrd diff --git a/.github/workflows/on_pull_request_target_contrib.yml b/.github/workflows/on_pull_request_target_contrib.yml index eb2e950e5006..e21c460d3245 100644 --- a/.github/workflows/on_pull_request_target_contrib.yml +++ b/.github/workflows/on_pull_request_target_contrib.yml @@ -23,20 +23,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: 3.11 - - - name: Install deps - shell: bash - run: | - python3 -m pip install -r ./scripts/ci/requirements.txt + pixi-version: v0.19.0 - name: Update PR description shell: bash run: | - ./scripts/ci/update_pr_body.py \ + pixi run ./scripts/ci/update_pr_body.py \ --github-token '${{ secrets.GITHUB_TOKEN }}' \ --github-repository '${{ github.repository }}' \ --pr-number '${{ github.event.pull_request.number }}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 423633405f42..4a1bc770da1f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,16 +78,6 @@ jobs: with: node-version: 18 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: 3.11 - - - name: Install deps - shell: bash - run: | - python3 -m pip install -r ./scripts/ci/requirements-crates.txt - - uses: prefix-dev/setup-pixi@v0.4.1 with: pixi-version: v0.19.0 @@ -97,40 +87,40 @@ jobs: shell: bash run: | echo Check that the release version matches expected format… - python3 scripts/ci/crates.py check-git-branch-name + pixi run python scripts/ci/crates.py check-git-branch-name echo Parse the release version from the branch name… # `release-0.8.1-meta.N` -> `0.8.1` - release_version=$(python3 scripts/ci/crates.py get-version --from git --finalize) + release_version=$(pixi run python scripts/ci/crates.py get-version --from git --finalize) echo "release_version: $release_version" echo Store version before the update, so we can later detect if it changed… - previous=$(python3 scripts/ci/crates.py get-version) + previous=$(pixi run python scripts/ci/crates.py get-version) echo If the version minus prerelease/build metadata is not the same as the release version, then update it.… - if [ $(python3 scripts/ci/crates.py get-version --finalize) != $release_version ]; then - python3 scripts/ci/crates.py version --exact $release_version + if [ $(pixi run python scripts/ci/crates.py get-version --finalize) != $release_version ]; then + pixi run python scripts/ci/crates.py version --exact $release_version fi echo If this is an 'rc', additionally set add '-rc.N'. This will also bump the 'N' if '-rc.N' is already set… if [ ${{ inputs.release-type }} = "rc" ]; then - python3 scripts/ci/crates.py version --bump prerelease --pre-id=rc + pixi run python scripts/ci/crates.py version --bump prerelease --pre-id=rc fi echo If this is an 'alpha', set the version to whatever is in the git branch name.… if [ ${{ inputs.release-type }} = "alpha" ]; then - python3 scripts/ci/crates.py version --exact $(python3 scripts/ci/crates.py get-version --from git) + pixi run python scripts/ci/crates.py version --exact $(pixi run python scripts/ci/crates.py get-version --from git) fi echo If this is a 'final', set the version to the final release version… if [ ${{ inputs.release-type }} = "final" ]; then - python3 scripts/ci/crates.py version --exact $release_version + pixi run python scripts/ci/crates.py version --exact $release_version fi echo Store version after the update, and the expected "final" release version… - current=$(python3 scripts/ci/crates.py get-version) - final=$(python3 scripts/ci/crates.py get-version --finalize) + current=$(pixi run python scripts/ci/crates.py get-version) + final=$(pixi run python scripts/ci/crates.py get-version --finalize) echo Output everything for use in other steps… echo "previous=$previous" >> "$GITHUB_OUTPUT" @@ -385,20 +375,10 @@ jobs: with: node-version: 18 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: 3.11 - - uses: prefix-dev/setup-pixi@v0.4.1 with: pixi-version: v0.19.0 - - name: Install dependencies - shell: bash - run: | - python3 -m pip install -r scripts/ci/requirements-crates.txt - - name: Commit new version shell: bash run: | @@ -409,9 +389,9 @@ jobs: git pull --rebase # bump version and commit it - python3 scripts/ci/crates.py version --bump auto + pixi run python scripts/ci/crates.py version --bump auto pixi run toml-fmt - version="$(python3 scripts/ci/crates.py get-version)" + version="$(pixi run python scripts/ci/crates.py get-version)" git commit -am "Bump versions to $version" git push diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 8f54a8421230..124b22e78b83 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -190,13 +190,6 @@ jobs: with: pixi-version: v0.19.0 - - name: Install dependencies - shell: bash - run: | - rustup target add ${{ needs.set-config.outputs.TARGET }} - pip install -r rerun_py/requirements-build.txt - pip install google-cloud-storage==2.9.0 - - name: Get sha id: get-sha shell: bash @@ -207,7 +200,7 @@ jobs: - name: Build shell: bash run: | - python3 scripts/ci/build_and_upload_wheels.py \ + pixi run python scripts/ci/build_and_upload_wheels.py \ --mode ${{ inputs.MODE }} \ --target ${{ needs.set-config.outputs.TARGET }} \ --dir commit/${{ steps.get-sha.outputs.sha }}/wheels \ diff --git a/.github/workflows/reusable_pr_summary.yml b/.github/workflows/reusable_pr_summary.yml index b0e5c3a5bb9f..89affe31959c 100644 --- a/.github/workflows/reusable_pr_summary.yml +++ b/.github/workflows/reusable_pr_summary.yml @@ -31,10 +31,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - name: Set up Python - uses: actions/setup-python@v5 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: 3.11 + pixi-version: v0.18.0 - id: "auth" uses: google-github-actions/auth@v2 @@ -47,14 +46,10 @@ jobs: with: version: ">= 363.0.0" - - name: Install deps - shell: bash - run: pip install google-cloud-storage Jinja2 PyGithub - - name: Render HTML template shell: bash run: | - python scripts/ci/generate_pr_summary.py \ + pixi run python scripts/ci/generate_pr_summary.py \ --github-token ${{secrets.GITHUB_TOKEN}} \ --github-repository ${GITHUB_REPOSITORY} \ --pr-number ${{ inputs.PR_NUMBER }} \ diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index 7f75b97b08a5..b65de3d61701 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -93,34 +93,33 @@ jobs: - name: Install Python dependencies and wheel shell: bash run: | - pixi run pip install -r scripts/ci/requirements.txt - pixi run pip uninstall rerun-sdk -y - pixi run pip install deprecated '"numpy>=1.23,<2"' pyarrow>=14.0.2 pytest==7.1.2 - pixi run pip install rerun-sdk --no-index --find-links wheel + pixi -e wheel-test run pip uninstall rerun-sdk -y + pixi -e wheel-test run pip install deprecated '"numpy>=1.23,<2"' pyarrow>=14.0.2 pytest==7.1.2 + pixi -e wheel-test run pip install rerun-sdk --no-index --find-links wheel - name: Installed wheel version shell: bash run: | - pixi run python3 -m rerun --version - pixi run which rerun - pixi run rerun --version + pixi -e wheel-test run python -m rerun --version + pixi -e wheel-test run which rerun + pixi -e wheel-test run rerun --version - name: Build web-viewer (release) shell: bash run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release -g + pixi -e wheel-test run cargo run --locked -p re_build_web_viewer -- --release -g - name: Build examples shell: bash run: | - pixi run build-examples rrd \ + pixi -e wheel-test run build-examples rrd \ --channel "release" \ web_viewer/examples - name: Build examples manifest shell: bash run: | - pixi run build-examples manifest \ + pixi -e wheel-test run build-examples manifest \ --base-url "https://app.rerun.io/version/${{inputs.release-version}}" \ --channel "release" \ web_viewer/examples_manifest.json diff --git a/.github/workflows/reusable_publish_wheels.yml b/.github/workflows/reusable_publish_wheels.yml index ed8b5e3afa30..efe874a58ddc 100644 --- a/.github/workflows/reusable_publish_wheels.yml +++ b/.github/workflows/reusable_publish_wheels.yml @@ -151,6 +151,10 @@ jobs: fetch-depth: 0 # Don't do a shallow clone since we need it for finding the full commit hash ref: ${{ inputs.release-commit }} + - uses: prefix-dev/setup-pixi@v0.4.1 + with: + pixi-version: v0.19.0 + - id: "auth" uses: google-github-actions/auth@v2 with: @@ -162,15 +166,10 @@ jobs: with: version: ">= 363.0.0" - - name: Install dependencies - shell: bash - run: | - python3 -m pip install packaging==23.1 google-cloud-storage==2.9.0 maturin==1.5.1 - - name: Publish to PyPI shell: bash run: | - python3 scripts/ci/publish_wheels.py \ + pixi run python scripts/ci/publish_wheels.py \ --version ${{ inputs.release-version }} \ --dir "commit/${{ needs.get-commit-sha.outputs.short-sha }}/wheels" \ --repository "${{ vars.PYPI_REPOSITORY }}" \ diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml index e5c9fccc82f9..714ea4683917 100644 --- a/.github/workflows/reusable_release_crates.yml +++ b/.github/workflows/reusable_release_crates.yml @@ -29,12 +29,7 @@ jobs: pixi-version: v0.19.0 - name: Build web-viewer (release) - shell: bash - run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release -g + run: pixi run cargo run --locked -p re_build_web_viewer -- --release -g - name: Publish - shell: bash - run: | - pixi run python -m pip install -r scripts/ci/requirements-crates.txt - pixi run python scripts/ci/crates.py publish --token ${{ secrets.CRATES_IO_TOKEN }} + run: pixi run python scripts/ci/crates.py publish --token ${{ secrets.CRATES_IO_TOKEN }} diff --git a/.github/workflows/reusable_sync_release_assets.yml b/.github/workflows/reusable_sync_release_assets.yml index b94288ccda20..a6d86782ebd8 100644 --- a/.github/workflows/reusable_sync_release_assets.yml +++ b/.github/workflows/reusable_sync_release_assets.yml @@ -35,14 +35,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - name: Set up Python - uses: actions/setup-python@v4 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: "3.11" - - - name: Install Python dependencies - shell: bash - run: pip install google-cloud-storage "PyGithub==1.59.0" "requests>=2.31,<3" + pixi-version: v0.18.0 - id: "auth" uses: google-github-actions/auth@v2 @@ -58,7 +53,7 @@ jobs: - name: Sync release assets & build.rerun.io shell: bash run: | - python ./scripts/ci/sync_release_assets.py \ + pixi run python ./scripts/ci/sync_release_assets.py \ --github-release ${{ inputs.RELEASE_VERSION }} \ --github-token ${{ secrets.GITHUB_TOKEN }} \ --wait ${{ inputs.WAIT_TIME_SECS }} \ diff --git a/.github/workflows/reusable_update_pr_body.yml b/.github/workflows/reusable_update_pr_body.yml index 927bd03026d1..28dd3df4cb4e 100644 --- a/.github/workflows/reusable_update_pr_body.yml +++ b/.github/workflows/reusable_update_pr_body.yml @@ -31,20 +31,14 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - name: Set up Python - uses: actions/setup-python@v5 + - uses: prefix-dev/setup-pixi@v0.4.1 with: - python-version: 3.11 - - - name: Install deps - shell: bash - run: | - python3 -m pip install PyGithub==1.59.0 Jinja2==3.1.2 + pixi-version: v0.18.0 - name: Update PR description shell: bash run: | - ./scripts/ci/update_pr_body.py \ + pixi run ./scripts/ci/update_pr_body.py \ --github-token '${{ secrets.GITHUB_TOKEN }}' \ --github-repository '${{ github.repository }}' \ --pr-number '${{ inputs.PR_NUMBER }}' diff --git a/noxfile.py b/noxfile.py index fe396a3a3278..1bd022e15aca 100644 --- a/noxfile.py +++ b/noxfile.py @@ -16,7 +16,6 @@ @nox.session(python=PYTHON_VERSIONS) def tests(session: nox.Session) -> None: """Run the Python test suite.""" - session.install("-r", "rerun_py/requirements-build.txt") session.install("./rerun_py") session.run("pixi", "run", "py-test", external=True) @@ -39,7 +38,6 @@ def roundtrips(session: nox.Session) -> None: global roundtrip_cpp_built - session.install("-r", "rerun_py/requirements-build.txt") session.install("opencv-python") session.install("./rerun_py") diff --git a/pixi.lock b/pixi.lock index 5665373a5a6c..86c0e34d765a 100644 --- a/pixi.lock +++ b/pixi.lock @@ -7,6 +7,8 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.9.3-py311h459d7ec_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.16-h79b3bcb_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.10-hb29e0c7_1.conda @@ -40,6 +42,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-23.5.26-h59595ed_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.4.1-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc-12.3.0-h8d2909c_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_impl_linux-64-12.3.0-he2b93b0_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gcc_linux-64-12.3.0-h76fc315_2.conda @@ -52,7 +55,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_impl_linux-64-12.3.0-he2b93b0_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gxx_linux-64-12.3.0-h8a814eb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-64-2.6.32-he073ed8_16.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda @@ -113,8 +118,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.5-h232c23b_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda - 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.0.5-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-h59595ed_2.conda @@ -123,7 +130,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.2-h00e871a_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda @@ -150,12 +157,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.18.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h75e419f_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -165,6 +174,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -174,7 +184,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -183,13 +192,21 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/_sysroot_linux-aarch64_curr_repodata_hack-4-h57d6b7b_14.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.9.3-py311hcd402e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda @@ -223,6 +240,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.4.1-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc-12.3.0-he80d746_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_impl_linux-aarch64-12.3.0-hcde2664_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gcc_linux-aarch64-12.3.0-h9622932_3.conda @@ -235,7 +253,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_impl_linux-aarch64-12.3.0-hcde2664_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gxx_linux-aarch64-12.3.0-h3d1e521_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/kernel-headers_linux-aarch64-4.18.0-h5b4a56d_14.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda @@ -295,7 +315,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.5-h3091e33_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - 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-2.1.5-py311hc8f2f60_0.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.0.5-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4-h0425590_2.conda @@ -330,12 +352,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -345,6 +369,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -354,7 +379,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -363,11 +387,19 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.16-h79cb451_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.10-h7beb4c2_1.conda @@ -407,13 +439,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-23.5.26-he965462_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/frozenlist-1.4.1-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64-609-ha02d983_16.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ld64_osx-64-609-ha20a434_16.conda @@ -465,7 +500,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.6-hb6ac08f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-16.0.6-hbedff68_3.conda - 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-2.1.5-py311he705e18_0.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.0.5-py311h5547dcb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4-h93d8f39_2.conda @@ -474,7 +511,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h3758fe2_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda @@ -499,11 +536,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.18.1-h11a7dfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -513,6 +552,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -522,7 +562,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -531,11 +570,19 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.16-h51b92d1_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.10-hf888d4c_1.conda @@ -575,13 +622,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-23.5.26-h13dd4ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozenlist-1.4.1-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64-609-h634c8be_16.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ld64_osx-arm64-609-ha4bd21c_16.conda @@ -633,7 +683,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-17.0.6-hcd81f8e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-16.0.6-haab561b_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda - 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/multidict-6.0.5-py311he2be06e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h463b476_2.conda @@ -642,7 +694,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h798d188_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda @@ -667,11 +719,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.18.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -681,6 +735,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -690,7 +745,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -699,11 +753,19 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda @@ -729,11 +791,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/frozenlist-1.4.1-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.41-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.0.0-h57928b3_49841.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-hd01637b_10_cpu.conda @@ -776,9 +841,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.0.0-h66d3029_49657.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.0.5-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda @@ -786,7 +853,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda @@ -809,6 +876,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.18.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda @@ -820,6 +888,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vswhere-3.1.4-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl @@ -828,6 +897,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -837,7 +907,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -846,10 +915,16 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl default: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -857,6 +932,8 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.9.3-py311h459d7ec_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.10-h0100c56_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.9-h5d48c4d_2.conda @@ -883,13 +960,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-23.5.26-h59595ed_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.4.1-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.6.0-h6f12383_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda @@ -944,8 +1024,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.11.5-h232c23b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda - 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.0.5-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4-hcb278e6_0.conda @@ -954,7 +1036,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.2.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/orc-1.9.2-h4b38347_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/patchelf-0.17.2-h58526e2_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda @@ -980,12 +1062,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-h2797004_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -995,6 +1079,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -1004,7 +1089,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -1013,12 +1097,20 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.9.3-py311hcd402e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.16-hcac9c52_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.10-h967b9ec_1.conda @@ -1045,13 +1137,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.7-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.4.1-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.42-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda @@ -1107,7 +1202,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.5-h3091e33_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - 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-2.1.5-py311hc8f2f60_0.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.0.5-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4-h0425590_2.conda @@ -1141,12 +1238,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.10.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -1156,6 +1255,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -1165,7 +1265,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -1174,11 +1273,19 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.10-h5ed86db_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.9-had988b7_2.conda @@ -1205,13 +1312,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-23.5.26-he965462_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/frozenlist-1.4.1-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.6.0-h8ac2a54_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20230802.1-cxx17_h048a20a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-h1aaacd4_3_cpu.conda @@ -1259,7 +1369,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-17.0.2-hff08bdf_0.conda - 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-2.1.5-py311he705e18_0.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.0.5-py311h5547dcb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4-hf0c8a7f_0.conda @@ -1268,7 +1380,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/openssl-3.2.1-hd75f5a5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/orc-1.9.2-h9ab30d4_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/prettier-2.8.8-h3db311d_1.conda @@ -1291,11 +1403,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-hef22860_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.16.20-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -1305,6 +1419,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -1314,7 +1429,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -1323,11 +1437,19 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.10-h8e8137d_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.9-hb1772db_2.conda @@ -1354,13 +1476,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-23.5.26-h13dd4ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozenlist-1.4.1-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.6.0-h6da1cb0_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20230802.1-cxx17_h13dd4ca_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h4ce3932_3_cpu.conda @@ -1408,7 +1533,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-17.0.2-h1c12783_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda - 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/multidict-6.0.5-py311he2be06e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_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/ncurses-6.4-h7ea286d_0.conda @@ -1417,7 +1544,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.2.1-h0d3ecfb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/orc-1.9.2-h7c018df_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/prettier-2.8.8-ha12bae2_1.conda @@ -1440,11 +1567,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-hb31c410_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.16.20-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -1454,6 +1583,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -1463,7 +1593,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -1472,11 +1601,19 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.1.0-pyh71513ae_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.16-hec1de76_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.10-hd481e46_1.conda @@ -1502,11 +1639,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-23.5.26-h63175ca_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/frozenlist-1.4.1-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.9-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.40-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2023.2.0-h57928b3_50496.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-hd01637b_10_cpu.conda @@ -1549,9 +1689,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2022.1.0-h6a75c08_874.tar.bz2 - 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.0.5-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda @@ -1559,7 +1701,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openssl-3.2.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/orc-1.9.2-h2702c50_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pip-23.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/prettier-2.8.8-hd2f1330_1.conda @@ -1582,6 +1724,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.16.20-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda @@ -1591,6 +1734,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.36.32532-h05e6639_17.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl @@ -1599,6 +1743,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl @@ -1608,7 +1753,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl @@ -1617,10 +1761,16 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl py-docs: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -1628,6 +1778,8 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.9.3-py311h459d7ec_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.17-he0b1f16_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.11-heb1d5e4_0.conda @@ -1654,13 +1806,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.25-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.4.1-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda @@ -1716,8 +1871,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda - 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.0.5-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4.20240210-h59595ed_0.conda @@ -1752,12 +1909,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.20.7-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-ha691c75_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -1769,6 +1928,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl @@ -1780,12 +1940,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl @@ -1807,8 +1964,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl @@ -1819,12 +1979,17 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.9.3-py311hcd402e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.17-h43c0ec5_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.11-hd75f5ff_0.conda @@ -1851,13 +2016,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.25-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.4.1-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda @@ -1913,7 +2081,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.6-h3091e33_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - 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-2.1.5-py311hc8f2f60_0.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.0.5-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4.20240210-h0425590_0.conda @@ -1947,12 +2117,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.20.7-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hb4872d8_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -1964,6 +2136,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl @@ -1975,12 +2148,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl @@ -2002,8 +2172,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl @@ -2014,11 +2187,16 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.17-hb47d15a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.11-hbce485b_0.conda @@ -2045,13 +2223,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.25-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/frozenlist-1.4.1-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20240116.1-cxx17_hc1bcbd7_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-hf13115f_16_cpu.conda @@ -2100,7 +2281,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda - 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-2.1.5-py311he705e18_0.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.0.5-py311h5547dcb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4.20240210-h73e2aa4_0.conda @@ -2132,11 +2315,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.20.7-h11a7dfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -2148,6 +2333,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl @@ -2159,12 +2345,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl @@ -2186,8 +2369,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl @@ -2198,11 +2384,16 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.17-h382b9c6_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.11-hd34e5fa_0.conda @@ -2229,13 +2420,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.25-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozenlist-1.4.1-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20240116.1-cxx17_hebf3989_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h3fc723a_16_cpu.conda @@ -2284,7 +2478,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda - 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/multidict-6.0.5-py311he2be06e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_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/ncurses-6.4.20240210-h078ce10_0.conda @@ -2316,11 +2512,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.20.7-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -2332,6 +2530,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl @@ -2343,12 +2542,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl @@ -2370,8 +2566,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl @@ -2382,11 +2581,16 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.17-hb40cdec_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.11-ha21e00f_0.conda @@ -2412,11 +2616,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.25-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/frozenlist-1.4.1-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.1.0-h57928b3_964.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h45212c0_16_cpu.conda @@ -2459,9 +2666,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_692.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.0.5-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda @@ -2492,6 +2701,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.20.7-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda @@ -2501,6 +2711,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl @@ -2511,6 +2722,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f7/ec/67fbef5d497f86283db54c22eec6f6140243aae73265799baaaa19cd17fb/ghp_import-2.1.0-py3-none-any.whl @@ -2522,12 +2734,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/30/8d/3b296acc69a4009eab33ef4665d634c7d11f84f43324179787157ff9b41a/griffe-0.39.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/39/9d/b035d024c62c85f2e2d4806a59ca7b8520307f34e0932fbc8cc75fe7b2d9/jsonschema-4.21.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/07/44bd408781594c4d0a027666ef27fab1e441b109dc3b76b4f836f8fd04fe/jsonschema_specifications-2023.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/b3/0c0c994fe49cd661084f8d5dc06562af53818cc0abefaca35bdc894577c3/Markdown-3.6-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/2c/19/04f9b178c2d8a15b076c8b5140708fa6ffc5601fb6f1e975537072df5b2a/mergedeep-1.3.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/8a/f226f8c512a4e3ee36438613fde32d371262e985643d308850cf4bdaed15/mike-1.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/58/aa3301b23966a71d7f8e55233f467b3cec94a651434e9cd9053811342539/mkdocs-1.5.3-py3-none-any.whl @@ -2549,8 +2758,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/97/9c/372fef8377a6e340b1704768d20daaded98bf13282b5327beb2e2fe2c7ef/pygments-2.17.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/4b/4ebb08f36e83e91b31117fe8f67844bac7f5c7d11ed151ae5db807be363f/pymdown_extensions-10.7.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl @@ -2561,10 +2773,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl wheel-test: channels: - url: https://conda.anaconda.org/conda-forge/ @@ -2572,6 +2787,8 @@ environments: linux-64: - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.9.3-py311h459d7ec_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-auth-0.7.17-he0b1f16_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-c-cal-0.6.11-heb1d5e4_0.conda @@ -2598,13 +2815,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/doxygen-1.9.7-h661eb56_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/flatbuffers-24.3.25-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.4.1-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-he1b5a44_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.0-hed5481d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-73.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/keyutils-1.6.1-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/krb5-1.21.2-h659d440_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-h41732ed_0.conda @@ -2660,8 +2880,10 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.6-h232c23b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda - 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.0.5-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_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/ncurses-6.4.20240210-h59595ed_0.conda @@ -2696,12 +2918,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.20.7-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-ha691c75_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -2711,6 +2935,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl @@ -2721,9 +2946,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl @@ -2746,15 +2968,23 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/bd/ac/3974caaa459bf2c3a244a84be8d17561f631f7d42af370fc311defeca2fb/triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.9.3-py311hcd402e7_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-auth-0.7.17-h43c0ec5_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-c-cal-0.6.11-hd75f5ff_0.conda @@ -2781,13 +3011,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/doxygen-1.9.7-h7b6a552_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/flatbuffers-24.3.25-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.4.1-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/gflags-2.2.2-h54f1f3f_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/glog-0.7.0-ha63034d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-73.2-h787c7f5_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/keyutils-1.6.1-h4e544f5_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/krb5-1.21.2-hc419048_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ld_impl_linux-aarch64-2.40-h2d8c526_0.conda @@ -2843,7 +3076,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libxml2-2.12.6-h3091e33_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - 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-2.1.5-py311hc8f2f60_0.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.0.5-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_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/ncurses-6.4.20240210-h0425590_0.conda @@ -2877,12 +3112,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/tk-8.6.13-h194ca79_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.20.7-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hb4872d8_8.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -2892,6 +3129,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl @@ -2902,9 +3140,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl @@ -2915,13 +3150,21 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: + - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-auth-0.7.17-hb47d15a_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-c-cal-0.6.11-hbce485b_0.conda @@ -2948,13 +3191,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/doxygen-1.9.7-hd7636e7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/flatbuffers-24.3.25-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/frozenlist-1.4.1-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/gflags-2.2.2-hb1e8313_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/glog-0.7.0-h31b1b29_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-73.2-hf5e326d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/krb5-1.21.2-hb884880_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libabseil-20240116.1-cxx17_hc1bcbd7_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/libarrow-14.0.2-hf13115f_16_cpu.conda @@ -3003,7 +3249,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/libzlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda - 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-2.1.5-py311he705e18_0.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.0.5-py311h5547dcb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_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/ncurses-6.4.20240210-h73e2aa4_0.conda @@ -3035,11 +3283,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.13-h1abcd95_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.20.7-h11a7dfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -3049,6 +3299,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl @@ -3059,9 +3310,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl @@ -3072,13 +3320,21 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-auth-0.7.17-h382b9c6_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-c-cal-0.6.11-hd34e5fa_0.conda @@ -3105,13 +3361,16 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/doxygen-1.9.7-h0e2417a_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/flatbuffers-24.3.25-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/frozenlist-1.4.1-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/gflags-2.2.2-hc88da5d_1004.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/glog-0.7.0-hc6770e3_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-73.2-hc8870d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/krb5-1.21.2-h92f50d5_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libabseil-20240116.1-cxx17_hebf3989_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libarrow-14.0.2-h3fc723a_16_cpu.conda @@ -3160,7 +3419,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libzlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda - 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/multidict-6.0.5-py311he2be06e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_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/ncurses-6.4.20240210-h078ce10_0.conda @@ -3192,11 +3453,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/tk-8.6.13-h5083fa2_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.20.7-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl @@ -3206,6 +3469,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl @@ -3216,9 +3480,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl @@ -3229,13 +3490,21 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: + - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-auth-0.7.17-hb40cdec_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-c-cal-0.6.11-ha21e00f_0.conda @@ -3261,11 +3530,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/doxygen-1.9.7-h849606c_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/flatbuffers-24.3.25-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/frozenlist-1.4.1-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.1.0-h57928b3_964.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/krb5-1.21.2-heb0366b_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libabseil-20240116.1-cxx17_h63175ca_2.conda - conda: https://conda.anaconda.org/conda-forge/win-64/libarrow-14.0.2-h45212c0_16_cpu.conda @@ -3308,9 +3580,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gcc-libs-core-5.3.0-7.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_692.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.0.5-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_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/ninja-1.11.1-h91493d7_0.conda @@ -3341,6 +3615,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/tk-8.6.13-h5226925_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.20.7-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda @@ -3350,6 +3625,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl @@ -3358,6 +3634,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl @@ -3368,9 +3645,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl @@ -3381,12 +3655,18 @@ environments: - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl packages: - kind: conda name: _libgcc_mutex @@ -3448,6 +3728,146 @@ packages: license_family: GPL size: 21238 timestamp: 1708000885951 +- kind: conda + name: aiohttp + version: 3.9.3 + build: py311h05b510d_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda + sha256: d9bbaafe8f06afe5bb65cf5a62935e07e02dc6b0b9ff246cd8da95dee1092168 + md5: cec5e9c7692dddfb0cf9608063f922e7 + depends: + - aiosignal >=1.1.2 + - attrs >=17.3.0 + - frozenlist >=1.1.1 + - multidict >=4.5,<7.0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - yarl >=1.0,<2.0 + license: MIT AND Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/aiohttp + size: 775891 + timestamp: 1710512114607 +- kind: conda + name: aiohttp + version: 3.9.3 + build: py311h459d7ec_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.9.3-py311h459d7ec_1.conda + sha256: f36286e4cfc6e86c6dd296695f066ebd64767a39477d8e951bc2dce7ebdfcde2 + md5: 7fd17e8947afbddd2855720d643a48f0 + depends: + - aiosignal >=1.1.2 + - attrs >=17.3.0 + - frozenlist >=1.1.1 + - libgcc-ng >=12 + - multidict >=4.5,<7.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - yarl >=1.0,<2.0 + license: MIT AND Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/aiohttp + size: 803387 + timestamp: 1710511729342 +- kind: conda + name: aiohttp + version: 3.9.3 + build: py311ha68e1ae_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda + sha256: ded1d0a2983470b3504ca3067a788431c882e7247693b8e9f67ea45a305eb8a0 + md5: 82225d1426e777cc4d8b75e6fca50349 + depends: + - aiosignal >=1.1.2 + - attrs >=17.3.0 + - frozenlist >=1.1.1 + - multidict >=4.5,<7.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + - yarl >=1.0,<2.0 + license: MIT AND Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/aiohttp + size: 759880 + timestamp: 1710512185335 +- kind: conda + name: aiohttp + version: 3.9.3 + build: py311hcd402e7_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/aiohttp-3.9.3-py311hcd402e7_1.conda + sha256: 4989ad64818d3c62b51aeb2ae16256cd846fbf7b19f5e2d5c40d09593c4e1c1f + md5: 02c524704f13bd6042cf5e95f34ace5e + depends: + - aiosignal >=1.1.2 + - attrs >=17.3.0 + - frozenlist >=1.1.1 + - libgcc-ng >=12 + - multidict >=4.5,<7.0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + - yarl >=1.0,<2.0 + license: MIT AND Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/aiohttp + size: 799584 + timestamp: 1710511852985 +- kind: conda + name: aiohttp + version: 3.9.3 + build: py311he705e18_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda + sha256: 2e3323688afb87c92a5f14387b27bd48bc6017d6f440c5652ca0218cb551b6fa + md5: 09a52057d5221a7a2de2a7729b651aed + depends: + - aiosignal >=1.1.2 + - attrs >=17.3.0 + - frozenlist >=1.1.1 + - multidict >=4.5,<7.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - yarl >=1.0,<2.0 + license: MIT AND Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/aiohttp + size: 770316 + timestamp: 1710511859514 +- kind: conda + name: aiosignal + version: 1.3.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/aiosignal-1.3.1-pyhd8ed1ab_0.tar.bz2 + sha256: 575c742e14c86575986dc867463582a970463da50b77264cdf54df74f5563783 + md5: d1e1eb7e21a9e2c74279d87dafb68156 + depends: + - frozenlist >=1.1.0 + - python >=3.7 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/aiosignal + size: 12730 + timestamp: 1667935912504 - kind: pypi name: argcomplete version: 3.2.3 @@ -3480,23 +3900,6 @@ packages: - pkg:pypi/attrs size: 55022 timestamp: 1683424195402 -- kind: conda - name: attrs - version: 23.2.0 - build: pyh71513ae_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/attrs-23.2.0-pyh71513ae_0.conda - sha256: 77c7d03bdb243a048fff398cedc74327b7dc79169ebe3b4c8448b0331ea55fea - md5: 5e4c0743c70186509d1412e03c2d8dfa - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/attrs - size: 54582 - timestamp: 1704011393776 - kind: conda name: attrs version: 23.2.0 @@ -7443,72 +7846,72 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 + url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: conda name: clang @@ -8559,23 +8962,6 @@ packages: license_family: BSD size: 16525734 timestamp: 1695270838345 -- kind: conda - name: colorama - version: 0.4.6 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/colorama-0.4.6-pyhd8ed1ab_0.tar.bz2 - sha256: 2c1b2e9755ce3102bca8d69e8f26e4f087ece73f50418186aee7c74bef8e1698 - md5: 3faab06a954c2a04039983f2c4a50d99 - depends: - - python >=3.7 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/colorama@0.4.6 - size: 25170 - timestamp: 1666700778190 - kind: conda name: colorama version: 0.4.6 @@ -8683,8 +9069,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d + url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -8711,8 +9097,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 + url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -8739,8 +9125,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 + url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -8767,8 +9153,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb + url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -8795,8 +9181,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -8878,6 +9264,19 @@ packages: license: BSD size: 6415 timestamp: 1701504710176 +- kind: pypi + name: deprecated + version: 1.2.14 + url: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl + sha256: 6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c + requires_dist: + - wrapt <2, >=1.10 + - tox ; extra == 'dev' + - pytest ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - bump2version <1 ; extra == 'dev' + - sphinx <2 ; extra == 'dev' + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' - kind: pypi name: distlib version: 0.3.8 @@ -8986,23 +9385,6 @@ packages: - pkg:pypi/exceptiongroup size: 19262 timestamp: 1692026296517 -- kind: conda - name: exceptiongroup - version: 1.2.0 - build: pyhd8ed1ab_2 - build_number: 2 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.2.0-pyhd8ed1ab_2.conda - sha256: a6ae416383bda0e3ed14eaa187c653e22bec94ff2aa3b56970cdf0032761e80d - md5: 8d652ea2ee8eaee02ed8dc820bc794aa - depends: - - python >=3.7 - license: MIT and PSF-2.0 - purls: - - pkg:pypi/exceptiongroup - size: 20551 - timestamp: 1704921321122 - kind: conda name: exceptiongroup version: 1.2.0 @@ -9190,6 +9572,98 @@ packages: license_family: APACHE size: 1280038 timestamp: 1711467768202 +- kind: conda + name: frozenlist + version: 1.4.1 + build: py311h05b510d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/frozenlist-1.4.1-py311h05b510d_0.conda + sha256: 57a0b0677fbf065ae150e5a874f08d6263646acaa808ad44d01149b8abe7c739 + md5: 9dfb057a46648eb850a8a7b400ae0ae4 + depends: + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/frozenlist + size: 53365 + timestamp: 1702645980217 +- kind: conda + name: frozenlist + version: 1.4.1 + build: py311h459d7ec_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.4.1-py311h459d7ec_0.conda + sha256: 56917dda8da109d51a3b25d30256365e1676f7b2fbaf793a3f003e51548bf794 + md5: b267e553a337e1878512621e374845c5 + depends: + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/frozenlist + size: 60669 + timestamp: 1702645612671 +- kind: conda + name: frozenlist + version: 1.4.1 + build: py311ha68e1ae_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/frozenlist-1.4.1-py311ha68e1ae_0.conda + sha256: a30775ce649c48dd00c5e68a675a29e521802694a73d728a4d418ab847d80412 + md5: 60608857f155a14154a95182e56b09a7 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/frozenlist + size: 54239 + timestamp: 1702646200957 +- kind: conda + name: frozenlist + version: 1.4.1 + build: py311hcd402e7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/frozenlist-1.4.1-py311hcd402e7_0.conda + sha256: d030ba61da32917f811f27a353cead99cd762159addb4cabb18c40506acfde70 + md5: f47a5e6b599d1a564bca854e6dbff2a1 + depends: + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/frozenlist + size: 60441 + timestamp: 1702645707187 +- kind: conda + name: frozenlist + version: 1.4.1 + build: py311he705e18_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/frozenlist-1.4.1-py311he705e18_0.conda + sha256: 6c496e4a740f191d7ab23744d39bd6d415789f9d5dcf74ed043a16a3f8968ef4 + md5: 6b64f053b1a2e3bfe1f93c2714844ef0 + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/frozenlist + size: 53105 + timestamp: 1702645839241 - kind: pypi name: fsspec version: 2024.3.1 @@ -9419,24 +9893,6 @@ packages: - markdown ; extra == 'dev' - flake8 ; extra == 'dev' - wheel ; extra == 'dev' -- kind: conda - name: gitdb - version: 4.0.11 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/gitdb-4.0.11-pyhd8ed1ab_0.conda - sha256: 52ab2798be31b8f509eeec458712f447ced4f96ecb672c6c9a42778f47e07b1b - md5: 623b19f616f2ca0c261441067e18ae40 - depends: - - python >=3.7 - - smmap >=3.0.1,<6 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/gitdb@4.0.11 - size: 52872 - timestamp: 1697791718749 - kind: conda name: gitdb version: 4.0.11 @@ -9490,29 +9946,12 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/gitignore-parser + - pkg:pypi/gitignore-parser@0.1.11 size: 11460 timestamp: 1705776957779 - kind: conda - name: gitignore-parser - version: 0.1.11 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/gitignore-parser-0.1.11-pyhd8ed1ab_0.conda - sha256: 10b3621e508e6c647eae4c52d48ff2659f4f0b426d6dd5979ccc7475d5383eb6 - md5: 251ce4bb7b478eacf297b1fb8eb838bb - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/gitignore-parser@0.1.11 - size: 11460 - timestamp: 1705776957779 -- kind: conda - name: gitpython - version: 3.1.40 + name: gitpython + version: 3.1.40 build: pyhd8ed1ab_0 subdir: win-64 noarch: python @@ -9569,25 +10008,6 @@ packages: - pkg:pypi/gitpython size: 149604 timestamp: 1708069389374 -- kind: conda - name: gitpython - version: 3.1.43 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/gitpython-3.1.43-pyhd8ed1ab_0.conda - sha256: cbb2802641a009ce9bcc2a047e817fd8816f9c842036a42f4730398d8e4cda2a - md5: 0b2154c1818111e17381b1df5b4b0176 - depends: - - gitdb >=4.0.1,<5 - - python >=3.7 - - typing_extensions >=3.7.4.3 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/gitpython - size: 156827 - timestamp: 1711991122366 - kind: conda name: gitpython version: 3.1.43 @@ -9780,40 +10200,40 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 + url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -10001,29 +10421,23 @@ packages: license_family: MIT size: 11787527 timestamp: 1692901622519 -- kind: pypi - name: idna - version: '3.7' - url: https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl - sha256: 82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 - requires_python: '>=3.5' - kind: conda - name: iniconfig - version: 2.0.0 + name: idna + version: '3.6' build: pyhd8ed1ab_0 subdir: noarch noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda - sha256: 38740c939b668b36a50ef455b077e8015b8c9cf89860d421b3fff86048f49666 - md5: f800d2da156d08e289b14e87e43c1ae5 + url: https://conda.anaconda.org/conda-forge/noarch/idna-3.6-pyhd8ed1ab_0.conda + sha256: 6ee4c986d69ce61e60a20b2459b6f2027baeba153f0a64995fd3cb47c2cc7e07 + md5: 1a76f09108576397c41c0b0c5bd84134 depends: - - python >=3.7 - license: MIT - license_family: MIT + - python >=3.6 + license: BSD-3-Clause + license_family: BSD purls: - - pkg:pypi/iniconfig@2.0.0 - size: 11101 - timestamp: 1673103208955 + - pkg:pypi/idna + size: 50124 + timestamp: 1701027126206 - kind: conda name: iniconfig version: 2.0.0 @@ -10084,15 +10498,24 @@ packages: license_family: Proprietary size: 1616281 timestamp: 1712153179165 -- kind: pypi +- kind: conda name: jinja2 version: 3.1.3 - url: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl - sha256: 7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa - requires_dist: + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/jinja2-3.1.3-pyhd8ed1ab_0.conda + sha256: fd517b7dd3a61eca34f8a6f9f92f306397149cae1204fce72ac3d227107dafdc + md5: e7d8df6509ba635247ff9aea31134262 + depends: - markupsafe >=2.0 - - babel >=2.7 ; extra == 'i18n' - requires_python: '>=3.7' + - python >=3.7 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/jinja2 + size: 111589 + timestamp: 1704967140287 - kind: pypi name: jsonschema version: 4.21.1 @@ -16102,25 +16525,6 @@ packages: license_family: Apache size: 33333655 timestamp: 1690527825436 -- kind: conda - name: libllvm15 - version: 15.0.7 - build: hb3ce162_4 - build_number: 4 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libllvm15-15.0.7-hb3ce162_4.conda - sha256: e71584c0f910140630580fdd0a013029a52fd31e435192aea2aa8d29005262d1 - md5: 8a35df3cbc0c8b12cc8af9473ae75eef - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - libxml2 >=2.12.1,<2.13.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 33321457 - timestamp: 1701375836233 - kind: conda name: libllvm15 version: 15.0.7 @@ -16252,25 +16656,6 @@ packages: license_family: Apache size: 23347663 timestamp: 1701374993634 -- kind: conda - name: libllvm16 - version: 16.0.6 - build: hb3ce162_3 - build_number: 3 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libllvm16-16.0.6-hb3ce162_3.conda - sha256: 624fa4012397bc5a8c9269247bf9baa7d907eb59079aefc6f6fa6a40f10fd0ba - md5: a4d48c40dd5c60edbab7fd69c9a88967 - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - libxml2 >=2.12.1,<2.13.0a0 - - libzlib >=1.2.13,<1.3.0a0 - - zstd >=1.5.5,<1.6.0a0 - license: Apache-2.0 WITH LLVM-exception - license_family: Apache - size: 35359734 - timestamp: 1701375139881 - kind: conda name: libllvm16 version: 16.0.6 @@ -18781,54 +19166,107 @@ packages: - coverage ; extra == 'testing' - pyyaml ; extra == 'testing' requires_python: '>=3.8' -- kind: pypi - name: markupsafe - version: 2.1.5 - url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl - sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 - requires_python: '>=3.7' -- kind: pypi +- kind: conda name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 - requires_python: '>=3.7' -- kind: pypi + build: py311h05b510d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda + sha256: 3f2127bd8788dc4b7c3d6d65ae4b7d2f8c7d02a246fc17b819390edeca53fd93 + md5: a27177455a9d29f4ac9d687a489e5d52 + depends: + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe + size: 26578 + timestamp: 1706900556332 +- kind: conda name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 - requires_python: '>=3.7' -- kind: pypi + build: py311h459d7ec_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda + sha256: 14912e557a6576e03f65991be89e9d289c6e301921b6ecfb4e7186ba974f453d + md5: a322b4185121935c871d201ae00ac143 + depends: + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe + size: 27502 + timestamp: 1706900084436 +- kind: conda name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced - requires_python: '>=3.7' -- kind: pypi + build: py311ha68e1ae_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda + sha256: c629f79fe78b5df7f08daa6b7f125f7a67f789bf734949c6d68aa063d7296208 + md5: 07da1326e2837e055ef6f44ef3334b0a + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe + size: 30011 + timestamp: 1706900632904 +- kind: conda name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f - requires_python: '>=3.7' -- kind: conda - name: maturin - version: 1.5.1 - build: py311h06e5ef9_0 + build: py311hc8f2f60_0 subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/maturin-1.5.1-py311h06e5ef9_0.conda - sha256: ec876128344c775817ce6c64a979c5570236fe4091eee96cf6547b72fb760736 - md5: f0abfc82e48c4179c8ebecdfc1ce7a59 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/markupsafe-2.1.5-py311hc8f2f60_0.conda + sha256: d870de9a79c8bce61e0a7579577076a854aecef55c4d3765680eb35a87542dab + md5: e0b4d562accc096561afce52343d72d8 depends: - libgcc-ng >=12 - - openssl >=3.2.1,<4.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - license: MIT - license_family: MIT - size: 5883670 - timestamp: 1711053175449 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe + size: 27935 + timestamp: 1706901541195 +- kind: conda + name: markupsafe + version: 2.1.5 + build: py311he705e18_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-2.1.5-py311he705e18_0.conda + sha256: 83a2b764a4946a04e693a4dd8fe5a35bf093a378da9ce18bf0689cd5dcb3c3fe + md5: 75abe7e2e3a0874a49d7c175115f443f + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - jinja2 >=3.0.0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/markupsafe + size: 26155 + timestamp: 1706900211496 - kind: conda name: maturin version: 1.5.1 @@ -18849,25 +19287,6 @@ packages: - pkg:pypi/maturin@1.5.1 size: 5883670 timestamp: 1711053175449 -- kind: conda - name: maturin - version: 1.5.1 - build: py311h24bb903_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.5.1-py311h24bb903_0.conda - sha256: 52f9e9e54d36ef40cd5c2fa171613750ee56d722e5ac718e5d71d5e4696e559c - md5: 0ffabfb12f4fbb545781a385744ae75a - depends: - - openssl >=3.2.1,<4.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - constrains: - - __osx >=10.12 - license: MIT - license_family: MIT - size: 4746594 - timestamp: 1711043864724 - kind: conda name: maturin version: 1.5.1 @@ -18889,24 +19308,6 @@ packages: - pkg:pypi/maturin@1.5.1 size: 4746594 timestamp: 1711043864724 -- kind: conda - name: maturin - version: 1.5.1 - build: py311h63ff55d_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.5.1-py311h63ff55d_0.conda - sha256: c16ac56fb748e39ae52387395f98c79d031b15d763c1877226bfe8b970690fdb - md5: b988008c60e0ffda52e533668a298c6f - depends: - - libgcc-ng >=12 - - openssl >=3.2.1,<4.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - license: MIT - license_family: MIT - size: 5875793 - timestamp: 1711042912603 - kind: conda name: maturin version: 1.5.1 @@ -18927,26 +19328,6 @@ packages: - pkg:pypi/maturin@1.5.1 size: 5875793 timestamp: 1711042912603 -- kind: conda - name: maturin - version: 1.5.1 - build: py311h71175c2_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.5.1-py311h71175c2_0.conda - sha256: 5e508cb34bf0f2cfc1f06635d3cceefbe679d3fb81ce64d7d2dc0b4bf8af4584 - md5: 50560d0477396cebcaffc864bad10e42 - depends: - - openssl >=3.2.1,<4.0a0 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - constrains: - - __osx >=11.0 - license: MIT - license_family: MIT - size: 4579808 - timestamp: 1711043620752 - kind: conda name: maturin version: 1.5.1 @@ -18985,26 +19366,8 @@ packages: - tomli >=1.1.0 license: MIT license_family: MIT - size: 4498445 - timestamp: 1711044494832 -- kind: conda - name: maturin - version: 1.5.1 - build: py311h9a9e57f_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - sha256: 5307c7955e2a4da23b6a593c715edd8b9e2abe802c1056a225e757ef35eb3356 - md5: 9eeaf6831c4f0a721385e2e9d10c52a7 - depends: - - m2w64-gcc-libs - - m2w64-gcc-libs-core - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/maturin@1.5.1 + purls: + - pkg:pypi/maturin@1.5.1 size: 4498445 timestamp: 1711044494832 - kind: conda @@ -19259,24 +19622,97 @@ packages: size: 3227 timestamp: 1608166968312 - kind: conda - name: mypy - version: 1.8.0 - build: py311h05b510d_0 + name: multidict + version: 6.0.5 + build: py311h459d7ec_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.0.5-py311h459d7ec_0.conda + sha256: aa20fb2d8ecb16099126ec5607fc12082de4111b5e4882e944f4b6cd846178d9 + md5: 4288ea5cbe686d1b18fc3efb36c009a5 + depends: + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/multidict + size: 61944 + timestamp: 1707040860316 +- kind: conda + name: multidict + version: 6.0.5 + build: py311h5547dcb_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.0.5-py311h5547dcb_0.conda + sha256: 6bb2acb8f4c1c25e4bb61421f654559c044af98d409c794cd84ae9fbac031ded + md5: 163d2cb37b054606283917075809c5be + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/multidict + size: 55414 + timestamp: 1707040997198 +- kind: conda + name: multidict + version: 6.0.5 + build: py311ha68e1ae_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/multidict-6.0.5-py311ha68e1ae_0.conda + sha256: 2c293ae0eea6a117f307ac19cc2f3a8ffa0489f91e836bc5e573112e8e24915a + md5: 524a0b4313bfc6986a9ab28d5aed5d1e + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/multidict + size: 56996 + timestamp: 1707041405260 +- kind: conda + name: multidict + version: 6.0.5 + build: py311hcd402e7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/multidict-6.0.5-py311hcd402e7_0.conda + sha256: ed3c773e8c999e80d884f2a277c31cfb3e1431e959c275e25523680e20e7282b + md5: 7f5efe4e95b59dca66f3030507b2ab2a + depends: + - libgcc-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/multidict + size: 63270 + timestamp: 1707040946441 +- kind: conda + name: multidict + version: 6.0.5 + build: py311he2be06e_0 subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda - sha256: e31c811f99b842020350f9df6c6e4b5e2bf07353fee3cc0029c655e8980d9431 - md5: 93010b2e72e263002f6c60dc1c1f7e1d + url: https://conda.anaconda.org/conda-forge/osx-arm64/multidict-6.0.5-py311he2be06e_0.conda + sha256: 4cec39a59647f2ed4c43e3ce67367bf9114782cbc6c6901c17aa9f9fa2c18174 + md5: da67ca4f3cc3f0bf140643d5e03cabe5 depends: - - 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 - license: MIT - license_family: MIT - size: 9655583 - timestamp: 1703185105616 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/multidict + size: 56038 + timestamp: 1707041092018 - kind: conda name: mypy version: 1.8.0 @@ -19298,25 +19734,6 @@ packages: - pkg:pypi/mypy@1.8.0 size: 9655583 timestamp: 1703185105616 -- kind: conda - name: mypy - version: 1.8.0 - build: py311h459d7ec_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda - sha256: 943c43f2d68a6d4e8fa8a3a4e62538e090f5f0afe551f50092ea024850f5cccb - md5: 93b7b2391a045cea0d97772f550f1d77 - depends: - - libgcc-ng >=12 - - mypy_extensions >=1.0.0 - - psutil >=4.0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - typing_extensions >=4.1.0 - license: MIT - license_family: MIT - size: 17719191 - timestamp: 1703185056003 - kind: conda name: mypy version: 1.8.0 @@ -19338,27 +19755,6 @@ packages: - pkg:pypi/mypy@1.8.0 size: 17719191 timestamp: 1703185056003 -- kind: conda - name: mypy - version: 1.8.0 - build: py311ha68e1ae_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/mypy-1.8.0-py311ha68e1ae_0.conda - sha256: cebfab3f247a752be06e945a3a2a1281195d6917fa09906a9618dbc7b2cf734e - md5: 9a949cc91276bf313755857a11ce1ec3 - depends: - - mypy_extensions >=1.0.0 - - psutil >=4.0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - typing_extensions >=4.1.0 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: MIT - license_family: MIT - size: 9963457 - timestamp: 1703184979309 - kind: conda name: mypy version: 1.8.0 @@ -19382,26 +19778,6 @@ packages: - pkg:pypi/mypy@1.8.0 size: 9963457 timestamp: 1703184979309 -- kind: conda - name: mypy - version: 1.8.0 - build: py311hcd402e7_0 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda - sha256: 2a1d84dc94a02ed3cae2fad6dfea0fab4a9504649c1a009d1fff7bfbd9d48e57 - md5: 22b4d0e0a591e6dba331d95f8a702517 - depends: - - libgcc-ng >=12 - - 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 - license: MIT - license_family: MIT - size: 15129179 - timestamp: 1703185374507 - kind: conda name: mypy version: 1.8.0 @@ -19424,24 +19800,6 @@ packages: - pkg:pypi/mypy@1.8.0 size: 15129179 timestamp: 1703185374507 -- kind: conda - name: mypy - version: 1.8.0 - build: py311he705e18_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda - sha256: affdf64692efcf05888cc42fc2c4159fe5bade7d610847b5610e5b2cc621cd3a - md5: c32cbc41e84a67f1b30b3f157b46996b - depends: - - mypy_extensions >=1.0.0 - - psutil >=4.0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - typing_extensions >=4.1.0 - license: MIT - license_family: MIT - size: 11969071 - timestamp: 1703184938293 - kind: conda name: mypy version: 1.8.0 @@ -19462,23 +19820,6 @@ packages: - pkg:pypi/mypy@1.8.0 size: 11969071 timestamp: 1703184938293 -- kind: conda - name: mypy_extensions - version: 1.0.0 - build: pyha770c72_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda - sha256: f240217476e148e825420c6bc3a0c0efb08c0718b7042fae960400c02af858a3 - md5: 4eccaeba205f0aed9ac3a9ea58568ca3 - depends: - - python >=3.5 - license: MIT - license_family: MIT - purls: - - pkg:pypi/mypy-extensions@1.0.0 - size: 10492 - timestamp: 1675543414256 - kind: conda name: mypy_extensions version: 1.0.0 @@ -19933,31 +20274,6 @@ packages: - tox ; extra == 'tox_to_nox' - uv ; extra == 'uv' requires_python: '>=3.7' -- kind: conda - name: numpy - version: 1.26.4 - build: py311h0b4df5a_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/numpy-1.26.4-py311h0b4df5a_0.conda - sha256: 14116e72107de3089cc58119a5ce5905c22abf9a715c9fe41f8ac14db0992326 - md5: 7b240edd44fd7a0991aa409b07cee776 - depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - liblapack >=3.9.0,<4.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - numpy-base <0a0 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/numpy - size: 7104093 - timestamp: 1707226459646 - kind: conda name: numpy version: 1.26.4 @@ -19983,30 +20299,6 @@ packages: - pkg:pypi/numpy@1.26.4 size: 7104093 timestamp: 1707226459646 -- kind: conda - name: numpy - version: 1.26.4 - build: py311h64a7726_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py311h64a7726_0.conda - sha256: 3f4365e11b28e244c95ba8579942b0802761ba7bb31c026f50d1a9ea9c728149 - md5: a502d7aad449a1206efb366d6a12c52d - depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - libgcc-ng >=12 - - liblapack >=3.9.0,<4.0a0 - - libstdcxx-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - numpy-base <0a0 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/numpy - size: 8065890 - timestamp: 1707225944355 - kind: conda name: numpy version: 1.26.4 @@ -20031,31 +20323,6 @@ packages: - pkg:pypi/numpy@1.26.4 size: 8065890 timestamp: 1707225944355 -- kind: conda - name: numpy - version: 1.26.4 - build: py311h69ead2a_0 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/numpy-1.26.4-py311h69ead2a_0.conda - sha256: 88800a1d9d11c2fccab09d40d36f7001616f5119eaf0ec86186562f33564e651 - md5: 3fd00dd400c8d3f9da12bf33061dd28d - depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - libgcc-ng >=12 - - liblapack >=3.9.0,<4.0a0 - - libstdcxx-ng >=12 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - numpy-base <0a0 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/numpy - size: 7234391 - timestamp: 1707225781489 - kind: conda name: numpy version: 1.26.4 @@ -20102,64 +20369,17 @@ packages: license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/numpy + - pkg:pypi/numpy@1.26.4 size: 6652352 timestamp: 1707226297967 - kind: conda name: numpy version: 1.26.4 - build: py311h7125741_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py311h7125741_0.conda - sha256: 160a52a01fea44fe9753a2ed22cf13d7b55c8a89ea0b8738546fdbf4795d6514 - md5: 3160b93669a0def35a7a8158ebb33816 - depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - libcxx >=16 - - liblapack >=3.9.0,<4.0a0 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - numpy-base <0a0 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/numpy@1.26.4 - size: 6652352 - timestamp: 1707226297967 -- kind: conda - name: numpy - version: 1.26.4 - build: py311hc43a94b_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - sha256: dc9628197125ee1d02b2e7a859a769d26291d747ed79337309b8a9e67a8b8e00 - md5: bb02b8801d17265160e466cf8bbf28da - depends: - - libblas >=3.9.0,<4.0a0 - - libcblas >=3.9.0,<4.0a0 - - libcxx >=16 - - liblapack >=3.9.0,<4.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - numpy-base <0a0 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/numpy - size: 7504319 - timestamp: 1707226235372 -- kind: conda - name: numpy - version: 1.26.4 - build: py311hc43a94b_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda - sha256: dc9628197125ee1d02b2e7a859a769d26291d747ed79337309b8a9e67a8b8e00 - md5: bb02b8801d17265160e466cf8bbf28da + build: py311hc43a94b_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.26.4-py311hc43a94b_0.conda + sha256: dc9628197125ee1d02b2e7a859a769d26291d747ed79337309b8a9e67a8b8e00 + md5: bb02b8801d17265160e466cf8bbf28da depends: - libblas >=3.9.0,<4.0a0 - libcblas >=3.9.0,<4.0a0 @@ -20709,42 +20929,6 @@ packages: license_family: Apache size: 433233 timestamp: 1712616573866 -- kind: conda - name: packaging - version: '23.2' - build: pyhd8ed1ab_0 - subdir: win-64 - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.2-pyhd8ed1ab_0.conda - sha256: 69b3ace6cca2dab9047b2c24926077d81d236bef45329d264b394001e3c3e52f - md5: 79002079284aa895f883c6b7f3f88fd6 - depends: - - python >=3.7 - arch: x86_64 - platform: win - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/packaging - size: 49452 - timestamp: 1696202521121 -- kind: conda - name: packaging - version: '24.0' - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/packaging-24.0-pyhd8ed1ab_0.conda - sha256: a390182d74c31dfd713c16db888c92c277feeb6d1fe96ff9d9c105f9564be48a - md5: 248f521b64ce055e7feae3105e7abeb8 - depends: - - python >=3.8 - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/packaging - size: 49832 - timestamp: 1710076089469 - kind: conda name: packaging version: '24.0' @@ -20791,8 +20975,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -20815,8 +20999,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -20839,8 +21023,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -20863,8 +21047,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -20887,8 +21071,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -20929,25 +21113,6 @@ packages: - pkg:pypi/pip size: 1386212 timestamp: 1690024763393 -- kind: conda - name: pip - version: '24.0' - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - sha256: b7c1c5d8f13e8cb491c4bd1d0d1896a4cf80fc47de01059ad77509112b664a4a - md5: f586ac1e56c8638b64f9c8122a7b8a67 - depends: - - python >=3.7 - - setuptools - - wheel - license: MIT - license_family: MIT - purls: - - pkg:pypi/pip - size: 1398245 - timestamp: 1706960660581 - kind: conda name: pip version: '24.0' @@ -21002,23 +21167,6 @@ packages: - pkg:pypi/pluggy size: 22548 timestamp: 1693086745921 -- kind: conda - name: pluggy - version: 1.4.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pluggy-1.4.0-pyhd8ed1ab_0.conda - sha256: 6edfd2c41938ea772096c674809bfcf2ebb9bef7e82de6c7ea0b966b86bfb4d0 - md5: 139e9feb65187e916162917bb2484976 - depends: - - python >=3.8 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pluggy - size: 23384 - timestamp: 1706116931972 - kind: conda name: pluggy version: 1.4.0 @@ -21124,45 +21272,27 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl - sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 + url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d + url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c + url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl - sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 + url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d requires_python: '>=3.8' -- kind: conda - name: psutil - version: 5.9.8 - build: py311h05b510d_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - sha256: 2b6e485c761fa3e7271c44a070c0d08e79a6758ac4d7a660eaff0ed0a60c6f2b - md5: 970ef0edddc6c2cfeb16b7225a28a1f4 - depends: - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil - size: 513415 - timestamp: 1705722847446 - kind: conda name: psutil version: 5.9.8 @@ -21181,24 +21311,6 @@ packages: - pkg:pypi/psutil@5.9.8 size: 513415 timestamp: 1705722847446 -- kind: conda - name: psutil - version: 5.9.8 - build: py311h459d7ec_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - sha256: 467788418a2c71fb3df9ac0a6282ae693d1070a6cb47cb59bdb529b53acaee1c - md5: 9bc62d25dcf64eec484974a3123c9d57 - depends: - - libgcc-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil - size: 505516 - timestamp: 1705722586221 - kind: conda name: psutil version: 5.9.8 @@ -21217,26 +21329,6 @@ packages: - pkg:pypi/psutil@5.9.8 size: 505516 timestamp: 1705722586221 -- kind: conda - name: psutil - version: 5.9.8 - build: py311ha68e1ae_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/psutil-5.9.8-py311ha68e1ae_0.conda - sha256: 77760f2ce0d2be9339d94d0fb5b3d102659355563f5b6471a1231525e63ff581 - md5: 17e48538806e7c682d2ffcbd5c9f9aa0 - depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil - size: 520242 - timestamp: 1705723070638 - kind: conda name: psutil version: 5.9.8 @@ -21257,25 +21349,6 @@ packages: - pkg:pypi/psutil@5.9.8 size: 520242 timestamp: 1705723070638 -- kind: conda - name: psutil - version: 5.9.8 - build: py311hcd402e7_0 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda - sha256: d04efc76d734ac2f1e00f52e3385ba80b089becf60aaae52f0edf185ca9f69e0 - md5: 858767f880caa447ae640a991ec5ba9e - depends: - - libgcc-ng >=12 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil - size: 506604 - timestamp: 1705722743163 - kind: conda name: psutil version: 5.9.8 @@ -21295,23 +21368,6 @@ packages: - pkg:pypi/psutil@5.9.8 size: 506604 timestamp: 1705722743163 -- kind: conda - name: psutil - version: 5.9.8 - build: py311he705e18_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - sha256: fcff83f4d265294b54821656a10be62421da377885ab2e9811a80eb76419b3fe - md5: 31aa294c58b3058c179a7a9593e99e18 - depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/psutil - size: 513371 - timestamp: 1705722716862 - kind: conda name: psutil version: 5.9.8 @@ -21343,23 +21399,6 @@ packages: license: LGPL 2 size: 144301 timestamp: 1537755684331 -- kind: conda - name: py-cpuinfo - version: 9.0.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - sha256: 1bb0459fdebf2f3155ee511e99097c5506ef206acbdd871b74ae9fc4b0c4a019 - md5: 6f6d42b894118f8378fce11887ccdaff - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/py-cpuinfo - size: 24947 - timestamp: 1666774595872 - kind: conda name: py-cpuinfo version: 9.0.0 @@ -21377,35 +21416,6 @@ packages: - pkg:pypi/py-cpuinfo@9.0.0 size: 24947 timestamp: 1666774595872 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311h05400ba_16_cpu - build_number: 16 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h05400ba_16_cpu.conda - sha256: e7ae2e78a52e7c986fd8260ab9cbb33c483f0997bf24f8c2cdc24c28c49428c7 - md5: 13eea94cd11c751009580c32ce6056cc - depends: - - libarrow 14.0.2 h45212c0_16_cpu - - libarrow-acero 14.0.2 h8681a6d_16_cpu - - libarrow-dataset 14.0.2 h8681a6d_16_cpu - - libarrow-flight 14.0.2 h83a3238_16_cpu - - libarrow-flight-sql 14.0.2 h21569af_16_cpu - - libarrow-gandiva 14.0.2 h4e6a3a4_16_cpu - - libarrow-substrait 14.0.2 hea7f8fd_16_cpu - - libparquet 14.0.2 h39135fc_16_cpu - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - size: 3469033 - timestamp: 1712761753340 - kind: conda name: pyarrow version: 14.0.2 @@ -21465,6 +21475,8 @@ packages: - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/pyarrow size: 4398440 timestamp: 1710295377459 - kind: conda @@ -21494,6 +21506,8 @@ packages: - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/pyarrow size: 4524767 timestamp: 1708692350829 - kind: conda @@ -21523,38 +21537,10 @@ packages: - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/pyarrow size: 4511688 timestamp: 1706611416247 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311h4c23913_16_cpu - build_number: 16 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311h4c23913_16_cpu.conda - sha256: 166d22fcb756ae4b627d6c11a7539bba6513982bea03e1f5101575ac486fdf22 - md5: 72676f83b15af074051028a3d87f2dd7 - depends: - - __osx >=11.0 - - libarrow 14.0.2 h3fc723a_16_cpu - - libarrow-acero 14.0.2 h43a2c78_16_cpu - - libarrow-dataset 14.0.2 h43a2c78_16_cpu - - libarrow-flight 14.0.2 h161034a_16_cpu - - libarrow-flight-sql 14.0.2 h32643e2_16_cpu - - libarrow-gandiva 14.0.2 ha803c60_16_cpu - - libarrow-substrait 14.0.2 h7a0fec1_16_cpu - - libcxx >=14 - - libparquet 14.0.2 he0622da_16_cpu - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - license_family: APACHE - size: 4085287 - timestamp: 1712761619928 - kind: conda name: pyarrow version: 14.0.2 @@ -21613,6 +21599,8 @@ packages: - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/pyarrow size: 4009410 timestamp: 1708691836141 - kind: conda @@ -21641,6 +21629,8 @@ packages: - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/pyarrow size: 4013259 timestamp: 1706613498055 - kind: conda @@ -21657,51 +21647,24 @@ packages: - libarrow-acero 14.0.2 h63175ca_10_cpu - libarrow-dataset 14.0.2 h63175ca_10_cpu - libarrow-flight 14.0.2 hca4e5ea_10_cpu - - libarrow-flight-sql 14.0.2 h1ef3bed_10_cpu - - libarrow-gandiva 14.0.2 h6d0e577_10_cpu - - libarrow-substrait 14.0.2 hf368baa_10_cpu - - libparquet 14.0.2 h7ec3a38_10_cpu - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - license_family: APACHE - size: 3465525 - timestamp: 1708693288111 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311h78dcc79_16_cpu - build_number: 16 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h78dcc79_16_cpu.conda - sha256: b1902c06a4269496fe4e5b1d93167df5de7a63e4cc17148fb363a0769f458036 - md5: d2c07999b8658fa0052c41ffbe85e3a0 - depends: - - libarrow 14.0.2 he70291f_16_cpu - - libarrow-acero 14.0.2 hac33072_16_cpu - - libarrow-dataset 14.0.2 hac33072_16_cpu - - libarrow-flight 14.0.2 hd42f311_16_cpu - - libarrow-flight-sql 14.0.2 h9241762_16_cpu - - libarrow-gandiva 14.0.2 hd4ab825_16_cpu - - libarrow-substrait 14.0.2 h9241762_16_cpu - - libgcc-ng >=12 - - libparquet 14.0.2 h6a7eafb_16_cpu - - libstdcxx-ng >=12 + - libarrow-flight-sql 14.0.2 h1ef3bed_10_cpu + - libarrow-gandiva 14.0.2 h6d0e577_10_cpu + - libarrow-substrait 14.0.2 hf368baa_10_cpu + - libparquet 14.0.2 h7ec3a38_10_cpu - numpy >=1.23.5,<2.0a0 - python >=3.11,<3.12.0a0 - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 constrains: - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE - size: 4497078 - timestamp: 1712756648356 + purls: + - pkg:pypi/pyarrow + size: 3465525 + timestamp: 1708693288111 - kind: conda name: pyarrow version: 14.0.2 @@ -21733,34 +21696,6 @@ packages: - pkg:pypi/pyarrow@14.0.2 size: 4497078 timestamp: 1712756648356 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311hb0c4a44_16_cpu - build_number: 16 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311hb0c4a44_16_cpu.conda - sha256: fdf91161069ef925975a4706da24185d62b45d702c7e3e954e2c3851ce31eea0 - md5: 63c818d925da4ce74da9ff6e4ebaea94 - depends: - - __osx >=10.13 - - libarrow 14.0.2 hf13115f_16_cpu - - libarrow-acero 14.0.2 hcdcf8f8_16_cpu - - libarrow-dataset 14.0.2 hcdcf8f8_16_cpu - - libarrow-flight 14.0.2 hcd10e87_16_cpu - - libarrow-flight-sql 14.0.2 hd7485ff_16_cpu - - libarrow-gandiva 14.0.2 h1359b85_16_cpu - - libarrow-substrait 14.0.2 hd7485ff_16_cpu - - libcxx >=14 - - libparquet 14.0.2 h4aea69c_16_cpu - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - size: 4011396 - timestamp: 1712760246531 - kind: conda name: pyarrow version: 14.0.2 @@ -21818,6 +21753,8 @@ packages: - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/pyarrow size: 4094429 timestamp: 1708693258443 - kind: conda @@ -21847,37 +21784,10 @@ packages: - apache-arrow-proc =*=cpu license: Apache-2.0 license_family: APACHE + purls: + - pkg:pypi/pyarrow size: 4074654 timestamp: 1706611920192 -- kind: conda - name: pyarrow - version: 14.0.2 - build: py311hf60b7a8_16_cpu - build_number: 16 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311hf60b7a8_16_cpu.conda - sha256: cfe2988de02922323fea070d1a520a07fc5626db58f908e6f531d763a4802941 - md5: 92eebc9a1f517898d5c1d82ceee0978e - depends: - - libarrow 14.0.2 h520d24b_16_cpu - - libarrow-acero 14.0.2 h0a1ffab_16_cpu - - libarrow-dataset 14.0.2 h0a1ffab_16_cpu - - libarrow-flight 14.0.2 hbf3f4d3_16_cpu - - libarrow-flight-sql 14.0.2 h7624240_16_cpu - - libarrow-gandiva 14.0.2 h1eebba3_16_cpu - - libarrow-substrait 14.0.2 h9b67ed8_16_cpu - - libgcc-ng >=12 - - libparquet 14.0.2 h70b04f6_16_cpu - - libstdcxx-ng >=12 - - numpy >=1.23.5,<2.0a0 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - apache-arrow-proc =*=cpu - license: Apache-2.0 - size: 4395299 - timestamp: 1712757143110 - kind: conda name: pyarrow version: 14.0.2 @@ -21929,6 +21839,17 @@ packages: url: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl sha256: c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc requires_python: '>=3.8' +- kind: pypi + name: pygithub + version: 1.59.0 + url: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl + sha256: 126bdbae72087d8d038b113aab6b059b4553cb59348e3024bb1a1cae406ace9e + requires_dist: + - deprecated + - pyjwt[crypto] >=2.4.0 + - pynacl >=1.4.0 + - requests >=2.14.0 + requires_python: '>=3.7' - kind: pypi name: pygments version: 2.17.2 @@ -21938,6 +21859,27 @@ packages: - importlib-metadata ; python_version < '3.8' and extra == 'plugins' - colorama >=0.4.6 ; extra == 'windows-terminal' requires_python: '>=3.7' +- kind: pypi + name: pyjwt + version: 2.8.0 + url: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl + sha256: 59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 + requires_dist: + - typing-extensions ; python_version <= '3.7' + - cryptography >=3.4.0 ; extra == 'crypto' + - sphinx <5.0.0, >=4.5.0 ; extra == 'dev' + - sphinx-rtd-theme ; extra == 'dev' + - zope-interface ; extra == 'dev' + - cryptography >=3.4.0 ; extra == 'dev' + - pytest <7.0.0, >=6.0.0 ; extra == 'dev' + - coverage[toml] ==5.0.4 ; extra == 'dev' + - pre-commit ; extra == 'dev' + - sphinx <5.0.0, >=4.5.0 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - zope-interface ; extra == 'docs' + - pytest <7.0.0, >=6.0.0 ; extra == 'tests' + - coverage[toml] ==5.0.4 ; extra == 'tests' + requires_python: '>=3.7' - kind: pypi name: pymdown-extensions version: 10.7.1 @@ -21948,6 +21890,54 @@ packages: - pyyaml - pygments >=2.12 ; extra == 'extra' requires_python: '>=3.8' +- kind: pypi + name: pynacl + version: 1.5.0 + url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 + requires_dist: + - cffi >=1.4.1 + - sphinx >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' + - hypothesis >=3.27.0 ; extra == 'tests' + requires_python: '>=3.6' +- kind: pypi + name: pynacl + version: 1.5.0 + url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl + sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 + requires_dist: + - cffi >=1.4.1 + - sphinx >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' + - hypothesis >=3.27.0 ; extra == 'tests' + requires_python: '>=3.6' +- kind: pypi + name: pynacl + version: 1.5.0 + url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl + sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 + requires_dist: + - cffi >=1.4.1 + - sphinx >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' + - hypothesis >=3.27.0 ; extra == 'tests' + requires_python: '>=3.6' +- kind: pypi + name: pynacl + version: 1.5.0 + url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl + sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d + requires_dist: + - cffi >=1.4.1 + - sphinx >=1.6.5 ; extra == 'docs' + - sphinx-rtd-theme ; extra == 'docs' + - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' + - hypothesis >=3.27.0 ; extra == 'tests' + requires_python: '>=3.6' - kind: conda name: pytest version: 7.4.2 @@ -22000,31 +21990,6 @@ packages: - pkg:pypi/pytest size: 251713 timestamp: 1706448088334 -- kind: conda - name: pytest - version: 8.1.1 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - sha256: 3c481d6b54af1a33c32a3f3eaa3e0971955431e7023db55808740cd062271c73 - md5: 94ff09cdedcb7b17e9cd5097ee2cfcff - depends: - - colorama - - exceptiongroup >=1.0.0rc8 - - iniconfig - - packaging - - pluggy <2.0,>=1.4 - - python >=3.8 - - tomli >=1 - constrains: - - pytest-faulthandler >=2 - license: MIT - license_family: MIT - purls: - - pkg:pypi/pytest - size: 255523 - timestamp: 1709992719691 - kind: conda name: pytest version: 8.1.1 @@ -22050,25 +22015,6 @@ packages: - pkg:pypi/pytest@8.1.1 size: 255523 timestamp: 1709992719691 -- kind: conda - name: pytest-benchmark - version: 4.0.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - sha256: e08bba57295c6ca9cbc265347c312aaab1f0cf66f4e8ff53a2461f32c397536f - md5: 8c3168375e2ac100c17b133f4e2eb536 - depends: - - py-cpuinfo - - pytest >=3.8 - - python >=3.5 - license: BSD-2-Clause - license_family: BSD - purls: - - pkg:pypi/pytest-benchmark - size: 39571 - timestamp: 1666782598879 - kind: conda name: pytest-benchmark version: 4.0.0 @@ -22310,8 +22256,8 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl - sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 + url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab requires_python: '>=3.6' - kind: pypi name: pyyaml @@ -22328,14 +22274,14 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d + url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl + sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab + url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d requires_python: '>=3.6' - kind: pypi name: pyyaml-env-tag @@ -22622,8 +22568,8 @@ packages: - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl - sha256: 7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f + url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl + sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 requires_python: '>=3.7' - kind: pypi name: regex @@ -22640,14 +22586,14 @@ packages: - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb + url: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl + sha256: 7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f requires_python: '>=3.7' - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl - sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 + url: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb requires_python: '>=3.7' - kind: pypi name: requests @@ -22717,8 +22663,8 @@ packages: - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl - sha256: 998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa + url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 requires_python: '>=3.8' - kind: pypi name: rpds-py @@ -22735,14 +22681,14 @@ packages: - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 + url: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl + sha256: 998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 + url: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 requires_python: '>=3.8' - kind: pypi name: rsa @@ -22752,25 +22698,6 @@ packages: requires_dist: - pyasn1 >=0.1.3 requires_python: '>=3.6,<4' -- kind: conda - name: ruff - version: 0.3.5 - build: py311h7145743_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda - sha256: 21d492a207c88672288668018ff931eea06c65625f2660fc4e4985e52243f4e8 - md5: 476ec3ffa92e3178463c666a221b401b - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - license: MIT - license_family: MIT - purls: - - pkg:pypi/ruff - size: 6286425 - timestamp: 1711999691593 - kind: conda name: ruff version: 0.3.5 @@ -22790,27 +22717,6 @@ packages: - pkg:pypi/ruff@0.3.5 size: 6286425 timestamp: 1711999691593 -- kind: conda - name: ruff - version: 0.3.5 - build: py311h8c97afb_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda - sha256: 1af91e59adc5bf40a8b5b0e1a2c369286c3e9388179dc76fc2760498a6f2c48c - md5: 8e1fe4c5e7bb5c9a585c57e8cec44d1a - depends: - - libcxx >=16 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - __osx >=11.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/ruff - size: 5764786 - timestamp: 1712000852408 - kind: conda name: ruff version: 0.3.5 @@ -22839,59 +22745,19 @@ packages: subdir: win-64 url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda sha256: 7800532c6daeb465b5847d532cd1244ae86dd1eb95878c28f378d3b0c85d5d47 - md5: d0c971d5173e4d2400ab21f7674d8055 - depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: MIT - license_family: MIT - purls: - - pkg:pypi/ruff - size: 6257429 - timestamp: 1712000640263 -- kind: conda - name: ruff - version: 0.3.5 - build: py311hc14472d_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda - sha256: 7800532c6daeb465b5847d532cd1244ae86dd1eb95878c28f378d3b0c85d5d47 - md5: d0c971d5173e4d2400ab21f7674d8055 - depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - license: MIT - license_family: MIT - purls: - - pkg:pypi/ruff@0.3.5 - size: 6257429 - timestamp: 1712000640263 -- kind: conda - name: ruff - version: 0.3.5 - build: py311he69e3a7_0 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda - sha256: db0e13ff550e1afd405487d3aeb14dc534bca8bf62c297323e83a13fb67e92a8 - md5: c3dc02c8cc9a80ca0b34fc86b083e284 + md5: d0c971d5173e4d2400ab21f7674d8055 depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 license: MIT license_family: MIT purls: - - pkg:pypi/ruff - size: 5937629 - timestamp: 1711999839570 + - pkg:pypi/ruff@0.3.5 + size: 6257429 + timestamp: 1712000640263 - kind: conda name: ruff version: 0.3.5 @@ -22912,26 +22778,6 @@ packages: - pkg:pypi/ruff@0.3.5 size: 5937629 timestamp: 1711999839570 -- kind: conda - name: ruff - version: 0.3.5 - build: py311hfff7943_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda - sha256: 576c9a798ac3a78e8ea4cddd914f45aa7f1615a0e4393bf4cead8d9808ac97b6 - md5: b5410e0ebf58e4444b4659b1f3ee21fc - depends: - - libcxx >=16 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - __osx >=10.12 - license: MIT - license_family: MIT - purls: - - pkg:pypi/ruff - size: 6083087 - timestamp: 1712000648440 - kind: conda name: ruff version: 0.3.5 @@ -23029,23 +22875,6 @@ packages: license_family: Apache size: 339709 timestamp: 1712101772538 -- kind: conda - name: semver - version: 2.13.0 - build: pyh9f0ad1d_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - sha256: 673ef5ef04cef60c3584b1d9b81024646b9d9a4c50749356c7ba5cede755e61d - md5: 2cab9f3a9683cb40a2176ccaf76e66c6 - depends: - - python - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/semver@2.13.0 - size: 15712 - timestamp: 1603697876069 - kind: conda name: semver version: 2.13.0 @@ -23101,23 +22930,6 @@ packages: - pkg:pypi/setuptools size: 470548 timestamp: 1704224855187 -- kind: conda - name: setuptools - version: 69.2.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda - sha256: 78a75c75a5dacda6de5f4056c9c990141bdaf4f64245673a590594d00bc63713 - md5: da214ecd521a720a9d521c68047682dc - depends: - - python >=3.8 - license: MIT - license_family: MIT - purls: - - pkg:pypi/setuptools - size: 471183 - timestamp: 1710344615844 - kind: conda name: setuptools version: 69.2.0 @@ -23169,23 +22981,6 @@ packages: url: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl sha256: 8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*' -- kind: conda - name: smmap - version: 5.0.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/smmap-5.0.0-pyhd8ed1ab_0.tar.bz2 - sha256: 23011cb3e064525bdb8787c75126a2e78d2344a72cd6773922006d1da1f2af16 - md5: 62f26a3d1387acee31322208f0cfa3e0 - depends: - - python >=3.5 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/smmap@5.0.0 - size: 22483 - timestamp: 1634310465482 - kind: conda name: smmap version: 5.0.0 @@ -23697,23 +23492,6 @@ packages: license_family: BSD size: 3318875 timestamp: 1699202167581 -- kind: conda - name: tomli - version: 2.0.1 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - sha256: 4cd48aba7cd026d17e86886af48d0d2ebc67ed36f87f6534f4b67138f5a5a58f - md5: 5844808ffab9ebdb694585b50ba02a96 - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/tomli@2.0.1 - size: 15940 - timestamp: 1644342331069 - kind: conda name: tomli version: 2.0.1 @@ -23733,23 +23511,6 @@ packages: - pkg:pypi/tomli size: 15940 timestamp: 1644342331069 -- kind: conda - name: tomlkit - version: 0.12.3 - build: pyha770c72_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/tomlkit-0.12.3-pyha770c72_0.conda - sha256: 53cc436ab92d38683df1320e4468a8b978428e800195bf1c8c2460e90b0bc117 - md5: 074d0ce7a6261ab8b497c3518796ef3e - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/tomlkit@0.12.3 - size: 37132 - timestamp: 1700046842169 - kind: conda name: tomlkit version: 0.12.3 @@ -23799,8 +23560,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl - sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c requires_dist: - filelock - typing-extensions >=4.8.0 @@ -23826,8 +23587,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl - sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 + url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 requires_dist: - filelock - typing-extensions >=4.8.0 @@ -23853,8 +23614,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf requires_dist: - filelock - typing-extensions >=4.8.0 @@ -23880,8 +23641,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 requires_dist: - filelock - typing-extensions >=4.8.0 @@ -23904,6 +23665,23 @@ packages: - opt-einsum >=3.3 ; extra == 'opt-einsum' - optree >=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' +- kind: conda + name: tqdm + version: 4.66.2 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.66.2-pyhd8ed1ab_0.conda + sha256: 416d1d9318f3267325ad7e2b8a575df20ff9031197b30c0222c3d3b023877260 + md5: 2b8dfb969f984497f3f98409a9545776 + depends: + - colorama + - python >=3.7 + license: MPL-2.0 or MIT + purls: + - pkg:pypi/tqdm + size: 89567 + timestamp: 1707598746354 - kind: pypi name: triton version: 2.2.0 @@ -23924,6 +23702,19 @@ packages: - pandas ; extra == 'tutorials' - tabulate ; extra == 'tutorials' - torch ; extra == 'tutorials' +- kind: pypi + name: types-deprecated + version: 1.2.9.2 + url: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl + sha256: 327783e137353b0ef9cf47a8cd4b1c0b8ae72f6554eb25820783c6a81a3d556f +- kind: pypi + name: types-requests + version: 2.31.0.20240406 + url: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl + sha256: 6216cdac377c6b9a040ac1c0404f7284bd13199c0e1bb235f4324627e8898cf5 + requires_dist: + - urllib3 >=2 + requires_python: '>=3.8' - kind: conda name: typing_extensions version: 4.8.0 @@ -23977,23 +23768,6 @@ packages: - pkg:pypi/typing-extensions size: 37018 timestamp: 1708904796013 -- kind: conda - name: typing_extensions - version: 4.11.0 - build: pyha770c72_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - sha256: a7e8714d14f854058e971a6ed44f18cc37cc685f98ddefb2e6b7899a0cc4d1a2 - md5: 6ef2fc37559256cf682d8b3375e89b80 - depends: - - python >=3.8 - license: PSF-2.0 - license_family: PSF - purls: - - pkg:pypi/typing-extensions - size: 37583 - timestamp: 1712330089194 - kind: conda name: typing_extensions version: 4.11.0 @@ -24527,8 +24301,8 @@ packages: - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl - sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245 + url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' @@ -24551,36 +24325,19 @@ packages: - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl - sha256: 8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3 + url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl + sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b + url: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl + sha256: 8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' -- kind: conda - name: wheel - version: 0.38.4 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - sha256: bd4f11ff075ff251ade9f57686f31473e25be46ab282d9603f551401250f9f44 - md5: c829cfb8cb826acb9de0ac1a2df0a940 - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/wheel@0.38.4 - size: 32521 - timestamp: 1668051714265 - kind: conda name: wheel version: 0.38.4 @@ -24600,6 +24357,36 @@ packages: - pkg:pypi/wheel size: 32521 timestamp: 1668051714265 +- kind: pypi + name: wrapt + version: 1.16.0 + url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 + requires_python: '>=3.6' +- kind: pypi + name: wrapt + version: 1.16.0 + url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 + requires_python: '>=3.6' +- kind: pypi + name: wrapt + version: 1.16.0 + url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl + sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 + requires_python: '>=3.6' +- kind: pypi + name: wrapt + version: 1.16.0 + url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 + requires_python: '>=3.6' +- kind: pypi + name: wrapt + version: 1.16.0 + url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d + requires_python: '>=3.6' - kind: conda name: xz version: 5.2.6 @@ -24662,6 +24449,108 @@ packages: license: LGPL-2.1 and GPL-2.0 size: 440555 timestamp: 1660348056328 +- kind: conda + name: yarl + version: 1.9.4 + build: py311h05b510d_0 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda + sha256: 1da2a08c44e284d17156838d8207fde58dececde3c07626114df4d9a64ae9213 + md5: 510eded0989b4ef17f3adeca6cb21b22 + depends: + - idna >=2.0 + - multidict >=4.0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/yarl + size: 113463 + timestamp: 1705508875443 +- kind: conda + name: yarl + version: 1.9.4 + build: py311h459d7ec_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda + sha256: 673e4a626e9e7d661154e5609f696c0c8a9247087f5c8b7744cfbb4fe0872713 + md5: fff0f2058e9d86c8bf5848ee93917a8d + depends: + - idna >=2.0 + - libgcc-ng >=12 + - multidict >=4.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/yarl + size: 122372 + timestamp: 1705508480013 +- kind: conda + name: yarl + version: 1.9.4 + build: py311ha68e1ae_0 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda + sha256: 647a7f6395be44b82a3dd4ad58d02fd1ce56cca19083061cbb118f788c0f31e5 + md5: 522f873d68d2557056d6cfed8335fe96 + depends: + - idna >=2.0 + - multidict >=4.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/yarl + size: 113426 + timestamp: 1705509198913 +- kind: conda + name: yarl + version: 1.9.4 + build: py311hcd402e7_0 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda + sha256: bfd885fa804df0d2238aeddcb656e87475208e9f406cb9009a43d8d37ede0309 + md5: 144e7ef78cd4bfb0d462cb2d5a000fff + depends: + - idna >=2.0 + - libgcc-ng >=12 + - multidict >=4.0 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/yarl + size: 120752 + timestamp: 1705508610476 +- kind: conda + name: yarl + version: 1.9.4 + build: py311he705e18_0 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda + sha256: 668ea9d1e0c7b4eaa769cc79de1ea4e8da22a61d4112e660ecbaca140f097109 + md5: 6b7f34fc151c338cdaca4d4d6fb92d55 + depends: + - idna >=2.0 + - multidict >=4.0 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/yarl + size: 112887 + timestamp: 1705508591601 - kind: conda name: zlib version: 1.2.13 diff --git a/pixi.toml b/pixi.toml index 3f158737047b..45194fb82a20 100644 --- a/pixi.toml +++ b/pixi.toml @@ -167,15 +167,14 @@ py-docs-serve = "mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py" [feature.py-docs.pypi-dependencies] griffe = "==0.39.0" -# forked mkdocs-redirects with https://github.com/rerun-io/mkdocs-redirects/commit/d367a0847928438b66f73508e49852be1190409bmkdocs = "==1.5.3" -mkdocs-redirects = { git = "https://github.com/rerun-io/mkdocs-redirects.git", rev = "fb6b074554975ba7729d68d04957ce7c7dfd5003" } +mike = "==1.1.2" mkdocs-gen-files = "==0.5.0" mkdocs-literate-nav = "==0.6.1" mkdocs-material = "==9.4.7" mkdocs-material-extensions = "==1.3" +mkdocs-redirects = { git = "https://github.com/rerun-io/mkdocs-redirects.git", rev = "fb6b074554975ba7729d68d04957ce7c7dfd5003" } # forked mkdocs-redirects with https://github.com/rerun-io/mkdocs-redirects/commit/d367a0847928438b66f73508e49852be1190409bmkdocs = "==1.5.3" mkdocstrings = "==0.23.0" mkdocstrings-python = "==1.7.3" -mike = "==1.1.2" sphobjinv = "==2.3.1" typing_extensions = "==4.11.0" # uncaptured dep for mkdocstrings (https://github.com/mkdocstrings/mkdocstrings/issues/548) @@ -244,41 +243,48 @@ rerun = "rerun" # `meilisearch`). # - Last resort, use a feature to conditionally include a dependency (e.g. `taplo`). +aiohttp = ">=3.9.3,<3.10" # For `zombie_todos.py` attrs = ">=23.1.0" +binaryen = "117.*" # for `wasm-opt` clang-tools = "16.0.6" # clang-format cmake = "3.27.6" +colorama = ">=0.4.6,<0.5" +doxygen = "1.9.7.*" # Make sure to use a version that is compatible with the theme we're using, see https://github.com/jothepro/doxygen-awesome-css/blob/v2.2.1/README.md flatbuffers = ">=23" gitignore-parser = ">=0.1.9" gitpython = ">=3.1.40" +jinja2 = ">=3.1.3,<3.2" # For `update_pr_bodies.py`, `generate_pr_summary.py`, `build_screenshot_compare.py` and other utilities that build websites. maturin = "1.5.1" mypy = "1.8.0" +ninja = "1.11.1" numpy = ">=1.23,<2" +packaging = ">=24.0,<25" # For `publish_wheels.py` pip = ">=23" +prettier = "2.8.8.*" pyarrow = "14.0.2" pytest = ">=7" pytest-benchmark = ">=4.0.0,<4.1" python = "=3.11" # We use the latest Python version here, so we get the latest mypy etc, EXCEPT 3.12 is too new for some of our examples. We run our CI tests on ALL supported versions though. ruff = "0.3.5" semver = ">=2.13,<2.14" +taplo = "=0.9.1" +tomlkit = "0.12.3.*" +tqdm = ">=4.66.2,<4.67" # For displaying progress in various utility scripts. typing_extensions = ">4.5" typos = ">=1.16.20" wheel = ">=0.38,<0.39" -ninja = "1.11.1" -# Make sure to use a version that is compatible with -# the theme we're using, see https://github.com/jothepro/doxygen-awesome-css/blob/v2.2.1/README.md -doxygen = "1.9.7.*" -binaryen = "117.*" # for `wasm-opt` -prettier = "2.8.8.*" -taplo = "=0.9.1" -tomlkit = "0.12.3.*" [pypi-dependencies] +colorama = "==0.4.6" # For `crates.py` cryptography = "==38.0.4" # For `upload_image.py` google-cloud-storage = "==2.9.0" # For `upload_image.py` -nox = ">=2024.3.2" # the conda-forge package is (wrongly) tagged as platform-specific +nox = ">=2024.3.2" # The conda-forge package is (wrongly) tagged as platform-specific Pillow = "==10.0.0" # For `thumbnails.py` +pygithub = "==1.59.0" # Among others for `generate_pr_summary.py`, `sync_release_assets.py`, `update_pr_body.py`. requests = ">=2.31,<3" # For `thumbnails.py` & `upload_image.py` -tomlkit = ">=0.11.8" # For `thumbnails.py` +types-Deprecated = "==1.2.9.2" # Type hint stubs +types-requests = ">=2.31,<3" # Type hint stubs + [target.linux-64.dependencies] patchelf = ">=0.17" diff --git a/rerun_py/requirements-build.txt b/rerun_py/requirements-build.txt deleted file mode 100644 index 4eeb5d293455..000000000000 --- a/rerun_py/requirements-build.txt +++ /dev/null @@ -1,6 +0,0 @@ -attrs>=23.1.0 -maturin>=1.5.1 -semver -wheel -pytest -torch>=2.0.1 diff --git a/rerun_py/requirements-lint.txt b/rerun_py/requirements-lint.txt deleted file mode 100644 index 001d44d5eaac..000000000000 --- a/rerun_py/requirements-lint.txt +++ /dev/null @@ -1,10 +0,0 @@ -attrs>=23.1.0 # for mypy to work -blackdoc==0.3.8 -mypy==1.8.0 -numpy>=1.23,<2 # For mypy plugin -torch>=2.0.1 -pip-check-reqs==2.4.4 # Checks for missing deps in requirements.txt files -pytest # For mypy to work -ruff==0.2.2 -types-Deprecated==1.2.9.2 -types-requests>=2.31,<3 diff --git a/scripts/ci/approve_workflow_runs.py b/scripts/ci/approve_workflow_runs.py index bb781ffebfdf..404ff5dd5d8f 100755 --- a/scripts/ci/approve_workflow_runs.py +++ b/scripts/ci/approve_workflow_runs.py @@ -7,9 +7,6 @@ and approves any workflow runs with pending approval. This is expected to be run by the `auto_approve.yml` GitHub workflow. - -Requires the following packages: - pip install PyGithub==1.59.0 requests>=2.31,<3 """ from __future__ import annotations diff --git a/scripts/ci/build_and_upload_wheels.py b/scripts/ci/build_and_upload_wheels.py index 932f9a672b54..90ad4bff6168 100755 --- a/scripts/ci/build_and_upload_wheels.py +++ b/scripts/ci/build_and_upload_wheels.py @@ -54,11 +54,6 @@ def detect_target() -> str: return f"{arch}-{os}" -def detect_pixi() -> bool: - path = os.environ.get("PATH") - return path is not None and ".pixi/env/bin" in path - - class BuildMode(Enum): PYPI = "pypi" PR = "pr" @@ -68,9 +63,6 @@ def __str__(self) -> str: def build_and_upload(bucket: Bucket, mode: BuildMode, gcs_dir: str, target: str, compatibility: str) -> None: - if detect_pixi(): - raise Exception("the build script cannot be started in the pixi environment") - if mode is BuildMode.PYPI: # Only build web viewer when publishing to pypi run("pixi run cargo run --locked -p re_build_web_viewer -- --release -g") diff --git a/scripts/ci/crates.py b/scripts/ci/crates.py index 0a38b522e7dc..a61bf6fc6e61 100755 --- a/scripts/ci/crates.py +++ b/scripts/ci/crates.py @@ -3,21 +3,18 @@ """ Versioning and packaging. -Install dependencies: - python3 -m pip install -r scripts/ci/requirements.txt - Use the script: - python3 scripts/ci/crates.py --help + pixi run python scripts/ci/crates.py --help # Update crate versions to the next prerelease version, # e.g. `0.8.0` -> `0.8.0-alpha.0`, `0.8.0-alpha.0` -> `0.8.0-alpha.1` - python3 scripts/ci/crates.py version --bump prerelase --dry-run + pixi run python scripts/ci/crates.py version --bump prerelase --dry-run # Update crate versions to an exact version - python3 scripts/ci/crates.py version --exact 0.10.1 --dry-run + pixi run python scripts/ci/crates.py version --exact 0.10.1 --dry-run # Publish all crates in topological order - python3 scripts/ci/publish.py --token + pixi run python scripts/ci/publish.py --token """ from __future__ import annotations diff --git a/scripts/ci/generate_pr_summary.py b/scripts/ci/generate_pr_summary.py index c1f4cbf69ba5..0674da0e57b7 100644 --- a/scripts/ci/generate_pr_summary.py +++ b/scripts/ci/generate_pr_summary.py @@ -5,9 +5,6 @@ to find and link to the builds associated with a given PR. This is expected to be run by the `reusable_pr_summary.yml` GitHub workflow. - -Requires the following packages: - pip install google-cloud-storage Jinja2 PyGithub """ from __future__ import annotations diff --git a/scripts/ci/publish_wheels.py b/scripts/ci/publish_wheels.py index 943a5e870dff..6790d2434e95 100755 --- a/scripts/ci/publish_wheels.py +++ b/scripts/ci/publish_wheels.py @@ -3,9 +3,6 @@ """ Publish wheels to PyPI. -Install dependencies: - python3 -m pip install packaging==23.1 google-cloud-storage==2.9.0 - Use the script: python3 scripts/ci/verify_wheels.py --help """ diff --git a/scripts/ci/requirements-crates.txt b/scripts/ci/requirements-crates.txt deleted file mode 100644 index aeaba8ef46ff..000000000000 --- a/scripts/ci/requirements-crates.txt +++ /dev/null @@ -1,6 +0,0 @@ -PyGithub==1.59.0 -GitPython==3.1.37 -colorama==0.4.6 -requests>=2.31,<3 -tomlkit==0.11.8 -semver>=2.13,<2.14 diff --git a/scripts/ci/requirements.txt b/scripts/ci/requirements.txt deleted file mode 100644 index de54cb955f88..000000000000 --- a/scripts/ci/requirements.txt +++ /dev/null @@ -1,16 +0,0 @@ - --r ../../rerun_py/requirements-build.txt --r ../../rerun_py/requirements-lint.txt --r ./requirements-crates.txt - -Jinja2==3.1.2 -Pillow==10.0.0 -PyGithub==1.59.0 -GitPython==3.1.37 -aiohttp==3.8.5 -colorama==0.4.6 -gitignore-parser==0.1.4 -google-cloud-storage==2.9.0 -packaging==23.1 -requests>=2.31,<3 -tomlkit==0.11.8 diff --git a/scripts/ci/sync_release_assets.py b/scripts/ci/sync_release_assets.py index 60da0b3eab30..60bb6ab7ded5 100644 --- a/scripts/ci/sync_release_assets.py +++ b/scripts/ci/sync_release_assets.py @@ -9,9 +9,6 @@ You can also run it manually if you want to update a specific release's assets: python scripts/ci/sync_release_assets.py --github-release prerelease --github-token --update - -Requires the following packages: - pip install google-cloud-storage PyGithub """ from __future__ import annotations diff --git a/scripts/ci/update_pr_body.py b/scripts/ci/update_pr_body.py index 697b15191fc0..295f106cda4c 100755 --- a/scripts/ci/update_pr_body.py +++ b/scripts/ci/update_pr_body.py @@ -4,9 +4,6 @@ Script to update the PR description template. This is expected to be run by the `reusable_update_pr_body.yml` GitHub workflow. - -Requires the following packages: - pip install Jinja2 PyGithub """ from __future__ import annotations diff --git a/scripts/requirements-dev.txt b/scripts/requirements-dev.txt deleted file mode 100644 index a31dbf2ae238..000000000000 --- a/scripts/requirements-dev.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Pip packages all developers need - --r ../rerun_py/requirements-build.txt --r ../rerun_py/requirements-lint.txt - -PyGithub==1.58.2 # for scripts/ci/generate_pr_summary.py and scripts/ci/update_pr_body.py -torch -tqdm -requests -gitignore_parser # handle .gitignore From 549fdf104414b64939b10249aa169a6d03ac3e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 13:29:07 +0200 Subject: [PATCH 275/508] Full check part 2 (#5946) ### What The job failed: https://github.com/rerun-io/rerun/actions/runs/8661322011/job/23750996001 Needed to add `checkout` so that `gh cli` has a git repository ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index d26b4628f073..3723e5de0b5d 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -32,6 +32,9 @@ jobs: if: needs.parse-command.outputs.command == 'full-check' runs-on: ubuntu-latest steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Dispatch main workflow id: dispatch shell: bash From 5367a63829f16e74d19615f2bd9d0a15ddf8d8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 13:41:23 +0200 Subject: [PATCH 276/508] Full check 3 (#5947) ### What The ref name is now retrieved using the GH CLI (`gh pr view `), because issue_comment always runs on `main` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 3723e5de0b5d..1f9d9f5370e6 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -70,7 +70,7 @@ jobs: } workflow_name='on_push_main.yml' - ref_name='${{ github.ref_name }}' + ref_name=$(gh pr view ${{ github.event.issue.number }} --json headRefName --jq '.headRefName') now=$(date --utc --iso-8601=seconds) echo "Dispatching workflow $workflow_name on branch $ref_name" From 97240ef90e927f6aa18ec6fc3a7eaa7400f03211 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 12 Apr 2024 13:48:38 +0200 Subject: [PATCH 277/508] A bunch of small fixes (#5944) ### What See commit messages. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5944?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5944?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5944) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) --- .github/workflows/contrib_rerun_py.yml | 2 +- .github/workflows/reusable_build_examples.yml | 2 +- .github/workflows/reusable_test_wheels.yml | 2 +- CHANGELOG.md | 2 +- crates/re_viewer/src/ui/welcome_screen/example_section.rs | 3 ++- scripts/ci/build_and_upload_wheels.py | 3 ++- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 688b5c7c410e..1bcb5feb8e2d 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -85,7 +85,7 @@ jobs: pixi run -e wheel-test pip uninstall rerun-sdk pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links dist - - name: Verify built wheel version + - name: Print wheel version shell: bash run: | pixi run -e wheel-test python -m rerun --version diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index b41b19b813c2..ac96673d5d78 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -82,7 +82,7 @@ jobs: pixi run -e wheel-test pip uninstall rerun-sdk -y pixi run -e wheel-test pip install rerun-sdk --no-index --find-links wheel - - name: Verify built wheel version + - name: Print wheel version shell: bash run: | pixi run -e wheel-test python -m rerun --version diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 0042137f453c..f8d9f0fc376b 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -168,7 +168,7 @@ jobs: pixi run -e wheel-test pip uninstall rerun-sdk pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links wheel - - name: Verify built wheel version + - name: Print wheel version shell: bash run: | pixi run -e wheel-test python -m rerun --version diff --git a/CHANGELOG.md b/CHANGELOG.md index cb61acae9cd3..91396c6d046d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## [Unreleased](https://github.com/rerun-io/rerun/compare/latest...HEAD) -## [0.15.1](https://github.com/rerun-io/rerun/compare/0.15.1...0.15.0) - Bug fix for notebooks - 2024-04-11 +## [0.15.1](https://github.com/rerun-io/rerun/compare/0.15.0...0.15.1) - Bug fix for notebooks - 2024-04-11 - Fix timeout in notebooks by making the `app_url` correctly point to `app.rerun.io` [#5877](https://github.com/rerun-io/rerun/pull/5877) - CMake: Allow to call `find_package(rerun_sdk)` two or more times [#5886](https://github.com/rerun-io/rerun/pull/5886) (thanks [@traversaro](https://github.com/traversaro)!) diff --git a/crates/re_viewer/src/ui/welcome_screen/example_section.rs b/crates/re_viewer/src/ui/welcome_screen/example_section.rs index d0280e5e9144..26692c388ca2 100644 --- a/crates/re_viewer/src/ui/welcome_screen/example_section.rs +++ b/crates/re_viewer/src/ui/welcome_screen/example_section.rs @@ -1,5 +1,6 @@ use egui::{NumExt as _, Ui}; use ehttp::{fetch, Request}; +use itertools::Itertools as _; use poll_promise::Promise; use re_viewer_context::{CommandSender, SystemCommand, SystemCommandSender as _}; @@ -567,7 +568,7 @@ impl ExampleDescLayout { // TODO(ab): use design tokens ui.style_mut().spacing.button_padding = egui::vec2(4.0, 2.0); ui.style_mut().spacing.item_spacing = egui::vec2(4.0, 4.0); - for tag in &self.desc.tags { + for tag in self.desc.tags.iter().sorted() { ui.add( egui::Button::new( egui::RichText::new(tag).text_style(re_ui::ReUi::welcome_screen_tag()), diff --git a/scripts/ci/build_and_upload_wheels.py b/scripts/ci/build_and_upload_wheels.py index 90ad4bff6168..147de0453906 100755 --- a/scripts/ci/build_and_upload_wheels.py +++ b/scripts/ci/build_and_upload_wheels.py @@ -65,7 +65,7 @@ def __str__(self) -> str: def build_and_upload(bucket: Bucket, mode: BuildMode, gcs_dir: str, target: str, compatibility: str) -> None: if mode is BuildMode.PYPI: # Only build web viewer when publishing to pypi - run("pixi run cargo run --locked -p re_build_web_viewer -- --release -g") + run("pixi run cargo run --quiet --locked -p re_build_web_viewer -- --release -g") maturin_feature_flags = "--no-default-features --features pypi" elif mode is BuildMode.PR: maturin_feature_flags = "--no-default-features --features extension-module" @@ -79,6 +79,7 @@ def build_and_upload(bucket: Bucket, mode: BuildMode, gcs_dir: str, target: str, "maturin build " f"{compatibility} " "--manifest-path rerun_py/Cargo.toml " + "--quiet " "--release " f"--target {target} " f"{maturin_feature_flags} " From 4334b02e5809707e8f6837e92dc08786af37a75f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:02:15 +0200 Subject: [PATCH 278/508] Full check part 4 (#5950) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 15 +++++++++------ README.md | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 1f9d9f5370e6..185bf915958f 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -45,7 +45,7 @@ jobs: # https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow GH_TOKEN: ${{ secrets.RERUN_BOT_TOKEN }} run: | - get_latest_workflow_run_id () { + get_latest_workflow_run () { local workflow_name=$1 local ref_name=$2 local created_after=$3 @@ -57,8 +57,7 @@ jobs: --branch $ref_name \ # https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates --created ">$created_after" \ - --json databaseId \ - --jq '.[0].databaseId' + --json databaseId ) } @@ -70,7 +69,7 @@ jobs: } workflow_name='on_push_main.yml' - ref_name=$(gh pr view ${{ github.event.issue.number }} --json headRefName --jq '.headRefName') + ref_name=$(gh pr view ${{ github.event.issue.number }} --json headRefName | jq '.headRefName') now=$(date --utc --iso-8601=seconds) echo "Dispatching workflow $workflow_name on branch $ref_name" @@ -82,10 +81,14 @@ jobs: # started a workflow in parallel with us on the same branch. echo "Fetching workflow run id…" - run_id=$(get_latest_workflow_run_id $workflow_name $ref_name $now) + run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) + echo $run_info + run_id=$(echo $run_info | jq '.[0].databaseId') while [ -z $run_id ] do - run_id=$(get_latest_workflow_run_id $workflow_name $ref_name $now) + run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) + echo $run_info + run_id=$(echo $run_info | jq '.[0].databaseId') sleep 1 done echo "Workflow run: https://github.com/rerun-io/rerun/actions/runs/$run_id" diff --git a/README.md b/README.md index 02e832749897..ad39c450d273 100644 --- a/README.md +++ b/README.md @@ -130,3 +130,6 @@ facilitates the tool's discovery by other researchers. 1. Download the correct `.whl` from [GitHub Releases](https://github.com/rerun-io/rerun/releases) 2. Run `pip install rerun_sdk<…>.whl` (replace `<…>` with the actual filename) 3. Test it: `rerun --version` + + +### Hi From d135172b3a3f20671ff754f0039548111279127d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:09:37 +0200 Subject: [PATCH 279/508] Full check 5 (#5951) ### What ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 185bf915958f..63f4d737b6cc 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -34,6 +34,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Dispatch main workflow id: dispatch From eb702c89d2a81a1edf648c36d8d985e4f5d40a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:14:53 +0200 Subject: [PATCH 280/508] Random change to test PR comment trigger (#5952) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5952?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5952?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5952) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index ad39c450d273..02e832749897 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,3 @@ facilitates the tool's discovery by other researchers. 1. Download the correct `.whl` from [GitHub Releases](https://github.com/rerun-io/rerun/releases) 2. Run `pip install rerun_sdk<…>.whl` (replace `<…>` with the actual filename) 3. Test it: `rerun --version` - - -### Hi From d75177b324f9e7391be6e2191d9c3e6fc63e9914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:18:54 +0200 Subject: [PATCH 281/508] Full check 6 (#5953) ### What I'm getting "ref not found" errors, which may be because of the `/` in the branch name. Using a fully qualified ref instead ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 63f4d737b6cc..8e2706956134 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -67,7 +67,7 @@ jobs: local workflow_name=$1 local ref_name=$2 # https://cli.github.com/manual/gh_workflow_run - gh workflow run $workflow_name --ref $ref_name + gh workflow run $workflow_name --ref "refs/heads/$ref_name" } workflow_name='on_push_main.yml' From 134486ad6fe317dd712d35144eb2d1ac4f827393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:22:15 +0200 Subject: [PATCH 282/508] Full check 7 (#5955) ### What Using `jq -r` to print unquoted output ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 6 +++--- README.md | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 8e2706956134..600b7dbd12f6 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -71,7 +71,7 @@ jobs: } workflow_name='on_push_main.yml' - ref_name=$(gh pr view ${{ github.event.issue.number }} --json headRefName | jq '.headRefName') + ref_name=$(gh pr view ${{ github.event.issue.number }} --json headRefName | jq -r '.headRefName') now=$(date --utc --iso-8601=seconds) echo "Dispatching workflow $workflow_name on branch $ref_name" @@ -85,12 +85,12 @@ jobs: echo "Fetching workflow run id…" run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) echo $run_info - run_id=$(echo $run_info | jq '.[0].databaseId') + run_id=$(echo $run_info | jq -r '.[0].databaseId') while [ -z $run_id ] do run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) echo $run_info - run_id=$(echo $run_info | jq '.[0].databaseId') + run_id=$(echo $run_info | jq -r '.[0].databaseId') sleep 1 done echo "Workflow run: https://github.com/rerun-io/rerun/actions/runs/$run_id" diff --git a/README.md b/README.md index 02e832749897..c1afc3026426 100644 --- a/README.md +++ b/README.md @@ -130,3 +130,6 @@ facilitates the tool's discovery by other researchers. 1. Download the correct `.whl` from [GitHub Releases](https://github.com/rerun-io/rerun/releases) 2. Run `pip install rerun_sdk<…>.whl` (replace `<…>` with the actual filename) 3. Test it: `rerun --version` + + +### Test From 99d0a0142e7dea786f202048ed40392dffdad337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:32:37 +0200 Subject: [PATCH 283/508] Full check 8 (#5956) ### What A comment in bash still counts as a line, so in ```bash asdf \ --test \ # comment --foo ``` `--foo` is treated as a separate command ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 600b7dbd12f6..92f3bbcc9173 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -53,11 +53,11 @@ jobs: local created_after=$3 echo $( # https://cli.github.com/manual/gh_run_list + # https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates gh run list \ --workflow $workflow_name \ --event workflow_dispatch \ --branch $ref_name \ - # https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates --created ">$created_after" \ --json databaseId ) @@ -83,14 +83,10 @@ jobs: # started a workflow in parallel with us on the same branch. echo "Fetching workflow run id…" - run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) - echo $run_info - run_id=$(echo $run_info | jq -r '.[0].databaseId') + run_id=$(get_latest_workflow_run $workflow_name $ref_name $now | jq -r '.[0].databaseId') while [ -z $run_id ] do - run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) - echo $run_info - run_id=$(echo $run_info | jq -r '.[0].databaseId') + run_id=$(get_latest_workflow_run $workflow_name $ref_name $now | jq -r '.[0].databaseId') sleep 1 done echo "Workflow run: https://github.com/rerun-io/rerun/actions/runs/$run_id" From d03850b40bf9d1115c1c1dbbdf244a19cf3358b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:35:57 +0200 Subject: [PATCH 284/508] Full check 9 (#5957) ### What Re-adding some debug stuff because for some reason again the run ID could not be fetched ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 12 +++++++----- README.md | 3 --- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 92f3bbcc9173..c45c352a38b4 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -34,8 +34,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 - with: - fetch-depth: 0 - name: Dispatch main workflow id: dispatch @@ -53,11 +51,11 @@ jobs: local created_after=$3 echo $( # https://cli.github.com/manual/gh_run_list - # https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates gh run list \ --workflow $workflow_name \ --event workflow_dispatch \ --branch $ref_name \ + # https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates --created ">$created_after" \ --json databaseId ) @@ -83,10 +81,14 @@ jobs: # started a workflow in parallel with us on the same branch. echo "Fetching workflow run id…" - run_id=$(get_latest_workflow_run $workflow_name $ref_name $now | jq -r '.[0].databaseId') + run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) + echo $run_info + run_id=$(echo $run_info | jq -r '.[0].databaseId') while [ -z $run_id ] do - run_id=$(get_latest_workflow_run $workflow_name $ref_name $now | jq -r '.[0].databaseId') + run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) + echo $run_info + run_id=$(echo $run_info | jq -r '.[0].databaseId') sleep 1 done echo "Workflow run: https://github.com/rerun-io/rerun/actions/runs/$run_id" diff --git a/README.md b/README.md index c1afc3026426..02e832749897 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,3 @@ facilitates the tool's discovery by other researchers. 1. Download the correct `.whl` from [GitHub Releases](https://github.com/rerun-io/rerun/releases) 2. Run `pip install rerun_sdk<…>.whl` (replace `<…>` with the actual filename) 3. Test it: `rerun --version` - - -### Test From fec8713ea502493e926910163d2d8245d8d0bacb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:38:41 +0200 Subject: [PATCH 285/508] Jan/full check 10 (#5959) ### What ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. From 5ca2b85dd8036549053eafbbaccc087ffd2bafb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:40:00 +0200 Subject: [PATCH 286/508] Jan/full check 11 (#5960) ### What ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index c45c352a38b4..fe763f4cbf9b 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -51,11 +51,11 @@ jobs: local created_after=$3 echo $( # https://cli.github.com/manual/gh_run_list + # https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates gh run list \ --workflow $workflow_name \ --event workflow_dispatch \ --branch $ref_name \ - # https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates --created ">$created_after" \ --json databaseId ) From 9f3c45dd5c8353b9682b4e3de7ad937252c6720d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:46:22 +0200 Subject: [PATCH 287/508] Jan/full check 12 (#5961) ### What Set job concurrency to something other than what's used on `main`, and compare against `null` in run id fetch loop ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 6 ++++-- .github/workflows/on_push_main.yml | 32 ++++++++++++++++------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index fe763f4cbf9b..78d5414a3806 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -64,12 +64,14 @@ jobs: dispatch_workflow () { local workflow_name=$1 local ref_name=$2 + local inputs=$3 # https://cli.github.com/manual/gh_workflow_run - gh workflow run $workflow_name --ref "refs/heads/$ref_name" + echo $inputs | gh workflow run $workflow_name --ref "refs/heads/$ref_name" } workflow_name='on_push_main.yml' ref_name=$(gh pr view ${{ github.event.issue.number }} --json headRefName | jq -r '.headRefName') + inputs='{"CONCURRENCY": "pr-${{ github.event.issue.number }}-full-check"}' now=$(date --utc --iso-8601=seconds) echo "Dispatching workflow $workflow_name on branch $ref_name" @@ -84,7 +86,7 @@ jobs: run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) echo $run_info run_id=$(echo $run_info | jq -r '.[0].databaseId') - while [ -z $run_id ] + while [ $run_id == 'null' ] do run_info=$(get_latest_workflow_run $workflow_name $ref_name $now) echo $run_info diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 9d39be4101b1..f32485d92859 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -8,20 +8,24 @@ on: # Can be triggered manually from within the UI or using the GH CLI, # e.g. `gh workflow run on_push_main.yml --ref main` workflow_dispatch: + inputs: + CONCURRENCY: + required: true + type: string jobs: checks: name: Checks uses: ./.github/workflows/reusable_checks.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} secrets: inherit cpp_checks: name: Checks uses: ./.github/workflows/reusable_checks_cpp.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} FULL: "true" secrets: inherit @@ -29,7 +33,7 @@ jobs: name: Checks uses: ./.github/workflows/reusable_checks_rust.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} CHANNEL: main secrets: inherit @@ -37,7 +41,7 @@ jobs: name: Checks uses: ./.github/workflows/reusable_checks_python.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} secrets: inherit deploy-docs: @@ -45,7 +49,7 @@ jobs: name: Deploy Docs uses: ./.github/workflows/reusable_deploy_docs.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} PY_DOCS_VERSION_NAME: "main" CPP_DOCS_VERSION_NAME: "main" RS_DOCS_VERSION_NAME: "head" @@ -56,7 +60,7 @@ jobs: name: "Build web viewer" uses: ./.github/workflows/reusable_build_web.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} CHANNEL: main secrets: inherit @@ -65,7 +69,7 @@ jobs: needs: [build-web] uses: ./.github/workflows/reusable_upload_web.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} secrets: inherit build-examples: @@ -73,7 +77,7 @@ jobs: needs: [build-wheel-linux-x64] uses: ./.github/workflows/reusable_build_examples.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} CHANNEL: main WHEEL_ARTIFACT_NAME: linux-x64-wheel secrets: inherit @@ -83,7 +87,7 @@ jobs: needs: [build-web, build-examples] uses: ./.github/workflows/reusable_track_size.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} WITH_EXAMPLES: true secrets: inherit @@ -92,7 +96,7 @@ jobs: needs: [build-examples] uses: ./.github/workflows/reusable_upload_examples.yml with: - CONCURRENCY: push-${{ github.ref_name }} + CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} secrets: inherit # ----------------------------------------------------------------------------------- @@ -103,7 +107,7 @@ jobs: name: "Linux-x64: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: push-linux-x64-${{ github.ref_name }} + CONCURRENCY: push-linux-x64-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} PLATFORM: linux-x64 secrets: inherit @@ -115,7 +119,7 @@ jobs: name: "Linux-x64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: push-linux-x64-${{ github.ref_name }} + CONCURRENCY: push-linux-x64-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} PLATFORM: linux-x64 secrets: inherit @@ -127,7 +131,7 @@ jobs: name: "Linux-x64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: push-linux-x64-${{ github.ref_name }} + CONCURRENCY: push-linux-x64-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} PLATFORM: linux-x64 WHEEL_ARTIFACT_NAME: linux-x64-wheel MODE: "pypi" @@ -138,7 +142,7 @@ jobs: name: "Linux-x64: Test Wheels" uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: push-linux-x64-${{ github.ref_name }} + CONCURRENCY: push-linux-x64-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} PLATFORM: linux-x64 WHEEL_ARTIFACT_NAME: linux-x64-wheel secrets: inherit From 2f25be38e5bc85b55c306da7c4714368952d2d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:48:28 +0200 Subject: [PATCH 288/508] Jan/full check 13 (#5962) ### What Typo in `input` variable, should've been `inputs` ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 78d5414a3806..58ae764eb749 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -75,7 +75,7 @@ jobs: now=$(date --utc --iso-8601=seconds) echo "Dispatching workflow $workflow_name on branch $ref_name" - dispatch_workflow $workflow_name $ref_name $input + dispatch_workflow $workflow_name $ref_name $inputs # `gh workflow run` does NOT return the ID. # In fact, it returns absolutely nothing: https://github.com/cli/cli/issues/4001 From 502cbb9579dd687145bbc4d4c7272b835d183342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:51:26 +0200 Subject: [PATCH 289/508] Jan/full check 14 (#5963) ### What `gh workflow run` reads JSON input from stdin only if `--json` flag is passed in, and it was not ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 58ae764eb749..8a4262aa7920 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -66,7 +66,7 @@ jobs: local ref_name=$2 local inputs=$3 # https://cli.github.com/manual/gh_workflow_run - echo $inputs | gh workflow run $workflow_name --ref "refs/heads/$ref_name" + echo $inputs | gh workflow run $workflow_name --ref "refs/heads/$ref_name" --json } workflow_name='on_push_main.yml' From 1fa245598d13d7dd76f1703ec7e226ed2238b374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 12 Apr 2024 14:58:28 +0200 Subject: [PATCH 290/508] Jan/full check 15 (#5964) ### What A space in JSON inputs was causing `echo` to only print half of it ### Checklist * [ ] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pr_comment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml index 8a4262aa7920..0734c65d7b62 100644 --- a/.github/workflows/on_pr_comment.yml +++ b/.github/workflows/on_pr_comment.yml @@ -71,7 +71,7 @@ jobs: workflow_name='on_push_main.yml' ref_name=$(gh pr view ${{ github.event.issue.number }} --json headRefName | jq -r '.headRefName') - inputs='{"CONCURRENCY": "pr-${{ github.event.issue.number }}-full-check"}' + inputs='{"CONCURRENCY":"pr-${{ github.event.issue.number }}-full-check"}' now=$(date --utc --iso-8601=seconds) echo "Dispatching workflow $workflow_name on branch $ref_name" From d90ed2f7ee3021353b953b1cd760ca3848b18a48 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 12 Apr 2024 21:00:55 +0200 Subject: [PATCH 291/508] Install & cache needed pixi environments on ci (#5958) ### What Before we'd only cache the default environment. Now, jobs install & cache the needed environments ahead of time. see https://github.com/marketplace/actions/setup-pixi#caching ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5958?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5958?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5958) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/auto_approve.yml | 2 +- .github/workflows/auto_release_crates.yml | 2 +- .github/workflows/checkboxes.yml | 2 +- .github/workflows/contrib_checks.yml | 12 +++++++----- .github/workflows/contrib_rerun_py.yml | 3 ++- .github/workflows/on_pull_request_target_contrib.yml | 2 +- .github/workflows/release.yml | 4 ++-- .../reusable_build_and_upload_rerun_cli.yml | 2 +- .../workflows/reusable_build_and_upload_wheels.yml | 2 +- .github/workflows/reusable_build_examples.yml | 3 ++- .github/workflows/reusable_build_web.yml | 2 +- .github/workflows/reusable_checks.yml | 9 +++++---- .github/workflows/reusable_checks_cpp.yml | 3 ++- .github/workflows/reusable_checks_python.yml | 5 +++-- .github/workflows/reusable_checks_rust.yml | 2 +- .github/workflows/reusable_deploy_docs.yml | 5 +++-- .github/workflows/reusable_pr_summary.yml | 2 +- .github/workflows/reusable_publish_web.yml | 3 ++- .github/workflows/reusable_publish_wheels.yml | 2 +- .github/workflows/reusable_release_crates.yml | 2 +- .github/workflows/reusable_sync_release_assets.yml | 2 +- .github/workflows/reusable_test_wheels.yml | 3 ++- .github/workflows/reusable_update_pr_body.yml | 2 +- 23 files changed, 43 insertions(+), 33 deletions(-) diff --git a/.github/workflows/auto_approve.yml b/.github/workflows/auto_approve.yml index d02aef9751fc..fa7fe8c80b9c 100644 --- a/.github/workflows/auto_approve.yml +++ b/.github/workflows/auto_approve.yml @@ -20,7 +20,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.18.0 diff --git a/.github/workflows/auto_release_crates.yml b/.github/workflows/auto_release_crates.yml index 506f748f84af..9ffec72f680f 100644 --- a/.github/workflows/auto_release_crates.yml +++ b/.github/workflows/auto_release_crates.yml @@ -20,7 +20,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/checkboxes.yml b/.github/workflows/checkboxes.yml index 75af8364585f..f229de7a768f 100644 --- a/.github/workflows/checkboxes.yml +++ b/.github/workflows/checkboxes.yml @@ -28,7 +28,7 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.18.0 diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 06cd6b8fd4ed..b354144937f5 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -46,7 +46,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 @@ -62,9 +62,10 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: py-docs - name: Build via mkdocs run: pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml @@ -78,7 +79,7 @@ jobs: # PR introduces a new type and another PR changes the codegen. - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 @@ -102,7 +103,7 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 @@ -154,9 +155,10 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: cpp # TODO(emilk): make this work somehow. Right now this just results in # > Compiler: GNU 12.3.0 (/__w/rerun/rerun/.pixi/env/bin/x86_64-conda-linux-gnu-c++) diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 1bcb5feb8e2d..5fb22ddb4281 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -52,9 +52,10 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: wheel-test - name: Build Wheel uses: PyO3/maturin-action@v1 diff --git a/.github/workflows/on_pull_request_target_contrib.yml b/.github/workflows/on_pull_request_target_contrib.yml index e21c460d3245..23fb8a59a5b9 100644 --- a/.github/workflows/on_pull_request_target_contrib.yml +++ b/.github/workflows/on_pull_request_target_contrib.yml @@ -23,7 +23,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4a1bc770da1f..9487b8e3dc97 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,7 +78,7 @@ jobs: with: node-version: 18 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 @@ -375,7 +375,7 @@ jobs: with: node-version: 18 - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index 89113325da81..a06ab82946c5 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -161,7 +161,7 @@ jobs: service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} targets: ${{ needs.set-config.outputs.TARGET }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 124b22e78b83..9ee496f844aa 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -186,7 +186,7 @@ jobs: service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} targets: ${{ needs.set-config.outputs.TARGET }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index ac96673d5d78..2f122bed33b7 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -59,9 +59,10 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: wheel-test - name: Download Wheel uses: actions/download-artifact@v4 diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 78072007e8b6..34127757b4f5 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -61,7 +61,7 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index a7938760cfc3..6164351afa91 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -45,9 +45,10 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: py-docs - name: Build via mkdocs run: pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml @@ -71,7 +72,7 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 @@ -90,7 +91,7 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 @@ -145,7 +146,7 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index 3359358776bc..125fc56eebfe 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -75,9 +75,10 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: cpp - name: Set up Rust uses: ./.github/actions/setup-rust diff --git a/.github/workflows/reusable_checks_python.yml b/.github/workflows/reusable_checks_python.yml index 1b5e232d4d87..2a682ba610a3 100644 --- a/.github/workflows/reusable_checks_python.yml +++ b/.github/workflows/reusable_checks_python.yml @@ -29,7 +29,7 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 @@ -49,9 +49,10 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: py-docs - name: Build via mkdocs shell: bash diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 0e11da44adab..1fe8ade91dbd 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -58,7 +58,7 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index 5948e0636ec8..e7e14ca988c0 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -68,9 +68,10 @@ jobs: fetch-depth: 0 # Don't do a shallow clone ref: ${{ inputs.RELEASE_COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || '') }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: py-docs - name: Set up git author shell: bash @@ -202,7 +203,7 @@ jobs: fetch-depth: 0 # Don't do a shallow clone since we need to push gh-pages ref: ${{ inputs.RELEASE_COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || '') }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_pr_summary.yml b/.github/workflows/reusable_pr_summary.yml index 89affe31959c..34e4b0853d1e 100644 --- a/.github/workflows/reusable_pr_summary.yml +++ b/.github/workflows/reusable_pr_summary.yml @@ -31,7 +31,7 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.18.0 diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index b65de3d61701..f6078aaa7911 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -72,9 +72,10 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: wheel-test # built by `reusable_build_and_publish_wheels` - name: Download Wheel diff --git a/.github/workflows/reusable_publish_wheels.yml b/.github/workflows/reusable_publish_wheels.yml index efe874a58ddc..8b87e372c091 100644 --- a/.github/workflows/reusable_publish_wheels.yml +++ b/.github/workflows/reusable_publish_wheels.yml @@ -151,7 +151,7 @@ jobs: fetch-depth: 0 # Don't do a shallow clone since we need it for finding the full commit hash ref: ${{ inputs.release-commit }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml index 714ea4683917..669e1fc12f0f 100644 --- a/.github/workflows/reusable_release_crates.yml +++ b/.github/workflows/reusable_release_crates.yml @@ -24,7 +24,7 @@ jobs: with: ref: ${{ inputs.RELEASE_COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || '') }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 diff --git a/.github/workflows/reusable_sync_release_assets.yml b/.github/workflows/reusable_sync_release_assets.yml index a6d86782ebd8..ba0623ef2b7d 100644 --- a/.github/workflows/reusable_sync_release_assets.yml +++ b/.github/workflows/reusable_sync_release_assets.yml @@ -35,7 +35,7 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.18.0 diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index f8d9f0fc376b..07b46e6274a1 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -143,9 +143,10 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.19.0 + environments: wheel-test - name: Download Wheel uses: actions/download-artifact@v4 diff --git a/.github/workflows/reusable_update_pr_body.yml b/.github/workflows/reusable_update_pr_body.yml index 28dd3df4cb4e..c1dda64c893d 100644 --- a/.github/workflows/reusable_update_pr_body.yml +++ b/.github/workflows/reusable_update_pr_body.yml @@ -31,7 +31,7 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.4.1 + - uses: prefix-dev/setup-pixi@v0.5.2 with: pixi-version: v0.18.0 From e8d39d7a9b3672c6df58268bde171e85476b0942 Mon Sep 17 00:00:00 2001 From: Nikolaus West Date: Mon, 15 Apr 2024 08:57:11 +0200 Subject: [PATCH 292/508] Move "What is Rerun for?" to it's own page (#5965) Also includes some copy tweaks. ![Screenshot 2024-04-12 at 15 37 46](https://github.com/rerun-io/rerun/assets/2624717/0f80b16c-a949-4ffb-a800-6a802203f819) --------- Co-authored-by: Clement Rey --- .gitignore | 2 ++ .../getting-started/configure-the-viewer.md | 2 +- docs/content/getting-started/data-in.md | 2 +- .../getting-started/installing-viewer.md | 2 +- .../getting-started/navigating-the-viewer.md | 2 +- docs/content/getting-started/quick-start.md | 2 +- .../getting-started/troubleshooting.md | 2 +- .../getting-started/what-is-rerun-for.md | 30 +++++++++++++++++++ docs/content/getting-started/what-is-rerun.md | 27 ----------------- 9 files changed, 38 insertions(+), 33 deletions(-) create mode 100644 docs/content/getting-started/what-is-rerun-for.md diff --git a/.gitignore b/.gitignore index e0171fa38d5a..e32ceb08f5ac 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,5 @@ wheels *.rrd /meilisearch + +.pixi/* diff --git a/docs/content/getting-started/configure-the-viewer.md b/docs/content/getting-started/configure-the-viewer.md index 21fc71ae590d..28425ffba7ce 100644 --- a/docs/content/getting-started/configure-the-viewer.md +++ b/docs/content/getting-started/configure-the-viewer.md @@ -1,6 +1,6 @@ --- title: Configure the viewer -order: 5 +order: 600 --- By default, the Rerun viewer uses heuristics to automatically determine an appropriate diff --git a/docs/content/getting-started/data-in.md b/docs/content/getting-started/data-in.md index a7ea02f8b6ed..2154d5d49610 100644 --- a/docs/content/getting-started/data-in.md +++ b/docs/content/getting-started/data-in.md @@ -1,6 +1,6 @@ --- title: Get data into Rerun -order: 3 +order: 400 --- This section talks about how to get data out of your application into Rerun. diff --git a/docs/content/getting-started/installing-viewer.md b/docs/content/getting-started/installing-viewer.md index 807dba0f026c..c9be59b52578 100644 --- a/docs/content/getting-started/installing-viewer.md +++ b/docs/content/getting-started/installing-viewer.md @@ -1,6 +1,6 @@ --- title: Installing Rerun -order: 2 +order: 300 --- ## Installing the SDK diff --git a/docs/content/getting-started/navigating-the-viewer.md b/docs/content/getting-started/navigating-the-viewer.md index f3f7fbfe2390..080e41865d46 100644 --- a/docs/content/getting-started/navigating-the-viewer.md +++ b/docs/content/getting-started/navigating-the-viewer.md @@ -1,6 +1,6 @@ --- title: Navigating the viewer -order: 4 +order: 500 --- This guide will familiarize you with the basics of using the Rerun Viewer with an example dataset. By the end you should diff --git a/docs/content/getting-started/quick-start.md b/docs/content/getting-started/quick-start.md index 378e620051bb..ee1083987d32 100644 --- a/docs/content/getting-started/quick-start.md +++ b/docs/content/getting-started/quick-start.md @@ -1,6 +1,6 @@ --- title: Quick start -order: 1 +order: 200 --- Rerun is an SDK and engine for visualizing and interacting with multimodal data diff --git a/docs/content/getting-started/troubleshooting.md b/docs/content/getting-started/troubleshooting.md index 212b5435e46e..8e522853951a 100644 --- a/docs/content/getting-started/troubleshooting.md +++ b/docs/content/getting-started/troubleshooting.md @@ -1,6 +1,6 @@ --- title: Troubleshooting -order: 5 +order: 600 --- You can set `RUST_LOG=debug` before running to get some verbose logging output. diff --git a/docs/content/getting-started/what-is-rerun-for.md b/docs/content/getting-started/what-is-rerun-for.md new file mode 100644 index 000000000000..cf72c44fd461 --- /dev/null +++ b/docs/content/getting-started/what-is-rerun-for.md @@ -0,0 +1,30 @@ +--- +title: What is Rerun for? +order: 100 +--- + +Rerun is built to help you understand complex processes that include rich multimodal data, like 2D, 3D, text, time series, tensors, etc. +It is used in many industries, including robotics, simulation, computer vision, +or anything that involves a lot of sensors or other signals that evolve over time. + +### Example use case +Say you're building a vacuum cleaning robot and it keeps running into walls. Why is it doing that? You need some tool to debug it, but a normal debugger isn't gonna be helpful. Similarly, just logging text won't be very helpful either. The robot may log "Going through doorway" but that won't explain why it thinks the wall is a door. + +What you need is a visual and temporal debugger, that can log all the different representations of the world the robots holds in its little head, such as: + +* RGB camera feed +* depth images +* lidar scan +* segmentation image (how the robot interprets what it sees) +* its 3D map of the apartment +* all the objects the robot has detected (or thinks it has detected), as 3D shapes in the 3D map +* its confidence in its prediction +* etc + +You also want to see how all these streams of data evolve over time so you can go back and pinpoint exactly what went wrong, when and why. + +Maybe it turns out that a glare from the sun hit one of the sensors in the wrong way, confusing the segmentation network leading to bad object detection. Or maybe it was a bug in the lidar scanning code. Or maybe the robot thought it was somewhere else in the apartment, because its odometry was broken. Or it could be one of a thousand other things. Rerun will help you find out! + +But seeing the world from the point of the view of the robot is not just for debugging - it will also give you ideas on how to improve the algorithms, new test cases to set up, or datasets to collect. It will also let you explain the brains of the robot to your colleagues, boss, and customers. And so on. Seeing is believing, and an image is worth a thousand words, and multimodal temporal logging is worth a thousand images :) + +Of course, Rerun is useful for much more than just robots. Any time you have any form of sensors, or 2D or 3D state evolving over time, Rerun would be a great tool. diff --git a/docs/content/getting-started/what-is-rerun.md b/docs/content/getting-started/what-is-rerun.md index ddda4cd3c52b..26d8fa87b848 100644 --- a/docs/content/getting-started/what-is-rerun.md +++ b/docs/content/getting-started/what-is-rerun.md @@ -38,33 +38,6 @@ That's a big question for a welcome page. The short answer is that Rerun goes to extreme lengths to make handling and visualizing multimodal data streams easy and performant. -## What is Rerun for? -Rerun is built to help you understand complex processes that include rich multimodal data, including 2D, 3D, text, time series, tensors, etc. -It is used in many industries, including robotics, simulation, computer vision, or anything that involves a lot of sensors. -Let's look at a more concrete example: - -### Example use case -Say you're building a vacuum cleaning robot and it keeps running into walls. Why is it doing that? You need some tool to debug it, but a normal debugger isn't gonna be helpful. Similarly, just logging text won't be very helpful either. The robot may log "Going through doorway" but that won't explain why it thinks the wall is a door. - -What you need is a visual and temporal debugger, that can log all the different representations of the world the robots holds in its little head, such as: - -* RGB camera feed -* depth images -* lidar scan -* segmentation image (how the robot interprets what it sees) -* its 3D map of the apartment -* all the objects the robot has detected (or thinks it has detected), as 3D shapes in the 3D map -* its confidence in its prediction -* etc - -You also want to see how all these streams of data evolve over time so you can go back and pinpoint exactly what went wrong, when and why. - -Maybe it turns out that a glare from the sun hit one of the sensors in the wrong way, confusing the segmentation network leading to bad object detection. Or maybe it was a bug in the lidar scanning code. Or maybe the robot thought it were somewhere else in the apartment, because its odometry was broken. Or it could be one of a thousand other things. Rerun will help you find out! - -But seeing the world from the point of the view of the robot is not just for debugging - it will also give you ideas on how to improve the algorithms. It will also let you explain the brains of the robot to your colleagues, boss, and customers. And so on. Seeing is believing, and an image is worth a thousand words, and multimodal temporal logging is worth a thousand images :) - -Of course, Rerun is useful for much more than just robots. Any time you have any for of sensors, or 2D or 3D state evolving over time, Rerun would be a great tool. - ## Can't find what you're looking for? - Join us in the [Rerun Community Discord](https://discord.gg/xwcxHUjD35) From 0e4b2139c8512cf18f5ac7c22aeba1ba7fd5242f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Mon, 15 Apr 2024 09:22:46 +0200 Subject: [PATCH 293/508] Fix nightly (#5970) ### What - Closes https://github.com/rerun-io/rerun/issues/5945 Concurrency was setup incorrectly, causing all the build jobs to be cancelled. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/nightly.yml | 44 ++++++++++--------- .../reusable_bundle_and_upload_rerun_cpp.yml | 7 +++ .../workflows/reusable_publish_rerun_c.yml | 1 + .github/workflows/reusable_test_wheels.yml | 2 +- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index ebe2131654e7..ffd5d04334aa 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -79,7 +79,7 @@ jobs: name: "Linux-arm64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-linux-arm64 PLATFORM: linux-arm64 WHEEL_ARTIFACT_NAME: linux-arm64-wheel MODE: "pypi" @@ -90,7 +90,7 @@ jobs: name: "Linux-x64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-linux-x64 PLATFORM: linux-x64 WHEEL_ARTIFACT_NAME: linux-x64-wheel MODE: "pypi" @@ -101,7 +101,7 @@ jobs: name: "Macos-arm64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-macos-arm64 PLATFORM: macos-arm64 WHEEL_ARTIFACT_NAME: macos-arm64-wheel MODE: "pypi" @@ -112,7 +112,7 @@ jobs: name: "Macos-x64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-macos-x64 PLATFORM: macos-x64 WHEEL_ARTIFACT_NAME: "macos-x64-wheel" MODE: "pypi" @@ -123,7 +123,7 @@ jobs: name: "Windows-x64: Build & Upload Wheels" uses: ./.github/workflows/reusable_build_and_upload_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-windows-x64 PLATFORM: windows-x64 WHEEL_ARTIFACT_NAME: windows-x64-wheel MODE: "pypi" @@ -137,7 +137,7 @@ jobs: name: "linux-arm64: Test Wheels" uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-linux-arm64 PLATFORM: linux-arm64 WHEEL_ARTIFACT_NAME: linux-arm64-wheel secrets: inherit @@ -147,7 +147,7 @@ jobs: name: "Linux-x64: Test Wheels" uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-linux-x64 PLATFORM: linux-x64 WHEEL_ARTIFACT_NAME: linux-x64-wheel secrets: inherit @@ -157,7 +157,7 @@ jobs: name: "macos-arm64: Test Wheels" uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-macos-arm64 PLATFORM: macos-arm64 WHEEL_ARTIFACT_NAME: macos-arm64-wheel secrets: inherit @@ -167,7 +167,7 @@ jobs: name: "macos-x64: Test Wheels" uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-macos-x64 PLATFORM: macos-x64 WHEEL_ARTIFACT_NAME: macos-x64-wheel secrets: inherit @@ -177,7 +177,7 @@ jobs: name: "Windows-x64: Test Wheels" uses: ./.github/workflows/reusable_test_wheels.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-windows-x64 PLATFORM: windows-x64 WHEEL_ARTIFACT_NAME: windows-x64-wheel secrets: inherit @@ -190,7 +190,7 @@ jobs: name: "Linux-Arm64: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-linux-arm64 PLATFORM: linux-arm64 secrets: inherit @@ -199,7 +199,7 @@ jobs: name: "Linux-x64: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-linux-x64 PLATFORM: linux-x64 secrets: inherit @@ -208,7 +208,7 @@ jobs: name: "Mac-Intel: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-macos-x64 PLATFORM: macos-x64 secrets: inherit @@ -217,7 +217,7 @@ jobs: name: "Mac-Arm64: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-macos-arm64 PLATFORM: macos-arm64 secrets: inherit @@ -226,7 +226,7 @@ jobs: name: "Windows-x64: Build & Upload rerun_c" uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-windows-x64 PLATFORM: windows-x64 secrets: inherit @@ -239,7 +239,7 @@ jobs: name: "Linux-arm64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-linux-arm64 PLATFORM: linux-arm64 secrets: inherit @@ -248,7 +248,7 @@ jobs: name: "Linux-x64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-linux-x64 PLATFORM: linux-x64 secrets: inherit @@ -257,7 +257,7 @@ jobs: name: "Mac-x64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-macos-x64 PLATFORM: macos-x64 secrets: inherit @@ -266,7 +266,7 @@ jobs: name: "Mac-arm64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-macos-arm64 PLATFORM: macos-arm64 secrets: inherit @@ -275,7 +275,7 @@ jobs: name: "Windows-x64: Build & Upload rerun-cli" uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml with: - CONCURRENCY: nightly + CONCURRENCY: nightly-windows-x64 PLATFORM: windows-x64 secrets: inherit @@ -348,11 +348,13 @@ jobs: build-rerun_c-and-upload-windows-x64, ] uses: ./.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml + with: + CONCURRENCY: nightly secrets: inherit pre-release: name: Pre Release - concurrency: NIGHTLY + concurrency: nightly needs: [ build-rerun-cli-and-upload-linux-arm64, diff --git a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml index 9040104db517..ca531b4e0a30 100644 --- a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml +++ b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml @@ -3,6 +3,9 @@ name: Reusable C++ bundling and upload on: workflow_call: inputs: + CONCURRENCY: + required: true + type: string PLATFORM_FILTER: required: false type: string @@ -11,6 +14,10 @@ on: type: string default: "" +concurrency: + group: ${{ inputs.CONCURRENCY }}-bundle-and-upload-rerun-cpp + cancel-in-progress: true + jobs: bundle-and-upload-rerun_cpp: name: Bundle and upload rerun_cpp_sdk.zip diff --git a/.github/workflows/reusable_publish_rerun_c.yml b/.github/workflows/reusable_publish_rerun_c.yml index 423d299f1d14..e4ce79b3cff5 100644 --- a/.github/workflows/reusable_publish_rerun_c.yml +++ b/.github/workflows/reusable_publish_rerun_c.yml @@ -66,5 +66,6 @@ jobs: needs: [linux-arm64, linux-x64, macos-x64, macos-arm64, windows-x64] uses: ./.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml with: + CONCURRENCY: bundle-rerun-c-${{ github.ref_name }} RELEASE_COMMIT: ${{ inputs.release-commit }} secrets: inherit diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 07b46e6274a1..fa8702f0d976 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -23,7 +23,7 @@ on: default: false concurrency: - group: ${{ inputs.CONCURRENCY }}-build-wheels + group: ${{ inputs.CONCURRENCY }}-test-wheels cancel-in-progress: true env: From 8aed31000717f73e3f4bbbcfbeddadbfefa4d522 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 15 Apr 2024 10:30:43 +0200 Subject: [PATCH 294/508] Replace linkinator with lychee (#5969) ### What Use https://github.com/lycheeverse/lychee instead of Linkinator and fix a bunch of links. Advantages of lychee: * can run locally easily, config is an easy to read file and not on the ci job * finds a bunch of links linkinator missed * caches successful links for a while Unfortunately, there's no conda package, so I couldn't make this a pixi task. But this is rarely needed to run locally and the install instructions are simple. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5969?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5969?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5969) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/pull_request_template.md | 2 +- .github/workflows/README.md | 62 --- .github/workflows/documentation.yaml | 37 -- .github/workflows/reusable_checks.yml | 24 + CHANGELOG.md | 2 +- CONTRIBUTING.md | 2 +- examples/rust/revy/README.md | 2 - lychee.toml | 60 +++ pixi.lock | 656 +++++++++++++++++--------- 9 files changed, 528 insertions(+), 319 deletions(-) delete mode 100644 .github/workflows/documentation.yaml create mode 100644 lychee.toml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 30c0224982e0..7907c312282b 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -21,7 +21,7 @@ To get an auto-generated PR description you can put "copilot:summary" or "copilo * [ ] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! -- [PR Build Summary](https://build.rerun.io/pr/{{ pr.number }}) +- [PR Build Summary](https://build.rerun.io/pr/{{pr.number}}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 101f9415afb7..deb5a77c0565 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -14,65 +14,3 @@ By convention: If you are going to be doing any editing of workflows, the [VS Code extension](https://marketplace.visualstudio.com/items?itemName=cschleiden.vscode-github-actions) for GitHub Actions is highly recommended. - -## Reusable workflows - -- [reusable_checks.yml](reusable_checks.yml) - These are all the checks that run to ensure the code is formatted, - linted, and tested. This job produces no artifacts other than a pass/fail criteria for the build. - - `SAVE_CACHE` - If true, the rust cache will be saved. Generally we only do this for builds on `main` -- [reusable_bench.yml](reusable_bench.yml) - This job runs the benchmarks to check for performance regressions. - - `SAVE_BENCH` - If true, then the benchmark results are saved to update https://ref.rerun.io/dev/bench/ -- [reusable_deploy_docs](reusable_deploy_docs.yml) - This job deploys the python and rust documentation to https://ref.rerun.io - - `PY_AND_CPP_DOCS_VERSION_NAME` - The name to use for versioning the python docs. This should generally match the version in - `Cargo.toml`. - - `UPDATE_LATEST` - If true, then the docs will be deployed to `latest/` as well as the versioned directory. -- [reusable_build_and_test_wheels.yml](reusable_build_and_test_wheels.yml) - This job builds the wheels, runs the - end-to-end test, and produces a sample RRD. The artifacts are accessible via GitHub artifacts, but not otherwise - uploaded anywhere. - - `MATURIN_FEATURE_FLAGS` - The feature flags to pass to maturin. - - `PLATFORM` - Which platform to build for: `linux-arm64`, `linux-x64`, `macos-arm64`, `macos-x64`, or `windows-x64`. - - `RELEASE_VERSION` - If producing a release, the version number. This must match the version in `Cargo.toml`. - - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact for passing to `reusable_upload_wheels.yml` - - `SAVE_CACHE` - If true, the rust cache will be saved. Generally we only do this for builds on `main` - - `WHEEL_ARTIFACT_NAME` - Intermediate name of the GitHub wheel artifact for passing to `reusable_upload_wheels.yml` -- [reusable_upload_wheels.yml](reusable_upload_wheels.yml) - This job uploads the wheels to google cloud - - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact. This should match the name passed to - `reusable_build_and_test_wheels.yml` - - `WHEEL_ARTIFACT_NAME` - Intermediate name of the GitHub wheel artifact. This should match the name passed to - `reusable_build_and_test_wheels.yml` -- [reusable_build_web.yml](reusable_build_web.yml) - This job builds the wasm artifacts for the web. - - `RELEASE_VERSION` - If producing a release, the version number. This must match the version in `Cargo.toml`. -- [reusable_upload_web.yml](reusable_upload_web.yml) - This job uploads the web assets to google cloud. By default this - only uploads to: `app.rerun.io/commit//` - - `MARK_TAGGED_VERSION` - If true, then the web assets will go to `app.rerun.io/version/` - - `RELEASE_VERSION` - If producing a release, the version number. - - `RRD_ARTIFACT_NAME` - Intermediate name of the GitHub rrd artifact. This should match the name passed to - `reusable_build_and_test_wheels.yml` - - `UPLOAD_COMMIT_OVERRIDE` - If set, will replace the value of ``. This is necessary because we want pull - request builds associated with their originating commit, even if the web-build happens on an ephemeral merge-commit. -- [reusable_build_web_demo.yml](reusable_build_web.yml) - This job builds the assets uploaded to `demo.rerun.io`. - - `SOURCE_LINK_COMMIT_OVERRIDE` - If set, will replace the value of `` in the built app. This ensures that the - source code link in the built app always points to the pull request's `HEAD`. -- [reusable_upload_web_demo.yml](reusable_upload_web_demo.yml) - This job uploads the `demo.rerun.io` assets to google cloud. By default this - only uploads to: `demo.rerun.io/commit//` - - `MARK_TAGGED_VERSION` - If true, then the web assets will go to `demo.rerun.io/version/` - - `RELEASE_VERSION` - If producing a release, the version number. - - `UPLOAD_COMMIT_OVERRIDE` - If set, will replace the value of ``. This is necessary because we want pull - request builds associated with their originating commit, even if the web-build happens on an ephemeral merge-commit. - - `PR_NUMBER` - If set, will upload `demo.rerun.io/pr/` -- [reusable_pr_summary.yml](reusable_pr_summary.yml) - This job updates the PR summary with the results of the CI run. - - This summary can be found at: - `https://build.rerun.io/pr//` - - `PR_NUMBER` - The PR number to update. This will generally be set by the `on_pull_request.yml` workflow using: - `${{github.event.pull_request.number}}` - -## Manual workflows - -- [manual_dispatch](manual_dispatch.yml) - This workflow is used to manually trigger the assorted reusable workflows for - testing. - - See the workflow file for the list of parameters. -- [manual_build_wheels_for_pr.yml](manual_build_wheels_for_pr.yml) - This workflow can be dispatched on a branch and - will build all of the wheels for the associated pull-request. Uses: - - [reusable_build_and_test_wheels.yml](reusable_build_and_test_wheels.yml) - - [reusable_upload_wheels.yml](reusable_upload_wheels.yml) - - [reusable_pr_summary.yml](reusable_pr_summary.yml) diff --git a/.github/workflows/documentation.yaml b/.github/workflows/documentation.yaml deleted file mode 100644 index 15e45e8a28df..000000000000 --- a/.github/workflows/documentation.yaml +++ /dev/null @@ -1,37 +0,0 @@ -name: Dead links check - -on: - pull_request: - push: - branches: - - "main" - -permissions: - contents: read - -jobs: - linkinator: - name: linkinator - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: jprochazk/linkinator-action@main - with: - # This list of file extensions matches the one in `scripts/lint.py`, except .html is omitted due to relative links. - paths: "**/*.c, **/*.cpp, **/*.fbs, **/*.h, **/*.hpp, **/*.js, **/*.md, **/*.py, **/*.rs, **/*.sh, **/*.toml, **/*.txt, **/*.wgsl, **/*.yml" - - # Exceptions: - # * avoid crates.io rate-limiting - # * skip changelog PR links (so many) - # * skip speculative links - # * Stackoverflow links are no longer accessible from CI. - # * Tuxfamily.org links are down intermittently. - # * Nyud links are down every now and then. - # * tensorflow.org apparently blocks CI. - # * TODO(#4085): https://rerun-io.github.io/rerun/dev/bench/ often 404:s for unknown reasons - # * TODO(#4556): remove the `static.rerun.io` and `github.com` skips - linksToSkip: "https://stackoverflow.com/.*, https://eigen.tuxfamily.org/, https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html, https://static.rerun.io/.*, https://github.com/.*, https://crates.io/crates/.*, https://github.com/rerun-io/rerun/pull/.*, .*?speculative-link, https://rerun-io.github.io/rerun/dev/bench/, https://www.tensorflow.org/" - retry: true - retryErrors: true - retryErrorsCount: 5 - retryErrorsJitter: 2000 diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 6164351afa91..9b663e1d1bfc 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -152,3 +152,27 @@ jobs: - name: prettier --check run: pixi run misc-fmt-check + + # --------------------------------------------------------------------------- + + link-checker: + name: Check links + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Restore link checker cache + uses: actions/cache@v3 + with: + path: .lycheecache + key: cache-lychee-${{ github.sha }} + restore-keys: cache-lychee- + + # Check https://github.com/lycheeverse/lychee on how to run locally. + - name: Link Checker + id: lychee + uses: lycheeverse/lychee-action@v1.9.0 + with: + fail: true + lycheeVersion: "0.14.3" + args: "--base . --cache --max-cache-age 1d ." diff --git a/CHANGELOG.md b/CHANGELOG.md index 91396c6d046d..fa45b432acdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -229,7 +229,7 @@ We're still ramping up for programmable blueprints (soon!), but meanwhile enjoy - 🔺 Built-in STL mesh support. - 🎥 First-person camera. - 🐛 Fixes regressions in Space View spawn heuristics from 0.13, and many more bugfixes. -- 🧑‍🏫 Two new examples: [Gesture Recognition](https://github.com/rerun-io/rerun/tree/release-0.14.0/examples/python/gesture_detection) & [RRT* Pathfinding](https://github.com/rerun-io/rerun/tree/release-0.14.0/examples/python/rrt-star) +- 🧑‍🏫 Two new examples: [Gesture Recognition](https://github.com/rerun-io/rerun/tree/0.14.0/examples/python/gesture_detection) & [RRT* Pathfinding](https://github.com/rerun-io/rerun/tree/0.14.0/examples/python/rrt-star) ### 🔎 Details ### 🔎 Details diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f51c579b1d7..80b948e92cec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,7 @@ We use [Trunk Based Development](https://trunkbaseddevelopment.com/), which mean All PR:s are merged with [`Squash and Merge`](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-commits), meaning they all get squashed to just one commit on the `main` branch. This means you don't need to keep a clean commit history on your feature branches. In fact, it is preferable to add new commits to a branch rather than rebasing or squashing. For one, it makes it easier to track progress on a branch, but rebasing and force-pushing also discourages collaboration on a branch. -Our CI will run benchmarks on each merged PR. The results can be found at . +Our CI will [record various binary sizes](https://build.rerun.io/graphs/sizes.html) and run [some benchmarks](https://build.rerun.io/graphs/crates.html) on each merged PR. Pull requests from external contributors require approval for CI runs. This can be done manually, by clicking the `Approve and run` button: diff --git a/examples/rust/revy/README.md b/examples/rust/revy/README.md index 8caa95218dfe..d9d79c5ec3ec 100644 --- a/examples/rust/revy/README.md +++ b/examples/rust/revy/README.md @@ -11,10 +11,8 @@ thumbnail_dimensions = [480, 480] - - ## Overview Revy is a proof-of-concept time-travel debugger for the [Bevy](https://github.com/bevyengine/bevy) game engine, built using [Rerun](https://github.com/rerun-io/rerun). diff --git a/lychee.toml b/lychee.toml new file mode 100644 index 000000000000..0fc7002c378b --- /dev/null +++ b/lychee.toml @@ -0,0 +1,60 @@ +################################################################################ +# Config for the link checker lychee. +# +# Download & learn more at: +# https://github.com/lycheeverse/lychee +# +# Example config: +# https://github.com/lycheeverse/lychee/blob/master/lychee.example.toml +# +# Run `lychee . --dump` to list all found links that are being checked. +################################################################################ + +# Maximum number of concurrent link checks. +# Workaround for "too many open files" error on MacOS, see https://github.com/lycheeverse/lychee/issues/1248 +max_concurrency = 32 + + +# URLs to check (supports regex). Has preference over all excludes. +exclude_path = [ + # Unfortunately lychee doesn't yet read .gitignore https://github.com/lycheeverse/lychee/issues/1331 + # The following entries are there because of that: + "__pycache__", + "_deps/", + ".pixi", + "build", + "docs/python/", + "rerun_cpp/docs/html", + "rerun_cpp/docs/xml", + "rerun_py/site/", + "target_ra", + "target_wasm", + "target", + "rerun_cpp/tmp/", + + # Actually ignored files beyond .gitignore + "scripts/screenshot_compare/assets/templates/", +] + +# Exclude URLs and mail addresses from checking (supports regex). +exclude = [ + '.*?speculative-link', # Skip speculative links + '.github/workflows/.*.yml', # GitHub action workflows cause issues on CI. + '\$relpath\^', # Relative paths as used by rerun_cpp's doc header. + '%7B%7B.+%7D%7D', # Ignore things that look like links because of `href` but are actually replacement strings. The URL escaping is for '{{.+}}' (this seems to be needed for html embedded urls since lychee assumes they use this encoding). + 'https://crates.io/crates/.*', # Avoid crates.io rate-limiting + 'https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html', # Nyud links are down every now and then. + 'https://eigen.tuxfamily.org/', # Website down https://gitlab.com/libeigen/eigen/-/issues/2804 + 'https://fonts.googleapis.com/', # Font API entrypoint, not a link. + 'https://fonts.gstatic.com/', # Font API entrypoint, not a link. + 'https://github.com/rerun-io/rerun/pull/\.*', # Ignore links to our own pull requests (typically in changelog). + 'https://github.com/rerun-io/rerun/commit/\.*', # Ignore links to our own commits (typically in changelog). + 'https://stackoverflow.com/.', # Stackoverflow links are no longer accessible from CI. + 'https://www.tensorflow.org/', # tensorflow.org apparently blocks CI. + + # Works but is really slow at times: + 'https://openaccess.thecvf.com/content/CVPR2023/html/Du_Learning_To_Render_Novel_Views_From_Wide-Baseline_Stereo_Pairs_CVPR_2023_paper.html', + 'https://anaconda.org/conda-forge/arrow-cpp', + + #'^file:///', # Ignore local file links. They need to be tested, but it's useful for external links we have to ping. +] diff --git a/pixi.lock b/pixi.lock index 86c0e34d765a..b0f28d6d8caa 100644 --- a/pixi.lock +++ b/pixi.lock @@ -27,10 +27,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils-2.40-hdd6e379_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_impl_linux-64-2.40-hf600244_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binutils_linux-64-2.40-hbdbef99_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.26.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-compiler-1.6.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-16-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-16.0.6-hda56bd4_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_hb11cfb5_4.conda @@ -138,6 +141,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda @@ -145,6 +149,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-50.0-hd3aeb46_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.5-h06160fa_0.conda @@ -162,6 +167,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.18.1-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h75e419f_3.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda @@ -169,9 +175,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -195,11 +199,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: @@ -225,10 +227,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils-2.40-h64c2a2e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_impl_linux-aarch64-2.40-h870a726_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binutils_linux-aarch64-2.40-h95d2017_3.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.1.0-py311h8715677_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-compiler-1.6.0-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-16-16.0.6-default_hb368394_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-16.0.6-h250cd41_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda @@ -333,6 +338,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda @@ -340,6 +346,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda @@ -357,6 +364,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda @@ -364,9 +372,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -390,11 +396,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: @@ -415,12 +419,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.2-h56a5195_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h4da54b2_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.26.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-compiler-1.6.0-h282daa2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools-973.0.1-h40f6528_16.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/cctools_osx-64-973.0.1-ha1c5b94_16.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-16-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-16.0.6-hdae98eb_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_5.conda @@ -518,12 +525,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -540,6 +549,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.18.1-h11a7dfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda @@ -547,9 +557,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -573,11 +581,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: @@ -598,12 +604,15 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.2-h06549c9_7.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h73c0887_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.26.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-compiler-1.6.0-h6aa9301_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools-973.0.1-h4faf515_16.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/cctools_osx-arm64-973.0.1-h62378fb_16.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-16-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-16.0.6-h30cc82d_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_5.conda @@ -701,12 +710,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -723,6 +734,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.9.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.18.1-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda @@ -730,9 +742,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -756,11 +766,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: @@ -781,9 +789,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py311h12c1d0e_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda @@ -861,11 +872,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.0.3-pyhd8ed1ab_0.conda @@ -881,20 +894,20 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.18.1-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2022_win-64-19.37.32822-h0123c8e_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vswhere-3.1.4-h57928b3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -918,11 +931,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl default: @@ -949,9 +960,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.0-h3b5eec7_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.210-hac0d6e5_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h7f98852_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.24.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.7.22-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_hb11cfb5_4.conda @@ -1044,6 +1058,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda @@ -1051,6 +1066,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-28.9-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.06.02-h2873b5e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.1-h06160fa_0.conda @@ -1067,6 +1083,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda @@ -1074,9 +1091,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -1100,11 +1115,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: @@ -1126,9 +1139,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.2-h07bb24a_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.1.0-py311h8715677_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda @@ -1220,6 +1236,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda @@ -1227,6 +1244,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda @@ -1243,6 +1261,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda @@ -1250,9 +1269,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -1276,11 +1293,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: @@ -1301,9 +1316,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.0-h88f2ebf_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.210-heeba50e_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h0d85af4_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.24.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2023.7.22-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_5.conda @@ -1387,12 +1405,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.06.02-hd34609a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -1407,6 +1427,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.16.20-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda @@ -1414,9 +1435,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -1440,11 +1459,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: @@ -1465,9 +1482,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.0-hcc526ff_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.210-ha042220_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h3422bc3_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.24.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2023.7.22-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_5.conda @@ -1551,12 +1571,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_3_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.06.02-h6135d0a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -1571,6 +1593,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.16.20-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda @@ -1578,9 +1601,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -1604,11 +1625,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: @@ -1629,9 +1648,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py311h12c1d0e_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h8ffe710_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2023.7.22-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda @@ -1709,11 +1731,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda @@ -1729,18 +1753,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.16.20-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h64f974e_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.36.32532-hdcecf7f_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.36.32532-h05e6639_17.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -1764,11 +1788,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl py-docs: @@ -1795,9 +1817,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.6-hf567797_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-hbf3e495_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.28.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_6.conda @@ -1891,6 +1916,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h78dcc79_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda @@ -1898,6 +1924,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-51.0-hd3aeb46_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.9-h06160fa_0.conda @@ -1914,6 +1941,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.20.7-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-ha691c75_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda @@ -1922,9 +1950,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl @@ -1974,14 +2000,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl @@ -2005,9 +2029,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.6-h497fec5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hc40fc56_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.1.0-py311h8715677_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.28.1-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_6.conda @@ -2099,6 +2126,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311hf60b7a8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda @@ -2106,6 +2134,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-51.0-h0425590_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.9-h5a25046_0.conda @@ -2122,6 +2151,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.20.7-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hb4872d8_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda @@ -2130,9 +2160,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl @@ -2182,14 +2210,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl @@ -2212,9 +2238,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.6-hfb53d2e_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h01edc24_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_6.conda @@ -2299,12 +2328,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311hb0c4a44_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -2319,6 +2350,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.20.7-h11a7dfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda @@ -2327,9 +2359,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl @@ -2379,14 +2409,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl @@ -2409,9 +2437,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.6-h13f0230_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h134aaec_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_6.conda @@ -2496,12 +2527,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311h4c23913_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -2516,6 +2549,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.20.7-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda @@ -2524,9 +2558,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl @@ -2576,14 +2608,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl @@ -2606,9 +2636,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.6-h5bc0ceb_4.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h5d77392_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py311h12c1d0e_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.28.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda @@ -2686,11 +2719,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h05400ba_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda @@ -2706,19 +2741,19 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.20.7-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl @@ -2768,14 +2803,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/89/d2/4642eb80e3c5a9a00bf8a2ae5cb9390aadfd2a491f161d26a014afa63c4a/sphobjinv-2.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl @@ -2804,9 +2837,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.6-hf567797_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.267-hbf3e495_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.28.1-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.2.2-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_h127d8a8_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_h127d8a8_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_h127d8a8_6.conda @@ -2900,6 +2936,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h78dcc79_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda @@ -2907,6 +2944,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-51.0-hd3aeb46_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.09.01-h7f4b329_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.9-h06160fa_0.conda @@ -2923,6 +2961,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.20.7-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-ha691c75_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda @@ -2930,9 +2969,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -2971,14 +3008,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/bd/ac/3974caaa459bf2c3a244a84be8d17561f631f7d42af370fc311defeca2fb/triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: @@ -3000,9 +3035,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.6-h497fec5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hc40fc56_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.1.0-py311h8715677_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.28.1-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_6.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_6.conda @@ -3094,6 +3132,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311hf60b7a8_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda @@ -3101,6 +3140,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-51.0-h0425590_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.9-h5a25046_0.conda @@ -3117,6 +3157,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.20.7-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hb4872d8_8.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda @@ -3124,9 +3165,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -3153,13 +3192,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: @@ -3180,9 +3217,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.6-hfb53d2e_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.267-h01edc24_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h10d778d_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.28.1-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2024.2.2-h8857fd0_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_6.conda @@ -3267,12 +3307,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311hb0c4a44_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.09.01-hb168e87_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -3287,6 +3329,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.20.7-h11a7dfb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda @@ -3294,9 +3337,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -3323,13 +3364,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: @@ -3350,9 +3389,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.6-h13f0230_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.267-h134aaec_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h93a5062_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.28.1-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2024.2.2-hf0a4a13_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_6.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_6.conda @@ -3437,12 +3479,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311h4c23913_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.09.01-h4cba328_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -3457,6 +3501,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.11.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.20.7-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda @@ -3464,9 +3509,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -3493,13 +3536,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: @@ -3520,9 +3561,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.6-h5bc0ceb_4.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h5d77392_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py311h12c1d0e_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-hcfcfb64_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.28.1-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2024.2.2-h56e8100_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_6.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda @@ -3600,11 +3644,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h05400ba_16_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-69.2.0-pyhd8ed1ab_0.conda @@ -3620,18 +3666,18 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.20.7-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hcf57466_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.38.33130-h82b7239_18.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.38.33130-hcb4865c_18.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl @@ -3658,13 +3704,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl packages: @@ -7264,6 +7308,117 @@ packages: license_family: BSD size: 28888 timestamp: 1710259827989 +- kind: conda + name: brotli-python + version: 1.1.0 + build: py311h12c1d0e_1 + build_number: 1 + subdir: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py311h12c1d0e_1.conda + sha256: 5390e1e5e8e159d4893ecbfd2c08ca75ef51bdce1a4a44ff4ee9e2d596004aac + md5: 42fbf4e947c17ea605e6a4d7f526669a + depends: + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + - ucrt >=10.0.20348.0 + - vc >=14.2,<15 + - vc14_runtime >=14.29.30139 + constrains: + - libbrotlicommon 1.1.0 hcfcfb64_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli + size: 322086 + timestamp: 1695990976742 +- kind: conda + name: brotli-python + version: 1.1.0 + build: py311h8715677_1 + build_number: 1 + subdir: linux-aarch64 + url: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.1.0-py311h8715677_1.conda + sha256: f108fced985f7aa4457564c1e8f49cc5166d2e82bfdc120657c61888cd1f3a53 + md5: 22c060f41b1407ed9f40ce6468bdc338 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - libbrotlicommon 1.1.0 h31becfc_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli + size: 355054 + timestamp: 1695990590279 +- kind: conda + name: brotli-python + version: 1.1.0 + build: py311ha891d26_1 + build_number: 1 + subdir: osx-arm64 + url: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda + sha256: 2d78c79ccf2c17236c52ef217a4c34b762eb7908a6903d94439f787aac1c8f4b + md5: 5e802b015e33447d1283d599d21f052b + depends: + - libcxx >=15.0.7 + - python >=3.11,<3.12.0a0 + - python >=3.11,<3.12.0a0 *_cpython + - python_abi 3.11.* *_cp311 + constrains: + - libbrotlicommon 1.1.0 hb547adb_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli + size: 343332 + timestamp: 1695991223439 +- kind: conda + name: brotli-python + version: 1.1.0 + build: py311hb755f60_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda + sha256: 559093679e9fdb6061b7b80ca0f9a31fe6ffc213f1dae65bc5c82e2cd1a94107 + md5: cce9e7c3f1c307f2a5fb08a2922d6164 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - libbrotlicommon 1.1.0 hd590300_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli + size: 351340 + timestamp: 1695990160360 +- kind: conda + name: brotli-python + version: 1.1.0 + build: py311hdf8f085_1 + build_number: 1 + subdir: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda + sha256: 0f5e0a7de58006f349220365e32db521a1fe494c37ee455e5ecf05b8fe567dcc + md5: 546fdccabb90492fbaf2da4ffb78f352 + depends: + - libcxx >=15.0.7 + - python >=3.11,<3.12.0a0 + - python_abi 3.11.* *_cp311 + constrains: + - libbrotlicommon 1.1.0 h0dc2134_1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/brotli + size: 366864 + timestamp: 1695990449997 - kind: conda name: bzip2 version: 1.0.8 @@ -7837,12 +7992,22 @@ packages: license_family: Other size: 1124537 timestamp: 1706798177156 -- kind: pypi +- kind: conda name: certifi version: 2024.2.2 - url: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - sha256: dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 - requires_python: '>=3.6' + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda + sha256: f1faca020f988696e6b6ee47c82524c7806380b37cfdd1def32f92c326caca54 + md5: 0876280e409658fc6f9e75d035960333 + depends: + - python >=3.7 + license: ISC + purls: + - pkg:pypi/certifi + size: 160559 + timestamp: 1707022289175 - kind: pypi name: cffi version: 1.16.0 @@ -7862,57 +8027,44 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba requires_dist: - pycparser requires_python: '>=3.8' -- kind: pypi - name: charset-normalizer - version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f - requires_python: '>=3.7.0' -- kind: pypi - name: charset-normalizer - version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 - requires_python: '>=3.7.0' -- kind: pypi - name: charset-normalizer - version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 - requires_python: '>=3.7.0' -- kind: pypi - name: charset-normalizer - version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 - requires_python: '>=3.7.0' -- kind: pypi +- kind: conda name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e - requires_python: '>=3.7.0' + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda + sha256: 20cae47d31fdd58d99c4d2e65fbdcefa0b0de0c84e455ba9d6356a4bdbc4b5b9 + md5: 7f4a9e3fcff3f6356ae99244a014da6a + depends: + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/charset-normalizer + size: 46597 + timestamp: 1698833765762 - kind: conda name: clang version: 16.0.6 @@ -9125,8 +9277,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d + url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -9153,8 +9305,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -9181,8 +9333,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 + url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -10216,24 +10368,24 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -21023,8 +21175,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -21047,8 +21199,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -21071,8 +21223,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -21284,14 +21436,14 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl - sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 + url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d + url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 requires_python: '>=3.8' - kind: conda name: psutil @@ -21917,8 +22069,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 + url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl + sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d requires_dist: - cffi >=1.4.1 - sphinx >=1.6.5 ; extra == 'docs' @@ -21929,8 +22081,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d + url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl + sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 requires_dist: - cffi >=1.4.1 - sphinx >=1.6.5 ; extra == 'docs' @@ -21938,6 +22090,45 @@ packages: - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - hypothesis >=3.27.0 ; extra == 'tests' requires_python: '>=3.6' +- kind: conda + name: pysocks + version: 1.7.1 + build: pyh0701188_6 + build_number: 6 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 + sha256: b3a612bc887f3dd0fb7c4199ad8e342bd148cf69a9b74fd9468a18cf2bef07b7 + md5: 56cd9fe388baac0e90c7149cfac95b60 + depends: + - __win + - python >=3.8 + - win_inet_pton + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks + size: 19348 + timestamp: 1661605138291 +- kind: conda + name: pysocks + version: 1.7.1 + build: pyha2e5f31_6 + build_number: 6 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 + sha256: a42f826e958a8d22e65b3394f437af7332610e43ee313393d1cf143f0a2d274b + md5: 2a7de29fb590ca14b5243c4c812c8025 + depends: + - __unix + - python >=3.8 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/pysocks + size: 18981 + timestamp: 1661604969727 - kind: conda name: pytest version: 7.4.2 @@ -22256,14 +22447,8 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab - requires_python: '>=3.6' -- kind: pypi - name: pyyaml - version: 6.0.1 - url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 + url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d requires_python: '>=3.6' - kind: pypi name: pyyaml @@ -22280,8 +22465,14 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d + url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 + requires_python: '>=3.6' +- kind: pypi + name: pyyaml + version: 6.0.1 + url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab requires_python: '>=3.6' - kind: pypi name: pyyaml-env-tag @@ -22568,14 +22759,8 @@ packages: - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl - sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 - requires_python: '>=3.7' -- kind: pypi - name: regex - version: 2023.12.25 - url: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl - sha256: d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97 + url: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb requires_python: '>=3.7' - kind: pypi name: regex @@ -22592,22 +22777,38 @@ packages: - kind: pypi name: regex version: 2023.12.25 - url: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb + url: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl + sha256: d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97 requires_python: '>=3.7' - kind: pypi + name: regex + version: 2023.12.25 + url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl + sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887 + requires_python: '>=3.7' +- kind: conda name: requests version: 2.31.0 - url: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - sha256: 58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f - requires_dist: - - charset-normalizer <4, >=2 - - idna <4, >=2.5 - - urllib3 <3, >=1.21.1 + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda + sha256: 9f629d6fd3c8ac5f2a198639fe7af87c4db2ac9235279164bfe0fcb49d8c4bad + md5: a30144e4156cdbb236f99ebb49828f8b + depends: - certifi >=2017.4.17 - - pysocks !=1.5.7, >=1.5.6 ; extra == 'socks' - - chardet <6, >=3.0.2 ; extra == 'use_chardet_on_py3' - requires_python: '>=3.7' + - charset-normalizer >=2,<4 + - idna >=2.5,<4 + - python >=3.7 + - urllib3 >=1.21.1,<3 + constrains: + - chardet >=3.0.2,<6 + license: Apache-2.0 + license_family: APACHE + purls: + - pkg:pypi/requests + size: 56690 + timestamp: 1684774408600 - kind: conda name: rhash version: 1.4.4 @@ -22663,14 +22864,8 @@ packages: - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 - requires_python: '>=3.8' -- kind: pypi - name: rpds-py - version: 0.18.0 - url: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4 + url: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 requires_python: '>=3.8' - kind: pypi name: rpds-py @@ -22687,8 +22882,14 @@ packages: - kind: pypi name: rpds-py version: 0.18.0 - url: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58 + url: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4 + requires_python: '>=3.8' +- kind: pypi + name: rpds-py + version: 0.18.0 + url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6 requires_python: '>=3.8' - kind: pypi name: rsa @@ -23533,8 +23734,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf requires_dist: - filelock - typing-extensions >=4.8.0 @@ -23560,8 +23761,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl + sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb requires_dist: - filelock - typing-extensions >=4.8.0 @@ -23614,8 +23815,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c requires_dist: - filelock - typing-extensions >=4.8.0 @@ -24112,18 +24313,25 @@ packages: license_family: BSD size: 6868398 timestamp: 1710357060520 -- kind: pypi +- kind: conda name: urllib3 version: 2.2.1 - url: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - sha256: 450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d - requires_dist: - - brotli >=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' - - h2 <5, >=4 ; extra == 'h2' - - pysocks !=1.5.7, <2.0, >=1.5.6 ; extra == 'socks' - - zstandard >=0.18.0 ; extra == 'zstd' - requires_python: '>=3.8' + build: pyhd8ed1ab_0 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda + sha256: d4009dcc9327684d6409706ce17656afbeae690d8522d3c9bc4df57649a352cd + md5: 08807a87fa7af10754d46f63b368e016 + depends: + - brotli-python >=1.0.9 + - pysocks >=1.5.6,<2.0,!=1.5.7 + - python >=3.7 + license: MIT + license_family: MIT + purls: + - pkg:pypi/urllib3 + size: 94669 + timestamp: 1708239595549 - kind: conda name: vc version: '14.3' @@ -24301,40 +24509,40 @@ packages: - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b + url: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl + sha256: 8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935 + url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl + sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl - sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269 + url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl + sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl - sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245 + url: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935 requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' - kind: pypi name: watchdog version: 4.0.0 - url: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl - sha256: 8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3 + url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b requires_dist: - pyyaml >=3.10 ; extra == 'watchmedo' requires_python: '>=3.8' @@ -24357,6 +24565,24 @@ packages: - pkg:pypi/wheel size: 32521 timestamp: 1668051714265 +- kind: conda + name: win_inet_pton + version: 1.1.0 + build: pyhd8ed1ab_6 + build_number: 6 + subdir: noarch + noarch: python + url: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 + sha256: a11ae693a0645bf6c7b8a47bac030be9c0967d0b1924537b9ff7458e832c0511 + md5: 30878ecc4bd36e8deeea1e3c151b2e0b + depends: + - __win + - python >=3.6 + license: PUBLIC-DOMAIN + purls: + - pkg:pypi/win-inet-pton + size: 8191 + timestamp: 1667051294134 - kind: pypi name: wrapt version: 1.16.0 @@ -24369,12 +24595,6 @@ packages: url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 requires_python: '>=3.6' -- kind: pypi - name: wrapt - version: 1.16.0 - url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl - sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 - requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 @@ -24387,6 +24607,12 @@ packages: url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d requires_python: '>=3.6' +- kind: pypi + name: wrapt + version: 1.16.0 + url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl + sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 + requires_python: '>=3.6' - kind: conda name: xz version: 5.2.6 From 1681bfc35a20b747ca6bcd9a32b03ef049fa5938 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 15 Apr 2024 15:55:59 +0200 Subject: [PATCH 295/508] Remove old assertion in arrow bench (#5975) We're now using our own fork anyhow -- there cannot be shenanigans going on on that front without us knowing. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5975?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5975?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5975) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_data_store/benches/arrow2.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/crates/re_data_store/benches/arrow2.rs b/crates/re_data_store/benches/arrow2.rs index b8e972945d14..dee0628802d0 100644 --- a/crates/re_data_store/benches/arrow2.rs +++ b/crates/re_data_store/benches/arrow2.rs @@ -111,16 +111,7 @@ fn erased_clone(c: &mut Criterion) { .iter() .map(|array| array.total_size_bytes()) .sum::(); - let expected_total_size_bytes = data.total_size_bytes(); - // NOTE: `+ 1` because the computation is off by one bytes, which is irrelevant for the - // purposes of this benchmark. - assert!( - total_size_bytes + 1 >= expected_total_size_bytes, - "Size for {} calculated to be {} bytes, but should be at least {} bytes", - T::name(), - total_size_bytes, - expected_total_size_bytes, - ); + assert!(total_size_bytes > 0); group.bench_function("array", |b| { b.iter(|| { From 0cb6157eb2d98a6f15f14f3f2439d950baf09126 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 15 Apr 2024 16:15:06 +0200 Subject: [PATCH 296/508] Fix weekly alpha crate release (#5977) ### What Fix for https://github.com/rerun-io/rerun/actions/runs/8690522249/job/23830652154 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{pr.number}}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/auto_release_crates.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto_release_crates.yml b/.github/workflows/auto_release_crates.yml index 9ffec72f680f..5ef698569697 100644 --- a/.github/workflows/auto_release_crates.yml +++ b/.github/workflows/auto_release_crates.yml @@ -33,7 +33,7 @@ jobs: id: versioning shell: bash run: | - crate_version=$(python3 scripts/ci/crates.py get-version) + crate_version=$(pixi run python scripts/ci/crates.py get-version) echo "crate_version=$crate_version" >> "$GITHUB_OUTPUT" - name: Create pull request From 25aac8aa4174e44bbae7a1a83fb7b6488e902046 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 15 Apr 2024 16:39:17 +0200 Subject: [PATCH 297/508] Merge rust scripts into `re_dev_tools` crate (#5972) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What * Fixes #5889 Puts a bunch of tooling under a new extensible home. ``` pixi run dev-tools --help ✨ Pixi task (default): cargo run -q --locked -p re_dev_tools -- --help Usage: re_dev_tools [] Various development tools for Rerun. Options: --help display usage information Commands: build-examples Build examples and their manifest. build-web-viewer Build the web-viewer. search-index Meilisearch indexer and REPL ``` Intentionally left out `re_types_builder` since it's fairly big on its own. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5972?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5972?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5972) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../reusable_build_and_upload_rerun_cli.yml | 4 +- .github/workflows/reusable_build_web.yml | 2 +- .github/workflows/reusable_checks_rust.yml | 4 +- .github/workflows/reusable_publish_web.yml | 2 +- .github/workflows/reusable_release_crates.yml | 2 +- ARCHITECTURE.md | 14 ++- Cargo.lock | 76 +++++---------- Cargo.toml | 6 +- crates/re_build_examples/Cargo.toml | 30 ------ crates/re_build_web_viewer/Cargo.toml | 24 ----- crates/re_build_web_viewer/src/main.rs | 94 ------------------- .../Cargo.toml | 9 +- crates/re_dev_tools/README.md | 11 +++ .../src/build_examples}/example.rs | 1 + .../src/build_examples}/manifest.rs | 2 +- .../src/build_examples/mod.rs} | 35 ++++--- .../src/build_examples}/rrd.rs | 3 +- .../src/build_examples}/snippets.rs | 2 +- .../src/build_examples/wait_for_output.rs} | 10 +- .../src/build_search_index}/README.md | 2 +- .../src/build_search_index}/build.rs | 2 +- .../src/build_search_index}/ingest.rs | 0 .../src/build_search_index}/ingest/cpp.rs | 2 +- .../src/build_search_index}/ingest/docs.rs | 0 .../build_search_index}/ingest/examples.rs | 9 +- .../src/build_search_index}/ingest/python.rs | 6 +- .../src/build_search_index}/ingest/rust.rs | 0 .../src/build_search_index}/meili.rs | 2 +- .../src/build_search_index/mod.rs} | 31 ++---- .../src/build_search_index}/repl.rs | 4 +- .../src/build_search_index}/util.rs | 0 .../src/build_web_viewer}/README.md | 10 +- .../src/build_web_viewer}/lib.rs | 0 .../re_dev_tools/src/build_web_viewer/mod.rs | 45 +++++++++ crates/re_dev_tools/src/main.rs | 34 +++++++ crates/re_web_viewer_server/Cargo.toml | 2 +- crates/re_web_viewer_server/README.md | 2 +- docs/snippets/snippets.toml | 2 +- pixi.toml | 13 +-- rerun_cpp/docs/Doxyfile | 2 +- rerun_js/web-viewer/package.json | 6 +- rerun_py/docs/gen_common_index.py | 2 +- scripts/ci/build_and_upload_wheels.py | 2 +- .../build_screenshot_compare.py | 12 +-- web_viewer/README.md | 2 +- 45 files changed, 210 insertions(+), 313 deletions(-) delete mode 100644 crates/re_build_examples/Cargo.toml delete mode 100644 crates/re_build_web_viewer/Cargo.toml delete mode 100644 crates/re_build_web_viewer/src/main.rs rename crates/{re_build_search_index => re_dev_tools}/Cargo.toml (86%) create mode 100644 crates/re_dev_tools/README.md rename crates/{re_build_examples/src => re_dev_tools/src/build_examples}/example.rs (99%) rename crates/{re_build_examples/src => re_dev_tools/src/build_examples}/manifest.rs (99%) rename crates/{re_build_examples/src/main.rs => re_dev_tools/src/build_examples/mod.rs} (73%) rename crates/{re_build_examples/src => re_dev_tools/src/build_examples}/rrd.rs (98%) rename crates/{re_build_examples/src => re_dev_tools/src/build_examples}/snippets.rs (99%) rename crates/{re_build_examples/src/lib.rs => re_dev_tools/src/build_examples/wait_for_output.rs} (82%) rename crates/{re_build_search_index => re_dev_tools/src/build_search_index}/README.md (95%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/build.rs (94%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/ingest.rs (100%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/ingest/cpp.rs (99%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/ingest/docs.rs (100%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/ingest/examples.rs (88%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/ingest/python.rs (98%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/ingest/rust.rs (100%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/meili.rs (99%) rename crates/{re_build_search_index/src/main.rs => re_dev_tools/src/build_search_index/mod.rs} (60%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/repl.rs (96%) rename crates/{re_build_search_index/src => re_dev_tools/src/build_search_index}/util.rs (100%) rename crates/{re_build_web_viewer => re_dev_tools/src/build_web_viewer}/README.md (51%) rename crates/{re_build_web_viewer/src => re_dev_tools/src/build_web_viewer}/lib.rs (100%) create mode 100644 crates/re_dev_tools/src/build_web_viewer/mod.rs create mode 100644 crates/re_dev_tools/src/main.rs diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index a06ab82946c5..35e98d6839b3 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -166,9 +166,7 @@ jobs: pixi-version: v0.19.0 - name: Build web-viewer (release) - shell: bash - run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release -g + run: pixi run rerun-build-web-release # This does not run in the pixi environment, doing so # causes it to select the wrong compiler on macos-arm64 diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 34127757b4f5..e1f8a863fedd 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -71,7 +71,7 @@ jobs: if [ ${{ inputs.CHANNEL }} = "nightly" ]; then export DEFAULT_EXAMPLES_MANIFEST_URL="https://app.rerun.io/version/nightly/examples_manifest.json" fi - pixi run cargo run --locked -p re_build_web_viewer -- --release -g + pixi run rerun-build-web-release # We build a single manifest pointing to the `commit` # All the `pr`, `main`, release tag, etc. variants will always just point to the resolved commit diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 1fe8ade91dbd..575cb403e997 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -65,9 +65,7 @@ jobs: # We need to build the web viewer for `rust_checks.py` to succeed. # We build in release so that we can reuse the results for actual publishing, if necessary - name: Build web-viewer (release) - shell: bash - run: | - pixi run cargo run --locked -p re_build_web_viewer -- --release -g + run: pixi run rerun-build-web-release - name: Rust checks & tests if: ${{ inputs.CHANNEL == 'pr' }} diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index f6078aaa7911..5ef2daadd9f8 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -108,7 +108,7 @@ jobs: - name: Build web-viewer (release) shell: bash run: | - pixi -e wheel-test run cargo run --locked -p re_build_web_viewer -- --release -g + pixi -e wheel-test run rerun-build-web-release - name: Build examples shell: bash diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml index 669e1fc12f0f..63ad82f3bed1 100644 --- a/.github/workflows/reusable_release_crates.yml +++ b/.github/workflows/reusable_release_crates.yml @@ -29,7 +29,7 @@ jobs: pixi-version: v0.19.0 - name: Build web-viewer (release) - run: pixi run cargo run --locked -p re_build_web_viewer -- --release -g + run: pixi run rerun-build-web-release - name: Publish run: pixi run python scripts/ci/crates.py publish --token ${{ secrets.CRATES_IO_TOKEN }} diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 3c2f5a8511bd..af6ab630813c 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -176,14 +176,12 @@ Update instructions: ### Build support -| Crate | Description | -|----------------------------|---------------------------------------------------------------| -| re_build_info | Information about the build. Use together with re_build_tools | -| re_build_tools | build.rs helpers for generating build info | -| re_types_builder | Generates code for Rerun's SDKs from flatbuffers definitions. | -| re_build_examples | Build rerun example RRD files and manifest | -| re_build_search_index | Build a Meilisearch index from all our documentation | -| re_build_web_viewer | Build the rerun web-viewer Wasm from source | +| Crate | Description | +|----------------------------|------------------------------------------------------------------| +| re_build_info | Information about the build. Use together with re_build_tools | +| re_build_tools | build.rs helpers for generating build info | +| re_types_builder | Generates code for Rerun's SDKs from flatbuffers definitions. | +| re_dev_tools | Various tools for Rerun development. Each tool has a subcommand. | ### Utilities diff --git a/Cargo.lock b/Cargo.lock index 5eddcb0ff171..36b29ac7242e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4196,50 +4196,10 @@ dependencies = [ "simdutf8", ] -[[package]] -name = "re_build_examples" -version = "0.16.0-alpha.1+dev" -dependencies = [ - "anyhow", - "argh", - "indicatif", - "rayon", - "re_build_tools", - "re_format", - "serde", - "serde_json", - "toml", -] - [[package]] name = "re_build_info" version = "0.16.0-alpha.1+dev" -[[package]] -name = "re_build_search_index" -version = "0.16.0-alpha.1+dev" -dependencies = [ - "anyhow", - "argh", - "camino", - "cargo_metadata 0.18.1", - "glob", - "indicatif", - "itertools 0.12.0", - "rayon", - "re_build_examples", - "re_build_tools", - "roxmltree", - "rustdoc-json", - "rustdoc-types", - "serde", - "serde_json", - "serde_yaml", - "toml", - "ureq", - "url", -] - [[package]] name = "re_build_tools" version = "0.16.0-alpha.1+dev" @@ -4253,16 +4213,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "re_build_web_viewer" -version = "0.16.0-alpha.1+dev" -dependencies = [ - "anyhow", - "cargo_metadata 0.18.1", - "re_error", - "wasm-bindgen-cli-support", -] - [[package]] name = "re_crash_handler" version = "0.16.0-alpha.1+dev" @@ -4358,6 +4308,32 @@ dependencies = [ "rfd", ] +[[package]] +name = "re_dev_tools" +version = "0.16.0-alpha.1+dev" +dependencies = [ + "anyhow", + "argh", + "camino", + "cargo_metadata 0.18.1", + "glob", + "indicatif", + "itertools 0.12.0", + "rayon", + "re_build_tools", + "re_format", + "roxmltree", + "rustdoc-json", + "rustdoc-types", + "serde", + "serde_json", + "serde_yaml", + "toml", + "ureq", + "url", + "wasm-bindgen-cli-support", +] + [[package]] name = "re_entity_db" version = "0.16.0-alpha.1+dev" diff --git a/Cargo.toml b/Cargo.toml index 3fc940776264..e0789da88ba3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,15 +29,13 @@ version = "0.16.0-alpha.1+dev" # In particular: if we compile rerun 0.3.0-alpha.0 we only want it to use # re_log_types 0.3.0-alpha.0, NOT 0.3.0-alpha.4 even though it is newer and semver-compatible. re_analytics = { path = "crates/re_analytics", version = "=0.16.0-alpha.1", default-features = false } -re_build_search_index = { path = "crates/re_build_search_index", version = "=0.16.0-alpha.1", default-features = false } -re_build_examples = { path = "crates/re_build_examples", version = "=0.16.0-alpha.1", default-features = false } re_build_info = { path = "crates/re_build_info", version = "=0.16.0-alpha.1", default-features = false } re_build_tools = { path = "crates/re_build_tools", version = "=0.16.0-alpha.1", default-features = false } -re_build_web_viewer = { path = "crates/re_build_web_viewer", version = "=0.16.0-alpha.1", default-features = false } re_crash_handler = { path = "crates/re_crash_handler", version = "=0.16.0-alpha.1", default-features = false } re_data_source = { path = "crates/re_data_source", version = "=0.16.0-alpha.1", default-features = false } re_data_store = { path = "crates/re_data_store", version = "=0.16.0-alpha.1", default-features = false } re_data_ui = { path = "crates/re_data_ui", version = "=0.16.0-alpha.1", default-features = false } +re_dev_tools = { path = "crates/re_dev_tools", version = "=0.16.0-alpha.1", default-features = false } re_entity_db = { path = "crates/re_entity_db", version = "=0.16.0-alpha.1", default-features = false } re_error = { path = "crates/re_error", version = "=0.16.0-alpha.1", default-features = false } re_format = { path = "crates/re_format", version = "=0.16.0-alpha.1", default-features = false } @@ -47,9 +45,9 @@ re_log_encoding = { path = "crates/re_log_encoding", version = "=0.16.0-alpha.1" re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.1", default-features = false } re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.1", default-features = false } re_query = { path = "crates/re_query", version = "=0.16.0-alpha.1", default-features = false } -re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.1", default-features = false } re_query_cache = { path = "crates/re_query_cache", version = "=0.16.0-alpha.1", default-features = false } re_query_cache2 = { path = "crates/re_query_cache2", version = "=0.16.0-alpha.1", default-features = false } +re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.1", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.1", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.1", default-features = false } re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.16.0-alpha.1", default-features = false } diff --git a/crates/re_build_examples/Cargo.toml b/crates/re_build_examples/Cargo.toml deleted file mode 100644 index a2d0f8b12f04..000000000000 --- a/crates/re_build_examples/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "re_build_examples" -authors.workspace = true -description = "Build rerun example RRD files" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -publish = false -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[dependencies] -re_build_tools.workspace = true -re_format.workspace = true - -# External -anyhow.workspace = true -argh.workspace = true -indicatif.workspace = true -rayon.workspace = true -serde = { workspace = true, features = ["derive"] } -serde_json.workspace = true -toml = { workspace = true, features = ["parse", "preserve_order"] } diff --git a/crates/re_build_web_viewer/Cargo.toml b/crates/re_build_web_viewer/Cargo.toml deleted file mode 100644 index 1cf09c138a7d..000000000000 --- a/crates/re_build_web_viewer/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "re_build_web_viewer" -authors.workspace = true -description = "Build the rerun web-viewer Wasm from source" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -publish = true -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[dependencies] -re_error.workspace = true - -anyhow.workspace = true -cargo_metadata.workspace = true -wasm-bindgen-cli-support.workspace = true diff --git a/crates/re_build_web_viewer/src/main.rs b/crates/re_build_web_viewer/src/main.rs deleted file mode 100644 index f734d4097ef4..000000000000 --- a/crates/re_build_web_viewer/src/main.rs +++ /dev/null @@ -1,94 +0,0 @@ -use cargo_metadata::camino::Utf8PathBuf; -use re_build_web_viewer::{default_build_dir, Profile, Target}; -use std::process::ExitCode; - -struct Opts { - profile: Option, - debug_symbols: bool, - target: Target, - build_dir: Utf8PathBuf, -} - -impl Default for Opts { - fn default() -> Self { - Self { - profile: None, - debug_symbols: false, - target: Target::Browser, - build_dir: default_build_dir(), - } - } -} - -fn main() -> ExitCode { - let mut opts = Opts::default(); - - let mut args = std::env::args().skip(1); - while let Some(arg) = args.next() { - match arg.as_str() { - "--help" => { - print_help(); - return ExitCode::SUCCESS; - } - "--debug" => { - assert!( - opts.profile.is_none(), - "Can't set both --release and --debug" - ); - opts.profile = Some(Profile::Debug); - } - "--release" => { - assert!( - opts.profile.is_none(), - "Can't set both --release and --debug" - ); - opts.profile = Some(Profile::Release); - } - "-g" => { - opts.debug_symbols = true; - } - "-o" | "--out" => match args.next() { - Some(value) if !value.starts_with('-') => { - opts.build_dir = Utf8PathBuf::from(value); - } - _ => panic!("expected path after {arg}"), - }, - "--module" => { - opts.target = Target::Module; - } - _ => { - print_help(); - return ExitCode::FAILURE; - } - } - } - - let Some(release) = opts.profile else { - eprintln!("You need to pass either --debug or --release"); - return ExitCode::FAILURE; - }; - - if let Err(err) = - re_build_web_viewer::build(release, opts.debug_symbols, opts.target, &opts.build_dir) - { - eprintln!("Failed to build web viewer: {}", re_error::format(err)); - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } -} - -fn print_help() { - eprintln!( - r"Build the web-viewer. - - --help: Print this help text - --debug: Build a debug binary - --release: Compile for release, and run wasm-opt. - NOTE: --release also removes debug symbols which are otherwise useful for in-browser profiling. - -g: Keep debug symbols, even in release builds. - This gives better callstacks on panics, and also allows for in-browser profiling of the Wasm. - -o, --out: Set the output directory. This is a path relative to the cargo workspace root. -" - ); -} diff --git a/crates/re_build_search_index/Cargo.toml b/crates/re_dev_tools/Cargo.toml similarity index 86% rename from crates/re_build_search_index/Cargo.toml rename to crates/re_dev_tools/Cargo.toml index 5ea7f86fe1a1..d53eebfb2995 100644 --- a/crates/re_build_search_index/Cargo.toml +++ b/crates/re_dev_tools/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "re_build_search_index" +name = "re_dev_tools" authors.workspace = true -description = "Build a Meilisearch index from all of Rerun's documentation" +description = "Various tools for rerun development" edition.workspace = true homepage.workspace = true include.workspace = true @@ -17,8 +17,8 @@ all-features = true [dependencies] -re_build_examples.workspace = true re_build_tools.workspace = true +re_format.workspace = true # External anyhow.workspace = true @@ -28,8 +28,8 @@ cargo_metadata.workspace = true glob.workspace = true indicatif.workspace = true itertools.workspace = true -roxmltree = "0.19.0" rayon.workspace = true +roxmltree = "0.19.0" rustdoc-json = "0.8.8" rustdoc-types = "0.24.0" serde = { workspace = true, features = ["derive"] } @@ -38,3 +38,4 @@ serde_yaml.workspace = true toml = { workspace = true, features = ["parse", "preserve_order"] } ureq = { workspace = true, features = ["json"] } url.workspace = true +wasm-bindgen-cli-support.workspace = true diff --git a/crates/re_dev_tools/README.md b/crates/re_dev_tools/README.md new file mode 100644 index 000000000000..5fc1e4544695 --- /dev/null +++ b/crates/re_dev_tools/README.md @@ -0,0 +1,11 @@ +# re_dev_tools +Crate that combines several development utilities. +To get an overview over all tools run `pixi run dev-tools --help`. + +We keep all smaller rust "scripts" in this single crate so we don't needlessly +increase the number of such utility crates and to make it easy to get +an overview over all build tooling written in Rust. + +## Adding a new tool +* Create a folder under `src` with your new tool +* Add a new enum entry to `main.rs` diff --git a/crates/re_build_examples/src/example.rs b/crates/re_dev_tools/src/build_examples/example.rs similarity index 99% rename from crates/re_build_examples/src/example.rs rename to crates/re_dev_tools/src/build_examples/example.rs index 69f68b481705..6027510c5028 100644 --- a/crates/re_build_examples/src/example.rs +++ b/crates/re_dev_tools/src/build_examples/example.rs @@ -79,6 +79,7 @@ impl Example { pub enum Language { Rust, Python, + #[allow(dead_code)] C, Cpp, } diff --git a/crates/re_build_examples/src/manifest.rs b/crates/re_dev_tools/src/build_examples/manifest.rs similarity index 99% rename from crates/re_build_examples/src/manifest.rs rename to crates/re_dev_tools/src/build_examples/manifest.rs index 4ddd85ce8102..cb09f4714ebd 100644 --- a/crates/re_build_examples/src/manifest.rs +++ b/crates/re_dev_tools/src/build_examples/manifest.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use re_build_tools::Environment; -use crate::{Channel, Example}; +use super::{Channel, Example}; /// Collect examples in the repository and produce a manifest file. /// diff --git a/crates/re_build_examples/src/main.rs b/crates/re_dev_tools/src/build_examples/mod.rs similarity index 73% rename from crates/re_build_examples/src/main.rs rename to crates/re_dev_tools/src/build_examples/mod.rs index b4adb0725684..8addde805a61 100644 --- a/crates/re_build_examples/src/main.rs +++ b/crates/re_dev_tools/src/build_examples/mod.rs @@ -10,24 +10,25 @@ //! An example may also specify args to be run with via the frontmatter //! `build_args` string array. -pub use re_build_examples::*; +mod example; +mod manifest; +mod rrd; +mod snippets; +mod wait_for_output; -use argh::FromArgs; +use example::Channel; +use wait_for_output::wait_for_output; -fn main() -> anyhow::Result<()> { - re_build_tools::set_output_cargo_build_instructions(false); +pub use example::{Example, ExamplesManifest, Language}; - let args: Args = argh::from_env(); - match args.cmd { - Cmd::Rrd(cmd) => cmd.run(), - Cmd::Manifest(cmd) => cmd.run(), - Cmd::Snippets(cmd) => cmd.run(), - } -} +// ----------------------------------------------------------------------------- + +use argh::FromArgs; /// Build examples and their manifest. #[derive(FromArgs)] -struct Args { +#[argh(subcommand, name = "build-examples")] +pub struct Args { #[argh(subcommand)] cmd: Cmd, } @@ -39,3 +40,13 @@ enum Cmd { Manifest(manifest::Manifest), Snippets(snippets::Snippets), } + +pub fn main(args: Args) -> anyhow::Result<()> { + re_build_tools::set_output_cargo_build_instructions(false); + + match args.cmd { + Cmd::Rrd(cmd) => cmd.run(), + Cmd::Manifest(cmd) => cmd.run(), + Cmd::Snippets(cmd) => cmd.run(), + } +} diff --git a/crates/re_build_examples/src/rrd.rs b/crates/re_dev_tools/src/build_examples/rrd.rs similarity index 98% rename from crates/re_build_examples/src/rrd.rs rename to crates/re_dev_tools/src/build_examples/rrd.rs index efddf252d2d2..ef625cd6e161 100644 --- a/crates/re_build_examples/src/rrd.rs +++ b/crates/re_dev_tools/src/build_examples/rrd.rs @@ -1,5 +1,4 @@ -use crate::wait_for_output; -use crate::{Channel, Example}; +use super::{wait_for_output, Channel, Example}; use indicatif::MultiProgress; use rayon::prelude::IntoParallelIterator; use rayon::prelude::ParallelIterator; diff --git a/crates/re_build_examples/src/snippets.rs b/crates/re_dev_tools/src/build_examples/snippets.rs similarity index 99% rename from crates/re_build_examples/src/snippets.rs rename to crates/re_dev_tools/src/build_examples/snippets.rs index a75ed82f9f6c..d4ae335e0631 100644 --- a/crates/re_build_examples/src/snippets.rs +++ b/crates/re_dev_tools/src/build_examples/snippets.rs @@ -11,7 +11,7 @@ use indicatif::MultiProgress; use rayon::prelude::IntoParallelIterator; use rayon::prelude::ParallelIterator; -use crate::wait_for_output; +use super::wait_for_output; /// Collect code snippets from `docs/snippets` in the repository and run them to produce `.rrd` files. #[derive(argh::FromArgs)] diff --git a/crates/re_build_examples/src/lib.rs b/crates/re_dev_tools/src/build_examples/wait_for_output.rs similarity index 82% rename from crates/re_build_examples/src/lib.rs rename to crates/re_dev_tools/src/build_examples/wait_for_output.rs index 5f3784bdbdb6..ca809f49aa67 100644 --- a/crates/re_build_examples/src/lib.rs +++ b/crates/re_dev_tools/src/build_examples/wait_for_output.rs @@ -1,21 +1,13 @@ -//! Build rerun example RRD files and manifest - -pub mod example; -pub mod manifest; -pub mod rrd; -pub mod snippets; - use std::io::stdout; use std::io::IsTerminal; use std::process::Command; use std::process::Output; use std::time::Duration; -pub use example::{Channel, Example}; use indicatif::MultiProgress; use indicatif::ProgressBar; -fn wait_for_output( +pub fn wait_for_output( mut cmd: Command, name: &str, progress: &MultiProgress, diff --git a/crates/re_build_search_index/README.md b/crates/re_dev_tools/src/build_search_index/README.md similarity index 95% rename from crates/re_build_search_index/README.md rename to crates/re_dev_tools/src/build_search_index/README.md index cd86fc1b4cff..18c12860d796 100644 --- a/crates/re_build_search_index/README.md +++ b/crates/re_dev_tools/src/build_search_index/README.md @@ -1,4 +1,4 @@ -# re_build_search_index +# build_search_index Builds a Meilisearch index from our documentation. diff --git a/crates/re_build_search_index/src/build.rs b/crates/re_dev_tools/src/build_search_index/build.rs similarity index 94% rename from crates/re_build_search_index/src/build.rs rename to crates/re_dev_tools/src/build_search_index/build.rs index 24ce4b5e12d5..a2b57728289f 100644 --- a/crates/re_build_search_index/src/build.rs +++ b/crates/re_dev_tools/src/build_search_index/build.rs @@ -1,4 +1,4 @@ -use crate::{ingest, meili, DEFAULT_INDEX, DEFAULT_KEY, DEFAULT_URL}; +use super::{ingest, meili, DEFAULT_INDEX, DEFAULT_KEY, DEFAULT_URL}; /// Index documentation, examples, and API references for all languages #[derive(argh::FromArgs)] diff --git a/crates/re_build_search_index/src/ingest.rs b/crates/re_dev_tools/src/build_search_index/ingest.rs similarity index 100% rename from crates/re_build_search_index/src/ingest.rs rename to crates/re_dev_tools/src/build_search_index/ingest.rs diff --git a/crates/re_build_search_index/src/ingest/cpp.rs b/crates/re_dev_tools/src/build_search_index/ingest/cpp.rs similarity index 99% rename from crates/re_build_search_index/src/ingest/cpp.rs rename to crates/re_dev_tools/src/build_search_index/ingest/cpp.rs index c191279051f4..a9894a1f6ffb 100644 --- a/crates/re_build_search_index/src/ingest/cpp.rs +++ b/crates/re_dev_tools/src/build_search_index/ingest/cpp.rs @@ -10,7 +10,7 @@ use roxmltree::Descendants; use roxmltree::Document; use roxmltree::Node; -use crate::util::CommandExt as _; +use crate::build_search_index::util::CommandExt as _; use super::Context; use super::DocumentData; diff --git a/crates/re_build_search_index/src/ingest/docs.rs b/crates/re_dev_tools/src/build_search_index/ingest/docs.rs similarity index 100% rename from crates/re_build_search_index/src/ingest/docs.rs rename to crates/re_dev_tools/src/build_search_index/ingest/docs.rs diff --git a/crates/re_build_search_index/src/ingest/examples.rs b/crates/re_dev_tools/src/build_search_index/ingest/examples.rs similarity index 88% rename from crates/re_build_search_index/src/ingest/examples.rs rename to crates/re_dev_tools/src/build_search_index/ingest/examples.rs index 4688c1476347..680f0658109b 100644 --- a/crates/re_build_search_index/src/ingest/examples.rs +++ b/crates/re_dev_tools/src/build_search_index/ingest/examples.rs @@ -1,11 +1,6 @@ -use re_build_examples::example::ExamplesManifest; -use re_build_examples::example::Language; -use re_build_examples::Example; +use crate::build_examples::{Example, ExamplesManifest, Language}; -use crate::ingest::DocumentData; -use crate::ingest::DocumentKind; - -use super::Context; +use super::{Context, DocumentData, DocumentKind}; const LANGUAGES: &[Language] = &[Language::Python, Language::Rust, Language::Cpp]; diff --git a/crates/re_build_search_index/src/ingest/python.rs b/crates/re_dev_tools/src/build_search_index/ingest/python.rs similarity index 98% rename from crates/re_build_search_index/src/ingest/python.rs rename to crates/re_dev_tools/src/build_search_index/ingest/python.rs index bdbd6f863187..b3daba65e938 100644 --- a/crates/re_build_search_index/src/ingest/python.rs +++ b/crates/re_dev_tools/src/build_search_index/ingest/python.rs @@ -5,11 +5,9 @@ use std::process::Command; use anyhow::Context as _; use serde::Deserialize; -use crate::ingest::DocumentData; -use crate::ingest::DocumentKind; -use crate::util::CommandExt as _; +use crate::build_search_index::util::CommandExt as _; -use super::Context; +use super::{Context, DocumentData, DocumentKind}; const RERUN_SDK: &str = "rerun_sdk"; diff --git a/crates/re_build_search_index/src/ingest/rust.rs b/crates/re_dev_tools/src/build_search_index/ingest/rust.rs similarity index 100% rename from crates/re_build_search_index/src/ingest/rust.rs rename to crates/re_dev_tools/src/build_search_index/ingest/rust.rs diff --git a/crates/re_build_search_index/src/meili.rs b/crates/re_dev_tools/src/build_search_index/meili.rs similarity index 99% rename from crates/re_build_search_index/src/meili.rs rename to crates/re_dev_tools/src/build_search_index/meili.rs index ced580ff93b5..64a1d71ed890 100644 --- a/crates/re_build_search_index/src/meili.rs +++ b/crates/re_dev_tools/src/build_search_index/meili.rs @@ -3,7 +3,7 @@ use std::ops::ControlFlow; use anyhow::Context; use url::Url; -use crate::ingest::Document; +use super::ingest::Document; pub fn connect(url: &str, master_key: &str) -> anyhow::Result { SearchClient::connect(url, master_key) diff --git a/crates/re_build_search_index/src/main.rs b/crates/re_dev_tools/src/build_search_index/mod.rs similarity index 60% rename from crates/re_build_search_index/src/main.rs rename to crates/re_dev_tools/src/build_search_index/mod.rs index 162aaf00ade7..f174a12cf7b6 100644 --- a/crates/re_build_search_index/src/main.rs +++ b/crates/re_dev_tools/src/build_search_index/mod.rs @@ -7,30 +7,12 @@ mod meili; mod repl; mod util; -fn main() -> anyhow::Result<()> { - let args: Args = argh::from_env(); - - let Some(cmd) = args.cmd else { - let help_text = ::from_args(&["search-index"], &["--help"]) - .err() - .unwrap() - .output; - - eprintln!("{help_text}"); - return Ok(()); - }; - - match cmd { - Cmd::Repl(cmd) => cmd.run(), - Cmd::Build(cmd) => cmd.run(), - } -} - /// Meilisearch indexer and REPL #[derive(argh::FromArgs)] -struct Args { +#[argh(subcommand, name = "search-index")] +pub struct Args { #[argh(subcommand)] - cmd: Option, + cmd: Cmd, } #[derive(argh::FromArgs)] @@ -40,6 +22,13 @@ enum Cmd { Build(build::Build), } +pub fn main(args: Args) -> anyhow::Result<()> { + match args.cmd { + Cmd::Repl(cmd) => cmd.run(), + Cmd::Build(cmd) => cmd.run(), + } +} + const DEFAULT_URL: &str = "http://localhost:7700"; const DEFAULT_KEY: &str = "test"; const DEFAULT_INDEX: &str = "temp"; diff --git a/crates/re_build_search_index/src/repl.rs b/crates/re_dev_tools/src/build_search_index/repl.rs similarity index 96% rename from crates/re_build_search_index/src/repl.rs rename to crates/re_dev_tools/src/build_search_index/repl.rs index 77819c869515..21b064f0468d 100644 --- a/crates/re_build_search_index/src/repl.rs +++ b/crates/re_dev_tools/src/build_search_index/repl.rs @@ -1,5 +1,5 @@ -use crate::meili::SearchClient; -use crate::{ingest, meili, DEFAULT_INDEX, DEFAULT_KEY, DEFAULT_URL}; +use super::meili::SearchClient; +use super::{ingest, meili, DEFAULT_INDEX, DEFAULT_KEY, DEFAULT_URL}; use std::io::stdin; use std::io::stdout; diff --git a/crates/re_build_search_index/src/util.rs b/crates/re_dev_tools/src/build_search_index/util.rs similarity index 100% rename from crates/re_build_search_index/src/util.rs rename to crates/re_dev_tools/src/build_search_index/util.rs diff --git a/crates/re_build_web_viewer/README.md b/crates/re_dev_tools/src/build_web_viewer/README.md similarity index 51% rename from crates/re_build_web_viewer/README.md rename to crates/re_dev_tools/src/build_web_viewer/README.md index ca71944cbf2d..7d6f07ba9801 100644 --- a/crates/re_build_web_viewer/README.md +++ b/crates/re_dev_tools/src/build_web_viewer/README.md @@ -1,13 +1,13 @@ -# `re_build_web_viewer` +# `build_web_viewer` Binary and library for building the Rerun web viewer. This is also called by the `build.rs` of `re_web_viewer_server`. -``` -cargo r -p re_build_web_viewer -- --debug +```sh +pixi run dev-tools -- build-web-viewer ``` -``` -cargo r -p re_build_web_viewer -- --release -g +```sh +pixi run dev-tools -- build-web-viewer --release -g ``` diff --git a/crates/re_build_web_viewer/src/lib.rs b/crates/re_dev_tools/src/build_web_viewer/lib.rs similarity index 100% rename from crates/re_build_web_viewer/src/lib.rs rename to crates/re_dev_tools/src/build_web_viewer/lib.rs diff --git a/crates/re_dev_tools/src/build_web_viewer/mod.rs b/crates/re_dev_tools/src/build_web_viewer/mod.rs new file mode 100644 index 000000000000..0bc78827a32d --- /dev/null +++ b/crates/re_dev_tools/src/build_web_viewer/mod.rs @@ -0,0 +1,45 @@ +mod lib; + +use argh::FromArgs; +use cargo_metadata::camino::Utf8PathBuf; + +use lib::{build, default_build_dir, Profile, Target}; + +/// Build the web-viewer. +#[derive(FromArgs)] +#[argh(subcommand, name = "build-web-viewer")] +pub struct Args { + /// compile for release and run wasm-opt. + /// NOTE: --release also removes debug symbols which are otherwise useful for in-browser profiling. + #[argh(switch)] + release: bool, + + /// keep debug symbols, even in release builds. + /// This gives better callstacks on panics, and also allows for in-browser profiling of the Wasm. + #[argh(switch, short = 'g')] + debug_symbols: bool, + + /// if set, will build the module target instead of the browser target. + #[argh(switch)] + module: bool, + + /// set the output directory. This is a path relative to the cargo workspace root. + #[argh(option, short = 'o', long = "out")] + build_dir: Option, +} + +pub fn main(args: Args) -> anyhow::Result<()> { + let profile = if args.release { + Profile::Release + } else { + Profile::Debug + }; + let target = if args.module { + Target::Module + } else { + Target::Browser + }; + let build_dir = args.build_dir.unwrap_or_else(default_build_dir); + + build(profile, args.debug_symbols, target, &build_dir) +} diff --git a/crates/re_dev_tools/src/main.rs b/crates/re_dev_tools/src/main.rs new file mode 100644 index 000000000000..d2ba6dc5f5cb --- /dev/null +++ b/crates/re_dev_tools/src/main.rs @@ -0,0 +1,34 @@ +//! Crate that combines several development utilities. +//! +//! To get an overview over all tools run `pixi run dev-tools --help`. + +use argh::FromArgs; + +mod build_examples; +mod build_search_index; +mod build_web_viewer; + +#[derive(FromArgs)] +#[argh(subcommand)] +enum Commands { + BuildExamples(build_examples::Args), + BuildWebViewer(build_web_viewer::Args), + SearchIndex(build_search_index::Args), +} + +/// Various development tools for Rerun. +#[derive(FromArgs)] +struct TopLevel { + #[argh(subcommand)] + cmd: Commands, +} + +fn main() -> anyhow::Result<()> { + let args: TopLevel = argh::from_env(); + + match args.cmd { + Commands::BuildExamples(args) => build_examples::main(args), + Commands::SearchIndex(args) => build_search_index::main(args), + Commands::BuildWebViewer(args) => build_web_viewer::main(args), + } +} diff --git a/crates/re_web_viewer_server/Cargo.toml b/crates/re_web_viewer_server/Cargo.toml index 95248cde757e..da454704019f 100644 --- a/crates/re_web_viewer_server/Cargo.toml +++ b/crates/re_web_viewer_server/Cargo.toml @@ -36,7 +36,7 @@ all-features = true ## For instance: when the CI builds the docs for all crates, it uses `--all-features`, which means ## it can build the docs for this crate without having to build the web-viewer first. ## -## When not set, you must build the `.wasm` before building the crate, using `cargo run -p re_build_web_viewer`. +## When not set, you must build the `.wasm` before building the crate, using `pixi run rerun-build-web-release`. __ci = [] ## Enable telemetry using our analytics SDK. diff --git a/crates/re_web_viewer_server/README.md b/crates/re_web_viewer_server/README.md index 0fb29bef3da7..7ae7f9b849b6 100644 --- a/crates/re_web_viewer_server/README.md +++ b/crates/re_web_viewer_server/README.md @@ -9,5 +9,5 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. Serves the Rerun web viewer (`re_viewer` as Wasm and HTML) over HTTP. -When developing, you must run `cargo r -p re_build_web_viewer -- --debug` (or `--release`), before building this package. +When developing, you must run `pixi run rerun-build-web` (or `pixi run rerun-build-web-release`), before building this package. This is done automatically with `pixi run rerun-web`. diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 7f918fa81cf6..9ccb452f5d2e 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -1,4 +1,4 @@ -# This file is read in `compare_snippet_output.py` and the `snippets` command in `re_build_examples`. +# This file is read in `compare_snippet_output.py` and the `snippets` command in `re_dev_tools`/`build_examples`. # These entries won't run at all. # diff --git a/pixi.toml b/pixi.toml index 45194fb82a20..5a9242e032a4 100644 --- a/pixi.toml +++ b/pixi.toml @@ -56,13 +56,13 @@ rerun-web = { cmd = "cargo run --package rerun-cli --no-default-features --featu # # This installs the `wasm32-unknown-unknown` rust target if it's not already installed. # (this looks heavy but takes typically below 0.1s!) -rerun-build-web = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --debug" +rerun-build-web = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer --debug" # Compile the web-viewer wasm and the cli. # # This installs the `wasm32-unknown-unknown` rust target if it's not already installed. # (this looks heavy but takes typically below 0.1s!) -rerun-build-web-cli = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --debug && cargo build --package rerun-cli --no-default-features --features web_viewer" +rerun-build-web-cli = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer --debug && cargo build --package rerun-cli --no-default-features --features web_viewer" # Compile and run the web-viewer in release mode via rerun-cli. # @@ -78,12 +78,10 @@ rerun-web-release = { cmd = "cargo run --package rerun-cli --no-default-features # # This installs the `wasm32-unknown-unknown` rust target if it's not already installed. # (this looks heavy but takes typically below 0.1s!) -rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run -p re_build_web_viewer -- --release -g" +rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer --release -g" rs-check = "rustup target add wasm32-unknown-unknown && python scripts/ci/rust_checks.py" -build-examples = "cargo run -q --locked -p re_build_examples --" - # Code formatting for all languages. format = { depends_on = ["py-fmt", "cpp-fmt", "toml-fmt", "misc-fmt"] } fmt = { depends_on = ["format"] } @@ -137,9 +135,12 @@ py-plot-dashboard = { cmd = "python tests/python/plot_dashboard_stress/main.py", ] } rs-plot-dashboard = { cmd = "cargo r -p plot_dashboard_stress --release --" } +dev-tools = "cargo run -q --locked -p re_dev_tools --" +build-examples = "cargo run -q --locked -p re_dev_tools -- build-examples" + # Build the documentation search index. # See `pixi run search-index --help` for more information. -search-index = "cargo run -p re_build_search_index --release --" +search-index = "cargo run -q --locked -p re_dev_tools -- search-index" # Start a local meilisearch instance at `localhost:7700` with master key `test`. # This should only be used for testing the search index locally. diff --git a/rerun_cpp/docs/Doxyfile b/rerun_cpp/docs/Doxyfile index d44f1a409476..9b9e39fcb46d 100644 --- a/rerun_cpp/docs/Doxyfile +++ b/rerun_cpp/docs/Doxyfile @@ -1773,7 +1773,7 @@ GENERATE_MAN = NO # captures the structure of the code including all documentation. # The default value is: NO. -GENERATE_XML = YES # Generated files are used in `re_build_search_index` +GENERATE_XML = YES # Generated files are used in `build_search_index` #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output diff --git a/rerun_js/web-viewer/package.json b/rerun_js/web-viewer/package.json index 534416d3eca3..2c67800b8ea5 100644 --- a/rerun_js/web-viewer/package.json +++ b/rerun_js/web-viewer/package.json @@ -11,8 +11,8 @@ } ], "scripts": { - "build:wasm": "cargo run -p re_build_web_viewer -- --release -g --module -o rerun_js/web-viewer", - "build:wasm:debug": "cargo run -p re_build_web_viewer -- --debug --module -o rerun_js/web-viewer", + "build:wasm": "cargo run -p re_dev_tools -- build-web-viewer --release -g --module -o rerun_js/web-viewer", + "build:wasm:debug": "cargo run -p re_dev_tools -- build-web-viewer --module -o rerun_js/web-viewer", "build:types": "tsc --noEmit && dts-buddy", "build": "npm run build:wasm && npm run build:types" }, @@ -53,4 +53,4 @@ "dts-buddy": "^0.3.0", "typescript": "^5.2.2" } -} \ No newline at end of file +} diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 2c1cca4fbaf8..51d3ad70af7d 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -2,7 +2,7 @@ """ Generate an index table and rendered pages for the common APIs. -NOTE: When changing anything in this file, also consider how it affects `re_build_search_index/src/ingest/python.rs`. +NOTE: When changing anything in this file, also consider how it affects `crates/re_dev_tools/src/build_search_index/ingest/python.rs`. The top-level index file should look like ``` diff --git a/scripts/ci/build_and_upload_wheels.py b/scripts/ci/build_and_upload_wheels.py index 147de0453906..d2c681350ffb 100755 --- a/scripts/ci/build_and_upload_wheels.py +++ b/scripts/ci/build_and_upload_wheels.py @@ -65,7 +65,7 @@ def __str__(self) -> str: def build_and_upload(bucket: Bucket, mode: BuildMode, gcs_dir: str, target: str, compatibility: str) -> None: if mode is BuildMode.PYPI: # Only build web viewer when publishing to pypi - run("pixi run cargo run --quiet --locked -p re_build_web_viewer -- --release -g") + run("pixi run rerun-build-web-release") maturin_feature_flags = "--no-default-features --features pypi" elif mode is BuildMode.PR: maturin_feature_flags = "--no-default-features --features extension-module" diff --git a/scripts/screenshot_compare/build_screenshot_compare.py b/scripts/screenshot_compare/build_screenshot_compare.py index 9a485efaa81b..2b5cebd3175d 100755 --- a/scripts/screenshot_compare/build_screenshot_compare.py +++ b/scripts/screenshot_compare/build_screenshot_compare.py @@ -8,7 +8,7 @@ - The screenshots listed in .fbs files (crates/re_types/definitions/rerun/**/*.fbs), and the corresponding snippets in the docs (docs/snippets/*.rs) -- The `rerun.io/viewer` examples, as built by the `re_build_examples` script. +- The `rerun.io/viewer` examples, as built by the `re_dev_tools`/`build_examples` script. The comparisons are generated in the `compare_screenshot` directory. Use the `--serve` option to show them in a browser. @@ -146,7 +146,7 @@ def collect_snippets() -> Iterable[Example]: # ==================================================================================================== # DEMO EXAMPLES # -# We run the `build_examples` script and scrap the output "example_data" directory. +# We run the `re_dev_tools`/`build_examples` script and scrap the output "example_data" directory. # ==================================================================================================== @@ -154,15 +154,15 @@ def build_examples() -> None: # fmt: off cmd = [ "cargo", "run", "--locked", - "-p", "re_build_examples", "--", - "rrd", "example_data", + "-p", "re_dev_tools", "--", + "build-examples", "rrd", "example_data", ] run(cmd, cwd=RERUN_DIR) cmd = [ "cargo", "run", "--locked", - "-p", "re_build_examples", "--", - "manifest", "example_data/examples_manifest.json", + "-p", "re_dev_tools", "--", + "build-examples", "manifest", "example_data/examples_manifest.json", ] run(cmd, cwd=RERUN_DIR) # fmt: on diff --git a/web_viewer/README.md b/web_viewer/README.md index c532f4ace282..16532e2a3766 100644 --- a/web_viewer/README.md +++ b/web_viewer/README.md @@ -2,4 +2,4 @@ This folder contains the files required for the web viewer app. You can build the web viewer with: -`cargo r -p re_build_web_viewer -- --release -g` +`pixi run rerun-build-web-release` From 78d281a921b82213da5aba81d952940ee790f5f5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 15 Apr 2024 18:08:22 +0200 Subject: [PATCH 298/508] Fix rust ci not running on cargo.lock changes (#5980) ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{pr.number}}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/on_pull_request.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index f4b3feb7614a..40e8e21c7184 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -99,6 +99,7 @@ jobs: filters: | rust_changes: # - .github/**/*.yml - this is tempting, but leads to constant rebuilds + - Cargo.lock - pixi.lock # maybe out build commands have changed - pixi.toml # maybe out build commands have changed - scripts/ci/* @@ -119,6 +120,7 @@ jobs: filters: | web_changes: # - .github/**/*.yml - this is tempting, but leads to constant rebuilds + - Cargo.lock - pixi.lock # maybe out build commands have changed - pixi.toml # maybe out build commands have changed - scripts/ci/* From 61af62243666c7c6094156421a775130ea9a438f Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 16 Apr 2024 09:31:36 +0200 Subject: [PATCH 299/508] Update tornado for python notebook example to address security issue (#5981) ### What * part of https://github.com/rerun-io/rerun/issues/5927 tested the notebook locally with this dependency and it worked for me --- examples/python/notebook/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/python/notebook/requirements.txt b/examples/python/notebook/requirements.txt index 3802de423c95..ed3e15cdccda 100644 --- a/examples/python/notebook/requirements.txt +++ b/examples/python/notebook/requirements.txt @@ -8,4 +8,4 @@ rerun-sdk # See e.g. https://github.com/jupyter/notebook/issues/6721 jupyter_client<8 pyzmq<25 -tornado<=6.1 +tornado<=6.3.2 From 88a94ee3bad5c02da1c10e243280601c6d3221dd Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 16 Apr 2024 09:32:54 +0200 Subject: [PATCH 300/508] Merge check_requirements.py into lint.py (#5982) ### What * Fixes #5893 --- .github/workflows/contrib_checks.yml | 9 +----- .github/workflows/reusable_checks.yml | 3 -- scripts/ci/check_requirements.py | 46 --------------------------- scripts/lint.py | 41 ++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 57 deletions(-) delete mode 100755 scripts/ci/check_requirements.py diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index b354144937f5..18bac34afa00 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -116,15 +116,8 @@ jobs: - name: Check for too large files run: pixi run check-large-files - - name: Check Python example requirements - shell: bash - run: | - pixi run ./scripts/ci/check_requirements.py - - name: Check Python example thumbnails - shell: bash - run: | - pixi run ./scripts/ci/thumbnails.py check + run: pixi run ./scripts/ci/thumbnails.py check spell-check: name: Spell Check diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 9b663e1d1bfc..33f7dd4e95df 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -116,9 +116,6 @@ jobs: - name: Check for too large files run: pixi run check-large-files - - name: Check Python example requirements - run: pixi run ./scripts/ci/check_requirements.py - - name: Check Python example thumbnails run: pixi run ./scripts/ci/thumbnails.py check diff --git a/scripts/ci/check_requirements.py b/scripts/ci/check_requirements.py deleted file mode 100755 index 7b5b925dad9c..000000000000 --- a/scripts/ci/check_requirements.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 -from __future__ import annotations - -import os -from glob import glob - - -def main() -> None: - failed = False - - print("Checking `examples/python/requirements.txt`...") - with open("examples/python/requirements.txt") as f: - lines = f.read().strip().splitlines() - sorted_lines = lines.copy() - sorted_lines.sort() - requirements = set(lines) - - missing = [] - for path in glob("examples/python/*/requirements.txt"): - line = f"-r {os.path.relpath(path, 'examples/python')}" - if line not in requirements: - missing.append(line) - - if len(missing) != 0: - print("\n`examples/python/requirements.txt` is missing the following requirements:") - for line in missing: - print(line) - failed = True - - if lines != sorted_lines: - print("\n`examples/python/requirements.txt` is not correctly sorted.") - failed = True - - if failed: - print("\nHere is what `examples/python/requirements.txt` should contain:") - expected = glob("examples/python/*/requirements.txt") - expected.sort() - for path in expected: - print(f"-r {os.path.relpath(path, 'examples/python')}") - exit(1) - else: - print("All clear.") - - -if __name__ == "__main__": - main() diff --git a/scripts/lint.py b/scripts/lint.py index 452449c4acd4..1faf674ee752 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -9,6 +9,7 @@ from __future__ import annotations import argparse +from glob import glob import os import re import sys @@ -959,6 +960,44 @@ def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: return error_count +def lint_example_requirements() -> int: + """Check that `examples/python/requirements.txt` contains all requirements from the subdirectories and is correctly sorted.""" + + failed = False + + with open("examples/python/requirements.txt") as f: + lines = f.read().strip().splitlines() + sorted_lines = lines.copy() + sorted_lines.sort() + requirements = set(lines) + + missing = [] + for path in glob("examples/python/*/requirements.txt"): + line = f"-r {os.path.relpath(path, 'examples/python')}" + if line not in requirements: + missing.append(line) + + if len(missing) != 0: + print("\n`examples/python/requirements.txt` is missing the following requirements:") + for line in missing: + print(line) + failed = True + + if lines != sorted_lines: + print("\n`examples/python/requirements.txt` is not correctly sorted.") + failed = True + + if failed: + print("\nHere is what `examples/python/requirements.txt` should contain:") + expected = glob("examples/python/*/requirements.txt") + expected.sort() + for path in expected: + print(f"-r {os.path.relpath(path, 'examples/python')}") + return 1 + + return 0 + + def main() -> None: # Make sure we are bug free before we run: test_lint_line() @@ -1062,6 +1101,8 @@ def main() -> None: # Since no files have been specified, we also run the global lints. num_errors += lint_crate_docs(should_ignore) + num_errors += lint_example_requirements() + if num_errors == 0: print(f"{sys.argv[0]} finished without error") sys.exit(0) From a5bafa84b92422697087a02a3f5060b3b826c409 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 16 Apr 2024 09:36:05 +0200 Subject: [PATCH 301/508] Allow PR bodies without any checkboxes (#5983) :point_up: It's very annoying that the CI fails for PR bodies without checkboxes in them. --- scripts/ci/check_pr_checkboxes.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/ci/check_pr_checkboxes.py b/scripts/ci/check_pr_checkboxes.py index 160a7697278d..0055f5b90b7e 100755 --- a/scripts/ci/check_pr_checkboxes.py +++ b/scripts/ci/check_pr_checkboxes.py @@ -29,12 +29,6 @@ def main() -> None: if "* [ ]" in body_lower or "- [ ]" in body_lower: print("PR contains unchecked checkboxes") exit(1) - elif "* [x]" in body_lower or "- [x]" in body_lower: - print("All clear") - exit(0) - else: - print("Don't delete the PR description") - exit(1) if __name__ == "__main__": From c3de17252837066949a41065302bcfa5cf400d33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 09:37:24 +0200 Subject: [PATCH 302/508] Build(deps): Bump rustix from 0.37.19 to 0.37.27 (#5979) --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36b29ac7242e..6047ec37e818 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,7 +418,7 @@ dependencies = [ "log", "parking", "polling 2.8.0", - "rustix 0.37.19", + "rustix 0.37.27", "slab", "socket2", "waker-fn", @@ -2749,7 +2749,7 @@ checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix 0.37.19", + "rustix 0.37.27", "windows-sys 0.48.0", ] @@ -5781,9 +5781,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", @@ -6280,7 +6280,7 @@ dependencies = [ "cfg-if", "fastrand 1.9.0", "redox_syscall 0.3.5", - "rustix 0.37.19", + "rustix 0.37.27", "windows-sys 0.45.0", ] From 5f1115e53df355c0cbb845df2c0adfb2c46179a5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 16 Apr 2024 12:58:46 +0200 Subject: [PATCH 303/508] Fix rust wasm check not using clippy_wasm/clippy.toml (#5987) ### What https://github.com/rerun-io/rerun/pull/5922 broke wasm check by not specifying the purpose made clippy.toml for wasm. Tested by putting ```rs std::thread::spawn(move || { std::thread::sleep(std::time::Duration::from_secs(1)); }); ``` into re_space_view and then running `pixi run rs-check` (with a bunch of checks commented out inside the rust check script) to verify that we get the desired error. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{pr.number}}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Emil Ernerfeldt --- scripts/ci/rust_checks.py | 5 ++++- scripts/clippy_wasm/clippy.toml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/ci/rust_checks.py b/scripts/ci/rust_checks.py index ff5305b182c3..2aa21689d2ed 100755 --- a/scripts/ci/rust_checks.py +++ b/scripts/ci/rust_checks.py @@ -19,7 +19,7 @@ def __init__(self, command: str, duration: float) -> None: self.duration = duration -def run_cargo(cargo_cmd, cargo_args: str) -> Timing: +def run_cargo(cargo_cmd, cargo_args: str, clippy_conf: str | None = None) -> Timing: args = ["cargo", cargo_cmd] if cargo_cmd != "deny": args.append("--quiet") @@ -32,6 +32,8 @@ def run_cargo(cargo_cmd, cargo_args: str) -> Timing: env = os.environ.copy() env["RUSTFLAGS"] = "--deny warnings" env["RUSTDOCFLAGS"] = "--deny warnings --deny rustdoc::missing_crate_level_docs" + if clippy_conf is not None: + env["CLIPPY_CONF_DIR"] = clippy_conf result = subprocess.run(args, env=env, check=False, capture_output=True, text=True) if result.returncode != 0: @@ -110,6 +112,7 @@ def main() -> None: run_cargo( "cranky", "--all-features --target wasm32-unknown-unknown --target-dir target_wasm -p re_viewer -- --deny warnings", + clippy_conf="scripts/clippy_wasm", # Use scripts/clippy_wasm/clippy.toml ) ) # Check re_renderer examples for wasm32. diff --git a/scripts/clippy_wasm/clippy.toml b/scripts/clippy_wasm/clippy.toml index c475058e4748..ba93b917d52d 100644 --- a/scripts/clippy_wasm/clippy.toml +++ b/scripts/clippy_wasm/clippy.toml @@ -1,4 +1,4 @@ -# This is used by `scripts/clippy_wasm.sh` so we can forbid some methods that are not available in wasm. +# This is used by `scripts/rust_checks.py` wasm checks so we can forbid some methods that are not available in wasm. # # We cannot forbid all these methods in the main `clippy.toml` because of # https://github.com/rust-lang/rust-clippy/issues/10406 From 44c4d3f95d004f640878f167e020f6f12b644ff7 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 16 Apr 2024 13:07:45 +0200 Subject: [PATCH 304/508] Fix various links in rust, python and toml files (#5986) ### What Code files are now included in link checking. * Fixes #5925 Some issues encountered: * globs don't respect exclude_files which makes working with this locally harder https://github.com/lycheeverse/lychee/issues/1405 * can't specify extensions / correct files aren't picked up automatically https://github.com/lycheeverse/lychee/issues/410 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5986?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/5986?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/5986) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/reusable_checks.yml | 5 +- crates/re_crash_handler/src/lib.rs | 6 +- crates/re_types_core/src/lib.rs | 8 +-- crates/re_viewer/src/app.rs | 3 +- deny.toml | 4 +- examples/rust/log_file/src/main.rs | 2 +- lychee.toml | 88 ++++++++++++++++++++++----- pixi.toml | 5 +- rerun_py/Cargo.toml | 2 +- rerun_py/build.rs | 2 +- rerun_py/rerun_sdk/rerun/_log.py | 4 +- 11 files changed, 95 insertions(+), 34 deletions(-) diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 33f7dd4e95df..5692a7164894 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -172,4 +172,7 @@ jobs: with: fail: true lycheeVersion: "0.14.3" - args: "--base . --cache --max-cache-age 1d ." + # When given a directory, lychee checks only markdown, html and text files, everything else we have to glob in manually. + # Pass --verbose, so that all considered links are printed, making it easier to debug. + args: | + --verbose --base . --cache --max-cache-age 1d . "**/*.rs" "**/*.toml" "**/*.hpp" "**/*.cpp" "**/CMakeLists.txt" "**/*.py" "**/*.yml" diff --git a/crates/re_crash_handler/src/lib.rs b/crates/re_crash_handler/src/lib.rs index c543527bc133..52c99abb6fe0 100644 --- a/crates/re_crash_handler/src/lib.rs +++ b/crates/re_crash_handler/src/lib.rs @@ -59,7 +59,7 @@ fn install_panic_hook(_build_info: BuildInfo) { eprintln!( "\n\ - Troubleshooting Rerun: https://www.rerun.io/docs/getting-started/troubleshooting\n\ + Troubleshooting Rerun: https://www.rerun.io/docs/getting-started/troubleshooting \n\ Report bugs: https://github.com/rerun-io/rerun/issues" ); @@ -129,9 +129,9 @@ fn install_signal_handler(build_info: BuildInfo) { write_to_stderr(signal_name); write_to_stderr("\n"); write_to_stderr( - "Troubleshooting Rerun: https://www.rerun.io/docs/getting-started/troubleshooting\n", + "Troubleshooting Rerun: https://www.rerun.io/docs/getting-started/troubleshooting \n", ); - write_to_stderr("Report bugs: https://github.com/rerun-io/rerun/issues\n"); + write_to_stderr("Report bugs: https://github.com/rerun-io/rerun/issues \n"); write_to_stderr("\n"); } diff --git a/crates/re_types_core/src/lib.rs b/crates/re_types_core/src/lib.rs index 707471d76bf1..e50b6ef053fe 100644 --- a/crates/re_types_core/src/lib.rs +++ b/crates/re_types_core/src/lib.rs @@ -28,18 +28,18 @@ /// [`AsComponents::as_component_batches`], which describes how the bundle can be interpreted /// as a set of [`ComponentBatch`]es: arrays of components that are ready to be serialized. /// -/// Have a look at our [Custom Data] example to learn more about handwritten bundles. +/// Have a look at our [Custom Data Loader] example to learn more about handwritten bundles. /// /// [IDL definitions]: https://github.com/rerun-io/rerun/tree/latest/crates/re_types/definitions/rerun -/// [Custom Data]: https://github.com/rerun-io/rerun/blob/latest/examples/rust/custom_data/src/main.rs +/// [Custom Data Loader]: https://github.com/rerun-io/rerun/blob/latest/examples/rust/custom_data_loader pub trait AsComponents { /// Exposes the object's contents as a set of [`ComponentBatch`]s. /// /// This is the main mechanism for easily extending builtin archetypes or even writing /// fully custom ones. - /// Have a look at our [Custom Data] example to learn more about extending archetypes. + /// Have a look at our [Custom Data Loader] example to learn more about extending archetypes. /// - /// [Custom Data]: https://github.com/rerun-io/rerun/blob/latest/examples/rust/custom_data/src/main.rs + /// [Custom Data Loader]: https://github.com/rerun-io/rerun/tree/latest/examples/rust/custom_data_loader // // NOTE: Don't bother returning a CoW here: we need to dynamically discard optional components // depending on their presence (or lack thereof) at runtime anyway. diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index ebd1013d4dae..4332f02f3af7 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -545,7 +545,8 @@ impl App { UICommand::OpenWebHelp => { egui_ctx.open_url(egui::output::OpenUrl { - url: "https://www.rerun.io/docs/getting-started/viewer-walkthrough".to_owned(), + url: "https://www.rerun.io/docs/getting-started/navigating-the-viewer" + .to_owned(), new_tab: true, }); } diff --git a/deny.toml b/deny.toml index 07df1b13bf8b..dfc8af646a78 100644 --- a/deny.toml +++ b/deny.toml @@ -81,8 +81,8 @@ allow = [ "BSD-3-Clause", # https://tldrlegal.com/license/bsd-3-clause-license-(revised) "BSL-1.0", # https://tldrlegal.com/license/boost-software-license-1.0-explained "CC0-1.0", # https://creativecommons.org/publicdomain/zero/1.0/ - "ISC", # https://tldrlegal.com/license/-isc-license - "LicenseRef-UFL-1.0", # https://tldrlegal.com/license/ubuntu-font-license,-1.0 - no official SPDX, see https://github.com/emilk/egui/issues/2321 + "ISC", # https://www.tldrlegal.com/license/isc-license + "LicenseRef-UFL-1.0", # See https://github.com/emilk/egui/issues/2321 "MIT-0", # https://choosealicense.com/licenses/mit-0/ "MIT", # https://tldrlegal.com/license/mit-license "MPL-2.0", # https://www.mozilla.org/en-US/MPL/2.0/FAQ/ - see Q11. Used by webpki-roots on Linux. diff --git a/examples/rust/log_file/src/main.rs b/examples/rust/log_file/src/main.rs index 0ad21d312f5a..26ceabb9d089 100644 --- a/examples/rust/log_file/src/main.rs +++ b/examples/rust/log_file/src/main.rs @@ -1,6 +1,6 @@ //! Demonstrates how to log any file from the SDK using the `DataLoader` machinery. //! -//! See for more information. +//! See for more information. //! //! Usage: //! ``` diff --git a/lychee.toml b/lychee.toml index 0fc7002c378b..aeb1fc8845f4 100644 --- a/lychee.toml +++ b/lychee.toml @@ -8,29 +8,46 @@ # https://github.com/lycheeverse/lychee/blob/master/lychee.example.toml # # Run `lychee . --dump` to list all found links that are being checked. +# +# Note that by default lychee will only check markdown and html files, +# to check any other files you have to point to them explicitly, e.g.: +# `lychee **/*.rs` +# To make things worse, `exclude_path` is ignored for these globs, +# so local runs with lots of gitignored files will be slow. +# (https://github.com/lycheeverse/lychee/issues/1405) +# +# This unfortunately doesn't list anything for non-glob checks. ################################################################################ # Maximum number of concurrent link checks. # Workaround for "too many open files" error on MacOS, see https://github.com/lycheeverse/lychee/issues/1248 max_concurrency = 32 +# Check links inside `` and `

` blocks as well as Markdown code blocks.
+include_verbatim = true
 
-# URLs to check (supports regex). Has preference over all excludes.
+# Proceed for server connections considered insecure (invalid TLS).
+insecure = true
+
+# Exclude these filesystem paths from getting checked.
 exclude_path = [
   # Unfortunately lychee doesn't yet read .gitignore https://github.com/lycheeverse/lychee/issues/1331
   # The following entries are there because of that:
+  ".git",
   "__pycache__",
   "_deps/",
   ".pixi",
   "build",
   "docs/python/",
+  "rerun_cpp/_deps",
   "rerun_cpp/docs/html",
   "rerun_cpp/docs/xml",
+  "rerun_cpp/tmp/",
   "rerun_py/site/",
   "target_ra",
   "target_wasm",
   "target",
-  "rerun_cpp/tmp/",
+  "venv",
 
   # Actually ignored files beyond .gitignore
   "scripts/screenshot_compare/assets/templates/",
@@ -38,19 +55,60 @@ exclude_path = [
 
 # Exclude URLs and mail addresses from checking (supports regex).
 exclude = [
-  '.*?speculative-link',                                      # Skip speculative links
-  '.github/workflows/.*.yml',                                 # GitHub action workflows cause issues on CI.
-  '\$relpath\^',                                              # Relative paths as used by rerun_cpp's doc header.
-  '%7B%7B.+%7D%7D',                                           # Ignore things that look like links because of `href` but are actually replacement strings. The URL escaping is for '{{.+}}' (this seems to be needed for html embedded urls since lychee assumes they use this encoding).
-  'https://crates.io/crates/.*',                              # Avoid crates.io rate-limiting
-  'https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html', # Nyud links are down every now and then.
-  'https://eigen.tuxfamily.org/',                             # Website down https://gitlab.com/libeigen/eigen/-/issues/2804
-  'https://fonts.googleapis.com/',                            # Font API entrypoint, not a link.
-  'https://fonts.gstatic.com/',                               # Font API entrypoint, not a link.
-  'https://github.com/rerun-io/rerun/pull/\.*',               # Ignore links to our own pull requests (typically in changelog).
-  'https://github.com/rerun-io/rerun/commit/\.*',             # Ignore links to our own commits (typically in changelog).
-  'https://stackoverflow.com/.',                              # Stackoverflow links are no longer accessible from CI.
-  'https://www.tensorflow.org/',                              # tensorflow.org apparently blocks CI.
+  # Skip speculative links
+  '.*?speculative-link',
+
+  # Strings with replacements.
+  '/__VIEWER_VERSION__/', # Replacement variable __VIEWER_VERSION__.
+  '/\$',                  # Replacement variable $.
+  '/GIT_HASH/',           # Replacement variable GIT_HASH.
+  '\{\}',                 # Ignore links with string interpolation.
+  '\$relpath\^',          # Relative paths as used by rerun_cpp's doc header.
+  '%7B.+%7D',             # Ignore strings that look like ready to use links but contain a replacement strings. The URL escaping is for '{.+}' (this seems to be needed for html embedded urls since lychee assumes they use this encoding).
+  '%7B%7D',               # Ignore links with string interpolation, escaped variant.
+
+  # Local links that require further setup.
+  'http://127.0.0.1',
+  'http://localhost',
+  'recording:/',      # rrd recording link.
+  'ws:/',
+  're_viewer.js',     # Build artifact that html is linking to.
+
+  # Api endpoints.
+  'https://fonts.googleapis.com/', # Font API entrypoint, not a link.
+  'https://fonts.gstatic.com/',    # Font API entrypoint, not a link.
+  'https://tel.rerun.io/',         # Analytics endpoint.
+
+  # Avoid rate limiting.
+  'https://crates.io/crates/.*',                  # Avoid crates.io rate-limiting
+  'https://github.com/rerun-io/rerun/commit/\.*', # Ignore links to our own commits (typically in changelog).
+  'https://github.com/rerun-io/rerun/pull/\.*',   # Ignore links to our own pull requests (typically in changelog).
+
+  # Intentionally faked links.
+  'file://foo',
+  'http://foo.com/',
+  'https://link.to',
+  'https://static.rerun.io/my_screenshot/',
+
+  # Link fragments and data links in examples.
+  'https://raw.githubusercontent.com/googlefonts/noto-emoji/', # URL fragment.
+  'https://static.rerun.io/rgbd_dataset',                      # Base data link for rgbd dataset.
+  'https://storage.googleapis.com/',                           # Storage API entrypoint, not a link.
+
+  # Not accessible from CI.
+  '.github/workflows/.*.yml',            # GitHub action workflows cause issues on CI.
+  'https://stackoverflow.com/.',         # Stackoverflow links are no longer accessible from CI.
+  'https://www.tensorflow.org/',         # tensorflow.org apparently blocks CI.
+  'https://9p.io/sys/doc/lexnames.html', # Works locally but on ci we get: `Failed: Network error: error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:ssl/statem/extensions.c:946:`
+
+  # Need GitHub login.
+  'https://github.com/rerun-io/landing',
+  'https://github.com/rerun-io/documentation',
+
+  # Temporarily down or not accessible.
+  'https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html',       # Nyud links are down every now and then.
+  'https://eigen.tuxfamily.org/',                                   # Website down https://gitlab.com/libeigen/eigen/-/issues/2804
+  'https://github.com/rerun-io/rerun/releases/download/prerelease', # Pre-release downloads may go down while a pre-release updates or pre-release CI partially breaks.
 
   # Works but is really slow at times:
   'https://openaccess.thecvf.com/content/CVPR2023/html/Du_Learning_To_Render_Novel_Views_From_Wide-Baseline_Stereo_Pairs_CVPR_2023_paper.html',
diff --git a/pixi.toml b/pixi.toml
index 5a9242e032a4..4d261315d216 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -148,7 +148,6 @@ search-index = "cargo run -q --locked -p re_dev_tools -- search-index"
 meilisearch = "meilisearch --db-path=./meilisearch/data.ms --dump-dir=./meilisearch/dumps/ --snapshot-dir=./meilisearch/snapshots/ --env=development --no-analytics --experimental-reduce-indexing-memory-usage --master-key=test"
 
 # Update the design_tokens.json used to style the GUI.
-# See https://rerun-design-guidelines.netlify.app/tokens for their meanings.
 # To update the upstream `design_tokens.json`, modify
 # https://github.com/rerun-io/documentation/blob/main/src/utils/tokens.ts and push to main.
 download-design-tokens = "curl --fail https://rerun-docs.netlify.app/api/tokens | jq > crates/re_ui/data/design_tokens.json"
@@ -173,7 +172,7 @@ mkdocs-gen-files = "==0.5.0"
 mkdocs-literate-nav = "==0.6.1"
 mkdocs-material = "==9.4.7"
 mkdocs-material-extensions = "==1.3"
-mkdocs-redirects = { git = "https://github.com/rerun-io/mkdocs-redirects.git", rev = "fb6b074554975ba7729d68d04957ce7c7dfd5003" } # forked mkdocs-redirects with https://github.com/rerun-io/mkdocs-redirects/commit/d367a0847928438b66f73508e49852be1190409bmkdocs = "==1.5.3"
+mkdocs-redirects = { git = "https://github.com/rerun-io/mkdocs-redirects.git", rev = "fb6b074554975ba7729d68d04957ce7c7dfd5003" } # forked mkdocs-redirects ==1.5.3
 mkdocstrings = "==0.23.0"
 mkdocstrings-python = "==1.7.3"
 sphobjinv = "==2.3.1"
@@ -236,7 +235,7 @@ rerun = "rerun"
 # platforms (including linux-aarch64), or added conditionally.
 #
 # Hints:
-# - To check a given package, go to https://prefix.dev/channels/conda-forge/packages/XXXX. It should support Windows,
+# - To check a given package, go to the package on https://prefix.dev/channels/conda-forge/. It should support Windows,
 #   x86_64 and aarch64 macOS architectures, and x86_64 and aarch64 Linux architectures.
 # - Some pure Python packages may wrongly be tagged as platform-specific. In this case, use `[pypi-dependencies]`
 #   instead (e.g. `nox`).
diff --git a/rerun_py/Cargo.toml b/rerun_py/Cargo.toml
index 3394a559bbe1..b93a006fb8fb 100644
--- a/rerun_py/Cargo.toml
+++ b/rerun_py/Cargo.toml
@@ -22,7 +22,7 @@ pypi = ["extension-module", "native_viewer", "web_viewer"]
 ## but we cannot enable it when building tests and benchmarks, so we
 ## must make it an opt-in feature.
 ## * 
-## * 
+## * 
 extension-module = ["pyo3/extension-module"]
 
 ## Support spawning a native Rerun viewer with `spawn()`.
diff --git a/rerun_py/build.rs b/rerun_py/build.rs
index 0da90e56d92e..bf40581aca5a 100644
--- a/rerun_py/build.rs
+++ b/rerun_py/build.rs
@@ -1,5 +1,5 @@
 fn main() {
-    // Required for `cargo build` to work on mac: https://pyo3.rs/v0.14.2/building_and_distribution.html#macos
+    // Required for `cargo build` to work on mac: https://pyo3.rs/main/building-and-distribution#macos
     pyo3_build_config::add_extension_module_link_args();
 
     re_build_tools::export_build_info_vars_for_crate("rerun_py");
diff --git a/rerun_py/rerun_sdk/rerun/_log.py b/rerun_py/rerun_sdk/rerun/_log.py
index 0f541b27bb35..1b3573e8ebce 100644
--- a/rerun_py/rerun_sdk/rerun/_log.py
+++ b/rerun_py/rerun_sdk/rerun/_log.py
@@ -347,7 +347,7 @@ def log_file_from_path(
     This method blocks until either at least one `DataLoader` starts
     streaming data in or all of them fail.
 
-    See  for more information.
+    See  for more information.
 
     Parameters
     ----------
@@ -412,7 +412,7 @@ def log_file_from_contents(
     This method blocks until either at least one `DataLoader` starts
     streaming data in or all of them fail.
 
-    See  for more information.
+    See  for more information.
 
     Parameters
     ----------

From 279c73f5bd9e8030288da32bfcb81910b148a2c8 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Tue, 16 Apr 2024 15:12:33 +0200
Subject: [PATCH 305/508] Fix main ci - cranky didn't understand config path
 env var (#5989)

### What

Worked locally already, but ci didn't find the clippy config file so
far, trying to address that here.
Tested that config is still picked up by putting `let _ =
std::time::SystemTime::now();` into space_view.rs

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5989?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5989?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5989)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 scripts/ci/rust_checks.py | 6 ++++--
 scripts/lint.py           | 2 +-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/scripts/ci/rust_checks.py b/scripts/ci/rust_checks.py
index 2aa21689d2ed..d6cfa115a2e2 100755
--- a/scripts/ci/rust_checks.py
+++ b/scripts/ci/rust_checks.py
@@ -33,7 +33,9 @@ def run_cargo(cargo_cmd, cargo_args: str, clippy_conf: str | None = None) -> Tim
     env["RUSTFLAGS"] = "--deny warnings"
     env["RUSTDOCFLAGS"] = "--deny warnings --deny rustdoc::missing_crate_level_docs"
     if clippy_conf is not None:
-        env["CLIPPY_CONF_DIR"] = clippy_conf
+        env["CLIPPY_CONF_DIR"] = (
+            f"{os.getcwd()}/{clippy_conf}"  # Clippy has issues finding this directory on CI when we're not using an absolute path here.
+        )
 
     result = subprocess.run(args, env=env, check=False, capture_output=True, text=True)
     if result.returncode != 0:
@@ -112,7 +114,7 @@ def main() -> None:
             run_cargo(
                 "cranky",
                 "--all-features --target wasm32-unknown-unknown --target-dir target_wasm -p re_viewer -- --deny warnings",
-                clippy_conf="scripts/clippy_wasm", # Use scripts/clippy_wasm/clippy.toml
+                clippy_conf="scripts/clippy_wasm",  # Use ./scripts/clippy_wasm/clippy.toml
             )
         )
         # Check re_renderer examples for wasm32.
diff --git a/scripts/lint.py b/scripts/lint.py
index 1faf674ee752..bf52210c7a75 100755
--- a/scripts/lint.py
+++ b/scripts/lint.py
@@ -9,10 +9,10 @@
 from __future__ import annotations
 
 import argparse
-from glob import glob
 import os
 import re
 import sys
+from glob import glob
 from pathlib import Path
 from typing import Any, Callable, Dict, Iterator
 

From 8bb33f9a1b1ece35d0679a19b39474412362f501 Mon Sep 17 00:00:00 2001
From: Leonard Bruns 
Date: Tue, 16 Apr 2024 15:52:59 +0200
Subject: [PATCH 306/508] Update depth-guided stable diffusion example to
 diffusers 0.27.2 (#5985)

### What
Closes #5976

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5985?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG

- [PR Build Summary](https://build.rerun.io/pr/5985)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .../depth_guided_stable_diffusion/README.md   |   6 +-
 .../huggingface_pipeline.py                   | 781 ++++++++++++------
 .../depth_guided_stable_diffusion/main.py     |   4 +-
 .../requirements.txt                          |   2 +-
 4 files changed, 544 insertions(+), 249 deletions(-)

diff --git a/examples/python/depth_guided_stable_diffusion/README.md b/examples/python/depth_guided_stable_diffusion/README.md
index ac014c2628b1..3dfda2e44952 100644
--- a/examples/python/depth_guided_stable_diffusion/README.md
+++ b/examples/python/depth_guided_stable_diffusion/README.md
@@ -40,10 +40,10 @@ rr.log("prompt/uncond_input/ids", rr.Tensor(uncond_input.input_ids))
 ```
 
 ### Text embeddings
-Visualizing the text embeddings. The text embeddings are generated in response to the specific prompts used while the unconditional text embeddings represent a neutral or baseline state without specific input conditions.
+Visualizing the text embeddings (i.e., numerical representation of the input texts) from the prompt and negative prompt.
 ```python
-rr.log("prompt/text_embeddings", rr.Tensor(text_embeddings))
-rr.log("prompt/uncond_embeddings", rr.Tensor(uncond_embeddings))
+rr.log("prompt/text_embeddings", rr.Tensor(prompt_embeds))
+rr.log("prompt/negative_text_embeddings", rr.Tensor(negative_prompt_embeds))
 ```
 
 ### Depth map
diff --git a/examples/python/depth_guided_stable_diffusion/huggingface_pipeline.py b/examples/python/depth_guided_stable_diffusion/huggingface_pipeline.py
index eab92e43bd89..9928f4843ff0 100644
--- a/examples/python/depth_guided_stable_diffusion/huggingface_pipeline.py
+++ b/examples/python/depth_guided_stable_diffusion/huggingface_pipeline.py
@@ -1,13 +1,13 @@
+# Modified StableDiffusionDepth2ImgPipeline to log internal data to Rerun
 #
 # This file was originally copied from
-# https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_depth2img.py
-# commit 9b37ed33b5fa09e594b38e4e6f7477beff3bd66a
+# https://github.com/huggingface/diffusers/blob/8e963d1c2a2b6ebf2880675516809bd9a39359a4/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_depth2img.py
 #
 # The original copyright and license note are included below.
 #
 # This file has only been modified to use the Rerun SDK to log internal data for visualization.
 #
-# Copyright 2022 The HuggingFace Team. All rights reserved.
+# Copyright 2024 The HuggingFace Team. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -20,48 +20,59 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
+#
 # type: ignore
 from __future__ import annotations
 
 import contextlib
 import inspect
-from typing import Callable
-from typing import List
-from typing import Optional
-from typing import Union
+from typing import Any, Callable, Optional, Union
 
 import numpy as np
-import PIL
+import PIL.Image
 import rerun as rr  # pip install rerun-sdk
 import torch
 from diffusers.configuration_utils import FrozenDict
-from diffusers.models import AutoencoderKL
-from diffusers.models import UNet2DConditionModel
-from diffusers.pipeline_utils import DiffusionPipeline
-from diffusers.pipeline_utils import ImagePipelineOutput
-from diffusers.schedulers import DDIMScheduler
-from diffusers.schedulers import DPMSolverMultistepScheduler
-from diffusers.schedulers import EulerAncestralDiscreteScheduler
-from diffusers.schedulers import EulerDiscreteScheduler
-from diffusers.schedulers import LMSDiscreteScheduler
-from diffusers.schedulers import PNDMScheduler
-from diffusers.utils import deprecate
-from diffusers.utils import is_accelerate_available
-from diffusers.utils import logging
-from diffusers.utils import PIL_INTERPOLATION
+from diffusers.image_processor import PipelineImageInput, VaeImageProcessor
+from diffusers.loaders import LoraLoaderMixin, TextualInversionLoaderMixin
+from diffusers.models import AutoencoderKL, UNet2DConditionModel
+from diffusers.models.lora import adjust_lora_scale_text_encoder
+from diffusers.pipelines.pipeline_utils import DiffusionPipeline, ImagePipelineOutput
+from diffusers.schedulers import KarrasDiffusionSchedulers
+from diffusers.utils import (
+    PIL_INTERPOLATION,
+    USE_PEFT_BACKEND,
+    deprecate,
+    logging,
+    scale_lora_layers,
+    unscale_lora_layers,
+)
 from diffusers.utils.torch_utils import randn_tensor
 from packaging import version
-from transformers import CLIPTextModel
-from transformers import CLIPTokenizer
-from transformers import DPTFeatureExtractor
-from transformers import DPTForDepthEstimation
+from transformers import CLIPTextModel, CLIPTokenizer, DPTFeatureExtractor, DPTForDepthEstimation
 
 logger = logging.get_logger(__name__)  # pylint: disable=invalid-name
 logger.addHandler(rr.LoggingHandler("logs"))
 
 
+# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_img2img.retrieve_latents
+def retrieve_latents(
+    encoder_output: torch.Tensor, generator: Optional[torch.Generator] = None, sample_mode: str = "sample"
+):
+    if hasattr(encoder_output, "latent_dist") and sample_mode == "sample":
+        return encoder_output.latent_dist.sample(generator)
+    elif hasattr(encoder_output, "latent_dist") and sample_mode == "argmax":
+        return encoder_output.latent_dist.mode()
+    elif hasattr(encoder_output, "latents"):
+        return encoder_output.latents
+    else:
+        raise AttributeError("Could not access latents of provided encoder_output")
+
+
 # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_img2img.preprocess
 def preprocess(image):
+    deprecation_message = "The preprocess method is deprecated and will be removed in diffusers 1.0.0. Please use VaeImageProcessor.preprocess(…) instead"
+    deprecate("preprocess", "1.0.0", deprecation_message, standard_warn=False)
     if isinstance(image, torch.Tensor):
         return image
     elif isinstance(image, PIL.Image.Image):
@@ -69,7 +80,7 @@ def preprocess(image):
 
     if isinstance(image[0], PIL.Image.Image):
         w, h = image[0].size
-        w, h = map(lambda x: x - x % 8, (w, h))  # resize to integer multiple of 8
+        w, h = (x - x % 8 for x in (w, h))  # resize to integer multiple of 8
 
         image = [np.array(i.resize((w, h), resample=PIL_INTERPOLATION["lanczos"]))[None, :] for i in image]
         image = np.concatenate(image, axis=0)
@@ -82,41 +93,44 @@ def preprocess(image):
     return image
 
 
-class StableDiffusionDepth2ImgPipeline(DiffusionPipeline):
+class StableDiffusionDepth2ImgPipeline(DiffusionPipeline, TextualInversionLoaderMixin, LoraLoaderMixin):
     r"""
-    Pipeline for text-guided image to image generation using Stable Diffusion.
-    This model inherits from [`DiffusionPipeline`]. Check the superclass documentation for the generic methods the
-    library implements for all the pipelines (such as downloading or saving, running on a particular device, etc.)
+    Pipeline for text-guided depth-based image-to-image generation using Stable Diffusion.
+
+    This model inherits from [`DiffusionPipeline`]. Check the superclass documentation for the generic methods
+    implemented for all pipelines (downloading, saving, running on a particular device, etc.).
+
+    The pipeline also inherits the following loading methods:
+        - [`~loaders.TextualInversionLoaderMixin.load_textual_inversion`] for loading textual inversion embeddings
+        - [`~loaders.LoraLoaderMixin.load_lora_weights`] for loading LoRA weights
+        - [`~loaders.LoraLoaderMixin.save_lora_weights`] for saving LoRA weights
+
     Args:
+    ----
         vae ([`AutoencoderKL`]):
-            Variational Auto-Encoder (VAE) Model to encode and decode images to and from latent representations.
-        text_encoder ([`CLIPTextModel`]):
-            Frozen text-encoder. Stable Diffusion uses the text portion of
-            [CLIP](https://huggingface.co/docs/transformers/model_doc/clip#transformers.CLIPTextModel), specifically
-            the [clip-vit-large-patch14](https://huggingface.co/openai/clip-vit-large-patch14) variant.
-        tokenizer (`CLIPTokenizer`):
-            Tokenizer of class
-            [CLIPTokenizer](https://huggingface.co/docs/transformers/v4.21.0/en/model_doc/clip#transformers.CLIPTokenizer).
-        unet ([`UNet2DConditionModel`]): Conditional U-Net architecture to denoise the encoded image latents.
+            Variational Auto-Encoder (VAE) model to encode and decode images to and from latent representations.
+        text_encoder ([`~transformers.CLIPTextModel`]):
+            Frozen text-encoder ([clip-vit-large-patch14](https://huggingface.co/openai/clip-vit-large-patch14)).
+        tokenizer ([`~transformers.CLIPTokenizer`]):
+            A `CLIPTokenizer` to tokenize text.
+        unet ([`UNet2DConditionModel`]):
+            A `UNet2DConditionModel` to denoise the encoded image latents.
         scheduler ([`SchedulerMixin`]):
             A scheduler to be used in combination with `unet` to denoise the encoded image latents. Can be one of
             [`DDIMScheduler`], [`LMSDiscreteScheduler`], or [`PNDMScheduler`].
+
     """
 
+    model_cpu_offload_seq = "text_encoder->unet->vae"
+    _callback_tensor_inputs = ["latents", "prompt_embeds", "negative_prompt_embeds", "depth_mask"]
+
     def __init__(
         self,
         vae: AutoencoderKL,
         text_encoder: CLIPTextModel,
         tokenizer: CLIPTokenizer,
         unet: UNet2DConditionModel,
-        scheduler: (
-            DDIMScheduler
-            | PNDMScheduler
-            | LMSDiscreteScheduler
-            | EulerDiscreteScheduler
-            | EulerAncestralDiscreteScheduler
-            | DPMSolverMultistepScheduler
-        ),
+        scheduler: KarrasDiffusionSchedulers,
         depth_estimator: DPTForDepthEstimation,
         feature_extractor: DPTFeatureExtractor,
     ):
@@ -153,49 +167,60 @@ def __init__(
             feature_extractor=feature_extractor,
         )
         self.vae_scale_factor = 2 ** (len(self.vae.config.block_out_channels) - 1)
+        self.image_processor = VaeImageProcessor(vae_scale_factor=self.vae_scale_factor)
 
-    def enable_sequential_cpu_offload(self, gpu_id=0):
-        r"""
-        Offloads all models to CPU using accelerate, significantly reducing memory usage. When called, unet,
-        text_encoder, vae and safety checker have their state dicts saved to CPU and then are moved to a
-        `torch.device('meta') and loaded to GPU only when their specific submodule has its `forward` method called.
-        """
-        if is_accelerate_available():
-            from accelerate import cpu_offload
-        else:
-            raise ImportError("Please install accelerate via `pip install accelerate`")
-
-        device = torch.device(f"cuda:{gpu_id}")
+    # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline._encode_prompt
+    def _encode_prompt(
+        self,
+        prompt,
+        device,
+        num_images_per_prompt,
+        do_classifier_free_guidance,
+        negative_prompt=None,
+        prompt_embeds: Optional[torch.FloatTensor] = None,
+        negative_prompt_embeds: Optional[torch.FloatTensor] = None,
+        lora_scale: Optional[float] = None,
+        **kwargs,
+    ):
+        deprecation_message = "`_encode_prompt()` is deprecated and it will be removed in a future version. Use `encode_prompt()` instead. Also, be aware that the output format changed from a concatenated tensor to a tuple."
+        deprecate("_encode_prompt()", "1.0.0", deprecation_message, standard_warn=False)
+
+        prompt_embeds_tuple = self.encode_prompt(
+            prompt=prompt,
+            device=device,
+            num_images_per_prompt=num_images_per_prompt,
+            do_classifier_free_guidance=do_classifier_free_guidance,
+            negative_prompt=negative_prompt,
+            prompt_embeds=prompt_embeds,
+            negative_prompt_embeds=negative_prompt_embeds,
+            lora_scale=lora_scale,
+            **kwargs,
+        )
 
-        for cpu_offloaded_model in [self.unet, self.text_encoder, self.vae, self.depth_estimator]:
-            if cpu_offloaded_model is not None:
-                cpu_offload(cpu_offloaded_model, device)
+        # concatenate for backwards comp
+        prompt_embeds = torch.cat([prompt_embeds_tuple[1], prompt_embeds_tuple[0]])
 
-    @property
-    # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline._execution_device
-    def _execution_device(self):
-        r"""
-        Returns the device on which the pipeline's models will be executed. After calling
-        `pipeline.enable_sequential_cpu_offload()` the execution device can only be inferred from Accelerate's module
-        hooks.
-        """
-        if self.device != torch.device("meta") or not hasattr(self.unet, "_hf_hook"):
-            return self.device
-        for module in self.unet.modules():
-            if (
-                hasattr(module, "_hf_hook")
-                and hasattr(module._hf_hook, "execution_device")
-                and module._hf_hook.execution_device is not None
-            ):
-                return torch.device(module._hf_hook.execution_device)
-        return self.device
+        return prompt_embeds
 
-    # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline._encode_prompt
-    def _encode_prompt(self, prompt, device, num_images_per_prompt, do_classifier_free_guidance, negative_prompt):
+    # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline.encode_prompt
+    def encode_prompt(
+        self,
+        prompt,
+        device,
+        num_images_per_prompt,
+        do_classifier_free_guidance,
+        negative_prompt=None,
+        prompt_embeds: Optional[torch.FloatTensor] = None,
+        negative_prompt_embeds: Optional[torch.FloatTensor] = None,
+        lora_scale: Optional[float] = None,
+        clip_skip: Optional[int] = None,
+    ):
         r"""
         Encodes the prompt into text encoder hidden states.
+
         Args:
-            prompt (`str` or `list(int)`):
+        ----
+            prompt (`str` or `List[str]`, *optional*):
                 prompt to be encoded
             device: (`torch.device`):
                 torch device
@@ -203,54 +228,113 @@ def _encode_prompt(self, prompt, device, num_images_per_prompt, do_classifier_fr
                 number of images that should be generated per prompt
             do_classifier_free_guidance (`bool`):
                 whether to use classifier free guidance or not
-            negative_prompt (`str` or `List[str]`):
-                The prompt or prompts not to guide the image generation. Ignored when not using guidance (i.e., ignored
-                if `guidance_scale` is less than `1`).
+            negative_prompt (`str` or `List[str]`, *optional*):
+                The prompt or prompts not to guide the image generation. If not defined, one has to pass
+                `negative_prompt_embeds` instead. Ignored when not using guidance (i.e., ignored if `guidance_scale` is
+                less than `1`).
+            prompt_embeds (`torch.FloatTensor`, *optional*):
+                Pre-generated text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt weighting. If not
+                provided, text embeddings will be generated from `prompt` input argument.
+            negative_prompt_embeds (`torch.FloatTensor`, *optional*):
+                Pre-generated negative text embeddings. Can be used to easily tweak text inputs, *e.g.* prompt
+                weighting. If not provided, negative_prompt_embeds will be generated from `negative_prompt` input
+                argument.
+            lora_scale (`float`, *optional*):
+                A LoRA scale that will be applied to all LoRA layers of the text encoder if LoRA layers are loaded.
+            clip_skip (`int`, *optional*):
+                Number of layers to be skipped from CLIP while computing the prompt embeddings. A value of 1 means that
+                the output of the pre-final layer will be used for computing the prompt embeddings.
+
         """
-        batch_size = len(prompt) if isinstance(prompt, list) else 1
         rr.log("prompt/text", rr.TextLog(prompt))
-        rr.log("prompt/text_negative", rr.TextLog(negative_prompt))
-        text_inputs = self.tokenizer(
-            prompt,
-            padding="max_length",
-            max_length=self.tokenizer.model_max_length,
-            truncation=True,
-            return_tensors="pt",
-        )
-        text_input_ids = text_inputs.input_ids
-        rr.log("prompt/text_input/ids", rr.BarChart(text_input_ids))
-        untruncated_ids = self.tokenizer(prompt, padding="longest", return_tensors="pt").input_ids
-
-        if untruncated_ids.shape[-1] >= text_input_ids.shape[-1] and not torch.equal(text_input_ids, untruncated_ids):
-            removed_text = self.tokenizer.batch_decode(untruncated_ids[:, self.tokenizer.model_max_length - 1 : -1])
-            logger.warning(
-                "The following part of your input was truncated because CLIP can only handle sequences up to"
-                f" {self.tokenizer.model_max_length} tokens: {removed_text}"
+        rr.log("prompt/text_negative", rr.TextLog(negative_prompt if negative_prompt is not None else ""))
+
+        # set lora scale so that monkey patched LoRA
+        # function of text encoder can correctly access it
+        if lora_scale is not None and isinstance(self, LoraLoaderMixin):
+            self._lora_scale = lora_scale
+
+            # dynamically adjust the LoRA scale
+            if not USE_PEFT_BACKEND:
+                adjust_lora_scale_text_encoder(self.text_encoder, lora_scale)
+            else:
+                scale_lora_layers(self.text_encoder, lora_scale)
+
+        if prompt is not None and isinstance(prompt, str):
+            batch_size = 1
+        elif prompt is not None and isinstance(prompt, list):
+            batch_size = len(prompt)
+        else:
+            batch_size = prompt_embeds.shape[0]
+
+        if prompt_embeds is None:
+            # textual inversion: process multi-vector tokens if necessary
+            if isinstance(self, TextualInversionLoaderMixin):
+                prompt = self.maybe_convert_prompt(prompt, self.tokenizer)
+
+            text_inputs = self.tokenizer(
+                prompt,
+                padding="max_length",
+                max_length=self.tokenizer.model_max_length,
+                truncation=True,
+                return_tensors="pt",
             )
+            text_input_ids = text_inputs.input_ids
+            rr.log("prompt/text_input/ids", rr.BarChart(text_input_ids))
+            untruncated_ids = self.tokenizer(prompt, padding="longest", return_tensors="pt").input_ids
+
+            if untruncated_ids.shape[-1] >= text_input_ids.shape[-1] and not torch.equal(
+                text_input_ids, untruncated_ids
+            ):
+                removed_text = self.tokenizer.batch_decode(untruncated_ids[:, self.tokenizer.model_max_length - 1 : -1])
+                logger.warning(
+                    "The following part of your input was truncated because CLIP can only handle sequences up to"
+                    f" {self.tokenizer.model_max_length} tokens: {removed_text}"
+                )
+
+            if hasattr(self.text_encoder.config, "use_attention_mask") and self.text_encoder.config.use_attention_mask:
+                rr.log("prompt/text_input/attention_mask", rr.BarChart(text_inputs.attention_mask))
+                attention_mask = text_inputs.attention_mask.to(device)
+            else:
+                attention_mask = None
 
-        if hasattr(self.text_encoder.config, "use_attention_mask") and self.text_encoder.config.use_attention_mask:
-            rr.log("prompt/text_input/attention_mask", rr.BarChart(text_inputs.attention_mask))
-            attention_mask = text_inputs.attention_mask.to(device)
+            if clip_skip is None:
+                prompt_embeds = self.text_encoder(text_input_ids.to(device), attention_mask=attention_mask)
+                prompt_embeds = prompt_embeds[0]
+            else:
+                prompt_embeds = self.text_encoder(
+                    text_input_ids.to(device), attention_mask=attention_mask, output_hidden_states=True
+                )
+                # Access the `hidden_states` first, that contains a tuple of
+                # all the hidden states from the encoder layers. Then index into
+                # the tuple to access the hidden states from the desired layer.
+                prompt_embeds = prompt_embeds[-1][-(clip_skip + 1)]
+                # We also need to apply the final LayerNorm here to not mess with the
+                # representations. The `last_hidden_states` that we typically use for
+                # obtaining the final prompt representations passes through the LayerNorm
+                # layer.
+                prompt_embeds = self.text_encoder.text_model.final_layer_norm(prompt_embeds)
+
+        if self.text_encoder is not None:
+            prompt_embeds_dtype = self.text_encoder.dtype
+        elif self.unet is not None:
+            prompt_embeds_dtype = self.unet.dtype
         else:
-            attention_mask = None
+            prompt_embeds_dtype = prompt_embeds.dtype
 
-        text_embeddings = self.text_encoder(
-            text_input_ids.to(device),
-            attention_mask=attention_mask,
-        )
-        text_embeddings = text_embeddings[0]
+        prompt_embeds = prompt_embeds.to(dtype=prompt_embeds_dtype, device=device)
 
+        bs_embed, seq_len, _ = prompt_embeds.shape
         # duplicate text embeddings for each generation per prompt, using mps friendly method
-        bs_embed, seq_len, _ = text_embeddings.shape
-        text_embeddings = text_embeddings.repeat(1, num_images_per_prompt, 1)
-        text_embeddings = text_embeddings.view(bs_embed * num_images_per_prompt, seq_len, -1)
+        prompt_embeds = prompt_embeds.repeat(1, num_images_per_prompt, 1)
+        prompt_embeds = prompt_embeds.view(bs_embed * num_images_per_prompt, seq_len, -1)
 
         # get unconditional embeddings for classifier free guidance
-        if do_classifier_free_guidance:
+        if do_classifier_free_guidance and negative_prompt_embeds is None:
             uncond_tokens: list[str]
             if negative_prompt is None:
                 uncond_tokens = [""] * batch_size
-            elif type(prompt) is not type(negative_prompt):
+            elif prompt is not None and type(prompt) is not type(negative_prompt):
                 raise TypeError(
                     f"`negative_prompt` should be the same type to `prompt`, but got {type(negative_prompt)} !="
                     f" {type(prompt)}."
@@ -266,7 +350,11 @@ def _encode_prompt(self, prompt, device, num_images_per_prompt, do_classifier_fr
             else:
                 uncond_tokens = negative_prompt
 
-            max_length = text_input_ids.shape[-1]
+            # textual inversion: process multi-vector tokens if necessary
+            if isinstance(self, TextualInversionLoaderMixin):
+                uncond_tokens = self.maybe_convert_prompt(uncond_tokens, self.tokenizer)
+
+            max_length = prompt_embeds.shape[1]
             uncond_input = self.tokenizer(
                 uncond_tokens,
                 padding="max_length",
@@ -281,43 +369,53 @@ def _encode_prompt(self, prompt, device, num_images_per_prompt, do_classifier_fr
             else:
                 attention_mask = None
 
-            uncond_embeddings = self.text_encoder(
+            negative_prompt_embeds = self.text_encoder(
                 uncond_input.input_ids.to(device),
                 attention_mask=attention_mask,
             )
-            uncond_embeddings = uncond_embeddings[0]
+            negative_prompt_embeds = negative_prompt_embeds[0]
 
+        if do_classifier_free_guidance:
             # duplicate unconditional embeddings for each generation per prompt, using mps friendly method
-            seq_len = uncond_embeddings.shape[1]
-            uncond_embeddings = uncond_embeddings.repeat(1, num_images_per_prompt, 1)
-            uncond_embeddings = uncond_embeddings.view(batch_size * num_images_per_prompt, seq_len, -1)
+            seq_len = negative_prompt_embeds.shape[1]
+
+            negative_prompt_embeds = negative_prompt_embeds.to(dtype=prompt_embeds_dtype, device=device)
+
+            negative_prompt_embeds = negative_prompt_embeds.repeat(1, num_images_per_prompt, 1)
+            negative_prompt_embeds = negative_prompt_embeds.view(batch_size * num_images_per_prompt, seq_len, -1)
 
-            # For classifier free guidance, we need to do two forward passes.
-            # Here we concatenate the unconditional and text embeddings into a single batch
-            # to avoid doing two forward passes
-            rr.log("prompt/text_embeddings", rr.Tensor(text_embeddings))
-            rr.log("prompt/uncond_embeddings", rr.Tensor(uncond_embeddings))
-            text_embeddings = torch.cat([uncond_embeddings, text_embeddings])
+        if isinstance(self, LoraLoaderMixin) and USE_PEFT_BACKEND:
+            # Retrieve the original scale by scaling back the LoRA layers
+            unscale_lora_layers(self.text_encoder, lora_scale)
 
-        return text_embeddings
+        rr.log("prompt/text_embeddings", rr.Tensor(prompt_embeds))
+        rr.log("prompt/negative_text_embeddings", rr.Tensor(negative_prompt_embeds))
+        return prompt_embeds, negative_prompt_embeds
 
     # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline.run_safety_checker
     def run_safety_checker(self, image, device, dtype):
-        if self.safety_checker is not None:
-            safety_checker_input = self.feature_extractor(self.numpy_to_pil(image), return_tensors="pt").to(device)
+        if self.safety_checker is None:
+            has_nsfw_concept = None
+        else:
+            if torch.is_tensor(image):
+                feature_extractor_input = self.image_processor.postprocess(image, output_type="pil")
+            else:
+                feature_extractor_input = self.image_processor.numpy_to_pil(image)
+            safety_checker_input = self.feature_extractor(feature_extractor_input, return_tensors="pt").to(device)
             image, has_nsfw_concept = self.safety_checker(
                 images=image, clip_input=safety_checker_input.pixel_values.to(dtype)
             )
-        else:
-            has_nsfw_concept = None
         return image, has_nsfw_concept
 
     # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline.decode_latents
     def decode_latents(self, latents):
-        latents = 1 / 0.18215 * latents
-        image = self.vae.decode(latents).sample
+        deprecation_message = "The decode_latents method is deprecated and will be removed in 1.0.0. Please use VaeImageProcessor.postprocess(…) instead"
+        deprecate("decode_latents", "1.0.0", deprecation_message, standard_warn=False)
+
+        latents = 1 / self.vae.config.scaling_factor * latents
+        image = self.vae.decode(latents, return_dict=False)[0]
         image = (image / 2 + 0.5).clamp(0, 1)
-        # we always cast to float32 as this does not cause significant overhead and is compatible with bfloa16
+        # we always cast to float32 as this does not cause significant overhead and is compatible with bfloat16
         image = image.cpu().permute(0, 2, 3, 1).float().numpy()
         return image
 
@@ -339,28 +437,66 @@ def prepare_extra_step_kwargs(self, generator, eta):
             extra_step_kwargs["generator"] = generator
         return extra_step_kwargs
 
-    def check_inputs(self, prompt, strength, callback_steps):
-        if not isinstance(prompt, str) and not isinstance(prompt, list):
-            raise ValueError(f"`prompt` has to be of type `str` or `list` but is {type(prompt)}")
-
+    def check_inputs(
+        self,
+        prompt,
+        strength,
+        callback_steps,
+        negative_prompt=None,
+        prompt_embeds=None,
+        negative_prompt_embeds=None,
+        callback_on_step_end_tensor_inputs=None,
+    ):
         if strength < 0 or strength > 1:
-            raise ValueError(f"The value of strength should in [1.0, 1.0] but is {strength}")
+            raise ValueError(f"The value of strength should in [0.0, 1.0] but is {strength}")
 
-        if (callback_steps is None) or (
-            callback_steps is not None and (not isinstance(callback_steps, int) or callback_steps <= 0)
-        ):
+        if callback_steps is not None and (not isinstance(callback_steps, int) or callback_steps <= 0):
             raise ValueError(
                 f"`callback_steps` has to be a positive integer but is {callback_steps} of type"
                 f" {type(callback_steps)}."
             )
 
+        if callback_on_step_end_tensor_inputs is not None and not all(
+            k in self._callback_tensor_inputs for k in callback_on_step_end_tensor_inputs
+        ):
+            raise ValueError(
+                f"`callback_on_step_end_tensor_inputs` has to be in {self._callback_tensor_inputs}, but found {[k for k in callback_on_step_end_tensor_inputs if k not in self._callback_tensor_inputs]}"
+            )
+        if prompt is not None and prompt_embeds is not None:
+            raise ValueError(
+                f"Cannot forward both `prompt`: {prompt} and `prompt_embeds`: {prompt_embeds}. Please make sure to"
+                " only forward one of the two."
+            )
+        elif prompt is None and prompt_embeds is None:
+            raise ValueError(
+                "Provide either `prompt` or `prompt_embeds`. Cannot leave both `prompt` and `prompt_embeds` undefined."
+            )
+        elif prompt is not None and (not isinstance(prompt, str) and not isinstance(prompt, list)):
+            raise ValueError(f"`prompt` has to be of type `str` or `list` but is {type(prompt)}")
+
+        if negative_prompt is not None and negative_prompt_embeds is not None:
+            raise ValueError(
+                f"Cannot forward both `negative_prompt`: {negative_prompt} and `negative_prompt_embeds`:"
+                f" {negative_prompt_embeds}. Please make sure to only forward one of the two."
+            )
+
+        if prompt_embeds is not None and negative_prompt_embeds is not None:
+            if prompt_embeds.shape != negative_prompt_embeds.shape:
+                raise ValueError(
+                    "`prompt_embeds` and `negative_prompt_embeds` must have the same shape when passed directly, but"
+                    f" got: `prompt_embeds` {prompt_embeds.shape} != `negative_prompt_embeds`"
+                    f" {negative_prompt_embeds.shape}."
+                )
+
     # Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_img2img.StableDiffusionImg2ImgPipeline.get_timesteps
     def get_timesteps(self, num_inference_steps, strength, device):
         # get the original timestep using init_timestep
         init_timestep = min(int(num_inference_steps * strength), num_inference_steps)
 
         t_start = max(num_inference_steps - init_timestep, 0)
-        timesteps = self.scheduler.timesteps[t_start:]
+        timesteps = self.scheduler.timesteps[t_start * self.scheduler.order :]
+        if hasattr(self.scheduler, "set_begin_index"):
+            self.scheduler.set_begin_index(t_start * self.scheduler.order)
 
         return timesteps, num_inference_steps - t_start
 
@@ -370,19 +506,37 @@ def prepare_latents(self, image, timestep, batch_size, num_images_per_prompt, dt
             raise ValueError(
                 f"`image` has to be of type `torch.Tensor`, `PIL.Image.Image` or list but is {type(image)}"
             )
+
         image = image.to(device=device, dtype=dtype)
-        init_latent_dist = self.vae.encode(image).latent_dist
-        init_latents = init_latent_dist.sample(generator=generator)
-        rr.log("encoded_input_image", rr.Tensor(init_latents, dim_names=["b", "c", "h", "w"]))
 
-        # Decode the initial latents so we can inspect the image->latent->image loop
-        decoded = self.vae.decode(init_latents).sample
-        decoded = (decoded / 2 + 0.5).clamp(0, 1)
-        decoded = decoded.cpu().permute(0, 2, 3, 1).float().numpy()
-        decoded = (decoded * 255).round().astype("uint8")
-        rr.log("decoded_init_latents", rr.Image(decoded))
+        batch_size = batch_size * num_images_per_prompt
 
-        init_latents = 0.18215 * init_latents
+        if image.shape[1] == 4:
+            init_latents = image
+
+        else:
+            if isinstance(generator, list) and len(generator) != batch_size:
+                raise ValueError(
+                    f"You have passed a list of generators of length {len(generator)}, but requested an effective batch"
+                    f" size of {batch_size}. Make sure the batch size matches the length of the generators."
+                )
+
+            elif isinstance(generator, list):
+                init_latents = [
+                    retrieve_latents(self.vae.encode(image[i : i + 1]), generator=generator[i])
+                    for i in range(batch_size)
+                ]
+                init_latents = torch.cat(init_latents, dim=0)
+            else:
+                init_latents = retrieve_latents(self.vae.encode(image), generator=generator)
+
+            rr.log("encoded_input_image", rr.Tensor(init_latents, dim_names=["b", "c", "h", "w"]))
+
+            decoded = self.vae.decode(init_latents / self.vae.config.scaling_factor, return_dict=False)[0]
+            decoded = self.image_processor.postprocess(decoded)
+            rr.log("decoded_init_latents", rr.Image(decoded[0]))
+
+            init_latents = self.vae.config.scaling_factor * init_latents
 
         if batch_size > init_latents.shape[0] and batch_size % init_latents.shape[0] == 0:
             # expand init_latents for batch_size
@@ -394,16 +548,16 @@ def prepare_latents(self, image, timestep, batch_size, num_images_per_prompt, dt
             )
             deprecate("len(prompt) != len(image)", "1.0.0", deprecation_message, standard_warn=False)
             additional_image_per_prompt = batch_size // init_latents.shape[0]
-            init_latents = torch.cat([init_latents] * additional_image_per_prompt * num_images_per_prompt, dim=0)
+            init_latents = torch.cat([init_latents] * additional_image_per_prompt, dim=0)
         elif batch_size > init_latents.shape[0] and batch_size % init_latents.shape[0] != 0:
             raise ValueError(
                 f"Cannot duplicate `image` of batch size {init_latents.shape[0]} to {batch_size} text prompts."
             )
         else:
-            init_latents = torch.cat([init_latents] * num_images_per_prompt, dim=0)
+            init_latents = torch.cat([init_latents], dim=0)
 
-        # add noise to latents using the timesteps
-        noise = randn_tensor(init_latents.shape, generator=generator, device=device, dtype=dtype)
+        shape = init_latents.shape
+        noise = randn_tensor(shape, generator=generator, device=device, dtype=dtype)
 
         # get latents
         init_latents = self.scheduler.add_noise(init_latents, noise, timestep)
@@ -415,12 +569,14 @@ def prepare_depth_map(self, image, depth_map, batch_size, do_classifier_free_gui
         if isinstance(image, PIL.Image.Image):
             image = [image]
         else:
-            image = [img for img in image]
+            image = list(image)
 
         if isinstance(image[0], PIL.Image.Image):
             width, height = image[0].size
+        elif isinstance(image[0], np.ndarray):
+            width, height = image[0].shape[:-1]
         else:
-            width, height = image[0].shape[-2:]
+            height, width = image[0].shape[-2:]
 
         if depth_map is None:
             pixel_values = self.feature_extractor(images=image, return_tensors="pt").pixel_values
@@ -451,174 +607,313 @@ def prepare_depth_map(self, image, depth_map, batch_size, do_classifier_free_gui
 
         # duplicate mask and masked_image_latents for each generation per prompt, using mps friendly method
         if depth_map.shape[0] < batch_size:
-            depth_map = depth_map.repeat(batch_size, 1, 1, 1)
+            repeat_by = batch_size // depth_map.shape[0]
+            depth_map = depth_map.repeat(repeat_by, 1, 1, 1)
 
         depth_map = torch.cat([depth_map] * 2) if do_classifier_free_guidance else depth_map
         return depth_map
 
+    @property
+    def guidance_scale(self):
+        return self._guidance_scale
+
+    @property
+    def clip_skip(self):
+        return self._clip_skip
+
+    # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)
+    # of the Imagen paper: https://arxiv.org/pdf/2205.11487.pdf . `guidance_scale = 1`
+    # corresponds to doing no classifier free guidance.
+    @property
+    def do_classifier_free_guidance(self):
+        return self._guidance_scale > 1
+
+    @property
+    def cross_attention_kwargs(self):
+        return self._cross_attention_kwargs
+
+    @property
+    def num_timesteps(self):
+        return self._num_timesteps
+
     @torch.no_grad()
     def __call__(
         self,
-        prompt: str | list[str],
-        image: torch.FloatTensor | PIL.Image.Image,
-        depth_map: torch.FloatTensor | None = None,
+        prompt: Union[str, list[str]] = None,
+        image: PipelineImageInput = None,
+        depth_map: Optional[torch.FloatTensor] = None,
         strength: float = 0.8,
-        num_inference_steps: int | None = 50,
-        guidance_scale: float | None = 7.5,
-        negative_prompt: str | list[str] | None = None,
-        num_images_per_prompt: int | None = 1,
-        eta: float | None = 0.0,
-        generator: torch.Generator | None = None,
-        output_type: str | None = "pil",
+        num_inference_steps: Optional[int] = 50,
+        guidance_scale: Optional[float] = 7.5,
+        negative_prompt: Optional[Union[str, list[str]]] = None,
+        num_images_per_prompt: Optional[int] = 1,
+        eta: Optional[float] = 0.0,
+        generator: Optional[Union[torch.Generator, list[torch.Generator]]] = None,
+        prompt_embeds: Optional[torch.FloatTensor] = None,
+        negative_prompt_embeds: Optional[torch.FloatTensor] = None,
+        output_type: Optional[str] = "pil",
         return_dict: bool = True,
-        callback: Callable[[int, int, torch.FloatTensor], None] | None = None,
-        callback_steps: int | None = 1,
+        cross_attention_kwargs: Optional[dict[str, Any]] = None,
+        clip_skip: Optional[int] = None,
+        callback_on_step_end: Optional[Callable[[int, int, dict], None]] = None,
+        callback_on_step_end_tensor_inputs: list[str] = ["latents"],
+        **kwargs,
     ):
         r"""
-        Function invoked when calling the pipeline for generation.
+        The call function to the pipeline for generation.
+
         Args:
-            prompt (`str` or `List[str]`):
-                The prompt or prompts to guide the image generation.
-            image (`torch.FloatTensor` or `PIL.Image.Image`):
-                `Image`, or tensor representing an image batch, that will be used as the starting point for the
-                process.
+        ----
+            prompt (`str` or `List[str]`, *optional*):
+                The prompt or prompts to guide image generation. If not defined, you need to pass `prompt_embeds`.
+            image (`torch.FloatTensor`, `PIL.Image.Image`, `np.ndarray`, `List[torch.FloatTensor]`, `List[PIL.Image.Image]`, or `List[np.ndarray]`):
+                `Image` or tensor representing an image batch to be used as the starting point. Can accept image
+                latents as `image` only if `depth_map` is not `None`.
+            depth_map (`torch.FloatTensor`, *optional*):
+                Depth prediction to be used as additional conditioning for the image generation process. If not
+                defined, it automatically predicts the depth with `self.depth_estimator`.
             strength (`float`, *optional*, defaults to 0.8):
-                Conceptually, indicates how much to transform the reference `image`. Must be between 0 and 1. `image`
-                will be used as a starting point, adding more noise to it the larger the `strength`. The number of
-                denoising steps depends on the amount of noise initially added. When `strength` is 1, added noise will
-                be maximum and the denoising process will run for the full number of iterations specified in
-                `num_inference_steps`. A value of 1, therefore, essentially ignores `image`.
+                Indicates extent to transform the reference `image`. Must be between 0 and 1. `image` is used as a
+                starting point and more noise is added the higher the `strength`. The number of denoising steps depends
+                on the amount of noise initially added. When `strength` is 1, added noise is maximum and the denoising
+                process runs for the full number of iterations specified in `num_inference_steps`. A value of 1
+                essentially ignores `image`.
             num_inference_steps (`int`, *optional*, defaults to 50):
                 The number of denoising steps. More denoising steps usually lead to a higher quality image at the
-                expense of slower inference. This parameter will be modulated by `strength`.
+                expense of slower inference. This parameter is modulated by `strength`.
             guidance_scale (`float`, *optional*, defaults to 7.5):
-                Guidance scale as defined in [Classifier-Free Diffusion Guidance](https://arxiv.org/abs/2207.12598).
-                `guidance_scale` is defined as `w` of equation 2. of [Imagen
-                Paper](https://arxiv.org/pdf/2205.11487.pdf). Guidance scale is enabled by setting `guidance_scale >
-                1`. Higher guidance scale encourages to generate images that are closely linked to the text `prompt`,
-                usually at the expense of lower image quality.
+                A higher guidance scale value encourages the model to generate images closely linked to the text
+                `prompt` at the expense of lower image quality. Guidance scale is enabled when `guidance_scale > 1`.
             negative_prompt (`str` or `List[str]`, *optional*):
-                The prompt or prompts not to guide the image generation. Ignored when not using guidance (i.e., ignored
-                if `guidance_scale` is less than `1`).
+                The prompt or prompts to guide what to not include in image generation. If not defined, you need to
+                pass `negative_prompt_embeds` instead. Ignored when not using guidance (`guidance_scale < 1`).
             num_images_per_prompt (`int`, *optional*, defaults to 1):
                 The number of images to generate per prompt.
             eta (`float`, *optional*, defaults to 0.0):
-                Corresponds to parameter eta (η) in the DDIM paper: https://arxiv.org/abs/2010.02502. Only applies to
-                [`schedulers.DDIMScheduler`], will be ignored for others.
-            generator (`torch.Generator`, *optional*):
-                A [torch generator](https://pytorch.org/docs/stable/generated/torch.Generator.html) to make generation
-                deterministic.
+                Corresponds to parameter eta (η) from the [DDIM](https://arxiv.org/abs/2010.02502) paper. Only applies
+                to the [`~schedulers.DDIMScheduler`], and is ignored in other schedulers.
+            generator (`torch.Generator` or `List[torch.Generator]`, *optional*):
+                A [`torch.Generator`](https://pytorch.org/docs/stable/generated/torch.Generator.html) to make
+                generation deterministic.
+            prompt_embeds (`torch.FloatTensor`, *optional*):
+                Pre-generated text embeddings. Can be used to easily tweak text inputs (prompt weighting). If not
+                provided, text embeddings are generated from the `prompt` input argument.
+            negative_prompt_embeds (`torch.FloatTensor`, *optional*):
+                Pre-generated negative text embeddings. Can be used to easily tweak text inputs (prompt weighting). If
+                not provided, `negative_prompt_embeds` are generated from the `negative_prompt` input argument.
             output_type (`str`, *optional*, defaults to `"pil"`):
-                The output format of the generate image. Choose between
-                [PIL](https://pillow.readthedocs.io/en/stable/): `PIL.Image.Image` or `np.array`.
+                The output format of the generated image. Choose between `PIL.Image` or `np.array`.
             return_dict (`bool`, *optional*, defaults to `True`):
                 Whether or not to return a [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] instead of a
                 plain tuple.
-            callback (`Callable`, *optional*):
-                A function that will be called every `callback_steps` steps during inference. The function will be
-                called with the following arguments: `callback(step: int, timestep: int, latents: torch.FloatTensor)`.
-            callback_steps (`int`, *optional*, defaults to 1):
-                The frequency at which the `callback` function will be called. If not specified, the callback will be
-                called at every step.
+            cross_attention_kwargs (`dict`, *optional*):
+                A kwargs dictionary that if specified is passed along to the [`AttentionProcessor`] as defined in
+                [`self.processor`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention_processor.py).
+            clip_skip (`int`, *optional*):
+                Number of layers to be skipped from CLIP while computing the prompt embeddings. A value of 1 means that
+                the output of the pre-final layer will be used for computing the prompt embeddings.
+            callback_on_step_end (`Callable`, *optional*):
+                A function that calls at the end of each denoising steps during the inference. The function is called
+                with the following arguments: `callback_on_step_end(self: DiffusionPipeline, step: int, timestep: int,
+                callback_kwargs: Dict)`. `callback_kwargs` will include a list of all tensors as specified by
+                `callback_on_step_end_tensor_inputs`.
+            callback_on_step_end_tensor_inputs (`List`, *optional*):
+                The list of tensor inputs for the `callback_on_step_end` function. The tensors specified in the list
+                will be passed as `callback_kwargs` argument. You will only be able to include variables listed in the
+                `._callback_tensor_inputs` attribute of your pipeline class.
+            kwargs:
+                Only used for deprecated arguments.
+
+        Examples:
+        --------
+        ```py
+        >>> import torch
+        >>> import requests
+        >>> from PIL import Image
+
+        >>> from diffusers import StableDiffusionDepth2ImgPipeline
+
+        >>> pipe = StableDiffusionDepth2ImgPipeline.from_pretrained(
+        …     "stabilityai/stable-diffusion-2-depth",
+        …     torch_dtype=torch.float16,
+        …   )
+        >>> pipe.to("cuda")
+
+
+        >>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
+        >>> init_image = Image.open(requests.get(url, stream=True).raw)
+        >>> prompt = "two tigers"
+        >>> prompt = "bad, deformed, ugly, bad anotomy"
+        >>> image = pipe(prompt=prompt, image=init_image, negative_prompt=prompt, strength=0.7).images[0]
+        ```
+
         Returns:
+        -------
             [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] or `tuple`:
-            [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] if `return_dict` is True, otherwise a `tuple.
-            When returning a tuple, the first element is a list with the generated images, and the second element is a
-            list of `bool`s denoting whether the corresponding generated image likely represents "not-safe-for-work"
-            (nsfw) content, according to the `safety_checker`.
+                If `return_dict` is `True`, [`~pipelines.stable_diffusion.StableDiffusionPipelineOutput`] is returned,
+                otherwise a `tuple` is returned where the first element is a list with the generated images.
+
         """
+
+        callback = kwargs.pop("callback", None)
+        callback_steps = kwargs.pop("callback_steps", None)
+
+        if callback is not None:
+            deprecate(
+                "callback",
+                "1.0.0",
+                "Passing `callback` as an input argument to `__call__` is deprecated, consider use `callback_on_step_end`",
+            )
+        if callback_steps is not None:
+            deprecate(
+                "callback_steps",
+                "1.0.0",
+                "Passing `callback_steps` as an input argument to `__call__` is deprecated, consider use `callback_on_step_end`",
+            )
+
         rr.set_time_sequence("step", -1)
+
         # 1. Check inputs
-        self.check_inputs(prompt, strength, callback_steps)
+        self.check_inputs(
+            prompt,
+            strength,
+            callback_steps,
+            negative_prompt=negative_prompt,
+            prompt_embeds=prompt_embeds,
+            negative_prompt_embeds=negative_prompt_embeds,
+            callback_on_step_end_tensor_inputs=callback_on_step_end_tensor_inputs,
+        )
+
+        self._guidance_scale = guidance_scale
+        self._clip_skip = clip_skip
+        self._cross_attention_kwargs = cross_attention_kwargs
+
+        if image is None:
+            raise ValueError("`image` input cannot be undefined.")
 
         # 2. Define call parameters
-        batch_size = 1 if isinstance(prompt, str) else len(prompt)
+        if prompt is not None and isinstance(prompt, str):
+            batch_size = 1
+        elif prompt is not None and isinstance(prompt, list):
+            batch_size = len(prompt)
+        else:
+            batch_size = prompt_embeds.shape[0]
+
         device = self._execution_device
-        # here `guidance_scale` is defined analog to the guidance weight `w` of equation (2)
-        # of the Imagen paper: https://arxiv.org/pdf/2205.11487.pdf . `guidance_scale = 1`
-        # corresponds to doing no classifier free guidance.
-        do_classifier_free_guidance = guidance_scale > 1.0
 
         # 3. Encode input prompt
-        text_embeddings = self._encode_prompt(
-            prompt, device, num_images_per_prompt, do_classifier_free_guidance, negative_prompt
+        text_encoder_lora_scale = (
+            self.cross_attention_kwargs.get("scale", None) if self.cross_attention_kwargs is not None else None
+        )
+        prompt_embeds, negative_prompt_embeds = self.encode_prompt(
+            prompt,
+            device,
+            num_images_per_prompt,
+            self.do_classifier_free_guidance,
+            negative_prompt,
+            prompt_embeds=prompt_embeds,
+            negative_prompt_embeds=negative_prompt_embeds,
+            lora_scale=text_encoder_lora_scale,
+            clip_skip=self.clip_skip,
         )
+        # For classifier free guidance, we need to do two forward passes.
+        # Here we concatenate the unconditional and text embeddings into a single batch
+        # to avoid doing two forward passes
+        if self.do_classifier_free_guidance:
+            prompt_embeds = torch.cat([negative_prompt_embeds, prompt_embeds])
 
         # 4. Prepare depth mask
         depth_mask = self.prepare_depth_map(
             image,
             depth_map,
             batch_size * num_images_per_prompt,
-            do_classifier_free_guidance,
-            text_embeddings.dtype,
+            self.do_classifier_free_guidance,
+            prompt_embeds.dtype,
             device,
         )
 
         # 5. Preprocess image
         rr.log("image/original", rr.Image(image))
-        image = preprocess(image)
+        image = self.image_processor.preprocess(image)
         rr.log("input_image/preprocessed", rr.Tensor(image))
 
-        # 6. set timesteps
+        # 6. Set timesteps
         self.scheduler.set_timesteps(num_inference_steps, device=device)
         timesteps, num_inference_steps = self.get_timesteps(num_inference_steps, strength, device)
         latent_timestep = timesteps[:1].repeat(batch_size * num_images_per_prompt)
 
         # 7. Prepare latent variables
         latents = self.prepare_latents(
-            image, latent_timestep, batch_size, num_images_per_prompt, text_embeddings.dtype, device, generator
+            image, latent_timestep, batch_size, num_images_per_prompt, prompt_embeds.dtype, device, generator
         )
         rr.log("diffusion/latents", rr.Tensor(latents, dim_names=["b", "c", "h", "w"]))
 
         # 8. Prepare extra step kwargs.
-        # TODO(someone): Logic should ideally just be moved out of the pipeline
         extra_step_kwargs = self.prepare_extra_step_kwargs(generator, eta)
 
         # 9. Denoising loop
         num_warmup_steps = len(timesteps) - num_inference_steps * self.scheduler.order
+        self._num_timesteps = len(timesteps)
         with self.progress_bar(total=num_inference_steps) as progress_bar:
             for i, t in enumerate(timesteps):
                 rr.set_time_sequence("step", i)
                 rr.set_time_sequence("timestep", t)
 
                 # expand the latents if we are doing classifier free guidance
-                latent_model_input = torch.cat([latents] * 2) if do_classifier_free_guidance else latents
+                latent_model_input = torch.cat([latents] * 2) if self.do_classifier_free_guidance else latents
                 latent_model_input = self.scheduler.scale_model_input(latent_model_input, t)
                 latent_model_input = torch.cat([latent_model_input, depth_mask], dim=1)
                 rr.log("diffusion/latent_model_input", rr.Tensor(latent_model_input))
 
                 # predict the noise residual
-                noise_pred = self.unet(latent_model_input, t, encoder_hidden_states=text_embeddings).sample
+                noise_pred = self.unet(
+                    latent_model_input,
+                    t,
+                    encoder_hidden_states=prompt_embeds,
+                    cross_attention_kwargs=self.cross_attention_kwargs,
+                    return_dict=False,
+                )[0]
                 rr.log("diffusion/noise_pred", rr.Tensor(noise_pred, dim_names=["b", "c", "h", "w"]))
 
                 # perform guidance
-                if do_classifier_free_guidance:
+                if self.do_classifier_free_guidance:
                     noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
-                    noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)
+                    noise_pred = noise_pred_uncond + self.guidance_scale * (noise_pred_text - noise_pred_uncond)
 
                 # compute the previous noisy sample x_t -> x_t-1
-                latents = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs).prev_sample
+                latents = self.scheduler.step(noise_pred, t, latents, **extra_step_kwargs, return_dict=False)[0]
                 rr.log("diffusion/latents", rr.Tensor(latents, dim_names=["b", "c", "h", "w"]))
 
                 # Decode the latents for visualization purposes
-                image = self.decode_latents(latents)
-                image = (image * 255).round().astype("uint8")
-                rr.log("image/diffused", rr.Image(image))
+                image = self.vae.decode(latents / self.vae.config.scaling_factor, return_dict=False)[0]
+                image = self.image_processor.postprocess(image, output_type=output_type)
+                rr.log("image/diffused", rr.Image(image[0]))
+
+                if callback_on_step_end is not None:
+                    callback_kwargs = {}
+                    for k in callback_on_step_end_tensor_inputs:
+                        callback_kwargs[k] = locals()[k]
+                    callback_outputs = callback_on_step_end(self, i, t, callback_kwargs)
+
+                    latents = callback_outputs.pop("latents", latents)
+                    prompt_embeds = callback_outputs.pop("prompt_embeds", prompt_embeds)
+                    negative_prompt_embeds = callback_outputs.pop("negative_prompt_embeds", negative_prompt_embeds)
+                    depth_mask = callback_outputs.pop("depth_mask", depth_mask)
 
                 # call the callback, if provided
                 if i == len(timesteps) - 1 or ((i + 1) > num_warmup_steps and (i + 1) % self.scheduler.order == 0):
                     progress_bar.update()
                     if callback is not None and i % callback_steps == 0:
-                        callback(i, t, latents)
+                        step_idx = i // getattr(self.scheduler, "order", 1)
+                        callback(step_idx, t, latents)
 
-        # 10. Post-processing
-        image = self.decode_latents(latents)
-        image_8 = (image * 255).round().astype("uint8")
-        rr.log("image/diffused", rr.Image(image_8))
+        if not output_type == "latent":
+            image = self.vae.decode(latents / self.vae.config.scaling_factor, return_dict=False)[0]
+        else:
+            image = latents
 
-        # 11. Convert to PIL
-        if output_type == "pil":
-            image = self.numpy_to_pil(image)
+        image = self.image_processor.postprocess(image, output_type=output_type)
+        self.maybe_free_model_hooks()
 
         if not return_dict:
             return (image,)
diff --git a/examples/python/depth_guided_stable_diffusion/main.py b/examples/python/depth_guided_stable_diffusion/main.py
index 370573ce2413..dafccd255def 100755
--- a/examples/python/depth_guided_stable_diffusion/main.py
+++ b/examples/python/depth_guided_stable_diffusion/main.py
@@ -134,8 +134,8 @@ def main() -> None:
                     rrb.Vertical(
                         rrb.TextLogView(name="Prompt", contents=["prompt/text", "prompt/text_negative"]),
                         rrb.Tabs(
-                            rrb.TensorView(name="Text embeddings", origin="prompt/text_embeddings"),
-                            rrb.TensorView(name="Unconditional embeddings", origin="prompt/uncond_embeddings"),
+                            rrb.TensorView(name="Prompt embeddings", origin="prompt/text_embeddings"),
+                            rrb.TensorView(name="Negative prompt embeddings", origin="prompt/negative_text_embeddings"),
                         ),
                         rrb.BarChartView(name="Prompt ids", origin="prompt/text_input"),
                         name="Prompt Inputs",
diff --git a/examples/python/depth_guided_stable_diffusion/requirements.txt b/examples/python/depth_guided_stable_diffusion/requirements.txt
index f48c42477775..141b6f665518 100644
--- a/examples/python/depth_guided_stable_diffusion/requirements.txt
+++ b/examples/python/depth_guided_stable_diffusion/requirements.txt
@@ -1,5 +1,5 @@
 accelerate
-diffusers>=0.12.1,<=0.21
+diffusers==0.27.2
 ftfy
 numpy
 packaging

From 50d71d1378c53e1d79aec6b793c53448e8b11a27 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Tue, 16 Apr 2024 15:55:21 +0200
Subject: [PATCH 307/508] Improve type index pages, codegen now knows about doc
 categories (#5978)

### What

* Fixes #5533

image


### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5978?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5978?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5978)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .../re_types/definitions/docs/attributes.fbs  |  3 +
 .../definitions/rerun/archetypes/arrows2d.fbs |  3 +-
 .../definitions/rerun/archetypes/arrows3d.fbs |  3 +-
 .../definitions/rerun/archetypes/asset3d.fbs  |  3 +-
 .../rerun/archetypes/bar_chart.fbs            |  3 +-
 .../definitions/rerun/archetypes/boxes2d.fbs  |  3 +-
 .../definitions/rerun/archetypes/boxes3d.fbs  |  3 +-
 .../rerun/archetypes/depth_image.fbs          |  3 +-
 .../definitions/rerun/archetypes/image.fbs    |  3 +-
 .../rerun/archetypes/line_strips2d.fbs        |  3 +-
 .../rerun/archetypes/line_strips3d.fbs        |  3 +-
 .../definitions/rerun/archetypes/mesh3d.fbs   |  3 +-
 .../definitions/rerun/archetypes/pinhole.fbs  |  3 +-
 .../definitions/rerun/archetypes/points2d.fbs |  3 +-
 .../definitions/rerun/archetypes/points3d.fbs |  3 +-
 .../definitions/rerun/archetypes/scalar.fbs   |  3 +-
 .../rerun/archetypes/segmentation_image.fbs   |  3 +-
 .../rerun/archetypes/series_line.fbs          |  4 +-
 .../rerun/archetypes/series_point.fbs         |  4 +-
 .../definitions/rerun/archetypes/tensor.fbs   |  3 +-
 .../rerun/archetypes/text_document.fbs        |  3 +-
 .../definitions/rerun/archetypes/text_log.fbs |  3 +-
 .../rerun/archetypes/transform3d.fbs          |  3 +-
 .../rerun/archetypes/view_coordinates.fbs     |  3 +-
 .../re_types_builder/src/codegen/docs/mod.rs  | 84 +++++++++++------
 crates/re_types_builder/src/docs.rs           |  7 ++
 crates/re_types_builder/src/lib.rs            |  1 +
 crates/re_types_builder/src/objects.rs        |  4 +
 docs/content/reference/types.md               | 60 ++----------
 docs/content/reference/types/archetypes.md    | 78 ++++++++++------
 docs/content/reference/types/components.md    | 92 ++++++++++---------
 docs/content/reference/types/datatypes.md     | 78 ++++++++--------
 32 files changed, 264 insertions(+), 214 deletions(-)

diff --git a/crates/re_types/definitions/docs/attributes.fbs b/crates/re_types/definitions/docs/attributes.fbs
index 2cc3a775c372..60dd49b482ee 100644
--- a/crates/re_types/definitions/docs/attributes.fbs
+++ b/crates/re_types/definitions/docs/attributes.fbs
@@ -6,3 +6,6 @@ namespace docs.attributes;
 /// Speculative links contain a `?speculative-link` query param. Any such links are ignored by linkinator,
 /// and we check for their absence as the first step in our release process.
 attribute "attr.docs.unreleased";
+
+/// Apply to an archetype to set its category used in the docs.
+attribute "attr.docs.category";
diff --git a/crates/re_types/definitions/rerun/archetypes/arrows2d.fbs b/crates/re_types/definitions/rerun/archetypes/arrows2d.fbs
index 0b904c0cec74..995973929f2d 100644
--- a/crates/re_types/definitions/rerun/archetypes/arrows2d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/arrows2d.fbs
@@ -15,7 +15,8 @@ namespace rerun.archetypes;
 table Arrows2D (
   "attr.rust.derive": "PartialEq",
   "attr.rust.new_pub_crate",
-  "attr.cpp.no_field_ctors"
+  "attr.cpp.no_field_ctors",
+  "attr.docs.category": "Spatial 2D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/arrows3d.fbs b/crates/re_types/definitions/rerun/archetypes/arrows3d.fbs
index 47dc8f6fdbd7..2ddc8eaa9db7 100644
--- a/crates/re_types/definitions/rerun/archetypes/arrows3d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/arrows3d.fbs
@@ -15,7 +15,8 @@ namespace rerun.archetypes;
 table Arrows3D (
   "attr.rust.derive": "PartialEq",
   "attr.rust.new_pub_crate",
-  "attr.cpp.no_field_ctors"
+  "attr.cpp.no_field_ctors",
+  "attr.docs.category": "Spatial 3D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/asset3d.fbs b/crates/re_types/definitions/rerun/archetypes/asset3d.fbs
index 6fd1d6f339a4..f0be08ea0880 100644
--- a/crates/re_types/definitions/rerun/archetypes/asset3d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/asset3d.fbs
@@ -15,7 +15,8 @@ namespace rerun.archetypes;
 /// \example asset3d_simple title="Simple 3D asset" image="https://static.rerun.io/asset3d_simple/af238578188d3fd0de3e330212120e2842a8ddb2/1200w.png"
 /// \example asset3d_out_of_tree !api title="3D asset with out-of-tree transform"
 table Asset3D (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Spatial 3D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/bar_chart.fbs b/crates/re_types/definitions/rerun/archetypes/bar_chart.fbs
index bcb3c6d093d7..1af9584ccd12 100644
--- a/crates/re_types/definitions/rerun/archetypes/bar_chart.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/bar_chart.fbs
@@ -12,7 +12,8 @@ namespace rerun.archetypes;
 ///
 /// \example bar_chart title="Simple bar chart" image="https://static.rerun.io/barchart_simple/cf6014b18265edfcaa562c06526c0716b296b193/1200w.png"
 table BarChart (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Plotting"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/boxes2d.fbs b/crates/re_types/definitions/rerun/archetypes/boxes2d.fbs
index 171f4b2128d3..a9b2bec06c60 100644
--- a/crates/re_types/definitions/rerun/archetypes/boxes2d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/boxes2d.fbs
@@ -15,7 +15,8 @@ namespace rerun.archetypes;
 table Boxes2D (
   "attr.rust.derive": "PartialEq",
   "attr.rust.new_pub_crate",
-  "attr.cpp.no_field_ctors"
+  "attr.cpp.no_field_ctors",
+  "attr.docs.category": "Spatial 2D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/boxes3d.fbs b/crates/re_types/definitions/rerun/archetypes/boxes3d.fbs
index 709bbf7cef69..b23fda975c13 100644
--- a/crates/re_types/definitions/rerun/archetypes/boxes3d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/boxes3d.fbs
@@ -16,7 +16,8 @@ namespace rerun.archetypes;
 table Boxes3D (
   "attr.rust.derive": "PartialEq",
   "attr.rust.new_pub_crate",
-  "attr.cpp.no_field_ctors"
+  "attr.cpp.no_field_ctors",
+  "attr.docs.category": "Spatial 3D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/depth_image.fbs b/crates/re_types/definitions/rerun/archetypes/depth_image.fbs
index dc027148590a..5466ca0bd31c 100644
--- a/crates/re_types/definitions/rerun/archetypes/depth_image.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/depth_image.fbs
@@ -19,7 +19,8 @@ namespace rerun.archetypes;
 /// \example depth_image_3d title="Depth to 3D example" image="https://static.rerun.io/depth_image_3d/f78674bdae0eb25786c6173307693c5338f38b87/1200w.png"
 table DepthImage (
   "attr.rust.derive": "PartialEq",
-  "attr.cpp.no_field_ctors"
+  "attr.cpp.no_field_ctors",
+  "attr.docs.category": "Image & tensor"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/image.fbs b/crates/re_types/definitions/rerun/archetypes/image.fbs
index 3d9ab91b2126..2b99ac3b5f56 100644
--- a/crates/re_types/definitions/rerun/archetypes/image.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/image.fbs
@@ -30,7 +30,8 @@ namespace rerun.archetypes;
 /// \example image_simple image="https://static.rerun.io/image_simple/06ba7f8582acc1ffb42a7fd0006fad7816f3e4e4/1200w.png"
 table Image (
   "attr.rust.derive": "PartialEq",
-  "attr.cpp.no_field_ctors"
+  "attr.cpp.no_field_ctors",
+  "attr.docs.category": "Image & tensor"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/line_strips2d.fbs b/crates/re_types/definitions/rerun/archetypes/line_strips2d.fbs
index b04bd9775bae..69b5cec2bd66 100644
--- a/crates/re_types/definitions/rerun/archetypes/line_strips2d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/line_strips2d.fbs
@@ -13,7 +13,8 @@ namespace rerun.archetypes;
 /// \example line_segments2d_simple !api image="https://static.rerun.io/line_segment2d_simple/53df596662dd9ffaaea5d09d091ef95220346c83/1200w.png"
 /// \example line_strip2d_batch image="https://static.rerun.io/line_strip2d_batch/d8aae7ca3d6c3b0e3b636de60b8067fa2f0b6db9/1200w.png"
 table LineStrips2D (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Spatial 2D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/line_strips3d.fbs b/crates/re_types/definitions/rerun/archetypes/line_strips3d.fbs
index 3b14a76e2e0e..9e242a2a1934 100644
--- a/crates/re_types/definitions/rerun/archetypes/line_strips3d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/line_strips3d.fbs
@@ -13,7 +13,8 @@ namespace rerun.archetypes;
 /// \example line_segments3d_simple !api title="Many individual segments" image="https://static.rerun.io/line_segment3d_simple/aa800b2a6e6a7b8e32e762b42861bae36f5014bb/1200w.png"
 /// \example line_strip3d_batch title="Many strips" image="https://static.rerun.io/line_strip3d_batch/102e5ec5271475657fbc76b469267e4ec8e84337/1200w.png"
 table LineStrips3D (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Spatial 3D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/mesh3d.fbs b/crates/re_types/definitions/rerun/archetypes/mesh3d.fbs
index febd12e5ecb5..83b692f8e109 100644
--- a/crates/re_types/definitions/rerun/archetypes/mesh3d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/mesh3d.fbs
@@ -15,7 +15,8 @@ namespace rerun.archetypes;
 /// \example mesh3d_indexed title="Simple indexed 3D mesh" image="https://static.rerun.io/mesh3d_simple/e1e5fd97265daf0d0bc7b782d862f19086fd6975/1200w.png"
 /// \example mesh3d_partial_updates !api title="3D mesh with partial updates" image="https://static.rerun.io/mesh3d_partial_updates/a11e4accb0257dcd9531867b7e1d6fd5e3bee5c3/1200w.png"
 table Mesh3D (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Spatial 2D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/pinhole.fbs b/crates/re_types/definitions/rerun/archetypes/pinhole.fbs
index d69b1a475b75..2519e0b1fa87 100644
--- a/crates/re_types/definitions/rerun/archetypes/pinhole.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/pinhole.fbs
@@ -11,7 +11,8 @@ namespace rerun.archetypes;
 /// \example pinhole_simple title="Simple pinhole camera" image="https://static.rerun.io/pinhole_simple/9af9441a94bcd9fd54e1fea44fb0c59ff381a7f2/1200w.png"
 /// \example pinhole_perspective title="Perspective pinhole camera" image="https://static.rerun.io/pinhole_perspective/d0bd02a0cf354a5c8eafb79a84fe8674335cab98/1200w.png"
 table Pinhole (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Spatial 3D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/points2d.fbs b/crates/re_types/definitions/rerun/archetypes/points2d.fbs
index fdc48f20edf9..c88441d02a2a 100644
--- a/crates/re_types/definitions/rerun/archetypes/points2d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/points2d.fbs
@@ -14,7 +14,8 @@ namespace rerun.archetypes;
 /// \example point2d_simple !api title="Simple 2D points" image="https://static.rerun.io/point2d_simple/a8e801958bce5aa4e080659c033630f86ce95f71/1200w.png"
 /// \example point2d_random title="Randomly distributed 2D points with varying color and radius" image="https://static.rerun.io/point2d_random/8e8ac75373677bd72bd3f56a15e44fcab309a168/1200w.png"
 table Points2D (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Spatial 2D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/points3d.fbs b/crates/re_types/definitions/rerun/archetypes/points3d.fbs
index f569f0caabec..8afb33729265 100644
--- a/crates/re_types/definitions/rerun/archetypes/points3d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/points3d.fbs
@@ -12,7 +12,8 @@ namespace rerun.archetypes;
 /// \example point3d_simple !api title="Simple 3D points" image="https://static.rerun.io/point3d_simple/32fb3e9b65bea8bd7ffff95ad839f2f8a157a933/1200w.png"
 /// \example point3d_random title="Randomly distributed 3D points with varying color and radius" image="https://static.rerun.io/point3d_random/7e94e1806d2c381943748abbb3bedb68d564de24/1200w.png"
 table Points3D (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Spatial 3D"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/scalar.fbs b/crates/re_types/definitions/rerun/archetypes/scalar.fbs
index 176a3c7fd661..70938ef2183f 100644
--- a/crates/re_types/definitions/rerun/archetypes/scalar.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/scalar.fbs
@@ -24,7 +24,8 @@ namespace rerun.archetypes;
 /// \example scalar_simple title="Simple line plot" image="https://static.rerun.io/scalar_simple/8bcc92f56268739f8cd24d60d1fe72a655f62a46/1200w.png"
 /// \example scalar_multiple_plots !api title="Multiple time series plots" image="https://static.rerun.io/scalar_multiple/15845c2a348f875248fbd694e03eabd922741c4c/1200w.png"
 table Scalar (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Plotting"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/segmentation_image.fbs b/crates/re_types/definitions/rerun/archetypes/segmentation_image.fbs
index 6338b4310324..f9e4f5b06f62 100644
--- a/crates/re_types/definitions/rerun/archetypes/segmentation_image.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/segmentation_image.fbs
@@ -27,7 +27,8 @@ namespace rerun.archetypes;
 /// \example segmentation_image_simple title="Simple segmentation image" image="https://static.rerun.io/segmentation_image_simple/eb49e0b8cb870c75a69e2a47a2d202e5353115f6/1200w.png"
 table SegmentationImage (
   "attr.rust.derive": "PartialEq",
-  "attr.cpp.no_field_ctors"
+  "attr.cpp.no_field_ctors",
+  "attr.docs.category": "Image & tensor"
 ) {
   // --- Required ---
 
diff --git a/crates/re_types/definitions/rerun/archetypes/series_line.fbs b/crates/re_types/definitions/rerun/archetypes/series_line.fbs
index 5524d21566e8..2cf098a4ac36 100644
--- a/crates/re_types/definitions/rerun/archetypes/series_line.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/series_line.fbs
@@ -18,7 +18,9 @@ namespace rerun.archetypes;
 /// \cpp See `rerun::archetypes::Scalar`
 ///
 /// \example series_line_style title="Line series" image="https://static.rerun.io/series_line_style/d2616d98b1e46bdb85849b8669154fdf058e3453/1200w.png"
-table SeriesLine {
+table SeriesLine (
+    "attr.docs.category": "Plotting"
+) {
     // --- Required ---
 
     // --- Optional ---
diff --git a/crates/re_types/definitions/rerun/archetypes/series_point.fbs b/crates/re_types/definitions/rerun/archetypes/series_point.fbs
index 60d544ae1953..9ffc07e8082b 100644
--- a/crates/re_types/definitions/rerun/archetypes/series_point.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/series_point.fbs
@@ -18,7 +18,9 @@ namespace rerun.archetypes;
 /// \cpp See `rerun::archetypes::Scalar`
 ///
 /// \example series_point_style title="Point series" image="https://static.rerun.io/series_point_style/82207a705da6c086b28ce161db1db9e8b12258b7/1200w.png"
-table SeriesPoint {
+table SeriesPoint (
+    "attr.docs.category": "Plotting"
+) {
     // --- Required ---
 
     // --- Optional ---
diff --git a/crates/re_types/definitions/rerun/archetypes/tensor.fbs b/crates/re_types/definitions/rerun/archetypes/tensor.fbs
index c645fdea5a9f..b04ed9a018bc 100644
--- a/crates/re_types/definitions/rerun/archetypes/tensor.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/tensor.fbs
@@ -14,7 +14,8 @@ namespace rerun.archetypes;
 ///
 /// \example tensor_simple title="Simple tensor" image="https://static.rerun.io/tensor_simple/baacb07712f7b706e3c80e696f70616c6c20b367/1200w.png"
 table Tensor (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Image & tensor"
 ) {
   /// The tensor data
   data: rerun.components.TensorData ("attr.rerun.component_required", order: 1000);
diff --git a/crates/re_types/definitions/rerun/archetypes/text_document.fbs b/crates/re_types/definitions/rerun/archetypes/text_document.fbs
index cb4e6e0ff7f6..5153d5ec5b8e 100644
--- a/crates/re_types/definitions/rerun/archetypes/text_document.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/text_document.fbs
@@ -13,7 +13,8 @@ namespace rerun.archetypes;
 ///
 /// \example text_document title="Markdown text document" image="https://static.rerun.io/textdocument/babda19558ee32ed8d730495b595aee7a5e2c174/1200w.png"
 table TextDocument (
-  "attr.rust.derive": "PartialEq, Eq"
+  "attr.rust.derive": "PartialEq, Eq",
+  "attr.docs.category": "Text"
 ) {
   /// Contents of the text document.
   text: rerun.components.Text ("attr.rerun.component_required", order: 100);
diff --git a/crates/re_types/definitions/rerun/archetypes/text_log.fbs b/crates/re_types/definitions/rerun/archetypes/text_log.fbs
index 3d9656e7894f..144cd956668d 100644
--- a/crates/re_types/definitions/rerun/archetypes/text_log.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/text_log.fbs
@@ -11,7 +11,8 @@ namespace rerun.archetypes;
 ///
 /// \example text_log_integration text="Logging text directly or via a logger" image="https://static.rerun.io/text_log_integration/9737d0c986325802a9885499d6fcc773b1736488/1200w.png"
 table TextLog (
-  "attr.rust.derive": "PartialEq, Eq"
+  "attr.rust.derive": "PartialEq, Eq",
+  "attr.docs.category": "Text"
 ) {
   /// The body of the message.
   text: rerun.components.Text ("attr.rerun.component_required", order: 100);
diff --git a/crates/re_types/definitions/rerun/archetypes/transform3d.fbs b/crates/re_types/definitions/rerun/archetypes/transform3d.fbs
index b4e8f1abf009..445430668c0b 100644
--- a/crates/re_types/definitions/rerun/archetypes/transform3d.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/transform3d.fbs
@@ -10,7 +10,8 @@ namespace rerun.archetypes;
 ///
 /// \example transform3d_simple title="Variety of 3D transforms" image="https://static.rerun.io/transform3d_simple/141368b07360ce3fcb1553079258ae3f42bdb9ac/1200w.png"
 table Transform3D (
-  "attr.rust.derive": "PartialEq"
+  "attr.rust.derive": "PartialEq",
+  "attr.docs.category": "Spatial 3D"
 ) {
   /// The transform
   transform: rerun.components.Transform3D ("attr.rerun.component_required", order: 1000);
diff --git a/crates/re_types/definitions/rerun/archetypes/view_coordinates.fbs b/crates/re_types/definitions/rerun/archetypes/view_coordinates.fbs
index 41279c44c28d..21f876bec85d 100644
--- a/crates/re_types/definitions/rerun/archetypes/view_coordinates.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/view_coordinates.fbs
@@ -18,7 +18,8 @@ namespace rerun.archetypes;
 /// \example view_coordinates_simple title="View coordinates for adjusting the eye camera" image="https://static.rerun.io/viewcoordinates/0833f0dc8616a676b7b2c566f2a6f613363680c5/1200w.png"
 table ViewCoordinates (
   "attr.rust.derive": "Copy, PartialEq, Eq, bytemuck::Pod, bytemuck::Zeroable",
-  "attr.rust.repr": "transparent"
+  "attr.rust.repr": "transparent",
+  "attr.docs.category": "Spatial 3D"
 ) {
   xyz: rerun.components.ViewCoordinates ("attr.rerun.component_required", required, order: 1000);
 }
diff --git a/crates/re_types_builder/src/codegen/docs/mod.rs b/crates/re_types_builder/src/codegen/docs/mod.rs
index 8a9c77c2f8a4..b47f1d99430e 100644
--- a/crates/re_types_builder/src/codegen/docs/mod.rs
+++ b/crates/re_types_builder/src/codegen/docs/mod.rs
@@ -1,10 +1,12 @@
 use std::fmt::Write;
 
 use camino::Utf8PathBuf;
+use itertools::Itertools;
 
 use crate::{
-    codegen::common::ExampleInfo, objects::FieldKind, CodeGenerator, GeneratedFiles, Object,
-    ObjectKind, Objects, Reporter, Type,
+    codegen::{autogen_warning, common::ExampleInfo},
+    objects::FieldKind,
+    CodeGenerator, GeneratedFiles, Object, ObjectKind, Objects, Reporter, Type,
 };
 
 type ObjectMap = std::collections::BTreeMap;
@@ -69,19 +71,25 @@ impl CodeGenerator for DocsCodeGenerator {
             (
                 ObjectKind::Archetype,
                 1,
-                "Archetypes are bundles of components",
+                "Archetypes are bundles of components. This page lists all built-in components.",
                 &archetypes,
             ),
             (
                 ObjectKind::Component,
                 2,
-                "Archetypes are bundles of components",
+                r"Components are the fundamental unit of logging in Rerun. This page lists all built-in components.
+
+An entity can only ever contain a single array of any given component type.
+If you log the same component several times on an entity, the last value (or array of values) will overwrite the previous.
+
+For more information on the relationship between **archetypes** and **components**, check out the concept page
+on [Entities and Components](../../concepts/entity-component.md).",
                 &components,
             ),
             (
                 ObjectKind::Datatype,
                 3,
-                "Data types are the lowest layer of the data model hierarchy",
+                r"Data types are the lowest layer of the data model hierarchy. They are re-usable types used by the components.",
                 &datatypes,
             ),
         ] {
@@ -101,38 +109,58 @@ fn index_page(kind: ObjectKind, order: u64, prelude: &str, objects: &[&Object])
 
     write_frontmatter(&mut page, kind.plural_name(), Some(order));
     putln!(page);
+    // Can't put the autogen warning before the frontmatter, stuff breaks down then.
+    putln!(page, "", autogen_warning!());
+    putln!(page);
     putln!(page, "{prelude}");
     putln!(page);
-    if !objects.is_empty() {
-        // First all non deprecated ones:
-        putln!(page, "## Available {}", kind.plural_name().to_lowercase());
+
+    let mut any_category = false;
+    for (category, objects) in &objects
+        .iter()
+        .sorted_by(|a, b| {
+            // Put other category last.
+            if a.doc_category().is_none() {
+                std::cmp::Ordering::Greater
+            } else if b.doc_category().is_none() {
+                std::cmp::Ordering::Less
+            } else {
+                a.doc_category().cmp(&b.doc_category())
+            }
+        })
+        .group_by(|o| o.doc_category())
+    {
+        if category.is_some() {
+            any_category = true;
+        }
+        if let Some(category) = category.or_else(|| {
+            if any_category {
+                Some("Other".to_owned())
+            } else {
+                None
+            }
+        }) {
+            putln!(page, "## {category}");
+        }
         putln!(page);
-        for object in objects.iter().filter(|o| o.deprecation_notice().is_none()) {
+
+        for object in objects.sorted_by_key(|object| &object.name) {
+            let deprecation_note = if object.deprecation_notice().is_some() {
+                "⚠️ _deprecated_ "
+            } else {
+                ""
+            };
+
             putln!(
                 page,
-                "* [`{}`]({}/{}.md)",
+                "* {deprecation_note}[`{}`]({}/{}.md): {}",
                 object.name,
                 object.kind.plural_snake_case(),
-                object.snake_case_name()
+                object.snake_case_name(),
+                object.docs.first_line().unwrap_or_default(),
             );
         }
-
-        // Then all deprecated ones:
-        if objects.iter().any(|o| o.deprecation_notice().is_some()) {
-            putln!(page);
-            putln!(page);
-            putln!(page, "## Deprecated {}", kind.plural_name().to_lowercase());
-            putln!(page);
-            for object in objects.iter().filter(|o| o.deprecation_notice().is_some()) {
-                putln!(
-                    page,
-                    "* [`{}`]({}/{}.md)",
-                    object.name,
-                    object.kind.plural_snake_case(),
-                    object.snake_case_name()
-                );
-            }
-        }
+        putln!(page);
     }
 
     page
diff --git a/crates/re_types_builder/src/docs.rs b/crates/re_types_builder/src/docs.rs
index 3bfe9b2cf339..489a64cd9d8d 100644
--- a/crates/re_types_builder/src/docs.rs
+++ b/crates/re_types_builder/src/docs.rs
@@ -70,6 +70,13 @@ impl Docs {
             .collect()
     }
 
+    /// Get the first line of the documentation untagged.
+    pub fn first_line(&self) -> Option<&str> {
+        self.lines_with_tag_matching(|t| t.is_empty())
+            .first()
+            .copied()
+    }
+
     /// Get all doc lines that are untagged, or match the given tag.
     ///
     /// For instance, pass `"py"` to get all lines that are untagged or starta with `"\py"`.
diff --git a/crates/re_types_builder/src/lib.rs b/crates/re_types_builder/src/lib.rs
index 80b0ca697ab9..395ea8c2fa4d 100644
--- a/crates/re_types_builder/src/lib.rs
+++ b/crates/re_types_builder/src/lib.rs
@@ -194,6 +194,7 @@ pub const ATTR_RUST_TUPLE_STRUCT: &str = "attr.rust.tuple_struct";
 pub const ATTR_CPP_NO_FIELD_CTORS: &str = "attr.cpp.no_field_ctors";
 
 pub const ATTR_DOCS_UNRELEASED: &str = "attr.docs.unreleased";
+pub const ATTR_DOCS_CATEGORY: &str = "attr.docs.category";
 
 // --- Entrypoints ---
 
diff --git a/crates/re_types_builder/src/objects.rs b/crates/re_types_builder/src/objects.rs
index d368f7a4eab9..93b2ab368425 100644
--- a/crates/re_types_builder/src/objects.rs
+++ b/crates/re_types_builder/src/objects.rs
@@ -523,6 +523,10 @@ impl Object {
         self.try_get_attr::(crate::ATTR_RERUN_DEPRECATED)
     }
 
+    pub fn doc_category(&self) -> Option {
+        self.try_get_attr::(crate::ATTR_DOCS_CATEGORY)
+    }
+
     /// Returns the crate name of an object, accounting for overrides.
     pub fn crate_name(&self) -> String {
         self.try_get_attr::(crate::ATTR_RUST_OVERRIDE_CRATE)
diff --git a/docs/content/reference/types.md b/docs/content/reference/types.md
index 02da158ab288..b2b7dd6cd3f6 100644
--- a/docs/content/reference/types.md
+++ b/docs/content/reference/types.md
@@ -3,60 +3,14 @@ title: Types
 order: 400
 ---
 
-Rerun comes with built-in support for a number of different types that can be logged via the Python and Rust Logging
-APIs and then visualized in the [Viewer](viewer.md).
+Rerun has 3 levels of types that can be used in all SDK languages:
 
-The top-level types are called [**archetypes**](types/archetypes.md) to differentiate them from the lower-level
-[**data types**](types/datatypes.md) that make up the individual [**components**](types/components.md).
-For more information on the relationship between **archetypes** and **components**, check out the concept page
-on [Entities and Components](../concepts/entity-component.md).
-
-## Spatial **archetypes**
-
-The spatial archetypes represent 2D and 3D spatial data. These types have some notion of a coordinate system and
-generally support spatial transformations. These types can be visualized by 2D and 3D space views.
-
-To visualize a 2D entity in a 3D space view it must be under a pinhole transformation.
-To visualize a 3D entity in a 2D space view, the 2D's origin must be at a pinhole transform and all 3D objects are above it.
-
--   [Arrows3D](types/archetypes/arrows3d.md)
--   [Asset3D](types/archetypes/asset3d.md)
--   [Boxes2D](types/archetypes/boxes2d.md)
--   [Boxes3D](types/archetypes/boxes3d.md)
--   [LineStrips2D](types/archetypes/line_strips2d.md)
--   [LineStrips3D](types/archetypes/line_strips3d.md)
--   [Mesh3D](types/archetypes/mesh3d.md)
--   [Points2D](types/archetypes/points2d.md)
--   [Points3D](types/archetypes/points3d.md)
-
-### Spatial transformations
+* [**Archetypes**](types/archetypes.md) - high level bundles of components.
+* [**Components**](types/components.md) - the base unit of logging data.
+* [**Data types**](types/datatypes.md) - that make up the individual components.
 
--   [Transform3D](types/archetypes/transform3d.md)
--   [Pinhole](types/archetypes/pinhole.md)
--   [DisconnectedSpace](types/archetypes/disconnected_space.md): disconnect an entity path from its parent.
+To get an overview of what the Rerun [Viewer](./viewer.md) can show, start at [**Archetypes**](types/archetypes.md).
 
-## Image & tensor **archetypes**
-
-Image and tensor archetypes all build on top of a common tensor component. The tensor component is a multi-dimensional
-generic container for arrays of data. Images are restricted to tensors of rank 2 or rank 3; these can be viewed in the
-`Spatial` space view. Generic tensors of greater rank can only be viewed in the specialized `Tensor` space view.
-
--   [Image](types/archetypes/image.md)
--   [DepthImage](types/archetypes/depth_image.md)
--   [SegmentationImage](types/archetypes/segmentation_image.md)
--   [Tensor](types/archetypes/tensor.md)
-
-## Time series **archetypes**
-
--   [Scalar](types/archetypes/scalar.md): a single scalar / metric value.
--   [SeriesPoint](types/archetypes/series_point.md): define the style properties for a point series in a chart.
--   [SeriesLine](types/archetypes/series_line.md): define the style properties for a line series in a chart.
-
-## Other **archetypes**
+For more information on the relationship between **archetypes** and **components**, check out the concept page
+on [Entities and Components](../concepts/entity-component.md).
 
--   [AnnotationContext](types/archetypes/annotation_context.md): not viewed directly, but provides classes, labels, and connectivity information for other entities.
--   [BarChart](types/archetypes/bar_chart.md): data displayed in a `BarChart` space view.
--   [Clear](types/archetypes/clear.md): clear all components of an entity.
--   [TextDocument](types/archetypes/text_document.md): text displayed in a `TextDocument` space view.
--   [TextLog](types/archetypes/text_log.md): a log entry in a `TextLog` space view.
--   [ViewCoordinates](types/archetypes/view_coordinates.md): determines how we interpret the coordinate system of an entity/space.
diff --git a/docs/content/reference/types/archetypes.md b/docs/content/reference/types/archetypes.md
index 36b682a1e4a5..f6d6a75eb7f6 100644
--- a/docs/content/reference/types/archetypes.md
+++ b/docs/content/reference/types/archetypes.md
@@ -3,33 +3,51 @@ title: "Archetypes"
 order: 1
 ---
 
-Archetypes are bundles of components
-
-## Available archetypes
-
-* [`AnnotationContext`](archetypes/annotation_context.md)
-* [`Arrows2D`](archetypes/arrows2d.md)
-* [`Arrows3D`](archetypes/arrows3d.md)
-* [`Asset3D`](archetypes/asset3d.md)
-* [`BarChart`](archetypes/bar_chart.md)
-* [`Boxes2D`](archetypes/boxes2d.md)
-* [`Boxes3D`](archetypes/boxes3d.md)
-* [`Clear`](archetypes/clear.md)
-* [`DepthImage`](archetypes/depth_image.md)
-* [`DisconnectedSpace`](archetypes/disconnected_space.md)
-* [`Image`](archetypes/image.md)
-* [`LineStrips2D`](archetypes/line_strips2d.md)
-* [`LineStrips3D`](archetypes/line_strips3d.md)
-* [`Mesh3D`](archetypes/mesh3d.md)
-* [`Pinhole`](archetypes/pinhole.md)
-* [`Points2D`](archetypes/points2d.md)
-* [`Points3D`](archetypes/points3d.md)
-* [`Scalar`](archetypes/scalar.md)
-* [`SegmentationImage`](archetypes/segmentation_image.md)
-* [`SeriesLine`](archetypes/series_line.md)
-* [`SeriesPoint`](archetypes/series_point.md)
-* [`Tensor`](archetypes/tensor.md)
-* [`TextDocument`](archetypes/text_document.md)
-* [`TextLog`](archetypes/text_log.md)
-* [`Transform3D`](archetypes/transform3d.md)
-* [`ViewCoordinates`](archetypes/view_coordinates.md)
+
+
+Archetypes are bundles of components. This page lists all built-in components.
+
+## Image & tensor
+
+* [`DepthImage`](archetypes/depth_image.md): A depth image.
+* [`Image`](archetypes/image.md): A monochrome or color image.
+* [`SegmentationImage`](archetypes/segmentation_image.md): An image made up of integer class-ids.
+* [`Tensor`](archetypes/tensor.md): A generic n-dimensional Tensor.
+
+## Plotting
+
+* [`BarChart`](archetypes/bar_chart.md): A bar chart.
+* [`Scalar`](archetypes/scalar.md): Log a double-precision scalar.
+* [`SeriesLine`](archetypes/series_line.md): Define the style properties for a line series in a chart.
+* [`SeriesPoint`](archetypes/series_point.md): Define the style properties for a point series in a chart.
+
+## Spatial 2D
+
+* [`Arrows2D`](archetypes/arrows2d.md): 2D arrows with optional colors, radii, labels, etc.
+* [`Boxes2D`](archetypes/boxes2d.md): 2D boxes with half-extents and optional center, rotations, rotations, colors etc.
+* [`LineStrips2D`](archetypes/line_strips2d.md): 2D line strips with positions and optional colors, radii, labels, etc.
+* [`Mesh3D`](archetypes/mesh3d.md): A 3D triangle mesh as specified by its per-mesh and per-vertex properties.
+* [`Points2D`](archetypes/points2d.md): A 2D point cloud with positions and optional colors, radii, labels, etc.
+
+## Spatial 3D
+
+* [`Arrows3D`](archetypes/arrows3d.md): 3D arrows with optional colors, radii, labels, etc.
+* [`Asset3D`](archetypes/asset3d.md): A prepacked 3D asset (`.gltf`, `.glb`, `.obj`, `.stl`, etc.).
+* [`Boxes3D`](archetypes/boxes3d.md): 3D boxes with half-extents and optional center, rotations, rotations, colors etc.
+* [`LineStrips3D`](archetypes/line_strips3d.md): 3D line strips with positions and optional colors, radii, labels, etc.
+* [`Pinhole`](archetypes/pinhole.md): Camera perspective projection (a.k.a. intrinsics).
+* [`Points3D`](archetypes/points3d.md): A 3D point cloud with positions and optional colors, radii, labels, etc.
+* [`Transform3D`](archetypes/transform3d.md): A 3D transform.
+* [`ViewCoordinates`](archetypes/view_coordinates.md): How we interpret the coordinate system of an entity/space.
+
+## Text
+
+* [`TextDocument`](archetypes/text_document.md): A text element intended to be displayed in its own text-box.
+* [`TextLog`](archetypes/text_log.md): A log entry in a text log, comprised of a text body and its log level.
+
+## Other
+
+* [`AnnotationContext`](archetypes/annotation_context.md): The `AnnotationContext` provides additional information on how to display entities.
+* [`Clear`](archetypes/clear.md): Empties all the components of an entity.
+* [`DisconnectedSpace`](archetypes/disconnected_space.md): Spatially disconnect this entity from its parent.
+
diff --git a/docs/content/reference/types/components.md b/docs/content/reference/types/components.md
index f12d2fd1bfe6..d11ab090ef1e 100644
--- a/docs/content/reference/types/components.md
+++ b/docs/content/reference/types/components.md
@@ -3,47 +3,55 @@ title: "Components"
 order: 2
 ---
 
-Archetypes are bundles of components
+
 
-## Available components
+Components are the fundamental unit of logging in Rerun. This page lists all built-in components.
+
+An entity can only ever contain a single array of any given component type.
+If you log the same component several times on an entity, the last value (or array of values) will overwrite the previous.
+
+For more information on the relationship between **archetypes** and **components**, check out the concept page
+on [Entities and Components](../../concepts/entity-component.md).
+
+
+* [`AnnotationContext`](components/annotation_context.md): The `AnnotationContext` provides additional information on how to display entities.
+* [`Blob`](components/blob.md): A binary blob of data.
+* [`ClassId`](components/class_id.md): A 16-bit ID representing a type of semantic class.
+* [`ClearIsRecursive`](components/clear_is_recursive.md): Configures how a clear operation should behave - recursive or not.
+* [`Color`](components/color.md): An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha.
+* [`DepthMeter`](components/depth_meter.md): A component indicating how long a meter is, expressed in native units.
+* [`DisconnectedSpace`](components/disconnected_space.md): Spatially disconnect this entity from its parent.
+* [`DrawOrder`](components/draw_order.md): Draw order used for the display order of 2D elements.
+* [`HalfSizes2D`](components/half_sizes2d.md): Half-sizes (extents) of a 2D box along its local axis, starting at its local origin/center.
+* [`HalfSizes3D`](components/half_sizes3d.md): Half-sizes (extents) of a 3D box along its local axis, starting at its local origin/center.
+* [`InstanceKey`](components/instance_key.md): A unique numeric identifier for each individual instance within a batch.
+* [`KeypointId`](components/keypoint_id.md): A 16-bit ID representing a type of semantic keypoint within a class.
+* [`LineStrip2D`](components/line_strip2d.md): A line strip in 2D space.
+* [`LineStrip3D`](components/line_strip3d.md): A line strip in 3D space.
+* [`MarkerShape`](components/marker_shape.md): Shape of a marker.
+* [`MarkerSize`](components/marker_size.md): Size of a marker in UI points.
+* [`Material`](components/material.md): Material properties of a mesh.
+* [`MediaType`](components/media_type.md): A standardized media type (RFC2046, formerly known as MIME types), encoded as a utf8 string.
+* [`MeshProperties`](components/mesh_properties.md): Optional triangle indices for a mesh.
+* [`Name`](components/name.md): A display name, typically for an entity or a item like a plot series.
+* [`OutOfTreeTransform3D`](components/out_of_tree_transform3d.md): An out-of-tree affine transform between two 3D spaces, represented in a given direction.
+* [`PinholeProjection`](components/pinhole_projection.md): Camera projection, from image coordinates to view coordinates.
+* [`Position2D`](components/position2d.md): A position in 2D space.
+* [`Position3D`](components/position3d.md): A position in 3D space.
+* [`Radius`](components/radius.md): A Radius component.
+* [`Range1D`](components/range1d.md): A 1D range, specifying a lower and upper bound.
+* [`Resolution`](components/resolution.md): Pixel resolution width & height, e.g. of a camera sensor.
+* [`Rotation3D`](components/rotation3d.md): A 3D rotation, represented either by a quaternion or a rotation around axis.
+* [`Scalar`](components/scalar.md): A double-precision scalar.
+* [`ScalarScattering`](components/scalar_scattering.md): If true, a scalar will be shown as individual point in a scatter plot.
+* [`StrokeWidth`](components/stroke_width.md): The width of a stroke specified in UI points.
+* [`TensorData`](components/tensor_data.md): A multi-dimensional `Tensor` of data.
+* [`Texcoord2D`](components/texcoord2d.md): A 2D texture UV coordinate.
+* [`Text`](components/text.md): A string of text, e.g. for labels and text documents.
+* [`TextLogLevel`](components/text_log_level.md): The severity level of a text log message.
+* [`Transform3D`](components/transform3d.md): An affine transform between two 3D spaces, represented in a given direction.
+* [`Vector2D`](components/vector2d.md): A vector in 2D space.
+* [`Vector3D`](components/vector3d.md): A vector in 3D space.
+* [`ViewCoordinates`](components/view_coordinates.md): How we interpret the coordinate system of an entity/space.
+* [`VisualizerOverrides`](components/visualizer_overrides.md): The name of a visualizer.
 
-* [`AnnotationContext`](components/annotation_context.md)
-* [`Blob`](components/blob.md)
-* [`ClassId`](components/class_id.md)
-* [`ClearIsRecursive`](components/clear_is_recursive.md)
-* [`Color`](components/color.md)
-* [`DepthMeter`](components/depth_meter.md)
-* [`DisconnectedSpace`](components/disconnected_space.md)
-* [`DrawOrder`](components/draw_order.md)
-* [`HalfSizes2D`](components/half_sizes2d.md)
-* [`HalfSizes3D`](components/half_sizes3d.md)
-* [`InstanceKey`](components/instance_key.md)
-* [`KeypointId`](components/keypoint_id.md)
-* [`LineStrip2D`](components/line_strip2d.md)
-* [`LineStrip3D`](components/line_strip3d.md)
-* [`MarkerShape`](components/marker_shape.md)
-* [`MarkerSize`](components/marker_size.md)
-* [`Material`](components/material.md)
-* [`MediaType`](components/media_type.md)
-* [`MeshProperties`](components/mesh_properties.md)
-* [`Name`](components/name.md)
-* [`OutOfTreeTransform3D`](components/out_of_tree_transform3d.md)
-* [`PinholeProjection`](components/pinhole_projection.md)
-* [`Position2D`](components/position2d.md)
-* [`Position3D`](components/position3d.md)
-* [`Radius`](components/radius.md)
-* [`Range1D`](components/range1d.md)
-* [`Resolution`](components/resolution.md)
-* [`Rotation3D`](components/rotation3d.md)
-* [`Scalar`](components/scalar.md)
-* [`ScalarScattering`](components/scalar_scattering.md)
-* [`StrokeWidth`](components/stroke_width.md)
-* [`TensorData`](components/tensor_data.md)
-* [`Texcoord2D`](components/texcoord2d.md)
-* [`Text`](components/text.md)
-* [`TextLogLevel`](components/text_log_level.md)
-* [`Transform3D`](components/transform3d.md)
-* [`Vector2D`](components/vector2d.md)
-* [`Vector3D`](components/vector3d.md)
-* [`ViewCoordinates`](components/view_coordinates.md)
-* [`VisualizerOverrides`](components/visualizer_overrides.md)
diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md
index 95daf97ca8f7..90467a297494 100644
--- a/docs/content/reference/types/datatypes.md
+++ b/docs/content/reference/types/datatypes.md
@@ -3,43 +3,45 @@ title: "Datatypes"
 order: 3
 ---
 
-Data types are the lowest layer of the data model hierarchy
+
 
-## Available datatypes
+Data types are the lowest layer of the data model hierarchy. They are re-usable types used by the components.
+
+
+* [`Angle`](datatypes/angle.md): Angle in either radians or degrees.
+* [`AnnotationInfo`](datatypes/annotation_info.md): Annotation info annotating a class id or key-point id.
+* [`Bool`](datatypes/bool.md): A single boolean.
+* [`ClassDescription`](datatypes/class_description.md): The description of a semantic Class.
+* [`ClassDescriptionMapElem`](datatypes/class_description_map_elem.md): A helper type for mapping class IDs to class descriptions.
+* [`ClassId`](datatypes/class_id.md): A 16-bit ID representing a type of semantic class.
+* [`EntityPath`](datatypes/entity_path.md): A path to an entity in the `DataStore`.
+* [`Float32`](datatypes/float32.md): A single-precision 32-bit IEEE 754 floating point number.
+* [`KeypointId`](datatypes/keypoint_id.md): A 16-bit ID representing a type of semantic keypoint within a class.
+* [`KeypointPair`](datatypes/keypoint_pair.md): A connection between two `Keypoints`.
+* [`Mat3x3`](datatypes/mat3x3.md): A 3x3 Matrix.
+* [`Mat4x4`](datatypes/mat4x4.md): A 4x4 Matrix.
+* [`Material`](datatypes/material.md): Material properties of a mesh.
+* [`MeshProperties`](datatypes/mesh_properties.md): Optional triangle indices for a mesh.
+* [`Quaternion`](datatypes/quaternion.md): A Quaternion represented by 4 real numbers.
+* [`Rgba32`](datatypes/rgba32.md): An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha.
+* [`Rotation3D`](datatypes/rotation3d.md): A 3D rotation.
+* [`RotationAxisAngle`](datatypes/rotation_axis_angle.md): 3D rotation represented by a rotation around a given axis.
+* [`Scale3D`](datatypes/scale3d.md): 3D scaling factor, part of a transform representation.
+* [`TensorBuffer`](datatypes/tensor_buffer.md): The underlying storage for a `Tensor`.
+* [`TensorData`](datatypes/tensor_data.md): A multi-dimensional `Tensor` of data.
+* [`TensorDimension`](datatypes/tensor_dimension.md): A single dimension within a multi-dimensional tensor.
+* [`TimeInt`](datatypes/time_int.md): A 64-bit number describing either nanoseconds OR sequence numbers.
+* [`Transform3D`](datatypes/transform3d.md): Representation of a 3D affine transform.
+* [`TranslationAndMat3x3`](datatypes/translation_and_mat3x3.md): Representation of an affine transform via a 3x3 affine matrix paired with a translation.
+* [`TranslationRotationScale3D`](datatypes/translation_rotation_scale3d.md): Representation of an affine transform via separate translation, rotation & scale.
+* [`UInt32`](datatypes/uint32.md): A 32bit unsigned integer.
+* [`UInt64`](datatypes/uint64.md): A 64bit unsigned integer.
+* [`UVec2D`](datatypes/uvec2d.md): A uint32 vector in 2D space.
+* [`UVec3D`](datatypes/uvec3d.md): A uint32 vector in 3D space.
+* [`UVec4D`](datatypes/uvec4d.md): A uint vector in 4D space.
+* [`Utf8`](datatypes/utf8.md): A string of text, encoded as UTF-8.
+* [`Uuid`](datatypes/uuid.md): A 16-byte uuid.
+* [`Vec2D`](datatypes/vec2d.md): A vector in 2D space.
+* [`Vec3D`](datatypes/vec3d.md): A vector in 3D space.
+* [`Vec4D`](datatypes/vec4d.md): A vector in 4D space.
 
-* [`Angle`](datatypes/angle.md)
-* [`AnnotationInfo`](datatypes/annotation_info.md)
-* [`Bool`](datatypes/bool.md)
-* [`ClassDescription`](datatypes/class_description.md)
-* [`ClassDescriptionMapElem`](datatypes/class_description_map_elem.md)
-* [`ClassId`](datatypes/class_id.md)
-* [`EntityPath`](datatypes/entity_path.md)
-* [`Float32`](datatypes/float32.md)
-* [`KeypointId`](datatypes/keypoint_id.md)
-* [`KeypointPair`](datatypes/keypoint_pair.md)
-* [`Mat3x3`](datatypes/mat3x3.md)
-* [`Mat4x4`](datatypes/mat4x4.md)
-* [`Material`](datatypes/material.md)
-* [`MeshProperties`](datatypes/mesh_properties.md)
-* [`Quaternion`](datatypes/quaternion.md)
-* [`Rgba32`](datatypes/rgba32.md)
-* [`Rotation3D`](datatypes/rotation3d.md)
-* [`RotationAxisAngle`](datatypes/rotation_axis_angle.md)
-* [`Scale3D`](datatypes/scale3d.md)
-* [`TensorBuffer`](datatypes/tensor_buffer.md)
-* [`TensorData`](datatypes/tensor_data.md)
-* [`TensorDimension`](datatypes/tensor_dimension.md)
-* [`TimeInt`](datatypes/time_int.md)
-* [`Transform3D`](datatypes/transform3d.md)
-* [`TranslationAndMat3x3`](datatypes/translation_and_mat3x3.md)
-* [`TranslationRotationScale3D`](datatypes/translation_rotation_scale3d.md)
-* [`UInt32`](datatypes/uint32.md)
-* [`UInt64`](datatypes/uint64.md)
-* [`UVec2D`](datatypes/uvec2d.md)
-* [`UVec3D`](datatypes/uvec3d.md)
-* [`UVec4D`](datatypes/uvec4d.md)
-* [`Utf8`](datatypes/utf8.md)
-* [`Uuid`](datatypes/uuid.md)
-* [`Vec2D`](datatypes/vec2d.md)
-* [`Vec3D`](datatypes/vec3d.md)
-* [`Vec4D`](datatypes/vec4d.md)

From 85cb1025b98981a71e2fdc6d0b8f450e3da29618 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Tue, 16 Apr 2024 18:28:57 +0200
Subject: [PATCH 308/508] Fix nightly ci (#5973)

### What

* Fixes #5945
   * various wheel build issues
   * notebook issues
* Fixes #3924

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5973?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5973?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5973)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .github/workflows/reusable_checks_rust.yml  | 26 ++++++++++++++++++
 .github/workflows/reusable_run_notebook.yml | 30 ++++++++++-----------
 .github/workflows/reusable_test_wheels.yml  | 25 +++++++----------
 docs/snippets/snippets.toml                 |  3 +++
 scripts/run_python_e2e_test.py              |  9 ++-----
 tests/roundtrips.py                         |  3 ++-
 6 files changed, 58 insertions(+), 38 deletions(-)

diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml
index 575cb403e997..7044158007d2 100644
--- a/.github/workflows/reusable_checks_rust.yml
+++ b/.github/workflows/reusable_checks_rust.yml
@@ -78,3 +78,29 @@ jobs:
       - name: Rust all checks & tests
         if: ${{ inputs.CHANNEL == 'nightly' }}
         run: pixi run rs-check
+
+  # Run some basics tests on Mac and Windows
+  mac-windows-tests:
+    name: Test on macOS and Windows
+    if: ${{ inputs.CHANNEL == 'nightly' }}
+    strategy:
+      matrix:
+        include:
+          - os: macos-latest
+            name: macos
+          - os: windows-latest-8-cores
+            name: windows
+    runs-on: ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Set up Rust
+        uses: ./.github/actions/setup-rust
+        with:
+          cache_key: "build-${{ matrix.name }}"
+          save_cache: true
+          workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }}
+          service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }}
+
+      - name: cargo test --all-targets --all-features
+        run: cargo test --all-targets --all-features
diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml
index e54512d6e3c7..795a3a22267a 100644
--- a/.github/workflows/reusable_run_notebook.yml
+++ b/.github/workflows/reusable_run_notebook.yml
@@ -33,37 +33,37 @@ jobs:
         with:
           ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }}
 
-      - name: Download Wheel Artifact
+      - uses: prefix-dev/setup-pixi@v0.5.2
+        with:
+          pixi-version: v0.19.0
+          environments: wheel-test
+
+      - name: Download Wheel
         uses: actions/download-artifact@v4
         with:
           name: ${{ inputs.WHEEL_ARTIFACT_NAME }}
-          path: wheel_artifact
+          path: wheel
 
-      - name: Install wheel dependencies
-        # First we install the dependencies manually so we can use `--no-index` when installing the wheel.
-        # This needs to be a separate step for some reason or the following step fails
-        # TODO(jleibs): pull these deps from pyproject.toml
+      - name: Get version
+        id: get-version
         shell: bash
         run: |
-          pip install deprecated 'numpy>=1.23,<2' pillow>=9.5.0 pyarrow>=14.0.2 pytest==7.1.2
+          pixi run -e wheel-test 'echo "wheel_version=$(python scripts/ci/crates.py get-version)"' >> "$GITHUB_OUTPUT"
 
-      - name: Install downloaded wheel_artifact
+      - name: Install built wheel
         # Now install the wheel using a specific version and --no-index to guarantee we get the version from
         # the pre-dist folder. Note we don't use --force-reinstall here because --no-index means it wouldn't
         # find the dependencies to reinstall them.
         shell: bash
         run: |
-          pip install rerun-sdk --no-index --find-links wheel_artifact
+          pixi run -e wheel-test pip uninstall rerun-sdk
+          pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links wheel
 
       - name: Install Deps
-        shell: bash
-        run: |
-          pip install -r examples/python/notebook/requirements.txt
+        run: pixi run -e wheel-test pip install -r examples/python/notebook/requirements.txt
 
       - name: Create notebook
-        shell: bash
-        run: |
-          jupyter nbconvert --to=html --ExecutePreprocessor.enabled=True examples/python/notebook/cube.ipynb --output /tmp/cube.html
+        run: pixi run -e wheel-test jupyter nbconvert --to=html --ExecutePreprocessor.enabled=True examples/python/notebook/cube.ipynb --output /tmp/cube.html
 
       - id: "auth"
         uses: google-github-actions/auth@v2
diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml
index fa8702f0d976..5d5b15bdeed4 100644
--- a/.github/workflows/reusable_test_wheels.yml
+++ b/.github/workflows/reusable_test_wheels.yml
@@ -87,12 +87,12 @@ jobs:
               container="null"
               ;;
             macos-arm64)
-              runner="macos-latest-large" # See https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/
+              runner="macos-13-xlarge" # This is an Arm vm, https://docs.github.com/en/actions/using-github-hosted-runners/about-larger-runners/about-larger-runners#about-macos-larger-runners
               target="aarch64-apple-darwin"
               container="null"
               ;;
             macos-x64)
-              runner="macos-latest-large" # See https://github.blog/2023-10-02-introducing-the-new-apple-silicon-powered-m1-macos-larger-runner-for-github-actions/
+              runner="macos-13-large" # This is an Intel vm, see https://docs.github.com/en/actions/using-github-hosted-runners/about-larger-runners/about-larger-runners#about-macos-larger-runners
               target="x86_64-apple-darwin"
               container="null"
               ;;
@@ -158,7 +158,7 @@ jobs:
         id: get-version
         shell: bash
         run: |
-          echo "wheel_version=$(pixi run scripts/ci/crates.py get-version)" >> "$GITHUB_OUTPUT"
+          pixi run -e wheel-test 'echo "wheel_version=$(python scripts/ci/crates.py get-version)"' >> "$GITHUB_OUTPUT"
 
       - name: Install built wheel
         # Now install the wheel using a specific version and --no-index to guarantee we get the version from
@@ -181,23 +181,18 @@ jobs:
         run: cd rerun_py/tests && pixi run -e wheel-test pytest -c ../pyproject.toml
 
       - name: Run e2e test
-        shell: bash
-        run: pixi run -e wheel-test RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed
+        run: pixi run -e wheel-test RUST_LOG=debug python scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed
 
       - name: Run tests/roundtrips.py
-        if: ${{ inputs.PLATFORM != 'windows-x64' && !inputs.FAST }}
-        shell: bash
+        if: ${{ !inputs.FAST }}
         # --release so we can inherit from some of the artifacts that maturin has just built before
-        # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow…
+        # explicit target because otherwise cargo loses the target cache… even though this is the target anyhow…
         # --no-py-build because rerun-sdk is already built and installed
-        run: |
-          pixi run -e wheel-test RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build
+        run: pixi run -e wheel-test RUST_LOG=debug python tests/roundtrips.py --release --target ${{ needs.set-config.outputs.TARGET }} --no-py-build
 
       - name: Run docs/snippets/compare_snippet_output.py
-        if: ${{ inputs.PLATFORM != 'windows-x64' && !inputs.FAST }}
-        shell: bash
+        if: ${{ !inputs.FAST }}
         # --release so we can inherit from some of the artifacts that maturin has just built before
-        # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow…
+        # explicit target because otherwise cargo loses the target cache… even though this is the target anyhow…
         # --no-py-build because rerun-sdk is already built and installed
-        run: |
-          pixi run -e wheel-test RUST_LOG=debug docs/snippets/compare_snippet_output.py --release --target x86_64-unknown-linux-gnu --no-py-build
+        run: pixi run -e wheel-test RUST_LOG=debug python docs/snippets/compare_snippet_output.py --release --target ${{ needs.set-config.outputs.TARGET }} --no-py-build
diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml
index 9ccb452f5d2e..c825a57ce6a8 100644
--- a/docs/snippets/snippets.toml
+++ b/docs/snippets/snippets.toml
@@ -38,6 +38,9 @@ asset3d_out_of_tree = [ # float issues since calculation is done slightly differ
   "py",
   "rust",
 ]
+bar_chart = [ # On Windows this logs f64 instead of u64 unless a numpy array with explicit type is used.
+  "py",
+]
 mesh3d_partial_updates = ["cpp", "py", "rust"] # float precision issues
 pinhole_simple = [ # TODO(#3206): examples use different RNGs
   "cpp",
diff --git a/scripts/run_python_e2e_test.py b/scripts/run_python_e2e_test.py
index 6080e1a1a5e8..e3bd74d0ca54 100755
--- a/scripts/run_python_e2e_test.py
+++ b/scripts/run_python_e2e_test.py
@@ -81,20 +81,15 @@ def main() -> None:
 
 
 def run_example(example: str, extra_args: list[str]) -> None:
-    # sys.executable: the absolute path of the executable binary for the Python interpreter
-    python_executable = sys.executable
-    if python_executable is None:
-        python_executable = "python3"
-
     env = os.environ.copy()
     env["RERUN_STRICT"] = "1"
     env["RERUN_PANIC_ON_WARN"] = "1"
 
-    cmd = [python_executable, "-m", "rerun", "--port", str(PORT), "--test-receive"]
+    cmd = ["python", "-m", "rerun", "--port", str(PORT), "--test-receive"]
     rerun_process = subprocess.Popen(cmd, env=env)
     time.sleep(0.5)  # Wait for rerun server to start to remove a logged warning
 
-    cmd = [python_executable, example, "--connect", "--addr", f"127.0.0.1:{PORT}"] + extra_args
+    cmd = ["python", example, "--connect", "--addr", f"127.0.0.1:{PORT}"] + extra_args
     python_process = subprocess.Popen(cmd, env=env)
 
     print("Waiting for python process to finish…")
diff --git a/tests/roundtrips.py b/tests/roundtrips.py
index 66730d0ac01a..9d62cb1bcc90 100755
--- a/tests/roundtrips.py
+++ b/tests/roundtrips.py
@@ -205,7 +205,8 @@ def run_roundtrip_cpp(arch: str, release: bool) -> str:
 
     cmake_build(target_name, release)
 
-    cmd = [f"{cpp_build_dir}/tests/cpp/roundtrips/{target_name}", output_path]
+    target_path = f"Release/{target_name}.exe" if os.name == "nt" else target_name
+    cmd = [f"{cpp_build_dir}/tests/cpp/roundtrips/{target_path}", output_path]
     run(cmd, env=roundtrip_env(), timeout=12000)
 
     return output_path

From c83306c6ac43d986692defba71697482f67240ba Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Tue, 16 Apr 2024 22:46:21 +0200
Subject: [PATCH 309/508] Enable lint for not specifying encoding on opening
 files in python (#5991)

### What

This fixes issues on windows where `open('somefile')` would use the
currently active encoding which may be governed my the locale / the
command line's configuration. This then causes issues loading utf8
encoded files.

The lint is part of Ruff's
[preview](https://docs.astral.sh/ruff/preview/) feature and therefore
requires enabling the `preview` option.
Unfortunately, this also changes the formatting despite specifying
`lint.explicit-preview-rules`, but looking over the changed formatting
it's consistently an improvement!

**Review commit by commit**


### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5991?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5991?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5991)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .../all/annotation_context_connections.py     |  26 +-
 examples/python/arkit_scenes/main.py          |   2 +-
 .../python/detect_and_track_objects/main.py   |   2 +-
 examples/python/external_data_loader/main.py  |   2 +-
 examples/python/human_pose_tracking/main.py   |  10 +-
 .../python/open_photogrammetry_format/main.py |  36 +-
 examples/python/raw_mesh/download_dataset.py  |   2 +-
 rerun_py/docs/gen_common_index.py             |   2 +-
 rerun_py/pyproject.toml                       |  24 +-
 .../blueprint/components/background3d_kind.py |  14 +-
 .../blueprint/components/container_kind.py    |  16 +-
 .../rerun/blueprint/components/corner2d.py    |  16 +-
 .../blueprint/datatypes/visible_time_range.py | 166 +++--
 .../datatypes/visible_time_range_boundary.py  |  32 +-
 .../visible_time_range_boundary_kind.py       |  14 +-
 .../rerun/components/annotation_context.py    | 106 ++-
 .../rerun/components/marker_shape.py          |  28 +-
 rerun_py/rerun_sdk/rerun/datatypes/angle.py   |  12 +-
 .../rerun/datatypes/annotation_info.py        |  12 +-
 .../rerun/datatypes/class_description.py      |  88 ++-
 .../datatypes/class_description_map_elem.py   | 102 ++-
 .../rerun/datatypes/keypoint_pair.py          |  10 +-
 .../rerun/datatypes/mesh_properties.py        |  18 +-
 .../rerun_sdk/rerun/datatypes/rotation3d.py   |  68 +-
 .../rerun/datatypes/rotation_axis_angle.py    |  40 +-
 rerun_py/rerun_sdk/rerun/datatypes/scale3d.py |  22 +-
 .../rerun/datatypes/tensor_buffer.py          | 176 +++--
 .../rerun_sdk/rerun/datatypes/tensor_data.py  | 222 ++++---
 .../rerun/datatypes/tensor_dimension.py       |  10 +-
 .../rerun_sdk/rerun/datatypes/transform3d.py  | 192 +++---
 .../rerun/datatypes/translation_and_mat3x3.py |  32 +-
 .../datatypes/translation_rotation_scale3d.py | 116 ++--
 rerun_py/rerun_sdk/rerun/utilities/data.py    |  30 +-
 rerun_py/rerun_sdk/rerun/utilities/turbo.py   | 518 ++++++++-------
 .../test_types/components/affix_fuzzer16.py   | 118 ++--
 .../test_types/components/affix_fuzzer17.py   | 118 ++--
 .../test_types/components/affix_fuzzer18.py   | 560 +++++++---------
 .../test_types/components/affix_fuzzer7.py    |  64 +-
 .../tests/test_types/components/enum_test.py  |  20 +-
 .../test_types/datatypes/affix_fuzzer1.py     |  64 +-
 .../test_types/datatypes/affix_fuzzer20.py    |  10 +-
 .../test_types/datatypes/affix_fuzzer21.py    |  20 +-
 .../test_types/datatypes/affix_fuzzer22.py    |  18 +-
 .../test_types/datatypes/affix_fuzzer3.py     | 108 ++--
 .../test_types/datatypes/affix_fuzzer4.py     | 467 +++++--------
 .../test_types/datatypes/affix_fuzzer5.py     | 611 +++++++-----------
 rerun_py/tests/unit/test_line_strips2d.py     |  30 +-
 rerun_py/tests/unit/test_line_strips3d.py     |  20 +-
 rerun_py/tests/unit/test_mesh3d.py            |  26 +-
 rerun_py/tests/unit/test_points2d.py          |  10 +-
 rerun_py/tests/unit/test_points3d.py          |  10 +-
 rerun_py/tests/unit/test_view_coordinates.py  |  12 +-
 scripts/ci/check_large_files.py               |   2 +-
 scripts/ci/check_links.py                     |   2 +-
 scripts/ci/compare.py                         |  14 +-
 scripts/ci/count_bytes.py                     |  12 +-
 scripts/ci/dag.py                             |  14 +-
 scripts/ci/generate_pr_summary.py             |   2 +-
 scripts/ci/generate_prerelease_pip_index.py   |   2 +-
 scripts/ci/render_bench.py                    |   2 +-
 scripts/ci/rust_checks.py                     |   2 +-
 scripts/generate_changelog.py                 |   4 +-
 scripts/generate_view_coordinate_defs.py      |   4 +-
 scripts/highlight_issues.py                   |   2 +-
 scripts/lint.py                               |   4 +-
 scripts/run_all.py                            |  32 +-
 scripts/zombie_todos.py                       |   2 +-
 .../annotation_context_ui_stress.py           |  26 +-
 tests/python/plot_dashboard_stress/main.py    |   4 +-
 tests/python/release_checklist/main.py        |   2 +-
 .../roundtrips/annotation_context/main.py     |  18 +-
 tests/python/test_api/main.py                 |  12 +-
 72 files changed, 2027 insertions(+), 2587 deletions(-)

diff --git a/docs/snippets/all/annotation_context_connections.py b/docs/snippets/all/annotation_context_connections.py
index 96c32c095caf..a8b260547386 100644
--- a/docs/snippets/all/annotation_context_connections.py
+++ b/docs/snippets/all/annotation_context_connections.py
@@ -7,20 +7,18 @@
 
 rr.log(
     "/",
-    rr.AnnotationContext(
-        [
-            ClassDescription(
-                info=0,
-                keypoint_annotations=[
-                    (0, "zero", (255, 0, 0)),
-                    (1, "one", (0, 255, 0)),
-                    (2, "two", (0, 0, 255)),
-                    (3, "three", (255, 255, 0)),
-                ],
-                keypoint_connections=[(0, 2), (1, 2), (2, 3)],
-            )
-        ]
-    ),
+    rr.AnnotationContext([
+        ClassDescription(
+            info=0,
+            keypoint_annotations=[
+                (0, "zero", (255, 0, 0)),
+                (1, "one", (0, 255, 0)),
+                (2, "two", (0, 0, 255)),
+                (3, "three", (255, 255, 0)),
+            ],
+            keypoint_connections=[(0, 2), (1, 2), (2, 3)],
+        )
+    ]),
     static=True,
 )
 
diff --git a/examples/python/arkit_scenes/main.py b/examples/python/arkit_scenes/main.py
index 27c13ca9a7f9..a633508daf78 100755
--- a/examples/python/arkit_scenes/main.py
+++ b/examples/python/arkit_scenes/main.py
@@ -44,7 +44,7 @@
 
 
 def load_json(js_path: Path) -> dict[str, Any]:
-    with open(js_path) as f:
+    with open(js_path, encoding="utf8") as f:
         json_data: dict[str, Any] = json.load(f)
     return json_data
 
diff --git a/examples/python/detect_and_track_objects/main.py b/examples/python/detect_and_track_objects/main.py
index 51ed28a90e4e..8baffd9ec05a 100755
--- a/examples/python/detect_and_track_objects/main.py
+++ b/examples/python/detect_and_track_objects/main.py
@@ -328,7 +328,7 @@ def update_trackers_with_detections(
 
 
 def track_objects(video_path: str, *, max_frame_count: int | None) -> None:
-    with open(COCO_CATEGORIES_PATH) as f:
+    with open(COCO_CATEGORIES_PATH, encoding="utf8") as f:
         coco_categories = json.load(f)
     class_descriptions = [
         rr.AnnotationInfo(id=cat["id"], color=cat["color"], label=cat["name"]) for cat in coco_categories
diff --git a/examples/python/external_data_loader/main.py b/examples/python/external_data_loader/main.py
index 39c057b2f96f..ac05af371970 100755
--- a/examples/python/external_data_loader/main.py
+++ b/examples/python/external_data_loader/main.py
@@ -74,7 +74,7 @@ def main() -> None:
     else:
         entity_path = args.filepath
 
-    with open(args.filepath) as file:
+    with open(args.filepath, encoding="utf8") as file:
         body = file.read()
         text = f"""## Some Python code\n```python\n{body}\n```\n"""
         rr.log(
diff --git a/examples/python/human_pose_tracking/main.py b/examples/python/human_pose_tracking/main.py
index b3c8ff5b798c..e58809c4eb46 100755
--- a/examples/python/human_pose_tracking/main.py
+++ b/examples/python/human_pose_tracking/main.py
@@ -61,12 +61,10 @@ def track_pose(video_path: str, model_path: str, *, segment: bool, max_frame_cou
     # Use a separate annotation context for the segmentation mask.
     rr.log(
         "video/mask",
-        rr.AnnotationContext(
-            [
-                rr.AnnotationInfo(id=0, label="Background"),
-                rr.AnnotationInfo(id=1, label="Person", color=(0, 0, 0)),
-            ]
-        ),
+        rr.AnnotationContext([
+            rr.AnnotationInfo(id=0, label="Background"),
+            rr.AnnotationInfo(id=1, label="Person", color=(0, 0, 0)),
+        ]),
         static=True,
     )
     rr.log("person", rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, static=True)
diff --git a/examples/python/open_photogrammetry_format/main.py b/examples/python/open_photogrammetry_format/main.py
index d09409cceb13..0649e7e4f5f2 100755
--- a/examples/python/open_photogrammetry_format/main.py
+++ b/examples/python/open_photogrammetry_format/main.py
@@ -157,27 +157,21 @@ def log_calibrated_cameras(self, jpeg_quality: int | None) -> None:
             # https://pix4d.github.io/opf-spec/specification/calibrated_cameras.html#calibrated-camera
             omega, phi, kappa = tuple(np.deg2rad(a) for a in calib_camera.orientation_deg)
             rot = (
-                np.array(
-                    [
-                        [1, 0, 0],
-                        [0, np.cos(omega), -np.sin(omega)],
-                        [0, np.sin(omega), np.cos(omega)],
-                    ]
-                )
-                @ np.array(
-                    [
-                        [np.cos(phi), 0, np.sin(phi)],
-                        [0, 1, 0],
-                        [-np.sin(phi), 0, np.cos(phi)],
-                    ]
-                )
-                @ np.array(
-                    [
-                        [np.cos(kappa), -np.sin(kappa), 0],
-                        [np.sin(kappa), np.cos(kappa), 0],
-                        [0, 0, 1],
-                    ]
-                )
+                np.array([
+                    [1, 0, 0],
+                    [0, np.cos(omega), -np.sin(omega)],
+                    [0, np.sin(omega), np.cos(omega)],
+                ])
+                @ np.array([
+                    [np.cos(phi), 0, np.sin(phi)],
+                    [0, 1, 0],
+                    [-np.sin(phi), 0, np.cos(phi)],
+                ])
+                @ np.array([
+                    [np.cos(kappa), -np.sin(kappa), 0],
+                    [np.sin(kappa), np.cos(kappa), 0],
+                    [0, 0, 1],
+                ])
             )
 
             rr.log(entity, rr.Transform3D(translation=calib_camera.position, mat3x3=rot))
diff --git a/examples/python/raw_mesh/download_dataset.py b/examples/python/raw_mesh/download_dataset.py
index 5d50b811d86f..1c92f48c3a0b 100755
--- a/examples/python/raw_mesh/download_dataset.py
+++ b/examples/python/raw_mesh/download_dataset.py
@@ -93,7 +93,7 @@ def download(url: str, path: Path) -> None:
             resp = requests.get(url)
             resp.raise_for_status()
             os.makedirs(path.parent, exist_ok=True)
-            with open(path, "wb") as f:
+            with open(path, "wb", encoding="utf8") as f:
                 f.write(resp.content)
 
     name = name.lower()
diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py
index 51d3ad70af7d..5afcc0ddd83d 100755
--- a/rerun_py/docs/gen_common_index.py
+++ b/rerun_py/docs/gen_common_index.py
@@ -50,7 +50,7 @@ def all_archetypes() -> list[str]:
     pattern = r'"([^"]*)"'
 
     # Open the file for reading
-    with open(file_path) as file:
+    with open(file_path, encoding="utf8") as file:
         # Read the file line by line
         for line in file:
             # Use re.findall to find all quoted strings in the line
diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml
index 0b0066f1ebe5..5f68e4e92f28 100644
--- a/rerun_py/pyproject.toml
+++ b/rerun_py/pyproject.toml
@@ -51,6 +51,11 @@ rerun = "rerun_bindings:main"
 # This is needed because otherwise ruff will not be able to trim whitespaces in (codegened) docstrings.
 unsafe-fixes = true
 
+# Allow preview lints to be enabled (like `PLW1514` to force `encoding` on open).
+preview = true
+# But we only want to opt-in to certain preview rules!
+lint.explicit-preview-rules = true
+
 extend-exclude = [
   # Automatically generated test artifacts
   "venv/",
@@ -101,13 +106,18 @@ lint.ignore = [
 
 line-length = 120
 lint.select = [
-  "D",   # pydocstyle codes https://www.pydocstyle.org/en/latest/error_codes.html
-  "E",   # pycodestyle error codes: https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes
-  "F",   # Flake8 error codes https://flake8.pycqa.org/en/latest/user/error-codes.html
-  "I",   # Isort
-  "TID", # flake8-tidy-imports
-  "W",   # pycodestyle warning codes: https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes
-  "UP",  # pyupgrade (ensures idomatic code for supported python version)
+  "D",       # pydocstyle codes https://www.pydocstyle.org/en/latest/error_codes.html
+  "E",       # pycodestyle error codes: https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes
+  "F",       # Flake8 error codes https://flake8.pycqa.org/en/latest/user/error-codes.html
+  "I",       # Isort
+  "TID",     # flake8-tidy-imports
+  "W",       # pycodestyle warning codes: https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes
+  "UP",      # pyupgrade (ensures idomatic code for supported python version)
+  "PLW1514", # Force setting `encoding` for open calls. This is in order to prevent issues when opening utf8 files on windows where the default encoding may depend on the active locale. https://docs.astral.sh/ruff/rules/unspecified-encoding/
+]
+
+lint.unfixable = [
+  "PLW1514", # Automatic fix for `encoding` doesn't do what we want - it queries the locale for the preferred encoding which is exactly what we want to avoid.
 ]
 
 [tool.ruff.lint.per-file-ignores]
diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py b/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py
index c37142f11140..815aba7d92d7 100644
--- a/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py
+++ b/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py
@@ -46,14 +46,12 @@ class Background3DKindType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.sparse_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field("GradientDark", pa.null(), nullable=True, metadata={}),
-                    pa.field("GradientBright", pa.null(), nullable=True, metadata={}),
-                    pa.field("SolidColor", pa.null(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.sparse_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field("GradientDark", pa.null(), nullable=True, metadata={}),
+                pa.field("GradientBright", pa.null(), nullable=True, metadata={}),
+                pa.field("SolidColor", pa.null(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/container_kind.py b/rerun_py/rerun_sdk/rerun/blueprint/components/container_kind.py
index 5c40eb987b3b..e0347d25a5df 100644
--- a/rerun_py/rerun_sdk/rerun/blueprint/components/container_kind.py
+++ b/rerun_py/rerun_sdk/rerun/blueprint/components/container_kind.py
@@ -36,15 +36,13 @@ class ContainerKindType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.sparse_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field("Tabs", pa.null(), nullable=True, metadata={}),
-                    pa.field("Horizontal", pa.null(), nullable=True, metadata={}),
-                    pa.field("Vertical", pa.null(), nullable=True, metadata={}),
-                    pa.field("Grid", pa.null(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.sparse_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field("Tabs", pa.null(), nullable=True, metadata={}),
+                pa.field("Horizontal", pa.null(), nullable=True, metadata={}),
+                pa.field("Vertical", pa.null(), nullable=True, metadata={}),
+                pa.field("Grid", pa.null(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/corner2d.py b/rerun_py/rerun_sdk/rerun/blueprint/components/corner2d.py
index 058b988a6a86..a682ad577fe8 100644
--- a/rerun_py/rerun_sdk/rerun/blueprint/components/corner2d.py
+++ b/rerun_py/rerun_sdk/rerun/blueprint/components/corner2d.py
@@ -36,15 +36,13 @@ class Corner2DType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.sparse_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field("LeftTop", pa.null(), nullable=True, metadata={}),
-                    pa.field("RightTop", pa.null(), nullable=True, metadata={}),
-                    pa.field("LeftBottom", pa.null(), nullable=True, metadata={}),
-                    pa.field("RightBottom", pa.null(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.sparse_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field("LeftTop", pa.null(), nullable=True, metadata={}),
+                pa.field("RightTop", pa.null(), nullable=True, metadata={}),
+                pa.field("LeftBottom", pa.null(), nullable=True, metadata={}),
+                pa.field("RightBottom", pa.null(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py
index 735c720b7a47..a588b0ac926c 100644
--- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py
+++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py
@@ -86,102 +86,84 @@ class VisibleTimeRangeType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "from_sequence",
-                        pa.struct(
-                            [
-                                pa.field(
-                                    "kind",
-                                    pa.sparse_union(
-                                        [
-                                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                            pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Absolute", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Infinite", pa.null(), nullable=True, metadata={}),
-                                        ]
-                                    ),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field("time", pa.int64(), nullable=False, metadata={}),
-                            ]
+            pa.struct([
+                pa.field(
+                    "from_sequence",
+                    pa.struct([
+                        pa.field(
+                            "kind",
+                            pa.sparse_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
+                                pa.field("Absolute", pa.null(), nullable=True, metadata={}),
+                                pa.field("Infinite", pa.null(), nullable=True, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "to_sequence",
-                        pa.struct(
-                            [
-                                pa.field(
-                                    "kind",
-                                    pa.sparse_union(
-                                        [
-                                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                            pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Absolute", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Infinite", pa.null(), nullable=True, metadata={}),
-                                        ]
-                                    ),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field("time", pa.int64(), nullable=False, metadata={}),
-                            ]
+                        pa.field("time", pa.int64(), nullable=False, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "to_sequence",
+                    pa.struct([
+                        pa.field(
+                            "kind",
+                            pa.sparse_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
+                                pa.field("Absolute", pa.null(), nullable=True, metadata={}),
+                                pa.field("Infinite", pa.null(), nullable=True, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "from_time",
-                        pa.struct(
-                            [
-                                pa.field(
-                                    "kind",
-                                    pa.sparse_union(
-                                        [
-                                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                            pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Absolute", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Infinite", pa.null(), nullable=True, metadata={}),
-                                        ]
-                                    ),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field("time", pa.int64(), nullable=False, metadata={}),
-                            ]
+                        pa.field("time", pa.int64(), nullable=False, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "from_time",
+                    pa.struct([
+                        pa.field(
+                            "kind",
+                            pa.sparse_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
+                                pa.field("Absolute", pa.null(), nullable=True, metadata={}),
+                                pa.field("Infinite", pa.null(), nullable=True, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "to_time",
-                        pa.struct(
-                            [
-                                pa.field(
-                                    "kind",
-                                    pa.sparse_union(
-                                        [
-                                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                            pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Absolute", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Infinite", pa.null(), nullable=True, metadata={}),
-                                        ]
-                                    ),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field("time", pa.int64(), nullable=False, metadata={}),
-                            ]
+                        pa.field("time", pa.int64(), nullable=False, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "to_time",
+                    pa.struct([
+                        pa.field(
+                            "kind",
+                            pa.sparse_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
+                                pa.field("Absolute", pa.null(), nullable=True, metadata={}),
+                                pa.field("Infinite", pa.null(), nullable=True, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+                        pa.field("time", pa.int64(), nullable=False, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py
index 7d94422c9c4e..6f5ffdfc9bd0 100644
--- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py
+++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py
@@ -74,24 +74,20 @@ class VisibleTimeRangeBoundaryType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "kind",
-                        pa.sparse_union(
-                            [
-                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
-                                pa.field("Absolute", pa.null(), nullable=True, metadata={}),
-                                pa.field("Infinite", pa.null(), nullable=True, metadata={}),
-                            ]
-                        ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field("time", pa.int64(), nullable=False, metadata={}),
-                ]
-            ),
+            pa.struct([
+                pa.field(
+                    "kind",
+                    pa.sparse_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
+                        pa.field("Absolute", pa.null(), nullable=True, metadata={}),
+                        pa.field("Infinite", pa.null(), nullable=True, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field("time", pa.int64(), nullable=False, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py
index e179602b070d..72a218b1b3fd 100644
--- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py
+++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py
@@ -48,14 +48,12 @@ class VisibleTimeRangeBoundaryKindType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.sparse_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
-                    pa.field("Absolute", pa.null(), nullable=True, metadata={}),
-                    pa.field("Infinite", pa.null(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.sparse_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}),
+                pa.field("Absolute", pa.null(), nullable=True, metadata={}),
+                pa.field("Infinite", pa.null(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/components/annotation_context.py b/rerun_py/rerun_sdk/rerun/components/annotation_context.py
index 55ee8280a28a..6a57c850a770 100644
--- a/rerun_py/rerun_sdk/rerun/components/annotation_context.py
+++ b/rerun_py/rerun_sdk/rerun/components/annotation_context.py
@@ -79,73 +79,59 @@ def __init__(self) -> None:
             pa.list_(
                 pa.field(
                     "item",
-                    pa.struct(
-                        [
-                            pa.field("class_id", pa.uint16(), nullable=False, metadata={}),
-                            pa.field(
-                                "class_description",
-                                pa.struct(
-                                    [
-                                        pa.field(
-                                            "info",
-                                            pa.struct(
-                                                [
-                                                    pa.field("id", pa.uint16(), nullable=False, metadata={}),
-                                                    pa.field("label", pa.utf8(), nullable=True, metadata={}),
-                                                    pa.field("color", pa.uint32(), nullable=True, metadata={}),
-                                                ]
-                                            ),
-                                            nullable=False,
-                                            metadata={},
-                                        ),
+                    pa.struct([
+                        pa.field("class_id", pa.uint16(), nullable=False, metadata={}),
+                        pa.field(
+                            "class_description",
+                            pa.struct([
+                                pa.field(
+                                    "info",
+                                    pa.struct([
+                                        pa.field("id", pa.uint16(), nullable=False, metadata={}),
+                                        pa.field("label", pa.utf8(), nullable=True, metadata={}),
+                                        pa.field("color", pa.uint32(), nullable=True, metadata={}),
+                                    ]),
+                                    nullable=False,
+                                    metadata={},
+                                ),
+                                pa.field(
+                                    "keypoint_annotations",
+                                    pa.list_(
                                         pa.field(
-                                            "keypoint_annotations",
-                                            pa.list_(
-                                                pa.field(
-                                                    "item",
-                                                    pa.struct(
-                                                        [
-                                                            pa.field("id", pa.uint16(), nullable=False, metadata={}),
-                                                            pa.field("label", pa.utf8(), nullable=True, metadata={}),
-                                                            pa.field("color", pa.uint32(), nullable=True, metadata={}),
-                                                        ]
-                                                    ),
-                                                    nullable=False,
-                                                    metadata={},
-                                                )
-                                            ),
+                                            "item",
+                                            pa.struct([
+                                                pa.field("id", pa.uint16(), nullable=False, metadata={}),
+                                                pa.field("label", pa.utf8(), nullable=True, metadata={}),
+                                                pa.field("color", pa.uint32(), nullable=True, metadata={}),
+                                            ]),
                                             nullable=False,
                                             metadata={},
-                                        ),
+                                        )
+                                    ),
+                                    nullable=False,
+                                    metadata={},
+                                ),
+                                pa.field(
+                                    "keypoint_connections",
+                                    pa.list_(
                                         pa.field(
-                                            "keypoint_connections",
-                                            pa.list_(
-                                                pa.field(
-                                                    "item",
-                                                    pa.struct(
-                                                        [
-                                                            pa.field(
-                                                                "keypoint0", pa.uint16(), nullable=False, metadata={}
-                                                            ),
-                                                            pa.field(
-                                                                "keypoint1", pa.uint16(), nullable=False, metadata={}
-                                                            ),
-                                                        ]
-                                                    ),
-                                                    nullable=False,
-                                                    metadata={},
-                                                )
-                                            ),
+                                            "item",
+                                            pa.struct([
+                                                pa.field("keypoint0", pa.uint16(), nullable=False, metadata={}),
+                                                pa.field("keypoint1", pa.uint16(), nullable=False, metadata={}),
+                                            ]),
                                             nullable=False,
                                             metadata={},
-                                        ),
-                                    ]
+                                        )
+                                    ),
+                                    nullable=False,
+                                    metadata={},
                                 ),
-                                nullable=False,
-                                metadata={},
-                            ),
-                        ]
-                    ),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        ),
+                    ]),
                     nullable=False,
                     metadata={},
                 )
diff --git a/rerun_py/rerun_sdk/rerun/components/marker_shape.py b/rerun_py/rerun_sdk/rerun/components/marker_shape.py
index eb320d2d80fa..e945fa04f9cc 100644
--- a/rerun_py/rerun_sdk/rerun/components/marker_shape.py
+++ b/rerun_py/rerun_sdk/rerun/components/marker_shape.py
@@ -42,21 +42,19 @@ class MarkerShapeType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.sparse_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field("Circle", pa.null(), nullable=True, metadata={}),
-                    pa.field("Diamond", pa.null(), nullable=True, metadata={}),
-                    pa.field("Square", pa.null(), nullable=True, metadata={}),
-                    pa.field("Cross", pa.null(), nullable=True, metadata={}),
-                    pa.field("Plus", pa.null(), nullable=True, metadata={}),
-                    pa.field("Up", pa.null(), nullable=True, metadata={}),
-                    pa.field("Down", pa.null(), nullable=True, metadata={}),
-                    pa.field("Left", pa.null(), nullable=True, metadata={}),
-                    pa.field("Right", pa.null(), nullable=True, metadata={}),
-                    pa.field("Asterisk", pa.null(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.sparse_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field("Circle", pa.null(), nullable=True, metadata={}),
+                pa.field("Diamond", pa.null(), nullable=True, metadata={}),
+                pa.field("Square", pa.null(), nullable=True, metadata={}),
+                pa.field("Cross", pa.null(), nullable=True, metadata={}),
+                pa.field("Plus", pa.null(), nullable=True, metadata={}),
+                pa.field("Up", pa.null(), nullable=True, metadata={}),
+                pa.field("Down", pa.null(), nullable=True, metadata={}),
+                pa.field("Left", pa.null(), nullable=True, metadata={}),
+                pa.field("Right", pa.null(), nullable=True, metadata={}),
+                pa.field("Asterisk", pa.null(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/angle.py b/rerun_py/rerun_sdk/rerun/datatypes/angle.py
index e0fd7c03002e..6d298b1337b7 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/angle.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/angle.py
@@ -66,13 +66,11 @@ class AngleType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.dense_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field("Radians", pa.float32(), nullable=False, metadata={}),
-                    pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
-                ]
-            ),
+            pa.dense_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field("Radians", pa.float32(), nullable=False, metadata={}),
+                pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/annotation_info.py b/rerun_py/rerun_sdk/rerun/datatypes/annotation_info.py
index 26a295d6f009..fb8e6dea8890 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/annotation_info.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/annotation_info.py
@@ -109,13 +109,11 @@ class AnnotationInfoType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field("id", pa.uint16(), nullable=False, metadata={}),
-                    pa.field("label", pa.utf8(), nullable=True, metadata={}),
-                    pa.field("color", pa.uint32(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.struct([
+                pa.field("id", pa.uint16(), nullable=False, metadata={}),
+                pa.field("label", pa.utf8(), nullable=True, metadata={}),
+                pa.field("color", pa.uint32(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/class_description.py b/rerun_py/rerun_sdk/rerun/datatypes/class_description.py
index ee42782245a2..bb366ff0e3ee 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/class_description.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/class_description.py
@@ -87,59 +87,51 @@ class ClassDescriptionType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "info",
-                        pa.struct(
-                            [
+            pa.struct([
+                pa.field(
+                    "info",
+                    pa.struct([
+                        pa.field("id", pa.uint16(), nullable=False, metadata={}),
+                        pa.field("label", pa.utf8(), nullable=True, metadata={}),
+                        pa.field("color", pa.uint32(), nullable=True, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "keypoint_annotations",
+                    pa.list_(
+                        pa.field(
+                            "item",
+                            pa.struct([
                                 pa.field("id", pa.uint16(), nullable=False, metadata={}),
                                 pa.field("label", pa.utf8(), nullable=True, metadata={}),
                                 pa.field("color", pa.uint32(), nullable=True, metadata={}),
-                            ]
-                        ),
-                        nullable=False,
-                        metadata={},
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        )
                     ),
-                    pa.field(
-                        "keypoint_annotations",
-                        pa.list_(
-                            pa.field(
-                                "item",
-                                pa.struct(
-                                    [
-                                        pa.field("id", pa.uint16(), nullable=False, metadata={}),
-                                        pa.field("label", pa.utf8(), nullable=True, metadata={}),
-                                        pa.field("color", pa.uint32(), nullable=True, metadata={}),
-                                    ]
-                                ),
-                                nullable=False,
-                                metadata={},
-                            )
-                        ),
-                        nullable=False,
-                        metadata={},
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "keypoint_connections",
+                    pa.list_(
+                        pa.field(
+                            "item",
+                            pa.struct([
+                                pa.field("keypoint0", pa.uint16(), nullable=False, metadata={}),
+                                pa.field("keypoint1", pa.uint16(), nullable=False, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        )
                     ),
-                    pa.field(
-                        "keypoint_connections",
-                        pa.list_(
-                            pa.field(
-                                "item",
-                                pa.struct(
-                                    [
-                                        pa.field("keypoint0", pa.uint16(), nullable=False, metadata={}),
-                                        pa.field("keypoint1", pa.uint16(), nullable=False, metadata={}),
-                                    ]
-                                ),
-                                nullable=False,
-                                metadata={},
-                            )
-                        ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/class_description_map_elem.py b/rerun_py/rerun_sdk/rerun/datatypes/class_description_map_elem.py
index 2b3953264be8..cc99e8ebace5 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/class_description_map_elem.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/class_description_map_elem.py
@@ -86,69 +86,59 @@ class ClassDescriptionMapElemType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field("class_id", pa.uint16(), nullable=False, metadata={}),
-                    pa.field(
-                        "class_description",
-                        pa.struct(
-                            [
-                                pa.field(
-                                    "info",
-                                    pa.struct(
-                                        [
-                                            pa.field("id", pa.uint16(), nullable=False, metadata={}),
-                                            pa.field("label", pa.utf8(), nullable=True, metadata={}),
-                                            pa.field("color", pa.uint32(), nullable=True, metadata={}),
-                                        ]
-                                    ),
-                                    nullable=False,
-                                    metadata={},
-                                ),
+            pa.struct([
+                pa.field("class_id", pa.uint16(), nullable=False, metadata={}),
+                pa.field(
+                    "class_description",
+                    pa.struct([
+                        pa.field(
+                            "info",
+                            pa.struct([
+                                pa.field("id", pa.uint16(), nullable=False, metadata={}),
+                                pa.field("label", pa.utf8(), nullable=True, metadata={}),
+                                pa.field("color", pa.uint32(), nullable=True, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "keypoint_annotations",
+                            pa.list_(
                                 pa.field(
-                                    "keypoint_annotations",
-                                    pa.list_(
-                                        pa.field(
-                                            "item",
-                                            pa.struct(
-                                                [
-                                                    pa.field("id", pa.uint16(), nullable=False, metadata={}),
-                                                    pa.field("label", pa.utf8(), nullable=True, metadata={}),
-                                                    pa.field("color", pa.uint32(), nullable=True, metadata={}),
-                                                ]
-                                            ),
-                                            nullable=False,
-                                            metadata={},
-                                        )
-                                    ),
+                                    "item",
+                                    pa.struct([
+                                        pa.field("id", pa.uint16(), nullable=False, metadata={}),
+                                        pa.field("label", pa.utf8(), nullable=True, metadata={}),
+                                        pa.field("color", pa.uint32(), nullable=True, metadata={}),
+                                    ]),
                                     nullable=False,
                                     metadata={},
-                                ),
+                                )
+                            ),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "keypoint_connections",
+                            pa.list_(
                                 pa.field(
-                                    "keypoint_connections",
-                                    pa.list_(
-                                        pa.field(
-                                            "item",
-                                            pa.struct(
-                                                [
-                                                    pa.field("keypoint0", pa.uint16(), nullable=False, metadata={}),
-                                                    pa.field("keypoint1", pa.uint16(), nullable=False, metadata={}),
-                                                ]
-                                            ),
-                                            nullable=False,
-                                            metadata={},
-                                        )
-                                    ),
+                                    "item",
+                                    pa.struct([
+                                        pa.field("keypoint0", pa.uint16(), nullable=False, metadata={}),
+                                        pa.field("keypoint1", pa.uint16(), nullable=False, metadata={}),
+                                    ]),
                                     nullable=False,
                                     metadata={},
-                                ),
-                            ]
+                                )
+                            ),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/keypoint_pair.py b/rerun_py/rerun_sdk/rerun/datatypes/keypoint_pair.py
index 246801ad49d8..762551957e6d 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/keypoint_pair.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/keypoint_pair.py
@@ -79,12 +79,10 @@ class KeypointPairType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field("keypoint0", pa.uint16(), nullable=False, metadata={}),
-                    pa.field("keypoint1", pa.uint16(), nullable=False, metadata={}),
-                ]
-            ),
+            pa.struct([
+                pa.field("keypoint0", pa.uint16(), nullable=False, metadata={}),
+                pa.field("keypoint1", pa.uint16(), nullable=False, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/mesh_properties.py b/rerun_py/rerun_sdk/rerun/datatypes/mesh_properties.py
index 29b7d6ca8d7e..da993757d1c2 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/mesh_properties.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/mesh_properties.py
@@ -72,16 +72,14 @@ class MeshPropertiesType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "indices",
-                        pa.list_(pa.field("item", pa.uint32(), nullable=False, metadata={})),
-                        nullable=True,
-                        metadata={},
-                    )
-                ]
-            ),
+            pa.struct([
+                pa.field(
+                    "indices",
+                    pa.list_(pa.field("item", pa.uint32(), nullable=False, metadata={})),
+                    nullable=True,
+                    metadata={},
+                )
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/rotation3d.py b/rerun_py/rerun_sdk/rerun/datatypes/rotation3d.py
index fcc1a03cb987..9fcdf1d81a06 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/rotation3d.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/rotation3d.py
@@ -56,44 +56,38 @@ class Rotation3DType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.dense_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field(
-                        "Quaternion",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 4),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "AxisAngle",
-                        pa.struct(
-                            [
-                                pa.field(
-                                    "axis",
-                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "angle",
-                                    pa.dense_union(
-                                        [
-                                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                            pa.field("Radians", pa.float32(), nullable=False, metadata={}),
-                                            pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
-                                        ]
-                                    ),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                            ]
+            pa.dense_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field(
+                    "Quaternion",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 4),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "AxisAngle",
+                    pa.struct([
+                        pa.field(
+                            "axis",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+                        pa.field(
+                            "angle",
+                            pa.dense_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                pa.field("Radians", pa.float32(), nullable=False, metadata={}),
+                                pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        ),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle.py b/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle.py
index 535b01a7aab1..209b57e16c92 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle.py
@@ -66,28 +66,24 @@ class RotationAxisAngleType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "axis",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "angle",
-                        pa.dense_union(
-                            [
-                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                pa.field("Radians", pa.float32(), nullable=False, metadata={}),
-                                pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
-                            ]
-                        ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+            pa.struct([
+                pa.field(
+                    "axis",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "angle",
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field("Radians", pa.float32(), nullable=False, metadata={}),
+                        pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/scale3d.py b/rerun_py/rerun_sdk/rerun/datatypes/scale3d.py
index 897f6f56c04c..b07f31a7c611 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/scale3d.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/scale3d.py
@@ -70,18 +70,16 @@ class Scale3DType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.dense_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field(
-                        "ThreeD",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field("Uniform", pa.float32(), nullable=False, metadata={}),
-                ]
-            ),
+            pa.dense_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field(
+                    "ThreeD",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field("Uniform", pa.float32(), nullable=False, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py
index 36ae3c1e1c76..9e61d27392d9 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py
@@ -188,95 +188,93 @@ class TensorBufferType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.dense_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field(
-                        "U8",
-                        pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "U16",
-                        pa.list_(pa.field("item", pa.uint16(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "U32",
-                        pa.list_(pa.field("item", pa.uint32(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "U64",
-                        pa.list_(pa.field("item", pa.uint64(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "I8",
-                        pa.list_(pa.field("item", pa.int8(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "I16",
-                        pa.list_(pa.field("item", pa.int16(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "I32",
-                        pa.list_(pa.field("item", pa.int32(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "I64",
-                        pa.list_(pa.field("item", pa.int64(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "F16",
-                        pa.list_(pa.field("item", pa.float16(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "F32",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "F64",
-                        pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "JPEG",
-                        pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "NV12",
-                        pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "YUY2",
-                        pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+            pa.dense_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field(
+                    "U8",
+                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "U16",
+                    pa.list_(pa.field("item", pa.uint16(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "U32",
+                    pa.list_(pa.field("item", pa.uint32(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "U64",
+                    pa.list_(pa.field("item", pa.uint64(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "I8",
+                    pa.list_(pa.field("item", pa.int8(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "I16",
+                    pa.list_(pa.field("item", pa.int16(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "I32",
+                    pa.list_(pa.field("item", pa.int32(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "I64",
+                    pa.list_(pa.field("item", pa.int64(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "F16",
+                    pa.list_(pa.field("item", pa.float16(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "F32",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "F64",
+                    pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "JPEG",
+                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "NV12",
+                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "YUY2",
+                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py
index 1752ce60a208..35b34f38da33 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py
@@ -63,122 +63,116 @@ class TensorDataType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "shape",
-                        pa.list_(
-                            pa.field(
-                                "item",
-                                pa.struct(
-                                    [
-                                        pa.field("size", pa.uint64(), nullable=False, metadata={}),
-                                        pa.field("name", pa.utf8(), nullable=True, metadata={}),
-                                    ]
-                                ),
-                                nullable=False,
-                                metadata={},
-                            )
-                        ),
-                        nullable=False,
-                        metadata={},
+            pa.struct([
+                pa.field(
+                    "shape",
+                    pa.list_(
+                        pa.field(
+                            "item",
+                            pa.struct([
+                                pa.field("size", pa.uint64(), nullable=False, metadata={}),
+                                pa.field("name", pa.utf8(), nullable=True, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        )
                     ),
-                    pa.field(
-                        "buffer",
-                        pa.dense_union(
-                            [
-                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                pa.field(
-                                    "U8",
-                                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "U16",
-                                    pa.list_(pa.field("item", pa.uint16(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "U32",
-                                    pa.list_(pa.field("item", pa.uint32(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "U64",
-                                    pa.list_(pa.field("item", pa.uint64(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "I8",
-                                    pa.list_(pa.field("item", pa.int8(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "I16",
-                                    pa.list_(pa.field("item", pa.int16(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "I32",
-                                    pa.list_(pa.field("item", pa.int32(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "I64",
-                                    pa.list_(pa.field("item", pa.int64(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "F16",
-                                    pa.list_(pa.field("item", pa.float16(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "F32",
-                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "F64",
-                                    pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "JPEG",
-                                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "NV12",
-                                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "YUY2",
-                                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                            ]
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "buffer",
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field(
+                            "U8",
+                            pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+                        pa.field(
+                            "U16",
+                            pa.list_(pa.field("item", pa.uint16(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "U32",
+                            pa.list_(pa.field("item", pa.uint32(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "U64",
+                            pa.list_(pa.field("item", pa.uint64(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "I8",
+                            pa.list_(pa.field("item", pa.int8(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "I16",
+                            pa.list_(pa.field("item", pa.int16(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "I32",
+                            pa.list_(pa.field("item", pa.int32(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "I64",
+                            pa.list_(pa.field("item", pa.int64(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "F16",
+                            pa.list_(pa.field("item", pa.float16(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "F32",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "F64",
+                            pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "JPEG",
+                            pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "NV12",
+                            pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "YUY2",
+                            pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py
index 56d75add04b4..e7d11a6a585e 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py
@@ -68,12 +68,10 @@ class TensorDimensionType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field("size", pa.uint64(), nullable=False, metadata={}),
-                    pa.field("name", pa.utf8(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.struct([
+                pa.field("size", pa.uint64(), nullable=False, metadata={}),
+                pa.field("name", pa.utf8(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py b/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py
index 7c09f28f83bf..e10448ac7c09 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py
@@ -56,133 +56,95 @@ class Transform3DType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.dense_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field(
-                        "TranslationAndMat3x3",
-                        pa.struct(
-                            [
+            pa.dense_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field(
+                    "TranslationAndMat3x3",
+                    pa.struct([
+                        pa.field(
+                            "translation",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                            nullable=True,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "mat3x3",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 9),
+                            nullable=True,
+                            metadata={},
+                        ),
+                        pa.field("from_parent", pa.bool_(), nullable=False, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "TranslationRotationScale",
+                    pa.struct([
+                        pa.field(
+                            "translation",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                            nullable=True,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "rotation",
+                            pa.dense_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
                                 pa.field(
-                                    "translation",
-                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                                    nullable=True,
+                                    "Quaternion",
+                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 4),
+                                    nullable=False,
                                     metadata={},
                                 ),
                                 pa.field(
-                                    "mat3x3",
-                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 9),
-                                    nullable=True,
+                                    "AxisAngle",
+                                    pa.struct([
+                                        pa.field(
+                                            "axis",
+                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                        pa.field(
+                                            "angle",
+                                            pa.dense_union([
+                                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                                pa.field("Radians", pa.float32(), nullable=False, metadata={}),
+                                                pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
+                                            ]),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                    ]),
+                                    nullable=False,
                                     metadata={},
                                 ),
-                                pa.field("from_parent", pa.bool_(), nullable=False, metadata={}),
-                            ]
+                            ]),
+                            nullable=True,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "TranslationRotationScale",
-                        pa.struct(
-                            [
+                        pa.field(
+                            "scale",
+                            pa.dense_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
                                 pa.field(
-                                    "translation",
+                                    "ThreeD",
                                     pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                                    nullable=True,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "rotation",
-                                    pa.dense_union(
-                                        [
-                                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                            pa.field(
-                                                "Quaternion",
-                                                pa.list_(
-                                                    pa.field("item", pa.float32(), nullable=False, metadata={}), 4
-                                                ),
-                                                nullable=False,
-                                                metadata={},
-                                            ),
-                                            pa.field(
-                                                "AxisAngle",
-                                                pa.struct(
-                                                    [
-                                                        pa.field(
-                                                            "axis",
-                                                            pa.list_(
-                                                                pa.field(
-                                                                    "item", pa.float32(), nullable=False, metadata={}
-                                                                ),
-                                                                3,
-                                                            ),
-                                                            nullable=False,
-                                                            metadata={},
-                                                        ),
-                                                        pa.field(
-                                                            "angle",
-                                                            pa.dense_union(
-                                                                [
-                                                                    pa.field(
-                                                                        "_null_markers",
-                                                                        pa.null(),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "Radians",
-                                                                        pa.float32(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "Degrees",
-                                                                        pa.float32(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                ]
-                                                            ),
-                                                            nullable=False,
-                                                            metadata={},
-                                                        ),
-                                                    ]
-                                                ),
-                                                nullable=False,
-                                                metadata={},
-                                            ),
-                                        ]
-                                    ),
-                                    nullable=True,
-                                    metadata={},
-                                ),
-                                pa.field(
-                                    "scale",
-                                    pa.dense_union(
-                                        [
-                                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                            pa.field(
-                                                "ThreeD",
-                                                pa.list_(
-                                                    pa.field("item", pa.float32(), nullable=False, metadata={}), 3
-                                                ),
-                                                nullable=False,
-                                                metadata={},
-                                            ),
-                                            pa.field("Uniform", pa.float32(), nullable=False, metadata={}),
-                                        ]
-                                    ),
-                                    nullable=True,
+                                    nullable=False,
                                     metadata={},
                                 ),
-                                pa.field("from_parent", pa.bool_(), nullable=False, metadata={}),
-                            ]
+                                pa.field("Uniform", pa.float32(), nullable=False, metadata={}),
+                            ]),
+                            nullable=True,
+                            metadata={},
                         ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+                        pa.field("from_parent", pa.bool_(), nullable=False, metadata={}),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py
index 10fee8b83f9e..16294b40c079 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py
@@ -91,23 +91,21 @@ class TranslationAndMat3x3Type(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "translation",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                        nullable=True,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "mat3x3",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 9),
-                        nullable=True,
-                        metadata={},
-                    ),
-                    pa.field("from_parent", pa.bool_(), nullable=False, metadata={}),
-                ]
-            ),
+            pa.struct([
+                pa.field(
+                    "translation",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                    nullable=True,
+                    metadata={},
+                ),
+                pa.field(
+                    "mat3x3",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 9),
+                    nullable=True,
+                    metadata={},
+                ),
+                pa.field("from_parent", pa.bool_(), nullable=False, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py
index 35274d15baad..545d80e8ca43 100644
--- a/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py
+++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py
@@ -95,81 +95,67 @@ class TranslationRotationScale3DType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "translation",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                        nullable=True,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "rotation",
-                        pa.dense_union(
-                            [
-                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+            pa.struct([
+                pa.field(
+                    "translation",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                    nullable=True,
+                    metadata={},
+                ),
+                pa.field(
+                    "rotation",
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field(
+                            "Quaternion",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 4),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "AxisAngle",
+                            pa.struct([
                                 pa.field(
-                                    "Quaternion",
-                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 4),
+                                    "axis",
+                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
                                     nullable=False,
                                     metadata={},
                                 ),
                                 pa.field(
-                                    "AxisAngle",
-                                    pa.struct(
-                                        [
-                                            pa.field(
-                                                "axis",
-                                                pa.list_(
-                                                    pa.field("item", pa.float32(), nullable=False, metadata={}), 3
-                                                ),
-                                                nullable=False,
-                                                metadata={},
-                                            ),
-                                            pa.field(
-                                                "angle",
-                                                pa.dense_union(
-                                                    [
-                                                        pa.field(
-                                                            "_null_markers", pa.null(), nullable=True, metadata={}
-                                                        ),
-                                                        pa.field("Radians", pa.float32(), nullable=False, metadata={}),
-                                                        pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
-                                                    ]
-                                                ),
-                                                nullable=False,
-                                                metadata={},
-                                            ),
-                                        ]
-                                    ),
+                                    "angle",
+                                    pa.dense_union([
+                                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                        pa.field("Radians", pa.float32(), nullable=False, metadata={}),
+                                        pa.field("Degrees", pa.float32(), nullable=False, metadata={}),
+                                    ]),
                                     nullable=False,
                                     metadata={},
                                 ),
-                            ]
+                            ]),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=True,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "scale",
-                        pa.dense_union(
-                            [
-                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                pa.field(
-                                    "ThreeD",
-                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                                    nullable=False,
-                                    metadata={},
-                                ),
-                                pa.field("Uniform", pa.float32(), nullable=False, metadata={}),
-                            ]
+                    ]),
+                    nullable=True,
+                    metadata={},
+                ),
+                pa.field(
+                    "scale",
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field(
+                            "ThreeD",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=True,
-                        metadata={},
-                    ),
-                    pa.field("from_parent", pa.bool_(), nullable=False, metadata={}),
-                ]
-            ),
+                        pa.field("Uniform", pa.float32(), nullable=False, metadata={}),
+                    ]),
+                    nullable=True,
+                    metadata={},
+                ),
+                pa.field("from_parent", pa.bool_(), nullable=False, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/rerun_sdk/rerun/utilities/data.py b/rerun_py/rerun_sdk/rerun/utilities/data.py
index d8419f5370bd..6d02871fe8a3 100644
--- a/rerun_py/rerun_sdk/rerun/utilities/data.py
+++ b/rerun_py/rerun_sdk/rerun/utilities/data.py
@@ -56,16 +56,14 @@ def build_color_grid(x_count: int = 10, y_count: int = 10, z_count: int = 10, tw
 
     positions = np.vstack([xyz.ravel() for xyz in grid])
 
-    colors = np.vstack(
-        [
-            xyz.ravel()
-            for xyz in np.mgrid[
-                slice(0, 255, x_count * 1j),
-                slice(0, 255, y_count * 1j),
-                slice(0, 255, z_count * 1j),
-            ]
+    colors = np.vstack([
+        xyz.ravel()
+        for xyz in np.mgrid[
+            slice(0, 255, x_count * 1j),
+            slice(0, 255, y_count * 1j),
+            slice(0, 255, z_count * 1j),
         ]
-    )
+    ])
 
     return ColorGrid(positions.T, colors.T.astype(np.uint8))
 
@@ -132,16 +130,14 @@ def build_color_spiral(
         The factor applied between each step along the Z axis.
 
     """
-    positions = np.array(
+    positions = np.array([
         [
-            [
-                cos(i * tau * angular_step + angular_offset) * radius,
-                sin(i * tau * angular_step + angular_offset) * radius,
-                i * z_step,
-            ]
-            for i in range(num_points)
+            cos(i * tau * angular_step + angular_offset) * radius,
+            sin(i * tau * angular_step + angular_offset) * radius,
+            i * z_step,
         ]
-    )
+        for i in range(num_points)
+    ])
     colors = turbo_colormap_data[np.linspace(0, len(turbo_colormap_data) - 1, num_points, dtype=int)]
 
     return ColorSpiral(positions, colors)
diff --git a/rerun_py/rerun_sdk/rerun/utilities/turbo.py b/rerun_py/rerun_sdk/rerun/utilities/turbo.py
index e711fbc2a7e7..005af175d6ce 100644
--- a/rerun_py/rerun_sdk/rerun/utilities/turbo.py
+++ b/rerun_py/rerun_sdk/rerun/utilities/turbo.py
@@ -4,263 +4,261 @@
 
 __all__ = ["turbo_colormap_data"]
 
-turbo_colormap_data = np.array(
-    [
-        [0.18995, 0.07176, 0.23217],
-        [0.19483, 0.08339, 0.26149],
-        [0.19956, 0.09498, 0.29024],
-        [0.20415, 0.10652, 0.31844],
-        [0.20860, 0.11802, 0.34607],
-        [0.21291, 0.12947, 0.37314],
-        [0.21708, 0.14087, 0.39964],
-        [0.22111, 0.15223, 0.42558],
-        [0.22500, 0.16354, 0.45096],
-        [0.22875, 0.17481, 0.47578],
-        [0.23236, 0.18603, 0.50004],
-        [0.23582, 0.19720, 0.52373],
-        [0.23915, 0.20833, 0.54686],
-        [0.24234, 0.21941, 0.56942],
-        [0.24539, 0.23044, 0.59142],
-        [0.24830, 0.24143, 0.61286],
-        [0.25107, 0.25237, 0.63374],
-        [0.25369, 0.26327, 0.65406],
-        [0.25618, 0.27412, 0.67381],
-        [0.25853, 0.28492, 0.69300],
-        [0.26074, 0.29568, 0.71162],
-        [0.26280, 0.30639, 0.72968],
-        [0.26473, 0.31706, 0.74718],
-        [0.26652, 0.32768, 0.76412],
-        [0.26816, 0.33825, 0.78050],
-        [0.26967, 0.34878, 0.79631],
-        [0.27103, 0.35926, 0.81156],
-        [0.27226, 0.36970, 0.82624],
-        [0.27334, 0.38008, 0.84037],
-        [0.27429, 0.39043, 0.85393],
-        [0.27509, 0.40072, 0.86692],
-        [0.27576, 0.41097, 0.87936],
-        [0.27628, 0.42118, 0.89123],
-        [0.27667, 0.43134, 0.90254],
-        [0.27691, 0.44145, 0.91328],
-        [0.27701, 0.45152, 0.92347],
-        [0.27698, 0.46153, 0.93309],
-        [0.27680, 0.47151, 0.94214],
-        [0.27648, 0.48144, 0.95064],
-        [0.27603, 0.49132, 0.95857],
-        [0.27543, 0.50115, 0.96594],
-        [0.27469, 0.51094, 0.97275],
-        [0.27381, 0.52069, 0.97899],
-        [0.27273, 0.53040, 0.98461],
-        [0.27106, 0.54015, 0.98930],
-        [0.26878, 0.54995, 0.99303],
-        [0.26592, 0.55979, 0.99583],
-        [0.26252, 0.56967, 0.99773],
-        [0.25862, 0.57958, 0.99876],
-        [0.25425, 0.58950, 0.99896],
-        [0.24946, 0.59943, 0.99835],
-        [0.24427, 0.60937, 0.99697],
-        [0.23874, 0.61931, 0.99485],
-        [0.23288, 0.62923, 0.99202],
-        [0.22676, 0.63913, 0.98851],
-        [0.22039, 0.64901, 0.98436],
-        [0.21382, 0.65886, 0.97959],
-        [0.20708, 0.66866, 0.97423],
-        [0.20021, 0.67842, 0.96833],
-        [0.19326, 0.68812, 0.96190],
-        [0.18625, 0.69775, 0.95498],
-        [0.17923, 0.70732, 0.94761],
-        [0.17223, 0.71680, 0.93981],
-        [0.16529, 0.72620, 0.93161],
-        [0.15844, 0.73551, 0.92305],
-        [0.15173, 0.74472, 0.91416],
-        [0.14519, 0.75381, 0.90496],
-        [0.13886, 0.76279, 0.89550],
-        [0.13278, 0.77165, 0.88580],
-        [0.12698, 0.78037, 0.87590],
-        [0.12151, 0.78896, 0.86581],
-        [0.11639, 0.79740, 0.85559],
-        [0.11167, 0.80569, 0.84525],
-        [0.10738, 0.81381, 0.83484],
-        [0.10357, 0.82177, 0.82437],
-        [0.10026, 0.82955, 0.81389],
-        [0.09750, 0.83714, 0.80342],
-        [0.09532, 0.84455, 0.79299],
-        [0.09377, 0.85175, 0.78264],
-        [0.09287, 0.85875, 0.77240],
-        [0.09267, 0.86554, 0.76230],
-        [0.09320, 0.87211, 0.75237],
-        [0.09451, 0.87844, 0.74265],
-        [0.09662, 0.88454, 0.73316],
-        [0.09958, 0.89040, 0.72393],
-        [0.10342, 0.89600, 0.71500],
-        [0.10815, 0.90142, 0.70599],
-        [0.11374, 0.90673, 0.69651],
-        [0.12014, 0.91193, 0.68660],
-        [0.12733, 0.91701, 0.67627],
-        [0.13526, 0.92197, 0.66556],
-        [0.14391, 0.92680, 0.65448],
-        [0.15323, 0.93151, 0.64308],
-        [0.16319, 0.93609, 0.63137],
-        [0.17377, 0.94053, 0.61938],
-        [0.18491, 0.94484, 0.60713],
-        [0.19659, 0.94901, 0.59466],
-        [0.20877, 0.95304, 0.58199],
-        [0.22142, 0.95692, 0.56914],
-        [0.23449, 0.96065, 0.55614],
-        [0.24797, 0.96423, 0.54303],
-        [0.26180, 0.96765, 0.52981],
-        [0.27597, 0.97092, 0.51653],
-        [0.29042, 0.97403, 0.50321],
-        [0.30513, 0.97697, 0.48987],
-        [0.32006, 0.97974, 0.47654],
-        [0.33517, 0.98234, 0.46325],
-        [0.35043, 0.98477, 0.45002],
-        [0.36581, 0.98702, 0.43688],
-        [0.38127, 0.98909, 0.42386],
-        [0.39678, 0.99098, 0.41098],
-        [0.41229, 0.99268, 0.39826],
-        [0.42778, 0.99419, 0.38575],
-        [0.44321, 0.99551, 0.37345],
-        [0.45854, 0.99663, 0.36140],
-        [0.47375, 0.99755, 0.34963],
-        [0.48879, 0.99828, 0.33816],
-        [0.50362, 0.99879, 0.32701],
-        [0.51822, 0.99910, 0.31622],
-        [0.53255, 0.99919, 0.30581],
-        [0.54658, 0.99907, 0.29581],
-        [0.56026, 0.99873, 0.28623],
-        [0.57357, 0.99817, 0.27712],
-        [0.58646, 0.99739, 0.26849],
-        [0.59891, 0.99638, 0.26038],
-        [0.61088, 0.99514, 0.25280],
-        [0.62233, 0.99366, 0.24579],
-        [0.63323, 0.99195, 0.23937],
-        [0.64362, 0.98999, 0.23356],
-        [0.65394, 0.98775, 0.22835],
-        [0.66428, 0.98524, 0.22370],
-        [0.67462, 0.98246, 0.21960],
-        [0.68494, 0.97941, 0.21602],
-        [0.69525, 0.97610, 0.21294],
-        [0.70553, 0.97255, 0.21032],
-        [0.71577, 0.96875, 0.20815],
-        [0.72596, 0.96470, 0.20640],
-        [0.73610, 0.96043, 0.20504],
-        [0.74617, 0.95593, 0.20406],
-        [0.75617, 0.95121, 0.20343],
-        [0.76608, 0.94627, 0.20311],
-        [0.77591, 0.94113, 0.20310],
-        [0.78563, 0.93579, 0.20336],
-        [0.79524, 0.93025, 0.20386],
-        [0.80473, 0.92452, 0.20459],
-        [0.81410, 0.91861, 0.20552],
-        [0.82333, 0.91253, 0.20663],
-        [0.83241, 0.90627, 0.20788],
-        [0.84133, 0.89986, 0.20926],
-        [0.85010, 0.89328, 0.21074],
-        [0.85868, 0.88655, 0.21230],
-        [0.86709, 0.87968, 0.21391],
-        [0.87530, 0.87267, 0.21555],
-        [0.88331, 0.86553, 0.21719],
-        [0.89112, 0.85826, 0.21880],
-        [0.89870, 0.85087, 0.22038],
-        [0.90605, 0.84337, 0.22188],
-        [0.91317, 0.83576, 0.22328],
-        [0.92004, 0.82806, 0.22456],
-        [0.92666, 0.82025, 0.22570],
-        [0.93301, 0.81236, 0.22667],
-        [0.93909, 0.80439, 0.22744],
-        [0.94489, 0.79634, 0.22800],
-        [0.95039, 0.78823, 0.22831],
-        [0.95560, 0.78005, 0.22836],
-        [0.96049, 0.77181, 0.22811],
-        [0.96507, 0.76352, 0.22754],
-        [0.96931, 0.75519, 0.22663],
-        [0.97323, 0.74682, 0.22536],
-        [0.97679, 0.73842, 0.22369],
-        [0.98000, 0.73000, 0.22161],
-        [0.98289, 0.72140, 0.21918],
-        [0.98549, 0.71250, 0.21650],
-        [0.98781, 0.70330, 0.21358],
-        [0.98986, 0.69382, 0.21043],
-        [0.99163, 0.68408, 0.20706],
-        [0.99314, 0.67408, 0.20348],
-        [0.99438, 0.66386, 0.19971],
-        [0.99535, 0.65341, 0.19577],
-        [0.99607, 0.64277, 0.19165],
-        [0.99654, 0.63193, 0.18738],
-        [0.99675, 0.62093, 0.18297],
-        [0.99672, 0.60977, 0.17842],
-        [0.99644, 0.59846, 0.17376],
-        [0.99593, 0.58703, 0.16899],
-        [0.99517, 0.57549, 0.16412],
-        [0.99419, 0.56386, 0.15918],
-        [0.99297, 0.55214, 0.15417],
-        [0.99153, 0.54036, 0.14910],
-        [0.98987, 0.52854, 0.14398],
-        [0.98799, 0.51667, 0.13883],
-        [0.98590, 0.50479, 0.13367],
-        [0.98360, 0.49291, 0.12849],
-        [0.98108, 0.48104, 0.12332],
-        [0.97837, 0.46920, 0.11817],
-        [0.97545, 0.45740, 0.11305],
-        [0.97234, 0.44565, 0.10797],
-        [0.96904, 0.43399, 0.10294],
-        [0.96555, 0.42241, 0.09798],
-        [0.96187, 0.41093, 0.09310],
-        [0.95801, 0.39958, 0.08831],
-        [0.95398, 0.38836, 0.08362],
-        [0.94977, 0.37729, 0.07905],
-        [0.94538, 0.36638, 0.07461],
-        [0.94084, 0.35566, 0.07031],
-        [0.93612, 0.34513, 0.06616],
-        [0.93125, 0.33482, 0.06218],
-        [0.92623, 0.32473, 0.05837],
-        [0.92105, 0.31489, 0.05475],
-        [0.91572, 0.30530, 0.05134],
-        [0.91024, 0.29599, 0.04814],
-        [0.90463, 0.28696, 0.04516],
-        [0.89888, 0.27824, 0.04243],
-        [0.89298, 0.26981, 0.03993],
-        [0.88691, 0.26152, 0.03753],
-        [0.88066, 0.25334, 0.03521],
-        [0.87422, 0.24526, 0.03297],
-        [0.86760, 0.23730, 0.03082],
-        [0.86079, 0.22945, 0.02875],
-        [0.85380, 0.22170, 0.02677],
-        [0.84662, 0.21407, 0.02487],
-        [0.83926, 0.20654, 0.02305],
-        [0.83172, 0.19912, 0.02131],
-        [0.82399, 0.19182, 0.01966],
-        [0.81608, 0.18462, 0.01809],
-        [0.80799, 0.17753, 0.01660],
-        [0.79971, 0.17055, 0.01520],
-        [0.79125, 0.16368, 0.01387],
-        [0.78260, 0.15693, 0.01264],
-        [0.77377, 0.15028, 0.01148],
-        [0.76476, 0.14374, 0.01041],
-        [0.75556, 0.13731, 0.00942],
-        [0.74617, 0.13098, 0.00851],
-        [0.73661, 0.12477, 0.00769],
-        [0.72686, 0.11867, 0.00695],
-        [0.71692, 0.11268, 0.00629],
-        [0.70680, 0.10680, 0.00571],
-        [0.69650, 0.10102, 0.00522],
-        [0.68602, 0.09536, 0.00481],
-        [0.67535, 0.08980, 0.00449],
-        [0.66449, 0.08436, 0.00424],
-        [0.65345, 0.07902, 0.00408],
-        [0.64223, 0.07380, 0.00401],
-        [0.63082, 0.06868, 0.00401],
-        [0.61923, 0.06367, 0.00410],
-        [0.60746, 0.05878, 0.00427],
-        [0.59550, 0.05399, 0.00453],
-        [0.58336, 0.04931, 0.00486],
-        [0.57103, 0.04474, 0.00529],
-        [0.55852, 0.04028, 0.00579],
-        [0.54583, 0.03593, 0.00638],
-        [0.53295, 0.03169, 0.00705],
-        [0.51989, 0.02756, 0.00780],
-        [0.50664, 0.02354, 0.00863],
-        [0.49321, 0.01963, 0.00955],
-        [0.47960, 0.01583, 0.01055],
-    ]
-)
+turbo_colormap_data = np.array([
+    [0.18995, 0.07176, 0.23217],
+    [0.19483, 0.08339, 0.26149],
+    [0.19956, 0.09498, 0.29024],
+    [0.20415, 0.10652, 0.31844],
+    [0.20860, 0.11802, 0.34607],
+    [0.21291, 0.12947, 0.37314],
+    [0.21708, 0.14087, 0.39964],
+    [0.22111, 0.15223, 0.42558],
+    [0.22500, 0.16354, 0.45096],
+    [0.22875, 0.17481, 0.47578],
+    [0.23236, 0.18603, 0.50004],
+    [0.23582, 0.19720, 0.52373],
+    [0.23915, 0.20833, 0.54686],
+    [0.24234, 0.21941, 0.56942],
+    [0.24539, 0.23044, 0.59142],
+    [0.24830, 0.24143, 0.61286],
+    [0.25107, 0.25237, 0.63374],
+    [0.25369, 0.26327, 0.65406],
+    [0.25618, 0.27412, 0.67381],
+    [0.25853, 0.28492, 0.69300],
+    [0.26074, 0.29568, 0.71162],
+    [0.26280, 0.30639, 0.72968],
+    [0.26473, 0.31706, 0.74718],
+    [0.26652, 0.32768, 0.76412],
+    [0.26816, 0.33825, 0.78050],
+    [0.26967, 0.34878, 0.79631],
+    [0.27103, 0.35926, 0.81156],
+    [0.27226, 0.36970, 0.82624],
+    [0.27334, 0.38008, 0.84037],
+    [0.27429, 0.39043, 0.85393],
+    [0.27509, 0.40072, 0.86692],
+    [0.27576, 0.41097, 0.87936],
+    [0.27628, 0.42118, 0.89123],
+    [0.27667, 0.43134, 0.90254],
+    [0.27691, 0.44145, 0.91328],
+    [0.27701, 0.45152, 0.92347],
+    [0.27698, 0.46153, 0.93309],
+    [0.27680, 0.47151, 0.94214],
+    [0.27648, 0.48144, 0.95064],
+    [0.27603, 0.49132, 0.95857],
+    [0.27543, 0.50115, 0.96594],
+    [0.27469, 0.51094, 0.97275],
+    [0.27381, 0.52069, 0.97899],
+    [0.27273, 0.53040, 0.98461],
+    [0.27106, 0.54015, 0.98930],
+    [0.26878, 0.54995, 0.99303],
+    [0.26592, 0.55979, 0.99583],
+    [0.26252, 0.56967, 0.99773],
+    [0.25862, 0.57958, 0.99876],
+    [0.25425, 0.58950, 0.99896],
+    [0.24946, 0.59943, 0.99835],
+    [0.24427, 0.60937, 0.99697],
+    [0.23874, 0.61931, 0.99485],
+    [0.23288, 0.62923, 0.99202],
+    [0.22676, 0.63913, 0.98851],
+    [0.22039, 0.64901, 0.98436],
+    [0.21382, 0.65886, 0.97959],
+    [0.20708, 0.66866, 0.97423],
+    [0.20021, 0.67842, 0.96833],
+    [0.19326, 0.68812, 0.96190],
+    [0.18625, 0.69775, 0.95498],
+    [0.17923, 0.70732, 0.94761],
+    [0.17223, 0.71680, 0.93981],
+    [0.16529, 0.72620, 0.93161],
+    [0.15844, 0.73551, 0.92305],
+    [0.15173, 0.74472, 0.91416],
+    [0.14519, 0.75381, 0.90496],
+    [0.13886, 0.76279, 0.89550],
+    [0.13278, 0.77165, 0.88580],
+    [0.12698, 0.78037, 0.87590],
+    [0.12151, 0.78896, 0.86581],
+    [0.11639, 0.79740, 0.85559],
+    [0.11167, 0.80569, 0.84525],
+    [0.10738, 0.81381, 0.83484],
+    [0.10357, 0.82177, 0.82437],
+    [0.10026, 0.82955, 0.81389],
+    [0.09750, 0.83714, 0.80342],
+    [0.09532, 0.84455, 0.79299],
+    [0.09377, 0.85175, 0.78264],
+    [0.09287, 0.85875, 0.77240],
+    [0.09267, 0.86554, 0.76230],
+    [0.09320, 0.87211, 0.75237],
+    [0.09451, 0.87844, 0.74265],
+    [0.09662, 0.88454, 0.73316],
+    [0.09958, 0.89040, 0.72393],
+    [0.10342, 0.89600, 0.71500],
+    [0.10815, 0.90142, 0.70599],
+    [0.11374, 0.90673, 0.69651],
+    [0.12014, 0.91193, 0.68660],
+    [0.12733, 0.91701, 0.67627],
+    [0.13526, 0.92197, 0.66556],
+    [0.14391, 0.92680, 0.65448],
+    [0.15323, 0.93151, 0.64308],
+    [0.16319, 0.93609, 0.63137],
+    [0.17377, 0.94053, 0.61938],
+    [0.18491, 0.94484, 0.60713],
+    [0.19659, 0.94901, 0.59466],
+    [0.20877, 0.95304, 0.58199],
+    [0.22142, 0.95692, 0.56914],
+    [0.23449, 0.96065, 0.55614],
+    [0.24797, 0.96423, 0.54303],
+    [0.26180, 0.96765, 0.52981],
+    [0.27597, 0.97092, 0.51653],
+    [0.29042, 0.97403, 0.50321],
+    [0.30513, 0.97697, 0.48987],
+    [0.32006, 0.97974, 0.47654],
+    [0.33517, 0.98234, 0.46325],
+    [0.35043, 0.98477, 0.45002],
+    [0.36581, 0.98702, 0.43688],
+    [0.38127, 0.98909, 0.42386],
+    [0.39678, 0.99098, 0.41098],
+    [0.41229, 0.99268, 0.39826],
+    [0.42778, 0.99419, 0.38575],
+    [0.44321, 0.99551, 0.37345],
+    [0.45854, 0.99663, 0.36140],
+    [0.47375, 0.99755, 0.34963],
+    [0.48879, 0.99828, 0.33816],
+    [0.50362, 0.99879, 0.32701],
+    [0.51822, 0.99910, 0.31622],
+    [0.53255, 0.99919, 0.30581],
+    [0.54658, 0.99907, 0.29581],
+    [0.56026, 0.99873, 0.28623],
+    [0.57357, 0.99817, 0.27712],
+    [0.58646, 0.99739, 0.26849],
+    [0.59891, 0.99638, 0.26038],
+    [0.61088, 0.99514, 0.25280],
+    [0.62233, 0.99366, 0.24579],
+    [0.63323, 0.99195, 0.23937],
+    [0.64362, 0.98999, 0.23356],
+    [0.65394, 0.98775, 0.22835],
+    [0.66428, 0.98524, 0.22370],
+    [0.67462, 0.98246, 0.21960],
+    [0.68494, 0.97941, 0.21602],
+    [0.69525, 0.97610, 0.21294],
+    [0.70553, 0.97255, 0.21032],
+    [0.71577, 0.96875, 0.20815],
+    [0.72596, 0.96470, 0.20640],
+    [0.73610, 0.96043, 0.20504],
+    [0.74617, 0.95593, 0.20406],
+    [0.75617, 0.95121, 0.20343],
+    [0.76608, 0.94627, 0.20311],
+    [0.77591, 0.94113, 0.20310],
+    [0.78563, 0.93579, 0.20336],
+    [0.79524, 0.93025, 0.20386],
+    [0.80473, 0.92452, 0.20459],
+    [0.81410, 0.91861, 0.20552],
+    [0.82333, 0.91253, 0.20663],
+    [0.83241, 0.90627, 0.20788],
+    [0.84133, 0.89986, 0.20926],
+    [0.85010, 0.89328, 0.21074],
+    [0.85868, 0.88655, 0.21230],
+    [0.86709, 0.87968, 0.21391],
+    [0.87530, 0.87267, 0.21555],
+    [0.88331, 0.86553, 0.21719],
+    [0.89112, 0.85826, 0.21880],
+    [0.89870, 0.85087, 0.22038],
+    [0.90605, 0.84337, 0.22188],
+    [0.91317, 0.83576, 0.22328],
+    [0.92004, 0.82806, 0.22456],
+    [0.92666, 0.82025, 0.22570],
+    [0.93301, 0.81236, 0.22667],
+    [0.93909, 0.80439, 0.22744],
+    [0.94489, 0.79634, 0.22800],
+    [0.95039, 0.78823, 0.22831],
+    [0.95560, 0.78005, 0.22836],
+    [0.96049, 0.77181, 0.22811],
+    [0.96507, 0.76352, 0.22754],
+    [0.96931, 0.75519, 0.22663],
+    [0.97323, 0.74682, 0.22536],
+    [0.97679, 0.73842, 0.22369],
+    [0.98000, 0.73000, 0.22161],
+    [0.98289, 0.72140, 0.21918],
+    [0.98549, 0.71250, 0.21650],
+    [0.98781, 0.70330, 0.21358],
+    [0.98986, 0.69382, 0.21043],
+    [0.99163, 0.68408, 0.20706],
+    [0.99314, 0.67408, 0.20348],
+    [0.99438, 0.66386, 0.19971],
+    [0.99535, 0.65341, 0.19577],
+    [0.99607, 0.64277, 0.19165],
+    [0.99654, 0.63193, 0.18738],
+    [0.99675, 0.62093, 0.18297],
+    [0.99672, 0.60977, 0.17842],
+    [0.99644, 0.59846, 0.17376],
+    [0.99593, 0.58703, 0.16899],
+    [0.99517, 0.57549, 0.16412],
+    [0.99419, 0.56386, 0.15918],
+    [0.99297, 0.55214, 0.15417],
+    [0.99153, 0.54036, 0.14910],
+    [0.98987, 0.52854, 0.14398],
+    [0.98799, 0.51667, 0.13883],
+    [0.98590, 0.50479, 0.13367],
+    [0.98360, 0.49291, 0.12849],
+    [0.98108, 0.48104, 0.12332],
+    [0.97837, 0.46920, 0.11817],
+    [0.97545, 0.45740, 0.11305],
+    [0.97234, 0.44565, 0.10797],
+    [0.96904, 0.43399, 0.10294],
+    [0.96555, 0.42241, 0.09798],
+    [0.96187, 0.41093, 0.09310],
+    [0.95801, 0.39958, 0.08831],
+    [0.95398, 0.38836, 0.08362],
+    [0.94977, 0.37729, 0.07905],
+    [0.94538, 0.36638, 0.07461],
+    [0.94084, 0.35566, 0.07031],
+    [0.93612, 0.34513, 0.06616],
+    [0.93125, 0.33482, 0.06218],
+    [0.92623, 0.32473, 0.05837],
+    [0.92105, 0.31489, 0.05475],
+    [0.91572, 0.30530, 0.05134],
+    [0.91024, 0.29599, 0.04814],
+    [0.90463, 0.28696, 0.04516],
+    [0.89888, 0.27824, 0.04243],
+    [0.89298, 0.26981, 0.03993],
+    [0.88691, 0.26152, 0.03753],
+    [0.88066, 0.25334, 0.03521],
+    [0.87422, 0.24526, 0.03297],
+    [0.86760, 0.23730, 0.03082],
+    [0.86079, 0.22945, 0.02875],
+    [0.85380, 0.22170, 0.02677],
+    [0.84662, 0.21407, 0.02487],
+    [0.83926, 0.20654, 0.02305],
+    [0.83172, 0.19912, 0.02131],
+    [0.82399, 0.19182, 0.01966],
+    [0.81608, 0.18462, 0.01809],
+    [0.80799, 0.17753, 0.01660],
+    [0.79971, 0.17055, 0.01520],
+    [0.79125, 0.16368, 0.01387],
+    [0.78260, 0.15693, 0.01264],
+    [0.77377, 0.15028, 0.01148],
+    [0.76476, 0.14374, 0.01041],
+    [0.75556, 0.13731, 0.00942],
+    [0.74617, 0.13098, 0.00851],
+    [0.73661, 0.12477, 0.00769],
+    [0.72686, 0.11867, 0.00695],
+    [0.71692, 0.11268, 0.00629],
+    [0.70680, 0.10680, 0.00571],
+    [0.69650, 0.10102, 0.00522],
+    [0.68602, 0.09536, 0.00481],
+    [0.67535, 0.08980, 0.00449],
+    [0.66449, 0.08436, 0.00424],
+    [0.65345, 0.07902, 0.00408],
+    [0.64223, 0.07380, 0.00401],
+    [0.63082, 0.06868, 0.00401],
+    [0.61923, 0.06367, 0.00410],
+    [0.60746, 0.05878, 0.00427],
+    [0.59550, 0.05399, 0.00453],
+    [0.58336, 0.04931, 0.00486],
+    [0.57103, 0.04474, 0.00529],
+    [0.55852, 0.04028, 0.00579],
+    [0.54583, 0.03593, 0.00638],
+    [0.53295, 0.03169, 0.00705],
+    [0.51989, 0.02756, 0.00780],
+    [0.50664, 0.02354, 0.00863],
+    [0.49321, 0.01963, 0.00955],
+    [0.47960, 0.01583, 0.01055],
+])
diff --git a/rerun_py/tests/test_types/components/affix_fuzzer16.py b/rerun_py/tests/test_types/components/affix_fuzzer16.py
index 16b10dbb6800..817e55f94cf3 100644
--- a/rerun_py/tests/test_types/components/affix_fuzzer16.py
+++ b/rerun_py/tests/test_types/components/affix_fuzzer16.py
@@ -43,74 +43,60 @@ def __init__(self) -> None:
             pa.list_(
                 pa.field(
                     "item",
-                    pa.dense_union(
-                        [
-                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                            pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                            pa.field("radians", pa.float32(), nullable=False, metadata={}),
-                            pa.field(
-                                "craziness",
-                                pa.list_(
-                                    pa.field(
-                                        "item",
-                                        pa.struct(
-                                            [
-                                                pa.field(
-                                                    "single_float_optional", pa.float32(), nullable=True, metadata={}
-                                                ),
-                                                pa.field(
-                                                    "single_string_required", pa.utf8(), nullable=False, metadata={}
-                                                ),
-                                                pa.field(
-                                                    "single_string_optional", pa.utf8(), nullable=True, metadata={}
-                                                ),
-                                                pa.field(
-                                                    "many_floats_optional",
-                                                    pa.list_(
-                                                        pa.field("item", pa.float32(), nullable=False, metadata={})
-                                                    ),
-                                                    nullable=True,
-                                                    metadata={},
-                                                ),
-                                                pa.field(
-                                                    "many_strings_required",
-                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                                                    nullable=False,
-                                                    metadata={},
-                                                ),
-                                                pa.field(
-                                                    "many_strings_optional",
-                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                                                    nullable=True,
-                                                    metadata={},
-                                                ),
-                                                pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
-                                                pa.field(
-                                                    "almost_flattened_scalar",
-                                                    pa.struct(
-                                                        [pa.field("value", pa.float32(), nullable=False, metadata={})]
-                                                    ),
-                                                    nullable=False,
-                                                    metadata={},
-                                                ),
-                                                pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
-                                            ]
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                        pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                        pa.field(
+                            "craziness",
+                            pa.list_(
+                                pa.field(
+                                    "item",
+                                    pa.struct([
+                                        pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
+                                        pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
+                                        pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
+                                        pa.field(
+                                            "many_floats_optional",
+                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
+                                            nullable=True,
+                                            metadata={},
                                         ),
-                                        nullable=False,
-                                        metadata={},
-                                    )
-                                ),
-                                nullable=False,
-                                metadata={},
-                            ),
-                            pa.field(
-                                "fixed_size_shenanigans",
-                                pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                                nullable=False,
-                                metadata={},
+                                        pa.field(
+                                            "many_strings_required",
+                                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                        pa.field(
+                                            "many_strings_optional",
+                                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                            nullable=True,
+                                            metadata={},
+                                        ),
+                                        pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                                        pa.field(
+                                            "almost_flattened_scalar",
+                                            pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                    ]),
+                                    nullable=False,
+                                    metadata={},
+                                )
                             ),
-                        ]
-                    ),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "fixed_size_shenanigans",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                            nullable=False,
+                            metadata={},
+                        ),
+                    ]),
                     nullable=False,
                     metadata={},
                 )
diff --git a/rerun_py/tests/test_types/components/affix_fuzzer17.py b/rerun_py/tests/test_types/components/affix_fuzzer17.py
index 9c99643cfe3e..d80061aadac7 100644
--- a/rerun_py/tests/test_types/components/affix_fuzzer17.py
+++ b/rerun_py/tests/test_types/components/affix_fuzzer17.py
@@ -43,74 +43,60 @@ def __init__(self) -> None:
             pa.list_(
                 pa.field(
                     "item",
-                    pa.dense_union(
-                        [
-                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                            pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                            pa.field("radians", pa.float32(), nullable=False, metadata={}),
-                            pa.field(
-                                "craziness",
-                                pa.list_(
-                                    pa.field(
-                                        "item",
-                                        pa.struct(
-                                            [
-                                                pa.field(
-                                                    "single_float_optional", pa.float32(), nullable=True, metadata={}
-                                                ),
-                                                pa.field(
-                                                    "single_string_required", pa.utf8(), nullable=False, metadata={}
-                                                ),
-                                                pa.field(
-                                                    "single_string_optional", pa.utf8(), nullable=True, metadata={}
-                                                ),
-                                                pa.field(
-                                                    "many_floats_optional",
-                                                    pa.list_(
-                                                        pa.field("item", pa.float32(), nullable=False, metadata={})
-                                                    ),
-                                                    nullable=True,
-                                                    metadata={},
-                                                ),
-                                                pa.field(
-                                                    "many_strings_required",
-                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                                                    nullable=False,
-                                                    metadata={},
-                                                ),
-                                                pa.field(
-                                                    "many_strings_optional",
-                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                                                    nullable=True,
-                                                    metadata={},
-                                                ),
-                                                pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
-                                                pa.field(
-                                                    "almost_flattened_scalar",
-                                                    pa.struct(
-                                                        [pa.field("value", pa.float32(), nullable=False, metadata={})]
-                                                    ),
-                                                    nullable=False,
-                                                    metadata={},
-                                                ),
-                                                pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
-                                            ]
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                        pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                        pa.field(
+                            "craziness",
+                            pa.list_(
+                                pa.field(
+                                    "item",
+                                    pa.struct([
+                                        pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
+                                        pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
+                                        pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
+                                        pa.field(
+                                            "many_floats_optional",
+                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
+                                            nullable=True,
+                                            metadata={},
                                         ),
-                                        nullable=False,
-                                        metadata={},
-                                    )
-                                ),
-                                nullable=False,
-                                metadata={},
-                            ),
-                            pa.field(
-                                "fixed_size_shenanigans",
-                                pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                                nullable=False,
-                                metadata={},
+                                        pa.field(
+                                            "many_strings_required",
+                                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                        pa.field(
+                                            "many_strings_optional",
+                                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                            nullable=True,
+                                            metadata={},
+                                        ),
+                                        pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                                        pa.field(
+                                            "almost_flattened_scalar",
+                                            pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                    ]),
+                                    nullable=False,
+                                    metadata={},
+                                )
                             ),
-                        ]
-                    ),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "fixed_size_shenanigans",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                            nullable=False,
+                            metadata={},
+                        ),
+                    ]),
                     nullable=False,
                     metadata={},
                 )
diff --git a/rerun_py/tests/test_types/components/affix_fuzzer18.py b/rerun_py/tests/test_types/components/affix_fuzzer18.py
index 93692238959c..2a8fbe788308 100644
--- a/rerun_py/tests/test_types/components/affix_fuzzer18.py
+++ b/rerun_py/tests/test_types/components/affix_fuzzer18.py
@@ -43,13 +43,83 @@ def __init__(self) -> None:
             pa.list_(
                 pa.field(
                     "item",
-                    pa.dense_union(
-                        [
-                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                            pa.field(
-                                "single_required",
-                                pa.dense_union(
-                                    [
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field(
+                            "single_required",
+                            pa.dense_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                                pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                                pa.field(
+                                    "craziness",
+                                    pa.list_(
+                                        pa.field(
+                                            "item",
+                                            pa.struct([
+                                                pa.field(
+                                                    "single_float_optional", pa.float32(), nullable=True, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "single_string_required", pa.utf8(), nullable=False, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "single_string_optional", pa.utf8(), nullable=True, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "many_floats_optional",
+                                                    pa.list_(
+                                                        pa.field("item", pa.float32(), nullable=False, metadata={})
+                                                    ),
+                                                    nullable=True,
+                                                    metadata={},
+                                                ),
+                                                pa.field(
+                                                    "many_strings_required",
+                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                                    nullable=False,
+                                                    metadata={},
+                                                ),
+                                                pa.field(
+                                                    "many_strings_optional",
+                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                                    nullable=True,
+                                                    metadata={},
+                                                ),
+                                                pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                                                pa.field(
+                                                    "almost_flattened_scalar",
+                                                    pa.struct([
+                                                        pa.field("value", pa.float32(), nullable=False, metadata={})
+                                                    ]),
+                                                    nullable=False,
+                                                    metadata={},
+                                                ),
+                                                pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                            ]),
+                                            nullable=False,
+                                            metadata={},
+                                        )
+                                    ),
+                                    nullable=False,
+                                    metadata={},
+                                ),
+                                pa.field(
+                                    "fixed_size_shenanigans",
+                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                                    nullable=False,
+                                    metadata={},
+                                ),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "many_required",
+                            pa.list_(
+                                pa.field(
+                                    "item",
+                                    pa.dense_union([
                                         pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
                                         pa.field("degrees", pa.float32(), nullable=False, metadata={}),
                                         pa.field("radians", pa.float32(), nullable=False, metadata={}),
@@ -58,85 +128,69 @@ def __init__(self) -> None:
                                             pa.list_(
                                                 pa.field(
                                                     "item",
-                                                    pa.struct(
-                                                        [
-                                                            pa.field(
-                                                                "single_float_optional",
-                                                                pa.float32(),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "single_string_required",
-                                                                pa.utf8(),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "single_string_optional",
-                                                                pa.utf8(),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_floats_optional",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item",
-                                                                        pa.float32(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    )
-                                                                ),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_strings_required",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item", pa.utf8(), nullable=False, metadata={}
-                                                                    )
-                                                                ),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_strings_optional",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item", pa.utf8(), nullable=False, metadata={}
-                                                                    )
-                                                                ),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "flattened_scalar",
-                                                                pa.float32(),
-                                                                nullable=False,
-                                                                metadata={},
+                                                    pa.struct([
+                                                        pa.field(
+                                                            "single_float_optional",
+                                                            pa.float32(),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "single_string_required",
+                                                            pa.utf8(),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "single_string_optional",
+                                                            pa.utf8(),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_floats_optional",
+                                                            pa.list_(
+                                                                pa.field(
+                                                                    "item", pa.float32(), nullable=False, metadata={}
+                                                                )
                                                             ),
-                                                            pa.field(
-                                                                "almost_flattened_scalar",
-                                                                pa.struct(
-                                                                    [
-                                                                        pa.field(
-                                                                            "value",
-                                                                            pa.float32(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        )
-                                                                    ]
-                                                                ),
-                                                                nullable=False,
-                                                                metadata={},
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_strings_required",
+                                                            pa.list_(
+                                                                pa.field("item", pa.utf8(), nullable=False, metadata={})
                                                             ),
-                                                            pa.field(
-                                                                "from_parent", pa.bool_(), nullable=True, metadata={}
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_strings_optional",
+                                                            pa.list_(
+                                                                pa.field("item", pa.utf8(), nullable=False, metadata={})
                                                             ),
-                                                        ]
-                                                    ),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "flattened_scalar",
+                                                            pa.float32(),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "almost_flattened_scalar",
+                                                            pa.struct([
+                                                                pa.field(
+                                                                    "value", pa.float32(), nullable=False, metadata={}
+                                                                )
+                                                            ]),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                                    ]),
                                                     nullable=False,
                                                     metadata={},
                                                 )
@@ -150,267 +204,113 @@ def __init__(self) -> None:
                                             nullable=False,
                                             metadata={},
                                         ),
-                                    ]
-                                ),
-                                nullable=False,
-                                metadata={},
+                                    ]),
+                                    nullable=False,
+                                    metadata={},
+                                )
                             ),
-                            pa.field(
-                                "many_required",
-                                pa.list_(
-                                    pa.field(
-                                        "item",
-                                        pa.dense_union(
-                                            [
-                                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                                pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                                                pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "many_optional",
+                            pa.list_(
+                                pa.field(
+                                    "item",
+                                    pa.dense_union([
+                                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                        pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                                        pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                                        pa.field(
+                                            "craziness",
+                                            pa.list_(
                                                 pa.field(
-                                                    "craziness",
-                                                    pa.list_(
+                                                    "item",
+                                                    pa.struct([
+                                                        pa.field(
+                                                            "single_float_optional",
+                                                            pa.float32(),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "single_string_required",
+                                                            pa.utf8(),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "single_string_optional",
+                                                            pa.utf8(),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
                                                         pa.field(
-                                                            "item",
-                                                            pa.struct(
-                                                                [
-                                                                    pa.field(
-                                                                        "single_float_optional",
-                                                                        pa.float32(),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "single_string_required",
-                                                                        pa.utf8(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "single_string_optional",
-                                                                        pa.utf8(),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "many_floats_optional",
-                                                                        pa.list_(
-                                                                            pa.field(
-                                                                                "item",
-                                                                                pa.float32(),
-                                                                                nullable=False,
-                                                                                metadata={},
-                                                                            )
-                                                                        ),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "many_strings_required",
-                                                                        pa.list_(
-                                                                            pa.field(
-                                                                                "item",
-                                                                                pa.utf8(),
-                                                                                nullable=False,
-                                                                                metadata={},
-                                                                            )
-                                                                        ),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "many_strings_optional",
-                                                                        pa.list_(
-                                                                            pa.field(
-                                                                                "item",
-                                                                                pa.utf8(),
-                                                                                nullable=False,
-                                                                                metadata={},
-                                                                            )
-                                                                        ),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "flattened_scalar",
-                                                                        pa.float32(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "almost_flattened_scalar",
-                                                                        pa.struct(
-                                                                            [
-                                                                                pa.field(
-                                                                                    "value",
-                                                                                    pa.float32(),
-                                                                                    nullable=False,
-                                                                                    metadata={},
-                                                                                )
-                                                                            ]
-                                                                        ),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "from_parent",
-                                                                        pa.bool_(),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                ]
+                                                            "many_floats_optional",
+                                                            pa.list_(
+                                                                pa.field(
+                                                                    "item", pa.float32(), nullable=False, metadata={}
+                                                                )
+                                                            ),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_strings_required",
+                                                            pa.list_(
+                                                                pa.field("item", pa.utf8(), nullable=False, metadata={})
                                                             ),
                                                             nullable=False,
                                                             metadata={},
-                                                        )
-                                                    ),
-                                                    nullable=False,
-                                                    metadata={},
-                                                ),
-                                                pa.field(
-                                                    "fixed_size_shenanigans",
-                                                    pa.list_(
-                                                        pa.field("item", pa.float32(), nullable=False, metadata={}), 3
-                                                    ),
-                                                    nullable=False,
-                                                    metadata={},
-                                                ),
-                                            ]
-                                        ),
-                                        nullable=False,
-                                        metadata={},
-                                    )
-                                ),
-                                nullable=False,
-                                metadata={},
-                            ),
-                            pa.field(
-                                "many_optional",
-                                pa.list_(
-                                    pa.field(
-                                        "item",
-                                        pa.dense_union(
-                                            [
-                                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                                pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                                                pa.field("radians", pa.float32(), nullable=False, metadata={}),
-                                                pa.field(
-                                                    "craziness",
-                                                    pa.list_(
+                                                        ),
                                                         pa.field(
-                                                            "item",
-                                                            pa.struct(
-                                                                [
-                                                                    pa.field(
-                                                                        "single_float_optional",
-                                                                        pa.float32(),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "single_string_required",
-                                                                        pa.utf8(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "single_string_optional",
-                                                                        pa.utf8(),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "many_floats_optional",
-                                                                        pa.list_(
-                                                                            pa.field(
-                                                                                "item",
-                                                                                pa.float32(),
-                                                                                nullable=False,
-                                                                                metadata={},
-                                                                            )
-                                                                        ),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "many_strings_required",
-                                                                        pa.list_(
-                                                                            pa.field(
-                                                                                "item",
-                                                                                pa.utf8(),
-                                                                                nullable=False,
-                                                                                metadata={},
-                                                                            )
-                                                                        ),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "many_strings_optional",
-                                                                        pa.list_(
-                                                                            pa.field(
-                                                                                "item",
-                                                                                pa.utf8(),
-                                                                                nullable=False,
-                                                                                metadata={},
-                                                                            )
-                                                                        ),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "flattened_scalar",
-                                                                        pa.float32(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "almost_flattened_scalar",
-                                                                        pa.struct(
-                                                                            [
-                                                                                pa.field(
-                                                                                    "value",
-                                                                                    pa.float32(),
-                                                                                    nullable=False,
-                                                                                    metadata={},
-                                                                                )
-                                                                            ]
-                                                                        ),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    ),
-                                                                    pa.field(
-                                                                        "from_parent",
-                                                                        pa.bool_(),
-                                                                        nullable=True,
-                                                                        metadata={},
-                                                                    ),
-                                                                ]
+                                                            "many_strings_optional",
+                                                            pa.list_(
+                                                                pa.field("item", pa.utf8(), nullable=False, metadata={})
                                                             ),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "flattened_scalar",
+                                                            pa.float32(),
                                                             nullable=False,
                                                             metadata={},
-                                                        )
-                                                    ),
-                                                    nullable=False,
-                                                    metadata={},
-                                                ),
-                                                pa.field(
-                                                    "fixed_size_shenanigans",
-                                                    pa.list_(
-                                                        pa.field("item", pa.float32(), nullable=False, metadata={}), 3
-                                                    ),
+                                                        ),
+                                                        pa.field(
+                                                            "almost_flattened_scalar",
+                                                            pa.struct([
+                                                                pa.field(
+                                                                    "value", pa.float32(), nullable=False, metadata={}
+                                                                )
+                                                            ]),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                                    ]),
                                                     nullable=False,
                                                     metadata={},
-                                                ),
-                                            ]
+                                                )
+                                            ),
+                                            nullable=False,
+                                            metadata={},
                                         ),
-                                        nullable=False,
-                                        metadata={},
-                                    )
-                                ),
-                                nullable=False,
-                                metadata={},
+                                        pa.field(
+                                            "fixed_size_shenanigans",
+                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                    ]),
+                                    nullable=False,
+                                    metadata={},
+                                )
                             ),
-                        ]
-                    ),
+                            nullable=False,
+                            metadata={},
+                        ),
+                    ]),
                     nullable=False,
                     metadata={},
                 )
diff --git a/rerun_py/tests/test_types/components/affix_fuzzer7.py b/rerun_py/tests/test_types/components/affix_fuzzer7.py
index 3902fb9a733c..13adb7102f3d 100644
--- a/rerun_py/tests/test_types/components/affix_fuzzer7.py
+++ b/rerun_py/tests/test_types/components/affix_fuzzer7.py
@@ -43,39 +43,37 @@ def __init__(self) -> None:
             pa.list_(
                 pa.field(
                     "item",
-                    pa.struct(
-                        [
-                            pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
-                            pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
-                            pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
-                            pa.field(
-                                "many_floats_optional",
-                                pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
-                                nullable=True,
-                                metadata={},
-                            ),
-                            pa.field(
-                                "many_strings_required",
-                                pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                                nullable=False,
-                                metadata={},
-                            ),
-                            pa.field(
-                                "many_strings_optional",
-                                pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                                nullable=True,
-                                metadata={},
-                            ),
-                            pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
-                            pa.field(
-                                "almost_flattened_scalar",
-                                pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
-                                nullable=False,
-                                metadata={},
-                            ),
-                            pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
-                        ]
-                    ),
+                    pa.struct([
+                        pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
+                        pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
+                        pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
+                        pa.field(
+                            "many_floats_optional",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
+                            nullable=True,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "many_strings_required",
+                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "many_strings_optional",
+                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                            nullable=True,
+                            metadata={},
+                        ),
+                        pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                        pa.field(
+                            "almost_flattened_scalar",
+                            pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                    ]),
                     nullable=False,
                     metadata={},
                 )
diff --git a/rerun_py/tests/test_types/components/enum_test.py b/rerun_py/tests/test_types/components/enum_test.py
index d0e5325520fc..c57d80a06268 100644
--- a/rerun_py/tests/test_types/components/enum_test.py
+++ b/rerun_py/tests/test_types/components/enum_test.py
@@ -48,17 +48,15 @@ class EnumTestType(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.sparse_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field("Up", pa.null(), nullable=True, metadata={}),
-                    pa.field("Down", pa.null(), nullable=True, metadata={}),
-                    pa.field("Right", pa.null(), nullable=True, metadata={}),
-                    pa.field("Left", pa.null(), nullable=True, metadata={}),
-                    pa.field("Forward", pa.null(), nullable=True, metadata={}),
-                    pa.field("Back", pa.null(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.sparse_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field("Up", pa.null(), nullable=True, metadata={}),
+                pa.field("Down", pa.null(), nullable=True, metadata={}),
+                pa.field("Right", pa.null(), nullable=True, metadata={}),
+                pa.field("Left", pa.null(), nullable=True, metadata={}),
+                pa.field("Forward", pa.null(), nullable=True, metadata={}),
+                pa.field("Back", pa.null(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py
index c9b69542b4fc..7496d15d1773 100644
--- a/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py
+++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py
@@ -88,39 +88,37 @@ class AffixFuzzer1Type(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
-                    pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
-                    pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
-                    pa.field(
-                        "many_floats_optional",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
-                        nullable=True,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "many_strings_required",
-                        pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "many_strings_optional",
-                        pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                        nullable=True,
-                        metadata={},
-                    ),
-                    pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
-                    pa.field(
-                        "almost_flattened_scalar",
-                        pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
-                ]
-            ),
+            pa.struct([
+                pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
+                pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
+                pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
+                pa.field(
+                    "many_floats_optional",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
+                    nullable=True,
+                    metadata={},
+                ),
+                pa.field(
+                    "many_strings_required",
+                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "many_strings_optional",
+                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                    nullable=True,
+                    metadata={},
+                ),
+                pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                pa.field(
+                    "almost_flattened_scalar",
+                    pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py
index 3ec3196bb726..af092d58ba59 100644
--- a/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py
+++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py
@@ -57,12 +57,10 @@ class AffixFuzzer20Type(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field("p", pa.uint32(), nullable=False, metadata={}),
-                    pa.field("s", pa.utf8(), nullable=False, metadata={}),
-                ]
-            ),
+            pa.struct([
+                pa.field("p", pa.uint32(), nullable=False, metadata={}),
+                pa.field("s", pa.utf8(), nullable=False, metadata={}),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py
index e45c8cc35cde..ab09b21a9bc8 100644
--- a/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py
+++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py
@@ -44,17 +44,15 @@ class AffixFuzzer21Type(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field("single_half", pa.float16(), nullable=False, metadata={}),
-                    pa.field(
-                        "many_halves",
-                        pa.list_(pa.field("item", pa.float16(), nullable=False, metadata={})),
-                        nullable=False,
-                        metadata={},
-                    ),
-                ]
-            ),
+            pa.struct([
+                pa.field("single_half", pa.float16(), nullable=False, metadata={}),
+                pa.field(
+                    "many_halves",
+                    pa.list_(pa.field("item", pa.float16(), nullable=False, metadata={})),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py
index 940bd360cb50..6e732c2ce20e 100644
--- a/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py
+++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py
@@ -47,16 +47,14 @@ class AffixFuzzer22Type(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "fixed_sized_native",
-                        pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={}), 4),
-                        nullable=False,
-                        metadata={},
-                    )
-                ]
-            ),
+            pa.struct([
+                pa.field(
+                    "fixed_sized_native",
+                    pa.list_(pa.field("item", pa.uint8(), nullable=False, metadata={}), 4),
+                    nullable=False,
+                    metadata={},
+                )
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer3.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer3.py
index e9558ce2f2a7..3030782c0d40 100644
--- a/rerun_py/tests/test_types/datatypes/affix_fuzzer3.py
+++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer3.py
@@ -74,64 +74,60 @@ class AffixFuzzer3Type(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.dense_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                    pa.field("radians", pa.float32(), nullable=False, metadata={}),
-                    pa.field(
-                        "craziness",
-                        pa.list_(
-                            pa.field(
-                                "item",
-                                pa.struct(
-                                    [
-                                        pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
-                                        pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
-                                        pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
-                                        pa.field(
-                                            "many_floats_optional",
-                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
-                                            nullable=True,
-                                            metadata={},
-                                        ),
-                                        pa.field(
-                                            "many_strings_required",
-                                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                                            nullable=False,
-                                            metadata={},
-                                        ),
-                                        pa.field(
-                                            "many_strings_optional",
-                                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
-                                            nullable=True,
-                                            metadata={},
-                                        ),
-                                        pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
-                                        pa.field(
-                                            "almost_flattened_scalar",
-                                            pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
-                                            nullable=False,
-                                            metadata={},
-                                        ),
-                                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
-                                    ]
+            pa.dense_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                pa.field(
+                    "craziness",
+                    pa.list_(
+                        pa.field(
+                            "item",
+                            pa.struct([
+                                pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
+                                pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
+                                pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
+                                pa.field(
+                                    "many_floats_optional",
+                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
+                                    nullable=True,
+                                    metadata={},
                                 ),
-                                nullable=False,
-                                metadata={},
-                            )
-                        ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "fixed_size_shenanigans",
-                        pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                        nullable=False,
-                        metadata={},
+                                pa.field(
+                                    "many_strings_required",
+                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                    nullable=False,
+                                    metadata={},
+                                ),
+                                pa.field(
+                                    "many_strings_optional",
+                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                    nullable=True,
+                                    metadata={},
+                                ),
+                                pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                                pa.field(
+                                    "almost_flattened_scalar",
+                                    pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
+                                    nullable=False,
+                                    metadata={},
+                                ),
+                                pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        )
                     ),
-                ]
-            ),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "fixed_size_shenanigans",
+                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer4.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer4.py
index 77932d2fc75c..672729cd04b2 100644
--- a/rerun_py/tests/test_types/datatypes/affix_fuzzer4.py
+++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer4.py
@@ -66,13 +66,73 @@ class AffixFuzzer4Type(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.dense_union(
-                [
-                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                    pa.field(
-                        "single_required",
-                        pa.dense_union(
-                            [
+            pa.dense_union([
+                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                pa.field(
+                    "single_required",
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                        pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                        pa.field(
+                            "craziness",
+                            pa.list_(
+                                pa.field(
+                                    "item",
+                                    pa.struct([
+                                        pa.field("single_float_optional", pa.float32(), nullable=True, metadata={}),
+                                        pa.field("single_string_required", pa.utf8(), nullable=False, metadata={}),
+                                        pa.field("single_string_optional", pa.utf8(), nullable=True, metadata={}),
+                                        pa.field(
+                                            "many_floats_optional",
+                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={})),
+                                            nullable=True,
+                                            metadata={},
+                                        ),
+                                        pa.field(
+                                            "many_strings_required",
+                                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                        pa.field(
+                                            "many_strings_optional",
+                                            pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                            nullable=True,
+                                            metadata={},
+                                        ),
+                                        pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                                        pa.field(
+                                            "almost_flattened_scalar",
+                                            pa.struct([pa.field("value", pa.float32(), nullable=False, metadata={})]),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                    ]),
+                                    nullable=False,
+                                    metadata={},
+                                )
+                            ),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "fixed_size_shenanigans",
+                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                            nullable=False,
+                            metadata={},
+                        ),
+                    ]),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "many_required",
+                    pa.list_(
+                        pa.field(
+                            "item",
+                            pa.dense_union([
                                 pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
                                 pa.field("degrees", pa.float32(), nullable=False, metadata={}),
                                 pa.field("radians", pa.float32(), nullable=False, metadata={}),
@@ -81,62 +141,47 @@ def __init__(self) -> None:
                                     pa.list_(
                                         pa.field(
                                             "item",
-                                            pa.struct(
-                                                [
-                                                    pa.field(
-                                                        "single_float_optional",
-                                                        pa.float32(),
-                                                        nullable=True,
-                                                        metadata={},
-                                                    ),
-                                                    pa.field(
-                                                        "single_string_required", pa.utf8(), nullable=False, metadata={}
-                                                    ),
-                                                    pa.field(
-                                                        "single_string_optional", pa.utf8(), nullable=True, metadata={}
-                                                    ),
-                                                    pa.field(
-                                                        "many_floats_optional",
-                                                        pa.list_(
-                                                            pa.field("item", pa.float32(), nullable=False, metadata={})
-                                                        ),
-                                                        nullable=True,
-                                                        metadata={},
-                                                    ),
-                                                    pa.field(
-                                                        "many_strings_required",
-                                                        pa.list_(
-                                                            pa.field("item", pa.utf8(), nullable=False, metadata={})
-                                                        ),
-                                                        nullable=False,
-                                                        metadata={},
-                                                    ),
-                                                    pa.field(
-                                                        "many_strings_optional",
-                                                        pa.list_(
-                                                            pa.field("item", pa.utf8(), nullable=False, metadata={})
-                                                        ),
-                                                        nullable=True,
-                                                        metadata={},
-                                                    ),
-                                                    pa.field(
-                                                        "flattened_scalar", pa.float32(), nullable=False, metadata={}
-                                                    ),
-                                                    pa.field(
-                                                        "almost_flattened_scalar",
-                                                        pa.struct(
-                                                            [
-                                                                pa.field(
-                                                                    "value", pa.float32(), nullable=False, metadata={}
-                                                                )
-                                                            ]
-                                                        ),
-                                                        nullable=False,
-                                                        metadata={},
+                                            pa.struct([
+                                                pa.field(
+                                                    "single_float_optional", pa.float32(), nullable=True, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "single_string_required", pa.utf8(), nullable=False, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "single_string_optional", pa.utf8(), nullable=True, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "many_floats_optional",
+                                                    pa.list_(
+                                                        pa.field("item", pa.float32(), nullable=False, metadata={})
                                                     ),
-                                                    pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
-                                                ]
-                                            ),
+                                                    nullable=True,
+                                                    metadata={},
+                                                ),
+                                                pa.field(
+                                                    "many_strings_required",
+                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                                    nullable=False,
+                                                    metadata={},
+                                                ),
+                                                pa.field(
+                                                    "many_strings_optional",
+                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                                    nullable=True,
+                                                    metadata={},
+                                                ),
+                                                pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                                                pa.field(
+                                                    "almost_flattened_scalar",
+                                                    pa.struct([
+                                                        pa.field("value", pa.float32(), nullable=False, metadata={})
+                                                    ]),
+                                                    nullable=False,
+                                                    metadata={},
+                                                ),
+                                                pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                            ]),
                                             nullable=False,
                                             metadata={},
                                         )
@@ -150,245 +195,91 @@ def __init__(self) -> None:
                                     nullable=False,
                                     metadata={},
                                 ),
-                            ]
-                        ),
-                        nullable=False,
-                        metadata={},
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        )
                     ),
-                    pa.field(
-                        "many_required",
-                        pa.list_(
-                            pa.field(
-                                "item",
-                                pa.dense_union(
-                                    [
-                                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                        pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                                        pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                    nullable=False,
+                    metadata={},
+                ),
+                pa.field(
+                    "many_optional",
+                    pa.list_(
+                        pa.field(
+                            "item",
+                            pa.dense_union([
+                                pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                                pa.field("radians", pa.float32(), nullable=False, metadata={}),
+                                pa.field(
+                                    "craziness",
+                                    pa.list_(
                                         pa.field(
-                                            "craziness",
-                                            pa.list_(
+                                            "item",
+                                            pa.struct([
                                                 pa.field(
-                                                    "item",
-                                                    pa.struct(
-                                                        [
-                                                            pa.field(
-                                                                "single_float_optional",
-                                                                pa.float32(),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "single_string_required",
-                                                                pa.utf8(),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "single_string_optional",
-                                                                pa.utf8(),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_floats_optional",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item",
-                                                                        pa.float32(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    )
-                                                                ),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_strings_required",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item", pa.utf8(), nullable=False, metadata={}
-                                                                    )
-                                                                ),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_strings_optional",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item", pa.utf8(), nullable=False, metadata={}
-                                                                    )
-                                                                ),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "flattened_scalar",
-                                                                pa.float32(),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "almost_flattened_scalar",
-                                                                pa.struct(
-                                                                    [
-                                                                        pa.field(
-                                                                            "value",
-                                                                            pa.float32(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        )
-                                                                    ]
-                                                                ),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "from_parent", pa.bool_(), nullable=True, metadata={}
-                                                            ),
-                                                        ]
+                                                    "single_float_optional", pa.float32(), nullable=True, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "single_string_required", pa.utf8(), nullable=False, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "single_string_optional", pa.utf8(), nullable=True, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "many_floats_optional",
+                                                    pa.list_(
+                                                        pa.field("item", pa.float32(), nullable=False, metadata={})
                                                     ),
+                                                    nullable=True,
+                                                    metadata={},
+                                                ),
+                                                pa.field(
+                                                    "many_strings_required",
+                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
                                                     nullable=False,
                                                     metadata={},
-                                                )
-                                            ),
-                                            nullable=False,
-                                            metadata={},
-                                        ),
-                                        pa.field(
-                                            "fixed_size_shenanigans",
-                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
-                                            nullable=False,
-                                            metadata={},
-                                        ),
-                                    ]
-                                ),
-                                nullable=False,
-                                metadata={},
-                            )
-                        ),
-                        nullable=False,
-                        metadata={},
-                    ),
-                    pa.field(
-                        "many_optional",
-                        pa.list_(
-                            pa.field(
-                                "item",
-                                pa.dense_union(
-                                    [
-                                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                        pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                                        pa.field("radians", pa.float32(), nullable=False, metadata={}),
-                                        pa.field(
-                                            "craziness",
-                                            pa.list_(
+                                                ),
                                                 pa.field(
-                                                    "item",
-                                                    pa.struct(
-                                                        [
-                                                            pa.field(
-                                                                "single_float_optional",
-                                                                pa.float32(),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "single_string_required",
-                                                                pa.utf8(),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "single_string_optional",
-                                                                pa.utf8(),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_floats_optional",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item",
-                                                                        pa.float32(),
-                                                                        nullable=False,
-                                                                        metadata={},
-                                                                    )
-                                                                ),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_strings_required",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item", pa.utf8(), nullable=False, metadata={}
-                                                                    )
-                                                                ),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "many_strings_optional",
-                                                                pa.list_(
-                                                                    pa.field(
-                                                                        "item", pa.utf8(), nullable=False, metadata={}
-                                                                    )
-                                                                ),
-                                                                nullable=True,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "flattened_scalar",
-                                                                pa.float32(),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "almost_flattened_scalar",
-                                                                pa.struct(
-                                                                    [
-                                                                        pa.field(
-                                                                            "value",
-                                                                            pa.float32(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        )
-                                                                    ]
-                                                                ),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            ),
-                                                            pa.field(
-                                                                "from_parent", pa.bool_(), nullable=True, metadata={}
-                                                            ),
-                                                        ]
-                                                    ),
+                                                    "many_strings_optional",
+                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                                    nullable=True,
+                                                    metadata={},
+                                                ),
+                                                pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                                                pa.field(
+                                                    "almost_flattened_scalar",
+                                                    pa.struct([
+                                                        pa.field("value", pa.float32(), nullable=False, metadata={})
+                                                    ]),
                                                     nullable=False,
                                                     metadata={},
-                                                )
-                                            ),
-                                            nullable=False,
-                                            metadata={},
-                                        ),
-                                        pa.field(
-                                            "fixed_size_shenanigans",
-                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                                                ),
+                                                pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                            ]),
                                             nullable=False,
                                             metadata={},
-                                        ),
-                                    ]
+                                        )
+                                    ),
+                                    nullable=False,
+                                    metadata={},
                                 ),
-                                nullable=False,
-                                metadata={},
-                            )
-                        ),
-                        nullable=False,
-                        metadata={},
+                                pa.field(
+                                    "fixed_size_shenanigans",
+                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                                    nullable=False,
+                                    metadata={},
+                                ),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        )
                     ),
-                ]
-            ),
+                    nullable=False,
+                    metadata={},
+                ),
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py
index c110886cea93..4bd517892ea4 100644
--- a/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py
+++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py
@@ -53,396 +53,281 @@ class AffixFuzzer5Type(BaseExtensionType):
     def __init__(self) -> None:
         pa.ExtensionType.__init__(
             self,
-            pa.struct(
-                [
-                    pa.field(
-                        "single_optional_union",
-                        pa.dense_union(
-                            [
+            pa.struct([
+                pa.field(
+                    "single_optional_union",
+                    pa.dense_union([
+                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                        pa.field(
+                            "single_required",
+                            pa.dense_union([
                                 pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                                pa.field("radians", pa.float32(), nullable=False, metadata={}),
                                 pa.field(
-                                    "single_required",
-                                    pa.dense_union(
-                                        [
-                                            pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                            pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                                            pa.field("radians", pa.float32(), nullable=False, metadata={}),
-                                            pa.field(
-                                                "craziness",
-                                                pa.list_(
-                                                    pa.field(
-                                                        "item",
-                                                        pa.struct(
-                                                            [
-                                                                pa.field(
-                                                                    "single_float_optional",
-                                                                    pa.float32(),
-                                                                    nullable=True,
-                                                                    metadata={},
-                                                                ),
-                                                                pa.field(
-                                                                    "single_string_required",
-                                                                    pa.utf8(),
-                                                                    nullable=False,
-                                                                    metadata={},
-                                                                ),
-                                                                pa.field(
-                                                                    "single_string_optional",
-                                                                    pa.utf8(),
-                                                                    nullable=True,
-                                                                    metadata={},
-                                                                ),
-                                                                pa.field(
-                                                                    "many_floats_optional",
-                                                                    pa.list_(
-                                                                        pa.field(
-                                                                            "item",
-                                                                            pa.float32(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        )
-                                                                    ),
-                                                                    nullable=True,
-                                                                    metadata={},
-                                                                ),
-                                                                pa.field(
-                                                                    "many_strings_required",
-                                                                    pa.list_(
-                                                                        pa.field(
-                                                                            "item",
-                                                                            pa.utf8(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        )
-                                                                    ),
-                                                                    nullable=False,
-                                                                    metadata={},
-                                                                ),
-                                                                pa.field(
-                                                                    "many_strings_optional",
-                                                                    pa.list_(
-                                                                        pa.field(
-                                                                            "item",
-                                                                            pa.utf8(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        )
-                                                                    ),
-                                                                    nullable=True,
-                                                                    metadata={},
-                                                                ),
-                                                                pa.field(
-                                                                    "flattened_scalar",
-                                                                    pa.float32(),
-                                                                    nullable=False,
-                                                                    metadata={},
-                                                                ),
-                                                                pa.field(
-                                                                    "almost_flattened_scalar",
-                                                                    pa.struct(
-                                                                        [
-                                                                            pa.field(
-                                                                                "value",
-                                                                                pa.float32(),
-                                                                                nullable=False,
-                                                                                metadata={},
-                                                                            )
-                                                                        ]
-                                                                    ),
-                                                                    nullable=False,
-                                                                    metadata={},
-                                                                ),
-                                                                pa.field(
-                                                                    "from_parent",
-                                                                    pa.bool_(),
-                                                                    nullable=True,
-                                                                    metadata={},
-                                                                ),
-                                                            ]
-                                                        ),
-                                                        nullable=False,
-                                                        metadata={},
-                                                    )
+                                    "craziness",
+                                    pa.list_(
+                                        pa.field(
+                                            "item",
+                                            pa.struct([
+                                                pa.field(
+                                                    "single_float_optional", pa.float32(), nullable=True, metadata={}
                                                 ),
-                                                nullable=False,
-                                                metadata={},
-                                            ),
-                                            pa.field(
-                                                "fixed_size_shenanigans",
-                                                pa.list_(
-                                                    pa.field("item", pa.float32(), nullable=False, metadata={}), 3
+                                                pa.field(
+                                                    "single_string_required", pa.utf8(), nullable=False, metadata={}
                                                 ),
-                                                nullable=False,
-                                                metadata={},
-                                            ),
-                                        ]
+                                                pa.field(
+                                                    "single_string_optional", pa.utf8(), nullable=True, metadata={}
+                                                ),
+                                                pa.field(
+                                                    "many_floats_optional",
+                                                    pa.list_(
+                                                        pa.field("item", pa.float32(), nullable=False, metadata={})
+                                                    ),
+                                                    nullable=True,
+                                                    metadata={},
+                                                ),
+                                                pa.field(
+                                                    "many_strings_required",
+                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                                    nullable=False,
+                                                    metadata={},
+                                                ),
+                                                pa.field(
+                                                    "many_strings_optional",
+                                                    pa.list_(pa.field("item", pa.utf8(), nullable=False, metadata={})),
+                                                    nullable=True,
+                                                    metadata={},
+                                                ),
+                                                pa.field("flattened_scalar", pa.float32(), nullable=False, metadata={}),
+                                                pa.field(
+                                                    "almost_flattened_scalar",
+                                                    pa.struct([
+                                                        pa.field("value", pa.float32(), nullable=False, metadata={})
+                                                    ]),
+                                                    nullable=False,
+                                                    metadata={},
+                                                ),
+                                                pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                            ]),
+                                            nullable=False,
+                                            metadata={},
+                                        )
                                     ),
                                     nullable=False,
                                     metadata={},
                                 ),
                                 pa.field(
-                                    "many_required",
-                                    pa.list_(
+                                    "fixed_size_shenanigans",
+                                    pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                                    nullable=False,
+                                    metadata={},
+                                ),
+                            ]),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "many_required",
+                            pa.list_(
+                                pa.field(
+                                    "item",
+                                    pa.dense_union([
+                                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                        pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                                        pa.field("radians", pa.float32(), nullable=False, metadata={}),
                                         pa.field(
-                                            "item",
-                                            pa.dense_union(
-                                                [
-                                                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                                    pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                                                    pa.field("radians", pa.float32(), nullable=False, metadata={}),
-                                                    pa.field(
-                                                        "craziness",
-                                                        pa.list_(
-                                                            pa.field(
-                                                                "item",
-                                                                pa.struct(
-                                                                    [
-                                                                        pa.field(
-                                                                            "single_float_optional",
-                                                                            pa.float32(),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "single_string_required",
-                                                                            pa.utf8(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "single_string_optional",
-                                                                            pa.utf8(),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "many_floats_optional",
-                                                                            pa.list_(
-                                                                                pa.field(
-                                                                                    "item",
-                                                                                    pa.float32(),
-                                                                                    nullable=False,
-                                                                                    metadata={},
-                                                                                )
-                                                                            ),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "many_strings_required",
-                                                                            pa.list_(
-                                                                                pa.field(
-                                                                                    "item",
-                                                                                    pa.utf8(),
-                                                                                    nullable=False,
-                                                                                    metadata={},
-                                                                                )
-                                                                            ),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "many_strings_optional",
-                                                                            pa.list_(
-                                                                                pa.field(
-                                                                                    "item",
-                                                                                    pa.utf8(),
-                                                                                    nullable=False,
-                                                                                    metadata={},
-                                                                                )
-                                                                            ),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "flattened_scalar",
-                                                                            pa.float32(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "almost_flattened_scalar",
-                                                                            pa.struct(
-                                                                                [
-                                                                                    pa.field(
-                                                                                        "value",
-                                                                                        pa.float32(),
-                                                                                        nullable=False,
-                                                                                        metadata={},
-                                                                                    )
-                                                                                ]
-                                                                            ),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "from_parent",
-                                                                            pa.bool_(),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                    ]
-                                                                ),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            )
+                                            "craziness",
+                                            pa.list_(
+                                                pa.field(
+                                                    "item",
+                                                    pa.struct([
+                                                        pa.field(
+                                                            "single_float_optional",
+                                                            pa.float32(),
+                                                            nullable=True,
+                                                            metadata={},
                                                         ),
-                                                        nullable=False,
-                                                        metadata={},
-                                                    ),
-                                                    pa.field(
-                                                        "fixed_size_shenanigans",
-                                                        pa.list_(
-                                                            pa.field("item", pa.float32(), nullable=False, metadata={}),
-                                                            3,
+                                                        pa.field(
+                                                            "single_string_required",
+                                                            pa.utf8(),
+                                                            nullable=False,
+                                                            metadata={},
                                                         ),
-                                                        nullable=False,
-                                                        metadata={},
-                                                    ),
-                                                ]
+                                                        pa.field(
+                                                            "single_string_optional",
+                                                            pa.utf8(),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_floats_optional",
+                                                            pa.list_(
+                                                                pa.field(
+                                                                    "item", pa.float32(), nullable=False, metadata={}
+                                                                )
+                                                            ),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_strings_required",
+                                                            pa.list_(
+                                                                pa.field("item", pa.utf8(), nullable=False, metadata={})
+                                                            ),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_strings_optional",
+                                                            pa.list_(
+                                                                pa.field("item", pa.utf8(), nullable=False, metadata={})
+                                                            ),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "flattened_scalar",
+                                                            pa.float32(),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "almost_flattened_scalar",
+                                                            pa.struct([
+                                                                pa.field(
+                                                                    "value", pa.float32(), nullable=False, metadata={}
+                                                                )
+                                                            ]),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                                    ]),
+                                                    nullable=False,
+                                                    metadata={},
+                                                )
                                             ),
                                             nullable=False,
                                             metadata={},
-                                        )
-                                    ),
+                                        ),
+                                        pa.field(
+                                            "fixed_size_shenanigans",
+                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                    ]),
                                     nullable=False,
                                     metadata={},
-                                ),
+                                )
+                            ),
+                            nullable=False,
+                            metadata={},
+                        ),
+                        pa.field(
+                            "many_optional",
+                            pa.list_(
                                 pa.field(
-                                    "many_optional",
-                                    pa.list_(
+                                    "item",
+                                    pa.dense_union([
+                                        pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
+                                        pa.field("degrees", pa.float32(), nullable=False, metadata={}),
+                                        pa.field("radians", pa.float32(), nullable=False, metadata={}),
                                         pa.field(
-                                            "item",
-                                            pa.dense_union(
-                                                [
-                                                    pa.field("_null_markers", pa.null(), nullable=True, metadata={}),
-                                                    pa.field("degrees", pa.float32(), nullable=False, metadata={}),
-                                                    pa.field("radians", pa.float32(), nullable=False, metadata={}),
-                                                    pa.field(
-                                                        "craziness",
-                                                        pa.list_(
-                                                            pa.field(
-                                                                "item",
-                                                                pa.struct(
-                                                                    [
-                                                                        pa.field(
-                                                                            "single_float_optional",
-                                                                            pa.float32(),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "single_string_required",
-                                                                            pa.utf8(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "single_string_optional",
-                                                                            pa.utf8(),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "many_floats_optional",
-                                                                            pa.list_(
-                                                                                pa.field(
-                                                                                    "item",
-                                                                                    pa.float32(),
-                                                                                    nullable=False,
-                                                                                    metadata={},
-                                                                                )
-                                                                            ),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "many_strings_required",
-                                                                            pa.list_(
-                                                                                pa.field(
-                                                                                    "item",
-                                                                                    pa.utf8(),
-                                                                                    nullable=False,
-                                                                                    metadata={},
-                                                                                )
-                                                                            ),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "many_strings_optional",
-                                                                            pa.list_(
-                                                                                pa.field(
-                                                                                    "item",
-                                                                                    pa.utf8(),
-                                                                                    nullable=False,
-                                                                                    metadata={},
-                                                                                )
-                                                                            ),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "flattened_scalar",
-                                                                            pa.float32(),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "almost_flattened_scalar",
-                                                                            pa.struct(
-                                                                                [
-                                                                                    pa.field(
-                                                                                        "value",
-                                                                                        pa.float32(),
-                                                                                        nullable=False,
-                                                                                        metadata={},
-                                                                                    )
-                                                                                ]
-                                                                            ),
-                                                                            nullable=False,
-                                                                            metadata={},
-                                                                        ),
-                                                                        pa.field(
-                                                                            "from_parent",
-                                                                            pa.bool_(),
-                                                                            nullable=True,
-                                                                            metadata={},
-                                                                        ),
-                                                                    ]
-                                                                ),
-                                                                nullable=False,
-                                                                metadata={},
-                                                            )
+                                            "craziness",
+                                            pa.list_(
+                                                pa.field(
+                                                    "item",
+                                                    pa.struct([
+                                                        pa.field(
+                                                            "single_float_optional",
+                                                            pa.float32(),
+                                                            nullable=True,
+                                                            metadata={},
                                                         ),
-                                                        nullable=False,
-                                                        metadata={},
-                                                    ),
-                                                    pa.field(
-                                                        "fixed_size_shenanigans",
-                                                        pa.list_(
-                                                            pa.field("item", pa.float32(), nullable=False, metadata={}),
-                                                            3,
+                                                        pa.field(
+                                                            "single_string_required",
+                                                            pa.utf8(),
+                                                            nullable=False,
+                                                            metadata={},
                                                         ),
-                                                        nullable=False,
-                                                        metadata={},
-                                                    ),
-                                                ]
+                                                        pa.field(
+                                                            "single_string_optional",
+                                                            pa.utf8(),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_floats_optional",
+                                                            pa.list_(
+                                                                pa.field(
+                                                                    "item", pa.float32(), nullable=False, metadata={}
+                                                                )
+                                                            ),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_strings_required",
+                                                            pa.list_(
+                                                                pa.field("item", pa.utf8(), nullable=False, metadata={})
+                                                            ),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "many_strings_optional",
+                                                            pa.list_(
+                                                                pa.field("item", pa.utf8(), nullable=False, metadata={})
+                                                            ),
+                                                            nullable=True,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "flattened_scalar",
+                                                            pa.float32(),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field(
+                                                            "almost_flattened_scalar",
+                                                            pa.struct([
+                                                                pa.field(
+                                                                    "value", pa.float32(), nullable=False, metadata={}
+                                                                )
+                                                            ]),
+                                                            nullable=False,
+                                                            metadata={},
+                                                        ),
+                                                        pa.field("from_parent", pa.bool_(), nullable=True, metadata={}),
+                                                    ]),
+                                                    nullable=False,
+                                                    metadata={},
+                                                )
                                             ),
                                             nullable=False,
                                             metadata={},
-                                        )
-                                    ),
+                                        ),
+                                        pa.field(
+                                            "fixed_size_shenanigans",
+                                            pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 3),
+                                            nullable=False,
+                                            metadata={},
+                                        ),
+                                    ]),
                                     nullable=False,
                                     metadata={},
-                                ),
-                            ]
+                                )
+                            ),
+                            nullable=False,
+                            metadata={},
                         ),
-                        nullable=True,
-                        metadata={},
-                    )
-                ]
-            ),
+                    ]),
+                    nullable=True,
+                    metadata={},
+                )
+            ]),
             self._TYPE_NAME,
         )
 
diff --git a/rerun_py/tests/unit/test_line_strips2d.py b/rerun_py/tests/unit/test_line_strips2d.py
index c4ff870008b3..979a038480fb 100644
--- a/rerun_py/tests/unit/test_line_strips2d.py
+++ b/rerun_py/tests/unit/test_line_strips2d.py
@@ -127,12 +127,10 @@ def test_line_strips2d() -> None:
 def test_line_segments2d(data: LineStrip2DArrayLike) -> None:
     arch = rr.LineStrips2D(data)
 
-    assert arch.strips == LineStrip2DBatch(
-        [
-            [[0, 0], [2, 1]],
-            [[4, -1], [6, 0]],
-        ]
-    )
+    assert arch.strips == LineStrip2DBatch([
+        [[0, 0], [2, 1]],
+        [[4, -1], [6, 0]],
+    ])
 
 
 def test_single_line_strip2d() -> None:
@@ -169,21 +167,17 @@ def test_line_strip2d_invalid_shapes() -> None:
     # not homogeneous numpy arrays
     with pytest.raises(ValueError):
         rr.LineStrips2D(
-            np.array(
-                [
-                    [[0, 0], (2, 1), [4, -1], (6, 0)],
-                    [[0, 3], (1, 4), [2, 2], (3, 4), [4, 2], (5, 4), [6, 3]],
-                ]
-            )
+            np.array([
+                [[0, 0], (2, 1), [4, -1], (6, 0)],
+                [[0, 3], (1, 4), [2, 2], (3, 4), [4, 2], (5, 4), [6, 3]],
+            ])
         )
     with pytest.raises(ValueError):
         rr.LineStrips2D(
-            np.array(
-                [
-                    [0, 0, 2, 1, 4, -1, 6, 0],
-                    [0, 3, 1, 4, 2, 2, 3, 4, 4, 2, 5, 4, 6, 3],
-                ]
-            ),
+            np.array([
+                [0, 0, 2, 1, 4, -1, 6, 0],
+                [0, 3, 1, 4, 2, 2, 3, 4, 4, 2, 5, 4, 6, 3],
+            ]),
         )
 
 
diff --git a/rerun_py/tests/unit/test_line_strips3d.py b/rerun_py/tests/unit/test_line_strips3d.py
index f19583fd644c..fc8e3a628dc8 100644
--- a/rerun_py/tests/unit/test_line_strips3d.py
+++ b/rerun_py/tests/unit/test_line_strips3d.py
@@ -175,22 +175,18 @@ def test_line_strip2d_invalid_shapes() -> None:
     with pytest.raises(ValueError):
         rr.LineStrips3D(
             np.array(
-                np.array(
-                    [
-                        [([0, 0, 2]), [1, 0, 2], [1, 1, 2], [0, 1, 2]],
-                        [([0, 0, 0]), [0, 0, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1], [0, 1, 0], [0, 1, 1]],
-                    ]
-                ),
+                np.array([
+                    [([0, 0, 2]), [1, 0, 2], [1, 1, 2], [0, 1, 2]],
+                    [([0, 0, 0]), [0, 0, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1], [0, 1, 0], [0, 1, 1]],
+                ]),
             )
         )
     with pytest.raises(ValueError):
         rr.LineStrips3D(
-            np.array(
-                [
-                    [0, 0, 2, 1, 4, -1, 6, 0],
-                    [0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1],
-                ]
-            ),
+            np.array([
+                [0, 0, 2, 1, 4, -1, 6, 0],
+                [0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1],
+            ]),
         )
 
 
diff --git a/rerun_py/tests/unit/test_mesh3d.py b/rerun_py/tests/unit/test_mesh3d.py
index e9185b377034..bab3c59c777b 100644
--- a/rerun_py/tests/unit/test_mesh3d.py
+++ b/rerun_py/tests/unit/test_mesh3d.py
@@ -124,21 +124,17 @@ def test_nullable_albedo_factor() -> None:
     # NOTE: We're just making sure that this doesn't crash… trust me, it used to.
     assert (
         len(
-            MaterialBatch(
-                [
-                    Material(albedo_factor=[0xCC, 0x00, 0xCC, 0xFF]),
-                ]
-            )
+            MaterialBatch([
+                Material(albedo_factor=[0xCC, 0x00, 0xCC, 0xFF]),
+            ])
         )
         == 1
     )
     assert (
         len(
-            MaterialBatch(
-                [
-                    Material(),
-                ]
-            )
+            MaterialBatch([
+                Material(),
+            ])
         )
         == 1
     )
@@ -148,12 +144,10 @@ def test_nullable_indices() -> None:
     # NOTE: We're just making sure that this doesn't crash… trust me, it used to.
     assert (
         len(
-            MeshPropertiesBatch(
-                [
-                    MeshProperties(indices=[1, 2, 3, 4, 5, 6]),
-                    MeshProperties(),
-                ]
-            )
+            MeshPropertiesBatch([
+                MeshProperties(indices=[1, 2, 3, 4, 5, 6]),
+                MeshProperties(),
+            ])
         )
         == 2
     )
diff --git a/rerun_py/tests/unit/test_points2d.py b/rerun_py/tests/unit/test_points2d.py
index 67cd83b49ec1..fd10f1b976a1 100644
--- a/rerun_py/tests/unit/test_points2d.py
+++ b/rerun_py/tests/unit/test_points2d.py
@@ -130,12 +130,10 @@ def test_point2d_single_color(data: Rgba32ArrayLike) -> None:
 def test_point2d_multiple_colors(data: Rgba32ArrayLike) -> None:
     pts = rr.Points2D(positions=np.zeros((5, 2)), colors=data)
 
-    assert pts.colors == ColorBatch(
-        [
-            Color([0, 128, 0, 255]),
-            Color([128, 0, 0, 255]),
-        ]
-    )
+    assert pts.colors == ColorBatch([
+        Color([0, 128, 0, 255]),
+        Color([128, 0, 0, 255]),
+    ])
 
 
 if __name__ == "__main__":
diff --git a/rerun_py/tests/unit/test_points3d.py b/rerun_py/tests/unit/test_points3d.py
index 1c691698ba59..0d4a7d5738a4 100644
--- a/rerun_py/tests/unit/test_points3d.py
+++ b/rerun_py/tests/unit/test_points3d.py
@@ -122,12 +122,10 @@ def test_point3d_single_color(data: Rgba32ArrayLike) -> None:
 def test_point3d_multiple_colors(data: Rgba32ArrayLike) -> None:
     pts = rr.Points3D(positions=np.zeros((5, 3)), colors=data)
 
-    assert pts.colors == ColorBatch(
-        [
-            Color([0, 128, 0, 255]),
-            Color([128, 0, 0, 255]),
-        ]
-    )
+    assert pts.colors == ColorBatch([
+        Color([0, 128, 0, 255]),
+        Color([128, 0, 0, 255]),
+    ])
 
 
 if __name__ == "__main__":
diff --git a/rerun_py/tests/unit/test_view_coordinates.py b/rerun_py/tests/unit/test_view_coordinates.py
index 057e2239bd46..9f084469723c 100644
--- a/rerun_py/tests/unit/test_view_coordinates.py
+++ b/rerun_py/tests/unit/test_view_coordinates.py
@@ -18,13 +18,11 @@ def view_coordinates_expected(obj: Any) -> rrc.ViewCoordinatesBatch:
 
 VIEW_COORDINATES_INPUTS: list[rrc.ViewCoordinatesArrayLike | None] = [
     None,
-    rrc.ViewCoordinates(
-        [
-            rrc.ViewCoordinates.ViewDir.Right,
-            rrc.ViewCoordinates.ViewDir.Down,
-            rrc.ViewCoordinates.ViewDir.Forward,
-        ]
-    ),
+    rrc.ViewCoordinates([
+        rrc.ViewCoordinates.ViewDir.Right,
+        rrc.ViewCoordinates.ViewDir.Down,
+        rrc.ViewCoordinates.ViewDir.Forward,
+    ]),
     [
         rrc.ViewCoordinates.ViewDir.Right,
         rrc.ViewCoordinates.ViewDir.Down,
diff --git a/scripts/ci/check_large_files.py b/scripts/ci/check_large_files.py
index 78d772cb877e..9c9a857e372e 100755
--- a/scripts/ci/check_large_files.py
+++ b/scripts/ci/check_large_files.py
@@ -24,7 +24,7 @@
     if actual_size >= maximum_size:
         allow_list_path = os.path.join(script_path, "check_large_files_allow_list.txt")
 
-        with open(allow_list_path) as allow_list_file:
+        with open(allow_list_path, encoding="utf8") as allow_list_file:
             allow_list = allow_list_file.read().splitlines()
 
         if file_path not in allow_list:
diff --git a/scripts/ci/check_links.py b/scripts/ci/check_links.py
index 549a9dc7c5ca..fe7432500364 100755
--- a/scripts/ci/check_links.py
+++ b/scripts/ci/check_links.py
@@ -14,7 +14,7 @@
 
 def check_file(file_path: str) -> list[str] | None:
     links = []
-    with open(file_path) as f:
+    with open(file_path, encoding="utf8") as f:
         content = f.read()
         for m in re.finditer(f"(https://.*){NEW_LINK_MARKER}", content):
             link = m.group(0)
diff --git a/scripts/ci/compare.py b/scripts/ci/compare.py
index ca040ab97cab..ce078d128189 100755
--- a/scripts/ci/compare.py
+++ b/scripts/ci/compare.py
@@ -129,14 +129,12 @@ def compare(
                     change = f"{change_pct:+.2f}%"
                 else:
                     change = f"{format_num(current - previous)} {unit}"
-                rows.append(
-                    (
-                        name,
-                        f"{format_num(previous)} {unit}",
-                        f"{format_num(current)} {unit}",
-                        change,
-                    )
-                )
+                rows.append((
+                    name,
+                    f"{format_num(previous)} {unit}",
+                    f"{format_num(current)} {unit}",
+                    change,
+                ))
         elif "current" in entry:
             value = entry["current"]["value"]
             unit = entry["current"]["unit"]
diff --git a/scripts/ci/count_bytes.py b/scripts/ci/count_bytes.py
index 71f188ab3bb4..c79ea3b5f6d2 100755
--- a/scripts/ci/count_bytes.py
+++ b/scripts/ci/count_bytes.py
@@ -97,13 +97,11 @@ def measure(files: list[str], format: Format) -> None:
         unit = parts[2] if len(parts) > 2 else get_unit(size)
         div = get_divisor(unit)
 
-        output.append(
-            {
-                "name": name,
-                "value": str(round(size / div, 2)),
-                "unit": unit,
-            }
-        )
+        output.append({
+            "name": name,
+            "value": str(round(size / div, 2)),
+            "unit": unit,
+        })
 
     sys.stdout.write(format.render(output))
     sys.stdout.flush()
diff --git a/scripts/ci/dag.py b/scripts/ci/dag.py
index 90887e45096c..f5e99f7eeede 100644
--- a/scripts/ci/dag.py
+++ b/scripts/ci/dag.py
@@ -204,14 +204,12 @@ def process(node: str) -> None:
     #   Processed B at T+0.5
     #   Processed D at T+1
     # `A` and `C` may swap places.
-    dag = DAG(
-        {
-            "A": [],
-            "B": ["A"],
-            "C": [],
-            "D": ["A", "B", "C"],
-        }
-    )
+    dag = DAG({
+        "A": [],
+        "B": ["A"],
+        "C": [],
+        "D": ["A", "B", "C"],
+    })
 
     # `walk_parallel` can be called multiple times
     dag.walk_parallel(
diff --git a/scripts/ci/generate_pr_summary.py b/scripts/ci/generate_pr_summary.py
index 0674da0e57b7..a90bf7668e0a 100644
--- a/scripts/ci/generate_pr_summary.py
+++ b/scripts/ci/generate_pr_summary.py
@@ -87,7 +87,7 @@ def generate_pr_summary(github_token: str, github_repository: str, pr_number: in
     template_path = os.path.join(os.path.dirname(os.path.relpath(__file__)), "templates/pr_results_summary.html")
 
     # Render the Jinja template with the found_builds variable
-    with open(template_path) as f:
+    with open(template_path, encoding="utf8") as f:
         template = Template(f.read())
 
     buffer = io.BytesIO(template.render(found_builds=found_builds, pr_number=pr_number).encode("utf-8"))
diff --git a/scripts/ci/generate_prerelease_pip_index.py b/scripts/ci/generate_prerelease_pip_index.py
index 6d4d752f2284..4918ba42d963 100755
--- a/scripts/ci/generate_prerelease_pip_index.py
+++ b/scripts/ci/generate_prerelease_pip_index.py
@@ -52,7 +52,7 @@ def generate_pip_index(title: str, dir: str, upload: bool, check: bool) -> None:
     template_path = os.path.join(os.path.dirname(os.path.relpath(__file__)), "templates/pip_index.html")
 
     # Render the Jinja template with the found_builds variable
-    with open(template_path) as f:
+    with open(template_path, encoding="utf8") as f:
         template = Template(f.read())
 
     buffer = io.BytesIO(template.render(found_builds=found_builds).encode("utf-8"))
diff --git a/scripts/ci/render_bench.py b/scripts/ci/render_bench.py
index a76f51967f32..a1431f4f8d9c 100755
--- a/scripts/ci/render_bench.py
+++ b/scripts/ci/render_bench.py
@@ -258,7 +258,7 @@ def label(entry: BenchmarkEntry) -> str:
             "data": data,
         }
 
-    with open(os.path.join(SCRIPT_PATH, "templates/benchmark.html")) as template_file:
+    with open(os.path.join(SCRIPT_PATH, "templates/benchmark.html"), encoding="utf8") as template_file:
         html = template_file.read()
         html = html.replace("%%TITLE%%", title)
         # double encode to escape the data as a single string
diff --git a/scripts/ci/rust_checks.py b/scripts/ci/rust_checks.py
index d6cfa115a2e2..c614ea447cd8 100755
--- a/scripts/ci/rust_checks.py
+++ b/scripts/ci/rust_checks.py
@@ -46,7 +46,7 @@ def run_cargo(cargo_cmd, cargo_args: str, clippy_conf: str | None = None) -> Tim
 
 
 def package_name_from_cargo_toml(cargo_toml_path: str) -> str:
-    with open(cargo_toml_path) as file:
+    with open(cargo_toml_path, encoding="utf8") as file:
         cargo_toml_contents = file.read()
     package_name_result = re.search(r'name\s+=\s"([\w\-_]+)"', cargo_toml_contents)
     if package_name_result is None:
diff --git a/scripts/generate_changelog.py b/scripts/generate_changelog.py
index 4bdb8cda6f54..ddb5f21adc92 100755
--- a/scripts/generate_changelog.py
+++ b/scripts/generate_changelog.py
@@ -65,7 +65,7 @@ def get_github_token() -> str:
     token_file = os.path.join(home_dir, ".githubtoken")
 
     try:
-        with open(token_file) as f:
+        with open(token_file, encoding="utf8") as f:
             token = f.read().strip()
         return token
     except Exception:
@@ -127,7 +127,7 @@ def main() -> None:
     args = parser.parse_args()
 
     # Because how we branch, we sometimes get duplicate commits in the changelog unless we check for it
-    previous_changelog = open("CHANGELOG.md").read()
+    previous_changelog = open("CHANGELOG.md", encoding="utf8").read()
 
     repo = Repo(".")
     commits = list(repo.iter_commits(args.commit_range))
diff --git a/scripts/generate_view_coordinate_defs.py b/scripts/generate_view_coordinate_defs.py
index 5a3814097543..a947c6f0dcbc 100755
--- a/scripts/generate_view_coordinate_defs.py
+++ b/scripts/generate_view_coordinate_defs.py
@@ -268,13 +268,13 @@ def show_preview(lines: list[str]) -> None:
 
 
 def patch_file(filename: str, lines: list[str], key: str) -> None:
-    contents = open(filename).readlines()
+    contents = open(filename, encoding="utf8").readlines()
     start_line = next((i for i, line in enumerate(contents) if BEGIN_MARKER.format(key) in line), None)
     end_line = next((i for i, line in enumerate(contents) if END_MARKER.format(key) in line), None)
     if (start_line is None) or (end_line is None):
         raise Exception("Could not find the generated section in the file.")
     new_contents = contents[:start_line] + lines + contents[end_line + 1 :]
-    open(filename, "w").writelines(new_contents)
+    open(filename, "w", encoding="utf8").writelines(new_contents)
 
 
 ################################################################################
diff --git a/scripts/highlight_issues.py b/scripts/highlight_issues.py
index 79b69fc2db64..92810cbe6349 100755
--- a/scripts/highlight_issues.py
+++ b/scripts/highlight_issues.py
@@ -38,7 +38,7 @@ def get_github_token() -> str:
     token_file = os.path.join(home_dir, ".githubtoken")
 
     try:
-        with open(token_file) as f:
+        with open(token_file, encoding="utf8") as f:
             token = f.read().strip()
         return token
     except Exception:
diff --git a/scripts/lint.py b/scripts/lint.py
index bf52210c7a75..e8f3acef2dfe 100755
--- a/scripts/lint.py
+++ b/scripts/lint.py
@@ -812,7 +812,7 @@ def rewrite(self, new_lines: list[str]) -> None:
         """Rewrite the contents of the file."""
         if new_lines != self.lines:
             self.lines = new_lines
-            with open(self.path, "w") as f:
+            with open(self.path, "w", encoding="utf8") as f:
                 f.writelines(new_lines)
             self._update_content()
             print(f"{self.path} fixed.")
@@ -965,7 +965,7 @@ def lint_example_requirements() -> int:
 
     failed = False
 
-    with open("examples/python/requirements.txt") as f:
+    with open("examples/python/requirements.txt", encoding="utf8") as f:
         lines = f.read().strip().splitlines()
         sorted_lines = lines.copy()
         sorted_lines.sort()
diff --git a/scripts/run_all.py b/scripts/run_all.py
index e27d8f9e726c..19fff88146b6 100755
--- a/scripts/run_all.py
+++ b/scripts/run_all.py
@@ -217,17 +217,15 @@ def run_sdk_build() -> None:
 
 def run_viewer_build(web: bool) -> None:
     print("Building Rerun Viewer…")
-    returncode = subprocess.Popen(
-        [
-            "cargo",
-            "build",
-            "-p",
-            "rerun-cli",
-            "--no-default-features",
-            "--features=web_viewer" if web else "--features=native_viewer",
-            "--quiet",
-        ]
-    ).wait()
+    returncode = subprocess.Popen([
+        "cargo",
+        "build",
+        "-p",
+        "rerun-cli",
+        "--no-default-features",
+        "--features=web_viewer" if web else "--features=native_viewer",
+        "--quiet",
+    ]).wait()
     assert returncode == 0, f"process exited with error code {returncode}"
 
 
@@ -240,13 +238,11 @@ def run_install_requirements(examples: list[str]) -> None:
             args.extend(["-r", req])
 
     print("Installing examples requirements…")
-    returncode = subprocess.Popen(
-        [
-            "pip",
-            "install",
-            *args,
-        ]
-    ).wait()
+    returncode = subprocess.Popen([
+        "pip",
+        "install",
+        *args,
+    ]).wait()
     assert returncode == 0, f"process exited with error code {returncode}"
 
 
diff --git a/scripts/zombie_todos.py b/scripts/zombie_todos.py
index 8184861f49c1..369d4f1f4d52 100755
--- a/scripts/zombie_todos.py
+++ b/scripts/zombie_todos.py
@@ -78,7 +78,7 @@ async def fetch_issues():
 def check_file(path: str) -> bool:
     ok = True
     closed_issues = set(issues)
-    with open(path) as f:
+    with open(path, encoding="utf8") as f:
         for i, line in enumerate(f.readlines()):
             matches = internal_issue_number_pattern.search(line)
             if matches is not None:
diff --git a/tests/python/annotation_context_ui_stress/annotation_context_ui_stress.py b/tests/python/annotation_context_ui_stress/annotation_context_ui_stress.py
index 829afac6dc20..a90dde844779 100644
--- a/tests/python/annotation_context_ui_stress/annotation_context_ui_stress.py
+++ b/tests/python/annotation_context_ui_stress/annotation_context_ui_stress.py
@@ -13,20 +13,18 @@
 rr.script_setup(args, "rerun_example_annotation_context_ui_stress")
 
 
-annotation_context = rr.AnnotationContext(
-    [
-        ClassDescription(
-            info=(0, "class_info", (255, 0, 0)),
-            keypoint_annotations=[(i, f"keypoint {i}", (255, 255 - i, 0)) for i in range(100)],
-            keypoint_connections=[(i, 99 - i) for i in range(50)],
-        ),
-        ClassDescription(
-            info=(1, "another_class_info", (255, 0, 255)),
-            keypoint_annotations=[(i, f"keypoint {i}", (255, 255, i)) for i in range(100)],
-            keypoint_connections=[(0, 2), (1, 2), (2, 3)],
-        ),
-    ]
-)
+annotation_context = rr.AnnotationContext([
+    ClassDescription(
+        info=(0, "class_info", (255, 0, 0)),
+        keypoint_annotations=[(i, f"keypoint {i}", (255, 255 - i, 0)) for i in range(100)],
+        keypoint_connections=[(i, 99 - i) for i in range(50)],
+    ),
+    ClassDescription(
+        info=(1, "another_class_info", (255, 0, 255)),
+        keypoint_annotations=[(i, f"keypoint {i}", (255, 255, i)) for i in range(100)],
+        keypoint_connections=[(0, 2), (1, 2), (2, 3)],
+    ),
+])
 
 # log two of those to test multi-selection
 rr.log("annotation1", annotation_context)
diff --git a/tests/python/plot_dashboard_stress/main.py b/tests/python/plot_dashboard_stress/main.py
index 26f230f7997a..32c0a536bb1e 100755
--- a/tests/python/plot_dashboard_stress/main.py
+++ b/tests/python/plot_dashboard_stress/main.py
@@ -115,7 +115,7 @@ def main() -> None:
         if total_elapsed >= 1.0:
             print(
                 f"logged {total_num_scalars} scalars over {round(total_elapsed, 3)}s \
-(freq={round(total_num_scalars/total_elapsed, 3)}Hz, expected={round(expected_total_freq, 3)}Hz, \
+(freq={round(total_num_scalars / total_elapsed, 3)}Hz, expected={round(expected_total_freq, 3)}Hz, \
 load={round(max_load * 100.0, 3)}%)"
             )
 
@@ -145,7 +145,7 @@ def main() -> None:
     total_elapsed = time.time() - total_start_time
     print(
         f"logged {total_num_scalars} scalars over {round(total_elapsed, 3)}s \
-(freq={round(total_num_scalars/total_elapsed, 3)}Hz, expected={round(expected_total_freq, 3)}Hz, \
+(freq={round(total_num_scalars / total_elapsed, 3)}Hz, expected={round(expected_total_freq, 3)}Hz, \
 load={round(max_load * 100.0, 3)}%)"
     )
 
diff --git a/tests/python/release_checklist/main.py b/tests/python/release_checklist/main.py
index b34ba2a7605a..44184dc272f0 100755
--- a/tests/python/release_checklist/main.py
+++ b/tests/python/release_checklist/main.py
@@ -20,7 +20,7 @@ def log_checks(args: argparse.Namespace) -> None:
 
 
 def log_readme() -> None:
-    with open(join(dirname(__file__), "README.md")) as f:
+    with open(join(dirname(__file__), "README.md"), encoding="utf8") as f:
         rr.log("readme", rr.TextDocument(f.read(), media_type=rr.MediaType.MARKDOWN), static=True)
 
 
diff --git a/tests/python/roundtrips/annotation_context/main.py b/tests/python/roundtrips/annotation_context/main.py
index d1e4be862327..62766f4b68c1 100755
--- a/tests/python/roundtrips/annotation_context/main.py
+++ b/tests/python/roundtrips/annotation_context/main.py
@@ -11,16 +11,14 @@
 
 
 def main() -> None:
-    annotation_context = rr.AnnotationContext(
-        [
-            (1, "hello"),
-            ClassDescription(
-                info=(2, "world", [3, 4, 5]),
-                keypoint_annotations=[(17, "head"), (42, "shoulders")],
-                keypoint_connections=[(1, 2), (3, 4)],
-            ),
-        ]
-    )
+    annotation_context = rr.AnnotationContext([
+        (1, "hello"),
+        ClassDescription(
+            info=(2, "world", [3, 4, 5]),
+            keypoint_annotations=[(17, "head"), (42, "shoulders")],
+            keypoint_connections=[(1, 2), (3, 4)],
+        ),
+    ])
 
     parser = argparse.ArgumentParser(description="Logs rich data using the Rerun SDK.")
     rr.script_add_args(parser)
diff --git a/tests/python/test_api/main.py b/tests/python/test_api/main.py
index e59aa39ea953..b71755817ad9 100755
--- a/tests/python/test_api/main.py
+++ b/tests/python/test_api/main.py
@@ -78,13 +78,11 @@ def run_segmentation() -> None:
 
     rr.log(
         "seg_test",
-        rr.AnnotationContext(
-            [
-                rr.AnnotationInfo(13, color=(255, 0, 0)),
-                (42, "label2", (0, 255, 0)),
-                rr.AnnotationInfo(99, label="label3"),
-            ]
-        ),
+        rr.AnnotationContext([
+            rr.AnnotationInfo(13, color=(255, 0, 0)),
+            (42, "label2", (0, 255, 0)),
+            rr.AnnotationInfo(99, label="label3"),
+        ]),
         static=False,
     )
     rr.log("logs/seg_test_log", rr.TextLog("label1 disappears and everything with label3 is now default colored again"))

From 05855467685b2cacebaed63e9ee040f783b4e529 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Tue, 16 Apr 2024 22:46:39 +0200
Subject: [PATCH 310/508] Fix `pixi py-fmt-check` not running `ruff check`
 (#5995)

### What

Previously, you could pass ci without fixing all ruff lints - `pixi run
py-fmt` would fix them but `pixi run py-fmt-check` wouldn't complain.

Technically none of this is formatting, but we still put it under
formatting since most of it can be fixed automatically and it runs
blazingly fast (very much in contrast to `pixi run py-lint`), both of
which are more typical for formatting.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5995?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5995?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5995)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 pixi.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pixi.toml b/pixi.toml
index 4d261315d216..af43b59ef49f 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -106,7 +106,7 @@ misc-fmt-check = "prettier --check '**/*.{yml,yaml,js,css,html}'"
 
 # Run first ruff fix, then ruff format, order is important see also https://twitter.com/charliermarsh/status/1717229721954799727
 py-fmt = "ruff check --fix --config rerun_py/pyproject.toml . && ruff format --config rerun_py/pyproject.toml ."
-py-fmt-check = "ruff format --check --config rerun_py/pyproject.toml"
+py-fmt-check = "ruff check --config rerun_py/pyproject.toml . && ruff format --check --config rerun_py/pyproject.toml"
 py-lint = "mypy --install-types --non-interactive --no-warn-unused-ignore"
 
 py-build = "maturin develop --manifest-path rerun_py/Cargo.toml --extras=tests"

From 7e0177c165700d6646caa9f3449f58461f9c5404 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= 
Date: Wed, 17 Apr 2024 10:59:32 +0200
Subject: [PATCH 311/508] Setup `rerun.io` deploy from `docs-latest` (#5988)

### What

Right now the workflow for updating docs on `rerun.io` is:
1. Push your changes to some branch in this repository
2. Get the hash of your latest commit
3. Login to our project on Vercel
4. Manually update the `RELEASE_COMMIT` env var
5. Trigger a redeploy of the latest production deployment

After this PR, the new workflow will be:
1. Cherry-pick any docs commits to the `docs-latest` branch

`rerun.io` now always fetches docs from the `docs-latest` branch,
instead of a specific commit hash. Any push to `docs-latest` will
trigger a redeploy of the website.

The release workflow has been updated to no longer deploy the website,
and instead only update the `RELEASE_VERSION` env var.

This PR also contains a refactor of the `deploy-vercel` action, removing
some code duplication and simplifying its usage locally through
`manual.mjs`.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5988?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5988?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5988)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .github/actions/deploy-vercel/index.mjs       |  32 --
 .github/actions/deploy-vercel/manual.mjs      |  48 ---
 .github/actions/deploy-vercel/preview.mjs     |  49 ---
 .github/actions/deploy-vercel/production.mjs  |  68 ----
 .github/actions/deploy-vercel/test.mjs        |  38 ---
 .../{deploy-vercel => vercel}/action.yml      |   8 +-
 .../vercel/commands/deploy-preview.mjs        |  36 +++
 .../vercel/commands/deploy-production.mjs     |  23 ++
 .../actions/vercel/commands/update-env.mjs    |  20 ++
 .github/actions/vercel/index.mjs              |  72 +++++
 .github/actions/vercel/manual.mjs             |  73 +++++
 .../{deploy-vercel => vercel}/util.mjs        |  24 +-
 .../{deploy-vercel => vercel}/vercel.mjs      | 303 ++++++++++--------
 .github/workflows/on_push_docs.yml            |  25 ++
 .github/workflows/release.yml                 |   6 +-
 .github/workflows/reusable_deploy_docs.yml    |   9 +-
 .../reusable_deploy_landing_preview.yml       |   7 +-
 docs/README.md                                |   8 +
 18 files changed, 450 insertions(+), 399 deletions(-)
 delete mode 100644 .github/actions/deploy-vercel/index.mjs
 delete mode 100755 .github/actions/deploy-vercel/manual.mjs
 delete mode 100644 .github/actions/deploy-vercel/preview.mjs
 delete mode 100644 .github/actions/deploy-vercel/production.mjs
 delete mode 100644 .github/actions/deploy-vercel/test.mjs
 rename .github/actions/{deploy-vercel => vercel}/action.yml (91%)
 create mode 100644 .github/actions/vercel/commands/deploy-preview.mjs
 create mode 100644 .github/actions/vercel/commands/deploy-production.mjs
 create mode 100644 .github/actions/vercel/commands/update-env.mjs
 create mode 100644 .github/actions/vercel/index.mjs
 create mode 100755 .github/actions/vercel/manual.mjs
 rename .github/actions/{deploy-vercel => vercel}/util.mjs (77%)
 rename .github/actions/{deploy-vercel => vercel}/vercel.mjs (64%)
 create mode 100644 .github/workflows/on_push_docs.yml

diff --git a/.github/actions/deploy-vercel/index.mjs b/.github/actions/deploy-vercel/index.mjs
deleted file mode 100644
index b306ef8c2fb3..000000000000
--- a/.github/actions/deploy-vercel/index.mjs
+++ /dev/null
@@ -1,32 +0,0 @@
-// @ts-check
-
-import { Client } from "./vercel.mjs";
-import { assert, getInput, getRequiredInput } from "./util.mjs";
-import { deployToProduction } from "./production.mjs";
-import { deployToPreview } from "./preview.mjs";
-
-// These inputs are defined in `action.yml`, and should be kept in sync
-const token = getRequiredInput("vercel_token");
-const team = getRequiredInput("vercel_team_name");
-const project = getRequiredInput("vercel_project_name");
-const commit = getRequiredInput("release_commit");
-const target = getRequiredInput("target");
-
-const client = new Client(token);
-
-switch (target) {
-  case "production": {
-    const version = getRequiredInput("release_version");
-    await deployToProduction(client, { team, project, commit, version });
-    break;
-  }
-
-  case "preview": {
-    await deployToPreview(client, { team, project, commit });
-    break;
-  }
-
-  default: {
-    throw new Error(`"target" must be one of: production, preview`);
-  }
-}
diff --git a/.github/actions/deploy-vercel/manual.mjs b/.github/actions/deploy-vercel/manual.mjs
deleted file mode 100755
index 74232ada93cd..000000000000
--- a/.github/actions/deploy-vercel/manual.mjs
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env node
-
-// Manually run the deployment:
-//
-//   node manual.mjs \
-//     --token VERCEL_TOKEN \
-//     --team rerun \
-//     --project landing \
-//     --commit RELEASE_COMMIT
-//
-
-import { execSync } from "node:child_process";
-import { parseArgs } from "node:util";
-import { fileURLToPath } from "node:url";
-import path from "node:path";
-import { assert } from "./util.mjs";
-
-const dirname = path.dirname(fileURLToPath(import.meta.url));
-
-/** @type {typeof execSync} */
-const $ = (cmd, opts) => execSync(cmd, { stdio: "inherit", ...opts });
-
-const { token, team, project, commit } = parseArgs({
-  options: {
-    token: { type: "string" },
-    team: { type: "string" },
-    project: { type: "string" },
-    commit: { type: "string" },
-  },
-  strict: true,
-  allowPositionals: false,
-}).values;
-assert(token, "missing `--token`");
-assert(team, "missing `--team`");
-assert(project, "missing `--project`");
-assert(commit, "missing `--commit`");
-
-$("node index.mjs", {
-  cwd: dirname,
-  env: {
-    ...process.env,
-    INPUT_VERCEL_TOKEN: token,
-    INPUT_VERCEL_TEAM_NAME: team,
-    INPUT_VERCEL_PROJECT_NAME: project,
-    INPUT_RELEASE_COMMIT: commit,
-  },
-});
-
diff --git a/.github/actions/deploy-vercel/preview.mjs b/.github/actions/deploy-vercel/preview.mjs
deleted file mode 100644
index 1ff791694d98..000000000000
--- a/.github/actions/deploy-vercel/preview.mjs
+++ /dev/null
@@ -1,49 +0,0 @@
-// @ts-check
-
-import { assert, info, setOutput } from "./util.mjs";
-import { Client } from "./vercel.mjs";
-
-/**
- *
- * @param {Client} client
- * @param {{
- *   team: string;
- *   project: string;
- *   commit: string;
- * }} options
- */
-export async function deployToPreview(client, options) {
-  info`Fetching team "${options.team}"`;
-  const availableTeams = await client.teams();
-  assert(availableTeams, `failed to get team "${options.team}"`);
-  const team = availableTeams.find((team) => team.name === options.team);
-  assert(team, `failed to get team "${options.team}"`);
-
-  info`Fetching project "${options.project}"`;
-  const projectsInTeam = await client.projects(team.id);
-  const project = projectsInTeam.find(
-    (project) => project.name === options.project,
-  );
-  assert(project, `failed to get project "${options.project}"`);
-
-  info`Fetching latest production deployment`;
-  const productionDeployments = await client.deployments(team.id, project.id);
-  const latestProductionDeployment = productionDeployments[0];
-  assert(
-    latestProductionDeployment,
-    `failed to get latest production deployment`,
-  );
-
-  info`Deploying preview with RELEASE_COMMIT=${options.commit}`;
-  const { url } = await client.deployPreviewFrom(
-    team.id,
-    latestProductionDeployment.uid,
-    "landing-preview",
-    {
-      RELEASE_COMMIT: options.commit,
-      IS_PR_PREVIEW: "true",
-    },
-  );
-
-  setOutput("vercel_preview_url", url);
-}
diff --git a/.github/actions/deploy-vercel/production.mjs b/.github/actions/deploy-vercel/production.mjs
deleted file mode 100644
index f73b462850a4..000000000000
--- a/.github/actions/deploy-vercel/production.mjs
+++ /dev/null
@@ -1,68 +0,0 @@
-// @ts-check
-
-import { assert, info } from "./util.mjs";
-import { Client } from "./vercel.mjs";
-
-/**
- *
- * @param {Client} client
- * @param {{
- *   team: string;
- *   project: string;
- *   commit: string;
- *   version: string;
- * }} options
- */
-export async function deployToProduction(client, options) {
-  info`Fetching team "${options.team}"`;
-  const availableTeams = await client.teams();
-  assert(availableTeams, `failed to get team "${options.team}"`);
-  const team = availableTeams.find((team) => team.name === options.team);
-  assert(team, `failed to get team "${options.team}"`);
-
-  info`Fetching project "${options.project}"`;
-  const projectsInTeam = await client.projects(team.id);
-  const project = projectsInTeam.find(
-    (project) => project.name === options.project,
-  );
-  assert(project, `failed to get project "${options.project}"`);
-
-  info`Fetching latest production deployment`;
-  const productionDeployments = await client.deployments(team.id, project.id);
-  const latestProductionDeployment = productionDeployments[0];
-  assert(
-    latestProductionDeployment,
-    `failed to get latest production deployment`,
-  );
-
-  const environment = await client.envs(team.id, project.id);
-  const RELEASE_COMMIT_KEY = "RELEASE_COMMIT";
-  const RELEASE_VERSION_KEY = "RELEASE_VERSION";
-
-  info`Fetching "${RELEASE_COMMIT_KEY}" env var`;
-  const releaseCommitEnv = environment.find(
-    (env) => env.key === RELEASE_COMMIT_KEY,
-  );
-  assert(releaseCommitEnv, `failed to get "${RELEASE_COMMIT_KEY}" env var`);
-
-  info`Fetching "${RELEASE_VERSION_KEY}" env var`;
-  const releaseVersionEnv = environment.find(
-    (env) => env.key === RELEASE_VERSION_KEY,
-  );
-  assert(releaseVersionEnv, `failed to get "${RELEASE_VERSION_KEY}" env var`);
-
-  info`Setting "${RELEASE_COMMIT_KEY}" env to "${options.commit}"`;
-  await client.setEnv(team.id, project.id, releaseCommitEnv.id, {
-    key: RELEASE_COMMIT_KEY,
-    value: options.commit,
-  });
-
-  info`Setting "${RELEASE_VERSION_KEY}" env to "${options.version}"`;
-  await client.setEnv(team.id, project.id, releaseVersionEnv.id, {
-    key: RELEASE_VERSION_KEY,
-    value: options.version,
-  });
-
-  info`Triggering redeploy`;
-  await client.redeploy(team.id, latestProductionDeployment.uid, "landing");
-}
diff --git a/.github/actions/deploy-vercel/test.mjs b/.github/actions/deploy-vercel/test.mjs
deleted file mode 100644
index a4d63265d3be..000000000000
--- a/.github/actions/deploy-vercel/test.mjs
+++ /dev/null
@@ -1,38 +0,0 @@
-// @ts-check
-
-import { Client } from "./vercel.mjs";
-import { assert, info } from "./util.mjs";
-
-const client = new Client("NzuZ9WBTnfUGiwHrhd7mit2E");
-
-const teamName = "rerun";
-const projectName = "landing";
-
-info`Fetching team "${teamName}"`;
-const availableTeams = await client.teams();
-assert(availableTeams, `failed to get team "${teamName}"`);
-const team = availableTeams.find((team) => team.name === teamName);
-assert(team, `failed to get team "${teamName}"`);
-
-info`Fetching project "${projectName}"`;
-const projectsInTeam = await client.projects(team.id);
-const project = projectsInTeam.find((project) => project.name === projectName);
-assert(project, `failed to get project "${projectName}"`);
-
-info`Fetching latest production deployment`;
-const productionDeployments = await client.deployments(team.id, project.id);
-const latestProductionDeployment = productionDeployments[0];
-assert(
-  latestProductionDeployment,
-  `failed to get latest production deployment`,
-);
-
-const response = await client.deployPreviewFrom(
-  team.id,
-  latestProductionDeployment.uid,
-  "rerun-custom-preview-test",
-  {
-    RELEASE_COMMIT: "main",
-  },
-);
-console.log(response);
diff --git a/.github/actions/deploy-vercel/action.yml b/.github/actions/vercel/action.yml
similarity index 91%
rename from .github/actions/deploy-vercel/action.yml
rename to .github/actions/vercel/action.yml
index c33cc346b7e5..727ea7dbc552 100644
--- a/.github/actions/deploy-vercel/action.yml
+++ b/.github/actions/vercel/action.yml
@@ -22,10 +22,14 @@ inputs:
     description: "Vercel project name to update and redeploy"
     type: string
     required: true
+  command:
+    description: "`deploy` or `update-env`"
+    type: string
+    required: true
   release_commit:
     description: "Release commit to update the deployment to"
     type: string
-    required: true
+    required: false
   release_version:
     description: "Which release version to update the deployment to"
     type: string
@@ -33,7 +37,7 @@ inputs:
   target:
     description: "Which Vercel environment to deploy to"
     type: string
-    required: true
+    required: false
 
 runs:
   using: "node20"
diff --git a/.github/actions/vercel/commands/deploy-preview.mjs b/.github/actions/vercel/commands/deploy-preview.mjs
new file mode 100644
index 000000000000..c66a46b59a03
--- /dev/null
+++ b/.github/actions/vercel/commands/deploy-preview.mjs
@@ -0,0 +1,36 @@
+// @ts-check
+
+import { setOutput } from "../util.mjs";
+import { Client } from "../vercel.mjs";
+
+/**
+ *
+ * @param {Client} client
+ * @param {{
+ *   team: string;
+ *   project: string;
+ *   commit: string | null;
+ *   version: string | null;
+ * }} options
+ */
+export async function deployToPreview(client, options) {
+  const project = await client.project(options.team, options.project);
+  const deployment = await project.latestProductionDeployment();
+
+  let line = `Deploying preview`;
+  if (options.commit) line += ` RELEASE_COMMIT=${options.commit}`;
+  if (options.version) line += ` RELEASE_VERSION=${options.version}`;
+  console.log(line);
+
+  const env = { IS_PR_PREVIEW: "true" };
+  if (options.commit) env["RELEASE_COMMIT"] = options.commit;
+  if (options.version) env["RELEASE_VERSION"] = options.version;
+
+  const { url } = await project.deployPreviewFrom(
+    deployment.uid,
+    "landing-preview",
+    env,
+  );
+
+  setOutput("vercel_preview_url", url);
+}
diff --git a/.github/actions/vercel/commands/deploy-production.mjs b/.github/actions/vercel/commands/deploy-production.mjs
new file mode 100644
index 000000000000..56541a13a50b
--- /dev/null
+++ b/.github/actions/vercel/commands/deploy-production.mjs
@@ -0,0 +1,23 @@
+// @ts-check
+
+import { Client } from "../vercel.mjs";
+
+/**
+ *
+ * @param {Client} client
+ * @param {{
+ *   team: string;
+ *   project: string;
+ *   commit: string | null;
+ *   version: string | null;
+ * }} options
+ */
+export async function deployToProduction(client, options) {
+  const project = await client.project(options.team, options.project);
+  const deployment = await project.latestProductionDeployment();
+
+  if (options.commit) await project.setEnv("RELEASE_COMMIT", options.commit);
+  if (options.version) await project.setEnv("RELEASE_VERSION", options.version);
+
+  await project.redeploy(deployment.uid, "landing");
+}
diff --git a/.github/actions/vercel/commands/update-env.mjs b/.github/actions/vercel/commands/update-env.mjs
new file mode 100644
index 000000000000..418aa4fc591d
--- /dev/null
+++ b/.github/actions/vercel/commands/update-env.mjs
@@ -0,0 +1,20 @@
+// @ts-check
+
+import { Client } from "../vercel.mjs";
+
+/**
+ *
+ * @param {Client} client
+ * @param {{
+ *   team: string;
+ *   project: string;
+ *   commit: string | null;
+ *   version: string | null;
+ * }} options
+ */
+export async function updateProjectEnv(client, options) {
+  const project = await client.project(options.team, options.project);
+
+  if (options.commit) await project.setEnv("RELEASE_COMMIT", options.commit);
+  if (options.version) await project.setEnv("RELEASE_VERSION", options.version);
+}
diff --git a/.github/actions/vercel/index.mjs b/.github/actions/vercel/index.mjs
new file mode 100644
index 000000000000..810aa3037f2d
--- /dev/null
+++ b/.github/actions/vercel/index.mjs
@@ -0,0 +1,72 @@
+// @ts-check
+
+import { Client } from "./vercel.mjs";
+import { getInput, getRequiredInput } from "./util.mjs";
+import { deployToProduction } from "./commands/deploy-production.mjs";
+import { deployToPreview } from "./commands/deploy-preview.mjs";
+import { updateProjectEnv } from "./commands/update-env.mjs";
+
+// All inputs retrieved via `getInput` are defined in `action.yml`, and should be kept in sync
+
+const client = new Client(getRequiredInput("vercel_token"));
+
+const command = getRequiredInput("command");
+const team = getRequiredInput("vercel_team_name");
+const project = getRequiredInput("vercel_project_name");
+
+switch (command) {
+  case "deploy":
+    await deploy(client, team, project);
+    break;
+  case "update-env":
+    await updateEnv(client, team, project);
+    break;
+  default:
+    throw new Error(`"command" must be one of: deploy, update-env`);
+}
+
+/**
+ * @param {Client} client
+ * @param {string} team
+ * @param {string} project
+ */
+async function deploy(client, team, project) {
+  const target = getRequiredInput("target");
+  switch (target) {
+    case "production": {
+      const commit = getRequiredInput("release_commit");
+      const version = getRequiredInput("release_version");
+      await deployToProduction(client, { team, project, commit, version });
+      break;
+    }
+
+    case "preview": {
+      const commit = getRequiredInput("release_commit");
+      const version = getInput("release_version");
+      await deployToPreview(client, { team, project, commit, version });
+      break;
+    }
+
+    default: {
+      throw new Error(`"target" must be one of: production, preview`);
+    }
+  }
+}
+
+/**
+ * @param {Client} client
+ * @param {string} team
+ * @param {string} project
+ */
+async function updateEnv(client, team, project) {
+  const commit = getInput("release_commit");
+  const version = getInput("release_version");
+
+  if (!commit && !version) {
+    throw new Error(
+      `one of "release_commit", "release_version" must be specified`,
+    );
+  }
+
+  await updateProjectEnv(client, { team, project, commit, version });
+}
diff --git a/.github/actions/vercel/manual.mjs b/.github/actions/vercel/manual.mjs
new file mode 100755
index 000000000000..aebe273cc9c9
--- /dev/null
+++ b/.github/actions/vercel/manual.mjs
@@ -0,0 +1,73 @@
+#!/usr/bin/env node
+
+// Convenience script for running `index.mjs` locally,
+// passing in inputs as CLI args instead of env vars.
+
+// @ts-check
+
+// Manually run the deployment:
+//
+//   # Redeploy `landing`:
+//   node manual.mjs \
+//     --command deploy \
+//     --token VERCEL_TOKEN \
+//     --team rerun \
+//     --project landing \
+//     --target production \
+//     --commit RELEASE_COMMIT \
+//     --version RELEASE_VERSION
+//
+//   # Deploy a preview of `landing` with a `RELEASE_COMMIT` override:
+//   node manual.mjs \
+//     --command deploy \
+//     --token VERCEL_TOKEN \
+//     --team rerun \
+//     --project landing \
+//     --target preview \
+//     --commit RELEASE_COMMIT
+//
+//   # Only update env:
+//   node manual.mjs \
+//     --command update-env \
+//     --token VERCEL_TOKEN \
+//     --team rerun \
+//     --project landing \
+//     --commit RELEASE_COMMIT \
+//     --version RELEASE_VERSION
+//
+
+import { execSync } from "node:child_process";
+import { parseArgs } from "node:util";
+import { fileURLToPath } from "node:url";
+import path from "node:path";
+
+try {
+  const { command, token, team, project, target, commit, version } = parseArgs({
+    options: {
+      command: { type: "string" },
+      token: { type: "string" },
+      team: { type: "string" },
+      project: { type: "string" },
+      target: { type: "string" },
+      commit: { type: "string" },
+      version: { type: "string" },
+    },
+    strict: true,
+    allowPositionals: false,
+  }).values;
+
+  const env = { ...process.env, MANUAL_RUN: "true" };
+  if (command) env["INPUT_COMMAND"] = command;
+  if (token) env["INPUT_VERCEL_TOKEN"] = token;
+  if (team) env["INPUT_VERCEL_TEAM_NAME"] = team;
+  if (project) env["INPUT_VERCEL_PROJECT_NAME"] = project;
+  if (target) env["INPUT_TARGET"] = target;
+  if (commit) env["INPUT_RELEASE_COMMIT"] = commit;
+  if (version) env["INPUT_RELEASE_VERSION"] = version;
+
+  const cwd = path.dirname(fileURLToPath(import.meta.url));
+  execSync("node index.mjs", { cwd, env, stdio: "inherit" });
+} catch (err) {
+  console.error(err.message);
+  process.exit(1);
+}
diff --git a/.github/actions/deploy-vercel/util.mjs b/.github/actions/vercel/util.mjs
similarity index 77%
rename from .github/actions/deploy-vercel/util.mjs
rename to .github/actions/vercel/util.mjs
index 24bb3d76db98..8e8a81fa9abc 100644
--- a/.github/actions/deploy-vercel/util.mjs
+++ b/.github/actions/vercel/util.mjs
@@ -3,23 +3,6 @@
 import { appendFileSync } from "fs";
 import os from "os";
 
-/**
- * Log a message with level `INFO`
- *
- * @param {TemplateStringsArray} strings
- * @param {any[]} values
- */
-export function info(strings, ...values) {
-  let out = "";
-  for (let i = 0; i < strings.length; i++) {
-    out += strings[i];
-    if (i < values.length) {
-      out += values[i].toString();
-    }
-  }
-  console.info(out);
-}
-
 /**
  * Return a GitHub Actions input, returning `null` if it was not set.
  *
@@ -50,8 +33,13 @@ export function getRequiredInput(name) {
  * @param {string} value
  */
 export function setOutput(key, value) {
+  const s = `${key}=${value}${os.EOL}`;
+  if (process.env["MANUAL_RUN"]) {
+    console.log(s);
+    return;
+  }
   const outputFile = /** @type {string} */ (process.env["GITHUB_OUTPUT"]);
-  appendFileSync(outputFile, `${key}=${value}${os.EOL}`);
+  appendFileSync(outputFile, s);
 }
 
 /**
diff --git a/.github/actions/deploy-vercel/vercel.mjs b/.github/actions/vercel/vercel.mjs
similarity index 64%
rename from .github/actions/deploy-vercel/vercel.mjs
rename to .github/actions/vercel/vercel.mjs
index e69aab2a5fcb..1550c4ef4635 100644
--- a/.github/actions/deploy-vercel/vercel.mjs
+++ b/.github/actions/vercel/vercel.mjs
@@ -6,8 +6,8 @@ import { assert } from "./util.mjs";
  * @typedef {Record} Headers
  * @typedef {object} Body
  *
- * @typedef {{ id: string; name: string }} Team
- * @typedef {{ id: string; name: string }} Project
+ * @typedef {{ id: string; name: string }} TeamInfo
+ * @typedef {{ id: string; name: string }} ProjectInfo
  * @typedef {{ uid: string }} Deployment
  * @typedef {{ id: string, key: string, value: string }} Env
  *
@@ -15,6 +15,153 @@ import { assert } from "./util.mjs";
  * @typedef {"encrypted" | "secret"} EnvType
  */
 
+export class Project {
+  constructor(
+    /** @type {Client} */ client,
+    /** @type {TeamInfo} */ team,
+    /** @type {ProjectInfo} */ project,
+  ) {
+    this.client = client;
+    this.team = team;
+    this.project = project;
+  }
+
+  /**
+   * Return deployments under the current team and project.
+   *
+   * The endpoint used is a paginated one, but this call does not support pagination,
+   * and only returns the first 20 results.
+   *
+   * The results are sorted by their created date, so the latest deployment
+   * for the given `target` is at index `0`.
+   * @param {"production" | "preview" | "development"} target
+   * @returns {Promise}
+   */
+  async deployments(target = "production") {
+    const response = await this.client.get("v6/deployments", {
+      teamId: this.team.id,
+      projectId: this.project.id,
+      target,
+      sort: "created",
+    });
+    assert(
+      "deployments" in response,
+      () => `failed to get deployments: ${JSON.stringify(response)}`,
+    );
+    return response.deployments;
+  }
+
+  async latestProductionDeployment() {
+    console.log("get latest production deployment");
+    const productionDeployments = await this.deployments("production");
+    const latestProductionDeployment = productionDeployments[0];
+    assert(
+      latestProductionDeployment,
+      `failed to get latest production deployment`,
+    );
+    return latestProductionDeployment;
+  }
+
+  /**
+   * Return environment variables available to the current team and project.
+   *
+   * @returns {Promise}
+   */
+  async envs() {
+    const response = await this.client.get(
+      `v9/projects/${this.project.id}/env`,
+      {
+        teamId: this.team.id,
+      },
+    );
+    assert(
+      "envs" in response,
+      () => `failed to get environment variables: ${JSON.stringify(response)}`,
+    );
+    return response.envs;
+  }
+
+  /**
+   * Set an environment variable (`envId`), making it available to the current team and project.
+   *
+   * @param {string} key
+   * @param {string} value
+   * @param {EnvTarget[]} [target]
+   * @param {EnvType} [type]
+   * @returns {Promise}
+   */
+  async setEnv(
+    key,
+    value,
+    target = ["production", "preview", "development"],
+    type = "encrypted",
+  ) {
+    console.log(`set env ${key}=${value} (target: ${target}, type: ${type})`);
+    const env = await this.envs().then((envs) =>
+      envs.find((env) => env.key === key),
+    );
+    assert(env);
+    return this.client.patch(
+      `v9/projects/${this.project.id}/env/${env.id}`,
+      { gitBranch: null, key, target, type, value },
+      { teamId: this.team.id },
+    );
+  }
+
+  /**
+   * Trigger a redeploy of an existing deployment (`deploymentId`)
+   * of a project (`name`) under a specific team (`teamId`).
+   *
+   * The resulting deployment will be set as the current production deployment.
+   *
+   * @param {string} deploymentId
+   * @param {string} name
+   * @returns {Promise}
+   */
+  async redeploy(deploymentId, name) {
+    console.log(`redeploy ${name} (id: ${deploymentId})`);
+    return this.client.post(
+      `v13/deployments`,
+      {
+        deploymentId,
+        meta: { action: "redeploy" },
+        name,
+        target: "production",
+      },
+      { teamId: this.team.id, forceNew: "1" },
+    );
+  }
+
+  /**
+   * Trigger a preview deploy using the files of an existing deployment (`deploymentId`).
+   *
+   * @param {string} deploymentId
+   * @param {string} name
+   * @param {Record} [env]
+   * @returns {Promise}
+   */
+  async deployPreviewFrom(deploymentId, name, env) {
+    console.log(
+      `deploy preview from ${name} (id: ${deploymentId}) with env:`,
+      env,
+    );
+    // `target` not being set means "preview"
+    const body = {
+      deploymentId,
+      meta: { action: "redeploy" },
+      name,
+    };
+    if (env) {
+      body.env = env;
+      body.build = { env };
+    }
+    return this.client.post(`v13/deployments`, body, {
+      teamId: this.team.id,
+      forceNew: "1",
+    });
+  }
+}
+
 /**
  * Vercel API Client
  */
@@ -47,7 +194,8 @@ export class Client {
    * @returns {Promise}
    */
   async get(endpoint, params, headers) {
-    return await fetch(this.url(endpoint, params), {
+    const url = this.url(endpoint, params);
+    return fetch(url, {
       headers: {
         Authorization: `Bearer ${this.token}`,
         ...headers,
@@ -66,7 +214,8 @@ export class Client {
    * @returns {Promise}
    */
   async post(endpoint, body, params, headers) {
-    return await fetch(this.url(endpoint, params), {
+    const url = this.url(endpoint, params);
+    return fetch(url, {
       method: "POST",
       headers: {
         Authorization: `Bearer ${this.token}`,
@@ -88,7 +237,8 @@ export class Client {
    * @returns {Promise}
    */
   async patch(endpoint, body, params, headers) {
-    return await fetch(this.url(endpoint, params), {
+    const url = this.url(endpoint, params);
+    return fetch(url, {
       method: "PATCH",
       headers: {
         Authorization: `Bearer ${this.token}`,
@@ -102,7 +252,7 @@ export class Client {
   /**
    * Return all available teams for the user authorized by this client's token.
    *
-   * @returns {Promise}
+   * @returns {Promise}
    */
   async teams() {
     const response = await this.get("v2/teams");
@@ -118,7 +268,7 @@ export class Client {
    * for the user authorized by this client's token.
    *
    * @param {string} teamId
-   * @returns {Promise}
+   * @returns {Promise}
    */
   async projects(teamId) {
     const response = await this.get("v9/projects", { teamId });
@@ -130,137 +280,20 @@ export class Client {
   }
 
   /**
-   * Return deployments under a given team (`teamId`) and project (`projectId`).
-   *
-   * The endpoint used is a paginated one, but this call does not support pagination,
-   * and only returns the first 20 results.
-   *
-   * The results are sorted by their created date, so the latest deployment
-   * for the given `target` is at index `0`.
-   *
-   * @param {string} teamId
-   * @param {string} projectId
-   * @param {"production" | "preview" | "development"} target
-   * @returns {Promise}
-   */
-  async deployments(teamId, projectId, target = "production") {
-    const response = await this.get("v6/deployments", {
-      teamId,
-      projectId,
-      target,
-      sort: "created",
-    });
-    assert(
-      "deployments" in response,
-      () => `failed to get deployments: ${JSON.stringify(response)}`,
-    );
-    return response.deployments;
-  }
-
-  /**
-   * Return environment variables available to a project (`projectId`) under a team (`teamId`).
    *
-   * @param {string} teamId
-   * @param {string} projectId
-   * @returns {Promise}
+   * @param {string} teamName
+   * @param {string} projectName
    */
-  async envs(teamId, projectId) {
-    const response = await this.get(`v9/projects/${projectId}/env`, { teamId });
-    assert(
-      "envs" in response,
-      () => `failed to get environment variables: ${JSON.stringify(response)}`,
-    );
-    return response.envs;
-  }
+  async project(teamName, projectName) {
+    console.log(`get project ${teamName}/${projectName}`);
 
-  /**
-   * Get the decrypted version of an environment variable (`envId`)
-   * available to a project (`projectId`) under a team (`teamId`).
-   *
-   * @param {string} teamId
-   * @param {string} projectId
-   * @param {string} envId
-   * @returns {Promise}
-   */
-  async getEnvDecrypted(teamId, projectId, envId) {
-    return await this.get(`v9/projects/${projectId}/env/${envId}`, {
-      teamId,
-      decrypt: "true",
-    });
-  }
+    const teams = await this.teams();
+    const team = teams.find((team) => team.name === teamName);
+    assert(team);
+    const projects = await this.projects(team.id);
+    const project = projects.find((project) => project.name === projectName);
+    assert(project);
 
-  /**
-   * Set an environment variable (`envId`), making it available to a project `projectId`
-   * under a team (`teamId`).
-   *
-   * @param {string} teamId
-   * @param {string} projectId
-   * @param {string} envId
-   * @param {{ key: string, target?: EnvTarget[], type?: EnvType, value: string }} param3
-   * @returns {Promise}
-   */
-  async setEnv(
-    teamId,
-    projectId,
-    envId,
-    {
-      key,
-      target = ["production", "preview", "development"],
-      type = "encrypted",
-      value,
-    },
-  ) {
-    return await this.patch(
-      `v9/projects/${projectId}/env/${envId}`,
-      { gitBranch: null, key, target, type, value },
-      { teamId },
-    );
-  }
-
-  /**
-   * Trigger a redeploy of an existing deployment (`deploymentId`)
-   * of a project (`name`) under a specific team (`teamId`).
-   *
-   * The resulting deployment will be set as the current production deployment.
-   *
-   * @param {string} teamId
-   * @param {string} deploymentId
-   * @param {string} name
-   * @returns {Promise}
-   */
-  async redeploy(teamId, deploymentId, name) {
-    return await this.post(
-      `v13/deployments`,
-      {
-        deploymentId,
-        meta: { action: "redeploy" },
-        name,
-        target: "production",
-      },
-      { teamId, forceNew: "1" },
-    );
-  }
-
-  /**
-   * Trigger a preview deploy using the files of an existing deployment (`deploymentId`).
-   *
-   * @param {string} teamId
-   * @param {string} deploymentId
-   * @param {string} name
-   * @param {Record} [env]
-   * @returns {Promise}
-   */
-  async deployPreviewFrom(teamId, deploymentId, name, env) {
-    // `target` not being set means "preview"
-    const body = {
-      deploymentId,
-      meta: { action: "redeploy" },
-      name,
-    };
-    if (env) {
-      body.env = env;
-      body.build = { env };
-    }
-    return await this.post(`v13/deployments`, body, { teamId, forceNew: "1" });
+    return new Project(this, team, project);
   }
 }
diff --git a/.github/workflows/on_push_docs.yml b/.github/workflows/on_push_docs.yml
new file mode 100644
index 000000000000..442e87c8582b
--- /dev/null
+++ b/.github/workflows/on_push_docs.yml
@@ -0,0 +1,25 @@
+name: "Push Docs"
+
+on:
+  push:
+    branches: [docs-latest]
+
+concurrency:
+  group: on-push-docs
+  cancel-in-progress: true
+
+jobs:
+  redeploy-rerun-io:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Re-deploy rerun.io
+        uses: ./.github/actions/vercel
+        with:
+          command: "deploy"
+          vercel_token: ${{ secrets.VERCEL_TOKEN }}
+          vercel_team_name: ${{ vars.VERCEL_TEAM_NAME }}
+          vercel_project_name: ${{ vars.VERCEL_PROJECT_NAME }}
+          release_commit: "docs-latest"
+          target: "production"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 9487b8e3dc97..113d13a09829 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -174,7 +174,7 @@ jobs:
           - If this is an 'alpha' release, you can just merge the pull request.
           - Otherwise:
             - For any added commits, run the release workflow in 'rc' mode again
-            - After testing, run the release workflow in 'release' mode
+            - After testing, _ensure that this PR is mergeable to `main`_, then run the release workflow in 'release' mode
             - Once the final release workflow finishes it will create a GitHub release for you. Then:
               - [ ] Sanity check the build artifacts:
                 - [ ] pip install: does it install and run?
@@ -184,6 +184,7 @@ jobs:
               - [ ] Make sure the [conda feedstock PR](https://github.com/conda-forge/rerun-sdk-feedstock/pulls) gets
               merged. This will be created by the `regro-cf-autotick-bot` once the GitHub release is created.
               - [ ] Update the [google colab notebooks](https://drive.google.com/drive/folders/0AC0q24MFKh3fUk9PVA) to install this version and re-execute the notebook.
+              - [ ] Merge this PR
 
           - [ ] Tests
             - [ ] Windows
@@ -274,6 +275,8 @@ jobs:
       concurrency: ${{ github.ref_name }}
     secrets: inherit
 
+  # Force-pushes `latest` and `docs-latest` to the contents of the release branch.
+  # The push to `docs-latest` also triggers a re-deploy of `rerun.io`.
   update-latest-branch:
     name: "Update Latest Branch"
     if: inputs.release-type == 'final'
@@ -302,6 +305,7 @@ jobs:
           git fetch
           git checkout ${{ github.ref_name }}
           git push --force origin refs/heads/${{ github.ref_name }}:refs/heads/latest
+          git push --force origin refs/heads/${{ github.ref_name }}:refs/heads/docs-latest
 
   github-release:
     name: "GitHub Release"
diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml
index e7e14ca988c0..d38ddf52a5e3 100644
--- a/.github/workflows/reusable_deploy_docs.yml
+++ b/.github/workflows/reusable_deploy_docs.yml
@@ -245,7 +245,7 @@ jobs:
           git fetch
           python3 -m ghp_import -n -p -x docs/cpp/${{ inputs.CPP_DOCS_VERSION_NAME }} rerun_cpp/docs/html/ -m "Update the C++ docs"
 
-  redeploy-rerun-io:
+  update-rerun-io-env:
     runs-on: ubuntu-latest
     if: inputs.UPDATE_LATEST
     steps:
@@ -253,12 +253,11 @@ jobs:
         with:
           ref: ${{ inputs.RELEASE_COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || '') }}
 
-      - name: Re-deploy rerun.io
-        uses: ./.github/actions/deploy-vercel
+      - name: Update Vercel env
+        uses: ./.github/actions/vercel
         with:
+          command: "update-env"
           vercel_token: ${{ secrets.VERCEL_TOKEN }}
           vercel_team_name: ${{ vars.VERCEL_TEAM_NAME }}
           vercel_project_name: ${{ vars.VERCEL_PROJECT_NAME }}
-          release_commit: ${{ inputs.RELEASE_COMMIT }}
           release_version: ${{ inputs.RELEASE_VERSION }}
-          target: "production"
diff --git a/.github/workflows/reusable_deploy_landing_preview.yml b/.github/workflows/reusable_deploy_landing_preview.yml
index e5e9abe85d17..dcdcb165ad5d 100644
--- a/.github/workflows/reusable_deploy_landing_preview.yml
+++ b/.github/workflows/reusable_deploy_landing_preview.yml
@@ -38,9 +38,10 @@ jobs:
           echo "sha=$full_commit" >> "$GITHUB_OUTPUT"
 
       - name: Re-deploy rerun.io
-        id: deploy-vercel
-        uses: ./.github/actions/deploy-vercel
+        id: vercel
+        uses: ./.github/actions/vercel
         with:
+          command: "deploy"
           vercel_token: ${{ secrets.VERCEL_TOKEN }}
           vercel_team_name: ${{ vars.VERCEL_TEAM_NAME }}
           vercel_project_name: ${{ vars.VERCEL_PROJECT_NAME }}
@@ -57,4 +58,4 @@ jobs:
 
             | Commit  | Link  |
             | ------- | ----- |
-            | ${{ steps.get-sha.outputs.sha }} | https://${{ steps.deploy-vercel.outputs.vercel_preview_url }}/docs |
+            | ${{ steps.get-sha.outputs.sha }} | https://${{ steps.vercel.outputs.vercel_preview_url }}/docs |
diff --git a/docs/README.md b/docs/README.md
index 3b0bd54450f4..5a2bd6173fa3 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -14,6 +14,14 @@ The site documentation lives in Markdown files inside [`/content`](./content).
 
 The entry point to the documentation is [`/content/index.md`](./content/index.md).
 
+## Updating the docs
+
+The `rerun.io` docs are built from the contents of the `/docs` directory on the `docs-latest` branch. Any push to `docs-latest` will trigger an automatic redeploy of the website.
+
+Do not push directly to the `docs-latest` branch! To update the docs, either [create a Release](../RELEASES.md), or cherry-pick commits to the `docs-latest` branch _after_ they've been committed to `main`.
+
+⚠ Any commits which are not on `main` and were instead submitted directly to the `docs-latest` branch will be lost the next time we create a release, because the `docs-latest` branch is force-pushed during the release process.
+
 ## Special syntax
 
 ### Frontmatter

From 1544f429159ce11590ba780878200cc213df48fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= 
Date: Wed, 17 Apr 2024 11:13:55 +0200
Subject: [PATCH 312/508] Fix `docs-latest` deploy (#6002)

### What

The `release_version` input was supposed to be not required

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/{{pr.number}})
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .github/actions/vercel/index.mjs | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/.github/actions/vercel/index.mjs b/.github/actions/vercel/index.mjs
index 810aa3037f2d..92f387a0fe3f 100644
--- a/.github/actions/vercel/index.mjs
+++ b/.github/actions/vercel/index.mjs
@@ -8,11 +8,15 @@ import { updateProjectEnv } from "./commands/update-env.mjs";
 
 // All inputs retrieved via `getInput` are defined in `action.yml`, and should be kept in sync
 
-const client = new Client(getRequiredInput("vercel_token"));
-
-const command = getRequiredInput("command");
+const token = getRequiredInput("vercel_token");
 const team = getRequiredInput("vercel_team_name");
 const project = getRequiredInput("vercel_project_name");
+const command = getRequiredInput("command");
+const commit = getInput("release_commit");
+const version = getInput("release_version");
+const target = getInput("target");
+
+const client = new Client(token);
 
 switch (command) {
   case "deploy":
@@ -31,18 +35,13 @@ switch (command) {
  * @param {string} project
  */
 async function deploy(client, team, project) {
-  const target = getRequiredInput("target");
   switch (target) {
     case "production": {
-      const commit = getRequiredInput("release_commit");
-      const version = getRequiredInput("release_version");
       await deployToProduction(client, { team, project, commit, version });
       break;
     }
 
     case "preview": {
-      const commit = getRequiredInput("release_commit");
-      const version = getInput("release_version");
       await deployToPreview(client, { team, project, commit, version });
       break;
     }
@@ -59,9 +58,6 @@ async function deploy(client, team, project) {
  * @param {string} project
  */
 async function updateEnv(client, team, project) {
-  const commit = getInput("release_commit");
-  const version = getInput("release_version");
-
   if (!commit && !version) {
     throw new Error(
       `one of "release_commit", "release_version" must be specified`,

From 271d78884ed48e7030fabdff99e0881e3bf43edb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= 
Date: Wed, 17 Apr 2024 11:22:56 +0200
Subject: [PATCH 313/508] Fix main CI (#6003)

### What

Just passing by

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6003?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6003?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6003)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 scripts/run_python_e2e_test.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/scripts/run_python_e2e_test.py b/scripts/run_python_e2e_test.py
index e3bd74d0ca54..5ddd31a8a727 100755
--- a/scripts/run_python_e2e_test.py
+++ b/scripts/run_python_e2e_test.py
@@ -16,7 +16,6 @@
 import argparse
 import os
 import subprocess
-import sys
 import time
 
 PORT = 9752

From 3e9fa6dfb4231ee7bc1dda07fc8189ec9c1e486b Mon Sep 17 00:00:00 2001
From: Emil Ernerfeldt 
Date: Wed, 17 Apr 2024 13:07:20 +0200
Subject: [PATCH 314/508] Update `cargo-deny` (#5999)

### What

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5999?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5999?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5999)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 Cargo.lock | 14 ++------------
 deny.toml  | 26 +++++++++++++++++---------
 2 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 6047ec37e818..1d54c9a4d249 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2710,15 +2710,14 @@ dependencies = [
 
 [[package]]
 name = "insta"
-version = "1.29.0"
+version = "1.38.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a28d25139df397cbca21408bb742cf6837e04cdbebf1b07b760caf971d6a972"
+checksum = "3eab73f58e59ca6526037208f0e98851159ec1633cf17b6cd2e1f2c3fd5d53cc"
 dependencies = [
  "console",
  "lazy_static",
  "linked-hash-map",
  "similar",
- "yaml-rust",
 ]
 
 [[package]]
@@ -7737,15 +7736,6 @@ version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1dbabb1cbd15a1d6d12d9ed6b35cc6777d4af87ab3ba155ea37215f20beab80c"
 
-[[package]]
-name = "yaml-rust"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
-dependencies = [
- "linked-hash-map",
-]
-
 [[package]]
 name = "zbus"
 version = "3.14.1"
diff --git a/deny.toml b/deny.toml
index dfc8af646a78..c7773eb03dd2 100644
--- a/deny.toml
+++ b/deny.toml
@@ -6,8 +6,10 @@
 # Install: `cargo install cargo-deny`
 # Check: `cargo deny check`.
 
+
 # Note: running just `cargo deny check` without a `--target` can result in
 # false positives due to https://github.com/EmbarkStudios/cargo-deny/issues/324
+[graph]
 targets = [
   { triple = "aarch64-apple-darwin" },
   { triple = "i686-pc-windows-gnu" },
@@ -21,16 +23,19 @@ targets = [
   { triple = "x86_64-unknown-linux-musl" },
   { triple = "x86_64-unknown-redox" },
 ]
+all-features = true
+
 
 [advisories]
-vulnerability = "deny"
-unmaintained = "warn"
-yanked = "deny"
-ignore = []
+version = 2
+ignore = [
+  "RUSTSEC-2023-0081", # TODO(#5998): unmaintained crate "safemem" pulled in by "cargo-run-wasm"
+]
+
 
 [bans]
 multiple-versions = "deny"
-wildcards = "allow" # at least until https://github.com/EmbarkStudios/cargo-deny/issues/241 is fixed
+wildcards = "allow" # We use them for examples
 deny = [
   { name = "cgmath" },      # We use glam
   { name = "cmake" },       # Never again
@@ -69,11 +74,9 @@ skip-tree = [
 
 
 [licenses]
+version = 2
 private = { ignore = true }
-unlicensed = "deny"
-allow-osi-fsf-free = "neither"
-confidence-threshold = 0.92 # We want really high confidence when inferring licenses from text
-copyleft = "deny"
+confidence-threshold = 0.93 # We want really high confidence when inferring licenses from text
 allow = [
   "Apache-2.0 WITH LLVM-exception", # https://spdx.org/licenses/LLVM-exception.html
   "Apache-2.0",                     # https://tldrlegal.com/license/apache-license-2.0-(apache-2.0)
@@ -91,6 +94,7 @@ allow = [
   "Unicode-DFS-2016",               # https://spdx.org/licenses/Unicode-DFS-2016.html
   "Zlib",                           # https://tldrlegal.com/license/zlib-libpng-license-(zlib)
 ]
+exceptions = []
 
 [[licenses.clarify]]
 name = "webpki"
@@ -103,5 +107,9 @@ expression = "MIT AND ISC AND OpenSSL"
 license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }]
 
 
+[sources]
+unknown-registry = "deny"
+unknown-git = "deny"
+
 [sources.allow-org]
 github = ["emilk", "rerun-io"]

From 9d858261204c6163c68aebcc46e8e7e279fe8109 Mon Sep 17 00:00:00 2001
From: Clement Rey 
Date: Wed, 17 Apr 2024 13:27:09 +0200
Subject: [PATCH 315/508] Fix `compare_snippet_output.py` by including `cv2` in
 pixi's env (#6000)

Before:
```
Traceback (most recent call last):
  File "/home/cmc/dev/rerun-io/rerun/docs/snippets/all/image_advanced.py", line 5, in 
    import cv2
ModuleNotFoundError: No module named 'cv2'
```

After: :+1:

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6000?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6000?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6000)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 pixi.lock | 464 +++++++++++++++++++++++++++++++++---------------------
 pixi.toml |   1 +
 2 files changed, 286 insertions(+), 179 deletions(-)

diff --git a/pixi.lock b/pixi.lock
index b0f28d6d8caa..c3608dc5f77e 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -173,7 +173,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -188,7 +188,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -202,7 +203,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       linux-aarch64:
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2
@@ -370,7 +371,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -385,7 +386,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -399,7 +401,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       osx-64:
       - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda
@@ -555,7 +557,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -570,7 +572,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz
       - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -584,7 +587,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
       osx-arm64:
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda
@@ -740,7 +743,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -755,7 +758,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -769,7 +773,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl
       win-64:
       - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda
@@ -905,7 +909,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2
       - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda
       - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -920,7 +924,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -934,7 +939,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl
   default:
     channels:
@@ -1089,7 +1094,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -1104,7 +1109,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -1118,7 +1124,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       linux-aarch64:
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2
@@ -1267,7 +1273,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -1282,7 +1288,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -1296,7 +1303,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       osx-64:
       - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda
@@ -1433,7 +1440,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -1448,7 +1455,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz
       - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -1462,7 +1470,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
       osx-arm64:
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda
@@ -1599,7 +1607,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -1614,7 +1622,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -1628,7 +1637,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl
       win-64:
       - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda
@@ -1762,7 +1771,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2
       - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda
       - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -1777,7 +1786,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -1791,7 +1801,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl
   py-docs:
     channels:
@@ -1947,7 +1957,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
@@ -1980,7 +1990,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz
       - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
@@ -1999,7 +2010,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+      - pypi: https://files.pythonhosted.org/packages/8b/9e/05bc55a3295d469ae658e15c7f6edc0f54d39745ad3bd268351ac31be73d/regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
@@ -2007,7 +2018,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       linux-aarch64:
@@ -2157,7 +2168,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
@@ -2190,7 +2201,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz
       - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
@@ -2209,7 +2221,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+      - pypi: https://files.pythonhosted.org/packages/ce/94/74388e3bcc7f274cef5df7aba75e5cb661b319e6923dae99612a7174d93a/regex-2024.4.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/2a/3e/d2ef968eed02cfd9494d5bac0906bce830c4eb2cd27658303d3884e82e27/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
@@ -2217,7 +2229,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/dd/3d/b19ab5850a2c35d11cda16d132842314ae15f9bda5fafb93407ea396f74b/watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       osx-64:
@@ -2356,7 +2368,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
@@ -2389,7 +2401,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz
       - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz
       - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl
@@ -2408,7 +2421,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl
+      - pypi: https://files.pythonhosted.org/packages/fd/b2/8069e8940bc3224d2cef6418aa6de4f2119d59709b841ecab012e3fc1d65/regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
@@ -2416,7 +2429,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
       osx-arm64:
@@ -2555,7 +2568,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl
@@ -2588,7 +2601,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz
       - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl
@@ -2607,7 +2621,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl
+      - pypi: https://files.pythonhosted.org/packages/aa/f1/de801945e6a18c9b7d7ea9ffe01d2433b40d1609426c3581f7d60acd1416/regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
@@ -2615,7 +2629,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl
       win-64:
@@ -2750,7 +2764,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2
       - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda
       - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/0d/35/4196b21041e29a42dc4f05866d0c94fa26c9da88ce12c38c2265e42c82fb/Babel-2.14.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl
@@ -2783,7 +2797,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/e9/f1/a4d3c449b7fa9e9694236a621b12e994653bd45ad96dc041cbb58a630005/mkdocs_material_extensions-1.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/64/2f/6b72f8f8bf168a5820c6c38bffe54d25cfdafd9b4be6fbb335a9a57dd7c9/mkdocstrings-0.23.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/35/ec/a9d5e3b98eb5d7da229481049f8031c2dad2a72d48192d3471c72ae0eda6/mkdocstrings_python-1.7.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/68/58/e670a947136fdcece8ac5376b3df1369d29e4f6659b0c9b358605b115e9e/paginate-0.5.6.tar.gz
       - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl
@@ -2802,7 +2817,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/5a/66/bbb1dd374f5c870f59c5bb1db0e18cbe7fa739415a24cbd95b2d1f5ae0c4/pyyaml_env_tag-0.1-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/42/8e/ae1de7b12223986e949bdb886c004de7c304b6fa94de5b87c926c1099656/referencing-0.34.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl
+      - pypi: https://files.pythonhosted.org/packages/b3/d0/1a054b685849b018cff594ccd4859fc6a3132f67698da805ed06d5b6974a/regex-2024.4.16-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
@@ -2810,7 +2825,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/a4/ce/3b6fee91c85626eaf769d617f1be9d2e15c1cca027bbdeb2e0d751469355/verspec-0.1.0-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl
   wheel-test:
@@ -2967,7 +2982,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.13-hd590300_5.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -2985,7 +3000,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/37/6d/121efd7382d5b0284239f4ab1fc1590d86d34ed4a4a2fdb13b30ca8e5740/nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/7e/00/6b218edd739ecfc60524e585ba8e6b00554dd908de2c9c66c1af3e44e18d/nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/b6/9f/c64c03f49d6fbc56196664d05dba14e3a561038a81a638eeb47f4d4cfd48/nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl
@@ -2998,6 +3013,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/38/00/d0d4e48aef772ad5aebcf70b73028f88db6e5640b36c38e90445b7a57c45/nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/ff/ff/847841bacfbefc97a00036e0fce5a0f086b640756dc38caea5e1bb002655/nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/da/d3/8057f0587683ed2fcd4dbfbdfdfa807b9160b809976099d36b8f60d08f03/nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl
+      - pypi: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -3014,7 +3030,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/bd/ac/3974caaa459bf2c3a244a84be8d17561f631f7d42af370fc311defeca2fb/triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
       linux-aarch64:
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2
@@ -3163,7 +3179,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zlib-1.2.13-h31becfc_5.conda
       - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -3181,7 +3197,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -3197,7 +3214,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
       osx-64:
       - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda
@@ -3335,7 +3352,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.13-h8a1eda9_5.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -3353,7 +3370,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz
       - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -3369,7 +3387,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
       osx-arm64:
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda
@@ -3507,7 +3525,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zlib-1.2.13-h53f4e23_5.conda
       - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -3525,7 +3543,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -3541,7 +3560,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl
       win-64:
       - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda
@@ -3675,7 +3694,7 @@ environments:
       - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2
       - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda
       - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda
-      - pypi: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl
@@ -3693,7 +3712,8 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl
@@ -3709,7 +3729,7 @@ environments:
       - pypi: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl
       - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl
-      - pypi: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
+      - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
       - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl
 packages:
 - kind: conda
@@ -3914,9 +3934,9 @@ packages:
   timestamp: 1667935912504
 - kind: pypi
   name: argcomplete
-  version: 3.2.3
-  url: https://files.pythonhosted.org/packages/88/8c/61021c45428ad2ef6131c6068d14f7f0968767e972e427cd87bd25c9ea7b/argcomplete-3.2.3-py3-none-any.whl
-  sha256: c12355e0494c76a2a7b73e3a59b09024ca0ba1e279fb9ed6c1b82d5b74b6a70c
+  version: 3.3.0
+  url: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl
+  sha256: c168c3723482c031df3c207d4ba8fa702717ccb9fc0bfe4117166c1f537b4a54
   requires_dist:
   - coverage ; extra == 'test'
   - pexpect ; extra == 'test'
@@ -8011,24 +8031,24 @@ packages:
 - kind: pypi
   name: cffi
   version: 1.16.0
-  url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
-  sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936
+  url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e
   requires_dist:
   - pycparser
   requires_python: '>=3.8'
 - kind: pypi
   name: cffi
   version: 1.16.0
-  url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
-  sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404
+  url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl
+  sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba
   requires_dist:
   - pycparser
   requires_python: '>=3.8'
 - kind: pypi
   name: cffi
   version: 1.16.0
-  url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-  sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e
+  url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
+  sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404
   requires_dist:
   - pycparser
   requires_python: '>=3.8'
@@ -8043,8 +8063,8 @@ packages:
 - kind: pypi
   name: cffi
   version: 1.16.0
-  url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl
-  sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba
+  url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+  sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936
   requires_dist:
   - pycparser
   requires_python: '>=3.8'
@@ -9221,8 +9241,8 @@ packages:
 - kind: pypi
   name: cryptography
   version: 38.0.4
-  url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl
-  sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d
+  url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8
   requires_dist:
   - cffi >=1.12
   - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs'
@@ -9249,8 +9269,8 @@ packages:
 - kind: pypi
   name: cryptography
   version: 38.0.4
-  url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl
-  sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb
+  url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl
+  sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d
   requires_dist:
   - cffi >=1.12
   - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs'
@@ -9277,8 +9297,8 @@ packages:
 - kind: pypi
   name: cryptography
   version: 38.0.4
-  url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-  sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8
+  url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl
+  sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb
   requires_dist:
   - cffi >=1.12
   - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs'
@@ -9333,8 +9353,8 @@ packages:
 - kind: pypi
   name: cryptography
   version: 38.0.4
-  url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl
-  sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d
+  url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl
+  sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d
   requires_dist:
   - cffi >=1.12
   - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs'
@@ -10352,24 +10372,24 @@ packages:
 - kind: pypi
   name: google-crc32c
   version: 1.5.0
-  url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
-  sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57
+  url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906
   requires_dist:
   - pytest ; extra == 'testing'
   requires_python: '>=3.7'
 - kind: pypi
   name: google-crc32c
   version: 1.5.0
-  url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl
-  sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298
+  url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl
+  sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968
   requires_dist:
   - pytest ; extra == 'testing'
   requires_python: '>=3.7'
 - kind: pypi
   name: google-crc32c
   version: 1.5.0
-  url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-  sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906
+  url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl
+  sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298
   requires_dist:
   - pytest ; extra == 'testing'
   requires_python: '>=3.7'
@@ -10384,8 +10404,8 @@ packages:
 - kind: pypi
   name: google-crc32c
   version: 1.5.0
-  url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl
-  sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968
+  url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+  sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57
   requires_dist:
   - pytest ; extra == 'testing'
   requires_python: '>=3.7'
@@ -20412,19 +20432,20 @@ packages:
   timestamp: 1707414728922
 - kind: pypi
   name: nox
-  version: 2024.3.2
-  url: https://files.pythonhosted.org/packages/c2/55/c0d4ca1e6f68da8a1c7055ad80d4bf1fef651af08a68b52323cee97880c9/nox-2024.3.2-py3-none-any.whl
-  sha256: e53514173ac0b98dd47585096a55572fe504fecede58ced708979184d05440be
+  version: 2024.4.15
+  url: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl
+  sha256: 6492236efa15a460ecb98e7b67562a28b70da006ab0be164e8821177577c0565
   requires_dist:
   - argcomplete <4.0, >=1.9.4
   - colorlog <7.0.0, >=2.6.1
   - importlib-metadata ; python_version < '3.8'
   - packaging >=20.9
+  - tomli >=1 ; python_version < '3.11'
   - typing-extensions >=3.7.4 ; python_version < '3.8'
   - virtualenv >=20.14.1
   - jinja2 ; extra == 'tox_to_nox'
   - tox ; extra == 'tox_to_nox'
-  - uv ; extra == 'uv'
+  - uv >=0.1.6 ; extra == 'uv'
   requires_python: '>=3.7'
 - kind: conda
   name: numpy
@@ -20627,6 +20648,91 @@ packages:
   url: https://files.pythonhosted.org/packages/da/d3/8057f0587683ed2fcd4dbfbdfdfa807b9160b809976099d36b8f60d08f03/nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl
   sha256: dc21cf308ca5691e7c04d962e213f8a4aa9bbfa23d95412f452254c2caeb09e5
   requires_python: '>=3'
+- kind: pypi
+  name: opencv-python
+  version: 4.9.0.80
+  url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57
+  requires_dist:
+  - numpy >=1.13.3 ; python_version < '3.7'
+  - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64'
+  - numpy >=1.21.2 ; python_version >= '3.10'
+  - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin'
+  - numpy >=1.23.5 ; python_version >= '3.11'
+  - numpy >=1.26.0 ; python_version >= '3.12'
+  - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'
+  - numpy >=1.17.0 ; python_version >= '3.7'
+  - numpy >=1.17.3 ; python_version >= '3.8'
+  - numpy >=1.19.3 ; python_version >= '3.9'
+  requires_python: '>=3.6'
+- kind: pypi
+  name: opencv-python
+  version: 4.9.0.80
+  url: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl
+  sha256: 3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0
+  requires_dist:
+  - numpy >=1.13.3 ; python_version < '3.7'
+  - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64'
+  - numpy >=1.21.2 ; python_version >= '3.10'
+  - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin'
+  - numpy >=1.23.5 ; python_version >= '3.11'
+  - numpy >=1.26.0 ; python_version >= '3.12'
+  - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'
+  - numpy >=1.17.0 ; python_version >= '3.7'
+  - numpy >=1.17.3 ; python_version >= '3.8'
+  - numpy >=1.19.3 ; python_version >= '3.9'
+  requires_python: '>=3.6'
+- kind: pypi
+  name: opencv-python
+  version: 4.9.0.80
+  url: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz
+  sha256: 1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1
+  requires_dist:
+  - numpy >=1.13.3 ; python_version < '3.7'
+  - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64'
+  - numpy >=1.21.2 ; python_version >= '3.10'
+  - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin'
+  - numpy >=1.23.5 ; python_version >= '3.11'
+  - numpy >=1.26.0 ; python_version >= '3.12'
+  - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'
+  - numpy >=1.17.0 ; python_version >= '3.7'
+  - numpy >=1.17.3 ; python_version >= '3.8'
+  - numpy >=1.19.3 ; python_version >= '3.9'
+  requires_python: '>=3.6'
+- kind: pypi
+  name: opencv-python
+  version: 4.9.0.80
+  url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl
+  sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3
+  requires_dist:
+  - numpy >=1.13.3 ; python_version < '3.7'
+  - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64'
+  - numpy >=1.21.2 ; python_version >= '3.10'
+  - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin'
+  - numpy >=1.23.5 ; python_version >= '3.11'
+  - numpy >=1.26.0 ; python_version >= '3.12'
+  - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'
+  - numpy >=1.17.0 ; python_version >= '3.7'
+  - numpy >=1.17.3 ; python_version >= '3.8'
+  - numpy >=1.19.3 ; python_version >= '3.9'
+  requires_python: '>=3.6'
+- kind: pypi
+  name: opencv-python
+  version: 4.9.0.80
+  url: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+  sha256: 7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a
+  requires_dist:
+  - numpy >=1.13.3 ; python_version < '3.7'
+  - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64'
+  - numpy >=1.21.2 ; python_version >= '3.10'
+  - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin'
+  - numpy >=1.23.5 ; python_version >= '3.11'
+  - numpy >=1.26.0 ; python_version >= '3.12'
+  - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64'
+  - numpy >=1.17.0 ; python_version >= '3.7'
+  - numpy >=1.17.3 ; python_version >= '3.8'
+  - numpy >=1.19.3 ; python_version >= '3.9'
+  requires_python: '>=3.6'
 - kind: conda
   name: openssl
   version: 3.2.1
@@ -21127,8 +21233,8 @@ packages:
 - kind: pypi
   name: pillow
   version: 10.0.0
-  url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
-  sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3
+  url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d
   requires_dist:
   - furo ; extra == 'docs'
   - olefile ; extra == 'docs'
@@ -21151,8 +21257,8 @@ packages:
 - kind: pypi
   name: pillow
   version: 10.0.0
-  url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl
-  sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485
+  url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl
+  sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f
   requires_dist:
   - furo ; extra == 'docs'
   - olefile ; extra == 'docs'
@@ -21175,8 +21281,8 @@ packages:
 - kind: pypi
   name: pillow
   version: 10.0.0
-  url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-  sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d
+  url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl
+  sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485
   requires_dist:
   - furo ; extra == 'docs'
   - olefile ; extra == 'docs'
@@ -21223,8 +21329,8 @@ packages:
 - kind: pypi
   name: pillow
   version: 10.0.0
-  url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl
-  sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f
+  url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+  sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3
   requires_dist:
   - furo ; extra == 'docs'
   - olefile ; extra == 'docs'
@@ -21424,26 +21530,26 @@ packages:
 - kind: pypi
   name: protobuf
   version: 4.25.3
-  url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl
-  sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019
+  url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl
+  sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d
   requires_python: '>=3.8'
 - kind: pypi
   name: protobuf
   version: 4.25.3
-  url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl
-  sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c
+  url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl
+  sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8
   requires_python: '>=3.8'
 - kind: pypi
   name: protobuf
   version: 4.25.3
-  url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl
-  sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d
+  url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl
+  sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c
   requires_python: '>=3.8'
 - kind: pypi
   name: protobuf
   version: 4.25.3
-  url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl
-  sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8
+  url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl
+  sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019
   requires_python: '>=3.8'
 - kind: conda
   name: psutil
@@ -22045,8 +22151,8 @@ packages:
 - kind: pypi
   name: pynacl
   version: 1.5.0
-  url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl
-  sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92
+  url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl
+  sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d
   requires_dist:
   - cffi >=1.4.1
   - sphinx >=1.6.5 ; extra == 'docs'
@@ -22057,8 +22163,8 @@ packages:
 - kind: pypi
   name: pynacl
   version: 1.5.0
-  url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl
-  sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1
+  url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl
+  sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93
   requires_dist:
   - cffi >=1.4.1
   - sphinx >=1.6.5 ; extra == 'docs'
@@ -22069,8 +22175,8 @@ packages:
 - kind: pypi
   name: pynacl
   version: 1.5.0
-  url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl
-  sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d
+  url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl
+  sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1
   requires_dist:
   - cffi >=1.4.1
   - sphinx >=1.6.5 ; extra == 'docs'
@@ -22081,8 +22187,8 @@ packages:
 - kind: pypi
   name: pynacl
   version: 1.5.0
-  url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl
-  sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93
+  url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl
+  sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92
   requires_dist:
   - cffi >=1.4.1
   - sphinx >=1.6.5 ; extra == 'docs'
@@ -22453,26 +22559,26 @@ packages:
 - kind: pypi
   name: pyyaml
   version: 6.0.1
-  url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-  sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673
+  url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl
+  sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007
   requires_python: '>=3.6'
 - kind: pypi
   name: pyyaml
   version: 6.0.1
-  url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl
-  sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34
+  url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl
+  sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab
   requires_python: '>=3.6'
 - kind: pypi
   name: pyyaml
   version: 6.0.1
-  url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl
-  sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007
+  url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl
+  sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34
   requires_python: '>=3.6'
 - kind: pypi
   name: pyyaml
   version: 6.0.1
-  url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl
-  sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab
+  url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673
   requires_python: '>=3.6'
 - kind: pypi
   name: pyyaml-env-tag
@@ -22758,33 +22864,33 @@ packages:
   requires_python: '>=3.8'
 - kind: pypi
   name: regex
-  version: 2023.12.25
-  url: https://files.pythonhosted.org/packages/9b/71/b55b5ffc75918a96ea99794783524609ac3ff9e2d8f51e7ece8648a968f6/regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
-  sha256: c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb
+  version: 2024.4.16
+  url: https://files.pythonhosted.org/packages/ce/94/74388e3bcc7f274cef5df7aba75e5cb661b319e6923dae99612a7174d93a/regex-2024.4.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+  sha256: 7bb966fdd9217e53abf824f437a5a2d643a38d4fd5fd0ca711b9da683d452969
   requires_python: '>=3.7'
 - kind: pypi
   name: regex
-  version: 2023.12.25
-  url: https://files.pythonhosted.org/packages/8d/6b/2f6478814954c07c04ba60b78d688d3d7bab10d786e0b6c1db607e4f6673/regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-  sha256: f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa
+  version: 2024.4.16
+  url: https://files.pythonhosted.org/packages/fd/b2/8069e8940bc3224d2cef6418aa6de4f2119d59709b841ecab012e3fc1d65/regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl
+  sha256: 9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd
   requires_python: '>=3.7'
 - kind: pypi
   name: regex
-  version: 2023.12.25
-  url: https://files.pythonhosted.org/packages/a8/01/18232f93672c1d530834e2e0568a80eaab1df12d67ae499b1762ab462b5c/regex-2023.12.25-cp311-cp311-win_amd64.whl
-  sha256: 7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f
+  version: 2024.4.16
+  url: https://files.pythonhosted.org/packages/aa/f1/de801945e6a18c9b7d7ea9ffe01d2433b40d1609426c3581f7d60acd1416/regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl
+  sha256: fd80d1280d473500d8086d104962a82d77bfbf2b118053824b7be28cd5a79ea5
   requires_python: '>=3.7'
 - kind: pypi
   name: regex
-  version: 2023.12.25
-  url: https://files.pythonhosted.org/packages/dc/c2/b3c89e9c8933ceb2a8f56fcd25f1133f21d8e490fbdbd76160dfc2c83a6e/regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl
-  sha256: d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97
+  version: 2024.4.16
+  url: https://files.pythonhosted.org/packages/b3/d0/1a054b685849b018cff594ccd4859fc6a3132f67698da805ed06d5b6974a/regex-2024.4.16-cp311-cp311-win_amd64.whl
+  sha256: 8f83b6fd3dc3ba94d2b22717f9c8b8512354fd95221ac661784df2769ea9bba9
   requires_python: '>=3.7'
 - kind: pypi
   name: regex
-  version: 2023.12.25
-  url: https://files.pythonhosted.org/packages/60/9e/4b0223e05776aa3be806a902093b2ab1de3ba26b652d92065d5c7e1d4df3/regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl
-  sha256: d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887
+  version: 2024.4.16
+  url: https://files.pythonhosted.org/packages/8b/9e/05bc55a3295d469ae658e15c7f6edc0f54d39745ad3bd268351ac31be73d/regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: 0c8290b44d8b0af4e77048646c10c6e3aa583c1ca67f3b5ffb6e06cf0c6f0f89
   requires_python: '>=3.7'
 - kind: conda
   name: requests
@@ -22870,26 +22976,26 @@ packages:
 - kind: pypi
   name: rpds-py
   version: 0.18.0
-  url: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-  sha256: 0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5
+  url: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl
+  sha256: 3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4
   requires_python: '>=3.8'
 - kind: pypi
   name: rpds-py
   version: 0.18.0
-  url: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl
-  sha256: 998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa
+  url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl
+  sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6
   requires_python: '>=3.8'
 - kind: pypi
   name: rpds-py
   version: 0.18.0
-  url: https://files.pythonhosted.org/packages/78/60/3a1cd42addbaac4d160d60a25c62e45d4dcb815eda6a70bbdd0993584328/rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl
-  sha256: 3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4
+  url: https://files.pythonhosted.org/packages/a8/de/68280c51afdb241111dec873dd7d457986adfd9fd5225494eee0c4a3b9a3/rpds_py-0.18.0-cp311-none-win_amd64.whl
+  sha256: 998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa
   requires_python: '>=3.8'
 - kind: pypi
   name: rpds-py
   version: 0.18.0
-  url: https://files.pythonhosted.org/packages/c5/5e/0e9d41935934ff839fde917cab1449de02ccf9d84c02521949add9705844/rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl
-  sha256: 30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6
+  url: https://files.pythonhosted.org/packages/81/6a/aa2e389852e48f77b7ce086d60628d855745a520be89c3868b90657b2fd2/rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: 0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5
   requires_python: '>=3.8'
 - kind: pypi
   name: rsa
@@ -23734,8 +23840,8 @@ packages:
 - kind: pypi
   name: torch
   version: 2.2.2
-  url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl
-  sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf
+  url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl
+  sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb
   requires_dist:
   - filelock
   - typing-extensions >=4.8.0
@@ -23761,8 +23867,8 @@ packages:
 - kind: pypi
   name: torch
   version: 2.2.2
-  url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl
-  sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb
+  url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl
+  sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059
   requires_dist:
   - filelock
   - typing-extensions >=4.8.0
@@ -23815,8 +23921,8 @@ packages:
 - kind: pypi
   name: torch
   version: 2.2.2
-  url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl
-  sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c
+  url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl
+  sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf
   requires_dist:
   - filelock
   - typing-extensions >=4.8.0
@@ -23842,8 +23948,8 @@ packages:
 - kind: pypi
   name: torch
   version: 2.2.2
-  url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl
-  sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059
+  url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl
+  sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c
   requires_dist:
   - filelock
   - typing-extensions >=4.8.0
@@ -24417,9 +24523,9 @@ packages:
   - pytest ; extra == 'test'
 - kind: pypi
   name: virtualenv
-  version: 20.25.1
-  url: https://files.pythonhosted.org/packages/16/65/0d0bdfdac31e2db8c6d6c18fe1e00236f0dea279f9846f94a9aafa49cfc9/virtualenv-20.25.1-py3-none-any.whl
-  sha256: 961c026ac520bac5f69acb8ea063e8a4f071bcc9457b9c1f28f6b085c511583a
+  version: 20.25.2
+  url: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl
+  sha256: 6e1281a57849c8a54da89ba82e5eb7c8937b9d057ff01aaf5bc9afaa3552e90f
   requires_dist:
   - distlib <1, >=0.3.7
   - filelock <4, >=3.12.2
@@ -24427,8 +24533,8 @@ packages:
   - platformdirs <5, >=3.9.1
   - furo >=2023.7.26 ; extra == 'docs'
   - proselint >=0.13 ; extra == 'docs'
+  - sphinx !=7.3, >=7.1.2 ; extra == 'docs'
   - sphinx-argparse >=0.4 ; extra == 'docs'
-  - sphinx >=7.1.2 ; extra == 'docs'
   - sphinxcontrib-towncrier >=0.2.1a0 ; extra == 'docs'
   - towncrier >=23.6 ; extra == 'docs'
   - covdefaults >=2.3 ; extra == 'test'
@@ -24517,32 +24623,32 @@ packages:
 - kind: pypi
   name: watchdog
   version: 4.0.0
-  url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl
-  sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269
+  url: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl
+  sha256: c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935
   requires_dist:
   - pyyaml >=3.10 ; extra == 'watchmedo'
   requires_python: '>=3.8'
 - kind: pypi
   name: watchdog
   version: 4.0.0
-  url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl
-  sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245
+  url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl
+  sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b
   requires_dist:
   - pyyaml >=3.10 ; extra == 'watchmedo'
   requires_python: '>=3.8'
 - kind: pypi
   name: watchdog
   version: 4.0.0
-  url: https://files.pythonhosted.org/packages/7f/9b/04110f5c61fe2a90d5cccfc6445c8cce8c560c2fae236571c397b0dd68d0/watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl
-  sha256: c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935
+  url: https://files.pythonhosted.org/packages/d2/5c/110884d0c632aedc54cdef5b7de3a78b388b03582e3ba57ae06c79db8b10/watchdog-4.0.0-py3-none-win_amd64.whl
+  sha256: f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245
   requires_dist:
   - pyyaml >=3.10 ; extra == 'watchmedo'
   requires_python: '>=3.8'
 - kind: pypi
   name: watchdog
   version: 4.0.0
-  url: https://files.pythonhosted.org/packages/fb/01/2275fe6a5598daf95b9e44cc10a4db642c637ae00986836478e01eaccb4f/watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl
-  sha256: 4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b
+  url: https://files.pythonhosted.org/packages/91/7b/26d2f43aa9fe428416be21ee1cb9ac75638cf302466b7e706c14eeaea42c/watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl
+  sha256: 6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269
   requires_dist:
   - pyyaml >=3.10 ; extra == 'watchmedo'
   requires_python: '>=3.8'
@@ -24586,20 +24692,20 @@ packages:
 - kind: pypi
   name: wrapt
   version: 1.16.0
-  url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
-  sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389
+  url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
+  sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1
   requires_python: '>=3.6'
 - kind: pypi
   name: wrapt
   version: 1.16.0
-  url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
-  sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09
+  url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl
+  sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89
   requires_python: '>=3.6'
 - kind: pypi
   name: wrapt
   version: 1.16.0
-  url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
-  sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1
+  url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl
+  sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09
   requires_python: '>=3.6'
 - kind: pypi
   name: wrapt
@@ -24610,8 +24716,8 @@ packages:
 - kind: pypi
   name: wrapt
   version: 1.16.0
-  url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl
-  sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89
+  url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
+  sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389
   requires_python: '>=3.6'
 - kind: conda
   name: xz
diff --git a/pixi.toml b/pixi.toml
index af43b59ef49f..056f4a3497e3 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -284,6 +284,7 @@ pygithub = "==1.59.0"            # Among others for `generate_pr_summary.py`, `s
 requests = ">=2.31,<3"           # For `thumbnails.py` & `upload_image.py`
 types-Deprecated = "==1.2.9.2"   # Type hint stubs
 types-requests = ">=2.31,<3"     # Type hint stubs
+opencv-python = ">4.6"           # For `compare_snippet_output.py`
 
 
 [target.linux-64.dependencies]

From a299f4b6036aa44cf618a6a218fea1021270b038 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Wed, 17 Apr 2024 17:05:21 +0200
Subject: [PATCH 316/508] Rewrite `re_ws_comms` to work without `async` &
 `tokio` runtime (#6005)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

### What

* Big chunk of #5907

Removes tokio & async code from re_ws_comms. Achieves this by spawning a
thread for listening and another one for relaying messages (the later
was already the case but via tokio).
Main disadvantage of this change here is that all clients now share the
same thread for sending whereas before this was handled by the tokio
pool. In theory we have less latency though since before we had to go
from the broadcast thread to the client worker threads in a separate
step.

Ended up depending on the
[`polling`](https://docs.rs/polling/latest/polling/index.html) crate
because otherwise shutting down a tcplistener with vanilla std rust is
close to impossible. The version I picked is such that Cargo.lock
doesn't have (yet) another instance of this crate.

This change fixes a bug in the process where we'd not send all so far
received messages to new clients.

⚠️ Rerun serve still needs a tokio runtime with this change ⚠️: To fix
this we need to remove it also for the web server which should be quite
a bit easier 🤞

Testing done:
* [x] `pixi run rerun-web ` to serve several local browsers
* [x] `pixi run python .\examples\python\face_tracking\main.py --serve`
to serve several local browsers and checking that they catch up on old
data
* [x] keeping an eye on debug output ensuring that shutdown is graceful
* [x] Test the same on Mac (did only windows so far)

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6005?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6005?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6005
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 Cargo.lock                       |  17 +-
 Cargo.toml                       |  17 +-
 crates/re_sdk/src/web_viewer.rs  |  10 +-
 crates/re_ws_comms/Cargo.toml    |  31 +--
 crates/re_ws_comms/src/lib.rs    |  10 +-
 crates/re_ws_comms/src/server.rs | 400 ++++++++++++++++++-------------
 crates/rerun/src/run.rs          |  10 +-
 pixi.toml                        |   4 +-
 scripts/lint.py                  |   6 +-
 9 files changed, 258 insertions(+), 247 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 1d54c9a4d249..ec7ac2225bf9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5266,9 +5266,8 @@ dependencies = [
  "bincode",
  "document-features",
  "ewebsock",
- "futures-channel",
- "futures-util",
  "parking_lot",
+ "polling 2.8.0",
  "re_format",
  "re_log",
  "re_log_types",
@@ -5276,8 +5275,6 @@ dependencies = [
  "re_smart_channel",
  "re_tracing",
  "thiserror",
- "tokio",
- "tokio-tungstenite",
  "tungstenite",
 ]
 
@@ -6467,18 +6464,6 @@ dependencies = [
  "syn 2.0.48",
 ]
 
-[[package]]
-name = "tokio-tungstenite"
-version = "0.20.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
-dependencies = [
- "futures-util",
- "log",
- "tokio",
- "tungstenite",
-]
-
 [[package]]
 name = "tokio-util"
 version = "0.7.8"
diff --git a/Cargo.toml b/Cargo.toml
index e0789da88ba3..6d84fa84bad4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -109,8 +109,8 @@ arrow2 = { package = "re_arrow2", version = "0.17" }
 async-executor = "1.0"
 backtrace = "0.3"
 bincode = "1.3"
-bitflags = { version = "2.4", features = ["bytemuck"] }
 bit-vec = "0.6"
+bitflags = { version = "2.4", features = ["bytemuck"] }
 blackbox = "0.2.0"
 bytemuck = { version = "1.11", features = ["extern_crate_alloc"] }
 camino = "1.1"
@@ -137,20 +137,19 @@ flatbuffers = "23.0"
 futures-channel = "0.3"
 futures-util = { version = "0.3", default-features = false }
 getrandom = "0.2"
-glam = "0.22"                                                      # glam update blocked by macaw
+glam = "0.22" # glam update blocked by macaw
 glob = "0.3"
 gltf = "1.1"
 half = "2.3.1"
 hyper = "0.14"
 image = { version = "0.24", default-features = false }
 indent = "0.1"
-indexmap = "2.1"                                                   # Version chosen to align with other dependencies
-indicatif = "0.17.7"                                               # Progress bar
-infer = "0.15"                                                     # infer MIME type by checking the magic number signaturefer MIME type by checking the magic number signature
+indexmap = "2.1" # Version chosen to align with other dependencies
+indicatif = "0.17.7" # Progress bar
+infer = "0.15" # infer MIME type by checking the magic number signaturefer MIME type by checking the magic number signature
 insta = "1.23"
-itertools = "0.12"                                                 # updating itertools is blocked on the next egui_tiles update
+itertools = "0.12" # updating itertools is blocked on the next egui_tiles update
 js-sys = "0.3"
-# No lazy_static - use `std::sync::OnceLock` or `once_cell` instead
 libc = "0.2"
 linked-hash-map = { version = "0.5", default-features = false }
 log = "0.4"
@@ -170,7 +169,7 @@ nohash-hasher = "0.2"
 notify = "6.0"
 num-derive = "0.4"
 num-traits = "0.2"
-once_cell = "1.17"
+once_cell = "1.17" # No lazy_static - use `std::sync::OnceLock` or `once_cell` instead
 ordered-float = "4.2"
 parking_lot = "0.12"
 paste = "1.0"
@@ -178,6 +177,7 @@ pathdiff = "0.2"
 pico-args = "0.5"
 ply-rs = { version = "0.1", default-features = false }
 poll-promise = "0.3"
+polling = "2.2.0"
 pollster = "0.3"
 prettyplease = "0.2"
 proc-macro2 = { version = "1.0", default-features = false }
@@ -219,7 +219,6 @@ tinystl = { version = "0.0.3", default-features = false }
 tinyvec = { version = "1.6", features = ["alloc", "rustc_1_55"] }
 tobj = "4.0"
 tokio = { version = "1.24", default-features = false }
-tokio-tungstenite = { version = "0.20.0", default-features = false }
 toml = { version = "0.8.10", default-features = false }
 tracing = { version = "0.1", default-features = false }
 tungstenite = { version = "0.20", default-features = false }
diff --git a/crates/re_sdk/src/web_viewer.rs b/crates/re_sdk/src/web_viewer.rs
index 2b70ddf7592a..da4447acc93a 100644
--- a/crates/re_sdk/src/web_viewer.rs
+++ b/crates/re_sdk/src/web_viewer.rs
@@ -1,6 +1,6 @@
 use re_log_types::LogMsg;
 use re_web_viewer_server::{WebViewerServerHandle, WebViewerServerPort};
-use re_ws_comms::{RerunServerHandle, RerunServerPort};
+use re_ws_comms::{RerunServer, RerunServerPort};
 
 /// Failure to host a web viewer and/or Rerun server.
 #[derive(thiserror::Error, Debug)]
@@ -21,8 +21,8 @@ struct WebViewerSink {
     /// Sender to send messages to the [`re_ws_comms::RerunServer`]
     sender: re_smart_channel::Sender,
 
-    /// Handle to keep the [`re_ws_comms::RerunServer`] alive
-    _rerun_server: RerunServerHandle,
+    /// Rerun websocket server.
+    _rerun_server: RerunServer,
 
     /// Handle to keep the [`re_web_viewer_server::WebViewerServer`] alive
     _webviewer_server: WebViewerServerHandle,
@@ -43,9 +43,9 @@ impl WebViewerSink {
             re_smart_channel::SmartChannelSource::Sdk,
         );
 
-        let rerun_server = RerunServerHandle::new(
+        let rerun_server = RerunServer::new(
             re_smart_channel::ReceiveSet::new(vec![rerun_rx]),
-            bind_ip.to_owned(),
+            bind_ip,
             ws_port,
             server_memory_limit,
         )?;
diff --git a/crates/re_ws_comms/Cargo.toml b/crates/re_ws_comms/Cargo.toml
index d581e475a60d..b62194c57290 100644
--- a/crates/re_ws_comms/Cargo.toml
+++ b/crates/re_ws_comms/Cargo.toml
@@ -21,15 +21,7 @@ all-features = true
 client = ["ewebsock"]
 
 ## Enable the server.
-server = [
-  "dep:futures-channel",
-  "dep:futures-util",
-  "dep:parking_lot",
-  "dep:re_smart_channel",
-  "dep:tokio-tungstenite",
-  "dep:tokio",
-  "tungstenite",
-]
+server = ["dep:parking_lot", "dep:re_smart_channel", "tungstenite", "polling"]
 
 ## Enable encryption using TLS support (`wss://`).
 tls = [
@@ -54,24 +46,7 @@ thiserror.workspace = true
 ewebsock = { workspace = true, optional = true }
 
 # Server:
-re_smart_channel = { workspace = true, optional = true }
-
-[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
-futures-channel = { workspace = true, optional = true }
-futures-util = { workspace = true, optional = true, default-features = false, features = [
-  "sink",
-  "std",
-] }
 parking_lot = { workspace = true, optional = true }
-tokio-tungstenite = { workspace = true, optional = true, features = [
-  "handshake",
-] }
-tokio = { workspace = true, optional = true, features = [
-  "io-std",
-  "macros",
-  "net",
-  "rt-multi-thread",
-  "sync",
-  "time",
-] }
+polling = { workspace = true, optional = true }
+re_smart_channel = { workspace = true, optional = true }
 tungstenite = { workspace = true, optional = true, default-features = false }
diff --git a/crates/re_ws_comms/src/lib.rs b/crates/re_ws_comms/src/lib.rs
index 9ea0e0ee3da3..2182c3b0dce3 100644
--- a/crates/re_ws_comms/src/lib.rs
+++ b/crates/re_ws_comms/src/lib.rs
@@ -14,7 +14,7 @@ pub use client::viewer_to_server;
 #[cfg(feature = "server")]
 mod server;
 #[cfg(feature = "server")]
-pub use server::{RerunServer, RerunServerHandle};
+pub use server::RerunServer;
 
 use re_log_types::LogMsg;
 
@@ -41,12 +41,8 @@ pub enum RerunServerError {
     InvalidMessage(#[from] bincode::Error),
 
     #[cfg(feature = "server")]
-    #[error("Failed to join web viewer server task: {0}")]
-    JoinError(#[from] tokio::task::JoinError),
-
-    #[cfg(feature = "server")]
-    #[error("Tokio error: {0}")]
-    TokioIoError(#[from] tokio::io::Error),
+    #[error("IO error: {0}")]
+    IoError(#[from] std::io::Error),
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
diff --git a/crates/re_ws_comms/src/server.rs b/crates/re_ws_comms/src/server.rs
index 68235caaf878..509c9da8b82b 100644
--- a/crates/re_ws_comms/src/server.rs
+++ b/crates/re_ws_comms/src/server.rs
@@ -6,12 +6,15 @@
 //! In the future thing will be changed to a protocol where the clients can query
 //! for specific data based on e.g. time.
 
-use std::{collections::VecDeque, net::SocketAddr, sync::Arc};
+use std::{
+    collections::VecDeque,
+    net::{TcpListener, TcpStream},
+    sync::{atomic::AtomicBool, Arc},
+};
 
-use futures_util::{SinkExt, StreamExt};
 use parking_lot::Mutex;
-use tokio::net::{TcpListener, TcpStream};
-use tokio_tungstenite::{accept_async, tungstenite::Error};
+use polling::{Event, Poller};
+use tungstenite::WebSocket;
 
 use re_log_types::LogMsg;
 use re_memory::MemoryLimit;
@@ -19,10 +22,9 @@ use re_smart_channel::ReceiveSet;
 
 use crate::{server_url, RerunServerError, RerunServerPort};
 
-#[derive(Clone)]
 struct MessageQueue {
     server_memory_limit: MemoryLimit,
-    messages: VecDeque>,
+    messages: VecDeque>,
 }
 
 impl MessageQueue {
@@ -33,7 +35,7 @@ impl MessageQueue {
         }
     }
 
-    pub fn push(&mut self, msg: Arc<[u8]>) {
+    pub fn push(&mut self, msg: Vec) {
         self.gc_if_using_too_much_ram();
         self.messages.push_back(msg);
     }
@@ -76,10 +78,14 @@ impl MessageQueue {
 }
 
 /// Websocket host for relaying [`LogMsg`]s to a web viewer.
+///
+/// When dropped, the server will be shut down.
 pub struct RerunServer {
-    server_memory_limit: MemoryLimit,
-    listener: TcpListener,
     local_addr: std::net::SocketAddr,
+
+    listener_join_handle: Option>,
+    poller: Arc,
+    shutdown_flag: Arc,
 }
 
 impl RerunServer {
@@ -88,29 +94,56 @@ impl RerunServer {
     ///
     /// A `bind_ip` of `"0.0.0.0"` is a good default.
     /// A port of 0 will let the OS choose a free port.
-    pub async fn new(
-        bind_ip: String,
+    ///
+    /// Once created, the server will immediately start listening for connections.
+    pub fn new(
+        rerun_rx: ReceiveSet,
+        bind_ip: &str,
         port: RerunServerPort,
         server_memory_limit: MemoryLimit,
     ) -> Result {
         let bind_addr = format!("{bind_ip}:{port}");
 
-        let listener = match TcpListener::bind(&bind_addr).await {
+        let listener_socket = match TcpListener::bind(bind_addr) {
             Ok(listener) => listener,
             Err(err) if err.kind() == std::io::ErrorKind::AddrInUse => {
                 let bind_addr = format!("{bind_ip}:0");
 
-                TcpListener::bind(&bind_addr)
-                    .await
+                TcpListener::bind(bind_addr)
                     .map_err(|err| RerunServerError::BindFailed(RerunServerPort(0), err))?
             }
             Err(err) => return Err(RerunServerError::BindFailed(port, err)),
         };
 
+        // Blocking listener socket seems much easier at first glance:
+        // No polling needed and as such no extra libraries!
+        // However, there is no portable way of stopping an `accept` call on a blocking socket.
+        // Therefore, we do the "correct thing" and use a non-blocking socket together with the `polling` library.
+        listener_socket.set_nonblocking(true)?;
+
+        let poller = Arc::new(Poller::new()?);
+        let shutdown_flag = Arc::new(AtomicBool::new(false));
+
+        let local_addr = listener_socket.local_addr()?;
+        let poller_copy = poller.clone();
+        let shutdown_flag_copy = shutdown_flag.clone();
+
+        let listener_join_handle = std::thread::Builder::new()
+            .name("rerun_ws_server: listener".to_owned())
+            .spawn(move || {
+                Self::listen_thread_func(
+                    &poller,
+                    &listener_socket,
+                    &ReceiveSetBroadcaster::new(rerun_rx, server_memory_limit),
+                    &shutdown_flag,
+                );
+            })?;
+
         let slf = Self {
-            server_memory_limit,
-            local_addr: listener.local_addr()?,
-            listener,
+            local_addr,
+            poller: poller_copy,
+            listener_join_handle: Some(listener_join_handle),
+            shutdown_flag: shutdown_flag_copy,
         };
 
         re_log::info!(
@@ -121,120 +154,182 @@ impl RerunServer {
         Ok(slf)
     }
 
-    /// Accept new connections
-    pub async fn listen(self, rx: ReceiveSet) -> Result<(), RerunServerError> {
-        let (_shutdown_tx, shutdown_rx) = tokio::sync::broadcast::channel(1);
-        self.listen_with_graceful_shutdown(rx, shutdown_rx).await
+    /// Contains the `ws://` or `wss://` prefix.
+    pub fn server_url(&self) -> String {
+        server_url(&self.local_addr)
     }
 
-    /// Accept new connections until we get a message on `shutdown_rx`
-    pub async fn listen_with_graceful_shutdown(
-        self,
-        rx: ReceiveSet,
-        mut shutdown_rx: tokio::sync::broadcast::Receiver<()>,
-    ) -> Result<(), RerunServerError> {
-        let history = Arc::new(Mutex::new(MessageQueue::new(self.server_memory_limit)));
-
-        let log_stream = to_broadcast_stream(rx, history.clone());
+    fn listen_thread_func(
+        poller: &Poller,
+        listener_socket: &TcpListener,
+        message_broadcaster: &ReceiveSetBroadcaster,
+        shutdown_flag: &AtomicBool,
+    ) {
+        // Each socket in `poll::Poller` needs a "name".
+        // Doesn't matter much what we're using here, as long as it's not used for something else
+        // on the same poller.
+        let listener_poll_key = 1;
+
+        if let Err(err) = poller.add(listener_socket, Event::readable(listener_poll_key)) {
+            re_log::error!("Error when polling listener socket for incoming connections: {err}");
+            return;
+        }
 
+        let mut events = Vec::new();
         loop {
-            let (tcp_stream, _) = tokio::select! {
-                res = self.listener.accept() => res?,
-                _ = shutdown_rx.recv() => {
-                    re_log::debug!("Shutting down WebSocket server");
-                    return Ok(());
+            if let Err(err) = poller.wait(&mut events, None) {
+                re_log::warn!("Error polling WebSocket server listener: {err}");
+            }
+
+            if shutdown_flag.load(std::sync::atomic::Ordering::Acquire) {
+                re_log::debug!("Stopping WebSocket server listener.");
+                break;
+            }
+
+            for event in events.drain(..) {
+                if event.key == listener_poll_key {
+                    Self::accept_connection(
+                        listener_socket,
+                        message_broadcaster,
+                        poller,
+                        listener_poll_key,
+                    );
                 }
-            };
-
-            let peer = tcp_stream.peer_addr()?;
-            tokio::spawn(accept_connection(
-                log_stream.clone(),
-                peer,
-                tcp_stream,
-                history.clone(),
-            ));
+            }
         }
     }
 
-    /// Contains the `ws://` or `wss://` prefix.
-    pub fn server_url(&self) -> String {
-        server_url(&self.local_addr)
+    fn accept_connection(
+        listener_socket: &TcpListener,
+        message_broadcaster: &ReceiveSetBroadcaster,
+        poller: &Poller,
+        listener_poll_key: usize,
+    ) {
+        match listener_socket.accept() {
+            Ok((tcp_stream, _)) => {
+                let address = tcp_stream.peer_addr();
+
+                // Keep the client simple, otherwise we need to do polling there as well.
+                tcp_stream.set_nonblocking(false).ok();
+
+                re_log::debug!("New WebSocket connection from {address:?}");
+
+                match tungstenite::accept(tcp_stream) {
+                    Ok(ws_stream) => {
+                        message_broadcaster.add_client(ws_stream);
+                    }
+                    Err(err) => {
+                        re_log::warn!("Error accepting WebSocket connection: {err}");
+                    }
+                };
+            }
+
+            Err(err) => {
+                re_log::warn!("Error accepting WebSocket connection: {err}");
+            }
+        };
+
+        // Set interest in the next readability event.
+        if let Err(err) = poller.modify(listener_socket, Event::readable(listener_poll_key)) {
+            re_log::error!("Error when polling listener socket for incoming connections: {err}");
+        }
     }
-}
 
-/// Sync handle for the [`RerunServer`]
-///
-/// When dropped, the server will be shut down.
-pub struct RerunServerHandle {
-    local_addr: std::net::SocketAddr,
-    shutdown_tx: tokio::sync::broadcast::Sender<()>,
+    fn stop_listener(&mut self) {
+        let Some(join_handle) = self.listener_join_handle.take() else {
+            return;
+        };
+
+        self.shutdown_flag
+            .store(true, std::sync::atomic::Ordering::Release);
+
+        if let Err(err) = self.poller.notify() {
+            re_log::warn!("Error notifying WebSocket server listener: {err}");
+            return;
+        }
+
+        join_handle.join().ok();
+    }
 }
 
-impl Drop for RerunServerHandle {
+impl Drop for RerunServer {
     fn drop(&mut self) {
         re_log::info!("Shutting down Rerun server on {}", self.server_url());
-        self.shutdown_tx.send(()).ok();
+        self.stop_listener();
     }
 }
 
-impl RerunServerHandle {
-    /// Create new [`RerunServer`] to relay [`LogMsg`]s to a websocket.
-    /// Returns a [`RerunServerHandle`] that will shutdown the server when dropped.
-    ///
-    /// A `bind_ip` of `"0.0.0.0"` is a good default.
-    /// A port of 0 will let the OS choose a free port.
-    ///
-    /// The caller needs to ensure that there is a `tokio` runtime running.
-    pub fn new(
-        rerun_rx: ReceiveSet,
-        bind_ip: String,
-        requested_port: RerunServerPort,
-        server_memory_limit: MemoryLimit,
-    ) -> Result {
-        let (shutdown_tx, shutdown_rx) = tokio::sync::broadcast::channel(1);
-
-        let rt = tokio::runtime::Handle::current();
-
-        let ws_server = rt.block_on(tokio::spawn(async move {
-            RerunServer::new(bind_ip, requested_port, server_memory_limit).await
-        }))??;
-
-        let local_addr = ws_server.local_addr;
+/// Broadcasts messages to all connected clients and stores a history of messages to resend to new clients.
+///
+/// This starts a thread which will close when the underlying `ReceiveSet` gets a quit message or looses all its connections.
+struct ReceiveSetBroadcaster {
+    inner: Arc>,
+    shutdown_on_next_recv: Arc,
+}
 
-        tokio::spawn(async move {
-            ws_server
-                .listen_with_graceful_shutdown(rerun_rx, shutdown_rx)
-                .await
-        });
+/// Inner state of the [`ReceiveSetBroadcaster`], protected by a mutex.
+struct ReceiveSetBroadcasterInnerState {
+    /// Don't allow adding to the history while adding/removing clients.
+    /// This way, no messages history is lost!
+    history: MessageQueue,
+    clients: Vec>,
+}
 
-        Ok(Self {
-            local_addr,
-            shutdown_tx,
-        })
-    }
+impl ReceiveSetBroadcaster {
+    pub fn new(log_rx: ReceiveSet, server_memory_limit: MemoryLimit) -> Self {
+        let inner = Arc::new(Mutex::new(ReceiveSetBroadcasterInnerState {
+            history: MessageQueue::new(server_memory_limit),
+            clients: Vec::new(),
+        }));
+        let shutdown = Arc::new(AtomicBool::new(false));
+
+        let inner_copy = inner.clone();
+        let shutdown_copy = shutdown.clone();
+
+        if let Err(err) = std::thread::Builder::new()
+            .name("rerun_ws_server: broadcaster".to_owned())
+            .spawn(move || {
+                Self::broadcast_thread_func(&log_rx, &inner, &shutdown);
+            })
+        {
+            re_log::error!(
+                "Failed to spawn thread for broadcasting messages to websocket connections: {err}"
+            );
+        }
 
-    /// Contains the `ws://` or `wss://` prefix.
-    pub fn server_url(&self) -> String {
-        server_url(&self.local_addr)
+        Self {
+            inner: inner_copy,
+            shutdown_on_next_recv: shutdown_copy,
+        }
     }
-}
 
-fn to_broadcast_stream(
-    log_rx: ReceiveSet,
-    history: Arc>,
-) -> tokio::sync::broadcast::Sender> {
-    let (tx, _) = tokio::sync::broadcast::channel(1024 * 1024);
-    let tx1 = tx.clone();
-    tokio::task::spawn_blocking(move || {
+    fn broadcast_thread_func(
+        log_rx: &ReceiveSet,
+        inner: &Mutex,
+        shutdown: &AtomicBool,
+    ) {
         while let Ok(msg) = log_rx.recv() {
+            if shutdown.load(std::sync::atomic::Ordering::Acquire) {
+                re_log::debug!("Shutting down broadcaster.");
+                break;
+            }
+
             match msg.payload {
                 re_smart_channel::SmartMessagePayload::Msg(data) => {
-                    let bytes = crate::encode_log_msg(&data);
-                    let bytes: Arc<[u8]> = bytes.into();
-                    history.lock().push(bytes.clone());
-                    if let Err(tokio::sync::broadcast::error::SendError(_bytes)) = tx1.send(bytes) {
-                        // no receivers currently - that's fine!
-                    }
+                    let msg = crate::encode_log_msg(&data);
+                    let mut inner = inner.lock();
+
+                    // TODO(andreas): Should this be a parallel-for?
+                    inner.clients.retain_mut(|client| {
+                        if let Err(err) = client.send(tungstenite::Message::Binary(msg.clone())) {
+                            re_log::warn!("Error sending message to web socket client: {err}");
+                            false
+                        } else {
+                            true
+                        }
+                    });
+
+                    inner.history.push(msg);
                 }
                 re_smart_channel::SmartMessagePayload::Quit(err) => {
                     if let Some(err) = err {
@@ -244,78 +339,39 @@ fn to_broadcast_stream(
                     }
                 }
             }
-        }
-    });
-    tx
-}
-
-async fn accept_connection(
-    log_stream: tokio::sync::broadcast::Sender>,
-    _peer: SocketAddr,
-    tcp_stream: TcpStream,
-    history: Arc>,
-) {
-    // let span = re_log::span!(
-    //     re_log::Level::INFO,
-    //     "Connection",
-    //     peer = _peer.to_string().as_str()
-    // );
-    // let _enter = span.enter();
-
-    re_log::debug!("New WebSocket connection");
-
-    if let Err(err) = handle_connection(log_stream, tcp_stream, history).await {
-        match err {
-            Error::ConnectionClosed | Error::Protocol(_) | Error::Utf8 => (),
-            err => re_log::error!("Error processing connection: {err}"),
-        }
-    }
-}
 
-async fn handle_connection(
-    log_stream: tokio::sync::broadcast::Sender>,
-    tcp_stream: TcpStream,
-    history: Arc>,
-) -> tungstenite::Result<()> {
-    let ws_stream = accept_async(tcp_stream).await?;
-    let (mut ws_sender, mut ws_receiver) = ws_stream.split();
-
-    {
-        // Re-sending packet history - this is not water tight, but better than nothing.
-        // TODO(emilk): water-proof resending of history + streaming of new stuff, without anything missed.
-        let history: MessageQueue = history.lock().clone();
-        for packet in history.messages {
-            ws_sender
-                .send(tungstenite::Message::Binary(packet.to_vec()))
-                .await?;
+            if log_rx.is_empty() {
+                re_log::debug!("No more connections. Shutting down broadcaster.");
+                break;
+            }
         }
     }
 
-    let mut log_rx = log_stream.subscribe();
-
-    loop {
-        tokio::select! {
-            ws_msg = ws_receiver.next() => {
-                match ws_msg {
-                    Some(Ok(msg)) => {
-                        re_log::debug!("Received message: {:?}", msg);
-                    }
-                    Some(Err(err)) => {
-                        re_log::warn!("Error message: {err}");
-                        break;
-                    }
-                    None => {
-                        break;
-                    }
-                }
-            }
-            data_msg = log_rx.recv() => {
-                let data_msg = data_msg.unwrap();
-
-                ws_sender.send(tungstenite::Message::Binary(data_msg.to_vec())).await?;
+    /// Adds a websocket client to the broadcaster and replies all message history so far to it.
+    pub fn add_client(&self, mut client: WebSocket) {
+        // TODO(andreas): While it's great that we don't loose any messages while adding clients,
+        // the problem with this is that now we won't be able to keep the other clients fed, until this one is done!
+        // Meaning that if a new one connects, we stall the old connections until we have sent all messages to this one.
+        let mut inner = self.inner.lock();
+
+        for msg in &inner.history.messages {
+            if let Err(err) = client.send(tungstenite::Message::Binary(msg.clone())) {
+                re_log::warn!("Error sending message to web socket client: {err}");
+                return;
             }
         }
+
+        inner.clients.push(client);
     }
+}
 
-    Ok(())
+impl Drop for ReceiveSetBroadcaster {
+    fn drop(&mut self) {
+        // Close all connections and shut down the receive thread on the next message.
+        // This would only cause a dangling thread if the `ReceiveSet`'s channels are
+        // neither closing nor sending any more messages.
+        self.shutdown_on_next_recv
+            .store(true, std::sync::atomic::Ordering::Release);
+        self.inner.lock().clients.clear();
+    }
 }
diff --git a/crates/rerun/src/run.rs b/crates/rerun/src/run.rs
index b0411a35b702..ce6326185953 100644
--- a/crates/rerun/src/run.rs
+++ b/crates/rerun/src/run.rs
@@ -724,14 +724,12 @@ async fn run_impl(
 
             // This is the server which the web viewer will talk to:
             let ws_server = re_ws_comms::RerunServer::new(
-                args.bind.clone(),
+                ReceiveSet::new(rx),
+                &args.bind,
                 args.ws_server_port,
                 server_memory_limit,
-            )
-            .await?;
+            )?;
             let _ws_server_url = ws_server.server_url();
-            let rx = ReceiveSet::new(rx);
-            let ws_server_handle = tokio::spawn(ws_server.listen(rx));
 
             #[cfg(feature = "web_viewer")]
             {
@@ -753,7 +751,7 @@ async fn run_impl(
                 web_server_handle.await?.map_err(anyhow::Error::from)?;
             }
 
-            return ws_server_handle.await?.map_err(anyhow::Error::from);
+            return Ok(());
         }
     } else {
         #[cfg(feature = "native_viewer")]
diff --git a/pixi.toml b/pixi.toml
index 056f4a3497e3..36d31751211a 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -56,13 +56,13 @@ rerun-web = { cmd = "cargo run --package rerun-cli --no-default-features --featu
 #
 # This installs the `wasm32-unknown-unknown` rust target if it's not already installed.
 # (this looks heavy but takes typically below 0.1s!)
-rerun-build-web = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer --debug"
+rerun-build-web = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer"
 
 # Compile the web-viewer wasm and the cli.
 #
 # This installs the `wasm32-unknown-unknown` rust target if it's not already installed.
 # (this looks heavy but takes typically below 0.1s!)
-rerun-build-web-cli = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer --debug && cargo build --package rerun-cli --no-default-features --features web_viewer"
+rerun-build-web-cli = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer && cargo build --package rerun-cli --no-default-features --features web_viewer"
 
 # Compile and run the web-viewer in release mode via rerun-cli.
 #
diff --git a/scripts/lint.py b/scripts/lint.py
index e8f3acef2dfe..4bb767b74320 100755
--- a/scripts/lint.py
+++ b/scripts/lint.py
@@ -973,7 +973,8 @@ def lint_example_requirements() -> int:
 
     missing = []
     for path in glob("examples/python/*/requirements.txt"):
-        line = f"-r {os.path.relpath(path, 'examples/python')}"
+        path = str(os.path.relpath(path, "examples/python")).replace("\\", "/")
+        line = f"-r {path}"
         if line not in requirements:
             missing.append(line)
 
@@ -992,7 +993,8 @@ def lint_example_requirements() -> int:
         expected = glob("examples/python/*/requirements.txt")
         expected.sort()
         for path in expected:
-            print(f"-r {os.path.relpath(path, 'examples/python')}")
+            path = str(os.path.relpath(path, "examples/python")).replace("\\", "/")
+            print(f"-r {path}")
         return 1
 
     return 0

From 627431e2c166776448f9b5eb1023fa7da6ff7ac8 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Wed, 17 Apr 2024 18:32:22 +0200
Subject: [PATCH 317/508] Fix listing `tornado` dependency twice in
 `python/notebook/requirements.txt` (#6021)

### What

Overlooked this on https://github.com/rerun-io/rerun/pull/5981

Tested again that notebook still works. This time on windows:
```cmd
pixi run pip install -r .\examples\python\notebook\requirements.txt
pixi run jupyter notebook .\examples\python\notebook\cube.ipynb
```

* Should fix https://github.com/rerun-io/rerun/issues/5927


### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/{{pr.number}})
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 examples/python/notebook/requirements.txt | 1 -
 1 file changed, 1 deletion(-)

diff --git a/examples/python/notebook/requirements.txt b/examples/python/notebook/requirements.txt
index ed3e15cdccda..931f6f7bf8fd 100644
--- a/examples/python/notebook/requirements.txt
+++ b/examples/python/notebook/requirements.txt
@@ -1,5 +1,4 @@
 ipython<=8.12 # ipython 8.13 or greater doesn't work with python 3.8
-tornado<=6.1 # later versions don't work with recent jupyter releases…
 jupyter
 rerun-sdk
 

From 1334e9d69d6cfb914e1e5b291fcb6c79046d03d6 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Wed, 17 Apr 2024 19:03:31 +0200
Subject: [PATCH 318/508] Python linting fixes (#6020)

### What

* Fixes #5945

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6020?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6020?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6020)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 examples/python/detect_and_track_objects/main.py | 16 ++++++++--------
 examples/python/face_tracking/main.py            |  5 ++---
 examples/python/gesture_detection/main.py        |  3 +--
 examples/python/raw_mesh/download_dataset.py     |  2 +-
 examples/python/segment_anything_model/main.py   |  5 ++---
 5 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/examples/python/detect_and_track_objects/main.py b/examples/python/detect_and_track_objects/main.py
index 8baffd9ec05a..f0386d8da6d3 100755
--- a/examples/python/detect_and_track_objects/main.py
+++ b/examples/python/detect_and_track_objects/main.py
@@ -89,7 +89,7 @@ def __init__(self, coco_categories: list[dict[str, Any]]) -> None:
 
         self.is_thing_from_id: dict[int, bool] = {cat["id"]: bool(cat["isthing"]) for cat in coco_categories}
 
-    def detect_objects_to_track(self, rgb: npt.NDArray[np.uint8], frame_idx: int) -> list[Detection]:
+    def detect_objects_to_track(self, rgb: cv2.typing.MatLike, frame_idx: int) -> list[Detection]:
         logging.info("Looking for things to track on frame %d", frame_idx)
 
         logging.debug("Preprocess image for detection network")
@@ -172,23 +172,23 @@ class Tracker:
     next_tracking_id = 0
     MAX_TIMES_UNDETECTED = 2
 
-    def __init__(self, tracking_id: int, detection: Detection, bgr: npt.NDArray[np.uint8]) -> None:
+    def __init__(self, tracking_id: int, detection: Detection, bgr: cv2.typing.MatLike) -> None:
         self.tracking_id = tracking_id
         self.tracked = detection.scaled_to_fit_image(bgr)
         self.num_recent_undetected_frames = 0
 
-        self.tracker = cv2.TrackerCSRT_create()
+        self.tracker = cv2.TrackerCSRT_create()  # type: ignore[attr-defined]
         bbox_xywh_rounded = [int(val) for val in self.tracked.bbox_xywh]
         self.tracker.init(bgr, bbox_xywh_rounded)
         self.log_tracked()
 
     @classmethod
-    def create_new_tracker(cls, detection: Detection, bgr: npt.NDArray[np.uint8]) -> Tracker:
+    def create_new_tracker(cls, detection: Detection, bgr: cv2.typing.MatLike) -> Tracker:
         new_tracker = cls(cls.next_tracking_id, detection, bgr)
         cls.next_tracking_id += 1
         return new_tracker
 
-    def update(self, bgr: npt.NDArray[np.uint8]) -> None:
+    def update(self, bgr: cv2.typing.MatLike) -> None:
         if not self.is_tracking:
             return
         success, bbox_xywh = self.tracker.update(bgr)
@@ -216,10 +216,10 @@ def log_tracked(self) -> None:
         else:
             rr.log(f"image/tracked/{self.tracking_id}", rr.Clear(recursive=False))  # TODO(#3381)
 
-    def update_with_detection(self, detection: Detection, bgr: npt.NDArray[np.uint8]) -> None:
+    def update_with_detection(self, detection: Detection, bgr: cv2.typing.MatLike) -> None:
         self.num_recent_undetected_frames = 0
         self.tracked = detection.scaled_to_fit_image(bgr)
-        self.tracker = cv2.TrackerCSRT_create()
+        self.tracker = cv2.TrackerCSRT_create()  # type: ignore[attr-defined]
         bbox_xywh_rounded = [int(val) for val in self.tracked.bbox_xywh]
         self.tracker.init(bgr, bbox_xywh_rounded)
         self.log_tracked()
@@ -285,7 +285,7 @@ def update_trackers_with_detections(
     trackers: list[Tracker],
     detections: Sequence[Detection],
     label_strs: Sequence[str],
-    bgr: npt.NDArray[np.uint8],
+    bgr: cv2.typing.MatLike,
 ) -> list[Tracker]:
     """
     Tries to match detections to existing trackers and updates the trackers if they match.
diff --git a/examples/python/face_tracking/main.py b/examples/python/face_tracking/main.py
index 4448270f8c8d..5d5a09c13a0c 100755
--- a/examples/python/face_tracking/main.py
+++ b/examples/python/face_tracking/main.py
@@ -14,7 +14,6 @@
 import cv2
 import mediapipe as mp
 import numpy as np
-import numpy.typing as npt
 import requests
 import rerun as rr  # pip install rerun-sdk
 import rerun.blueprint as rrb
@@ -124,7 +123,7 @@ def __init__(self, video_mode: bool = False):
             static=True,
         )
 
-    def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> None:
+    def detect_and_log(self, image: cv2.typing.MatLike, frame_time_nano: int) -> None:
         height, width, _ = image.shape
         image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image)
 
@@ -230,7 +229,7 @@ def __init__(self, video_mode: bool = False, num_faces: int = 1):
         # properly align the 3D face in the viewer
         rr.log("reconstruction", rr.ViewCoordinates.RDF, static=True)
 
-    def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> None:
+    def detect_and_log(self, image: cv2.typing.MatLike, frame_time_nano: int) -> None:
         height, width, _ = image.shape
         image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image)
 
diff --git a/examples/python/gesture_detection/main.py b/examples/python/gesture_detection/main.py
index 3f284315c296..c0c21e6f2cac 100755
--- a/examples/python/gesture_detection/main.py
+++ b/examples/python/gesture_detection/main.py
@@ -13,7 +13,6 @@
 import cv2
 import mediapipe as mp
 import numpy as np
-import numpy.typing as npt
 import requests
 import rerun as rr  # pip install rerun-sdk
 import rerun.blueprint as rrb
@@ -101,7 +100,7 @@ def convert_landmarks_to_image_coordinates(
     def convert_landmarks_to_3d(hand_landmarks: list[list[NormalizedLandmark]]) -> list[tuple[float, float, float]]:
         return [(lm.x, lm.y, lm.z) for hand_landmark in hand_landmarks for lm in hand_landmark]
 
-    def detect_and_log(self, image: npt.NDArray[np.uint8], frame_time_nano: int) -> None:
+    def detect_and_log(self, image: cv2.typing.MatLike, frame_time_nano: int) -> None:
         # Recognize gestures in the image
         height, width, _ = image.shape
         image = mp.Image(image_format=mp.ImageFormat.SRGB, data=image)
diff --git a/examples/python/raw_mesh/download_dataset.py b/examples/python/raw_mesh/download_dataset.py
index 1c92f48c3a0b..5d50b811d86f 100755
--- a/examples/python/raw_mesh/download_dataset.py
+++ b/examples/python/raw_mesh/download_dataset.py
@@ -93,7 +93,7 @@ def download(url: str, path: Path) -> None:
             resp = requests.get(url)
             resp.raise_for_status()
             os.makedirs(path.parent, exist_ok=True)
-            with open(path, "wb", encoding="utf8") as f:
+            with open(path, "wb") as f:
                 f.write(resp.content)
 
     name = name.lower()
diff --git a/examples/python/segment_anything_model/main.py b/examples/python/segment_anything_model/main.py
index 4eb278ecc724..24fe3eed4e7c 100755
--- a/examples/python/segment_anything_model/main.py
+++ b/examples/python/segment_anything_model/main.py
@@ -31,7 +31,6 @@
 import rerun.blueprint as rrb
 import torch
 import torchvision
-from cv2 import Mat
 from segment_anything import SamAutomaticMaskGenerator, sam_model_registry
 from segment_anything.modeling import Sam
 from tqdm import tqdm
@@ -89,7 +88,7 @@ def create_sam(model: str, device: str) -> Sam:
     return sam.to(device=device)
 
 
-def run_segmentation(mask_generator: SamAutomaticMaskGenerator, image: Mat) -> None:
+def run_segmentation(mask_generator: SamAutomaticMaskGenerator, image: cv2.typing.MatLike) -> None:
     """Run segmentation on a single image."""
     rr.log("image", rr.Image(image))
 
@@ -137,7 +136,7 @@ def is_url(path: str) -> bool:
         return False
 
 
-def load_image(image_uri: str) -> Mat:
+def load_image(image_uri: str) -> cv2.typing.MatLike:
     """Conditionally download an image from URL or load it from disk."""
     logging.info(f"Loading: {image_uri}")
     if is_url(image_uri):

From 0cc6c030ac9baa60203854b939b0c00e4fbe893a Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Wed, 17 Apr 2024 19:04:06 +0200
Subject: [PATCH 319/508] Bring back --debug for build web viewer tool (#6019)

### What

* fixes #6014

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6019?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6019?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6019)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 crates/re_dev_tools/src/build_web_viewer/mod.rs | 17 +++++++++++++++--
 pixi.toml                                       |  4 ++--
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/crates/re_dev_tools/src/build_web_viewer/mod.rs b/crates/re_dev_tools/src/build_web_viewer/mod.rs
index 0bc78827a32d..2c6b6f3c11f0 100644
--- a/crates/re_dev_tools/src/build_web_viewer/mod.rs
+++ b/crates/re_dev_tools/src/build_web_viewer/mod.rs
@@ -10,10 +10,18 @@ use lib::{build, default_build_dir, Profile, Target};
 #[argh(subcommand, name = "build-web-viewer")]
 pub struct Args {
     /// compile for release and run wasm-opt.
+    ///
+    /// Mutually exclusive with `--debug`.
     /// NOTE: --release also removes debug symbols which are otherwise useful for in-browser profiling.
     #[argh(switch)]
     release: bool,
 
+    /// compile for debug and don't run wasm-opt.
+    ///
+    /// Mutually exclusive with `--release`.
+    #[argh(switch)]
+    debug: bool,
+
     /// keep debug symbols, even in release builds.
     /// This gives better callstacks on panics, and also allows for in-browser profiling of the Wasm.
     #[argh(switch, short = 'g')]
@@ -29,11 +37,16 @@ pub struct Args {
 }
 
 pub fn main(args: Args) -> anyhow::Result<()> {
-    let profile = if args.release {
+    let profile = if args.release && !args.debug {
         Profile::Release
-    } else {
+    } else if !args.release && args.debug {
         Profile::Debug
+    } else {
+        return Err(anyhow::anyhow!(
+            "Exactly one of --release or --debug must be set"
+        ));
     };
+
     let target = if args.module {
         Target::Module
     } else {
diff --git a/pixi.toml b/pixi.toml
index 36d31751211a..056f4a3497e3 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -56,13 +56,13 @@ rerun-web = { cmd = "cargo run --package rerun-cli --no-default-features --featu
 #
 # This installs the `wasm32-unknown-unknown` rust target if it's not already installed.
 # (this looks heavy but takes typically below 0.1s!)
-rerun-build-web = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer"
+rerun-build-web = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer --debug"
 
 # Compile the web-viewer wasm and the cli.
 #
 # This installs the `wasm32-unknown-unknown` rust target if it's not already installed.
 # (this looks heavy but takes typically below 0.1s!)
-rerun-build-web-cli = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer && cargo build --package rerun-cli --no-default-features --features web_viewer"
+rerun-build-web-cli = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer --debug && cargo build --package rerun-cli --no-default-features --features web_viewer"
 
 # Compile and run the web-viewer in release mode via rerun-cli.
 #

From 2f45d1263244e5030c6cee016c27e646ef1fd4be Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Wed, 17 Apr 2024 19:05:05 +0200
Subject: [PATCH 320/508] Set default shell to bash for all ci jobs (#6023)

### What

Default shell varies per platform (windows uses powershell) which be
quite confusing on what you can put in `run` and what not! This sets the
default shell to bash everywhere.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6023?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6023?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6023)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .github/workflows/auto_approve.yml            |  6 ++++--
 .github/workflows/auto_release_crates.yml     |  5 ++++-
 .github/workflows/checkboxes.yml              |  5 ++++-
 .github/workflows/contrib_checks.yml          | 10 +++++-----
 .github/workflows/contrib_rerun_py.yml        | 12 ++++--------
 .github/workflows/nightly.yml                 |  6 ++++--
 .github/workflows/on_gh_release.yml           |  4 ++++
 .github/workflows/on_pr_comment.yml           |  6 ++++--
 .../on_pull_request_target_contrib.yml        |  5 ++++-
 .github/workflows/on_push_docs.yml            |  4 ++++
 .github/workflows/release.yml                 | 14 +++++---------
 .github/workflows/reusable_bench.yml          | 10 ++++------
 .../reusable_build_and_upload_rerun_c.yml     |  7 ++++---
 .../reusable_build_and_upload_rerun_cli.yml   |  8 ++++----
 .../reusable_build_and_upload_wheels.yml      |  8 ++++----
 .github/workflows/reusable_build_examples.yml | 10 ++++------
 .github/workflows/reusable_build_js.yml       |  6 ++++--
 .github/workflows/reusable_build_web.yml      |  6 ++++--
 .../reusable_bundle_and_upload_rerun_cpp.yml  |  7 ++++---
 .github/workflows/reusable_checks.yml         |  6 ++++--
 .github/workflows/reusable_checks_cpp.yml     |  9 ++++-----
 .github/workflows/reusable_checks_python.yml  |  5 ++++-
 .github/workflows/reusable_checks_rust.yml    |  4 ++++
 .github/workflows/reusable_deploy_docs.yml    | 19 ++++---------------
 .../reusable_deploy_landing_preview.yml       |  5 ++++-
 .github/workflows/reusable_pip_index.yml      |  6 ++++--
 .github/workflows/reusable_pr_summary.yml     |  5 ++++-
 .github/workflows/reusable_publish_js.yml     |  7 ++++---
 .github/workflows/reusable_publish_web.yml    | 13 ++++---------
 .github/workflows/reusable_publish_wheels.yml |  7 ++++---
 .github/workflows/reusable_release_crates.yml |  4 ++++
 .github/workflows/reusable_run_notebook.yml   |  7 ++++---
 .../reusable_sync_release_assets.yml          |  5 ++++-
 .github/workflows/reusable_test_wheels.yml    | 14 ++++++--------
 .github/workflows/reusable_track_size.yml     |  9 ++++-----
 .github/workflows/reusable_update_pr_body.yml |  5 ++++-
 .../workflows/reusable_upload_examples.yml    |  5 ++++-
 .github/workflows/reusable_upload_web.yml     |  5 ++++-
 38 files changed, 156 insertions(+), 123 deletions(-)

diff --git a/.github/workflows/auto_approve.yml b/.github/workflows/auto_approve.yml
index fa7fe8c80b9c..98cfa3423233 100644
--- a/.github/workflows/auto_approve.yml
+++ b/.github/workflows/auto_approve.yml
@@ -5,6 +5,10 @@ on:
   issue_comment:
     types: [created, edited]
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   actions: "write"
@@ -25,13 +29,11 @@ jobs:
           pixi-version: v0.18.0
 
       - name: Wait a few seconds
-        shell: bash
         run: |
           # Give GitHub a bit of time to synchronize everything
           sleep 5s
 
       - name: Approve workflow runs
-        shell: bash
         run: |
           pixi run python scripts/ci/approve_workflow_runs.py \
             --github-token "${{ secrets.GITHUB_TOKEN }}" \
diff --git a/.github/workflows/auto_release_crates.yml b/.github/workflows/auto_release_crates.yml
index 5ef698569697..f31e21be1927 100644
--- a/.github/workflows/auto_release_crates.yml
+++ b/.github/workflows/auto_release_crates.yml
@@ -7,6 +7,10 @@ on:
   push:
     branches: [main]
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: write
   id-token: "write"
@@ -31,7 +35,6 @@ jobs:
 
       - name: Get bumped version
         id: versioning
-        shell: bash
         run: |
           crate_version=$(pixi run python scripts/ci/crates.py get-version)
           echo "crate_version=$crate_version" >> "$GITHUB_OUTPUT"
diff --git a/.github/workflows/checkboxes.yml b/.github/workflows/checkboxes.yml
index f229de7a768f..a1bdfcea6577 100644
--- a/.github/workflows/checkboxes.yml
+++ b/.github/workflows/checkboxes.yml
@@ -14,6 +14,10 @@ concurrency:
   group: ${{ github.event.pull_request.number }}-pr-checkboxes
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   pull-requests: "write"
@@ -33,7 +37,6 @@ jobs:
           pixi-version: v0.18.0
 
       - name: Check PR checkboxes
-        shell: bash
         run: |
           pixi run ./scripts/ci/check_pr_checkboxes.py \
             --github-token ${{ secrets.GITHUB_TOKEN }} \
diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml
index 18bac34afa00..10d67b40eda6 100644
--- a/.github/workflows/contrib_checks.yml
+++ b/.github/workflows/contrib_checks.yml
@@ -36,6 +36,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
 
@@ -84,9 +88,7 @@ jobs:
           pixi-version: v0.19.0
 
       - name: Codegen check
-        shell: bash
-        run: |
-          pixi run codegen --force --check
+        run: pixi run codegen --force --check
 
   rs-lints:
     name: Rust lints (fmt, check, cranky, tests, doc)
@@ -157,14 +159,12 @@ jobs:
       # > Compiler: GNU 12.3.0 (/__w/rerun/rerun/.pixi/env/bin/x86_64-conda-linux-gnu-c++)
       # 😭
       # - name: Build and run C++ tests with clang++
-      #   shell: bash
       #   run: |
       #     pixi run cpp-clean
       #     RERUN_WERROR=ON RERUN_USE_ASAN=ON CXX=clang++ pixi run cpp-build-all
       #     RERUN_WERROR=ON RERUN_USE_ASAN=ON CXX=clang++ pixi run cpp-test
 
       - name: Build and run C++ tests with g++
-        shell: bash
         run: |
           pixi run cpp-clean
           RERUN_WERROR=ON RERUN_USE_ASAN=ON CXX=g++ pixi run cpp-build-all
diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml
index 5fb22ddb4281..5a079ded93cf 100644
--- a/.github/workflows/contrib_rerun_py.yml
+++ b/.github/workflows/contrib_rerun_py.yml
@@ -40,6 +40,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
 
@@ -73,7 +77,6 @@ jobs:
 
       - name: Get version
         id: get-version
-        shell: bash
         run: |
           echo "wheel_version=$(python3 scripts/ci/crates.py get-version)" >> "$GITHUB_OUTPUT"
 
@@ -81,28 +84,23 @@ jobs:
         # Now install the wheel using a specific version and --no-index to guarantee we get the version from
         # the pre-dist folder. Note we don't use --force-reinstall here because --no-index means it wouldn't
         # find the dependencies to reinstall them.
-        shell: bash
         run: |
           pixi run -e wheel-test pip uninstall rerun-sdk
           pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links dist
 
       - name: Print wheel version
-        shell: bash
         run: |
           pixi run -e wheel-test python -m rerun --version
           pixi run -e wheel-test which rerun
           pixi run -e wheel-test rerun --version
 
       - name: Run Python unit-tests
-        shell: bash
         run: pixi run -e wheel-test cd rerun_py/tests && pixi run -e wheel-test pytest -c ../pyproject.toml
 
       - name: Run e2e test
-        shell: bash
         run: pixi run -e wheel-test RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed
 
       - name: Run tests/roundtrips.py
-        shell: bash
         # --release so we can inherit from some of the artifacts that maturin has just built before
         # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow…
         # --no-py-build because rerun-sdk is already built and installed
@@ -110,7 +108,6 @@ jobs:
           pixi run -e wheel-test RUST_LOG=debug tests/roundtrips.py --release --target x86_64-unknown-linux-gnu --no-py-build
 
       - name: Run docs/snippets/compare_snippet_output.py
-        shell: bash
         # --release so we can inherit from some of the artifacts that maturin has just built before
         # --target x86_64-unknown-linux-gnu because otherwise cargo loses the target cache… even though this is the target anyhow…
         # --no-py-build because rerun-sdk is already built and installed
@@ -126,7 +123,6 @@ jobs:
           key: structure-from-motion-dataset-structure-from-motion-fiat-v1
 
       - name: Generate Embedded RRD file
-        shell: bash
         # If you change the line below you should almost definitely change the `key:` line above by giving it a new, unique name
         run: |
           mkdir rrd
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index ffd5d04334aa..97cbd746f7bf 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -7,6 +7,10 @@ on:
     # 12:15 UTC, every day
     - cron: "15 12 * * *"
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   checks:
     name: Checks
@@ -52,7 +56,6 @@ jobs:
           toolchain: 1.76.0
 
       - run: cargo build -p rerun
-        shell: bash
 
   build-web:
     name: "Build web viewer"
@@ -374,7 +377,6 @@ jobs:
     runs-on: "ubuntu-latest"
     steps:
       - name: Add SHORT_SHA env property with commit short sha
-        shell: bash
         run: echo "SHORT_SHA=`echo ${{github.sha}} | cut -c1-7`" >> $GITHUB_ENV
 
       # First delete the old prerelease. If we don't do this, we don't get things like
diff --git a/.github/workflows/on_gh_release.yml b/.github/workflows/on_gh_release.yml
index 79b3075df46a..837e657928ad 100644
--- a/.github/workflows/on_gh_release.yml
+++ b/.github/workflows/on_gh_release.yml
@@ -17,6 +17,10 @@ concurrency:
   group: "release-${{ github.event.release.tag_name }}"
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   # required for updating the release
   contents: write
diff --git a/.github/workflows/on_pr_comment.yml b/.github/workflows/on_pr_comment.yml
index 0734c65d7b62..5ebe8718c59d 100644
--- a/.github/workflows/on_pr_comment.yml
+++ b/.github/workflows/on_pr_comment.yml
@@ -10,6 +10,10 @@ on:
   issue_comment:
     types: [created, edited]
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   parse-command:
     if: |
@@ -21,7 +25,6 @@ jobs:
     steps:
       - name: Parse comment
         id: parse
-        shell: bash
         run: |
           # Parse `@rerun-bot `
           command=$(echo "${{ github.event.comment.body }}" | sed -n 's/.*@rerun-bot[[:space:]]\+\([a-zA-Z\-]*\).*/\1/p')
@@ -37,7 +40,6 @@ jobs:
 
       - name: Dispatch main workflow
         id: dispatch
-        shell: bash
         env:
           # NOTE: This uses `RERUN_BOT_TOKEN` instead of `GITHUB_TOKEN`,
           # otherwise the recursive workflow protection prevents us from
diff --git a/.github/workflows/on_pull_request_target_contrib.yml b/.github/workflows/on_pull_request_target_contrib.yml
index 23fb8a59a5b9..c79b62bac88c 100644
--- a/.github/workflows/on_pull_request_target_contrib.yml
+++ b/.github/workflows/on_pull_request_target_contrib.yml
@@ -10,6 +10,10 @@ on:
       - opened
       - synchronize
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   pull-requests: "write" # Updates PR body
@@ -28,7 +32,6 @@ jobs:
           pixi-version: v0.19.0
 
       - name: Update PR description
-        shell: bash
         run: |
           pixi run ./scripts/ci/update_pr_body.py \
             --github-token '${{ secrets.GITHUB_TOKEN }}' \
diff --git a/.github/workflows/on_push_docs.yml b/.github/workflows/on_push_docs.yml
index 442e87c8582b..01c77b476955 100644
--- a/.github/workflows/on_push_docs.yml
+++ b/.github/workflows/on_push_docs.yml
@@ -8,6 +8,10 @@ concurrency:
   group: on-push-docs
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   redeploy-rerun-io:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 113d13a09829..9b22a543a396 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -16,6 +16,10 @@ concurrency:
   group: ${{ github.ref_name }}
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 permissions: # wants to push commits and create a PR
   contents: write
   id-token: write
@@ -84,7 +88,6 @@ jobs:
 
       - name: Update crate versions
         id: versioning
-        shell: bash
         run: |
           echo Check that the release version matches expected format…
           pixi run python scripts/ci/crates.py check-git-branch-name
@@ -128,23 +131,20 @@ jobs:
           echo "final=$final"       >> "$GITHUB_OUTPUT"
 
       - name: Update JS package versions
-        shell: bash
         run: |
           pixi run node rerun_js/scripts/version.mjs "${{ steps.versioning.outputs.current }}"
 
       - name: Update rerun_c version
-        shell: bash
+
         # Configuring CMake is enough to change the version on rerun.h!
         run: |
           cmake -B build -S .
 
       - run: pixi run toml-fmt
-        shell: bash
 
       - name: Commit new version
         id: commit
         if: steps.versioning.outputs.previous != steps.versioning.outputs.current
-        shell: bash
         run: |
           git pull
           git config --global user.name "rerun-bot"
@@ -156,7 +156,6 @@ jobs:
       - name: Create pull request
         env:
           GH_TOKEN: ${{ secrets.RERUN_BOT_TOKEN }}
-        shell: bash
         run: |
           set +e
           pr=$(gh pr view --json headRefName 2>/dev/null || echo "{}")
@@ -300,7 +299,6 @@ jobs:
           ref: ${{ needs.version.outputs.release-commit }}
 
       - name: Update latest branch
-        shell: bash
         run: |
           git fetch
           git checkout ${{ github.ref_name }}
@@ -384,7 +382,6 @@ jobs:
           pixi-version: v0.19.0
 
       - name: Commit new version
-        shell: bash
         run: |
           # checkout + pull changes
           git config --global user.name "rerun-bot"
@@ -424,7 +421,6 @@ jobs:
       - name: Create comment
         env:
           GH_TOKEN: ${{ secrets.RERUN_BOT_TOKEN }}
-        shell: bash
         run: |
           pr_number=$(gh pr view --json number | jq '.number')
           echo "pr_number: $pr_number"
diff --git a/.github/workflows/reusable_bench.yml b/.github/workflows/reusable_bench.yml
index 751132abe5ae..14b29302b683 100644
--- a/.github/workflows/reusable_bench.yml
+++ b/.github/workflows/reusable_bench.yml
@@ -44,6 +44,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   # ---------------------------------------------------------------------------
 
@@ -75,12 +79,10 @@ jobs:
           service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }}
 
       - name: Add SHORT_SHA env property with commit short sha
-        shell: bash
         run: echo "SHORT_SHA=`echo ${{github.sha}} | cut -c1-7`" >> $GITHUB_ENV
 
       - name: Run benchmark
         # Use bash shell so we get pipefail behavior with tee
-        shell: bash
         run: |
           cargo bench \
             --all-features \
@@ -105,7 +107,6 @@ jobs:
 
       - name: Download comparison bench from GCS
         if: ${{ inputs.COMPARE_TO != '' }}
-        shell: bash
         run: |
           mkdir /tmp/compare/
           gsutil cp gs://rerun-builds/benches/${{inputs.COMPARE_TO}} /tmp/compare/${{ inputs.COMPARE_TO }}
@@ -115,7 +116,6 @@ jobs:
 
       - name: Compare results with benchcmp
         if: ${{ inputs.COMPARE_TO != '' }}
-        shell: bash
         run: cargo benchcmp /tmp/compare/${{ inputs.COMPARE_TO }} /tmp/${{ env.SHORT_SHA }} > /tmp/bench_results.txt
 
       - name: "Upload bench-results to GCS"
@@ -127,7 +127,6 @@ jobs:
 
       - name: "Copy bench to named file"
         if: ${{ inputs.BENCH_NAME != '' }}
-        shell: bash
         run: cp /tmp/${{ env.SHORT_SHA }} /tmp/${{ inputs.BENCH_NAME }}
 
       # Don't upload the new named bench until the end in case the names are the same
@@ -159,7 +158,6 @@ jobs:
 
       - name: Render benchmark result
         if: github.ref == 'refs/heads/main'
-        shell: bash
         run: |
           python3 -m pip install google-cloud-storage==2.9.0
           scripts/ci/render_bench.py crates \
diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml
index df0c75dcae91..2dd930c6f314 100644
--- a/.github/workflows/reusable_build_and_upload_rerun_c.yml
+++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml
@@ -65,6 +65,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   id-token: "write"
@@ -81,7 +85,6 @@ jobs:
     steps:
       - name: Set runner and target based on platform
         id: set-config
-        shell: bash
         run: |
           case "${{ inputs.PLATFORM }}" in
             linux-arm64)
@@ -135,7 +138,6 @@ jobs:
 
     steps:
       - name: Show context
-        shell: bash
         run: |
           echo "GITHUB_CONTEXT": $GITHUB_CONTEXT
           echo "JOB_CONTEXT": $JOB_CONTEXT
@@ -168,7 +170,6 @@ jobs:
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha) }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"
diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml
index 35e98d6839b3..894c7b615f54 100644
--- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml
+++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml
@@ -66,6 +66,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   id-token: "write"
@@ -82,7 +86,6 @@ jobs:
     steps:
       - name: Set runner and target based on platform
         id: set-config
-        shell: bash
         run: |
           case "${{ inputs.PLATFORM }}" in
             linux-arm64)
@@ -136,7 +139,6 @@ jobs:
 
     steps:
       - name: Show context
-        shell: bash
         run: |
           echo "GITHUB_CONTEXT": $GITHUB_CONTEXT
           echo "JOB_CONTEXT": $JOB_CONTEXT
@@ -171,7 +173,6 @@ jobs:
       # This does not run in the pixi environment, doing so
       # causes it to select the wrong compiler on macos-arm64
       - name: Build rerun-cli
-        shell: bash
         env:
           # this stops `re_web_viewer_server/build.rs` from running
           RERUN_IS_PUBLISHING: true
@@ -186,7 +187,6 @@ jobs:
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha) }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"
diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml
index 9ee496f844aa..a419ab9f9bc1 100644
--- a/.github/workflows/reusable_build_and_upload_wheels.yml
+++ b/.github/workflows/reusable_build_and_upload_wheels.yml
@@ -86,6 +86,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   id-token: "write"
@@ -104,7 +108,6 @@ jobs:
     steps:
       - name: Set runner and target based on platform
         id: set-config
-        shell: bash
         run: |
           case "${{ inputs.PLATFORM }}" in
             linux-arm64)
@@ -160,7 +163,6 @@ jobs:
 
     steps:
       - name: Show context
-        shell: bash
         run: |
           echo "GITHUB_CONTEXT": $GITHUB_CONTEXT
           echo "JOB_CONTEXT": $JOB_CONTEXT
@@ -192,13 +194,11 @@ jobs:
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.ref) || github.sha) }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"
 
       - name: Build
-        shell: bash
         run: |
           pixi run python scripts/ci/build_and_upload_wheels.py \
             --mode ${{ inputs.MODE }} \
diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml
index 2f122bed33b7..d2ef5e174a01 100644
--- a/.github/workflows/reusable_build_examples.yml
+++ b/.github/workflows/reusable_build_examples.yml
@@ -37,6 +37,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   rs-build-examples:
     name: Build Examples
@@ -71,20 +75,17 @@ jobs:
           path: wheel
 
       - name: Install example dependencies
-        shell: bash
         run: |
           pixi run -e wheel-test pip install \
             -r scripts/ci/requirements-examples-${{ inputs.CHANNEL }}.txt \
             --no-input
 
       - name: Install built wheel
-        shell: bash
         run: |
           pixi run -e wheel-test pip uninstall rerun-sdk -y
           pixi run -e wheel-test pip install rerun-sdk --no-index --find-links wheel
 
       - name: Print wheel version
-        shell: bash
         run: |
           pixi run -e wheel-test python -m rerun --version
           pixi run -e wheel-test which rerun
@@ -92,20 +93,17 @@ jobs:
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"
 
       - name: Build examples
-        shell: bash
         run: |
           pixi run -e wheel-test build-examples rrd \
             --channel ${{ inputs.CHANNEL }} \
             example_data
 
       - name: Build snippets
-        shell: bash
         run: |
           pixi run -e wheel-test build-examples snippets \
             example_data/snippets
diff --git a/.github/workflows/reusable_build_js.yml b/.github/workflows/reusable_build_js.yml
index 774c1c9e99ef..01e2989a36b5 100644
--- a/.github/workflows/reusable_build_js.yml
+++ b/.github/workflows/reusable_build_js.yml
@@ -31,6 +31,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   build:
     name: Build rerun_js
@@ -66,9 +70,7 @@ jobs:
           pixi-version: v0.19.0
 
       - name: Install yarn dependencies
-        shell: bash
         run: pixi run yarn --cwd rerun_js install
 
       - name: Build rerun_js package
-        shell: bash
         run: pixi run yarn --cwd rerun_js workspaces run build
diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml
index e1f8a863fedd..ed7726014280 100644
--- a/.github/workflows/reusable_build_web.yml
+++ b/.github/workflows/reusable_build_web.yml
@@ -38,6 +38,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   rs-build-web-viewer:
     name: Build web viewer
@@ -66,7 +70,6 @@ jobs:
           pixi-version: v0.19.0
 
       - name: Build web-viewer (release)
-        shell: bash
         run: |
           if [ ${{ inputs.CHANNEL }} = "nightly" ]; then
             export DEFAULT_EXAMPLES_MANIFEST_URL="https://app.rerun.io/version/nightly/examples_manifest.json"
@@ -76,7 +79,6 @@ jobs:
       # We build a single manifest pointing to the `commit`
       # All the `pr`, `main`, release tag, etc. variants will always just point to the resolved commit
       - name: Build examples manifest
-        shell: bash
         run: |
           full_commit="${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha }}"
           sha="$(echo $full_commit | cut -c1-7)"
diff --git a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml
index ca531b4e0a30..050a51c7dcb0 100644
--- a/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml
+++ b/.github/workflows/reusable_bundle_and_upload_rerun_cpp.yml
@@ -18,6 +18,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-bundle-and-upload-rerun-cpp
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   bundle-and-upload-rerun_cpp:
     name: Bundle and upload rerun_cpp_sdk.zip
@@ -49,17 +53,14 @@ jobs:
           version: ">= 363.0.0"
 
       - name: Install python gcs library
-        shell: bash
         run: |
           python3 -m pip install google-cloud-storage
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha) }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"
 
       - name: "Bundle and upload rerun_cpp_sdk.zip"
-        shell: bash
         run: python3 ./scripts/ci/bundle_and_upload_rerun_cpp.py --git-hash ${{ steps.get-sha.outputs.sha }} --platform-filter=${{ inputs.PLATFORM_FILTER }}
diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml
index 5692a7164894..bd1ab1cd298d 100644
--- a/.github/workflows/reusable_checks.yml
+++ b/.github/workflows/reusable_checks.yml
@@ -32,10 +32,13 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   id-token: "write"
-
 jobs:
   py-test-docs:
     name: Test Python Docs
@@ -77,7 +80,6 @@ jobs:
           pixi-version: v0.19.0
 
       - name: Codegen check
-        shell: bash
         run: |
           pixi run codegen --force --check
 
diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml
index 125fc56eebfe..07911278af8b 100644
--- a/.github/workflows/reusable_checks_cpp.yml
+++ b/.github/workflows/reusable_checks_cpp.yml
@@ -40,6 +40,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   id-token: "write"
@@ -55,7 +59,6 @@ jobs:
           ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }}
       - name: Load C++ test matrix
         id: set-matrix
-        shell: bash
         run: |
           echo "Full matrix: ${{ inputs.FULL }}"
           if ${{ inputs.FULL }}; then
@@ -98,19 +101,15 @@ jobs:
         run: sudo sysctl vm.mmap_rnd_bits=28
 
       - name: pixi run cpp-clean
-        shell: bash
         run: pixi run cpp-clean
 
       - name: pixi run cpp-build-all
-        shell: bash
         run: ${{ matrix.extra_env_vars }} RERUN_WERROR=ON pixi run cpp-build-all
 
       - name: pixi run cpp-test
-        shell: bash
         run: ${{ matrix.extra_env_vars }} RERUN_WERROR=ON pixi run cpp-test
 
       - name: additional_commands
-        shell: bash
         run: ${{ matrix.additional_commands }}
 
   cpp-formatting:
diff --git a/.github/workflows/reusable_checks_python.yml b/.github/workflows/reusable_checks_python.yml
index 2a682ba610a3..7d70ff6f7d2a 100644
--- a/.github/workflows/reusable_checks_python.yml
+++ b/.github/workflows/reusable_checks_python.yml
@@ -14,6 +14,10 @@ concurrency:
 env:
   PYTHON_VERSION: "3.8"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   id-token: "write"
@@ -55,6 +59,5 @@ jobs:
           environments: py-docs
 
       - name: Build via mkdocs
-        shell: bash
         run: |
           pixi run -e py-docs mkdocs build --strict -f rerun_py/mkdocs.yml
diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml
index 7044158007d2..a4084020e17b 100644
--- a/.github/workflows/reusable_checks_rust.yml
+++ b/.github/workflows/reusable_checks_rust.yml
@@ -35,6 +35,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   id-token: "write"
diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml
index d38ddf52a5e3..fd8a49b1862e 100644
--- a/.github/workflows/reusable_deploy_docs.yml
+++ b/.github/workflows/reusable_deploy_docs.yml
@@ -30,6 +30,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-deploy-docs
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "write"
   id-token: "write"
@@ -74,7 +78,6 @@ jobs:
           environments: py-docs
 
       - name: Set up git author
-        shell: bash
         run: |
           remote_repo="https://${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
           git config --global user.name "${GITHUB_ACTOR}"
@@ -87,7 +90,6 @@ jobs:
       # to make sure we don't accumulate unnecessary history in gh-pages branch
       - name: Deploy via mike # https://github.com/jimporter/mike
         if: ${{ inputs.UPDATE_LATEST }}
-        shell: bash
         run: |
           git fetch
           pixi run -e py-docs mike deploy -F rerun_py/mkdocs.yml --rebase -b gh-pages --prefix docs/python -u ${{inputs.PY_DOCS_VERSION_NAME}} stable
@@ -101,7 +103,6 @@ jobs:
       # to make sure we don't accumulate unnecessary history in gh-pages branch
       - name: Deploy tag via mike # https://github.com/jimporter/mike
         if: ${{ ! inputs.UPDATE_LATEST }}
-        shell: bash
         run: |
           git fetch
           pixi run -e py-docs mike deploy -F rerun_py/mkdocs.yml --rebase -b gh-pages --prefix docs/python ${{inputs.PY_DOCS_VERSION_NAME}}
@@ -118,7 +119,6 @@ jobs:
     runs-on: ubuntu-latest-16-cores
     steps:
       - name: Show context
-        shell: bash
         run: |
           echo "GITHUB_CONTEXT": $GITHUB_CONTEXT
           echo "JOB_CONTEXT": $JOB_CONTEXT
@@ -145,7 +145,6 @@ jobs:
           service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }}
 
       - name: Delete existing /target/doc
-        shell: bash
         run: rm -rf ./target/doc
 
       - name: cargo doc --document-private-items
@@ -155,7 +154,6 @@ jobs:
           args: --document-private-items --no-deps --all-features --workspace --exclude rerun-cli
 
       - name: Set up git author
-        shell: bash
         run: |
           remote_repo="https://${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
           git config --global user.name "${GITHUB_ACTOR}"
@@ -164,18 +162,15 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
       - name: Set up ghp-import
-        shell: bash
         run: pip install ghp-import
 
       - name: Patch in a redirect page
-        shell: bash
         run: echo "" > target/doc/index.html
         env:
           REDIRECT_CRATE: rerun
 
       # See: https://github.com/c-w/ghp-import
       - name: Deploy the docs
-        shell: bash
         run: |
           git fetch
           python3 -m ghp_import -n -p -x docs/rust/${{ inputs.RS_DOCS_VERSION_NAME }} target/doc/ -m "Update the rust docs"
@@ -186,7 +181,6 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Show context
-        shell: bash
         run: |
           echo "GITHUB_CONTEXT": $GITHUB_CONTEXT
           echo "JOB_CONTEXT": $JOB_CONTEXT
@@ -208,11 +202,9 @@ jobs:
           pixi-version: v0.19.0
 
       - name: Doxygen C++ docs
-        shell: bash
         run: pixi run cpp-docs
 
       - name: Set up git author
-        shell: bash
         run: |
           remote_repo="https://${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
           git config --global user.name "${GITHUB_ACTOR}"
@@ -221,7 +213,6 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
       - name: Set up ghp-import
-        shell: bash
         run: pip install ghp-import
 
         # TODO(andreas): Do we need this?
@@ -234,13 +225,11 @@ jobs:
       # See: https://github.com/c-w/ghp-import
       - name: Deploy the docs (versioned)
         if: ${{ inputs.RELEASE_VERSION }}
-        shell: bash
         run: |
           git fetch
           python3 -m ghp_import -n -p -x docs/cpp/${{ inputs.RELEASE_VERSION }} rerun_cpp/docs/html/ -m "Update the C++ docs (versioned)"
 
       - name: Deploy the docs (named)
-        shell: bash
         run: |
           git fetch
           python3 -m ghp_import -n -p -x docs/cpp/${{ inputs.CPP_DOCS_VERSION_NAME }} rerun_cpp/docs/html/ -m "Update the C++ docs"
diff --git a/.github/workflows/reusable_deploy_landing_preview.yml b/.github/workflows/reusable_deploy_landing_preview.yml
index dcdcb165ad5d..3ae87315b530 100644
--- a/.github/workflows/reusable_deploy_landing_preview.yml
+++ b/.github/workflows/reusable_deploy_landing_preview.yml
@@ -14,6 +14,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-deploy-landing-preview
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "write"
   id-token: "write"
@@ -32,7 +36,6 @@ jobs:
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha }}"
           echo "sha=$full_commit" >> "$GITHUB_OUTPUT"
diff --git a/.github/workflows/reusable_pip_index.yml b/.github/workflows/reusable_pip_index.yml
index 6c177a18b781..924e565872dc 100644
--- a/.github/workflows/reusable_pip_index.yml
+++ b/.github/workflows/reusable_pip_index.yml
@@ -15,6 +15,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-pip-index
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   pr-summary:
     name: Create a Pip Index file
@@ -48,11 +52,9 @@ jobs:
           version: ">= 363.0.0"
 
       - name: Install deps
-        shell: bash
         run: pip install google-cloud-storage Jinja2
 
       - name: Render pip index and upload to gcloud
-        shell: bash
         run: |
           full_commit="${{ inputs.COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha) }}"
           commit=$(echo $full_commit | cut -c1-7)
diff --git a/.github/workflows/reusable_pr_summary.yml b/.github/workflows/reusable_pr_summary.yml
index 34e4b0853d1e..8fa2a0b3cab8 100644
--- a/.github/workflows/reusable_pr_summary.yml
+++ b/.github/workflows/reusable_pr_summary.yml
@@ -14,6 +14,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-pr-summary
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   pr-summary:
     name: Create HTML summary for PR
@@ -47,7 +51,6 @@ jobs:
           version: ">= 363.0.0"
 
       - name: Render HTML template
-        shell: bash
         run: |
           pixi run python scripts/ci/generate_pr_summary.py \
           --github-token ${{secrets.GITHUB_TOKEN}} \
diff --git a/.github/workflows/reusable_publish_js.yml b/.github/workflows/reusable_publish_js.yml
index e98a96214413..99e560d69175 100644
--- a/.github/workflows/reusable_publish_js.yml
+++ b/.github/workflows/reusable_publish_js.yml
@@ -15,6 +15,10 @@ concurrency:
   group: ${{ inputs.concurrency }}-publish-js
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "write"
   id-token: "write"
@@ -29,12 +33,10 @@ jobs:
     steps:
       - name: "Set short-sha"
         id: get-short-sha
-        shell: bash
         run: echo "short-sha=$(echo ${{ inputs.release-commit }} | cut -c1-7)" >> $GITHUB_OUTPUT
 
       - name: "Set full-sha"
         id: get-full-sha
-        shell: bash
         run: echo "full-sha=${{ inputs.release-commit }}" >> $GITHUB_OUTPUT
 
   build:
@@ -68,6 +70,5 @@ jobs:
       - name: Publish packages
         env:
           NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
-        shell: bash
         run: |
           pixi run node rerun_js/scripts/publish.mjs
diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml
index 5ef2daadd9f8..00f8a9768c80 100644
--- a/.github/workflows/reusable_publish_web.yml
+++ b/.github/workflows/reusable_publish_web.yml
@@ -23,6 +23,10 @@ on:
         type: boolean
         required: true
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "write"
   id-token: "write"
@@ -37,12 +41,10 @@ jobs:
     steps:
       - name: "Set short-sha"
         id: get-short-sha
-        shell: bash
         run: echo "short-sha=$(echo ${{ inputs.release-commit }} | cut -c1-7)" >> $GITHUB_OUTPUT
 
       - name: "Set full-sha"
         id: get-full-sha
-        shell: bash
         run: echo "full-sha=${{ inputs.release-commit }}" >> $GITHUB_OUTPUT
 
   build-web:
@@ -85,40 +87,34 @@ jobs:
           path: wheel
 
       - name: Install example dependencies
-        shell: bash
         run: |
           pixi run pip install \
             -r scripts/ci/requirements-examples-nightly.txt \
             --no-input
 
       - name: Install Python dependencies and wheel
-        shell: bash
         run: |
           pixi -e wheel-test run pip uninstall rerun-sdk -y
           pixi -e wheel-test run pip install deprecated '"numpy>=1.23,<2"' pyarrow>=14.0.2 pytest==7.1.2
           pixi -e wheel-test run pip install rerun-sdk --no-index --find-links wheel
 
       - name: Installed wheel version
-        shell: bash
         run: |
           pixi -e wheel-test run python -m rerun --version
           pixi -e wheel-test run which rerun
           pixi -e wheel-test run rerun --version
 
       - name: Build web-viewer (release)
-        shell: bash
         run: |
           pixi -e wheel-test run rerun-build-web-release
 
       - name: Build examples
-        shell: bash
         run: |
           pixi -e wheel-test run build-examples rrd \
             --channel "release" \
             web_viewer/examples
 
       - name: Build examples manifest
-        shell: bash
         run: |
           pixi -e wheel-test run build-examples manifest \
             --base-url "https://app.rerun.io/version/${{inputs.release-version}}" \
@@ -141,6 +137,5 @@ jobs:
 
       - name: Publish app.rerun.io
         if: inputs.update-latest
-        shell: bash
         run: |
           gsutil -m cp -r 'gs://rerun-web-viewer/version/${{ inputs.release-version }}/*' gs://rerun-web-viewer/version/latest
diff --git a/.github/workflows/reusable_publish_wheels.yml b/.github/workflows/reusable_publish_wheels.yml
index 8b87e372c091..78cf634da862 100644
--- a/.github/workflows/reusable_publish_wheels.yml
+++ b/.github/workflows/reusable_publish_wheels.yml
@@ -20,6 +20,10 @@ on:
         type: string
         required: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   get-commit-sha:
     name: Get Commit Sha
@@ -30,12 +34,10 @@ jobs:
     steps:
       - name: "Set short-sha"
         id: get-short-sha
-        shell: bash
         run: echo "short-sha=$(echo ${{ inputs.release-commit }} | cut -c1-7)" >> $GITHUB_OUTPUT
 
       - name: "Set full-sha"
         id: get-full-sha
-        shell: bash
         run: echo "full-sha=${{ inputs.release-commit }}" >> $GITHUB_OUTPUT
 
   ## Build
@@ -167,7 +169,6 @@ jobs:
           version: ">= 363.0.0"
 
       - name: Publish to PyPI
-        shell: bash
         run: |
           pixi run python scripts/ci/publish_wheels.py \
             --version ${{ inputs.release-version }} \
diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml
index 63ad82f3bed1..d0490a73b436 100644
--- a/.github/workflows/reusable_release_crates.yml
+++ b/.github/workflows/reusable_release_crates.yml
@@ -14,6 +14,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-release-crates
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   publish-crates:
     name: "Publish Crates"
diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml
index 795a3a22267a..4d1b02827ca7 100644
--- a/.github/workflows/reusable_run_notebook.yml
+++ b/.github/workflows/reusable_run_notebook.yml
@@ -15,6 +15,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-run-notebook
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   run-notebook:
     name: Run notebook
@@ -46,7 +50,6 @@ jobs:
 
       - name: Get version
         id: get-version
-        shell: bash
         run: |
           pixi run -e wheel-test 'echo "wheel_version=$(python scripts/ci/crates.py get-version)"' >> "$GITHUB_OUTPUT"
 
@@ -54,7 +57,6 @@ jobs:
         # Now install the wheel using a specific version and --no-index to guarantee we get the version from
         # the pre-dist folder. Note we don't use --force-reinstall here because --no-index means it wouldn't
         # find the dependencies to reinstall them.
-        shell: bash
         run: |
           pixi run -e wheel-test pip uninstall rerun-sdk
           pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links wheel
@@ -73,7 +75,6 @@ jobs:
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"
diff --git a/.github/workflows/reusable_sync_release_assets.yml b/.github/workflows/reusable_sync_release_assets.yml
index ba0623ef2b7d..cc8a1c56bd7b 100644
--- a/.github/workflows/reusable_sync_release_assets.yml
+++ b/.github/workflows/reusable_sync_release_assets.yml
@@ -19,6 +19,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-sync-assets
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   sync-assets:
     name: Upload assets from build.rerun.io
@@ -51,7 +55,6 @@ jobs:
           version: ">= 363.0.0"
 
       - name: Sync release assets & build.rerun.io
-        shell: bash
         run: |
           pixi run python ./scripts/ci/sync_release_assets.py \
             --github-release ${{ inputs.RELEASE_VERSION }} \
diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml
index 5d5b15bdeed4..563ed878e3fe 100644
--- a/.github/workflows/reusable_test_wheels.yml
+++ b/.github/workflows/reusable_test_wheels.yml
@@ -50,6 +50,10 @@ env:
   # these incremental artifacts when running on CI.
   CARGO_INCREMENTAL: "0"
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: "read"
   id-token: "write"
@@ -67,7 +71,7 @@ jobs:
     steps:
       - name: Set runner and target based on platform
         id: set-config
-        shell: bash
+
         # TODO(#5525): at least this target is broken, maybe others — we currently only use linux-x64 and windows-x64
         run: |
           case "${{ inputs.PLATFORM }}" in
@@ -118,7 +122,6 @@ jobs:
 
     steps:
       - name: Show context
-        shell: bash
         run: |
           echo "GITHUB_CONTEXT": $GITHUB_CONTEXT
           echo "JOB_CONTEXT": $JOB_CONTEXT
@@ -156,28 +159,23 @@ jobs:
 
       - name: Get version
         id: get-version
-        shell: bash
-        run: |
-          pixi run -e wheel-test 'echo "wheel_version=$(python scripts/ci/crates.py get-version)"' >> "$GITHUB_OUTPUT"
+        run: pixi run -e wheel-test 'echo "wheel_version=$(python scripts/ci/crates.py get-version)"' >> "$GITHUB_OUTPUT"
 
       - name: Install built wheel
         # Now install the wheel using a specific version and --no-index to guarantee we get the version from
         # the pre-dist folder. Note we don't use --force-reinstall here because --no-index means it wouldn't
         # find the dependencies to reinstall them.
-        shell: bash
         run: |
           pixi run -e wheel-test pip uninstall rerun-sdk
           pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links wheel
 
       - name: Print wheel version
-        shell: bash
         run: |
           pixi run -e wheel-test python -m rerun --version
           pixi run -e wheel-test which rerun
           pixi run -e wheel-test rerun --version
 
       - name: Run unit tests
-        shell: bash
         run: cd rerun_py/tests && pixi run -e wheel-test pytest -c ../pyproject.toml
 
       - name: Run e2e test
diff --git a/.github/workflows/reusable_track_size.yml b/.github/workflows/reusable_track_size.yml
index 522768353b97..56492e41dbd7 100644
--- a/.github/workflows/reusable_track_size.yml
+++ b/.github/workflows/reusable_track_size.yml
@@ -13,6 +13,10 @@ on:
         required: true
         type: boolean
 
+defaults:
+  run:
+    shell: bash
+
 permissions:
   contents: write
   id-token: write
@@ -31,7 +35,6 @@ jobs:
 
       - name: Get context
         id: context
-        shell: bash
         run: |
           echo "short_sha=$(echo ${{ github.sha }} | cut -c1-7)" >> "$GITHUB_OUTPUT"
 
@@ -60,7 +63,6 @@ jobs:
           path: example_data
 
       - name: Download base results
-        shell: bash
         run: |
           # Get base commit:
           # 1. From the index file
@@ -89,7 +91,6 @@ jobs:
 
       - name: Measure sizes
         id: measure
-        shell: bash
         run: |
           entries=()
 
@@ -145,7 +146,6 @@ jobs:
 
       - name: Create index file
         if: github.ref == 'refs/heads/main'
-        shell: bash
         run: |
           echo "${{ steps.context.outputs.short_sha }}" > "/tmp/index"
 
@@ -189,7 +189,6 @@ jobs:
 
       - name: Render benchmark result
         if: github.ref == 'refs/heads/main'
-        shell: bash
         run: |
           python3 -m pip install google-cloud-storage==2.9.0
           scripts/ci/render_bench.py sizes \
diff --git a/.github/workflows/reusable_update_pr_body.yml b/.github/workflows/reusable_update_pr_body.yml
index c1dda64c893d..ea7a867a3bcc 100644
--- a/.github/workflows/reusable_update_pr_body.yml
+++ b/.github/workflows/reusable_update_pr_body.yml
@@ -14,6 +14,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-pr-update-body
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   update-pr-body:
     name: Update PR body
@@ -36,7 +40,6 @@ jobs:
           pixi-version: v0.18.0
 
       - name: Update PR description
-        shell: bash
         run: |
           pixi run ./scripts/ci/update_pr_body.py \
             --github-token '${{ secrets.GITHUB_TOKEN }}' \
diff --git a/.github/workflows/reusable_upload_examples.yml b/.github/workflows/reusable_upload_examples.yml
index 22a0bbf3a506..5df3c1de25ec 100644
--- a/.github/workflows/reusable_upload_examples.yml
+++ b/.github/workflows/reusable_upload_examples.yml
@@ -30,6 +30,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-upload-examples
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   upload-web:
     name: Upload Examples to Google Cloud
@@ -59,7 +63,6 @@ jobs:
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"
diff --git a/.github/workflows/reusable_upload_web.yml b/.github/workflows/reusable_upload_web.yml
index 97da0f4c50b8..c96af522f2c1 100644
--- a/.github/workflows/reusable_upload_web.yml
+++ b/.github/workflows/reusable_upload_web.yml
@@ -31,6 +31,10 @@ concurrency:
   group: ${{ inputs.CONCURRENCY }}-upload-web
   cancel-in-progress: true
 
+defaults:
+  run:
+    shell: bash
+
 jobs:
   upload-web:
     name: Upload web build to google cloud (wasm32 + wasm-bindgen)
@@ -60,7 +64,6 @@ jobs:
 
       - name: Get sha
         id: get-sha
-        shell: bash
         run: |
           full_commit="${{ (github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"

From 3fd541a3782564847b64af18deea1604254ef837 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Wed, 17 Apr 2024 21:38:50 +0200
Subject: [PATCH 321/508] Update tornado due to dependabot security warning
 (#6022)

### What

* followup to
* #6021
* #5981

As per https://github.com/rerun-io/rerun/security/dependabot/17 we have
to update higher still.
Because of previous documented issues in this requirements.txt I'm wary
of updating too high.

Tested again that notebook still works:
```cmd
pixi run pip install -r .\examples\python\notebook\requirements.txt
pixi run jupyter notebook .\examples\python\notebook\cube.ipynb
```

This time around maybe @jleibs can also sanity check this works? Might
be a linux issue.

* Should fix https://github.com/rerun-io/rerun/issues/5927


### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6021?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6021?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6021)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 examples/python/notebook/requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/examples/python/notebook/requirements.txt b/examples/python/notebook/requirements.txt
index 931f6f7bf8fd..17b6ed7ffe3f 100644
--- a/examples/python/notebook/requirements.txt
+++ b/examples/python/notebook/requirements.txt
@@ -7,4 +7,4 @@ rerun-sdk
 # See e.g. https://github.com/jupyter/notebook/issues/6721
 jupyter_client<8
 pyzmq<25
-tornado<=6.3.2
+tornado<=6.3.3

From 093fc88c370eba4c63bae1eaa7379fe1a2b4971b Mon Sep 17 00:00:00 2001
From: Jeremy Leibs 
Date: Wed, 17 Apr 2024 22:23:25 +0200
Subject: [PATCH 322/508] Update the notebooks docs for 0.15 (#6025)

Preview: https://landing-da5h78n7j-rerun.vercel.app/docs/howto/notebook

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6025?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6025?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6025)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 docs/content/howto/notebook.md | 128 ++++++++++++++++++++++++++-------
 1 file changed, 102 insertions(+), 26 deletions(-)

diff --git a/docs/content/howto/notebook.md b/docs/content/howto/notebook.md
index b02328d7c956..dc320b32047d 100644
--- a/docs/content/howto/notebook.md
+++ b/docs/content/howto/notebook.md
@@ -4,58 +4,133 @@ order: 600
 description: How to embed Rerun in notebooks like Jupyter or Colab
 ---
 
-Starting with version 0.5.0, Rerun now has limited support for embedding the Rerun viewer directly within IPython-style
+Starting with version 0.15.1, Rerun has improved support for embedding the Rerun viewer directly within IPython-style
 notebooks. This makes it easy to iterate on API calls as well as to share data with others.
 
 Rerun has been tested with:
- - [Jupyter Notebook Classic](https://jupyter.org/)
- - [Jupyter Lab](https://jupyter.org/)
- - [VSCode](https://code.visualstudio.com/blogs/2021/08/05/notebooks)
- - [Google Colab](https://colab.research.google.com/)
+
+-   [Jupyter Notebook Classic](https://jupyter.org/)
+-   [Jupyter Lab](https://jupyter.org/)
+-   [VSCode](https://code.visualstudio.com/blogs/2021/08/05/notebooks)
+-   [Google Colab](https://colab.research.google.com/)
 
 ## Basic concept
 
-Rather than logging to a file or a remote server, you can also configure the Rerun SDK to store data in a local
-[MemoryRecording](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.MemoryRecording).
+When using the Rerun logging APIs, by default, the logged messages are buffered in-memory until
+you send them to a sink such as via `rr.connect()` or `rr.save()`. When using Rerun in a notebook,
+rather than using the other sinks, you have the option to use a helper method: [`rr.notebook_show()`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.notebook_show).
+This method takes any buffered messages and converts them into an HTML snipped including
+the inlined data along with an instance of the viewer in an iframe.
+
+## The APIs
 
-This `MemoryRecording` can then used to produce an inline HTML snippet to be directly displayed in most notebook
-environments. The snippet includes an embedded copy of an RRD file and some javascript that loads that RRD file into an
-IFrame.
+In order to output the current recording data to a notebook cell, call:
+[`rr.notebook_show()`](https://ref.rerun.io/docs/python/stable/common/initialization_functions/#rerun.notebook_show).
 
-Each cell in the notebook is fully isolated from the other cells and will only display the data from the source
-`MemoryRecording`.
+For example:
 
-## The APIs
+```python
+import rerun as rr
+from numpy.random import default_rng
+
+rr.init("rerun_example_notebook")
+
+rng = default_rng(12345)
+
+positions = rng.uniform(-5, 5, size=[10, 3])
+colors = rng.uniform(0, 255, size=[10, 3])
+radii = rng.uniform(0, 1, size=[10])
+
+rr.log("random", rr.Points3D(positions, colors=colors, radii=radii))
+
+rr.notebook_show()
+```
+
+
+  
+  
+  
+  
+  
+
+
+This is similar to calling `rr.connect()` or `rr.save()` in that it configures the Rerun SDK to use
+this memory buffer as the sink for future logging calls.
+
+Note that the output cell is essentially a fixed snapshot of the
+current state of the recording at the time that `notebook_show()` is called. Rerun does not yet
+support live incremental streaming from the jupyter kernel into the embedded viewer.
+
+Messages will continue to be buffered incrementally, and each call to `notebook_show()` will
+display all messages that have been logged since the last call to `rr.init()`.
+
+If you wish to clear the current recording, you can call `rr.init()` again.
+
+The `notebook_show()` method also takes optional arguments for specifying the width and height of the IFrame. For example:
 
-In order to create a new `MemoryRecording`, you call:
 ```python
-rec = rr.memory_recording()
+rr.notebook_show(width=400, height=400)
 ```
-This is similar to calling `rr.connect()` or `rr.save()` in that it configures the Rerun SDK to use this new
-recording as a target for future API calls.
 
-After logging data to the recording you can display it in a cell by calling the
-[show()](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.MemoryRecording.show) method
-on the `MemoryRecording`. The `show()` method also takes optional arguments for specifying the width and height of the IFrame. For example:
+## Working with Blueprints
+
+[Blueprints](./configure-viewer-through-code.md) can also be used with `notebook_show()` by providing a `blueprint`
+parameter.
+
+For example
+
 ```python
-rec.show(width=400, height=400)
+blueprint = rrb.Blueprint(
+    rrb.Horizontal(
+        rrb.Spatial3DView(origin="/world"),
+        rrb.Spatial2DView(origin="/world/camera"),
+        column_shares=[2,1]),
+)
+
+rr.notebook_show(blueprint=blueprint)
 ```
 
-The `MemoryRecording` also implements `_repr_html_()` which means in most notebook environments, if it is the last
-expression returned in a cell it will display itself automatically, without the need to call `show()`.
+Because blueprint types implement `_repr_html_`, you can also just end any cell with a blueprint
+object, and it will call `notebook_show()` behind the scenes.
+
 ```python
-rec = rr.memory_recording()
-rr.log("img", my_image)
-rec
+import numpy as np
+import rerun as rr
+import rerun.blueprint as rrb
+
+rr.init("rerun_example_image")
+rng = np.random.default_rng(12345)
+
+image1 = rng.uniform(0, 255, size=[24, 64, 3])
+image2 = rng.uniform(0, 255, size=[24, 64, 1])
+
+rr.log("image1", rr.Image(image1))
+rr.log("image2", rr.Image(image2))
+
+rrb.Vertical(
+    rrb.Spatial2DView(origin='/image1'),
+    rrb.Spatial2DView(origin='/image2')
+)
 ```
+
+
+  
+  
+  
+  
+  
+
+
 ## Some working examples
 
 To experiment with notebooks yourself, there are a few options.
+
 ### Running locally
 
 The GitHub repo includes a [notebook example](https://github.com/rerun-io/rerun/blob/main/examples/python/notebook/cube.ipynb).
 
 If you have a local checkout of Rerun, you can:
+
 ```bash
 $ cd examples/python/notebook
 $ pip install -r requirements.txt
@@ -77,6 +152,7 @@ Because the Rerun viewer in the notebook is just an embedded HTML snippet it als
 tools like nbconvert.
 
 You can convert the notebook to HTML using the following command:
+
 ```bash
 $ jupyter nbconvert --to=html --ExecutePreprocessor.enabled=True examples/python/notebook/cube.ipynb
 ```

From 7daca806db4d17af3ec2a09da5ac2db802adee7f Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Thu, 18 Apr 2024 09:14:43 +0200
Subject: [PATCH 323/508] Remove unused dependencies and set up cargo-machete
 exceptions (#6026)

### What

Ignored everything related to re_query(_cache)(2) since it's so much in
flux right now.

(Very slight untangling, but mostly cosmetic)

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6026?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6026?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6026)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 Cargo.lock                                   | 23 --------------------
 crates/re_data_store/Cargo.toml              |  1 -
 crates/re_data_ui/Cargo.toml                 |  1 -
 crates/re_log_types/Cargo.toml               |  6 +++++
 crates/re_renderer/Cargo.toml                |  3 +++
 crates/re_space_view/Cargo.toml              |  1 -
 crates/re_space_view_dataframe/Cargo.toml    |  1 -
 crates/re_space_view_spatial/Cargo.toml      |  1 -
 crates/re_space_view_time_series/Cargo.toml  |  1 -
 crates/re_types_blueprint/Cargo.toml         |  8 -------
 crates/re_viewport/Cargo.toml                |  6 -----
 crates/rerun-cli/Cargo.toml                  |  1 -
 examples/rust/incremental_logging/Cargo.toml |  1 -
 examples/rust/log_file/Cargo.toml            |  1 -
 14 files changed, 9 insertions(+), 46 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ec7ac2225bf9..067b322c3fdf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2622,7 +2622,6 @@ version = "0.16.0-alpha.1+dev"
 dependencies = [
  "anyhow",
  "clap",
- "glam",
  "rand",
  "rerun",
 ]
@@ -2983,7 +2982,6 @@ version = "0.16.0-alpha.1+dev"
 dependencies = [
  "anyhow",
  "clap",
- "glam",
  "rerun",
 ]
 
@@ -4263,7 +4261,6 @@ dependencies = [
  "parking_lot",
  "rand",
  "re_arrow2",
- "re_error",
  "re_format",
  "re_log",
  "re_log_types",
@@ -4295,7 +4292,6 @@ dependencies = [
  "re_format",
  "re_log",
  "re_log_types",
- "re_query",
  "re_renderer",
  "re_smart_channel",
  "re_tracing",
@@ -4740,7 +4736,6 @@ dependencies = [
 name = "re_space_view"
 version = "0.16.0-alpha.1+dev"
 dependencies = [
- "ahash",
  "egui",
  "itertools 0.12.0",
  "nohash-hasher",
@@ -4788,7 +4783,6 @@ dependencies = [
  "re_query",
  "re_renderer",
  "re_tracing",
- "re_types",
  "re_ui",
  "re_viewer_context",
 ]
@@ -4809,7 +4803,6 @@ dependencies = [
  "mimalloc",
  "nohash-hasher",
  "once_cell",
- "parking_lot",
  "rayon",
  "re_data_store",
  "re_data_ui",
@@ -4902,7 +4895,6 @@ dependencies = [
  "egui",
  "egui_plot",
  "itertools 0.12.0",
- "parking_lot",
  "rayon",
  "re_data_store",
  "re_format",
@@ -5014,21 +5006,13 @@ dependencies = [
 name = "re_types_blueprint"
 version = "0.16.0-alpha.1+dev"
 dependencies = [
- "anyhow",
  "array-init",
- "backtrace",
  "bytemuck",
- "document-features",
  "once_cell",
  "re_arrow2",
- "re_error",
- "re_string_interner",
  "re_tracing",
- "re_tuid",
  "re_types",
  "re_types_core",
- "smallvec",
- "thiserror",
 ]
 
 [[package]]
@@ -5212,8 +5196,6 @@ name = "re_viewport"
 version = "0.16.0-alpha.1+dev"
 dependencies = [
  "ahash",
- "array-init",
- "bytemuck",
  "egui",
  "egui_tiles",
  "glam",
@@ -5222,24 +5204,20 @@ dependencies = [
  "nohash-hasher",
  "once_cell",
  "rayon",
- "re_arrow2",
  "re_data_store",
  "re_data_ui",
  "re_entity_db",
  "re_log",
  "re_log_types",
- "re_query",
  "re_renderer",
  "re_smart_channel",
  "re_space_view",
- "re_space_view_time_series",
  "re_tracing",
  "re_types",
  "re_types_blueprint",
  "re_types_core",
  "re_ui",
  "re_viewer_context",
- "rmp-serde",
  "smallvec",
 ]
 
@@ -5385,7 +5363,6 @@ version = "0.16.0-alpha.1+dev"
 dependencies = [
  "document-features",
  "mimalloc",
- "rayon",
  "re_build_info",
  "re_build_tools",
  "re_error",
diff --git a/crates/re_data_store/Cargo.toml b/crates/re_data_store/Cargo.toml
index 6a7ce969b98e..09ac6f10d43c 100644
--- a/crates/re_data_store/Cargo.toml
+++ b/crates/re_data_store/Cargo.toml
@@ -25,7 +25,6 @@ deadlock_detection = ["parking_lot/deadlock_detection"]
 
 [dependencies]
 # Rerun dependencies:
-re_error.workspace = true
 re_format = { workspace = true, features = ["arrow"] }
 re_log_types.workspace = true
 re_log = { workspace = true, features = ["setup"] }
diff --git a/crates/re_data_ui/Cargo.toml b/crates/re_data_ui/Cargo.toml
index 028f4101438c..66b9829e98fe 100644
--- a/crates/re_data_ui/Cargo.toml
+++ b/crates/re_data_ui/Cargo.toml
@@ -22,7 +22,6 @@ re_error.workspace = true
 re_format.workspace = true
 re_log.workspace = true
 re_log_types.workspace = true
-re_query.workspace = true
 re_renderer.workspace = true
 re_smart_channel.workspace = true
 re_tracing.workspace = true
diff --git a/crates/re_log_types/Cargo.toml b/crates/re_log_types/Cargo.toml
index 452c7a3d2957..6bb887d77f60 100644
--- a/crates/re_log_types/Cargo.toml
+++ b/crates/re_log_types/Cargo.toml
@@ -15,6 +15,12 @@ version.workspace = true
 [package.metadata.docs.rs]
 all-features = true
 
+[package.metadata.cargo-machete]
+ignored = [
+  "num-traits", # Needed for `num-derive`'s macros to work.
+  "half",       # Needed so that `fixed` is pinned at the right version.
+]
+
 
 [features]
 default = []
diff --git a/crates/re_renderer/Cargo.toml b/crates/re_renderer/Cargo.toml
index 052822bf4c7a..857717a985af 100644
--- a/crates/re_renderer/Cargo.toml
+++ b/crates/re_renderer/Cargo.toml
@@ -22,6 +22,9 @@ include = [
 all-features = true
 targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"]
 
+[package.metadata.cargo-machete]
+ignored = ["profiling"] # Needed to hook up wgpu, see below at dependency setup.
+
 
 [features]
 default = ["import-obj", "import-gltf", "import-stl"]
diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml
index 8cad48981e5e..e0bb57654314 100644
--- a/crates/re_space_view/Cargo.toml
+++ b/crates/re_space_view/Cargo.toml
@@ -29,7 +29,6 @@ re_types_core.workspace = true
 re_types.workspace = true
 re_viewer_context.workspace = true
 
-ahash.workspace = true
 egui.workspace = true
 itertools.workspace = true
 nohash-hasher.workspace = true
diff --git a/crates/re_space_view_dataframe/Cargo.toml b/crates/re_space_view_dataframe/Cargo.toml
index 9bfbf233c859..0150a8783f2a 100644
--- a/crates/re_space_view_dataframe/Cargo.toml
+++ b/crates/re_space_view_dataframe/Cargo.toml
@@ -23,7 +23,6 @@ re_log_types.workspace = true
 re_query.workspace = true
 re_renderer.workspace = true
 re_tracing.workspace = true
-re_types.workspace = true
 re_ui.workspace = true
 re_viewer_context.workspace = true
 
diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml
index 395fb8fa7226..a3063e552189 100644
--- a/crates/re_space_view_spatial/Cargo.toml
+++ b/crates/re_space_view_spatial/Cargo.toml
@@ -46,7 +46,6 @@ itertools.workspace = true
 macaw = { workspace = true, features = ["with_serde"] }
 nohash-hasher.workspace = true
 once_cell.workspace = true
-parking_lot.workspace = true
 rayon.workspace = true
 serde.workspace = true
 smallvec = { workspace = true, features = ["serde"] }
diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml
index 5612ffea50e5..84de5f76d5be 100644
--- a/crates/re_space_view_time_series/Cargo.toml
+++ b/crates/re_space_view_time_series/Cargo.toml
@@ -32,5 +32,4 @@ re_viewer_context.workspace = true
 egui.workspace = true
 egui_plot.workspace = true
 itertools.workspace = true
-parking_lot.workspace = true
 rayon.workspace = true
diff --git a/crates/re_types_blueprint/Cargo.toml b/crates/re_types_blueprint/Cargo.toml
index 7a8ea0c19163..f089828736ad 100644
--- a/crates/re_types_blueprint/Cargo.toml
+++ b/crates/re_types_blueprint/Cargo.toml
@@ -23,24 +23,16 @@ default = []
 
 [dependencies]
 # Rerun
-re_error.workspace = true
-re_string_interner.workspace = true
 re_tracing.workspace = true
-re_tuid.workspace = true
 re_types.workspace = true
 re_types_core.workspace = true
 
 # External
-anyhow.workspace = true
 array-init.workspace = true
 arrow2 = { workspace = true, features = [
   "io_ipc",
   "io_print",
   "compute_concatenate",
 ] }
-backtrace.workspace = true
 bytemuck.workspace = true
-document-features.workspace = true
 once_cell.workspace = true
-smallvec.workspace = true
-thiserror.workspace = true
diff --git a/crates/re_viewport/Cargo.toml b/crates/re_viewport/Cargo.toml
index 2834143090c0..abffead0211b 100644
--- a/crates/re_viewport/Cargo.toml
+++ b/crates/re_viewport/Cargo.toml
@@ -21,7 +21,6 @@ re_data_ui.workspace = true
 re_entity_db = { workspace = true, features = ["serde"] }
 re_log_types.workspace = true
 re_log.workspace = true
-re_query.workspace = true
 re_renderer = { workspace = true, default-features = false, features = [
   "arrow",
   "import-gltf",
@@ -30,7 +29,6 @@ re_renderer = { workspace = true, default-features = false, features = [
 ] }
 re_smart_channel.workspace = true
 re_space_view.workspace = true
-re_space_view_time_series.workspace = true
 re_tracing.workspace = true
 re_types.workspace = true
 re_types_blueprint.workspace = true
@@ -39,9 +37,6 @@ re_ui.workspace = true
 re_viewer_context.workspace = true
 
 ahash.workspace = true
-array-init.workspace = true
-arrow2.workspace = true
-bytemuck.workspace = true
 egui_tiles.workspace = true
 egui.workspace = true
 glam.workspace = true
@@ -50,5 +45,4 @@ itertools.workspace = true
 nohash-hasher.workspace = true
 once_cell.workspace = true
 rayon.workspace = true
-rmp-serde.workspace = true
 smallvec.workspace = true
diff --git a/crates/rerun-cli/Cargo.toml b/crates/rerun-cli/Cargo.toml
index cb1ac99b8625..b7b4eadc2e08 100644
--- a/crates/rerun-cli/Cargo.toml
+++ b/crates/rerun-cli/Cargo.toml
@@ -64,7 +64,6 @@ rerun = { workspace = true, features = [
 
 document-features.workspace = true
 mimalloc.workspace = true
-rayon.workspace = true
 tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
 
 
diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml
index 0c835299899b..6075cb1f9b04 100644
--- a/examples/rust/incremental_logging/Cargo.toml
+++ b/examples/rust/incremental_logging/Cargo.toml
@@ -11,5 +11,4 @@ rerun = { path = "../../../crates/rerun", features = ["web_viewer", "clap"] }
 
 anyhow = "1.0"
 clap = { version = "4.0", features = ["derive"] }
-glam = "0.22"
 rand = "0.8"
diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml
index c7ae23912ee1..5b74dd346b0a 100644
--- a/examples/rust/log_file/Cargo.toml
+++ b/examples/rust/log_file/Cargo.toml
@@ -11,4 +11,3 @@ rerun = { path = "../../../crates/rerun", features = ["web_viewer", "clap"] }
 
 anyhow = "1.0"
 clap = { version = "4.0", features = ["derive"] }
-glam = "0.22"

From 49da25dd3e5e14b5284e9eb8cc6f3de475411f90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= 
Date: Thu, 18 Apr 2024 10:13:39 +0200
Subject: [PATCH 324/508] Fix CI warnings (#6027)

### What

Mostly just Node 12/16 compatibility deprecation warnings

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6027?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6027?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6027)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .github/actions/setup-rust/action.yml                     | 2 +-
 .github/workflows/contrib_rerun_py.yml                    | 2 +-
 .github/workflows/release.yml                             | 2 +-
 .github/workflows/reusable_bench.yml                      | 3 +++
 .github/workflows/reusable_build_and_upload_rerun_c.yml   | 7 +++----
 .github/workflows/reusable_build_and_upload_rerun_cli.yml | 2 ++
 .github/workflows/reusable_checks.yml                     | 4 ++--
 .github/workflows/reusable_deploy_docs.yml                | 5 +----
 .github/workflows/reusable_publish_web.yml                | 2 ++
 .github/workflows/reusable_run_notebook.yml               | 1 +
 .github/workflows/reusable_track_size.yml                 | 2 ++
 .github/workflows/reusable_upload_examples.yml            | 7 +++++++
 .github/workflows/reusable_upload_web.yml                 | 7 +++++++
 13 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml
index b069bcd20ba1..cee8f34d7b50 100644
--- a/.github/actions/setup-rust/action.yml
+++ b/.github/actions/setup-rust/action.yml
@@ -53,7 +53,7 @@ runs:
       shell: bash
 
     - name: Set up sccache
-      uses: rerun-io/sccache-action@v0.7.0
+      uses: rerun-io/sccache-action@v0.7.1
       with:
         version: "v0.7.7"
         use_gcs: true
diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml
index 5a079ded93cf..da228426ec5b 100644
--- a/.github/workflows/contrib_rerun_py.yml
+++ b/.github/workflows/contrib_rerun_py.yml
@@ -116,7 +116,7 @@ jobs:
 
       - name: Cache RRD dataset
         id: dataset
-        uses: actions/cache@v3
+        uses: actions/cache@v4
         with:
           path: examples/python/structure_from_motion/dataset/
           # TODO(jleibs): Derive this key from the invocation below
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 9b22a543a396..6f11aa26df6b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -47,7 +47,7 @@ jobs:
         uses: actions/checkout@v4
 
       - name: Setup Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: 3.11
 
diff --git a/.github/workflows/reusable_bench.yml b/.github/workflows/reusable_bench.yml
index 14b29302b683..ddcc03f9599e 100644
--- a/.github/workflows/reusable_bench.yml
+++ b/.github/workflows/reusable_bench.yml
@@ -104,6 +104,7 @@ jobs:
         with:
           path: /tmp/${{ env.SHORT_SHA }}
           destination: "rerun-builds/benches/"
+          process_gcloudignore: false
 
       - name: Download comparison bench from GCS
         if: ${{ inputs.COMPARE_TO != '' }}
@@ -124,6 +125,7 @@ jobs:
         with:
           path: /tmp/bench_results.txt
           destination: "rerun-builds/commit/${{env.SHORT_SHA}}/"
+          process_gcloudignore: false
 
       - name: "Copy bench to named file"
         if: ${{ inputs.BENCH_NAME != '' }}
@@ -136,6 +138,7 @@ jobs:
         with:
           path: /tmp/${{ inputs.BENCH_NAME }}
           destination: "rerun-builds/benches/"
+          process_gcloudignore: false
 
       - name: Alert on regression
         # https://github.com/benchmark-action/github-action-benchmark
diff --git a/.github/workflows/reusable_build_and_upload_rerun_c.yml b/.github/workflows/reusable_build_and_upload_rerun_c.yml
index 2dd930c6f314..4d5c8d4ced0a 100644
--- a/.github/workflows/reusable_build_and_upload_rerun_c.yml
+++ b/.github/workflows/reusable_build_and_upload_rerun_c.yml
@@ -163,10 +163,7 @@ jobs:
           targets: ${{ needs.set-config.outputs.TARGET }}
 
       - name: Build rerun_c (release)
-        uses: actions-rs/cargo@v1
-        with:
-          command: build
-          args: --locked -p rerun_c --release --target ${{ needs.set-config.outputs.TARGET }}
+        run: cargo build --locked -p rerun_c --release --target ${{ needs.set-config.outputs.TARGET }}
 
       - name: Get sha
         id: get-sha
@@ -180,6 +177,7 @@ jobs:
           path: "./target/${{ needs.set-config.outputs.TARGET }}/release/${{ needs.set-config.outputs.LIB_NAME }}"
           destination: "rerun-builds/commit/${{ steps.get-sha.outputs.sha }}/rerun_c/${{ inputs.PLATFORM }}"
           parent: false
+          process_gcloudignore: false
 
       - name: "Upload rerun_c (adhoc)"
         if: ${{ inputs.ADHOC_NAME != '' }}
@@ -188,3 +186,4 @@ jobs:
           path: "./target/${{ needs.set-config.outputs.TARGET }}/release/${{ needs.set-config.outputs.LIB_NAME }}"
           destination: "rerun-builds/adhoc/${{inputs.ADHOC_NAME}}/rerun_c/${{ inputs.PLATFORM }}"
           parent: false
+          process_gcloudignore: false
diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml
index 894c7b615f54..2cc1ca3170d2 100644
--- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml
+++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml
@@ -197,6 +197,7 @@ jobs:
           path: "./target/${{ needs.set-config.outputs.TARGET }}/release/${{ needs.set-config.outputs.BIN_NAME }}"
           destination: "rerun-builds/commit/${{ steps.get-sha.outputs.sha }}/rerun-cli/${{ inputs.PLATFORM }}"
           parent: false
+          process_gcloudignore: false
 
       - name: "Upload rerun-cli (adhoc)"
         if: ${{ inputs.ADHOC_NAME != '' }}
@@ -205,3 +206,4 @@ jobs:
           path: "./target/${{ needs.set-config.outputs.TARGET }}/release/${{ needs.set-config.outputs.BIN_NAME }}"
           destination: "rerun-builds/adhoc/${{inputs.ADHOC_NAME}}/rerun-cli/${{ inputs.PLATFORM }}"
           parent: false
+          process_gcloudignore: false
diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml
index bd1ab1cd298d..1009f242bab4 100644
--- a/.github/workflows/reusable_checks.yml
+++ b/.github/workflows/reusable_checks.yml
@@ -98,7 +98,7 @@ jobs:
           pixi-version: v0.19.0
 
       - name: Set up Python
-        uses: actions/setup-python@v4
+        uses: actions/setup-python@v5
         with:
           python-version: "3.8"
 
@@ -161,7 +161,7 @@ jobs:
       - uses: actions/checkout@v4
 
       - name: Restore link checker cache
-        uses: actions/cache@v3
+        uses: actions/cache@v4
         with:
           path: .lycheecache
           key: cache-lychee-${{ github.sha }}
diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml
index fd8a49b1862e..7192bf65d1e7 100644
--- a/.github/workflows/reusable_deploy_docs.yml
+++ b/.github/workflows/reusable_deploy_docs.yml
@@ -148,10 +148,7 @@ jobs:
         run: rm -rf ./target/doc
 
       - name: cargo doc --document-private-items
-        uses: actions-rs/cargo@v1
-        with:
-          command: doc
-          args: --document-private-items --no-deps --all-features --workspace --exclude rerun-cli
+        run: cargo doc --document-private-items --no-deps --all-features --workspace --exclude rerun-cli
 
       - name: Set up git author
         run: |
diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml
index 00f8a9768c80..17f801c89a44 100644
--- a/.github/workflows/reusable_publish_web.yml
+++ b/.github/workflows/reusable_publish_web.yml
@@ -127,6 +127,7 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/version/${{ inputs.release-version }}"
           parent: false
+          process_gcloudignore: false
 
       - name: Upload app.rerun.io (commit)
         uses: google-github-actions/upload-cloud-storage@v2
@@ -134,6 +135,7 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/commit/${{ needs.get-commit-sha.outputs.short-sha }}"
           parent: false
+          process_gcloudignore: false
 
       - name: Publish app.rerun.io
         if: inputs.update-latest
diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml
index 4d1b02827ca7..f9f4a29fbb00 100644
--- a/.github/workflows/reusable_run_notebook.yml
+++ b/.github/workflows/reusable_run_notebook.yml
@@ -85,3 +85,4 @@ jobs:
           path: "/tmp/cube.html"
           destination: "rerun-builds/commit/${{ steps.get-sha.outputs.sha }}/notebooks"
           parent: false
+          process_gcloudignore: false
diff --git a/.github/workflows/reusable_track_size.yml b/.github/workflows/reusable_track_size.yml
index 56492e41dbd7..d5e83f412246 100644
--- a/.github/workflows/reusable_track_size.yml
+++ b/.github/workflows/reusable_track_size.yml
@@ -143,6 +143,7 @@ jobs:
         with:
           path: /tmp/data.json
           destination: "rerun-builds/sizes/commit/${{ steps.context.outputs.short_sha }}"
+          process_gcloudignore: false
 
       - name: Create index file
         if: github.ref == 'refs/heads/main'
@@ -155,6 +156,7 @@ jobs:
         with:
           path: /tmp/index
           destination: "rerun-builds/sizes"
+          process_gcloudignore: false
 
       - name: Create PR comment
         if: inputs.PR_NUMBER != '' && steps.measure.outputs.is_comparison_set == 'true'
diff --git a/.github/workflows/reusable_upload_examples.yml b/.github/workflows/reusable_upload_examples.yml
index 5df3c1de25ec..210855fd9fc0 100644
--- a/.github/workflows/reusable_upload_examples.yml
+++ b/.github/workflows/reusable_upload_examples.yml
@@ -74,6 +74,7 @@ jobs:
           path: "example_data"
           destination: "rerun-web-viewer/commit/${{ steps.get-sha.outputs.sha }}/examples"
           parent: false
+          process_gcloudignore: false
 
       - name: "Upload examples (tagged)"
         if: inputs.MARK_TAGGED_VERSION
@@ -82,6 +83,7 @@ jobs:
           path: "example_data"
           destination: "rerun-web-viewer/version/${{ inputs.RELEASE_VERSION }}/examples"
           parent: false
+          process_gcloudignore: false
 
       - name: "Upload examples (adhoc)"
         if: ${{ inputs.ADHOC_NAME != '' }}
@@ -90,6 +92,7 @@ jobs:
           path: "example_data"
           destination: "rerun-web-viewer/adhoc/${{ inputs.ADHOC_NAME }}/examples"
           parent: false
+          process_gcloudignore: false
 
       - name: "Upload examples (prerelease)"
         if: github.ref == 'refs/heads/main'
@@ -98,6 +101,7 @@ jobs:
           path: "example_data"
           destination: "rerun-web-viewer/prerelease/examples"
           parent: false
+          process_gcloudignore: false
           headers: |-
             cache-control: no-cache, max-age=0
 
@@ -108,6 +112,7 @@ jobs:
           path: "example_data"
           destination: "rerun-web-viewer/version/main/examples"
           parent: false
+          process_gcloudignore: false
           headers: |-
             cache-control: no-cache, max-age=0
 
@@ -118,6 +123,7 @@ jobs:
           path: "example_data"
           destination: "rerun-web-viewer/pr/${{ inputs.PR_NUMBER }}/examples"
           parent: false
+          process_gcloudignore: false
           headers: |-
             cache-control: no-cache, max-age=0
 
@@ -128,5 +134,6 @@ jobs:
           path: "example_data"
           destination: "rerun-web-viewer/version/nightly/examples"
           parent: false
+          process_gcloudignore: false
           headers: |-
             cache-control: no-cache, max-age=0
diff --git a/.github/workflows/reusable_upload_web.yml b/.github/workflows/reusable_upload_web.yml
index c96af522f2c1..2334ab6f4c13 100644
--- a/.github/workflows/reusable_upload_web.yml
+++ b/.github/workflows/reusable_upload_web.yml
@@ -75,6 +75,7 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/commit/${{ steps.get-sha.outputs.sha }}"
           parent: false
+          process_gcloudignore: false
 
       - name: "Upload web-viewer (tagged)"
         if: inputs.MARK_TAGGED_VERSION
@@ -83,6 +84,7 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/version/${{inputs.RELEASE_VERSION}}"
           parent: false
+          process_gcloudignore: false
 
       - name: "Upload web-viewer (adhoc)"
         if: ${{ inputs.ADHOC_NAME != '' }}
@@ -91,6 +93,7 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/adhoc/${{inputs.ADHOC_NAME}}"
           parent: false
+          process_gcloudignore: false
 
       - name: "Upload web-viewer (prerelease)"
         if: github.ref == 'refs/heads/main'
@@ -99,6 +102,7 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/prerelease"
           parent: false
+          process_gcloudignore: false
           headers: |-
             cache-control: no-cache, max-age=0
 
@@ -109,6 +113,7 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/version/main"
           parent: false
+          process_gcloudignore: false
           headers: |-
             cache-control: no-cache, max-age=0
 
@@ -119,6 +124,7 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/pr/${{ inputs.PR_NUMBER }}"
           parent: false
+          process_gcloudignore: false
           headers: |-
             cache-control: no-cache, max-age=0
 
@@ -129,5 +135,6 @@ jobs:
           path: "web_viewer"
           destination: "rerun-web-viewer/version/nightly"
           parent: false
+          process_gcloudignore: false
           headers: |-
             cache-control: no-cache, max-age=0

From 702c9923b565c98b399bf58406b34048811285bb Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Thu, 18 Apr 2024 14:24:37 +0200
Subject: [PATCH 325/508] `re_web_viewer_server` no longer needs tokio, split
 out sync code path (#6030)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

### What

* Followup to #6005
* another piece of #5907

Removes tokio dependency from re_web_viewer_server:
* async `WebViewerServer` no longer uses tokio internally, instead use
`future_channel::oneshot` for shutdown
* `WebViewerServerHandle` is now optional (but default enabled) and
spawns a thread that internally uses the tiny pollster crate
* removed `re_web_viewer_server`'s main file - it's not used by any test
and may thus rot
    * this allows us to also remove the clap dependency from this crate


⚠️ Rerun serve/connect still needs a tokio runtime with this change ⚠️:
Likely the last piece after this is `re_sdk_comms` which is very similar
in nature to `re_ws_comms`.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6030?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6030?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6030)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 Cargo.lock                              |  5 +-
 crates/re_sdk/Cargo.toml                |  4 +-
 crates/re_web_viewer_server/Cargo.toml  | 15 +++---
 crates/re_web_viewer_server/src/lib.rs  | 69 +++++-------------------
 crates/re_web_viewer_server/src/main.rs | 49 -----------------
 crates/re_web_viewer_server/src/sync.rs | 70 +++++++++++++++++++++++++
 examples/rust/minimal_serve/Cargo.toml  |  2 +-
 7 files changed, 96 insertions(+), 118 deletions(-)
 delete mode 100644 crates/re_web_viewer_server/src/main.rs
 create mode 100644 crates/re_web_viewer_server/src/sync.rs

diff --git a/Cargo.lock b/Cargo.lock
index 067b322c3fdf..9dedcb56747a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5225,15 +5225,14 @@ dependencies = [
 name = "re_web_viewer_server"
 version = "0.16.0-alpha.1+dev"
 dependencies = [
- "clap",
  "document-features",
+ "futures-channel",
  "futures-util",
  "hyper",
+ "pollster",
  "re_analytics",
  "re_log",
  "thiserror",
- "tokio",
- "webbrowser",
 ]
 
 [[package]]
diff --git a/crates/re_sdk/Cargo.toml b/crates/re_sdk/Cargo.toml
index dfaa9ba26a21..0ad7e9e109a8 100644
--- a/crates/re_sdk/Cargo.toml
+++ b/crates/re_sdk/Cargo.toml
@@ -68,7 +68,9 @@ thiserror.workspace = true
 re_data_source = { workspace = true, optional = true }
 re_smart_channel = { workspace = true, optional = true }
 re_ws_comms = { workspace = true, optional = true }
-re_web_viewer_server = { workspace = true, optional = true }
+re_web_viewer_server = { workspace = true, optional = true, features = [
+  "sync",
+] }
 
 anyhow = { workspace = true, optional = true }
 webbrowser = { workspace = true, optional = true }
diff --git a/crates/re_web_viewer_server/Cargo.toml b/crates/re_web_viewer_server/Cargo.toml
index da454704019f..8d284f4e08ae 100644
--- a/crates/re_web_viewer_server/Cargo.toml
+++ b/crates/re_web_viewer_server/Cargo.toml
@@ -30,6 +30,8 @@ all-features = true
 
 
 [features]
+default = ["sync"]
+
 ## ONLY FOR CI!
 ##
 ## When set, the crate builds despite the `.wasm` being missing, but will panic at runtime.
@@ -42,6 +44,9 @@ __ci = []
 ## Enable telemetry using our analytics SDK.
 analytics = ["dep:re_analytics"]
 
+## Enable `WebViewerServerHandle` for use without an async runtime.
+sync = ["pollster"]
+
 
 [dependencies]
 re_log = { workspace = true, features = ["setup"] }
@@ -50,14 +55,8 @@ document-features.workspace = true
 futures-util.workspace = true
 hyper = { workspace = true, features = ["full"] }
 thiserror.workspace = true
-tokio = { workspace = true, default-features = false, features = [
-  "macros",
-  "rt-multi-thread",
-] }
-
-# Only needed for main.rs:
-clap = { workspace = true, features = ["derive"] }
-webbrowser.workspace = true
+futures-channel.workspace = true                  # Used for server shutdown signaling. Picked this one because it's already used by hyper.
 
 # Optional dependencies:
 re_analytics = { workspace = true, optional = true }
+pollster = { workspace = true, optional = true }
diff --git a/crates/re_web_viewer_server/src/lib.rs b/crates/re_web_viewer_server/src/lib.rs
index d229ec44c3ea..5c2857f46ba8 100644
--- a/crates/re_web_viewer_server/src/lib.rs
+++ b/crates/re_web_viewer_server/src/lib.rs
@@ -17,6 +17,11 @@ use std::{
 use futures_util::future;
 use hyper::{server::conn::AddrIncoming, service::Service, Body, Request, Response};
 
+#[cfg(feature = "sync")]
+mod sync;
+#[cfg(feature = "sync")]
+pub use sync::WebViewerServerHandle;
+
 pub const DEFAULT_WEB_VIEWER_SERVER_PORT: u16 = 9090;
 
 #[cfg(not(feature = "__ci"))]
@@ -33,6 +38,7 @@ mod data {
 
 /// Failure to host the web viewer.
 #[derive(thiserror::Error, Debug)]
+#[allow(clippy::enum_variant_names)]
 pub enum WebViewerServerError {
     #[error("Could not parse address: {0}")]
     AddrParseFailed(#[from] std::net::AddrParseError),
@@ -40,11 +46,12 @@ pub enum WebViewerServerError {
     #[error("Failed to bind to port {0} for HTTP: {1}")]
     BindFailed(WebViewerServerPort, hyper::Error),
 
-    #[error("Failed to join web viewer server task: {0}")]
-    JoinError(#[from] tokio::task::JoinError),
-
     #[error("Failed to serve web viewer: {0}")]
     ServeFailed(hyper::Error),
+
+    #[cfg(feature = "sync")]
+    #[error("Failed to spawn web viewer thread: {0}")]
+    ThreadSpawnFailed(#[from] std::io::Error),
 }
 
 struct Svc {
@@ -229,11 +236,11 @@ impl WebViewerServer {
 
     pub async fn serve_with_graceful_shutdown(
         self,
-        mut shutdown_rx: tokio::sync::broadcast::Receiver<()>,
+        shutdown_rx: futures_channel::oneshot::Receiver<()>,
     ) -> Result<(), WebViewerServerError> {
         self.server
             .with_graceful_shutdown(async {
-                shutdown_rx.recv().await.ok();
+                shutdown_rx.await.ok();
             })
             .await
             .map_err(WebViewerServerError::ServeFailed)?;
@@ -246,57 +253,7 @@ impl WebViewerServer {
     }
 }
 
-/// Sync handle for the [`WebViewerServer`]
-///
-/// When dropped, the server will be shut down.
-pub struct WebViewerServerHandle {
-    local_addr: std::net::SocketAddr,
-    shutdown_tx: tokio::sync::broadcast::Sender<()>,
-}
-
-impl Drop for WebViewerServerHandle {
-    fn drop(&mut self) {
-        re_log::info!("Shutting down web server on {}", self.server_url());
-        self.shutdown_tx.send(()).ok();
-    }
-}
-
-impl WebViewerServerHandle {
-    /// Create new [`WebViewerServer`] to host the Rerun Web Viewer on a specified port.
-    /// Returns a [`WebViewerServerHandle`] that will shutdown the server when dropped.
-    ///
-    /// A port of 0 will let the OS choose a free port.
-    ///
-    /// The caller needs to ensure that there is a `tokio` runtime running.
-    pub fn new(
-        bind_ip: &str,
-        requested_port: WebViewerServerPort,
-    ) -> Result {
-        let (shutdown_tx, shutdown_rx) = tokio::sync::broadcast::channel(1);
-
-        let web_server = WebViewerServer::new(bind_ip, requested_port)?;
-
-        let local_addr = web_server.server.local_addr();
-
-        tokio::spawn(async move { web_server.serve_with_graceful_shutdown(shutdown_rx).await });
-
-        let slf = Self {
-            local_addr,
-            shutdown_tx,
-        };
-
-        re_log::info!("Started web server on {}", slf.server_url());
-
-        Ok(slf)
-    }
-
-    /// Includes `http://` prefix
-    pub fn server_url(&self) -> String {
-        server_url(&self.local_addr)
-    }
-}
-
-fn server_url(local_addr: &SocketAddr) -> String {
+pub(crate) fn server_url(local_addr: &SocketAddr) -> String {
     if local_addr.ip().is_unspecified() {
         // "0.0.0.0"
         format!("http://localhost:{}", local_addr.port())
diff --git a/crates/re_web_viewer_server/src/main.rs b/crates/re_web_viewer_server/src/main.rs
deleted file mode 100644
index 6f377e1b3ca9..000000000000
--- a/crates/re_web_viewer_server/src/main.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-#![forbid(unsafe_code)]
-#![warn(clippy::all, rust_2018_idioms)]
-
-/// Build and host the rerun web-viewer.
-///
-/// Debug-builds will build and host the debug version of the viewer.
-#[derive(Debug, clap::Parser)]
-#[clap(author, version, about)]
-struct Args {
-    /// What TCP port do we listen to?
-    ///
-    /// Use `0` to tell the OS to use any port.
-    #[clap(long, default_value_t = 0)]
-    port: u16,
-
-    /// What bind address IP to use.
-    #[clap(long, default_value = "0.0.0.0")]
-    bind: String,
-
-    /// Open the web-viewer in the default browser?
-    #[clap(long)]
-    open: bool,
-}
-
-#[tokio::main]
-async fn main() {
-    re_log::setup_logging();
-
-    use clap::Parser as _;
-    let args = Args::parse();
-
-    let bind_ip = &args.bind;
-    let server = re_web_viewer_server::WebViewerServer::new(
-        bind_ip,
-        re_web_viewer_server::WebViewerServerPort(args.port),
-    )
-    .expect("Could not create web server");
-
-    let url = server.server_url();
-    eprintln!("Hosting web-viewer on {url}");
-
-    if args.open {
-        if let Err(err) = webbrowser::open(&url) {
-            re_log::error!("Could not open web browser: {err}");
-        }
-    }
-
-    server.serve().await.unwrap();
-}
diff --git a/crates/re_web_viewer_server/src/sync.rs b/crates/re_web_viewer_server/src/sync.rs
new file mode 100644
index 000000000000..6def41ca8cd2
--- /dev/null
+++ b/crates/re_web_viewer_server/src/sync.rs
@@ -0,0 +1,70 @@
+use crate::{server_url, WebViewerServer, WebViewerServerError, WebViewerServerPort};
+
+/// Sync handle for the [`WebViewerServer`]
+///
+/// When dropped, the server will be shut down.
+pub struct WebViewerServerHandle {
+    local_addr: std::net::SocketAddr,
+    shutdown: Option<(
+        futures_channel::oneshot::Sender<()>,
+        std::thread::JoinHandle<()>,
+    )>,
+}
+
+impl Drop for WebViewerServerHandle {
+    fn drop(&mut self) {
+        re_log::info!("Shutting down web server on {}", self.server_url());
+
+        if let Some((shutdown_tx, thread_handle)) = self.shutdown.take() {
+            if shutdown_tx.send(()).is_err() {
+                re_log::error!("Failed to send shutdown signal to web server thread.");
+            }
+            thread_handle.join().ok();
+        }
+    }
+}
+
+impl WebViewerServerHandle {
+    /// Create new [`WebViewerServer`] to host the Rerun Web Viewer on a specified port.
+    /// Returns a [`WebViewerServerHandle`] that will shutdown the server when dropped.
+    ///
+    /// A port of 0 will let the OS choose a free port.
+    ///
+    /// Internally spawns a thread to run the server.
+    /// If you instead want to use the server in your async runtime (e.g. [`tokio`](https://docs.rs/tokio/latest/tokio/) or [`smol`](https://docs.rs/smol/latest/smol/)), use [`WebViewerServer`].
+    pub fn new(
+        bind_ip: &str,
+        requested_port: WebViewerServerPort,
+    ) -> Result {
+        let (shutdown_tx, shutdown_rx) = futures_channel::oneshot::channel();
+
+        let web_server = WebViewerServer::new(bind_ip, requested_port)?;
+
+        let local_addr = web_server.server.local_addr();
+
+        let server_serve_future = async {
+            if let Err(err) = web_server.serve_with_graceful_shutdown(shutdown_rx).await {
+                re_log::error!("Web server failed: {err}");
+            }
+        };
+
+        let thread_handle = std::thread::Builder::new()
+            .name("WebViewerServerHandle".to_owned())
+            .spawn(move || pollster::block_on(server_serve_future))
+            .map_err(WebViewerServerError::ThreadSpawnFailed)?;
+
+        let slf = Self {
+            local_addr,
+            shutdown: Some((shutdown_tx, thread_handle)),
+        };
+
+        re_log::info!("Started web server on {}", slf.server_url());
+
+        Ok(slf)
+    }
+
+    /// Includes `http://` prefix
+    pub fn server_url(&self) -> String {
+        server_url(&self.local_addr)
+    }
+}
diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml
index f7f69125513a..44db28b8491c 100644
--- a/examples/rust/minimal_serve/Cargo.toml
+++ b/examples/rust/minimal_serve/Cargo.toml
@@ -8,4 +8,4 @@ publish = false
 
 [dependencies]
 rerun = { path = "../../../crates/rerun", features = ["web_viewer"] }
-tokio = "1.0"
+tokio = { version = "1.24", features = ["rt-multi-thread"] }

From cbe281b6decba39dd4f8768b305c3866566c9c2f Mon Sep 17 00:00:00 2001
From: Jeremy Leibs 
Date: Thu, 18 Apr 2024 18:02:20 +0200
Subject: [PATCH 326/508] Make rerun-py use an embedded rerun-cli executable
 (#5996)

### What

- Resolves: https://github.com/rerun-io/rerun/issues/5196

- Move `rerun_py` over to a dependency on `re_sdk` instead of `rerun`
- Modify the pyproject / build script to look for a bin/rerun in the
python project.
- Update the launch/spawn scripts to use the embedded copy of the
`rerun` executable.
- Spawn now dispatches through the SDK the same way as cpp / rust.
- When executed inside the editable dev environment, use the copy of
`rerun` from `target/debug`
- Build and upload a copy of rerun-cli to embed into the wheel during PR
builds.

- [x] Verify wheels build correctly on nightly

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5996?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/5996?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5996)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.

---------

Co-authored-by: Andreas Reich 
Co-authored-by: Emil Ernerfeldt 
---
 .github/workflows/nightly.yml                 | 203 +++++++++---------
 .github/workflows/on_pull_request.yml         |  10 +-
 .github/workflows/on_push_main.yml            |   8 +-
 .github/workflows/release.yml                 |  38 ++--
 .../reusable_build_and_upload_wheels.yml      |  10 +-
 Cargo.lock                                    |   2 +-
 crates/re_sdk/src/recording_stream.rs         |  35 +--
 crates/re_sdk/src/spawn.rs                    |  19 ++
 crates/rerun/src/run.rs                       |  21 +-
 crates/rerun_c/src/lib.rs                     |   2 +
 pixi.toml                                     |  27 ++-
 rerun_py/.gitignore                           |   3 +-
 rerun_py/Cargo.toml                           |  23 +-
 rerun_py/build.rs                             |  18 ++
 rerun_py/pyproject.toml                       |  14 +-
 rerun_py/rerun/__init__.py                    |   9 +
 rerun_py/rerun_cli/__init__.py                |  36 ++++
 rerun_py/rerun_sdk/rerun/__main__.py          |  31 ++-
 rerun_py/rerun_sdk/rerun/_spawn.py            |  60 +-----
 rerun_py/rerun_sdk/rerun_cli/__init__.py      |   0
 rerun_py/rerun_sdk/rerun_cli/__main__.py      |  25 +++
 rerun_py/src/python_bridge.rs                 | 105 +++++----
 scripts/ci/fetch_artifact.py                  |  59 +++++
 23 files changed, 439 insertions(+), 319 deletions(-)
 create mode 100644 rerun_py/rerun_cli/__init__.py
 create mode 100644 rerun_py/rerun_sdk/rerun_cli/__init__.py
 create mode 100644 rerun_py/rerun_sdk/rerun_cli/__main__.py
 create mode 100644 scripts/ci/fetch_artifact.py

diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index 97cbd746f7bf..a0181aaba6c3 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -74,11 +74,107 @@ jobs:
       NIGHTLY: true
     secrets: inherit
 
+  # -----------------------------------------------------------------------------------
+  # Build rerun_c library binaries:
+
+  build-rerun_c-and-upload-linux-arm64:
+    needs: [checks]
+    name: "Linux-Arm64: Build & Upload rerun_c"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
+    with:
+      CONCURRENCY: nightly-linux-arm64
+      PLATFORM: linux-arm64
+    secrets: inherit
+
+  build-rerun_c-and-upload-linux-x64:
+    needs: [checks]
+    name: "Linux-x64: Build & Upload rerun_c"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
+    with:
+      CONCURRENCY: nightly-linux-x64
+      PLATFORM: linux-x64
+    secrets: inherit
+
+  build-rerun_c-and-upload-macos-x64:
+    needs: [checks]
+    name: "Mac-Intel: Build & Upload rerun_c"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
+    with:
+      CONCURRENCY: nightly-macos-x64
+      PLATFORM: macos-x64
+    secrets: inherit
+
+  build-rerun_c-and-upload-macos-arm64:
+    needs: [checks]
+    name: "Mac-Arm64: Build & Upload rerun_c"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
+    with:
+      CONCURRENCY: nightly-macos-arm64
+      PLATFORM: macos-arm64
+    secrets: inherit
+
+  build-rerun_c-and-upload-windows-x64:
+    needs: [checks]
+    name: "Windows-x64: Build & Upload rerun_c"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
+    with:
+      CONCURRENCY: nightly-windows-x64
+      PLATFORM: windows-x64
+    secrets: inherit
+
+  # -----------------------------------------------------------------------------------
+  # Build rerun-cli (rerun binaries):
+
+  build-rerun-cli-and-upload-linux-arm64:
+    needs: [checks]
+    name: "Linux-arm64: Build & Upload rerun-cli"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
+    with:
+      CONCURRENCY: nightly-linux-arm64
+      PLATFORM: linux-arm64
+    secrets: inherit
+
+  build-rerun-cli-and-upload-linux-x64:
+    needs: [checks]
+    name: "Linux-x64: Build & Upload rerun-cli"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
+    with:
+      CONCURRENCY: nightly-linux-x64
+      PLATFORM: linux-x64
+    secrets: inherit
+
+  build-rerun-cli-and-upload-macos-x64:
+    needs: [checks]
+    name: "Mac-x64: Build & Upload rerun-cli"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
+    with:
+      CONCURRENCY: nightly-macos-x64
+      PLATFORM: macos-x64
+    secrets: inherit
+
+  build-rerun-cli-and-upload-macos-arm64:
+    needs: [checks]
+    name: "Mac-arm64: Build & Upload rerun-cli"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
+    with:
+      CONCURRENCY: nightly-macos-arm64
+      PLATFORM: macos-arm64
+    secrets: inherit
+
+  build-rerun-cli-and-upload-windows-x64:
+    needs: [checks]
+    name: "Windows-x64: Build & Upload rerun-cli"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
+    with:
+      CONCURRENCY: nightly-windows-x64
+      PLATFORM: windows-x64
+    secrets: inherit
+
   # ---------------------------------------------------------------------------
   # Build wheels:
 
   build-wheel-linux-arm64:
-    needs: [checks]
+    needs: [checks, build-rerun-cli-and-upload-linux-arm64]
     name: "Linux-arm64: Build & Upload Wheels"
     uses: ./.github/workflows/reusable_build_and_upload_wheels.yml
     with:
@@ -89,7 +185,7 @@ jobs:
     secrets: inherit
 
   build-wheel-linux-x64:
-    needs: [checks]
+    needs: [checks, build-rerun-cli-and-upload-linux-x64]
     name: "Linux-x64: Build & Upload Wheels"
     uses: ./.github/workflows/reusable_build_and_upload_wheels.yml
     with:
@@ -100,7 +196,7 @@ jobs:
     secrets: inherit
 
   build-wheel-macos-arm64:
-    needs: [checks]
+    needs: [checks, build-rerun-cli-and-upload-macos-arm64]
     name: "Macos-arm64: Build & Upload Wheels"
     uses: ./.github/workflows/reusable_build_and_upload_wheels.yml
     with:
@@ -111,7 +207,7 @@ jobs:
     secrets: inherit
 
   build-wheel-macos-x64:
-    needs: [checks]
+    needs: [checks, build-rerun-cli-and-upload-macos-x64]
     name: "Macos-x64: Build & Upload Wheels"
     uses: ./.github/workflows/reusable_build_and_upload_wheels.yml
     with:
@@ -122,7 +218,7 @@ jobs:
     secrets: inherit
 
   build-wheel-windows-x64:
-    needs: [checks]
+    needs: [checks, build-rerun-cli-and-upload-windows-x64]
     name: "Windows-x64: Build & Upload Wheels"
     uses: ./.github/workflows/reusable_build_and_upload_wheels.yml
     with:
@@ -185,103 +281,6 @@ jobs:
       WHEEL_ARTIFACT_NAME: windows-x64-wheel
     secrets: inherit
 
-  # -----------------------------------------------------------------------------------
-  # Build rerun_c library binaries:
-
-  build-rerun_c-and-upload-linux-arm64:
-    needs: [checks]
-    name: "Linux-Arm64: Build & Upload rerun_c"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
-    with:
-      CONCURRENCY: nightly-linux-arm64
-      PLATFORM: linux-arm64
-    secrets: inherit
-
-  build-rerun_c-and-upload-linux-x64:
-    needs: [checks]
-    name: "Linux-x64: Build & Upload rerun_c"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
-    with:
-      CONCURRENCY: nightly-linux-x64
-      PLATFORM: linux-x64
-    secrets: inherit
-
-  build-rerun_c-and-upload-macos-x64:
-    needs: [checks]
-    name: "Mac-Intel: Build & Upload rerun_c"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
-    with:
-      CONCURRENCY: nightly-macos-x64
-      PLATFORM: macos-x64
-    secrets: inherit
-
-  build-rerun_c-and-upload-macos-arm64:
-    needs: [checks]
-    name: "Mac-Arm64: Build & Upload rerun_c"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
-    with:
-      CONCURRENCY: nightly-macos-arm64
-      PLATFORM: macos-arm64
-    secrets: inherit
-
-  build-rerun_c-and-upload-windows-x64:
-    needs: [checks]
-    name: "Windows-x64: Build & Upload rerun_c"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_c.yml
-    with:
-      CONCURRENCY: nightly-windows-x64
-      PLATFORM: windows-x64
-    secrets: inherit
-
-  # -----------------------------------------------------------------------------------
-  # TODO(emilk): build and test one additional platorm, picked at random
-  # Build rerun-cli (rerun binaries):
-
-  build-rerun-cli-and-upload-linux-arm64:
-    needs: [checks]
-    name: "Linux-arm64: Build & Upload rerun-cli"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
-    with:
-      CONCURRENCY: nightly-linux-arm64
-      PLATFORM: linux-arm64
-    secrets: inherit
-
-  build-rerun-cli-and-upload-linux-x64:
-    needs: [checks]
-    name: "Linux-x64: Build & Upload rerun-cli"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
-    with:
-      CONCURRENCY: nightly-linux-x64
-      PLATFORM: linux-x64
-    secrets: inherit
-
-  build-rerun-cli-and-upload-macos-x64:
-    needs: [checks]
-    name: "Mac-x64: Build & Upload rerun-cli"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
-    with:
-      CONCURRENCY: nightly-macos-x64
-      PLATFORM: macos-x64
-    secrets: inherit
-
-  build-rerun-cli-and-upload-macos-arm64:
-    needs: [checks]
-    name: "Mac-arm64: Build & Upload rerun-cli"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
-    with:
-      CONCURRENCY: nightly-macos-arm64
-      PLATFORM: macos-arm64
-    secrets: inherit
-
-  build-rerun-cli-and-upload-windows-x64:
-    needs: [checks]
-    name: "Windows-x64: Build & Upload rerun-cli"
-    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
-    with:
-      CONCURRENCY: nightly-windows-x64
-      PLATFORM: windows-x64
-    secrets: inherit
-
   # ---------------------------------------------------------------------------
 
   run-notebook:
diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml
index 40e8e21c7184..b5ed0d6ca214 100644
--- a/.github/workflows/on_pull_request.yml
+++ b/.github/workflows/on_pull_request.yml
@@ -161,11 +161,19 @@ jobs:
       FULL: "true"
     secrets: inherit
 
+  min-cli-build:
+    name: "Minimum CLI Build"
+    uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
+    with:
+      CONCURRENCY: pr-${{ github.event.pull_request.number }}
+      PLATFORM: linux-x64
+    secrets: inherit
+
   # Build and test a single wheel to limit CI cost. We use linux-x64 because it's fast. linux-arm64 would also be a good
   # choice, but reusable_test_wheels.yml is broken for that target (https://github.com/rerun-io/rerun/issues/5525)
   min-wheel-build:
     name: "Minimum Wheel Build"
-    needs: [python-paths-filter, rust-paths-filter]
+    needs: [min-cli-build, python-paths-filter, rust-paths-filter]
     if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && (needs.python-paths-filter.outputs.python_changes == 'true' || needs.rust-paths-filter.outputs.rust_changes == 'true')
     uses: ./.github/workflows/reusable_build_and_upload_wheels.yml
     with:
diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml
index f32485d92859..182819f96026 100644
--- a/.github/workflows/on_push_main.yml
+++ b/.github/workflows/on_push_main.yml
@@ -100,7 +100,7 @@ jobs:
     secrets: inherit
 
   # -----------------------------------------------------------------------------------
-  # TODO(emilk): build and test one additional platorm, picked at random
+  # TODO(emilk): build and test one additional platform, picked at random
 
   build-rerun_c-and-upload-linux-x64:
     needs: [checks]
@@ -112,7 +112,7 @@ jobs:
     secrets: inherit
 
   # -----------------------------------------------------------------------------------
-  # TODO(emilk): build and test one additional platorm, picked at random
+  # TODO(emilk): build and test one additional platform, picked at random
 
   build-rerun-cli-and-upload-linux-x64:
     needs: [checks]
@@ -124,10 +124,10 @@ jobs:
     secrets: inherit
 
   # -----------------------------------------------------------------------------------
-  # TODO(emilk): build and test one additional platorm, picked at random
+  # TODO(emilk): build and test one additional platform, picked at random
 
   build-wheel-linux-x64:
-    needs: [checks]
+    needs: [checks, build-rerun-cli-and-upload-linux-x64]
     name: "Linux-x64: Build & Upload Wheels"
     uses: ./.github/workflows/reusable_build_and_upload_wheels.yml
     with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6f11aa26df6b..fc38a4ca650c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -223,46 +223,46 @@ jobs:
       RELEASE_COMMIT: ${{ needs.version.outputs.release-commit }}
     secrets: inherit
 
-  publish-wheels:
-    name: "Build and Publish Wheels"
+  publish-rerun_c:
+    name: "Build and Publish rerun_c"
     needs: [version]
-    uses: ./.github/workflows/reusable_publish_wheels.yml
+    uses: ./.github/workflows/reusable_publish_rerun_c.yml
     with:
       release-version: ${{ needs.version.outputs.current }}
-      concurrency: ${{ github.ref_name }}
       release-commit: ${{ needs.version.outputs.release-commit }}
+      concurrency: ${{ github.ref_name }}
     secrets: inherit
 
-  publish-web:
-    name: "Build and Publish Web"
-    needs: [version, publish-wheels]
-    uses: ./.github/workflows/reusable_publish_web.yml
+  publish-rerun-cli:
+    name: "Publish rerun-cli"
+    needs: [version]
+    uses: ./.github/workflows/reusable_publish_rerun_cli.yml
     with:
       release-version: ${{ needs.version.outputs.current }}
       release-commit: ${{ needs.version.outputs.release-commit }}
       concurrency: ${{ github.ref_name }}
-      wheel-artifact-name: linux-x64-wheel
-      update-latest: ${{ inputs.release-type == 'final' }}
     secrets: inherit
 
-  publish-rerun_c:
-    name: "Build and Publish rerun_c"
-    needs: [version]
-    uses: ./.github/workflows/reusable_publish_rerun_c.yml
+  publish-wheels:
+    name: "Build and Publish Wheels"
+    needs: [version, publish-rerun-cli]
+    uses: ./.github/workflows/reusable_publish_wheels.yml
     with:
       release-version: ${{ needs.version.outputs.current }}
-      release-commit: ${{ needs.version.outputs.release-commit }}
       concurrency: ${{ github.ref_name }}
+      release-commit: ${{ needs.version.outputs.release-commit }}
     secrets: inherit
 
-  publish-rerun-cli:
-    name: "Publish rerun-cli"
-    needs: [version]
-    uses: ./.github/workflows/reusable_publish_rerun_cli.yml
+  publish-web:
+    name: "Build and Publish Web"
+    needs: [version, publish-wheels]
+    uses: ./.github/workflows/reusable_publish_web.yml
     with:
       release-version: ${{ needs.version.outputs.current }}
       release-commit: ${{ needs.version.outputs.release-commit }}
       concurrency: ${{ github.ref_name }}
+      wheel-artifact-name: linux-x64-wheel
+      update-latest: ${{ inputs.release-type == 'final' }}
     secrets: inherit
 
   publish-js:
diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml
index a419ab9f9bc1..e076978fec19 100644
--- a/.github/workflows/reusable_build_and_upload_wheels.yml
+++ b/.github/workflows/reusable_build_and_upload_wheels.yml
@@ -195,9 +195,17 @@ jobs:
       - name: Get sha
         id: get-sha
         run: |
-          full_commit="${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.ref) || github.sha) }}"
+          full_commit="${{ inputs.RELEASE_COMMIT || ((github.event_name == 'pull_request' && github.event.pull_request.head.sha) || github.sha) }}"
           echo "sha=$(echo $full_commit | cut -c1-7)" >> "$GITHUB_OUTPUT"
 
+      - name: "Download rerun-cli"
+        run: |
+          pixi run fetch-artifact \
+          --commit-sha ${{ steps.get-sha.outputs.sha }} \
+          --artifact rerun-cli \
+          --platform ${{ inputs.PLATFORM }} \
+          --dest rerun_py/rerun_sdk/bin
+
       - name: Build
         run: |
           pixi run python scripts/ci/build_and_upload_wheels.py \
diff --git a/Cargo.lock b/Cargo.lock
index 9dedcb56747a..ae2f66f56af3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5412,9 +5412,9 @@ dependencies = [
  "re_log",
  "re_log_types",
  "re_memory",
+ "re_sdk",
  "re_web_viewer_server",
  "re_ws_comms",
- "rerun",
  "tokio",
  "uuid",
 ]
diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs
index 9947e1bfc46e..f37053686baf 100644
--- a/crates/re_sdk/src/recording_stream.rs
+++ b/crates/re_sdk/src/recording_stream.rs
@@ -453,7 +453,7 @@ impl RecordingStreamBuilder {
             return self.connect_opts(connect_addr, flush_timeout);
         }
 
-        spawn(opts)?;
+        crate::spawn(opts)?;
 
         self.connect_opts(connect_addr, flush_timeout)
     }
@@ -1621,7 +1621,7 @@ impl RecordingStream {
             return Ok(());
         }
 
-        spawn(opts)?;
+        crate::spawn(opts)?;
 
         self.connect_opts(opts.connect_addr(), flush_timeout);
 
@@ -1807,37 +1807,6 @@ impl fmt::Debug for RecordingStream {
     }
 }
 
-/// Helper to deduplicate spawn logic across [`RecordingStreamBuilder`] & [`RecordingStream`].
-fn spawn(opts: &crate::SpawnOptions) -> RecordingStreamResult<()> {
-    use std::{net::TcpStream, time::Duration};
-
-    let connect_addr = opts.connect_addr();
-
-    // TODO(#4019): application-level handshake
-    if TcpStream::connect_timeout(&connect_addr, Duration::from_secs(1)).is_ok() {
-        re_log::info!(
-            addr = %opts.listen_addr(),
-            "A process is already listening at this address. Trying to connect instead."
-        );
-    } else {
-        crate::spawn(opts)?;
-
-        // Give the newly spawned Rerun Viewer some time to bind.
-        //
-        // NOTE: The timeout only covers the TCP handshake: if no process is bound to that address
-        // at all, the connection will fail immediately, irrelevant of the timeout configuration.
-        // For that reason we use an extra loop.
-        for _ in 0..5 {
-            if TcpStream::connect_timeout(&connect_addr, Duration::from_secs(1)).is_ok() {
-                break;
-            }
-            std::thread::sleep(Duration::from_millis(100));
-        }
-    }
-
-    Ok(())
-}
-
 // --- Stateful time ---
 
 /// Thread-local data.
diff --git a/crates/re_sdk/src/spawn.rs b/crates/re_sdk/src/spawn.rs
index 384753fcc0e1..9e76654fc65f 100644
--- a/crates/re_sdk/src/spawn.rs
+++ b/crates/re_sdk/src/spawn.rs
@@ -18,6 +18,10 @@ pub struct SpawnOptions {
     /// Defaults to `9876`.
     pub port: u16,
 
+    /// If `true`, the call to [`spawn`] will block until the Rerun Viewer
+    /// has successfully bound to the port.
+    pub wait_for_bind: bool,
+
     /// An upper limit on how much memory the Rerun Viewer should use.
     /// When this limit is reached, Rerun will drop the oldest data.
     /// Example: `16GB` or `50%` (of system total).
@@ -49,6 +53,7 @@ impl Default for SpawnOptions {
     fn default() -> Self {
         Self {
             port: crate::default_server_addr().port(),
+            wait_for_bind: false,
             memory_limit: "75%".into(),
             executable_name: RERUN_BINARY.into(),
             executable_path: None,
@@ -251,6 +256,20 @@ pub fn spawn(opts: &SpawnOptions) -> Result<(), SpawnError> {
         .spawn()
         .map_err(map_err)?;
 
+    if opts.wait_for_bind {
+        // Give the newly spawned Rerun Viewer some time to bind.
+        //
+        // NOTE: The timeout only covers the TCP handshake: if no process is bound to that address
+        // at all, the connection will fail immediately, irrelevant of the timeout configuration.
+        // For that reason we use an extra loop.
+        for _ in 0..5 {
+            if TcpStream::connect_timeout(&connect_addr, Duration::from_secs(1)).is_ok() {
+                break;
+            }
+            std::thread::sleep(Duration::from_millis(100));
+        }
+    }
+
     // Simply forget about the child process, we want it to outlive the parent process if needed.
     _ = rerun_bin;
 
diff --git a/crates/rerun/src/run.rs b/crates/rerun/src/run.rs
index ce6326185953..73d970b32259 100644
--- a/crates/rerun/src/run.rs
+++ b/crates/rerun/src/run.rs
@@ -5,7 +5,7 @@ use clap::Subcommand;
 use itertools::Itertools;
 
 use re_data_source::DataSource;
-use re_log_types::{DataTable, LogMsg, PythonVersion, SetStoreInfo};
+use re_log_types::{DataTable, LogMsg, SetStoreInfo};
 use re_smart_channel::{ReceiveSet, Receiver, SmartMessagePayload};
 
 #[cfg(feature = "web_viewer")]
@@ -295,21 +295,15 @@ enum AnalyticsCommands {
 }
 
 /// Where are we calling [`run`] from?
-#[derive(Clone, Debug, PartialEq, Eq)]
+// TODO(jleibs): Maybe remove call-source all together.
+// However, this context of spawn vs direct CLI-invocation still seems
+// useful for analytics. We just need to capture the data some other way.
 pub enum CallSource {
     /// Called from a command-line-input (the terminal).
     Cli,
-
-    /// Called from the Rerun Python SDK.
-    Python(PythonVersion),
 }
 
 impl CallSource {
-    #[allow(dead_code)]
-    fn is_python(&self) -> bool {
-        matches!(self, Self::Python(_))
-    }
-
     #[cfg(feature = "native_viewer")]
     fn app_env(&self) -> re_viewer::AppEnvironment {
         match self {
@@ -317,9 +311,6 @@ impl CallSource {
                 rustc_version: env!("RE_BUILD_RUSTC_VERSION").into(),
                 llvm_version: env!("RE_BUILD_LLVM_VERSION").into(),
             },
-            CallSource::Python(python_version) => {
-                re_viewer::AppEnvironment::PythonSdk(python_version.clone())
-            }
         }
     }
 }
@@ -643,9 +634,7 @@ async fn run_impl(
         {
             let server_options = re_sdk_comms::ServerOptions {
                 max_latency_sec: parse_max_latency(args.drop_at_latency.as_ref()),
-
-                // `rerun.spawn()` doesn't need to log that a connection has been made
-                quiet: call_source.is_python(),
+                quiet: false,
             };
             let rx = re_sdk_comms::serve(&args.bind, args.port, server_options).await?;
             vec![rx]
diff --git a/crates/rerun_c/src/lib.rs b/crates/rerun_c/src/lib.rs
index b9420bca3c2b..75844824e1c3 100644
--- a/crates/rerun_c/src/lib.rs
+++ b/crates/rerun_c/src/lib.rs
@@ -98,6 +98,8 @@ impl CSpawnOptions {
             spawn_opts.port = self.port;
         }
 
+        spawn_opts.wait_for_bind = true;
+
         if !self.memory_limit.is_empty() {
             spawn_opts.memory_limit = self.memory_limit.as_str("memory_limit")?.to_owned();
         }
diff --git a/pixi.toml b/pixi.toml
index 056f4a3497e3..e4c2b43f870c 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -37,6 +37,9 @@ codegen = "cargo --quiet run --package re_types_builder -- "
 # You can also give an argument for what to view (e.g. an .rrd file).
 rerun = "cargo run --package rerun-cli --no-default-features --features native_viewer --"
 
+# Compile `rerun-cli` without the web-viewer.
+rerun-build = "cargo build --package rerun-cli --no-default-features --features native_viewer"
+
 # Compile and run the rerun viewer with --release.
 #
 # You can also give an argument for what to view (e.g. an .rrd file).
@@ -109,8 +112,23 @@ py-fmt = "ruff check --fix --config rerun_py/pyproject.toml . && ruff format --c
 py-fmt-check = "ruff check --config rerun_py/pyproject.toml . && ruff format --check --config rerun_py/pyproject.toml"
 py-lint = "mypy --install-types --non-interactive --no-warn-unused-ignore"
 
-py-build = "maturin develop --manifest-path rerun_py/Cargo.toml --extras=tests"
-py-wheel = "maturin build --manifest-path rerun_py/Cargo.toml"
+# Build and install a development version of the rerun-sdk Python package.
+#
+# This only needs to be called when you have made changes that would impact the rust bindings of
+# the python package. The python code will be imported directly from the source folder and will
+# reflect changes immediately upon re-import.
+py-build = { cmd = "RERUN_ALLOW_MISSING_BIN=1 maturin develop --manifest-path rerun_py/Cargo.toml --extras=tests", depends_on = [
+  "rerun-build",
+] }
+
+# Build a wheel for the rerun-sdk Python package.
+#
+# The built wheel can be found in the `target/wheels` folder, and needs to be manually
+# installed via `pip install target/wheels/rerun_sdk-*.whl`.
+#
+# This is useful for testing of the packainge process or working with rerun in the
+# context of a separate venv. Otherwise, `py-build` will be faster and much more convenient.
+py-wheel = "maturin build --manifest-path rerun_py/Cargo.toml --features pypi"
 
 # Run the Python tests.
 # Don't call this on CI - use `nox` to run tests on all supported Python versions instead.
@@ -161,6 +179,11 @@ upload-image = "python scripts/upload_image.py"
 # Check whether there's too large files in the repository.
 check-large-files = "python scripts/ci/check_large_files.py"
 
+# Download a specific artifact from gcloud.
+#
+# Requires that gcloud authentication has already been set up in your shell.
+fetch-artifact = "python scripts/ci/fetch_artifact.py"
+
 [feature.py-docs.tasks]
 # Serve python docs locally
 py-docs-serve = "mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py"
diff --git a/rerun_py/.gitignore b/rerun_py/.gitignore
index a52325cc33c6..c0446e80d07d 100644
--- a/rerun_py/.gitignore
+++ b/rerun_py/.gitignore
@@ -1,6 +1,7 @@
 !Cargo.lock
 .DS_Store
+rerun_sdk/bin/**
+site/
 target/
 venv/
 wheels/
-site/
diff --git a/rerun_py/Cargo.toml b/rerun_py/Cargo.toml
index b93a006fb8fb..d55f4e9fdb47 100644
--- a/rerun_py/Cargo.toml
+++ b/rerun_py/Cargo.toml
@@ -12,11 +12,11 @@ name = "rerun_bindings" # name of the .so library that the Python module will im
 
 
 [features]
-default = ["extension-module", "native_viewer"]
+default = ["extension-module"]
 
 ## The features we turn on when building the `rerun-sdk` PyPi package
 ## for .
-pypi = ["extension-module", "native_viewer", "web_viewer"]
+pypi = ["extension-module", "web_viewer"]
 
 ## We need to enable the `pyo3/extension-module` when building the SDK,
 ## but we cannot enable it when building tests and benchmarks, so we
@@ -25,29 +25,24 @@ pypi = ["extension-module", "native_viewer", "web_viewer"]
 ## * 
 extension-module = ["pyo3/extension-module"]
 
-## Support spawning a native Rerun viewer with `spawn()`.
-native_viewer = ["rerun/native_viewer"]
-
 ## Support serving a web viewer over HTTP with `serve()`.
 ##
 ## Enabling this adds quite a bit to the compile time and binary size,
 ## since it requires compiling and bundling the viewer as wasm.
-web_viewer = ["rerun/web_viewer", "dep:re_web_viewer_server", "dep:re_ws_comms"]
+web_viewer = [
+  "re_sdk/web_viewer",
+  "dep:re_web_viewer_server",
+  "dep:re_ws_comms",
+]
 
 
 [dependencies]
 re_build_info.workspace = true
 re_error.workspace = true
-re_log.workspace = true
+re_log = { workspace = true, features = ["setup"] }
 re_log_types.workspace = true
 re_memory.workspace = true
-rerun = { workspace = true, features = [
-  "analytics",
-  "data_loaders",
-  "run",
-  "server",
-  "sdk",
-] }
+re_sdk = { workspace = true, features = ["data_loaders"] }
 re_web_viewer_server = { workspace = true, optional = true }
 re_ws_comms = { workspace = true, optional = true }
 
diff --git a/rerun_py/build.rs b/rerun_py/build.rs
index bf40581aca5a..dac279d73a86 100644
--- a/rerun_py/build.rs
+++ b/rerun_py/build.rs
@@ -3,4 +3,22 @@ fn main() {
     pyo3_build_config::add_extension_module_link_args();
 
     re_build_tools::export_build_info_vars_for_crate("rerun_py");
+
+    // Fail if bin/rerun is missing and we haven't specified it's ok.
+    if re_build_tools::is_tracked_env_var_set("RERUN_BUILDING_WHEEL")
+        && !re_build_tools::is_tracked_env_var_set("RERUN_ALLOW_MISSING_BIN")
+    {
+        #[cfg(target_os = "windows")]
+        let rerun_bin = std::env::current_dir()
+            .unwrap()
+            .join("rerun_sdk/bin/rerun.exe");
+
+        #[cfg(not(target_os = "windows"))]
+        let rerun_bin = std::env::current_dir().unwrap().join("rerun_sdk/bin/rerun");
+
+        if !rerun_bin.exists() {
+            eprintln!("ERROR: Expected to find `rerun` at `{rerun_bin:?}`.");
+            std::process::exit(1);
+        }
+    }
 }
diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml
index 5f68e4e92f28..0499001c9e3e 100644
--- a/rerun_py/pyproject.toml
+++ b/rerun_py/pyproject.toml
@@ -40,7 +40,7 @@ homepage = "https://www.rerun.io"
 repository = "https://github.com/rerun-io/rerun"
 
 [project.scripts]
-rerun = "rerun_bindings:main"
+rerun = "rerun_cli.__main__:main"
 
 [tool.ruff]
 # https://beta.ruff.rs/docs/configuration/
@@ -139,10 +139,18 @@ required-imports = ["from __future__ import annotations"]
 # with the other `rerun` pypi package. The rerun_sdk.pth adds this to the pythonpath
 # which then allows `import rerun` to work as expected.
 # See https://github.com/rerun-io/rerun/pull/1085 for more details
-include = ["rerun_sdk.pth"]
+# Even though both `rerun` and `rerun.exe` are here, only one will be included since
+# they both should not be fetched in CI when running the build.
+# Files missing from this list is not a packaging failure.
+include = ["rerun_sdk.pth", "rerun_sdk/bin/rerun", "rerun_sdk/bin/rerun.exe"]
 locked = true
 name = "rerun_bindings"
-python-packages = ["rerun_sdk/rerun"]
+python-packages = ["rerun_sdk/rerun", "rerun_sdk/rerun_cli"]
+
+# Setting this to 1 causes lets the build.rs script know we are building a wheel,
+# which will cause it to check for the existence of the `rerun` binary.
+config = ["env.RERUN_BUILDING_WHEEL=\"1\""]
+
 
 [tool.pytest.ini_options]
 # These conform to Python's Warning Filter syntax:
diff --git a/rerun_py/rerun/__init__.py b/rerun_py/rerun/__init__.py
index be05e3b1f63c..4806b16a6e1c 100644
--- a/rerun_py/rerun/__init__.py
+++ b/rerun_py/rerun/__init__.py
@@ -10,10 +10,15 @@
 When we encounter this file on import, we instead redirect to the
 real rerun module by adding it to the path and then, and then
 replacing our own module content with it.
+
+Additionally, we set the RERUN_CLI_PATH environment variable to point
+to the rerun binary in the target directory so that we don't need to
+inject it into the source tree.
 """
 
 from __future__ import annotations
 
+import os
 import pathlib
 import sys
 
@@ -21,6 +26,10 @@
 
 print(f"DEV ENVIRONMENT DETECTED! Re-importing rerun from: {real_path}", file=sys.stderr)
 
+if "RERUN_CLI_PATH" not in os.environ:
+    target_path = pathlib.Path(__file__).parent.parent.parent.joinpath("target/debug/rerun").resolve()
+    os.environ["RERUN_CLI_PATH"] = str(target_path)
+
 sys.path.insert(0, str(real_path))
 
 del sys.modules["rerun"]
diff --git a/rerun_py/rerun_cli/__init__.py b/rerun_py/rerun_cli/__init__.py
new file mode 100644
index 000000000000..df2785e7a4bf
--- /dev/null
+++ b/rerun_py/rerun_cli/__init__.py
@@ -0,0 +1,36 @@
+"""
+A shim necessary to make maturin dev builds work properly.
+
+Our maturin builds stick our package inside of a "rerun_sdk" folder
+to avoid conflicting with the non-rerun "rerun" package. In released
+builds, we include a rerun_sdk.pth file that makes things work properly,
+but that doesn't work in dev builds where maturin generates its own
+.pth file that points 1 level too high.
+
+When we encounter this file on import, we instead redirect to the
+real rerun module by adding it to the path and then, and then
+replacing our own module content with it.
+
+Additionally, we set the RERUN_CLI_PATH environment variable to point
+to the rerun binary in the target directory so that we don't need to
+inject it into the source tree.
+"""
+
+from __future__ import annotations
+
+import os
+import pathlib
+import sys
+
+real_path = pathlib.Path(__file__).parent.parent.joinpath("rerun_sdk").resolve()
+
+print(f"DEV ENVIRONMENT DETECTED! Re-importing rerun from: {real_path}", file=sys.stderr)
+
+if "RERUN_CLI_PATH" not in os.environ:
+    target_path = pathlib.Path(__file__).parent.parent.parent.joinpath("target/debug/rerun").resolve()
+    os.environ["RERUN_CLI_PATH"] = str(target_path)
+
+sys.path.insert(0, str(real_path))
+
+del sys.modules["rerun_cli"]
+sys.modules["rerun_cli"] = __import__("rerun_cli")
diff --git a/rerun_py/rerun_sdk/rerun/__main__.py b/rerun_py/rerun_sdk/rerun/__main__.py
index 9fc0a594394a..6b2e9525c09c 100644
--- a/rerun_py/rerun_sdk/rerun/__main__.py
+++ b/rerun_py/rerun_sdk/rerun/__main__.py
@@ -1,20 +1,35 @@
-"""See `python3 -m rerun --help`."""
+"""
+See `python3 -m rerun --help`.
+
+This is a duplicate of `rerun_cli/__main__.py` to allow running `python3 -m rerun` directly.
+In general `rerun -m rerun_cli` should be preferred, as it carries less overhead related to
+importing the module.
+"""
 
 from __future__ import annotations
 
-import rerun_bindings as bindings
+import os
+import subprocess
+import sys
 
 from rerun import unregister_shutdown
 
 
-def main() -> None:
-    # When running `python -m rerun` (i.e. executing this file), the `rerun` package and its `__init__.py` are still
-    # loaded. This has the side effect of executing `register_shutdown()` (schedule `bindings.shutdown()` to be called
-    # at exit. We don't need this here, so we unregister that call.
-    # TODO(ab): figure out a way to skip loading `__init__.py` entirely (to avoid doing this and save on loading time)
+def main() -> int:
+    # Importing of the rerun module registers a shutdown hook that we know we don't
+    # need when running the CLI directly. We can safely unregister it.
     unregister_shutdown()
+    if "RERUN_CLI_PATH" in os.environ:
+        print(f"Using overridden RERUN_CLI_PATH={os.environ['RERUN_CLI_PATH']}", file=sys.stderr)
+        target_path = os.environ["RERUN_CLI_PATH"]
+    else:
+        target_path = os.path.join(os.path.dirname(__file__), "..", "bin", "rerun")
+
+    if not os.path.exists(target_path):
+        print(f"Error: Could not find rerun binary at {target_path}", file=sys.stderr)
+        return 1
 
-    exit(bindings.main())
+    return subprocess.call([target_path, *sys.argv[1:]])
 
 
 if __name__ == "__main__":
diff --git a/rerun_py/rerun_sdk/rerun/_spawn.py b/rerun_py/rerun_sdk/rerun/_spawn.py
index 1d3b9b2979d0..a5e1cc5e78dc 100644
--- a/rerun_py/rerun_sdk/rerun/_spawn.py
+++ b/rerun_py/rerun_sdk/rerun/_spawn.py
@@ -1,22 +1,6 @@
 from __future__ import annotations
 
-import socket
-
-
-# TODO(#4019): application-level handshake
-def _check_for_existing_viewer(port: int) -> bool:
-    try:
-        # Try opening a connection to the port to see if something is there
-        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        s.settimeout(1)
-        s.connect(("127.0.0.1", port))
-        return True
-    except Exception:
-        # If the connection times out or is refused, the port is not open
-        return False
-    finally:
-        # Always close the socket to release resources
-        s.close()
+import os
 
 
 def _spawn_viewer(
@@ -42,10 +26,7 @@ def _spawn_viewer(
 
     """
 
-    import os
-    import subprocess
-    import sys
-    from time import sleep
+    import rerun_bindings
 
     # Let the spawned rerun process know it's just an app
     new_env = os.environ.copy()
@@ -55,39 +36,4 @@ def _spawn_viewer(
         return
     new_env["RERUN_APP_ONLY"] = "true"
 
-    # sys.executable: the absolute path of the executable binary for the Python interpreter
-    python_executable = sys.executable
-    if python_executable is None:
-        python_executable = "python3"
-
-    # TODO(jleibs): More options to opt out of this behavior.
-    if _check_for_existing_viewer(port):
-        # Using print here for now rather than `logging.info` because logging.info isn't
-        # visible by default.
-        #
-        # If we spawn a process it's going to send a bunch of stuff to stdout anyways.
-        print(f"Found existing process on port {port}. Trying to connect.")
-    else:
-        # start_new_session=True ensures the spawned process does NOT die when
-        # we hit ctrl-c in the terminal running the parent Python process.
-        subprocess.Popen(
-            [
-                python_executable,
-                "-c",
-                "import rerun_bindings; rerun_bindings.main()",
-                f"--port={port}",
-                f"--memory-limit={memory_limit}",
-                "--expect-data-soon",
-            ],
-            env=new_env,
-            start_new_session=True,
-        )
-
-        # Give the newly spawned Rerun Viewer some time to bind.
-        #
-        # NOTE: The timeout only covers the TCP handshake: if no process is bound to that address
-        # at all, the connection will fail immediately, irrelevant of the timeout configuration.
-        # For that reason we use an extra loop.
-        for _ in range(0, 5):
-            _check_for_existing_viewer(port)
-            sleep(0.1)
+    rerun_bindings.spawn(port=port, memory_limit=memory_limit)
diff --git a/rerun_py/rerun_sdk/rerun_cli/__init__.py b/rerun_py/rerun_sdk/rerun_cli/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/rerun_py/rerun_sdk/rerun_cli/__main__.py b/rerun_py/rerun_sdk/rerun_cli/__main__.py
new file mode 100644
index 000000000000..f3c5f416e2e8
--- /dev/null
+++ b/rerun_py/rerun_sdk/rerun_cli/__main__.py
@@ -0,0 +1,25 @@
+"""See `python3 -m rerun_cli --help`."""
+
+from __future__ import annotations
+
+import os
+import subprocess
+import sys
+
+
+def main() -> int:
+    if "RERUN_CLI_PATH" in os.environ:
+        print(f"Using overridden RERUN_CLI_PATH={os.environ['RERUN_CLI_PATH']}", file=sys.stderr)
+        target_path = os.environ["RERUN_CLI_PATH"]
+    else:
+        target_path = os.path.join(os.path.dirname(__file__), "..", "bin", "rerun")
+
+    if not os.path.exists(target_path):
+        print(f"Error: Could not find rerun binary at {target_path}", file=sys.stderr)
+        return 1
+
+    return subprocess.call([target_path, *sys.argv[1:]])
+
+
+if __name__ == "__main__":
+    main()
diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs
index 2cdf41bd8fe3..71c5b46d5e10 100644
--- a/rerun_py/src/python_bridge.rs
+++ b/rerun_py/src/python_bridge.rs
@@ -14,7 +14,7 @@ use pyo3::{
 };
 
 use re_log_types::{BlueprintActivationCommand, EntityPathPart, StoreKind};
-use rerun::{
+use re_sdk::{
     sink::MemorySinkStorage, time::TimePoint, EntityPath, RecordingStream, RecordingStreamBuilder,
     StoreId,
 };
@@ -91,34 +91,6 @@ fn global_web_viewer_server(
     WEB_HANDLE.get_or_init(Default::default).lock()
 }
 
-#[pyfunction]
-fn main(py: Python<'_>) -> PyResult {
-    // We access argv ourselves instead of accepting as parameter, so that `main`'s signature is
-    // compatible with `[project.scripts]` in `pyproject.toml`.
-    let sys = py.import("sys")?;
-    let argv: Vec = sys.getattr("argv")?.extract()?;
-
-    let build_info = re_build_info::build_info!();
-    let call_src = rerun::CallSource::Python(python_version(py));
-    tokio::runtime::Builder::new_multi_thread()
-        .enable_all()
-        .build()
-        .unwrap()
-        .block_on(async {
-            // Python catches SIGINT and waits for us to release the GIL before shutting down.
-            // That's no good, so we need to catch SIGINT ourselves and shut down:
-            tokio::spawn(async move {
-                tokio::signal::ctrl_c().await.unwrap();
-                eprintln!("Ctrl-C detected in rerun_py. Shutting down.");
-                #[allow(clippy::exit)]
-                std::process::exit(42);
-            });
-
-            rerun::run(build_info, call_src, argv).await
-        })
-        .map_err(|err| PyRuntimeError::new_err(re_error::format(err)))
-}
-
 /// The python module is called "rerun_bindings".
 #[pymodule]
 fn rerun_bindings(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
@@ -126,9 +98,6 @@ fn rerun_bindings(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
     // called more than once.
     re_log::setup_logging();
 
-    // We always want main to be available
-    m.add_function(wrap_pyfunction!(main, m)?)?;
-
     // These two components are necessary for imports to work
     m.add_class::()?;
     m.add_class::()?;
@@ -145,6 +114,7 @@ fn rerun_bindings(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
     m.add_function(wrap_pyfunction!(new_blueprint, m)?)?;
     m.add_function(wrap_pyfunction!(shutdown, m)?)?;
     m.add_function(wrap_pyfunction!(cleanup_if_forked_child, m)?)?;
+    m.add_function(wrap_pyfunction!(spawn, m)?)?;
 
     // recordings
     m.add_function(wrap_pyfunction!(get_application_id, m)?)?;
@@ -369,7 +339,7 @@ fn get_recording_id(recording: Option<&PyRecordingStream>) -> Option {
 #[pyfunction]
 fn get_data_recording(recording: Option<&PyRecordingStream>) -> Option {
     RecordingStream::get_quiet(
-        rerun::StoreKind::Recording,
+        re_sdk::StoreKind::Recording,
         recording.map(|rec| rec.0.clone()),
     )
     .map(PyRecordingStream)
@@ -378,13 +348,13 @@ fn get_data_recording(recording: Option<&PyRecordingStream>) -> Option Option {
-    RecordingStream::global(rerun::StoreKind::Recording).map(PyRecordingStream)
+    RecordingStream::global(re_sdk::StoreKind::Recording).map(PyRecordingStream)
 }
 
 /// Cleans up internal state if this is the child of a forked process.
 #[pyfunction]
 fn cleanup_if_forked_child() {
-    rerun::cleanup_if_forked_child();
+    re_sdk::cleanup_if_forked_child();
 }
 
 /// Replaces the currently active recording in the global scope with the specified one.
@@ -404,7 +374,7 @@ fn set_global_data_recording(
     // sorry.
     py.allow_threads(|| {
         let rec = RecordingStream::set_global(
-            rerun::StoreKind::Recording,
+            re_sdk::StoreKind::Recording,
             recording.map(|rec| rec.0.clone()),
         )
         .map(PyRecordingStream);
@@ -416,7 +386,7 @@ fn set_global_data_recording(
 /// Returns the currently active data recording in the thread-local scope, if any.
 #[pyfunction]
 fn get_thread_local_data_recording() -> Option {
-    RecordingStream::thread_local(rerun::StoreKind::Recording).map(PyRecordingStream)
+    RecordingStream::thread_local(re_sdk::StoreKind::Recording).map(PyRecordingStream)
 }
 
 /// Replaces the currently active recording in the thread-local scope with the specified one.
@@ -436,7 +406,7 @@ fn set_thread_local_data_recording(
     // sorry.
     py.allow_threads(|| {
         let rec = RecordingStream::set_thread_local(
-            rerun::StoreKind::Recording,
+            re_sdk::StoreKind::Recording,
             recording.map(|rec| rec.0.clone()),
         )
         .map(PyRecordingStream);
@@ -450,7 +420,7 @@ fn set_thread_local_data_recording(
 #[pyfunction]
 fn get_blueprint_recording(overrides: Option<&PyRecordingStream>) -> Option {
     RecordingStream::get_quiet(
-        rerun::StoreKind::Blueprint,
+        re_sdk::StoreKind::Blueprint,
         overrides.map(|rec| rec.0.clone()),
     )
     .map(PyRecordingStream)
@@ -459,7 +429,7 @@ fn get_blueprint_recording(overrides: Option<&PyRecordingStream>) -> Option Option {
-    RecordingStream::global(rerun::StoreKind::Blueprint).map(PyRecordingStream)
+    RecordingStream::global(re_sdk::StoreKind::Blueprint).map(PyRecordingStream)
 }
 
 /// Replaces the currently active recording in the global scope with the specified one.
@@ -479,7 +449,7 @@ fn set_global_blueprint_recording(
     // sorry.
     py.allow_threads(|| {
         let rec = RecordingStream::set_global(
-            rerun::StoreKind::Blueprint,
+            re_sdk::StoreKind::Blueprint,
             recording.map(|rec| rec.0.clone()),
         )
         .map(PyRecordingStream);
@@ -491,7 +461,7 @@ fn set_global_blueprint_recording(
 /// Returns the currently active blueprint recording in the thread-local scope, if any.
 #[pyfunction]
 fn get_thread_local_blueprint_recording() -> Option {
-    RecordingStream::thread_local(rerun::StoreKind::Blueprint).map(PyRecordingStream)
+    RecordingStream::thread_local(re_sdk::StoreKind::Blueprint).map(PyRecordingStream)
 }
 
 /// Replaces the currently active recording in the thread-local scope with the specified one.
@@ -511,7 +481,7 @@ fn set_thread_local_blueprint_recording(
     // sorry.
     py.allow_threads(|| {
         let rec = RecordingStream::set_thread_local(
-            rerun::StoreKind::Blueprint,
+            re_sdk::StoreKind::Blueprint,
             recording.map(|rec| rec.0.clone()),
         )
         .map(PyRecordingStream);
@@ -529,7 +499,7 @@ fn is_enabled(recording: Option<&PyRecordingStream>) -> bool {
 
 /// Helper for forwarding the blueprint memory-sink representation to a given sink
 fn send_mem_sink_as_default_blueprint(
-    sink: &dyn rerun::sink::LogSink,
+    sink: &dyn re_sdk::sink::LogSink,
     default_blueprint: &PyMemorySinkStorage,
 ) {
     if let Some(id) = default_blueprint.inner.store_id() {
@@ -541,7 +511,28 @@ fn send_mem_sink_as_default_blueprint(
 }
 
 #[pyfunction]
-#[pyo3(signature = (addr = None, flush_timeout_sec=rerun::default_flush_timeout().unwrap().as_secs_f32(), default_blueprint = None, recording = None))]
+#[pyo3(signature = (port = 9876, memory_limit = "75%".to_owned(), executable_name = "rerun".to_owned(), executable_path = None, extra_args = vec![]))]
+fn spawn(
+    port: u16,
+    memory_limit: String,
+    executable_name: String,
+    executable_path: Option,
+    extra_args: Vec,
+) -> PyResult<()> {
+    let spawn_opts = re_sdk::SpawnOptions {
+        port,
+        wait_for_bind: true,
+        memory_limit,
+        executable_name,
+        executable_path,
+        extra_args,
+    };
+
+    re_sdk::spawn(&spawn_opts).map_err(|err| PyRuntimeError::new_err(err.to_string()))
+}
+
+#[pyfunction]
+#[pyo3(signature = (addr = None, flush_timeout_sec=re_sdk::default_flush_timeout().unwrap().as_secs_f32(), default_blueprint = None, recording = None))]
 fn connect(
     addr: Option,
     flush_timeout_sec: Option,
@@ -553,7 +544,7 @@ fn connect(
         return Ok(());
     };
 
-    if rerun::forced_sink_path().is_some() {
+    if re_sdk::forced_sink_path().is_some() {
         re_log::debug!("Ignored call to `connect()` since _RERUN_TEST_FORCE_SAVE is set");
         return Ok(());
     }
@@ -561,7 +552,7 @@ fn connect(
     let addr = if let Some(addr) = addr {
         addr.parse()?
     } else {
-        rerun::default_server_addr()
+        re_sdk::default_server_addr()
     };
 
     let flush_timeout = flush_timeout_sec.map(std::time::Duration::from_secs_f32);
@@ -571,7 +562,7 @@ fn connect(
     py.allow_threads(|| {
         // We create the sink manually so we can send the default blueprint
         // first before the rest of the current recording stream.
-        let sink = rerun::sink::TcpSink::new(addr, flush_timeout);
+        let sink = re_sdk::sink::TcpSink::new(addr, flush_timeout);
 
         if let Some(default_blueprint) = default_blueprint {
             send_mem_sink_as_default_blueprint(&sink, default_blueprint);
@@ -598,7 +589,7 @@ fn connect_blueprint(
     let addr = if let Some(addr) = addr {
         addr.parse()?
     } else {
-        rerun::default_server_addr()
+        re_sdk::default_server_addr()
     };
 
     if let Some(blueprint_id) = (*blueprint_stream).store_info().map(|info| info.store_id) {
@@ -639,7 +630,7 @@ fn save(
         return Ok(());
     };
 
-    if rerun::forced_sink_path().is_some() {
+    if re_sdk::forced_sink_path().is_some() {
         re_log::debug!("Ignored call to `save()` since _RERUN_TEST_FORCE_SAVE is set");
         return Ok(());
     }
@@ -649,7 +640,7 @@ fn save(
     py.allow_threads(|| {
         // We create the sink manually so we can send the default blueprint
         // first before the rest of the current recording stream.
-        let sink = rerun::sink::FileSink::new(path)
+        let sink = re_sdk::sink::FileSink::new(path)
             .map_err(|err| PyRuntimeError::new_err(err.to_string()))?;
 
         if let Some(default_blueprint) = default_blueprint {
@@ -707,7 +698,7 @@ fn stdout(
         return Ok(());
     };
 
-    if rerun::forced_sink_path().is_some() {
+    if re_sdk::forced_sink_path().is_some() {
         re_log::debug!("Ignored call to `stdout()` since _RERUN_TEST_FORCE_SAVE is set");
         return Ok(());
     }
@@ -715,12 +706,12 @@ fn stdout(
     // The call to stdout may internally flush.
     // Release the GIL in case any flushing behavior needs to cleanup a python object.
     py.allow_threads(|| {
-        let sink: Box = if std::io::stdout().is_terminal() {
+        let sink: Box = if std::io::stdout().is_terminal() {
             re_log::debug!("Ignored call to stdout() because stdout is a terminal");
-            Box::new(rerun::sink::BufferedSink::new())
+            Box::new(re_sdk::sink::BufferedSink::new())
         } else {
             Box::new(
-                rerun::sink::FileSink::stdout()
+                re_sdk::sink::FileSink::stdout()
                     .map_err(|err| PyRuntimeError::new_err(err.to_string()))?,
             )
         };
@@ -830,7 +821,7 @@ fn serve(
             return Ok(());
         };
 
-        if rerun::forced_sink_path().is_some() {
+        if re_sdk::forced_sink_path().is_some() {
             re_log::debug!("Ignored call to `serve()` since _RERUN_TEST_FORCE_SAVE is set");
             return Ok(());
         }
@@ -840,7 +831,7 @@ fn serve(
 
         let _guard = enter_tokio_runtime();
 
-        let sink = rerun::web_viewer::new_sink(
+        let sink = re_sdk::web_viewer::new_sink(
             open_browser,
             "0.0.0.0",
             web_port.map(WebViewerServerPort).unwrap_or_default(),
diff --git a/scripts/ci/fetch_artifact.py b/scripts/ci/fetch_artifact.py
new file mode 100644
index 000000000000..ab856f7e3ea5
--- /dev/null
+++ b/scripts/ci/fetch_artifact.py
@@ -0,0 +1,59 @@
+"""Script to manage artifacts stored in Google Cloud Storage."""
+
+from __future__ import annotations
+
+import argparse
+import os
+import stat
+from pathlib import Path
+
+from google.cloud import storage
+
+
+def main() -> None:
+    parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
+    parser.add_argument("--commit-sha", required=True, help="Which sha are we fetching artifacts for")
+    parser.add_argument("--artifact", choices=["rerun-cli"], help="Which artifact are we fetching")
+    parser.add_argument(
+        "--platform",
+        choices=[
+            "linux-arm64",
+            "linux-x64",
+            "macos-x64",
+            "macos-arm64",
+            "windows-x64",
+        ],
+    )
+    parser.add_argument("--dest", required=True, help="Where to save the artifact to")
+
+    args = parser.parse_args()
+
+    artifact_names: dict[tuple[str, str], str] = {}
+    artifact_names["rerun-cli", "linux-arm64"] = "rerun"
+    artifact_names["rerun-cli", "linux-x64"] = "rerun"
+    artifact_names["rerun-cli", "macos-x64"] = "rerun"
+    artifact_names["rerun-cli", "macos-arm64"] = "rerun"
+    artifact_names["rerun-cli", "windows-x64"] = "rerun.exe"
+
+    artifact_name = artifact_names[args.artifact, args.platform]
+
+    bucket_path = f"commit/{args.commit_sha}/{args.artifact}/{args.platform}/{artifact_name}"
+    print(f"Fetching artifact from {bucket_path} to {args.dest}")
+
+    gcs = storage.Client()
+    bucket = gcs.bucket("rerun-builds")
+    artifact = bucket.blob(bucket_path)
+
+    os.makedirs(args.dest, exist_ok=True)
+
+    filename = os.path.join(args.dest, artifact_name)
+
+    with open(filename, "wb") as f:
+        artifact.download_to_file(f)
+
+    file = Path(filename)
+    file.chmod(file.stat().st_mode | stat.S_IEXEC)
+
+
+if __name__ == "__main__":
+    main()

From 62ce6df98c985d21c31eda5688cff03b7e39cc85 Mon Sep 17 00:00:00 2001
From: Emil Ernerfeldt 
Date: Fri, 19 Apr 2024 08:46:38 +0200
Subject: [PATCH 327/508] Explain what Rerun is in top README.md (#6039)

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6039?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6039?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6039)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 README.md | 36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 02e832749897..258507526f84 100644
--- a/README.md
+++ b/README.md
@@ -75,13 +75,43 @@ We are in active development.
 There are many features we want to add, and the API is still evolving.
 _Expect breaking changes!_
 
-Some shortcomings:
-* [Multi-million point clouds are slow](https://github.com/rerun-io/rerun/issues/1136).
-* The data you want to visualize must fit in RAM.
+Current shortcomings that we are working on:
+* [Multi-million point clouds are slow](https://github.com/rerun-io/rerun/issues/1136)
+* [Logging many tiny things (e.g. scalars) has a lot of overhead](https://github.com/rerun-io/rerun/issues/5967)
+* The data you want to visualize must fit in RAM
   - See  for how to bound memory use.
   - We plan on having a disk-based data store some time in the future.
 
 
+## What is Rerun for?
+
+Rerun is built to help you understand complex processes that include rich multimodal data, like 2D, 3D, text, time series, tensors, etc.
+It is used in many industries, including robotics, simulation, computer vision,
+or anything that involves a lot of sensors or other signals that evolve over time.
+
+### Example use case
+Say you're building a vacuum cleaning robot and it keeps running into walls. Why is it doing that? You need some tool to debug it, but a normal debugger isn't gonna be helpful. Similarly, just logging text won't be very helpful either. The robot may log "Going through doorway" but that won't explain why it thinks the wall is a door.
+
+What you need is a visual and temporal debugger, that can log all the different representations of the world the robots holds in its little head, such as:
+
+* RGB camera feed
+* depth images
+* lidar scan
+* segmentation image (how the robot interprets what it sees)
+* its 3D map of the apartment
+* all the objects the robot has detected (or thinks it has detected), as 3D shapes in the 3D map
+* its confidence in its prediction
+* etc
+
+You also want to see how all these streams of data evolve over time so you can go back and pinpoint exactly what went wrong, when and why.
+
+Maybe it turns out that a glare from the sun hit one of the sensors in the wrong way, confusing the segmentation network leading to bad object detection. Or maybe it was a bug in the lidar scanning code. Or maybe the robot thought it was somewhere else in the apartment, because its odometry was broken. Or it could be one of a thousand other things. Rerun will help you find out!
+
+But seeing the world from the point of the view of the robot is not just for debugging - it will also give you ideas on how to improve the algorithms, new test cases to set up, or datasets to collect. It will also let you explain the brains of the robot to your colleagues, boss, and customers. And so on. Seeing is believing, and an image is worth a thousand words, and multimodal temporal logging is worth a thousand images :)
+
+Of course, Rerun is useful for much more than just robots. Any time you have any form of sensors, or 2D or 3D state evolving over time, Rerun would be a great tool.
+
+
 ## Business model
 Rerun uses an open-core model. Everything in this repository will stay open source and free (both as in beer and as in freedom).
 In the future, Rerun will offer a commercial product that builds on top of the core free project.

From 36f00a5b0bd3edf06bc0f4ec65ce58f86a32e458 Mon Sep 17 00:00:00 2001
From: Emil Ernerfeldt 
Date: Fri, 19 Apr 2024 08:56:09 +0200
Subject: [PATCH 328/508] CI on PR: only build CLI if Python or Rust has
 changed (#6040)

### What
No need to build it for doc changes

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x ] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6040?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6040?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6040)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .github/workflows/on_pull_request.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml
index b5ed0d6ca214..6bfcfbde3af0 100644
--- a/.github/workflows/on_pull_request.yml
+++ b/.github/workflows/on_pull_request.yml
@@ -163,6 +163,8 @@ jobs:
 
   min-cli-build:
     name: "Minimum CLI Build"
+    needs: [python-paths-filter, rust-paths-filter]
+    if: needs.python-paths-filter.outputs.python_changes == 'true' || needs.rust-paths-filter.outputs.rust_changes == 'true'
     uses: ./.github/workflows/reusable_build_and_upload_rerun_cli.yml
     with:
       CONCURRENCY: pr-${{ github.event.pull_request.number }}

From 74e5680748f34d5174790a475274932f45874a75 Mon Sep 17 00:00:00 2001
From: Antoine Beyeler <49431240+abey79@users.noreply.github.com>
Date: Sun, 21 Apr 2024 09:09:54 +0200
Subject: [PATCH 329/508] Update `rustls` to 0.21.11 (#6051)

### What

Appeases cargo deny.

Also fixes a bunch of dead links

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6051?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6051?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6051)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 CHANGELOG.md                    | 4 ++--
 Cargo.lock                      | 4 ++--
 examples/python/lidar/README.md | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa45b432acdc..2fc0c44c1a94 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1702,11 +1702,11 @@ This new release adds MVP support for embedding Rerun in Jupyter notebooks, and
     * Try it out live on [Google Colab](https://colab.research.google.com/drive/1R9I7s4o6wydQC_zkybqaSRFTtlEaked_?usp=sharing)
 * All colormapping tasks are now done directly on the GPU
     * This yields _very significant_ performance improvements for colormapping heavy workload (e.g. segmentation)
-    * Try it out in our new [`segment_anything` example](https://www.rerun.io/examples/real-data/segment_anything_model) that shows off the latest models from Meta AI
+    * Try it out in our new [`segment_anything` example](https://www.rerun.io/examples/video-image/segment_anything_model) that shows off the latest models from Meta AI
 * GPU picking & hovering now works with all of our primitives, including meshes & depth clouds
     * This fixes all the shortcomings of the previous CPU-based system
     * Rerun's automatic backprojection of depth textures ("depth clouds") is now feature complete
-    * Try it out in our updated [`nyud` example](https://www.rerun.io/examples/real-data/rgbd)
+    * Try it out in our updated [`nyud` example](https://www.rerun.io/examples/robotics/rgbd)
 * Our datastore has been completely revamped to more closely match our latest data model
     * This yields _very significant_ performance improvements for workloads with many events
     * Checkout [this post](https://github.com/rerun-io/rerun/issues/1619#issuecomment-1511046649) for a detailed walkthrough of the changes
diff --git a/Cargo.lock b/Cargo.lock
index ae2f66f56af3..c35292eb7738 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5780,9 +5780,9 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.21.10"
+version = "0.21.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
+checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4"
 dependencies = [
  "log",
  "ring",
diff --git a/examples/python/lidar/README.md b/examples/python/lidar/README.md
index 283fcc34a83f..52b725220f8b 100644
--- a/examples/python/lidar/README.md
+++ b/examples/python/lidar/README.md
@@ -23,7 +23,7 @@ This example demonstrates the ability to read and visualize LiDAR data from the
 The scenes in this dataset encompass data collected from a comprehensive suite of sensors on autonomous vehicles, including 6 cameras, 1 LIDAR, 5 RADAR, GPS and IMU sensors.
 
 
-It's important to note that in this example, only the LiDAR data is visualized. For a more extensive example including other sensors and annotations check out the [nuScenes example](https://www.rerun.io/examples/real-data/nuscenes).
+It's important to note that in this example, only the LiDAR data is visualized. For a more extensive example including other sensors and annotations check out the [nuScenes example](https://www.rerun.io/examples/robotics/nuscenes).
 
 ## Logging and visualizing with Rerun
 

From a68008678b64eaa23f2d1b13933e7a63c95950f3 Mon Sep 17 00:00:00 2001
From: Emil Ernerfeldt 
Date: Mon, 22 Apr 2024 09:22:47 +0200
Subject: [PATCH 330/508] Split out arrow-formatting from `re_format` to
 `re_format_arrow` (#6058)

Keep `re_format` light-weight, and usable from any crate without cyclic
dependencies.

Maybe I'll move `re_format` into the egui repository to make it useable
from `egui_plot`, but if so that will come later (and this is a good
first step).

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6058?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6058?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6058)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.

---------

Co-authored-by: Clement Rey 
---
 ARCHITECTURE.md                               | 21 +++++++++--------
 Cargo.lock                                    | 12 +++++++++-
 Cargo.toml                                    |  1 +
 crates/re_data_store/Cargo.toml               |  3 ++-
 crates/re_data_store/src/store_format.rs      |  4 ++--
 crates/re_format/Cargo.toml                   | 14 +----------
 crates/re_format/src/lib.rs                   |  7 ++----
 crates/re_format_arrow/Cargo.toml             | 23 +++++++++++++++++++
 crates/re_format_arrow/README.md              | 11 +++++++++
 .../arrow.rs => re_format_arrow/src/lib.rs}   |  0
 crates/re_log_types/Cargo.toml                |  3 ++-
 crates/re_log_types/src/data_cell.rs          |  2 +-
 crates/re_log_types/src/data_row.rs           |  2 +-
 crates/re_log_types/src/data_table.rs         |  2 +-
 crates/re_query/Cargo.toml                    |  3 ++-
 crates/re_query/src/archetype_view.rs         |  6 ++---
 crates/re_query2/Cargo.toml                   |  3 ++-
 17 files changed, 76 insertions(+), 41 deletions(-)
 create mode 100644 crates/re_format_arrow/Cargo.toml
 create mode 100644 crates/re_format_arrow/README.md
 rename crates/{re_format/src/arrow.rs => re_format_arrow/src/lib.rs} (100%)

diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index af6ab630813c..0bc22487db3f 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -88,11 +88,11 @@ Of course, this will only take us so far. In the future we plan on caching queri
 Here is an overview of the crates included in the project:
 
 
-  
-  
-  
-  
-  
+  
+  
+  
+  
+  
 
 
 
+    
+    
+    
+
     
     
      0) {
             status_element.innerHTML =
               Math.round(Math.min((loaded / total_bytes) * 100, 100)) + "%";
           } else {
@@ -267,8 +271,12 @@
           // Use the uncompressed size
           var content_length;
           var content_multiplier = 1;
-          // If the content is gzip encoded, try to get the uncompressed size.
-          if (response.headers.get("content-encoding") == "gzip") {
+          // If our custom size header is set, use that (see `re_web_viewer_server` crate)
+          var custom_size_header = response.headers.get("rerun-final-length");
+          if (custom_size_header != null) {
+            content_length = custom_size_header;
+          } else if (response.headers.get("content-encoding") == "gzip") {
+            // If the content is gzip encoded, try to get the uncompressed size.
             content_length = response.headers.get(
               "x-goog-meta-uncompressed-size",
             );

From 2f73825d28be1fd6c9b2c33f7c765aab45c6d532 Mon Sep 17 00:00:00 2001
From: Andreas Reich 
Date: Mon, 22 Apr 2024 16:01:23 +0200
Subject: [PATCH 336/508] Remove need for tokio runtime for supporting `serve`
 (#6043)

### What

Rust users now no longer need to ensure to have tokio runtime set up
when using `serve`.

* Fixes #5907
* Direct follow-up / merges into #6042

Last PR in a series of PRs for removal of the tokio runtime:
* removes need for tokio in re_sdk_comms
*similar to the refactor in re_ws_comms only in spirit - a lot simpler:
no fancy broadcast, no other libraries involved. Just a bunch of threads
hammering on blocking sockets).
* remove remaining usages of async in this context
* removes tokio need from all documentation

-----

Dependency count `0.15.1` -> last friday `d90ed2f7e`-> `this pr`

* `cargo build -p rerun --no-default-features` 225 -> 274 -> 275
dependencies
* `cargo build -p rerun -F default` 361 -> 364 -> 364 dependencies
* `cargo build -p rerun -F web_viewer` 409 -> 412 -> 374 dependencies

Notes:
* 0.15.1 already regressed quite a bit compared back to January:
https://github.com/rerun-io/rerun/pull/4824
* we currently have a few temporary crates while migrating to re_query2
which weren't present in 0.15

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6043?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6043?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6043)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 Cargo.lock                                    |  36 -------
 Cargo.toml                                    |   1 -
 crates/re_sdk/src/recording_stream.rs         |  13 ---
 crates/re_sdk/src/web_viewer.rs               |   2 -
 crates/re_sdk_comms/Cargo.toml                |   8 +-
 crates/re_sdk_comms/src/server.rs             | 102 ++++++++++--------
 crates/re_web_viewer_server/src/lib.rs        |   4 -
 crates/rerun-cli/Cargo.toml                   |   1 -
 crates/rerun-cli/src/bin/rerun.rs             |   5 +-
 crates/rerun/Cargo.toml                       |   9 +-
 crates/rerun/src/clap.rs                      |  34 ++----
 crates/rerun/src/lib.rs                       |   4 -
 crates/rerun/src/run.rs                       |  13 ++-
 examples/rust/custom_data_loader/src/main.rs  |   6 +-
 examples/rust/custom_space_view/Cargo.toml    |   3 -
 examples/rust/custom_space_view/src/main.rs   |   6 +-
 .../rust/custom_store_subscriber/src/main.rs  |   6 +-
 examples/rust/extend_viewer_ui/Cargo.toml     |   3 -
 examples/rust/extend_viewer_ui/src/main.rs    |   6 +-
 examples/rust/minimal_serve/Cargo.toml        |   1 -
 examples/rust/minimal_serve/src/main.rs       |   4 -
 rerun_py/Cargo.toml                           |   1 -
 rerun_py/src/python_bridge.rs                 |  11 --
 23 files changed, 83 insertions(+), 196 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 851382b98ba1..134c857a11a1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1420,7 +1420,6 @@ dependencies = [
  "re_crash_handler",
  "re_sdk_comms",
  "re_viewer",
- "tokio",
 ]
 
 [[package]]
@@ -1973,7 +1972,6 @@ dependencies = [
  "re_crash_handler",
  "re_sdk_comms",
  "re_viewer",
- "tokio",
 ]
 
 [[package]]
@@ -3096,7 +3094,6 @@ name = "minimal_serve"
 version = "0.16.0-alpha.1+dev"
 dependencies = [
  "rerun",
- "tokio",
 ]
 
 [[package]]
@@ -4686,7 +4683,6 @@ dependencies = [
  "re_log_types",
  "re_smart_channel",
  "thiserror",
- "tokio",
 ]
 
 [[package]]
@@ -5318,7 +5314,6 @@ dependencies = [
  "re_viewer",
  "re_web_viewer_server",
  "re_ws_comms",
- "tokio",
 ]
 
 [[package]]
@@ -5333,7 +5328,6 @@ dependencies = [
  "re_log",
  "re_memory",
  "rerun",
- "tokio",
 ]
 
 [[package]]
@@ -5380,7 +5374,6 @@ dependencies = [
  "re_sdk",
  "re_web_viewer_server",
  "re_ws_comms",
- "tokio",
  "uuid",
 ]
 
@@ -6388,35 +6381,6 @@ dependencies = [
  "ahash",
 ]
 
-[[package]]
-name = "tokio"
-version = "1.28.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
-dependencies = [
- "autocfg",
- "bytes",
- "libc",
- "mio",
- "num_cpus",
- "pin-project-lite",
- "signal-hook-registry",
- "socket2",
- "tokio-macros",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "tokio-macros"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.48",
-]
-
 [[package]]
 name = "toml"
 version = "0.8.10"
diff --git a/Cargo.toml b/Cargo.toml
index 3bcc4b8babc6..e51070f75557 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -219,7 +219,6 @@ tiny_http = { version = "0.12", default-features = false }
 tinystl = { version = "0.0.3", default-features = false }
 tinyvec = { version = "1.6", features = ["alloc", "rustc_1_55"] }
 tobj = "4.0"
-tokio = { version = "1.24", default-features = false }
 toml = { version = "0.8.10", default-features = false }
 tracing = { version = "0.1", default-features = false }
 tungstenite = { version = "0.20", default-features = false }
diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs
index f37053686baf..c0affed8233f 100644
--- a/crates/re_sdk/src/recording_stream.rs
+++ b/crates/re_sdk/src/recording_stream.rs
@@ -461,9 +461,6 @@ impl RecordingStreamBuilder {
     /// Creates a new [`RecordingStream`] that is pre-configured to stream the data through to a
     /// web-based Rerun viewer via WebSockets.
     ///
-    /// This method needs to be called in a context where a Tokio runtime is already running (see
-    /// example below).
-    ///
     /// If the `open_browser` argument is `true`, your default browser will be opened with a
     /// connected web-viewer.
     ///
@@ -481,16 +478,6 @@ impl RecordingStreamBuilder {
     /// ## Example
     ///
     /// ```ignore
-    /// // Ensure we have a running tokio runtime.
-    /// let mut tokio_runtime = None;
-    /// let tokio_runtime_handle = if let Ok(handle) = tokio::runtime::Handle::try_current() {
-    ///     handle
-    /// } else {
-    ///     let rt = tokio::runtime::Runtime::new().expect("Failed to create tokio runtime");
-    ///     tokio_runtime.get_or_insert(rt).handle().clone()
-    /// };
-    /// let _tokio_runtime_guard = tokio_runtime_handle.enter();
-    ///
     /// let rec = re_sdk::RecordingStreamBuilder::new("rerun_example_app")
     ///     .serve("0.0.0.0",
     ///            Default::default(),
diff --git a/crates/re_sdk/src/web_viewer.rs b/crates/re_sdk/src/web_viewer.rs
index cb9e2123a407..d6d32053df62 100644
--- a/crates/re_sdk/src/web_viewer.rs
+++ b/crates/re_sdk/src/web_viewer.rs
@@ -122,8 +122,6 @@ impl crate::sink::LogSink for WebViewerSink {
 /// NOTE: you can not connect one `Session` to another.
 ///
 /// This function returns immediately.
-///
-/// The caller needs to ensure that there is a `tokio` runtime running.
 #[must_use = "the sink must be kept around to keep the servers running"]
 pub fn new_sink(
     open_browser: bool,
diff --git a/crates/re_sdk_comms/Cargo.toml b/crates/re_sdk_comms/Cargo.toml
index 341a67d42564..9ce91ab96dca 100644
--- a/crates/re_sdk_comms/Cargo.toml
+++ b/crates/re_sdk_comms/Cargo.toml
@@ -24,7 +24,7 @@ all-features = true
 client = ["re_log_encoding/encoder"]
 
 ## Enable the server.
-server = ["rand", "tokio", "re_log_encoding/decoder"]
+server = ["rand", "re_log_encoding/decoder"]
 
 
 [dependencies]
@@ -46,9 +46,3 @@ rand = { workspace = true, optional = true, features = [
   "std_rng",
   "small_rng",
 ] }
-
-tokio = { workspace = true, optional = true, features = [
-  "io-util",
-  "net",
-  "rt",
-] }
diff --git a/crates/re_sdk_comms/src/server.rs b/crates/re_sdk_comms/src/server.rs
index 3ad74cbbe93b..346b20939251 100644
--- a/crates/re_sdk_comms/src/server.rs
+++ b/crates/re_sdk_comms/src/server.rs
@@ -1,7 +1,10 @@
-use std::{io::ErrorKind, time::Instant};
+use std::{
+    io::{ErrorKind, Read as _},
+    net::{TcpListener, TcpStream},
+    time::Instant,
+};
 
 use rand::{Rng as _, SeedableRng};
-use tokio::net::{TcpListener, TcpStream};
 
 use re_log_types::{LogMsg, TimePoint, TimeType, TimelineName};
 use re_smart_channel::{Receiver, Sender};
@@ -13,6 +16,9 @@ pub enum ServerError {
         bind_addr: String,
         err: std::io::Error,
     },
+
+    #[error(transparent)]
+    FailedToSpawnThread(#[from] std::io::Error),
 }
 
 #[derive(thiserror::Error, Debug)]
@@ -68,12 +74,15 @@ impl Default for ServerOptions {
 ///
 /// ``` no_run
 /// # use re_sdk_comms::{serve, ServerOptions};
-/// #[tokio::main]
-/// async fn main() {
-///     let log_msg_rx = serve("0.0.0.0", re_sdk_comms::DEFAULT_SERVER_PORT, ServerOptions::default()).await.unwrap();
+/// fn main() {
+///     let log_msg_rx = serve("0.0.0.0", re_sdk_comms::DEFAULT_SERVER_PORT, ServerOptions::default()).unwrap();
 /// }
 /// ```
-pub async fn serve(
+///
+/// Internally spawns a thread that listens for incoming TCP connections on the given `bind_ip` and `port`
+/// and one thread per connected client.
+// TODO(andreas): Reconsider if we should use `smol` tasks instead of threads both here and in re_ws_comms.
+pub fn serve(
     bind_ip: &str,
     port: u16,
     options: ServerOptions,
@@ -85,13 +94,16 @@ pub async fn serve(
     );
 
     let bind_addr = format!("{bind_ip}:{port}");
-    let listener =
-        TcpListener::bind(&bind_addr)
-            .await
-            .map_err(|err| ServerError::TcpBindError {
-                bind_addr: bind_addr.clone(),
-                err,
-            })?;
+    let listener = TcpListener::bind(&bind_addr).map_err(|err| ServerError::TcpBindError {
+        bind_addr: bind_addr.clone(),
+        err,
+    })?;
+
+    std::thread::Builder::new()
+        .name("rerun_sdk_comms: listener".to_owned())
+        .spawn(move || {
+            listen_for_new_clients(&listener, options, &tx);
+        })?;
 
     if options.quiet {
         re_log::debug!(
@@ -103,19 +115,24 @@ pub async fn serve(
         );
     }
 
-    tokio::spawn(listen_for_new_clients(listener, options, tx));
-
     Ok(rx)
 }
 
-async fn listen_for_new_clients(listener: TcpListener, options: ServerOptions, tx: Sender) {
-    #[allow(clippy::infinite_loop)] // TODO(emilk): some way of aborting this loop
+fn listen_for_new_clients(listener: &TcpListener, options: ServerOptions, tx: &Sender) {
+    // TODO(emilk): some way of aborting this loop
+    #[allow(clippy::infinite_loop)]
     loop {
-        match listener.accept().await {
+        match listener.accept() {
             Ok((stream, _)) => {
                 let addr = stream.peer_addr().ok();
                 let tx = tx.clone_as(re_smart_channel::SmartMessageSource::TcpClient { addr });
-                spawn_client(stream, tx, options, addr);
+
+                std::thread::Builder::new()
+                    .name("rerun_sdk_comms: client".to_owned())
+                    .spawn(move || {
+                        spawn_client(stream, &tx, options, addr);
+                    })
+                    .ok();
             }
             Err(err) => {
                 re_log::warn!("Failed to accept incoming SDK client: {err}");
@@ -126,46 +143,41 @@ async fn listen_for_new_clients(listener: TcpListener, options: ServerOptions, t
 
 fn spawn_client(
     stream: TcpStream,
-    tx: Sender,
+    tx: &Sender,
     options: ServerOptions,
     peer_addr: Option,
 ) {
-    tokio::spawn(async move {
-        let addr_string =
-            peer_addr.map_or_else(|| "(unknown ip)".to_owned(), |addr| addr.to_string());
+    let addr_string = peer_addr.map_or_else(|| "(unknown ip)".to_owned(), |addr| addr.to_string());
 
-        if options.quiet {
-            re_log::debug!("New SDK client connected: {addr_string}");
-        } else {
-            re_log::info!("New SDK client connected: {addr_string}");
-        }
+    if options.quiet {
+        re_log::debug!("New SDK client connected: {addr_string}");
+    } else {
+        re_log::info!("New SDK client connected: {addr_string}");
+    }
 
-        if let Err(err) = run_client(stream, &tx, options).await {
-            if let ConnectionError::SendError(err) = &err {
-                if err.kind() == ErrorKind::UnexpectedEof {
-                    // Client gracefully severed the connection.
-                    tx.quit(None).ok(); // best-effort at this point
-                    return;
-                }
+    if let Err(err) = run_client(stream, tx, options) {
+        if let ConnectionError::SendError(err) = &err {
+            if err.kind() == ErrorKind::UnexpectedEof {
+                // Client gracefully severed the connection.
+                tx.quit(None).ok(); // best-effort at this point
+                return;
             }
-            re_log::warn_once!("Closing connection to client at {addr_string}: {err}");
-            let err: Box = err.to_string().into();
-            tx.quit(Some(err)).ok(); // best-effort at this point
         }
-    });
+        re_log::warn_once!("Closing connection to client at {addr_string}: {err}");
+        let err: Box = err.to_string().into();
+        tx.quit(Some(err)).ok(); // best-effort at this point
+    }
 }
 
-async fn run_client(
+fn run_client(
     mut stream: TcpStream,
     tx: &Sender,
     options: ServerOptions,
 ) -> Result<(), ConnectionError> {
     #![allow(clippy::read_zero_byte_vec)] // false positive: https://github.com/rust-lang/rust-clippy/issues/9274
 
-    use tokio::io::AsyncReadExt as _;
-
     let mut client_version = [0_u8; 2];
-    stream.read_exact(&mut client_version).await?;
+    stream.read_exact(&mut client_version)?;
     let client_version = u16::from_le_bytes(client_version);
 
     match client_version.cmp(&crate::PROTOCOL_VERSION) {
@@ -190,11 +202,11 @@ async fn run_client(
 
     loop {
         let mut packet_size = [0_u8; 4];
-        stream.read_exact(&mut packet_size).await?;
+        stream.read_exact(&mut packet_size)?;
         let packet_size = u32::from_le_bytes(packet_size);
 
         packet.resize(packet_size as usize, 0_u8);
-        stream.read_exact(&mut packet).await?;
+        stream.read_exact(&mut packet)?;
 
         re_log::trace!("Received packet of size {packet_size}.");
 
diff --git a/crates/re_web_viewer_server/src/lib.rs b/crates/re_web_viewer_server/src/lib.rs
index dc88f9e79385..853be4d107a1 100644
--- a/crates/re_web_viewer_server/src/lib.rs
+++ b/crates/re_web_viewer_server/src/lib.rs
@@ -37,10 +37,6 @@ pub enum WebViewerServerError {
 
     #[error("Failed to create server at address {0}: {1}")]
     CreateServerFailed(String, Box),
-
-    #[cfg(feature = "sync")]
-    #[error("Failed to spawn web viewer thread: {0}")]
-    ThreadSpawnFailed(#[from] std::io::Error),
 }
 
 // ----------------------------------------------------------------------------
diff --git a/crates/rerun-cli/Cargo.toml b/crates/rerun-cli/Cargo.toml
index a6e1effcf0e8..501ad7ce2a6f 100644
--- a/crates/rerun-cli/Cargo.toml
+++ b/crates/rerun-cli/Cargo.toml
@@ -67,7 +67,6 @@ rerun = { workspace = true, features = [
 
 document-features.workspace = true
 mimalloc.workspace = true
-tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
 
 
 [build-dependencies]
diff --git a/crates/rerun-cli/src/bin/rerun.rs b/crates/rerun-cli/src/bin/rerun.rs
index ad6b3c223703..bc8a6ffd0a92 100644
--- a/crates/rerun-cli/src/bin/rerun.rs
+++ b/crates/rerun-cli/src/bin/rerun.rs
@@ -16,13 +16,12 @@ use re_memory::AccountingAllocator;
 static GLOBAL: AccountingAllocator =
     AccountingAllocator::new(mimalloc::MiMalloc);
 
-#[tokio::main]
-async fn main() -> std::process::ExitCode {
+fn main() -> std::process::ExitCode {
     re_log::setup_logging();
 
     let build_info = re_build_info::build_info!();
 
-    let result = rerun::run(build_info, rerun::CallSource::Cli, std::env::args()).await;
+    let result = rerun::run(build_info, rerun::CallSource::Cli, std::env::args());
 
     match result {
         Ok(exit_code) => std::process::ExitCode::from(exit_code),
diff --git a/crates/rerun/Cargo.toml b/crates/rerun/Cargo.toml
index 09751a1bdac2..03ee3a3c5646 100644
--- a/crates/rerun/Cargo.toml
+++ b/crates/rerun/Cargo.toml
@@ -43,7 +43,7 @@ analytics = [
 ]
 
 ## Integration with `clap`.
-clap = ["dep:clap", "dep:tokio"]
+clap = ["dep:clap"]
 
 ## Support for using Rerun's data-loaders directly from the SDK.
 ##
@@ -84,7 +84,6 @@ run = [
   "dep:re_log_encoding",
   "dep:re_sdk_comms",
   "dep:re_ws_comms",
-  "dep:tokio",
 ]
 
 ## Support for running a TCP server that listens to incoming log messages from a Rerun SDK.
@@ -143,12 +142,6 @@ rayon.workspace = true
 
 # Native, optional:
 clap = { workspace = true, optional = true, features = ["derive"] }
-tokio = { workspace = true, optional = true, features = [
-  "macros",
-  "rt-multi-thread",
-  "time",
-] }
-
 
 [build-dependencies]
 re_build_tools.workspace = true
diff --git a/crates/rerun/src/clap.rs b/crates/rerun/src/clap.rs
index db7f1cafc1e1..61c2db5f379b 100644
--- a/crates/rerun/src/clap.rs
+++ b/crates/rerun/src/clap.rs
@@ -87,16 +87,15 @@ pub struct RerunArgs {
 #[doc(hidden)]
 #[derive(Default)]
 pub struct ServeGuard {
-    tokio_rt: Option,
+    block_on_drop: bool,
 }
 
 impl Drop for ServeGuard {
     fn drop(&mut self) {
-        if let Some(tokio_rt) = self.tokio_rt.take() {
+        if self.block_on_drop {
             eprintln!("Sleeping indefinitely while serving web viewer... Press ^C when done.");
-            tokio_rt.block_on(async {
-                tokio::time::sleep(std::time::Duration::from_secs(u64::MAX)).await;
-            });
+            // TODO(andreas): It would be a lot better if we had a handle to the web server and could call `block_until_shutdown` on it.
+            std::thread::sleep(std::time::Duration::from_secs(u64::MAX));
         }
     }
 }
@@ -129,27 +128,9 @@ impl RerunArgs {
 
             #[cfg(feature = "web_viewer")]
             RerunBehavior::Serve => {
-                let mut tokio_rt = None;
-
-                // Get the Tokio runtime for the current thread, or create one if there isn't any.
-                // If we do create one, we'll have to make sure it both outlives and gets
-                // polled to completion as we return from this method!
-                let tokio_rt_handle = if let Ok(handle) = tokio::runtime::Handle::try_current() {
-                    handle
-                } else {
-                    tokio_rt
-                        .get_or_insert(tokio::runtime::Runtime::new()?)
-                        .handle()
-                        .clone()
-                };
-
                 let server_memory_limit = re_memory::MemoryLimit::parse(&self.server_memory_limit)
                     .map_err(|err| anyhow::format_err!("Bad --server-memory-limit: {err}"))?;
 
-                // Creating the actual web sink and associated servers will require the current
-                // thread to be in a Tokio context.
-                let _tokio_rt_guard = tokio_rt_handle.enter();
-
                 let open_browser = true;
                 let rec = RecordingStreamBuilder::new(application_id).serve(
                     &self.bind,
@@ -159,9 +140,10 @@ impl RerunArgs {
                     open_browser,
                 )?;
 
-                // If we had to create a Tokio runtime from scratch, make sure it outlives this
-                // method and gets polled to completion.
-                let sleep_guard = ServeGuard { tokio_rt };
+                // Ensure the server stays alive until the end of the program.
+                let sleep_guard = ServeGuard {
+                    block_on_drop: true,
+                };
 
                 Ok((rec, sleep_guard))
             }
diff --git a/crates/rerun/src/lib.rs b/crates/rerun/src/lib.rs
index 698cb6cb5e4e..9553cb851e85 100644
--- a/crates/rerun/src/lib.rs
+++ b/crates/rerun/src/lib.rs
@@ -166,10 +166,6 @@ pub mod external {
     #[cfg(not(target_arch = "wasm32"))]
     pub use clap;
 
-    #[cfg(feature = "run")]
-    #[cfg(not(target_arch = "wasm32"))]
-    pub use tokio;
-
     #[cfg(feature = "native_viewer")]
     pub use re_viewer;
 
diff --git a/crates/rerun/src/run.rs b/crates/rerun/src/run.rs
index bad95de20add..b2055c7bafca 100644
--- a/crates/rerun/src/run.rs
+++ b/crates/rerun/src/run.rs
@@ -331,7 +331,7 @@ impl CallSource {
 //
 // It would be nice to use [`std::process::ExitCode`] here but
 // then there's no good way to get back at the exit code from python
-pub async fn run(
+pub fn run(
     build_info: re_build_info::BuildInfo,
     call_source: CallSource,
     args: I,
@@ -382,7 +382,7 @@ where
             Command::Reset => re_viewer::reset_viewer_persistence(),
         }
     } else {
-        run_impl(build_info, call_source, args).await
+        run_impl(build_info, call_source, args)
     };
 
     match res {
@@ -594,7 +594,7 @@ fn profiler(args: &Args) -> re_tracing::Profiler {
     profiler
 }
 
-async fn run_impl(
+fn run_impl(
     _build_info: re_build_info::BuildInfo,
     call_source: CallSource,
     args: Args,
@@ -636,7 +636,7 @@ async fn run_impl(
                 max_latency_sec: parse_max_latency(args.drop_at_latency.as_ref()),
                 quiet: false,
             };
-            let rx = re_sdk_comms::serve(&args.bind, args.port, server_options).await?;
+            let rx = re_sdk_comms::serve(&args.bind, args.port, server_options)?;
             vec![rx]
         }
 
@@ -714,13 +714,12 @@ async fn run_impl(
                 .map_err(|err| anyhow::format_err!("Bad --server-memory-limit: {err}"))?;
 
             // This is the server which the web viewer will talk to:
-            let ws_server = re_ws_comms::RerunServer::new(
+            let _ws_server = re_ws_comms::RerunServer::new(
                 ReceiveSet::new(rx),
                 &args.bind,
                 args.ws_server_port,
                 server_memory_limit,
             )?;
-            let _ws_server_url = ws_server.server_url();
 
             #[cfg(feature = "web_viewer")]
             {
@@ -735,7 +734,7 @@ async fn run_impl(
                     args.web_viewer_port,
                     args.renderer,
                     open_browser,
-                    &_ws_server_url,
+                    &_ws_server.server_url(),
                 )?
                 .block(); // dropping should stop the server
             }
diff --git a/examples/rust/custom_data_loader/src/main.rs b/examples/rust/custom_data_loader/src/main.rs
index 761c9185a028..022745e1b971 100644
--- a/examples/rust/custom_data_loader/src/main.rs
+++ b/examples/rust/custom_data_loader/src/main.rs
@@ -7,20 +7,18 @@
 //! ```
 
 use rerun::{
-    external::{anyhow, re_build_info, re_data_source, re_log, tokio},
+    external::{anyhow, re_build_info, re_data_source, re_log},
     log::{DataRow, RowId},
     EntityPath, TimePoint,
 };
 
-#[tokio::main]
-async fn main() -> anyhow::Result {
+fn main() -> anyhow::Result {
     re_log::setup_logging();
 
     re_data_source::register_custom_data_loader(HashLoader);
 
     let build_info = re_build_info::build_info!();
     rerun::run(build_info, rerun::CallSource::Cli, std::env::args())
-        .await
         .map(std::process::ExitCode::from)
 }
 
diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml
index 952646cfa948..e80164e63f77 100644
--- a/examples/rust/custom_space_view/Cargo.toml
+++ b/examples/rust/custom_space_view/Cargo.toml
@@ -21,6 +21,3 @@ re_sdk_comms = { path = "../../../crates/re_sdk_comms", features = ["server"] }
 
 # mimalloc is a much faster allocator:
 mimalloc = "0.1"
-
-# We need tokio for re_sdk_comms:
-tokio = { version = "1.24", features = ["macros", "rt-multi-thread"] }
diff --git a/examples/rust/custom_space_view/src/main.rs b/examples/rust/custom_space_view/src/main.rs
index 32d151b6c106..0fcc9159a907 100644
--- a/examples/rust/custom_space_view/src/main.rs
+++ b/examples/rust/custom_space_view/src/main.rs
@@ -12,8 +12,7 @@ mod color_coordinates_visualizer_system;
 static GLOBAL: re_memory::AccountingAllocator =
     re_memory::AccountingAllocator::new(mimalloc::MiMalloc);
 
-#[tokio::main]
-async fn main() -> Result<(), Box> {
+fn main() -> Result<(), Box> {
     // Direct calls using the `log` crate to stderr. Control with `RUST_LOG=debug` etc.
     re_log::setup_logging();
 
@@ -27,8 +26,7 @@ async fn main() -> Result<(), Box> {
         "0.0.0.0",
         re_sdk_comms::DEFAULT_SERVER_PORT,
         Default::default(),
-    )
-    .await?;
+    )?;
 
     let startup_options = re_viewer::StartupOptions::default();
 
diff --git a/examples/rust/custom_store_subscriber/src/main.rs b/examples/rust/custom_store_subscriber/src/main.rs
index ed9b8c03e706..fd24e90b5425 100644
--- a/examples/rust/custom_store_subscriber/src/main.rs
+++ b/examples/rust/custom_store_subscriber/src/main.rs
@@ -13,13 +13,12 @@
 use std::collections::BTreeMap;
 
 use rerun::{
-    external::{anyhow, re_build_info, re_data_store, re_log, re_log_types::TimeRange, tokio},
+    external::{anyhow, re_build_info, re_data_store, re_log, re_log_types::TimeRange},
     time::TimeInt,
     ComponentName, EntityPath, StoreEvent, StoreId, StoreSubscriber, Timeline,
 };
 
-#[tokio::main]
-async fn main() -> anyhow::Result {
+fn main() -> anyhow::Result {
     re_log::setup_logging();
 
     let _handle = re_data_store::DataStore::register_subscriber(Box::::default());
@@ -27,7 +26,6 @@ async fn main() -> anyhow::Result {
 
     let build_info = re_build_info::build_info!();
     rerun::run(build_info, rerun::CallSource::Cli, std::env::args())
-        .await
         .map(std::process::ExitCode::from)
 }
 
diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml
index 78f480231f97..8f470162da51 100644
--- a/examples/rust/extend_viewer_ui/Cargo.toml
+++ b/examples/rust/extend_viewer_ui/Cargo.toml
@@ -21,6 +21,3 @@ re_sdk_comms = { path = "../../../crates/re_sdk_comms", features = ["server"] }
 
 # mimalloc is a much faster allocator:
 mimalloc = "0.1"
-
-# We need tokio for re_sdk_comms:
-tokio = { version = "1.24", features = ["macros", "rt-multi-thread"] }
diff --git a/examples/rust/extend_viewer_ui/src/main.rs b/examples/rust/extend_viewer_ui/src/main.rs
index fbc37dee872b..f7cb1533392e 100644
--- a/examples/rust/extend_viewer_ui/src/main.rs
+++ b/examples/rust/extend_viewer_ui/src/main.rs
@@ -11,8 +11,7 @@ use re_viewer::external::{
 static GLOBAL: re_memory::AccountingAllocator =
     re_memory::AccountingAllocator::new(mimalloc::MiMalloc);
 
-#[tokio::main]
-async fn main() -> Result<(), Box> {
+fn main() -> Result<(), Box> {
     // Direct calls using the `log` crate to stderr. Control with `RUST_LOG=debug` etc.
     re_log::setup_logging();
 
@@ -26,8 +25,7 @@ async fn main() -> Result<(), Box> {
         "0.0.0.0",
         re_sdk_comms::DEFAULT_SERVER_PORT,
         Default::default(),
-    )
-    .await?;
+    )?;
 
     let native_options = eframe::NativeOptions {
         viewport: egui::ViewportBuilder::default().with_app_id("rerun_extend_viewer_ui_example"),
diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml
index 44db28b8491c..2e46275d5b95 100644
--- a/examples/rust/minimal_serve/Cargo.toml
+++ b/examples/rust/minimal_serve/Cargo.toml
@@ -8,4 +8,3 @@ publish = false
 
 [dependencies]
 rerun = { path = "../../../crates/rerun", features = ["web_viewer"] }
-tokio = { version = "1.24", features = ["rt-multi-thread"] }
diff --git a/examples/rust/minimal_serve/src/main.rs b/examples/rust/minimal_serve/src/main.rs
index 81fa05aa0768..6cddaf9b3587 100644
--- a/examples/rust/minimal_serve/src/main.rs
+++ b/examples/rust/minimal_serve/src/main.rs
@@ -3,10 +3,6 @@
 use rerun::{demo_util::grid, external::glam};
 
 fn main() -> Result<(), Box> {
-    // `serve()` requires to have a running Tokio runtime in the current context.
-    let rt = tokio::runtime::Runtime::new().expect("Failed to create tokio runtime");
-    let _guard = rt.enter();
-
     let open_browser = true;
     let rec = rerun::RecordingStreamBuilder::new("rerun_example_minimal_serve").serve(
         "0.0.0.0",
diff --git a/rerun_py/Cargo.toml b/rerun_py/Cargo.toml
index fe1f03b3bd8c..57b287160fa9 100644
--- a/rerun_py/Cargo.toml
+++ b/rerun_py/Cargo.toml
@@ -58,7 +58,6 @@ once_cell.workspace = true
 parking_lot.workspace = true
 pyo3 = { workspace = true, features = ["abi3-py38"] }
 rand = { workspace = true, features = ["std_rng"] }
-tokio = { workspace = true, features = ["rt-multi-thread", "signal"] }
 uuid.workspace = true
 
 
diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs
index ea753026bd00..2d67d968835e 100644
--- a/rerun_py/src/python_bridge.rs
+++ b/rerun_py/src/python_bridge.rs
@@ -794,14 +794,6 @@ impl PyMemorySinkStorage {
     }
 }
 
-#[cfg(feature = "web_viewer")]
-#[must_use = "the tokio_runtime guard must be kept alive while using tokio"]
-fn enter_tokio_runtime() -> tokio::runtime::EnterGuard<'static> {
-    static TOKIO_RUNTIME: Lazy =
-        Lazy::new(|| tokio::runtime::Runtime::new().expect("Failed to create tokio runtime"));
-    TOKIO_RUNTIME.enter()
-}
-
 /// Serve a web-viewer.
 #[allow(clippy::unnecessary_wraps)] // False positive
 #[pyfunction]
@@ -828,8 +820,6 @@ fn serve(
         let server_memory_limit = re_memory::MemoryLimit::parse(&server_memory_limit)
             .map_err(|err| PyRuntimeError::new_err(format!("Bad server_memory_limit: {err}:")))?;
 
-        let _guard = enter_tokio_runtime();
-
         let sink = re_sdk::web_viewer::new_sink(
             open_browser,
             "0.0.0.0",
@@ -1122,7 +1112,6 @@ fn start_web_viewer_server(port: u16) -> PyResult<()> {
     {
         let mut web_handle = global_web_viewer_server();
 
-        let _guard = enter_tokio_runtime();
         *web_handle = Some(
             re_web_viewer_server::WebViewerServer::new("0.0.0.0", WebViewerServerPort(port))
                 .map_err(|err| {

From 7cad0dc12a6084b80c25dc87728f21e444183b83 Mon Sep 17 00:00:00 2001
From: Jeremy Leibs 
Date: Mon, 22 Apr 2024 17:45:05 +0200
Subject: [PATCH 337/508] Make rerun execution script handle .exe suffix
 correctly and cleanup scripts (#6046)

### What
I broke the windows wheel when adding a check for the existence of the
file.
Also move the rerun binary into the rerun_cli folder since this is seems
more aligned
with the intent of the newly introduced package.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6046?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6046?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6046)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 .../reusable_build_and_upload_wheels.yml         |  2 +-
 rerun_py/.gitignore                              |  3 ++-
 rerun_py/build.rs                                |  6 ++++--
 rerun_py/pyproject.toml                          |  6 +++++-
 rerun_py/rerun_sdk/rerun/__main__.py             | 15 ++-------------
 rerun_py/rerun_sdk/rerun_cli/__main__.py         | 16 +++++++++++++++-
 6 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml
index bca224ce9a97..75e2b3be99d8 100644
--- a/.github/workflows/reusable_build_and_upload_wheels.yml
+++ b/.github/workflows/reusable_build_and_upload_wheels.yml
@@ -203,7 +203,7 @@ jobs:
           --commit-sha ${{ steps.get-sha.outputs.sha }} \
           --artifact rerun-cli \
           --platform ${{ inputs.PLATFORM }} \
-          --dest rerun_py/rerun_sdk/bin
+          --dest rerun_py/rerun_sdk/rerun_cli
 
       - name: Build
         run: |
diff --git a/rerun_py/.gitignore b/rerun_py/.gitignore
index c0446e80d07d..a7ee3091de02 100644
--- a/rerun_py/.gitignore
+++ b/rerun_py/.gitignore
@@ -1,6 +1,7 @@
 !Cargo.lock
 .DS_Store
-rerun_sdk/bin/**
+rerun_sdk/rerun_cli/rerun
+rerun_sdk/rerun_cli/rerun.exe
 site/
 target/
 venv/
diff --git a/rerun_py/build.rs b/rerun_py/build.rs
index dac279d73a86..c7c2c207ed5c 100644
--- a/rerun_py/build.rs
+++ b/rerun_py/build.rs
@@ -11,10 +11,12 @@ fn main() {
         #[cfg(target_os = "windows")]
         let rerun_bin = std::env::current_dir()
             .unwrap()
-            .join("rerun_sdk/bin/rerun.exe");
+            .join("rerun_sdk/rerun_cli/rerun.exe");
 
         #[cfg(not(target_os = "windows"))]
-        let rerun_bin = std::env::current_dir().unwrap().join("rerun_sdk/bin/rerun");
+        let rerun_bin = std::env::current_dir()
+            .unwrap()
+            .join("rerun_sdk/rerun_cli/rerun");
 
         if !rerun_bin.exists() {
             eprintln!("ERROR: Expected to find `rerun` at `{rerun_bin:?}`.");
diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml
index d5ff8e663303..bdf5f80725d2 100644
--- a/rerun_py/pyproject.toml
+++ b/rerun_py/pyproject.toml
@@ -142,7 +142,11 @@ required-imports = ["from __future__ import annotations"]
 # Even though both `rerun` and `rerun.exe` are here, only one will be included since
 # they both should not be fetched in CI when running the build.
 # Files missing from this list is not a packaging failure.
-include = ["rerun_sdk.pth", "rerun_sdk/bin/rerun", "rerun_sdk/bin/rerun.exe"]
+include = [
+  "rerun_sdk.pth",
+  "rerun_sdk/rerun_cli/rerun",
+  "rerun_sdk/rerun_cli/rerun.exe",
+]
 locked = true
 name = "rerun_bindings"
 python-packages = ["rerun_sdk/rerun", "rerun_sdk/rerun_cli"]
diff --git a/rerun_py/rerun_sdk/rerun/__main__.py b/rerun_py/rerun_sdk/rerun/__main__.py
index 6b2e9525c09c..029f4e949c55 100644
--- a/rerun_py/rerun_sdk/rerun/__main__.py
+++ b/rerun_py/rerun_sdk/rerun/__main__.py
@@ -8,9 +8,7 @@
 
 from __future__ import annotations
 
-import os
-import subprocess
-import sys
+from rerun_cli.__main__ import main as cli_main
 
 from rerun import unregister_shutdown
 
@@ -19,17 +17,8 @@ def main() -> int:
     # Importing of the rerun module registers a shutdown hook that we know we don't
     # need when running the CLI directly. We can safely unregister it.
     unregister_shutdown()
-    if "RERUN_CLI_PATH" in os.environ:
-        print(f"Using overridden RERUN_CLI_PATH={os.environ['RERUN_CLI_PATH']}", file=sys.stderr)
-        target_path = os.environ["RERUN_CLI_PATH"]
-    else:
-        target_path = os.path.join(os.path.dirname(__file__), "..", "bin", "rerun")
 
-    if not os.path.exists(target_path):
-        print(f"Error: Could not find rerun binary at {target_path}", file=sys.stderr)
-        return 1
-
-    return subprocess.call([target_path, *sys.argv[1:]])
+    return cli_main()
 
 
 if __name__ == "__main__":
diff --git a/rerun_py/rerun_sdk/rerun_cli/__main__.py b/rerun_py/rerun_sdk/rerun_cli/__main__.py
index f3c5f416e2e8..9772b70ec325 100644
--- a/rerun_py/rerun_sdk/rerun_cli/__main__.py
+++ b/rerun_py/rerun_sdk/rerun_cli/__main__.py
@@ -7,12 +7,26 @@
 import sys
 
 
+def exe_suffix() -> str:
+    if sys.platform.startswith("win"):
+        return ".exe"
+    return ""
+
+
+def add_exe_suffix(path: str) -> str:
+    if not path.endswith(exe_suffix()):
+        return path + exe_suffix()
+    return path
+
+
 def main() -> int:
     if "RERUN_CLI_PATH" in os.environ:
         print(f"Using overridden RERUN_CLI_PATH={os.environ['RERUN_CLI_PATH']}", file=sys.stderr)
         target_path = os.environ["RERUN_CLI_PATH"]
     else:
-        target_path = os.path.join(os.path.dirname(__file__), "..", "bin", "rerun")
+        target_path = os.path.join(os.path.dirname(__file__), "rerun")
+
+    target_path = add_exe_suffix(target_path)
 
     if not os.path.exists(target_path):
         print(f"Error: Could not find rerun binary at {target_path}", file=sys.stderr)

From 487866d704d174e138a8782a6d52d197f524f31a Mon Sep 17 00:00:00 2001
From: Jeremy Leibs 
Date: Mon, 22 Apr 2024 17:46:19 +0200
Subject: [PATCH 338/508] Clarify tensor dimension order in image docstring
 (#6047)

### What

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6047?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6047?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6047)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 crates/re_types/definitions/rerun/archetypes/image.fbs | 8 ++++++--
 crates/re_types/src/archetypes/image.rs                | 8 ++++++--
 docs/content/reference/types/archetypes/image.md       | 8 ++++++--
 rerun_cpp/src/rerun/archetypes/image.hpp               | 8 ++++++--
 rerun_py/rerun_sdk/rerun/archetypes/image.py           | 8 ++++++--
 5 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/crates/re_types/definitions/rerun/archetypes/image.fbs b/crates/re_types/definitions/rerun/archetypes/image.fbs
index 2b99ac3b5f56..ac33c82ced97 100644
--- a/crates/re_types/definitions/rerun/archetypes/image.fbs
+++ b/crates/re_types/definitions/rerun/archetypes/image.fbs
@@ -8,13 +8,17 @@ namespace rerun.archetypes;
 
 /// A monochrome or color image.
 ///
-/// The shape of the `TensorData` must be mappable to:
+/// The order of dimensions in the underlying `TensorData` follows the typical
+/// row-major, interleaved-pixel image format. Additionally, Rerun orders the
+/// `TensorDimension`s within the shape description from outer-most to inner-most.
+///
+/// As such, the shape of the `TensorData` must be mappable to:
 /// - A `HxW` tensor, treated as a grayscale image.
 /// - A `HxWx3` tensor, treated as an RGB image.
 /// - A `HxWx4` tensor, treated as an RGBA image.
 ///
 /// Leading and trailing unit-dimensions are ignored, so that
-/// `1x640x480x3x1` is treated as a `640x480x3` RGB image.
+/// `1x480x640x3x1` is treated as a `480x640x3` RGB image.
 ///
 /// Rerun also supports compressed image encoded as JPEG, N12, and YUY2.
 /// Using these formats can save a lot of bandwidth and memory.
diff --git a/crates/re_types/src/archetypes/image.rs b/crates/re_types/src/archetypes/image.rs
index 40b954c47d42..2a9c32f743ed 100644
--- a/crates/re_types/src/archetypes/image.rs
+++ b/crates/re_types/src/archetypes/image.rs
@@ -24,13 +24,17 @@ use ::re_types_core::{DeserializationError, DeserializationResult};
 
 /// **Archetype**: A monochrome or color image.
 ///
-/// The shape of the `TensorData` must be mappable to:
+/// The order of dimensions in the underlying `TensorData` follows the typical
+/// row-major, interleaved-pixel image format. Additionally, Rerun orders the
+/// `TensorDimension`s within the shape description from outer-most to inner-most.
+///
+/// As such, the shape of the `TensorData` must be mappable to:
 /// - A `HxW` tensor, treated as a grayscale image.
 /// - A `HxWx3` tensor, treated as an RGB image.
 /// - A `HxWx4` tensor, treated as an RGBA image.
 ///
 /// Leading and trailing unit-dimensions are ignored, so that
-/// `1x640x480x3x1` is treated as a `640x480x3` RGB image.
+/// `1x480x640x3x1` is treated as a `480x640x3` RGB image.
 ///
 /// Rerun also supports compressed image encoded as JPEG, N12, and YUY2.
 /// Using these formats can save a lot of bandwidth and memory.
diff --git a/docs/content/reference/types/archetypes/image.md b/docs/content/reference/types/archetypes/image.md
index 04aac2a6cdc0..48476af7a6e5 100644
--- a/docs/content/reference/types/archetypes/image.md
+++ b/docs/content/reference/types/archetypes/image.md
@@ -4,13 +4,17 @@ title: "Image"
 
 A monochrome or color image.
 
-The shape of the `TensorData` must be mappable to:
+The order of dimensions in the underlying `TensorData` follows the typical
+row-major, interleaved-pixel image format. Additionally, Rerun orders the
+`TensorDimension`s within the shape description from outer-most to inner-most.
+
+As such, the shape of the `TensorData` must be mappable to:
 - A `HxW` tensor, treated as a grayscale image.
 - A `HxWx3` tensor, treated as an RGB image.
 - A `HxWx4` tensor, treated as an RGBA image.
 
 Leading and trailing unit-dimensions are ignored, so that
-`1x640x480x3x1` is treated as a `640x480x3` RGB image.
+`1x480x640x3x1` is treated as a `480x640x3` RGB image.
 
 Rerun also supports compressed image encoded as JPEG, N12, and YUY2.
 Using these formats can save a lot of bandwidth and memory.
diff --git a/rerun_cpp/src/rerun/archetypes/image.hpp b/rerun_cpp/src/rerun/archetypes/image.hpp
index 95c7ba3a25a1..48c5968463f9 100644
--- a/rerun_cpp/src/rerun/archetypes/image.hpp
+++ b/rerun_cpp/src/rerun/archetypes/image.hpp
@@ -19,13 +19,17 @@
 namespace rerun::archetypes {
     /// **Archetype**: A monochrome or color image.
     ///
-    /// The shape of the `TensorData` must be mappable to:
+    /// The order of dimensions in the underlying `TensorData` follows the typical
+    /// row-major, interleaved-pixel image format. Additionally, Rerun orders the
+    /// `TensorDimension`s within the shape description from outer-most to inner-most.
+    ///
+    /// As such, the shape of the `TensorData` must be mappable to:
     /// - A `HxW` tensor, treated as a grayscale image.
     /// - A `HxWx3` tensor, treated as an RGB image.
     /// - A `HxWx4` tensor, treated as an RGBA image.
     ///
     /// Leading and trailing unit-dimensions are ignored, so that
-    /// `1x640x480x3x1` is treated as a `640x480x3` RGB image.
+    /// `1x480x640x3x1` is treated as a `480x640x3` RGB image.
     ///
     /// Rerun also supports compressed image encoded as JPEG, N12, and YUY2.
     /// Using these formats can save a lot of bandwidth and memory.
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/image.py b/rerun_py/rerun_sdk/rerun/archetypes/image.py
index 0f3bb50cdb27..1135219aa32e 100644
--- a/rerun_py/rerun_sdk/rerun/archetypes/image.py
+++ b/rerun_py/rerun_sdk/rerun/archetypes/image.py
@@ -22,13 +22,17 @@ class Image(ImageExt, Archetype):
     """
     **Archetype**: A monochrome or color image.
 
-    The shape of the `TensorData` must be mappable to:
+    The order of dimensions in the underlying `TensorData` follows the typical
+    row-major, interleaved-pixel image format. Additionally, Rerun orders the
+    `TensorDimension`s within the shape description from outer-most to inner-most.
+
+    As such, the shape of the `TensorData` must be mappable to:
     - A `HxW` tensor, treated as a grayscale image.
     - A `HxWx3` tensor, treated as an RGB image.
     - A `HxWx4` tensor, treated as an RGBA image.
 
     Leading and trailing unit-dimensions are ignored, so that
-    `1x640x480x3x1` is treated as a `640x480x3` RGB image.
+    `1x480x640x3x1` is treated as a `480x640x3` RGB image.
 
     Rerun also supports compressed image encoded as JPEG, N12, and YUY2.
     Using these formats can save a lot of bandwidth and memory.

From 7cabcca88aec7c107ef479a8b5ef39592b103f84 Mon Sep 17 00:00:00 2001
From: rerun-bot <132550499+rerun-bot@users.noreply.github.com>
Date: Tue, 23 Apr 2024 08:09:07 +0200
Subject: [PATCH 339/508] Release 0.16.0-alpha.2 (#6063)

### What

- [x] Bump all crate versions to `0.16.0-alpha.2`

The release process will begin once this pull request is merged.


---
 Cargo.lock                                    | 190 +++++++++---------
 Cargo.toml                                    |  98 ++++-----
 examples/rust/clock/Cargo.toml                |   2 +-
 examples/rust/custom_data_loader/Cargo.toml   |   2 +-
 examples/rust/custom_space_view/Cargo.toml    |   2 +-
 .../rust/custom_store_subscriber/Cargo.toml   |   2 +-
 examples/rust/dna/Cargo.toml                  |   2 +-
 examples/rust/extend_viewer_ui/Cargo.toml     |   2 +-
 examples/rust/external_data_loader/Cargo.toml |   2 +-
 examples/rust/incremental_logging/Cargo.toml  |   2 +-
 examples/rust/log_file/Cargo.toml             |   2 +-
 examples/rust/minimal/Cargo.toml              |   2 +-
 examples/rust/minimal_options/Cargo.toml      |   2 +-
 examples/rust/minimal_serve/Cargo.toml        |   2 +-
 examples/rust/objectron/Cargo.toml            |   2 +-
 examples/rust/raw_mesh/Cargo.toml             |   2 +-
 examples/rust/shared_recording/Cargo.toml     |   2 +-
 examples/rust/spawn_viewer/Cargo.toml         |   2 +-
 examples/rust/stdio/Cargo.toml                |   2 +-
 examples/rust/template/Cargo.toml             |   2 +-
 20 files changed, 162 insertions(+), 162 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 134c857a11a1..65e08ab3eaa7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1069,7 +1069,7 @@ dependencies = [
 
 [[package]]
 name = "clock"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -1406,7 +1406,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
 
 [[package]]
 name = "custom_data_loader"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "re_build_tools",
  "rerun",
@@ -1414,7 +1414,7 @@ dependencies = [
 
 [[package]]
 name = "custom_space_view"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "mimalloc",
  "re_crash_handler",
@@ -1424,7 +1424,7 @@ dependencies = [
 
 [[package]]
 name = "custom_store_subscriber"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "re_build_tools",
  "rerun",
@@ -1535,7 +1535,7 @@ dependencies = [
 
 [[package]]
 name = "dna"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "itertools 0.12.0",
  "rand",
@@ -1966,7 +1966,7 @@ dependencies = [
 
 [[package]]
 name = "extend_viewer_ui"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "mimalloc",
  "re_crash_handler",
@@ -2574,7 +2574,7 @@ dependencies = [
 
 [[package]]
 name = "incremental_logging"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -2923,7 +2923,7 @@ dependencies = [
 
 [[package]]
 name = "log_benchmark"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -2934,7 +2934,7 @@ dependencies = [
 
 [[package]]
 name = "log_file"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -3074,14 +3074,14 @@ dependencies = [
 
 [[package]]
 name = "minimal"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "rerun",
 ]
 
 [[package]]
 name = "minimal_options"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -3091,7 +3091,7 @@ dependencies = [
 
 [[package]]
 name = "minimal_serve"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "rerun",
 ]
@@ -3458,7 +3458,7 @@ dependencies = [
 
 [[package]]
 name = "objectron"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -3641,7 +3641,7 @@ dependencies = [
 
 [[package]]
 name = "plot_dashboard_stress"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -4069,7 +4069,7 @@ checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544"
 
 [[package]]
 name = "raw_mesh"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "bytes",
@@ -4108,7 +4108,7 @@ dependencies = [
 
 [[package]]
 name = "re_analytics"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "crossbeam",
  "directories-next",
@@ -4150,11 +4150,11 @@ dependencies = [
 
 [[package]]
 name = "re_build_info"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 
 [[package]]
 name = "re_build_tools"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "cargo_metadata 0.18.1",
@@ -4167,7 +4167,7 @@ dependencies = [
 
 [[package]]
 name = "re_crash_handler"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "backtrace",
  "itertools 0.12.0",
@@ -4179,7 +4179,7 @@ dependencies = [
 
 [[package]]
 name = "re_data_source"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4202,7 +4202,7 @@ dependencies = [
 
 [[package]]
 name = "re_data_store"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4232,7 +4232,7 @@ dependencies = [
 
 [[package]]
 name = "re_data_ui"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4261,7 +4261,7 @@ dependencies = [
 
 [[package]]
 name = "re_dev_tools"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "argh",
@@ -4287,7 +4287,7 @@ dependencies = [
 
 [[package]]
 name = "re_entity_db"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4323,21 +4323,21 @@ dependencies = [
 
 [[package]]
 name = "re_error"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
 ]
 
 [[package]]
 name = "re_format"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "num-traits",
 ]
 
 [[package]]
 name = "re_format_arrow"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "comfy-table",
  "re_arrow2",
@@ -4347,7 +4347,7 @@ dependencies = [
 
 [[package]]
 name = "re_int_histogram"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "criterion",
  "insta",
@@ -4358,7 +4358,7 @@ dependencies = [
 
 [[package]]
 name = "re_log"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "env_logger",
  "js-sys",
@@ -4371,7 +4371,7 @@ dependencies = [
 
 [[package]]
 name = "re_log_encoding"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "criterion",
  "ehttp",
@@ -4396,7 +4396,7 @@ dependencies = [
 
 [[package]]
 name = "re_log_types"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4436,7 +4436,7 @@ dependencies = [
 
 [[package]]
 name = "re_memory"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "backtrace",
@@ -4457,7 +4457,7 @@ dependencies = [
 
 [[package]]
 name = "re_query"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "backtrace",
  "criterion",
@@ -4482,7 +4482,7 @@ dependencies = [
 
 [[package]]
 name = "re_query2"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4513,7 +4513,7 @@ dependencies = [
 
 [[package]]
 name = "re_query_cache"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "criterion",
@@ -4539,7 +4539,7 @@ dependencies = [
 
 [[package]]
 name = "re_query_cache2"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4569,7 +4569,7 @@ dependencies = [
 
 [[package]]
 name = "re_renderer"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4616,7 +4616,7 @@ dependencies = [
 
 [[package]]
 name = "re_renderer_examples"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4640,7 +4640,7 @@ dependencies = [
 
 [[package]]
 name = "re_sdk"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4672,7 +4672,7 @@ dependencies = [
 
 [[package]]
 name = "re_sdk_comms"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "crossbeam",
@@ -4687,7 +4687,7 @@ dependencies = [
 
 [[package]]
 name = "re_smart_channel"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "crossbeam",
  "parking_lot",
@@ -4698,7 +4698,7 @@ dependencies = [
 
 [[package]]
 name = "re_space_view"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "egui",
  "itertools 0.12.0",
@@ -4718,7 +4718,7 @@ dependencies = [
 
 [[package]]
 name = "re_space_view_bar_chart"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "egui",
  "egui_plot",
@@ -4736,7 +4736,7 @@ dependencies = [
 
 [[package]]
 name = "re_space_view_dataframe"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "egui",
  "egui_extras",
@@ -4753,7 +4753,7 @@ dependencies = [
 
 [[package]]
 name = "re_space_view_spatial"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4790,7 +4790,7 @@ dependencies = [
 
 [[package]]
 name = "re_space_view_tensor"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -4816,7 +4816,7 @@ dependencies = [
 
 [[package]]
 name = "re_space_view_text_document"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "egui",
  "egui_commonmark",
@@ -4834,7 +4834,7 @@ dependencies = [
 
 [[package]]
 name = "re_space_view_text_log"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "egui",
  "egui_extras",
@@ -4854,7 +4854,7 @@ dependencies = [
 
 [[package]]
 name = "re_space_view_time_series"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "egui",
  "egui_plot",
@@ -4876,7 +4876,7 @@ dependencies = [
 
 [[package]]
 name = "re_string_interner"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "nohash-hasher",
@@ -4888,7 +4888,7 @@ dependencies = [
 
 [[package]]
 name = "re_time_panel"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "egui",
  "itertools 0.12.0",
@@ -4907,7 +4907,7 @@ dependencies = [
 
 [[package]]
 name = "re_tracing"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "puffin",
  "puffin_http",
@@ -4917,7 +4917,7 @@ dependencies = [
 
 [[package]]
 name = "re_tuid"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "criterion",
  "document-features",
@@ -4929,7 +4929,7 @@ dependencies = [
 
 [[package]]
 name = "re_types"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "array-init",
@@ -4968,7 +4968,7 @@ dependencies = [
 
 [[package]]
 name = "re_types_blueprint"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "array-init",
  "bytemuck",
@@ -4981,7 +4981,7 @@ dependencies = [
 
 [[package]]
 name = "re_types_builder"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "camino",
@@ -5007,7 +5007,7 @@ dependencies = [
 
 [[package]]
 name = "re_types_core"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "backtrace",
@@ -5027,7 +5027,7 @@ dependencies = [
 
 [[package]]
 name = "re_ui"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "eframe",
  "egui",
@@ -5049,7 +5049,7 @@ dependencies = [
 
 [[package]]
 name = "re_viewer"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -5115,7 +5115,7 @@ dependencies = [
 
 [[package]]
 name = "re_viewer_context"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "anyhow",
@@ -5157,7 +5157,7 @@ dependencies = [
 
 [[package]]
 name = "re_viewport"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "egui",
@@ -5187,7 +5187,7 @@ dependencies = [
 
 [[package]]
 name = "re_web_viewer_server"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "document-features",
  "re_analytics",
@@ -5198,7 +5198,7 @@ dependencies = [
 
 [[package]]
 name = "re_ws_comms"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "bincode",
@@ -5285,7 +5285,7 @@ checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b"
 
 [[package]]
 name = "rerun"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5318,7 +5318,7 @@ dependencies = [
 
 [[package]]
 name = "rerun-cli"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "document-features",
  "mimalloc",
@@ -5332,7 +5332,7 @@ dependencies = [
 
 [[package]]
 name = "rerun-loader-rust-file"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "argh",
@@ -5341,7 +5341,7 @@ dependencies = [
 
 [[package]]
 name = "rerun_c"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "ahash",
  "once_cell",
@@ -5353,7 +5353,7 @@ dependencies = [
 
 [[package]]
 name = "rerun_py"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "crossbeam",
  "document-features",
@@ -5451,7 +5451,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_annotation_context"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5461,7 +5461,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_arrows2d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5471,7 +5471,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_arrows3d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5481,7 +5481,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_boxes2d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5491,7 +5491,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_boxes3d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5501,7 +5501,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_depth_image"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5512,7 +5512,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_disconnected_space"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5522,7 +5522,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_image"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5535,7 +5535,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_line_strips2d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5545,7 +5545,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_line_strips3d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5555,7 +5555,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_pinhole"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5565,7 +5565,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_points2d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5575,7 +5575,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_points3d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5585,7 +5585,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_segmentation_image"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5596,7 +5596,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_tensor"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5607,7 +5607,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_text_document"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5617,7 +5617,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_text_log"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5627,7 +5627,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_transform3d"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5637,7 +5637,7 @@ dependencies = [
 
 [[package]]
 name = "roundtrip_view_coordinates"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -5653,7 +5653,7 @@ checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
 
 [[package]]
 name = "run_wasm"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "cargo-run-wasm",
  "pico-args",
@@ -5928,7 +5928,7 @@ dependencies = [
 
 [[package]]
 name = "shared_recording"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "rerun",
 ]
@@ -6064,7 +6064,7 @@ dependencies = [
 
 [[package]]
 name = "snippets"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "itertools 0.12.0",
  "ndarray",
@@ -6086,7 +6086,7 @@ dependencies = [
 
 [[package]]
 name = "spawn_viewer"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "rerun",
 ]
@@ -6120,7 +6120,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
 [[package]]
 name = "stdio"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "rerun",
 ]
@@ -6216,7 +6216,7 @@ dependencies = [
 
 [[package]]
 name = "template"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "rerun",
 ]
@@ -6232,7 +6232,7 @@ dependencies = [
 
 [[package]]
 name = "test_api"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "anyhow",
  "clap",
@@ -6247,7 +6247,7 @@ dependencies = [
 
 [[package]]
 name = "test_image_memory"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 dependencies = [
  "mimalloc",
  "re_format",
diff --git a/Cargo.toml b/Cargo.toml
index e51070f75557..5df25ff9ff7d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,61 +21,61 @@ include = ["../../LICENSE-APACHE", "../../LICENSE-MIT", "**/*.rs", "Cargo.toml"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rerun-io/rerun"
 rust-version = "1.76"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 
 [workspace.dependencies]
 # When using alpha-release, always use exact version, e.g. `version = "=0.x.y-alpha.z"
 # This is because we treat alpha-releases as incompatible, but semver doesn't.
 # In particular: if we compile rerun 0.3.0-alpha.0 we only want it to use
 # re_log_types 0.3.0-alpha.0, NOT 0.3.0-alpha.4 even though it is newer and semver-compatible.
-re_analytics = { path = "crates/re_analytics", version = "=0.16.0-alpha.1", default-features = false }
-re_build_info = { path = "crates/re_build_info", version = "=0.16.0-alpha.1", default-features = false }
-re_build_tools = { path = "crates/re_build_tools", version = "=0.16.0-alpha.1", default-features = false }
-re_crash_handler = { path = "crates/re_crash_handler", version = "=0.16.0-alpha.1", default-features = false }
-re_data_source = { path = "crates/re_data_source", version = "=0.16.0-alpha.1", default-features = false }
-re_data_store = { path = "crates/re_data_store", version = "=0.16.0-alpha.1", default-features = false }
-re_data_ui = { path = "crates/re_data_ui", version = "=0.16.0-alpha.1", default-features = false }
-re_dev_tools = { path = "crates/re_dev_tools", version = "=0.16.0-alpha.1", default-features = false }
-re_entity_db = { path = "crates/re_entity_db", version = "=0.16.0-alpha.1", default-features = false }
-re_error = { path = "crates/re_error", version = "=0.16.0-alpha.1", default-features = false }
-re_format = { path = "crates/re_format", version = "=0.16.0-alpha.1", default-features = false }
-re_format_arrow = { path = "crates/re_format_arrow", version = "=0.16.0-alpha.1", default-features = false }
-re_int_histogram = { path = "crates/re_int_histogram", version = "=0.16.0-alpha.1", default-features = false }
-re_log = { path = "crates/re_log", version = "=0.16.0-alpha.1", default-features = false }
-re_log_encoding = { path = "crates/re_log_encoding", version = "=0.16.0-alpha.1", default-features = false }
-re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.1", default-features = false }
-re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.1", default-features = false }
-re_query = { path = "crates/re_query", version = "=0.16.0-alpha.1", default-features = false }
-re_query_cache = { path = "crates/re_query_cache", version = "=0.16.0-alpha.1", default-features = false }
-re_query_cache2 = { path = "crates/re_query_cache2", version = "=0.16.0-alpha.1", default-features = false }
-re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.1", default-features = false }
-re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.1", default-features = false }
-re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.1", default-features = false }
-re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.16.0-alpha.1", default-features = false }
-re_smart_channel = { path = "crates/re_smart_channel", version = "=0.16.0-alpha.1", default-features = false }
-re_space_view = { path = "crates/re_space_view", version = "=0.16.0-alpha.1", default-features = false }
-re_space_view_bar_chart = { path = "crates/re_space_view_bar_chart", version = "=0.16.0-alpha.1", default-features = false }
-re_space_view_dataframe = { path = "crates/re_space_view_dataframe", version = "=0.16.0-alpha.1", default-features = false }
-re_space_view_spatial = { path = "crates/re_space_view_spatial", version = "=0.16.0-alpha.1", default-features = false }
-re_space_view_tensor = { path = "crates/re_space_view_tensor", version = "=0.16.0-alpha.1", default-features = false }
-re_space_view_text_document = { path = "crates/re_space_view_text_document", version = "=0.16.0-alpha.1", default-features = false }
-re_space_view_text_log = { path = "crates/re_space_view_text_log", version = "=0.16.0-alpha.1", default-features = false }
-re_space_view_time_series = { path = "crates/re_space_view_time_series", version = "=0.16.0-alpha.1", default-features = false }
-re_string_interner = { path = "crates/re_string_interner", version = "=0.16.0-alpha.1", default-features = false }
-re_time_panel = { path = "crates/re_time_panel", version = "=0.16.0-alpha.1", default-features = false }
-re_tracing = { path = "crates/re_tracing", version = "=0.16.0-alpha.1", default-features = false }
-re_tuid = { path = "crates/re_tuid", version = "=0.16.0-alpha.1", default-features = false }
-re_types = { path = "crates/re_types", version = "=0.16.0-alpha.1", default-features = false }
-re_types_blueprint = { path = "crates/re_types_blueprint", version = "=0.16.0-alpha.1", default-features = false }
-re_types_builder = { path = "crates/re_types_builder", version = "=0.16.0-alpha.1", default-features = false }
-re_types_core = { path = "crates/re_types_core", version = "=0.16.0-alpha.1", default-features = false }
-re_ui = { path = "crates/re_ui", version = "=0.16.0-alpha.1", default-features = false }
-re_viewer = { path = "crates/re_viewer", version = "=0.16.0-alpha.1", default-features = false }
-re_viewer_context = { path = "crates/re_viewer_context", version = "=0.16.0-alpha.1", default-features = false }
-re_viewport = { path = "crates/re_viewport", version = "=0.16.0-alpha.1", default-features = false }
-re_web_viewer_server = { path = "crates/re_web_viewer_server", version = "=0.16.0-alpha.1", default-features = false }
-re_ws_comms = { path = "crates/re_ws_comms", version = "=0.16.0-alpha.1", default-features = false }
-rerun = { path = "crates/rerun", version = "=0.16.0-alpha.1", default-features = false }
+re_analytics = { path = "crates/re_analytics", version = "=0.16.0-alpha.2", default-features = false }
+re_build_info = { path = "crates/re_build_info", version = "=0.16.0-alpha.2", default-features = false }
+re_build_tools = { path = "crates/re_build_tools", version = "=0.16.0-alpha.2", default-features = false }
+re_crash_handler = { path = "crates/re_crash_handler", version = "=0.16.0-alpha.2", default-features = false }
+re_data_source = { path = "crates/re_data_source", version = "=0.16.0-alpha.2", default-features = false }
+re_data_store = { path = "crates/re_data_store", version = "=0.16.0-alpha.2", default-features = false }
+re_data_ui = { path = "crates/re_data_ui", version = "=0.16.0-alpha.2", default-features = false }
+re_dev_tools = { path = "crates/re_dev_tools", version = "=0.16.0-alpha.2", default-features = false }
+re_entity_db = { path = "crates/re_entity_db", version = "=0.16.0-alpha.2", default-features = false }
+re_error = { path = "crates/re_error", version = "=0.16.0-alpha.2", default-features = false }
+re_format = { path = "crates/re_format", version = "=0.16.0-alpha.2", default-features = false }
+re_format_arrow = { path = "crates/re_format_arrow", version = "=0.16.0-alpha.2", default-features = false }
+re_int_histogram = { path = "crates/re_int_histogram", version = "=0.16.0-alpha.2", default-features = false }
+re_log = { path = "crates/re_log", version = "=0.16.0-alpha.2", default-features = false }
+re_log_encoding = { path = "crates/re_log_encoding", version = "=0.16.0-alpha.2", default-features = false }
+re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.2", default-features = false }
+re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.2", default-features = false }
+re_query = { path = "crates/re_query", version = "=0.16.0-alpha.2", default-features = false }
+re_query_cache = { path = "crates/re_query_cache", version = "=0.16.0-alpha.2", default-features = false }
+re_query_cache2 = { path = "crates/re_query_cache2", version = "=0.16.0-alpha.2", default-features = false }
+re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.2", default-features = false }
+re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.2", default-features = false }
+re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.2", default-features = false }
+re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.16.0-alpha.2", default-features = false }
+re_smart_channel = { path = "crates/re_smart_channel", version = "=0.16.0-alpha.2", default-features = false }
+re_space_view = { path = "crates/re_space_view", version = "=0.16.0-alpha.2", default-features = false }
+re_space_view_bar_chart = { path = "crates/re_space_view_bar_chart", version = "=0.16.0-alpha.2", default-features = false }
+re_space_view_dataframe = { path = "crates/re_space_view_dataframe", version = "=0.16.0-alpha.2", default-features = false }
+re_space_view_spatial = { path = "crates/re_space_view_spatial", version = "=0.16.0-alpha.2", default-features = false }
+re_space_view_tensor = { path = "crates/re_space_view_tensor", version = "=0.16.0-alpha.2", default-features = false }
+re_space_view_text_document = { path = "crates/re_space_view_text_document", version = "=0.16.0-alpha.2", default-features = false }
+re_space_view_text_log = { path = "crates/re_space_view_text_log", version = "=0.16.0-alpha.2", default-features = false }
+re_space_view_time_series = { path = "crates/re_space_view_time_series", version = "=0.16.0-alpha.2", default-features = false }
+re_string_interner = { path = "crates/re_string_interner", version = "=0.16.0-alpha.2", default-features = false }
+re_time_panel = { path = "crates/re_time_panel", version = "=0.16.0-alpha.2", default-features = false }
+re_tracing = { path = "crates/re_tracing", version = "=0.16.0-alpha.2", default-features = false }
+re_tuid = { path = "crates/re_tuid", version = "=0.16.0-alpha.2", default-features = false }
+re_types = { path = "crates/re_types", version = "=0.16.0-alpha.2", default-features = false }
+re_types_blueprint = { path = "crates/re_types_blueprint", version = "=0.16.0-alpha.2", default-features = false }
+re_types_builder = { path = "crates/re_types_builder", version = "=0.16.0-alpha.2", default-features = false }
+re_types_core = { path = "crates/re_types_core", version = "=0.16.0-alpha.2", default-features = false }
+re_ui = { path = "crates/re_ui", version = "=0.16.0-alpha.2", default-features = false }
+re_viewer = { path = "crates/re_viewer", version = "=0.16.0-alpha.2", default-features = false }
+re_viewer_context = { path = "crates/re_viewer_context", version = "=0.16.0-alpha.2", default-features = false }
+re_viewport = { path = "crates/re_viewport", version = "=0.16.0-alpha.2", default-features = false }
+re_web_viewer_server = { path = "crates/re_web_viewer_server", version = "=0.16.0-alpha.2", default-features = false }
+re_ws_comms = { path = "crates/re_ws_comms", version = "=0.16.0-alpha.2", default-features = false }
+rerun = { path = "crates/rerun", version = "=0.16.0-alpha.2", default-features = false }
 
 # egui-crates:
 ecolor = "0.27.2"
diff --git a/examples/rust/clock/Cargo.toml b/examples/rust/clock/Cargo.toml
index ba5c87353b23..436e04b96bcf 100644
--- a/examples/rust/clock/Cargo.toml
+++ b/examples/rust/clock/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clock"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/custom_data_loader/Cargo.toml b/examples/rust/custom_data_loader/Cargo.toml
index 20523c8cf6d8..be7f08bc5af6 100644
--- a/examples/rust/custom_data_loader/Cargo.toml
+++ b/examples/rust/custom_data_loader/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "custom_data_loader"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml
index e80164e63f77..e9d05114dc00 100644
--- a/examples/rust/custom_space_view/Cargo.toml
+++ b/examples/rust/custom_space_view/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "custom_space_view"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/custom_store_subscriber/Cargo.toml b/examples/rust/custom_store_subscriber/Cargo.toml
index 4cdd909aba29..baab7e3e18f8 100644
--- a/examples/rust/custom_store_subscriber/Cargo.toml
+++ b/examples/rust/custom_store_subscriber/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "custom_store_subscriber"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml
index 6e2a2f64c07c..62c3aa1fdd6e 100644
--- a/examples/rust/dna/Cargo.toml
+++ b/examples/rust/dna/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "dna"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml
index 8f470162da51..bbff65909271 100644
--- a/examples/rust/extend_viewer_ui/Cargo.toml
+++ b/examples/rust/extend_viewer_ui/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "extend_viewer_ui"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/external_data_loader/Cargo.toml b/examples/rust/external_data_loader/Cargo.toml
index 4fc476291a69..d2bd523ff1f4 100644
--- a/examples/rust/external_data_loader/Cargo.toml
+++ b/examples/rust/external_data_loader/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "rerun-loader-rust-file"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml
index 6075cb1f9b04..756c32dc6670 100644
--- a/examples/rust/incremental_logging/Cargo.toml
+++ b/examples/rust/incremental_logging/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "incremental_logging"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml
index 5b74dd346b0a..d560387c23e0 100644
--- a/examples/rust/log_file/Cargo.toml
+++ b/examples/rust/log_file/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "log_file"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/minimal/Cargo.toml b/examples/rust/minimal/Cargo.toml
index e1bb2fedda46..97c35c462f90 100644
--- a/examples/rust/minimal/Cargo.toml
+++ b/examples/rust/minimal/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "minimal"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/minimal_options/Cargo.toml b/examples/rust/minimal_options/Cargo.toml
index f16187b9720f..bbd813e47624 100644
--- a/examples/rust/minimal_options/Cargo.toml
+++ b/examples/rust/minimal_options/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "minimal_options"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml
index 2e46275d5b95..81bbc8b212a5 100644
--- a/examples/rust/minimal_serve/Cargo.toml
+++ b/examples/rust/minimal_serve/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "minimal_serve"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/objectron/Cargo.toml b/examples/rust/objectron/Cargo.toml
index bcf6dfc1fa84..ee197b54b6cc 100644
--- a/examples/rust/objectron/Cargo.toml
+++ b/examples/rust/objectron/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "objectron"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/raw_mesh/Cargo.toml b/examples/rust/raw_mesh/Cargo.toml
index 63ecc0b96ce0..810c880c1057 100644
--- a/examples/rust/raw_mesh/Cargo.toml
+++ b/examples/rust/raw_mesh/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "raw_mesh"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/shared_recording/Cargo.toml b/examples/rust/shared_recording/Cargo.toml
index 3ae2cbd51edd..a273614f20b9 100644
--- a/examples/rust/shared_recording/Cargo.toml
+++ b/examples/rust/shared_recording/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "shared_recording"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/spawn_viewer/Cargo.toml b/examples/rust/spawn_viewer/Cargo.toml
index 2b50de7a3369..35aa525d7426 100644
--- a/examples/rust/spawn_viewer/Cargo.toml
+++ b/examples/rust/spawn_viewer/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "spawn_viewer"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/stdio/Cargo.toml b/examples/rust/stdio/Cargo.toml
index 0369c6ed3b5d..25739e5bfdca 100644
--- a/examples/rust/stdio/Cargo.toml
+++ b/examples/rust/stdio/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "stdio"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"
diff --git a/examples/rust/template/Cargo.toml b/examples/rust/template/Cargo.toml
index 27f63350ee67..dd73ad9fc75c 100644
--- a/examples/rust/template/Cargo.toml
+++ b/examples/rust/template/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "template"
-version = "0.16.0-alpha.1+dev"
+version = "0.16.0-alpha.2"
 edition = "2021"
 rust-version = "1.76"
 license = "MIT OR Apache-2.0"

From 62546324567184448f4b086a08d209e73f310d32 Mon Sep 17 00:00:00 2001
From: Emil Ernerfeldt 
Date: Tue, 23 Apr 2024 08:32:24 +0200
Subject: [PATCH 340/508] Fix crate publishing script (#6073)

I didn't properly handle new crates
---
 scripts/ci/crates.py | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/scripts/ci/crates.py b/scripts/ci/crates.py
index b720aefece23..a80ae5b98fdc 100755
--- a/scripts/ci/crates.py
+++ b/scripts/ci/crates.py
@@ -382,11 +382,10 @@ def is_already_published(version: str, crate: Crate) -> bool:
     # the request failed
     if not resp.ok:
         detail = body["errors"][0]["detail"]
-        if detail == "Not Found":
-            # First time we're publishing this crate
-            return False
+        if resp.status_code == 404:
+            return False  # New crate that hasn't been published before
         else:
-            raise Exception(f"failed to get crate {crate_name}: {detail}")
+            raise Exception(f"Failed to get crate '{crate_name}': {resp.status_code} {detail}")
 
     # crate has not been uploaded yet
     if "versions" not in body:

From 72e80c6d3a9788b2b3a3eb6934c11e18e7a845af Mon Sep 17 00:00:00 2001
From: Clement Rey 
Date: Tue, 23 Apr 2024 09:38:39 +0200
Subject: [PATCH 341/508] Fix cargo install of CLI (#6076)

```
cargo install --force --path crates/rerun-cli
  Installing rerun-cli v0.16.0-alpha.2 (/home/cmc/dev/rerun-io/rerun/crates/rerun-cli)

error[E0425]: cannot find function `accept` in crate `tungstenite`
   --> crates/re_ws_comms/src/server.rs:217:36
    |
217 |                 match tungstenite::accept(tcp_stream) {
    |                                    ^^^^^^ not found in `tungstenite`
    |
note: found an item that was configured out
   --> /home/cmc/.cargo/registry/src/index.crates.io-6f17d22bba15001f/tungstenite-0.20.1/src/lib.rs:44:14
    |
44  |     server::{accept, accept_hdr, accept_hdr_with_config, accept_with_config},
    |              ^^^^^^
    = note: the item is gated behind the `handshake` feature

For more information about this error, try `rustc --explain E0425`.
warning: `re_ws_comms` (lib) generated 1 warning
error: could not compile `re_ws_comms` (lib) due to 1 previous error; 1 warning emitted
warning: build failed, waiting for other jobs to finish...
error: failed to compile `rerun-cli v0.16.0-alpha.2 (/home/cmc/dev/rerun-io/rerun/crates/rerun-cli)`, intermediate artifacts can be found at `/home/cmc/dev/rerun-io/rerun/target`.
To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.
```

Cannot have a server without `accept`, and cannot have `accept` without
`tungstenite/handshake`.

No `Cargo.lock` changes necessary because it was already accounted in
there due to implicit workspace deps union on some other path.
---
 crates/re_ws_comms/Cargo.toml | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/crates/re_ws_comms/Cargo.toml b/crates/re_ws_comms/Cargo.toml
index 9bd70a93bc25..71d196783042 100644
--- a/crates/re_ws_comms/Cargo.toml
+++ b/crates/re_ws_comms/Cargo.toml
@@ -24,7 +24,13 @@ all-features = true
 client = ["ewebsock"]
 
 ## Enable the server.
-server = ["dep:parking_lot", "dep:re_smart_channel", "tungstenite", "polling"]
+server = [
+  "dep:parking_lot",
+  "dep:re_smart_channel",
+  "dep:tungstenite",
+  "dep:polling",
+  "tungstenite/handshake",
+]
 
 ## Enable encryption using TLS support (`wss://`).
 tls = [

From f69fa6a5c5448d2c35a51a655822d400f11dc15c Mon Sep 17 00:00:00 2001
From: Emil Ernerfeldt 
Date: Tue, 23 Apr 2024 09:51:28 +0200
Subject: [PATCH 342/508] Add memory overhead test for the datastore (#6067)

Part of https://github.com/rerun-io/rerun/issues/6066

Shows that datastore currently uses 936 bytes to store a 16 byte RowId,
a 8 byte TimeInt, and a 8 byte f64, i.e. around 29x the memory use it
should have.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6067?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6067?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6067)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.

---------

Co-authored-by: Clement Rey 
---
 Cargo.lock                                    |   1 +
 crates/re_data_store/Cargo.toml               |   4 +-
 crates/re_data_store/tests/memory_test.rs     | 107 ++++++++++++++++++
 .../memory_test__scalars_on_one_timeline.snap |  10 ++
 pixi.toml                                     |   2 +-
 5 files changed, 122 insertions(+), 2 deletions(-)
 create mode 100644 crates/re_data_store/tests/memory_test.rs
 create mode 100644 crates/re_data_store/tests/snapshots/memory_test__scalars_on_one_timeline.snap

diff --git a/Cargo.lock b/Cargo.lock
index 65e08ab3eaa7..d40b30b738bd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4209,6 +4209,7 @@ dependencies = [
  "criterion",
  "document-features",
  "indent",
+ "insta",
  "itertools 0.12.0",
  "mimalloc",
  "nohash-hasher",
diff --git a/crates/re_data_store/Cargo.toml b/crates/re_data_store/Cargo.toml
index 5356836263dc..a81e47ecf21d 100644
--- a/crates/re_data_store/Cargo.toml
+++ b/crates/re_data_store/Cargo.toml
@@ -30,8 +30,8 @@ deadlock_detection = ["parking_lot/deadlock_detection"]
 # Rerun dependencies:
 re_format.workspace = true
 re_format_arrow.workspace = true
-re_log_types.workspace = true
 re_log = { workspace = true, features = ["setup"] }
+re_log_types.workspace = true
 re_tracing.workspace = true
 re_types_core.workspace = true
 
@@ -50,10 +50,12 @@ web-time.workspace = true
 
 
 [dev-dependencies]
+re_format.workspace = true
 re_types = { workspace = true, features = ["datagen", "testing"] }
 
 anyhow.workspace = true
 criterion.workspace = true
+insta.workspace = true
 mimalloc.workspace = true
 rand.workspace = true
 similar-asserts.workspace = true
diff --git a/crates/re_data_store/tests/memory_test.rs b/crates/re_data_store/tests/memory_test.rs
new file mode 100644
index 000000000000..2b9b1f5c409f
--- /dev/null
+++ b/crates/re_data_store/tests/memory_test.rs
@@ -0,0 +1,107 @@
+//! Measures the memory overhead of the data store.
+
+use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+
+thread_local! {
+    static LIVE_BYTES_IN_THREAD: AtomicUsize = AtomicUsize::new(0);
+}
+
+pub struct TrackingAllocator {
+    allocator: std::alloc::System,
+}
+
+#[global_allocator]
+pub static GLOBAL_ALLOCATOR: TrackingAllocator = TrackingAllocator {
+    allocator: std::alloc::System,
+};
+
+#[allow(unsafe_code)]
+// SAFETY:
+// We just do book-keeping and then let another allocator do all the actual work.
+unsafe impl std::alloc::GlobalAlloc for TrackingAllocator {
+    #[allow(clippy::let_and_return)]
+    unsafe fn alloc(&self, layout: std::alloc::Layout) -> *mut u8 {
+        LIVE_BYTES_IN_THREAD.with(|bytes| bytes.fetch_add(layout.size(), Relaxed));
+
+        // SAFETY:
+        // Just deferring
+        unsafe { self.allocator.alloc(layout) }
+    }
+
+    unsafe fn dealloc(&self, ptr: *mut u8, layout: std::alloc::Layout) {
+        LIVE_BYTES_IN_THREAD.with(|bytes| bytes.fetch_sub(layout.size(), Relaxed));
+
+        // SAFETY:
+        // Just deferring
+        unsafe { self.allocator.dealloc(ptr, layout) };
+    }
+}
+
+fn live_bytes() -> usize {
+    LIVE_BYTES_IN_THREAD.with(|bytes| bytes.load(Relaxed))
+}
+
+/// Assumes all allocations are on the calling thread.
+///
+/// The reason we use thread-local counting is so that
+/// the counting won't be confused by any other running threads (e.g. other tests).
+fn memory_use(run: impl Fn() -> R) -> usize {
+    let used_bytes_start = live_bytes();
+    let ret = run();
+    let bytes_used = live_bytes() - used_bytes_start;
+    drop(ret);
+    bytes_used
+}
+
+// ----------------------------------------------------------------------------
+
+use re_data_store::{DataStore, DataStoreConfig};
+use re_log_types::{DataRow, RowId, TimePoint, TimeType, Timeline};
+use re_types::components::{InstanceKey, Scalar};
+use re_types_core::Loggable as _;
+
+/// The memory overhead of storing many scalars in the store.
+#[test]
+fn scalar_memory_overhead() {
+    re_log::setup_logging();
+
+    const NUM_SCALARS: usize = 1024 * 1024;
+
+    let total_mem_use = memory_use(|| {
+        let mut store = DataStore::new(
+            re_log_types::StoreId::random(re_log_types::StoreKind::Recording),
+            InstanceKey::name(),
+            DataStoreConfig::default(),
+        );
+
+        for i in 0..NUM_SCALARS {
+            let entity_path = re_log_types::entity_path!("scalar");
+            let timepoint =
+                TimePoint::default().with(Timeline::new("log_time", TimeType::Time), i as i64);
+            let num_instances = 1;
+            let row = DataRow::from_cells1_sized(
+                RowId::new(),
+                entity_path,
+                timepoint,
+                num_instances,
+                vec![Scalar(i as f64)],
+            )
+            .unwrap();
+            store.insert_row(&row).unwrap();
+        }
+
+        store
+    });
+
+    insta::assert_debug_snapshot!(
+        "scalars_on_one_timeline",
+        [
+            format!("{NUM_SCALARS} scalars"),
+            format!("{} in total", re_format::format_bytes(total_mem_use as _)),
+            format!(
+                "{} per row",
+                re_format::format_bytes(total_mem_use as f64 / NUM_SCALARS as f64)
+            ),
+        ]
+    );
+}
diff --git a/crates/re_data_store/tests/snapshots/memory_test__scalars_on_one_timeline.snap b/crates/re_data_store/tests/snapshots/memory_test__scalars_on_one_timeline.snap
new file mode 100644
index 000000000000..6ba35e5cf106
--- /dev/null
+++ b/crates/re_data_store/tests/snapshots/memory_test__scalars_on_one_timeline.snap
@@ -0,0 +1,10 @@
+---
+source: crates/re_data_store/tests/memory_test.rs
+assertion_line: 96
+expression: "[format!(\"{NUM_SCALARS} scalars\"),\n        format!(\"{} in total\", re_format::format_bytes(total_mem_use as _)),\n        format!(\"{} per row\",\n            re_format::format_bytes(total_mem_use as f64 / NUM_SCALARS as\n            f64))]"
+---
+[
+    "1048576 scalars",
+    "936 MiB in total",
+    "936 B per row",
+]
diff --git a/pixi.toml b/pixi.toml
index be6b61507499..bc76285745df 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -186,7 +186,7 @@ meilisearch = "meilisearch --db-path=./meilisearch/data.ms --dump-dir=./meilisea
 download-design-tokens = "curl --fail https://rerun-docs.netlify.app/api/tokens | jq > crates/re_ui/data/design_tokens.json"
 
 # Update the results of `insta` snapshot regression tests
-rs-update-insta-tests = "cargo test && cargo insta review"
+rs-update-insta-tests = "cargo test ; cargo insta review"
 
 # Upload image to gcloud storage.
 upload-image = "python scripts/upload_image.py"

From 711c3aaa4329f1267fa7abbc80db57d8f5ff5d51 Mon Sep 17 00:00:00 2001
From: Emil Ernerfeldt 
Date: Tue, 23 Apr 2024 10:21:39 +0200
Subject: [PATCH 343/508] Add lint against linking into `main` branch on GitHub
 (#6078)

### What
While investigating recently broken links (because of
https://github.com/rerun-io/rerun/pull/5966#issuecomment-2071633876) I
decided to add a lint against linking to stuff on changing branches
(e.g. `/blobs/main`).

Unfortunately I cannot cover it all (see
https://github.com/rerun-io/rerun/issues/6077 for more), but this is an
OK start.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6078?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6078?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6078)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
---
 BUILD.md                                      |  4 +--
 CHANGELOG.md                                  |  2 +-
 CMakeLists.txt                                |  2 +-
 README.md                                     | 10 +++---
 .../re_log_types/src/path/natural_ordering.rs |  2 +-
 crates/re_renderer/shader/colormap.wgsl       |  2 +-
 crates/re_renderer/src/colormap.rs            |  2 +-
 crates/re_types/tests/fuzzy.rs                |  8 ++---
 crates/re_viewer/src/ui/rerun_menu.rs         |  4 +--
 crates/rerun-cli/README.md                    | 10 +++---
 crates/rerun/README.md                        | 10 +++---
 docs/content/reference/about.md               |  2 +-
 examples/python/arflow/README.md              |  2 +-
 .../arkit_scenes/download_dataset.py          |  4 +--
 .../huggingface_pipeline.py                   |  2 +-
 .../detect_and_track_objects.py               |  4 +--
 examples/rust/objectron/src/main.rs           |  2 +-
 lychee.toml                                   |  1 +
 .../docs/templates/python/material/class.html |  2 +-
 .../templates/python/material/function.html   |  2 +-
 rerun_py/pyproject.toml                       |  2 +-
 rerun_py/src/arrow.rs                         |  2 +-
 scripts/lint.py                               | 35 +++++++++++++++++++
 23 files changed, 76 insertions(+), 40 deletions(-)

diff --git a/BUILD.md b/BUILD.md
index 331af5c97e41..382603a4abeb 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -102,8 +102,8 @@ pixi run cpp-build-all
 
 High-level documentation for rerun can be found at [http://rerun.io/docs](http://rerun.io/docs). It is built from the separate repository [rerun-docs](https://github.com/rerun-io/rerun-docs).
 
-- 🌊 [C++ API docs](https://ref.rerun.io/docs/cpp) are built with `doxygen` and hosted on GitHub. Use `pixi run cpp-docs` to build them locally. For details on the C++ doc-system, see [Writing Docs](https://github.com/rerun-io/rerun/blob/main/rerun_cpp/docs/writing_docs.md).
-- 🐍 [Python API docs](https://ref.rerun.io/docs/python) are built via `mkdocs` and hosted on GitHub. For details on the python doc-system, see [Writing Docs](https://github.com/rerun-io/rerun/blob/main/rerun_py/docs/writing_docs.md).
+- 🌊 [C++ API docs](https://ref.rerun.io/docs/cpp) are built with `doxygen` and hosted on GitHub. Use `pixi run cpp-docs` to build them locally. For details on the C++ doc-system, see [Writing Docs](rerun_cpp/docs/writing_docs.md).
+- 🐍 [Python API docs](https://ref.rerun.io/docs/python) are built via `mkdocs` and hosted on GitHub. For details on the python doc-system, see [Writing Docs](rerun_py/docs/writing_docs.md).
 - 🦀 [Rust API docs](https://docs.rs/rerun/) are hosted on  . You can build them locally with: `cargo doc --all-features --no-deps --open`.
 
 ## Building for the web
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2fc0c44c1a94..ecdcd1f4ba21 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -661,7 +661,7 @@ Check out our [migration guide](https://www.rerun.io/docs/reference/migration/mi
   - Much more powerful UI, allowing query ranges relative to time cursor
 - 🕸️ The viewer can now be easily embedded in your web apps via our [npm package](https://www.npmjs.com/package/@rerun-io/web-viewer)
 - 🐍 ⚠️ Legacy Python API now removed, check the [migration guide](https://github.com/rerun-io/rerun/issues/723) if you're not using `rr.log` yet
-- 🦀 The new `StoreSubscriber` trait allows to be notified of all changes in the datastore. This can be used to build custom indices and trigger systems, and serves as a foundation for upcoming performance improvements. Check out [our example](https://github.com/rerun-io/rerun/blob/main/examples/rust/custom_store_subscriber/README.md) for more information.
+- 🦀 The new `StoreSubscriber` trait allows to be notified of all changes in the datastore. This can be used to build custom indices and trigger systems, and serves as a foundation for upcoming performance improvements. Check out [our example](examples/rust/custom_store_subscriber/README.md) for more information.
 
 ⚠️ Known issues on Visual Time Range:
 - Time cursor [sometimes stops scrolling correctly](https://github.com/rerun-io/rerun/issues/4246) on plot window
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c9918f250cdb..0b1ebab184f8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -138,7 +138,7 @@ message(STATUS "Rerun version ${RERUN_VERSION}")
 # Loguru logging library (https://github.com/emilk/loguru):
 set(CMAKE_DL_LIBS "dl") # Required by Loguru for backtraces
 
-# Loguru, see https://github.com/emilk/loguru/blob/master/loguru_cmake_example/CMakeLists.txt
+# Loguru, see https://github.com/emilk/loguru/blob/4adaa185883e3c04da25913579c451d3c32cfac1/loguru_cmake_example/CMakeLists.txt
 include(FetchContent)
 FetchContent_Declare(LoguruGitRepo
     GIT_REPOSITORY "https://github.com/emilk/loguru" # can be a filesystem path
diff --git a/README.md b/README.md
index 258507526f84..85f2879e051d 100644
--- a/README.md
+++ b/README.md
@@ -5,11 +5,11 @@
 

- PyPi - crates.io - MIT - Apache - Rerun Discord + PyPi + crates.io + MIT + Apache + Rerun Discord

# Build time aware visualizations of multimodal data diff --git a/crates/re_log_types/src/path/natural_ordering.rs b/crates/re_log_types/src/path/natural_ordering.rs index 205ef3c608f9..f0f33b2a3195 100644 --- a/crates/re_log_types/src/path/natural_ordering.rs +++ b/crates/re_log_types/src/path/natural_ordering.rs @@ -1,7 +1,7 @@ //! Implement natural ordering for strings, so that "file5" < "file10". //! //! Crates considered: -//! * `human-sort`: - overflows on large integers +//! * `human-sort`: - overflows on large integers //! * `lexical-sort`: - comes with a huge unicode->ascii table //! * `natord`: - the one we're using diff --git a/crates/re_renderer/shader/colormap.wgsl b/crates/re_renderer/shader/colormap.wgsl index 68f34e44c350..003076893d70 100644 --- a/crates/re_renderer/shader/colormap.wgsl +++ b/crates/re_renderer/shader/colormap.wgsl @@ -86,7 +86,7 @@ fn colormap_turbo_srgb(t: f32) -> vec3f { // - use nested horner representation for polynomials // - polynomials were fitted to minimize maximum error (as opposed to least squares) // -// Data fitted from https://github.com/BIDS/colormap/blob/master/colormaps.py (CC0). +// Data fitted from https://github.com/BIDS/colormap/blob/bc549477db0c12b54a5928087552ad2cf274980f/colormaps.py (CC0). /// Returns a gamma-space sRGB in 0-1 range. /// This is a polynomial approximation from Viridis color map, assuming `t` is diff --git a/crates/re_renderer/src/colormap.rs b/crates/re_renderer/src/colormap.rs index ace54dd94d72..cb09679df988 100644 --- a/crates/re_renderer/src/colormap.rs +++ b/crates/re_renderer/src/colormap.rs @@ -112,7 +112,7 @@ pub fn colormap_turbo_srgb(t: f32) -> [u8; 4] { // - use nested horner representation for polynomials // - polynomials were fitted to minimize maximum error (as opposed to least squares) // -// Data fitted from https://github.com/BIDS/colormap/blob/master/colormaps.py (CC0). +// Data fitted from https://github.com/BIDS/colormap/blob/bc549477db0c12b54a5928087552ad2cf274980f/colormaps.py (CC0). /// Returns sRGB polynomial approximation from Viridis color map, assuming `t` is normalized. pub fn colormap_viridis_srgb(t: f32) -> [u8; 4] { diff --git a/crates/re_types/tests/fuzzy.rs b/crates/re_types/tests/fuzzy.rs index 3f9c9a6867b5..71ac1435d5d4 100644 --- a/crates/re_types/tests/fuzzy.rs +++ b/crates/re_types/tests/fuzzy.rs @@ -264,7 +264,7 @@ fn roundtrip() { // eprintln!("array = {array:#?}"); if field.name == "rerun.testing.components.AffixFuzzer21" { // TODO(jleibs): Fields that contain Float16 apparently don't supported fmt - // https://github.com/jorgecarleitao/arrow2/blob/main/src/array/primitive/fmt.rs#L35 + // https://github.com/rerun-io/re_arrow2/blob/33a32000001df800e4840d92c33b03e7007311e1/src/array/primitive/fmt.rs#L39 eprintln!("{} = Can't be printed (float16 not supported)", field.name); } else { eprintln!("{} = {array:#?}", field.name); @@ -326,7 +326,7 @@ fn roundtrip() { // eprintln!("array = {array:#?}"); if field.name == "rerun.testing.components.AffixFuzzer21" { // TODO(jleibs): Fields that contain Float16 apparently don't supported fmt - // https://github.com/jorgecarleitao/arrow2/blob/main/src/array/primitive/fmt.rs#L35 + // https://github.com/rerun-io/re_arrow2/blob/33a32000001df800e4840d92c33b03e7007311e1/src/array/primitive/fmt.rs#L39 eprintln!("{} = Can't be printed (float16 not supported)", field.name); } else { eprintln!("{} = {array:#?}", field.name); @@ -380,7 +380,7 @@ fn roundtrip() { // eprintln!("array = {array:#?}"); if field.name == "rerun.testing.components.AffixFuzzer21" { // TODO(jleibs): Fields that contain Float16 apparently don't supported fmt - // https://github.com/jorgecarleitao/arrow2/blob/main/src/array/primitive/fmt.rs#L35 + // https://github.com/rerun-io/re_arrow2/blob/33a32000001df800e4840d92c33b03e7007311e1/src/array/primitive/fmt.rs#L39 eprintln!("{} = Can't be printed (float16 not supported)", field.name); } else { eprintln!("{} = {array:#?}", field.name); @@ -433,7 +433,7 @@ fn roundtrip() { // eprintln!("array = {array:#?}"); if field.name == "rerun.testing.components.AffixFuzzer21" { // TODO(jleibs): Fields that contain Float16 apparently don't supported fmt - // https://github.com/jorgecarleitao/arrow2/blob/main/src/array/primitive/fmt.rs#L35 + // https://github.com/rerun-io/re_arrow2/blob/33a32000001df800e4840d92c33b03e7007311e1/src/array/primitive/fmt.rs#L39 eprintln!("{} = Can't be printed (float16 not supported)", field.name); } else { eprintln!("{} = {array:#?}", field.name); diff --git a/crates/re_viewer/src/ui/rerun_menu.rs b/crates/re_viewer/src/ui/rerun_menu.rs index e9270b132751..dc0575c886a2 100644 --- a/crates/re_viewer/src/ui/rerun_menu.rs +++ b/crates/re_viewer/src/ui/rerun_menu.rs @@ -503,7 +503,7 @@ fn debug_menu_options_ui( } if ui.button("SEGFAULT").clicked() { - // Taken from https://github.com/EmbarkStudios/crash-handling/blob/main/sadness-generator/src/lib.rs + // Taken from https://github.com/EmbarkStudios/crash-handling/blob/065f3dd9c1c318630e539375165cf74961b44bcc/sadness-generator/src/lib.rs /// This is the fixed address used to generate a segfault. It's possible that /// this address can be mapped and writable by the your process in which case a @@ -522,7 +522,7 @@ fn debug_menu_options_ui( } if ui.button("Stack overflow").clicked() { - // Taken from https://github.com/EmbarkStudios/crash-handling/blob/main/sadness-generator/src/lib.rs + // Taken from https://github.com/EmbarkStudios/crash-handling/blob/065f3dd9c1c318630e539375165cf74961b44bcc/sadness-generator/src/lib.rs fn recurse(data: u64) -> u64 { let mut buff = [0u8; 256]; buff[..9].copy_from_slice(b"junk data"); diff --git a/crates/rerun-cli/README.md b/crates/rerun-cli/README.md index a05eadaa39ef..bc26b4659ee0 100644 --- a/crates/rerun-cli/README.md +++ b/crates/rerun-cli/README.md @@ -5,11 +5,11 @@

- Latest version - Documentation - MIT - Apache - Rerun Discord + Latest version + Documentation + MIT + Apache + Rerun Discord

## Rerun command-line tool diff --git a/crates/rerun/README.md b/crates/rerun/README.md index fbcf092ab448..ce27bba93f94 100644 --- a/crates/rerun/README.md +++ b/crates/rerun/README.md @@ -5,11 +5,11 @@

- Latest version - Documentation - MIT - Apache - Rerun Discord + Latest version + Documentation + MIT + Apache + Rerun Discord

# Rerun Rust logging SDK diff --git a/docs/content/reference/about.md b/docs/content/reference/about.md index 8c3c0abb073f..96e6c7619217 100644 --- a/docs/content/reference/about.md +++ b/docs/content/reference/about.md @@ -8,7 +8,7 @@ To learn more about Rerun, the company, visit our Website at [https://www.rerun. Code & License -------------- The Rerun SDK & Viewer are open source, all code is available on [GitHub](https://github.com/rerun-io/rerun/) and open for contributions. -Licensing is permissive, the project is dual licensed under [MIT](https://github.com/rerun-io/rerun/blob/latest/LICENSE-MIT) & [Apache 2.0](https://github.com/rerun-io/rerun/blob/latest/LICENSE-APACHE). +Licensing is permissive, the project is dual licensed under [MIT](https://github.com/rerun-io/rerun/blob/main/LICENSE-MIT) & [Apache 2.0](https://github.com/rerun-io/rerun/blob/main/LICENSE-APACHE). Under the hood diff --git a/examples/python/arflow/README.md b/examples/python/arflow/README.md index a9be17a4c53f..51e52e0abf83 100644 --- a/examples/python/arflow/README.md +++ b/examples/python/arflow/README.md @@ -26,7 +26,7 @@ Watch our demo video: ## Get started -Please check our [project repo](https://github.com/cake-lab/ARFlow/blob/main/README.md), and refer to the individual [server](https://github.com/cake-lab/ARFlow/blob/main/python/README.md) and [client](https://github.com/cake-lab/ARFlow/blob/main/unity/README.md) installation guides. +Please see [the original project repo](https://github.com/cake-lab/ARFlow/blob/main/README.md), and refer to the individual [server](https://github.com/cake-lab/ARFlow/blob/main/python/README.md) and [client](https://github.com/cake-lab/ARFlow/blob/main/unity/README.md) installation guides. ## Citation diff --git a/examples/python/arkit_scenes/arkit_scenes/download_dataset.py b/examples/python/arkit_scenes/arkit_scenes/download_dataset.py index b9e1c9d2889e..2ed6ca7797d5 100644 --- a/examples/python/arkit_scenes/arkit_scenes/download_dataset.py +++ b/examples/python/arkit_scenes/arkit_scenes/download_dataset.py @@ -1,5 +1,5 @@ -# Copied from https://github.com/apple/ARKitScenes/blob/main/download_data.py -# Licensing information: https://github.com/apple/ARKitScenes/blob/main/LICENSE +# Copied from https://github.com/apple/ARKitScenes/blob/9ec0b99c3cd55e29fc0724e1229e2e6c2909ab45/download_data.py +# Licensing information: https://github.com/apple/ARKitScenes/blob/9ec0b99c3cd55e29fc0724e1229e2e6c2909ab45/LICENSE from __future__ import annotations import math diff --git a/examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py b/examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py index 9928f4843ff0..bf1f82ede0f6 100644 --- a/examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py +++ b/examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py @@ -708,7 +708,7 @@ def __call__( plain tuple. cross_attention_kwargs (`dict`, *optional*): A kwargs dictionary that if specified is passed along to the [`AttentionProcessor`] as defined in - [`self.processor`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/attention_processor.py). + [`self.processor`](https://github.com/huggingface/diffusers/blob/fc9fecc217e58d72c0d5796575c72088251ff4df/src/diffusers/models/attention_processor.py). clip_skip (`int`, *optional*): Number of layers to be skipped from CLIP while computing the prompt embeddings. A value of 1 means that the output of the pre-final layer will be used for computing the prompt embeddings. diff --git a/examples/python/detect_and_track_objects/detect_and_track_objects.py b/examples/python/detect_and_track_objects/detect_and_track_objects.py index 5eca234340c1..6ebb9d2e7789 100755 --- a/examples/python/detect_and_track_objects/detect_and_track_objects.py +++ b/examples/python/detect_and_track_objects/detect_and_track_objects.py @@ -35,8 +35,8 @@ CACHE_DIR: Final = EXAMPLE_DIR / "cache" # panoptic_coco_categories.json comes from: -# https://github.com/cocodataset/panopticapi/blob/master/panoptic_coco_categories.json -# License: https://github.com/cocodataset/panopticapi/blob/master/license.txt +# https://github.com/cocodataset/panopticapi/blob/7bb4655548f98f3fedc07bf37e9040a992b054b0/panoptic_coco_categories.json +# License: https://github.com/cocodataset/panopticapi/blob/7bb4655548f98f3fedc07bf37e9040a992b054b0/license.txt COCO_CATEGORIES_PATH = EXAMPLE_DIR / "panoptic_coco_categories.json" DOWNSCALE_FACTOR = 2 diff --git a/examples/rust/objectron/src/main.rs b/examples/rust/objectron/src/main.rs index 678b70db72d2..587af1314c98 100644 --- a/examples/rust/objectron/src/main.rs +++ b/examples/rust/objectron/src/main.rs @@ -153,7 +153,7 @@ fn log_ar_camera( // input (1920x1440); we need to convert between the two. // See: // - https://github.com/google-research-datasets/Objectron/issues/39 - // - https://github.com/google-research-datasets/Objectron/blob/master/notebooks/objectron-3dprojection-hub-tutorial.ipynb + // - https://github.com/google-research-datasets/Objectron/blob/c06a65165a18396e1e00091981fd1652875c97b5/notebooks/objectron-3dprojection-hub-tutorial.ipynb // swap px/py use glam::Vec3Swizzles as _; intrinsics.z_axis = intrinsics.z_axis.yxz(); diff --git a/lychee.toml b/lychee.toml index 3611d82bbe7e..0d396e251977 100644 --- a/lychee.toml +++ b/lychee.toml @@ -50,6 +50,7 @@ exclude_path = [ "venv", # Actually ignored files beyond .gitignore + "scripts/lint.py", # Contains url-matching regexes that aren't actual urls "scripts/screenshot_compare/assets/templates/", ] diff --git a/rerun_py/docs/templates/python/material/class.html b/rerun_py/docs/templates/python/material/class.html index a4408aa91bae..eca79046777e 100644 --- a/rerun_py/docs/templates/python/material/class.html +++ b/rerun_py/docs/templates/python/material/class.html @@ -1,5 +1,5 @@ {# Very minimally patched from: -https://github.com/mkdocstrings/python/blob/master/src/mkdocstrings_handlers/python/templates/material/_base/class.html +https://github.com/mkdocstrings/python/blob/b0123719ae90cb2d47e9b923166ac69fdce86632/src/mkdocstrings_handlers/python/templates/material/_base/class.html See: CHANGE comments below #} diff --git a/rerun_py/docs/templates/python/material/function.html b/rerun_py/docs/templates/python/material/function.html index f1dd1ed0e6bb..dabfa64bfafb 100644 --- a/rerun_py/docs/templates/python/material/function.html +++ b/rerun_py/docs/templates/python/material/function.html @@ -1,5 +1,5 @@ {# Very minimally patched from: -https://github.com/mkdocstrings/python/blob/master/src/mkdocstrings_handlers/python/templates/material/_base/function.html +https://github.com/mkdocstrings/python/blob/b0123719ae90cb2d47e9b923166ac69fdce86632/src/mkdocstrings_handlers/python/templates/material/_base/function.html See: CHANGE comments below #} diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index bdf5f80725d2..422270d6347f 100644 --- a/rerun_py/pyproject.toml +++ b/rerun_py/pyproject.toml @@ -70,7 +70,7 @@ extend-exclude = [ # generated "examples/python/objectron/objectron/proto/objectron/proto.py", - # Copied from https://github.com/huggingface/diffusers/blob/main/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_depth2img.py + # Copied from https://github.com/huggingface/diffusers/blob/fc9fecc217e58d72c0d5796575c72088251ff4df/src/diffusers/pipelines/stable_diffusion/pipeline_stable_diffusion_depth2img.py "examples/python/depth_guided_stable_diffusion/depth_guided_stable_diffusion/huggingface_pipeline.py", # Copied from https://github.com/colmap/colmap/blob/bf3e19140f491c3042bfd85b7192ef7d249808ec/scripts/python/read_write_model.py diff --git a/rerun_py/src/arrow.rs b/rerun_py/src/arrow.rs index 52d818402c86..a305cb856e33 100644 --- a/rerun_py/src/arrow.rs +++ b/rerun_py/src/arrow.rs @@ -28,7 +28,7 @@ fn array_to_rust(arrow_array: &PyAny, name: Option<&str>) -> PyResult<(Box str | None: return None +def lint_url(url: str) -> str | None: + ALLOW_LIST_URLS = { + "https://github.com/lycheeverse/lychee/blob/master/lychee.example.toml", + "https://github.com/rerun-io/documentation/blob/main/src/utils/tokens.ts", + "https://github.com/rerun-io/rerun/blob/main/ARCHITECTURE.md", + "https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md", + "https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md", + "https://github.com/rerun-io/rerun/blob/main/LICENSE-APACHE", + "https://github.com/rerun-io/rerun/blob/main/LICENSE-MIT", + } + + if url in ALLOW_LIST_URLS: + return + + if m := re.match(r"https://github.com/.*/blob/(\w+)/.*", url): + branch = m.group(1) + if branch in ("main", "master", "trunk", "latest"): + if "#L" in url: + return f"Do not link directly to a file:line on '{branch}' - it may change! Use a perma-link instead (commit hash or tag). Url: {url}" + + if "/README.md" in url: + pass # Probably fine + elif url.startswith("https://github.com/rerun-io/rerun/blob/"): + pass # TODO(#6077): figure out how we best link to our own code from our docs + else: + return f"Do not link directly to a file on '{branch}' - it may disappear! Use a commit hash or tag instead. Url: {url}" + + return None + + def lint_line( line: str, prev_line: str | None, file_extension: str = "rs", is_in_docstring: bool = False ) -> str | None: @@ -116,6 +146,11 @@ def lint_line( if m := double_word.search(line): return f"Found double word: '{m.group(0)}'" + if m := re.search(r'https?://[^ )"]+', line): + url = m.group(0) + if err := lint_url(url): + return err + if file_extension not in ("txt"): if ( ellipsis.search(line) From b9eb600ec2bb8270d97d09367130057185a6ac36 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 23 Apr 2024 12:37:23 +0200 Subject: [PATCH 344/508] Fix links to Python examples (#6080) Co-authored-by: Clement Rey --- BUILD.md | 2 +- crates/re_space_view_spatial/benches/bench_points.rs | 2 +- crates/re_space_view_spatial/src/heuristics.rs | 2 +- docs/content/getting-started/data-in/open-any-file.md | 2 +- examples/python/blueprint_stocks/README.md | 6 +++--- examples/python/controlnet/controlnet.py | 5 ----- examples/python/dicom_mri/dicom_mri.py | 9 +-------- examples/python/dna/dna.py | 6 +----- examples/python/llm_embedding_ner/llm_embedding_ner.py | 9 +-------- examples/python/log_file/log_file.py | 5 ----- examples/python/nv12/nv12.py | 10 +--------- examples/python/objectron/objectron/__main__.py | 6 +----- examples/python/plots/plots.py | 2 +- examples/python/raw_mesh/raw_mesh/__main__.py | 10 +--------- examples/python/rrt_star/rrt_star.py | 6 ------ .../segment_anything_model/segment_anything_model.py | 9 --------- .../signed_distance_fields/__main__.py | 6 ------ examples/python/template/template.py | 10 +--------- examples/rust/objectron/src/main.rs | 2 +- examples/rust/raw_mesh/src/main.rs | 2 +- rerun_py/README.md | 4 ++-- tests/python/test_api/test_api.py | 4 ++-- 22 files changed, 21 insertions(+), 98 deletions(-) diff --git a/BUILD.md b/BUILD.md index 382603a4abeb..ced1a8583098 100644 --- a/BUILD.md +++ b/BUILD.md @@ -59,7 +59,7 @@ Additionally, nightly dev wheels from head of `main` are available at 0.0 { - scene_size * 0.02 // Works pretty well for `examples/python/open_photogrammetry_format/main.py --no-frames` + scene_size * 0.02 // Works pretty well for `examples/python/open_photogrammetry_format/open_photogrammetry_format.py --no-frames` } else { // This value somewhat arbitrary. In almost all cases where the scene has defined bounds // the heuristic will change it or it will be user edited. In the case of non-defined bounds diff --git a/docs/content/getting-started/data-in/open-any-file.md b/docs/content/getting-started/data-in/open-any-file.md index fc3df08913ec..0051c7e220cf 100644 --- a/docs/content/getting-started/data-in/open-any-file.md +++ b/docs/content/getting-started/data-in/open-any-file.md @@ -27,7 +27,7 @@ With the exception of `rrd` files that can be streamed from an HTTP URL (e.g. `r ## Logging file contents from the SDK -To log the contents of a file from the SDK you can use the `log_file_from_path` and `log_file_from_contents` methods ([C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a8f253422a7adc2a19b89d1538c05bcac), [Python](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.log_file_from_path), [Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path)) and the associated examples ([C++](https://github.com/rerun-io/rerun/blob/main/examples/cpp/log_file/main.cpp), [Python](https://github.com/rerun-io/rerun/blob/main/examples/python/log_file/main.py), [Rust](https://github.com/rerun-io/rerun/blob/main/examples/rust/log_file/src/main.rs)). +To log the contents of a file from the SDK you can use the `log_file_from_path` and `log_file_from_contents` methods ([C++](https://ref.rerun.io/docs/cpp/stable/classrerun_1_1RecordingStream.html#a8f253422a7adc2a19b89d1538c05bcac), [Python](https://ref.rerun.io/docs/python/stable/common/other_classes_and_functions/#rerun.log_file_from_path), [Rust](https://docs.rs/rerun/latest/rerun/struct.RecordingStream.html#method.log_file_from_path)) and the associated examples ([C++](https://github.com/rerun-io/rerun/blob/main/examples/cpp/log_file/main.cpp), [Python](https://github.com/rerun-io/rerun/blob/main/examples/python/log_file/log_file.py), [Rust](https://github.com/rerun-io/rerun/blob/main/examples/rust/log_file/src/main.rs)). Note: when calling these APIs from the SDK, the data will be loaded by the process running the SDK, not the Viewer! diff --git a/examples/python/blueprint_stocks/README.md b/examples/python/blueprint_stocks/README.md index 094026f4572d..c20690e5a170 100644 --- a/examples/python/blueprint_stocks/README.md +++ b/examples/python/blueprint_stocks/README.md @@ -18,14 +18,14 @@ We show how Rerun blueprints can then be used to present many different views of ```bash -pip install -r examples/python/blueprint_stocks/requirements.txt -python examples/python/blueprint_stocks/blueprint_main.py +pip install -e examples/python/blueprint_stocks +python -m blueprint_stocks ``` The different blueprints can be explored using the `--blueprint` flag. For example: ``` -python examples/python/blueprint_stocks/main.py --blueprint=one-stock +python -m blueprint_stocks --blueprint=one-stock ``` Available choices are: diff --git a/examples/python/controlnet/controlnet.py b/examples/python/controlnet/controlnet.py index 72406f356d1e..49c716ca2bd6 100755 --- a/examples/python/controlnet/controlnet.py +++ b/examples/python/controlnet/controlnet.py @@ -3,11 +3,6 @@ Example running ControlNet conditioned on Canny edges. Based on https://huggingface.co/docs/diffusers/using-diffusers/controlnet. - -Run -```sh -examples/python/controlnet/main.py -``` """ from __future__ import annotations diff --git a/examples/python/dicom_mri/dicom_mri.py b/examples/python/dicom_mri/dicom_mri.py index bf59ff311462..afd552fe8ba7 100755 --- a/examples/python/dicom_mri/dicom_mri.py +++ b/examples/python/dicom_mri/dicom_mri.py @@ -1,12 +1,5 @@ #!/usr/bin/env python3 -""" -Example using MRI scan data in the DICOM format. - -Run: -``` sh -python3 examples/python/dicom/main.py -``` -""" +"""Example using MRI scan data in the DICOM format.""" from __future__ import annotations diff --git a/examples/python/dna/dna.py b/examples/python/dna/dna.py index 8cacc502ba3f..b0d71e7d9a78 100755 --- a/examples/python/dna/dna.py +++ b/examples/python/dna/dna.py @@ -1,9 +1,5 @@ #!/usr/bin/env python3 -""" -The example from our Getting Started page. - -`examples/python/dna/main.py` -""" +"""The example from our Getting Started page.""" from __future__ import annotations diff --git a/examples/python/llm_embedding_ner/llm_embedding_ner.py b/examples/python/llm_embedding_ner/llm_embedding_ner.py index dab018fe1f77..d5aca76eb207 100755 --- a/examples/python/llm_embedding_ner/llm_embedding_ner.py +++ b/examples/python/llm_embedding_ner/llm_embedding_ner.py @@ -1,12 +1,5 @@ #!/usr/bin/env python3 -""" -Example running BERT-based named entity recognition (NER). - -Run -```sh -examples/python/llm_embedding_ner/main.py -``` -""" +"""Example running BERT-based named entity recognition (NER).""" from __future__ import annotations diff --git a/examples/python/log_file/log_file.py b/examples/python/log_file/log_file.py index 799182dee957..bc301ff7092f 100755 --- a/examples/python/log_file/log_file.py +++ b/examples/python/log_file/log_file.py @@ -3,11 +3,6 @@ Demonstrates how to log any file from the SDK using the `DataLoader` machinery. See for more information. - -Usage: -``` -python examples/python/log_file/main.py -- examples/assets -``` """ from __future__ import annotations diff --git a/examples/python/nv12/nv12.py b/examples/python/nv12/nv12.py index d841edd7ab9e..700413c403af 100755 --- a/examples/python/nv12/nv12.py +++ b/examples/python/nv12/nv12.py @@ -1,13 +1,5 @@ #!/usr/bin/env python3 -""" -Stream NV12 images from a webcam. - -Run: -```sh -pip install -r examples/python/nv12/requirements.txt -python examples/python/nv12/main.py -``` -""" +"""Stream NV12 images from a webcam.""" from __future__ import annotations diff --git a/examples/python/objectron/objectron/__main__.py b/examples/python/objectron/objectron/__main__.py index 1788cc98621f..360f7a64c7db 100755 --- a/examples/python/objectron/objectron/__main__.py +++ b/examples/python/objectron/objectron/__main__.py @@ -1,9 +1,5 @@ #!/usr/bin/env python3 -""" -Example of using the Rerun SDK to log the Objectron dataset. - -Example: `examples/python/objectron/main.py --recording chair` -""" +"""Example of using the Rerun SDK to log the Objectron dataset.""" from __future__ import annotations diff --git a/examples/python/plots/plots.py b/examples/python/plots/plots.py index 7aff7e7881f0..44ebb72d2f24 100755 --- a/examples/python/plots/plots.py +++ b/examples/python/plots/plots.py @@ -4,7 +4,7 @@ Run: ```sh -./examples/python/plot/main.py +./examples/python/plot/plots.py ``` """ diff --git a/examples/python/raw_mesh/raw_mesh/__main__.py b/examples/python/raw_mesh/raw_mesh/__main__.py index 83cae41c0d85..819b9d8dcbea 100755 --- a/examples/python/raw_mesh/raw_mesh/__main__.py +++ b/examples/python/raw_mesh/raw_mesh/__main__.py @@ -1,13 +1,5 @@ #!/usr/bin/env python3 -""" -Shows how to use the Rerun SDK to log raw 3D meshes (so-called "triangle soups") and their transform hierarchy. - -Run: -```sh -# assuming your virtual env is up -examples/python/raw_mesh/main.py -``` -""" +"""Shows how to use the Rerun SDK to log raw 3D meshes (so-called "triangle soups") and their transform hierarchy.""" from __future__ import annotations diff --git a/examples/python/rrt_star/rrt_star.py b/examples/python/rrt_star/rrt_star.py index 36a90e6158b2..fd7a56afa5c9 100755 --- a/examples/python/rrt_star/rrt_star.py +++ b/examples/python/rrt_star/rrt_star.py @@ -10,12 +10,6 @@ A more detailed explanation can be found in the original paper Karaman, S. Frazzoli, S. 2011. "Sampling-based algorithms for optimal motion planning". or in the following medium article: https://theclassytim.medium.com/robotic-path-planning-rrt-and-rrt-212319121378 - -Run: -```bash -pip install -r examples/python/rrt-star/requirements.txt -python examples/python/rrt-star/main.py -``` """ from __future__ import annotations diff --git a/examples/python/segment_anything_model/segment_anything_model.py b/examples/python/segment_anything_model/segment_anything_model.py index 24fe3eed4e7c..ea3cc91ae384 100755 --- a/examples/python/segment_anything_model/segment_anything_model.py +++ b/examples/python/segment_anything_model/segment_anything_model.py @@ -4,15 +4,6 @@ Can be used to test mask-generation on one or more images. Images can be local file-paths or remote urls. - -Exa: -``` -# Run on a remote image: -python main.py https://raw.githubusercontent.com/facebookresearch/segment-anything/main/notebooks/images/dog.jpg - -# Use cuda and a different model on a local image -python main.py --device cuda --model vit_h /path/to/my_image.jpg -``` """ from __future__ import annotations diff --git a/examples/python/signed_distance_fields/signed_distance_fields/__main__.py b/examples/python/signed_distance_fields/signed_distance_fields/__main__.py index 74b35ffb3efa..abb9ccb5041d 100755 --- a/examples/python/signed_distance_fields/signed_distance_fields/__main__.py +++ b/examples/python/signed_distance_fields/signed_distance_fields/__main__.py @@ -18,12 +18,6 @@ month = {June}, year = {2019} } - -Run: -```sh -# assuming your virtual env is up -examples/python/signed_distance_fields/main.py -``` """ from __future__ import annotations diff --git a/examples/python/template/template.py b/examples/python/template/template.py index 856d490b18bc..906dc7be3283 100755 --- a/examples/python/template/template.py +++ b/examples/python/template/template.py @@ -1,13 +1,5 @@ #!/usr/bin/env python3 -""" -Example template. - -Run: -```sh -pip install -r examples/python/template/requirements.txt -python examples/python/template/main.py -``` -""" +"""Example template.""" from __future__ import annotations diff --git a/examples/rust/objectron/src/main.rs b/examples/rust/objectron/src/main.rs index 587af1314c98..18be9a07c6ac 100644 --- a/examples/rust/objectron/src/main.rs +++ b/examples/rust/objectron/src/main.rs @@ -324,7 +324,7 @@ fn run(rec: &rerun::RecordingStream, args: &Args) -> anyhow::Result<()> { format!( "Could not read the recording, have you downloaded the dataset? \ Try running the python version first to download it automatically \ - (`examples/python/objectron/main.py --recording {}`).", + (`python -m objectron --recording {}`).", args.recording.to_possible_value().unwrap().get_name(), ) })?; diff --git a/examples/rust/raw_mesh/src/main.rs b/examples/rust/raw_mesh/src/main.rs index d5781de96501..c4de7719e0b2 100644 --- a/examples/rust/raw_mesh/src/main.rs +++ b/examples/rust/raw_mesh/src/main.rs @@ -148,7 +148,7 @@ impl Args { anyhow::bail!( "Could not load the scene, have you downloaded the dataset? \ Try running the python version first to download it automatically \ - (`examples/python/raw_mesh/main.py --scene {scene_name}`).", + (`python -m raw_mesh --scene {scene_name}`).", ) } diff --git a/rerun_py/README.md b/rerun_py/README.md index c3ffb5cbb727..0601a0a4b36d 100644 --- a/rerun_py/README.md +++ b/rerun_py/README.md @@ -49,7 +49,7 @@ python3 -m rerun In a second terminal, run the example with the `--connect` option: ```sh -python3 examples/python/plots/main.py --connect +python3 examples/python/plots/plots.py --connect ``` Note that SDK and Viewer can run on different machines! @@ -63,7 +63,7 @@ pixi run py-build --release ``` To build SDK & viewer for python (or `pixi run py-build` for a debug build) and install it in the pixi environment. -You can then run examples from the repository, either by making the pixi shell active with `pixi shell` and then running python or by using `pixi run`, e.g. `pixi run python examples/python/minimal/main.py`. +You can then run examples from the repository, either by making the pixi shell active with `pixi shell` and then running python or by using `pixi run`, e.g. `pixi run python examples/python/minimal/minimal.py`. Respectively, to build a wheel instead for manual install use: ```sh diff --git a/tests/python/test_api/test_api.py b/tests/python/test_api/test_api.py index b71755817ad9..e94dc68f98ef 100755 --- a/tests/python/test_api/test_api.py +++ b/tests/python/test_api/test_api.py @@ -5,8 +5,8 @@ It uses a lot of different aspects of the Rerun API in order to test it. Example usage: -* Run all tests: `examples/python/test_api/main.py` -* Run specific test: `examples/python/test_api/main.py --test rects` +* Run all tests: `examples/python/test_api/test_api.py` +* Run specific test: `examples/python/test_api/test_api.py --test rects` """ from __future__ import annotations From f2ee289e6616cff33d3c36ba5bd4c4e9d1d3ac0a Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 23 Apr 2024 13:38:40 +0200 Subject: [PATCH 345/508] Support shared library building on Windows (#6053) Developers tend to have strong opinions on shared libraries, that become even stronger when they see the effort required to get shared libraries to work on Windows. However, C++ binary package managers (such as conda/pixi/conda-forge) tend to use shared libraries also on Windows, so it would be convenient to be able to compile C++ bindings of rerun as shared libraries on Windows. This PR does add support for compiling the rerun-cpp library as a shared library on Windows. The PR is a bit invasive, so feel free to reject it if you think the maintenance effort is not worth the benefit. Why all the complexity? In a nutshell, Linux and macOS by default export all the symbols contained in a shared library. Instead, Windows does not support that, and require the developers that want to export the symbols to either annotate every class/attribute/method that needs to be visible, or pass the attributes with a `.def` file. As this tend to be cumbersome, CMake has implemented the `WINDOWS_EXPORT_ALL_SYMBOLS` property, that emulates the "export all symbols" behavior of Linux/macOS also on Windows. However, it does not support static variables. So for libraries that do use static variables, can just use `WINDOWS_EXPORT_ALL_SYMBOLS` and they are good to go. However, if static variables are used (as in the case of rerun) it is necessary to annotate every static variable with the appropriate storage-class attribute. The easiest way to do so is use GenerateExportHeader module to generate a rerun_sdk_export.hpp header file that define the RERUN_SDK_EXPORT macro, and add that macro to all static variables. As RERUN_SDK_EXPORT is added in the C++ source code, we need to make sure that this macro is also defined in Linux/macOS builds, so the use of generate_export_header is present even if MSVC AND BUILD_SHARED_LIBS is OFF. This annotation process is a bit cumbersome in rerun case, as it needs to be done in all codegen logic that generate `static const` attributes. ### What ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6053?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6053?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6053) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Andreas Reich --- .github/workflows/contrib_checks.yml | 12 +- .github/workflows/contrib_rerun_py.yml | 58 +- .github/workflows/cpp_matrix_partial.json | 11 - .github/workflows/nightly.yml | 2 +- .github/workflows/on_pull_request.yml | 14 +- .github/workflows/on_push_docs.yml | 4 +- .github/workflows/on_push_main.yml | 2 +- .github/workflows/reusable_checks.yml | 3 +- .github/workflows/reusable_checks_cpp.yml | 30 +- .github/workflows/reusable_checks_rust.yml | 5 - CMakeLists.txt | 20 + pixi.lock | 609 +++++++----------- pixi.toml | 37 +- rerun_cpp/CMakeLists.txt | 24 + rerun_cpp/src/rerun/archetypes/clear.hpp | 5 +- rerun_cpp/src/rerun/archetypes/clear_ext.cpp | 9 +- .../src/rerun/archetypes/transform3d.hpp | 3 +- .../src/rerun/archetypes/transform3d_ext.cpp | 7 +- .../src/rerun/archetypes/view_coordinates.hpp | 121 ++-- .../rerun/archetypes/view_coordinates_ext.cpp | 125 ++-- rerun_cpp/src/rerun/components/resolution.hpp | 3 +- .../src/rerun/components/resolution_ext.cpp | 7 +- rerun_cpp/src/rerun/components/rotation3d.hpp | 3 +- .../src/rerun/components/rotation3d_ext.cpp | 7 +- .../src/rerun/components/text_log_level.hpp | 13 +- .../rerun/components/text_log_level_ext.cpp | 17 +- .../src/rerun/components/view_coordinates.hpp | 121 ++-- .../rerun/components/view_coordinates_ext.cpp | 125 ++-- rerun_cpp/src/rerun/datatypes/mat3x3.hpp | 1 + rerun_cpp/src/rerun/datatypes/mat3x3_ext.cpp | 1 + rerun_cpp/src/rerun/datatypes/mat4x4.hpp | 3 +- rerun_cpp/src/rerun/datatypes/mat4x4_ext.cpp | 3 +- rerun_cpp/src/rerun/datatypes/quaternion.hpp | 3 +- .../src/rerun/datatypes/quaternion_ext.cpp | 7 +- rerun_cpp/src/rerun/datatypes/rotation3d.hpp | 3 +- .../src/rerun/datatypes/rotation3d_ext.cpp | 7 +- .../datatypes/translation_and_mat3x3.hpp | 3 +- .../datatypes/translation_and_mat3x3_ext.cpp | 7 +- .../translation_rotation_scale3d.hpp | 3 +- .../translation_rotation_scale3d_ext.cpp | 3 +- rerun_cpp/src/rerun/rerun_sdk_export.hpp | 25 + rerun_cpp/tests/CMakeLists.txt | 12 + scripts/generate_view_coordinate_defs.py | 6 +- 43 files changed, 724 insertions(+), 760 deletions(-) delete mode 100644 .github/workflows/cpp_matrix_partial.json create mode 100644 rerun_cpp/src/rerun/rerun_sdk_export.hpp diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 1133e8441d34..999a85e098af 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -24,12 +24,8 @@ env: RUSTDOCFLAGS: --deny warnings - # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. - # See: https://github.com/marketplace/actions/sccache-action - SCCACHE_GHA_ENABLED: "false" - - # Wrap every `rustc` invocation in `sccache`. - RUSTC_WRAPPER: "sccache" + # Do *not* use sscache since on contributor ci we don't have access to the gcloud stored cache. + #RUSTC_WRAPPER: "sccache" # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all # these incremental artifacts when running on CI. @@ -103,6 +99,10 @@ jobs: steps: - uses: actions/checkout@v4 + - uses: prefix-dev/setup-pixi@v0.5.2 + with: + pixi-version: v0.19.1 + - name: Rust checks & tests run: pixi run rs-check --skip-check-individual-crates diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index e0315daf75aa..42ac3002a308 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -28,12 +28,8 @@ env: RUSTDOCFLAGS: --deny warnings - # Disable the GHA backend (Github's 10GB storage) since we use our own GCS backend. - # See: https://github.com/marketplace/actions/sccache-action - SCCACHE_GHA_ENABLED: "false" - - # Wrap every `rustc` invocation in `sccache`. - RUSTC_WRAPPER: "sccache" + # Do *not* use sscache since on contributor ci we don't have access to the gcloud stored cache. + #RUSTC_WRAPPER: "sccache" # Not only `sccache` cannot cache incremental builds, it's counter-productive to generate all # these incremental artifacts when running on CI. @@ -60,41 +56,8 @@ jobs: pixi-version: v0.19.1 environments: wheel-test - - name: Build Wheel - uses: PyO3/maturin-action@v1 - with: - maturin-version: "1.5.1" - manylinux: manylinux_2_31 - container: off - command: build - args: | - --manifest-path rerun_py/Cargo.toml - --release - --target x86_64-unknown-linux-gnu - ${{ inputs.MATURIN_FEATURE_FLAGS }} - --out dist - - - name: Get version - id: get-version - run: | - echo "wheel_version=$(python3 scripts/ci/crates.py get-version)" >> "$GITHUB_OUTPUT" - - - name: Install built wheel - # Now install the wheel using a specific version and --no-index to guarantee we get the version from - # the pre-dist folder. Note we don't use --force-reinstall here because --no-index means it wouldn't - # find the dependencies to reinstall them. - run: | - pixi run -e wheel-test pip uninstall rerun-sdk - pixi run -e wheel-test pip install rerun-sdk==${{ steps.get-version.outputs.wheel_version }} --no-index --find-links dist - - - name: Print wheel version - run: | - pixi run -e wheel-test python -m rerun --version - pixi run -e wheel-test which rerun - pixi run -e wheel-test rerun --version - - name: Run Python unit-tests - run: pixi run -e wheel-test cd rerun_py/tests && pixi run -e wheel-test pytest -c ../pyproject.toml + run: pixi run -e wheel-test py-test - name: Run e2e test run: pixi run -e wheel-test RUST_LOG=debug scripts/run_python_e2e_test.py --no-build # rerun-sdk is already built and installed @@ -112,18 +75,3 @@ jobs: # --no-py-build because rerun-sdk is already built and installed run: | pixi run -e wheel-test RUST_LOG=debug docs/snippets/compare_snippet_output.py --release --target x86_64-unknown-linux-gnu --no-py-build - - - name: Cache RRD dataset - id: dataset - uses: actions/cache@v4 - with: - path: examples/python/structure_from_motion/dataset/ - # TODO(jleibs): Derive this key from the invocation below - key: structure-from-motion-dataset-structure-from-motion-fiat-v1 - - - name: Generate Embedded RRD file - # If you change the line below you should almost definitely change the `key:` line above by giving it a new, unique name - run: | - mkdir rrd - pip install -r examples/python/structure_from_motion/requirements.txt - pixi run -e wheel-test python examples/python/structure_from_motion/main.py --dataset colmap_fiat --resize 800x600 --save rrd/colmap_fiat.rrd diff --git a/.github/workflows/cpp_matrix_partial.json b/.github/workflows/cpp_matrix_partial.json deleted file mode 100644 index 4b15fdccbef5..000000000000 --- a/.github/workflows/cpp_matrix_partial.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "include": [ - { - "name": "Linux x64", - "runs_on": "ubuntu-latest-16-cores", - "cache_key": "build-linux", - "extra_env_vars": "", - "additional_commands": "pixi run cpp-docs" - } - ] -} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index a0181aaba6c3..1ee26528925b 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -24,7 +24,7 @@ jobs: uses: ./.github/workflows/reusable_checks_cpp.yml with: CONCURRENCY: nightly - FULL: "true" + CHANNEL: nightly secrets: inherit checks-rust: diff --git a/.github/workflows/on_pull_request.yml b/.github/workflows/on_pull_request.yml index 6bfcfbde3af0..20faf39bb98d 100644 --- a/.github/workflows/on_pull_request.yml +++ b/.github/workflows/on_pull_request.yml @@ -1,7 +1,8 @@ # Jobs that only run for developers on the `rerun` team. -# - We have to ensure that these jobs _only_ run for PRs inside the `rerun-io` organization -# this is done using the following check, added to every job: +# We have to ensure that these jobs _only_ run for PRs inside the `rerun-io` organization +# this is done using the following check, added to every job: # if: github.event.pull_request.head.repo.owner.login == 'rerun-io' +# (unfortunately this does not work on the trigger or the entire `jobs` category) name: Pull-Request @@ -22,6 +23,7 @@ jobs: secrets: inherit cpp-paths-filter: + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' runs-on: ubuntu-latest outputs: cpp_changes: ${{ steps.filter.outputs.cpp_changes }} @@ -44,6 +46,7 @@ jobs: - '**/*cmake' docs-paths-filter: + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' runs-on: ubuntu-latest outputs: docs_changes: ${{ steps.filter.outputs.docs_changes }} @@ -65,6 +68,7 @@ jobs: - 'examples/manifest.toml' python-paths-filter: + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' runs-on: ubuntu-latest outputs: python_changes: ${{ steps.filter.outputs.python_changes }} @@ -86,6 +90,7 @@ jobs: - '**/pyproject.toml' rust-paths-filter: + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' runs-on: ubuntu-latest outputs: rust_changes: ${{ steps.filter.outputs.rust_changes }} @@ -107,6 +112,7 @@ jobs: - "**/*.toml" web-paths-filter: + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' runs-on: ubuntu-latest outputs: web_changes: ${{ steps.filter.outputs.web_changes }} @@ -158,7 +164,7 @@ jobs: uses: ./.github/workflows/reusable_checks_cpp.yml with: CONCURRENCY: pr-${{ github.event.pull_request.number }} - FULL: "true" + CHANNEL: pr secrets: inherit min-cli-build: @@ -247,7 +253,7 @@ jobs: deploy-landing-preview: name: "Deploy Landing Preview" - if: needs.docs-paths-filter.outputs.docs_changes == 'true' + if: github.event.pull_request.head.repo.owner.login == 'rerun-io' && needs.docs-paths-filter.outputs.docs_changes == 'true' needs: docs-paths-filter uses: ./.github/workflows/reusable_deploy_landing_preview.yml with: diff --git a/.github/workflows/on_push_docs.yml b/.github/workflows/on_push_docs.yml index 1cd366f97487..1c0b7b7ad1bf 100644 --- a/.github/workflows/on_push_docs.yml +++ b/.github/workflows/on_push_docs.yml @@ -32,7 +32,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.5.2 with: - pixi-version: v0.19.0 + pixi-version: v0.19.1 - name: Get version id: versioning @@ -57,7 +57,7 @@ jobs: - uses: prefix-dev/setup-pixi@v0.5.2 with: - pixi-version: v0.19.0 + pixi-version: v0.19.1 - name: Install rerun-sdk run: | diff --git a/.github/workflows/on_push_main.yml b/.github/workflows/on_push_main.yml index 182819f96026..f6fe00b95eec 100644 --- a/.github/workflows/on_push_main.yml +++ b/.github/workflows/on_push_main.yml @@ -26,7 +26,7 @@ jobs: uses: ./.github/workflows/reusable_checks_cpp.yml with: CONCURRENCY: push-${{ github.ref_name }}-${{ inputs.CONCURRENCY }} - FULL: "true" + CHANNEL: main secrets: inherit rust_checks: diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index a11048cbea01..cc9fc9c2e55e 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -89,8 +89,7 @@ jobs: pixi-version: v0.19.1 - name: Codegen check - run: | - pixi run codegen --force --check + run: pixi run codegen --force --check # --------------------------------------------------------------------------- diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index 15f50dc00aec..3756ce1a5997 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -6,12 +6,9 @@ on: CONCURRENCY: required: true type: string - FULL: - # Booleans are almost unusable - # See https://medium.com/@sohail.ra5/github-actions-passing-boolean-input-variables-to-reusable-workflow-call-42d39bf7342e - type: string - required: true - default: "true" + CHANNEL: + required: false + type: string # enum: 'nightly', 'main', or 'pr' workflow_dispatch: inputs: @@ -19,12 +16,9 @@ on: required: false type: string default: "adhoc" - FULL: - description: "If false only linux is tested" - type: choice - options: - - "true" - - "false" + CHANNEL: + required: false + type: string # enum: 'nightly', 'main', or 'pr' concurrency: group: ${{ inputs.CONCURRENCY }}-checks_cpp @@ -59,13 +53,7 @@ jobs: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - name: Load C++ test matrix id: set-matrix - run: | - echo "Full matrix: ${{ inputs.FULL }}" - if ${{ inputs.FULL }}; then - echo "matrix=$(jq -c . < ./.github/workflows/cpp_matrix_full.json)" >> $GITHUB_OUTPUT - else - echo "matrix=$(jq -c . < ./.github/workflows/cpp_matrix_partial.json)" >> $GITHUB_OUTPUT - fi + run: echo "matrix=$(jq -c . < ./.github/workflows/cpp_matrix_full.json)" >> $GITHUB_OUTPUT cpp-tests: name: C++ build & test - ${{ matrix.name }} @@ -109,6 +97,10 @@ jobs: - name: pixi run cpp-test run: ${{ matrix.extra_env_vars }} RERUN_WERROR=ON pixi run cpp-test + - name: pixi run cpp-build-all-shared-libs + if: ${{ inputs.CHANNEL == 'nightly' }} + run: ${{ matrix.extra_env_vars }} RERUN_WERROR=ON pixi run cpp-build-all-shared-libs + - name: additional_commands run: ${{ matrix.additional_commands }} diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 188923916fbe..36f2d32099ae 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -65,11 +65,6 @@ jobs: with: pixi-version: v0.19.1 - # We need to build the web viewer for `rust_checks.py` to succeed. - # We build in release so that we can reuse the results for actual publishing, if necessary - - name: Build web-viewer (release) - run: pixi run rerun-build-web-release - - name: Rust checks & tests if: ${{ inputs.CHANNEL == 'pr' }} run: pixi run rs-check --skip-check-individual-crates --skip-wasm-checks --skip-test diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b1ebab184f8..03cd2d0dab0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,14 @@ function(rerun_strict_warning_settings target) # TODO(andreas): Try to enable /Wall target_compile_options(${target} PRIVATE /W4) + if(BUILD_SHARED_LIBS) + # If we are building as shared libs, we are going to have to disable the C4251 + # warning, as it would trigger for any datatype derived from a STL class + # See also https://github.com/protocolbuffers/protobuf/blob/v26.1/cmake/README.md#notes-on-compiler-warnings + # We need also to make it public, otherwise downstream code will be flooded by c4251 warnings + target_compile_options(${target} PUBLIC /wd4251) + endif() + # CMAKE_COMPILE_WARNING_AS_ERROR is only directly supported starting in CMake `3.24` # https://cmake.org/cmake/help/latest/prop_tgt/COMPILE_WARNING_AS_ERROR.html if(CMAKE_COMPILE_WARNING_AS_ERROR) @@ -144,8 +152,20 @@ FetchContent_Declare(LoguruGitRepo GIT_REPOSITORY "https://github.com/emilk/loguru" # can be a filesystem path GIT_TAG "master" ) + +# Loguru does not support being build with BUILD_SHARED_LIBS=ON on Windows +# so we always compile it with BUILD_SHARED_LIBS=OFF on Windows +if(MSVC AND BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS_RERUN_SDK ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS OFF) +endif() + FetchContent_MakeAvailable(LoguruGitRepo) # defines target 'loguru::loguru' +if(MSVC AND BUILD_SHARED_LIBS_RERUN_SDK) + set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_RERUN_SDK}) +endif() + # Set any loguru compile-time flags before calling MakeAvailable() # Stacktraces are not yet supported on Windows. if(NOT WIN32) diff --git a/pixi.lock b/pixi.lock index f3f5cbecd6b4..817d6b830c71 100644 --- a/pixi.lock +++ b/pixi.lock @@ -119,6 +119,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda + - 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.0.5-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda @@ -314,6 +315,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - 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-2.1.5-py311hc8f2f60_0.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.0.5-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda @@ -497,6 +499,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-tools-16.0.6-hbedff68_3.conda - 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-2.1.5-py311he705e18_0.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.0.5-py311h5547dcb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda @@ -678,6 +681,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-tools-16.0.6-haab561b_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda + - 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/multidict-6.0.5-py311he2be06e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda @@ -834,6 +838,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.0.0-h66d3029_49657.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.0.5-py311ha68e1ae_0.conda @@ -2550,6 +2555,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.2.13-hd590300_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.9.4-hcb278e6_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.5-py311h459d7ec_0.conda + - 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.0.5-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.8.0-py311h459d7ec_0.conda @@ -2745,6 +2751,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/libzlib-1.2.13-h31becfc_5.conda - 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-2.1.5-py311hc8f2f60_0.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.0.5-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/mypy-1.8.0-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda @@ -2917,6 +2924,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-18.1.3-hb6ac08f_0.conda - 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-2.1.5-py311he705e18_0.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.0.5-py311h5547dcb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/mypy-1.8.0-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda @@ -3086,6 +3094,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-18.1.3-hcd81f8e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/lz4-c-1.9.4-hb7217d7_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/markupsafe-2.1.5-py311h05b510d_0.conda + - 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/multidict-6.0.5-py311he2be06e_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.8.0-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.0.0-pyha770c72_0.conda @@ -3246,6 +3255,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-gmp-6.1.0-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/m2w64-libwinpthread-git-5.0.0.4634.697f757-2.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.5-py311ha68e1ae_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mkl-2024.1.0-h66d3029_692.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.0.5-py311ha68e1ae_0.conda @@ -7096,8 +7106,8 @@ packages: - kind: pypi name: black version: 24.4.0 - url: https://files.pythonhosted.org/packages/cb/95/4a02a0fed559bf638001f6bf4e4c9d685111db959d221485e7e27c91e954/black-24.4.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8e5537f456a22cf5cfcb2707803431d2feeb82ab3748ade280d6ccd0b40ed2e8 + url: https://files.pythonhosted.org/packages/97/a6/f5857f79bba7eca05ebdc7e27e3447e3d2fc23898bb04f34bf3ff5dfb2db/black-24.4.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 64e60a7edd71fd542a10a9643bf369bfd2644de95ec71e86790b063aa02ff745 requires_dist: - click >=8.0.0 - mypy-extensions >=0.4.3 @@ -7116,8 +7126,8 @@ packages: - kind: pypi name: black version: 24.4.0 - url: https://files.pythonhosted.org/packages/0f/11/fa05ac9429d971d0fc10da85f24dafc3fa5788733fbd0d1c186b7577cefd/black-24.4.0-cp311-cp311-win_amd64.whl - sha256: 64578cf99b6b46a6301bc28bdb89f9d6f9b592b1c5837818a177c98525dbe397 + url: https://files.pythonhosted.org/packages/cb/95/4a02a0fed559bf638001f6bf4e4c9d685111db959d221485e7e27c91e954/black-24.4.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 8e5537f456a22cf5cfcb2707803431d2feeb82ab3748ade280d6ccd0b40ed2e8 requires_dist: - click >=8.0.0 - mypy-extensions >=0.4.3 @@ -7136,8 +7146,8 @@ packages: - kind: pypi name: black version: 24.4.0 - url: https://files.pythonhosted.org/packages/97/a6/f5857f79bba7eca05ebdc7e27e3447e3d2fc23898bb04f34bf3ff5dfb2db/black-24.4.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 64e60a7edd71fd542a10a9643bf369bfd2644de95ec71e86790b063aa02ff745 + url: https://files.pythonhosted.org/packages/0f/11/fa05ac9429d971d0fc10da85f24dafc3fa5788733fbd0d1c186b7577cefd/black-24.4.0-cp311-cp311-win_amd64.whl + sha256: 64578cf99b6b46a6301bc28bdb89f9d6f9b592b1c5837818a177c98525dbe397 requires_dist: - click >=8.0.0 - mypy-extensions >=0.4.3 @@ -7882,16 +7892,16 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 + url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' @@ -7906,16 +7916,16 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba requires_dist: - pycparser requires_python: '>=3.8' @@ -7928,26 +7938,26 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' - kind: conda name: charset-normalizer @@ -9161,8 +9171,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 + url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 requires_dist: - numpy >=1.20 - furo ; extra == 'docs' @@ -9185,8 +9195,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl - sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 + url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 requires_dist: - numpy >=1.20 - furo ; extra == 'docs' @@ -9209,8 +9219,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 + url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl + sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 requires_dist: - numpy >=1.20 - furo ; extra == 'docs' @@ -9249,8 +9259,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -9277,8 +9287,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d + url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -9333,8 +9343,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 + url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -9361,8 +9371,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 + url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -9389,8 +9399,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl - sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b + url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl + sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -9417,8 +9427,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl - sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c + url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl + sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b requires_dist: - cffi >=1.12 - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' @@ -10021,8 +10031,8 @@ packages: - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/84/51/8203a3e6e475e6766ac950638d42f45470f36c6a4f0615ff0a1c1f2ed0d6/fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8ac27f436e8af7779f0bb4d5425aa3535270494d3bc5459ed27de3f03151e4c2 + url: https://files.pythonhosted.org/packages/33/47/f2ca671af61757eaaac608963dda5b76ec9100621e45d0fd63a153fd8cd7/fonttools-4.51.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: a8feca65bab31479d795b0d16c9a9852902e3a3c0630678efb0b2b7941ea9c74 requires_dist: - fs <3, >=2.2.0 ; extra == 'all' - lxml >=4.0 ; extra == 'all' @@ -10058,8 +10068,8 @@ packages: - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/c5/d4/f426fa1ca42e47bcfff0c878fa9d49d9c03379d00903a7c178f95b97867a/fonttools-4.51.0-cp311-cp311-win_amd64.whl - sha256: 0f08c901d3866a8905363619e3741c33f0a83a680d92a9f0e575985c2634fcc1 + url: https://files.pythonhosted.org/packages/84/51/8203a3e6e475e6766ac950638d42f45470f36c6a4f0615ff0a1c1f2ed0d6/fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 8ac27f436e8af7779f0bb4d5425aa3535270494d3bc5459ed27de3f03151e4c2 requires_dist: - fs <3, >=2.2.0 ; extra == 'all' - lxml >=4.0 ; extra == 'all' @@ -10095,8 +10105,8 @@ packages: - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/33/47/f2ca671af61757eaaac608963dda5b76ec9100621e45d0fd63a153fd8cd7/fonttools-4.51.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: a8feca65bab31479d795b0d16c9a9852902e3a3c0630678efb0b2b7941ea9c74 + url: https://files.pythonhosted.org/packages/c5/d4/f426fa1ca42e47bcfff0c878fa9d49d9c03379d00903a7c178f95b97867a/fonttools-4.51.0-cp311-cp311-win_amd64.whl + sha256: 0f08c901d3866a8905363619e3741c33f0a83a680d92a9f0e575985c2634fcc1 requires_dist: - fs <3, >=2.2.0 ; extra == 'all' - lxml >=4.0 ; extra == 'all' @@ -10785,16 +10795,16 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -10809,16 +10819,16 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -11526,24 +11536,24 @@ packages: - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90 + url: https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl - sha256: 6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355 + url: https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797 + url: https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl + sha256: 6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' @@ -20085,20 +20095,20 @@ packages: - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/13/97/4aac09bdfc1bc35f8eb64e21ff5897224a788170e5e8cab3e62c9eb78efb/llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf + url: https://files.pythonhosted.org/packages/ba/3a/286d01191e62ddbe645d4a3f1e0d96106a98d3fd7f82441d20ffe93ab669/llvmlite-0.42.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 81e674c2fe85576e6c4474e8c7e7aba7901ac0196e864fe7985492b737dbab65 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/f3/bd/3b27a1c8bbbe01b053f5e0c9ca9a37dbc3e39282dfcf596d143ad389f156/llvmlite-0.42.0-cp311-cp311-win_amd64.whl - sha256: 7e0c4c11c8c2aa9b0701f91b799cb9134a6a6de51444eff5a9087fc7c1384275 + url: https://files.pythonhosted.org/packages/13/97/4aac09bdfc1bc35f8eb64e21ff5897224a788170e5e8cab3e62c9eb78efb/llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/ba/3a/286d01191e62ddbe645d4a3f1e0d96106a98d3fd7f82441d20ffe93ab669/llvmlite-0.42.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 81e674c2fe85576e6c4474e8c7e7aba7901ac0196e864fe7985492b737dbab65 + url: https://files.pythonhosted.org/packages/f3/bd/3b27a1c8bbbe01b053f5e0c9ca9a37dbc3e39282dfcf596d143ad389f156/llvmlite-0.42.0-cp311-cp311-win_amd64.whl + sha256: 7e0c4c11c8c2aa9b0701f91b799cb9134a6a6de51444eff5a9087fc7c1384275 requires_python: '>=3.9' - kind: pypi name: log-file @@ -20123,8 +20133,8 @@ packages: - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/95/4c/fc5e63fb41e867f530a70519e1bcab0c14e84a95aa659f697bc97531be96/lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe + url: https://files.pythonhosted.org/packages/43/43/66a84c2a034f5df2782240cb2f68696a72ad6734d7a91f824e0360cde08b/lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl + sha256: 70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867 requires_dist: - cssselect >=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -20135,8 +20145,8 @@ packages: - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/df/c5/8b05e69685b48cf11b596fbdd466f76cb3c1e3efe0361d8be0edb9df0325/lxml-5.2.1-cp311-cp311-win_amd64.whl - sha256: 5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102 + url: https://files.pythonhosted.org/packages/95/4c/fc5e63fb41e867f530a70519e1bcab0c14e84a95aa659f697bc97531be96/lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe requires_dist: - cssselect >=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -20147,8 +20157,8 @@ packages: - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/43/43/66a84c2a034f5df2782240cb2f68696a72ad6734d7a91f824e0360cde08b/lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl - sha256: 70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867 + url: https://files.pythonhosted.org/packages/df/c5/8b05e69685b48cf11b596fbdd466f76cb3c1e3efe0361d8be0edb9df0325/lxml-5.2.1-cp311-cp311-win_amd64.whl + sha256: 5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102 requires_dist: - cssselect >=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -20316,20 +20326,20 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 + url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl - sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 + url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f + url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl + sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 requires_python: '>=3.7' - kind: conda name: markupsafe @@ -20471,8 +20481,8 @@ packages: - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/36/11/62250ea25780d4b59c2c6044ec161235c47cc05a18d0ec0a05657de75b7d/matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661 + url: https://files.pythonhosted.org/packages/14/60/12d4f27b859a74359306662da69c2d08826a2b05cfe7f96e66b490f41573/matplotlib-3.8.4-cp311-cp311-macosx_11_0_arm64.whl + sha256: 232ce322bfd020a434caaffbd9a95333f7c2491e59cfc014041d95e38ab90d1c requires_dist: - contourpy >=1.0.1 - cycler >=0.10 @@ -20488,8 +20498,8 @@ packages: - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/2d/d5/6227732ecab9165586966ccb54301e3164f61b470c954c4cf6940654fbe1/matplotlib-3.8.4-cp311-cp311-win_amd64.whl - sha256: 8080d5081a86e690d7688ffa542532e87f224c38a6ed71f8fbed34dd1d9fedae + url: https://files.pythonhosted.org/packages/36/11/62250ea25780d4b59c2c6044ec161235c47cc05a18d0ec0a05657de75b7d/matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661 requires_dist: - contourpy >=1.0.1 - cycler >=0.10 @@ -20505,8 +20515,8 @@ packages: - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/14/60/12d4f27b859a74359306662da69c2d08826a2b05cfe7f96e66b490f41573/matplotlib-3.8.4-cp311-cp311-macosx_11_0_arm64.whl - sha256: 232ce322bfd020a434caaffbd9a95333f7c2491e59cfc014041d95e38ab90d1c + url: https://files.pythonhosted.org/packages/2d/d5/6227732ecab9165586966ccb54301e3164f61b470c954c4cf6940654fbe1/matplotlib-3.8.4-cp311-cp311-win_amd64.whl + sha256: 8080d5081a86e690d7688ffa542532e87f224c38a6ed71f8fbed34dd1d9fedae requires_dist: - contourpy >=1.0.1 - cycler >=0.10 @@ -20536,30 +20546,9 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/maturin@1.5.1 + - pkg:pypi/maturin size: 5883670 timestamp: 1711053175449 -- kind: conda - name: maturin - version: 1.5.1 - build: py311h24bb903_0 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/maturin-1.5.1-py311h24bb903_0.conda - sha256: 52f9e9e54d36ef40cd5c2fa171613750ee56d722e5ac718e5d71d5e4696e559c - md5: 0ffabfb12f4fbb545781a385744ae75a - depends: - - openssl >=3.2.1,<4.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - constrains: - - __osx >=10.12 - license: MIT - license_family: MIT - purls: - - pkg:pypi/maturin@1.5.1 - size: 4746594 - timestamp: 1711043864724 - kind: conda name: maturin version: 1.5.1 @@ -20581,26 +20570,6 @@ packages: - pkg:pypi/maturin size: 4746594 timestamp: 1711043864724 -- kind: conda - name: maturin - version: 1.5.1 - build: py311h63ff55d_0 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/maturin-1.5.1-py311h63ff55d_0.conda - sha256: c16ac56fb748e39ae52387395f98c79d031b15d763c1877226bfe8b970690fdb - md5: b988008c60e0ffda52e533668a298c6f - depends: - - libgcc-ng >=12 - - openssl >=3.2.1,<4.0a0 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/maturin@1.5.1 - size: 5875793 - timestamp: 1711042912603 - kind: conda name: maturin version: 1.5.1 @@ -20621,28 +20590,6 @@ packages: - pkg:pypi/maturin size: 5875793 timestamp: 1711042912603 -- kind: conda - name: maturin - version: 1.5.1 - build: py311h71175c2_0 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/maturin-1.5.1-py311h71175c2_0.conda - sha256: 5e508cb34bf0f2cfc1f06635d3cceefbe679d3fb81ce64d7d2dc0b4bf8af4584 - md5: 50560d0477396cebcaffc864bad10e42 - depends: - - openssl >=3.2.1,<4.0a0 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - constrains: - - __osx >=11.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/maturin@1.5.1 - size: 4579808 - timestamp: 1711043620752 - kind: conda name: maturin version: 1.5.1 @@ -20682,34 +20629,14 @@ packages: license: MIT license_family: MIT purls: - - pkg:pypi/maturin@1.5.1 - size: 4498445 - timestamp: 1711044494832 -- kind: conda - name: maturin - version: 1.5.1 - build: py311h9a9e57f_0 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/maturin-1.5.1-py311h9a9e57f_0.conda - sha256: 5307c7955e2a4da23b6a593c715edd8b9e2abe802c1056a225e757ef35eb3356 - md5: 9eeaf6831c4f0a721385e2e9d10c52a7 - depends: - - m2w64-gcc-libs - - m2w64-gcc-libs-core - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - tomli >=1.1.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/maturin + - pkg:pypi/maturin size: 4498445 timestamp: 1711044494832 - kind: pypi name: mediapipe version: 0.10.9 - url: https://files.pythonhosted.org/packages/c1/71/38b16b1e4504ff92dff875d455c19e62125fccd73d5ce7e06b560f77fd26/mediapipe-0.10.9-cp311-cp311-macosx_11_0_x86_64.whl - sha256: b7dde54b82732479b9b856c9230b9f7b3da55b0913dde5254a7489e20c2e3c6e + url: https://files.pythonhosted.org/packages/a3/3a/f309c6bdebe596cc8c960542e167331cb01ef130ec38f3da46a499718889/mediapipe-0.10.9-cp311-cp311-macosx_11_0_universal2.whl + sha256: 8733735f582e6e6a05bf9b15c48b03a6387a0795793a2530aa1189eecfd33780 requires_dist: - absl-py - attrs >=19.1.0 @@ -20722,8 +20649,8 @@ packages: - kind: pypi name: mediapipe version: 0.10.9 - url: https://files.pythonhosted.org/packages/a3/3a/f309c6bdebe596cc8c960542e167331cb01ef130ec38f3da46a499718889/mediapipe-0.10.9-cp311-cp311-macosx_11_0_universal2.whl - sha256: 8733735f582e6e6a05bf9b15c48b03a6387a0795793a2530aa1189eecfd33780 + url: https://files.pythonhosted.org/packages/c1/71/38b16b1e4504ff92dff875d455c19e62125fccd73d5ce7e06b560f77fd26/mediapipe-0.10.9-cp311-cp311-macosx_11_0_x86_64.whl + sha256: b7dde54b82732479b9b856c9230b9f7b3da55b0913dde5254a7489e20c2e3c6e requires_dist: - absl-py - attrs >=19.1.0 @@ -20923,20 +20850,20 @@ packages: - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e + url: https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: 612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl - sha256: 2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea + url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: 612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd + url: https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl + sha256: 2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea requires_python: '>=3.7' - kind: conda name: multidict @@ -21632,8 +21559,8 @@ packages: - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/5f/2d/085c21f3086eff0b830e5d03d084a1b4b10dfde0c65feeac6be8c361265c/numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051 + url: https://files.pythonhosted.org/packages/70/7d/0d1419479997319ca72ef735791c2ee50819f9c200adea96142ee7499fae/numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: 411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966 requires_dist: - llvmlite <0.43, >=0.42.0.dev0 - numpy <1.27, >=1.22 @@ -21641,8 +21568,8 @@ packages: - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/38/f0/ad848815b0adafcf5f238e728933950034355a8d59969772be1cd57606d8/numba-0.59.1-cp311-cp311-win_amd64.whl - sha256: 0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450 + url: https://files.pythonhosted.org/packages/5f/2d/085c21f3086eff0b830e5d03d084a1b4b10dfde0c65feeac6be8c361265c/numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051 requires_dist: - llvmlite <0.43, >=0.42.0.dev0 - numpy <1.27, >=1.22 @@ -21650,8 +21577,8 @@ packages: - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/70/7d/0d1419479997319ca72ef735791c2ee50819f9c200adea96142ee7499fae/numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: 411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966 + url: https://files.pythonhosted.org/packages/38/f0/ad848815b0adafcf5f238e728933950034355a8d59969772be1cd57606d8/numba-0.59.1-cp311-cp311-win_amd64.whl + sha256: 0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450 requires_dist: - llvmlite <0.43, >=0.42.0.dev0 - numpy <1.27, >=1.22 @@ -21665,20 +21592,20 @@ packages: - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71 + url: https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl + sha256: edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef requires_python: '>=3.9' - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl - sha256: cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2 + url: https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71 requires_python: '>=3.9' - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl - sha256: edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef + url: https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl + sha256: cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2 requires_python: '>=3.9' - kind: conda name: numpy @@ -21938,8 +21865,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/16/07/bf25df600eeaedddf8fece3f1ff837bf72865b93a03651cf7375ce8172be/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl - sha256: 86078d3653ec3107877536c9178622b1f98b51acf59e554ddbc552785cba55fa + url: https://files.pythonhosted.org/packages/4c/c3/ccff2e1bfe2bb47a7eaebc4280e93bd2f97ebbe5b3573d48bcfcc0c32387/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl + sha256: b52e381144f774b486729ccee69911bdc7d16b5ced4830502e906ad803373ab0 requires_dist: - numpy >=1.13.3 ; python_version < '3.7' - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -21955,8 +21882,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/aa/2e/576ac47f21d555b459ca837bb3fb937e50339b8fbfd294945ea2f5290416/opencv_contrib_python-4.9.0.80-cp37-abi3-win_amd64.whl - sha256: fdd9b14028f74af8dbb69f90e6e4a956ce2eb5b59947df28ba0b79d337431477 + url: https://files.pythonhosted.org/packages/16/07/bf25df600eeaedddf8fece3f1ff837bf72865b93a03651cf7375ce8172be/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl + sha256: 86078d3653ec3107877536c9178622b1f98b51acf59e554ddbc552785cba55fa requires_dist: - numpy >=1.13.3 ; python_version < '3.7' - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -21972,8 +21899,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/4c/c3/ccff2e1bfe2bb47a7eaebc4280e93bd2f97ebbe5b3573d48bcfcc0c32387/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - sha256: b52e381144f774b486729ccee69911bdc7d16b5ced4830502e906ad803373ab0 + url: https://files.pythonhosted.org/packages/aa/2e/576ac47f21d555b459ca837bb3fb937e50339b8fbfd294945ea2f5290416/opencv_contrib_python-4.9.0.80-cp37-abi3-win_amd64.whl + sha256: fdd9b14028f74af8dbb69f90e6e4a956ce2eb5b59947df28ba0b79d337431477 requires_dist: - numpy >=1.13.3 ; python_version < '3.7' - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -21989,8 +21916,8 @@ packages: - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a + url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl + sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3 requires_dist: - numpy >=1.13.3 ; python_version < '3.7' - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -22006,8 +21933,8 @@ packages: - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl - sha256: 3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0 + url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57 requires_dist: - numpy >=1.13.3 ; python_version < '3.7' - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -22040,8 +21967,8 @@ packages: - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57 + url: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a requires_dist: - numpy >=1.13.3 ; python_version < '3.7' - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -22057,8 +21984,8 @@ packages: - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3 + url: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl + sha256: 3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0 requires_dist: - numpy >=1.13.3 ; python_version < '3.7' - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -22675,8 +22602,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 + url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 requires_dist: - numpy >=1.22.4 ; python_version < '3.11' - numpy >=1.23.2 ; python_version == '3.11' @@ -22767,8 +22694,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl - sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 + url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 requires_dist: - numpy >=1.22.4 ; python_version < '3.11' - numpy >=1.23.2 ; python_version == '3.11' @@ -22859,8 +22786,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 + url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl + sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 requires_dist: - numpy >=1.22.4 ; python_version < '3.11' - numpy >=1.23.2 ; python_version == '3.11' @@ -22977,8 +22904,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23001,8 +22928,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23049,8 +22976,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23073,8 +23000,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23097,8 +23024,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd + url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23121,8 +23048,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 + url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23173,8 +23100,8 @@ packages: - kind: pypi name: pillow version: 10.3.0 - url: https://files.pythonhosted.org/packages/e5/51/e4b35e394b4e5ca24983e50361a1db3d7da05b1758074f9c4f5b4be4b22a/pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795 + url: https://files.pythonhosted.org/packages/00/5c/7633f291def20082bad31b844fe5ed07742aae8504e4cfe2f331ee727178/pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23201,8 +23128,8 @@ packages: - kind: pypi name: pillow version: 10.3.0 - url: https://files.pythonhosted.org/packages/0a/16/c83877524c47976f16703d2e05c363244bc1e60ab439e078b3cd046d07db/pillow-10.3.0-cp311-cp311-win_amd64.whl - sha256: 8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d + url: https://files.pythonhosted.org/packages/e5/51/e4b35e394b4e5ca24983e50361a1db3d7da05b1758074f9c4f5b4be4b22a/pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23229,8 +23156,8 @@ packages: - kind: pypi name: pillow version: 10.3.0 - url: https://files.pythonhosted.org/packages/00/5c/7633f291def20082bad31b844fe5ed07742aae8504e4cfe2f331ee727178/pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57 + url: https://files.pythonhosted.org/packages/0a/16/c83877524c47976f16703d2e05c363244bc1e60ab439e078b3cd046d07db/pillow-10.3.0-cp311-cp311-win_amd64.whl + sha256: 8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -23281,25 +23208,6 @@ packages: - pkg:pypi/pip size: 1386212 timestamp: 1690024763393 -- kind: conda - name: pip - version: '24.0' - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pip-24.0-pyhd8ed1ab_0.conda - sha256: b7c1c5d8f13e8cb491c4bd1d0d1896a4cf80fc47de01059ad77509112b664a4a - md5: f586ac1e56c8638b64f9c8122a7b8a67 - depends: - - python >=3.7 - - setuptools - - wheel - license: MIT - license_family: MIT - purls: - - pkg:pypi/pip@24.0 - size: 1398245 - timestamp: 1706960660581 - kind: conda name: pip version: '24.0' @@ -23474,26 +23382,26 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl - sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 + url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl - sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 + url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c + url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d + url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 requires_python: '>=3.8' - kind: pypi name: psutil @@ -23510,8 +23418,8 @@ packages: - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl - sha256: aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81 + url: https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl + sha256: d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -23522,8 +23430,8 @@ packages: - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/93/52/3e39d26feae7df0aa0fd510b14012c3678b36ed068f7d78b8d8784d61f0e/psutil-5.9.8-cp37-abi3-win_amd64.whl - sha256: 8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf + url: https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl + sha256: aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -23534,8 +23442,8 @@ packages: - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl - sha256: d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8 + url: https://files.pythonhosted.org/packages/93/52/3e39d26feae7df0aa0fd510b14012c3678b36ed068f7d78b8d8784d61f0e/psutil-5.9.8-cp37-abi3-win_amd64.whl + sha256: 8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -24156,8 +24064,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 + url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl + sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 requires_dist: - cffi >=1.4.1 - sphinx >=1.6.5 ; extra == 'docs' @@ -24168,8 +24076,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 + url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl + sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d requires_dist: - cffi >=1.4.1 - sphinx >=1.6.5 ; extra == 'docs' @@ -24180,8 +24088,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 + url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 requires_dist: - cffi >=1.4.1 - sphinx >=1.6.5 ; extra == 'docs' @@ -24192,8 +24100,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d + url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl + sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 requires_dist: - cffi >=1.4.1 - sphinx >=1.6.5 ; extra == 'docs' @@ -24742,20 +24650,20 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 + url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl - sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 + url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab + url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl + sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 requires_python: '>=3.6' - kind: pypi name: raw-mesh @@ -25043,20 +24951,20 @@ packages: - kind: pypi name: regex version: 2024.4.16 - url: https://files.pythonhosted.org/packages/fd/b2/8069e8940bc3224d2cef6418aa6de4f2119d59709b841ecab012e3fc1d65/regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd + url: https://files.pythonhosted.org/packages/aa/f1/de801945e6a18c9b7d7ea9ffe01d2433b40d1609426c3581f7d60acd1416/regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl + sha256: fd80d1280d473500d8086d104962a82d77bfbf2b118053824b7be28cd5a79ea5 requires_python: '>=3.7' - kind: pypi name: regex version: 2024.4.16 - url: https://files.pythonhosted.org/packages/b3/d0/1a054b685849b018cff594ccd4859fc6a3132f67698da805ed06d5b6974a/regex-2024.4.16-cp311-cp311-win_amd64.whl - sha256: 8f83b6fd3dc3ba94d2b22717f9c8b8512354fd95221ac661784df2769ea9bba9 + url: https://files.pythonhosted.org/packages/fd/b2/8069e8940bc3224d2cef6418aa6de4f2119d59709b841ecab012e3fc1d65/regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd requires_python: '>=3.7' - kind: pypi name: regex version: 2024.4.16 - url: https://files.pythonhosted.org/packages/aa/f1/de801945e6a18c9b7d7ea9ffe01d2433b40d1609426c3581f7d60acd1416/regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl - sha256: fd80d1280d473500d8086d104962a82d77bfbf2b118053824b7be28cd5a79ea5 + url: https://files.pythonhosted.org/packages/b3/d0/1a054b685849b018cff594ccd4859fc6a3132f67698da805ed06d5b6974a/regex-2024.4.16-cp311-cp311-win_amd64.whl + sha256: 8f83b6fd3dc3ba94d2b22717f9c8b8512354fd95221ac661784df2769ea9bba9 requires_python: '>=3.7' - kind: pypi name: requests @@ -25400,8 +25308,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a + url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl + sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe requires_dist: - numpy >=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -25440,8 +25348,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl - sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 + url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a requires_dist: - numpy >=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -25480,8 +25388,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl - sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe + url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl + sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 requires_dist: - numpy >=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -25587,8 +25495,8 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/78/2b/5f985cf4cf59378f80dc212004a7692b7b49b2a3910c3584d70284db5b89/scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: ee83fdb1843ee938eabdfeb9498623282935ea30aa20dffc5d5d16698efb4b2a + url: https://files.pythonhosted.org/packages/b9/cf/9e5828fa29791bf7ac5c3fad3637ebb02f237a1c3de8233bd6a33c2c4aac/scikit_image-0.23.2-cp311-cp311-macosx_12_0_arm64.whl + sha256: a158f50d3df4867bbd1c698520ede8bc493e430ad83f54ac1f0d8f57b328779b requires_dist: - numpy >=1.23 - scipy >=1.9 @@ -25654,8 +25562,8 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/eb/ab/8791ce3063e6d4ac7f8efe3c993fd2e911c9e08f4c7dd05b603eaa2493b2/scikit_image-0.23.2-cp311-cp311-win_amd64.whl - sha256: ee65669aa586e110346f567ed5c92d1bd63799a19e951cb83da3f54b0caf7c52 + url: https://files.pythonhosted.org/packages/78/2b/5f985cf4cf59378f80dc212004a7692b7b49b2a3910c3584d70284db5b89/scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: ee83fdb1843ee938eabdfeb9498623282935ea30aa20dffc5d5d16698efb4b2a requires_dist: - numpy >=1.23 - scipy >=1.9 @@ -25721,8 +25629,8 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/b9/cf/9e5828fa29791bf7ac5c3fad3637ebb02f237a1c3de8233bd6a33c2c4aac/scikit_image-0.23.2-cp311-cp311-macosx_12_0_arm64.whl - sha256: a158f50d3df4867bbd1c698520ede8bc493e430ad83f54ac1f0d8f57b328779b + url: https://files.pythonhosted.org/packages/eb/ab/8791ce3063e6d4ac7f8efe3c993fd2e911c9e08f4c7dd05b603eaa2493b2/scikit_image-0.23.2-cp311-cp311-win_amd64.whl + sha256: ee65669aa586e110346f567ed5c92d1bd63799a19e951cb83da3f54b0caf7c52 requires_dist: - numpy >=1.23 - scipy >=1.9 @@ -25835,8 +25743,8 @@ packages: - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/59/11/63de36e6933b03490fdfe5cbc9b5a68870a1281d8e705a23b33076dc82fb/scikit_learn-1.4.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 45dee87ac5309bb82e3ea633955030df9bbcb8d2cdb30383c6cd483691c546cc + url: https://files.pythonhosted.org/packages/f2/30/1299e84d2ba3bc735baf17cebbf5b9d55144243c41b3ec6559ce3cf61e23/scikit_learn-1.4.2-cp311-cp311-macosx_12_0_arm64.whl + sha256: 1d0b25d9c651fd050555aadd57431b53d4cf664e749069da77f3d52c5ad14b3b requires_dist: - numpy >=1.19.5 - scipy >=1.6.0 @@ -25882,8 +25790,8 @@ packages: - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/79/3d/02d5d3ed359498fec3abdf65407d3c07e3b8765af17464969055aaec5171/scikit_learn-1.4.2-cp311-cp311-win_amd64.whl - sha256: 5cd7b524115499b18b63f0c96f4224eb885564937a0b3477531b2b63ce331904 + url: https://files.pythonhosted.org/packages/59/11/63de36e6933b03490fdfe5cbc9b5a68870a1281d8e705a23b33076dc82fb/scikit_learn-1.4.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 45dee87ac5309bb82e3ea633955030df9bbcb8d2cdb30383c6cd483691c546cc requires_dist: - numpy >=1.19.5 - scipy >=1.6.0 @@ -25929,8 +25837,8 @@ packages: - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/f2/30/1299e84d2ba3bc735baf17cebbf5b9d55144243c41b3ec6559ce3cf61e23/scikit_learn-1.4.2-cp311-cp311-macosx_12_0_arm64.whl - sha256: 1d0b25d9c651fd050555aadd57431b53d4cf664e749069da77f3d52c5ad14b3b + url: https://files.pythonhosted.org/packages/79/3d/02d5d3ed359498fec3abdf65407d3c07e3b8765af17464969055aaec5171/scikit_learn-1.4.2-cp311-cp311-win_amd64.whl + sha256: 5cd7b524115499b18b63f0c96f4224eb885564937a0b3477531b2b63ce331904 requires_dist: - numpy >=1.19.5 - scipy >=1.6.0 @@ -26015,8 +25923,8 @@ packages: - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/be/e3/236639c51636ec7e678f2aa608fe89acb9d02ef64e1fe1d8eb40373bc62b/scipy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 0fbcf8abaf5aa2dc8d6400566c1a727aed338b5fe880cde64907596a89d576fa + url: https://files.pythonhosted.org/packages/51/b6/188c8974d747b2998d672040c5b62a635a72240c515dc4577a28e1dedc80/scipy-1.13.0-cp311-cp311-macosx_12_0_arm64.whl + sha256: 5e4a756355522eb60fcd61f8372ac2549073c8788f6114449b37e9e8104f15a5 requires_dist: - numpy <2.3, >=1.22.4 - pytest ; extra == 'test' @@ -26054,8 +25962,8 @@ packages: - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/d4/a1/d4adf25b6d2bef8d0ad1682829dcfcba97f3f96bb5b6f137bc3e41003cc7/scipy-1.13.0-cp311-cp311-win_amd64.whl - sha256: a2f471de4d01200718b2b8927f7d76b5d9bde18047ea0fa8bd15c5ba3f26a1d6 + url: https://files.pythonhosted.org/packages/be/e3/236639c51636ec7e678f2aa608fe89acb9d02ef64e1fe1d8eb40373bc62b/scipy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 0fbcf8abaf5aa2dc8d6400566c1a727aed338b5fe880cde64907596a89d576fa requires_dist: - numpy <2.3, >=1.22.4 - pytest ; extra == 'test' @@ -26093,8 +26001,8 @@ packages: - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/51/b6/188c8974d747b2998d672040c5b62a635a72240c515dc4577a28e1dedc80/scipy-1.13.0-cp311-cp311-macosx_12_0_arm64.whl - sha256: 5e4a756355522eb60fcd61f8372ac2549073c8788f6114449b37e9e8104f15a5 + url: https://files.pythonhosted.org/packages/d4/a1/d4adf25b6d2bef8d0ad1682829dcfcba97f3f96bb5b6f137bc3e41003cc7/scipy-1.13.0-cp311-cp311-win_amd64.whl + sha256: a2f471de4d01200718b2b8927f7d76b5d9bde18047ea0fa8bd15c5ba3f26a1d6 requires_dist: - numpy <2.3, >=1.22.4 - pytest ; extra == 'test' @@ -26248,8 +26156,8 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/93/fd/b205661ed60294a344406fb04227042fcede9501e81ee1e7018e9159455a/shapely-2.0.4-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7 + url: https://files.pythonhosted.org/packages/2a/fb/e3f72b10a90e26bb1a92a38b3f30f3074ebac6d532f87848ac09c3e8a73b/shapely-2.0.4-cp311-cp311-macosx_11_0_arm64.whl + sha256: 58b0ecc505bbe49a99551eea3f2e8a9b3b24b3edd2a4de1ac0dc17bc75c9ec07 requires_dist: - numpy <3, >=1.14 - numpydoc ==1.1.* ; extra == 'docs' @@ -26263,8 +26171,8 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/6a/5c/3330f499ca860f0b92db4ceaebd7090096a83c1ea3ae7d8d4c6111761b82/shapely-2.0.4-cp311-cp311-win_amd64.whl - sha256: c52ed79f683f721b69a10fb9e3d940a468203f5054927215586c5d49a072de8d + url: https://files.pythonhosted.org/packages/93/fd/b205661ed60294a344406fb04227042fcede9501e81ee1e7018e9159455a/shapely-2.0.4-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7 requires_dist: - numpy <3, >=1.14 - numpydoc ==1.1.* ; extra == 'docs' @@ -26278,8 +26186,8 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/2a/fb/e3f72b10a90e26bb1a92a38b3f30f3074ebac6d532f87848ac09c3e8a73b/shapely-2.0.4-cp311-cp311-macosx_11_0_arm64.whl - sha256: 58b0ecc505bbe49a99551eea3f2e8a9b3b24b3edd2a4de1ac0dc17bc75c9ec07 + url: https://files.pythonhosted.org/packages/6a/5c/3330f499ca860f0b92db4ceaebd7090096a83c1ea3ae7d8d4c6111761b82/shapely-2.0.4-cp311-cp311-win_amd64.whl + sha256: c52ed79f683f721b69a10fb9e3d940a468203f5054927215586c5d49a072de8d requires_dist: - numpy <3, >=1.14 - numpydoc ==1.1.* ; extra == 'docs' @@ -26957,8 +26865,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 + url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 requires_dist: - huggingface-hub >=0.16.4, <1.0 - pytest ; extra == 'testing' @@ -26975,8 +26883,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl - sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 + url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 requires_dist: - huggingface-hub >=0.16.4, <1.0 - pytest ; extra == 'testing' @@ -26993,8 +26901,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 + url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl + sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 requires_dist: - huggingface-hub >=0.16.4, <1.0 - pytest ; extra == 'testing' @@ -27008,23 +26916,6 @@ packages: - setuptools-rust ; extra == 'docs' - tokenizers[testing] ; extra == 'dev' requires_python: '>=3.7' -- kind: conda - name: tomli - version: 2.0.1 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/tomli-2.0.1-pyhd8ed1ab_0.tar.bz2 - sha256: 4cd48aba7cd026d17e86886af48d0d2ebc67ed36f87f6534f4b67138f5a5a58f - md5: 5844808ffab9ebdb694585b50ba02a96 - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/tomli - size: 15940 - timestamp: 1644342331069 - kind: conda name: tomli version: 2.0.1 @@ -27066,8 +26957,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf requires_dist: - filelock - typing-extensions >=4.8.0 @@ -27093,8 +26984,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl - sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 + url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 requires_dist: - filelock - typing-extensions >=4.8.0 @@ -27120,8 +27011,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl + sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb requires_dist: - filelock - typing-extensions >=4.8.0 @@ -27147,8 +27038,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb + url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 requires_dist: - filelock - typing-extensions >=4.8.0 @@ -27174,8 +27065,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl - sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c requires_dist: - filelock - typing-extensions >=4.8.0 @@ -27212,8 +27103,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl - sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 + url: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d requires_dist: - numpy - torch ==2.2.2 @@ -27223,8 +27114,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl - sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 + url: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl + sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 requires_dist: - numpy - torch ==2.2.2 @@ -27234,8 +27125,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d + url: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl + sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 requires_dist: - numpy - torch ==2.2.2 @@ -28468,14 +28359,14 @@ packages: - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 + url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl - sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 + url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 requires_python: '>=3.6' - kind: pypi name: wrapt @@ -28486,14 +28377,14 @@ packages: - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 + url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d + url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl + sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 requires_python: '>=3.6' - kind: conda name: xz diff --git a/pixi.toml b/pixi.toml index bc76285745df..1256125e5933 100644 --- a/pixi.toml +++ b/pixi.toml @@ -97,7 +97,9 @@ rerun-web-release = { cmd = "cargo run --package rerun-cli --no-default-features # (this looks heavy but takes typically below 0.1s!) rerun-build-web-release = "rustup target add wasm32-unknown-unknown && cargo run -p re_dev_tools -- build-web-viewer --release -g" -rs-check = "rustup target add wasm32-unknown-unknown && python scripts/ci/rust_checks.py" +rs-check = { cmd = "rustup target add wasm32-unknown-unknown && python scripts/ci/rust_checks.py", depends_on = [ + "rerun-build-web", # The checks require the web viewer wasm to be around. +] } # Code formatting for all languages. format = { depends_on = ["py-fmt", "cpp-fmt", "toml-fmt", "misc-fmt"] } @@ -140,24 +142,6 @@ py-build = { cmd = "PIP_REQUIRE_VIRTUALENV=0 RERUN_ALLOW_MISSING_BIN=1 maturin d "rerun-build", ] } -# Build a wheel for the rerun-sdk Python package. -# -# The built wheel can be found in the `target/wheels` folder, and needs to be manually -# installed via `pip install target/wheels/rerun_sdk-*.whl`. -# -# This is useful for testing of the packainge process or working with rerun in the -# context of a separate venv. Otherwise, `py-build` will be faster and much more convenient. -py-wheel = "maturin build --manifest-path rerun_py/Cargo.toml --features pypi" - -# Run the Python tests. -# Don't call this on CI - use `nox` to run tests on all supported Python versions instead. -py-test = { cmd = "python -m pytest -vv rerun_py/tests/unit", depends_on = [ - "py-build", -] } -py-bench = { cmd = "python -m pytest -c rerun_py/pyproject.toml --benchmark-only", depends_on = [ - "py-build", -] } - # Python example utilities py-run-all-examples = { cmd = "python scripts/run_all.py --skip-build", depends_on = [ "py-build", @@ -215,6 +199,10 @@ cpp-prepare = "cmake -G 'Ninja' -B build/debug -S . -DCMAKE_BUILD_TYPE=Debug" cpp-build-all = { cmd = "cmake --build build/debug --config Debug --target all", depends_on = [ "cpp-prepare", ] } +cpp-prepare-shared-libs = "cmake -G 'Ninja' -B build/debug -S . -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON" +cpp-build-all-shared-libs = { cmd = "cmake --build build/debug --config Debug --target all", depends_on = [ + "cpp-prepare-shared-libs", +] } cpp-clean = "rm -rf build CMakeCache.txt CMakeFiles" cpp-build-tests = { cmd = "cmake --build build/debug --config Debug --target rerun_sdk_tests", depends_on = [ "cpp-prepare", @@ -254,12 +242,20 @@ cpp-prepare-msvc = "cmake -G 'Visual Studio 17 2022' -B build-msvc -S ." torch = ">=2.0.1" pip = ">=23" - [feature.wheel-test.tasks] # In the wheel-test environment we want to use the wheel-installed `rerun` binary on the path. # This overrides the `rerun` task from the default env which otherwise executes via cargo. rerun = "rerun" +# Run the Python tests. +# Don't call this on CI - use `nox` to run tests on all supported Python versions instead. +py-test = { cmd = "python -m pytest -vv rerun_py/tests/unit", depends_on = [ + "py-build", +] } +py-bench = { cmd = "python -m pytest -c rerun_py/pyproject.toml --benchmark-only", depends_on = [ + "py-build", +] } + [feature.base.dependencies] # IMPORTANT: do not add any dependencies here that may break CI. All dependencies should be available on all supported # platforms (including linux-aarch64), or added conditionally. @@ -284,6 +280,7 @@ flatbuffers = ">=23" gitignore-parser = ">=0.1.9" gitpython = ">=3.1.40" jinja2 = ">=3.1.3,<3.2" # For `update_pr_bodies.py`, `generate_pr_summary.py`, `build_screenshot_compare.py` and other utilities that build websites. +maturin = "1.5.1" # For py-build and dependents mypy = "1.8.0" ninja = "1.11.1" numpy = ">=1.23,<2" diff --git a/rerun_cpp/CMakeLists.txt b/rerun_cpp/CMakeLists.txt index 9d6fb8d0e285..5015ef3ab84a 100644 --- a/rerun_cpp/CMakeLists.txt +++ b/rerun_cpp/CMakeLists.txt @@ -116,6 +116,29 @@ endif() target_link_libraries(rerun_sdk PRIVATE rerun_arrow_target) +if(MSVC AND BUILD_SHARED_LIBS) + # This code is required by to support BUILD_SHARED_LIBS=ON on Windows + # Differently from Linux/macOS, by default Windows does not support + # exporting all symbols of a shared library, and instead requires + # annotating manually each class that needs to be exported + # The WINDOWS_EXPORT_ALL_SYMBOLS PROPERTY (set in the next line) + # simply the process of having shared library on Windows, by emulating + # in CMake the behavior of Linux/macOS. However, it does not cover + # static variables. + set_property(TARGET rerun_sdk PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON) + # For exporting static variables in shared libraries in Windows, it + # is not possible to just use WINDOWS_EXPORT_ALL_SYMBOLS, we need instead + # to manually annotate with the appropriate storage-class attributes + # all static variables. The easiest way to do so is use GenerateExportHeader + # module to generate a rerun_sdk_export.hpp header file that define the RERUN_SDK_EXPORT + # macro, and add that macro to all static variables. The RERUN_SDK_EXPORT is defined + # in src/rerun/rerun_sdk_export.hpp . The definition of the macro changes depending + # of whether the library is compiled as static or shared, so for shared builds we + # set the RERUN_SDK_COMPILED_AS_SHARED_LIBRARY to let the header know if the build + # is a shared library one + target_compile_definitions(rerun_sdk PUBLIC RERUN_SDK_COMPILED_AS_SHARED_LIBRARY) +endif() + # ----------------------------------------------------------------------------- # Installation. set(RERUN_SDK_INSTALL_CMAKE_DIR "lib/cmake/rerun_sdk") @@ -125,6 +148,7 @@ install(TARGETS rerun_sdk EXPORT rerun_sdkTargets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin INCLUDES DESTINATION include ) diff --git a/rerun_cpp/src/rerun/archetypes/clear.hpp b/rerun_cpp/src/rerun/archetypes/clear.hpp index d77de84f3150..e354dc87cae5 100644 --- a/rerun_cpp/src/rerun/archetypes/clear.hpp +++ b/rerun_cpp/src/rerun/archetypes/clear.hpp @@ -7,6 +7,7 @@ #include "../components/clear_is_recursive.hpp" #include "../data_cell.hpp" #include "../indicator_component.hpp" +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include @@ -92,9 +93,9 @@ namespace rerun::archetypes { public: // Extensions to generated type defined in 'clear_ext.cpp' - static const Clear FLAT; + RERUN_SDK_EXPORT static const Clear FLAT; - static const Clear RECURSIVE; + RERUN_SDK_EXPORT static const Clear RECURSIVE; Clear(bool _is_recursive = false) : Clear(components::ClearIsRecursive(_is_recursive)) {} diff --git a/rerun_cpp/src/rerun/archetypes/clear_ext.cpp b/rerun_cpp/src/rerun/archetypes/clear_ext.cpp index 46245d116a83..1b548e5a4bc1 100644 --- a/rerun_cpp/src/rerun/archetypes/clear_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/clear_ext.cpp @@ -1,5 +1,10 @@ #include "clear.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -12,9 +17,9 @@ namespace rerun { // - static const Clear FLAT; + RERUN_SDK_EXPORT static const Clear FLAT; - static const Clear RECURSIVE; + RERUN_SDK_EXPORT static const Clear RECURSIVE; Clear(bool _is_recursive = false) : Clear(components::ClearIsRecursive(_is_recursive)) {} diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.hpp b/rerun_cpp/src/rerun/archetypes/transform3d.hpp index 3de4117ae71e..439c93f47ef9 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.hpp @@ -7,6 +7,7 @@ #include "../components/transform3d.hpp" #include "../data_cell.hpp" #include "../indicator_component.hpp" +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include @@ -65,7 +66,7 @@ namespace rerun::archetypes { /// Identity transformation. /// /// Applying this transform does not alter an entity's transformation. - static const Transform3D IDENTITY; + RERUN_SDK_EXPORT static const Transform3D IDENTITY; /// New 3D transform from translation/matrix datatype. /// diff --git a/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp b/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp index 36628900c5ea..b762b046e035 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp @@ -1,5 +1,10 @@ #include "transform3d.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -12,7 +17,7 @@ namespace rerun { /// Identity transformation. /// /// Applying this transform does not alter an entity's transformation. - static const Transform3D IDENTITY; + RERUN_SDK_EXPORT static const Transform3D IDENTITY; /// New 3D transform from translation/matrix datatype. /// diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp index 8c014115270f..86292efb462f 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp @@ -7,6 +7,7 @@ #include "../components/view_coordinates.hpp" #include "../data_cell.hpp" #include "../indicator_component.hpp" +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include @@ -62,66 +63,66 @@ namespace rerun::archetypes { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` - static const rerun::archetypes::ViewCoordinates ULF; - static const rerun::archetypes::ViewCoordinates UFL; - static const rerun::archetypes::ViewCoordinates LUF; - static const rerun::archetypes::ViewCoordinates LFU; - static const rerun::archetypes::ViewCoordinates FUL; - static const rerun::archetypes::ViewCoordinates FLU; - static const rerun::archetypes::ViewCoordinates ULB; - static const rerun::archetypes::ViewCoordinates UBL; - static const rerun::archetypes::ViewCoordinates LUB; - static const rerun::archetypes::ViewCoordinates LBU; - static const rerun::archetypes::ViewCoordinates BUL; - static const rerun::archetypes::ViewCoordinates BLU; - static const rerun::archetypes::ViewCoordinates URF; - static const rerun::archetypes::ViewCoordinates UFR; - static const rerun::archetypes::ViewCoordinates RUF; - static const rerun::archetypes::ViewCoordinates RFU; - static const rerun::archetypes::ViewCoordinates FUR; - static const rerun::archetypes::ViewCoordinates FRU; - static const rerun::archetypes::ViewCoordinates URB; - static const rerun::archetypes::ViewCoordinates UBR; - static const rerun::archetypes::ViewCoordinates RUB; - static const rerun::archetypes::ViewCoordinates RBU; - static const rerun::archetypes::ViewCoordinates BUR; - static const rerun::archetypes::ViewCoordinates BRU; - static const rerun::archetypes::ViewCoordinates DLF; - static const rerun::archetypes::ViewCoordinates DFL; - static const rerun::archetypes::ViewCoordinates LDF; - static const rerun::archetypes::ViewCoordinates LFD; - static const rerun::archetypes::ViewCoordinates FDL; - static const rerun::archetypes::ViewCoordinates FLD; - static const rerun::archetypes::ViewCoordinates DLB; - static const rerun::archetypes::ViewCoordinates DBL; - static const rerun::archetypes::ViewCoordinates LDB; - static const rerun::archetypes::ViewCoordinates LBD; - static const rerun::archetypes::ViewCoordinates BDL; - static const rerun::archetypes::ViewCoordinates BLD; - static const rerun::archetypes::ViewCoordinates DRF; - static const rerun::archetypes::ViewCoordinates DFR; - static const rerun::archetypes::ViewCoordinates RDF; - static const rerun::archetypes::ViewCoordinates RFD; - static const rerun::archetypes::ViewCoordinates FDR; - static const rerun::archetypes::ViewCoordinates FRD; - static const rerun::archetypes::ViewCoordinates DRB; - static const rerun::archetypes::ViewCoordinates DBR; - static const rerun::archetypes::ViewCoordinates RDB; - static const rerun::archetypes::ViewCoordinates RBD; - static const rerun::archetypes::ViewCoordinates BDR; - static const rerun::archetypes::ViewCoordinates BRD; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_UP; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_DOWN; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_UP; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_DOWN; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_UP; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_DOWN; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_UP; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_DOWN; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_UP; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_DOWN; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_UP; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_DOWN; // public: diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp b/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp index 4c430f5f954c..5693f3249d19 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp @@ -1,5 +1,10 @@ #include "view_coordinates.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -19,66 +24,66 @@ namespace rerun { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` - static const rerun::archetypes::ViewCoordinates ULF; - static const rerun::archetypes::ViewCoordinates UFL; - static const rerun::archetypes::ViewCoordinates LUF; - static const rerun::archetypes::ViewCoordinates LFU; - static const rerun::archetypes::ViewCoordinates FUL; - static const rerun::archetypes::ViewCoordinates FLU; - static const rerun::archetypes::ViewCoordinates ULB; - static const rerun::archetypes::ViewCoordinates UBL; - static const rerun::archetypes::ViewCoordinates LUB; - static const rerun::archetypes::ViewCoordinates LBU; - static const rerun::archetypes::ViewCoordinates BUL; - static const rerun::archetypes::ViewCoordinates BLU; - static const rerun::archetypes::ViewCoordinates URF; - static const rerun::archetypes::ViewCoordinates UFR; - static const rerun::archetypes::ViewCoordinates RUF; - static const rerun::archetypes::ViewCoordinates RFU; - static const rerun::archetypes::ViewCoordinates FUR; - static const rerun::archetypes::ViewCoordinates FRU; - static const rerun::archetypes::ViewCoordinates URB; - static const rerun::archetypes::ViewCoordinates UBR; - static const rerun::archetypes::ViewCoordinates RUB; - static const rerun::archetypes::ViewCoordinates RBU; - static const rerun::archetypes::ViewCoordinates BUR; - static const rerun::archetypes::ViewCoordinates BRU; - static const rerun::archetypes::ViewCoordinates DLF; - static const rerun::archetypes::ViewCoordinates DFL; - static const rerun::archetypes::ViewCoordinates LDF; - static const rerun::archetypes::ViewCoordinates LFD; - static const rerun::archetypes::ViewCoordinates FDL; - static const rerun::archetypes::ViewCoordinates FLD; - static const rerun::archetypes::ViewCoordinates DLB; - static const rerun::archetypes::ViewCoordinates DBL; - static const rerun::archetypes::ViewCoordinates LDB; - static const rerun::archetypes::ViewCoordinates LBD; - static const rerun::archetypes::ViewCoordinates BDL; - static const rerun::archetypes::ViewCoordinates BLD; - static const rerun::archetypes::ViewCoordinates DRF; - static const rerun::archetypes::ViewCoordinates DFR; - static const rerun::archetypes::ViewCoordinates RDF; - static const rerun::archetypes::ViewCoordinates RFD; - static const rerun::archetypes::ViewCoordinates FDR; - static const rerun::archetypes::ViewCoordinates FRD; - static const rerun::archetypes::ViewCoordinates DRB; - static const rerun::archetypes::ViewCoordinates DBR; - static const rerun::archetypes::ViewCoordinates RDB; - static const rerun::archetypes::ViewCoordinates RBD; - static const rerun::archetypes::ViewCoordinates BDR; - static const rerun::archetypes::ViewCoordinates BRD; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_UP; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_DOWN; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_UP; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_DOWN; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_UP; - static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_DOWN; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_UP; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_DOWN; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_UP; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_DOWN; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_UP; - static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRU; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDL; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDF; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDB; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDR; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRD; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_DOWN; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_UP; + RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_DOWN; // // diff --git a/rerun_cpp/src/rerun/components/resolution.hpp b/rerun_cpp/src/rerun/components/resolution.hpp index 609e20117d4f..a43d1540ecd7 100644 --- a/rerun_cpp/src/rerun/components/resolution.hpp +++ b/rerun_cpp/src/rerun/components/resolution.hpp @@ -4,6 +4,7 @@ #pragma once #include "../datatypes/vec2d.hpp" +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include @@ -20,7 +21,7 @@ namespace rerun::components { public: // Extensions to generated type defined in 'resolution_ext.cpp' - static const Resolution IDENTITY; + RERUN_SDK_EXPORT static const Resolution IDENTITY; /// Construct resolution from width and height floats. Resolution(float width, float height) : resolution{width, height} {} diff --git a/rerun_cpp/src/rerun/components/resolution_ext.cpp b/rerun_cpp/src/rerun/components/resolution_ext.cpp index 8775782369a6..acd7f58e5aad 100644 --- a/rerun_cpp/src/rerun/components/resolution_ext.cpp +++ b/rerun_cpp/src/rerun/components/resolution_ext.cpp @@ -1,5 +1,10 @@ #include "resolution.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -13,7 +18,7 @@ namespace rerun { // - static const Resolution IDENTITY; + RERUN_SDK_EXPORT static const Resolution IDENTITY; /// Construct resolution from width and height floats. Resolution(float width, float height) : resolution{width, height} {} diff --git a/rerun_cpp/src/rerun/components/rotation3d.hpp b/rerun_cpp/src/rerun/components/rotation3d.hpp index ada3dab95177..d8bbc4dcf381 100644 --- a/rerun_cpp/src/rerun/components/rotation3d.hpp +++ b/rerun_cpp/src/rerun/components/rotation3d.hpp @@ -4,6 +4,7 @@ #pragma once #include "../datatypes/rotation3d.hpp" +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include @@ -18,7 +19,7 @@ namespace rerun::components { public: // Extensions to generated type defined in 'rotation3d_ext.cpp' - static const Rotation3D IDENTITY; + RERUN_SDK_EXPORT static const Rotation3D IDENTITY; /// Construct Rotation3d from Quaternion. Rotation3D(datatypes::Quaternion quaternion) : repr{quaternion} {} diff --git a/rerun_cpp/src/rerun/components/rotation3d_ext.cpp b/rerun_cpp/src/rerun/components/rotation3d_ext.cpp index e63590bcf766..659f13d1e5b6 100644 --- a/rerun_cpp/src/rerun/components/rotation3d_ext.cpp +++ b/rerun_cpp/src/rerun/components/rotation3d_ext.cpp @@ -1,5 +1,10 @@ #include "rotation3d.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -13,7 +18,7 @@ namespace rerun { // - static const Rotation3D IDENTITY; + RERUN_SDK_EXPORT static const Rotation3D IDENTITY; /// Construct Rotation3d from Quaternion. Rotation3D(datatypes::Quaternion quaternion) : repr{quaternion} {} diff --git a/rerun_cpp/src/rerun/components/text_log_level.hpp b/rerun_cpp/src/rerun/components/text_log_level.hpp index d26158b72ef4..96d7dd91b2a7 100644 --- a/rerun_cpp/src/rerun/components/text_log_level.hpp +++ b/rerun_cpp/src/rerun/components/text_log_level.hpp @@ -4,6 +4,7 @@ #pragma once #include "../datatypes/utf8.hpp" +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include @@ -28,22 +29,22 @@ namespace rerun::components { // Extensions to generated type defined in 'text_log_level_ext.cpp' /// Designates catastrophic failures. - static const TextLogLevel Critical; + RERUN_SDK_EXPORT static const TextLogLevel Critical; /// Designates very serious errors. - static const TextLogLevel Error; + RERUN_SDK_EXPORT static const TextLogLevel Error; /// Designates hazardous situations. - static const TextLogLevel Warning; + RERUN_SDK_EXPORT static const TextLogLevel Warning; /// Designates useful information. - static const TextLogLevel Info; + RERUN_SDK_EXPORT static const TextLogLevel Info; /// Designates lower priority information. - static const TextLogLevel Debug; + RERUN_SDK_EXPORT static const TextLogLevel Debug; /// Designates very low priority, often extremely verbose, information. - static const TextLogLevel Trace; + RERUN_SDK_EXPORT static const TextLogLevel Trace; /// Construct `TextLogLevel` from a null-terminated UTF8 string. TextLogLevel(const char* str) : value(str) {} diff --git a/rerun_cpp/src/rerun/components/text_log_level_ext.cpp b/rerun_cpp/src/rerun/components/text_log_level_ext.cpp index a603a37bf1df..397ed5cd488e 100644 --- a/rerun_cpp/src/rerun/components/text_log_level_ext.cpp +++ b/rerun_cpp/src/rerun/components/text_log_level_ext.cpp @@ -1,5 +1,10 @@ #include "text_log_level.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -16,22 +21,22 @@ namespace rerun { // /// Designates catastrophic failures. - static const TextLogLevel Critical; + RERUN_SDK_EXPORT static const TextLogLevel Critical; /// Designates very serious errors. - static const TextLogLevel Error; + RERUN_SDK_EXPORT static const TextLogLevel Error; /// Designates hazardous situations. - static const TextLogLevel Warning; + RERUN_SDK_EXPORT static const TextLogLevel Warning; /// Designates useful information. - static const TextLogLevel Info; + RERUN_SDK_EXPORT static const TextLogLevel Info; /// Designates lower priority information. - static const TextLogLevel Debug; + RERUN_SDK_EXPORT static const TextLogLevel Debug; /// Designates very low priority, often extremely verbose, information. - static const TextLogLevel Trace; + RERUN_SDK_EXPORT static const TextLogLevel Trace; /// Construct `TextLogLevel` from a null-terminated UTF8 string. TextLogLevel(const char* str) : value(str) {} diff --git a/rerun_cpp/src/rerun/components/view_coordinates.hpp b/rerun_cpp/src/rerun/components/view_coordinates.hpp index f06fa7d28db4..276ae58cd951 100644 --- a/rerun_cpp/src/rerun/components/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/components/view_coordinates.hpp @@ -3,6 +3,7 @@ #pragma once +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include @@ -58,66 +59,66 @@ namespace rerun::components { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` - static const rerun::components::ViewCoordinates ULF; - static const rerun::components::ViewCoordinates UFL; - static const rerun::components::ViewCoordinates LUF; - static const rerun::components::ViewCoordinates LFU; - static const rerun::components::ViewCoordinates FUL; - static const rerun::components::ViewCoordinates FLU; - static const rerun::components::ViewCoordinates ULB; - static const rerun::components::ViewCoordinates UBL; - static const rerun::components::ViewCoordinates LUB; - static const rerun::components::ViewCoordinates LBU; - static const rerun::components::ViewCoordinates BUL; - static const rerun::components::ViewCoordinates BLU; - static const rerun::components::ViewCoordinates URF; - static const rerun::components::ViewCoordinates UFR; - static const rerun::components::ViewCoordinates RUF; - static const rerun::components::ViewCoordinates RFU; - static const rerun::components::ViewCoordinates FUR; - static const rerun::components::ViewCoordinates FRU; - static const rerun::components::ViewCoordinates URB; - static const rerun::components::ViewCoordinates UBR; - static const rerun::components::ViewCoordinates RUB; - static const rerun::components::ViewCoordinates RBU; - static const rerun::components::ViewCoordinates BUR; - static const rerun::components::ViewCoordinates BRU; - static const rerun::components::ViewCoordinates DLF; - static const rerun::components::ViewCoordinates DFL; - static const rerun::components::ViewCoordinates LDF; - static const rerun::components::ViewCoordinates LFD; - static const rerun::components::ViewCoordinates FDL; - static const rerun::components::ViewCoordinates FLD; - static const rerun::components::ViewCoordinates DLB; - static const rerun::components::ViewCoordinates DBL; - static const rerun::components::ViewCoordinates LDB; - static const rerun::components::ViewCoordinates LBD; - static const rerun::components::ViewCoordinates BDL; - static const rerun::components::ViewCoordinates BLD; - static const rerun::components::ViewCoordinates DRF; - static const rerun::components::ViewCoordinates DFR; - static const rerun::components::ViewCoordinates RDF; - static const rerun::components::ViewCoordinates RFD; - static const rerun::components::ViewCoordinates FDR; - static const rerun::components::ViewCoordinates FRD; - static const rerun::components::ViewCoordinates DRB; - static const rerun::components::ViewCoordinates DBR; - static const rerun::components::ViewCoordinates RDB; - static const rerun::components::ViewCoordinates RBD; - static const rerun::components::ViewCoordinates BDR; - static const rerun::components::ViewCoordinates BRD; - static const rerun::components::ViewCoordinates RIGHT_HAND_X_UP; - static const rerun::components::ViewCoordinates RIGHT_HAND_X_DOWN; - static const rerun::components::ViewCoordinates RIGHT_HAND_Y_UP; - static const rerun::components::ViewCoordinates RIGHT_HAND_Y_DOWN; - static const rerun::components::ViewCoordinates RIGHT_HAND_Z_UP; - static const rerun::components::ViewCoordinates RIGHT_HAND_Z_DOWN; - static const rerun::components::ViewCoordinates LEFT_HAND_X_UP; - static const rerun::components::ViewCoordinates LEFT_HAND_X_DOWN; - static const rerun::components::ViewCoordinates LEFT_HAND_Y_UP; - static const rerun::components::ViewCoordinates LEFT_HAND_Y_DOWN; - static const rerun::components::ViewCoordinates LEFT_HAND_Z_UP; - static const rerun::components::ViewCoordinates LEFT_HAND_Z_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_X_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_X_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Y_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Y_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_DOWN; // public: diff --git a/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp b/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp index 3ac8e021b99f..f3ab06329086 100644 --- a/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp +++ b/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp @@ -1,5 +1,10 @@ #include "view_coordinates.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -32,66 +37,66 @@ namespace rerun { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` - static const rerun::components::ViewCoordinates ULF; - static const rerun::components::ViewCoordinates UFL; - static const rerun::components::ViewCoordinates LUF; - static const rerun::components::ViewCoordinates LFU; - static const rerun::components::ViewCoordinates FUL; - static const rerun::components::ViewCoordinates FLU; - static const rerun::components::ViewCoordinates ULB; - static const rerun::components::ViewCoordinates UBL; - static const rerun::components::ViewCoordinates LUB; - static const rerun::components::ViewCoordinates LBU; - static const rerun::components::ViewCoordinates BUL; - static const rerun::components::ViewCoordinates BLU; - static const rerun::components::ViewCoordinates URF; - static const rerun::components::ViewCoordinates UFR; - static const rerun::components::ViewCoordinates RUF; - static const rerun::components::ViewCoordinates RFU; - static const rerun::components::ViewCoordinates FUR; - static const rerun::components::ViewCoordinates FRU; - static const rerun::components::ViewCoordinates URB; - static const rerun::components::ViewCoordinates UBR; - static const rerun::components::ViewCoordinates RUB; - static const rerun::components::ViewCoordinates RBU; - static const rerun::components::ViewCoordinates BUR; - static const rerun::components::ViewCoordinates BRU; - static const rerun::components::ViewCoordinates DLF; - static const rerun::components::ViewCoordinates DFL; - static const rerun::components::ViewCoordinates LDF; - static const rerun::components::ViewCoordinates LFD; - static const rerun::components::ViewCoordinates FDL; - static const rerun::components::ViewCoordinates FLD; - static const rerun::components::ViewCoordinates DLB; - static const rerun::components::ViewCoordinates DBL; - static const rerun::components::ViewCoordinates LDB; - static const rerun::components::ViewCoordinates LBD; - static const rerun::components::ViewCoordinates BDL; - static const rerun::components::ViewCoordinates BLD; - static const rerun::components::ViewCoordinates DRF; - static const rerun::components::ViewCoordinates DFR; - static const rerun::components::ViewCoordinates RDF; - static const rerun::components::ViewCoordinates RFD; - static const rerun::components::ViewCoordinates FDR; - static const rerun::components::ViewCoordinates FRD; - static const rerun::components::ViewCoordinates DRB; - static const rerun::components::ViewCoordinates DBR; - static const rerun::components::ViewCoordinates RDB; - static const rerun::components::ViewCoordinates RBD; - static const rerun::components::ViewCoordinates BDR; - static const rerun::components::ViewCoordinates BRD; - static const rerun::components::ViewCoordinates RIGHT_HAND_X_UP; - static const rerun::components::ViewCoordinates RIGHT_HAND_X_DOWN; - static const rerun::components::ViewCoordinates RIGHT_HAND_Y_UP; - static const rerun::components::ViewCoordinates RIGHT_HAND_Y_DOWN; - static const rerun::components::ViewCoordinates RIGHT_HAND_Z_UP; - static const rerun::components::ViewCoordinates RIGHT_HAND_Z_DOWN; - static const rerun::components::ViewCoordinates LEFT_HAND_X_UP; - static const rerun::components::ViewCoordinates LEFT_HAND_X_DOWN; - static const rerun::components::ViewCoordinates LEFT_HAND_Y_UP; - static const rerun::components::ViewCoordinates LEFT_HAND_Y_DOWN; - static const rerun::components::ViewCoordinates LEFT_HAND_Z_UP; - static const rerun::components::ViewCoordinates LEFT_HAND_Z_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRU; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDL; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDF; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDB; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDR; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRD; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_X_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_X_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Y_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Y_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_DOWN; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_UP; + RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_DOWN; // // diff --git a/rerun_cpp/src/rerun/datatypes/mat3x3.hpp b/rerun_cpp/src/rerun/datatypes/mat3x3.hpp index 6ba35081b6b6..45a81ae4ec45 100644 --- a/rerun_cpp/src/rerun/datatypes/mat3x3.hpp +++ b/rerun_cpp/src/rerun/datatypes/mat3x3.hpp @@ -3,6 +3,7 @@ #pragma once +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include "vec3d.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/mat3x3_ext.cpp b/rerun_cpp/src/rerun/datatypes/mat3x3_ext.cpp index 48c14a04c7d9..ecde3c19df89 100644 --- a/rerun_cpp/src/rerun/datatypes/mat3x3_ext.cpp +++ b/rerun_cpp/src/rerun/datatypes/mat3x3_ext.cpp @@ -1,6 +1,7 @@ #include "mat3x3.hpp" // +#include "../rerun_sdk_export.hpp" #include "vec3d.hpp" // diff --git a/rerun_cpp/src/rerun/datatypes/mat4x4.hpp b/rerun_cpp/src/rerun/datatypes/mat4x4.hpp index 4c5da8272c68..088d94dc8b6c 100644 --- a/rerun_cpp/src/rerun/datatypes/mat4x4.hpp +++ b/rerun_cpp/src/rerun/datatypes/mat4x4.hpp @@ -3,6 +3,7 @@ #pragma once +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include "vec4d.hpp" @@ -35,7 +36,7 @@ namespace rerun::datatypes { public: // Extensions to generated type defined in 'mat4x4_ext.cpp' - static const Mat4x4 IDENTITY; + RERUN_SDK_EXPORT static const Mat4x4 IDENTITY; /// Creates a new 4x4 matrix from 3 *columns* of 4 elements each. Mat4x4(const Vec4D (&columns)[4]) diff --git a/rerun_cpp/src/rerun/datatypes/mat4x4_ext.cpp b/rerun_cpp/src/rerun/datatypes/mat4x4_ext.cpp index 90dbb2a25601..f0935227a9a4 100644 --- a/rerun_cpp/src/rerun/datatypes/mat4x4_ext.cpp +++ b/rerun_cpp/src/rerun/datatypes/mat4x4_ext.cpp @@ -1,6 +1,7 @@ #include "mat4x4.hpp" // +#include "../rerun_sdk_export.hpp" #include "vec4d.hpp" // @@ -11,7 +12,7 @@ namespace rerun { #if 0 // - static const Mat4x4 IDENTITY; + RERUN_SDK_EXPORT static const Mat4x4 IDENTITY; /// Creates a new 4x4 matrix from 3 *columns* of 4 elements each. Mat4x4(const Vec4D (&columns)[4]) diff --git a/rerun_cpp/src/rerun/datatypes/quaternion.hpp b/rerun_cpp/src/rerun/datatypes/quaternion.hpp index a23032eec45b..6aee78a89490 100644 --- a/rerun_cpp/src/rerun/datatypes/quaternion.hpp +++ b/rerun_cpp/src/rerun/datatypes/quaternion.hpp @@ -3,6 +3,7 @@ #pragma once +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include @@ -26,7 +27,7 @@ namespace rerun::datatypes { public: // Extensions to generated type defined in 'quaternion_ext.cpp' - static const Quaternion IDENTITY; + RERUN_SDK_EXPORT static const Quaternion IDENTITY; /// Construct Quaternion from x/y/z/w values. static Quaternion from_xyzw(float x, float y, float z, float w) { diff --git a/rerun_cpp/src/rerun/datatypes/quaternion_ext.cpp b/rerun_cpp/src/rerun/datatypes/quaternion_ext.cpp index a7243496a514..39d09d529d22 100644 --- a/rerun_cpp/src/rerun/datatypes/quaternion_ext.cpp +++ b/rerun_cpp/src/rerun/datatypes/quaternion_ext.cpp @@ -1,5 +1,10 @@ #include "quaternion.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -9,7 +14,7 @@ namespace rerun { #ifdef EDIT_EXTENSION // - static const Quaternion IDENTITY; + RERUN_SDK_EXPORT static const Quaternion IDENTITY; /// Construct Quaternion from x/y/z/w values. static Quaternion from_xyzw(float x, float y, float z, float w) { diff --git a/rerun_cpp/src/rerun/datatypes/rotation3d.hpp b/rerun_cpp/src/rerun/datatypes/rotation3d.hpp index ca22e66a0e05..467ce38db5d0 100644 --- a/rerun_cpp/src/rerun/datatypes/rotation3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/rotation3d.hpp @@ -3,6 +3,7 @@ #pragma once +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include "quaternion.hpp" #include "rotation_axis_angle.hpp" @@ -84,7 +85,7 @@ namespace rerun::datatypes { public: // Extensions to generated type defined in 'rotation3d_ext.cpp' - static const Rotation3D IDENTITY; + RERUN_SDK_EXPORT static const Rotation3D IDENTITY; void swap(Rotation3D& other) noexcept { std::swap(this->_tag, other._tag); diff --git a/rerun_cpp/src/rerun/datatypes/rotation3d_ext.cpp b/rerun_cpp/src/rerun/datatypes/rotation3d_ext.cpp index e412b5f228ed..bc3c10a6a753 100644 --- a/rerun_cpp/src/rerun/datatypes/rotation3d_ext.cpp +++ b/rerun_cpp/src/rerun/datatypes/rotation3d_ext.cpp @@ -1,5 +1,10 @@ #include "rotation3d.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -12,7 +17,7 @@ namespace rerun { // - static const Rotation3D IDENTITY; + RERUN_SDK_EXPORT static const Rotation3D IDENTITY; // }; diff --git a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp index bd535dfe2d0e..52a1bab40d13 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp +++ b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3.hpp @@ -3,6 +3,7 @@ #pragma once +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include "mat3x3.hpp" #include "vec3d.hpp" @@ -41,7 +42,7 @@ namespace rerun::datatypes { /// /// Applying this transform does not alter an entity's transformation. /// It has all optional fields set to `std::nullopt`. - static const TranslationAndMat3x3 IDENTITY; + RERUN_SDK_EXPORT static const TranslationAndMat3x3 IDENTITY; /// Creates a new 3D transform from translation/matrix. /// diff --git a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3_ext.cpp b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3_ext.cpp index bc0501b0ecbc..e945282d04c5 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3_ext.cpp +++ b/rerun_cpp/src/rerun/datatypes/translation_and_mat3x3_ext.cpp @@ -1,5 +1,10 @@ #include "translation_and_mat3x3.hpp" +// +#include "../rerun_sdk_export.hpp" + +// + // Uncomment for better auto-complete while editing the extension. // #define EDIT_EXTENSION @@ -13,7 +18,7 @@ namespace rerun { /// /// Applying this transform does not alter an entity's transformation. /// It has all optional fields set to `std::nullopt`. - static const TranslationAndMat3x3 IDENTITY; + RERUN_SDK_EXPORT static const TranslationAndMat3x3 IDENTITY; /// Creates a new 3D transform from translation/matrix. /// diff --git a/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.hpp b/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.hpp index ef36c3c31c9c..29a2b8162b1d 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d.hpp @@ -4,6 +4,7 @@ #pragma once #include "../compiler_utils.hpp" +#include "../rerun_sdk_export.hpp" #include "../result.hpp" #include "rotation3d.hpp" #include "scale3d.hpp" @@ -44,7 +45,7 @@ namespace rerun::datatypes { /// /// Applying this transform does not alter an entity's transformation. /// It has all optional fields set to `std::nullopt`. - static const TranslationRotationScale3D IDENTITY; + RERUN_SDK_EXPORT static const TranslationRotationScale3D IDENTITY; // Need to disable the maybe-uninitialized here because the compiler gets confused by the combination // of union-types datatypes inside of an optional component. diff --git a/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d_ext.cpp b/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d_ext.cpp index 66102562874e..71b1bd97c009 100644 --- a/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d_ext.cpp +++ b/rerun_cpp/src/rerun/datatypes/translation_rotation_scale3d_ext.cpp @@ -2,6 +2,7 @@ // #include "../compiler_utils.hpp" +#include "../rerun_sdk_export.hpp" // namespace rerun { @@ -14,7 +15,7 @@ namespace rerun { /// /// Applying this transform does not alter an entity's transformation. /// It has all optional fields set to `std::nullopt`. - static const TranslationRotationScale3D IDENTITY; + RERUN_SDK_EXPORT static const TranslationRotationScale3D IDENTITY; // Need to disable the maybe-uninitialized here because the compiler gets confused by the combination // of union-types datatypes inside of an optional component. diff --git a/rerun_cpp/src/rerun/rerun_sdk_export.hpp b/rerun_cpp/src/rerun/rerun_sdk_export.hpp new file mode 100644 index 000000000000..31f49271a798 --- /dev/null +++ b/rerun_cpp/src/rerun/rerun_sdk_export.hpp @@ -0,0 +1,25 @@ +#pragma once + +// If the library is not compiled on Windows, RERUN_SDK_EXPORT is defined as empty macro. +#ifndef _MSC_VER +#define RERUN_SDK_EXPORT +#else +// If rerun_sdk is compiled as shared on Windows, RERUN_SDK_EXPORT +// is __declspec(dllexport) for the compilation unit that are part +// of the library, and __declspec(dllimport) for compilation units +// that link to the library. +#ifdef RERUN_SDK_COMPILED_AS_SHARED_LIBRARY +// rerun_sdk_EXPORTS is defined by CMake itself when compiling a shared +// library, see https://cmake.org/cmake/help/latest/prop_tgt/DEFINE_SYMBOL.html +#ifdef rerun_sdk_EXPORTS +// We are building this library. +#define RERUN_SDK_EXPORT __declspec(dllexport) +#else +// We are using this library. +#define RERUN_SDK_EXPORT __declspec(dllimport) +#endif +#else +// If rerun_sdk is compiled as static on Windows, RERUN_SDK_EXPORT is defined as an empty macro. +#define RERUN_SDK_EXPORT +#endif +#endif diff --git a/rerun_cpp/tests/CMakeLists.txt b/rerun_cpp/tests/CMakeLists.txt index 3339d80159af..eb1778edcbe0 100644 --- a/rerun_cpp/tests/CMakeLists.txt +++ b/rerun_cpp/tests/CMakeLists.txt @@ -7,8 +7,20 @@ FetchContent_Declare( GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_TAG v3.4.0 ) + +# To avoid that tests to not pass on Windows with BUILD_SHARED_LIBS=ON +# because the loader can't find Catch2.dll, we always compile Catch2 as static +if(WIN32 AND BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS_RERUN_SDK ${BUILD_SHARED_LIBS}) + set(BUILD_SHARED_LIBS OFF) +endif() + FetchContent_MakeAvailable(Catch2) +if(WIN32 AND BUILD_SHARED_LIBS_RERUN_SDK) + set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_RERUN_SDK}) +endif() + file(GLOB_RECURSE rerun_sdk_tests_SRC CONFIGURE_DEPENDS "*.hpp" "*.cpp" diff --git a/scripts/generate_view_coordinate_defs.py b/scripts/generate_view_coordinate_defs.py index a947c6f0dcbc..d11da8b01ce7 100755 --- a/scripts/generate_view_coordinate_defs.py +++ b/scripts/generate_view_coordinate_defs.py @@ -18,7 +18,7 @@ END_MARKER = "" -SCRIPT_PATH = os.path.relpath(__file__, os.getcwd()) +SCRIPT_PATH = os.path.relpath(__file__, os.getcwd()).replace("\\", "/") ################################################################################ @@ -184,7 +184,7 @@ def gen_py_cmp_def() -> list[str]: def cpp_arch_decl(coords: ViewCoordinates) -> str: - return f"static const rerun::archetypes::ViewCoordinates {coords.name};\n" + return f"RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates {coords.name};\n" def gen_cpp_arch_decl() -> list[str]: @@ -225,7 +225,7 @@ def gen_cpp_arch_def() -> list[str]: def cpp_cmp_decl(coords: ViewCoordinates) -> str: - return f"static const rerun::components::ViewCoordinates {coords.name};\n" + return f"RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates {coords.name};\n" def gen_cpp_cmp_decl() -> list[str]: From ab710283351aaf88e3dfe499ce4e712f1b912d35 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 23 Apr 2024 15:58:45 +0200 Subject: [PATCH 346/508] Configurable background color from python code (POC for space view properties from code) (#6068) ### What This is primarily a quick exploration of our ideas on how to log blueprint from (python) code. It worked all well and arrived in a shippable state! The next thing to figure out is how we streamline this with codegen while still preserving all the flexibility that is demonstrated by the different ways of constructing Background3D here (construction as well as component name). Great time for feedback on the general direction! https://github.com/rerun-io/rerun/assets/1220815/b449baac-461c-4eaa-aa10-22f4e97aa38a ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6068?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6068?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6068) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .gitignore | 2 +- .../blueprint/archetypes/background_3d.fbs | 2 +- crates/re_types/source_hash.txt | 4 -- .../src/blueprint/archetypes/background3d.rs | 2 +- .../blueprint/archetypes/background3d.hpp | 2 +- .../rerun_sdk/rerun/blueprint/__init__.py | 6 ++ rerun_py/rerun_sdk/rerun/blueprint/api.py | 8 +++ .../blueprint/archetypes/background3d.py | 33 ++--------- .../blueprint/archetypes/background3d_ext.py | 56 +++++++++++++++++++ .../rerun_sdk/rerun/blueprint/space_views.py | 23 +++++++- rerun_py/tests/unit/test_background3d.py | 25 +++++++++ 11 files changed, 125 insertions(+), 38 deletions(-) delete mode 100644 crates/re_types/source_hash.txt create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d_ext.py create mode 100644 rerun_py/tests/unit/test_background3d.py diff --git a/.gitignore b/.gitignore index e50bd7e5e7d2..eab90c66485b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .DS_Store # Codegen stuff: -crates/re_types/source_hash.txt§ +crates/re_types/source_hash.txt crates/re_types_builder/source_hash.txt # C++ and CMake stuff: diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs index a286231a13fe..ffcc42964c6b 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs @@ -16,7 +16,7 @@ table Background3D ( ) { // --- Required --- - /// The type of the background. Defaults to DirectionalGradient + /// The type of the background. Defaults to Background3DKind.GradientDark. kind: rerun.blueprint.components.Background3DKind ("attr.rerun.component_required", order: 1000); // --- Optional --- diff --git a/crates/re_types/source_hash.txt b/crates/re_types/source_hash.txt deleted file mode 100644 index e1a15f388522..000000000000 --- a/crates/re_types/source_hash.txt +++ /dev/null @@ -1,4 +0,0 @@ -# This is a sha256 hash for all direct and indirect dependencies of this crate's build script. -# It can be safely removed at anytime to force the build script to run again. -# Check out build.rs to see how it's computed. -9db9060d979f575ae784945806bfb6916cb8a5ea12e8edcdd1d29ed79b668cfd diff --git a/crates/re_types/src/blueprint/archetypes/background3d.rs b/crates/re_types/src/blueprint/archetypes/background3d.rs index 944eb079de19..c4041b6df7f1 100644 --- a/crates/re_types/src/blueprint/archetypes/background3d.rs +++ b/crates/re_types/src/blueprint/archetypes/background3d.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: Configuration for the background of the 3D space view. #[derive(Clone, Debug)] pub struct Background3D { - /// The type of the background. Defaults to DirectionalGradient + /// The type of the background. Defaults to Background3DKind.GradientDark. pub kind: crate::blueprint::components::Background3DKind, /// Color used for Background3DKind.SolidColor. diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp index e1e97d9b85dd..f9571abcf615 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp @@ -19,7 +19,7 @@ namespace rerun::blueprint::archetypes { /// **Archetype**: Configuration for the background of the 3D space view. struct Background3D { - /// The type of the background. Defaults to DirectionalGradient + /// The type of the background. Defaults to Background3DKind.GradientDark. rerun::blueprint::components::Background3DKind kind; /// Color used for Background3DKind.SolidColor. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 1062d5442b12..92324fd94f96 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -38,6 +38,12 @@ SpaceView, TimePanel, ) +from .archetypes import ( + Background3D, +) +from .components import ( + Background3DKind, +) from .containers import Grid, Horizontal, Tabs, Vertical from .space_views import ( BarChartView, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 281b28ae9792..1083f509fd47 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -5,6 +5,7 @@ import rerun_bindings as bindings +from .._baseclasses import AsComponents from .._spawn import _spawn_viewer from ..datatypes import EntityPathLike, Utf8ArrayLike, Utf8Like from ..memory import MemoryRecording @@ -41,6 +42,7 @@ def __init__( origin: EntityPathLike, contents: SpaceViewContentsLike, name: Utf8Like | None, + properties: dict[str, AsComponents] = {}, ): """ Construct a blueprint for a new space view. @@ -58,6 +60,8 @@ def __init__( contents The contents of the space view specified as a query expression. This is either a single expression, or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. + properties + Dictionary of property archetypes to add to space view's internal hierarchy. """ self.id = uuid.uuid4() @@ -65,6 +69,7 @@ def __init__( self.name = name self.origin = origin self.contents = contents + self.properties = properties def blueprint_path(self) -> str: """ @@ -104,6 +109,9 @@ def _log_to_stream(self, stream: RecordingStream) -> None: stream.log(self.blueprint_path(), arch, recording=stream) # type: ignore[attr-defined] + for prop_name, prop in self.properties.items(): + stream.log(f"{self.blueprint_path()}/{prop_name}", prop, recording=stream) # type: ignore[attr-defined] + def _repr_html_(self) -> Any: """IPython interface to conversion to html.""" return as_html(blueprint=self) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py index 056c5c413973..77cca6819b3f 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py @@ -5,44 +5,21 @@ from __future__ import annotations -from typing import Any - from attrs import define, field -from ... import components, datatypes +from ... import components from ..._baseclasses import Archetype from ...blueprint import components as blueprint_components -from ...error_utils import catch_and_log_exceptions +from .background3d_ext import Background3DExt __all__ = ["Background3D"] @define(str=False, repr=False, init=False) -class Background3D(Archetype): +class Background3D(Background3DExt, Archetype): """**Archetype**: Configuration for the background of the 3D space view.""" - def __init__( - self: Any, kind: blueprint_components.Background3DKindLike, *, color: datatypes.Rgba32Like | None = None - ): - """ - Create a new instance of the Background3D archetype. - - Parameters - ---------- - kind: - The type of the background. Defaults to DirectionalGradient - color: - Color used for Background3DKind.SolidColor. - - Defaults to White. - - """ - - # You can define your own __init__ function as a member of Background3DExt in background3d_ext.py - with catch_and_log_exceptions(context=self.__class__.__name__): - self.__attrs_init__(kind=kind, color=color) - return - self.__attrs_clear__() + # __init__ can be found in background3d_ext.py def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" @@ -62,7 +39,7 @@ def _clear(cls) -> Background3D: metadata={"component": "required"}, converter=blueprint_components.Background3DKindBatch._required, # type: ignore[misc] ) - # The type of the background. Defaults to DirectionalGradient + # The type of the background. Defaults to Background3DKind.GradientDark. # # (Docstring intentionally commented out to hide this field from the docs) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d_ext.py new file mode 100644 index 000000000000..cce84ea80614 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d_ext.py @@ -0,0 +1,56 @@ +from __future__ import annotations + +from typing import Any + +from ... import datatypes +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + + +class Background3DExt: + """Extension for [Background3D][rerun.blueprint.archetypes.Background3D].""" + + def __init__( + self: Any, + color_or_kind: datatypes.Rgba32Like | blueprint_components.Background3DKindLike | None = None, + *, + color: datatypes.Rgba32Like | None = None, + kind: blueprint_components.Background3DKindLike | None = None, + ): + """ + Create a new instance of the Background3D archetype. + + Parameters + ---------- + color_or_kind: + Either a color for solid background color or kind of the background (see `Background3DKind`). + If set, `color` and `kind` must not be set. + + kind: + The type of the background. Defaults to Background3DKind.GradientDark. + color: + Color used for Background3DKind.SolidColor. + + Defaults to White. + + """ + + with catch_and_log_exceptions(context=self.__class__.__name__): + if color_or_kind is not None: + if color is not None or kind is not None: + raise ValueError("Only one of `color_or_kind` and `color`/`kind` can be set.") + + if isinstance(color_or_kind, blueprint_components.Background3DKind): + kind = color_or_kind + else: + color = color_or_kind # type: ignore[assignment] + + if kind is None: + if color is None: + kind = blueprint_components.Background3DKind.GradientDark + else: + kind = blueprint_components.Background3DKind.SolidColor + + self.__attrs_init__(kind=kind, color=color) + return + self.__attrs_clear__() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py index 347221e6e46a..a298367bb508 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py @@ -1,6 +1,9 @@ from __future__ import annotations -from ..datatypes import EntityPathLike, Utf8Like +from .._baseclasses import AsComponents +from ..datatypes import EntityPathLike, Rgba32Like, Utf8Like +from . import archetypes as blueprint_archetypes +from . import components as blueprint_components from .api import SpaceView, SpaceViewContentsLike @@ -69,6 +72,11 @@ def __init__( origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + # TODO(andreas): codegen everything that comes below: + background: blueprint_components.Background3DKindLike + | Rgba32Like + | blueprint_archetypes.Background3D + | None = None, ): """ Construct a blueprint for a new spatial 3D view. @@ -83,9 +91,20 @@ def __init__( or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. name The name of the view. + background: + Configuration for the background of the 3D space view. """ - super().__init__(class_identifier="3D", origin=origin, contents=contents, name=name) + properties: dict[str, AsComponents] = {} + # TODO(andreas): codegen creation of the properties dict + if background is not None: + properties["Background3D"] = ( + background + if isinstance(background, blueprint_archetypes.Background3D) + else blueprint_archetypes.Background3D(background) + ) + + super().__init__(class_identifier="3D", origin=origin, contents=contents, name=name, properties=properties) class TensorView(SpaceView): diff --git a/rerun_py/tests/unit/test_background3d.py b/rerun_py/tests/unit/test_background3d.py new file mode 100644 index 000000000000..d761111006f5 --- /dev/null +++ b/rerun_py/tests/unit/test_background3d.py @@ -0,0 +1,25 @@ +from __future__ import annotations + +import pytest +import rerun as rr +import rerun.blueprint as rrb + + +def test_background_3d_construction() -> None: + rr.set_strict_mode(True) + + assert rrb.Background3D((1.0, 0.0, 0.0)) == rrb.Background3D( + color=(1.0, 0.0, 0.0), kind=rrb.Background3DKind.SolidColor + ) + assert rrb.Background3D(rrb.Background3DKind.GradientBright) == rrb.Background3D( + color=None, kind=rrb.Background3DKind.GradientBright + ) + + with pytest.raises(ValueError): + rrb.Background3D(rrb.Background3DKind.GradientBright, kind=rrb.Background3DKind.GradientDark) + with pytest.raises(ValueError): + rrb.Background3D(rrb.Background3DKind.GradientBright, color=(0.0, 1.0, 0.0)) + with pytest.raises(ValueError): + rrb.Background3D((1.0, 0.0, 0.0), kind=rrb.Background3DKind.GradientDark) + with pytest.raises(ValueError): + rrb.Background3D((1.0, 0.0, 0.0), color=(0.0, 1.0, 0.0)) From 9d4f8a5d4bcb2fd92f1cc03abf03851864d72206 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 23 Apr 2024 17:36:50 +0200 Subject: [PATCH 347/508] Fix CI build of rerun_c on Linux ARM (#6086) ### What Silence a lint that would trigger only on linux arm because apparently `c_char` is something else there than elsewhere. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6086?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6086?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6086) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/rerun_c/src/error.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/rerun_c/src/error.rs b/crates/rerun_c/src/error.rs index b600142ac7bd..08b45e35197e 100644 --- a/crates/rerun_c/src/error.rs +++ b/crates/rerun_c/src/error.rs @@ -29,7 +29,12 @@ impl CError { c.encode_utf8(&mut bytes); for byte in &bytes[..c.len_utf8()] { - message_c[bytes_next] = *byte as _; + // `c_char` is something different depending on platforms, and this is needed for + // when it's the same as `u8`. + #[allow(trivial_numeric_casts)] + { + message_c[bytes_next] = *byte as _; + } bytes_next += 1; } } From a33f2b684c640a9da5be7c8d26da3d2bc75b1af5 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 23 Apr 2024 21:28:22 +0200 Subject: [PATCH 348/508] Don't override rerun task in wheel-test environment (#6087) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What Having the task defined in two environments creates the annoying behavior of: ``` $ pixi run rerun ? The task 'rerun' can be run in multiple environments. Please select an environment to run the task in: › ❯ default cpp py-docs wheel-test ``` We only used that task in one place in the wheel tests, so rename it to be clear. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6087?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6087?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6087) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/reusable_test_wheels.yml | 2 +- pixi.toml | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index a53d3fd1477b..9f0d5aece1c0 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -172,7 +172,7 @@ jobs: run: | pixi run -e wheel-test python -m rerun --version pixi run -e wheel-test which rerun - pixi run -e wheel-test rerun --version + pixi run -e wheel-test rerun-from-path --version - name: Run unit tests run: cd rerun_py/tests && pixi run -e wheel-test pytest -c ../pyproject.toml diff --git a/pixi.toml b/pixi.toml index 1256125e5933..641ed1875f45 100644 --- a/pixi.toml +++ b/pixi.toml @@ -243,9 +243,10 @@ torch = ">=2.0.1" pip = ">=23" [feature.wheel-test.tasks] -# In the wheel-test environment we want to use the wheel-installed `rerun` binary on the path. -# This overrides the `rerun` task from the default env which otherwise executes via cargo. -rerun = "rerun" +# In the wheel-test environment we want to confirm the`rerun` binary on the path executes as expected. +# However, since `rerun` is already its own task, we can't just `pixi run rerun`. This task lets us work +# around that and executes `rerun` from the system shell within the context of the pixi environment. +rerun-from-path = "rerun" # Run the Python tests. # Don't call this on CI - use `nox` to run tests on all supported Python versions instead. From 7b5eaafdadf3264612eaa2f5bb8db01d7c562314 Mon Sep 17 00:00:00 2001 From: Mathieu De Coster Date: Wed, 24 Apr 2024 12:12:19 +0200 Subject: [PATCH 349/508] Update the example in configure-viewer-through-code.md to use subclasses of `SpaceView` (#6092) ### What Whereas the Python API docs say that we should use subclasses of `SpaceView` instead of `SpaceView` directly (see [here](https://ref.rerun.io/docs/python/0.15.1/common/blueprint_apis/#rerun.blueprint.SpaceView)), the [blueprint documentation](https://www.rerun.io/docs/howto/configure-viewer-through-code) uses `SpaceView` with a subclass as positional argument to the constructor of the `SpaceView`. Not only is this contradictory, the example that is currently in the online docs does not run for me in version 0.15.1, see the error below. ``` Traceback (most recent call last): File "rerun_blueprint_test.py", line 6, in rrb.SpaceView(rrb.BarChartView()), TypeError: SpaceView.__init__() takes 1 positional argument but 2 were given ``` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [ ] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6092?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6092?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [ ] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6092) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- docs/content/howto/configure-viewer-through-code.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/howto/configure-viewer-through-code.md b/docs/content/howto/configure-viewer-through-code.md index 649d17003c19..8664db4a3bd9 100644 --- a/docs/content/howto/configure-viewer-through-code.md +++ b/docs/content/howto/configure-viewer-through-code.md @@ -37,10 +37,10 @@ For example: ```python my_blueprint = rrb.Blueprint( rrb.Horizontal( - rrb.SpaceView(rrb.BarChartView()), + rrb.BarChartView(), rrb.Vertical( - rrb.SpaceView(rrb.Spatial2DView()), - rrb.SpaceView(rrb.Spatial3DView()), + rrb.Spatial2DView(), + rrb.Spatial3DView(), ), ), ) From 9cdb234c996d68b7a9369dd772d16f8e1f7bf6fa Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 24 Apr 2024 14:09:51 +0200 Subject: [PATCH 350/508] Fix broken `log_timeless` on C++ (#6095) ### What * Fixes https://github.com/rerun-io/cpp-example-opencv-eigen/issues/25 * Huge thanks once more to @traversaro who saved us from doing a patch release on this after the next release, very unlikely we would have noticed in time! `log_timeless` broke when it got deprecated: this didn't get caught since the error only shows up when the template is instantiated - added a regression test to address this. (think Python ;-) T_T) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6095?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6095?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6095) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- rerun_cpp/src/rerun/recording_stream.hpp | 2 +- rerun_cpp/tests/recording_stream.cpp | 82 ++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/rerun_cpp/src/rerun/recording_stream.hpp b/rerun_cpp/src/rerun/recording_stream.hpp index 4646b44ebdcf..31df9f46374b 100644 --- a/rerun_cpp/src/rerun/recording_stream.hpp +++ b/rerun_cpp/src/rerun/recording_stream.hpp @@ -346,7 +346,7 @@ namespace rerun { [[deprecated("Use `log_static` instead")]] void log_timeless( std::string_view entity_path, const Ts&... archetypes_or_collections ) const { - return log_static(entity_path, true, archetypes_or_collections...); + return log_static(entity_path, archetypes_or_collections...); } /// Logs one or more archetype and/or component batches as static data. diff --git a/rerun_cpp/tests/recording_stream.cpp b/rerun_cpp/tests/recording_stream.cpp index 88840e3c9f62..4c6d4ff31d01 100644 --- a/rerun_cpp/tests/recording_stream.cpp +++ b/rerun_cpp/tests/recording_stream.cpp @@ -567,3 +567,85 @@ SCENARIO("RecordingStream can set time without errors", TEST_TAG) { check_logged_error([&] { stream.disable_timeline("exists"); }); } } + +// Regression test for https://github.com/rerun-io/cpp-example-opencv-eigen/issues/25 +SCENARIO("Deprecated log_timeless still works", TEST_TAG) { + rerun::RecordingStream stream("test"); + + // Disable deprecation warnings for this test since this is testing deprecated functionality. + RR_PUSH_WARNINGS + RR_DISABLE_DEPRECATION_WARNING + + GIVEN("a new RecordingStream and valid entity paths") { + THEN("components as std::initializer_list can be logged") { + const auto c_style_array = { + rerun::components::Position2D{1.0, 2.0}, + rerun::components::Position2D{4.0, 5.0}, + }; + stream.log_timeless("as-initializer-list", c_style_array); + } + + THEN("components as std::array can be logged") { + stream.log_timeless( + "as-array", + std::array{ + rerun::Vec2D{1.0, 2.0}, + rerun::Vec2D{4.0, 5.0}, + } + ); + } + + THEN("components as std::vector can be logged") { + stream.log_timeless( + "as-vector", + std::vector{ + rerun::Vec2D{1.0, 2.0}, + rerun::Vec2D{4.0, 5.0}, + } + ); + } + + THEN("several components with a mix of vector, array and c-array can be logged") { + rerun::Text c_style_array[3] = { + rerun::Text("hello"), + rerun::Text("friend"), + rerun::Text("yo"), + }; + stream.log_timeless( + "as-mix", + std::vector{ + rerun::Position2D(rerun::Vec2D{0.0, 0.0}), + rerun::Position2D(rerun::Vec2D{1.0, 3.0}), + rerun::Position2D(rerun::Vec2D{5.0, 5.0}), + }, + std::array{ + rerun::Color(0xFF0000FF), + rerun::Color(0x00FF00FF), + rerun::Color(0x0000FFFF), + }, + c_style_array + ); + } + + THEN("components with splatting some of them can be logged") { + stream.log_timeless( + "log-splat", + std::vector{ + rerun::Position2D(rerun::Vec2D{0.0, 0.0}), + rerun::Position2D(rerun::Vec2D{1.0, 3.0}), + }, + std::array{rerun::Color(0xFF0000FF)} + ); + } + + THEN("an archetype can be logged") { + stream.log_timeless( + "log_archetype-splat", + rerun::Points2D({rerun::Vec2D{1.0, 2.0}, rerun::Vec2D{4.0, 5.0}} + ).with_colors(rerun::Color(0xFF0000FF)) + ); + } + } + + RR_POP_WARNINGS // For `RR_DISABLE_DEPRECATION_WARNING`. +} From 33901180c14291735187139161462407f7ba4b19 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 24 Apr 2024 15:33:05 +0200 Subject: [PATCH 351/508] Remove link checker cache (#6098) ### What The cache was causing issues with us detecting dead links much much later. Also, strangely it previously reported to check over [5k](https://github.com/rerun-io/rerun/actions/runs/8816269511/job/24200018649) links and now only about [1k](https://github.com/rerun-io/rerun/actions/runs/8817096256/job/24202674748?pr=6098). This is now on-par with what I get on a fresh rerun checkout locally. Doesn't make any sense to me... To further dodge issues with github rate limiting I also included now our rerun github issue links. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6098?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6098?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6098) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/reusable_checks.yml | 9 +-------- lychee.toml | 1 + 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index cc9fc9c2e55e..0a819397352b 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -168,13 +168,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Restore link checker cache - uses: actions/cache@v4 - with: - path: .lycheecache - key: cache-lychee-${{ github.sha }} - restore-keys: cache-lychee- - # Check https://github.com/lycheeverse/lychee on how to run locally. - name: Link Checker id: lychee @@ -185,4 +178,4 @@ jobs: # When given a directory, lychee checks only markdown, html and text files, everything else we have to glob in manually. # Pass --verbose, so that all considered links are printed, making it easier to debug. args: | - --verbose --base . --cache --max-cache-age 1d . "**/*.rs" "**/*.toml" "**/*.hpp" "**/*.cpp" "**/CMakeLists.txt" "**/*.py" "**/*.yml" + --verbose --base . "**/*.rs" "**/*.toml" "**/*.hpp" "**/*.cpp" "**/CMakeLists.txt" "**/*.py" "**/*.yml" diff --git a/lychee.toml b/lychee.toml index 0d396e251977..ddd36f7a24e5 100644 --- a/lychee.toml +++ b/lychee.toml @@ -84,6 +84,7 @@ exclude = [ 'https://crates.io/crates/.*', # Avoid crates.io rate-limiting 'https://github.com/rerun-io/rerun/commit/\.*', # Ignore links to our own commits (typically in changelog). 'https://github.com/rerun-io/rerun/pull/\.*', # Ignore links to our own pull requests (typically in changelog). + 'https://github.com/rerun-io/rerun/issues/\.*', # Ignore links to our own issues. # Intentionally faked links. 'file://foo', From 890925b3123477d929bf6232a8d6c643388fd892 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Wed, 24 Apr 2024 16:28:57 +0200 Subject: [PATCH 352/508] Don't fail CI workflow when link checks fail (#6097) ### What Links check have proven flaky given it relies on remote servers to cooperate. It's pretty annoying when entire workflow fails (e.g. `nightly`) just because of a 500 error. This PR marks the link check step with `continue-on-error: true`. - Fixes https://github.com/rerun-io/rerun/issues/6055 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6097?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6097?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6097) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/reusable_checks.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 0a819397352b..53d770c3c22a 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -165,6 +165,8 @@ jobs: link-checker: name: Check links runs-on: ubuntu-latest + # do not fail entire workflow (e.g. nightly) if this is the only failing check + continue-on-error: true steps: - uses: actions/checkout@v4 From 7962fea0307b6ad33c7fd8f2f0f5f1f4114decfe Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Wed, 24 Apr 2024 18:27:23 +0200 Subject: [PATCH 353/508] Add new CMake target `ALL` to workaround CMake lying about built-in `all` target (#6091) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What While investigating https://github.com/rerun-io/cpp-example-opencv-eigen/issues/25 I noticed that our `cpp-build-all` command didn't actually build all targets 😱 The reason for this is as simple as it is absolutely idiotic: https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#selecting-a-target > The default target used by Makefile and Ninja generators. Builds all targets in the buildsystem, except those which are excluded by their [EXCLUDE_FROM_ALL](https://cmake.org/cmake/help/latest/prop_tgt/EXCLUDE_FROM_ALL.html#prop_tgt:EXCLUDE_FROM_ALL) target property or [EXCLUDE_FROM_ALL](https://cmake.org/cmake/help/latest/prop_dir/EXCLUDE_FROM_ALL.html#prop_dir:EXCLUDE_FROM_ALL) directory property. The name ALL_BUILD is used for this purpose for the Xcode and Visual Studio generators. At this point I'm trusting no-one and instead of relying on a combination of `ALL_BUILD` and `all` create our own `ALL` target by manually listing targets, that way I can at least debug it. (unfortunately it didn't get me a repro of the linked compilation issue within Rerun, still working on that) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6091?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6091?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6091) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- CMakeLists.txt | 33 +++++++++++++++++++++++++++++++++ pixi.toml | 4 ++-- rerun_cpp/src/rerun/c/rerun.h | 2 +- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03cd2d0dab0a..ae47f6e87d1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,3 +178,36 @@ add_subdirectory(rerun_cpp) # The Rerun C++ SDK library. add_subdirectory(examples/cpp) add_subdirectory(tests/cpp) add_subdirectory(docs/snippets) + +# ------------------------------------------------------------------------------ +# Setup an 'all_targets' target that depends on all targets in the project. +# +# CMake already has an `all` (lowercase!) target as the default, +# but it does NOT work with Visual Studio and XCode. +# See https://cmake.org/cmake/help/latest/guide/user-interaction/index.html#selecting-a-target + +# Collect all currently added targets in all subdirectories +# +# Via: https://stackoverflow.com/a/60232044 +# +# Parameters: +# - _result the list containing all found targets +# - _dir root directory to start looking from +function(get_all_targets _result _dir) + get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES) + + foreach(_subdir IN LISTS _subdirs) + get_all_targets(${_result} "${_subdir}") + endforeach() + + get_directory_property(_sub_targets DIRECTORY "${_dir}" BUILDSYSTEM_TARGETS) + set(${_result} ${${_result}} ${_sub_targets} PARENT_SCOPE) +endfunction() + +get_all_targets(all_targets ${CMAKE_CURRENT_SOURCE_DIR}) + +add_custom_target(ALL DEPENDS ${all_targets}) + +foreach(target IN LISTS all_targets_list) + add_dependencies(ALL ${target}) +endforeach() diff --git a/pixi.toml b/pixi.toml index 641ed1875f45..48bfc76dc0b6 100644 --- a/pixi.toml +++ b/pixi.toml @@ -196,11 +196,11 @@ py-docs-serve = "mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py" # All the cpp-* tasks can be configured with environment variables, e.g.: RERUN_WERROR=ON CXX=clang++ cpp-prepare-release = "cmake -G 'Ninja' -B build/release -S . -DCMAKE_BUILD_TYPE=Release" cpp-prepare = "cmake -G 'Ninja' -B build/debug -S . -DCMAKE_BUILD_TYPE=Debug" -cpp-build-all = { cmd = "cmake --build build/debug --config Debug --target all", depends_on = [ +cpp-build-all = { cmd = "cmake --build build/debug --config Debug --target ALL", depends_on = [ "cpp-prepare", ] } cpp-prepare-shared-libs = "cmake -G 'Ninja' -B build/debug -S . -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON" -cpp-build-all-shared-libs = { cmd = "cmake --build build/debug --config Debug --target all", depends_on = [ +cpp-build-all-shared-libs = { cmd = "cmake --build build/debug --config Debug --target ALL", depends_on = [ "cpp-prepare-shared-libs", ] } cpp-clean = "rm -rf build CMakeCache.txt CMakeFiles" diff --git a/rerun_cpp/src/rerun/c/rerun.h b/rerun_cpp/src/rerun/c/rerun.h index 614f3f5c3d41..8ff584a5173b 100644 --- a/rerun_cpp/src/rerun/c/rerun.h +++ b/rerun_cpp/src/rerun/c/rerun.h @@ -268,7 +268,7 @@ typedef struct rr_error { /// /// This should match the string returned by `rr_version_string`. /// If not, the SDK's binary and the C header are out of sync. -#define RERUN_SDK_HEADER_VERSION "0.16.0-alpha.1+dev" +#define RERUN_SDK_HEADER_VERSION "0.16.0-alpha.2" /// Returns a human-readable version string of the Rerun C SDK. /// From 45ec26a8652480bca60d8dcf09570140f1426e71 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 25 Apr 2024 09:16:48 +0200 Subject: [PATCH 354/508] Use same pixi version on all of CI (0.20.0) (#6088) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) - [PR Build Summary](https://build.rerun.io/pr/6088) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/auto_approve.yml | 4 +- .github/workflows/auto_release_crates.yml | 4 +- .github/workflows/checkboxes.yml | 4 +- .github/workflows/contrib_checks.yml | 20 +- .github/workflows/contrib_rerun_py.yml | 4 +- .../on_pull_request_target_contrib.yml | 4 +- .github/workflows/on_push_docs.yml | 8 +- .github/workflows/release.yml | 8 +- .../reusable_build_and_upload_rerun_cli.yml | 4 +- .../reusable_build_and_upload_wheels.yml | 4 +- .github/workflows/reusable_build_examples.yml | 4 +- .github/workflows/reusable_build_js.yml | 4 +- .github/workflows/reusable_build_web.yml | 4 +- .github/workflows/reusable_checks.yml | 12 +- .github/workflows/reusable_checks_cpp.yml | 4 +- .github/workflows/reusable_checks_python.yml | 4 +- .github/workflows/reusable_checks_rust.yml | 4 +- .github/workflows/reusable_deploy_docs.yml | 4 +- .github/workflows/reusable_pr_summary.yml | 4 +- .github/workflows/reusable_publish_js.yml | 4 +- .github/workflows/reusable_publish_web.yml | 4 +- .github/workflows/reusable_publish_wheels.yml | 4 +- .github/workflows/reusable_release_crates.yml | 4 +- .github/workflows/reusable_run_notebook.yml | 4 +- .../reusable_sync_release_assets.yml | 4 +- .github/workflows/reusable_test_wheels.yml | 4 +- .github/workflows/reusable_update_pr_body.yml | 4 +- pixi.lock | 4143 +++++++++-------- 28 files changed, 2150 insertions(+), 2133 deletions(-) diff --git a/.github/workflows/auto_approve.yml b/.github/workflows/auto_approve.yml index 98cfa3423233..632aa9bfb765 100644 --- a/.github/workflows/auto_approve.yml +++ b/.github/workflows/auto_approve.yml @@ -24,9 +24,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.18.0 + pixi-version: v0.20.0 - name: Wait a few seconds run: | diff --git a/.github/workflows/auto_release_crates.yml b/.github/workflows/auto_release_crates.yml index 3674be6dfd33..131f013d1e29 100644 --- a/.github/workflows/auto_release_crates.yml +++ b/.github/workflows/auto_release_crates.yml @@ -24,9 +24,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Update crate versions run: pixi run python scripts/ci/crates.py version --bump prerelease diff --git a/.github/workflows/checkboxes.yml b/.github/workflows/checkboxes.yml index a1bdfcea6577..60ebeb6636f4 100644 --- a/.github/workflows/checkboxes.yml +++ b/.github/workflows/checkboxes.yml @@ -32,9 +32,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.18.0 + pixi-version: v0.20.0 - name: Check PR checkboxes run: | diff --git a/.github/workflows/contrib_checks.yml b/.github/workflows/contrib_checks.yml index 999a85e098af..84af4b7bc0ba 100644 --- a/.github/workflows/contrib_checks.yml +++ b/.github/workflows/contrib_checks.yml @@ -45,9 +45,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Python format check run: pixi run py-fmt-check @@ -86,9 +86,9 @@ jobs: # PR introduces a new type and another PR changes the codegen. - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Codegen check run: pixi run codegen --force --check @@ -99,9 +99,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Rust checks & tests run: pixi run rs-check --skip-check-individual-crates @@ -112,9 +112,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Rerun lints run: pixi run lint-rerun @@ -157,9 +157,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 environments: cpp # TODO(emilk): make this work somehow. Right now this just results in diff --git a/.github/workflows/contrib_rerun_py.yml b/.github/workflows/contrib_rerun_py.yml index 42ac3002a308..54783fdc46f0 100644 --- a/.github/workflows/contrib_rerun_py.yml +++ b/.github/workflows/contrib_rerun_py.yml @@ -51,9 +51,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 environments: wheel-test - name: Run Python unit-tests diff --git a/.github/workflows/on_pull_request_target_contrib.yml b/.github/workflows/on_pull_request_target_contrib.yml index 2761cd52f93f..3bf85853ac6b 100644 --- a/.github/workflows/on_pull_request_target_contrib.yml +++ b/.github/workflows/on_pull_request_target_contrib.yml @@ -27,9 +27,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Update PR description run: | diff --git a/.github/workflows/on_push_docs.yml b/.github/workflows/on_push_docs.yml index 1c0b7b7ad1bf..4d58c6a22cc5 100644 --- a/.github/workflows/on_push_docs.yml +++ b/.github/workflows/on_push_docs.yml @@ -30,9 +30,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Get version id: versioning @@ -55,9 +55,9 @@ jobs: service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} toolchains: "nightly" - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Install rerun-sdk run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 436fa3011e1f..ea34f9b538f3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -82,9 +82,9 @@ jobs: with: node-version: 18 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Update crate versions id: versioning @@ -377,9 +377,9 @@ jobs: with: node-version: 18 - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Commit new version run: | diff --git a/.github/workflows/reusable_build_and_upload_rerun_cli.yml b/.github/workflows/reusable_build_and_upload_rerun_cli.yml index bfcddc4dd0a1..0bd2e54a119f 100644 --- a/.github/workflows/reusable_build_and_upload_rerun_cli.yml +++ b/.github/workflows/reusable_build_and_upload_rerun_cli.yml @@ -162,9 +162,9 @@ jobs: service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} targets: ${{ needs.set-config.outputs.TARGET }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Build web-viewer (release) run: pixi run rerun-build-web-release diff --git a/.github/workflows/reusable_build_and_upload_wheels.yml b/.github/workflows/reusable_build_and_upload_wheels.yml index 75e2b3be99d8..fb13ed486573 100644 --- a/.github/workflows/reusable_build_and_upload_wheels.yml +++ b/.github/workflows/reusable_build_and_upload_wheels.yml @@ -187,9 +187,9 @@ jobs: service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} targets: ${{ needs.set-config.outputs.TARGET }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Get sha id: get-sha diff --git a/.github/workflows/reusable_build_examples.yml b/.github/workflows/reusable_build_examples.yml index 56b186d75f56..101943a41fb0 100644 --- a/.github/workflows/reusable_build_examples.yml +++ b/.github/workflows/reusable_build_examples.yml @@ -62,9 +62,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 environments: wheel-test - name: Download Wheel diff --git a/.github/workflows/reusable_build_js.yml b/.github/workflows/reusable_build_js.yml index 26a1ae9bc3bc..ecdbc65c79e7 100644 --- a/.github/workflows/reusable_build_js.yml +++ b/.github/workflows/reusable_build_js.yml @@ -64,9 +64,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.3.0 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Install yarn dependencies run: pixi run yarn --cwd rerun_js install diff --git a/.github/workflows/reusable_build_web.yml b/.github/workflows/reusable_build_web.yml index 7367398b9903..e3143bfdfbb1 100644 --- a/.github/workflows/reusable_build_web.yml +++ b/.github/workflows/reusable_build_web.yml @@ -64,9 +64,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Build web-viewer (release) run: | diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index 53d770c3c22a..c414f6efb0be 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -84,9 +84,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Codegen check run: pixi run codegen --force --check @@ -101,9 +101,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Set up Python uses: actions/setup-python@v5 @@ -153,9 +153,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: prettier --check run: pixi run misc-fmt-check diff --git a/.github/workflows/reusable_checks_cpp.yml b/.github/workflows/reusable_checks_cpp.yml index 3756ce1a5997..f0b70a7fb4ae 100644 --- a/.github/workflows/reusable_checks_cpp.yml +++ b/.github/workflows/reusable_checks_cpp.yml @@ -66,9 +66,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 environments: cpp - name: Set up Rust diff --git a/.github/workflows/reusable_checks_python.yml b/.github/workflows/reusable_checks_python.yml index ea692ba4d9e9..b0c9e4a84863 100644 --- a/.github/workflows/reusable_checks_python.yml +++ b/.github/workflows/reusable_checks_python.yml @@ -33,9 +33,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Python format check run: pixi run py-fmt-check diff --git a/.github/workflows/reusable_checks_rust.yml b/.github/workflows/reusable_checks_rust.yml index 36f2d32099ae..8b6396af6a21 100644 --- a/.github/workflows/reusable_checks_rust.yml +++ b/.github/workflows/reusable_checks_rust.yml @@ -61,9 +61,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Rust checks & tests if: ${{ inputs.CHANNEL == 'pr' }} diff --git a/.github/workflows/reusable_deploy_docs.yml b/.github/workflows/reusable_deploy_docs.yml index 528c09d39ac7..61ebcd9163c7 100644 --- a/.github/workflows/reusable_deploy_docs.yml +++ b/.github/workflows/reusable_deploy_docs.yml @@ -201,9 +201,9 @@ jobs: fetch-depth: 0 # Don't do a shallow clone since we need to push gh-pages ref: ${{ inputs.RELEASE_COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || '') }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Doxygen C++ docs run: pixi run cpp-docs diff --git a/.github/workflows/reusable_pr_summary.yml b/.github/workflows/reusable_pr_summary.yml index 8fa2a0b3cab8..fb1b1ae994ee 100644 --- a/.github/workflows/reusable_pr_summary.yml +++ b/.github/workflows/reusable_pr_summary.yml @@ -35,9 +35,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.18.0 + pixi-version: v0.20.0 - id: "auth" uses: google-github-actions/auth@v2 diff --git a/.github/workflows/reusable_publish_js.yml b/.github/workflows/reusable_publish_js.yml index a6e0d57b2e8c..a32925520c50 100644 --- a/.github/workflows/reusable_publish_js.yml +++ b/.github/workflows/reusable_publish_js.yml @@ -63,9 +63,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.3.0 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Publish packages env: diff --git a/.github/workflows/reusable_publish_web.yml b/.github/workflows/reusable_publish_web.yml index 4b2487c2d7af..1d7cd7d5a681 100644 --- a/.github/workflows/reusable_publish_web.yml +++ b/.github/workflows/reusable_publish_web.yml @@ -74,9 +74,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 environments: wheel-test # built by `reusable_build_and_publish_wheels` diff --git a/.github/workflows/reusable_publish_wheels.yml b/.github/workflows/reusable_publish_wheels.yml index 01f11e8d329a..2440db9da677 100644 --- a/.github/workflows/reusable_publish_wheels.yml +++ b/.github/workflows/reusable_publish_wheels.yml @@ -153,9 +153,9 @@ jobs: fetch-depth: 0 # Don't do a shallow clone since we need it for finding the full commit hash ref: ${{ inputs.release-commit }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - id: "auth" uses: google-github-actions/auth@v2 diff --git a/.github/workflows/reusable_release_crates.yml b/.github/workflows/reusable_release_crates.yml index 8aff0babf399..b1e92da2bacd 100644 --- a/.github/workflows/reusable_release_crates.yml +++ b/.github/workflows/reusable_release_crates.yml @@ -28,9 +28,9 @@ jobs: with: ref: ${{ inputs.RELEASE_COMMIT || (github.event_name == 'pull_request' && github.event.pull_request.head.ref || '') }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 - name: Build web-viewer (release) run: pixi run rerun-build-web-release diff --git a/.github/workflows/reusable_run_notebook.yml b/.github/workflows/reusable_run_notebook.yml index 0b7527c43f5e..7871cc0dc155 100644 --- a/.github/workflows/reusable_run_notebook.yml +++ b/.github/workflows/reusable_run_notebook.yml @@ -37,9 +37,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 environments: wheel-test - name: Download Wheel diff --git a/.github/workflows/reusable_sync_release_assets.yml b/.github/workflows/reusable_sync_release_assets.yml index cc8a1c56bd7b..ccca340b830b 100644 --- a/.github/workflows/reusable_sync_release_assets.yml +++ b/.github/workflows/reusable_sync_release_assets.yml @@ -39,9 +39,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.18.0 + pixi-version: v0.20.0 - id: "auth" uses: google-github-actions/auth@v2 diff --git a/.github/workflows/reusable_test_wheels.yml b/.github/workflows/reusable_test_wheels.yml index 9f0d5aece1c0..4318f20c2c97 100644 --- a/.github/workflows/reusable_test_wheels.yml +++ b/.github/workflows/reusable_test_wheels.yml @@ -145,9 +145,9 @@ jobs: workload_identity_provider: ${{ secrets.GOOGLE_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.19.1 + pixi-version: v0.20.0 environments: wheel-test - name: Download Wheel diff --git a/.github/workflows/reusable_update_pr_body.yml b/.github/workflows/reusable_update_pr_body.yml index ea7a867a3bcc..0b1913ba057d 100644 --- a/.github/workflows/reusable_update_pr_body.yml +++ b/.github/workflows/reusable_update_pr_body.yml @@ -35,9 +35,9 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} - - uses: prefix-dev/setup-pixi@v0.5.2 + - uses: prefix-dev/setup-pixi@v0.6.0 with: - pixi-version: v0.18.0 + pixi-version: v0.20.0 - name: Update PR description run: | diff --git a/pixi.lock b/pixi.lock index 817d6b830c71..7ee3d63d6078 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1892,7 +1892,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/b1/2331e6b1fc8c61686dd9276f34142265462640eb0dd431246e30c4461065/peewee-3.17.3.tar.gz - pypi: https://files.pythonhosted.org/packages/81/ff/ad3c942d865f9e45ce84eeb31795e6d4d94e1f1eea51026d5154028510d7/pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/14/619e24a4c70df2901e1f4dbc50a6291eb63a759172558df326347dce1f0d/protobuf-3.20.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/4f/0e22aaa246f96d6ac87fe5ebb9c5a693fbe8877f537a1022527c47ca43c5/psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl @@ -1900,7 +1900,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl @@ -1927,7 +1927,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/2a/14/e75e52d521442e2fcc9f1df3c5e456aead034203d4797867980de558ab34/tqdm-4.66.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/09/c8/844d5518a6aeb4ffdc0cf0cae65ae13dbe5838306728c5c640b5a6e2a0c9/transformers-4.40.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/90/2596ac2ab49c4df6ff1fceaf7f5afb18401ba2f326348ce1a6261a65e7ed/transformers-4.40.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/40/c93b1215980d6d31119f742a5702a569b3abce363d68c731d69f312f292c/trimesh-3.15.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bd/ac/3974caaa459bf2c3a244a84be8d17561f631f7d42af370fc311defeca2fb/triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl @@ -2050,7 +2050,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/b1/2331e6b1fc8c61686dd9276f34142265462640eb0dd431246e30c4461065/peewee-3.17.3.tar.gz - pypi: https://files.pythonhosted.org/packages/e5/51/e4b35e394b4e5ca24983e50361a1db3d7da05b1758074f9c4f5b4be4b22a/pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/14/619e24a4c70df2901e1f4dbc50a6291eb63a759172558df326347dce1f0d/protobuf-3.20.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl @@ -2058,7 +2058,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl @@ -2085,7 +2085,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/2a/14/e75e52d521442e2fcc9f1df3c5e456aead034203d4797867980de558ab34/tqdm-4.66.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/09/c8/844d5518a6aeb4ffdc0cf0cae65ae13dbe5838306728c5c640b5a6e2a0c9/transformers-4.40.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/90/2596ac2ab49c4df6ff1fceaf7f5afb18401ba2f326348ce1a6261a65e7ed/transformers-4.40.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/40/c93b1215980d6d31119f742a5702a569b3abce363d68c731d69f312f292c/trimesh-3.15.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/01/f3/936e209267d6ef7510322191003885de524fc48d1b43269810cd589ceaf5/typing_extensions-4.11.0-py3-none-any.whl @@ -2207,7 +2207,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/b1/2331e6b1fc8c61686dd9276f34142265462640eb0dd431246e30c4461065/peewee-3.17.3.tar.gz - pypi: https://files.pythonhosted.org/packages/00/5c/7633f291def20082bad31b844fe5ed07742aae8504e4cfe2f331ee727178/pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/14/619e24a4c70df2901e1f4dbc50a6291eb63a759172558df326347dce1f0d/protobuf-3.20.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl @@ -2215,7 +2215,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl @@ -2242,7 +2242,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/2a/14/e75e52d521442e2fcc9f1df3c5e456aead034203d4797867980de558ab34/tqdm-4.66.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/09/c8/844d5518a6aeb4ffdc0cf0cae65ae13dbe5838306728c5c640b5a6e2a0c9/transformers-4.40.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/90/2596ac2ab49c4df6ff1fceaf7f5afb18401ba2f326348ce1a6261a65e7ed/transformers-4.40.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/40/c93b1215980d6d31119f742a5702a569b3abce363d68c731d69f312f292c/trimesh-3.15.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/01/f3/936e209267d6ef7510322191003885de524fc48d1b43269810cd589ceaf5/typing_extensions-4.11.0-py3-none-any.whl @@ -2376,7 +2376,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7a/b1/2331e6b1fc8c61686dd9276f34142265462640eb0dd431246e30c4461065/peewee-3.17.3.tar.gz - pypi: https://files.pythonhosted.org/packages/0a/16/c83877524c47976f16703d2e05c363244bc1e60ab439e078b3cd046d07db/pillow-10.3.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8d/14/619e24a4c70df2901e1f4dbc50a6291eb63a759172558df326347dce1f0d/protobuf-3.20.3-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/52/3e39d26feae7df0aa0fd510b14012c3678b36ed068f7d78b8d8784d61f0e/psutil-5.9.8-cp37-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl @@ -2384,7 +2384,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl @@ -2411,7 +2411,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/2a/14/e75e52d521442e2fcc9f1df3c5e456aead034203d4797867980de558ab34/tqdm-4.66.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/09/c8/844d5518a6aeb4ffdc0cf0cae65ae13dbe5838306728c5c640b5a6e2a0c9/transformers-4.40.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/cf/90/2596ac2ab49c4df6ff1fceaf7f5afb18401ba2f326348ce1a6261a65e7ed/transformers-4.40.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/40/c93b1215980d6d31119f742a5702a569b3abce363d68c731d69f312f292c/trimesh-3.15.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/01/f3/936e209267d6ef7510322191003885de524fc48d1b43269810cd589ceaf5/typing_extensions-4.11.0-py3-none-any.whl @@ -3414,23 +3414,23 @@ packages: url: https://files.pythonhosted.org/packages/53/fe/0251ccd9e0015c705e772da0fb2c96cdafd87b1d7dd45dc13dca7ced0eb7/accelerate-0.29.3-py3-none-any.whl sha256: 99d633d4b6126817c5e554487406748be95c8d1d1e659dd2fd60657e35f532dd requires_dist: - - numpy >=1.17 - - packaging >=20.0 + - numpy>=1.17 + - packaging>=20.0 - psutil - pyyaml - - torch >=1.10.0 + - torch>=1.10.0 - huggingface-hub - - safetensors >=0.3.1 - - black ~=23.1 ; extra == 'dev' - - hf-doc-builder >=0.3.0 ; extra == 'dev' - - ruff ~=0.2.1 ; extra == 'dev' - - pytest <=8.0.0, >=7.2.0 ; extra == 'dev' + - safetensors>=0.3.1 + - black~=23.1 ; extra == 'dev' + - hf-doc-builder>=0.3.0 ; extra == 'dev' + - ruff~=0.2.1 ; extra == 'dev' + - pytest<=8.0.0,>=7.2.0 ; extra == 'dev' - pytest-xdist ; extra == 'dev' - pytest-subtests ; extra == 'dev' - parameterized ; extra == 'dev' - datasets ; extra == 'dev' - evaluate ; extra == 'dev' - - torchpippy >=0.2.0 ; extra == 'dev' + - torchpippy>=0.2.0 ; extra == 'dev' - transformers ; extra == 'dev' - scipy ; extra == 'dev' - scikit-learn ; extra == 'dev' @@ -3439,14 +3439,14 @@ packages: - bitsandbytes ; extra == 'dev' - timm ; extra == 'dev' - rich ; extra == 'dev' - - black ~=23.1 ; extra == 'quality' - - hf-doc-builder >=0.3.0 ; extra == 'quality' - - ruff ~=0.2.1 ; extra == 'quality' + - black~=23.1 ; extra == 'quality' + - hf-doc-builder>=0.3.0 ; extra == 'quality' + - ruff~=0.2.1 ; extra == 'quality' - rich ; extra == 'rich' - sagemaker ; extra == 'sagemaker' - datasets ; extra == 'test_dev' - evaluate ; extra == 'test_dev' - - torchpippy >=0.2.0 ; extra == 'test_dev' + - torchpippy>=0.2.0 ; extra == 'test_dev' - transformers ; extra == 'test_dev' - scipy ; extra == 'test_dev' - scikit-learn ; extra == 'test_dev' @@ -3454,7 +3454,7 @@ packages: - tqdm ; extra == 'test_dev' - bitsandbytes ; extra == 'test_dev' - timm ; extra == 'test_dev' - - pytest <=8.0.0, >=7.2.0 ; extra == 'test_prod' + - pytest<=8.0.0,>=7.2.0 ; extra == 'test_prod' - pytest-xdist ; extra == 'test_prod' - pytest-subtests ; extra == 'test_prod' - parameterized ; extra == 'test_prod' @@ -3462,13 +3462,13 @@ packages: - comet-ml ; extra == 'test_trackers' - tensorboard ; extra == 'test_trackers' - dvclive ; extra == 'test_trackers' - - pytest <=8.0.0, >=7.2.0 ; extra == 'testing' + - pytest<=8.0.0,>=7.2.0 ; extra == 'testing' - pytest-xdist ; extra == 'testing' - pytest-subtests ; extra == 'testing' - parameterized ; extra == 'testing' - datasets ; extra == 'testing' - evaluate ; extra == 'testing' - - torchpippy >=0.2.0 ; extra == 'testing' + - torchpippy>=0.2.0 ; extra == 'testing' - transformers ; extra == 'testing' - scipy ; extra == 'testing' - scikit-learn ; extra == 'testing' @@ -3662,7 +3662,7 @@ packages: requires_dist: - importlib-metadata ; python_version < '3.8' - attrs[tests] ; extra == 'cov' - - coverage[toml] >=5.3 ; extra == 'cov' + - coverage[toml]>=5.3 ; extra == 'cov' - attrs[tests] ; extra == 'dev' - pre-commit ; extra == 'dev' - furo ; extra == 'docs' @@ -3674,14 +3674,14 @@ packages: - zope-interface ; extra == 'docs' - attrs[tests-no-zope] ; extra == 'tests' - zope-interface ; extra == 'tests' - - mypy >=1.6 ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' + - mypy>=1.6 ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' - pytest-mypy-plugins ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' - attrs[tests-mypy] ; extra == 'tests-no-zope' - cloudpickle ; platform_python_implementation == 'CPython' and extra == 'tests-no-zope' - hypothesis ; extra == 'tests-no-zope' - pympler ; extra == 'tests-no-zope' - pytest-xdist[psutil] ; extra == 'tests-no-zope' - - pytest >=4.3.0 ; extra == 'tests-no-zope' + - pytest>=4.3.0 ; extra == 'tests-no-zope' requires_python: '>=3.7' - kind: conda name: attrs @@ -6898,7 +6898,7 @@ packages: url: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl sha256: b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed requires_dist: - - soupsieve >1.2 + - soupsieve>1.2 - cchardet ; extra == 'cchardet' - chardet ; extra == 'chardet' - charset-normalizer ; extra == 'charset-normalizer' @@ -7089,19 +7089,19 @@ packages: url: https://files.pythonhosted.org/packages/0a/ef/37666bae20ba77d9a8420867077879fc0fd26e60e734ba5ee5ebc46f72fb/black-24.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 5cd5b4f76056cecce3e69b0d4c228326d2595f506797f40b9233424e2524c070 requires_dist: - - click >=8.0.0 - - mypy-extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9.0 - - platformdirs >=2 - - tomli >=1.1.0 ; python_version < '3.11' - - typing-extensions >=4.0.1 ; python_version < '3.11' - - colorama >=0.4.3 ; extra == 'colorama' - - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython >=7.8.0 ; extra == 'jupyter' - - tokenize-rt >=3.2.0 ; extra == 'jupyter' - - uvloop >=0.15.2 ; extra == 'uvloop' + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - tomli>=1.1.0 ; python_version < '3.11' + - typing-extensions>=4.0.1 ; python_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black @@ -7109,19 +7109,19 @@ packages: url: https://files.pythonhosted.org/packages/97/a6/f5857f79bba7eca05ebdc7e27e3447e3d2fc23898bb04f34bf3ff5dfb2db/black-24.4.0-cp311-cp311-macosx_11_0_arm64.whl sha256: 64e60a7edd71fd542a10a9643bf369bfd2644de95ec71e86790b063aa02ff745 requires_dist: - - click >=8.0.0 - - mypy-extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9.0 - - platformdirs >=2 - - tomli >=1.1.0 ; python_version < '3.11' - - typing-extensions >=4.0.1 ; python_version < '3.11' - - colorama >=0.4.3 ; extra == 'colorama' - - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython >=7.8.0 ; extra == 'jupyter' - - tokenize-rt >=3.2.0 ; extra == 'jupyter' - - uvloop >=0.15.2 ; extra == 'uvloop' + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - tomli>=1.1.0 ; python_version < '3.11' + - typing-extensions>=4.0.1 ; python_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black @@ -7129,19 +7129,19 @@ packages: url: https://files.pythonhosted.org/packages/cb/95/4a02a0fed559bf638001f6bf4e4c9d685111db959d221485e7e27c91e954/black-24.4.0-cp311-cp311-macosx_10_9_x86_64.whl sha256: 8e5537f456a22cf5cfcb2707803431d2feeb82ab3748ade280d6ccd0b40ed2e8 requires_dist: - - click >=8.0.0 - - mypy-extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9.0 - - platformdirs >=2 - - tomli >=1.1.0 ; python_version < '3.11' - - typing-extensions >=4.0.1 ; python_version < '3.11' - - colorama >=0.4.3 ; extra == 'colorama' - - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython >=7.8.0 ; extra == 'jupyter' - - tokenize-rt >=3.2.0 ; extra == 'jupyter' - - uvloop >=0.15.2 ; extra == 'uvloop' + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - tomli>=1.1.0 ; python_version < '3.11' + - typing-extensions>=4.0.1 ; python_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black @@ -7149,19 +7149,19 @@ packages: url: https://files.pythonhosted.org/packages/0f/11/fa05ac9429d971d0fc10da85f24dafc3fa5788733fbd0d1c186b7577cefd/black-24.4.0-cp311-cp311-win_amd64.whl sha256: 64578cf99b6b46a6301bc28bdb89f9d6f9b592b1c5837818a177c98525dbe397 requires_dist: - - click >=8.0.0 - - mypy-extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9.0 - - platformdirs >=2 - - tomli >=1.1.0 ; python_version < '3.11' - - typing-extensions >=4.0.1 ; python_version < '3.11' - - colorama >=0.4.3 ; extra == 'colorama' - - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython >=7.8.0 ; extra == 'jupyter' - - tokenize-rt >=3.2.0 ; extra == 'jupyter' - - uvloop >=0.15.2 ; extra == 'uvloop' + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - tomli>=1.1.0 ; python_version < '3.11' + - typing-extensions>=4.0.1 ; python_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: blueprint @@ -7892,72 +7892,72 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 + url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 requires_python: '>=3.7.0' - kind: conda name: charset-normalizer @@ -9150,15 +9150,15 @@ packages: url: https://files.pythonhosted.org/packages/ee/c0/9bd123d676eb61750e116a2cd915b06483fc406143cfc36c7f263f0f5368/contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df requires_dist: - - numpy >=1.20 + - numpy>=1.20 - furo ; extra == 'docs' - - sphinx >=7.2 ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy ==1.8.0 ; extra == 'mypy' + - mypy==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9174,15 +9174,15 @@ packages: url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 requires_dist: - - numpy >=1.20 + - numpy>=1.20 - furo ; extra == 'docs' - - sphinx >=7.2 ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy ==1.8.0 ; extra == 'mypy' + - mypy==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9198,15 +9198,15 @@ packages: url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 requires_dist: - - numpy >=1.20 + - numpy>=1.20 - furo ; extra == 'docs' - - sphinx >=7.2 ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy ==1.8.0 ; extra == 'mypy' + - mypy==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9222,15 +9222,15 @@ packages: url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 requires_dist: - - numpy >=1.20 + - numpy>=1.20 - furo ; extra == 'docs' - - sphinx >=7.2 ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy ==1.8.0 ; extra == 'mypy' + - mypy==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9247,34 +9247,34 @@ packages: sha256: 655921f31d08f05f5399715d72bd5a5bab6af08b9b04716b0855a7493659acf8 requires_dist: - accelerate - - diffusers ==0.27.2 - - numpy - opencv-python - pillow - - rerun-sdk + - diffusers==0.27.2 + - numpy - torch - transformers + - rerun-sdk requires_python: '>=3.10' editable: true - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 + url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9282,27 +9282,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 + url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9310,27 +9310,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb + url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9338,27 +9338,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9366,27 +9366,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d + url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9394,27 +9394,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl - sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c + url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl + sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9422,27 +9422,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl - sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b + url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl + sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9450,7 +9450,7 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: conda name: cxx-compiler @@ -9530,8 +9530,8 @@ packages: url: https://files.pythonhosted.org/packages/91/ca/7219b838086086972e662c19e908694bdc6744537fb41b70392501b8b5e4/dataclasses_json-0.6.4-py3-none-any.whl sha256: f90578b8a3177f7552f4e1a6e535e84293cd5da421fcce0642d49c0d7bdf8df2 requires_dist: - - marshmallow >=3.18.0, <4.0.0 - - typing-inspect >=0.4.0, <1 + - marshmallow>=3.18.0,<4.0.0 + - typing-inspect>=0.4.0,<1 requires_python: '>=3.7,<4.0' - kind: pypi name: deprecated @@ -9539,12 +9539,12 @@ packages: url: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl sha256: 6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c requires_dist: - - wrapt <2, >=1.10 + - wrapt<2,>=1.10 - tox ; extra == 'dev' - pytest ; extra == 'dev' - pytest-cov ; extra == 'dev' - - bump2version <1 ; extra == 'dev' - - sphinx <2 ; extra == 'dev' + - bump2version<1 ; extra == 'dev' + - sphinx<2 ; extra == 'dev' requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' - kind: pypi name: detect-and-track-objects @@ -9553,13 +9553,13 @@ packages: sha256: c8419d3c804263d1287fc17c21419116fe8ae6fec83cc6026162eb521e12437f requires_dist: - numpy - - opencv-contrib-python >4.6 - - opencv-python >4.6 + - opencv-contrib-python>4.6 + - opencv-python>4.6 - pillow - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - - timm ==0.9.11 - - torch >=1.13.0 + - timm==0.9.11 + - torch>=1.13.0 - transformers editable: true - kind: pypi @@ -9568,12 +9568,12 @@ packages: path: examples/python/dicom_mri sha256: 98cb91dc5758ae59e3cd0fb797f86f40fcf627f63e659365806f59feed4618d8 requires_dist: - - dicom-numpy ==0.6.2 + - dicom-numpy==0.6.2 - numpy - - pydicom ==2.3.0 - - requests <3, >=2.31 + - pydicom==2.3.0 + - requests>=2.31,<3 - rerun-sdk - - types-requests <3, >=2.31 + - types-requests>=2.31,<3 editable: true - kind: pypi name: dicom-numpy @@ -9581,7 +9581,7 @@ packages: url: https://files.pythonhosted.org/packages/a4/d2/6d475e8925fa3f46f676263bfc6bdcf1e20273a433b296b1d63abecd2426/dicom_numpy-0.6.2-py2.py3-none-any.whl sha256: 361c8dfc52d625bf3344e5c2745e9c928d263999a4c094fe285d9fe461895ea9 requires_dist: - - pydicom >=1.0 + - pydicom>=1.0 - numpy - check-manifest ; extra == 'dev' - sphinx ; extra == 'dev' @@ -9597,74 +9597,74 @@ packages: requires_dist: - importlib-metadata - filelock - - huggingface-hub >=0.20.2 + - huggingface-hub>=0.20.2 - numpy - - regex !=2019.12.17 + - regex!=2019.12.17 - requests - - safetensors >=0.3.1 + - safetensors>=0.3.1 - pillow - - urllib3 <=2.0.0 ; extra == 'dev' - - isort >=5.5.4 ; extra == 'dev' - - ruff ==0.1.5 ; extra == 'dev' - - hf-doc-builder >=0.3.0 ; extra == 'dev' - - compel ==0.1.8 ; extra == 'dev' - - gitpython <3.1.19 ; extra == 'dev' + - urllib3<=2.0.0 ; extra == 'dev' + - isort>=5.5.4 ; extra == 'dev' + - ruff==0.1.5 ; extra == 'dev' + - hf-doc-builder>=0.3.0 ; extra == 'dev' + - compel==0.1.8 ; extra == 'dev' + - gitpython<3.1.19 ; extra == 'dev' - datasets ; extra == 'dev' - jinja2 ; extra == 'dev' - - invisible-watermark >=0.2.0 ; extra == 'dev' - - k-diffusion >=0.0.12 ; extra == 'dev' + - invisible-watermark>=0.2.0 ; extra == 'dev' + - k-diffusion>=0.0.12 ; extra == 'dev' - librosa ; extra == 'dev' - parameterized ; extra == 'dev' - pytest ; extra == 'dev' - pytest-timeout ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - requests-mock ==1.10.0 ; extra == 'dev' - - safetensors >=0.3.1 ; extra == 'dev' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev' + - requests-mock==1.10.0 ; extra == 'dev' + - safetensors>=0.3.1 ; extra == 'dev' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev' - scipy ; extra == 'dev' - torchvision ; extra == 'dev' - - transformers >=4.25.1 ; extra == 'dev' - - accelerate >=0.11.0 ; extra == 'dev' - - protobuf <4, >=3.20.3 ; extra == 'dev' + - transformers>=4.25.1 ; extra == 'dev' + - accelerate>=0.11.0 ; extra == 'dev' + - protobuf<4,>=3.20.3 ; extra == 'dev' - tensorboard ; extra == 'dev' - - peft >=0.6.0 ; extra == 'dev' - - torch >=1.4 ; extra == 'dev' - - jax >=0.4.1 ; extra == 'dev' - - jaxlib >=0.4.1 ; extra == 'dev' - - flax >=0.4.1 ; extra == 'dev' - - hf-doc-builder >=0.3.0 ; extra == 'docs' - - jax >=0.4.1 ; extra == 'flax' - - jaxlib >=0.4.1 ; extra == 'flax' - - flax >=0.4.1 ; extra == 'flax' - - urllib3 <=2.0.0 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - ruff ==0.1.5 ; extra == 'quality' - - hf-doc-builder >=0.3.0 ; extra == 'quality' - - compel ==0.1.8 ; extra == 'test' - - gitpython <3.1.19 ; extra == 'test' + - peft>=0.6.0 ; extra == 'dev' + - torch>=1.4 ; extra == 'dev' + - jax>=0.4.1 ; extra == 'dev' + - jaxlib>=0.4.1 ; extra == 'dev' + - flax>=0.4.1 ; extra == 'dev' + - hf-doc-builder>=0.3.0 ; extra == 'docs' + - jax>=0.4.1 ; extra == 'flax' + - jaxlib>=0.4.1 ; extra == 'flax' + - flax>=0.4.1 ; extra == 'flax' + - urllib3<=2.0.0 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - ruff==0.1.5 ; extra == 'quality' + - hf-doc-builder>=0.3.0 ; extra == 'quality' + - compel==0.1.8 ; extra == 'test' + - gitpython<3.1.19 ; extra == 'test' - datasets ; extra == 'test' - jinja2 ; extra == 'test' - - invisible-watermark >=0.2.0 ; extra == 'test' - - k-diffusion >=0.0.12 ; extra == 'test' + - invisible-watermark>=0.2.0 ; extra == 'test' + - k-diffusion>=0.0.12 ; extra == 'test' - librosa ; extra == 'test' - parameterized ; extra == 'test' - pytest ; extra == 'test' - pytest-timeout ; extra == 'test' - pytest-xdist ; extra == 'test' - - requests-mock ==1.10.0 ; extra == 'test' - - safetensors >=0.3.1 ; extra == 'test' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'test' + - requests-mock==1.10.0 ; extra == 'test' + - safetensors>=0.3.1 ; extra == 'test' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'test' - scipy ; extra == 'test' - torchvision ; extra == 'test' - - transformers >=4.25.1 ; extra == 'test' - - torch >=1.4 ; extra == 'torch' - - accelerate >=0.11.0 ; extra == 'torch' - - accelerate >=0.11.0 ; extra == 'training' + - transformers>=4.25.1 ; extra == 'test' + - torch>=1.4 ; extra == 'torch' + - accelerate>=0.11.0 ; extra == 'torch' + - accelerate>=0.11.0 ; extra == 'training' - datasets ; extra == 'training' - - protobuf <4, >=3.20.3 ; extra == 'training' + - protobuf<4,>=3.20.3 ; extra == 'training' - tensorboard ; extra == 'training' - jinja2 ; extra == 'training' - - peft >=0.6.0 ; extra == 'training' + - peft>=0.6.0 ; extra == 'training' requires_python: '>=3.8.0' - kind: pypi name: distlib @@ -9807,10 +9807,10 @@ packages: path: examples/python/face_tracking sha256: b8725fe4d36c11aad2c6c936ba2b57c7f65a856aa179badca5d041db63119d55 requires_dist: - - mediapipe ==0.10.11 ; sys_platform != 'darwin' - - mediapipe ==0.10.9 ; sys_platform == 'darwin' + - mediapipe==0.10.11 ; sys_platform != 'darwin' + - mediapipe==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python >4.6 + - opencv-python>4.6 - requests - rerun-sdk - tqdm @@ -9822,17 +9822,17 @@ packages: url: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl sha256: 404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f requires_dist: - - furo >=2023.9.10 ; extra == 'docs' - - sphinx-autodoc-typehints !=1.23.4, >=1.25.2 ; extra == 'docs' - - sphinx >=7.2.6 ; extra == 'docs' - - covdefaults >=2.3 ; extra == 'testing' - - coverage >=7.3.2 ; extra == 'testing' - - diff-cover >=8.0.1 ; extra == 'testing' - - pytest-cov >=4.1 ; extra == 'testing' - - pytest-mock >=3.12 ; extra == 'testing' - - pytest-timeout >=2.2 ; extra == 'testing' - - pytest >=7.4.3 ; extra == 'testing' - - typing-extensions >=4.8 ; python_version < '3.11' and extra == 'typing' + - furo>=2023.9.10 ; extra == 'docs' + - sphinx-autodoc-typehints!=1.23.4,>=1.25.2 ; extra == 'docs' + - sphinx>=7.2.6 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'testing' + - coverage>=7.3.2 ; extra == 'testing' + - diff-cover>=8.0.1 ; extra == 'testing' + - pytest-cov>=4.1 ; extra == 'testing' + - pytest-mock>=3.12 ; extra == 'testing' + - pytest-timeout>=2.2 ; extra == 'testing' + - pytest>=7.4.3 ; extra == 'testing' + - typing-extensions>=4.8 ; python_version < '3.11' and extra == 'typing' requires_python: '>=3.8' - kind: pypi name: flatbuffers @@ -9997,36 +9997,36 @@ packages: url: https://files.pythonhosted.org/packages/c6/b5/dc17e93f60567fa1b0fa3720c2f28e0df5293927e2356e066e87af9adaba/fonttools-4.51.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: b2b92381f37b39ba2fc98c3a45a9d6383bfc9916a87d66ccb6553f7bdd129097 requires_dist: - - fs <3, >=2.2.0 ; extra == 'all' - - lxml >=4.0 ; extra == 'all' - - zopfli >=0.1.4 ; extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'all' + - fs<3,>=2.2.0 ; extra == 'all' + - lxml>=4.0 ; extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops >=0.5.0 ; extra == 'all' - - uharfbuzz >=0.23.0 ; extra == 'all' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.23.0 ; extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'graphite' + - lz4>=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml >=4.0 ; extra == 'lxml' - - skia-pathops >=0.5.0 ; extra == 'pathops' + - lxml>=4.0 ; extra == 'lxml' + - skia-pathops>=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz >=0.23.0 ; extra == 'repacker' + - uharfbuzz>=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs <3, >=2.2.0 ; extra == 'ufo' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli >=0.1.4 ; extra == 'woff' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs<3,>=2.2.0 ; extra == 'ufo' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli>=0.1.4 ; extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools @@ -10034,36 +10034,36 @@ packages: url: https://files.pythonhosted.org/packages/33/47/f2ca671af61757eaaac608963dda5b76ec9100621e45d0fd63a153fd8cd7/fonttools-4.51.0-cp311-cp311-macosx_10_9_universal2.whl sha256: a8feca65bab31479d795b0d16c9a9852902e3a3c0630678efb0b2b7941ea9c74 requires_dist: - - fs <3, >=2.2.0 ; extra == 'all' - - lxml >=4.0 ; extra == 'all' - - zopfli >=0.1.4 ; extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'all' + - fs<3,>=2.2.0 ; extra == 'all' + - lxml>=4.0 ; extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops >=0.5.0 ; extra == 'all' - - uharfbuzz >=0.23.0 ; extra == 'all' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.23.0 ; extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'graphite' + - lz4>=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml >=4.0 ; extra == 'lxml' - - skia-pathops >=0.5.0 ; extra == 'pathops' + - lxml>=4.0 ; extra == 'lxml' + - skia-pathops>=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz >=0.23.0 ; extra == 'repacker' + - uharfbuzz>=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs <3, >=2.2.0 ; extra == 'ufo' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli >=0.1.4 ; extra == 'woff' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs<3,>=2.2.0 ; extra == 'ufo' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli>=0.1.4 ; extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools @@ -10071,36 +10071,36 @@ packages: url: https://files.pythonhosted.org/packages/84/51/8203a3e6e475e6766ac950638d42f45470f36c6a4f0615ff0a1c1f2ed0d6/fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl sha256: 8ac27f436e8af7779f0bb4d5425aa3535270494d3bc5459ed27de3f03151e4c2 requires_dist: - - fs <3, >=2.2.0 ; extra == 'all' - - lxml >=4.0 ; extra == 'all' - - zopfli >=0.1.4 ; extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'all' + - fs<3,>=2.2.0 ; extra == 'all' + - lxml>=4.0 ; extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops >=0.5.0 ; extra == 'all' - - uharfbuzz >=0.23.0 ; extra == 'all' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.23.0 ; extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'graphite' + - lz4>=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml >=4.0 ; extra == 'lxml' - - skia-pathops >=0.5.0 ; extra == 'pathops' + - lxml>=4.0 ; extra == 'lxml' + - skia-pathops>=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz >=0.23.0 ; extra == 'repacker' + - uharfbuzz>=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs <3, >=2.2.0 ; extra == 'ufo' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli >=0.1.4 ; extra == 'woff' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs<3,>=2.2.0 ; extra == 'ufo' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli>=0.1.4 ; extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools @@ -10108,36 +10108,36 @@ packages: url: https://files.pythonhosted.org/packages/c5/d4/f426fa1ca42e47bcfff0c878fa9d49d9c03379d00903a7c178f95b97867a/fonttools-4.51.0-cp311-cp311-win_amd64.whl sha256: 0f08c901d3866a8905363619e3741c33f0a83a680d92a9f0e575985c2634fcc1 requires_dist: - - fs <3, >=2.2.0 ; extra == 'all' - - lxml >=4.0 ; extra == 'all' - - zopfli >=0.1.4 ; extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'all' + - fs<3,>=2.2.0 ; extra == 'all' + - lxml>=4.0 ; extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops >=0.5.0 ; extra == 'all' - - uharfbuzz >=0.23.0 ; extra == 'all' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.23.0 ; extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'graphite' + - lz4>=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml >=4.0 ; extra == 'lxml' - - skia-pathops >=0.5.0 ; extra == 'pathops' + - lxml>=4.0 ; extra == 'lxml' + - skia-pathops>=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz >=0.23.0 ; extra == 'repacker' + - uharfbuzz>=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs <3, >=2.2.0 ; extra == 'ufo' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli >=0.1.4 ; extra == 'woff' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs<3,>=2.2.0 ; extra == 'ufo' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli>=0.1.4 ; extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: freetype-py @@ -10263,7 +10263,7 @@ packages: requires_dist: - adlfs ; extra == 'abfs' - adlfs ; extra == 'adl' - - pyarrow >=1 ; extra == 'arrow' + - pyarrow>=1 ; extra == 'arrow' - dask ; extra == 'dask' - distributed ; extra == 'dask' - pytest ; extra == 'devel' @@ -10272,7 +10272,7 @@ packages: - requests ; extra == 'dropbox' - dropbox ; extra == 'dropbox' - adlfs ; extra == 'full' - - aiohttp !=4.0.0a0, !=4.0.0a1 ; extra == 'full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' - dask ; extra == 'full' - distributed ; extra == 'full' - dropbox ; extra == 'full' @@ -10283,7 +10283,7 @@ packages: - ocifs ; extra == 'full' - panel ; extra == 'full' - paramiko ; extra == 'full' - - pyarrow >=1 ; extra == 'full' + - pyarrow>=1 ; extra == 'full' - pygit2 ; extra == 'full' - requests ; extra == 'full' - s3fs ; extra == 'full' @@ -10295,8 +10295,8 @@ packages: - requests ; extra == 'github' - gcsfs ; extra == 'gs' - panel ; extra == 'gui' - - pyarrow >=1 ; extra == 'hdfs' - - aiohttp !=4.0.0a0, !=4.0.0a1 ; extra == 'http' + - pyarrow>=1 ; extra == 'hdfs' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' - libarchive-c ; extra == 'libarchive' - ocifs ; extra == 'oci' - s3fs ; extra == 's3' @@ -10417,11 +10417,11 @@ packages: path: examples/python/gesture_detection sha256: 36dfc4cc822ee47f7aa29ba951bab8a94e96b9fd737daa324a441e6962a620bd requires_dist: - - mediapipe ==0.10.11 ; sys_platform != 'darwin' - - mediapipe ==0.10.9 ; sys_platform == 'darwin' + - mediapipe==0.10.11 ; sys_platform != 'darwin' + - mediapipe==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python >4.9 - - requests <3, >=2.31 + - opencv-python>4.9 + - requests>=2.31,<3 - rerun-sdk - tqdm requires_python: <3.12 @@ -10737,17 +10737,17 @@ packages: url: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl sha256: 5a63aa102e0049abe85b5b88cb9409234c1f70afcda21ce1e40b285b9629c1d6 requires_dist: - - googleapis-common-protos <2.0.dev0, >=1.56.2 - - protobuf !=3.20.0, !=3.20.1, !=4.21.0, !=4.21.1, !=4.21.2, !=4.21.3, !=4.21.4, !=4.21.5, <5.0.0.dev0, >=3.19.5 - - proto-plus <2.0.0.dev0, >=1.22.3 - - google-auth <3.0.dev0, >=2.14.1 - - requests <3.0.0.dev0, >=2.18.0 - - grpcio <2.0.dev0, >=1.33.2 ; extra == 'grpc' - - grpcio-status <2.0.dev0, >=1.33.2 ; extra == 'grpc' - - grpcio <2.0.dev0, >=1.49.1 ; python_version >= '3.11' and extra == 'grpc' - - grpcio-status <2.0.dev0, >=1.49.1 ; python_version >= '3.11' and extra == 'grpc' - - grpcio-gcp <1.0.dev0, >=0.2.2 ; extra == 'grpcgcp' - - grpcio-gcp <1.0.dev0, >=0.2.2 ; extra == 'grpcio-gcp' + - googleapis-common-protos<2.0.dev0,>=1.56.2 + - protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0,>=3.19.5 + - proto-plus<2.0.0.dev0,>=1.22.3 + - google-auth<3.0.dev0,>=2.14.1 + - requests<3.0.0.dev0,>=2.18.0 + - grpcio<2.0.dev0,>=1.33.2 ; extra == 'grpc' + - grpcio-status<2.0.dev0,>=1.33.2 ; extra == 'grpc' + - grpcio<2.0.dev0,>=1.49.1 ; python_version >= '3.11' and extra == 'grpc' + - grpcio-status<2.0.dev0,>=1.49.1 ; python_version >= '3.11' and extra == 'grpc' + - grpcio-gcp<1.0.dev0,>=0.2.2 ; extra == 'grpcgcp' + - grpcio-gcp<1.0.dev0,>=0.2.2 ; extra == 'grpcio-gcp' requires_python: '>=3.7' - kind: pypi name: google-auth @@ -10755,17 +10755,17 @@ packages: url: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl sha256: d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415 requires_dist: - - cachetools <6.0, >=2.0.0 - - pyasn1-modules >=0.2.1 - - rsa <5, >=3.1.4 - - aiohttp <4.0.0.dev0, >=3.6.2 ; extra == 'aiohttp' - - requests <3.0.0.dev0, >=2.20.0 ; extra == 'aiohttp' - - cryptography ==36.0.2 ; extra == 'enterprise_cert' - - pyopenssl ==22.0.0 ; extra == 'enterprise_cert' - - pyopenssl >=20.0.0 ; extra == 'pyopenssl' - - cryptography >=38.0.3 ; extra == 'pyopenssl' - - pyu2f >=0.1.5 ; extra == 'reauth' - - requests <3.0.0.dev0, >=2.20.0 ; extra == 'requests' + - cachetools<6.0,>=2.0.0 + - pyasn1-modules>=0.2.1 + - rsa<5,>=3.1.4 + - aiohttp<4.0.0.dev0,>=3.6.2 ; extra == 'aiohttp' + - requests<3.0.0.dev0,>=2.20.0 ; extra == 'aiohttp' + - cryptography==36.0.2 ; extra == 'enterprise_cert' + - pyopenssl==22.0.0 ; extra == 'enterprise_cert' + - pyopenssl>=20.0.0 ; extra == 'pyopenssl' + - cryptography>=38.0.3 ; extra == 'pyopenssl' + - pyu2f>=0.1.5 ; extra == 'reauth' + - requests<3.0.0.dev0,>=2.20.0 ; extra == 'requests' requires_python: '>=3.7' - kind: pypi name: google-cloud-core @@ -10773,11 +10773,11 @@ packages: url: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl sha256: a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61 requires_dist: - - google-api-core !=2.0.*, !=2.1.*, !=2.2.*, !=2.3.0, <3.0.0.dev0, >=1.31.6 - - google-auth <3.0.dev0, >=1.25.0 - - importlib-metadata >1.0.0 ; python_version < '3.8' - - grpcio <2.0.dev0, >=1.38.0 ; extra == 'grpc' - - grpcio-status <2.0.dev0, >=1.38.0 ; extra == 'grpc' + - google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0.dev0,>=1.31.6 + - google-auth<3.0.dev0,>=1.25.0 + - importlib-metadata>1.0.0 ; python_version < '3.8' + - grpcio<2.0.dev0,>=1.38.0 ; extra == 'grpc' + - grpcio-status<2.0.dev0,>=1.38.0 ; extra == 'grpc' requires_python: '>=3.7' - kind: pypi name: google-cloud-storage @@ -10785,50 +10785,50 @@ packages: url: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl sha256: 83a90447f23d5edd045e0037982c270302e3aeb45fc1288d2c2ca713d27bad94 requires_dist: - - google-auth <3.0.dev0, >=1.25.0 - - google-api-core !=2.0.*, !=2.1.*, !=2.2.*, !=2.3.0, <3.0.0.dev0, >=1.31.5 - - google-cloud-core <3.0.dev0, >=2.3.0 - - google-resumable-media >=2.3.2 - - requests <3.0.0.dev0, >=2.18.0 - - protobuf <5.0.0.dev0 ; extra == 'protobuf' + - google-auth<3.0.dev0,>=1.25.0 + - google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0.dev0,>=1.31.5 + - google-cloud-core<3.0.dev0,>=2.3.0 + - google-resumable-media>=2.3.2 + - requests<3.0.0.dev0,>=2.18.0 + - protobuf<5.0.0.dev0 ; extra == 'protobuf' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 + url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -10838,10 +10838,10 @@ packages: url: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl sha256: 79543cfe433b63fd81c0844b7803aba1bb8950b47bedf7d980c38fa123937e08 requires_dist: - - google-crc32c <2.0.dev0, >=1.0 - - aiohttp <4.0.0.dev0, >=3.6.2 ; extra == 'aiohttp' - - google-auth <2.0.dev0, >=1.22.0 ; extra == 'aiohttp' - - requests <3.0.0.dev0, >=2.18.0 ; extra == 'requests' + - google-crc32c<2.0.dev0,>=1.0 + - aiohttp<4.0.0.dev0,>=3.6.2 ; extra == 'aiohttp' + - google-auth<2.0.dev0,>=1.22.0 ; extra == 'aiohttp' + - requests<3.0.0.dev0,>=2.18.0 ; extra == 'requests' requires_python: '>=3.7' - kind: pypi name: googleapis-common-protos @@ -10849,8 +10849,8 @@ packages: url: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl sha256: ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632 requires_dist: - - protobuf !=3.20.0, !=3.20.1, !=4.21.1, !=4.21.2, !=4.21.3, !=4.21.4, !=4.21.5, <5.0.0.dev0, >=3.19.5 - - grpcio <2.0.0.dev0, >=1.44.0 ; extra == 'grpc' + - protobuf!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0,>=3.19.5 + - grpcio<2.0.0.dev0,>=1.44.0 ; extra == 'grpc' requires_python: '>=3.7' - kind: pypi name: grpclib @@ -10858,9 +10858,9 @@ packages: url: https://files.pythonhosted.org/packages/79/b9/55936e462a5925190d7427e880b3033601d1effd13809b483d13a926061a/grpclib-0.4.7.tar.gz sha256: 2988ef57c02b22b7a2e8e961792c41ccf97efc2ace91ae7a5b0de03c363823c3 requires_dist: - - h2 <5, >=3.1.0 + - h2<5,>=3.1.0 - multidict - - protobuf >=3.20.0 ; extra == 'protobuf' + - protobuf>=3.20.0 ; extra == 'protobuf' requires_python: '>=3.7' - kind: conda name: gxx @@ -10970,8 +10970,8 @@ packages: url: https://files.pythonhosted.org/packages/2a/e5/db6d438da759efbb488c4f3fbdab7764492ff3c3f953132efa6b9f0e9e53/h2-4.1.0-py3-none-any.whl sha256: 03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d requires_dist: - - hyperframe <7, >=6.0 - - hpack <5, >=4.0 + - hyperframe<7,>=6.0 + - hpack<5,>=4.0 requires_python: '>=3.6.1' - kind: pypi name: hpack @@ -10985,12 +10985,12 @@ packages: url: https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl sha256: 0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d requires_dist: - - six >=1.9 + - six>=1.9 - webencodings - genshi ; extra == 'all' - - chardet >=2.2 ; extra == 'all' + - chardet>=2.2 ; extra == 'all' - lxml ; platform_python_implementation == 'CPython' and extra == 'all' - - chardet >=2.2 ; extra == 'chardet' + - chardet>=2.2 ; extra == 'chardet' - genshi ; extra == 'genshi' - lxml ; platform_python_implementation == 'CPython' and extra == 'lxml' requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' @@ -11001,15 +11001,15 @@ packages: sha256: 3429e25f38ccb834d310804a3b711e7e4953db5a9e420cc147a5e194ca90fd17 requires_dist: - filelock - - fsspec >=2023.5.0 - - packaging >=20.9 - - pyyaml >=5.1 + - fsspec>=2023.5.0 + - packaging>=20.9 + - pyyaml>=5.1 - requests - - tqdm >=4.42.1 - - typing-extensions >=3.7.4.3 - - inquirerpy ==0.3.4 ; extra == 'all' + - tqdm>=4.42.1 + - typing-extensions>=3.7.4.3 + - inquirerpy==0.3.4 ; extra == 'all' - aiohttp ; extra == 'all' - - minijinja >=1.0 ; extra == 'all' + - minijinja>=1.0 ; extra == 'all' - jedi ; extra == 'all' - jinja2 ; extra == 'all' - pytest ; extra == 'all' @@ -11019,24 +11019,24 @@ packages: - pytest-vcr ; extra == 'all' - pytest-asyncio ; extra == 'all' - pytest-rerunfailures ; extra == 'all' - - urllib3 <2.0 ; extra == 'all' + - urllib3<2.0 ; extra == 'all' - soundfile ; extra == 'all' - pillow ; extra == 'all' - gradio ; extra == 'all' - numpy ; extra == 'all' - - ruff >=0.3.0 ; extra == 'all' - - mypy ==1.5.1 ; extra == 'all' - - typing-extensions >=4.8.0 ; extra == 'all' + - ruff>=0.3.0 ; extra == 'all' + - mypy==1.5.1 ; extra == 'all' + - typing-extensions>=4.8.0 ; extra == 'all' - types-pyyaml ; extra == 'all' - types-requests ; extra == 'all' - types-simplejson ; extra == 'all' - types-toml ; extra == 'all' - types-tqdm ; extra == 'all' - types-urllib3 ; extra == 'all' - - inquirerpy ==0.3.4 ; extra == 'cli' - - inquirerpy ==0.3.4 ; extra == 'dev' + - inquirerpy==0.3.4 ; extra == 'cli' + - inquirerpy==0.3.4 ; extra == 'dev' - aiohttp ; extra == 'dev' - - minijinja >=1.0 ; extra == 'dev' + - minijinja>=1.0 ; extra == 'dev' - jedi ; extra == 'dev' - jinja2 ; extra == 'dev' - pytest ; extra == 'dev' @@ -11046,14 +11046,14 @@ packages: - pytest-vcr ; extra == 'dev' - pytest-asyncio ; extra == 'dev' - pytest-rerunfailures ; extra == 'dev' - - urllib3 <2.0 ; extra == 'dev' + - urllib3<2.0 ; extra == 'dev' - soundfile ; extra == 'dev' - pillow ; extra == 'dev' - gradio ; extra == 'dev' - numpy ; extra == 'dev' - - ruff >=0.3.0 ; extra == 'dev' - - mypy ==1.5.1 ; extra == 'dev' - - typing-extensions >=4.8.0 ; extra == 'dev' + - ruff>=0.3.0 ; extra == 'dev' + - mypy==1.5.1 ; extra == 'dev' + - typing-extensions>=4.8.0 ; extra == 'dev' - types-pyyaml ; extra == 'dev' - types-requests ; extra == 'dev' - types-simplejson ; extra == 'dev' @@ -11061,21 +11061,21 @@ packages: - types-tqdm ; extra == 'dev' - types-urllib3 ; extra == 'dev' - toml ; extra == 'fastai' - - fastai >=2.4 ; extra == 'fastai' - - fastcore >=1.3.27 ; extra == 'fastai' - - hf-transfer >=0.1.4 ; extra == 'hf_transfer' + - fastai>=2.4 ; extra == 'fastai' + - fastcore>=1.3.27 ; extra == 'fastai' + - hf-transfer>=0.1.4 ; extra == 'hf_transfer' - aiohttp ; extra == 'inference' - - minijinja >=1.0 ; extra == 'inference' - - ruff >=0.3.0 ; extra == 'quality' - - mypy ==1.5.1 ; extra == 'quality' + - minijinja>=1.0 ; extra == 'inference' + - ruff>=0.3.0 ; extra == 'quality' + - mypy==1.5.1 ; extra == 'quality' - tensorflow ; extra == 'tensorflow' - pydot ; extra == 'tensorflow' - graphviz ; extra == 'tensorflow' - tensorflow ; extra == 'tensorflow-testing' - - keras <3.0 ; extra == 'tensorflow-testing' - - inquirerpy ==0.3.4 ; extra == 'testing' + - keras<3.0 ; extra == 'tensorflow-testing' + - inquirerpy==0.3.4 ; extra == 'testing' - aiohttp ; extra == 'testing' - - minijinja >=1.0 ; extra == 'testing' + - minijinja>=1.0 ; extra == 'testing' - jedi ; extra == 'testing' - jinja2 ; extra == 'testing' - pytest ; extra == 'testing' @@ -11085,14 +11085,14 @@ packages: - pytest-vcr ; extra == 'testing' - pytest-asyncio ; extra == 'testing' - pytest-rerunfailures ; extra == 'testing' - - urllib3 <2.0 ; extra == 'testing' + - urllib3<2.0 ; extra == 'testing' - soundfile ; extra == 'testing' - pillow ; extra == 'testing' - gradio ; extra == 'testing' - numpy ; extra == 'testing' - torch ; extra == 'torch' - safetensors ; extra == 'torch' - - typing-extensions >=4.8.0 ; extra == 'typing' + - typing-extensions>=4.8.0 ; extra == 'typing' - types-pyyaml ; extra == 'typing' - types-requests ; extra == 'typing' - types-simplejson ; extra == 'typing' @@ -11106,11 +11106,11 @@ packages: path: examples/python/human_pose_tracking sha256: 8a80b67528d3f6d0c82671dc5c36cf551faa4b879f4434f0d386d8ef85666e86 requires_dist: - - mediapipe ==0.10.11 ; sys_platform != 'darwin' - - mediapipe ==0.10.9 ; sys_platform == 'darwin' + - mediapipe==0.10.11 ; sys_platform != 'darwin' + - mediapipe==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python >4.6 - - requests <3, >=2.31 + - opencv-python>4.6 + - requests>=2.31,<3 - rerun-sdk requires_python: <3.12 editable: true @@ -11214,7 +11214,7 @@ packages: sha256: 408c1d4d62f72c9e8347e7d1ca9bc11d8673328af3913868db3b828e28b40a4c requires_dist: - numpy - - pillow >=8.3.2 + - pillow>=8.3.2 - astropy ; extra == 'all-plugins' - av ; extra == 'all-plugins' - imageio-ffmpeg ; extra == 'all-plugins' @@ -11232,7 +11232,7 @@ packages: - fsspec[github] ; extra == 'dev' - black ; extra == 'dev' - flake8 ; extra == 'dev' - - sphinx <6 ; extra == 'docs' + - sphinx<6 ; extra == 'docs' - numpydoc ; extra == 'docs' - pydata-sphinx-theme ; extra == 'docs' - imageio-ffmpeg ; extra == 'ffmpeg' @@ -11252,7 +11252,7 @@ packages: - pydata-sphinx-theme ; extra == 'full' - pytest ; extra == 'full' - pytest-cov ; extra == 'full' - - sphinx <6 ; extra == 'full' + - sphinx<6 ; extra == 'full' - tifffile ; extra == 'full' - wheel ; extra == 'full' - gdal ; extra == 'gdal' @@ -11272,27 +11272,27 @@ packages: url: https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl sha256: 30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 requires_dist: - - zipp >=0.5 - - typing-extensions >=3.6.4 ; python_version < '3.8' - - sphinx >=3.5 ; extra == 'docs' - - jaraco-packaging >=9.3 ; extra == 'docs' - - rst-linker >=1.9 ; extra == 'docs' + - zipp>=0.5 + - typing-extensions>=3.6.4 ; python_version < '3.8' + - sphinx>=3.5 ; extra == 'docs' + - jaraco-packaging>=9.3 ; extra == 'docs' + - rst-linker>=1.9 ; extra == 'docs' - furo ; extra == 'docs' - sphinx-lint ; extra == 'docs' - - jaraco-tidelift >=1.4 ; extra == 'docs' + - jaraco-tidelift>=1.4 ; extra == 'docs' - ipython ; extra == 'perf' - - pytest >=6 ; extra == 'testing' - - pytest-checkdocs >=2.4 ; extra == 'testing' + - pytest>=6 ; extra == 'testing' + - pytest-checkdocs>=2.4 ; extra == 'testing' - pytest-cov ; extra == 'testing' - - pytest-enabler >=2.2 ; extra == 'testing' - - pytest-ruff >=0.2.1 ; extra == 'testing' + - pytest-enabler>=2.2 ; extra == 'testing' + - pytest-ruff>=0.2.1 ; extra == 'testing' - packaging ; extra == 'testing' - pyfakefs ; extra == 'testing' - flufl-flake8 ; extra == 'testing' - - pytest-perf >=0.9.2 ; extra == 'testing' - - jaraco-test >=5.4 ; extra == 'testing' + - pytest-perf>=0.9.2 ; extra == 'testing' + - jaraco-test>=5.4 ; extra == 'testing' - pytest-mypy ; platform_python_implementation != 'PyPy' and extra == 'testing' - - importlib-resources >=1.3 ; python_version < '3.9' and extra == 'testing' + - importlib-resources>=1.3 ; python_version < '3.9' and extra == 'testing' requires_python: '>=3.8' - kind: pypi name: incremental-logging @@ -11369,46 +11369,46 @@ packages: url: https://files.pythonhosted.org/packages/dc/d9/f387d9dfb2cf00f814b24e0f8bf6f4c68ae01870994dc436993fadd73563/jax-0.4.26-py3-none-any.whl sha256: 50dc795148ee6b0735b48b477e5abc556aa3a4c7af5d6940dad08024a908b02f requires_dist: - - ml-dtypes >=0.2.0 - - numpy >=1.22 + - ml-dtypes>=0.2.0 + - numpy>=1.22 - opt-einsum - - scipy >=1.9 - - importlib-metadata >=4.6 ; python_version < '3.10' - - numpy >=1.23.2 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - scipy >=1.11.1 ; python_version >= '3.12' - - protobuf <4, >=3.13 ; extra == 'australis' - - jaxlib ==0.4.25 ; extra == 'ci' - - jaxlib ==0.4.26 ; extra == 'cpu' - - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda' - - jaxlib ==0.4.26 ; extra == 'cuda12' - - jax-cuda12-plugin ==0.4.26 ; extra == 'cuda12' - - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12' - - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12' - - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12' - - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12' - - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12' - - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12' - - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12' - - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12' - - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12' - - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12' - - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_cudnn89' - - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_local' - - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_pip' - - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12_pip' - - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12_pip' - - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12_pip' - - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12_pip' - - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12_pip' - - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12_pip' - - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - jaxlib ==0.4.20 ; extra == 'minimum-jaxlib' - - jaxlib ==0.4.26 ; extra == 'tpu' - - libtpu-nightly ==0.1.dev20240403 ; extra == 'tpu' + - scipy>=1.9 + - importlib-metadata>=4.6 ; python_version < '3.10' + - numpy>=1.23.2 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - scipy>=1.11.1 ; python_version >= '3.12' + - protobuf<4,>=3.13 ; extra == 'australis' + - jaxlib==0.4.25 ; extra == 'ci' + - jaxlib==0.4.26 ; extra == 'cpu' + - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda' + - jaxlib==0.4.26 ; extra == 'cuda12' + - jax-cuda12-plugin==0.4.26 ; extra == 'cuda12' + - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12' + - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12' + - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12' + - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12' + - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12' + - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12' + - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12' + - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12' + - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12' + - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12' + - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_cudnn89' + - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_local' + - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_pip' + - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12_pip' + - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12_pip' + - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12_pip' + - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12_pip' + - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12_pip' + - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12_pip' + - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12_pip' + - jaxlib==0.4.20 ; extra == 'minimum-jaxlib' + - jaxlib==0.4.26 ; extra == 'tpu' + - libtpu-nightly==0.1.dev20240403 ; extra == 'tpu' - requests ; extra == 'tpu' requires_python: '>=3.9' - kind: pypi @@ -11417,20 +11417,20 @@ packages: url: https://files.pythonhosted.org/packages/a9/41/6bbe0a55e4df1c5d30da02dc3d26be2aea6333af9c35c6d846d431b86c74/jaxlib-0.4.26-cp311-cp311-manylinux2014_x86_64.whl sha256: 3069da7d75f5b4dd15350fffe6e6b86ca09c4b9fde60b10515edb09cef653335 requires_dist: - - scipy >=1.9 - - numpy >=1.22 - - ml-dtypes >=0.2.0 - - scipy >=1.11.1 ; python_version >= '3.12' - - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12_pip' - - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12_pip' - - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12_pip' - - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12_pip' - - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12_pip' - - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12_pip' - - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - scipy>=1.9 + - numpy>=1.22 + - ml-dtypes>=0.2.0 + - scipy>=1.11.1 ; python_version >= '3.12' + - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12_pip' + - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12_pip' + - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12_pip' + - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12_pip' + - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12_pip' + - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12_pip' + - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12_pip' requires_python: '>=3.9' - kind: pypi name: jinja2 @@ -11438,8 +11438,8 @@ packages: url: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl sha256: 7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa requires_dist: - - markupsafe >=2.0 - - babel >=2.7 ; extra == 'i18n' + - markupsafe>=2.0 + - babel>=2.7 ; extra == 'i18n' requires_python: '>=3.7' - kind: conda name: jinja2 @@ -11654,10 +11654,10 @@ packages: requires_dist: - packaging - importlib-metadata ; python_version < '3.8' - - changelist ==0.5 ; extra == 'dev' - - pre-commit ==3.7.0 ; extra == 'lint' - - pytest >=7.4 ; extra == 'test' - - pytest-cov >=4.1 ; extra == 'test' + - changelist==0.5 ; extra == 'dev' + - pre-commit==3.7.0 ; extra == 'lint' + - pytest>=7.4 ; extra == 'test' + - pytest-cov>=4.1 ; extra == 'test' requires_python: '>=3.7' - kind: conda name: ld64 @@ -20124,11 +20124,11 @@ packages: url: https://files.pythonhosted.org/packages/be/c3/1765e019344d3f042dfe750eb9a424c0ea2fd43deb6b2ac176b5603a436e/lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl sha256: 200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095 requires_dist: - - cssselect >=0.7 ; extra == 'cssselect' + - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython >=3.0.10 ; extra == 'source' + - cython>=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml @@ -20136,11 +20136,11 @@ packages: url: https://files.pythonhosted.org/packages/43/43/66a84c2a034f5df2782240cb2f68696a72ad6734d7a91f824e0360cde08b/lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl sha256: 70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867 requires_dist: - - cssselect >=0.7 ; extra == 'cssselect' + - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython >=3.0.10 ; extra == 'source' + - cython>=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml @@ -20148,11 +20148,11 @@ packages: url: https://files.pythonhosted.org/packages/95/4c/fc5e63fb41e867f530a70519e1bcab0c14e84a95aa659f697bc97531be96/lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl sha256: 1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe requires_dist: - - cssselect >=0.7 ; extra == 'cssselect' + - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython >=3.0.10 ; extra == 'source' + - cython>=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml @@ -20160,11 +20160,11 @@ packages: url: https://files.pythonhosted.org/packages/df/c5/8b05e69685b48cf11b596fbdd466f76cb3c1e3efe0361d8be0edb9df0325/lxml-5.2.1-cp311-cp311-win_amd64.whl sha256: 5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102 requires_dist: - - cssselect >=0.7 ; extra == 'cssselect' + - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython >=3.0.10 ; extra == 'source' + - cython>=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: conda name: lz4-c @@ -20448,15 +20448,15 @@ packages: url: https://files.pythonhosted.org/packages/38/04/37055b7013dfaaf66e3a9a51e46857cc9be151476a891b995fa70da7e139/marshmallow-3.21.1-py3-none-any.whl sha256: f085493f79efb0644f270a9bf2892843142d80d7174bbbd2f3713f2a589dc633 requires_dist: - - packaging >=17.0 + - packaging>=17.0 - marshmallow[tests] ; extra == 'dev' - tox ; extra == 'dev' - - pre-commit ~=3.5 ; extra == 'dev' - - sphinx ==7.2.6 ; extra == 'docs' - - sphinx-issues ==4.0.0 ; extra == 'docs' - - alabaster ==0.7.16 ; extra == 'docs' - - sphinx-version-warning ==1.1.2 ; extra == 'docs' - - autodocsumm ==0.2.12 ; extra == 'docs' + - pre-commit~=3.5 ; extra == 'dev' + - sphinx==7.2.6 ; extra == 'docs' + - sphinx-issues==4.0.0 ; extra == 'docs' + - alabaster==0.7.16 ; extra == 'docs' + - sphinx-version-warning==1.1.2 ; extra == 'docs' + - autodocsumm==0.2.12 ; extra == 'docs' - pytest ; extra == 'tests' - pytz ; extra == 'tests' - simplejson ; extra == 'tests' @@ -20467,16 +20467,16 @@ packages: url: https://files.pythonhosted.org/packages/80/3b/e363612ac1a514abfb5505aa209dd5b724b3232a6de98710d7759559706a/matplotlib-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: cc4ccdc64e3039fc303defd119658148f2349239871db72cd74e2eeaa9b80b71 requires_dist: - - contourpy >=1.0.1 - - cycler >=0.10 - - fonttools >=4.22.0 - - kiwisolver >=1.3.1 - - numpy >=1.21 - - packaging >=20.0 - - pillow >=8 - - pyparsing >=2.3.1 - - python-dateutil >=2.7 - - importlib-resources >=3.2.0 ; python_version < '3.10' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.21 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib @@ -20484,16 +20484,16 @@ packages: url: https://files.pythonhosted.org/packages/14/60/12d4f27b859a74359306662da69c2d08826a2b05cfe7f96e66b490f41573/matplotlib-3.8.4-cp311-cp311-macosx_11_0_arm64.whl sha256: 232ce322bfd020a434caaffbd9a95333f7c2491e59cfc014041d95e38ab90d1c requires_dist: - - contourpy >=1.0.1 - - cycler >=0.10 - - fonttools >=4.22.0 - - kiwisolver >=1.3.1 - - numpy >=1.21 - - packaging >=20.0 - - pillow >=8 - - pyparsing >=2.3.1 - - python-dateutil >=2.7 - - importlib-resources >=3.2.0 ; python_version < '3.10' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.21 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib @@ -20501,16 +20501,16 @@ packages: url: https://files.pythonhosted.org/packages/36/11/62250ea25780d4b59c2c6044ec161235c47cc05a18d0ec0a05657de75b7d/matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl sha256: 72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661 requires_dist: - - contourpy >=1.0.1 - - cycler >=0.10 - - fonttools >=4.22.0 - - kiwisolver >=1.3.1 - - numpy >=1.21 - - packaging >=20.0 - - pillow >=8 - - pyparsing >=2.3.1 - - python-dateutil >=2.7 - - importlib-resources >=3.2.0 ; python_version < '3.10' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.21 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib @@ -20518,16 +20518,16 @@ packages: url: https://files.pythonhosted.org/packages/2d/d5/6227732ecab9165586966ccb54301e3164f61b470c954c4cf6940654fbe1/matplotlib-3.8.4-cp311-cp311-win_amd64.whl sha256: 8080d5081a86e690d7688ffa542532e87f224c38a6ed71f8fbed34dd1d9fedae requires_dist: - - contourpy >=1.0.1 - - cycler >=0.10 - - fonttools >=4.22.0 - - kiwisolver >=1.3.1 - - numpy >=1.21 - - packaging >=20.0 - - pillow >=8 - - pyparsing >=2.3.1 - - python-dateutil >=2.7 - - importlib-resources >=3.2.0 ; python_version < '3.10' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.21 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: conda name: maturin @@ -20639,13 +20639,13 @@ packages: sha256: 8733735f582e6e6a05bf9b15c48b03a6387a0795793a2530aa1189eecfd33780 requires_dist: - absl-py - - attrs >=19.1.0 - - flatbuffers >=2.0 + - attrs>=19.1.0 + - flatbuffers>=2.0 - matplotlib - numpy - opencv-contrib-python - - protobuf <4, >=3.11 - - sounddevice >=0.4.4 + - protobuf<4,>=3.11 + - sounddevice>=0.4.4 - kind: pypi name: mediapipe version: 0.10.9 @@ -20653,13 +20653,13 @@ packages: sha256: b7dde54b82732479b9b856c9230b9f7b3da55b0913dde5254a7489e20c2e3c6e requires_dist: - absl-py - - attrs >=19.1.0 - - flatbuffers >=2.0 + - attrs>=19.1.0 + - flatbuffers>=2.0 - matplotlib - numpy - opencv-contrib-python - - protobuf <4, >=3.11 - - sounddevice >=0.4.4 + - protobuf<4,>=3.11 + - sounddevice>=0.4.4 - kind: pypi name: mediapipe version: 0.10.11 @@ -20667,16 +20667,16 @@ packages: sha256: ea751e043909ba7bbe27e7afdbcdafd79723d50ef4165afcaae431ab428eea13 requires_dist: - absl-py - - attrs >=19.1.0 - - flatbuffers >=2.0 + - attrs>=19.1.0 + - flatbuffers>=2.0 - jax - jaxlib - matplotlib - numpy - torch - opencv-contrib-python - - protobuf <4, >=3.11 - - sounddevice >=0.4.4 + - protobuf<4,>=3.11 + - sounddevice>=0.4.4 - kind: pypi name: mediapipe version: 0.10.11 @@ -20684,14 +20684,14 @@ packages: sha256: 36231eaf23cd795a923a8b015d36bd6e410a8e997c36dd9432db0157b822b181 requires_dist: - absl-py - - attrs >=19.1.0 - - flatbuffers >=2.0 + - attrs>=19.1.0 + - flatbuffers>=2.0 - jax - matplotlib - numpy - opencv-contrib-python - - protobuf <4, >=3.11 - - sounddevice >=0.4.4 + - protobuf<4,>=3.11 + - sounddevice>=0.4.4 - kind: conda name: meilisearch version: 1.5.1 @@ -20790,14 +20790,14 @@ packages: url: https://files.pythonhosted.org/packages/84/17/a936d3dfad84d028ba8539a93167274b7dcd7985e0d9df487e94a62f9428/ml_dtypes-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: e1e2f4237b459a63c97c2c9f449baa637d7e4c20addff6a9bac486f22432f3b6 requires_dist: - - numpy >1.20 - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.23.3 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' + - numpy>1.20 + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.23.3 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' - absl-py ; extra == 'dev' - pytest ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - pylint >=2.6.0 ; extra == 'dev' + - pylint>=2.6.0 ; extra == 'dev' - pyink ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -20806,14 +20806,14 @@ packages: url: https://files.pythonhosted.org/packages/f0/36/290745178e5776f7416818abc1334c1b19afb93c7c87fd1bef3cc99f84ca/ml_dtypes-0.4.0-cp311-cp311-win_amd64.whl sha256: 75b4faf99d0711b81f393db36d210b4255fd419f6f790bc6c1b461f95ffb7a9e requires_dist: - - numpy >1.20 - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.23.3 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' + - numpy>1.20 + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.23.3 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' - absl-py ; extra == 'dev' - pytest ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - pylint >=2.6.0 ; extra == 'dev' + - pylint>=2.6.0 ; extra == 'dev' - pyink ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -20822,14 +20822,14 @@ packages: url: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl sha256: a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c requires_dist: - - pytest >=4.6 ; extra == 'develop' + - pytest>=4.6 ; extra == 'develop' - pycodestyle ; extra == 'develop' - pytest-cov ; extra == 'develop' - codecov ; extra == 'develop' - wheel ; extra == 'develop' - sphinx ; extra == 'docs' - - gmpy2 >=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' - - pytest >=4.6 ; extra == 'tests' + - gmpy2>=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' + - pytest>=4.6 ; extra == 'tests' - kind: conda name: msys2-conda-epoch version: '20160418' @@ -21262,27 +21262,27 @@ packages: url: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl sha256: 28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2 requires_dist: - - numpy >=1.23 ; extra == 'default' - - scipy !=1.11.0, !=1.11.1, >=1.9 ; extra == 'default' - - matplotlib >=3.6 ; extra == 'default' - - pandas >=1.4 ; extra == 'default' - - changelist ==0.5 ; extra == 'developer' - - pre-commit >=3.2 ; extra == 'developer' - - mypy >=1.1 ; extra == 'developer' + - numpy>=1.23 ; extra == 'default' + - scipy!=1.11.0,!=1.11.1,>=1.9 ; extra == 'default' + - matplotlib>=3.6 ; extra == 'default' + - pandas>=1.4 ; extra == 'default' + - changelist==0.5 ; extra == 'developer' + - pre-commit>=3.2 ; extra == 'developer' + - mypy>=1.1 ; extra == 'developer' - rtoml ; extra == 'developer' - - sphinx >=7 ; extra == 'doc' - - pydata-sphinx-theme >=0.14 ; extra == 'doc' - - sphinx-gallery >=0.14 ; extra == 'doc' - - numpydoc >=1.7 ; extra == 'doc' - - pillow >=9.4 ; extra == 'doc' - - texext >=0.6.7 ; extra == 'doc' - - myst-nb >=1.0 ; extra == 'doc' - - lxml >=4.6 ; extra == 'extra' - - pygraphviz >=1.12 ; extra == 'extra' - - pydot >=2.0 ; extra == 'extra' - - sympy >=1.10 ; extra == 'extra' - - pytest >=7.2 ; extra == 'test' - - pytest-cov >=4.0 ; extra == 'test' + - sphinx>=7 ; extra == 'doc' + - pydata-sphinx-theme>=0.14 ; extra == 'doc' + - sphinx-gallery>=0.14 ; extra == 'doc' + - numpydoc>=1.7 ; extra == 'doc' + - pillow>=9.4 ; extra == 'doc' + - texext>=0.6.7 ; extra == 'doc' + - myst-nb>=1.0 ; extra == 'doc' + - lxml>=4.6 ; extra == 'extra' + - pygraphviz>=1.12 ; extra == 'extra' + - pydot>=2.0 ; extra == 'extra' + - sympy>=1.10 ; extra == 'extra' + - pytest>=7.2 ; extra == 'test' + - pytest-cov>=4.0 ; extra == 'test' requires_python: '>=3.10' - kind: conda name: ninja @@ -21536,16 +21536,16 @@ packages: url: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl sha256: 6492236efa15a460ecb98e7b67562a28b70da006ab0be164e8821177577c0565 requires_dist: - - argcomplete <4.0, >=1.9.4 - - colorlog <7.0.0, >=2.6.1 + - argcomplete<4.0,>=1.9.4 + - colorlog<7.0.0,>=2.6.1 - importlib-metadata ; python_version < '3.8' - - packaging >=20.9 - - tomli >=1 ; python_version < '3.11' - - typing-extensions >=3.7.4 ; python_version < '3.8' - - virtualenv >=20.14.1 + - packaging>=20.9 + - tomli>=1 ; python_version < '3.11' + - typing-extensions>=3.7.4 ; python_version < '3.8' + - virtualenv>=20.14.1 - jinja2 ; extra == 'tox_to_nox' - tox ; extra == 'tox_to_nox' - - uv >=0.1.6 ; extra == 'uv' + - uv>=0.1.6 ; extra == 'uv' requires_python: '>=3.7' - kind: pypi name: numba @@ -21553,8 +21553,8 @@ packages: url: https://files.pythonhosted.org/packages/54/f2/7d1579037643c874fa73516ea84c07e8d30ea347fb1a88c03b198447655d/numba-0.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl sha256: dd2842fac03be4e5324ebbbd4d2d0c8c0fc6e0df75c09477dd45b288a0777389 requires_dist: - - llvmlite <0.43, >=0.42.0.dev0 - - numpy <1.27, >=1.22 + - llvmlite<0.43,>=0.42.0.dev0 + - numpy<1.27,>=1.22 requires_python: '>=3.9' - kind: pypi name: numba @@ -21562,8 +21562,8 @@ packages: url: https://files.pythonhosted.org/packages/70/7d/0d1419479997319ca72ef735791c2ee50819f9c200adea96142ee7499fae/numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl sha256: 411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966 requires_dist: - - llvmlite <0.43, >=0.42.0.dev0 - - numpy <1.27, >=1.22 + - llvmlite<0.43,>=0.42.0.dev0 + - numpy<1.27,>=1.22 requires_python: '>=3.9' - kind: pypi name: numba @@ -21571,8 +21571,8 @@ packages: url: https://files.pythonhosted.org/packages/5f/2d/085c21f3086eff0b830e5d03d084a1b4b10dfde0c65feeac6be8c361265c/numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl sha256: 43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051 requires_dist: - - llvmlite <0.43, >=0.42.0.dev0 - - numpy <1.27, >=1.22 + - llvmlite<0.43,>=0.42.0.dev0 + - numpy<1.27,>=1.22 requires_python: '>=3.9' - kind: pypi name: numba @@ -21580,8 +21580,8 @@ packages: url: https://files.pythonhosted.org/packages/38/f0/ad848815b0adafcf5f238e728933950034355a8d59969772be1cd57606d8/numba-0.59.1-cp311-cp311-win_amd64.whl sha256: 0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450 requires_dist: - - llvmlite <0.43, >=0.42.0.dev0 - - numpy <1.27, >=1.22 + - llvmlite<0.43,>=0.42.0.dev0 + - numpy<1.27,>=1.22 requires_python: '>=3.9' - kind: pypi name: numpy @@ -21734,9 +21734,9 @@ packages: path: examples/python/nv12 sha256: c8ca97c5d8c04037cd5eb9a65be7b1e7d667c11d4dba3ee9aad5956ccf926dc4 requires_dist: - - numpy + - rerun-sdk>=0.10 - opencv-python - - rerun-sdk >=0.10 + - numpy editable: true - kind: pypi name: nvidia-cublas-cu12 @@ -21826,8 +21826,8 @@ packages: requires_dist: - betterproto[compiler] - numpy - - opencv-python >4.6 - - requests <3, >=2.31 + - opencv-python>4.6 + - requests>=2.31,<3 - rerun-sdk - scipy editable: true @@ -21851,16 +21851,16 @@ packages: url: https://files.pythonhosted.org/packages/8a/ea/aea6289058480b93157ad698ecd7f13cae4892ae0a4750abf33b3ac12f91/opencv_contrib_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 89ca1508dd895ae42176640bdd503cac82772f6efa25120738a469a6a69de321 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-contrib-python @@ -21868,16 +21868,16 @@ packages: url: https://files.pythonhosted.org/packages/4c/c3/ccff2e1bfe2bb47a7eaebc4280e93bd2f97ebbe5b3573d48bcfcc0c32387/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl sha256: b52e381144f774b486729ccee69911bdc7d16b5ced4830502e906ad803373ab0 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-contrib-python @@ -21885,16 +21885,16 @@ packages: url: https://files.pythonhosted.org/packages/16/07/bf25df600eeaedddf8fece3f1ff837bf72865b93a03651cf7375ce8172be/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl sha256: 86078d3653ec3107877536c9178622b1f98b51acf59e554ddbc552785cba55fa requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-contrib-python @@ -21902,101 +21902,101 @@ packages: url: https://files.pythonhosted.org/packages/aa/2e/576ac47f21d555b459ca837bb3fb937e50339b8fbfd294945ea2f5290416/opencv_contrib_python-4.9.0.80-cp37-abi3-win_amd64.whl sha256: fdd9b14028f74af8dbb69f90e6e4a956ce2eb5b59947df28ba0b79d337431477 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3 + url: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl + sha256: 3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57 + url: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz - sha256: 1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1 + url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a + url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl + sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl - sha256: 3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0 + url: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz + sha256: 1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python @@ -22004,16 +22004,16 @@ packages: url: https://files.pythonhosted.org/packages/35/69/b657974ddcbba54d59d7d62b01e60a8b815e35f415b996e4d355be0ac7b4/opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl sha256: 7e5f7aa4486651a6ebfa8ed4b594b65bd2d2f41beeb4241a3e4b1b85acbbbadb requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: conda name: openssl @@ -22196,8 +22196,8 @@ packages: url: https://files.pythonhosted.org/packages/bc/19/404708a7e54ad2798907210462fd950c3442ea51acc8790f3da48d2bee8b/opt_einsum-3.3.0-py3-none-any.whl sha256: 2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147 requires_dist: - - numpy >=1.7 - - sphinx ==1.2.3 ; extra == 'docs' + - numpy>=1.7 + - sphinx==1.2.3 ; extra == 'docs' - sphinxcontrib-napoleon ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - numpydoc ; extra == 'docs' @@ -22513,91 +22513,91 @@ packages: url: https://files.pythonhosted.org/packages/fc/a5/4d82be566f069d7a9a702dcdf6f9106df0e0b042e738043c0cc7ddd7e3f6/pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee requires_dist: - - numpy >=1.22.4 ; python_version < '3.11' - - numpy >=1.23.2 ; python_version == '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - python-dateutil >=2.8.2 - - pytz >=2020.1 - - tzdata >=2022.7 - - hypothesis >=6.46.1 ; extra == 'test' - - pytest >=7.3.2 ; extra == 'test' - - pytest-xdist >=2.2.0 ; extra == 'test' - - pyarrow >=10.0.1 ; extra == 'pyarrow' - - bottleneck >=1.3.6 ; extra == 'performance' - - numba >=0.56.4 ; extra == 'performance' - - numexpr >=2.8.4 ; extra == 'performance' - - scipy >=1.10.0 ; extra == 'computation' - - xarray >=2022.12.0 ; extra == 'computation' - - fsspec >=2022.11.0 ; extra == 'fss' - - s3fs >=2022.11.0 ; extra == 'aws' - - gcsfs >=2022.11.0 ; extra == 'gcp' - - pandas-gbq >=0.19.0 ; extra == 'gcp' - - odfpy >=1.4.1 ; extra == 'excel' - - openpyxl >=3.1.0 ; extra == 'excel' - - python-calamine >=0.1.7 ; extra == 'excel' - - pyxlsb >=1.0.10 ; extra == 'excel' - - xlrd >=2.0.1 ; extra == 'excel' - - xlsxwriter >=3.0.5 ; extra == 'excel' - - pyarrow >=10.0.1 ; extra == 'parquet' - - pyarrow >=10.0.1 ; extra == 'feather' - - tables >=3.8.0 ; extra == 'hdf5' - - pyreadstat >=1.2.0 ; extra == 'spss' - - sqlalchemy >=2.0.0 ; extra == 'postgresql' - - psycopg2 >=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' - - sqlalchemy >=2.0.0 ; extra == 'mysql' - - pymysql >=1.0.2 ; extra == 'mysql' - - sqlalchemy >=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' - - beautifulsoup4 >=4.11.2 ; extra == 'html' - - html5lib >=1.1 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'xml' - - matplotlib >=3.6.3 ; extra == 'plot' - - jinja2 >=3.1.2 ; extra == 'output-formatting' - - tabulate >=0.9.0 ; extra == 'output-formatting' - - pyqt5 >=5.15.9 ; extra == 'clipboard' - - qtpy >=2.3.0 ; extra == 'clipboard' - - zstandard >=0.19.0 ; extra == 'compression' - - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql >=0.8.0 ; extra == 'all' - - adbc-driver-sqlite >=0.8.0 ; extra == 'all' - - beautifulsoup4 >=4.11.2 ; extra == 'all' - - bottleneck >=1.3.6 ; extra == 'all' - - dataframe-api-compat >=0.1.7 ; extra == 'all' - - fastparquet >=2022.12.0 ; extra == 'all' - - fsspec >=2022.11.0 ; extra == 'all' - - gcsfs >=2022.11.0 ; extra == 'all' - - html5lib >=1.1 ; extra == 'all' - - hypothesis >=6.46.1 ; extra == 'all' - - jinja2 >=3.1.2 ; extra == 'all' - - lxml >=4.9.2 ; extra == 'all' - - matplotlib >=3.6.3 ; extra == 'all' - - numba >=0.56.4 ; extra == 'all' - - numexpr >=2.8.4 ; extra == 'all' - - odfpy >=1.4.1 ; extra == 'all' - - openpyxl >=3.1.0 ; extra == 'all' - - pandas-gbq >=0.19.0 ; extra == 'all' - - psycopg2 >=2.9.6 ; extra == 'all' - - pyarrow >=10.0.1 ; extra == 'all' - - pymysql >=1.0.2 ; extra == 'all' - - pyqt5 >=5.15.9 ; extra == 'all' - - pyreadstat >=1.2.0 ; extra == 'all' - - pytest >=7.3.2 ; extra == 'all' - - pytest-xdist >=2.2.0 ; extra == 'all' - - python-calamine >=0.1.7 ; extra == 'all' - - pyxlsb >=1.0.10 ; extra == 'all' - - qtpy >=2.3.0 ; extra == 'all' - - scipy >=1.10.0 ; extra == 'all' - - s3fs >=2022.11.0 ; extra == 'all' - - sqlalchemy >=2.0.0 ; extra == 'all' - - tables >=3.8.0 ; extra == 'all' - - tabulate >=0.9.0 ; extra == 'all' - - xarray >=2022.12.0 ; extra == 'all' - - xlrd >=2.0.1 ; extra == 'all' - - xlsxwriter >=3.0.5 ; extra == 'all' - - zstandard >=0.19.0 ; extra == 'all' + - numpy>=1.22.4 ; python_version < '3.11' + - numpy>=1.23.2 ; python_version == '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas @@ -22605,91 +22605,91 @@ packages: url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 requires_dist: - - numpy >=1.22.4 ; python_version < '3.11' - - numpy >=1.23.2 ; python_version == '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - python-dateutil >=2.8.2 - - pytz >=2020.1 - - tzdata >=2022.7 - - hypothesis >=6.46.1 ; extra == 'test' - - pytest >=7.3.2 ; extra == 'test' - - pytest-xdist >=2.2.0 ; extra == 'test' - - pyarrow >=10.0.1 ; extra == 'pyarrow' - - bottleneck >=1.3.6 ; extra == 'performance' - - numba >=0.56.4 ; extra == 'performance' - - numexpr >=2.8.4 ; extra == 'performance' - - scipy >=1.10.0 ; extra == 'computation' - - xarray >=2022.12.0 ; extra == 'computation' - - fsspec >=2022.11.0 ; extra == 'fss' - - s3fs >=2022.11.0 ; extra == 'aws' - - gcsfs >=2022.11.0 ; extra == 'gcp' - - pandas-gbq >=0.19.0 ; extra == 'gcp' - - odfpy >=1.4.1 ; extra == 'excel' - - openpyxl >=3.1.0 ; extra == 'excel' - - python-calamine >=0.1.7 ; extra == 'excel' - - pyxlsb >=1.0.10 ; extra == 'excel' - - xlrd >=2.0.1 ; extra == 'excel' - - xlsxwriter >=3.0.5 ; extra == 'excel' - - pyarrow >=10.0.1 ; extra == 'parquet' - - pyarrow >=10.0.1 ; extra == 'feather' - - tables >=3.8.0 ; extra == 'hdf5' - - pyreadstat >=1.2.0 ; extra == 'spss' - - sqlalchemy >=2.0.0 ; extra == 'postgresql' - - psycopg2 >=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' - - sqlalchemy >=2.0.0 ; extra == 'mysql' - - pymysql >=1.0.2 ; extra == 'mysql' - - sqlalchemy >=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' - - beautifulsoup4 >=4.11.2 ; extra == 'html' - - html5lib >=1.1 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'xml' - - matplotlib >=3.6.3 ; extra == 'plot' - - jinja2 >=3.1.2 ; extra == 'output-formatting' - - tabulate >=0.9.0 ; extra == 'output-formatting' - - pyqt5 >=5.15.9 ; extra == 'clipboard' - - qtpy >=2.3.0 ; extra == 'clipboard' - - zstandard >=0.19.0 ; extra == 'compression' - - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql >=0.8.0 ; extra == 'all' - - adbc-driver-sqlite >=0.8.0 ; extra == 'all' - - beautifulsoup4 >=4.11.2 ; extra == 'all' - - bottleneck >=1.3.6 ; extra == 'all' - - dataframe-api-compat >=0.1.7 ; extra == 'all' - - fastparquet >=2022.12.0 ; extra == 'all' - - fsspec >=2022.11.0 ; extra == 'all' - - gcsfs >=2022.11.0 ; extra == 'all' - - html5lib >=1.1 ; extra == 'all' - - hypothesis >=6.46.1 ; extra == 'all' - - jinja2 >=3.1.2 ; extra == 'all' - - lxml >=4.9.2 ; extra == 'all' - - matplotlib >=3.6.3 ; extra == 'all' - - numba >=0.56.4 ; extra == 'all' - - numexpr >=2.8.4 ; extra == 'all' - - odfpy >=1.4.1 ; extra == 'all' - - openpyxl >=3.1.0 ; extra == 'all' - - pandas-gbq >=0.19.0 ; extra == 'all' - - psycopg2 >=2.9.6 ; extra == 'all' - - pyarrow >=10.0.1 ; extra == 'all' - - pymysql >=1.0.2 ; extra == 'all' - - pyqt5 >=5.15.9 ; extra == 'all' - - pyreadstat >=1.2.0 ; extra == 'all' - - pytest >=7.3.2 ; extra == 'all' - - pytest-xdist >=2.2.0 ; extra == 'all' - - python-calamine >=0.1.7 ; extra == 'all' - - pyxlsb >=1.0.10 ; extra == 'all' - - qtpy >=2.3.0 ; extra == 'all' - - scipy >=1.10.0 ; extra == 'all' - - s3fs >=2022.11.0 ; extra == 'all' - - sqlalchemy >=2.0.0 ; extra == 'all' - - tables >=3.8.0 ; extra == 'all' - - tabulate >=0.9.0 ; extra == 'all' - - xarray >=2022.12.0 ; extra == 'all' - - xlrd >=2.0.1 ; extra == 'all' - - xlsxwriter >=3.0.5 ; extra == 'all' - - zstandard >=0.19.0 ; extra == 'all' + - numpy>=1.22.4 ; python_version < '3.11' + - numpy>=1.23.2 ; python_version == '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas @@ -22697,91 +22697,91 @@ packages: url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 requires_dist: - - numpy >=1.22.4 ; python_version < '3.11' - - numpy >=1.23.2 ; python_version == '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - python-dateutil >=2.8.2 - - pytz >=2020.1 - - tzdata >=2022.7 - - hypothesis >=6.46.1 ; extra == 'test' - - pytest >=7.3.2 ; extra == 'test' - - pytest-xdist >=2.2.0 ; extra == 'test' - - pyarrow >=10.0.1 ; extra == 'pyarrow' - - bottleneck >=1.3.6 ; extra == 'performance' - - numba >=0.56.4 ; extra == 'performance' - - numexpr >=2.8.4 ; extra == 'performance' - - scipy >=1.10.0 ; extra == 'computation' - - xarray >=2022.12.0 ; extra == 'computation' - - fsspec >=2022.11.0 ; extra == 'fss' - - s3fs >=2022.11.0 ; extra == 'aws' - - gcsfs >=2022.11.0 ; extra == 'gcp' - - pandas-gbq >=0.19.0 ; extra == 'gcp' - - odfpy >=1.4.1 ; extra == 'excel' - - openpyxl >=3.1.0 ; extra == 'excel' - - python-calamine >=0.1.7 ; extra == 'excel' - - pyxlsb >=1.0.10 ; extra == 'excel' - - xlrd >=2.0.1 ; extra == 'excel' - - xlsxwriter >=3.0.5 ; extra == 'excel' - - pyarrow >=10.0.1 ; extra == 'parquet' - - pyarrow >=10.0.1 ; extra == 'feather' - - tables >=3.8.0 ; extra == 'hdf5' - - pyreadstat >=1.2.0 ; extra == 'spss' - - sqlalchemy >=2.0.0 ; extra == 'postgresql' - - psycopg2 >=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' - - sqlalchemy >=2.0.0 ; extra == 'mysql' - - pymysql >=1.0.2 ; extra == 'mysql' - - sqlalchemy >=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' - - beautifulsoup4 >=4.11.2 ; extra == 'html' - - html5lib >=1.1 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'xml' - - matplotlib >=3.6.3 ; extra == 'plot' - - jinja2 >=3.1.2 ; extra == 'output-formatting' - - tabulate >=0.9.0 ; extra == 'output-formatting' - - pyqt5 >=5.15.9 ; extra == 'clipboard' - - qtpy >=2.3.0 ; extra == 'clipboard' - - zstandard >=0.19.0 ; extra == 'compression' - - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql >=0.8.0 ; extra == 'all' - - adbc-driver-sqlite >=0.8.0 ; extra == 'all' - - beautifulsoup4 >=4.11.2 ; extra == 'all' - - bottleneck >=1.3.6 ; extra == 'all' - - dataframe-api-compat >=0.1.7 ; extra == 'all' - - fastparquet >=2022.12.0 ; extra == 'all' - - fsspec >=2022.11.0 ; extra == 'all' - - gcsfs >=2022.11.0 ; extra == 'all' - - html5lib >=1.1 ; extra == 'all' - - hypothesis >=6.46.1 ; extra == 'all' - - jinja2 >=3.1.2 ; extra == 'all' - - lxml >=4.9.2 ; extra == 'all' - - matplotlib >=3.6.3 ; extra == 'all' - - numba >=0.56.4 ; extra == 'all' - - numexpr >=2.8.4 ; extra == 'all' - - odfpy >=1.4.1 ; extra == 'all' - - openpyxl >=3.1.0 ; extra == 'all' - - pandas-gbq >=0.19.0 ; extra == 'all' - - psycopg2 >=2.9.6 ; extra == 'all' - - pyarrow >=10.0.1 ; extra == 'all' - - pymysql >=1.0.2 ; extra == 'all' - - pyqt5 >=5.15.9 ; extra == 'all' - - pyreadstat >=1.2.0 ; extra == 'all' - - pytest >=7.3.2 ; extra == 'all' - - pytest-xdist >=2.2.0 ; extra == 'all' - - python-calamine >=0.1.7 ; extra == 'all' - - pyxlsb >=1.0.10 ; extra == 'all' - - qtpy >=2.3.0 ; extra == 'all' - - scipy >=1.10.0 ; extra == 'all' - - s3fs >=2022.11.0 ; extra == 'all' - - sqlalchemy >=2.0.0 ; extra == 'all' - - tables >=3.8.0 ; extra == 'all' - - tabulate >=0.9.0 ; extra == 'all' - - xarray >=2022.12.0 ; extra == 'all' - - xlrd >=2.0.1 ; extra == 'all' - - xlsxwriter >=3.0.5 ; extra == 'all' - - zstandard >=0.19.0 ; extra == 'all' + - numpy>=1.22.4 ; python_version < '3.11' + - numpy>=1.23.2 ; python_version == '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas @@ -22789,91 +22789,91 @@ packages: url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 requires_dist: - - numpy >=1.22.4 ; python_version < '3.11' - - numpy >=1.23.2 ; python_version == '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - python-dateutil >=2.8.2 - - pytz >=2020.1 - - tzdata >=2022.7 - - hypothesis >=6.46.1 ; extra == 'test' - - pytest >=7.3.2 ; extra == 'test' - - pytest-xdist >=2.2.0 ; extra == 'test' - - pyarrow >=10.0.1 ; extra == 'pyarrow' - - bottleneck >=1.3.6 ; extra == 'performance' - - numba >=0.56.4 ; extra == 'performance' - - numexpr >=2.8.4 ; extra == 'performance' - - scipy >=1.10.0 ; extra == 'computation' - - xarray >=2022.12.0 ; extra == 'computation' - - fsspec >=2022.11.0 ; extra == 'fss' - - s3fs >=2022.11.0 ; extra == 'aws' - - gcsfs >=2022.11.0 ; extra == 'gcp' - - pandas-gbq >=0.19.0 ; extra == 'gcp' - - odfpy >=1.4.1 ; extra == 'excel' - - openpyxl >=3.1.0 ; extra == 'excel' - - python-calamine >=0.1.7 ; extra == 'excel' - - pyxlsb >=1.0.10 ; extra == 'excel' - - xlrd >=2.0.1 ; extra == 'excel' - - xlsxwriter >=3.0.5 ; extra == 'excel' - - pyarrow >=10.0.1 ; extra == 'parquet' - - pyarrow >=10.0.1 ; extra == 'feather' - - tables >=3.8.0 ; extra == 'hdf5' - - pyreadstat >=1.2.0 ; extra == 'spss' - - sqlalchemy >=2.0.0 ; extra == 'postgresql' - - psycopg2 >=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' - - sqlalchemy >=2.0.0 ; extra == 'mysql' - - pymysql >=1.0.2 ; extra == 'mysql' - - sqlalchemy >=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' - - beautifulsoup4 >=4.11.2 ; extra == 'html' - - html5lib >=1.1 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'xml' - - matplotlib >=3.6.3 ; extra == 'plot' - - jinja2 >=3.1.2 ; extra == 'output-formatting' - - tabulate >=0.9.0 ; extra == 'output-formatting' - - pyqt5 >=5.15.9 ; extra == 'clipboard' - - qtpy >=2.3.0 ; extra == 'clipboard' - - zstandard >=0.19.0 ; extra == 'compression' - - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql >=0.8.0 ; extra == 'all' - - adbc-driver-sqlite >=0.8.0 ; extra == 'all' - - beautifulsoup4 >=4.11.2 ; extra == 'all' - - bottleneck >=1.3.6 ; extra == 'all' - - dataframe-api-compat >=0.1.7 ; extra == 'all' - - fastparquet >=2022.12.0 ; extra == 'all' - - fsspec >=2022.11.0 ; extra == 'all' - - gcsfs >=2022.11.0 ; extra == 'all' - - html5lib >=1.1 ; extra == 'all' - - hypothesis >=6.46.1 ; extra == 'all' - - jinja2 >=3.1.2 ; extra == 'all' - - lxml >=4.9.2 ; extra == 'all' - - matplotlib >=3.6.3 ; extra == 'all' - - numba >=0.56.4 ; extra == 'all' - - numexpr >=2.8.4 ; extra == 'all' - - odfpy >=1.4.1 ; extra == 'all' - - openpyxl >=3.1.0 ; extra == 'all' - - pandas-gbq >=0.19.0 ; extra == 'all' - - psycopg2 >=2.9.6 ; extra == 'all' - - pyarrow >=10.0.1 ; extra == 'all' - - pymysql >=1.0.2 ; extra == 'all' - - pyqt5 >=5.15.9 ; extra == 'all' - - pyreadstat >=1.2.0 ; extra == 'all' - - pytest >=7.3.2 ; extra == 'all' - - pytest-xdist >=2.2.0 ; extra == 'all' - - python-calamine >=0.1.7 ; extra == 'all' - - pyxlsb >=1.0.10 ; extra == 'all' - - qtpy >=2.3.0 ; extra == 'all' - - scipy >=1.10.0 ; extra == 'all' - - s3fs >=2022.11.0 ; extra == 'all' - - sqlalchemy >=2.0.0 ; extra == 'all' - - tables >=3.8.0 ; extra == 'all' - - tabulate >=0.9.0 ; extra == 'all' - - xarray >=2022.12.0 ; extra == 'all' - - xlrd >=2.0.1 ; extra == 'all' - - xlsxwriter >=3.0.5 ; extra == 'all' - - zstandard >=0.19.0 ; extra == 'all' + - numpy>=1.22.4 ; python_version < '3.11' + - numpy>=1.23.2 ; python_version == '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: conda name: patchelf @@ -22904,12 +22904,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22928,12 +22928,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22952,12 +22952,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22976,12 +22976,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23000,12 +23000,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23024,12 +23024,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 + url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23048,12 +23048,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd + url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23077,7 +23077,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23105,7 +23105,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23133,7 +23133,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23161,7 +23161,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23233,15 +23233,32 @@ packages: url: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl sha256: 0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068 requires_dist: - - furo >=2023.9.10 ; extra == 'docs' - - proselint >=0.13 ; extra == 'docs' - - sphinx-autodoc-typehints >=1.25.2 ; extra == 'docs' - - sphinx >=7.2.6 ; extra == 'docs' - - appdirs ==1.4.4 ; extra == 'test' - - covdefaults >=2.3 ; extra == 'test' - - pytest-cov >=4.1 ; extra == 'test' - - pytest-mock >=3.12 ; extra == 'test' - - pytest >=7.4.3 ; extra == 'test' + - furo>=2023.9.10 ; extra == 'docs' + - proselint>=0.13 ; extra == 'docs' + - sphinx-autodoc-typehints>=1.25.2 ; extra == 'docs' + - sphinx>=7.2.6 ; extra == 'docs' + - appdirs==1.4.4 ; extra == 'test' + - covdefaults>=2.3 ; extra == 'test' + - pytest-cov>=4.1 ; extra == 'test' + - pytest-mock>=3.12 ; extra == 'test' + - pytest>=7.4.3 ; extra == 'test' + requires_python: '>=3.8' +- kind: pypi + name: platformdirs + version: 4.2.1 + url: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl + sha256: 17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1 + requires_dist: + - furo>=2023.9.10 ; extra == 'docs' + - proselint>=0.13 ; extra == 'docs' + - sphinx-autodoc-typehints>=1.25.2 ; extra == 'docs' + - sphinx>=7.2.6 ; extra == 'docs' + - appdirs==1.4.4 ; extra == 'test' + - covdefaults>=2.3 ; extra == 'test' + - pytest-cov>=4.1 ; extra == 'test' + - pytest-mock>=3.12 ; extra == 'test' + - pytest>=7.4.3 ; extra == 'test' + - mypy>=1.8 ; extra == 'type' requires_python: '>=3.8' - kind: pypi name: plots @@ -23370,8 +23387,8 @@ packages: url: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl sha256: a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c requires_dist: - - protobuf <5.0.0.dev0, >=3.19.0 - - google-api-core[grpc] >=1.31.5 ; extra == 'testing' + - protobuf<5.0.0.dev0,>=3.19.0 + - google-api-core[grpc]>=1.31.5 ; extra == 'testing' requires_python: '>=3.6' - kind: pypi name: protobuf @@ -23382,26 +23399,26 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c + url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d + url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl - sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 + url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl - sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 + url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c requires_python: '>=3.8' - kind: pypi name: psutil @@ -23989,7 +24006,7 @@ packages: url: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl sha256: be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b requires_dist: - - pyasn1 <0.7.0, >=0.4.6 + - pyasn1<0.7.0,>=0.4.6 requires_python: '>=3.8' - kind: pypi name: pycparser @@ -24020,9 +24037,9 @@ packages: sha256: 126bdbae72087d8d038b113aab6b059b4553cb59348e3024bb1a1cae406ace9e requires_dist: - deprecated - - pyjwt[crypto] >=2.4.0 - - pynacl >=1.4.0 - - requests >=2.14.0 + - pyjwt[crypto]>=2.4.0 + - pynacl>=1.4.0 + - requests>=2.14.0 requires_python: '>=3.7' - kind: pypi name: pyglet @@ -24036,7 +24053,7 @@ packages: url: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz sha256: 4f9481f5841b0b8fb7b271b0414b394b503405260a6ee0cf2c330a5420d19b64 requires_dist: - - dataclasses-json >=0.0.25 + - dataclasses-json>=0.0.25 - deprecated - dataclasses ; python_version >= '3.6' and python_version < '3.7' requires_python: '>=3.6' @@ -24047,67 +24064,67 @@ packages: sha256: 59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 requires_dist: - typing-extensions ; python_version <= '3.7' - - cryptography >=3.4.0 ; extra == 'crypto' - - sphinx <5.0.0, >=4.5.0 ; extra == 'dev' + - cryptography>=3.4.0 ; extra == 'crypto' + - sphinx<5.0.0,>=4.5.0 ; extra == 'dev' - sphinx-rtd-theme ; extra == 'dev' - zope-interface ; extra == 'dev' - - cryptography >=3.4.0 ; extra == 'dev' - - pytest <7.0.0, >=6.0.0 ; extra == 'dev' - - coverage[toml] ==5.0.4 ; extra == 'dev' + - cryptography>=3.4.0 ; extra == 'dev' + - pytest<7.0.0,>=6.0.0 ; extra == 'dev' + - coverage[toml]==5.0.4 ; extra == 'dev' - pre-commit ; extra == 'dev' - - sphinx <5.0.0, >=4.5.0 ; extra == 'docs' + - sphinx<5.0.0,>=4.5.0 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - zope-interface ; extra == 'docs' - - pytest <7.0.0, >=6.0.0 ; extra == 'tests' - - coverage[toml] ==5.0.4 ; extra == 'tests' + - pytest<7.0.0,>=6.0.0 ; extra == 'tests' + - coverage[toml]==5.0.4 ; extra == 'tests' requires_python: '>=3.7' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 + url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl + sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 requires_dist: - - cffi >=1.4.1 - - sphinx >=1.6.5 ; extra == 'docs' + - cffi>=1.4.1 + - sphinx>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - - hypothesis >=3.27.0 ; extra == 'tests' + - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' + - hypothesis>=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d + url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 requires_dist: - - cffi >=1.4.1 - - sphinx >=1.6.5 ; extra == 'docs' + - cffi>=1.4.1 + - sphinx>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - - hypothesis >=3.27.0 ; extra == 'tests' + - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' + - hypothesis>=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 + url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl + sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d requires_dist: - - cffi >=1.4.1 - - sphinx >=1.6.5 ; extra == 'docs' + - cffi>=1.4.1 + - sphinx>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - - hypothesis >=3.27.0 ; extra == 'tests' + - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' + - hypothesis>=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 + url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl + sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 requires_dist: - - cffi >=1.4.1 - - sphinx >=1.6.5 ; extra == 'docs' + - cffi>=1.4.1 + - sphinx>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - - hypothesis >=3.27.0 ; extra == 'tests' + - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' + - hypothesis>=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynndescent @@ -24115,31 +24132,31 @@ packages: url: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl sha256: 9023dc5fea520a4e84d0633ae735db97d2509da927bfa86c897e61f3315473c7 requires_dist: - - scikit-learn >=0.18 - - scipy >=1.0 - - numba >=0.51.2 - - llvmlite >=0.30 - - joblib >=0.11 - - importlib-metadata >=4.8.1 ; python_version < '3.8' + - scikit-learn>=0.18 + - scipy>=1.0 + - numba>=0.51.2 + - llvmlite>=0.30 + - joblib>=0.11 + - importlib-metadata>=4.8.1 ; python_version < '3.8' - kind: pypi name: pyopengl version: 3.1.0 - url: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip - sha256: efa4e39a49b906ccbe66758812ca81ced13a6f26931ab2ba2dba2750c016c0d0 + url: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz + sha256: 9b47c5c3a094fa518ca88aeed35ae75834d53e4285512c61879f67a48c94ddaf - kind: pypi name: pyopf version: 1.1.1 url: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl sha256: 10971881afcb7ed0dd373f7e88862fa8ad0f70fe4329f2ef5093c152e923831f requires_dist: - - argparse >=1.4.0 - - numpy >=1.24.1 - - pillow >=9.5.0 - - pygltflib >=1.15.3 - - python-dateutil >=2.8.2 - - shapely >=2.0.1 - - tqdm >=4.65.0 - - simplejson >=18.3 ; extra == 'tests' + - argparse>=1.4.0 + - numpy>=1.24.1 + - pillow>=9.5.0 + - pygltflib>=1.15.3 + - python-dateutil>=2.8.2 + - shapely>=2.0.1 + - tqdm>=4.65.0 + - simplejson>=18.3 ; extra == 'tests' requires_python: '>=3.10' - kind: pypi name: pyparsing @@ -24161,8 +24178,8 @@ packages: - networkx - numpy - pillow - - pyglet >=1.4.10 - - pyopengl ==3.1.0 + - pyglet>=1.4.10 + - pyopengl==3.1.0 - scipy - six - trimesh @@ -24559,7 +24576,7 @@ packages: url: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 requires_dist: - - six >=1.5 + - six>=1.5 requires_python: '!=3.0.*,!=3.1.*,!=3.2.*,>=2.7' - kind: conda name: python_abi @@ -24672,10 +24689,10 @@ packages: sha256: 29d7482ea0dae8ceb7b95c4adeff04bd362cab0842f3f0a9572b2c42013c7656 requires_dist: - numpy - - pillow - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - - trimesh ==3.15.2 + - trimesh==3.15.2 + - pillow editable: true - kind: conda name: rdma-core @@ -24972,12 +24989,12 @@ packages: url: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl sha256: 58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f requires_dist: - - charset-normalizer <4, >=2 - - idna <4, >=2.5 - - urllib3 <3, >=1.21.1 - - certifi >=2017.4.17 - - pysocks !=1.5.7, >=1.5.6 ; extra == 'socks' - - chardet <6, >=3.0.2 ; extra == 'use_chardet_on_py3' + - charset-normalizer<4,>=2 + - idna<4,>=2.5 + - urllib3<3,>=1.21.1 + - certifi>=2017.4.17 + - pysocks!=1.5.7,>=1.5.6 ; extra == 'socks' + - chardet<6,>=3.0.2 ; extra == 'use_chardet_on_py3' requires_python: '>=3.7' - kind: conda name: requests @@ -25014,8 +25031,8 @@ packages: sha256: b2ef153b0bedd672c3e0ce89b7be1f64f4344b2b75d71748899faea270383fa2 requires_dist: - numpy - - opencv-python >4.6 - - requests <3, >=2.31 + - opencv-python>4.6 + - requests>=2.31,<3 - rerun-sdk - tqdm editable: true @@ -25086,7 +25103,7 @@ packages: url: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl sha256: 90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 requires_dist: - - pyasn1 >=0.1.3 + - pyasn1>=0.1.3 requires_python: '>=3.6,<4' - kind: conda name: ruff @@ -25271,31 +25288,31 @@ packages: url: https://files.pythonhosted.org/packages/d5/85/1e7d2804cbf82204cde462d16f1cb0ff5814b03f559fb46ceaa6b7020db4/safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b requires_dist: - - numpy >=1.21.6 ; extra == 'numpy' + - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch >=1.10 ; extra == 'torch' + - torch>=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow >=2.11.0 ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow ==2.11.0 ; extra == 'pinned-tf' + - tensorflow==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax >=0.6.3 ; extra == 'jax' - - jax >=0.3.25 ; extra == 'jax' - - jaxlib >=0.3.25 ; extra == 'jax' - - mlx >=0.0.9 ; extra == 'mlx' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' - - black ==22.3 ; extra == 'quality' - - click ==8.0.4 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - flake8 >=3.8.3 ; extra == 'quality' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - black==22.3 ; extra == 'quality' + - click==8.0.4 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - flake8>=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py >=3.7.0 ; extra == 'testing' - - huggingface-hub >=0.12.1 ; extra == 'testing' - - setuptools-rust >=1.5.2 ; extra == 'testing' - - pytest >=7.2.0 ; extra == 'testing' - - pytest-benchmark >=4.0.0 ; extra == 'testing' - - hypothesis >=6.70.2 ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - huggingface-hub>=0.12.1 ; extra == 'testing' + - setuptools-rust>=1.5.2 ; extra == 'testing' + - pytest>=7.2.0 ; extra == 'testing' + - pytest-benchmark>=4.0.0 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25311,31 +25328,31 @@ packages: url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe requires_dist: - - numpy >=1.21.6 ; extra == 'numpy' + - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch >=1.10 ; extra == 'torch' + - torch>=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow >=2.11.0 ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow ==2.11.0 ; extra == 'pinned-tf' + - tensorflow==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax >=0.6.3 ; extra == 'jax' - - jax >=0.3.25 ; extra == 'jax' - - jaxlib >=0.3.25 ; extra == 'jax' - - mlx >=0.0.9 ; extra == 'mlx' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' - - black ==22.3 ; extra == 'quality' - - click ==8.0.4 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - flake8 >=3.8.3 ; extra == 'quality' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - black==22.3 ; extra == 'quality' + - click==8.0.4 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - flake8>=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py >=3.7.0 ; extra == 'testing' - - huggingface-hub >=0.12.1 ; extra == 'testing' - - setuptools-rust >=1.5.2 ; extra == 'testing' - - pytest >=7.2.0 ; extra == 'testing' - - pytest-benchmark >=4.0.0 ; extra == 'testing' - - hypothesis >=6.70.2 ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - huggingface-hub>=0.12.1 ; extra == 'testing' + - setuptools-rust>=1.5.2 ; extra == 'testing' + - pytest>=7.2.0 ; extra == 'testing' + - pytest-benchmark>=4.0.0 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25351,31 +25368,31 @@ packages: url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a requires_dist: - - numpy >=1.21.6 ; extra == 'numpy' + - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch >=1.10 ; extra == 'torch' + - torch>=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow >=2.11.0 ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow ==2.11.0 ; extra == 'pinned-tf' + - tensorflow==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax >=0.6.3 ; extra == 'jax' - - jax >=0.3.25 ; extra == 'jax' - - jaxlib >=0.3.25 ; extra == 'jax' - - mlx >=0.0.9 ; extra == 'mlx' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' - - black ==22.3 ; extra == 'quality' - - click ==8.0.4 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - flake8 >=3.8.3 ; extra == 'quality' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - black==22.3 ; extra == 'quality' + - click==8.0.4 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - flake8>=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py >=3.7.0 ; extra == 'testing' - - huggingface-hub >=0.12.1 ; extra == 'testing' - - setuptools-rust >=1.5.2 ; extra == 'testing' - - pytest >=7.2.0 ; extra == 'testing' - - pytest-benchmark >=4.0.0 ; extra == 'testing' - - hypothesis >=6.70.2 ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - huggingface-hub>=0.12.1 ; extra == 'testing' + - setuptools-rust>=1.5.2 ; extra == 'testing' + - pytest>=7.2.0 ; extra == 'testing' + - pytest-benchmark>=4.0.0 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25391,31 +25408,31 @@ packages: url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 requires_dist: - - numpy >=1.21.6 ; extra == 'numpy' + - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch >=1.10 ; extra == 'torch' + - torch>=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow >=2.11.0 ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow ==2.11.0 ; extra == 'pinned-tf' + - tensorflow==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax >=0.6.3 ; extra == 'jax' - - jax >=0.3.25 ; extra == 'jax' - - jaxlib >=0.3.25 ; extra == 'jax' - - mlx >=0.0.9 ; extra == 'mlx' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' - - black ==22.3 ; extra == 'quality' - - click ==8.0.4 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - flake8 >=3.8.3 ; extra == 'quality' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - black==22.3 ; extra == 'quality' + - click==8.0.4 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - flake8>=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py >=3.7.0 ; extra == 'testing' - - huggingface-hub >=0.12.1 ; extra == 'testing' - - setuptools-rust >=1.5.2 ; extra == 'testing' - - pytest >=7.2.0 ; extra == 'testing' - - pytest-benchmark >=4.0.0 ; extra == 'testing' - - hypothesis >=6.70.2 ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - huggingface-hub>=0.12.1 ; extra == 'testing' + - setuptools-rust>=1.5.2 ; extra == 'testing' + - pytest>=7.2.0 ; extra == 'testing' + - pytest-benchmark>=4.0.0 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25431,63 +25448,63 @@ packages: url: https://files.pythonhosted.org/packages/0a/40/2c57864acd77c168b96cb6e4e62651b9c98733962793293991ef55e2982c/scikit_image-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: fce619a6d84fe40c1208fa579b646e93ce13ef0afc3652a23e9782b2c183291a requires_dist: - - numpy >=1.23 - - scipy >=1.9 - - networkx >=2.8 - - pillow >=9.1 - - imageio >=2.33 - - tifffile >=2022.8.12 - - packaging >=21 - - lazy-loader >=0.4 - - meson-python >=0.15 ; extra == 'build' + - numpy>=1.23 + - scipy>=1.9 + - networkx>=2.8 + - pillow>=9.1 + - imageio>=2.33 + - tifffile>=2022.8.12 + - packaging>=21 + - lazy-loader>=0.4 + - meson-python>=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools >=67 ; extra == 'build' - - packaging >=21 ; extra == 'build' + - setuptools>=67 ; extra == 'build' + - packaging>=21 ; extra == 'build' - ninja ; extra == 'build' - - cython >=3.0.4 ; extra == 'build' + - cython>=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy >=2.0.0rc1 ; extra == 'build' - - spin ==0.8 ; extra == 'build' + - numpy>=2.0.0rc1 ; extra == 'build' + - spin==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch >=1.6.0 ; extra == 'data' + - pooch>=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx >=7.3 ; extra == 'docs' - - sphinx-gallery >=0.14 ; extra == 'docs' - - numpydoc >=1.7 ; extra == 'docs' + - sphinx>=7.3 ; extra == 'docs' + - sphinx-gallery>=0.14 ; extra == 'docs' + - numpydoc>=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib >=3.6 ; extra == 'docs' - - dask[array] >=2022.9.2 ; extra == 'docs' - - pandas >=1.5 ; extra == 'docs' - - seaborn >=0.11 ; extra == 'docs' - - pooch >=1.6 ; extra == 'docs' - - tifffile >=2022.8.12 ; extra == 'docs' + - matplotlib>=3.6 ; extra == 'docs' + - dask[array]>=2022.9.2 ; extra == 'docs' + - pandas>=1.5 ; extra == 'docs' + - seaborn>=0.11 ; extra == 'docs' + - pooch>=1.6 ; extra == 'docs' + - tifffile>=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly >=5.10 ; extra == 'docs' + - plotly>=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn >=1.1 ; extra == 'docs' - - sphinx-design >=0.5 ; extra == 'docs' - - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' - - pywavelets >=1.1.1 ; extra == 'docs' + - scikit-learn>=1.1 ; extra == 'docs' + - sphinx-design>=0.5 ; extra == 'docs' + - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' + - pywavelets>=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy >=5.0 ; extra == 'optional' - - cloudpickle >=0.2.1 ; extra == 'optional' - - dask[array] >=2021.1.0 ; extra == 'optional' - - matplotlib >=3.6 ; extra == 'optional' - - pooch >=1.6.0 ; extra == 'optional' + - astropy>=5.0 ; extra == 'optional' + - cloudpickle>=0.2.1 ; extra == 'optional' + - dask[array]>=2021.1.0 ; extra == 'optional' + - matplotlib>=3.6 ; extra == 'optional' + - pooch>=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets >=1.1.1 ; extra == 'optional' - - scikit-learn >=1.1 ; extra == 'optional' + - pywavelets>=1.1.1 ; extra == 'optional' + - scikit-learn>=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc >=1.7 ; extra == 'test' - - pooch >=1.6.0 ; extra == 'test' - - pytest >=7.0 ; extra == 'test' - - pytest-cov >=2.11.0 ; extra == 'test' + - numpydoc>=1.7 ; extra == 'test' + - pooch>=1.6.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-cov>=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25498,63 +25515,63 @@ packages: url: https://files.pythonhosted.org/packages/b9/cf/9e5828fa29791bf7ac5c3fad3637ebb02f237a1c3de8233bd6a33c2c4aac/scikit_image-0.23.2-cp311-cp311-macosx_12_0_arm64.whl sha256: a158f50d3df4867bbd1c698520ede8bc493e430ad83f54ac1f0d8f57b328779b requires_dist: - - numpy >=1.23 - - scipy >=1.9 - - networkx >=2.8 - - pillow >=9.1 - - imageio >=2.33 - - tifffile >=2022.8.12 - - packaging >=21 - - lazy-loader >=0.4 - - meson-python >=0.15 ; extra == 'build' + - numpy>=1.23 + - scipy>=1.9 + - networkx>=2.8 + - pillow>=9.1 + - imageio>=2.33 + - tifffile>=2022.8.12 + - packaging>=21 + - lazy-loader>=0.4 + - meson-python>=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools >=67 ; extra == 'build' - - packaging >=21 ; extra == 'build' + - setuptools>=67 ; extra == 'build' + - packaging>=21 ; extra == 'build' - ninja ; extra == 'build' - - cython >=3.0.4 ; extra == 'build' + - cython>=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy >=2.0.0rc1 ; extra == 'build' - - spin ==0.8 ; extra == 'build' + - numpy>=2.0.0rc1 ; extra == 'build' + - spin==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch >=1.6.0 ; extra == 'data' + - pooch>=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx >=7.3 ; extra == 'docs' - - sphinx-gallery >=0.14 ; extra == 'docs' - - numpydoc >=1.7 ; extra == 'docs' + - sphinx>=7.3 ; extra == 'docs' + - sphinx-gallery>=0.14 ; extra == 'docs' + - numpydoc>=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib >=3.6 ; extra == 'docs' - - dask[array] >=2022.9.2 ; extra == 'docs' - - pandas >=1.5 ; extra == 'docs' - - seaborn >=0.11 ; extra == 'docs' - - pooch >=1.6 ; extra == 'docs' - - tifffile >=2022.8.12 ; extra == 'docs' + - matplotlib>=3.6 ; extra == 'docs' + - dask[array]>=2022.9.2 ; extra == 'docs' + - pandas>=1.5 ; extra == 'docs' + - seaborn>=0.11 ; extra == 'docs' + - pooch>=1.6 ; extra == 'docs' + - tifffile>=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly >=5.10 ; extra == 'docs' + - plotly>=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn >=1.1 ; extra == 'docs' - - sphinx-design >=0.5 ; extra == 'docs' - - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' - - pywavelets >=1.1.1 ; extra == 'docs' + - scikit-learn>=1.1 ; extra == 'docs' + - sphinx-design>=0.5 ; extra == 'docs' + - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' + - pywavelets>=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy >=5.0 ; extra == 'optional' - - cloudpickle >=0.2.1 ; extra == 'optional' - - dask[array] >=2021.1.0 ; extra == 'optional' - - matplotlib >=3.6 ; extra == 'optional' - - pooch >=1.6.0 ; extra == 'optional' + - astropy>=5.0 ; extra == 'optional' + - cloudpickle>=0.2.1 ; extra == 'optional' + - dask[array]>=2021.1.0 ; extra == 'optional' + - matplotlib>=3.6 ; extra == 'optional' + - pooch>=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets >=1.1.1 ; extra == 'optional' - - scikit-learn >=1.1 ; extra == 'optional' + - pywavelets>=1.1.1 ; extra == 'optional' + - scikit-learn>=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc >=1.7 ; extra == 'test' - - pooch >=1.6.0 ; extra == 'test' - - pytest >=7.0 ; extra == 'test' - - pytest-cov >=2.11.0 ; extra == 'test' + - numpydoc>=1.7 ; extra == 'test' + - pooch>=1.6.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-cov>=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25565,63 +25582,63 @@ packages: url: https://files.pythonhosted.org/packages/78/2b/5f985cf4cf59378f80dc212004a7692b7b49b2a3910c3584d70284db5b89/scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl sha256: ee83fdb1843ee938eabdfeb9498623282935ea30aa20dffc5d5d16698efb4b2a requires_dist: - - numpy >=1.23 - - scipy >=1.9 - - networkx >=2.8 - - pillow >=9.1 - - imageio >=2.33 - - tifffile >=2022.8.12 - - packaging >=21 - - lazy-loader >=0.4 - - meson-python >=0.15 ; extra == 'build' + - numpy>=1.23 + - scipy>=1.9 + - networkx>=2.8 + - pillow>=9.1 + - imageio>=2.33 + - tifffile>=2022.8.12 + - packaging>=21 + - lazy-loader>=0.4 + - meson-python>=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools >=67 ; extra == 'build' - - packaging >=21 ; extra == 'build' + - setuptools>=67 ; extra == 'build' + - packaging>=21 ; extra == 'build' - ninja ; extra == 'build' - - cython >=3.0.4 ; extra == 'build' + - cython>=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy >=2.0.0rc1 ; extra == 'build' - - spin ==0.8 ; extra == 'build' + - numpy>=2.0.0rc1 ; extra == 'build' + - spin==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch >=1.6.0 ; extra == 'data' + - pooch>=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx >=7.3 ; extra == 'docs' - - sphinx-gallery >=0.14 ; extra == 'docs' - - numpydoc >=1.7 ; extra == 'docs' + - sphinx>=7.3 ; extra == 'docs' + - sphinx-gallery>=0.14 ; extra == 'docs' + - numpydoc>=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib >=3.6 ; extra == 'docs' - - dask[array] >=2022.9.2 ; extra == 'docs' - - pandas >=1.5 ; extra == 'docs' - - seaborn >=0.11 ; extra == 'docs' - - pooch >=1.6 ; extra == 'docs' - - tifffile >=2022.8.12 ; extra == 'docs' + - matplotlib>=3.6 ; extra == 'docs' + - dask[array]>=2022.9.2 ; extra == 'docs' + - pandas>=1.5 ; extra == 'docs' + - seaborn>=0.11 ; extra == 'docs' + - pooch>=1.6 ; extra == 'docs' + - tifffile>=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly >=5.10 ; extra == 'docs' + - plotly>=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn >=1.1 ; extra == 'docs' - - sphinx-design >=0.5 ; extra == 'docs' - - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' - - pywavelets >=1.1.1 ; extra == 'docs' + - scikit-learn>=1.1 ; extra == 'docs' + - sphinx-design>=0.5 ; extra == 'docs' + - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' + - pywavelets>=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy >=5.0 ; extra == 'optional' - - cloudpickle >=0.2.1 ; extra == 'optional' - - dask[array] >=2021.1.0 ; extra == 'optional' - - matplotlib >=3.6 ; extra == 'optional' - - pooch >=1.6.0 ; extra == 'optional' + - astropy>=5.0 ; extra == 'optional' + - cloudpickle>=0.2.1 ; extra == 'optional' + - dask[array]>=2021.1.0 ; extra == 'optional' + - matplotlib>=3.6 ; extra == 'optional' + - pooch>=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets >=1.1.1 ; extra == 'optional' - - scikit-learn >=1.1 ; extra == 'optional' + - pywavelets>=1.1.1 ; extra == 'optional' + - scikit-learn>=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc >=1.7 ; extra == 'test' - - pooch >=1.6.0 ; extra == 'test' - - pytest >=7.0 ; extra == 'test' - - pytest-cov >=2.11.0 ; extra == 'test' + - numpydoc>=1.7 ; extra == 'test' + - pooch>=1.6.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-cov>=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25632,63 +25649,63 @@ packages: url: https://files.pythonhosted.org/packages/eb/ab/8791ce3063e6d4ac7f8efe3c993fd2e911c9e08f4c7dd05b603eaa2493b2/scikit_image-0.23.2-cp311-cp311-win_amd64.whl sha256: ee65669aa586e110346f567ed5c92d1bd63799a19e951cb83da3f54b0caf7c52 requires_dist: - - numpy >=1.23 - - scipy >=1.9 - - networkx >=2.8 - - pillow >=9.1 - - imageio >=2.33 - - tifffile >=2022.8.12 - - packaging >=21 - - lazy-loader >=0.4 - - meson-python >=0.15 ; extra == 'build' + - numpy>=1.23 + - scipy>=1.9 + - networkx>=2.8 + - pillow>=9.1 + - imageio>=2.33 + - tifffile>=2022.8.12 + - packaging>=21 + - lazy-loader>=0.4 + - meson-python>=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools >=67 ; extra == 'build' - - packaging >=21 ; extra == 'build' + - setuptools>=67 ; extra == 'build' + - packaging>=21 ; extra == 'build' - ninja ; extra == 'build' - - cython >=3.0.4 ; extra == 'build' + - cython>=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy >=2.0.0rc1 ; extra == 'build' - - spin ==0.8 ; extra == 'build' + - numpy>=2.0.0rc1 ; extra == 'build' + - spin==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch >=1.6.0 ; extra == 'data' + - pooch>=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx >=7.3 ; extra == 'docs' - - sphinx-gallery >=0.14 ; extra == 'docs' - - numpydoc >=1.7 ; extra == 'docs' + - sphinx>=7.3 ; extra == 'docs' + - sphinx-gallery>=0.14 ; extra == 'docs' + - numpydoc>=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib >=3.6 ; extra == 'docs' - - dask[array] >=2022.9.2 ; extra == 'docs' - - pandas >=1.5 ; extra == 'docs' - - seaborn >=0.11 ; extra == 'docs' - - pooch >=1.6 ; extra == 'docs' - - tifffile >=2022.8.12 ; extra == 'docs' + - matplotlib>=3.6 ; extra == 'docs' + - dask[array]>=2022.9.2 ; extra == 'docs' + - pandas>=1.5 ; extra == 'docs' + - seaborn>=0.11 ; extra == 'docs' + - pooch>=1.6 ; extra == 'docs' + - tifffile>=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly >=5.10 ; extra == 'docs' + - plotly>=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn >=1.1 ; extra == 'docs' - - sphinx-design >=0.5 ; extra == 'docs' - - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' - - pywavelets >=1.1.1 ; extra == 'docs' + - scikit-learn>=1.1 ; extra == 'docs' + - sphinx-design>=0.5 ; extra == 'docs' + - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' + - pywavelets>=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy >=5.0 ; extra == 'optional' - - cloudpickle >=0.2.1 ; extra == 'optional' - - dask[array] >=2021.1.0 ; extra == 'optional' - - matplotlib >=3.6 ; extra == 'optional' - - pooch >=1.6.0 ; extra == 'optional' + - astropy>=5.0 ; extra == 'optional' + - cloudpickle>=0.2.1 ; extra == 'optional' + - dask[array]>=2021.1.0 ; extra == 'optional' + - matplotlib>=3.6 ; extra == 'optional' + - pooch>=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets >=1.1.1 ; extra == 'optional' - - scikit-learn >=1.1 ; extra == 'optional' + - pywavelets>=1.1.1 ; extra == 'optional' + - scikit-learn>=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc >=1.7 ; extra == 'test' - - pooch >=1.6.0 ; extra == 'test' - - pytest >=7.0 ; extra == 'test' - - pytest-cov >=2.11.0 ; extra == 'test' + - numpydoc>=1.7 ; extra == 'test' + - pooch>=1.6.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-cov>=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25699,46 +25716,46 @@ packages: url: https://files.pythonhosted.org/packages/4e/53/14405a47292b59235d811a2af8634aba188ccfd1a38ef4b8042f3447d79a/scikit_learn-1.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 44c62f2b124848a28fd695db5bc4da019287abf390bfce602ddc8aa1ec186aae requires_dist: - - numpy >=1.19.5 - - scipy >=1.6.0 - - joblib >=1.2.0 - - threadpoolctl >=2.0.0 - - matplotlib >=3.3.4 ; extra == 'benchmark' - - pandas >=1.1.5 ; extra == 'benchmark' - - memory-profiler >=0.57.0 ; extra == 'benchmark' - - matplotlib >=3.3.4 ; extra == 'docs' - - scikit-image >=0.17.2 ; extra == 'docs' - - pandas >=1.1.5 ; extra == 'docs' - - seaborn >=0.9.0 ; extra == 'docs' - - memory-profiler >=0.57.0 ; extra == 'docs' - - sphinx >=6.0.0 ; extra == 'docs' - - sphinx-copybutton >=0.5.2 ; extra == 'docs' - - sphinx-gallery >=0.15.0 ; extra == 'docs' - - numpydoc >=1.2.0 ; extra == 'docs' - - pillow >=7.1.2 ; extra == 'docs' - - pooch >=1.6.0 ; extra == 'docs' - - sphinx-prompt >=1.3.0 ; extra == 'docs' - - sphinxext-opengraph >=0.4.2 ; extra == 'docs' - - plotly >=5.14.0 ; extra == 'docs' - - matplotlib >=3.3.4 ; extra == 'examples' - - scikit-image >=0.17.2 ; extra == 'examples' - - pandas >=1.1.5 ; extra == 'examples' - - seaborn >=0.9.0 ; extra == 'examples' - - pooch >=1.6.0 ; extra == 'examples' - - plotly >=5.14.0 ; extra == 'examples' - - matplotlib >=3.3.4 ; extra == 'tests' - - scikit-image >=0.17.2 ; extra == 'tests' - - pandas >=1.1.5 ; extra == 'tests' - - pytest >=7.1.2 ; extra == 'tests' - - pytest-cov >=2.9.0 ; extra == 'tests' - - ruff >=0.0.272 ; extra == 'tests' - - black >=23.3.0 ; extra == 'tests' - - mypy >=1.3 ; extra == 'tests' - - pyamg >=4.0.0 ; extra == 'tests' - - polars >=0.19.12 ; extra == 'tests' - - pyarrow >=12.0.0 ; extra == 'tests' - - numpydoc >=1.2.0 ; extra == 'tests' - - pooch >=1.6.0 ; extra == 'tests' + - numpy>=1.19.5 + - scipy>=1.6.0 + - joblib>=1.2.0 + - threadpoolctl>=2.0.0 + - matplotlib>=3.3.4 ; extra == 'benchmark' + - pandas>=1.1.5 ; extra == 'benchmark' + - memory-profiler>=0.57.0 ; extra == 'benchmark' + - matplotlib>=3.3.4 ; extra == 'docs' + - scikit-image>=0.17.2 ; extra == 'docs' + - pandas>=1.1.5 ; extra == 'docs' + - seaborn>=0.9.0 ; extra == 'docs' + - memory-profiler>=0.57.0 ; extra == 'docs' + - sphinx>=6.0.0 ; extra == 'docs' + - sphinx-copybutton>=0.5.2 ; extra == 'docs' + - sphinx-gallery>=0.15.0 ; extra == 'docs' + - numpydoc>=1.2.0 ; extra == 'docs' + - pillow>=7.1.2 ; extra == 'docs' + - pooch>=1.6.0 ; extra == 'docs' + - sphinx-prompt>=1.3.0 ; extra == 'docs' + - sphinxext-opengraph>=0.4.2 ; extra == 'docs' + - plotly>=5.14.0 ; extra == 'docs' + - matplotlib>=3.3.4 ; extra == 'examples' + - scikit-image>=0.17.2 ; extra == 'examples' + - pandas>=1.1.5 ; extra == 'examples' + - seaborn>=0.9.0 ; extra == 'examples' + - pooch>=1.6.0 ; extra == 'examples' + - plotly>=5.14.0 ; extra == 'examples' + - matplotlib>=3.3.4 ; extra == 'tests' + - scikit-image>=0.17.2 ; extra == 'tests' + - pandas>=1.1.5 ; extra == 'tests' + - pytest>=7.1.2 ; extra == 'tests' + - pytest-cov>=2.9.0 ; extra == 'tests' + - ruff>=0.0.272 ; extra == 'tests' + - black>=23.3.0 ; extra == 'tests' + - mypy>=1.3 ; extra == 'tests' + - pyamg>=4.0.0 ; extra == 'tests' + - polars>=0.19.12 ; extra == 'tests' + - pyarrow>=12.0.0 ; extra == 'tests' + - numpydoc>=1.2.0 ; extra == 'tests' + - pooch>=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn @@ -25746,46 +25763,46 @@ packages: url: https://files.pythonhosted.org/packages/f2/30/1299e84d2ba3bc735baf17cebbf5b9d55144243c41b3ec6559ce3cf61e23/scikit_learn-1.4.2-cp311-cp311-macosx_12_0_arm64.whl sha256: 1d0b25d9c651fd050555aadd57431b53d4cf664e749069da77f3d52c5ad14b3b requires_dist: - - numpy >=1.19.5 - - scipy >=1.6.0 - - joblib >=1.2.0 - - threadpoolctl >=2.0.0 - - matplotlib >=3.3.4 ; extra == 'benchmark' - - pandas >=1.1.5 ; extra == 'benchmark' - - memory-profiler >=0.57.0 ; extra == 'benchmark' - - matplotlib >=3.3.4 ; extra == 'docs' - - scikit-image >=0.17.2 ; extra == 'docs' - - pandas >=1.1.5 ; extra == 'docs' - - seaborn >=0.9.0 ; extra == 'docs' - - memory-profiler >=0.57.0 ; extra == 'docs' - - sphinx >=6.0.0 ; extra == 'docs' - - sphinx-copybutton >=0.5.2 ; extra == 'docs' - - sphinx-gallery >=0.15.0 ; extra == 'docs' - - numpydoc >=1.2.0 ; extra == 'docs' - - pillow >=7.1.2 ; extra == 'docs' - - pooch >=1.6.0 ; extra == 'docs' - - sphinx-prompt >=1.3.0 ; extra == 'docs' - - sphinxext-opengraph >=0.4.2 ; extra == 'docs' - - plotly >=5.14.0 ; extra == 'docs' - - matplotlib >=3.3.4 ; extra == 'examples' - - scikit-image >=0.17.2 ; extra == 'examples' - - pandas >=1.1.5 ; extra == 'examples' - - seaborn >=0.9.0 ; extra == 'examples' - - pooch >=1.6.0 ; extra == 'examples' - - plotly >=5.14.0 ; extra == 'examples' - - matplotlib >=3.3.4 ; extra == 'tests' - - scikit-image >=0.17.2 ; extra == 'tests' - - pandas >=1.1.5 ; extra == 'tests' - - pytest >=7.1.2 ; extra == 'tests' - - pytest-cov >=2.9.0 ; extra == 'tests' - - ruff >=0.0.272 ; extra == 'tests' - - black >=23.3.0 ; extra == 'tests' - - mypy >=1.3 ; extra == 'tests' - - pyamg >=4.0.0 ; extra == 'tests' - - polars >=0.19.12 ; extra == 'tests' - - pyarrow >=12.0.0 ; extra == 'tests' - - numpydoc >=1.2.0 ; extra == 'tests' - - pooch >=1.6.0 ; extra == 'tests' + - numpy>=1.19.5 + - scipy>=1.6.0 + - joblib>=1.2.0 + - threadpoolctl>=2.0.0 + - matplotlib>=3.3.4 ; extra == 'benchmark' + - pandas>=1.1.5 ; extra == 'benchmark' + - memory-profiler>=0.57.0 ; extra == 'benchmark' + - matplotlib>=3.3.4 ; extra == 'docs' + - scikit-image>=0.17.2 ; extra == 'docs' + - pandas>=1.1.5 ; extra == 'docs' + - seaborn>=0.9.0 ; extra == 'docs' + - memory-profiler>=0.57.0 ; extra == 'docs' + - sphinx>=6.0.0 ; extra == 'docs' + - sphinx-copybutton>=0.5.2 ; extra == 'docs' + - sphinx-gallery>=0.15.0 ; extra == 'docs' + - numpydoc>=1.2.0 ; extra == 'docs' + - pillow>=7.1.2 ; extra == 'docs' + - pooch>=1.6.0 ; extra == 'docs' + - sphinx-prompt>=1.3.0 ; extra == 'docs' + - sphinxext-opengraph>=0.4.2 ; extra == 'docs' + - plotly>=5.14.0 ; extra == 'docs' + - matplotlib>=3.3.4 ; extra == 'examples' + - scikit-image>=0.17.2 ; extra == 'examples' + - pandas>=1.1.5 ; extra == 'examples' + - seaborn>=0.9.0 ; extra == 'examples' + - pooch>=1.6.0 ; extra == 'examples' + - plotly>=5.14.0 ; extra == 'examples' + - matplotlib>=3.3.4 ; extra == 'tests' + - scikit-image>=0.17.2 ; extra == 'tests' + - pandas>=1.1.5 ; extra == 'tests' + - pytest>=7.1.2 ; extra == 'tests' + - pytest-cov>=2.9.0 ; extra == 'tests' + - ruff>=0.0.272 ; extra == 'tests' + - black>=23.3.0 ; extra == 'tests' + - mypy>=1.3 ; extra == 'tests' + - pyamg>=4.0.0 ; extra == 'tests' + - polars>=0.19.12 ; extra == 'tests' + - pyarrow>=12.0.0 ; extra == 'tests' + - numpydoc>=1.2.0 ; extra == 'tests' + - pooch>=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn @@ -25793,46 +25810,46 @@ packages: url: https://files.pythonhosted.org/packages/59/11/63de36e6933b03490fdfe5cbc9b5a68870a1281d8e705a23b33076dc82fb/scikit_learn-1.4.2-cp311-cp311-macosx_10_9_x86_64.whl sha256: 45dee87ac5309bb82e3ea633955030df9bbcb8d2cdb30383c6cd483691c546cc requires_dist: - - numpy >=1.19.5 - - scipy >=1.6.0 - - joblib >=1.2.0 - - threadpoolctl >=2.0.0 - - matplotlib >=3.3.4 ; extra == 'benchmark' - - pandas >=1.1.5 ; extra == 'benchmark' - - memory-profiler >=0.57.0 ; extra == 'benchmark' - - matplotlib >=3.3.4 ; extra == 'docs' - - scikit-image >=0.17.2 ; extra == 'docs' - - pandas >=1.1.5 ; extra == 'docs' - - seaborn >=0.9.0 ; extra == 'docs' - - memory-profiler >=0.57.0 ; extra == 'docs' - - sphinx >=6.0.0 ; extra == 'docs' - - sphinx-copybutton >=0.5.2 ; extra == 'docs' - - sphinx-gallery >=0.15.0 ; extra == 'docs' - - numpydoc >=1.2.0 ; extra == 'docs' - - pillow >=7.1.2 ; extra == 'docs' - - pooch >=1.6.0 ; extra == 'docs' - - sphinx-prompt >=1.3.0 ; extra == 'docs' - - sphinxext-opengraph >=0.4.2 ; extra == 'docs' - - plotly >=5.14.0 ; extra == 'docs' - - matplotlib >=3.3.4 ; extra == 'examples' - - scikit-image >=0.17.2 ; extra == 'examples' - - pandas >=1.1.5 ; extra == 'examples' - - seaborn >=0.9.0 ; extra == 'examples' - - pooch >=1.6.0 ; extra == 'examples' - - plotly >=5.14.0 ; extra == 'examples' - - matplotlib >=3.3.4 ; extra == 'tests' - - scikit-image >=0.17.2 ; extra == 'tests' - - pandas >=1.1.5 ; extra == 'tests' - - pytest >=7.1.2 ; extra == 'tests' - - pytest-cov >=2.9.0 ; extra == 'tests' - - ruff >=0.0.272 ; extra == 'tests' - - black >=23.3.0 ; extra == 'tests' - - mypy >=1.3 ; extra == 'tests' - - pyamg >=4.0.0 ; extra == 'tests' - - polars >=0.19.12 ; extra == 'tests' - - pyarrow >=12.0.0 ; extra == 'tests' - - numpydoc >=1.2.0 ; extra == 'tests' - - pooch >=1.6.0 ; extra == 'tests' + - numpy>=1.19.5 + - scipy>=1.6.0 + - joblib>=1.2.0 + - threadpoolctl>=2.0.0 + - matplotlib>=3.3.4 ; extra == 'benchmark' + - pandas>=1.1.5 ; extra == 'benchmark' + - memory-profiler>=0.57.0 ; extra == 'benchmark' + - matplotlib>=3.3.4 ; extra == 'docs' + - scikit-image>=0.17.2 ; extra == 'docs' + - pandas>=1.1.5 ; extra == 'docs' + - seaborn>=0.9.0 ; extra == 'docs' + - memory-profiler>=0.57.0 ; extra == 'docs' + - sphinx>=6.0.0 ; extra == 'docs' + - sphinx-copybutton>=0.5.2 ; extra == 'docs' + - sphinx-gallery>=0.15.0 ; extra == 'docs' + - numpydoc>=1.2.0 ; extra == 'docs' + - pillow>=7.1.2 ; extra == 'docs' + - pooch>=1.6.0 ; extra == 'docs' + - sphinx-prompt>=1.3.0 ; extra == 'docs' + - sphinxext-opengraph>=0.4.2 ; extra == 'docs' + - plotly>=5.14.0 ; extra == 'docs' + - matplotlib>=3.3.4 ; extra == 'examples' + - scikit-image>=0.17.2 ; extra == 'examples' + - pandas>=1.1.5 ; extra == 'examples' + - seaborn>=0.9.0 ; extra == 'examples' + - pooch>=1.6.0 ; extra == 'examples' + - plotly>=5.14.0 ; extra == 'examples' + - matplotlib>=3.3.4 ; extra == 'tests' + - scikit-image>=0.17.2 ; extra == 'tests' + - pandas>=1.1.5 ; extra == 'tests' + - pytest>=7.1.2 ; extra == 'tests' + - pytest-cov>=2.9.0 ; extra == 'tests' + - ruff>=0.0.272 ; extra == 'tests' + - black>=23.3.0 ; extra == 'tests' + - mypy>=1.3 ; extra == 'tests' + - pyamg>=4.0.0 ; extra == 'tests' + - polars>=0.19.12 ; extra == 'tests' + - pyarrow>=12.0.0 ; extra == 'tests' + - numpydoc>=1.2.0 ; extra == 'tests' + - pooch>=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn @@ -25840,46 +25857,46 @@ packages: url: https://files.pythonhosted.org/packages/79/3d/02d5d3ed359498fec3abdf65407d3c07e3b8765af17464969055aaec5171/scikit_learn-1.4.2-cp311-cp311-win_amd64.whl sha256: 5cd7b524115499b18b63f0c96f4224eb885564937a0b3477531b2b63ce331904 requires_dist: - - numpy >=1.19.5 - - scipy >=1.6.0 - - joblib >=1.2.0 - - threadpoolctl >=2.0.0 - - matplotlib >=3.3.4 ; extra == 'benchmark' - - pandas >=1.1.5 ; extra == 'benchmark' - - memory-profiler >=0.57.0 ; extra == 'benchmark' - - matplotlib >=3.3.4 ; extra == 'docs' - - scikit-image >=0.17.2 ; extra == 'docs' - - pandas >=1.1.5 ; extra == 'docs' - - seaborn >=0.9.0 ; extra == 'docs' - - memory-profiler >=0.57.0 ; extra == 'docs' - - sphinx >=6.0.0 ; extra == 'docs' - - sphinx-copybutton >=0.5.2 ; extra == 'docs' - - sphinx-gallery >=0.15.0 ; extra == 'docs' - - numpydoc >=1.2.0 ; extra == 'docs' - - pillow >=7.1.2 ; extra == 'docs' - - pooch >=1.6.0 ; extra == 'docs' - - sphinx-prompt >=1.3.0 ; extra == 'docs' - - sphinxext-opengraph >=0.4.2 ; extra == 'docs' - - plotly >=5.14.0 ; extra == 'docs' - - matplotlib >=3.3.4 ; extra == 'examples' - - scikit-image >=0.17.2 ; extra == 'examples' - - pandas >=1.1.5 ; extra == 'examples' - - seaborn >=0.9.0 ; extra == 'examples' - - pooch >=1.6.0 ; extra == 'examples' - - plotly >=5.14.0 ; extra == 'examples' - - matplotlib >=3.3.4 ; extra == 'tests' - - scikit-image >=0.17.2 ; extra == 'tests' - - pandas >=1.1.5 ; extra == 'tests' - - pytest >=7.1.2 ; extra == 'tests' - - pytest-cov >=2.9.0 ; extra == 'tests' - - ruff >=0.0.272 ; extra == 'tests' - - black >=23.3.0 ; extra == 'tests' - - mypy >=1.3 ; extra == 'tests' - - pyamg >=4.0.0 ; extra == 'tests' - - polars >=0.19.12 ; extra == 'tests' - - pyarrow >=12.0.0 ; extra == 'tests' - - numpydoc >=1.2.0 ; extra == 'tests' - - pooch >=1.6.0 ; extra == 'tests' + - numpy>=1.19.5 + - scipy>=1.6.0 + - joblib>=1.2.0 + - threadpoolctl>=2.0.0 + - matplotlib>=3.3.4 ; extra == 'benchmark' + - pandas>=1.1.5 ; extra == 'benchmark' + - memory-profiler>=0.57.0 ; extra == 'benchmark' + - matplotlib>=3.3.4 ; extra == 'docs' + - scikit-image>=0.17.2 ; extra == 'docs' + - pandas>=1.1.5 ; extra == 'docs' + - seaborn>=0.9.0 ; extra == 'docs' + - memory-profiler>=0.57.0 ; extra == 'docs' + - sphinx>=6.0.0 ; extra == 'docs' + - sphinx-copybutton>=0.5.2 ; extra == 'docs' + - sphinx-gallery>=0.15.0 ; extra == 'docs' + - numpydoc>=1.2.0 ; extra == 'docs' + - pillow>=7.1.2 ; extra == 'docs' + - pooch>=1.6.0 ; extra == 'docs' + - sphinx-prompt>=1.3.0 ; extra == 'docs' + - sphinxext-opengraph>=0.4.2 ; extra == 'docs' + - plotly>=5.14.0 ; extra == 'docs' + - matplotlib>=3.3.4 ; extra == 'examples' + - scikit-image>=0.17.2 ; extra == 'examples' + - pandas>=1.1.5 ; extra == 'examples' + - seaborn>=0.9.0 ; extra == 'examples' + - pooch>=1.6.0 ; extra == 'examples' + - plotly>=5.14.0 ; extra == 'examples' + - matplotlib>=3.3.4 ; extra == 'tests' + - scikit-image>=0.17.2 ; extra == 'tests' + - pandas>=1.1.5 ; extra == 'tests' + - pytest>=7.1.2 ; extra == 'tests' + - pytest-cov>=2.9.0 ; extra == 'tests' + - ruff>=0.0.272 ; extra == 'tests' + - black>=23.3.0 ; extra == 'tests' + - mypy>=1.3 ; extra == 'tests' + - pyamg>=4.0.0 ; extra == 'tests' + - polars>=0.19.12 ; extra == 'tests' + - pyarrow>=12.0.0 ; extra == 'tests' + - numpydoc>=1.2.0 ; extra == 'tests' + - pooch>=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scipy @@ -25887,7 +25904,7 @@ packages: url: https://files.pythonhosted.org/packages/e8/fb/e5955e2ddbdf2baee461eb53ec8d0adedd20a6dfc5510ef8d5e7e44ba461/scipy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 9ff7dad5d24a8045d836671e082a490848e8639cabb3dbdacb29f943a678683d requires_dist: - - numpy <2.3, >=1.22.4 + - numpy<2.3,>=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25898,26 +25915,26 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis >=6.30 ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx >=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' - - sphinx-design >=0.4.0 ; extra == 'doc' - - matplotlib >=3.5 ; extra == 'doc' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint >=0.12.2 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit >=0.36.0 ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -25926,7 +25943,7 @@ packages: url: https://files.pythonhosted.org/packages/51/b6/188c8974d747b2998d672040c5b62a635a72240c515dc4577a28e1dedc80/scipy-1.13.0-cp311-cp311-macosx_12_0_arm64.whl sha256: 5e4a756355522eb60fcd61f8372ac2549073c8788f6114449b37e9e8104f15a5 requires_dist: - - numpy <2.3, >=1.22.4 + - numpy<2.3,>=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25937,26 +25954,26 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis >=6.30 ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx >=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' - - sphinx-design >=0.4.0 ; extra == 'doc' - - matplotlib >=3.5 ; extra == 'doc' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint >=0.12.2 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit >=0.36.0 ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -25965,7 +25982,7 @@ packages: url: https://files.pythonhosted.org/packages/be/e3/236639c51636ec7e678f2aa608fe89acb9d02ef64e1fe1d8eb40373bc62b/scipy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl sha256: 0fbcf8abaf5aa2dc8d6400566c1a727aed338b5fe880cde64907596a89d576fa requires_dist: - - numpy <2.3, >=1.22.4 + - numpy<2.3,>=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25976,26 +25993,26 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis >=6.30 ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx >=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' - - sphinx-design >=0.4.0 ; extra == 'doc' - - matplotlib >=3.5 ; extra == 'doc' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint >=0.12.2 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit >=0.36.0 ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -26004,7 +26021,7 @@ packages: url: https://files.pythonhosted.org/packages/d4/a1/d4adf25b6d2bef8d0ad1682829dcfcba97f3f96bb5b6f137bc3e41003cc7/scipy-1.13.0-cp311-cp311-win_amd64.whl sha256: a2f471de4d01200718b2b8927f7d76b5d9bde18047ea0fa8bd15c5ba3f26a1d6 requires_dist: - - numpy <2.3, >=1.22.4 + - numpy<2.3,>=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -26015,26 +26032,26 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis >=6.30 ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx >=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' - - sphinx-design >=0.4.0 ; extra == 'doc' - - matplotlib >=3.5 ; extra == 'doc' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint >=0.12.2 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit >=0.36.0 ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -26057,11 +26074,11 @@ packages: path: examples/python/segment_anything_model sha256: 753b1345fb994adb562c3eb8199c98f90cea10ac5f5a394575854d959ba22424 requires_dist: + - segment-anything @ git+https://github.com/facebookresearch/segment-anything.git - numpy - opencv-python - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - - segment-anything @ git+https://github.com/facebookresearch/segment-anything.git - torch - torchvision - tqdm @@ -26144,8 +26161,8 @@ packages: url: https://files.pythonhosted.org/packages/d5/fb/bcf6a8164ed307c99f1a8fabe5acd86ac99a33f52530a3ca84b0936f95bd/shapely-2.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 4310b5494271e18580d61022c0857eb85d30510d88606fa3b8314790df7f367d requires_dist: - - numpy <3, >=1.14 - - numpydoc ==1.1.* ; extra == 'docs' + - numpy<3,>=1.14 + - numpydoc==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26159,8 +26176,8 @@ packages: url: https://files.pythonhosted.org/packages/2a/fb/e3f72b10a90e26bb1a92a38b3f30f3074ebac6d532f87848ac09c3e8a73b/shapely-2.0.4-cp311-cp311-macosx_11_0_arm64.whl sha256: 58b0ecc505bbe49a99551eea3f2e8a9b3b24b3edd2a4de1ac0dc17bc75c9ec07 requires_dist: - - numpy <3, >=1.14 - - numpydoc ==1.1.* ; extra == 'docs' + - numpy<3,>=1.14 + - numpydoc==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26174,8 +26191,8 @@ packages: url: https://files.pythonhosted.org/packages/93/fd/b205661ed60294a344406fb04227042fcede9501e81ee1e7018e9159455a/shapely-2.0.4-cp311-cp311-macosx_10_9_x86_64.whl sha256: 7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7 requires_dist: - - numpy <3, >=1.14 - - numpydoc ==1.1.* ; extra == 'docs' + - numpy<3,>=1.14 + - numpydoc==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26189,8 +26206,8 @@ packages: url: https://files.pythonhosted.org/packages/6a/5c/3330f499ca860f0b92db4ceaebd7090096a83c1ea3ae7d8d4c6111761b82/shapely-2.0.4-cp311-cp311-win_amd64.whl sha256: c52ed79f683f721b69a10fb9e3d940a468203f5054927215586c5d49a072de8d requires_dist: - - numpy <3, >=1.14 - - numpydoc ==1.1.* ; extra == 'docs' + - numpy<3,>=1.14 + - numpydoc==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26214,10 +26231,10 @@ packages: requires_dist: - mesh-to-sdf @ git+https://github.com/marian42/mesh_to_sdf.git - numpy - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - - scikit-learn >=1.1.3 - - trimesh ==3.15.2 + - scikit-learn>=1.1.3 + - trimesh==3.15.2 editable: true - kind: conda name: sigtool @@ -26431,7 +26448,7 @@ packages: url: https://files.pythonhosted.org/packages/d7/d5/f0a0aba169f23657c7af3f0c878db7413a9a3b113026fc759862a697c611/sounddevice-0.4.6-py3-none-any.whl sha256: 5de768ba6fe56ad2b5aaa2eea794b76b73e427961c95acad2ee2ed7f866a4b20 requires_dist: - - cffi >=1.0 + - cffi>=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi @@ -26440,7 +26457,7 @@ packages: url: https://files.pythonhosted.org/packages/24/5a/c0b9066fcaf783054b3f35254938dcba2d8cf02576ebdc56b6b4e85661f2/sounddevice-0.4.6-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl sha256: 8b0b806c205dd3e3cd5a97262b2482624fd21db7d47083b887090148a08051c8 requires_dist: - - cffi >=1.0 + - cffi>=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi @@ -26449,7 +26466,7 @@ packages: url: https://files.pythonhosted.org/packages/39/ae/5e84220bfca4256e4ca2a62a174636089ab6ff671b5f9ddd7e8238587acd/sounddevice-0.4.6-py3-none-win_amd64.whl sha256: 7830d4f8f8570f2e5552942f81d96999c5fcd9a0b682d6fc5d5c5529df23be2c requires_dist: - - cffi >=1.0 + - cffi>=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi @@ -26477,9 +26494,9 @@ packages: path: examples/python/structure_from_motion sha256: b20b79aa7bb2b4225b37d3cb28872a70dc7e9ab2ca9ab138b90d60fc8d7b4c15 requires_dist: + - opencv-python>4.6 - numpy - - opencv-python >4.6 - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - tqdm editable: true @@ -26489,7 +26506,7 @@ packages: url: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl sha256: c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5 requires_dist: - - mpmath >=0.19 + - mpmath>=0.19 requires_python: '>=3.8' - kind: conda name: sysroot_linux-64 @@ -26680,7 +26697,7 @@ packages: sha256: 72643b5c9ef886669a00a659c9fd60a81f220d2fb6572d184c3e147435ccec43 requires_dist: - numpy - - imagecodecs >=2023.8.12 ; extra == 'all' + - imagecodecs>=2023.8.12 ; extra == 'all' - matplotlib ; extra == 'all' - defusedxml ; extra == 'all' - lxml ; extra == 'all' @@ -26693,7 +26710,7 @@ packages: url: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl sha256: 02bba56786633ff46b55ee0ce3b991fa85375556844e500ad18e6b12921dc3da requires_dist: - - torch >=1.7 + - torch>=1.7 - torchvision - pyyaml - huggingface-hub @@ -26850,12 +26867,12 @@ packages: url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa requires_dist: - - huggingface-hub >=0.16.4, <1.0 + - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black ==22.3 ; extra == 'testing' + - black==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26868,12 +26885,12 @@ packages: url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 requires_dist: - - huggingface-hub >=0.16.4, <1.0 + - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black ==22.3 ; extra == 'testing' + - black==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26886,12 +26903,12 @@ packages: url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 requires_dist: - - huggingface-hub >=0.16.4, <1.0 + - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black ==22.3 ; extra == 'testing' + - black==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26904,12 +26921,12 @@ packages: url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 requires_dist: - - huggingface-hub >=0.16.4, <1.0 + - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black ==22.3 ; extra == 'testing' + - black==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26957,137 +26974,137 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl - sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb + url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl - sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 + url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl + sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torchvision @@ -27096,8 +27113,8 @@ packages: sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 requires_dist: - numpy - - torch ==2.2.2 - - pillow !=8.3.*, >=5.3.0 + - torch==2.2.2 + - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi @@ -27107,8 +27124,8 @@ packages: sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d requires_dist: - numpy - - torch ==2.2.2 - - pillow !=8.3.*, >=5.3.0 + - torch==2.2.2 + - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi @@ -27118,8 +27135,8 @@ packages: sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 requires_dist: - numpy - - torch ==2.2.2 - - pillow !=8.3.*, >=5.3.0 + - torch==2.2.2 + - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi @@ -27129,8 +27146,8 @@ packages: sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 requires_dist: - numpy - - torch ==2.2.2 - - pillow !=8.3.*, >=5.3.0 + - torch==2.2.2 + - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi @@ -27140,11 +27157,11 @@ packages: sha256: 1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9 requires_dist: - colorama ; platform_system == 'Windows' - - pytest >=6 ; extra == 'dev' + - pytest>=6 ; extra == 'dev' - pytest-cov ; extra == 'dev' - pytest-timeout ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - ipywidgets >=6 ; extra == 'notebook' + - ipywidgets>=6 ; extra == 'notebook' - slack-sdk ; extra == 'slack' - requests ; extra == 'telegram' requires_python: '>=3.7' @@ -27167,313 +27184,313 @@ packages: timestamp: 1707598746354 - kind: pypi name: transformers - version: 4.40.0 - url: https://files.pythonhosted.org/packages/09/c8/844d5518a6aeb4ffdc0cf0cae65ae13dbe5838306728c5c640b5a6e2a0c9/transformers-4.40.0-py3-none-any.whl - sha256: 92797ec3368ed4476a053529a4039a12ad09167d9e371981dda4afb4bdf590ac + version: 4.40.1 + url: https://files.pythonhosted.org/packages/cf/90/2596ac2ab49c4df6ff1fceaf7f5afb18401ba2f326348ce1a6261a65e7ed/transformers-4.40.1-py3-none-any.whl + sha256: 9d5ee0c8142a60501faf9e49a0b42f8e9cb8611823bce4f195a9325a6816337e requires_dist: - filelock - - huggingface-hub <1.0, >=0.19.3 - - numpy >=1.17 - - packaging >=20.0 - - pyyaml >=5.1 - - regex !=2019.12.17 + - huggingface-hub<1.0,>=0.19.3 + - numpy>=1.17 + - packaging>=20.0 + - pyyaml>=5.1 + - regex!=2019.12.17 - requests - - tokenizers <0.20, >=0.19 - - safetensors >=0.4.1 - - tqdm >=4.27 - - accelerate >=0.21.0 ; extra == 'accelerate' + - tokenizers<0.20,>=0.19 + - safetensors>=0.4.1 + - tqdm>=4.27 + - accelerate>=0.21.0 ; extra == 'accelerate' - diffusers ; extra == 'agents' - - accelerate >=0.21.0 ; extra == 'agents' - - datasets !=2.5.0 ; extra == 'agents' + - accelerate>=0.21.0 ; extra == 'agents' + - datasets!=2.5.0 ; extra == 'agents' - torch ; extra == 'agents' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'agents' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'agents' - opencv-python ; extra == 'agents' - - pillow <=15.0, >=10.0.1 ; extra == 'agents' - - tensorflow <2.16, >=2.6 ; extra == 'all' + - pillow<=15.0,>=10.0.1 ; extra == 'agents' + - tensorflow<2.16,>=2.6 ; extra == 'all' - onnxconverter-common ; extra == 'all' - tf2onnx ; extra == 'all' - - tensorflow-text <2.16 ; extra == 'all' - - keras-nlp >=0.3.1 ; extra == 'all' + - tensorflow-text<2.16 ; extra == 'all' + - keras-nlp>=0.3.1 ; extra == 'all' - torch ; extra == 'all' - - accelerate >=0.21.0 ; extra == 'all' - - jax <=0.4.13, >=0.4.1 ; extra == 'all' - - jaxlib <=0.4.13, >=0.4.1 ; extra == 'all' - - flax <=0.7.0, >=0.4.1 ; extra == 'all' - - optax <=0.1.4, >=0.0.8 ; extra == 'all' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'all' + - accelerate>=0.21.0 ; extra == 'all' + - jax<=0.4.13,>=0.4.1 ; extra == 'all' + - jaxlib<=0.4.13,>=0.4.1 ; extra == 'all' + - flax<=0.7.0,>=0.4.1 ; extra == 'all' + - optax<=0.1.4,>=0.0.8 ; extra == 'all' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'all' - protobuf ; extra == 'all' - - tokenizers <0.20, >=0.19 ; extra == 'all' + - tokenizers<0.20,>=0.19 ; extra == 'all' - torchaudio ; extra == 'all' - librosa ; extra == 'all' - - pyctcdecode >=0.4.0 ; extra == 'all' + - pyctcdecode>=0.4.0 ; extra == 'all' - phonemizer ; extra == 'all' - kenlm ; extra == 'all' - - pillow <=15.0, >=10.0.1 ; extra == 'all' + - pillow<=15.0,>=10.0.1 ; extra == 'all' - optuna ; extra == 'all' - - ray[tune] >=2.7.0 ; extra == 'all' + - ray[tune]>=2.7.0 ; extra == 'all' - sigopt ; extra == 'all' - timm ; extra == 'all' - torchvision ; extra == 'all' - - codecarbon ==1.2.0 ; extra == 'all' - - decord ==0.6.0 ; extra == 'all' - - av ==9.2.0 ; extra == 'all' + - codecarbon==1.2.0 ; extra == 'all' + - decord==0.6.0 ; extra == 'all' + - av==9.2.0 ; extra == 'all' - librosa ; extra == 'audio' - - pyctcdecode >=0.4.0 ; extra == 'audio' + - pyctcdecode>=0.4.0 ; extra == 'audio' - phonemizer ; extra == 'audio' - kenlm ; extra == 'audio' - - codecarbon ==1.2.0 ; extra == 'codecarbon' - - deepspeed >=0.9.3 ; extra == 'deepspeed' - - accelerate >=0.21.0 ; extra == 'deepspeed' - - deepspeed >=0.9.3 ; extra == 'deepspeed-testing' - - accelerate >=0.21.0 ; extra == 'deepspeed-testing' - - pytest <8.0.0, >=7.2.0 ; extra == 'deepspeed-testing' + - codecarbon==1.2.0 ; extra == 'codecarbon' + - deepspeed>=0.9.3 ; extra == 'deepspeed' + - accelerate>=0.21.0 ; extra == 'deepspeed' + - deepspeed>=0.9.3 ; extra == 'deepspeed-testing' + - accelerate>=0.21.0 ; extra == 'deepspeed-testing' + - pytest<8.0.0,>=7.2.0 ; extra == 'deepspeed-testing' - pytest-xdist ; extra == 'deepspeed-testing' - timeout-decorator ; extra == 'deepspeed-testing' - parameterized ; extra == 'deepspeed-testing' - psutil ; extra == 'deepspeed-testing' - - datasets !=2.5.0 ; extra == 'deepspeed-testing' - - dill <0.3.5 ; extra == 'deepspeed-testing' - - evaluate >=0.2.0 ; extra == 'deepspeed-testing' + - datasets!=2.5.0 ; extra == 'deepspeed-testing' + - dill<0.3.5 ; extra == 'deepspeed-testing' + - evaluate>=0.2.0 ; extra == 'deepspeed-testing' - pytest-timeout ; extra == 'deepspeed-testing' - - ruff ==0.1.5 ; extra == 'deepspeed-testing' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'deepspeed-testing' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'deepspeed-testing' + - ruff==0.1.5 ; extra == 'deepspeed-testing' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'deepspeed-testing' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'deepspeed-testing' - nltk ; extra == 'deepspeed-testing' - - gitpython <3.1.19 ; extra == 'deepspeed-testing' - - hf-doc-builder >=0.3.0 ; extra == 'deepspeed-testing' + - gitpython<3.1.19 ; extra == 'deepspeed-testing' + - hf-doc-builder>=0.3.0 ; extra == 'deepspeed-testing' - protobuf ; extra == 'deepspeed-testing' - sacremoses ; extra == 'deepspeed-testing' - rjieba ; extra == 'deepspeed-testing' - beautifulsoup4 ; extra == 'deepspeed-testing' - tensorboard ; extra == 'deepspeed-testing' - pydantic ; extra == 'deepspeed-testing' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'deepspeed-testing' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'deepspeed-testing' - faiss-cpu ; extra == 'deepspeed-testing' - - cookiecutter ==1.7.3 ; extra == 'deepspeed-testing' + - cookiecutter==1.7.3 ; extra == 'deepspeed-testing' - optuna ; extra == 'deepspeed-testing' - - tensorflow <2.16, >=2.6 ; extra == 'dev' + - tensorflow<2.16,>=2.6 ; extra == 'dev' - onnxconverter-common ; extra == 'dev' - tf2onnx ; extra == 'dev' - - tensorflow-text <2.16 ; extra == 'dev' - - keras-nlp >=0.3.1 ; extra == 'dev' + - tensorflow-text<2.16 ; extra == 'dev' + - keras-nlp>=0.3.1 ; extra == 'dev' - torch ; extra == 'dev' - - accelerate >=0.21.0 ; extra == 'dev' - - jax <=0.4.13, >=0.4.1 ; extra == 'dev' - - jaxlib <=0.4.13, >=0.4.1 ; extra == 'dev' - - flax <=0.7.0, >=0.4.1 ; extra == 'dev' - - optax <=0.1.4, >=0.0.8 ; extra == 'dev' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev' + - accelerate>=0.21.0 ; extra == 'dev' + - jax<=0.4.13,>=0.4.1 ; extra == 'dev' + - jaxlib<=0.4.13,>=0.4.1 ; extra == 'dev' + - flax<=0.7.0,>=0.4.1 ; extra == 'dev' + - optax<=0.1.4,>=0.0.8 ; extra == 'dev' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev' - protobuf ; extra == 'dev' - - tokenizers <0.20, >=0.19 ; extra == 'dev' + - tokenizers<0.20,>=0.19 ; extra == 'dev' - torchaudio ; extra == 'dev' - librosa ; extra == 'dev' - - pyctcdecode >=0.4.0 ; extra == 'dev' + - pyctcdecode>=0.4.0 ; extra == 'dev' - phonemizer ; extra == 'dev' - kenlm ; extra == 'dev' - - pillow <=15.0, >=10.0.1 ; extra == 'dev' + - pillow<=15.0,>=10.0.1 ; extra == 'dev' - optuna ; extra == 'dev' - - ray[tune] >=2.7.0 ; extra == 'dev' + - ray[tune]>=2.7.0 ; extra == 'dev' - sigopt ; extra == 'dev' - timm ; extra == 'dev' - torchvision ; extra == 'dev' - - codecarbon ==1.2.0 ; extra == 'dev' - - decord ==0.6.0 ; extra == 'dev' - - av ==9.2.0 ; extra == 'dev' - - pytest <8.0.0, >=7.2.0 ; extra == 'dev' + - codecarbon==1.2.0 ; extra == 'dev' + - decord==0.6.0 ; extra == 'dev' + - av==9.2.0 ; extra == 'dev' + - pytest<8.0.0,>=7.2.0 ; extra == 'dev' - pytest-xdist ; extra == 'dev' - timeout-decorator ; extra == 'dev' - parameterized ; extra == 'dev' - psutil ; extra == 'dev' - - datasets !=2.5.0 ; extra == 'dev' - - dill <0.3.5 ; extra == 'dev' - - evaluate >=0.2.0 ; extra == 'dev' + - datasets!=2.5.0 ; extra == 'dev' + - dill<0.3.5 ; extra == 'dev' + - evaluate>=0.2.0 ; extra == 'dev' - pytest-timeout ; extra == 'dev' - - ruff ==0.1.5 ; extra == 'dev' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev' + - ruff==0.1.5 ; extra == 'dev' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev' - nltk ; extra == 'dev' - - gitpython <3.1.19 ; extra == 'dev' - - hf-doc-builder >=0.3.0 ; extra == 'dev' + - gitpython<3.1.19 ; extra == 'dev' + - hf-doc-builder>=0.3.0 ; extra == 'dev' - sacremoses ; extra == 'dev' - rjieba ; extra == 'dev' - beautifulsoup4 ; extra == 'dev' - tensorboard ; extra == 'dev' - pydantic ; extra == 'dev' - faiss-cpu ; extra == 'dev' - - cookiecutter ==1.7.3 ; extra == 'dev' - - isort >=5.5.4 ; extra == 'dev' - - urllib3 <2.0.0 ; extra == 'dev' - - fugashi >=1.0 ; extra == 'dev' - - ipadic <2.0, >=1.0.0 ; extra == 'dev' - - unidic-lite >=1.0.7 ; extra == 'dev' - - unidic >=1.0.2 ; extra == 'dev' - - sudachipy >=0.6.6 ; extra == 'dev' - - sudachidict-core >=20220729 ; extra == 'dev' - - rhoknp <1.3.1, >=1.1.0 ; extra == 'dev' + - cookiecutter==1.7.3 ; extra == 'dev' + - isort>=5.5.4 ; extra == 'dev' + - urllib3<2.0.0 ; extra == 'dev' + - fugashi>=1.0 ; extra == 'dev' + - ipadic<2.0,>=1.0.0 ; extra == 'dev' + - unidic-lite>=1.0.7 ; extra == 'dev' + - unidic>=1.0.2 ; extra == 'dev' + - sudachipy>=0.6.6 ; extra == 'dev' + - sudachidict-core>=20220729 ; extra == 'dev' + - rhoknp<1.3.1,>=1.1.0 ; extra == 'dev' - hf-doc-builder ; extra == 'dev' - scikit-learn ; extra == 'dev' - - pytest <8.0.0, >=7.2.0 ; extra == 'dev-tensorflow' + - pytest<8.0.0,>=7.2.0 ; extra == 'dev-tensorflow' - pytest-xdist ; extra == 'dev-tensorflow' - timeout-decorator ; extra == 'dev-tensorflow' - parameterized ; extra == 'dev-tensorflow' - psutil ; extra == 'dev-tensorflow' - - datasets !=2.5.0 ; extra == 'dev-tensorflow' - - dill <0.3.5 ; extra == 'dev-tensorflow' - - evaluate >=0.2.0 ; extra == 'dev-tensorflow' + - datasets!=2.5.0 ; extra == 'dev-tensorflow' + - dill<0.3.5 ; extra == 'dev-tensorflow' + - evaluate>=0.2.0 ; extra == 'dev-tensorflow' - pytest-timeout ; extra == 'dev-tensorflow' - - ruff ==0.1.5 ; extra == 'dev-tensorflow' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev-tensorflow' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev-tensorflow' + - ruff==0.1.5 ; extra == 'dev-tensorflow' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev-tensorflow' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev-tensorflow' - nltk ; extra == 'dev-tensorflow' - - gitpython <3.1.19 ; extra == 'dev-tensorflow' - - hf-doc-builder >=0.3.0 ; extra == 'dev-tensorflow' + - gitpython<3.1.19 ; extra == 'dev-tensorflow' + - hf-doc-builder>=0.3.0 ; extra == 'dev-tensorflow' - protobuf ; extra == 'dev-tensorflow' - sacremoses ; extra == 'dev-tensorflow' - rjieba ; extra == 'dev-tensorflow' - beautifulsoup4 ; extra == 'dev-tensorflow' - tensorboard ; extra == 'dev-tensorflow' - pydantic ; extra == 'dev-tensorflow' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev-tensorflow' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev-tensorflow' - faiss-cpu ; extra == 'dev-tensorflow' - - cookiecutter ==1.7.3 ; extra == 'dev-tensorflow' - - tensorflow <2.16, >=2.6 ; extra == 'dev-tensorflow' + - cookiecutter==1.7.3 ; extra == 'dev-tensorflow' + - tensorflow<2.16,>=2.6 ; extra == 'dev-tensorflow' - onnxconverter-common ; extra == 'dev-tensorflow' - tf2onnx ; extra == 'dev-tensorflow' - - tensorflow-text <2.16 ; extra == 'dev-tensorflow' - - keras-nlp >=0.3.1 ; extra == 'dev-tensorflow' - - tokenizers <0.20, >=0.19 ; extra == 'dev-tensorflow' - - pillow <=15.0, >=10.0.1 ; extra == 'dev-tensorflow' - - isort >=5.5.4 ; extra == 'dev-tensorflow' - - urllib3 <2.0.0 ; extra == 'dev-tensorflow' + - tensorflow-text<2.16 ; extra == 'dev-tensorflow' + - keras-nlp>=0.3.1 ; extra == 'dev-tensorflow' + - tokenizers<0.20,>=0.19 ; extra == 'dev-tensorflow' + - pillow<=15.0,>=10.0.1 ; extra == 'dev-tensorflow' + - isort>=5.5.4 ; extra == 'dev-tensorflow' + - urllib3<2.0.0 ; extra == 'dev-tensorflow' - hf-doc-builder ; extra == 'dev-tensorflow' - scikit-learn ; extra == 'dev-tensorflow' - - onnxruntime >=1.4.0 ; extra == 'dev-tensorflow' - - onnxruntime-tools >=1.4.2 ; extra == 'dev-tensorflow' + - onnxruntime>=1.4.0 ; extra == 'dev-tensorflow' + - onnxruntime-tools>=1.4.2 ; extra == 'dev-tensorflow' - librosa ; extra == 'dev-tensorflow' - - pyctcdecode >=0.4.0 ; extra == 'dev-tensorflow' + - pyctcdecode>=0.4.0 ; extra == 'dev-tensorflow' - phonemizer ; extra == 'dev-tensorflow' - kenlm ; extra == 'dev-tensorflow' - - pytest <8.0.0, >=7.2.0 ; extra == 'dev-torch' + - pytest<8.0.0,>=7.2.0 ; extra == 'dev-torch' - pytest-xdist ; extra == 'dev-torch' - timeout-decorator ; extra == 'dev-torch' - parameterized ; extra == 'dev-torch' - psutil ; extra == 'dev-torch' - - datasets !=2.5.0 ; extra == 'dev-torch' - - dill <0.3.5 ; extra == 'dev-torch' - - evaluate >=0.2.0 ; extra == 'dev-torch' + - datasets!=2.5.0 ; extra == 'dev-torch' + - dill<0.3.5 ; extra == 'dev-torch' + - evaluate>=0.2.0 ; extra == 'dev-torch' - pytest-timeout ; extra == 'dev-torch' - - ruff ==0.1.5 ; extra == 'dev-torch' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev-torch' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev-torch' + - ruff==0.1.5 ; extra == 'dev-torch' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev-torch' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev-torch' - nltk ; extra == 'dev-torch' - - gitpython <3.1.19 ; extra == 'dev-torch' - - hf-doc-builder >=0.3.0 ; extra == 'dev-torch' + - gitpython<3.1.19 ; extra == 'dev-torch' + - hf-doc-builder>=0.3.0 ; extra == 'dev-torch' - protobuf ; extra == 'dev-torch' - sacremoses ; extra == 'dev-torch' - rjieba ; extra == 'dev-torch' - beautifulsoup4 ; extra == 'dev-torch' - tensorboard ; extra == 'dev-torch' - pydantic ; extra == 'dev-torch' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev-torch' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev-torch' - faiss-cpu ; extra == 'dev-torch' - - cookiecutter ==1.7.3 ; extra == 'dev-torch' + - cookiecutter==1.7.3 ; extra == 'dev-torch' - torch ; extra == 'dev-torch' - - accelerate >=0.21.0 ; extra == 'dev-torch' - - tokenizers <0.20, >=0.19 ; extra == 'dev-torch' + - accelerate>=0.21.0 ; extra == 'dev-torch' + - tokenizers<0.20,>=0.19 ; extra == 'dev-torch' - torchaudio ; extra == 'dev-torch' - librosa ; extra == 'dev-torch' - - pyctcdecode >=0.4.0 ; extra == 'dev-torch' + - pyctcdecode>=0.4.0 ; extra == 'dev-torch' - phonemizer ; extra == 'dev-torch' - kenlm ; extra == 'dev-torch' - - pillow <=15.0, >=10.0.1 ; extra == 'dev-torch' + - pillow<=15.0,>=10.0.1 ; extra == 'dev-torch' - optuna ; extra == 'dev-torch' - - ray[tune] >=2.7.0 ; extra == 'dev-torch' + - ray[tune]>=2.7.0 ; extra == 'dev-torch' - sigopt ; extra == 'dev-torch' - timm ; extra == 'dev-torch' - torchvision ; extra == 'dev-torch' - - codecarbon ==1.2.0 ; extra == 'dev-torch' - - isort >=5.5.4 ; extra == 'dev-torch' - - urllib3 <2.0.0 ; extra == 'dev-torch' - - fugashi >=1.0 ; extra == 'dev-torch' - - ipadic <2.0, >=1.0.0 ; extra == 'dev-torch' - - unidic-lite >=1.0.7 ; extra == 'dev-torch' - - unidic >=1.0.2 ; extra == 'dev-torch' - - sudachipy >=0.6.6 ; extra == 'dev-torch' - - sudachidict-core >=20220729 ; extra == 'dev-torch' - - rhoknp <1.3.1, >=1.1.0 ; extra == 'dev-torch' + - codecarbon==1.2.0 ; extra == 'dev-torch' + - isort>=5.5.4 ; extra == 'dev-torch' + - urllib3<2.0.0 ; extra == 'dev-torch' + - fugashi>=1.0 ; extra == 'dev-torch' + - ipadic<2.0,>=1.0.0 ; extra == 'dev-torch' + - unidic-lite>=1.0.7 ; extra == 'dev-torch' + - unidic>=1.0.2 ; extra == 'dev-torch' + - sudachipy>=0.6.6 ; extra == 'dev-torch' + - sudachidict-core>=20220729 ; extra == 'dev-torch' + - rhoknp<1.3.1,>=1.1.0 ; extra == 'dev-torch' - hf-doc-builder ; extra == 'dev-torch' - scikit-learn ; extra == 'dev-torch' - - onnxruntime >=1.4.0 ; extra == 'dev-torch' - - onnxruntime-tools >=1.4.2 ; extra == 'dev-torch' - - tensorflow <2.16, >=2.6 ; extra == 'docs' + - onnxruntime>=1.4.0 ; extra == 'dev-torch' + - onnxruntime-tools>=1.4.2 ; extra == 'dev-torch' + - tensorflow<2.16,>=2.6 ; extra == 'docs' - onnxconverter-common ; extra == 'docs' - tf2onnx ; extra == 'docs' - - tensorflow-text <2.16 ; extra == 'docs' - - keras-nlp >=0.3.1 ; extra == 'docs' + - tensorflow-text<2.16 ; extra == 'docs' + - keras-nlp>=0.3.1 ; extra == 'docs' - torch ; extra == 'docs' - - accelerate >=0.21.0 ; extra == 'docs' - - jax <=0.4.13, >=0.4.1 ; extra == 'docs' - - jaxlib <=0.4.13, >=0.4.1 ; extra == 'docs' - - flax <=0.7.0, >=0.4.1 ; extra == 'docs' - - optax <=0.1.4, >=0.0.8 ; extra == 'docs' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'docs' + - accelerate>=0.21.0 ; extra == 'docs' + - jax<=0.4.13,>=0.4.1 ; extra == 'docs' + - jaxlib<=0.4.13,>=0.4.1 ; extra == 'docs' + - flax<=0.7.0,>=0.4.1 ; extra == 'docs' + - optax<=0.1.4,>=0.0.8 ; extra == 'docs' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'docs' - protobuf ; extra == 'docs' - - tokenizers <0.20, >=0.19 ; extra == 'docs' + - tokenizers<0.20,>=0.19 ; extra == 'docs' - torchaudio ; extra == 'docs' - librosa ; extra == 'docs' - - pyctcdecode >=0.4.0 ; extra == 'docs' + - pyctcdecode>=0.4.0 ; extra == 'docs' - phonemizer ; extra == 'docs' - kenlm ; extra == 'docs' - - pillow <=15.0, >=10.0.1 ; extra == 'docs' + - pillow<=15.0,>=10.0.1 ; extra == 'docs' - optuna ; extra == 'docs' - - ray[tune] >=2.7.0 ; extra == 'docs' + - ray[tune]>=2.7.0 ; extra == 'docs' - sigopt ; extra == 'docs' - timm ; extra == 'docs' - torchvision ; extra == 'docs' - - codecarbon ==1.2.0 ; extra == 'docs' - - decord ==0.6.0 ; extra == 'docs' - - av ==9.2.0 ; extra == 'docs' + - codecarbon==1.2.0 ; extra == 'docs' + - decord==0.6.0 ; extra == 'docs' + - av==9.2.0 ; extra == 'docs' - hf-doc-builder ; extra == 'docs' - hf-doc-builder ; extra == 'docs_specific' - - jax <=0.4.13, >=0.4.1 ; extra == 'flax' - - jaxlib <=0.4.13, >=0.4.1 ; extra == 'flax' - - flax <=0.7.0, >=0.4.1 ; extra == 'flax' - - optax <=0.1.4, >=0.0.8 ; extra == 'flax' + - jax<=0.4.13,>=0.4.1 ; extra == 'flax' + - jaxlib<=0.4.13,>=0.4.1 ; extra == 'flax' + - flax<=0.7.0,>=0.4.1 ; extra == 'flax' + - optax<=0.1.4,>=0.0.8 ; extra == 'flax' - librosa ; extra == 'flax-speech' - - pyctcdecode >=0.4.0 ; extra == 'flax-speech' + - pyctcdecode>=0.4.0 ; extra == 'flax-speech' - phonemizer ; extra == 'flax-speech' - kenlm ; extra == 'flax-speech' - ftfy ; extra == 'ftfy' - optuna ; extra == 'integrations' - - ray[tune] >=2.7.0 ; extra == 'integrations' + - ray[tune]>=2.7.0 ; extra == 'integrations' - sigopt ; extra == 'integrations' - - fugashi >=1.0 ; extra == 'ja' - - ipadic <2.0, >=1.0.0 ; extra == 'ja' - - unidic-lite >=1.0.7 ; extra == 'ja' - - unidic >=1.0.2 ; extra == 'ja' - - sudachipy >=0.6.6 ; extra == 'ja' - - sudachidict-core >=20220729 ; extra == 'ja' - - rhoknp <1.3.1, >=1.1.0 ; extra == 'ja' - - cookiecutter ==1.7.3 ; extra == 'modelcreation' - - natten <0.15.0, >=0.14.6 ; extra == 'natten' + - fugashi>=1.0 ; extra == 'ja' + - ipadic<2.0,>=1.0.0 ; extra == 'ja' + - unidic-lite>=1.0.7 ; extra == 'ja' + - unidic>=1.0.2 ; extra == 'ja' + - sudachipy>=0.6.6 ; extra == 'ja' + - sudachidict-core>=20220729 ; extra == 'ja' + - rhoknp<1.3.1,>=1.1.0 ; extra == 'ja' + - cookiecutter==1.7.3 ; extra == 'modelcreation' + - natten<0.15.0,>=0.14.6 ; extra == 'natten' - onnxconverter-common ; extra == 'onnx' - tf2onnx ; extra == 'onnx' - - onnxruntime >=1.4.0 ; extra == 'onnx' - - onnxruntime-tools >=1.4.2 ; extra == 'onnx' - - onnxruntime >=1.4.0 ; extra == 'onnxruntime' - - onnxruntime-tools >=1.4.2 ; extra == 'onnxruntime' + - onnxruntime>=1.4.0 ; extra == 'onnx' + - onnxruntime-tools>=1.4.2 ; extra == 'onnx' + - onnxruntime>=1.4.0 ; extra == 'onnxruntime' + - onnxruntime-tools>=1.4.2 ; extra == 'onnxruntime' - optuna ; extra == 'optuna' - - datasets !=2.5.0 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - ruff ==0.1.5 ; extra == 'quality' - - gitpython <3.1.19 ; extra == 'quality' - - hf-doc-builder >=0.3.0 ; extra == 'quality' - - urllib3 <2.0.0 ; extra == 'quality' - - ray[tune] >=2.7.0 ; extra == 'ray' + - datasets!=2.5.0 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - ruff==0.1.5 ; extra == 'quality' + - gitpython<3.1.19 ; extra == 'quality' + - hf-doc-builder>=0.3.0 ; extra == 'quality' + - urllib3<2.0.0 ; extra == 'quality' + - ray[tune]>=2.7.0 ; extra == 'ray' - faiss-cpu ; extra == 'retrieval' - - datasets !=2.5.0 ; extra == 'retrieval' - - sagemaker >=2.31.0 ; extra == 'sagemaker' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'sentencepiece' + - datasets!=2.5.0 ; extra == 'retrieval' + - sagemaker>=2.31.0 ; extra == 'sagemaker' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'sentencepiece' - protobuf ; extra == 'sentencepiece' - pydantic ; extra == 'serving' - uvicorn ; extra == 'serving' @@ -27483,73 +27500,73 @@ packages: - scikit-learn ; extra == 'sklearn' - torchaudio ; extra == 'speech' - librosa ; extra == 'speech' - - pyctcdecode >=0.4.0 ; extra == 'speech' + - pyctcdecode>=0.4.0 ; extra == 'speech' - phonemizer ; extra == 'speech' - kenlm ; extra == 'speech' - - pytest <8.0.0, >=7.2.0 ; extra == 'testing' + - pytest<8.0.0,>=7.2.0 ; extra == 'testing' - pytest-xdist ; extra == 'testing' - timeout-decorator ; extra == 'testing' - parameterized ; extra == 'testing' - psutil ; extra == 'testing' - - datasets !=2.5.0 ; extra == 'testing' - - dill <0.3.5 ; extra == 'testing' - - evaluate >=0.2.0 ; extra == 'testing' + - datasets!=2.5.0 ; extra == 'testing' + - dill<0.3.5 ; extra == 'testing' + - evaluate>=0.2.0 ; extra == 'testing' - pytest-timeout ; extra == 'testing' - - ruff ==0.1.5 ; extra == 'testing' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'testing' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'testing' + - ruff==0.1.5 ; extra == 'testing' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'testing' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'testing' - nltk ; extra == 'testing' - - gitpython <3.1.19 ; extra == 'testing' - - hf-doc-builder >=0.3.0 ; extra == 'testing' + - gitpython<3.1.19 ; extra == 'testing' + - hf-doc-builder>=0.3.0 ; extra == 'testing' - protobuf ; extra == 'testing' - sacremoses ; extra == 'testing' - rjieba ; extra == 'testing' - beautifulsoup4 ; extra == 'testing' - tensorboard ; extra == 'testing' - pydantic ; extra == 'testing' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'testing' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'testing' - faiss-cpu ; extra == 'testing' - - cookiecutter ==1.7.3 ; extra == 'testing' - - tensorflow <2.16, >=2.6 ; extra == 'tf' + - cookiecutter==1.7.3 ; extra == 'testing' + - tensorflow<2.16,>=2.6 ; extra == 'tf' - onnxconverter-common ; extra == 'tf' - tf2onnx ; extra == 'tf' - - tensorflow-text <2.16 ; extra == 'tf' - - keras-nlp >=0.3.1 ; extra == 'tf' - - tensorflow-cpu <2.16, >=2.6 ; extra == 'tf-cpu' + - tensorflow-text<2.16 ; extra == 'tf' + - keras-nlp>=0.3.1 ; extra == 'tf' + - tensorflow-cpu<2.16,>=2.6 ; extra == 'tf-cpu' - onnxconverter-common ; extra == 'tf-cpu' - tf2onnx ; extra == 'tf-cpu' - - tensorflow-text <2.16 ; extra == 'tf-cpu' - - keras-nlp >=0.3.1 ; extra == 'tf-cpu' + - tensorflow-text<2.16 ; extra == 'tf-cpu' + - keras-nlp>=0.3.1 ; extra == 'tf-cpu' - librosa ; extra == 'tf-speech' - - pyctcdecode >=0.4.0 ; extra == 'tf-speech' + - pyctcdecode>=0.4.0 ; extra == 'tf-speech' - phonemizer ; extra == 'tf-speech' - kenlm ; extra == 'tf-speech' - timm ; extra == 'timm' - - tokenizers <0.20, >=0.19 ; extra == 'tokenizers' + - tokenizers<0.20,>=0.19 ; extra == 'tokenizers' - torch ; extra == 'torch' - - accelerate >=0.21.0 ; extra == 'torch' + - accelerate>=0.21.0 ; extra == 'torch' - torchaudio ; extra == 'torch-speech' - librosa ; extra == 'torch-speech' - - pyctcdecode >=0.4.0 ; extra == 'torch-speech' + - pyctcdecode>=0.4.0 ; extra == 'torch-speech' - phonemizer ; extra == 'torch-speech' - kenlm ; extra == 'torch-speech' - torchvision ; extra == 'torch-vision' - - pillow <=15.0, >=10.0.1 ; extra == 'torch-vision' + - pillow<=15.0,>=10.0.1 ; extra == 'torch-vision' - filelock ; extra == 'torchhub' - - huggingface-hub <1.0, >=0.19.3 ; extra == 'torchhub' + - huggingface-hub<1.0,>=0.19.3 ; extra == 'torchhub' - importlib-metadata ; extra == 'torchhub' - - numpy >=1.17 ; extra == 'torchhub' - - packaging >=20.0 ; extra == 'torchhub' + - numpy>=1.17 ; extra == 'torchhub' + - packaging>=20.0 ; extra == 'torchhub' - protobuf ; extra == 'torchhub' - - regex !=2019.12.17 ; extra == 'torchhub' + - regex!=2019.12.17 ; extra == 'torchhub' - requests ; extra == 'torchhub' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'torchhub' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'torchhub' - torch ; extra == 'torchhub' - - tokenizers <0.20, >=0.19 ; extra == 'torchhub' - - tqdm >=4.27 ; extra == 'torchhub' - - decord ==0.6.0 ; extra == 'video' - - av ==9.2.0 ; extra == 'video' - - pillow <=15.0, >=10.0.1 ; extra == 'vision' + - tokenizers<0.20,>=0.19 ; extra == 'torchhub' + - tqdm>=4.27 ; extra == 'torchhub' + - decord==0.6.0 ; extra == 'video' + - av==9.2.0 ; extra == 'video' + - pillow<=15.0,>=10.0.1 ; extra == 'vision' requires_python: '>=3.8.0' - kind: pypi name: trimesh @@ -27612,14 +27629,14 @@ packages: sha256: da58a152bddb62cafa9a857dd2bc1f886dbf9f9c90a2b5da82157cd2b34392b0 requires_dist: - filelock - - cmake >=3.20 ; extra == 'build' + - cmake>=3.20 ; extra == 'build' - lit ; extra == 'build' - autopep8 ; extra == 'tests' - flake8 ; extra == 'tests' - isort ; extra == 'tests' - numpy ; extra == 'tests' - pytest ; extra == 'tests' - - scipy >=1.7.1 ; extra == 'tests' + - scipy>=1.7.1 ; extra == 'tests' - torch ; extra == 'tests' - matplotlib ; extra == 'tutorials' - pandas ; extra == 'tutorials' @@ -27636,7 +27653,7 @@ packages: url: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl sha256: 6216cdac377c6b9a040ac1c0404f7284bd13199c0e1bb235f4324627e8898cf5 requires_dist: - - urllib3 >=2 + - urllib3>=2 requires_python: '>=3.8' - kind: pypi name: typing-extensions @@ -27650,9 +27667,9 @@ packages: url: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl sha256: 9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f requires_dist: - - mypy-extensions >=0.3.0 - - typing-extensions >=3.7.4 - - typing >=3.7.4 ; python_version < '3.5' + - mypy-extensions>=0.3.0 + - typing-extensions>=3.7.4 + - typing>=3.7.4 ; python_version < '3.5' - kind: conda name: typing_extensions version: 4.8.0 @@ -28056,13 +28073,13 @@ packages: url: https://files.pythonhosted.org/packages/d1/1b/46802a050b1c55d10c4f59fc6afd2b45ac9b4f62b2e12092d3f599286f14/umap_learn-0.5.6-py3-none-any.whl sha256: 881cc0c2ee845b790bf0455aa1664f9f68b838d9d0fe12a1291b85c5a559c913 requires_dist: - - numpy >=1.17 - - scipy >=1.3.1 - - scikit-learn >=0.22 - - numba >=0.51.2 - - pynndescent >=0.5 + - numpy>=1.17 + - scipy>=1.3.1 + - scikit-learn>=0.22 + - numba>=0.51.2 + - pynndescent>=0.5 - tqdm - - tensorflow >=2.1 ; extra == 'parametric_umap' + - tensorflow>=2.1 ; extra == 'parametric_umap' - pandas ; extra == 'plot' - matplotlib ; extra == 'plot' - datashader ; extra == 'plot' @@ -28071,18 +28088,18 @@ packages: - colorcet ; extra == 'plot' - seaborn ; extra == 'plot' - scikit-image ; extra == 'plot' - - tbb >=2019.0 ; extra == 'tbb' + - tbb>=2019.0 ; extra == 'tbb' - kind: pypi name: urllib3 version: 2.2.1 url: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl sha256: 450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d requires_dist: - - brotli >=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' - - h2 <5, >=4 ; extra == 'h2' - - pysocks !=1.5.7, <2.0, >=1.5.6 ; extra == 'socks' - - zstandard >=0.18.0 ; extra == 'zstd' + - brotli>=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2<5,>=4 ; extra == 'h2' + - pysocks!=1.5.7,<2.0,>=1.5.6 ; extra == 'socks' + - zstandard>=0.18.0 ; extra == 'zstd' requires_python: '>=3.8' - kind: conda name: urllib3 @@ -28181,29 +28198,29 @@ packages: url: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl sha256: 6e1281a57849c8a54da89ba82e5eb7c8937b9d057ff01aaf5bc9afaa3552e90f requires_dist: - - distlib <1, >=0.3.7 - - filelock <4, >=3.12.2 - - importlib-metadata >=6.6 ; python_version < '3.8' - - platformdirs <5, >=3.9.1 - - furo >=2023.7.26 ; extra == 'docs' - - proselint >=0.13 ; extra == 'docs' - - sphinx !=7.3, >=7.1.2 ; extra == 'docs' - - sphinx-argparse >=0.4 ; extra == 'docs' - - sphinxcontrib-towncrier >=0.2.1a0 ; extra == 'docs' - - towncrier >=23.6 ; extra == 'docs' - - covdefaults >=2.3 ; extra == 'test' - - coverage-enable-subprocess >=1 ; extra == 'test' - - coverage >=7.2.7 ; extra == 'test' - - flaky >=3.7 ; extra == 'test' - - packaging >=23.1 ; extra == 'test' - - pytest-env >=0.8.2 ; extra == 'test' - - pytest-freezer >=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' - - pytest-mock >=3.11.1 ; extra == 'test' - - pytest-randomly >=3.12 ; extra == 'test' - - pytest-timeout >=2.1 ; extra == 'test' - - pytest >=7.4 ; extra == 'test' - - setuptools >=68 ; extra == 'test' - - time-machine >=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' + - distlib<1,>=0.3.7 + - filelock<4,>=3.12.2 + - importlib-metadata>=6.6 ; python_version < '3.8' + - platformdirs<5,>=3.9.1 + - furo>=2023.7.26 ; extra == 'docs' + - proselint>=0.13 ; extra == 'docs' + - sphinx!=7.3,>=7.1.2 ; extra == 'docs' + - sphinx-argparse>=0.4 ; extra == 'docs' + - sphinxcontrib-towncrier>=0.2.1a0 ; extra == 'docs' + - towncrier>=23.6 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'test' + - coverage-enable-subprocess>=1 ; extra == 'test' + - coverage>=7.2.7 ; extra == 'test' + - flaky>=3.7 ; extra == 'test' + - packaging>=23.1 ; extra == 'test' + - pytest-env>=0.8.2 ; extra == 'test' + - pytest-freezer>=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' + - pytest-mock>=3.11.1 ; extra == 'test' + - pytest-randomly>=3.12 ; extra == 'test' + - pytest-timeout>=2.1 ; extra == 'test' + - pytest>=7.4 ; extra == 'test' + - setuptools>=68 ; extra == 'test' + - time-machine>=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' requires_python: '>=3.7' - kind: pypi name: virtualenv @@ -28211,29 +28228,29 @@ packages: url: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl sha256: 8aac4332f2ea6ef519c648d0bc48a5b1d324994753519919bddbb1aff25a104e requires_dist: - - distlib <1, >=0.3.7 - - filelock <4, >=3.12.2 - - importlib-metadata >=6.6 ; python_version < '3.8' - - platformdirs <5, >=3.9.1 - - furo >=2023.7.26 ; extra == 'docs' - - proselint >=0.13 ; extra == 'docs' - - sphinx !=7.3, >=7.1.2 ; extra == 'docs' - - sphinx-argparse >=0.4 ; extra == 'docs' - - sphinxcontrib-towncrier >=0.2.1a0 ; extra == 'docs' - - towncrier >=23.6 ; extra == 'docs' - - covdefaults >=2.3 ; extra == 'test' - - coverage-enable-subprocess >=1 ; extra == 'test' - - coverage >=7.2.7 ; extra == 'test' - - flaky >=3.7 ; extra == 'test' - - packaging >=23.1 ; extra == 'test' - - pytest-env >=0.8.2 ; extra == 'test' - - pytest-freezer >=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' - - pytest-mock >=3.11.1 ; extra == 'test' - - pytest-randomly >=3.12 ; extra == 'test' - - pytest-timeout >=2.1 ; extra == 'test' - - pytest >=7.4 ; extra == 'test' - - setuptools >=68 ; extra == 'test' - - time-machine >=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' + - distlib<1,>=0.3.7 + - filelock<4,>=3.12.2 + - importlib-metadata>=6.6 ; python_version < '3.8' + - platformdirs<5,>=3.9.1 + - furo>=2023.7.26 ; extra == 'docs' + - proselint>=0.13 ; extra == 'docs' + - sphinx!=7.3,>=7.1.2 ; extra == 'docs' + - sphinx-argparse>=0.4 ; extra == 'docs' + - sphinxcontrib-towncrier>=0.2.1a0 ; extra == 'docs' + - towncrier>=23.6 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'test' + - coverage-enable-subprocess>=1 ; extra == 'test' + - coverage>=7.2.7 ; extra == 'test' + - flaky>=3.7 ; extra == 'test' + - packaging>=23.1 ; extra == 'test' + - pytest-env>=0.8.2 ; extra == 'test' + - pytest-freezer>=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' + - pytest-mock>=3.11.1 ; extra == 'test' + - pytest-randomly>=3.12 ; extra == 'test' + - pytest-timeout>=2.1 ; extra == 'test' + - pytest>=7.4 ; extra == 'test' + - setuptools>=68 ; extra == 'test' + - time-machine>=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' requires_python: '>=3.7' - kind: conda name: vs2015_runtime @@ -28359,32 +28376,32 @@ packages: - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d + url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl + sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 + url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 + url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 + url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl - sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 + url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 requires_python: '>=3.6' - kind: conda name: xz @@ -28556,37 +28573,37 @@ packages: url: https://files.pythonhosted.org/packages/d5/b5/70bb98ee38ce532ee29fab76fb668382291fe6e1aa69a8c1ac7e6bc108e7/yfinance-0.2.38-py2.py3-none-any.whl sha256: 07525cf84414272723a3e2b9d4c0a2898ddb60cc0828aa190de26664fac6f676 requires_dist: - - pandas >=1.3.0 - - numpy >=1.16.5 - - requests >=2.31 - - multitasking >=0.0.7 - - lxml >=4.9.1 - - appdirs >=1.4.4 - - pytz >=2022.5 - - frozendict >=2.3.4 - - peewee >=3.16.2 - - beautifulsoup4 >=4.11.1 - - html5lib >=1.1 - - requests-cache >=1.0 ; extra == 'nospam' - - requests-ratelimiter >=0.3.1 ; extra == 'nospam' - - scipy >=1.6.3 ; extra == 'repair' + - pandas>=1.3.0 + - numpy>=1.16.5 + - requests>=2.31 + - multitasking>=0.0.7 + - lxml>=4.9.1 + - appdirs>=1.4.4 + - pytz>=2022.5 + - frozendict>=2.3.4 + - peewee>=3.16.2 + - beautifulsoup4>=4.11.1 + - html5lib>=1.1 + - requests-cache>=1.0 ; extra == 'nospam' + - requests-ratelimiter>=0.3.1 ; extra == 'nospam' + - scipy>=1.6.3 ; extra == 'repair' - kind: pypi name: zipp version: 3.18.1 url: https://files.pythonhosted.org/packages/c2/0a/ba9d0ee9536d3ef73a3448e931776e658b36f128d344e175bc32b092a8bf/zipp-3.18.1-py3-none-any.whl sha256: 206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b requires_dist: - - sphinx >=3.5 ; extra == 'docs' - - jaraco-packaging >=9.3 ; extra == 'docs' - - rst-linker >=1.9 ; extra == 'docs' + - sphinx>=3.5 ; extra == 'docs' + - jaraco-packaging>=9.3 ; extra == 'docs' + - rst-linker>=1.9 ; extra == 'docs' - furo ; extra == 'docs' - sphinx-lint ; extra == 'docs' - - jaraco-tidelift >=1.4 ; extra == 'docs' - - pytest >=6 ; extra == 'testing' - - pytest-checkdocs >=2.4 ; extra == 'testing' + - jaraco-tidelift>=1.4 ; extra == 'docs' + - pytest>=6 ; extra == 'testing' + - pytest-checkdocs>=2.4 ; extra == 'testing' - pytest-cov ; extra == 'testing' - - pytest-enabler >=2.2 ; extra == 'testing' - - pytest-ruff >=0.2.1 ; extra == 'testing' + - pytest-enabler>=2.2 ; extra == 'testing' + - pytest-ruff>=0.2.1 ; extra == 'testing' - jaraco-itertools ; extra == 'testing' - jaraco-functools ; extra == 'testing' - more-itertools ; extra == 'testing' From 17e646e91362bd91806c051935644266f072c437 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 25 Apr 2024 11:20:28 +0200 Subject: [PATCH 355/508] Codegen for space view python blueprint classes (#6100) ### What * Fixes #6081 Extends our codegen to accept a fourth object type, space views (in addition to datatypes/components/archetypes). Meaning we can do special codegen for space views now, making it easy to set them up consistently and define what properties a space view can be constructed from. Building up on the previous PR that exposed background3d color, this generates almost identical code now. Doesn't add yet any new view properties - this is going to happen in a follow-up PR since it requires getting a few more things serializable and subsequently also testing. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6100?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6100?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6100) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../definitions/python/attributes.fbs | 4 +- .../re_types/definitions/rerun/attributes.fbs | 7 +- .../re_types/definitions/rerun/blueprint.fbs | 8 + .../blueprint/archetypes/background_3d.fbs | 3 +- .../rerun/blueprint/views/bar_chart.fbs | 9 + .../rerun/blueprint/views/spatial2d.fbs | 9 + .../rerun/blueprint/views/spatial3d.fbs | 11 + .../rerun/blueprint/views/tensor.fbs | 9 + .../rerun/blueprint/views/text_document.fbs | 9 + .../rerun/blueprint/views/text_log.fbs | 9 + .../rerun/blueprint/views/time_series.fbs | 9 + crates/re_types/src/lib.rs | 4 +- .../re_types_builder/src/codegen/cpp/mod.rs | 8 + .../re_types_builder/src/codegen/docs/mod.rs | 10 + .../src/codegen/python/mod.rs | 63 +++-- .../src/codegen/python/views.rs | 173 ++++++++++++++ .../re_types_builder/src/codegen/rust/api.rs | 6 + crates/re_types_builder/src/format/python.rs | 6 +- crates/re_types_builder/src/lib.rs | 1 + crates/re_types_builder/src/objects.rs | 47 ++-- crates/re_types_builder/src/report.rs | 24 +- .../rerun_sdk/rerun/blueprint/__init__.py | 2 +- .../rerun_sdk/rerun/blueprint/space_views.py | 219 ------------------ .../rerun/blueprint/views/.gitattributes | 11 + .../rerun/blueprint/views/__init__.py | 21 ++ .../rerun/blueprint/views/bar_chart_view.py | 44 ++++ .../rerun/blueprint/views/spatial2d_view.py | 42 ++++ .../rerun/blueprint/views/spatial3d_view.py | 56 +++++ .../rerun/blueprint/views/tensor_view.py | 42 ++++ .../blueprint/views/text_document_view.py | 44 ++++ .../rerun/blueprint/views/text_log_view.py | 42 ++++ .../rerun/blueprint/views/time_series_view.py | 44 ++++ 32 files changed, 725 insertions(+), 271 deletions(-) create mode 100644 crates/re_types/definitions/rerun/blueprint/views/bar_chart.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/views/tensor.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/views/text_document.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/views/text_log.fbs create mode 100644 crates/re_types/definitions/rerun/blueprint/views/time_series.fbs create mode 100644 crates/re_types_builder/src/codegen/python/views.rs delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/space_views.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/.gitattributes create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/__init__.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/bar_chart_view.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/tensor_view.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/text_document_view.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/text_log_view.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py diff --git a/crates/re_types/definitions/python/attributes.fbs b/crates/re_types/definitions/python/attributes.fbs index 7e35944c6c8f..4b408e9f3442 100644 --- a/crates/re_types/definitions/python/attributes.fbs +++ b/crates/re_types/definitions/python/attributes.fbs @@ -1,8 +1,6 @@ namespace python.attributes; -/// Defines the type aliases for a component, e.g. the types that make up `ComponentLike`. -/// -/// Only applies to structs/unions that are components. +/// Defines the type aliases for a component or view property archetype, e.g. the types that make up `ComponentLike`. attribute "attr.python.aliases"; /// Defines the array type aliases for a component, e.g. the types that make up `ComponentArrayLike`. diff --git a/crates/re_types/definitions/rerun/attributes.fbs b/crates/re_types/definitions/rerun/attributes.fbs index c33b614a18f6..b9ffcda8272c 100644 --- a/crates/re_types/definitions/rerun/attributes.fbs +++ b/crates/re_types/definitions/rerun/attributes.fbs @@ -25,11 +25,16 @@ attribute "attr.rerun.component_optional"; /// For lists this will apply to the inner element. attribute "attr.rerun.override_type"; -/// Set the scope of the type +/// Set the scope of the type. /// /// This is used for example to scope blueprint types. attribute "attr.rerun.scope"; +/// Specifies the type identifier for a space view type. +/// +/// This is mandatory for space view types. +attribute "attr.rerun.view_identifier"; + /// Marks something as deprecated followed by a (mandatory!) migration note. /// /// If specified on an object (struct/enum/union), it becomes deprecated such diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index c7056192eca7..fe2b5a6b17c6 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -32,3 +32,11 @@ include "./blueprint/archetypes/viewport_blueprint.fbs"; include "./blueprint/archetypes/plot_legend.fbs"; include "./blueprint/archetypes/scalar_axis.fbs"; + +include "./blueprint/views/bar_chart.fbs"; +include "./blueprint/views/spatial2d.fbs"; +include "./blueprint/views/spatial3d.fbs"; +include "./blueprint/views/tensor.fbs"; +include "./blueprint/views/text_document.fbs"; +include "./blueprint/views/text_log.fbs"; +include "./blueprint/views/time_series.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs index ffcc42964c6b..12b68b3c6ed3 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs @@ -12,7 +12,8 @@ namespace rerun.blueprint.archetypes; /// Configuration for the background of the 3D space view. table Background3D ( - "attr.rerun.scope": "blueprint" + "attr.rerun.scope": "blueprint", + "attr.python.aliases": "datatypes.Rgba32Like, blueprint_components.Background3DKindLike" ) { // --- Required --- diff --git a/crates/re_types/definitions/rerun/blueprint/views/bar_chart.fbs b/crates/re_types/definitions/rerun/blueprint/views/bar_chart.fbs new file mode 100644 index 000000000000..bd16840d2bcf --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/views/bar_chart.fbs @@ -0,0 +1,9 @@ +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.views; + +/// A bar chart view. +table BarChartView ( + "attr.rerun.view_identifier": "BarChart" +) { +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs new file mode 100644 index 000000000000..208eae5e1735 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs @@ -0,0 +1,9 @@ +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.views; + +/// A Spatial 2D view. +table Spatial2DView ( + "attr.rerun.view_identifier": "2D" +) { +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs new file mode 100644 index 000000000000..c512b4eb8fbb --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs @@ -0,0 +1,11 @@ +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.views; + +/// A Spatial 3D view. +table Spatial3DView ( + "attr.rerun.view_identifier": "3D" +) { + /// Configuration for the background of the 3D space view. + background: rerun.blueprint.archetypes.Background3D (order: 1000); +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/tensor.fbs b/crates/re_types/definitions/rerun/blueprint/views/tensor.fbs new file mode 100644 index 000000000000..94997a606b31 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/views/tensor.fbs @@ -0,0 +1,9 @@ +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.views; + +/// A tensor view. +table TensorView ( + "attr.rerun.view_identifier": "Tensor" +) { +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/text_document.fbs b/crates/re_types/definitions/rerun/blueprint/views/text_document.fbs new file mode 100644 index 000000000000..df1cea54cf25 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/views/text_document.fbs @@ -0,0 +1,9 @@ +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.views; + +/// A text document view. +table TextDocumentView ( + "attr.rerun.view_identifier": "TextDocument" +) { +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/text_log.fbs b/crates/re_types/definitions/rerun/blueprint/views/text_log.fbs new file mode 100644 index 000000000000..dfaafe075525 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/views/text_log.fbs @@ -0,0 +1,9 @@ +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.views; + +/// A text log view. +table TextLogView ( + "attr.rerun.view_identifier": "TextLog" +) { +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs b/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs new file mode 100644 index 000000000000..6929a6b4aa3a --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs @@ -0,0 +1,9 @@ +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.views; + +/// A time series view. +table TimeSeriesView ( + "attr.rerun.view_identifier": "TimeSeries" +) { +} diff --git a/crates/re_types/src/lib.rs b/crates/re_types/src/lib.rs index a826d99724e0..3bb276d4796b 100644 --- a/crates/re_types/src/lib.rs +++ b/crates/re_types/src/lib.rs @@ -3,8 +3,8 @@ //! This crate contains both the IDL definitions for Rerun types (flatbuffers) as well as the code //! generated from those using `re_types_builder`. //! -//! All builtin archetypes, components and datatypes can be found in their respective top-level -//! modules. +//! All builtin archetypes, components, datatypes and space view definitions can be found in their +//! respective top-level modules. //! //! ## Contributing //! diff --git a/crates/re_types_builder/src/codegen/cpp/mod.rs b/crates/re_types_builder/src/codegen/cpp/mod.rs index de1e378d6364..cb84df76d863 100644 --- a/crates/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/re_types_builder/src/codegen/cpp/mod.rs @@ -136,6 +136,10 @@ impl crate::CodeGenerator for CppCodeGenerator { ObjectKind::ALL .par_iter() + .filter(|&&object_kind| { + // TODO(#5521): Implement view codegen for Rust. + object_kind != ObjectKind::View + }) .flat_map(|object_kind| { scopes .par_iter() @@ -405,6 +409,10 @@ impl QuotedObject { ObjectKind::Archetype => { Ok(Self::from_archetype(obj, hpp_includes, hpp_type_extensions)) } + ObjectKind::View => { + // TODO(#5521): Implement view codegen for Rust. + unimplemented!(); + } }, ObjectClass::Enum => Ok(Self::from_enum(objects, obj, hpp_includes)), ObjectClass::Union => Ok(Self::from_union( diff --git a/crates/re_types_builder/src/codegen/docs/mod.rs b/crates/re_types_builder/src/codegen/docs/mod.rs index b47f1d99430e..8af4fab66f30 100644 --- a/crates/re_types_builder/src/codegen/docs/mod.rs +++ b/crates/re_types_builder/src/codegen/docs/mod.rs @@ -56,6 +56,10 @@ impl CodeGenerator for DocsCodeGenerator { ObjectKind::Datatype => datatypes.push(object), ObjectKind::Component => components.push(object), ObjectKind::Archetype => archetypes.push(object), + ObjectKind::View => { + // TODO(#6082): Implement view docs generation. + continue; + } } let page = object_page(reporter, object, object_map); @@ -211,6 +215,9 @@ fn object_page(reporter: &Reporter, object: &Object, object_map: &ObjectMap) -> write_fields(&mut page, object, object_map); } ObjectKind::Archetype => write_archetype_fields(&mut page, object, object_map), + ObjectKind::View => { + // TODO(#6082): Implement view docs generation. + } } { @@ -284,6 +291,9 @@ fn object_page(reporter: &Reporter, object: &Object, object_map: &ObjectMap) -> } } } + ObjectKind::View => { + // TODO(#6082): Implement view docs generation. + } } page diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index f41c57804000..fc606ea0dcc4 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -1,5 +1,7 @@ //! Implements the Python codegen pass. +mod views; + use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use anyhow::Context as _; @@ -19,6 +21,8 @@ use crate::{ ObjectKind, Objects, Reporter, Type, ATTR_PYTHON_ALIASES, ATTR_PYTHON_ARRAY_ALIASES, }; +use self::views::code_for_view; + use super::common::ExampleInfo; /// The standard python init method. @@ -322,7 +326,7 @@ impl PythonCodeGenerator { ] } } - ObjectKind::Archetype => vec![obj.name.clone()], + ObjectKind::View | ObjectKind::Archetype => vec![obj.name.clone()], }; // NOTE: Isolating the file stem only works because we're handling datatypes, components @@ -342,14 +346,18 @@ impl PythonCodeGenerator { code.push_indented(0, &format!("# {}", autogen_warning!()), 1); if let Some(source_path) = obj.relative_filepath() { code.push_indented(0, &format!("# Based on {:?}.", format_path(source_path)), 2); - code.push_indented( - 0, - &format!( - "# You can extend this class by creating a {:?} class in {:?}.", - ext_class.name, ext_class.file_name - ), - 2, - ); + + if obj.kind != ObjectKind::View { + // View type extension isn't implemented yet (shouldn't be hard though to add if needed). + code.push_indented( + 0, + &format!( + "# You can extend this class by creating a {:?} class in {:?}.", + ext_class.name, ext_class.file_name + ), + 2, + ); + } } let manifest = quote_manifest(names); @@ -436,13 +444,17 @@ impl PythonCodeGenerator { let obj_code = match obj.class { crate::objects::ObjectClass::Struct => { - code_for_struct(reporter, arrow_registry, &ext_class, objects, obj) + if obj.kind == ObjectKind::View { + code_for_view(reporter, objects, obj) + } else { + code_for_struct(reporter, arrow_registry, &ext_class, objects, obj) + } } crate::objects::ObjectClass::Enum => { code_for_enum(reporter, arrow_registry, &ext_class, objects, obj) } crate::objects::ObjectClass::Union => { - code_for_union(arrow_registry, &ext_class, objects, obj) + code_for_union(reporter, arrow_registry, &ext_class, objects, obj) } }; @@ -458,7 +470,7 @@ impl PythonCodeGenerator { files_to_write.insert(filepath.clone(), code); } - // rerun/[{scope}]/{datatypes|components|archetypes}/__init__.py + // rerun/[{scope}]/{datatypes|components|archetypes|space_views}/__init__.py write_init_file(&kind_path, &mods, files_to_write); write_init_file(&test_kind_path, &test_mods, files_to_write); for (scope, mods) in scoped_mods { @@ -476,6 +488,10 @@ fn write_init_file( mods: &BTreeMap>, files_to_write: &mut BTreeMap, ) { + if mods.is_empty() { + return; + } + let path = kind_path.join("__init__.py"); let mut code = String::new(); let manifest = quote_manifest(mods.iter().flat_map(|(_, names)| names.iter())); @@ -766,6 +782,9 @@ fn code_for_struct( 1, ); } + ObjectKind::View => { + unreachable!("View processing shouldn't reach struct generation code."); + } } code @@ -915,12 +934,16 @@ return pa.UnionArray.from_buffers( 1, ); } + ObjectKind::View => { + reporter.error(&obj.virtpath, &obj.fqname, "A view cannot be an enum"); + } } code } fn code_for_union( + reporter: &Reporter, arrow_registry: &ArrowRegistry, ext_class: &ExtensionClass, objects: &Objects, @@ -1062,7 +1085,7 @@ fn code_for_union( match kind { ObjectKind::Archetype => (), ObjectKind::Component => { - unreachable!("component may not be a union") + reporter.error(&obj.virtpath, &obj.fqname, "An component cannot be an enum"); } ObjectKind::Datatype => { code.push_indented( @@ -1071,6 +1094,9 @@ fn code_for_union( 1, ); } + ObjectKind::View => { + reporter.error(&obj.virtpath, &obj.fqname, "An view cannot be an enum"); + } } code @@ -1970,15 +1996,10 @@ fn quote_init_method( }) .collect::>() }; - let doc_typedesc = match obj.kind { - ObjectKind::Datatype => "datatype", - ObjectKind::Component => "component", - ObjectKind::Archetype => "archetype", - }; - let mut doc_string_lines = vec![format!( - "Create a new instance of the {} {doc_typedesc}.", - obj.name + "Create a new instance of the {} {}.", + obj.name, + obj.kind.singular_name().to_lowercase() )]; if !parameter_docs.is_empty() { doc_string_lines.push("\n".to_owned()); diff --git a/crates/re_types_builder/src/codegen/python/views.rs b/crates/re_types_builder/src/codegen/python/views.rs new file mode 100644 index 000000000000..7fb154418a41 --- /dev/null +++ b/crates/re_types_builder/src/codegen/python/views.rs @@ -0,0 +1,173 @@ +use crate::{ + codegen::{ + common::StringExt as _, + python::{quote_doc_lines, quote_obj_docs}, + }, + Object, Objects, Reporter, ATTR_PYTHON_ALIASES, ATTR_RERUN_VIEW_IDENTIFIER, +}; + +pub fn code_for_view(reporter: &Reporter, objects: &Objects, obj: &Object) -> String { + assert!(obj.is_struct()); + + let mut code = String::new(); + + code.push_indented( + 0, + " +from .. import archetypes as blueprint_archetypes +from .. import components as blueprint_components +from ... import datatypes +from ..._baseclasses import AsComponents +from ...datatypes import EntityPathLike, Utf8Like +from ..api import SpaceView, SpaceViewContentsLike +", + 1, + ); + code.push('\n'); + + code.push_indented(0, format!("class {}(SpaceView):", obj.name), 1); + code.push_indented(1, quote_obj_docs(obj), 1); + + code.push_indented(1, init_method(reporter, objects, obj), 1); + + code +} + +fn init_method(reporter: &Reporter, objects: &Objects, obj: &Object) -> String { + let mut code = r#"def __init__( + self, *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + "# + .to_owned(); + + for property in &obj.fields { + let Some(property_type_fqname) = property.typ.fqname() else { + reporter.error( + &obj.virtpath, + &property.fqname, + "View properties must be archetypes.", + ); + continue; + }; + let property_type = &objects[property_type_fqname]; + let property_type_name = &property_type.name; + + // Right now we don't create "Like" type aliases for archetypes. + // So we have to list all the possible types here. + // For archetypes in general this would only be confusing, but for Space View properties it + // could be useful to make the annotation here shorter. + let additional_type_annotations = property_type + .try_get_attr::(ATTR_PYTHON_ALIASES) + .map_or(String::new(), |aliases| { + let mut types = String::new(); + for alias in aliases.split(',') { + types.push_str(alias.trim()); + types.push_str(" | "); + } + types + }); + + let parameter_name = &property.name; + code.push_str(&format!( + "{parameter_name}: blueprint_archetypes.{property_type_name} | {additional_type_annotations} None = None,\n" + )); + } + + code.push_indented(1, ") -> None:", 1); + + let mut init_docs = Vec::new(); + init_docs.push(format!( + "Construct a blueprint for a new {} view.", + obj.name + )); + init_docs.push(String::new()); + init_docs.push("Parameters".to_owned()); + init_docs.push("----------".to_owned()); + let mut parameter_docs = vec![ + ( + "origin", + "The `EntityPath` to use as the origin of this view. +All other entities will be transformed to be displayed relative to this origin." + .to_owned(), + ), + ( + "contents", + "The contents of the view specified as a query expression. +This is either a single expression, or a list of multiple expressions. +See [rerun.blueprint.archetypes.SpaceViewContents][]." + .to_owned(), + ), + ("name", "The display name of the view.".to_owned()), + ]; + for field in &obj.fields { + let doc_content = field.docs.doc_lines_for_untagged_and("py"); + if doc_content.is_empty() { + reporter.error( + &field.virtpath, + &field.fqname, + format!("Field {} is missing documentation", field.name), + ); + } + + parameter_docs.push((&field.name, doc_content.join("\n"))); + } + + for (name, doc) in parameter_docs { + let mut doc_string = format!("{name}:\n"); + doc_string.push_indented(1, doc, 0); + init_docs.push(doc_string); + } + code.push_indented(1, quote_doc_lines(init_docs), 1); + + let Some(identifier): Option = obj.try_get_attr(ATTR_RERUN_VIEW_IDENTIFIER) else { + reporter.error( + &obj.virtpath, + &obj.fqname, + format!("Missing {ATTR_RERUN_VIEW_IDENTIFIER} attribute for view"), + ); + return code; + }; + + code.push_indented(1, "properties: dict[str, AsComponents] = {}", 1); + + for property in &obj.fields { + let Some(property_type_fqname) = property.typ.fqname() else { + reporter.error( + &obj.virtpath, + &property.fqname, + "View properties must be archetypes.", + ); + continue; + }; + + let parameter_name = &property.name; + let property_type = &objects[property_type_fqname]; + let property_name = &property_type.name; + let property_type_name = format!("blueprint_archetypes.{}", &property_type.name); + code.push_indented(1, &format!("if {parameter_name} is not None:"), 1); + code.push_indented( + 2, + &format!("if not isinstance({parameter_name}, {property_type_name}):"), + 1, + ); + code.push_indented( + 3, + &format!("{parameter_name} = {property_type_name}({parameter_name})"), + 1, + ); + code.push_indented( + 2, + &format!(r#"properties["{property_name}"] = {parameter_name}"#), + 2, + ); + } + code.push_indented( + 1, + &format!(r#"super().__init__(class_identifier="{identifier}", origin=origin, contents=contents, name=name, properties=properties)"#), + 1, + ); + + code +} diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index 272229d45e1e..5787d06b144e 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -62,6 +62,11 @@ impl CodeGenerator for RustCodeGenerator { let mut files_to_write: BTreeMap = Default::default(); for object_kind in ObjectKind::ALL { + if object_kind == ObjectKind::View { + // TODO(#5521): Implement view codegen for Rust. + continue; + } + self.generate_folder( reporter, objects, @@ -1307,6 +1312,7 @@ fn quote_trait_impls_from_obj( } } } + ObjectKind::View => unimplemented!(), } } diff --git a/crates/re_types_builder/src/format/python.rs b/crates/re_types_builder/src/format/python.rs index 61d77ae49bb2..3b134264cfab 100644 --- a/crates/re_types_builder/src/format/python.rs +++ b/crates/re_types_builder/src/format/python.rs @@ -20,7 +20,7 @@ impl PythonCodeFormatter { } impl CodeFormatter for PythonCodeFormatter { - fn format(&mut self, _reporter: &crate::Reporter, files: &mut crate::GeneratedFiles) { + fn format(&mut self, reporter: &crate::Reporter, files: &mut crate::GeneratedFiles) { use rayon::prelude::*; re_tracing::profile_function!(); @@ -44,7 +44,9 @@ impl CodeFormatter for PythonCodeFormatter { crate::codegen::common::write_file(&formatted_source_path, contents); }); - format_python_dir(&tempdir_path).unwrap(); + if let Err(err) = format_python_dir(&tempdir_path) { + reporter.error_file(&tempdir_path, err); + } // Read back and copy to the final destination: files.par_iter_mut().for_each(|(filepath, contents)| { diff --git a/crates/re_types_builder/src/lib.rs b/crates/re_types_builder/src/lib.rs index 395ea8c2fa4d..8bd05dfa86ef 100644 --- a/crates/re_types_builder/src/lib.rs +++ b/crates/re_types_builder/src/lib.rs @@ -177,6 +177,7 @@ pub const ATTR_RERUN_COMPONENT_RECOMMENDED: &str = "attr.rerun.component_recomme pub const ATTR_RERUN_COMPONENT_REQUIRED: &str = "attr.rerun.component_required"; pub const ATTR_RERUN_OVERRIDE_TYPE: &str = "attr.rerun.override_type"; pub const ATTR_RERUN_SCOPE: &str = "attr.rerun.scope"; +pub const ATTR_RERUN_VIEW_IDENTIFIER: &str = "attr.rerun.view_identifier"; pub const ATTR_RERUN_DEPRECATED: &str = "attr.rerun.deprecated"; pub const ATTR_PYTHON_ALIASES: &str = "attr.python.aliases"; diff --git a/crates/re_types_builder/src/objects.rs b/crates/re_types_builder/src/objects.rs index 1c960fb87e67..24f34e89819f 100644 --- a/crates/re_types_builder/src/objects.rs +++ b/crates/re_types_builder/src/objects.rs @@ -68,28 +68,34 @@ impl Objects { objects: resolved_enums.into_iter().chain(resolved_objs).collect(), }; - // Validate fields types: Archetype consist of components, everything else consists of datatypes. + // Validate fields types: Archetype consist of components, Views (aka SuperArchetypes) consist of archetypes, everything else consists of datatypes. for obj in this.objects.values() { for field in &obj.fields { let virtpath = &field.virtpath; if let Some(field_type_fqname) = field.typ.fqname() { let field_obj = &this[field_type_fqname]; - if obj.kind == ObjectKind::Archetype { - assert!(field_obj.kind == ObjectKind::Component, - "{virtpath}: Field {:?} (pointing to an instance of {:?}) is part of an archetypes but is not a component. Only components are allowed as fields on an Archetype.", - field.fqname, field_type_fqname - ); - } else { - assert!(field_obj.kind == ObjectKind::Datatype, - "{virtpath}: Field {:?} (pointing to an instance of {:?}) is part of a Component or Datatype but is itself not a Datatype. Only Archetype fields can be Components, all other fields have to be primitive or be a datatypes.", - field.fqname, field_type_fqname - ); + match obj.kind { + ObjectKind::Datatype | ObjectKind::Component => { + if field_obj.kind != ObjectKind::Datatype { + reporter.error(virtpath, field_type_fqname, "Is part of a Component or Datatype but is itself not a Datatype. Only archetype fields can be components, all other fields have to be primitive or be a datatypes."); + } + } + ObjectKind::Archetype => { + if field_obj.kind != ObjectKind::Component { + reporter.error(virtpath, field_type_fqname, "Is part of an archetypes but is not a component. Only components are allowed as fields on an archetype."); + } + } + ObjectKind::View => { + if field_obj.kind != ObjectKind::Archetype { + reporter.error(virtpath, field_type_fqname, "Is part of an view but is not an archetype. Only archetypes are allowed as fields of a view's properties."); + } + } } } else { // Note that we *do* allow primitive fields on components for the moment. Not doing so creates a lot of bloat. - assert!(obj.kind != ObjectKind::Archetype, - "{virtpath}: Field {:?} is a primitive field of type {:?}. Only Components are allowed on Archetypes.", - field.fqname, field.typ); + if obj.kind == ObjectKind::Archetype || obj.kind == ObjectKind::View { + reporter.error(virtpath, &obj.fqname, format!("Field {:?} s a primitive field of type {:?}. Primitive types are only allowed on DataTypes & Components.", field.fqname, field.typ)); + } } } } @@ -202,10 +208,14 @@ pub enum ObjectKind { Datatype, Component, Archetype, + + /// Views are neither archetypes nor components but are used to generate code to make it easy + /// to add and configure views on the blueprint. + View, } impl ObjectKind { - pub const ALL: [Self; 3] = [Self::Datatype, Self::Component, Self::Archetype]; + pub const ALL: [Self; 4] = [Self::Datatype, Self::Component, Self::Archetype, Self::View]; // TODO(#2364): use an attr instead of the path pub fn from_pkg_name(pkg_name: &str, attrs: &Attributes) -> Self { @@ -223,6 +233,9 @@ impl ObjectKind { ObjectKind::Component } else if pkg_name.starts_with(format!("rerun{scope}.archetypes").as_str()) { ObjectKind::Archetype + } else if pkg_name.starts_with("rerun.blueprint.views") { + // Not bothering with scope attributes on views since they're always part of the blueprint. + ObjectKind::View } else { panic!("unknown package {pkg_name:?}"); } @@ -233,6 +246,7 @@ impl ObjectKind { ObjectKind::Datatype => "datatypes", ObjectKind::Component => "components", ObjectKind::Archetype => "archetypes", + ObjectKind::View => "views", } } @@ -241,6 +255,7 @@ impl ObjectKind { ObjectKind::Datatype => "Datatype", ObjectKind::Component => "Component", ObjectKind::Archetype => "Archetype", + ObjectKind::View => "View", } } @@ -249,6 +264,7 @@ impl ObjectKind { ObjectKind::Datatype => "Datatypes", ObjectKind::Component => "Components", ObjectKind::Archetype => "Archetypes", + ObjectKind::View => "Views", } } } @@ -517,6 +533,7 @@ impl Object { pub fn scope(&self) -> Option { self.try_get_attr::(crate::ATTR_RERUN_SCOPE) + .or_else(|| (self.kind == ObjectKind::View).then(|| "blueprint".to_owned())) } pub fn deprecation_notice(&self) -> Option { diff --git a/crates/re_types_builder/src/report.rs b/crates/re_types_builder/src/report.rs index 3da6ea32bafb..c6ccea99b689 100644 --- a/crates/re_types_builder/src/report.rs +++ b/crates/re_types_builder/src/report.rs @@ -1,5 +1,7 @@ use std::sync::mpsc; +use camino::Utf8Path; + /// Creates a new context. /// /// The [`Reporter`] can be freely cloned and sent to other threads. @@ -26,18 +28,28 @@ impl Reporter { Self { errors, warnings } } + /// Error about a file as a whole. + /// + /// Use sparingly for things like failing to write a file or failing to format it. + #[allow(clippy::needless_pass_by_value)] // `&impl ToString` has worse usability + pub fn error_file(&self, path: &Utf8Path, text: impl ToString) { + self.errors + .send(format!("{path}: {}", text.to_string())) + .ok(); + } + #[allow(clippy::needless_pass_by_value)] // `&impl ToString` has worse usability pub fn error(&self, virtpath: &str, fqname: &str, text: impl ToString) { - let _ = self - .errors - .send(format!("{virtpath} {fqname}: {}", text.to_string())); + self.errors + .send(format!("{virtpath} {fqname}: {}", text.to_string())) + .ok(); } #[allow(clippy::needless_pass_by_value)] // `&impl ToString` has worse usability pub fn warn(&self, virtpath: &str, fqname: &str, text: impl ToString) { - let _ = self - .warnings - .send(format!("{virtpath} {fqname}: {}", text.to_string())); + self.warnings + .send(format!("{virtpath} {fqname}: {}", text.to_string())) + .ok(); } } diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 92324fd94f96..8b8c0cbef659 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -45,7 +45,7 @@ Background3DKind, ) from .containers import Grid, Horizontal, Tabs, Vertical -from .space_views import ( +from .views import ( BarChartView, Spatial2DView, Spatial3DView, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py b/rerun_py/rerun_sdk/rerun/blueprint/space_views.py deleted file mode 100644 index a298367bb508..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/space_views.py +++ /dev/null @@ -1,219 +0,0 @@ -from __future__ import annotations - -from .._baseclasses import AsComponents -from ..datatypes import EntityPathLike, Rgba32Like, Utf8Like -from . import archetypes as blueprint_archetypes -from . import components as blueprint_components -from .api import SpaceView, SpaceViewContentsLike - - -class BarChartView(SpaceView): - """A bar chart view.""" - - def __init__( - self, - *, - origin: EntityPathLike = "/", - contents: SpaceViewContentsLike = "$origin/**", - name: Utf8Like | None = None, - ): - """ - Construct a blueprint for a new bar chart view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view specified as a query expression. This is either a single expression, - or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. - name - The name of the view. - - """ - super().__init__(class_identifier="BarChart", origin=origin, contents=contents, name=name) - - -class Spatial2DView(SpaceView): - """A Spatial 2D view.""" - - def __init__( - self, - *, - origin: EntityPathLike = "/", - contents: SpaceViewContentsLike = "$origin/**", - name: Utf8Like | None = None, - ): - """ - Construct a blueprint for a new spatial 2D view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view specified as a query expression. This is either a single expression, - or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. - name - The name of the view. - - """ - super().__init__(class_identifier="2D", origin=origin, contents=contents, name=name) - - -class Spatial3DView(SpaceView): - """A Spatial 3D view.""" - - def __init__( - self, - *, - origin: EntityPathLike = "/", - contents: SpaceViewContentsLike = "$origin/**", - name: Utf8Like | None = None, - # TODO(andreas): codegen everything that comes below: - background: blueprint_components.Background3DKindLike - | Rgba32Like - | blueprint_archetypes.Background3D - | None = None, - ): - """ - Construct a blueprint for a new spatial 3D view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view specified as a query expression. This is either a single expression, - or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. - name - The name of the view. - background: - Configuration for the background of the 3D space view. - - """ - properties: dict[str, AsComponents] = {} - # TODO(andreas): codegen creation of the properties dict - if background is not None: - properties["Background3D"] = ( - background - if isinstance(background, blueprint_archetypes.Background3D) - else blueprint_archetypes.Background3D(background) - ) - - super().__init__(class_identifier="3D", origin=origin, contents=contents, name=name, properties=properties) - - -class TensorView(SpaceView): - """A tensor view.""" - - def __init__( - self, - *, - origin: EntityPathLike = "/", - contents: SpaceViewContentsLike = "$origin/**", - name: Utf8Like | None = None, - ): - """ - Construct a blueprint for a new tensor view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view specified as a query expression. This is either a single expression, - or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. - name - The name of the view. - - """ - super().__init__(class_identifier="Tensor", origin=origin, contents=contents, name=name) - - -class TextDocumentView(SpaceView): - """A text document view.""" - - def __init__( - self, - *, - origin: EntityPathLike = "/", - contents: SpaceViewContentsLike = "$origin/**", - name: Utf8Like | None = None, - ): - """ - Construct a blueprint for a new text document view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view specified as a query expression. This is either a single expression, - or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. - name - The name of the view. - - """ - super().__init__(class_identifier="TextDocument", origin=origin, contents=contents, name=name) - - -class TextLogView(SpaceView): - """A text log view.""" - - def __init__( - self, - *, - origin: EntityPathLike = "/", - contents: SpaceViewContentsLike = "$origin/**", - name: Utf8Like | None = None, - ): - """ - Construct a blueprint for a new text log view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view specified as a query expression. This is either a single expression, - or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. - name - The name of the view. - - """ - super().__init__(class_identifier="TextLog", origin=origin, contents=contents, name=name) - - -class TimeSeriesView(SpaceView): - """A time series view.""" - - def __init__( - self, - *, - origin: EntityPathLike = "/", - contents: SpaceViewContentsLike = "$origin/**", - name: Utf8Like | None = None, - ): - """ - Construct a blueprint for a new time series view. - - Parameters - ---------- - origin - The `EntityPath` to use as the origin of this view. All other entities will be transformed - to be displayed relative to this origin. - contents - The contents of the space view specified as a query expression. This is either a single expression, - or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. - name - The name of the view. - - """ - super().__init__(class_identifier="TimeSeries", origin=origin, contents=contents, name=name) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/views/.gitattributes new file mode 100644 index 000000000000..7b44e3526b7e --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/.gitattributes @@ -0,0 +1,11 @@ +# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs + +.gitattributes linguist-generated=true +__init__.py linguist-generated=true +bar_chart_view.py linguist-generated=true +spatial2d_view.py linguist-generated=true +spatial3d_view.py linguist-generated=true +tensor_view.py linguist-generated=true +text_document_view.py linguist-generated=true +text_log_view.py linguist-generated=true +time_series_view.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/views/__init__.py new file mode 100644 index 000000000000..f178cb1134e1 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/__init__.py @@ -0,0 +1,21 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs + +from __future__ import annotations + +from .bar_chart_view import BarChartView +from .spatial2d_view import Spatial2DView +from .spatial3d_view import Spatial3DView +from .tensor_view import TensorView +from .text_document_view import TextDocumentView +from .text_log_view import TextLogView +from .time_series_view import TimeSeriesView + +__all__ = [ + "BarChartView", + "Spatial2DView", + "Spatial3DView", + "TensorView", + "TextDocumentView", + "TextLogView", + "TimeSeriesView", +] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/bar_chart_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/bar_chart_view.py new file mode 100644 index 000000000000..342f0b7a7a9a --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/bar_chart_view.py @@ -0,0 +1,44 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/views/bar_chart.fbs". + +from __future__ import annotations + +__all__ = ["BarChartView"] + + +from ..._baseclasses import AsComponents +from ...datatypes import EntityPathLike, Utf8Like +from ..api import SpaceView, SpaceViewContentsLike + + +class BarChartView(SpaceView): + """**View**: A bar chart view.""" + + def __init__( + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + ) -> None: + """ + Construct a blueprint for a new BarChartView view. + + Parameters + ---------- + origin: + The `EntityPath` to use as the origin of this view. + All other entities will be transformed to be displayed relative to this origin. + contents: + The contents of the view specified as a query expression. + This is either a single expression, or a list of multiple expressions. + See [rerun.blueprint.archetypes.SpaceViewContents][]. + name: + The display name of the view. + + """ + + properties: dict[str, AsComponents] = {} + super().__init__( + class_identifier="BarChart", origin=origin, contents=contents, name=name, properties=properties + ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py new file mode 100644 index 000000000000..06250abe69d3 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py @@ -0,0 +1,42 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs". + +from __future__ import annotations + +__all__ = ["Spatial2DView"] + + +from ..._baseclasses import AsComponents +from ...datatypes import EntityPathLike, Utf8Like +from ..api import SpaceView, SpaceViewContentsLike + + +class Spatial2DView(SpaceView): + """**View**: A Spatial 2D view.""" + + def __init__( + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + ) -> None: + """ + Construct a blueprint for a new Spatial2DView view. + + Parameters + ---------- + origin: + The `EntityPath` to use as the origin of this view. + All other entities will be transformed to be displayed relative to this origin. + contents: + The contents of the view specified as a query expression. + This is either a single expression, or a list of multiple expressions. + See [rerun.blueprint.archetypes.SpaceViewContents][]. + name: + The display name of the view. + + """ + + properties: dict[str, AsComponents] = {} + super().__init__(class_identifier="2D", origin=origin, contents=contents, name=name, properties=properties) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py new file mode 100644 index 000000000000..86e81372d7bb --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py @@ -0,0 +1,56 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs". + +from __future__ import annotations + +__all__ = ["Spatial3DView"] + + +from ... import datatypes +from ..._baseclasses import AsComponents +from ...datatypes import EntityPathLike, Utf8Like +from .. import archetypes as blueprint_archetypes +from .. import components as blueprint_components +from ..api import SpaceView, SpaceViewContentsLike + + +class Spatial3DView(SpaceView): + """**View**: A Spatial 3D view.""" + + def __init__( + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + background: blueprint_archetypes.Background3D + | datatypes.Rgba32Like + | blueprint_components.Background3DKindLike + | None = None, + ) -> None: + """ + Construct a blueprint for a new Spatial3DView view. + + Parameters + ---------- + origin: + The `EntityPath` to use as the origin of this view. + All other entities will be transformed to be displayed relative to this origin. + contents: + The contents of the view specified as a query expression. + This is either a single expression, or a list of multiple expressions. + See [rerun.blueprint.archetypes.SpaceViewContents][]. + name: + The display name of the view. + background: + Configuration for the background of the 3D space view. + + """ + + properties: dict[str, AsComponents] = {} + if background is not None: + if not isinstance(background, blueprint_archetypes.Background3D): + background = blueprint_archetypes.Background3D(background) + properties["Background3D"] = background + + super().__init__(class_identifier="3D", origin=origin, contents=contents, name=name, properties=properties) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/tensor_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/tensor_view.py new file mode 100644 index 000000000000..247bdf4da584 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/tensor_view.py @@ -0,0 +1,42 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/views/tensor.fbs". + +from __future__ import annotations + +__all__ = ["TensorView"] + + +from ..._baseclasses import AsComponents +from ...datatypes import EntityPathLike, Utf8Like +from ..api import SpaceView, SpaceViewContentsLike + + +class TensorView(SpaceView): + """**View**: A tensor view.""" + + def __init__( + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + ) -> None: + """ + Construct a blueprint for a new TensorView view. + + Parameters + ---------- + origin: + The `EntityPath` to use as the origin of this view. + All other entities will be transformed to be displayed relative to this origin. + contents: + The contents of the view specified as a query expression. + This is either a single expression, or a list of multiple expressions. + See [rerun.blueprint.archetypes.SpaceViewContents][]. + name: + The display name of the view. + + """ + + properties: dict[str, AsComponents] = {} + super().__init__(class_identifier="Tensor", origin=origin, contents=contents, name=name, properties=properties) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/text_document_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/text_document_view.py new file mode 100644 index 000000000000..3a5d60c6ed36 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/text_document_view.py @@ -0,0 +1,44 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/views/text_document.fbs". + +from __future__ import annotations + +__all__ = ["TextDocumentView"] + + +from ..._baseclasses import AsComponents +from ...datatypes import EntityPathLike, Utf8Like +from ..api import SpaceView, SpaceViewContentsLike + + +class TextDocumentView(SpaceView): + """**View**: A text document view.""" + + def __init__( + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + ) -> None: + """ + Construct a blueprint for a new TextDocumentView view. + + Parameters + ---------- + origin: + The `EntityPath` to use as the origin of this view. + All other entities will be transformed to be displayed relative to this origin. + contents: + The contents of the view specified as a query expression. + This is either a single expression, or a list of multiple expressions. + See [rerun.blueprint.archetypes.SpaceViewContents][]. + name: + The display name of the view. + + """ + + properties: dict[str, AsComponents] = {} + super().__init__( + class_identifier="TextDocument", origin=origin, contents=contents, name=name, properties=properties + ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/text_log_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/text_log_view.py new file mode 100644 index 000000000000..ab708803d718 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/text_log_view.py @@ -0,0 +1,42 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/views/text_log.fbs". + +from __future__ import annotations + +__all__ = ["TextLogView"] + + +from ..._baseclasses import AsComponents +from ...datatypes import EntityPathLike, Utf8Like +from ..api import SpaceView, SpaceViewContentsLike + + +class TextLogView(SpaceView): + """**View**: A text log view.""" + + def __init__( + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + ) -> None: + """ + Construct a blueprint for a new TextLogView view. + + Parameters + ---------- + origin: + The `EntityPath` to use as the origin of this view. + All other entities will be transformed to be displayed relative to this origin. + contents: + The contents of the view specified as a query expression. + This is either a single expression, or a list of multiple expressions. + See [rerun.blueprint.archetypes.SpaceViewContents][]. + name: + The display name of the view. + + """ + + properties: dict[str, AsComponents] = {} + super().__init__(class_identifier="TextLog", origin=origin, contents=contents, name=name, properties=properties) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py new file mode 100644 index 000000000000..00a25b2001f6 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py @@ -0,0 +1,44 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/views/time_series.fbs". + +from __future__ import annotations + +__all__ = ["TimeSeriesView"] + + +from ..._baseclasses import AsComponents +from ...datatypes import EntityPathLike, Utf8Like +from ..api import SpaceView, SpaceViewContentsLike + + +class TimeSeriesView(SpaceView): + """**View**: A time series view.""" + + def __init__( + self, + *, + origin: EntityPathLike = "/", + contents: SpaceViewContentsLike = "$origin/**", + name: Utf8Like | None = None, + ) -> None: + """ + Construct a blueprint for a new TimeSeriesView view. + + Parameters + ---------- + origin: + The `EntityPath` to use as the origin of this view. + All other entities will be transformed to be displayed relative to this origin. + contents: + The contents of the view specified as a query expression. + This is either a single expression, or a list of multiple expressions. + See [rerun.blueprint.archetypes.SpaceViewContents][]. + name: + The display name of the view. + + """ + + properties: dict[str, AsComponents] = {} + super().__init__( + class_identifier="TimeSeries", origin=origin, contents=contents, name=name, properties=properties + ) From b6a507284dd5e404f966f1e7e7d1bf1b032be71d Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:22:54 +0200 Subject: [PATCH 356/508] Update UI for static components (#6101) ### What This PR updates the UI to better display static components, including: - Components logged as static now have a different icon. - Components logged as static do not have any event displayed in the timeline (see below for possible follow-up work). - The "timeless" gutter in the timeline is gone. - The hover tooltip in the streams for static component now displays their content (timeful components have their content displayed on the corresponding event in the timeline). - All components now have a "logged time" displayed along their data (showing the actually logging time that was taken into consideration by the current LatestAt query). It shows `` for static components. This appears both in the selection panel and in the hover tooltips. - In addition, data consistency information is displayed for static component (both tooltip and selection panel): - Warning (yellow) if multiple static logs were recorded (the data of previous logging event is overwritten and not recoverable from the datastore). - Error (red) if the static component has timeful stuff logged as well (albeit that data is not loss, it's not queryable and extremely likely an indication of user error). Note: the included release checklist is nice to try the error/warning cases. - Fixes #6074 - Possible follow-up https://github.com/rerun-io/rerun/issues/6102 ### Screenshots static + timeful error: image multi-static warning: image selection panel: image ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6101?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6101?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6101) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- Cargo.lock | 1 + crates/re_data_ui/src/component.rs | 46 +++++++++++ crates/re_data_ui/src/instance_path.rs | 2 + crates/re_data_ui/src/item_ui.rs | 10 ++- crates/re_entity_db/src/entity_db.rs | 25 ++++-- crates/re_entity_db/src/entity_tree.rs | 4 +- .../src/time_histogram_per_timeline.rs | 36 +++++---- .../re_query_cache2/src/latest_at/results.rs | 6 ++ crates/re_time_panel/Cargo.toml | 1 + .../re_time_panel/src/data_density_graph.rs | 14 +--- crates/re_time_panel/src/lib.rs | 46 +++++++---- crates/re_time_panel/src/time_ranges_ui.rs | 25 ------ crates/re_ui/data/icons/component_static.png | Bin 0 -> 273 bytes crates/re_ui/src/icons.rs | 4 + crates/re_viewer/src/ui/selection_panel.rs | 19 +++-- crates/re_viewer_context/src/time_control.rs | 4 +- .../check_static_components_ui.py | 72 ++++++++++++++++++ 17 files changed, 235 insertions(+), 80 deletions(-) create mode 100644 crates/re_ui/data/icons/component_static.png create mode 100644 tests/python/release_checklist/check_static_components_ui.py diff --git a/Cargo.lock b/Cargo.lock index d40b30b738bd..3671eb702506 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4897,6 +4897,7 @@ dependencies = [ "re_data_ui", "re_entity_db", "re_format", + "re_log", "re_log_types", "re_tracing", "re_ui", diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index fd93605bc991..e3961b0a1789 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -52,6 +52,52 @@ impl DataUi for EntityLatestAtResults { UiVerbosity::LimitHeight | UiVerbosity::Full => num_instances, }; + // Display data time and additional diagnostic information for static components. + if verbosity != UiVerbosity::Small { + ui.label(format!( + "Data time: {}", + query + .timeline() + .typ() + .format(self.results.index().0, ctx.app_options.time_zone), + )); + + // if the component is static, we display extra diagnostic information + if self.results.is_static() { + if let Some(histogram) = db + .tree() + .subtree(&self.entity_path) + .and_then(|tree| tree.entity.components.get(&self.component_name)) + { + if histogram.num_static_messages() > 1 { + ui.label(ctx.re_ui.warning_text(format!( + "Static component value was overridden {} times", + histogram.num_static_messages().saturating_sub(1), + ))) + .on_hover_text( + "When a static component is logged multiple times, only the last value \ + is stored. Previously logged values are overwritten and not \ + recoverable.", + ); + } + + let timeline_message_count = histogram.num_temporal_messages(); + if timeline_message_count > 0 { + ui.label(ctx.re_ui.error_text(format!( + "Static component has {} event{} logged on timelines", + timeline_message_count, + if timeline_message_count > 1 { "s" } else { "" } + ))) + .on_hover_text( + "Components should be logged either as static or on timelines, but \ + never both. Values for static components logged to timelines cannot be \ + displayed.", + ); + } + } + } + } + // Here we enforce that exactly `max_row` rows are displayed, which means that: // - For `num_instances == max_row`, then `max_row` rows are displayed. // - For `num_instances == max_row + 1`, then `max_row-1` rows are displayed and "…2 more" diff --git a/crates/re_data_ui/src/instance_path.rs b/crates/re_data_ui/src/instance_path.rs index 11152fedd6f0..a3369bc5a2b8 100644 --- a/crates/re_data_ui/src/instance_path.rs +++ b/crates/re_data_ui/src/instance_path.rs @@ -65,6 +65,7 @@ impl DataUi for InstancePath { ctx, ui, &ComponentPath::new(entity_path.clone(), component_name), + db, ); } } @@ -89,6 +90,7 @@ impl DataUi for InstancePath { ctx, ui, &ComponentPath::new(entity_path.clone(), component_name), + db, ); if instance_key.is_splat() { diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 001c3320297d..ccbc561a538c 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -374,12 +374,14 @@ pub fn component_path_button( ctx: &ViewerContext<'_>, ui: &mut egui::Ui, component_path: &ComponentPath, + db: &re_entity_db::EntityDb, ) -> egui::Response { component_path_button_to( ctx, ui, component_path.component_name.short_name(), component_path, + db, ) .on_hover_text(component_path.component_name.full_name()) // we should show the full name somewhere } @@ -390,11 +392,17 @@ pub fn component_path_button_to( ui: &mut egui::Ui, text: impl Into, component_path: &ComponentPath, + db: &re_entity_db::EntityDb, ) -> egui::Response { let item = Item::ComponentPath(component_path.clone()); + let is_component_static = db.is_component_static(component_path).unwrap_or_default(); let response = ctx.re_ui.selectable_label_with_icon( ui, - &icons::COMPONENT, + if is_component_static { + &icons::COMPONENT_STATIC + } else { + &icons::COMPONENT + }, text, ctx.selection().contains_item(&item), re_ui::LabelStyle::Normal, diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 89848fee70de..68de41faeb7a 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -8,9 +8,9 @@ use re_data_store::{ DataStore, DataStoreConfig, GarbageCollectionOptions, StoreEvent, StoreSubscriber, }; use re_log_types::{ - ApplicationId, DataCell, DataRow, DataTable, DataTableResult, EntityPath, EntityPathHash, - LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, TimeRange, TimeRangeF, - Timeline, + ApplicationId, ComponentPath, DataCell, DataRow, DataTable, DataTableResult, EntityPath, + EntityPathHash, LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, + TimeRange, TimeRangeF, Timeline, }; use re_query2::PromiseResult; use re_types_core::{components::InstanceKey, Archetype, Loggable}; @@ -327,9 +327,22 @@ impl EntityDb { self.tree().subtree.time_histogram.get(timeline) } - /// Total number of timeless messages for any entity. - pub fn num_timeless_messages(&self) -> u64 { - self.tree.num_timeless_messages_recursive() + /// Total number of static messages for any entity. + pub fn num_static_messages(&self) -> u64 { + self.tree.num_static_messages_recursive() + } + + /// Returns whether a component is static. + pub fn is_component_static(&self, component_path: &ComponentPath) -> Option { + if let Some(entity_tree) = self.tree().subtree(component_path.entity_path()) { + entity_tree + .entity + .components + .get(&component_path.component_name) + .map(|component_histogram| component_histogram.is_static()) + } else { + None + } } pub fn num_rows(&self) -> usize { diff --git a/crates/re_entity_db/src/entity_tree.rs b/crates/re_entity_db/src/entity_tree.rs index 263633426a93..f1a744e4f8f8 100644 --- a/crates/re_entity_db/src/entity_tree.rs +++ b/crates/re_entity_db/src/entity_tree.rs @@ -245,8 +245,8 @@ impl EntityTree { } /// Number of timeless messages in this tree, or any child, recursively. - pub fn num_timeless_messages_recursive(&self) -> u64 { - self.subtree.time_histogram.num_timeless_messages() + pub fn num_static_messages_recursive(&self) -> u64 { + self.subtree.time_histogram.num_static_messages() } pub fn time_histogram_for_component( diff --git a/crates/re_entity_db/src/time_histogram_per_timeline.rs b/crates/re_entity_db/src/time_histogram_per_timeline.rs index ca8d79f900a8..b17432d2a801 100644 --- a/crates/re_entity_db/src/time_histogram_per_timeline.rs +++ b/crates/re_entity_db/src/time_histogram_per_timeline.rs @@ -16,14 +16,19 @@ pub struct TimeHistogramPerTimeline { /// When do we have data? Ignores timeless. times: BTreeMap, - /// Extra book-keeping used to seed any timelines that include timeless msgs. - num_timeless_messages: u64, + /// Extra bookkeeping used to seed any timelines that include static msgs. + num_static_messages: u64, } impl TimeHistogramPerTimeline { #[inline] pub fn is_empty(&self) -> bool { - self.times.is_empty() && self.num_timeless_messages == 0 + self.times.is_empty() && self.num_static_messages == 0 + } + + #[inline] + pub fn is_static(&self) -> bool { + self.num_static_messages > 0 } #[inline] @@ -47,20 +52,25 @@ impl TimeHistogramPerTimeline { } #[inline] - pub fn num_timeless_messages(&self) -> u64 { - self.num_timeless_messages + pub fn num_static_messages(&self) -> u64 { + self.num_static_messages + } + + /// Total number of temporal messages over all timelines. + pub fn num_temporal_messages(&self) -> u64 { + self.times.values().map(|hist| hist.total_count()).sum() } pub fn add(&mut self, times: &[(Timeline, TimeInt)], n: u32) { if times.is_empty() { - self.num_timeless_messages = self - .num_timeless_messages + self.num_static_messages = self + .num_static_messages .checked_add(n as u64) .unwrap_or_else(|| { re_log::debug!( - current = self.num_timeless_messages, + current = self.num_static_messages, added = n, - "book keeping overflowed" + "bookkeeping overflowed" ); u64::MAX }); @@ -76,15 +86,15 @@ impl TimeHistogramPerTimeline { pub fn remove(&mut self, timepoint: &TimePoint, n: u32) { if timepoint.is_static() { - self.num_timeless_messages = self - .num_timeless_messages + self.num_static_messages = self + .num_static_messages .checked_sub(n as u64) .unwrap_or_else(|| { // TODO(#4355): hitting this on plots demo re_log::debug!( - current = self.num_timeless_messages, + current = self.num_static_messages, removed = n, - "book keeping underflowed" + "bookkeeping underflowed" ); u64::MIN }); diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index 909c16916dd9..ec591ff97315 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -157,6 +157,12 @@ impl CachedLatestAtComponentResults { _ => None, } } + + /// Returns whether the resolved data is static. + #[inline] + pub fn is_static(&self) -> bool { + self.index.0 == TimeInt::STATIC + } } impl SizeBytes for CachedLatestAtComponentResults { diff --git a/crates/re_time_panel/Cargo.toml b/crates/re_time_panel/Cargo.toml index 3115f8891c21..6b95fb0cdf5d 100644 --- a/crates/re_time_panel/Cargo.toml +++ b/crates/re_time_panel/Cargo.toml @@ -23,6 +23,7 @@ re_data_store.workspace = true re_data_ui.workspace = true re_entity_db.workspace = true re_format.workspace = true +re_log.workspace = true re_log_types.workspace = true re_tracing.workspace = true re_ui.workspace = true diff --git a/crates/re_time_panel/src/data_density_graph.rs b/crates/re_time_panel/src/data_density_graph.rs index 3a73e4c1c224..858907e25d18 100644 --- a/crates/re_time_panel/src/data_density_graph.rs +++ b/crates/re_time_panel/src/data_density_graph.rs @@ -10,7 +10,7 @@ use egui::{epaint::Vertex, lerp, pos2, remap, Color32, NumExt as _, Rect, Shape} use re_data_ui::item_ui; use re_entity_db::TimeHistogram; -use re_log_types::{ComponentPath, TimeInt, TimeRange, TimeReal}; +use re_log_types::{ComponentPath, TimeRange, TimeReal}; use re_viewer_context::{Item, TimeControl, UiVerbosity, ViewerContext}; use crate::TimePanelItem; @@ -368,14 +368,13 @@ fn smooth(density: &[f32]) -> Vec { #[allow(clippy::too_many_arguments)] pub fn data_density_graph_ui( - data_dentity_graph_painter: &mut DataDensityGraphPainter, + data_density_graph_painter: &mut DataDensityGraphPainter, ctx: &ViewerContext<'_>, time_ctrl: &mut TimeControl, db: &re_entity_db::EntityDb, time_area_response: &egui::Response, time_area_painter: &egui::Painter, ui: &egui::Ui, - num_timeless_messages: usize, time_histogram: &TimeHistogram, row_rect: Rect, time_ranges_ui: &TimeRangesUi, @@ -435,11 +434,6 @@ pub fn data_density_graph_ui( } }; - add_data_point( - TimeRange::point(TimeInt::MIN_TIME_PANEL), - num_timeless_messages, - ); - let visible_time_range = time_ranges_ui .time_range_from_x_range((row_rect.left() - MARGIN_X)..=(row_rect.right() + MARGIN_X)); @@ -479,7 +473,7 @@ pub fn data_density_graph_ui( density_graph.buckets = smooth(&density_graph.buckets); density_graph.paint( - data_dentity_graph_painter, + data_density_graph_painter, row_rect.y_range(), time_area_painter, graph_color(ctx, &item.to_item(), ui), @@ -559,7 +553,7 @@ fn show_row_ids_tooltip( if let Some(component_name) = component_name { let component_path = ComponentPath::new(entity_path.clone(), *component_name); - item_ui::component_path_button(ctx, ui, &component_path); + item_ui::component_path_button(ctx, ui, &component_path, db); ui.add_space(8.0); component_path.data_ui(ctx, ui, verbosity, &query, db); } else { diff --git a/crates/re_time_panel/src/lib.rs b/crates/re_time_panel/src/lib.rs index 6aea8b62c413..b56aee1e0e12 100644 --- a/crates/re_time_panel/src/lib.rs +++ b/crates/re_time_panel/src/lib.rs @@ -14,6 +14,7 @@ use egui::emath::Rangef; use egui::{pos2, Color32, CursorIcon, NumExt, Painter, PointerButton, Rect, Shape, Ui, Vec2}; use re_data_ui::item_ui::guess_instance_path_icon; +use re_data_ui::DataUi as _; use re_entity_db::{EntityTree, InstancePath, TimeHistogram}; use re_log_types::{ external::re_types_core::ComponentName, ComponentPath, EntityPath, EntityPathPart, TimeInt, @@ -21,7 +22,8 @@ use re_log_types::{ }; use re_ui::list_item::{ListItem, WidthAllocationMode}; use re_viewer_context::{ - CollapseScope, HoverHighlight, Item, RecordingConfig, TimeControl, TimeView, ViewerContext, + CollapseScope, HoverHighlight, Item, RecordingConfig, TimeControl, TimeView, UiVerbosity, + ViewerContext, }; use re_viewport::{context_menu_ui_for_item, SelectionUpdateBehavior, ViewportBlueprint}; @@ -513,6 +515,7 @@ impl TimePanel { self.show_tree( ctx, viewport_blueprint, + entity_db, time_ctrl, time_area_response, time_area_painter, @@ -526,6 +529,7 @@ impl TimePanel { self.show_children( ctx, viewport_blueprint, + entity_db, time_ctrl, time_area_response, time_area_painter, @@ -542,6 +546,7 @@ impl TimePanel { &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, + entity_db: &re_entity_db::EntityDb, time_ctrl: &mut TimeControl, time_area_response: &egui::Response, time_area_painter: &egui::Painter, @@ -615,6 +620,7 @@ impl TimePanel { self.show_children( ctx, viewport_blueprint, + entity_db, time_ctrl, time_area_response, time_area_painter, @@ -693,7 +699,6 @@ impl TimePanel { time_area_response, time_area_painter, ui, - tree.num_timeless_messages_recursive() as usize, num_messages_at_time, row_rect, &self.time_ranges_ui, @@ -708,6 +713,7 @@ impl TimePanel { &mut self, ctx: &ViewerContext<'_>, viewport_blueprint: &ViewportBlueprint, + entity_db: &re_entity_db::EntityDb, time_ctrl: &mut TimeControl, time_area_response: &egui::Response, time_area_painter: &egui::Painter, @@ -719,6 +725,7 @@ impl TimePanel { self.show_tree( ctx, viewport_blueprint, + entity_db, time_ctrl, time_area_response, time_area_painter, @@ -737,11 +744,13 @@ impl TimePanel { for component_name in re_data_ui::ui_visible_components(tree.entity.components.keys()) { let data = &tree.entity.components[&component_name]; + let is_static = data.is_static(); let component_has_data_in_current_timeline = time_ctrl.component_has_data_in_current_timeline(data); + let component_path = ComponentPath::new(tree.path.clone(), component_name); let short_component_name = component_path.component_name.short_name(); - let item = TimePanelItem::component_path(component_path); + let item = TimePanelItem::component_path(component_path.clone()); let mut clip_rect = clip_rect_save; clip_rect.max.x = tree_max_y; @@ -755,7 +764,11 @@ impl TimePanel { .highlight_for_ui_element(&item.to_item()) == HoverHighlight::Hovered, ) - .with_icon(&re_ui::icons::COMPONENT) + .with_icon(if is_static { + &re_ui::icons::COMPONENT_STATIC + } else { + &re_ui::icons::COMPONENT + }) .show_hierarchical(ui); ui.set_clip_rect(clip_rect_save); @@ -776,9 +789,9 @@ impl TimePanel { let empty_messages_over_time = TimeHistogram::default(); let messages_over_time = data.get(timeline).unwrap_or(&empty_messages_over_time); - // `data.times` does not contain timeless. Need to add those manually: + // `data.times` does not contain static. Need to add those manually: let total_num_messages = - messages_over_time.total_count() + data.num_timeless_messages(); + messages_over_time.total_count() + data.num_static_messages(); response.on_hover_ui(|ui| { if total_num_messages == 0 { ui.label(ctx.re_ui.warning_text(format!( @@ -787,6 +800,17 @@ impl TimePanel { ))); } else { ui.label(format!("Number of events: {total_num_messages}")); + + // Static components are not displayed at all on the timeline, so cannot be + // previewed there. So we display their content in this tooltip instead. + if is_static { + let query = re_data_store::LatestAtQuery::new( + *time_ctrl.timeline(), + TimeInt::MAX, + ); + let verbosity = UiVerbosity::Reduced; + component_path.data_ui(ctx, ui, verbosity, &query, entity_db); + } } }); @@ -820,7 +844,6 @@ impl TimePanel { time_area_response, time_area_painter, ui, - data.num_timeless_messages() as usize, messages_over_time, row_rect, &self.time_ranges_ui, @@ -1024,7 +1047,7 @@ fn is_time_safe_to_show( timeline: &re_data_store::Timeline, time: TimeReal, ) -> bool { - if entity_db.num_timeless_messages() == 0 { + if entity_db.num_static_messages() == 0 { return true; // no timeless messages, no problem } @@ -1069,12 +1092,7 @@ fn initialize_time_ranges_ui( ) -> TimeRangesUi { re_tracing::profile_function!(); - // If there's any timeless data, add the "beginning range" that contains timeless data. - let mut time_range = if entity_db.num_timeless_messages() > 0 { - vec![TimeRange::point(TimeInt::MIN_TIME_PANEL)] - } else { - Vec::new() - }; + let mut time_range = Vec::new(); if let Some(times) = entity_db.time_histogram(time_ctrl.timeline()) { // NOTE: `times` can be empty if a GC wiped everything. diff --git a/crates/re_time_panel/src/time_ranges_ui.rs b/crates/re_time_panel/src/time_ranges_ui.rs index b5405fde570a..1cdeade5e39c 100644 --- a/crates/re_time_panel/src/time_ranges_ui.rs +++ b/crates/re_time_panel/src/time_ranges_ui.rs @@ -200,31 +200,6 @@ impl TimeRangesUi { TimeReal::from(first.tight_time.min()), TimeReal::from(last.tight_time.max()), ); - - // Special: don't allow users dragging time between MIN_TIME_PANEL (-∞ = timeless data) - // and some real time. - // - // Otherwise we get weird times (e.g. dates in 1923). - // Selecting times between other segments is not as problematic, as all other segments are - // real times, so interpolating between them always produces valid times - // (we want users to have a smooth experience dragging the time handle anywhere else). - // By disallowing times between MIN_TIME_PANEL and the first real segment, - // we also disallow users dragging the time to be between -∞ and the - // real beginning of their data. That further highlights the specialness of -∞. - // - // TODO(#5264): remove time panel hack once we migrate to the new static UI - if first.tight_time.contains(TimeInt::MIN_TIME_PANEL) { - if let Some(second) = self.segments.get(1) { - let half_way = - TimeRangeF::new(TimeInt::MIN_TIME_PANEL, second.tight_time.min()).lerp(0.5); - - if time < half_way { - time = TimeReal::from(TimeInt::MIN_TIME_PANEL); - } else if time < second.tight_time.min() { - time = second.tight_time.min().into(); - } - } - } } time } diff --git a/crates/re_ui/data/icons/component_static.png b/crates/re_ui/data/icons/component_static.png new file mode 100644 index 0000000000000000000000000000000000000000..b02f06f03337337e807335cfd53d2ff3d00ba3ab GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^G9b*s1|*Ak?@s|zoCO|{#S9E$svykh8Km+7D9BhG z8w_|{gVhUI+zVLlx~K=5 z7YGAcvPXHdn(8|G)g~&{J#o-@^i(b?gOTU(57B$Sd)y|Rc4WBSZtpI|G2Nst`H<(# zH%s*ySyc`%y=$L2U0K~$S!`a)hcGQ6yAyGqk&0rWj5hmdKI;Vst0N9UM3IG5A literal 0 HcmV?d00001 diff --git a/crates/re_ui/src/icons.rs b/crates/re_ui/src/icons.rs index bf434de7f3a4..6dbebf9a3a7e 100644 --- a/crates/re_ui/src/icons.rs +++ b/crates/re_ui/src/icons.rs @@ -144,6 +144,10 @@ pub const ENTITY_EMPTY: Icon = Icon::new( ); pub const LINK: Icon = Icon::new("link", include_bytes!("../data/icons/link.png")); pub const COMPONENT: Icon = Icon::new("component", include_bytes!("../data/icons/component.png")); +pub const COMPONENT_STATIC: Icon = Icon::new( + "component_static", + include_bytes!("../data/icons/component_static.png"), +); pub const APPLICATION: Icon = Icon::new( "application", diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index b311b38055bd..b6599c58e66b 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -359,15 +359,22 @@ fn what_is_selected_ui( } } - Item::ComponentPath(re_log_types::ComponentPath { - entity_path, - component_name, - }) => { + Item::ComponentPath(component_path) => { + let entity_path = &component_path.entity_path; + let component_name = &component_path.component_name; + + let (query, db) = guess_query_and_db_for_selected_entity(ctx, entity_path); + let is_static = db.is_component_static(component_path).unwrap_or_default(); + item_title_ui( ctx.re_ui, ui, component_name.short_name(), - Some(&re_ui::icons::COMPONENT), + Some(if is_static { + &re_ui::icons::COMPONENT_STATIC + } else { + &re_ui::icons::COMPONENT + }), &format!( "Component {} of entity '{}'", component_name.full_name(), @@ -375,8 +382,6 @@ fn what_is_selected_ui( ), ); - let (query, db) = guess_query_and_db_for_selected_entity(ctx, entity_path); - ui.horizontal(|ui| { ui.label("component of"); item_ui::entity_path_button(ctx, &query, db, ui, None, entity_path); diff --git a/crates/re_viewer_context/src/time_control.rs b/crates/re_viewer_context/src/time_control.rs index 71eaaf17318a..dbf1a9894153 100644 --- a/crates/re_viewer_context/src/time_control.rs +++ b/crates/re_viewer_context/src/time_control.rs @@ -548,7 +548,7 @@ impl TimeControl { pub fn tree_has_data_in_current_timeline(&self, tree: &EntityTree) -> bool { let top_time_histogram = &tree.subtree.time_histogram; top_time_histogram.has_timeline(self.timeline()) - || top_time_histogram.num_timeless_messages() > 0 + || top_time_histogram.num_static_messages() > 0 } /// Returns whether the given component has any data logged in the current timeline. @@ -556,7 +556,7 @@ impl TimeControl { &self, component_stat: &TimeHistogramPerTimeline, ) -> bool { - component_stat.has_timeline(self.timeline()) || component_stat.num_timeless_messages() > 0 + component_stat.has_timeline(self.timeline()) } } diff --git a/tests/python/release_checklist/check_static_components_ui.py b/tests/python/release_checklist/check_static_components_ui.py new file mode 100644 index 000000000000..f8d8035dd7b9 --- /dev/null +++ b/tests/python/release_checklist/check_static_components_ui.py @@ -0,0 +1,72 @@ +from __future__ import annotations + +import os +from argparse import Namespace +from uuid import uuid4 + +import rerun as rr + +README = """ +# Static components + +In the streams view, check the hover tooltips and selection panel for each `Position2D` components. They should both +display warnings/errors according to the following table: + + +```plaintext +========================================================================== +COMPONENT FEEDBACK +========================================================================== + +static:Position2D - + +static_overwrite:Position2D warning (orange): overridden 2 times + +hybrid:Position2D error (red): 12 events logged on timelines + +========================================================================== +``` +""" + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), static=True) + + +def log_some_space_views() -> None: + rr.log("static", rr.Points2D([(0, 0), (1, 1), (2, 2)]), static=True) + + # override static component + rr.log("static_overwrite", rr.Points2D([(0, 0), (1, 1), (2, 2)]), static=True) + rr.log("static_overwrite", rr.Points2D([(0, 0), (1, 1), (5, 2)]), static=True) + rr.log("static_overwrite", rr.Points2D([(0, 0), (1, 1), (10, 2)]), static=True) + + # mixed time-full and static logs + rr.log("hybrid", rr.Points2D([(0, 0), (1, 1), (2, 2)]), static=True) + + rr.set_time_seconds("time", 1.0) + rr.log("hybrid", rr.Points2D([(0, 0), (1, 1), (2, 2)])) + rr.set_time_seconds("time", 1.0) + rr.log("hybrid", rr.Points2D([(0, 0), (1, 1), (2, 2)])) + rr.set_time_seconds("time", 1.0) + rr.log("hybrid", rr.Points2D([(0, 0), (1, 1), (2, 2)])) + + rr.disable_timeline("time") + rr.set_time_seconds("other_time", 10.0) + rr.log("hybrid", rr.Points2D([(0, 0), (1, 1), (2, 2)])) + + +def run(args: Namespace) -> None: + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4()) + + log_readme() + log_some_space_views() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) From 10753fa6f52a4df6fabeb373bec80999d9c7df43 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 25 Apr 2024 12:13:16 +0200 Subject: [PATCH 357/508] Allow any pan/zoom in 2D spatial views (#6089) ### What * Closes https://github.com/rerun-io/rerun/issues/2531 * Closes https://github.com/rerun-io/rerun/issues/2490 By default the bounds are centered: Before: Screenshot 2024-04-24 at 11 46 47 After: Screenshot 2024-04-24 at 11 45 41 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6089?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6089?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6089) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Andreas Reich --- Cargo.lock | 11 + crates/re_renderer/src/global_bindings.rs | 2 +- crates/re_renderer/src/transform.rs | 5 + crates/re_renderer/src/view_builder.rs | 188 +++--- crates/re_renderer_examples/2d.rs | 6 +- crates/re_renderer_examples/depth_cloud.rs | 14 +- crates/re_renderer_examples/depth_offset.rs | 4 +- crates/re_renderer_examples/framework.rs | 2 +- crates/re_renderer_examples/multiview.rs | 4 +- crates/re_renderer_examples/outlines.rs | 4 +- crates/re_renderer_examples/picking.rs | 4 +- crates/re_space_view_spatial/src/picking.rs | 4 +- .../src/space_view_2d.rs | 19 +- crates/re_space_view_spatial/src/ui.rs | 11 +- crates/re_space_view_spatial/src/ui_2d.rs | 599 ++++++++---------- crates/re_space_view_spatial/src/ui_3d.rs | 2 +- crates/re_types/src/archetypes/pinhole_ext.rs | 11 + .../src/components/pinhole_projection_ext.rs | 14 + crates/re_types/src/datatypes/mat3x3_ext.rs | 23 + .../re_viewer_context/src/gpu_bridge/mod.rs | 12 +- examples/python/rgbd/rgbd.py | 2 + tests/rust/test_api/Cargo.toml | 2 +- tests/rust/test_pinhole_projection/Cargo.toml | 18 + .../rust/test_pinhole_projection/src/main.rs | 83 +++ 24 files changed, 586 insertions(+), 458 deletions(-) create mode 100644 tests/rust/test_pinhole_projection/Cargo.toml create mode 100644 tests/rust/test_pinhole_projection/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 3671eb702506..3175708dc900 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6256,6 +6256,17 @@ dependencies = [ "rerun", ] +[[package]] +name = "test_pinhole_projection" +version = "0.16.0-alpha.2" +dependencies = [ + "anyhow", + "clap", + "image", + "re_log", + "rerun", +] + [[package]] name = "thiserror" version = "1.0.56" diff --git a/crates/re_renderer/src/global_bindings.rs b/crates/re_renderer/src/global_bindings.rs index 6404da52b024..c23f17f8f611 100644 --- a/crates/re_renderer/src/global_bindings.rs +++ b/crates/re_renderer/src/global_bindings.rs @@ -33,7 +33,7 @@ pub struct FrameUniformBuffer { /// How many pixels there are per point. /// I.e. the UI zoom factor - pub pixels_from_point: f32, + pub pixels_per_point: f32, /// (tan(fov_y / 2) * aspect_ratio, tan(fov_y /2)), i.e. half ratio of screen dimension to screen distance in x & y. /// Both values are set to f32max for orthographic projection diff --git a/crates/re_renderer/src/transform.rs b/crates/re_renderer/src/transform.rs index b3aa4ba95339..deeadf308f69 100644 --- a/crates/re_renderer/src/transform.rs +++ b/crates/re_renderer/src/transform.rs @@ -36,10 +36,15 @@ pub fn ndc_from_pixel(pixel_coord: glam::Vec2, screen_extent: glam::UVec2) -> gl /// Defines a transformation from a rectangular region of interest into a rectangular target region. /// +/// This is "pan and scan". +/// /// Transforms the range of `region_of_interest` to the range of `region`. #[derive(Clone, Debug)] pub struct RectTransform { + /// The region of the scene that should be visible. pub region_of_interest: RectF32, + + /// The full scene. pub region: RectF32, } diff --git a/crates/re_renderer/src/view_builder.rs b/crates/re_renderer/src/view_builder.rs index 92464abd3ac7..e167326f3540 100644 --- a/crates/re_renderer/src/view_builder.rs +++ b/crates/re_renderer/src/view_builder.rs @@ -69,7 +69,7 @@ pub type SharedViewBuilder = Arc>>; /// Configures the camera placement in the orthographic frustum, /// as well as the coordinate system convention. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub enum OrthographicCameraMode { /// Puts the view space origin into the middle of the screen. /// @@ -94,7 +94,7 @@ pub enum OrthographicCameraMode { } /// How we project from 3D to 2D. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub enum Projection { /// Perspective camera looking along the negative z view space axis. Perspective { @@ -124,6 +124,74 @@ pub enum Projection { }, } +impl Projection { + fn projection_from_view(self, resolution_in_pixel: [u32; 2]) -> glam::Mat4 { + match self { + Projection::Perspective { + vertical_fov, + near_plane_distance, + aspect_ratio, + } => { + // We use infinite reverse-z projection matrix + // * great precision both with floating point and integer: https://developer.nvidia.com/content/depth-precision-visualized + // * no need to worry about far plane + glam::Mat4::perspective_infinite_reverse_rh( + vertical_fov, + aspect_ratio, + near_plane_distance, + ) + } + Projection::Orthographic { + camera_mode, + vertical_world_size, + far_plane_distance, + } => { + let aspect_ratio = resolution_in_pixel[0] as f32 / resolution_in_pixel[1] as f32; + let horizontal_world_size = vertical_world_size * aspect_ratio; + + // Note that we inverse z (by swapping near and far plane) to be consistent with our perspective projection. + match camera_mode { + OrthographicCameraMode::NearPlaneCenter => glam::Mat4::orthographic_rh( + -0.5 * horizontal_world_size, + 0.5 * horizontal_world_size, + -0.5 * vertical_world_size, + 0.5 * vertical_world_size, + far_plane_distance, + 0.0, + ), + OrthographicCameraMode::TopLeftCornerAndExtendZ => glam::Mat4::orthographic_rh( + 0.0, + horizontal_world_size, + vertical_world_size, + 0.0, + far_plane_distance, + -far_plane_distance, + ), + } + } + } + } + + fn tan_half_fov(&self) -> glam::Vec2 { + match self { + Projection::Perspective { + vertical_fov, + aspect_ratio, + .. + } => { + // Calculate ratio between screen size and screen distance. + // Great for getting directions from normalized device coordinates. + // (btw. this is the same as [1.0 / projection_from_view[0].x, 1.0 / projection_from_view[1].y]) + glam::vec2( + (vertical_fov * 0.5).tan() * aspect_ratio, + (vertical_fov * 0.5).tan(), + ) + } + Projection::Orthographic { .. } => glam::vec2(f32::MAX, f32::MAX), // Can't use infinity in shaders + } + } +} + /// How [`Size::AUTO`] is interpreted. #[derive(Clone, Copy, Debug, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] @@ -176,7 +244,7 @@ pub struct TargetConfiguration { /// I.e. the UI zoom factor. /// Note that this does not affect any of the camera & projection properties and is only used /// whenever point sizes were explicitly specified. - pub pixels_from_point: f32, + pub pixels_per_point: f32, /// How [`Size::AUTO`] is interpreted. pub auto_size_config: AutoSizeConfig, @@ -196,7 +264,7 @@ impl Default for TargetConfiguration { aspect_ratio: 1.0, }, viewport_transformation: RectTransform::IDENTITY, - pixels_from_point: 1.0, + pixels_per_point: 1.0, auto_size_config: Default::default(), outline_config: None, } @@ -314,89 +382,33 @@ impl ViewBuilder { }, ); - let (projection_from_view, tan_half_fov, pixel_world_size_from_camera_distance) = - match config.projection_from_view.clone() { - Projection::Perspective { - vertical_fov, - near_plane_distance, - aspect_ratio, - } => { - // We use infinite reverse-z projection matrix - // * great precision both with floating point and integer: https://developer.nvidia.com/content/depth-precision-visualized - // * no need to worry about far plane - let projection_from_view = glam::Mat4::perspective_infinite_reverse_rh( - vertical_fov, - aspect_ratio, - near_plane_distance, - ); - - // Calculate ratio between screen size and screen distance. - // Great for getting directions from normalized device coordinates. - // (btw. this is the same as [1.0 / projection_from_view[0].x, 1.0 / projection_from_view[1].y]) - let tan_half_fov = glam::vec2( - (vertical_fov * 0.5).tan() * aspect_ratio, - (vertical_fov * 0.5).tan(), - ); - - // Determine how wide a pixel is in world space at unit distance from the camera. - // - // derivation: - // tan(FOV / 2) = (screen_in_world / 2) / distance - // screen_in_world = tan(FOV / 2) * distance * 2 - // - // want: pixels in world per distance, i.e (screen_in_world / resolution / distance) - // => (resolution / screen_in_world / distance) = tan(FOV / 2) * distance * 2 / resolution / distance = - // = tan(FOV / 2) * 2.0 / resolution - let pixel_world_size_from_camera_distance = - tan_half_fov.y * 2.0 / config.resolution_in_pixel[1] as f32; - - ( - projection_from_view, - tan_half_fov, - pixel_world_size_from_camera_distance, - ) - } - Projection::Orthographic { - camera_mode, - vertical_world_size, - far_plane_distance, - } => { - let aspect_ratio = - config.resolution_in_pixel[0] as f32 / config.resolution_in_pixel[1] as f32; - let horizontal_world_size = vertical_world_size * aspect_ratio; - // Note that we inverse z (by swapping near and far plane) to be consistent with our perspective projection. - let projection_from_view = match camera_mode { - OrthographicCameraMode::NearPlaneCenter => glam::Mat4::orthographic_rh( - -0.5 * horizontal_world_size, - 0.5 * horizontal_world_size, - -0.5 * vertical_world_size, - 0.5 * vertical_world_size, - far_plane_distance, - 0.0, - ), - OrthographicCameraMode::TopLeftCornerAndExtendZ => { - glam::Mat4::orthographic_rh( - 0.0, - horizontal_world_size, - vertical_world_size, - 0.0, - far_plane_distance, - -far_plane_distance, - ) - } - }; - - let tan_half_fov = glam::vec2(f32::MAX, f32::MAX); - let pixel_world_size_from_camera_distance = vertical_world_size - / config.resolution_in_pixel[0].max(config.resolution_in_pixel[1]) as f32; - - ( - projection_from_view, - tan_half_fov, - pixel_world_size_from_camera_distance, - ) - } - }; + let projection_from_view = config + .projection_from_view + .projection_from_view(config.resolution_in_pixel); + + let tan_half_fov = config.projection_from_view.tan_half_fov(); + + let pixel_world_size_from_camera_distance = match config.projection_from_view { + Projection::Perspective { .. } => { + // Determine how wide a pixel is in world space at unit distance from the camera. + // + // derivation: + // tan(FOV / 2) = (screen_in_world / 2) / distance + // screen_in_world = tan(FOV / 2) * distance * 2 + // + // want: pixels in world per distance, i.e (screen_in_world / resolution / distance) + // => (resolution / screen_in_world / distance) = tan(FOV / 2) * distance * 2 / resolution / distance = + // = tan(FOV / 2) * 2.0 / resolution + tan_half_fov.y * 2.0 / config.resolution_in_pixel[1] as f32 + } + Projection::Orthographic { + vertical_world_size, + .. + } => { + vertical_world_size + / config.resolution_in_pixel[0].max(config.resolution_in_pixel[1]) as f32 + } + }; // Finally, apply a viewport transformation to the projection. let ndc_scale_and_translation = config @@ -443,7 +455,7 @@ impl ViewBuilder { camera_forward, tan_half_fov: tan_half_fov.into(), pixel_world_size_from_camera_distance, - pixels_from_point: config.pixels_from_point, + pixels_per_point: config.pixels_per_point, auto_size_points: auto_size_points.0, auto_size_lines: auto_size_lines.0, diff --git a/crates/re_renderer_examples/2d.rs b/crates/re_renderer_examples/2d.rs index a1753b4953cd..1000e0e4c8c0 100644 --- a/crates/re_renderer_examples/2d.rs +++ b/crates/re_renderer_examples/2d.rs @@ -60,7 +60,7 @@ impl framework::Example for Render2D { re_ctx: &re_renderer::RenderContext, resolution: [u32; 2], time: &framework::Time, - pixels_from_point: f32, + pixels_per_point: f32, ) -> Vec { let splits = framework::split_resolution(resolution, 1, 2).collect::>(); @@ -302,7 +302,7 @@ impl framework::Example for Render2D { vertical_world_size: splits[0].resolution_in_pixel[1] as f32, far_plane_distance: 1000.0, }, - pixels_from_point, + pixels_per_point, ..Default::default() }, ); @@ -344,7 +344,7 @@ impl framework::Example for Render2D { near_plane_distance: 0.01, aspect_ratio: resolution[0] as f32 / resolution[1] as f32, }, - pixels_from_point, + pixels_per_point, ..Default::default() }, ); diff --git a/crates/re_renderer_examples/depth_cloud.rs b/crates/re_renderer_examples/depth_cloud.rs index da160f24b8d1..e6f457654750 100644 --- a/crates/re_renderer_examples/depth_cloud.rs +++ b/crates/re_renderer_examples/depth_cloud.rs @@ -61,7 +61,7 @@ impl RenderDepthClouds { fn draw_backprojected_point_cloud( &mut self, re_ctx: &re_renderer::RenderContext, - pixels_from_point: f32, + pixels_per_point: f32, resolution_in_pixel: [u32; 2], target_location: glam::Vec2, frame_draw_data: FD, @@ -122,7 +122,7 @@ impl RenderDepthClouds { near_plane_distance: 0.01, aspect_ratio: resolution_in_pixel[0] as f32 / resolution_in_pixel[1] as f32, }, - pixels_from_point, + pixels_per_point, ..Default::default() }, ); @@ -146,7 +146,7 @@ impl RenderDepthClouds { fn draw_depth_cloud( &mut self, re_ctx: &re_renderer::RenderContext, - pixels_from_point: f32, + pixels_per_point: f32, resolution_in_pixel: [u32; 2], target_location: glam::Vec2, frame_draw_data: FD, @@ -202,7 +202,7 @@ impl RenderDepthClouds { near_plane_distance: 0.01, aspect_ratio: resolution_in_pixel[0] as f32 / resolution_in_pixel[1] as f32, }, - pixels_from_point, + pixels_per_point, ..Default::default() }, ); @@ -265,7 +265,7 @@ impl framework::Example for RenderDepthClouds { re_ctx: &re_renderer::RenderContext, resolution: [u32; 2], time: &framework::Time, - pixels_from_point: f32, + pixels_per_point: f32, ) -> Vec { let Self { albedo, @@ -329,7 +329,7 @@ impl framework::Example for RenderDepthClouds { vec![ self.draw_backprojected_point_cloud( re_ctx, - pixels_from_point, + pixels_per_point, splits[0].resolution_in_pixel, splits[0].target_location, frame_draw_data.clone(), @@ -337,7 +337,7 @@ impl framework::Example for RenderDepthClouds { ), self.draw_depth_cloud( re_ctx, - pixels_from_point, + pixels_per_point, splits[1].resolution_in_pixel, splits[1].target_location, frame_draw_data, diff --git a/crates/re_renderer_examples/depth_offset.rs b/crates/re_renderer_examples/depth_offset.rs index baba155ba81e..c2b1bc2724f8 100644 --- a/crates/re_renderer_examples/depth_offset.rs +++ b/crates/re_renderer_examples/depth_offset.rs @@ -38,7 +38,7 @@ impl framework::Example for Render2D { re_ctx: &re_renderer::RenderContext, resolution: [u32; 2], _time: &framework::Time, - pixels_from_point: f32, + pixels_per_point: f32, ) -> Vec { let mut rectangles = Vec::new(); @@ -110,7 +110,7 @@ impl framework::Example for Render2D { near_plane_distance: self.near_plane, aspect_ratio: resolution[0] as f32 / resolution[1] as f32, }, - pixels_from_point, + pixels_per_point, ..Default::default() }, ); diff --git a/crates/re_renderer_examples/framework.rs b/crates/re_renderer_examples/framework.rs index d0adf85cee80..2ad4fff1d1a0 100644 --- a/crates/re_renderer_examples/framework.rs +++ b/crates/re_renderer_examples/framework.rs @@ -33,7 +33,7 @@ pub trait Example { re_ctx: &RenderContext, resolution: [u32; 2], time: &Time, - pixels_from_point: f32, + pixels_per_point: f32, ) -> Vec; fn on_key_event(&mut self, _event: winit::event::KeyEvent) {} diff --git a/crates/re_renderer_examples/multiview.rs b/crates/re_renderer_examples/multiview.rs index f6d14dd07e09..6ced4e600a97 100644 --- a/crates/re_renderer_examples/multiview.rs +++ b/crates/re_renderer_examples/multiview.rs @@ -306,7 +306,7 @@ impl Example for Multiview { re_ctx: &RenderContext, resolution: [u32; 2], time: &framework::Time, - pixels_from_point: f32, + pixels_per_point: f32, ) -> Vec { if matches!(self.camera_control, CameraControl::RotateAroundCenter) { let seconds_since_startup = time.seconds_since_startup(); @@ -373,7 +373,7 @@ impl Example for Multiview { resolution_in_pixel: splits[$n].resolution_in_pixel, view_from_world, projection_from_view: projection_from_view.clone(), - pixels_from_point, + pixels_per_point, ..Default::default() }, skybox.clone(), diff --git a/crates/re_renderer_examples/outlines.rs b/crates/re_renderer_examples/outlines.rs index 37a606ea7b16..b7736d5c0695 100644 --- a/crates/re_renderer_examples/outlines.rs +++ b/crates/re_renderer_examples/outlines.rs @@ -40,7 +40,7 @@ impl framework::Example for Outlines { re_ctx: &re_renderer::RenderContext, resolution: [u32; 2], time: &framework::Time, - pixels_from_point: f32, + pixels_per_point: f32, ) -> Vec { if !self.is_paused { self.seconds_since_startup += time.last_frame_duration.as_secs_f32(); @@ -65,7 +65,7 @@ impl framework::Example for Outlines { near_plane_distance: 0.01, aspect_ratio: resolution[0] as f32 / resolution[1] as f32, }, - pixels_from_point, + pixels_per_point, outline_config: Some(OutlineConfig { outline_radius_pixel: (seconds_since_startup * 2.0).sin().abs() * 10.0 + 2.0, color_layer_a: re_renderer::Rgba::from_rgb(1.0, 0.6, 0.0), diff --git a/crates/re_renderer_examples/picking.rs b/crates/re_renderer_examples/picking.rs index 2d23745264b1..0f8868c4e9cd 100644 --- a/crates/re_renderer_examples/picking.rs +++ b/crates/re_renderer_examples/picking.rs @@ -98,7 +98,7 @@ impl framework::Example for Picking { re_ctx: &re_renderer::RenderContext, resolution: [u32; 2], _time: &framework::Time, - pixels_from_point: f32, + pixels_per_point: f32, ) -> Vec { while let Some(picking_result) = PickingLayerProcessor::next_readback_result::<()>(re_ctx, READBACK_IDENTIFIER) @@ -136,7 +136,7 @@ impl framework::Example for Picking { near_plane_distance: 0.01, aspect_ratio: resolution[0] as f32 / resolution[1] as f32, }, - pixels_from_point, + pixels_per_point, outline_config: None, ..Default::default() }, diff --git a/crates/re_space_view_spatial/src/picking.rs b/crates/re_space_view_spatial/src/picking.rs index 42732f0fd342..a3bc508b6c93 100644 --- a/crates/re_space_view_spatial/src/picking.rs +++ b/crates/re_space_view_spatial/src/picking.rs @@ -86,12 +86,12 @@ impl PickingContext { pointer_in_ui: egui::Pos2, space2d_from_ui: egui::emath::RectTransform, ui_clip_rect: egui::Rect, - pixels_from_points: f32, + pixels_per_point: f32, eye: &Eye, ) -> PickingContext { let pointer_in_space2d = space2d_from_ui.transform_pos(pointer_in_ui); let pointer_in_space2d = glam::vec2(pointer_in_space2d.x, pointer_in_space2d.y); - let pointer_in_pixel = (pointer_in_ui - ui_clip_rect.left_top()) * pixels_from_points; + let pointer_in_pixel = (pointer_in_ui - ui_clip_rect.left_top()) * pixels_per_point; PickingContext { pointer_in_space2d, diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index b2f3e1b841d4..431c92ad05ed 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -2,6 +2,7 @@ use ahash::HashSet; use nohash_hasher::{IntMap, IntSet}; use re_entity_db::{EntityDb, EntityProperties, EntityTree}; +use re_format::format_f32; use re_log_types::EntityPath; use re_types::{ archetypes::{DepthImage, Image}, @@ -248,7 +249,23 @@ impl SpaceViewClass for SpatialSpaceView2D { .show(ui, |ui| { state.default_size_ui(ctx, ui); state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::TwoD); - ui.end_row(); + + { + let visual_bounds = &mut state.state_2d.visual_bounds; + ctx.re_ui + .grid_left_hand_label(ui, "Bounds") + .on_hover_text("The area guaranteed to be visible.\nDepending on the view's current aspect ratio the actually visible area might be larger either horizontally or vertically."); + ui.vertical(|ui| { + ui.style_mut().wrap = Some(false); + let (min, max) = (visual_bounds.min, visual_bounds.max); + ui.label(format!("x [{} - {}]", format_f32(min.x), format_f32(max.x),)); + ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); + if ui.button("Reset bounds").clicked() { + *visual_bounds = egui::Rect::NAN; + } + }); + ui.end_row(); + } }); Ok(()) } diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 53e822295b99..674efd5f880e 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -105,6 +105,7 @@ impl SpatialSpaceViewState { ui.label(format!("z [{} - {}]", format_f32(min.z), format_f32(max.z),)); } }); + ui.end_row(); } pub fn default_size_ui(&mut self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { @@ -247,7 +248,7 @@ fn size_ui( pub fn create_labels( mut labels: Vec, - ui_from_canvas: egui::emath::RectTransform, + ui_from_scene: egui::emath::RectTransform, eye3d: &Eye, parent_ui: &egui::Ui, highlights: &SpaceViewHighlights, @@ -255,7 +256,7 @@ pub fn create_labels( ) -> (Vec, Vec) { re_tracing::profile_function!(); - let ui_from_world_3d = eye3d.ui_from_world(*ui_from_canvas.to()); + let ui_from_world_3d = eye3d.ui_from_world(*ui_from_scene.to()); // Closest last (painters algorithm) labels.sort_by_key(|label| { @@ -276,7 +277,7 @@ pub fn create_labels( if spatial_kind == SpatialSpaceViewKind::ThreeD { continue; } - let rect_in_ui = ui_from_canvas.transform_rect(rect); + let rect_in_ui = ui_from_scene.transform_rect(rect); ( // Place the text centered below the rect (rect_in_ui.width() - 4.0).at_least(60.0), @@ -288,7 +289,7 @@ pub fn create_labels( if spatial_kind == SpatialSpaceViewKind::ThreeD { continue; } - let pos_in_ui = ui_from_canvas.transform_pos(pos); + let pos_in_ui = ui_from_scene.transform_pos(pos); (f32::INFINITY, pos_in_ui + egui::vec2(0.0, 3.0)) } UiLabelTarget::Position3D(pos) => { @@ -352,7 +353,7 @@ pub fn create_labels( )); ui_rects.push(PickableUiRect { - rect: ui_from_canvas.inverse().transform_rect(bg_rect), + rect: ui_from_scene.inverse().transform_rect(bg_rect), instance_hash: label.labeled_instance, }); } diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index 6d3ca26bae21..9745a7462e38 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -1,7 +1,4 @@ -use egui::{ - emath::RectTransform, pos2, vec2, Align2, Color32, NumExt as _, Pos2, Rect, ScrollArea, Shape, - Vec2, -}; +use egui::{emath::RectTransform, pos2, vec2, Align2, Color32, Pos2, Rect, Shape, Vec2}; use macaw::IsoTransform; use re_entity_db::EntityPath; @@ -26,186 +23,127 @@ use crate::{ // --- -#[derive(Clone, Default, PartialEq, serde::Deserialize, serde::Serialize)] +#[derive(Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)] #[serde(default)] pub struct View2DState { - /// The zoom and pan state, which is either a zoom/center or `Auto` which will fill the screen - zoom: ZoomState2D, -} - -#[derive(Clone, Copy, Default, PartialEq, serde::Deserialize, serde::Serialize)] -/// Sub-state specific to the Zoom/Scale/Pan engine -pub enum ZoomState2D { - #[default] - Auto, - - Scaled { - /// Number of ui points per scene unit - scale: f32, - - /// Which scene coordinate will be at the center of the zoomed region. - center: Pos2, - - /// Whether to allow the state to be updated by the current `ScrollArea` offsets - accepting_scroll: bool, - }, + /// The visible parts of the scene, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Some thing outside of these bounds may also be visible due to letterboxing. + /// + /// Default: [`Rect::NAN`] (invalid). + /// Invalid bound will be set to the default on the next frame. + /// The default is usually the scene bounding box. + pub visual_bounds: Rect, } -impl View2DState { - /// Determine the optimal sub-region and size based on the `ZoomState` and - /// available size. This will generally be used to construct the painter and - /// subsequent transforms - /// - /// Returns `(desired_size, scroll_offset)` where: - /// - `desired_size` is the size of the painter necessary to capture the zoomed view in ui points - /// - `scroll_offset` is the position of the `ScrollArea` offset in ui points - fn desired_size_and_offset(&self, available_size: Vec2, canvas_rect: Rect) -> (Vec2, Vec2) { - match self.zoom { - ZoomState2D::Scaled { scale, center, .. } => { - let desired_size = canvas_rect.size() * scale; - - // Try to keep the center of the scene in the middle of the available size - let scroll_offset = (center.to_vec2() - canvas_rect.left_top().to_vec2()) * scale - - available_size / 2.0; - - (desired_size, scroll_offset) - } - ZoomState2D::Auto => { - // Otherwise, we autoscale the space to fit available area while maintaining aspect ratio - let scene_bbox = if canvas_rect.is_positive() { - canvas_rect - } else { - Rect::from_min_max(Pos2::ZERO, Pos2::new(1.0, 1.0)) - }; - let mut desired_size = scene_bbox.size(); - desired_size *= available_size.x / desired_size.x; // fill full width - desired_size *= (available_size.y / desired_size.y).at_most(1.0); // shrink so we don't fill more than full height - - if desired_size.is_finite() { - (desired_size, Vec2::ZERO) - } else { - (available_size, Vec2::ZERO) - } - } +impl Default for View2DState { + fn default() -> Self { + Self { + visual_bounds: Rect::NAN, } } +} - /// Update our zoom state based on response - /// If nothing else happens this will reset `accepting_scroll` to true when appropriate - fn update( +impl View2DState { + /// Pan and zoom, and return the current transform. + fn ui_from_scene( &mut self, response: &egui::Response, - ui_to_space: egui::emath::RectTransform, - canvas_rect: Rect, - available_size: Vec2, - ) { - // Determine if we are zooming - let zoom_delta = response.ctx.input(|i| i.zoom_delta()); - let hovered_zoom = if response.hovered() && zoom_delta != 1.0 { - Some(zoom_delta) - } else { - None - }; + default_scene_rect: Rect, + ) -> RectTransform { + fn valid_bound(rect: &Rect) -> bool { + rect.is_finite() && rect.is_positive() + } - match self.zoom { - ZoomState2D::Auto => { - if let Some(input_zoom) = hovered_zoom { - if input_zoom > 1.0 { - let scale = response.rect.height() / ui_to_space.to().height(); - let center = canvas_rect.center(); - self.zoom = ZoomState2D::Scaled { - scale, - center, - accepting_scroll: false, - }; - // Recursively update now that we have initialized `ZoomState` to `Scaled` - self.update(response, ui_to_space, canvas_rect, available_size); - } - } - } - ZoomState2D::Scaled { - mut scale, - mut center, - .. - } => { - let mut accepting_scroll = true; - - // If we are zooming, adjust the scale and center - if let Some(input_zoom) = hovered_zoom { - let new_scale = scale * input_zoom; - - // Adjust for mouse location while executing zoom - if let Some(hover_pos) = response.ctx.input(|i| i.pointer.hover_pos()) { - let zoom_loc = ui_to_space.transform_pos(hover_pos); - - // Space-units under the cursor will shift based on distance from center - let dist_from_center = zoom_loc - center; - // In UI points this happens based on the difference in scale; - let shift_in_ui = dist_from_center * (new_scale - scale); - // But we will compensate for it by a shift in space units - let shift_in_space = shift_in_ui / new_scale; - - // Moving the center in the direction of the desired shift - center += shift_in_space; - } - // Don't show less than one horizontal scene unit in the entire screen. - scale = new_scale.at_most(available_size.x); - accepting_scroll = false; - } + if response.double_clicked() { + self.visual_bounds = default_scene_rect; // double-click to reset + } - // If we are dragging, adjust the center accordingly - if response.dragged_by(DRAG_PAN2D_BUTTON) { - // Adjust center based on drag - center -= response.drag_delta() / scale; - accepting_scroll = false; - } + let bounds = &mut self.visual_bounds; + if !valid_bound(bounds) { + *bounds = default_scene_rect; + } + if !valid_bound(bounds) { + // Nothing in scene, probably. + // Just return something that isn't NaN. + let fake_bounds = Rect::from_min_size(Pos2::ZERO, Vec2::splat(1.0)); + return RectTransform::from_to(fake_bounds, response.rect); + } - // Save the zoom state - self.zoom = ZoomState2D::Scaled { - scale, - center, - accepting_scroll, - }; - } + // -------------------------------------------------------------------------- + // Expand bounds for uniform scaling (letterboxing): + + let mut letterboxed_bounds = *bounds; + + // Temporary before applying letterboxing: + let ui_from_scene = RectTransform::from_to(*bounds, response.rect); + + let scale_aspect = ui_from_scene.scale().x / ui_from_scene.scale().y; + if scale_aspect < 1.0 { + // Letterbox top/bottom: + let add = bounds.height() * (1.0 / scale_aspect - 1.0); + letterboxed_bounds.min.y -= 0.5 * add; + letterboxed_bounds.max.y += 0.5 * add; + } else { + // Letterbox sides: + let add = bounds.width() * (scale_aspect - 1.0); + letterboxed_bounds.min.x -= 0.5 * add; + letterboxed_bounds.max.x += 0.5 * add; } - // Process things that might reset ZoomState to Auto - if let ZoomState2D::Scaled { scale, .. } = self.zoom { - // If the user double-clicks - if response.double_clicked() { - self.zoom = ZoomState2D::Auto; - } + // -------------------------------------------------------------------------- - // If our zoomed region is smaller than the available size - if canvas_rect.size().x * scale < available_size.x - && canvas_rect.size().y * scale < available_size.y - { - self.zoom = ZoomState2D::Auto; - } + // Temporary before applying panning/zooming delta: + let ui_from_scene = RectTransform::from_to(letterboxed_bounds, response.rect); + + // -------------------------------------------------------------------------- + + let mut pan_delta_in_ui = response.drag_delta(); + if response.hovered() { + // NOTE: we use `raw_scroll` instead of `smooth_scroll_delta` to avoid the + // added latency of smoothing, which is really annoying on Mac trackpads. + // The smoothing is only useful for users with discreet scroll wheels, + // and they are likely to pan with dragging instead. + // TODO(egui#4401): https://github.com/emilk/egui/issues/4401 + pan_delta_in_ui += response.ctx.input(|i| i.raw_scroll_delta); + } + if pan_delta_in_ui != Vec2::ZERO { + *bounds = bounds.translate(-pan_delta_in_ui / ui_from_scene.scale()); } - } - /// Take the offset from the `ScrollArea` and apply it back to center so that other - /// scroll interfaces work as expected. - fn capture_scroll(&mut self, offset: Vec2, available_size: Vec2, canvas_rect: Rect) { - if let ZoomState2D::Scaled { - scale, - accepting_scroll, - .. - } = self.zoom - { - if accepting_scroll { - let center = canvas_rect.left_top() + (available_size / 2.0 + offset) / scale; - self.zoom = ZoomState2D::Scaled { - scale, - center, - accepting_scroll, - }; + if response.hovered() { + let zoom_delta = response.ctx.input(|i| i.zoom_delta_2d()); + + if zoom_delta != Vec2::splat(1.0) { + let zoom_center_in_ui = response + .hover_pos() + .unwrap_or_else(|| response.rect.center()); + let zoom_center_in_scene = ui_from_scene + .inverse() + .transform_pos(zoom_center_in_ui) + .to_vec2(); + *bounds = scale_rect( + bounds.translate(-zoom_center_in_scene), + Vec2::splat(1.0) / zoom_delta, + ) + .translate(zoom_center_in_scene); } } + + // -------------------------------------------------------------------------- + + RectTransform::from_to(letterboxed_bounds, response.rect) } } +fn scale_rect(rect: Rect, factor: Vec2) -> Rect { + Rect::from_min_max( + (factor * rect.min.to_vec2()).to_pos2(), + (factor * rect.max.to_vec2()).to_pos2(), + ) +} + pub fn help_text(re_ui: &re_ui::ReUi) -> egui::WidgetText { let mut layout = re_ui::LayoutJobBuilder::new(re_ui); @@ -222,6 +160,14 @@ pub fn help_text(re_ui: &re_ui::ReUi) -> egui::WidgetText { layout.layout_job.into() } +/// The pinhole sensor rectangle: [0, 0] - [width, height], +/// ignoring principal point. +fn pinhole_resolution_rect(pinhole: &Pinhole) -> Option { + pinhole + .resolution() + .map(|res| Rect::from_min_max(Pos2::ZERO, pos2(res.x, res.y))) +} + /// Create the outer 2D view, which consists of a scrollable region pub fn view_2d( ctx: &ViewerContext<'_>, @@ -238,177 +184,138 @@ pub fn view_2d( draw_data, } = system_output; - // Save off the available_size since this is used for some of the layout updates later - let available_size = ui.available_size(); + if ui.available_size().min_elem() <= 0.0 { + return Ok(()); + } - let scene_rect_accum = state.bounding_boxes.accumulated; - let scene_rect_accum = egui::Rect::from_min_max( - scene_rect_accum.min.truncate().to_array().into(), - scene_rect_accum.max.truncate().to_array().into(), - ); + // TODO(emilk): some way to visualize the resolution rectangle of the pinhole camera (in case there is no image logged). - // Determine the canvas which determines the extent of the explorable scene coordinates, - // and thus the size of the scroll area. - // - // TODO(andreas): We want to move away from the scroll area and instead work with open ended 2D scene coordinates! - // The term canvas might then refer to the area in scene coordinates visible at a given moment. - // Orthogonally, we'll want to visualize the resolution rectangle of the pinhole camera. - // - // For that we need to check if this is defined by a pinhole camera. // Note that we can't rely on the camera being part of scene.space_cameras since that requires // the camera to be added to the scene! let pinhole = query_pinhole(ctx.recording(), &ctx.current_query(), query.space_origin); - let canvas_rect = pinhole + + let default_scene_rect = pinhole .as_ref() - .and_then(|p| p.resolution()) - .map_or(scene_rect_accum, |res| { - Rect::from_min_max(egui::Pos2::ZERO, egui::pos2(res.x, res.y)) + .and_then(pinhole_resolution_rect) + .unwrap_or_else(|| { + // TODO(emilk): if there is a single image, use that as the default bounds + let scene_rect_accum = state.bounding_boxes.accumulated; + egui::Rect::from_min_max( + scene_rect_accum.min.truncate().to_array().into(), + scene_rect_accum.max.truncate().to_array().into(), + ) }); - let (desired_size, offset) = state - .state_2d - .desired_size_and_offset(available_size, canvas_rect); - - // Bound the offset based on sizes - // TODO(jleibs): can we derive this from the ScrollArea shape? - let offset = offset.at_most(desired_size - available_size); - let offset = offset.at_least(Vec2::ZERO); - - let scroll_area = ScrollArea::both() - .scroll_offset(offset) - .auto_shrink([false, false]); - - let scroll_out = scroll_area.show(ui, |ui| -> Result<(), SpaceViewSystemExecutionError> { - let desired_size = desired_size.at_least(Vec2::ZERO); - let (mut response, painter) = - ui.allocate_painter(desired_size, egui::Sense::click_and_drag()); - - if !response.rect.is_positive() { - return Ok(()); - } + let (mut response, painter) = + ui.allocate_painter(ui.available_size(), egui::Sense::click_and_drag()); - let ui_from_canvas = egui::emath::RectTransform::from_to(canvas_rect, response.rect); - let canvas_from_ui = ui_from_canvas.inverse(); + // Convert ui coordinates to/from scene coordinates. + let ui_from_scene = state.state_2d.ui_from_scene(&response, default_scene_rect); + let scene_from_ui = ui_from_scene.inverse(); - state - .state_2d - .update(&response, canvas_from_ui, canvas_rect, available_size); + // TODO(andreas): Use the same eye & transformations as in `setup_target_config`. + let eye = Eye { + world_from_rub_view: IsoTransform::IDENTITY, + fov_y: None, + }; - // TODO(andreas): Use the same eye & transformations as in `setup_target_config`. - let eye = Eye { - world_from_rub_view: IsoTransform::IDENTITY, - fov_y: None, - }; + let scene_bounds = *scene_from_ui.to(); + let Ok(target_config) = setup_target_config( + &painter, + scene_bounds, + &query.space_origin.to_string(), + state.auto_size_config(), + query.highlights.any_outlines(), + pinhole, + ) else { + return Ok(()); + }; - let Ok(target_config) = setup_target_config( - &painter, - canvas_from_ui, - &query.space_origin.to_string(), - state.auto_size_config(), - query.highlights.any_outlines(), - pinhole, - ) else { - return Ok(()); - }; + let mut view_builder = ViewBuilder::new(ctx.render_ctx, target_config); - let mut view_builder = ViewBuilder::new(ctx.render_ctx, target_config); + // Create labels now since their shapes participate are added to scene.ui for picking. + let (label_shapes, ui_rects) = create_labels( + collect_ui_labels(&parts), + ui_from_scene, + &eye, + ui, + &query.highlights, + SpatialSpaceViewKind::TwoD, + ); - // Create labels now since their shapes participate are added to scene.ui for picking. - let (label_shapes, ui_rects) = create_labels( - collect_ui_labels(&parts), - ui_from_canvas, - &eye, + if ui.ctx().dragged_id().is_none() { + response = picking( + ctx, + response, + scene_from_ui, + painter.clip_rect(), ui, - &query.highlights, + eye, + &mut view_builder, + state, + &view_ctx, + &parts, + &ui_rects, + query, SpatialSpaceViewKind::TwoD, - ); - - if ui.ctx().dragged_id().is_none() { - response = picking( - ctx, - response, - canvas_from_ui, - painter.clip_rect(), - ui, - eye, - &mut view_builder, - state, - &view_ctx, - &parts, - &ui_rects, - query, - SpatialSpaceViewKind::TwoD, - )?; - } + )?; + } - for draw_data in draw_data { - view_builder.queue_draw(draw_data); - } + for draw_data in draw_data { + view_builder.queue_draw(draw_data); + } - // ------------------------------------------------------------------------ + // ------------------------------------------------------------------------ - // Screenshot context menu. - if let Some(mode) = screenshot_context_menu(ctx, &response) { - view_builder - .schedule_screenshot(ctx.render_ctx, query.space_view_id.gpu_readback_id(), mode) - .ok(); - } + if let Some(mode) = screenshot_context_menu(ctx, &response) { + view_builder + .schedule_screenshot(ctx.render_ctx, query.space_view_id.gpu_readback_id(), mode) + .ok(); + } - // Draw a re_renderer driven view. - // Camera & projection are configured to ingest space coordinates directly. - painter.add(gpu_bridge::new_renderer_callback( - view_builder, - painter.clip_rect(), - ui.visuals().extreme_bg_color.into(), + // Draw a re_renderer driven view. + // Camera & projection are configured to ingest space coordinates directly. + painter.add(gpu_bridge::new_renderer_callback( + view_builder, + painter.clip_rect(), + ui.visuals().extreme_bg_color.into(), + )); + + // Make sure to _first_ draw the selected, and *then* the hovered context on top! + for selected_context in ctx.selection_state().selection_space_contexts() { + painter.extend(show_projections_from_3d_space( + ui, + query.space_origin, + &ui_from_scene, + selected_context, + ui.style().visuals.selection.bg_fill, )); + } + if let Some(hovered_context) = ctx.selection_state().hovered_space_context() { + painter.extend(show_projections_from_3d_space( + ui, + query.space_origin, + &ui_from_scene, + hovered_context, + egui::Color32::WHITE, + )); + } - // Make sure to _first_ draw the selected, and *then* the hovered context on top! - for selected_context in ctx.selection_state().selection_space_contexts() { - painter.extend(show_projections_from_3d_space( - ui, - query.space_origin, - &ui_from_canvas, - selected_context, - ui.style().visuals.selection.bg_fill, - )); - } - if let Some(hovered_context) = ctx.selection_state().hovered_space_context() { - painter.extend(show_projections_from_3d_space( - ui, - query.space_origin, - &ui_from_canvas, - hovered_context, - egui::Color32::WHITE, - )); - } - - // Add egui driven labels on top of re_renderer content. - painter.extend(label_shapes); - - Ok(()) - }); - scroll_out.inner?; + // Add egui driven labels on top of re_renderer content. + painter.extend(label_shapes); - // Update the scroll area based on the computed offset - // This handles cases of dragging/zooming the space - state - .state_2d - .capture_scroll(scroll_out.state.offset, available_size, scene_rect_accum); Ok(()) } fn setup_target_config( egui_painter: &egui::Painter, - canvas_from_ui: RectTransform, + scene_bounds: Rect, space_name: &str, auto_size_config: re_renderer::AutoSizeConfig, any_outlines: bool, - pinhole: Option, + scene_pinhole: Option, ) -> anyhow::Result { - let pixels_from_points = egui_painter.ctx().pixels_per_point(); - let resolution_in_pixel = - gpu_bridge::viewport_resolution_in_pixels(egui_painter.clip_rect(), pixels_from_points); - anyhow::ensure!(resolution_in_pixel[0] > 0 && resolution_in_pixel[1] > 0); + // ⚠️ When changing this code, make sure to run `tests/rust/test_pinhole_projection`. // TODO(#1025): // The camera setup is done in a way that works well with the way we inverse pinhole camera transformations right now. @@ -424,59 +331,83 @@ fn setup_target_config( // * a perspective camera *at the origin* for 3D rendering // Both share the same view-builder and the same viewport transformation but are independent otherwise. + // TODO(andreas): Support anamorphic pinhole cameras properly. + // For simplicity (and to reduce surprises!) we always render with a pinhole camera. // Make up a default pinhole camera if we don't have one placing it in a way to look at the entire space. - let canvas_size = glam::vec2(canvas_from_ui.to().width(), canvas_from_ui.to().height()); - let default_principal_point = canvas_from_ui.to().center(); - let default_principal_point = glam::vec2(default_principal_point.x, default_principal_point.y); - let pinhole = pinhole.unwrap_or_else(|| { - let focal_length_in_pixels = canvas_size.x; + let scene_bounds_size = glam::vec2(scene_bounds.width(), scene_bounds.height()); + + let pinhole; + let resolution; + + if let Some(scene_pinhole) = scene_pinhole { + // The user has a pinhole, and we may want to project 3D stuff into this 2D space, + // and we want to use that pinhole projection to do so. + pinhole = scene_pinhole; - Pinhole { + resolution = pinhole.resolution().unwrap_or_else(|| { + // This is weird - we have a projection with an unknown resolution. + // Let's just pick something plausible and hope for the best 😬. + re_log::warn_once!("Pinhole projection lacks resolution."); + glam::Vec2::splat(1000.0) + }); + } else { + // The user didn't pick a pinhole, but we still set up a 3D projection. + // So we just pick _any_ pinhole camera, but we pick a "plausible" one so that + // it is similar to real-life pinhole cameras, so that we get similar scales and precision. + let focal_length = 1000.0; // Whatever, but small values can cause precision issues, noticeable on rectangle corners. + let principal_point = glam::Vec2::splat(500.0); // Whatever + resolution = glam::Vec2::splat(1000.0); // Whatever + pinhole = Pinhole { image_from_camera: glam::Mat3::from_cols( - glam::vec3(focal_length_in_pixels, 0.0, 0.0), - glam::vec3(0.0, focal_length_in_pixels, 0.0), - default_principal_point.extend(1.0), + glam::vec3(focal_length, 0.0, 0.0), + glam::vec3(0.0, focal_length, 0.0), + principal_point.extend(1.0), ) .into(), - resolution: Some(canvas_size.into()), + resolution: Some([resolution.x, resolution.y].into()), camera_xyz: Some(ViewCoordinates::RDF), - } - }); + }; + } + let pinhole_rect = Rect::from_min_size(Pos2::ZERO, egui::vec2(resolution.x, resolution.y)); let projection_from_view = re_renderer::view_builder::Projection::Perspective { vertical_fov: pinhole.fov_y().unwrap_or(Eye::DEFAULT_FOV_Y), near_plane_distance: 0.1, aspect_ratio: pinhole .aspect_ratio() - .unwrap_or(canvas_size.x / canvas_size.y), + .unwrap_or(scene_bounds_size.x / scene_bounds_size.y), // only happens if the pinhole lacks resolution }; - // Put the camera at the position where it sees the entire image plane as defined - // by the pinhole camera. - // TODO(andreas): Support anamorphic pinhole cameras properly. let focal_length = pinhole.focal_length_in_pixels(); - let focal_length = 2.0 / (1.0 / focal_length.x() + 1.0 / focal_length.y()); // harmonic mean - let Some(view_from_world) = macaw::IsoTransform::look_at_rh( + let focal_length = 2.0 / (1.0 / focal_length.x() + 1.0 / focal_length.y()); // harmonic mean (lack of anamorphic support) + + // Position the camera looking straight at the principal point: + let view_from_world = macaw::IsoTransform::look_at_rh( pinhole.principal_point().extend(-focal_length), pinhole.principal_point().extend(0.0), -glam::Vec3::Y, - ) else { - anyhow::bail!("Failed to compute camera transform for 2D view."); - }; + ) + .ok_or_else(|| anyhow::format_err!("Failed to compute camera transform for 2D view."))?; - // Cut to the portion of the currently visible ui area. + // "pan-and-scan" to look at a particular part (scene_bounds) of the scene (pinhole_rect). let mut viewport_transformation = re_renderer::RectTransform { - region_of_interest: re_render_rect_from_egui_rect(egui_painter.clip_rect()), - region: re_render_rect_from_egui_rect(*canvas_from_ui.from()), + region: re_render_rect_from_egui_rect(pinhole_rect), + region_of_interest: re_render_rect_from_egui_rect(scene_bounds), }; - // The principal point might not be quite centered. - // We need to account for this translation in the viewport transformation. - let principal_point_offset = default_principal_point - pinhole.principal_point(); - let ui_from_canvas_scale = canvas_from_ui.inverse().scale(); - viewport_transformation.region_of_interest.min += - principal_point_offset * glam::vec2(ui_from_canvas_scale.x, ui_from_canvas_scale.y); + // We want to look at the center of the scene bounds, + // but we set up the camera to look at the principal point, + // so we need to translate the view camera to compensate for that: + let image_center = 0.5 * resolution; + viewport_transformation.region_of_interest.min += image_center - pinhole.principal_point(); + + // ---------------------- + + let pixels_per_point = egui_painter.ctx().pixels_per_point(); + let resolution_in_pixel = + gpu_bridge::viewport_resolution_in_pixels(egui_painter.clip_rect(), pixels_per_point); + anyhow::ensure!(0 < resolution_in_pixel[0] && 0 < resolution_in_pixel[1]); Ok({ let name = space_name.into(); @@ -486,7 +417,7 @@ fn setup_target_config( view_from_world, projection_from_view, viewport_transformation, - pixels_from_point: pixels_from_points, + pixels_per_point, auto_size_config, outline_config: any_outlines.then(|| outline_config(egui_painter.ctx())), } @@ -505,7 +436,7 @@ fn re_render_rect_from_egui_rect(rect: egui::Rect) -> re_renderer::RectF32 { fn show_projections_from_3d_space( ui: &egui::Ui, space: &EntityPath, - ui_from_canvas: &RectTransform, + ui_from_scene: &RectTransform, space_context: &ItemSpaceContext, color: egui::Color32, ) -> Vec { @@ -519,7 +450,7 @@ fn show_projections_from_3d_space( if space_2d == space { if let Some(pos_2d) = pos_2d { // User is hovering a 2D point inside a 3D view. - let pos_in_ui = ui_from_canvas.transform_pos(pos2(pos_2d.x, pos_2d.y)); + let pos_in_ui = ui_from_scene.transform_pos(pos2(pos_2d.x, pos_2d.y)); let radius = 4.0; shapes.push(Shape::circle_filled( pos_in_ui, diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 9affa4568b05..2ee61660dc75 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -511,7 +511,7 @@ pub fn view_3d( }, viewport_transformation: re_renderer::RectTransform::IDENTITY, - pixels_from_point: ui.ctx().pixels_per_point(), + pixels_per_point: ui.ctx().pixels_per_point(), auto_size_config: state.auto_size_config(), outline_config: query diff --git a/crates/re_types/src/archetypes/pinhole_ext.rs b/crates/re_types/src/archetypes/pinhole_ext.rs index e860bdb27716..385bd33f8c1e 100644 --- a/crates/re_types/src/archetypes/pinhole_ext.rs +++ b/crates/re_types/src/archetypes/pinhole_ext.rs @@ -37,6 +37,17 @@ impl Pinhole { Self::from_focal_length_and_resolution(focal_length, [aspect_ratio, 1.0]) } + /// Principal point of the pinhole camera, + /// i.e. the intersection of the optical axis and the image plane. + /// + /// [see definition of intrinsic matrix](https://en.wikipedia.org/wiki/Camera_resectioning#Intrinsic_parameters) + #[cfg(feature = "glam")] + #[inline] + pub fn with_principal_point(mut self, principal_point: impl Into) -> Self { + self.image_from_camera = self.image_from_camera.with_principal_point(principal_point); + self + } + /// Field of View on the Y axis, i.e. the angle between top and bottom (in radians). #[inline] pub fn fov_y(&self) -> Option { diff --git a/crates/re_types/src/components/pinhole_projection_ext.rs b/crates/re_types/src/components/pinhole_projection_ext.rs index 2154d5030b3b..9895acff5105 100644 --- a/crates/re_types/src/components/pinhole_projection_ext.rs +++ b/crates/re_types/src/components/pinhole_projection_ext.rs @@ -17,6 +17,20 @@ impl PinholeProjection { ]) } + /// Principal point of the pinhole camera, + /// i.e. the intersection of the optical axis and the image plane. + /// + /// [see definition of intrinsic matrix](https://en.wikipedia.org/wiki/Camera_resectioning#Intrinsic_parameters) + #[cfg(feature = "glam")] + #[inline] + pub fn with_principal_point(mut self, principal_point: impl Into) -> Self { + let pp = principal_point.into(); + let col = 2; + self.0.set(0, col, pp.x()); + self.0.set(1, col, pp.y()); + self + } + /// X & Y focal length in pixels. /// /// [see definition of intrinsic matrix](https://en.wikipedia.org/wiki/Camera_resectioning#Intrinsic_parameters) diff --git a/crates/re_types/src/datatypes/mat3x3_ext.rs b/crates/re_types/src/datatypes/mat3x3_ext.rs index b98899e13f47..dbc22211a002 100644 --- a/crates/re_types/src/datatypes/mat3x3_ext.rs +++ b/crates/re_types/src/datatypes/mat3x3_ext.rs @@ -24,6 +24,28 @@ impl Mat3x3 { _ => panic!("index out of bounds"), } } + + /// Get a specific element. + // NOTE: row-col is the normal index order for matrices in mathematics. + #[inline] + pub fn get(&self, row: usize, col: usize) -> f32 { + assert!( + row < 3 && col < 3, + "Mat3x3 index out of bounds (row: {row}, col: {col})" + ); + self.0[row + col * 3] + } + + /// Set a specific element. + // NOTE: row-col is the normal index order for matrices in mathematics. + #[inline] + pub fn set(&mut self, row: usize, col: usize, value: f32) { + assert!( + row < 3 && col < 3, + "Mat3x3 index out of bounds (row: {row}, col: {col})" + ); + self.0[row + col * 3] = value; + } } impl std::ops::Index for Mat3x3 @@ -32,6 +54,7 @@ where { type Output = Idx::Output; + /// Column-major order matrix coefficients. #[inline] fn index(&self, index: Idx) -> &Self::Output { &self.0[index] diff --git a/crates/re_viewer_context/src/gpu_bridge/mod.rs b/crates/re_viewer_context/src/gpu_bridge/mod.rs index 55adf3a1d9be..fd1072bcc545 100644 --- a/crates/re_viewer_context/src/gpu_bridge/mod.rs +++ b/crates/re_viewer_context/src/gpu_bridge/mod.rs @@ -86,9 +86,9 @@ pub fn tensor_decode_srgb_gamma_heuristic( // ---------------------------------------------------------------------------- -pub fn viewport_resolution_in_pixels(clip_rect: egui::Rect, pixels_from_point: f32) -> [u32; 2] { - let min = (clip_rect.min.to_vec2() * pixels_from_point).round(); - let max = (clip_rect.max.to_vec2() * pixels_from_point).round(); +pub fn viewport_resolution_in_pixels(clip_rect: egui::Rect, pixels_per_point: f32) -> [u32; 2] { + let min = (clip_rect.min.to_vec2() * pixels_per_point).round(); + let max = (clip_rect.max.to_vec2() * pixels_per_point).round(); let resolution = max - min; [resolution.x as u32, resolution.y as u32] } @@ -160,14 +160,14 @@ pub fn render_image( // ------------------------------------------------------------------------ - let pixels_from_points = egui_painter.ctx().pixels_per_point(); + let pixels_per_point = egui_painter.ctx().pixels_per_point(); let ui_from_space = egui::emath::RectTransform::from_to(space_rect, image_rect_on_screen); let space_from_ui = ui_from_space.inverse(); let space_from_points = space_from_ui.scale().y; let points_from_pixels = 1.0 / egui_painter.ctx().pixels_per_point(); let space_from_pixel = space_from_points * points_from_pixels; - let resolution_in_pixel = viewport_resolution_in_pixels(viewport, pixels_from_points); + let resolution_in_pixel = viewport_resolution_in_pixels(viewport, pixels_per_point); anyhow::ensure!(resolution_in_pixel[0] > 0 && resolution_in_pixel[1] > 0); let camera_position_space = space_from_ui.transform_pos(viewport.min); @@ -184,7 +184,7 @@ pub fn render_image( far_plane_distance: 1000.0, }, viewport_transformation: re_renderer::RectTransform::IDENTITY, - pixels_from_point: pixels_from_points, + pixels_per_point, auto_size_config: Default::default(), outline_config: None, }; diff --git a/examples/python/rgbd/rgbd.py b/examples/python/rgbd/rgbd.py index 0c575f3a0569..b3a289f3729b 100755 --- a/examples/python/rgbd/rgbd.py +++ b/examples/python/rgbd/rgbd.py @@ -98,6 +98,8 @@ def log_nyud_data(recording_path: Path, subset_idx: int, frames: int) -> None: rr.Pinhole( resolution=[img_depth.shape[1], img_depth.shape[0]], focal_length=0.7 * img_depth.shape[1], + # Intentionally off-center to demonstrate that we support it + principal_point=[0.45 * img_depth.shape[1], 0.55 * img_depth.shape[0]], ), ) diff --git a/tests/rust/test_api/Cargo.toml b/tests/rust/test_api/Cargo.toml index 19f59a6fc63e..d3384b84eb6c 100644 --- a/tests/rust/test_api/Cargo.toml +++ b/tests/rust/test_api/Cargo.toml @@ -11,7 +11,7 @@ workspace = true [dependencies] re_log = { workspace = true, features = ["setup"] } -rerun = { path = "../../../crates/rerun", features = ["web_viewer"] } +rerun = { path = "../../../crates/rerun", features = ["clap", "web_viewer"] } anyhow.workspace = true clap = { workspace = true, features = ["derive"] } diff --git a/tests/rust/test_pinhole_projection/Cargo.toml b/tests/rust/test_pinhole_projection/Cargo.toml new file mode 100644 index 000000000000..b575f36ce4b9 --- /dev/null +++ b/tests/rust/test_pinhole_projection/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "test_pinhole_projection" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +publish = false + +[lints] +workspace = true + +[dependencies] +re_log = { workspace = true, features = ["setup"] } +rerun = { path = "../../../crates/rerun", features = ["clap"] } + +anyhow.workspace = true +clap = { workspace = true, features = ["derive"] } +image = { workspace = true, default-features = false } diff --git a/tests/rust/test_pinhole_projection/src/main.rs b/tests/rust/test_pinhole_projection/src/main.rs new file mode 100644 index 000000000000..0bca676f25d9 --- /dev/null +++ b/tests/rust/test_pinhole_projection/src/main.rs @@ -0,0 +1,83 @@ +//! Visual test for how we project 3D into 2D using Pinhole. +//! +//! ``` +//! cargo run -p test_pinhole_projection +//! ``` + +use rerun::{external::re_log, MediaType, RecordingStream}; + +#[derive(Debug, clap::Parser)] +#[clap(author, version, about)] +struct Args { + #[command(flatten)] + rerun: rerun::clap::RerunArgs, +} + +fn main() -> anyhow::Result<()> { + re_log::setup_logging(); + + use clap::Parser as _; + let args = Args::parse(); + + let (rec, _serve_guard) = args.rerun.init("rerun_example_test_pinhole_projection")?; + run(&rec) +} + +fn run(rec: &RecordingStream) -> anyhow::Result<()> { + const DESCRIPTION: &str = "\ + Add `/world/points` to the 2D image space (projected).\n\nn\ + The five points should project onto the corners and center of the image.\n\n\ + Only the top-right point should be undistorted (circular). + "; + rec.log_static( + "description", + &rerun::TextDocument::new(DESCRIPTION).with_media_type(MediaType::markdown()), + )?; + + rec.log_static("world", &rerun::ViewCoordinates::RIGHT_HAND_Y_DOWN)?; + + const W: u32 = 2000; + const H: u32 = 1000; + + let focal_length = [H as f32, H as f32]; + + rec.log( + "world/camera/image", + &rerun::Pinhole::from_focal_length_and_resolution(focal_length, [W as f32, H as f32]) + // We put the principal point in the unusual top-right corner + .with_principal_point([W as f32, 0.0]), + )?; + + let mut depth_image: image::ImageBuffer, Vec> = + image::ImageBuffer::new(W, H); + for y in 0..H { + for x in 0..W { + let depth = 2000; // TODO(emilk): we could parameterize this over x/y to make it more interesting. + depth_image.put_pixel(x, y, image::Luma([depth])); + } + } + + rec.log( + "world/camera/image/depth", + &rerun::DepthImage::try_from(depth_image)?.with_meter(1000.0), + )?; + + rec.log( + "world/camera/image/bottom_right", + &rerun::Points2D::new([[W as f32, H as f32]]), + )?; + + rec.log( + "world/points", + &rerun::Points3D::new([ + [0.0, 0.0, 1.0], + [-2.0, 0.0, 1.0], + [0.0, 1.0, 1.0], + [-2.0, 1.0, 1.0], + [-1.0, 0.5, 1.0], + ]) + .with_radii([0.05]), + )?; + + Ok(()) +} From fe11d0caaa16e0837ab8d1259d408f08969a77ce Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 25 Apr 2024 13:19:08 +0200 Subject: [PATCH 358/508] Add `TextDocument::from_markdown` constructor (#6109) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6109?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6109?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6109) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_types/src/archetypes/text_document.rs | 3 +-- crates/re_types/src/archetypes/text_document_ext.rs | 8 ++++++++ docs/snippets/all/text_document.rs | 3 +-- examples/rust/external_data_loader/src/main.rs | 4 ++-- examples/rust/incremental_logging/src/main.rs | 5 +---- tests/rust/roundtrips/text_document/src/main.rs | 11 +++-------- tests/rust/test_pinhole_projection/src/main.rs | 4 ++-- 7 files changed, 18 insertions(+), 20 deletions(-) diff --git a/crates/re_types/src/archetypes/text_document.rs b/crates/re_types/src/archetypes/text_document.rs index c88c2d8c463a..f5a3a5bc6fc0 100644 --- a/crates/re_types/src/archetypes/text_document.rs +++ b/crates/re_types/src/archetypes/text_document.rs @@ -40,7 +40,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// rec.log( /// "markdown", -/// &rerun::TextDocument::new( +/// &rerun::TextDocument::from_markdown( /// r#" /// # Hello Markdown! /// [Click here to see the raw text](recording://markdown:Text). @@ -77,7 +77,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// ![A random image](https://picsum.photos/640/480) /// "#.trim(), /// ) -/// .with_media_type(rerun::MediaType::markdown()), /// )?; /// /// Ok(()) diff --git a/crates/re_types/src/archetypes/text_document_ext.rs b/crates/re_types/src/archetypes/text_document_ext.rs index 30ad37d48156..891921bb9435 100644 --- a/crates/re_types/src/archetypes/text_document_ext.rs +++ b/crates/re_types/src/archetypes/text_document_ext.rs @@ -32,4 +32,12 @@ impl TextDocument { media_type, }) } + + /// Creates a new [`TextDocument`] containing Markdown. + /// + /// Equivalent to `TextDocument::new(markdown).with_media_type(MediaType::markdown())`. + #[inline] + pub fn from_markdown(markdown: impl Into) -> Self { + Self::new(markdown).with_media_type(MediaType::markdown()) + } } diff --git a/docs/snippets/all/text_document.rs b/docs/snippets/all/text_document.rs index dee77da9d682..85df17b3eedf 100644 --- a/docs/snippets/all/text_document.rs +++ b/docs/snippets/all/text_document.rs @@ -10,7 +10,7 @@ fn main() -> Result<(), Box> { rec.log( "markdown", - &rerun::TextDocument::new( + &rerun::TextDocument::from_markdown( r#" # Hello Markdown! [Click here to see the raw text](recording://markdown:Text). @@ -47,7 +47,6 @@ Of course you can also have [normal https links](https://github.com/rerun-io/rer ![A random image](https://picsum.photos/640/480) "#.trim(), ) - .with_media_type(rerun::MediaType::markdown()), )?; Ok(()) diff --git a/examples/rust/external_data_loader/src/main.rs b/examples/rust/external_data_loader/src/main.rs index e6d44ea60433..eb30e655b2dc 100644 --- a/examples/rust/external_data_loader/src/main.rs +++ b/examples/rust/external_data_loader/src/main.rs @@ -1,6 +1,6 @@ //! Example of an external data-loader executable plugin for the Rerun Viewer. -use rerun::{MediaType, EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE}; +use rerun::EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE; // The Rerun Viewer will always pass at least these two pieces of information: // 1. The path to be loaded, as a positional arg. @@ -106,7 +106,7 @@ fn main() -> anyhow::Result<()> { rec.log_with_static( entity_path_prefix.join(&rerun::EntityPath::from_file_path(&args.filepath)), args.statically || args.timeless, - &rerun::TextDocument::new(text).with_media_type(MediaType::MARKDOWN), + &rerun::TextDocument::from_markdown(text), )?; Ok::<_, anyhow::Error>(()) diff --git a/examples/rust/incremental_logging/src/main.rs b/examples/rust/incremental_logging/src/main.rs index 05a1e8a5a06f..c155ec124bda 100644 --- a/examples/rust/incremental_logging/src/main.rs +++ b/examples/rust/incremental_logging/src/main.rs @@ -56,10 +56,7 @@ Move the time cursor around, and notice how the colors and radii from frame 0 ar "#; fn run(rec: &rerun::RecordingStream) -> anyhow::Result<()> { - rec.log_static( - "readme", - &rerun::TextDocument::new(README).with_media_type(rerun::MediaType::MARKDOWN), - )?; + rec.log_static("readme", &rerun::TextDocument::from_markdown(README))?; // TODO(#5264): just log one once clamp-to-edge semantics land. let colors = [rerun::Color::from_rgb(255, 0, 0); 10]; diff --git a/tests/rust/roundtrips/text_document/src/main.rs b/tests/rust/roundtrips/text_document/src/main.rs index 8d40faee0fba..01b45f37a178 100644 --- a/tests/rust/roundtrips/text_document/src/main.rs +++ b/tests/rust/roundtrips/text_document/src/main.rs @@ -1,10 +1,6 @@ //! Logs a `Tensor` archetype for roundtrip checks. -use rerun::{ - archetypes::TextDocument, - external::{re_log, re_types::components::MediaType}, - RecordingStream, -}; +use rerun::{archetypes::TextDocument, external::re_log, RecordingStream}; #[derive(Debug, clap::Parser)] #[clap(author, version, about)] @@ -17,15 +13,14 @@ fn run(rec: &RecordingStream, _args: &Args) -> anyhow::Result<()> { rec.log("text_document", &TextDocument::new("Hello, TextDocument!"))?; rec.log( "markdown", - &TextDocument::new( + &TextDocument::from_markdown( "# Hello\n\ Markdown with `code`!\n\ \n\ A random image:\n\ \n\ ![A random image](https://picsum.photos/640/480)", - ) - .with_media_type(MediaType::markdown()), + ), )?; Ok(()) } diff --git a/tests/rust/test_pinhole_projection/src/main.rs b/tests/rust/test_pinhole_projection/src/main.rs index 0bca676f25d9..160838eae9a7 100644 --- a/tests/rust/test_pinhole_projection/src/main.rs +++ b/tests/rust/test_pinhole_projection/src/main.rs @@ -4,7 +4,7 @@ //! cargo run -p test_pinhole_projection //! ``` -use rerun::{external::re_log, MediaType, RecordingStream}; +use rerun::{external::re_log, RecordingStream}; #[derive(Debug, clap::Parser)] #[clap(author, version, about)] @@ -31,7 +31,7 @@ fn run(rec: &RecordingStream) -> anyhow::Result<()> { "; rec.log_static( "description", - &rerun::TextDocument::new(DESCRIPTION).with_media_type(MediaType::markdown()), + &rerun::TextDocument::from_markdown(DESCRIPTION), )?; rec.log_static("world", &rerun::ViewCoordinates::RIGHT_HAND_Y_DOWN)?; From 9089ae5a7cff559b7b701319d1536c03aabf8ede Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 25 Apr 2024 17:46:49 +0200 Subject: [PATCH 359/508] Allow setting view visibility from blueprint api (#6108) ### What * Fixes #6107 Testing this from repl: ![image](https://github.com/rerun-io/rerun/assets/1220815/accd1f31-3226-4731-ab18-556104be9c36) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6108?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6108?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6108) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../re_types_builder/src/codegen/python/views.rs | 11 ++++++++++- rerun_py/rerun_sdk/rerun/blueprint/api.py | 9 ++++++++- .../rerun/blueprint/views/bar_chart_view.py | 13 ++++++++++++- .../rerun/blueprint/views/spatial2d_view.py | 10 +++++++++- .../rerun/blueprint/views/spatial3d_view.py | 9 ++++++++- .../rerun/blueprint/views/tensor_view.py | 15 ++++++++++++++- .../rerun/blueprint/views/text_document_view.py | 13 ++++++++++++- .../rerun/blueprint/views/text_log_view.py | 15 ++++++++++++++- .../rerun/blueprint/views/time_series_view.py | 13 ++++++++++++- 9 files changed, 99 insertions(+), 9 deletions(-) diff --git a/crates/re_types_builder/src/codegen/python/views.rs b/crates/re_types_builder/src/codegen/python/views.rs index 7fb154418a41..f48579656522 100644 --- a/crates/re_types_builder/src/codegen/python/views.rs +++ b/crates/re_types_builder/src/codegen/python/views.rs @@ -17,6 +17,7 @@ pub fn code_for_view(reporter: &Reporter, objects: &Objects, obj: &Object) -> St from .. import archetypes as blueprint_archetypes from .. import components as blueprint_components from ... import datatypes +from ... import components from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like from ..api import SpaceView, SpaceViewContentsLike @@ -39,6 +40,7 @@ fn init_method(reporter: &Reporter, objects: &Objects, obj: &Object) -> String { origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + visible: blueprint_components.VisibleLike | None = None, "# .to_owned(); @@ -100,6 +102,13 @@ See [rerun.blueprint.archetypes.SpaceViewContents][]." .to_owned(), ), ("name", "The display name of the view.".to_owned()), + ( + "visible", + "Whether this view is visible. + +Defaults to true if not specified." + .to_owned(), + ), ]; for field in &obj.fields { let doc_content = field.docs.doc_lines_for_untagged_and("py"); @@ -165,7 +174,7 @@ See [rerun.blueprint.archetypes.SpaceViewContents][]." } code.push_indented( 1, - &format!(r#"super().__init__(class_identifier="{identifier}", origin=origin, contents=contents, name=name, properties=properties)"#), + &format!(r#"super().__init__(class_identifier="{identifier}", origin=origin, contents=contents, name=name, visible=visible, properties=properties)"#), 1, ); diff --git a/rerun_py/rerun_sdk/rerun/blueprint/api.py b/rerun_py/rerun_sdk/rerun/blueprint/api.py index 1083f509fd47..8d97abdab414 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/api.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/api.py @@ -12,7 +12,7 @@ from ..notebook import as_html from ..recording_stream import RecordingStream from .archetypes import ContainerBlueprint, PanelBlueprint, SpaceViewBlueprint, SpaceViewContents, ViewportBlueprint -from .components import ColumnShareArrayLike, RowShareArrayLike +from .components import ColumnShareArrayLike, RowShareArrayLike, VisibleLike from .components.container_kind import ContainerKindLike SpaceViewContentsLike = Union[Utf8ArrayLike, SpaceViewContents] @@ -42,6 +42,7 @@ def __init__( origin: EntityPathLike, contents: SpaceViewContentsLike, name: Utf8Like | None, + visible: VisibleLike | None = None, properties: dict[str, AsComponents] = {}, ): """ @@ -60,6 +61,10 @@ def __init__( contents The contents of the space view specified as a query expression. This is either a single expression, or a list of multiple expressions. See [rerun.blueprint.archetypes.SpaceViewContents][]. + visible: + Whether this space view is visible. + + Defaults to true if not specified. properties Dictionary of property archetypes to add to space view's internal hierarchy. @@ -69,6 +74,7 @@ def __init__( self.name = name self.origin = origin self.contents = contents + self.visible = visible self.properties = properties def blueprint_path(self) -> str: @@ -105,6 +111,7 @@ def _log_to_stream(self, stream: RecordingStream) -> None: class_identifier=self.class_identifier, display_name=self.name, space_origin=self.origin, + visible=self.visible, ) stream.log(self.blueprint_path(), arch, recording=stream) # type: ignore[attr-defined] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/bar_chart_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/bar_chart_view.py index 342f0b7a7a9a..d458fbd561f6 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/bar_chart_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/bar_chart_view.py @@ -8,6 +8,7 @@ from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like +from .. import components as blueprint_components from ..api import SpaceView, SpaceViewContentsLike @@ -20,6 +21,7 @@ def __init__( origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + visible: blueprint_components.VisibleLike | None = None, ) -> None: """ Construct a blueprint for a new BarChartView view. @@ -35,10 +37,19 @@ def __init__( See [rerun.blueprint.archetypes.SpaceViewContents][]. name: The display name of the view. + visible: + Whether this view is visible. + + Defaults to true if not specified. """ properties: dict[str, AsComponents] = {} super().__init__( - class_identifier="BarChart", origin=origin, contents=contents, name=name, properties=properties + class_identifier="BarChart", + origin=origin, + contents=contents, + name=name, + visible=visible, + properties=properties, ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py index 06250abe69d3..8caca32be171 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py @@ -8,6 +8,7 @@ from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like +from .. import components as blueprint_components from ..api import SpaceView, SpaceViewContentsLike @@ -20,6 +21,7 @@ def __init__( origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + visible: blueprint_components.VisibleLike | None = None, ) -> None: """ Construct a blueprint for a new Spatial2DView view. @@ -35,8 +37,14 @@ def __init__( See [rerun.blueprint.archetypes.SpaceViewContents][]. name: The display name of the view. + visible: + Whether this view is visible. + + Defaults to true if not specified. """ properties: dict[str, AsComponents] = {} - super().__init__(class_identifier="2D", origin=origin, contents=contents, name=name, properties=properties) + super().__init__( + class_identifier="2D", origin=origin, contents=contents, name=name, visible=visible, properties=properties + ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py index 86e81372d7bb..66437db4cefb 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py @@ -23,6 +23,7 @@ def __init__( origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + visible: blueprint_components.VisibleLike | None = None, background: blueprint_archetypes.Background3D | datatypes.Rgba32Like | blueprint_components.Background3DKindLike @@ -42,6 +43,10 @@ def __init__( See [rerun.blueprint.archetypes.SpaceViewContents][]. name: The display name of the view. + visible: + Whether this view is visible. + + Defaults to true if not specified. background: Configuration for the background of the 3D space view. @@ -53,4 +58,6 @@ def __init__( background = blueprint_archetypes.Background3D(background) properties["Background3D"] = background - super().__init__(class_identifier="3D", origin=origin, contents=contents, name=name, properties=properties) + super().__init__( + class_identifier="3D", origin=origin, contents=contents, name=name, visible=visible, properties=properties + ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/tensor_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/tensor_view.py index 247bdf4da584..f40449068af5 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/tensor_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/tensor_view.py @@ -8,6 +8,7 @@ from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like +from .. import components as blueprint_components from ..api import SpaceView, SpaceViewContentsLike @@ -20,6 +21,7 @@ def __init__( origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + visible: blueprint_components.VisibleLike | None = None, ) -> None: """ Construct a blueprint for a new TensorView view. @@ -35,8 +37,19 @@ def __init__( See [rerun.blueprint.archetypes.SpaceViewContents][]. name: The display name of the view. + visible: + Whether this view is visible. + + Defaults to true if not specified. """ properties: dict[str, AsComponents] = {} - super().__init__(class_identifier="Tensor", origin=origin, contents=contents, name=name, properties=properties) + super().__init__( + class_identifier="Tensor", + origin=origin, + contents=contents, + name=name, + visible=visible, + properties=properties, + ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/text_document_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/text_document_view.py index 3a5d60c6ed36..4503186f7a92 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/text_document_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/text_document_view.py @@ -8,6 +8,7 @@ from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like +from .. import components as blueprint_components from ..api import SpaceView, SpaceViewContentsLike @@ -20,6 +21,7 @@ def __init__( origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + visible: blueprint_components.VisibleLike | None = None, ) -> None: """ Construct a blueprint for a new TextDocumentView view. @@ -35,10 +37,19 @@ def __init__( See [rerun.blueprint.archetypes.SpaceViewContents][]. name: The display name of the view. + visible: + Whether this view is visible. + + Defaults to true if not specified. """ properties: dict[str, AsComponents] = {} super().__init__( - class_identifier="TextDocument", origin=origin, contents=contents, name=name, properties=properties + class_identifier="TextDocument", + origin=origin, + contents=contents, + name=name, + visible=visible, + properties=properties, ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/text_log_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/text_log_view.py index ab708803d718..1adc402d2478 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/text_log_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/text_log_view.py @@ -8,6 +8,7 @@ from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like +from .. import components as blueprint_components from ..api import SpaceView, SpaceViewContentsLike @@ -20,6 +21,7 @@ def __init__( origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + visible: blueprint_components.VisibleLike | None = None, ) -> None: """ Construct a blueprint for a new TextLogView view. @@ -35,8 +37,19 @@ def __init__( See [rerun.blueprint.archetypes.SpaceViewContents][]. name: The display name of the view. + visible: + Whether this view is visible. + + Defaults to true if not specified. """ properties: dict[str, AsComponents] = {} - super().__init__(class_identifier="TextLog", origin=origin, contents=contents, name=name, properties=properties) + super().__init__( + class_identifier="TextLog", + origin=origin, + contents=contents, + name=name, + visible=visible, + properties=properties, + ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py index 00a25b2001f6..3524acbd0439 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py @@ -8,6 +8,7 @@ from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like +from .. import components as blueprint_components from ..api import SpaceView, SpaceViewContentsLike @@ -20,6 +21,7 @@ def __init__( origin: EntityPathLike = "/", contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, + visible: blueprint_components.VisibleLike | None = None, ) -> None: """ Construct a blueprint for a new TimeSeriesView view. @@ -35,10 +37,19 @@ def __init__( See [rerun.blueprint.archetypes.SpaceViewContents][]. name: The display name of the view. + visible: + Whether this view is visible. + + Defaults to true if not specified. """ properties: dict[str, AsComponents] = {} super().__init__( - class_identifier="TimeSeries", origin=origin, contents=contents, name=name, properties=properties + class_identifier="TimeSeries", + origin=origin, + contents=contents, + name=name, + visible=visible, + properties=properties, ) From 021add0d74b82261268f648b64ff1e50498c4bbe Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Thu, 25 Apr 2024 18:02:59 +0200 Subject: [PATCH 360/508] `pixi run format` now supports rust too (#6115) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6115?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6115?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6115) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- pixi.toml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pixi.toml b/pixi.toml index 48bfc76dc0b6..33f1cb942db2 100644 --- a/pixi.toml +++ b/pixi.toml @@ -101,8 +101,16 @@ rs-check = { cmd = "rustup target add wasm32-unknown-unknown && python scripts/c "rerun-build-web", # The checks require the web viewer wasm to be around. ] } +rs-fmt = "cargo fmt --all" + # Code formatting for all languages. -format = { depends_on = ["py-fmt", "cpp-fmt", "toml-fmt", "misc-fmt"] } +format = { depends_on = [ + "py-fmt", + "cpp-fmt", + "rs-fmt", + "toml-fmt", + "misc-fmt", +] } fmt = { depends_on = ["format"] } # Assorted linting tasks From b176e397dbb3672a4d15d0bb0ed4fd3f959d32a2 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 25 Apr 2024 18:23:00 +0200 Subject: [PATCH 361/508] Remove handwritten __all__ python definitions (#6117) ### What As discussed internally, we'll try without maintaining the handwritten `__all__`. Locally everything seems to be fine with my lsp so far ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6117?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6117?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6117) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- rerun_py/rerun_sdk/rerun/__init__.py | 102 ------------------ rerun_py/rerun_sdk/rerun/_converters.py | 19 ---- rerun_py/rerun_sdk/rerun/_image.py | 2 - rerun_py/rerun_sdk/rerun/_log.py | 2 - .../rerun_sdk/rerun/blueprint/__init__.py | 26 ----- rerun_py/rerun_sdk/rerun/error_utils.py | 4 - .../rerun_sdk/rerun/experimental/__init__.py | 2 - .../rerun_sdk/rerun/utilities/__init__.py | 18 ---- rerun_py/rerun_sdk/rerun/utilities/data.py | 12 --- rerun_py/rerun_sdk/rerun/utilities/turbo.py | 2 - rerun_py/rerun_sdk/rerun/utilities/util.py | 2 - 11 files changed, 191 deletions(-) diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index e356a7af5005..4ffdc2a1de2d 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -9,95 +9,6 @@ # ===================================== # API RE-EXPORTS - -__all__ = [ - "AnnotationContext", - "AnnotationInfo", - "AnyValues", - "Arrows3D", - "AsComponents", - "Asset3D", - "BarChart", - "Box2DFormat", - "Boxes2D", - "Boxes3D", - "ClassDescription", - "Clear", - "ComponentBatchLike", - "DepthImage", - "DisconnectedSpace", - "Image", - "ImageEncoded", - "ImageFormat", - "IndicatorComponentBatch", - "LineStrips2D", - "LineStrips3D", - "LoggingHandler", - "Material", - "MediaType", - "MemoryRecording", - "Mesh3D", - "MeshProperties", - "OutOfTreeTransform3D", - "OutOfTreeTransform3DBatch", - "Pinhole", - "Points2D", - "Points3D", - "Quaternion", - "RecordingStream", - "RotationAxisAngle", - "Scalar", - "Scale3D", - "SegmentationImage", - "SeriesLine", - "SeriesPoint", - "Tensor", - "TensorData", - "TextDocument", - "TextLog", - "TextLogLevel", - "Transform3D", - "TranslationAndMat3x3", - "TranslationRotationScale3D", - "ViewCoordinates", - "archetypes", - "bindings", - "blueprint", - "components", - "connect", - "datatypes", - "disable_timeline", - "disconnect", - "escape_entity_path_part", - "experimental", - "get_application_id", - "get_data_recording", - "get_global_data_recording", - "get_recording_id", - "get_thread_local_data_recording", - "is_enabled", - "log", - "log_components", - "log_file_from_contents", - "log_file_from_path", - "memory_recording", - "new_entity_path", - "notebook_show", - "reset_time", - "save", - "script_add_args", - "script_setup", - "script_teardown", - "serve", - "set_global_data_recording", - "set_thread_local_data_recording", - "set_time_nanos", - "set_time_seconds", - "set_time_sequence", - "send_blueprint", - "spawn", -] - import rerun_bindings as bindings # type: ignore[attr-defined] from ._image import ImageEncoded, ImageFormat @@ -193,19 +104,6 @@ # ===================================== # UTILITIES -__all__ += [ - "EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE", - "cleanup_if_forked_child", - "init", - "new_recording", - "rerun_shutdown", - "set_strict_mode", - "shutdown_at_exit", - "start_web_viewer_server", - "unregister_shutdown", - "version", -] - # NOTE: Always keep in sync with other languages. EXTERNAL_DATA_LOADER_INCOMPATIBLE_EXIT_CODE = 66 diff --git a/rerun_py/rerun_sdk/rerun/_converters.py b/rerun_py/rerun_sdk/rerun/_converters.py index e951032373ea..161c98c8197a 100644 --- a/rerun_py/rerun_sdk/rerun/_converters.py +++ b/rerun_py/rerun_sdk/rerun/_converters.py @@ -27,25 +27,6 @@ class ClassA: import numpy as np import numpy.typing as npt -__all__ = [ - "int_or_none", - "float_or_none", - "bool_or_none", - "str_or_none", - "to_np_uint8", - "to_np_uint16", - "to_np_uint32", - "to_np_uint64", - "to_np_int8", - "to_np_int16", - "to_np_int32", - "to_np_int64", - "to_np_bool", - "to_np_float16", - "to_np_float32", - "to_np_float64", -] - @overload def int_or_none(data: None) -> None: ... diff --git a/rerun_py/rerun_sdk/rerun/_image.py b/rerun_py/rerun_sdk/rerun/_image.py index 23a230f2b80d..0ba490015606 100644 --- a/rerun_py/rerun_sdk/rerun/_image.py +++ b/rerun_py/rerun_sdk/rerun/_image.py @@ -12,8 +12,6 @@ from .components import DrawOrderLike, TensorData from .datatypes import TensorBuffer, TensorDimension -__all__ = ["ImageFormat", "ImageEncoded"] - class ImageFormat: """Image file format.""" diff --git a/rerun_py/rerun_sdk/rerun/_log.py b/rerun_py/rerun_sdk/rerun/_log.py index 1b3573e8ebce..c22d7bbc57b0 100644 --- a/rerun_py/rerun_sdk/rerun/_log.py +++ b/rerun_py/rerun_sdk/rerun/_log.py @@ -11,8 +11,6 @@ from .error_utils import _send_warning_or_raise, catch_and_log_exceptions from .recording_stream import RecordingStream -__all__ = ["log", "IndicatorComponentBatch", "AsComponents"] - class IndicatorComponentBatch: """ diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 8b8c0cbef659..330b638c2c2c 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -1,31 +1,5 @@ from __future__ import annotations -__all__ = [ - "BarChartView", - "Blueprint", - "BlueprintLike", - "BlueprintPanel", - "BlueprintPart", - "Container", - "ContainerLike", - "Grid", - "Horizontal", - "SelectionPanel", - "SpaceView", - "Spatial2DView", - "Spatial3DView", - "Tabs", - "TensorView", - "TextDocumentView", - "TextLogView", - "TimePanel", - "TimeSeriesView", - "Vertical", - "archetypes", - "components", - "datatypes", -] - from . import archetypes, components, datatypes from .api import ( Blueprint, diff --git a/rerun_py/rerun_sdk/rerun/error_utils.py b/rerun_py/rerun_sdk/rerun/error_utils.py index e33df4a746be..bea826aa9cdc 100644 --- a/rerun_py/rerun_sdk/rerun/error_utils.py +++ b/rerun_py/rerun_sdk/rerun/error_utils.py @@ -10,10 +10,6 @@ from .recording_stream import RecordingStream -__all__ = [ - "_send_warning_or_raise", -] - _TFunc = TypeVar("_TFunc", bound=Callable[..., Any]) diff --git a/rerun_py/rerun_sdk/rerun/experimental/__init__.py b/rerun_py/rerun_sdk/rerun/experimental/__init__.py index 844bd63eb849..cb78ed0da732 100644 --- a/rerun_py/rerun_sdk/rerun/experimental/__init__.py +++ b/rerun_py/rerun_sdk/rerun/experimental/__init__.py @@ -6,5 +6,3 @@ """ from __future__ import annotations - -# __all__ = [] diff --git a/rerun_py/rerun_sdk/rerun/utilities/__init__.py b/rerun_py/rerun_sdk/rerun/utilities/__init__.py index 2203d365bc88..77f101690f8f 100644 --- a/rerun_py/rerun_sdk/rerun/utilities/__init__.py +++ b/rerun_py/rerun_sdk/rerun/utilities/__init__.py @@ -13,21 +13,3 @@ ) from .turbo import turbo_colormap_data from .util import bounce_lerp, interleave - -__all__ = [ - # data - "ColorGrid", - "build_color_grid", - "color_grid", - "RectPyramid", - "build_rect_pyramid", - "rect_pyramid", - "ColorSpiral", - "build_color_spiral", - "color_spiral", - # turbo - "turbo_colormap_data", - # util - "bounce_lerp", - "interleave", -] diff --git a/rerun_py/rerun_sdk/rerun/utilities/data.py b/rerun_py/rerun_sdk/rerun/utilities/data.py index 6d02871fe8a3..adc6bfebacff 100644 --- a/rerun_py/rerun_sdk/rerun/utilities/data.py +++ b/rerun_py/rerun_sdk/rerun/utilities/data.py @@ -11,18 +11,6 @@ from .turbo import turbo_colormap_data -__all__ = [ - "ColorGrid", - "build_color_grid", - "color_grid", - "RectPyramid", - "build_rect_pyramid", - "rect_pyramid", - "ColorSpiral", - "build_color_spiral", - "color_spiral", -] - ColorGrid = namedtuple("ColorGrid", ["positions", "colors"]) diff --git a/rerun_py/rerun_sdk/rerun/utilities/turbo.py b/rerun_py/rerun_sdk/rerun/utilities/turbo.py index 005af175d6ce..97a5fb1c1b50 100644 --- a/rerun_py/rerun_sdk/rerun/utilities/turbo.py +++ b/rerun_py/rerun_sdk/rerun/utilities/turbo.py @@ -2,8 +2,6 @@ import numpy as np -__all__ = ["turbo_colormap_data"] - turbo_colormap_data = np.array([ [0.18995, 0.07176, 0.23217], [0.19483, 0.08339, 0.26149], diff --git a/rerun_py/rerun_sdk/rerun/utilities/util.py b/rerun_py/rerun_sdk/rerun/utilities/util.py index 293fcbffb006..134d17c5ae5e 100644 --- a/rerun_py/rerun_sdk/rerun/utilities/util.py +++ b/rerun_py/rerun_sdk/rerun/utilities/util.py @@ -7,8 +7,6 @@ import numpy as np import numpy.typing as npt -__all__ = ["bounce_lerp", "interleave"] - def bounce_lerp( a: float, b: float, t: float | np.ndarray[Any, np.dtype[Any]] From 2b42d9484a31df2c7443451f97e4425b79c42edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Fri, 26 Apr 2024 07:48:32 +0200 Subject: [PATCH 362/508] Fix example manifest and ensure coverage on CI (#6122) ### What - Fix example manifest contents - Some examples were renamed, but not updated in the manifest - Update the manifest coverage script to `exit(1)` on failure - Use the script on CI On the `landing` side, I also added an error that is emitted when an example is missing. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6122?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6122?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6122) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/reusable_checks.yml | 3 +++ examples/manifest.toml | 8 +++++--- scripts/check_example_manifest_coverage.py | 16 ++++++++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) mode change 100644 => 100755 scripts/check_example_manifest_coverage.py diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index c414f6efb0be..ceb4af0d9e66 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -129,6 +129,9 @@ jobs: - name: Check Python example thumbnails run: pixi run ./scripts/ci/thumbnails.py check + - name: Check example manifest coverage + run: pixi run ./scripts/check_example_manifest_coverage.py + # --------------------------------------------------------------------------- spell-check: diff --git a/examples/manifest.toml b/examples/manifest.toml index 6f19820daba1..beaeb4231d75 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -33,13 +33,13 @@ Examples related to robotics, autonomous systems, and interfacing with sensor ha examples = [ # display order, most interesting first "ros_node", - "nuscenes", + "nuscenes_dataset", "ros_bridge", "kiss-icp", "urdf_loader", "live_depth_sensor", "lidar", - "rrt-star", + "rrt_star", "rgbd", "nv12", ] @@ -125,7 +125,7 @@ examples = [ "dna", "log_file", "minimal", - "multiprocessing", + "multiprocess_logging", "multithreading", "plots", "raw_mesh", @@ -148,4 +148,6 @@ examples = [ "spawn_viewer", "stdio", "template", + "all_examples", + "_empty_rerun_sdk", ] diff --git a/scripts/check_example_manifest_coverage.py b/scripts/check_example_manifest_coverage.py old mode 100644 new mode 100755 index 8d29a8819af0..a0ed0b40825b --- a/scripts/check_example_manifest_coverage.py +++ b/scripts/check_example_manifest_coverage.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + """Check if all examples are listed (or explicitly ignored) in our example manifest.""" from __future__ import annotations @@ -34,12 +36,22 @@ def main(): all_examples = list(gather_example_in_repo()) - print("Unlisted examples:") + print(*[f"- {example}\n" for example in listed_examples]) + print(*[f"- {example.name}\n" for example in all_examples]) + + unlisted_examples: list[Path] = [] for example_path in all_examples: if example_path.name not in listed_examples: - print(f"- {example_path.parent.name}/{example_path.name}") + unlisted_examples.append(example_path) print(f"({len(all_examples)} checked)") + if len(unlisted_examples) > 0: + print("Unlisted examples:") + for example_path in unlisted_examples: + print(f"- {example_path.parent.name}/{example_path.name}") + exit(1) + else: + print("all ok") if __name__ == "__main__": From 30184573883c888b617201da0283b352ee6269a7 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 09:10:36 +0200 Subject: [PATCH 363/508] Fix `pixi run fast-lint` (#6119) --- pixi.toml | 2 +- scripts/fast_lint.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pixi.toml b/pixi.toml index 33f1cb942db2..b89fb2ae041e 100644 --- a/pixi.toml +++ b/pixi.toml @@ -116,7 +116,7 @@ fmt = { depends_on = ["format"] } # Assorted linting tasks fast-lint = "python scripts/fast_lint.py" lint-codegen = "cargo --quiet run --package re_types_builder -- --check" -# TODO(jleibs): implement lint-cpp-all +# TODO(jleibs): implement lint-cpp-files lint-rerun = "python scripts/lint.py" lint-rs-files = "rustfmt --edition 2021 --check" lint-rs-all = "cargo fmt --check" diff --git a/scripts/fast_lint.py b/scripts/fast_lint.py index 7bca3b325c72..63f9d8521d66 100755 --- a/scripts/fast_lint.py +++ b/scripts/fast_lint.py @@ -139,11 +139,12 @@ def main() -> None: jobs = [ LintJob("lint-codegen", accepts_files=False), - LintJob( - "lint-cpp-files", - extensions=[".cpp", ".c", ".h", ".hpp"], - allow_no_filter=False, - ), + # TODO(jleibs): implement lint-cpp-files + # LintJob( + # "lint-cpp-files", + # extensions=[".cpp", ".c", ".h", ".hpp"], + # allow_no_filter=False, + # ), LintJob("lint-rerun"), LintJob( "lint-rs-files", From 8c30688ac82a0d7ac10be3e5b0c4dfdf37ecc680 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 26 Apr 2024 10:58:54 +0200 Subject: [PATCH 364/508] Fix log spam on Windows when shutting down viewer (#6118) ### What * Fixes #6099 Regressed recently with http server rewrite. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6118?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6118?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6118) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_sdk_comms/src/server.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/crates/re_sdk_comms/src/server.rs b/crates/re_sdk_comms/src/server.rs index 346b20939251..945737b8a0aa 100644 --- a/crates/re_sdk_comms/src/server.rs +++ b/crates/re_sdk_comms/src/server.rs @@ -135,6 +135,33 @@ fn listen_for_new_clients(listener: &TcpListener, options: ServerOptions, tx: &S .ok(); } Err(err) => { + if cfg!(target_os = "windows") { + // Windows error codes resolved to names via http://errorcodelookup.com/ + const WSANOTINITIALISED: i32 = 10093; + const WSAEINTR: i32 = 10004; + + if let Some(raw_os_error) = err.raw_os_error() { + #[allow(clippy::match_same_arms)] + match raw_os_error { + WSANOTINITIALISED => { + // This happens either if WSAStartup wasn't called beforehand, + // or WSACleanup was called as part of shutdown already. + // + // If we end up in here it's almost certainly the later case + // which implies that the process is shutting down. + break; + } + WSAEINTR => { + // A blocking operation was interrupted. + // This can only happen if the listener is closing, + // meaning that this server is shutting down. + break; + } + _ => {} + } + } + } + re_log::warn!("Failed to accept incoming SDK client: {err}"); } } From 2b4c22ed9eff54a0bad7233bc640a4e95cd9a42a Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 26 Apr 2024 10:59:50 +0200 Subject: [PATCH 365/508] Expose `PlotLegend` and `ScalarAxis` (axis_y) properties on `TimeSeriesView` blueprint (#6114) ### What * Part of [#6083](https://github.com/rerun-io/rerun/issues/6083) Usage example: ```py # ... # Plot with custom Y range that is locked into place during zoom and legend at the bottom left. rrb.TimeSeriesView( origin="/plot", axis_y=rrb.ScalarAxis(range=[0, 1], lock_range_during_zoom=True), plot_legend=rrb.Corner2D.LeftBottom, ), # Hide plot legend rrb.TimeSeriesView( origin="/plot", plot_legend=rrb.PlotLegend(visible=False), ), # ... ``` Changed codegen type definition: ```fbs /// A time series view. table TimeSeriesView ( "attr.rerun.view_identifier": "TimeSeries" ) { /// Configures the vertical axis of the plot. axis_y: rerun.blueprint.archetypes.ScalarAxis (order: 1000); /// Configures the legend of the plot. plot_legend: rerun.blueprint.archetypes.PlotLegend (order: 2000); } ``` Added the necessary serialization code and snippets. More aggressively using datatypes now to reduce amount of serialization code we need to write in Python. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6114?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6114?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6114) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../src/space_view_class.rs | 20 +- .../blueprint/archetypes/plot_legend.fbs | 3 +- .../components/lock_range_during_zoom.fbs | 5 +- .../rerun/blueprint/views/time_series.fbs | 5 + .../definitions/rerun/components/range1d.fbs | 6 +- .../re_types/definitions/rerun/datatypes.fbs | 1 + .../definitions/rerun/datatypes/range1d.fbs | 22 ++ .../components/lock_range_during_zoom.rs | 39 +++- crates/re_types/src/components/mod.rs | 1 + crates/re_types/src/components/range1d.rs | 49 ++-- crates/re_types/src/components/range1d_ext.rs | 20 ++ crates/re_types/src/datatypes/.gitattributes | 1 + crates/re_types/src/datatypes/mod.rs | 2 + crates/re_types/src/datatypes/range1d.rs | 213 ++++++++++++++++++ .../reference/types/components/range1d.md | 2 +- docs/content/reference/types/datatypes.md | 1 + .../reference/types/datatypes/.gitattributes | 1 + .../reference/types/datatypes/range1d.md | 19 ++ .../rerun/blueprint/components/.gitattributes | 1 - .../components/lock_range_during_zoom.cpp | 63 ------ .../components/lock_range_during_zoom.hpp | 47 ++-- rerun_cpp/src/rerun/components/.gitattributes | 1 - rerun_cpp/src/rerun/components/range1d.hpp | 38 ++-- rerun_cpp/src/rerun/datatypes.hpp | 1 + rerun_cpp/src/rerun/datatypes/.gitattributes | 2 + .../{components => datatypes}/range1d.cpp | 16 +- rerun_cpp/src/rerun/datatypes/range1d.hpp | 58 +++++ rerun_py/rerun_sdk/rerun/_validators.py | 11 +- .../rerun_sdk/rerun/blueprint/__init__.py | 4 + .../rerun/blueprint/archetypes/plot_legend.py | 34 +-- .../blueprint/archetypes/plot_legend_ext.py | 37 +++ .../rerun/blueprint/archetypes/scalar_axis.py | 6 +- .../rerun/blueprint/components/__init__.py | 10 +- .../components/lock_range_during_zoom.py | 49 +--- .../rerun/blueprint/views/time_series_view.py | 17 ++ .../rerun_sdk/rerun/components/__init__.py | 4 +- .../rerun_sdk/rerun/components/range1d.py | 51 +---- .../rerun_sdk/rerun/datatypes/.gitattributes | 1 + .../rerun_sdk/rerun/datatypes/__init__.py | 6 + .../rerun/datatypes/quaternion_ext.py | 4 +- rerun_py/rerun_sdk/rerun/datatypes/range1d.py | 65 ++++++ .../rerun_sdk/rerun/datatypes/range1d_ext.py | 24 ++ .../rerun_sdk/rerun/datatypes/vec2d_ext.py | 4 +- .../rerun_sdk/rerun/datatypes/vec3d_ext.py | 4 +- .../rerun_sdk/rerun/datatypes/vec4d_ext.py | 4 +- rerun_py/tests/unit/test_plot_legend.py | 50 ++++ rerun_py/tests/unit/test_scalar_axis.py | 51 +++++ 47 files changed, 783 insertions(+), 290 deletions(-) create mode 100644 crates/re_types/definitions/rerun/datatypes/range1d.fbs create mode 100644 crates/re_types/src/components/range1d_ext.rs create mode 100644 crates/re_types/src/datatypes/range1d.rs create mode 100644 docs/content/reference/types/datatypes/range1d.md delete mode 100644 rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.cpp rename rerun_cpp/src/rerun/{components => datatypes}/range1d.cpp (75%) create mode 100644 rerun_cpp/src/rerun/datatypes/range1d.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend_ext.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/range1d.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/range1d_ext.py create mode 100644 rerun_py/tests/unit/test_plot_legend.py create mode 100644 rerun_py/tests/unit/test_scalar_axis.py diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 4395005fd4e1..7b7e5e3e721a 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -386,7 +386,7 @@ It can greatly improve performance (and readability) in such situations as it pr // use timeline_name as part of id, so that egui stores different pan/zoom for different timelines let plot_id_src = ("plot", &timeline_name); - let y_lock_range_during_zoom = y_lock_range_during_zoom.map_or(false, |v| v.0); + let y_lock_range_during_zoom = y_lock_range_during_zoom.map_or(false, |v| (*v).0); let lock_y_during_zoom = y_lock_range_during_zoom || ui.input(|i| i.modifiers.contains(controls::ASPECT_SCROLL_MODIFIER)); @@ -491,8 +491,8 @@ It can greatly improve performance (and readability) in such situations as it pr let mut max = current_bounds.max(); if range_was_edited || is_resetting || locked_y_range_was_enabled { - min[1] = y_range.0[0]; - max[1] = y_range.0[1]; + min[1] = y_range.start(); + max[1] = y_range.end(); } let new_bounds = egui_plot::PlotBounds::from_min_max(min, max); @@ -722,25 +722,25 @@ fn axis_ui( }); if !auto_range { - let mut range_edit = y_range - .unwrap_or_else(|| y_range.unwrap_or(Range1D(state.saved_y_axis_range))); + let range_edit = y_range + .unwrap_or_else(|| y_range.unwrap_or(state.saved_y_axis_range.into())); ui.horizontal(|ui| { // Max < Min is not supported. // Also, egui_plot doesn't handle min==max (it ends up picking a default range instead then) - let prev_min = crate::util::next_up_f64(range_edit.0[0]); - let prev_max = range_edit.0[1]; + let prev_min = crate::util::next_up_f64(range_edit.start()); + let prev_max = range_edit.end(); // Scale the speed to the size of the range let speed = ((prev_max - prev_min) * 0.01).at_least(0.001); ui.label("Min"); ui.add( - egui::DragValue::new(&mut range_edit.0[0]) + egui::DragValue::new(&mut range_edit.start()) .speed(speed) .clamp_range(std::f64::MIN..=prev_max), ); ui.label("Max"); ui.add( - egui::DragValue::new(&mut range_edit.0[1]) + egui::DragValue::new(&mut range_edit.end()) .speed(speed) .clamp_range(prev_min..=std::f64::MAX), ); @@ -767,7 +767,7 @@ fn axis_ui( let y_lock_zoom = y_lock_range_during_zoom.unwrap_or(false.into()); let mut edit_locked = y_lock_zoom; ctx.re_ui - .checkbox(ui, &mut edit_locked.0, "Lock Range") + .checkbox(ui, &mut edit_locked.0.0, "Lock Range") .on_hover_text( "If set, when zooming, the Y axis range will remain locked to the specified range.", ); diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/plot_legend.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/plot_legend.fbs index 7e20af2f977a..0ddfb7164c67 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/plot_legend.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/plot_legend.fbs @@ -13,7 +13,8 @@ namespace rerun.blueprint.archetypes; /// Configuration for the legend of a plot. table PlotLegend ( "attr.rerun.scope": "blueprint", - "attr.rust.derive": "Default" + "attr.rust.derive": "Default", + "attr.python.aliases": "blueprint_components.Corner2D" ) { // --- Optional --- diff --git a/crates/re_types/definitions/rerun/blueprint/components/lock_range_during_zoom.fbs b/crates/re_types/definitions/rerun/blueprint/components/lock_range_during_zoom.fbs index 1db735069679..f35deead5ce4 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/lock_range_during_zoom.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/lock_range_during_zoom.fbs @@ -13,11 +13,10 @@ namespace rerun.blueprint.components; /// /// Default is `false`, i.e. zoom will change the visualized range. struct LockRangeDuringZoom ( - "attr.arrow.transparent", "attr.rerun.scope": "blueprint", - "attr.rust.derive": "Copy, PartialEq, Eq", + "attr.rust.derive": "Copy, Default, PartialEq, Eq, PartialOrd, Ord", "attr.rust.repr": "transparent", "attr.rust.tuple_struct" ) { - lock_range: bool (order: 100); + lock_range: rerun.datatypes.Bool (order: 100); } diff --git a/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs b/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs index 6929a6b4aa3a..a4391c61dc61 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs @@ -6,4 +6,9 @@ namespace rerun.blueprint.views; table TimeSeriesView ( "attr.rerun.view_identifier": "TimeSeries" ) { + /// Configures the vertical axis of the plot. + axis_y: rerun.blueprint.archetypes.ScalarAxis (order: 1000); + + /// Configures the legend of the plot. + plot_legend: rerun.blueprint.archetypes.PlotLegend (order: 2000); } diff --git a/crates/re_types/definitions/rerun/components/range1d.fbs b/crates/re_types/definitions/rerun/components/range1d.fbs index 78496dc8f1f9..dff9586fbb51 100644 --- a/crates/re_types/definitions/rerun/components/range1d.fbs +++ b/crates/re_types/definitions/rerun/components/range1d.fbs @@ -11,8 +11,8 @@ namespace rerun.components; /// A 1D range, specifying a lower and upper bound. struct Range1D ( - "attr.rust.derive": "Copy, PartialEq, PartialOrd, bytemuck::Pod, bytemuck::Zeroable", - "attr.rust.repr": "transparent" + "attr.rust.derive": "Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", + "attr.rust.repr": "transparent" ) { - range: [double: 2] (order: 100); + range: rerun.datatypes.Range1D (order: 100); } diff --git a/crates/re_types/definitions/rerun/datatypes.fbs b/crates/re_types/definitions/rerun/datatypes.fbs index 74d5fc31fea0..d1c52a2f654b 100644 --- a/crates/re_types/definitions/rerun/datatypes.fbs +++ b/crates/re_types/definitions/rerun/datatypes.fbs @@ -13,6 +13,7 @@ include "./datatypes/mat4x4.fbs"; include "./datatypes/material.fbs"; include "./datatypes/mesh_properties.fbs"; include "./datatypes/quaternion.fbs"; +include "./datatypes/range1d.fbs"; include "./datatypes/rgba32.fbs"; include "./datatypes/rotation_axis_angle.fbs"; include "./datatypes/rotation3d.fbs"; diff --git a/crates/re_types/definitions/rerun/datatypes/range1d.fbs b/crates/re_types/definitions/rerun/datatypes/range1d.fbs new file mode 100644 index 000000000000..451fd24527fe --- /dev/null +++ b/crates/re_types/definitions/rerun/datatypes/range1d.fbs @@ -0,0 +1,22 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.datatypes; + +// --- + +/// A 1D range, specifying a lower and upper bound. +struct Range1D ( + "attr.arrow.transparent", + "attr.python.aliases": "npt.NDArray[Any], npt.ArrayLike, Sequence[float], slice", + "attr.python.array_aliases": "npt.NDArray[Any], npt.ArrayLike, Sequence[Sequence[float]], Sequence[float]", + "attr.rust.derive": "Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", + "attr.rust.tuple_struct", + "attr.rust.repr": "C" +) { + range: [double: 2] (order: 100); +} diff --git a/crates/re_types/src/blueprint/components/lock_range_during_zoom.rs b/crates/re_types/src/blueprint/components/lock_range_during_zoom.rs index 04877be5b8c8..efba0347ba60 100644 --- a/crates/re_types/src/blueprint/components/lock_range_during_zoom.rs +++ b/crates/re_types/src/blueprint/components/lock_range_during_zoom.rs @@ -25,9 +25,9 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Indicate whether the range should be locked when zooming in on the data. /// /// Default is `false`, i.e. zoom will change the visualized range. -#[derive(Clone, Debug, Copy, PartialEq, Eq)] +#[derive(Clone, Debug, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] #[repr(transparent)] -pub struct LockRangeDuringZoom(pub bool); +pub struct LockRangeDuringZoom(pub crate::datatypes::Bool); impl ::re_types_core::SizeBytes for LockRangeDuringZoom { #[inline] @@ -37,21 +37,29 @@ impl ::re_types_core::SizeBytes for LockRangeDuringZoom { #[inline] fn is_pod() -> bool { - ::is_pod() + ::is_pod() } } -impl From for LockRangeDuringZoom { +impl> From for LockRangeDuringZoom { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for LockRangeDuringZoom { #[inline] - fn from(lock_range: bool) -> Self { - Self(lock_range) + fn borrow(&self) -> &crate::datatypes::Bool { + &self.0 } } -impl From for bool { +impl std::ops::Deref for LockRangeDuringZoom { + type Target = crate::datatypes::Bool; + #[inline] - fn from(value: LockRangeDuringZoom) -> Self { - value.0 + fn deref(&self) -> &crate::datatypes::Bool { + &self.0 } } @@ -99,7 +107,17 @@ impl ::re_types_core::Loggable for LockRangeDuringZoom { }; BooleanArray::new( Self::arrow_datatype(), - data0.into_iter().map(|v| v.unwrap_or_default()).collect(), + data0 + .into_iter() + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::Bool(data0) = datum; + data0 + }) + .unwrap_or_default() + }) + .collect(), data0_bitmap, ) .boxed() @@ -125,6 +143,7 @@ impl ::re_types_core::Loggable for LockRangeDuringZoom { }) .with_context("rerun.blueprint.components.LockRangeDuringZoom#lock_range")? .into_iter() + .map(|res_or_opt| res_or_opt.map(|v| crate::datatypes::Bool(v))) .map(|v| v.ok_or_else(DeserializationError::missing_data)) .map(|res| res.map(|v| Some(Self(v)))) .collect::>>>() diff --git a/crates/re_types/src/components/mod.rs b/crates/re_types/src/components/mod.rs index 8cb128077a6f..0a5d32a77b59 100644 --- a/crates/re_types/src/components/mod.rs +++ b/crates/re_types/src/components/mod.rs @@ -44,6 +44,7 @@ mod position3d_ext; mod radius; mod radius_ext; mod range1d; +mod range1d_ext; mod resolution; mod rotation3d; mod rotation3d_ext; diff --git a/crates/re_types/src/components/range1d.rs b/crates/re_types/src/components/range1d.rs index 438ff20290c9..2da4068cfa5c 100644 --- a/crates/re_types/src/components/range1d.rs +++ b/crates/re_types/src/components/range1d.rs @@ -23,9 +23,9 @@ use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: A 1D range, specifying a lower and upper bound. -#[derive(Clone, Debug, Copy, PartialEq, PartialOrd, bytemuck::Pod, bytemuck::Zeroable)] +#[derive(Clone, Debug, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] #[repr(transparent)] -pub struct Range1D(pub [f64; 2usize]); +pub struct Range1D(pub crate::datatypes::Range1D); impl ::re_types_core::SizeBytes for Range1D { #[inline] @@ -35,21 +35,29 @@ impl ::re_types_core::SizeBytes for Range1D { #[inline] fn is_pod() -> bool { - <[f64; 2usize]>::is_pod() + ::is_pod() } } -impl From<[f64; 2usize]> for Range1D { +impl> From for Range1D { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for Range1D { #[inline] - fn from(range: [f64; 2usize]) -> Self { - Self(range) + fn borrow(&self) -> &crate::datatypes::Range1D { + &self.0 } } -impl From for [f64; 2usize] { +impl std::ops::Deref for Range1D { + type Target = crate::datatypes::Range1D; + #[inline] - fn from(value: Range1D) -> Self { - value.0 + fn deref(&self) -> &crate::datatypes::Range1D { + &self.0 } } @@ -102,12 +110,15 @@ impl ::re_types_core::Loggable for Range1D { use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; let data0_inner_data: Vec<_> = data0 .iter() - .flat_map(|v| match v { - Some(v) => itertools::Either::Left(v.iter().cloned()), - None => itertools::Either::Right( - std::iter::repeat(Default::default()).take(2usize), - ), + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::Range1D(data0) = datum; + data0 + }) + .unwrap_or_default() }) + .flatten() .map(Some) .collect(); let data0_inner_bitmap: Option = @@ -200,6 +211,9 @@ impl ::re_types_core::Loggable for Range1D { }) .transpose() }) + .map(|res_or_opt| { + res_or_opt.map(|res_or_opt| res_or_opt.map(|v| crate::datatypes::Range1D(v))) + }) .collect::>>>()? } .into_iter() @@ -254,7 +268,12 @@ impl ::re_types_core::Loggable for Range1D { ) }; { - slice.iter().copied().map(|v| Self(v)).collect::>() + slice + .iter() + .copied() + .map(|v| crate::datatypes::Range1D(v)) + .map(|v| Self(v)) + .collect::>() } }) } diff --git a/crates/re_types/src/components/range1d_ext.rs b/crates/re_types/src/components/range1d_ext.rs new file mode 100644 index 000000000000..de5046b2c947 --- /dev/null +++ b/crates/re_types/src/components/range1d_ext.rs @@ -0,0 +1,20 @@ +use crate::datatypes; + +use super::Range1D; + +impl Range1D { + #[inline] + pub fn new(start: f64, end: f64) -> Self { + Self(datatypes::Range1D([start, end])) + } + + #[inline] + pub fn start(&self) -> f64 { + self.0 .0[0] + } + + #[inline] + pub fn end(&self) -> f64 { + self.0 .0[1] + } +} diff --git a/crates/re_types/src/datatypes/.gitattributes b/crates/re_types/src/datatypes/.gitattributes index fe920bd960dc..bb3603b3cdde 100644 --- a/crates/re_types/src/datatypes/.gitattributes +++ b/crates/re_types/src/datatypes/.gitattributes @@ -15,6 +15,7 @@ material.rs linguist-generated=true mesh_properties.rs linguist-generated=true mod.rs linguist-generated=true quaternion.rs linguist-generated=true +range1d.rs linguist-generated=true rgba32.rs linguist-generated=true rotation3d.rs linguist-generated=true rotation_axis_angle.rs linguist-generated=true diff --git a/crates/re_types/src/datatypes/mod.rs b/crates/re_types/src/datatypes/mod.rs index cc7296e88223..02fdfd040b3b 100644 --- a/crates/re_types/src/datatypes/mod.rs +++ b/crates/re_types/src/datatypes/mod.rs @@ -25,6 +25,7 @@ mod mesh_properties; mod mesh_properties_ext; mod quaternion; mod quaternion_ext; +mod range1d; mod rgba32; mod rgba32_ext; mod rotation3d; @@ -73,6 +74,7 @@ pub use self::mat4x4::Mat4x4; pub use self::material::Material; pub use self::mesh_properties::MeshProperties; pub use self::quaternion::Quaternion; +pub use self::range1d::Range1D; pub use self::rgba32::Rgba32; pub use self::rotation3d::Rotation3D; pub use self::rotation_axis_angle::RotationAxisAngle; diff --git a/crates/re_types/src/datatypes/range1d.rs b/crates/re_types/src/datatypes/range1d.rs new file mode 100644 index 000000000000..54f239fa306b --- /dev/null +++ b/crates/re_types/src/datatypes/range1d.rs @@ -0,0 +1,213 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/datatypes/range1d.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Datatype**: A 1D range, specifying a lower and upper bound. +#[derive(Clone, Debug, Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] +#[repr(C)] +pub struct Range1D(pub [f64; 2usize]); + +impl ::re_types_core::SizeBytes for Range1D { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + <[f64; 2usize]>::is_pod() + } +} + +impl From<[f64; 2usize]> for Range1D { + #[inline] + fn from(range: [f64; 2usize]) -> Self { + Self(range) + } +} + +impl From for [f64; 2usize] { + #[inline] + fn from(value: Range1D) -> Self { + value.0 + } +} + +::re_types_core::macros::impl_into_cow!(Range1D); + +impl ::re_types_core::Loggable for Range1D { + type Name = ::re_types_core::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.datatypes.Range1D".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::FixedSizeList( + std::sync::Arc::new(Field::new("item", DataType::Float64, false)), + 2usize, + ) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data0): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + let datum = datum.map(|datum| { + let Self(data0) = datum.into_owned(); + data0 + }); + (datum.is_some(), datum) + }) + .unzip(); + let data0_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; + let data0_inner_data: Vec<_> = data0 + .iter() + .flat_map(|v| match v { + Some(v) => itertools::Either::Left(v.iter().cloned()), + None => itertools::Either::Right( + std::iter::repeat(Default::default()).take(2usize), + ), + }) + .map(Some) + .collect(); + let data0_inner_bitmap: Option = + data0_bitmap.as_ref().map(|bitmap| { + bitmap + .iter() + .map(|i| std::iter::repeat(i).take(2usize)) + .flatten() + .collect::>() + .into() + }); + FixedSizeListArray::new( + Self::arrow_datatype(), + PrimitiveArray::new( + DataType::Float64, + data0_inner_data + .into_iter() + .map(|v| v.unwrap_or_default()) + .collect(), + data0_inner_bitmap, + ) + .boxed(), + data0_bitmap, + ) + .boxed() + } + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok({ + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.Range1D#range")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let offsets = (0..) + .step_by(2usize) + .zip((2usize..).step_by(2usize).take(arrow_data.len())); + let arrow_data_inner = { + let arrow_data_inner = &**arrow_data.values(); + arrow_data_inner + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::Float64; + let actual = arrow_data_inner.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.Range1D#range")? + .into_iter() + .map(|opt| opt.copied()) + .collect::>() + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + offsets, + arrow_data.validity(), + ) + .map(|elem| { + elem.map(|(start, end)| { + debug_assert!(end - start == 2usize); + if end as usize > arrow_data_inner.len() { + return Err(DeserializationError::offset_slice_oob( + (start, end), + arrow_data_inner.len(), + )); + } + + #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + let data = + unsafe { arrow_data_inner.get_unchecked(start as usize..end as usize) }; + let data = data.iter().cloned().map(Option::unwrap_or_default); + let arr = array_init::from_iter(data).unwrap(); + Ok(arr) + }) + .transpose() + }) + .collect::>>>()? + } + .into_iter() + } + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.datatypes.Range1D#range") + .with_context("rerun.datatypes.Range1D")?) + } +} diff --git a/docs/content/reference/types/components/range1d.md b/docs/content/reference/types/components/range1d.md index 496f4a680f74..120e4d662445 100644 --- a/docs/content/reference/types/components/range1d.md +++ b/docs/content/reference/types/components/range1d.md @@ -6,7 +6,7 @@ A 1D range, specifying a lower and upper bound. ## Fields -* range: 2x `f64` +* range: [`Range1D`](../datatypes/range1d.md) ## Links * 🌊 [C++ API docs for `Range1D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Range1D.html) diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index 90467a297494..8b94d62c0251 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -23,6 +23,7 @@ Data types are the lowest layer of the data model hierarchy. They are re-usable * [`Material`](datatypes/material.md): Material properties of a mesh. * [`MeshProperties`](datatypes/mesh_properties.md): Optional triangle indices for a mesh. * [`Quaternion`](datatypes/quaternion.md): A Quaternion represented by 4 real numbers. +* [`Range1D`](datatypes/range1d.md): A 1D range, specifying a lower and upper bound. * [`Rgba32`](datatypes/rgba32.md): An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha. * [`Rotation3D`](datatypes/rotation3d.md): A 3D rotation. * [`RotationAxisAngle`](datatypes/rotation_axis_angle.md): 3D rotation represented by a rotation around a given axis. diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index 1ef35ab8e55a..e4b7aacfd945 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -16,6 +16,7 @@ mat4x4.md linguist-generated=true material.md linguist-generated=true mesh_properties.md linguist-generated=true quaternion.md linguist-generated=true +range1d.md linguist-generated=true rgba32.md linguist-generated=true rotation3d.md linguist-generated=true rotation_axis_angle.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/range1d.md b/docs/content/reference/types/datatypes/range1d.md new file mode 100644 index 000000000000..5360463b53bd --- /dev/null +++ b/docs/content/reference/types/datatypes/range1d.md @@ -0,0 +1,19 @@ +--- +title: "Range1D" +--- + +A 1D range, specifying a lower and upper bound. + +## Fields + +* range: 2x `f64` + +## Links + * 🌊 [C++ API docs for `Range1D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Range1D.html) + * 🐍 [Python API docs for `Range1D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Range1D) + * 🦀 [Rust API docs for `Range1D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Range1D.html) + + +## Used by + +* [`Range1D`](../components/range1d.md) diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index 7b4380fbe687..f4360986e2c4 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -20,7 +20,6 @@ grid_columns.cpp linguist-generated=true grid_columns.hpp linguist-generated=true included_content.hpp linguist-generated=true included_space_view.hpp linguist-generated=true -lock_range_during_zoom.cpp linguist-generated=true lock_range_during_zoom.hpp linguist-generated=true panel_expanded.hpp linguist-generated=true query_expression.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.cpp b/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.cpp deleted file mode 100644 index f44feac14b8e..000000000000 --- a/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/lock_range_during_zoom.fbs". - -#include "lock_range_during_zoom.hpp" - -#include -#include - -namespace rerun::blueprint::components {} - -namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { - static const auto datatype = arrow::boolean(); - return datatype; - } - - Result> - Loggable::to_arrow( - const blueprint::components::LockRangeDuringZoom* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::BooleanBuilder* builder, const blueprint::components::LockRangeDuringZoom* elements, - size_t num_elements - ) { - if (builder == nullptr) { - return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); - } - if (elements == nullptr) { - return rerun::Error( - ErrorCode::UnexpectedNullArgument, - "Cannot serialize null pointer to arrow array." - ); - } - - static_assert(sizeof(*elements) == sizeof(elements->lock_range)); - ARROW_RETURN_NOT_OK(builder->AppendValues( - reinterpret_cast(&elements->lock_range), - static_cast(num_elements) - )); - - return Error::ok(); - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.hpp b/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.hpp index 820ea6487f27..5661271f9406 100644 --- a/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/lock_range_during_zoom.hpp @@ -3,39 +3,47 @@ #pragma once +#include "../../datatypes/bool.hpp" #include "../../result.hpp" #include #include -namespace arrow { - class Array; - class BooleanBuilder; - class DataType; -} // namespace arrow - namespace rerun::blueprint::components { /// **Component**: Indicate whether the range should be locked when zooming in on the data. /// /// Default is `false`, i.e. zoom will change the visualized range. struct LockRangeDuringZoom { - bool lock_range; + rerun::datatypes::Bool lock_range; public: LockRangeDuringZoom() = default; - LockRangeDuringZoom(bool lock_range_) : lock_range(lock_range_) {} + LockRangeDuringZoom(rerun::datatypes::Bool lock_range_) : lock_range(lock_range_) {} - LockRangeDuringZoom& operator=(bool lock_range_) { + LockRangeDuringZoom& operator=(rerun::datatypes::Bool lock_range_) { lock_range = lock_range_; return *this; } + + LockRangeDuringZoom(bool value_) : lock_range(value_) {} + + LockRangeDuringZoom& operator=(bool value_) { + lock_range = value_; + return *this; + } + + /// Cast to the underlying Bool datatype + operator rerun::datatypes::Bool() const { + return lock_range; + } }; } // namespace rerun::blueprint::components namespace rerun { - template - struct Loggable; + static_assert( + sizeof(rerun::datatypes::Bool) == sizeof(blueprint::components::LockRangeDuringZoom) + ); /// \private template <> @@ -43,17 +51,18 @@ namespace rerun { static constexpr const char Name[] = "rerun.blueprint.components.LockRangeDuringZoom"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::blueprint:: components::LockRangeDuringZoom` into an arrow array. static Result> to_arrow( const blueprint::components::LockRangeDuringZoom* instances, size_t num_instances - ); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::BooleanBuilder* builder, - const blueprint::components::LockRangeDuringZoom* elements, size_t num_elements - ); + ) { + return Loggable::to_arrow( + &instances->lock_range, + num_instances + ); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/components/.gitattributes b/rerun_cpp/src/rerun/components/.gitattributes index c6655108354f..41b719504a0d 100644 --- a/rerun_cpp/src/rerun/components/.gitattributes +++ b/rerun_cpp/src/rerun/components/.gitattributes @@ -38,7 +38,6 @@ position2d.hpp linguist-generated=true position3d.hpp linguist-generated=true radius.cpp linguist-generated=true radius.hpp linguist-generated=true -range1d.cpp linguist-generated=true range1d.hpp linguist-generated=true resolution.hpp linguist-generated=true rotation3d.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/range1d.hpp b/rerun_cpp/src/rerun/components/range1d.hpp index 874fafbf18e4..6594ddee8237 100644 --- a/rerun_cpp/src/rerun/components/range1d.hpp +++ b/rerun_cpp/src/rerun/components/range1d.hpp @@ -3,38 +3,44 @@ #pragma once +#include "../datatypes/range1d.hpp" #include "../result.hpp" #include #include #include -namespace arrow { - class Array; - class DataType; - class FixedSizeListBuilder; -} // namespace arrow - namespace rerun::components { /// **Component**: A 1D range, specifying a lower and upper bound. struct Range1D { - std::array range; + rerun::datatypes::Range1D range; public: Range1D() = default; + Range1D(rerun::datatypes::Range1D range_) : range(range_) {} + + Range1D& operator=(rerun::datatypes::Range1D range_) { + range = range_; + return *this; + } + Range1D(std::array range_) : range(range_) {} Range1D& operator=(std::array range_) { range = range_; return *this; } + + /// Cast to the underlying Range1D datatype + operator rerun::datatypes::Range1D() const { + return range; + } }; } // namespace rerun::components namespace rerun { - template - struct Loggable; + static_assert(sizeof(rerun::datatypes::Range1D) == sizeof(components::Range1D)); /// \private template <> @@ -42,17 +48,15 @@ namespace rerun { static constexpr const char Name[] = "rerun.components.Range1D"; /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } /// Serializes an array of `rerun::components::Range1D` into an arrow array. static Result> to_arrow( const components::Range1D* instances, size_t num_instances - ); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Range1D* elements, - size_t num_elements - ); + ) { + return Loggable::to_arrow(&instances->range, num_instances); + } }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 81c850bdde6f..6c5f01a1c546 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -17,6 +17,7 @@ #include "datatypes/material.hpp" #include "datatypes/mesh_properties.hpp" #include "datatypes/quaternion.hpp" +#include "datatypes/range1d.hpp" #include "datatypes/rgba32.hpp" #include "datatypes/rotation3d.hpp" #include "datatypes/rotation_axis_angle.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 83fde1441f4b..108c39703f4c 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -31,6 +31,8 @@ mesh_properties.cpp linguist-generated=true mesh_properties.hpp linguist-generated=true quaternion.cpp linguist-generated=true quaternion.hpp linguist-generated=true +range1d.cpp linguist-generated=true +range1d.hpp linguist-generated=true rgba32.cpp linguist-generated=true rgba32.hpp linguist-generated=true rotation3d.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/range1d.cpp b/rerun_cpp/src/rerun/datatypes/range1d.cpp similarity index 75% rename from rerun_cpp/src/rerun/components/range1d.cpp rename to rerun_cpp/src/rerun/datatypes/range1d.cpp index 01bb5228f1fa..fab74b313f73 100644 --- a/rerun_cpp/src/rerun/components/range1d.cpp +++ b/rerun_cpp/src/rerun/datatypes/range1d.cpp @@ -1,22 +1,22 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/range1d.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/range1d.fbs". #include "range1d.hpp" #include #include -namespace rerun::components {} +namespace rerun::datatypes {} namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { + const std::shared_ptr& Loggable::arrow_datatype() { static const auto datatype = arrow::fixed_size_list(arrow::field("item", arrow::float64(), false), 2); return datatype; } - Result> Loggable::to_arrow( - const components::Range1D* instances, size_t num_instances + Result> Loggable::to_arrow( + const datatypes::Range1D* instances, size_t num_instances ) { // TODO(andreas): Allow configuring the memory pool. arrow::MemoryPool* pool = arrow::default_memory_pool(); @@ -24,7 +24,7 @@ namespace rerun { ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( static_cast(builder.get()), instances, num_instances @@ -35,8 +35,8 @@ namespace rerun { return array; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::FixedSizeListBuilder* builder, const components::Range1D* elements, + rerun::Error Loggable::fill_arrow_array_builder( + arrow::FixedSizeListBuilder* builder, const datatypes::Range1D* elements, size_t num_elements ) { if (builder == nullptr) { diff --git a/rerun_cpp/src/rerun/datatypes/range1d.hpp b/rerun_cpp/src/rerun/datatypes/range1d.hpp new file mode 100644 index 000000000000..1e35db079712 --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/range1d.hpp @@ -0,0 +1,58 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/datatypes/range1d.fbs". + +#pragma once + +#include "../result.hpp" + +#include +#include +#include + +namespace arrow { + class Array; + class DataType; + class FixedSizeListBuilder; +} // namespace arrow + +namespace rerun::datatypes { + /// **Datatype**: A 1D range, specifying a lower and upper bound. + struct Range1D { + std::array range; + + public: + Range1D() = default; + + Range1D(std::array range_) : range(range_) {} + + Range1D& operator=(std::array range_) { + range = range_; + return *this; + } + }; +} // namespace rerun::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.Range1D"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::datatypes::Range1D` into an arrow array. + static Result> to_arrow( + const datatypes::Range1D* instances, size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::FixedSizeListBuilder* builder, const datatypes::Range1D* elements, + size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/_validators.py b/rerun_py/rerun_sdk/rerun/_validators.py index e0c0c92326ef..a5967cd5db06 100644 --- a/rerun_py/rerun_sdk/rerun/_validators.py +++ b/rerun_py/rerun_sdk/rerun/_validators.py @@ -5,7 +5,7 @@ import numpy as np import numpy.typing as npt -from ._converters import to_np_float32 +from ._converters import to_np_float32, to_np_float64 # This code is a straight port from Rust. @@ -46,13 +46,20 @@ def find_non_empty_dim_indices(shape: list[int]) -> list[int]: return list(range(min, max + 1)) -def flat_np_float_array_from_array_like(data: Any, dimension: int) -> npt.NDArray[np.float32]: +def flat_np_float32_array_from_array_like(data: Any, dimension: int) -> npt.NDArray[np.float32]: """Converts to a flat float numpy array from an arbitrary vector, validating for an expected dimensionality.""" array = to_np_float32(data) return flat_np_array_from_array_like(array, dimension) +def flat_np_float64_array_from_array_like(data: Any, dimension: int) -> npt.NDArray[np.float64]: + """Converts to a flat float numpy array from an arbitrary vector, validating for an expected dimensionality.""" + + array = to_np_float64(data) + return flat_np_array_from_array_like(array, dimension) + + def flat_np_array_from_array_like(array: npt.NDArray[Any], dimension: int) -> npt.NDArray[Any]: """Converts to a flat numpy array from an arbitrary vector, validating for an expected dimensionality.""" diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 330b638c2c2c..71c4fc2e4ff8 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -14,9 +14,13 @@ ) from .archetypes import ( Background3D, + PlotLegend, + ScalarAxis, ) from .components import ( Background3DKind, + Corner2D, + LockRangeDuringZoom, ) from .containers import Grid, Horizontal, Tabs, Vertical from .views import ( 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 e97ac8a9bc9d..c752f9323b5d 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend.py @@ -5,48 +5,20 @@ from __future__ import annotations -from typing import Any - from attrs import define, field 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"] @define(str=False, repr=False, init=False) -class PlotLegend(Archetype): +class PlotLegend(PlotLegendExt, Archetype): """**Archetype**: Configuration for the legend of a plot.""" - def __init__( - self: Any, - *, - corner: blueprint_components.Corner2DLike | None = None, - visible: blueprint_components.VisibleLike | None = None, - ): - """ - Create a new instance of the PlotLegend archetype. - - Parameters - ---------- - 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. - - """ - - # You can define your own __init__ function as a member of PlotLegendExt in plot_legend_ext.py - with catch_and_log_exceptions(context=self.__class__.__name__): - self.__attrs_init__(corner=corner, visible=visible) - return - self.__attrs_clear__() + # __init__ can be found in plot_legend_ext.py def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend_ext.py new file mode 100644 index 000000000000..e955aab70751 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/plot_legend_ext.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +from typing import Any + +from ...blueprint import components as blueprint_components +from ...error_utils import catch_and_log_exceptions + + +class PlotLegendExt: + """Extension for [PlotLegend][rerun.blueprint.archetypes.PlotLegend].""" + + def __init__( + self: Any, + corner: blueprint_components.Corner2DLike | None = None, + *, + visible: blueprint_components.VisibleLike | None = None, + ): + """ + Create a new instance of the PlotLegend archetype. + + Parameters + ---------- + 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. + + """ + + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(corner=corner, visible=visible) + return + self.__attrs_clear__() 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 77e0fe6c7556..0c98996d0dde 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/scalar_axis.py @@ -9,7 +9,7 @@ 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 @@ -24,8 +24,8 @@ class ScalarAxis(Archetype): def __init__( self: Any, *, - range: components.Range1DLike | None = None, - lock_range_during_zoom: blueprint_components.LockRangeDuringZoomLike | None = None, + range: datatypes.Range1DLike | None = None, + lock_range_during_zoom: datatypes.BoolLike | None = None, ): """ Create a new instance of the ScalarAxis archetype. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index 1dbd8f8d98c3..3d6a535018eb 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -37,13 +37,7 @@ from .grid_columns import GridColumns, GridColumnsArrayLike, GridColumnsBatch, GridColumnsLike, GridColumnsType from .included_content import IncludedContent, IncludedContentBatch, IncludedContentType from .included_space_view import IncludedSpaceView, IncludedSpaceViewBatch, IncludedSpaceViewType -from .lock_range_during_zoom import ( - LockRangeDuringZoom, - LockRangeDuringZoomArrayLike, - LockRangeDuringZoomBatch, - LockRangeDuringZoomLike, - LockRangeDuringZoomType, -) +from .lock_range_during_zoom import LockRangeDuringZoom, LockRangeDuringZoomBatch, LockRangeDuringZoomType from .panel_expanded import PanelExpanded, PanelExpandedBatch, PanelExpandedType from .query_expression import QueryExpression, QueryExpressionBatch, QueryExpressionType from .root_container import RootContainer, RootContainerBatch, RootContainerType @@ -110,9 +104,7 @@ "IncludedSpaceViewBatch", "IncludedSpaceViewType", "LockRangeDuringZoom", - "LockRangeDuringZoomArrayLike", "LockRangeDuringZoomBatch", - "LockRangeDuringZoomLike", "LockRangeDuringZoomType", "PanelExpanded", "PanelExpandedBatch", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/lock_range_during_zoom.py b/rerun_py/rerun_sdk/rerun/blueprint/components/lock_range_during_zoom.py index 657d5d9dea7b..0a91e50decaa 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/lock_range_during_zoom.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/lock_range_during_zoom.py @@ -5,59 +5,28 @@ from __future__ import annotations -from typing import Any, Sequence, Union +from ... import datatypes +from ..._baseclasses import ComponentBatchMixin -import pyarrow as pa -from attrs import define, field +__all__ = ["LockRangeDuringZoom", "LockRangeDuringZoomBatch", "LockRangeDuringZoomType"] -from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -__all__ = [ - "LockRangeDuringZoom", - "LockRangeDuringZoomArrayLike", - "LockRangeDuringZoomBatch", - "LockRangeDuringZoomLike", - "LockRangeDuringZoomType", -] - - -@define(init=False) -class LockRangeDuringZoom: +class LockRangeDuringZoom(datatypes.Bool): """ **Component**: Indicate whether the range should be locked when zooming in on the data. Default is `false`, i.e. zoom will change the visualized range. """ - def __init__(self: Any, lock_range: LockRangeDuringZoomLike): - """Create a new instance of the LockRangeDuringZoom component.""" - - # You can define your own __init__ function as a member of LockRangeDuringZoomExt in lock_range_during_zoom_ext.py - self.__attrs_init__(lock_range=lock_range) - - def __bool__(self) -> bool: - return self.lock_range + # You can define your own __init__ function as a member of LockRangeDuringZoomExt in lock_range_during_zoom_ext.py - lock_range: bool = field(converter=bool) + # Note: there are no fields here because LockRangeDuringZoom delegates to datatypes.Bool + pass -LockRangeDuringZoomLike = LockRangeDuringZoom -LockRangeDuringZoomArrayLike = Union[ - LockRangeDuringZoom, - Sequence[LockRangeDuringZoomLike], -] - - -class LockRangeDuringZoomType(BaseExtensionType): +class LockRangeDuringZoomType(datatypes.BoolType): _TYPE_NAME: str = "rerun.blueprint.components.LockRangeDuringZoom" - def __init__(self) -> None: - pa.ExtensionType.__init__(self, pa.bool_(), self._TYPE_NAME) - -class LockRangeDuringZoomBatch(BaseBatch[LockRangeDuringZoomArrayLike], ComponentBatchMixin): +class LockRangeDuringZoomBatch(datatypes.BoolBatch, ComponentBatchMixin): _ARROW_TYPE = LockRangeDuringZoomType() - - @staticmethod - def _native_to_pa_array(data: LockRangeDuringZoomArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in lock_range_during_zoom_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py index 3524acbd0439..37b42559b0a0 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py @@ -8,6 +8,7 @@ from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like +from .. import archetypes as blueprint_archetypes from .. import components as blueprint_components from ..api import SpaceView, SpaceViewContentsLike @@ -22,6 +23,8 @@ def __init__( contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, visible: blueprint_components.VisibleLike | None = None, + axis_y: blueprint_archetypes.ScalarAxis | None = None, + plot_legend: blueprint_archetypes.PlotLegend | blueprint_components.Corner2D | None = None, ) -> None: """ Construct a blueprint for a new TimeSeriesView view. @@ -41,10 +44,24 @@ def __init__( Whether this view is visible. Defaults to true if not specified. + axis_y: + Configures the vertical axis of the plot. + plot_legend: + Configures the legend of the plot. """ properties: dict[str, AsComponents] = {} + if axis_y is not None: + if not isinstance(axis_y, blueprint_archetypes.ScalarAxis): + axis_y = blueprint_archetypes.ScalarAxis(axis_y) + properties["ScalarAxis"] = axis_y + + if plot_legend is not None: + if not isinstance(plot_legend, blueprint_archetypes.PlotLegend): + plot_legend = blueprint_archetypes.PlotLegend(plot_legend) + properties["PlotLegend"] = plot_legend + super().__init__( class_identifier="TimeSeries", origin=origin, diff --git a/rerun_py/rerun_sdk/rerun/components/__init__.py b/rerun_py/rerun_sdk/rerun/components/__init__.py index 864da37209ef..27cfabb1b894 100644 --- a/rerun_py/rerun_sdk/rerun/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/components/__init__.py @@ -45,7 +45,7 @@ from .position2d import Position2D, Position2DBatch, Position2DType from .position3d import Position3D, Position3DBatch, Position3DType from .radius import Radius, RadiusArrayLike, RadiusBatch, RadiusLike, RadiusType -from .range1d import Range1D, Range1DArrayLike, Range1DBatch, Range1DLike, Range1DType +from .range1d import Range1D, Range1DBatch, Range1DType from .resolution import Resolution, ResolutionBatch, ResolutionType from .rotation3d import Rotation3D, Rotation3DBatch, Rotation3DType from .scalar import Scalar, ScalarArrayLike, ScalarBatch, ScalarLike, ScalarType @@ -180,9 +180,7 @@ "RadiusLike", "RadiusType", "Range1D", - "Range1DArrayLike", "Range1DBatch", - "Range1DLike", "Range1DType", "Resolution", "ResolutionBatch", diff --git a/rerun_py/rerun_sdk/rerun/components/range1d.py b/rerun_py/rerun_sdk/rerun/components/range1d.py index ff35cb5c5173..f2241d6363fe 100644 --- a/rerun_py/rerun_sdk/rerun/components/range1d.py +++ b/rerun_py/rerun_sdk/rerun/components/range1d.py @@ -5,57 +5,24 @@ from __future__ import annotations -from typing import Any, Sequence, Union +from .. import datatypes +from .._baseclasses import ComponentBatchMixin -import numpy as np -import numpy.typing as npt -import pyarrow as pa -from attrs import define, field +__all__ = ["Range1D", "Range1DBatch", "Range1DType"] -from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .._converters import ( - to_np_float64, -) -__all__ = ["Range1D", "Range1DArrayLike", "Range1DBatch", "Range1DLike", "Range1DType"] - - -@define(init=False) -class Range1D: +class Range1D(datatypes.Range1D): """**Component**: A 1D range, specifying a lower and upper bound.""" - def __init__(self: Any, range: Range1DLike): - """Create a new instance of the Range1D component.""" - - # You can define your own __init__ function as a member of Range1DExt in range1d_ext.py - self.__attrs_init__(range=range) - - range: npt.NDArray[np.float64] = field(converter=to_np_float64) + # You can define your own __init__ function as a member of Range1DExt in range1d_ext.py - def __array__(self, dtype: npt.DTypeLike = None) -> npt.NDArray[Any]: - # You can define your own __array__ function as a member of Range1DExt in range1d_ext.py - return np.asarray(self.range, dtype=dtype) + # Note: there are no fields here because Range1D delegates to datatypes.Range1D + pass -Range1DLike = Range1D -Range1DArrayLike = Union[ - Range1D, - Sequence[Range1DLike], -] - - -class Range1DType(BaseExtensionType): +class Range1DType(datatypes.Range1DType): _TYPE_NAME: str = "rerun.components.Range1D" - def __init__(self) -> None: - pa.ExtensionType.__init__( - self, pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), self._TYPE_NAME - ) - -class Range1DBatch(BaseBatch[Range1DArrayLike], ComponentBatchMixin): +class Range1DBatch(datatypes.Range1DBatch, ComponentBatchMixin): _ARROW_TYPE = Range1DType() - - @staticmethod - def _native_to_pa_array(data: Range1DArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in range1d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index 74fd88d4d968..d5a5eadf37f6 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -17,6 +17,7 @@ mat4x4.py linguist-generated=true material.py linguist-generated=true mesh_properties.py linguist-generated=true quaternion.py linguist-generated=true +range1d.py linguist-generated=true rgba32.py linguist-generated=true rotation3d.py linguist-generated=true rotation_axis_angle.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index 31fb9e4f05e4..58f639584e8b 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -41,6 +41,7 @@ MeshPropertiesType, ) from .quaternion import Quaternion, QuaternionArrayLike, QuaternionBatch, QuaternionLike, QuaternionType +from .range1d import Range1D, Range1DArrayLike, Range1DBatch, Range1DLike, Range1DType from .rgba32 import Rgba32, Rgba32ArrayLike, Rgba32Batch, Rgba32Like, Rgba32Type from .rotation3d import Rotation3D, Rotation3DArrayLike, Rotation3DBatch, Rotation3DLike, Rotation3DType from .rotation_axis_angle import ( @@ -163,6 +164,11 @@ "QuaternionBatch", "QuaternionLike", "QuaternionType", + "Range1D", + "Range1DArrayLike", + "Range1DBatch", + "Range1DLike", + "Range1DType", "Rgba32", "Rgba32ArrayLike", "Rgba32Batch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/quaternion_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/quaternion_ext.py index 0db43d66dd92..089020154002 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/quaternion_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/quaternion_ext.py @@ -6,7 +6,7 @@ import numpy.typing as npt import pyarrow as pa -from .._validators import flat_np_float_array_from_array_like +from .._validators import flat_np_float32_array_from_array_like if TYPE_CHECKING: from . import Quaternion, QuaternionArrayLike @@ -34,5 +34,5 @@ def native_to_pa_array_override(data: QuaternionArrayLike, data_type: pa.DataTyp if isinstance(data, Quaternion): data = [data] - quaternions = flat_np_float_array_from_array_like([q.xyzw for q in data], 4) + quaternions = flat_np_float32_array_from_array_like([q.xyzw for q in data], 4) return pa.FixedSizeListArray.from_arrays(quaternions, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/range1d.py b/rerun_py/rerun_sdk/rerun/datatypes/range1d.py new file mode 100644 index 000000000000..a0c2aec53ae5 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/range1d.py @@ -0,0 +1,65 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/datatypes/range1d.fbs". + +# You can extend this class by creating a "Range1DExt" class in "range1d_ext.py". + +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Sequence, Union + +import numpy as np +import numpy.typing as npt +import pyarrow as pa +from attrs import define, field + +from .._baseclasses import BaseBatch, BaseExtensionType +from .._converters import ( + to_np_float64, +) +from .range1d_ext import Range1DExt + +__all__ = ["Range1D", "Range1DArrayLike", "Range1DBatch", "Range1DLike", "Range1DType"] + + +@define(init=False) +class Range1D(Range1DExt): + """**Datatype**: A 1D range, specifying a lower and upper bound.""" + + def __init__(self: Any, range: Range1DLike): + """Create a new instance of the Range1D datatype.""" + + # You can define your own __init__ function as a member of Range1DExt in range1d_ext.py + self.__attrs_init__(range=range) + + range: npt.NDArray[np.float64] = field(converter=to_np_float64) + + def __array__(self, dtype: npt.DTypeLike = None) -> npt.NDArray[Any]: + # You can define your own __array__ function as a member of Range1DExt in range1d_ext.py + return np.asarray(self.range, dtype=dtype) + + +if TYPE_CHECKING: + Range1DLike = Union[Range1D, npt.NDArray[Any], npt.ArrayLike, Sequence[float], slice] +else: + Range1DLike = Any + +Range1DArrayLike = Union[ + Range1D, Sequence[Range1DLike], npt.NDArray[Any], npt.ArrayLike, Sequence[Sequence[float]], Sequence[float] +] + + +class Range1DType(BaseExtensionType): + _TYPE_NAME: str = "rerun.datatypes.Range1D" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), self._TYPE_NAME + ) + + +class Range1DBatch(BaseBatch[Range1DArrayLike]): + _ARROW_TYPE = Range1DType() + + @staticmethod + def _native_to_pa_array(data: Range1DArrayLike, data_type: pa.DataType) -> pa.Array: + return Range1DExt.native_to_pa_array_override(data, data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/range1d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/range1d_ext.py new file mode 100644 index 000000000000..6499d0ac4fca --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/range1d_ext.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import pyarrow as pa + +from .._validators import flat_np_float64_array_from_array_like + +if TYPE_CHECKING: + from . import Range1DArrayLike + + +class Range1DExt: + """Extension for [Range1D][rerun.datatypes.Range1D].""" + + @staticmethod + def native_to_pa_array_override(data: Range1DArrayLike, data_type: pa.DataType) -> pa.Array: + if isinstance(data, slice): + if data.step is not None and data.step != 1: + raise ValueError("Steps other than 1 are not supported for Range1D.") + data = [data.start, data.stop] + + ranges = flat_np_float64_array_from_array_like(data, 2) + return pa.FixedSizeListArray.from_arrays(ranges, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/vec2d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/vec2d_ext.py index 4f263e296ef6..76bf3eae22b1 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/vec2d_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/vec2d_ext.py @@ -5,7 +5,7 @@ import numpy as np import pyarrow as pa -from .._validators import flat_np_float_array_from_array_like +from .._validators import flat_np_float32_array_from_array_like if TYPE_CHECKING: from . import Vec2DArrayLike @@ -28,5 +28,5 @@ def native_to_pa_array_override(data: Vec2DArrayLike, data_type: pa.DataType) -> if isinstance(data, Sequence): data = [np.array(p.xy) if isinstance(p, Vec2D) else p for p in data] - points = flat_np_float_array_from_array_like(data, 2) + points = flat_np_float32_array_from_array_like(data, 2) return pa.FixedSizeListArray.from_arrays(points, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/vec3d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/vec3d_ext.py index 2cf1fad619ca..9dfffbebfaf1 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/vec3d_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/vec3d_ext.py @@ -5,7 +5,7 @@ import numpy as np import pyarrow as pa -from .._validators import flat_np_float_array_from_array_like +from .._validators import flat_np_float32_array_from_array_like if TYPE_CHECKING: from . import Vec3DArrayLike @@ -28,5 +28,5 @@ def native_to_pa_array_override(data: Vec3DArrayLike, data_type: pa.DataType) -> if isinstance(data, Sequence): data = [np.array(p.xyz) if isinstance(p, Vec3D) else p for p in data] - points = flat_np_float_array_from_array_like(data, 3) + points = flat_np_float32_array_from_array_like(data, 3) return pa.FixedSizeListArray.from_arrays(points, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/vec4d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/vec4d_ext.py index 83f85bb0f5bb..846439b9dd9f 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/vec4d_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/vec4d_ext.py @@ -5,7 +5,7 @@ import numpy as np import pyarrow as pa -from .._validators import flat_np_float_array_from_array_like +from .._validators import flat_np_float32_array_from_array_like if TYPE_CHECKING: from . import Vec4DArrayLike @@ -28,5 +28,5 @@ def native_to_pa_array_override(data: Vec4DArrayLike, data_type: pa.DataType) -> if isinstance(data, Sequence): data = [np.array(p.xyzw) if isinstance(p, Vec4D) else p for p in data] - points = flat_np_float_array_from_array_like(data, 4) + points = flat_np_float32_array_from_array_like(data, 4) return pa.FixedSizeListArray.from_arrays(points, type=data_type) diff --git a/rerun_py/tests/unit/test_plot_legend.py b/rerun_py/tests/unit/test_plot_legend.py new file mode 100644 index 000000000000..78c0fb6f3238 --- /dev/null +++ b/rerun_py/tests/unit/test_plot_legend.py @@ -0,0 +1,50 @@ +from __future__ import annotations + +import itertools +from typing import Optional, cast + +import rerun as rr +import rerun.blueprint as rrb +from rerun.blueprint import components as blueprint_components + +from .common_arrays import none_empty_or_value + + +def test_scalar_axis() -> None: + rr.set_strict_mode(True) + + corners = [ + rrb.Corner2D.LeftTop, + "lefttop", + None, + ] + visible_array = [ + None, + True, + ] + + all_arrays = itertools.zip_longest( + corners, + visible_array, + ) + + for corner, visible in all_arrays: + corner = cast(Optional[blueprint_components.Corner2DLike], corner) + visible = cast(Optional[blueprint_components.VisibleLike], visible) + + print( + f"rr.PlotLegend(\n" + f" corner={corner!r}\n" # + f" visible={visible!r}\n" + f")" + ) + arch = rrb.PlotLegend( + corner=corner, + visible=visible, + ) + print(f"{arch}\n") + + assert arch.corner == blueprint_components.Corner2DBatch._optional( + none_empty_or_value(corner, rrb.Corner2D.LeftTop) + ) + assert arch.visible == blueprint_components.VisibleBatch._optional(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 new file mode 100644 index 000000000000..d82abe4fac95 --- /dev/null +++ b/rerun_py/tests/unit/test_scalar_axis.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import itertools +from typing import Optional, cast + +import numpy as np +import rerun as rr +import rerun.blueprint as rrb + +from .common_arrays import none_empty_or_value + + +def test_scalar_axis() -> None: + rr.set_strict_mode(True) + + # All from 42.1337 to 1337.42, but expressed differently + ranges = [ + (42.1337, 1337.42), + [42.1337, 1337.42], + np.array([42.1337, 1337.42]), + rr.components.Range1D([42.1337, 1337.42]), + None, + ] + lock_range_during_zooms = [ + True, + False, + ] + + all_arrays = itertools.zip_longest( + ranges, + lock_range_during_zooms, + ) + + for range, lock_range_during_zoom in all_arrays: + range = cast(Optional[rr.datatypes.Range1DLike], range) + lock_range_during_zoom = cast(Optional[rr.datatypes.Bool], lock_range_during_zoom) + + print( + f"rr.ScalarAxis(\n" + f" range={range!r}\n" # + f" lock_range_during_zoom={lock_range_during_zoom!r}\n" + f")" + ) + arch = rrb.ScalarAxis( + range=range, + lock_range_during_zoom=lock_range_during_zoom, + ) + print(f"{arch}\n") + + assert arch.range == rr.components.Range1DBatch._optional(none_empty_or_value(range, [42.1337, 1337.42])) + assert arch.lock_range_during_zoom == rrb.components.LockRangeDuringZoomBatch._optional(lock_range_during_zoom) From c203d4e6866482031ff23e7b97c2fd9b4ec5dbdf Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 26 Apr 2024 11:27:18 +0200 Subject: [PATCH 366/508] Change background of 2D space views from code and/or UI (#6116) ### What * closes https://github.com/rerun-io/rerun/issues/6113 Very similar to 3D space views, even using the same gradient by default. Usage: ```py rrb.Spatial2DView(origin="/foo", background=[32, 0, 16]) ``` The default background color is still BLACK. --- Here the dark gradient is used. It looks a little bit too much like the 3D space view. Screenshot 2024-04-25 at 18 12 05 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6116?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6116?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6116) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Andreas Reich --- .../src/latest_at/to_archetype/.gitattributes | 2 +- .../{background3d.rs => background.rs} | 14 ++-- .../src/latest_at/to_archetype/mod.rs | 2 +- crates/re_space_view/src/lib.rs | 2 +- crates/re_space_view/src/sub_archetypes.rs | 17 ++++ crates/re_space_view_spatial/src/lib.rs | 44 ++++++++++ .../src/space_view_2d.rs | 8 +- .../src/space_view_3d.rs | 82 ++---------------- crates/re_space_view_spatial/src/ui.rs | 84 +++++++++++++++++-- crates/re_space_view_spatial/src/ui_2d.rs | 14 +++- crates/re_space_view_spatial/src/ui_3d.rs | 72 +++------------- .../re_types/definitions/rerun/blueprint.fbs | 4 +- .../{background_3d.fbs => background.fbs} | 13 +-- ...ground_3d_kind.fbs => background_kind.fbs} | 14 ++-- .../rerun/blueprint/views/spatial2d.fbs | 2 + .../rerun/blueprint/views/spatial3d.fbs | 4 +- .../src/blueprint/archetypes/.gitattributes | 2 +- .../{background3d.rs => background.rs} | 58 ++++++------- .../blueprint/archetypes/background3d_ext.rs | 17 ---- .../blueprint/archetypes/background_ext.rs | 23 +++++ .../re_types/src/blueprint/archetypes/mod.rs | 6 +- .../src/blueprint/components/.gitattributes | 2 +- ...ackground3d_kind.rs => background_kind.rs} | 41 ++++----- .../re_types/src/blueprint/components/mod.rs | 4 +- .../src/blueprint/validation_gen/mod.rs | 4 +- examples/python/rrt_star/rrt_star.py | 2 +- rerun_cpp/src/rerun/blueprint/archetypes.hpp | 2 +- .../rerun/blueprint/archetypes/.gitattributes | 4 +- .../{background3d.cpp => background.cpp} | 10 +-- .../{background3d.hpp => background.hpp} | 30 +++---- rerun_cpp/src/rerun/blueprint/components.hpp | 2 +- .../rerun/blueprint/components/.gitattributes | 4 +- ...kground3d_kind.cpp => background_kind.cpp} | 19 ++--- ...kground3d_kind.hpp => background_kind.hpp} | 24 +++--- .../rerun_sdk/rerun/blueprint/__init__.py | 4 +- .../rerun/blueprint/archetypes/.gitattributes | 2 +- .../rerun/blueprint/archetypes/__init__.py | 4 +- .../{background3d.py => background.py} | 26 +++--- ...{background3d_ext.py => background_ext.py} | 24 +++--- .../rerun/blueprint/components/.gitattributes | 2 +- .../rerun/blueprint/components/__init__.py | 22 ++--- ...ackground3d_kind.py => background_kind.py} | 62 ++++++++------ .../rerun/blueprint/views/spatial2d_view.py | 13 +++ .../rerun/blueprint/views/spatial3d_view.py | 12 +-- rerun_py/tests/unit/test_background.py | 23 +++++ rerun_py/tests/unit/test_background3d.py | 25 ------ 46 files changed, 463 insertions(+), 388 deletions(-) rename crates/re_query_cache2/src/latest_at/to_archetype/{background3d.rs => background.rs} (85%) rename crates/re_types/definitions/rerun/blueprint/archetypes/{background_3d.fbs => background.fbs} (58%) rename crates/re_types/definitions/rerun/blueprint/components/{background_3d_kind.fbs => background_kind.fbs} (51%) rename crates/re_types/src/blueprint/archetypes/{background3d.rs => background.rs} (78%) delete mode 100644 crates/re_types/src/blueprint/archetypes/background3d_ext.rs create mode 100644 crates/re_types/src/blueprint/archetypes/background_ext.rs rename crates/re_types/src/blueprint/components/{background3d_kind.rs => background_kind.rs} (83%) rename rerun_cpp/src/rerun/blueprint/archetypes/{background3d.cpp => background.cpp} (83%) rename rerun_cpp/src/rerun/blueprint/archetypes/{background3d.hpp => background.hpp} (64%) rename rerun_cpp/src/rerun/blueprint/components/{background3d_kind.cpp => background_kind.cpp} (78%) rename rerun_cpp/src/rerun/blueprint/components/{background3d_kind.hpp => background_kind.hpp} (64%) rename rerun_py/rerun_sdk/rerun/blueprint/archetypes/{background3d.py => background.py} (63%) rename rerun_py/rerun_sdk/rerun/blueprint/archetypes/{background3d_ext.py => background_ext.py} (64%) rename rerun_py/rerun_sdk/rerun/blueprint/components/{background3d_kind.py => background_kind.py} (54%) create mode 100644 rerun_py/tests/unit/test_background.py delete mode 100644 rerun_py/tests/unit/test_background3d.py diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes b/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes index b258bf0350f5..d8ec507351e3 100644 --- a/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes +++ b/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes @@ -5,7 +5,7 @@ annotation_context.rs linguist-generated=true arrows2d.rs linguist-generated=true arrows3d.rs linguist-generated=true asset3d.rs linguist-generated=true -background3d.rs linguist-generated=true +background.rs linguist-generated=true bar_chart.rs linguist-generated=true boxes2d.rs linguist-generated=true boxes3d.rs linguist-generated=true diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/background3d.rs b/crates/re_query_cache2/src/latest_at/to_archetype/background.rs similarity index 85% rename from crates/re_query_cache2/src/latest_at/to_archetype/background3d.rs rename to crates/re_query_cache2/src/latest_at/to_archetype/background.rs index d2317c1149b6..2494ac25b0e9 100644 --- a/crates/re_query_cache2/src/latest_at/to_archetype/background3d.rs +++ b/crates/re_query_cache2/src/latest_at/to_archetype/background.rs @@ -10,22 +10,22 @@ use re_query2::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for CachedLatestAtResults { #[inline] fn to_archetype( &self, resolver: &PromiseResolver, - ) -> PromiseResult> { - re_tracing::profile_function!(::name()); + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); // --- Required --- - use re_types::blueprint::components::Background3DKind; - let kind = match self.get_required(::name()) { + use re_types::blueprint::components::BackgroundKind; + let kind = match self.get_required(::name()) { Ok(kind) => kind, Err(query_err) => return PromiseResult::Ready(Err(query_err)), }; - let kind = match kind.to_dense::(resolver) { + let kind = match kind.to_dense::(resolver) { PromiseResult::Pending => return PromiseResult::Pending, PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), PromiseResult::Ready(query_res) => match query_res { @@ -59,7 +59,7 @@ impl crate::ToArchetype for Cache // --- - let arch = re_types::blueprint::archetypes::Background3D { kind, color }; + let arch = re_types::blueprint::archetypes::Background { kind, color }; PromiseResult::Ready(Ok(arch)) } diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs b/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs index b4e4e8b5a695..62d7ff7df884 100644 --- a/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs +++ b/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs @@ -4,7 +4,7 @@ mod annotation_context; mod arrows2d; mod arrows3d; mod asset3d; -mod background3d; +mod background; mod bar_chart; mod boxes2d; mod boxes3d; diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 322894c3ea78..25255c2a8358 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -19,7 +19,7 @@ pub use space_view::SpaceViewBlueprint; pub use space_view_contents::SpaceViewContents; pub use sub_archetypes::{ entity_path_for_space_view_sub_archetype, query_space_view_sub_archetype, - query_space_view_sub_archetype_or_default, + query_space_view_sub_archetype_or_default, space_view_sub_archetype, }; pub use visual_time_range::{ query_visual_history, time_range_boundary_to_visible_history_boundary, diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 1da0a8d04ab3..f1fff5423f9b 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -22,6 +22,23 @@ pub fn entity_path_for_space_view_sub_archetype( space_view_blueprint_path.join(&EntityPath::from_single_string(T::name().short_name())) } +/// Return the archetype value for the given space view, or `None` if it doesn't exist. +pub fn space_view_sub_archetype( + ctx: &re_viewer_context::ViewerContext<'_>, + space_view_id: re_viewer_context::SpaceViewId, +) -> Option +where + CachedLatestAtResults: ToArchetype, +{ + let blueprint_db = ctx.store_context.blueprint; + let blueprint_query = ctx.blueprint_query; + let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); + blueprint_db + .latest_at_archetype(&path, blueprint_query) + .ok() + .flatten() +} + /// Returns `Ok(None)` if any of the required components are missing. pub fn query_space_view_sub_archetype( space_view_id: SpaceViewId, diff --git a/crates/re_space_view_spatial/src/lib.rs b/crates/re_space_view_spatial/src/lib.rs index 53ea9688bbdc..2a2ca322342c 100644 --- a/crates/re_space_view_spatial/src/lib.rs +++ b/crates/re_space_view_spatial/src/lib.rs @@ -20,7 +20,9 @@ mod ui_2d; mod ui_3d; mod visualizers; +use re_types::blueprint::archetypes::Background; use re_types::components::{Resolution, TensorData}; + pub use space_view_2d::SpatialSpaceView2D; pub use space_view_3d::SpatialSpaceView3D; @@ -75,3 +77,45 @@ fn query_pinhole( .map(|c| c.value), }) } + +pub(crate) fn configure_background( + ctx: &re_viewer_context::ViewerContext<'_>, + background: re_types::blueprint::archetypes::Background, +) -> (Option, re_renderer::Rgba) { + use re_renderer::renderer; + use re_types::blueprint::components::BackgroundKind; + + let Background { kind, color } = background; + + match kind { + BackgroundKind::GradientDark => ( + Some( + renderer::GenericSkyboxDrawData::new( + ctx.render_ctx, + renderer::GenericSkyboxType::GradientDark, + ) + .into(), + ), + re_renderer::Rgba::TRANSPARENT, // All zero is slightly faster to clear usually. + ), + + BackgroundKind::GradientBright => ( + Some( + renderer::GenericSkyboxDrawData::new( + ctx.render_ctx, + renderer::GenericSkyboxType::GradientBright, + ) + .into(), + ), + re_renderer::Rgba::TRANSPARENT, // All zero is slightly faster to clear usually. + ), + + BackgroundKind::SolidColor => ( + None, + // If the user has told us to use a solid color, but hasn't picked a specific color, + // we need to fall back to something. For dark mode, black makes sense. + // TODO(#3058): support light mode + color.unwrap_or(re_types::components::Color::BLACK).into(), + ), + } +} diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index 431c92ad05ed..62d07852501c 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -6,6 +6,7 @@ use re_format::format_f32; use re_log_types::EntityPath; use re_types::{ archetypes::{DepthImage, Image}, + blueprint::archetypes::Background, Archetype, ComponentName, }; use re_viewer_context::{ @@ -240,14 +241,17 @@ impl SpaceViewClass for SpatialSpaceView2D { ui: &mut egui::Ui, state: &mut dyn SpaceViewState, _space_origin: &EntityPath, - _space_view_id: SpaceViewId, + space_view_id: SpaceViewId, _root_entity_properties: &mut EntityProperties, ) -> Result<(), SpaceViewSystemExecutionError> { let state = state.downcast_mut::()?; ctx.re_ui .selection_grid(ui, "spatial_settings_ui") .show(ui, |ui| { - state.default_size_ui(ctx, ui); + state.default_sizes_ui(ctx, ui); + + crate::ui::background_ui(ctx, ui, space_view_id, Background::DEFAULT_2D); + state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::TwoD); { diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 47dd77d59172..164fa47569f1 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -1,13 +1,9 @@ use itertools::Itertools; use nohash_hasher::IntSet; + use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::EntityPath; -use re_space_view::query_space_view_sub_archetype; -use re_types::{ - blueprint::{archetypes::Background3D, components::Background3DKind}, - components::ViewCoordinates, - Loggable, -}; +use re_types::{components::ViewCoordinates, Loggable}; use re_viewer_context::{ PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, @@ -314,7 +310,7 @@ impl SpaceViewClass for SpatialSpaceView3D { ctx.re_ui .selection_grid(ui, "spatial_settings_ui") .show(ui, |ui| { - state.default_size_ui(ctx, ui); + state.default_sizes_ui(ctx, ui); ctx.re_ui .grid_left_hand_label(ui, "Camera") @@ -367,11 +363,14 @@ impl SpaceViewClass for SpatialSpaceView3D { }); ui.end_row(); - background_ui(ctx, space_view_id, ui); - ui.end_row(); + crate::ui::background_ui( + ctx, + ui, + space_view_id, + re_types::blueprint::archetypes::Background::DEFAULT_3D, + ); state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::ThreeD); - ui.end_row(); }); Ok(()) @@ -400,66 +399,3 @@ impl SpaceViewClass for SpatialSpaceView3D { crate::ui_3d::view_3d(ctx, ui, state, query, system_output) } } - -fn background_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mut egui::Ui) { - let blueprint_db = ctx.store_context.blueprint; - let blueprint_query = ctx.blueprint_query; - let (archetype, blueprint_path) = - query_space_view_sub_archetype(space_view_id, blueprint_db, blueprint_query); - - let Background3D { color, mut kind } = archetype.ok().flatten().unwrap_or_default(); - - ctx.re_ui.grid_left_hand_label(ui, "Background"); - - ui.vertical(|ui| { - let kind_before = kind; - egui::ComboBox::from_id_source("background") - .selected_text(background_color_text(kind)) - .show_ui(ui, |ui| { - ui.selectable_value( - &mut kind, - Background3DKind::GradientDark, - background_color_text(Background3DKind::GradientDark), - ); - ui.selectable_value( - &mut kind, - Background3DKind::GradientBright, - background_color_text(Background3DKind::GradientBright), - ); - ui.selectable_value( - &mut kind, - Background3DKind::SolidColor, - background_color_text(Background3DKind::SolidColor), - ); - }); - if kind_before != kind { - ctx.save_blueprint_component(&blueprint_path, &kind); - } - - if kind == Background3DKind::SolidColor { - let current_color = color.unwrap_or(Background3D::DEFAULT_COLOR).into(); - let mut edit_color = current_color; - egui::color_picker::color_edit_button_srgba( - ui, - &mut edit_color, - egui::color_picker::Alpha::Opaque, - ); - if edit_color != current_color { - ctx.save_blueprint_component( - &blueprint_path, - &re_types::components::Color::from(edit_color), - ); - } - } - }); - - ui.end_row(); -} - -fn background_color_text(kind: Background3DKind) -> &'static str { - match kind { - Background3DKind::GradientDark => "Dark gradient", - Background3DKind::GradientBright => "Bright gradient", - Background3DKind::SolidColor => "Solid color", - } -} diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 674efd5f880e..70d750a8106a 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -6,15 +6,17 @@ use re_data_ui::{show_zoomed_image_region, show_zoomed_image_region_area_outline use re_format::format_f32; use re_renderer::OutlineConfig; use re_space_view::ScreenshotMode; -use re_types::components::{DepthMeter, InstanceKey, TensorData, ViewCoordinates}; -use re_types::tensor_data::TensorDataMeaning; +use re_types::{ + blueprint::archetypes::Background, + components::{Color, DepthMeter, InstanceKey, TensorData, ViewCoordinates}, +}; +use re_types::{blueprint::components::BackgroundKind, tensor_data::TensorDataMeaning}; use re_viewer_context::{ - HoverHighlight, Item, ItemSpaceContext, SelectionHighlight, SpaceViewHighlights, + HoverHighlight, Item, ItemSpaceContext, SelectionHighlight, SpaceViewHighlights, SpaceViewId, SpaceViewState, SpaceViewSystemExecutionError, TensorDecodeCache, TensorStatsCache, UiVerbosity, ViewContextCollection, ViewQuery, ViewerContext, VisualizerCollection, }; -use super::{eye::Eye, ui_2d::View2DState, ui_3d::View3DState}; use crate::scene_bounding_boxes::SceneBoundingBoxes; use crate::{ contexts::AnnotationSceneContext, @@ -24,6 +26,8 @@ use crate::{ }; use crate::{eye::EyeMode, heuristics::auto_size_world_heuristic}; +use super::{eye::Eye, ui_2d::View2DState, ui_3d::View3DState}; + /// Default auto point radius in UI points. const AUTO_POINT_RADIUS: f32 = 1.5; @@ -108,7 +112,8 @@ impl SpatialSpaceViewState { ui.end_row(); } - pub fn default_size_ui(&mut self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { + /// Default sizes of points and lines. + pub fn default_sizes_ui(&mut self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui) { let auto_size_world = auto_size_world_heuristic(&self.bounding_boxes.accumulated, self.scene_num_primitives); @@ -766,3 +771,72 @@ pub fn format_vector(v: glam::Vec3) -> String { format!("[{:.02}, {:.02}, {:.02}]", v.x, v.y, v.z) } } + +pub fn background_ui( + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + space_view_id: SpaceViewId, + default_background: Background, +) { + let blueprint_db = ctx.store_context.blueprint; + let blueprint_query = ctx.blueprint_query; + let (archetype, blueprint_path) = + re_space_view::query_space_view_sub_archetype(space_view_id, blueprint_db, blueprint_query); + + let Background { color, mut kind } = archetype.ok().flatten().unwrap_or(default_background); + + ctx.re_ui.grid_left_hand_label(ui, "Background"); + + ui.vertical(|ui| { + let kind_before = kind; + egui::ComboBox::from_id_source("background") + .selected_text(background_color_text(kind)) + .show_ui(ui, |ui| { + ui.selectable_value( + &mut kind, + BackgroundKind::GradientDark, + background_color_text(BackgroundKind::GradientDark), + ); + ui.selectable_value( + &mut kind, + BackgroundKind::GradientBright, + background_color_text(BackgroundKind::GradientBright), + ); + ui.selectable_value( + &mut kind, + BackgroundKind::SolidColor, + background_color_text(BackgroundKind::SolidColor), + ); + }); + if kind_before != kind { + ctx.save_blueprint_component(&blueprint_path, &kind); + } + + if kind == BackgroundKind::SolidColor { + let current_color = color + .or(default_background.color) + .unwrap_or(Color::BLACK) + .into(); + let mut edit_color = current_color; + egui::color_picker::color_edit_button_srgba( + ui, + &mut edit_color, + egui::color_picker::Alpha::Opaque, + ); + if edit_color != current_color { + ctx.save_blueprint_component(&blueprint_path, &BackgroundKind::SolidColor); + ctx.save_blueprint_component(&blueprint_path, &Color::from(edit_color)); + } + } + }); + + ui.end_row(); +} + +fn background_color_text(kind: BackgroundKind) -> &'static str { + match kind { + BackgroundKind::GradientDark => "Dark gradient", + BackgroundKind::GradientBright => "Bright gradient", + BackgroundKind::SolidColor => "Solid color", + } +} diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index 9745a7462e38..cdd2507c57eb 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -4,7 +4,9 @@ use macaw::IsoTransform; use re_entity_db::EntityPath; use re_renderer::view_builder::{TargetConfiguration, ViewBuilder}; use re_space_view::controls::{DRAG_PAN2D_BUTTON, RESET_VIEW_BUTTON_TEXT, ZOOM_SCROLL_MODIFIER}; -use re_types::{archetypes::Pinhole, components::ViewCoordinates}; +use re_types::{ + archetypes::Pinhole, blueprint::archetypes::Background, components::ViewCoordinates, +}; use re_viewer_context::{ gpu_bridge, ItemSpaceContext, SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, ViewerContext, @@ -265,6 +267,14 @@ pub fn view_2d( view_builder.queue_draw(draw_data); } + let background = + re_space_view::space_view_sub_archetype::(ctx, query.space_view_id) + .unwrap_or(Background::DEFAULT_2D); + let (background_drawable, clear_color) = crate::configure_background(ctx, background); + if let Some(background_drawable) = background_drawable { + view_builder.queue_draw(background_drawable); + } + // ------------------------------------------------------------------------ if let Some(mode) = screenshot_context_menu(ctx, &response) { @@ -278,7 +288,7 @@ pub fn view_2d( painter.add(gpu_bridge::new_renderer_callback( view_builder, painter.clip_rect(), - ui.visuals().extreme_bg_color.into(), + clear_color, )); // Make sure to _first_ draw the selected, and *then* the hovered context on top! diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 2ee61660dc75..6f882cd0de51 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -6,16 +6,15 @@ use web_time::Instant; use re_log_types::EntityPath; use re_renderer::{ view_builder::{Projection, TargetConfiguration, ViewBuilder}, - LineDrawableBuilder, QueueableDrawData, Size, + LineDrawableBuilder, Size, }; -use re_space_view::{ - controls::{ - RuntimeModifiers, DRAG_PAN3D_BUTTON, RESET_VIEW_BUTTON_TEXT, ROLL_MOUSE, ROLL_MOUSE_ALT, - ROLL_MOUSE_MODIFIER, ROTATE3D_BUTTON, SPEED_UP_3D_MODIFIER, TRACKED_OBJECT_RESTORE_KEY, - }, - query_space_view_sub_archetype_or_default, +use re_space_view::controls::{ + RuntimeModifiers, DRAG_PAN3D_BUTTON, RESET_VIEW_BUTTON_TEXT, ROLL_MOUSE, ROLL_MOUSE_ALT, + ROLL_MOUSE_MODIFIER, ROTATE3D_BUTTON, SPEED_UP_3D_MODIFIER, TRACKED_OBJECT_RESTORE_KEY, +}; +use re_types::{ + blueprint::archetypes::Background, components::ViewCoordinates, view_coordinates::SignedAxis3, }; -use re_types::{components::ViewCoordinates, view_coordinates::SignedAxis3}; use re_viewer_context::{ gpu_bridge, Item, ItemSpaceContext, SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, ViewerContext, @@ -666,7 +665,11 @@ pub fn view_3d( // Commit ui induced lines. view_builder.queue_draw(line_builder.into_draw_data()?); - let (background_drawable, clear_color) = configure_background(ctx, query); + let background = + re_space_view::space_view_sub_archetype::(ctx, query.space_view_id) + .unwrap_or(Background::DEFAULT_3D); + let (background_drawable, clear_color) = crate::configure_background(ctx, background); + if let Some(background_drawable) = background_drawable { view_builder.queue_draw(background_drawable); } @@ -684,57 +687,6 @@ pub fn view_3d( Ok(()) } -fn configure_background( - ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, -) -> (Option, re_renderer::Rgba) { - use re_renderer::renderer; - use re_types::blueprint::{archetypes::Background3D, components::Background3DKind}; - - let blueprint_db = ctx.store_context.blueprint; - let blueprint_query = ctx.blueprint_query; - let ( - Background3D { - kind, - color: solid_color, - }, - _, - ) = query_space_view_sub_archetype_or_default::( - query.space_view_id, - blueprint_db, - blueprint_query, - ); - - match kind { - Background3DKind::GradientDark => ( - Some( - renderer::GenericSkyboxDrawData::new( - ctx.render_ctx, - renderer::GenericSkyboxType::GradientDark, - ) - .into(), - ), - re_renderer::Rgba::TRANSPARENT, // All zero is slightly faster to clear usually. - ), - - Background3DKind::GradientBright => ( - Some( - renderer::GenericSkyboxDrawData::new( - ctx.render_ctx, - renderer::GenericSkyboxType::GradientBright, - ) - .into(), - ), - re_renderer::Rgba::TRANSPARENT, // All zero is slightly faster to clear usually. - ), - - Background3DKind::SolidColor => ( - None, - solid_color.unwrap_or(Background3D::DEFAULT_COLOR).into(), - ), - } -} - /// Show center of orbit camera when interacting with camera (it's quite helpful). fn show_orbit_eye_center( egui_ctx: &egui::Context, diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index fe2b5a6b17c6..0c53379e36e5 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -3,7 +3,7 @@ include "./blueprint/datatypes/visible_time_range.fbs"; include "./blueprint/components/active_tab.fbs"; include "./blueprint/components/auto_layout.fbs"; include "./blueprint/components/auto_space_views.fbs"; -include "./blueprint/components/background_3d_kind.fbs"; +include "./blueprint/components/background_kind.fbs"; include "./blueprint/components/column_share.fbs"; include "./blueprint/components/container_kind.fbs"; include "./blueprint/components/corner_2d.fbs"; @@ -23,7 +23,7 @@ include "./blueprint/components/viewer_recommendation_hash.fbs"; include "./blueprint/components/visible_time_range.fbs"; include "./blueprint/components/visible.fbs"; -include "./blueprint/archetypes/background_3d.fbs"; +include "./blueprint/archetypes/background.fbs"; include "./blueprint/archetypes/container_blueprint.fbs"; include "./blueprint/archetypes/panel_blueprint.fbs"; include "./blueprint/archetypes/space_view_blueprint.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs similarity index 58% rename from crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs rename to crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs index 12b68b3c6ed3..bdb5e1546fdf 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs @@ -10,19 +10,20 @@ namespace rerun.blueprint.archetypes; // --- -/// Configuration for the background of the 3D space view. -table Background3D ( +/// Configuration for the background of a view. +table Background ( + "attr.python.aliases": "datatypes.Rgba32Like, blueprint_components.BackgroundKindLike", "attr.rerun.scope": "blueprint", - "attr.python.aliases": "datatypes.Rgba32Like, blueprint_components.Background3DKindLike" + "attr.rust.derive": "Copy" ) { // --- Required --- - /// The type of the background. Defaults to Background3DKind.GradientDark. - kind: rerun.blueprint.components.Background3DKind ("attr.rerun.component_required", order: 1000); + /// The type of the background. Defaults to BackgroundKind.GradientDark. + kind: rerun.blueprint.components.BackgroundKind ("attr.rerun.component_required", order: 1000); // --- Optional --- - /// Color used for Background3DKind.SolidColor. + /// Color used for BackgroundKind.SolidColor. /// /// Defaults to White. color: rerun.components.Color ("attr.rerun.component_optional", nullable, order: 2000); diff --git a/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs b/crates/re_types/definitions/rerun/blueprint/components/background_kind.fbs similarity index 51% rename from crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs rename to crates/re_types/definitions/rerun/blueprint/components/background_kind.fbs index 08db29d323aa..fbe642dc108a 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/background_kind.fbs @@ -8,14 +8,18 @@ include "rerun/attributes.fbs"; namespace rerun.blueprint.components; -/// The type of the background in 3D space views. -enum Background3DKind: byte ( +/// The type of the background in a view. +enum BackgroundKind: byte ( "attr.rerun.scope": "blueprint" ) { - /// Gradient depending on the direction of the view, dark theme. - GradientDark (default), + /// A dark gradient. + /// + /// In 3D views it changes depending on the direction of the view. + GradientDark, - /// Gradient depending on the direction of the view, bright theme. + /// A bright gradient. + /// + /// In 3D views it changes depending on the direction of the view. GradientBright, /// Simple uniform color. diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs index 208eae5e1735..e133d2c41e7d 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs @@ -6,4 +6,6 @@ namespace rerun.blueprint.views; table Spatial2DView ( "attr.rerun.view_identifier": "2D" ) { + /// Configuration for the background of the space view. + background: rerun.blueprint.archetypes.Background (order: 1000); } diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs index c512b4eb8fbb..749bb24d5cbe 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs @@ -6,6 +6,6 @@ namespace rerun.blueprint.views; table Spatial3DView ( "attr.rerun.view_identifier": "3D" ) { - /// Configuration for the background of the 3D space view. - background: rerun.blueprint.archetypes.Background3D (order: 1000); + /// Configuration for the background of the space view. + background: rerun.blueprint.archetypes.Background (order: 1000); } diff --git a/crates/re_types/src/blueprint/archetypes/.gitattributes b/crates/re_types/src/blueprint/archetypes/.gitattributes index 4095717515a0..003fc96d78d4 100644 --- a/crates/re_types/src/blueprint/archetypes/.gitattributes +++ b/crates/re_types/src/blueprint/archetypes/.gitattributes @@ -1,7 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -background3d.rs linguist-generated=true +background.rs linguist-generated=true mod.rs linguist-generated=true plot_legend.rs linguist-generated=true scalar_axis.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/archetypes/background3d.rs b/crates/re_types/src/blueprint/archetypes/background.rs similarity index 78% rename from crates/re_types/src/blueprint/archetypes/background3d.rs rename to crates/re_types/src/blueprint/archetypes/background.rs index c4041b6df7f1..bd03c06267d4 100644 --- a/crates/re_types/src/blueprint/archetypes/background3d.rs +++ b/crates/re_types/src/blueprint/archetypes/background.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -22,19 +22,19 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Archetype**: Configuration for the background of the 3D space view. -#[derive(Clone, Debug)] -pub struct Background3D { - /// The type of the background. Defaults to Background3DKind.GradientDark. - pub kind: crate::blueprint::components::Background3DKind, +/// **Archetype**: Configuration for the background of a view. +#[derive(Clone, Debug, Copy)] +pub struct Background { + /// The type of the background. Defaults to BackgroundKind.GradientDark. + pub kind: crate::blueprint::components::BackgroundKind, - /// Color used for Background3DKind.SolidColor. + /// Color used for BackgroundKind.SolidColor. /// /// Defaults to White. pub color: Option, } -impl ::re_types_core::SizeBytes for Background3D { +impl ::re_types_core::SizeBytes for Background { #[inline] fn heap_size_bytes(&self) -> u64 { self.kind.heap_size_bytes() + self.color.heap_size_bytes() @@ -42,16 +42,16 @@ impl ::re_types_core::SizeBytes for Background3D { #[inline] fn is_pod() -> bool { - ::is_pod() + ::is_pod() && >::is_pod() } } static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.Background3DKind".into()]); + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.BackgroundKind".into()]); static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.Background3DIndicator".into()]); + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.BackgroundIndicator".into()]); static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { @@ -64,31 +64,31 @@ static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ - "rerun.blueprint.components.Background3DKind".into(), - "rerun.blueprint.components.Background3DIndicator".into(), + "rerun.blueprint.components.BackgroundKind".into(), + "rerun.blueprint.components.BackgroundIndicator".into(), "rerun.components.Color".into(), "rerun.components.InstanceKey".into(), ] }); -impl Background3D { +impl Background { pub const NUM_COMPONENTS: usize = 4usize; } -/// Indicator component for the [`Background3D`] [`::re_types_core::Archetype`] -pub type Background3DIndicator = ::re_types_core::GenericIndicatorComponent; +/// Indicator component for the [`Background`] [`::re_types_core::Archetype`] +pub type BackgroundIndicator = ::re_types_core::GenericIndicatorComponent; -impl ::re_types_core::Archetype for Background3D { - type Indicator = Background3DIndicator; +impl ::re_types_core::Archetype for Background { + type Indicator = BackgroundIndicator; #[inline] fn name() -> ::re_types_core::ArchetypeName { - "rerun.blueprint.archetypes.Background3D".into() + "rerun.blueprint.archetypes.Background".into() } #[inline] fn indicator() -> MaybeOwnedComponentBatch<'static> { - static INDICATOR: Background3DIndicator = Background3DIndicator::DEFAULT; + static INDICATOR: BackgroundIndicator = BackgroundIndicator::DEFAULT; MaybeOwnedComponentBatch::Ref(&INDICATOR) } @@ -124,20 +124,20 @@ impl ::re_types_core::Archetype for Background3D { .collect(); let kind = { let array = arrays_by_name - .get("rerun.blueprint.components.Background3DKind") + .get("rerun.blueprint.components.BackgroundKind") .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.blueprint.archetypes.Background3D#kind")?; - ::from_arrow_opt(&**array) - .with_context("rerun.blueprint.archetypes.Background3D#kind")? + .with_context("rerun.blueprint.archetypes.Background#kind")?; + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.Background#kind")? .into_iter() .next() .flatten() .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.blueprint.archetypes.Background3D#kind")? + .with_context("rerun.blueprint.archetypes.Background#kind")? }; let color = if let Some(array) = arrays_by_name.get("rerun.components.Color") { ::from_arrow_opt(&**array) - .with_context("rerun.blueprint.archetypes.Background3D#color")? + .with_context("rerun.blueprint.archetypes.Background#color")? .into_iter() .next() .flatten() @@ -148,7 +148,7 @@ impl ::re_types_core::Archetype for Background3D { } } -impl ::re_types_core::AsComponents for Background3D { +impl ::re_types_core::AsComponents for Background { fn as_component_batches(&self) -> Vec> { re_tracing::profile_function!(); use ::re_types_core::Archetype as _; @@ -170,8 +170,8 @@ impl ::re_types_core::AsComponents for Background3D { } } -impl Background3D { - pub fn new(kind: impl Into) -> Self { +impl Background { + pub fn new(kind: impl Into) -> Self { Self { kind: kind.into(), color: None, diff --git a/crates/re_types/src/blueprint/archetypes/background3d_ext.rs b/crates/re_types/src/blueprint/archetypes/background3d_ext.rs deleted file mode 100644 index 14daf0283ed1..000000000000 --- a/crates/re_types/src/blueprint/archetypes/background3d_ext.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::{blueprint::components::Background3DKind, components::Color}; - -use super::Background3D; - -impl Background3D { - pub const DEFAULT_COLOR: Color = Color::WHITE; -} - -impl Default for Background3D { - #[inline] - fn default() -> Self { - Self { - kind: Background3DKind::default(), - color: Some(Background3D::DEFAULT_COLOR), - } - } -} diff --git a/crates/re_types/src/blueprint/archetypes/background_ext.rs b/crates/re_types/src/blueprint/archetypes/background_ext.rs new file mode 100644 index 000000000000..1e8ed715c185 --- /dev/null +++ b/crates/re_types/src/blueprint/archetypes/background_ext.rs @@ -0,0 +1,23 @@ +use crate::{blueprint::components::BackgroundKind, components::Color}; + +use super::Background; + +impl Background { + /// Default background of 2D space views. + pub const DEFAULT_2D: Self = Self { + kind: BackgroundKind::SolidColor, + color: Some(Self::DEFAULT_COLOR_2D), + }; + + /// Default background of 3D space views. + pub const DEFAULT_3D: Self = Self { + kind: BackgroundKind::GradientDark, + color: Some(Self::DEFAULT_COLOR_3D), + }; + + /// Default background color of 2D space views. + pub const DEFAULT_COLOR_2D: Color = Color::BLACK; + + /// Default background color of 3D space views. + pub const DEFAULT_COLOR_3D: Color = Color::WHITE; +} diff --git a/crates/re_types/src/blueprint/archetypes/mod.rs b/crates/re_types/src/blueprint/archetypes/mod.rs index 2b251ddec081..6fcc74f24ee6 100644 --- a/crates/re_types/src/blueprint/archetypes/mod.rs +++ b/crates/re_types/src/blueprint/archetypes/mod.rs @@ -1,13 +1,13 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -mod background3d; -mod background3d_ext; +mod background; +mod background_ext; mod plot_legend; mod scalar_axis; mod space_view_blueprint; mod space_view_contents; -pub use self::background3d::Background3D; +pub use self::background::Background; pub use self::plot_legend::PlotLegend; pub use self::scalar_axis::ScalarAxis; pub use self::space_view_blueprint::SpaceViewBlueprint; diff --git a/crates/re_types/src/blueprint/components/.gitattributes b/crates/re_types/src/blueprint/components/.gitattributes index 02afa95257cd..bcc6988a5622 100644 --- a/crates/re_types/src/blueprint/components/.gitattributes +++ b/crates/re_types/src/blueprint/components/.gitattributes @@ -2,7 +2,7 @@ .gitattributes linguist-generated=true active_tab.rs linguist-generated=true -background3d_kind.rs linguist-generated=true +background_kind.rs linguist-generated=true column_share.rs linguist-generated=true corner2d.rs linguist-generated=true included_content.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/components/background3d_kind.rs b/crates/re_types/src/blueprint/components/background_kind.rs similarity index 83% rename from crates/re_types/src/blueprint/components/background3d_kind.rs rename to crates/re_types/src/blueprint/components/background_kind.rs index 0191c1f0b196..3a0d84047894 100644 --- a/crates/re_types/src/blueprint/components/background3d_kind.rs +++ b/crates/re_types/src/blueprint/components/background_kind.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/components/background_kind.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -22,26 +22,29 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Component**: The type of the background in 3D space views. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] -pub enum Background3DKind { - /// Gradient depending on the direction of the view, dark theme. - #[default] +/// **Component**: The type of the background in a view. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum BackgroundKind { + /// A dark gradient. + /// + /// In 3D views it changes depending on the direction of the view. GradientDark = 1, - /// Gradient depending on the direction of the view, bright theme. + /// A bright gradient. + /// + /// In 3D views it changes depending on the direction of the view. GradientBright = 2, /// Simple uniform color. SolidColor = 3, } -impl Background3DKind { +impl BackgroundKind { /// All the different enum variants. pub const ALL: [Self; 3] = [Self::GradientDark, Self::GradientBright, Self::SolidColor]; } -impl ::re_types_core::SizeBytes for Background3DKind { +impl ::re_types_core::SizeBytes for BackgroundKind { #[inline] fn heap_size_bytes(&self) -> u64 { 0 @@ -53,7 +56,7 @@ impl ::re_types_core::SizeBytes for Background3DKind { } } -impl std::fmt::Display for Background3DKind { +impl std::fmt::Display for BackgroundKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::GradientDark => write!(f, "GradientDark"), @@ -63,14 +66,14 @@ impl std::fmt::Display for Background3DKind { } } -::re_types_core::macros::impl_into_cow!(Background3DKind); +::re_types_core::macros::impl_into_cow!(BackgroundKind); -impl ::re_types_core::Loggable for Background3DKind { +impl ::re_types_core::Loggable for BackgroundKind { type Name = ::re_types_core::ComponentName; #[inline] fn name() -> Self::Name { - "rerun.blueprint.components.Background3DKind".into() + "rerun.blueprint.components.BackgroundKind".into() } #[allow(clippy::wildcard_imports)] @@ -119,7 +122,7 @@ impl ::re_types_core::Loggable for Background3DKind { .take(1 + num_variants) .collect(); UnionArray::new( - ::arrow_datatype(), + ::arrow_datatype(), types, fields, None, @@ -146,15 +149,15 @@ impl ::re_types_core::Loggable for Background3DKind { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.components.Background3DKind")?; + .with_context("rerun.blueprint.components.BackgroundKind")?; let arrow_data_types = arrow_data.types(); arrow_data_types .iter() .map(|typ| match typ { 0 => Ok(None), - 1 => Ok(Some(Background3DKind::GradientDark)), - 2 => Ok(Some(Background3DKind::GradientBright)), - 3 => Ok(Some(Background3DKind::SolidColor)), + 1 => Ok(Some(BackgroundKind::GradientDark)), + 2 => Ok(Some(BackgroundKind::GradientBright)), + 3 => Ok(Some(BackgroundKind::SolidColor)), _ => Err(DeserializationError::missing_union_arm( Self::arrow_datatype(), "", @@ -162,7 +165,7 @@ impl ::re_types_core::Loggable for Background3DKind { )), }) .collect::>>() - .with_context("rerun.blueprint.components.Background3DKind")? + .with_context("rerun.blueprint.components.BackgroundKind")? }) } } diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index 91c656fa8b69..403f8aecde4e 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -1,7 +1,7 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs mod active_tab; -mod background3d_kind; +mod background_kind; mod column_share; mod corner2d; mod corner2d_ext; @@ -20,7 +20,7 @@ mod visible_time_range; mod visible_time_range_ext; pub use self::active_tab::ActiveTab; -pub use self::background3d_kind::Background3DKind; +pub use self::background_kind::BackgroundKind; pub use self::column_share::ColumnShare; pub use self::corner2d::Corner2D; pub use self::included_content::IncludedContent; diff --git a/crates/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/re_viewer/src/blueprint/validation_gen/mod.rs index 44007decf33e..c21897873f93 100644 --- a/crates/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/re_viewer/src/blueprint/validation_gen/mod.rs @@ -3,7 +3,7 @@ use super::validation::validate_component; pub use re_entity_db::blueprint::components::EntityPropertiesComponent; use re_entity_db::EntityDb; pub use re_types::blueprint::components::ActiveTab; -pub use re_types::blueprint::components::Background3DKind; +pub use re_types::blueprint::components::BackgroundKind; pub use re_types::blueprint::components::ColumnShare; pub use re_types::blueprint::components::Corner2D; pub use re_types::blueprint::components::IncludedContent; @@ -31,7 +31,7 @@ pub fn is_valid_blueprint(blueprint: &EntityDb) -> bool { validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) - && validate_component::(blueprint) + && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) diff --git a/examples/python/rrt_star/rrt_star.py b/examples/python/rrt_star/rrt_star.py index fd7a56afa5c9..eb0cd9a5094e 100755 --- a/examples/python/rrt_star/rrt_star.py +++ b/examples/python/rrt_star/rrt_star.py @@ -270,7 +270,7 @@ def main() -> None: args = parser.parse_args() blueprint = rrb.Horizontal( - rrb.Spatial2DView(name="Map", origin="/map"), + rrb.Spatial2DView(name="Map", origin="/map", background=[32, 0, 16]), rrb.TextDocumentView(name="Description", origin="/description"), column_shares=[3, 1], ) diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index ef60a3d1b936..52de82f4046c 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -2,7 +2,7 @@ #pragma once -#include "blueprint/archetypes/background3d.hpp" +#include "blueprint/archetypes/background.hpp" #include "blueprint/archetypes/container_blueprint.hpp" #include "blueprint/archetypes/panel_blueprint.hpp" #include "blueprint/archetypes/plot_legend.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index 358568f59312..70303c75a9ef 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -1,8 +1,8 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -background3d.cpp linguist-generated=true -background3d.hpp linguist-generated=true +background.cpp linguist-generated=true +background.hpp linguist-generated=true container_blueprint.cpp linguist-generated=true container_blueprint.hpp linguist-generated=true panel_blueprint.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background3d.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp similarity index 83% rename from rerun_cpp/src/rerun/blueprint/archetypes/background3d.cpp rename to rerun_cpp/src/rerun/blueprint/archetypes/background.cpp index 989797dbe049..d4e3edbe3646 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background3d.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background.cpp @@ -1,7 +1,7 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs". -#include "background3d.hpp" +#include "background.hpp" #include "../../collection_adapter_builtins.hpp" @@ -9,8 +9,8 @@ namespace rerun::blueprint::archetypes {} namespace rerun { - Result> AsComponents::serialize( - const blueprint::archetypes::Background3D& archetype + Result> AsComponents::serialize( + const blueprint::archetypes::Background& archetype ) { using namespace blueprint::archetypes; std::vector cells; @@ -27,7 +27,7 @@ namespace rerun { cells.push_back(std::move(result.value)); } { - auto indicator = Background3D::IndicatorComponent(); + auto indicator = Background::IndicatorComponent(); auto result = DataCell::from_loggable(indicator); RR_RETURN_NOT_OK(result.error); cells.emplace_back(std::move(result.value)); diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp similarity index 64% rename from rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp rename to rerun_cpp/src/rerun/blueprint/archetypes/background.hpp index f9571abcf615..f99ff37914e1 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background3d.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp @@ -1,9 +1,9 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs". #pragma once -#include "../../blueprint/components/background3d_kind.hpp" +#include "../../blueprint/components/background_kind.hpp" #include "../../collection.hpp" #include "../../compiler_utils.hpp" #include "../../components/color.hpp" @@ -17,34 +17,34 @@ #include namespace rerun::blueprint::archetypes { - /// **Archetype**: Configuration for the background of the 3D space view. - struct Background3D { - /// The type of the background. Defaults to Background3DKind.GradientDark. - rerun::blueprint::components::Background3DKind kind; + /// **Archetype**: Configuration for the background of a view. + struct Background { + /// The type of the background. Defaults to BackgroundKind.GradientDark. + rerun::blueprint::components::BackgroundKind kind; - /// Color used for Background3DKind.SolidColor. + /// Color used for BackgroundKind.SolidColor. /// /// Defaults to White. std::optional color; public: static constexpr const char IndicatorComponentName[] = - "rerun.blueprint.components.Background3DIndicator"; + "rerun.blueprint.components.BackgroundIndicator"; /// Indicator component, used to identify the archetype when converting to a list of components. using IndicatorComponent = rerun::components::IndicatorComponent; public: - Background3D() = default; - Background3D(Background3D&& other) = default; + Background() = default; + Background(Background&& other) = default; - explicit Background3D(rerun::blueprint::components::Background3DKind _kind) + explicit Background(rerun::blueprint::components::BackgroundKind _kind) : kind(std::move(_kind)) {} - /// Color used for Background3DKind.SolidColor. + /// Color used for BackgroundKind.SolidColor. /// /// Defaults to White. - Background3D with_color(rerun::components::Color _color) && { + Background with_color(rerun::components::Color _color) && { color = std::move(_color); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) @@ -65,10 +65,10 @@ namespace rerun { /// \private template <> - struct AsComponents { + struct AsComponents { /// Serialize all set component batches. static Result> serialize( - const blueprint::archetypes::Background3D& archetype + const blueprint::archetypes::Background& archetype ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index 715845efe9dd..acc1c7879ee7 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -5,7 +5,7 @@ #include "blueprint/components/active_tab.hpp" #include "blueprint/components/auto_layout.hpp" #include "blueprint/components/auto_space_views.hpp" -#include "blueprint/components/background3d_kind.hpp" +#include "blueprint/components/background_kind.hpp" #include "blueprint/components/column_share.hpp" #include "blueprint/components/container_kind.hpp" #include "blueprint/components/corner2d.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index f4360986e2c4..bea2a6a8f0de 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -6,8 +6,8 @@ auto_layout.cpp linguist-generated=true auto_layout.hpp linguist-generated=true auto_space_views.cpp linguist-generated=true auto_space_views.hpp linguist-generated=true -background3d_kind.cpp linguist-generated=true -background3d_kind.hpp linguist-generated=true +background_kind.cpp linguist-generated=true +background_kind.hpp linguist-generated=true column_share.cpp linguist-generated=true column_share.hpp linguist-generated=true container_kind.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp b/rerun_cpp/src/rerun/blueprint/components/background_kind.cpp similarity index 78% rename from rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp rename to rerun_cpp/src/rerun/blueprint/components/background_kind.cpp index 7d6c7e969104..11b5ea61cb4d 100644 --- a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.cpp +++ b/rerun_cpp/src/rerun/blueprint/components/background_kind.cpp @@ -1,14 +1,14 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/components/background_kind.fbs". -#include "background3d_kind.hpp" +#include "background_kind.hpp" #include #include namespace rerun { const std::shared_ptr& - Loggable::arrow_datatype() { + Loggable::arrow_datatype() { static const auto datatype = arrow::sparse_union({ arrow::field("_null_markers", arrow::null(), true, nullptr), arrow::field("GradientDark", arrow::null(), true), @@ -18,10 +18,9 @@ namespace rerun { return datatype; } - Result> - Loggable::to_arrow( - const blueprint::components::Background3DKind* instances, size_t num_instances - ) { + Result> Loggable::to_arrow( + const blueprint::components::BackgroundKind* instances, size_t num_instances + ) { // TODO(andreas): Allow configuring the memory pool. arrow::MemoryPool* pool = arrow::default_memory_pool(); auto datatype = arrow_datatype(); @@ -29,7 +28,7 @@ namespace rerun { ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) if (instances && num_instances > 0) { RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( + Loggable::fill_arrow_array_builder( static_cast(builder.get()), instances, num_instances @@ -41,8 +40,8 @@ namespace rerun { return array; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::SparseUnionBuilder* builder, const blueprint::components::Background3DKind* elements, + rerun::Error Loggable::fill_arrow_array_builder( + arrow::SparseUnionBuilder* builder, const blueprint::components::BackgroundKind* elements, size_t num_elements ) { if (builder == nullptr) { diff --git a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp b/rerun_cpp/src/rerun/blueprint/components/background_kind.hpp similarity index 64% rename from rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp rename to rerun_cpp/src/rerun/blueprint/components/background_kind.hpp index 1989dc6c301a..90a53eea1a17 100644 --- a/rerun_cpp/src/rerun/blueprint/components/background3d_kind.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/background_kind.hpp @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/components/background_kind.fbs". #pragma once @@ -15,13 +15,17 @@ namespace arrow { } // namespace arrow namespace rerun::blueprint::components { - /// **Component**: The type of the background in 3D space views. - enum class Background3DKind : uint8_t { + /// **Component**: The type of the background in a view. + enum class BackgroundKind : uint8_t { - /// Gradient depending on the direction of the view, dark theme. + /// A dark gradient. + /// + /// In 3D views it changes depending on the direction of the view. GradientDark = 1, - /// Gradient depending on the direction of the view, bright theme. + /// A bright gradient. + /// + /// In 3D views it changes depending on the direction of the view. GradientBright = 2, /// Simple uniform color. @@ -35,21 +39,21 @@ namespace rerun { /// \private template <> - struct Loggable { - static constexpr const char Name[] = "rerun.blueprint.components.Background3DKind"; + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.BackgroundKind"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Serializes an array of `rerun::blueprint:: components::Background3DKind` into an arrow array. + /// Serializes an array of `rerun::blueprint:: components::BackgroundKind` into an arrow array. static Result> to_arrow( - const blueprint::components::Background3DKind* instances, size_t num_instances + const blueprint::components::BackgroundKind* instances, size_t num_instances ); /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, - const blueprint::components::Background3DKind* elements, size_t num_elements + const blueprint::components::BackgroundKind* elements, size_t num_elements ); }; } // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 71c4fc2e4ff8..507e7b007d05 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -13,12 +13,12 @@ TimePanel, ) from .archetypes import ( - Background3D, + Background, PlotLegend, ScalarAxis, ) from .components import ( - Background3DKind, + BackgroundKind, Corner2D, LockRangeDuringZoom, ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index 135b24010d97..e7b8aeea825b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -2,7 +2,7 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true -background3d.py linguist-generated=true +background.py linguist-generated=true container_blueprint.py linguist-generated=true panel_blueprint.py linguist-generated=true plot_legend.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py index 982c77a4ec65..79504acb3574 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -2,7 +2,7 @@ from __future__ import annotations -from .background3d import Background3D +from .background import Background from .container_blueprint import ContainerBlueprint from .panel_blueprint import PanelBlueprint from .plot_legend import PlotLegend @@ -12,7 +12,7 @@ from .viewport_blueprint import ViewportBlueprint __all__ = [ - "Background3D", + "Background", "ContainerBlueprint", "PanelBlueprint", "PlotLegend", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py similarity index 63% rename from rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py rename to rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py index 77cca6819b3f..977d63c15dbb 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background.py @@ -1,7 +1,7 @@ # DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background_3d.fbs". +# Based on "crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs". -# You can extend this class by creating a "Background3DExt" class in "background3d_ext.py". +# You can extend this class by creating a "BackgroundExt" class in "background_ext.py". from __future__ import annotations @@ -10,16 +10,16 @@ from ... import components from ..._baseclasses import Archetype from ...blueprint import components as blueprint_components -from .background3d_ext import Background3DExt +from .background_ext import BackgroundExt -__all__ = ["Background3D"] +__all__ = ["Background"] @define(str=False, repr=False, init=False) -class Background3D(Background3DExt, Archetype): - """**Archetype**: Configuration for the background of the 3D space view.""" +class Background(BackgroundExt, Archetype): + """**Archetype**: Configuration for the background of a view.""" - # __init__ can be found in background3d_ext.py + # __init__ can be found in background_ext.py def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" @@ -29,17 +29,17 @@ def __attrs_clear__(self) -> None: ) @classmethod - def _clear(cls) -> Background3D: - """Produce an empty Background3D, bypassing `__init__`.""" + def _clear(cls) -> Background: + """Produce an empty Background, bypassing `__init__`.""" inst = cls.__new__(cls) inst.__attrs_clear__() return inst - kind: blueprint_components.Background3DKindBatch = field( + kind: blueprint_components.BackgroundKindBatch = field( metadata={"component": "required"}, - converter=blueprint_components.Background3DKindBatch._required, # type: ignore[misc] + converter=blueprint_components.BackgroundKindBatch._required, # type: ignore[misc] ) - # The type of the background. Defaults to Background3DKind.GradientDark. + # The type of the background. Defaults to BackgroundKind.GradientDark. # # (Docstring intentionally commented out to hide this field from the docs) @@ -48,7 +48,7 @@ def _clear(cls) -> Background3D: default=None, converter=components.ColorBatch._optional, # type: ignore[misc] ) - # Color used for Background3DKind.SolidColor. + # Color used for BackgroundKind.SolidColor. # # Defaults to White. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background_ext.py similarity index 64% rename from rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d_ext.py rename to rerun_py/rerun_sdk/rerun/blueprint/archetypes/background_ext.py index cce84ea80614..cb914e98b538 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background3d_ext.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/background_ext.py @@ -3,33 +3,33 @@ from typing import Any from ... import datatypes -from ...blueprint import components as blueprint_components from ...error_utils import catch_and_log_exceptions +from .. import components as blueprint_components -class Background3DExt: - """Extension for [Background3D][rerun.blueprint.archetypes.Background3D].""" +class BackgroundExt: + """Extension for [Background][rerun.blueprint.archetypes.Background].""" def __init__( self: Any, - color_or_kind: datatypes.Rgba32Like | blueprint_components.Background3DKindLike | None = None, + color_or_kind: datatypes.Rgba32Like | blueprint_components.BackgroundKindLike | None = None, *, color: datatypes.Rgba32Like | None = None, - kind: blueprint_components.Background3DKindLike | None = None, + kind: blueprint_components.BackgroundKindLike | None = None, ): """ - Create a new instance of the Background3D archetype. + Create a new instance of the Background archetype. Parameters ---------- color_or_kind: - Either a color for solid background color or kind of the background (see `Background3DKind`). + Either a color for solid background color or kind of the background (see `BackgroundKind`). If set, `color` and `kind` must not be set. kind: - The type of the background. Defaults to Background3DKind.GradientDark. + The type of the background. Defaults to BackgroundKind.GradientDark. color: - Color used for Background3DKind.SolidColor. + Color used for BackgroundKind.SolidColor. Defaults to White. @@ -40,16 +40,16 @@ def __init__( if color is not None or kind is not None: raise ValueError("Only one of `color_or_kind` and `color`/`kind` can be set.") - if isinstance(color_or_kind, blueprint_components.Background3DKind): + if isinstance(color_or_kind, blueprint_components.BackgroundKind): kind = color_or_kind else: color = color_or_kind # type: ignore[assignment] if kind is None: if color is None: - kind = blueprint_components.Background3DKind.GradientDark + kind = blueprint_components.BackgroundKind.GradientDark else: - kind = blueprint_components.Background3DKind.SolidColor + kind = blueprint_components.BackgroundKind.SolidColor self.__attrs_init__(kind=kind, color=color) return diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index a8e9e72f9c7e..5f570fe84651 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -5,7 +5,7 @@ __init__.py linguist-generated=true active_tab.py linguist-generated=true auto_layout.py linguist-generated=true auto_space_views.py linguist-generated=true -background3d_kind.py linguist-generated=true +background_kind.py linguist-generated=true column_share.py linguist-generated=true container_kind.py linguist-generated=true corner2d.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index 3d6a535018eb..c398116775ac 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -11,12 +11,12 @@ AutoSpaceViewsLike, AutoSpaceViewsType, ) -from .background3d_kind import ( - Background3DKind, - Background3DKindArrayLike, - Background3DKindBatch, - Background3DKindLike, - Background3DKindType, +from .background_kind import ( + BackgroundKind, + BackgroundKindArrayLike, + BackgroundKindBatch, + BackgroundKindLike, + BackgroundKindType, ) from .column_share import ColumnShare, ColumnShareArrayLike, ColumnShareBatch, ColumnShareLike, ColumnShareType from .container_kind import ( @@ -67,11 +67,11 @@ "AutoSpaceViewsBatch", "AutoSpaceViewsLike", "AutoSpaceViewsType", - "Background3DKind", - "Background3DKindArrayLike", - "Background3DKindBatch", - "Background3DKindLike", - "Background3DKindType", + "BackgroundKind", + "BackgroundKindArrayLike", + "BackgroundKindBatch", + "BackgroundKindLike", + "BackgroundKindType", "ColumnShare", "ColumnShareArrayLike", "ColumnShareBatch", diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py b/rerun_py/rerun_sdk/rerun/blueprint/components/background_kind.py similarity index 54% rename from rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py rename to rerun_py/rerun_sdk/rerun/blueprint/components/background_kind.py index 815aba7d92d7..cdc8fc4eef9b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/background3d_kind.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/background_kind.py @@ -1,7 +1,7 @@ # DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/blueprint/components/background_3d_kind.fbs". +# Based on "crates/re_types/definitions/rerun/blueprint/components/background_kind.fbs". -# You can extend this class by creating a "Background3DKindExt" class in "background3d_kind_ext.py". +# You can extend this class by creating a "BackgroundKindExt" class in "background_kind_ext.py". from __future__ import annotations @@ -12,36 +12,44 @@ from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin __all__ = [ - "Background3DKind", - "Background3DKindArrayLike", - "Background3DKindBatch", - "Background3DKindLike", - "Background3DKindType", + "BackgroundKind", + "BackgroundKindArrayLike", + "BackgroundKindBatch", + "BackgroundKindLike", + "BackgroundKindType", ] from enum import Enum -class Background3DKind(Enum): - """**Component**: The type of the background in 3D space views.""" +class BackgroundKind(Enum): + """**Component**: The type of the background in a view.""" GradientDark = 1 - """Gradient depending on the direction of the view, dark theme.""" + """ + A dark gradient. + + In 3D views it changes depending on the direction of the view. + """ GradientBright = 2 - """Gradient depending on the direction of the view, bright theme.""" + """ + A bright gradient. + + In 3D views it changes depending on the direction of the view. + """ SolidColor = 3 """Simple uniform color.""" -Background3DKindLike = Union[Background3DKind, str] -Background3DKindArrayLike = Union[Background3DKindLike, Sequence[Background3DKindLike]] +BackgroundKindLike = Union[BackgroundKind, str] +BackgroundKindArrayLike = Union[BackgroundKindLike, Sequence[BackgroundKindLike]] -class Background3DKindType(BaseExtensionType): - _TYPE_NAME: str = "rerun.blueprint.components.Background3DKind" +class BackgroundKindType(BaseExtensionType): + _TYPE_NAME: str = "rerun.blueprint.components.BackgroundKind" def __init__(self) -> None: pa.ExtensionType.__init__( @@ -56,12 +64,12 @@ def __init__(self) -> None: ) -class Background3DKindBatch(BaseBatch[Background3DKindArrayLike], ComponentBatchMixin): - _ARROW_TYPE = Background3DKindType() +class BackgroundKindBatch(BaseBatch[BackgroundKindArrayLike], ComponentBatchMixin): + _ARROW_TYPE = BackgroundKindType() @staticmethod - def _native_to_pa_array(data: Background3DKindArrayLike, data_type: pa.DataType) -> pa.Array: - if isinstance(data, (Background3DKind, int, str)): + def _native_to_pa_array(data: BackgroundKindArrayLike, data_type: pa.DataType) -> pa.Array: + if isinstance(data, (BackgroundKind, int, str)): data = [data] types: list[int] = [] @@ -69,23 +77,23 @@ def _native_to_pa_array(data: Background3DKindArrayLike, data_type: pa.DataType) for value in data: if value is None: types.append(0) - elif isinstance(value, Background3DKind): + elif isinstance(value, BackgroundKind): types.append(value.value) # Actual enum value elif isinstance(value, int): types.append(value) # By number elif isinstance(value, str): - if hasattr(Background3DKind, value): - types.append(Background3DKind[value].value) # fast path + if hasattr(BackgroundKind, value): + types.append(BackgroundKind[value].value) # fast path elif value.lower() == "gradientdark": - types.append(Background3DKind.GradientDark.value) + types.append(BackgroundKind.GradientDark.value) elif value.lower() == "gradientbright": - types.append(Background3DKind.GradientBright.value) + types.append(BackgroundKind.GradientBright.value) elif value.lower() == "solidcolor": - types.append(Background3DKind.SolidColor.value) + types.append(BackgroundKind.SolidColor.value) else: - raise ValueError(f"Unknown Background3DKind kind: {value}") + raise ValueError(f"Unknown BackgroundKind kind: {value}") else: - raise ValueError(f"Unknown Background3DKind kind: {value}") + raise ValueError(f"Unknown BackgroundKind kind: {value}") buffers = [ None, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py index 8caca32be171..ae31233af77c 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py @@ -6,8 +6,10 @@ __all__ = ["Spatial2DView"] +from ... import datatypes from ..._baseclasses import AsComponents from ...datatypes import EntityPathLike, Utf8Like +from .. import archetypes as blueprint_archetypes from .. import components as blueprint_components from ..api import SpaceView, SpaceViewContentsLike @@ -22,6 +24,10 @@ def __init__( contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, visible: blueprint_components.VisibleLike | None = None, + background: blueprint_archetypes.Background + | datatypes.Rgba32Like + | blueprint_components.BackgroundKindLike + | None = None, ) -> None: """ Construct a blueprint for a new Spatial2DView view. @@ -41,10 +47,17 @@ def __init__( Whether this view is visible. Defaults to true if not specified. + background: + Configuration for the background of the space view. """ properties: dict[str, AsComponents] = {} + if background is not None: + if not isinstance(background, blueprint_archetypes.Background): + background = blueprint_archetypes.Background(background) + properties["Background"] = background + super().__init__( class_identifier="2D", origin=origin, contents=contents, name=name, visible=visible, properties=properties ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py index 66437db4cefb..e486bc45895e 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py @@ -24,9 +24,9 @@ def __init__( contents: SpaceViewContentsLike = "$origin/**", name: Utf8Like | None = None, visible: blueprint_components.VisibleLike | None = None, - background: blueprint_archetypes.Background3D + background: blueprint_archetypes.Background | datatypes.Rgba32Like - | blueprint_components.Background3DKindLike + | blueprint_components.BackgroundKindLike | None = None, ) -> None: """ @@ -48,15 +48,15 @@ def __init__( Defaults to true if not specified. background: - Configuration for the background of the 3D space view. + Configuration for the background of the space view. """ properties: dict[str, AsComponents] = {} if background is not None: - if not isinstance(background, blueprint_archetypes.Background3D): - background = blueprint_archetypes.Background3D(background) - properties["Background3D"] = background + if not isinstance(background, blueprint_archetypes.Background): + background = blueprint_archetypes.Background(background) + properties["Background"] = background super().__init__( class_identifier="3D", origin=origin, contents=contents, name=name, visible=visible, properties=properties diff --git a/rerun_py/tests/unit/test_background.py b/rerun_py/tests/unit/test_background.py new file mode 100644 index 000000000000..115347d4f01c --- /dev/null +++ b/rerun_py/tests/unit/test_background.py @@ -0,0 +1,23 @@ +from __future__ import annotations + +import pytest +import rerun as rr +import rerun.blueprint as rrb + + +def test_background_construction() -> None: + rr.set_strict_mode(True) + + assert rrb.Background((1.0, 0.0, 0.0)) == rrb.Background(color=(1.0, 0.0, 0.0), kind=rrb.BackgroundKind.SolidColor) + assert rrb.Background(rrb.BackgroundKind.GradientBright) == rrb.Background( + color=None, kind=rrb.BackgroundKind.GradientBright + ) + + with pytest.raises(ValueError): + rrb.Background(rrb.BackgroundKind.GradientBright, kind=rrb.BackgroundKind.GradientDark) + with pytest.raises(ValueError): + rrb.Background(rrb.BackgroundKind.GradientBright, color=(0.0, 1.0, 0.0)) + with pytest.raises(ValueError): + rrb.Background((1.0, 0.0, 0.0), kind=rrb.BackgroundKind.GradientDark) + with pytest.raises(ValueError): + rrb.Background((1.0, 0.0, 0.0), color=(0.0, 1.0, 0.0)) diff --git a/rerun_py/tests/unit/test_background3d.py b/rerun_py/tests/unit/test_background3d.py deleted file mode 100644 index d761111006f5..000000000000 --- a/rerun_py/tests/unit/test_background3d.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import annotations - -import pytest -import rerun as rr -import rerun.blueprint as rrb - - -def test_background_3d_construction() -> None: - rr.set_strict_mode(True) - - assert rrb.Background3D((1.0, 0.0, 0.0)) == rrb.Background3D( - color=(1.0, 0.0, 0.0), kind=rrb.Background3DKind.SolidColor - ) - assert rrb.Background3D(rrb.Background3DKind.GradientBright) == rrb.Background3D( - color=None, kind=rrb.Background3DKind.GradientBright - ) - - with pytest.raises(ValueError): - rrb.Background3D(rrb.Background3DKind.GradientBright, kind=rrb.Background3DKind.GradientDark) - with pytest.raises(ValueError): - rrb.Background3D(rrb.Background3DKind.GradientBright, color=(0.0, 1.0, 0.0)) - with pytest.raises(ValueError): - rrb.Background3D((1.0, 0.0, 0.0), kind=rrb.Background3DKind.GradientDark) - with pytest.raises(ValueError): - rrb.Background3D((1.0, 0.0, 0.0), color=(0.0, 1.0, 0.0)) From f42ad74059e13d620dc1d0e861358686f7cc6afa Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:38:35 +0200 Subject: [PATCH 367/508] New data APIs 9: cached range queries (#5755) Static-aware, key-less, component-based, cached range APIs. ```rust let caches = re_query_cache2::Caches::new(&store); // First, get the raw results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. let results: CachedRangeResults = caches.range( &store, &query, &entity_path.into(), MyPoints::all_components().iter().copied(), // no generics! ); // Then, grab the results for each individual components. // * `get_required` returns an error if the component batch is missing // * `get_or_empty` returns an empty set of results if the component if missing // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. let all_points: &CachedRangeComponentResults = results.get_required(MyPoint::name())?; let all_colors: &CachedRangeComponentResults = results.get_or_empty(MyColor::name()); let all_labels: &CachedRangeComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. // // That's when caching comes into play. // If the data has already been accessed in the past, then this will just grab the // pre-deserialized, pre-resolved/pre-converted result from the cache. // Otherwise, this will trigger a deserialization and cache the result for next time. let all_points = all_points.to_dense::(&resolver); let all_colors = all_colors.to_dense::(&resolver); let all_labels = all_labels.to_dense::(&resolver); // The cache might not have been able to resolve and deserialize the entire dataset across all // available timestamps. // // We can use the following APIs to check the status of the front and back sides of the data range. // // E.g. it is possible that the front-side of the range is still waiting for pending data while // the back-side has been fully loaded. assert!(matches!( all_points.status(), (PromiseResult::Ready(()), PromiseResult::Ready(())) )); // Zip the results together using a stateful time-based join. let all_frames = range_zip_1x2( all_points.range_indexed(), all_colors.range_indexed(), all_labels.range_indexed(), ); // Then comes the time to resolve/convert and deserialize the data, _for each timestamp_. // These steps have to be done together for efficiency reasons. // // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. // Use `PromiseResult::flatten` to simplify it down to a single result. eprintln!("results:"); for ((data_time, row_id), points, colors, labels) in all_frames { let colors = colors.unwrap_or(&[]); let color_default_fn = || { static DEFAULT: MyColor = MyColor(0xFF00FFFF); &DEFAULT }; let labels = labels.unwrap_or(&[]).iter().cloned().map(Some); let label_default_fn = || None; // With the data now fully resolved/converted and deserialized, the joining logic can be // applied. // // In most cases this will be either a clamped zip, or no joining at all. let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn) .collect_vec(); eprintln!("{data_time:?} @ {row_id}:\n {results:?}"); } ``` --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- Cargo.lock | 1 + crates/re_data_store/src/store_read.rs | 18 + crates/re_query2/examples/range.rs | 6 +- crates/re_query2/src/promise.rs | 17 +- crates/re_query2/src/range/results.rs | 22 +- crates/re_query2/tests/range.rs | 10 +- crates/re_query_cache2/Cargo.toml | 1 + crates/re_query_cache2/examples/latest_at.rs | 15 +- crates/re_query_cache2/examples/range.rs | 151 ++++ crates/re_query_cache2/src/cache.rs | 46 +- crates/re_query_cache2/src/latest_at/query.rs | 28 +- .../re_query_cache2/src/latest_at/results.rs | 87 +- crates/re_query_cache2/src/lib.rs | 7 +- crates/re_query_cache2/src/range/mod.rs | 8 + crates/re_query_cache2/src/range/query.rs | 393 +++++++++ crates/re_query_cache2/src/range/results.rs | 748 ++++++++++++++++++ crates/re_query_cache2/tests/latest_at.rs | 4 +- crates/re_query_cache2/tests/range.rs | 586 ++++++++++++++ 18 files changed, 2018 insertions(+), 130 deletions(-) create mode 100644 crates/re_query_cache2/examples/range.rs create mode 100644 crates/re_query_cache2/src/range/mod.rs create mode 100644 crates/re_query_cache2/src/range/query.rs create mode 100644 crates/re_query_cache2/src/range/results.rs create mode 100644 crates/re_query_cache2/tests/range.rs diff --git a/Cargo.lock b/Cargo.lock index 3175708dc900..da19fba00f29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4547,6 +4547,7 @@ dependencies = [ "backtrace", "criterion", "indent", + "indexmap 2.1.0", "itertools 0.12.0", "mimalloc", "nohash-hasher", diff --git a/crates/re_data_store/src/store_read.rs b/crates/re_data_store/src/store_read.rs index 6700163ff668..ad83948579e4 100644 --- a/crates/re_data_store/src/store_read.rs +++ b/crates/re_data_store/src/store_read.rs @@ -87,6 +87,24 @@ impl RangeQuery { pub const fn new(timeline: Timeline, range: TimeRange) -> Self { Self { timeline, range } } + + #[inline] + pub const fn everything(timeline: Timeline) -> Self { + Self { + timeline, + range: TimeRange::EVERYTHING, + } + } + + #[inline] + pub fn timeline(&self) -> Timeline { + self.timeline + } + + #[inline] + pub fn range(&self) -> TimeRange { + self.range + } } // --- Data store --- diff --git a/crates/re_query2/examples/range.rs b/crates/re_query2/examples/range.rs index 5bb5d62503ad..e8c1a5227dc8 100644 --- a/crates/re_query2/examples/range.rs +++ b/crates/re_query2/examples/range.rs @@ -39,11 +39,11 @@ fn main() -> anyhow::Result<()> { // _component batch_ itself (that says nothing about its _instances_!). // // * `get_required` returns an error if the component batch is missing - // * `get_optional` returns an empty set of results if the component if missing + // * `get_or_empty` returns an empty set of results if the component if missing // * `get` returns an option let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; - let all_colors: &RangeComponentResults = results.get_optional(MyColor::name()); - let all_labels: &RangeComponentResults = results.get_optional(MyLabel::name()); + let all_colors: &RangeComponentResults = results.get_or_empty(MyColor::name()); + let all_labels: &RangeComponentResults = results.get_or_empty(MyLabel::name()); let all_indexed_points = izip!( all_points.iter_indices(), diff --git a/crates/re_query2/src/promise.rs b/crates/re_query2/src/promise.rs index a8f473c725a5..a6234e12f21f 100644 --- a/crates/re_query2/src/promise.rs +++ b/crates/re_query2/src/promise.rs @@ -14,6 +14,13 @@ impl std::fmt::Display for PromiseId { } } +impl re_types_core::SizeBytes for PromiseId { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } +} + impl PromiseId { /// Create a new unique [`PromiseId`] based on the current time. #[allow(clippy::new_without_default)] @@ -39,6 +46,14 @@ pub struct Promise { static_assertions::assert_eq_size!(Promise, Option); +impl re_types_core::SizeBytes for Promise { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self { id, source } = self; + id.heap_size_bytes() + source.heap_size_bytes() + } +} + impl Promise { #[inline] pub fn new(source: DataCell) -> Self { @@ -75,7 +90,7 @@ impl PromiseResolver { } /// The result of resolving a [`Promise`] through a [`PromiseResolver`]. -#[derive(Clone)] +#[derive(Debug, Clone)] pub enum PromiseResult { /// The resolution process is still in progress. /// diff --git a/crates/re_query2/src/range/results.rs b/crates/re_query2/src/range/results.rs index 883101db0264..2cfe48751a7d 100644 --- a/crates/re_query2/src/range/results.rs +++ b/crates/re_query2/src/range/results.rs @@ -12,7 +12,7 @@ use crate::{Promise, PromiseResolver, PromiseResult}; /// The data is neither deserialized, nor resolved/converted. /// It it the raw [`DataCell`]s, straight from our datastore. /// -/// Use [`RangeResults::get`], [`RangeResults::get_required`] and [`RangeResults::get_optional`] +/// Use [`RangeResults::get`], [`RangeResults::get_required`] and [`RangeResults::get_or_empty`] /// in order to access the raw results for each individual component. #[derive(Default, Debug, Clone)] pub struct RangeResults { @@ -56,7 +56,7 @@ impl RangeResults { /// /// Returns empty results if the component is not present. #[inline] - pub fn get_optional(&self, component_name: impl Into) -> &RangeComponentResults { + pub fn get_or_empty(&self, component_name: impl Into) -> &RangeComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component @@ -79,7 +79,10 @@ impl RangeResults { .map(|(index, cell)| (index, Promise::new(cell))) .unzip(); - let results = RangeComponentResults { indices, cells }; + let results = RangeComponentResults { + indices, + promises: cells, + }; results.sanity_check(); self.components.insert(component_name, results); @@ -92,7 +95,7 @@ impl RangeResults { #[derive(Debug, Clone)] pub struct RangeComponentResults { pub indices: Vec<(TimeInt, RowId)>, - pub cells: Vec, + pub promises: Vec, } impl Default for RangeComponentResults { @@ -107,14 +110,17 @@ impl RangeComponentResults { pub const fn empty() -> Self { Self { indices: Vec::new(), - cells: Vec::new(), + promises: Vec::new(), } } /// No-op in release. #[inline] pub fn sanity_check(&self) { - let Self { indices, cells } = self; + let Self { + indices, + promises: cells, + } = self; if cfg!(debug_assertions) { assert_eq!(indices.len(), cells.len()); } @@ -141,7 +147,7 @@ impl RangeComponentResults { &self, resolver: &PromiseResolver, ) -> Vec>>> { - self.cells + self.promises .iter() .map(|cell| { resolver.resolve(cell).map(|cell| { @@ -173,7 +179,7 @@ impl RangeComponentResults { &self, resolver: &PromiseResolver, ) -> Vec>>>> { - self.cells + self.promises .iter() .map(|cell| { resolver.resolve(cell).map(|cell| { diff --git a/crates/re_query2/tests/range.rs b/crates/re_query2/tests/range.rs index 6f47f1fb1184..a000f588b311 100644 --- a/crates/re_query2/tests/range.rs +++ b/crates/re_query2/tests/range.rs @@ -68,7 +68,7 @@ fn simple_range() -> anyhow::Result<()> { ); let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_optional(MyColor::name()); + let all_colors = results.get_or_empty(MyColor::name()); let all_points = izip!( all_points.iter_indices(), @@ -131,7 +131,7 @@ fn simple_range() -> anyhow::Result<()> { ); let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_optional(MyColor::name()); + let all_colors = results.get_or_empty(MyColor::name()); let all_points = izip!( all_points.iter_indices(), @@ -313,7 +313,7 @@ fn static_range() -> anyhow::Result<()> { ); let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_optional(MyColor::name()); + let all_colors = results.get_or_empty(MyColor::name()); let all_points = izip!( all_points.iter_indices(), @@ -363,7 +363,7 @@ fn static_range() -> anyhow::Result<()> { ); let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_optional(MyColor::name()); + let all_colors = results.get_or_empty(MyColor::name()); let all_points = izip!( all_points.iter_indices(), @@ -434,7 +434,7 @@ fn static_range() -> anyhow::Result<()> { ); let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_optional(MyColor::name()); + let all_colors = results.get_or_empty(MyColor::name()); let all_points = izip!( all_points.iter_indices(), diff --git a/crates/re_query_cache2/Cargo.toml b/crates/re_query_cache2/Cargo.toml index 61dc907792b3..b8b67820c4ee 100644 --- a/crates/re_query_cache2/Cargo.toml +++ b/crates/re_query_cache2/Cargo.toml @@ -46,6 +46,7 @@ ahash.workspace = true anyhow.workspace = true backtrace.workspace = true indent.workspace = true +indexmap.workspace = true itertools.workspace = true nohash-hasher.workspace = true parking_lot.workspace = true diff --git a/crates/re_query_cache2/examples/latest_at.rs b/crates/re_query_cache2/examples/latest_at.rs index e47f70fa08fa..c283aac83f0f 100644 --- a/crates/re_query_cache2/examples/latest_at.rs +++ b/crates/re_query_cache2/examples/latest_at.rs @@ -51,16 +51,9 @@ fn main() -> anyhow::Result<()> { // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. // Use `PromiseResult::flatten` to simplify it down to a single result. // - // A choice now has to be made regarding the nullability of the _component batch's instances_. - // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably - // shouldn't be using anything but `iter_dense`. - // // This is the step at which caching comes into play. - // - // If the data has already been accessed with the same nullability characteristics in the - // past, then this will just grab the pre-deserialized, pre-resolved/pre-converted result from - // the cache. - // + // If the data has already been accessed in the past, then this will just grab the pre-deserialized, + // pre-resolved/pre-converted result from the cache. // Otherwise, this will trigger a deserialization and cache the result for next time. let points = match points.iter_dense::(&resolver).flatten() { @@ -81,12 +74,12 @@ fn main() -> anyhow::Result<()> { PromiseResult::Error(err) => return Err(err.into()), }; - let labels = match labels.iter_sparse::(&resolver).flatten() { + let labels = match labels.iter_dense::(&resolver).flatten() { PromiseResult::Pending => { // Handle the fact that the data isn't ready appropriately. return Ok(()); } - PromiseResult::Ready(data) => data, + PromiseResult::Ready(data) => data.map(Some), PromiseResult::Error(err) => return Err(err.into()), }; diff --git a/crates/re_query_cache2/examples/range.rs b/crates/re_query_cache2/examples/range.rs new file mode 100644 index 000000000000..45d46093beb0 --- /dev/null +++ b/crates/re_query_cache2/examples/range.rs @@ -0,0 +1,151 @@ +use itertools::Itertools; +use re_data_store::{DataStore, RangeQuery}; +use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; +use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; +use re_types_core::{Archetype as _, Loggable as _}; + +use re_query_cache2::{ + clamped_zip_1x2, range_zip_1x2, CachedRangeComponentResults, CachedRangeResults, + PromiseResolver, PromiseResult, +}; + +// --- + +fn main() -> anyhow::Result<()> { + let store = store()?; + eprintln!("store:\n{}", store.to_data_table()?); + + let resolver = PromiseResolver::default(); + + let entity_path = "points"; + let timeline = Timeline::new("frame_nr", TimeType::Sequence); + let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); + eprintln!("query:{query:?}"); + + let caches = re_query_cache2::Caches::new(&store); + + // First, get the raw results for this query. + // + // They might or might not already be cached. We won't know for sure until we try to access + // each individual component's data below. + let results: CachedRangeResults = caches.range( + &store, + &query, + &entity_path.into(), + MyPoints::all_components().iter().copied(), // no generics! + ); + + // Then, grab the results for each individual components. + // * `get_required` returns an error if the component batch is missing + // * `get_or_empty` returns an empty set of results if the component if missing + // * `get` returns an option + // + // At this point we still don't know whether they are cached or not. That's the next step. + let all_points: &CachedRangeComponentResults = results.get_required(MyPoint::name())?; + let all_colors: &CachedRangeComponentResults = results.get_or_empty(MyColor::name()); + let all_labels: &CachedRangeComponentResults = results.get_or_empty(MyLabel::name()); + + // Then comes the time to resolve/convert and deserialize the data. + // These steps have to be done together for efficiency reasons. + // + // That's when caching comes into play. + // If the data has already been accessed in the past, then this will just grab the + // pre-deserialized, pre-resolved/pre-converted result from the cache. + // Otherwise, this will trigger a deserialization and cache the result for next time. + let all_points = all_points.to_dense::(&resolver); + let all_colors = all_colors.to_dense::(&resolver); + let all_labels = all_labels.to_dense::(&resolver); + + // The cache might not have been able to resolve and deserialize the entire dataset across all + // available timestamps. + // + // We can use the following APIs to check the status of the front and back sides of the data range. + // + // E.g. it is possible that the front-side of the range is still waiting for pending data while + // the back-side has been fully loaded. + assert!(matches!( + all_points.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + )); + + // Zip the results together using a stateful time-based join. + let all_frames = range_zip_1x2( + all_points.range_indexed(), + all_colors.range_indexed(), + all_labels.range_indexed(), + ); + + // Then comes the time to resolve/convert and deserialize the data, _for each timestamp_. + // These steps have to be done together for efficiency reasons. + // + // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. + // Use `PromiseResult::flatten` to simplify it down to a single result. + eprintln!("results:"); + for ((data_time, row_id), points, colors, labels) in all_frames { + let colors = colors.unwrap_or(&[]); + let color_default_fn = || { + static DEFAULT: MyColor = MyColor(0xFF00FFFF); + &DEFAULT + }; + + let labels = labels.unwrap_or(&[]).iter().cloned().map(Some); + let label_default_fn = || None; + + // With the data now fully resolved/converted and deserialized, the joining logic can be + // applied. + // + // In most cases this will be either a clamped zip, or no joining at all. + + let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn) + .collect_vec(); + eprintln!("{data_time:?} @ {row_id}:\n {results:?}"); + } + + Ok(()) +} + +// --- + +fn store() -> anyhow::Result { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + re_types::components::InstanceKey::name(), + Default::default(), + ); + + let entity_path = "points"; + + { + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + store.insert_row(&row)?; + } + + { + let timepoint = [build_frame_nr(456)]; + + let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 0, 255)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + store.insert_row(&row)?; + + let points = vec![ + MyPoint::new(10.0, 20.0), + MyPoint::new(30.0, 40.0), + MyPoint::new(50.0, 60.0), + ]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + store.insert_row(&row)?; + } + + Ok(store) +} diff --git a/crates/re_query_cache2/src/cache.rs b/crates/re_query_cache2/src/cache.rs index 959707eca1c5..6e5278a9f1e5 100644 --- a/crates/re_query_cache2/src/cache.rs +++ b/crates/re_query_cache2/src/cache.rs @@ -7,7 +7,7 @@ use re_data_store::{DataStore, StoreDiff, StoreEvent, StoreSubscriber, TimeInt}; use re_log_types::{EntityPath, StoreId, Timeline}; use re_types_core::ComponentName; -use crate::LatestAtCache; +use crate::{LatestAtCache, RangeCache}; // --- @@ -19,6 +19,20 @@ pub struct CacheKey { pub component_name: ComponentName, } +impl re_types_core::SizeBytes for CacheKey { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self { + entity_path, + timeline, + component_name, + } = self; + entity_path.heap_size_bytes() + + timeline.heap_size_bytes() + + component_name.heap_size_bytes() + } +} + impl std::fmt::Debug for CacheKey { #[inline] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -55,7 +69,10 @@ pub struct Caches { pub(crate) store_id: StoreId, // NOTE: `Arc` so we can cheaply free the top-level lock early when needed. - pub(crate) per_cache_key: RwLock>>>, + pub(crate) latest_at_per_cache_key: RwLock>>>, + + // NOTE: `Arc` so we can cheaply free the top-level lock early when needed. + pub(crate) range_per_cache_key: RwLock>>>, } impl Caches { @@ -63,7 +80,8 @@ impl Caches { pub fn new(store: &DataStore) -> Self { Self { store_id: store.id().clone(), - per_cache_key: Default::default(), + latest_at_per_cache_key: Default::default(), + range_per_cache_key: Default::default(), } } } @@ -139,8 +157,9 @@ impl StoreSubscriber for Caches { } } - let caches = self.per_cache_key.write(); - // NOTE: Don't release the top-level lock -- even though this cannot happen yet with + let caches_latest_at = self.latest_at_per_cache_key.write(); + let caches_range = self.range_per_cache_key.write(); + // NOTE: Don't release the top-level locks -- even though this cannot happen yet with // our current macro-architecture, we want to prevent queries from concurrently // running while we're updating the invalidation flags. @@ -152,11 +171,17 @@ impl StoreSubscriber for Caches { // But since this pretty much never happens in practice, let's not go there until we // have metrics showing that show we need to. for (entity_path, component_name) in compacted.static_ { - for (key, cache) in caches.iter() { + for (key, cache) in caches_latest_at.iter() { if key.entity_path == entity_path && key.component_name == component_name { cache.write().pending_invalidations.insert(TimeInt::STATIC); } } + + for (key, cache) in caches_range.iter() { + if key.entity_path == entity_path && key.component_name == component_name { + cache.write().pending_invalidation = Some(TimeInt::STATIC); + } + } } } @@ -164,12 +189,19 @@ impl StoreSubscriber for Caches { re_tracing::profile_scope!("temporal"); for (key, times) in compacted.temporal { - if let Some(cache) = caches.get(&key) { + if let Some(cache) = caches_latest_at.get(&key) { cache .write() .pending_invalidations .extend(times.iter().copied()); } + + if let Some(cache) = caches_range.get(&key) { + let pending_invalidation = &mut cache.write().pending_invalidation; + let min_time = times.first().copied(); + *pending_invalidation = + Option::min(*pending_invalidation, min_time).or(min_time); + } } } } diff --git a/crates/re_query_cache2/src/latest_at/query.rs b/crates/re_query_cache2/src/latest_at/query.rs index 878dece4f81d..b2e9e931d2e3 100644 --- a/crates/re_query_cache2/src/latest_at/query.rs +++ b/crates/re_query_cache2/src/latest_at/query.rs @@ -36,7 +36,7 @@ impl Caches { for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); let cache = Arc::clone( - self.per_cache_key + self.latest_at_per_cache_key .write() .entry(key.clone()) .or_insert_with(|| Arc::new(RwLock::new(LatestAtCache::new(key.clone())))), @@ -217,7 +217,6 @@ impl LatestAtCache { index: (data_time, row_id), promise: Some(Promise::new(cell)), cached_dense: Default::default(), - cached_sparse: Default::default(), cached_heap_size_bytes: AtomicU64::new(0), }); @@ -248,8 +247,6 @@ impl LatestAtCache { pending_invalidations, } = self; - let pending_invalidations = std::mem::take(pending_invalidations); - // First, remove any data indexed by a _query time_ that's more recent than the oldest // _data time_ that's been invalidated. // @@ -260,6 +257,27 @@ impl LatestAtCache { } // Second, remove any data indexed by _data time_, if it's been invalidated. - per_data_time.retain(|data_time, _| !pending_invalidations.contains(data_time)); + let mut dropped_data_times = Vec::new(); + per_data_time.retain(|data_time, _| { + if pending_invalidations.contains(data_time) { + dropped_data_times.push(*data_time); + false + } else { + true + } + }); + + // TODO(#5974): Because of non-deterministic ordering and parallelism and all things of that + // nature, it can happen that we try to handle pending invalidations before we even cached + // the associated data. + // + // If that happens, the data will be cached after we've invalidated *nothing*, and will stay + // there indefinitely since the cache doesn't have a dedicated GC yet. + // + // TL;DR: make sure to keep track of pending invalidations indefinitely as long as we + // haven't had the opportunity to actually invalidate the associated data. + for data_time in dropped_data_times { + pending_invalidations.remove(&data_time); + } } } diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index ec591ff97315..4597807f3ec5 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -131,9 +131,6 @@ pub struct CachedLatestAtComponentResults { /// The resolved, converted, deserialized dense data. pub(crate) cached_dense: OnceLock>, - /// The resolved, converted, deserialized sparse data. - pub(crate) cached_sparse: OnceLock>, - pub(crate) cached_heap_size_bytes: AtomicU64, } @@ -144,7 +141,6 @@ impl CachedLatestAtComponentResults { index: (TimeInt::STATIC, RowId::ZERO), promise: None, cached_dense: OnceLock::new(), - cached_sparse: OnceLock::new(), cached_heap_size_bytes: AtomicU64::new(0), } } @@ -177,8 +173,7 @@ impl std::fmt::Debug for CachedLatestAtComponentResults { let Self { index, promise: _, - cached_dense: _, // we can't, we don't know the type - cached_sparse: _, // we can't, we don't know the type + cached_dense: _, // we can't, we don't know the type cached_heap_size_bytes, } = self; @@ -242,42 +237,6 @@ impl CachedLatestAtComponentResults { self.to_dense(resolver) .map(|data| data.map(|data| data.iter())) } - - /// Returns the component data as a sparse vector. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_sparse( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult]>> { - if let Some(cell) = self.promise.as_ref() { - resolver - .resolve(cell) - .map(|cell| self.downcast_sparse::(&cell)) - } else { - // Manufactured empty result. - PromiseResult::Ready(Ok(&[])) - } - } - - /// Iterates over the component data, assuming it is sparse. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_sparse( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>>> { - self.to_sparse(resolver) - .map(|data| data.map(|data| data.iter().map(Option::as_ref))) - } } impl CachedLatestAtComponentResults { @@ -306,32 +265,6 @@ impl CachedLatestAtComponentResults { downcast(&**cached) } - - fn downcast_sparse(&self, cell: &DataCell) -> crate::Result<&[Option]> { - // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the - // data has already been computed. - // - // See next comment as to why we need this. - if let Some(cached) = self.cached_sparse.get() { - return downcast_opt(&**cached); - } - - // We have to do this outside of the callback in order to propagate errors. - // Hence the early exit check above. - let data = cell - .try_to_native_opt::() - .map_err(|err| DeserializationError::DataCellError(err.to_string()))?; - - #[allow(clippy::borrowed_box)] - let cached: &Box = - self.cached_sparse.get_or_init(move || { - self.cached_heap_size_bytes - .fetch_add(data.total_size_bytes(), Relaxed); - Box::new(FlatVecDeque::from(data)) - }); - - downcast_opt(&**cached) - } } fn downcast(cached: &(dyn ErasedFlatVecDeque + Send + Sync)) -> crate::Result<&[C]> { @@ -349,21 +282,3 @@ fn downcast(cached: &(dyn ErasedFlatVecDeque + Send + Sync)) -> cr // unwrap checked just above ^^^ Ok(cached.iter().next().unwrap()) } - -fn downcast_opt( - cached: &(dyn ErasedFlatVecDeque + Send + Sync), -) -> crate::Result<&[Option]> { - let cached = cached - .as_any() - .downcast_ref::>>() - .ok_or_else(|| QueryError::TypeMismatch { - actual: "".into(), - requested: C::name(), - })?; - - if cached.num_entries() != 1 { - return Err(anyhow::anyhow!("latest_at deque must be single entry").into()); - } - // unwrap checked just above ^^^ - Ok(cached.iter().next().unwrap()) -} diff --git a/crates/re_query_cache2/src/lib.rs b/crates/re_query_cache2/src/lib.rs index 58e3f4b46669..d8965db3cc81 100644 --- a/crates/re_query_cache2/src/lib.rs +++ b/crates/re_query_cache2/src/lib.rs @@ -3,18 +3,21 @@ mod cache; mod flat_vec_deque; mod latest_at; +mod range; pub use self::cache::{CacheKey, Caches}; pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; pub use self::latest_at::{ CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, }; +pub use self::range::{CachedRangeComponentResults, CachedRangeData, CachedRangeResults}; pub(crate) use self::latest_at::LatestAtCache; +pub(crate) use self::range::{CachedRangeComponentResultsInner, RangeCache}; pub use re_query2::{ - clamped_zip::*, Promise, PromiseId, PromiseResolver, PromiseResult, QueryError, Result, - ToArchetype, + clamped_zip::*, range_zip::*, ExtraQueryHistory, Promise, PromiseId, PromiseResolver, + PromiseResult, QueryError, Result, ToArchetype, VisibleHistory, VisibleHistoryBoundary, }; pub mod external { diff --git a/crates/re_query_cache2/src/range/mod.rs b/crates/re_query_cache2/src/range/mod.rs new file mode 100644 index 000000000000..ffb93dd2f720 --- /dev/null +++ b/crates/re_query_cache2/src/range/mod.rs @@ -0,0 +1,8 @@ +mod query; +mod results; + +pub use self::query::RangeCache; +pub use self::results::{ + CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeData, + CachedRangeResults, +}; diff --git a/crates/re_query_cache2/src/range/query.rs b/crates/re_query_cache2/src/range/query.rs new file mode 100644 index 000000000000..f04664b96c25 --- /dev/null +++ b/crates/re_query_cache2/src/range/query.rs @@ -0,0 +1,393 @@ +use std::sync::Arc; + +use parking_lot::RwLock; + +use re_data_store::{DataStore, RangeQuery, TimeInt}; +use re_log_types::{EntityPath, TimeRange}; +use re_types_core::ComponentName; +use re_types_core::SizeBytes; + +use crate::{ + CacheKey, CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeResults, + Caches, Promise, +}; + +// --- + +impl Caches { + /// Queries for the given `component_names` using range semantics. + /// + /// See [`CachedRangeResults`] for more information about how to handle the results. + /// + /// This is a cached API -- data will be lazily cached upon access. + pub fn range( + &self, + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, + component_names: impl IntoIterator, + ) -> CachedRangeResults { + re_tracing::profile_function!(entity_path.to_string()); + + let mut results = CachedRangeResults::new(query.clone()); + + for component_name in component_names { + let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); + + let cache = Arc::clone( + self.range_per_cache_key + .write() + .entry(key.clone()) + .or_insert_with(|| Arc::new(RwLock::new(RangeCache::new(key.clone())))), + ); + + let mut cache = cache.write(); + cache.handle_pending_invalidation(); + let cached = cache.range(store, query, entity_path, component_name); + results.add(component_name, cached); + } + + results + } +} + +// --- + +/// Caches the results of `Range` queries for a given [`CacheKey`]. +pub struct RangeCache { + /// For debugging purposes. + pub cache_key: CacheKey, + + /// All temporal data, organized by _data_ time. + /// + /// Query time is irrelevant for range queries. + pub per_data_time: CachedRangeComponentResults, + + /// Everything greater than or equal to this timestamp has been asynchronously invalidated. + /// + /// The next time this cache gets queried, it must remove any entry matching this criteria. + /// `None` indicates that there's no pending invalidation. + /// + /// Invalidation is deferred to query time because it is far more efficient that way: the frame + /// time effectively behaves as a natural micro-batching mechanism. + pub pending_invalidation: Option, +} + +impl RangeCache { + #[inline] + pub fn new(cache_key: CacheKey) -> Self { + Self { + cache_key, + per_data_time: CachedRangeComponentResults::default(), + pending_invalidation: None, + } + } +} + +impl std::fmt::Debug for RangeCache { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + cache_key, + per_data_time, + pending_invalidation: _, + } = self; + + let mut strings = Vec::new(); + + let mut data_time_min = TimeInt::MAX; + let mut data_time_max = TimeInt::MIN; + + { + let per_data_time = per_data_time.read(); + + let per_data_time_indices = &per_data_time.indices; + if let Some(time_front) = per_data_time_indices.front().map(|(t, _)| *t) { + data_time_min = TimeInt::min(data_time_min, time_front); + } + if let Some(time_back) = per_data_time_indices.back().map(|(t, _)| *t) { + data_time_max = TimeInt::max(data_time_max, time_back); + } + } + + strings.push(format!( + "{} ({})", + cache_key + .timeline + .typ() + .format_range_utc(TimeRange::new(data_time_min, data_time_max)), + re_format::format_bytes(per_data_time.total_size_bytes() as _), + )); + + if strings.is_empty() { + return f.write_str(""); + } + + f.write_str(&strings.join("\n").replace("\n\n", "\n")) + } +} + +impl SizeBytes for RangeCache { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self { + cache_key, + per_data_time, + pending_invalidation, + } = self; + + cache_key.heap_size_bytes() + + per_data_time.heap_size_bytes() + + pending_invalidation.heap_size_bytes() + } +} + +impl RangeCache { + /// Queries cached range data for a single component. + pub fn range( + &mut self, + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, + component_name: ComponentName, + ) -> CachedRangeComponentResults { + re_tracing::profile_scope!("range", format!("{query:?}")); + + let RangeCache { + cache_key: _, + per_data_time, + pending_invalidation: _, + } = self; + + let mut per_data_time = per_data_time.write(); + + let query_front = per_data_time.compute_front_query(query); + if let Some(query_front) = query_front.as_ref() { + re_tracing::profile_scope!("front"); + + for (data_time, row_id, mut cells) in + store.range(query_front, entity_path, [component_name]) + { + // Soundness: + // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` + // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null + let Some(cell) = cells[0].take() else { + debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); + continue; + }; + + per_data_time + .promises_front + .push(((data_time, row_id), Promise::new(cell))); + per_data_time + .promises_front + .sort_by_key(|(index, _)| *index); + } + } + + if let Some(query_back) = per_data_time.compute_back_query(query, query_front.as_ref()) { + re_tracing::profile_scope!("back"); + + for (data_time, row_id, mut cells) in store + .range(&query_back, entity_path, [component_name]) + // If there's static data to be found, the front query will take care of it already. + .filter(|(data_time, _, _)| !data_time.is_static()) + { + // Soundness: + // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` + // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null + let Some(cell) = cells[0].take() else { + debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); + continue; + }; + + per_data_time + .promises_back + .push(((data_time, row_id), Promise::new(cell))); + per_data_time.promises_back.sort_by_key(|(index, _)| *index); + } + } + + per_data_time.sanity_check(); + drop(per_data_time); + + self.per_data_time.clone_at(query.range()) + } + + pub fn handle_pending_invalidation(&mut self) { + re_tracing::profile_function!(); + + let Self { + cache_key: _, + per_data_time, + pending_invalidation, + } = self; + + let Some(pending_invalidation) = pending_invalidation.take() else { + return; + }; + + per_data_time.write().truncate_at_time(pending_invalidation); + } +} + +// --- + +impl CachedRangeComponentResultsInner { + /// How many _indices_ across this entire cache? + #[inline] + pub fn num_indices(&self) -> u64 { + self.indices.len() as _ + } + + /// How many _instances_ across this entire cache? + #[inline] + pub fn num_instances(&self) -> u64 { + self.cached_dense + .as_ref() + .map_or(0u64, |cached| cached.dyn_num_values() as _) + } + + /// Given a `query`, returns N reduced queries that are sufficient to fill the missing data + /// on both the front & back sides of the cache. + #[inline] + pub fn compute_queries(&self, query: &RangeQuery) -> impl Iterator { + let front = self.compute_front_query(query); + let back = self.compute_back_query(query, front.as_ref()); + front.into_iter().chain(back) + } + + /// Given a `query`, returns a reduced query that is sufficient to fill the missing data + /// on the front side of the cache, or `None` if all the necessary data is already + /// cached. + pub fn compute_front_query(&self, query: &RangeQuery) -> Option { + let mut reduced_query = query.clone(); + + // If nothing has been cached already, then we just want to query everything. + if self.indices.is_empty() + && self.promises_front.is_empty() + && self.promises_back.is_empty() + { + return Some(reduced_query); + } + + // If the cache contains static data, then there's no point in querying anything else since + // static data overrides everything anyway. + if self + .indices + .front() + .map_or(false, |(data_time, _)| data_time.is_static()) + { + return None; + } + + // Otherwise, query for what's missing on the front-side of the cache, while making sure to + // take pending promises into account! + // + // Keep in mind: it is not possible for the cache to contain only part of a given + // timestamp. All entries for a given timestamp are loaded and invalidated atomically, + // whether it's promises or already resolved entries. + + let pending_front_min = self + .promises_front + .first() + .map_or(TimeInt::MAX.as_i64(), |((t, _), _)| { + t.as_i64().saturating_sub(1) + }); + + if let Some(time_range) = self.time_range() { + let time_range_min = i64::min( + time_range.min().as_i64().saturating_sub(1), + pending_front_min, + ); + reduced_query + .range + .set_max(i64::min(reduced_query.range.max().as_i64(), time_range_min)); + } else { + reduced_query.range.set_max(i64::min( + reduced_query.range.max().as_i64(), + pending_front_min, + )); + } + + if reduced_query.range.max() < reduced_query.range.min() { + return None; + } + + Some(reduced_query) + } + + /// Given a `query`, returns a reduced query that is sufficient to fill the missing data + /// on the back side of the cache, or `None` if all the necessary data is already + /// cached. + pub fn compute_back_query( + &self, + query: &RangeQuery, + query_front: Option<&RangeQuery>, + ) -> Option { + let mut reduced_query = query.clone(); + + // If nothing has been cached already, then the front query is already going to take care + // of everything. + if self.indices.is_empty() + && self.promises_front.is_empty() + && self.promises_back.is_empty() + { + return None; + } + + // If the cache contains static data, then there's no point in querying anything else since + // static data overrides everything anyway. + if self + .indices + .front() + .map_or(false, |(data_time, _)| data_time.is_static()) + { + return None; + } + + // Otherwise, query for what's missing on the back-side of the cache, while making sure to + // take pending promises into account! + // + // Keep in mind: it is not possible for the cache to contain only part of a given + // timestamp. All entries for a given timestamp are loaded and invalidated atomically, + // whether it's promises or already resolved entries. + + let pending_back_max = self + .promises_back + .last() + .map_or(TimeInt::MIN.as_i64(), |((t, _), _)| { + t.as_i64().saturating_add(1) + }); + + if let Some(time_range) = self.time_range() { + let time_range_max = i64::max( + time_range.max().as_i64().saturating_add(1), + pending_back_max, + ); + reduced_query + .range + .set_min(i64::max(reduced_query.range.min().as_i64(), time_range_max)); + } else { + reduced_query.range.set_min(i64::max( + reduced_query.range.min().as_i64(), + pending_back_max, + )); + } + + // Back query should never overlap with the front query. + // Reminder: time ranges are all inclusive. + if let Some(query_front) = query_front { + let front_max_plus_one = query_front.range().max().as_i64().saturating_add(1); + let back_min = reduced_query.range().min().as_i64(); + reduced_query + .range + .set_min(i64::max(back_min, front_max_plus_one)); + } + + if reduced_query.range.max() < reduced_query.range.min() { + return None; + } + + Some(reduced_query) + } +} diff --git a/crates/re_query_cache2/src/range/results.rs b/crates/re_query_cache2/src/range/results.rs new file mode 100644 index 000000000000..cfd804055fc0 --- /dev/null +++ b/crates/re_query_cache2/src/range/results.rs @@ -0,0 +1,748 @@ +use std::{ + cell::RefCell, + collections::VecDeque, + ops::Range, + sync::{Arc, OnceLock}, +}; + +use nohash_hasher::IntMap; + +use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; +use re_data_store::RangeQuery; +use re_log_types::{RowId, TimeInt, TimeRange}; +use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; + +use crate::{ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, PromiseResult}; + +// --- + +/// Cached results for a range query. +/// +/// The data is both deserialized and resolved/converted. +/// +/// Use [`CachedRangeResults::get`], [`CachedRangeResults::get_required`] and +/// [`CachedRangeResults::get_or_empty`] in order to access the results for each individual component. +#[derive(Debug)] +pub struct CachedRangeResults { + pub query: RangeQuery, + pub components: IntMap, +} + +impl CachedRangeResults { + #[inline] + pub(crate) fn new(query: RangeQuery) -> Self { + Self { + query, + components: Default::default(), + } + } + + #[inline] + pub fn contains(&self, component_name: impl Into) -> bool { + self.components.contains_key(&component_name.into()) + } + + /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + #[inline] + pub fn get( + &self, + component_name: impl Into, + ) -> Option<&CachedRangeComponentResults> { + self.components.get(&component_name.into()) + } + + /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// + /// Returns an error if the component is not present. + #[inline] + pub fn get_required( + &self, + component_name: impl Into, + ) -> crate::Result<&CachedRangeComponentResults> { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { + Ok(component) + } else { + Err(DeserializationError::MissingComponent { + component: component_name, + backtrace: ::backtrace::Backtrace::new_unresolved(), + } + .into()) + } + } + + /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// + /// Returns empty results if the component is not present. + #[inline] + pub fn get_or_empty( + &self, + component_name: impl Into, + ) -> &CachedRangeComponentResults { + let component_name = component_name.into(); + if let Some(component) = self.components.get(&component_name) { + component + } else { + CachedRangeComponentResults::empty() + } + } +} + +impl CachedRangeResults { + #[doc(hidden)] + #[inline] + pub fn add(&mut self, component_name: ComponentName, cached: CachedRangeComponentResults) { + self.components.insert(component_name, cached); + } +} + +// --- + +/// Lazily cached results for a particular component when using a cached range query. +#[derive(Debug)] +pub struct CachedRangeComponentResults { + /// The [`TimeRange`] of the query that was used in order to retrieve these results in the + /// first place. + /// + /// The "original" copy in the cache just stores [`TimeRange::EMPTY`]. It's meaningless. + pub(crate) time_range: TimeRange, + + pub(crate) inner: Arc>, +} + +impl CachedRangeComponentResults { + /// Clones the results while making sure to stamp them with the [`TimeRange`] of the associated query. + #[inline] + pub(crate) fn clone_at(&self, time_range: TimeRange) -> Self { + Self { + time_range, + inner: self.inner.clone(), + } + } +} + +impl CachedRangeComponentResults { + #[inline] + pub fn empty() -> &'static Self { + static EMPTY: OnceLock = OnceLock::new(); + EMPTY.get_or_init(CachedRangeComponentResults::default) + } +} + +impl re_types_core::SizeBytes for CachedRangeComponentResults { + #[inline] + fn heap_size_bytes(&self) -> u64 { + // NOTE: it's all on the heap past this point. + self.inner.read_recursive().total_size_bytes() + } +} + +impl Default for CachedRangeComponentResults { + #[inline] + fn default() -> Self { + Self { + time_range: TimeRange::EMPTY, + inner: Arc::new(RwLock::new(CachedRangeComponentResultsInner::empty())), + } + } +} + +impl std::ops::Deref for CachedRangeComponentResults { + type Target = RwLock; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[derive(Debug)] +pub struct CachedRangeData<'a, T> { + // NOTE: Options so we can represent an empty result without having to somehow conjure a mutex + // guard out of thin air. + // + // TODO(Amanieu/parking_lot#289): we need two distinct mapped guards because it's + // impossible to return an owned type in a `parking_lot` guard. + // See . + indices: Option>>, + data: Option>>, + + time_range: TimeRange, + front_status: PromiseResult<()>, + back_status: PromiseResult<()>, + + /// Keeps track of reentrancy counts for the current thread. + /// + /// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing + /// environments such as Rayon. + reentering: &'static std::thread::LocalKey>, +} + +impl<'a, T> Drop for CachedRangeData<'a, T> { + #[inline] + fn drop(&mut self) { + self.reentering + .with_borrow_mut(|reentering| *reentering = reentering.saturating_sub(1)); + } +} + +impl<'a, T> CachedRangeData<'a, T> { + /// Returns the current status on both ends of the range. + /// + /// E.g. it is possible that the front-side of the range is still waiting for pending data while + /// the back-side has been fully loaded. + #[inline] + pub fn status(&self) -> (PromiseResult<()>, PromiseResult<()>) { + (self.front_status.clone(), self.back_status.clone()) + } + + #[inline] + pub fn range_indices( + &self, + entry_range: Range, + ) -> impl Iterator { + match self.indices.as_ref() { + Some(indices) => itertools::Either::Left(indices.range(entry_range)), + None => itertools::Either::Right(std::iter::empty()), + } + } + + #[inline] + pub fn range_data(&self, entry_range: Range) -> impl Iterator { + match self.data.as_ref() { + Some(indices) => itertools::Either::Left(indices.range(entry_range)), + None => itertools::Either::Right(std::iter::empty()), + } + } + + /// Range both the indices and data by zipping them together. + /// + /// Useful for time-based joins (`range_zip`). + #[inline] + pub fn range_indexed(&self) -> impl Iterator { + let entry_range = self.entry_range(); + itertools::izip!( + self.range_indices(entry_range.clone()), + self.range_data(entry_range) + ) + } + + /// Returns the index range that corresponds to the specified `time_range`. + /// + /// Use the returned range with one of the range iteration methods: + /// - [`Self::range_indices`] + /// - [`Self::range_data`] + /// - [`Self::range_indexed`] + /// + /// Make sure that the bucket hasn't been modified in-between! + /// + /// This is `O(2*log(n))`, so make sure to clone the returned range rather than calling this + /// multiple times. + #[inline] + pub fn entry_range(&self) -> Range { + let Some(indices) = self.indices.as_ref() else { + return 0..0; + }; + + // If there's any static data cached, make sure to look for it explicitly. + // + // Remember: `TimeRange`s can never contain `TimeInt::STATIC`. + let static_override = if matches!(indices.front(), Some((TimeInt::STATIC, _))) { + TimeInt::STATIC + } else { + TimeInt::MAX + }; + + let start_index = indices.partition_point(|(data_time, _)| { + *data_time < TimeInt::min(self.time_range.min(), static_override) + }); + let end_index = indices.partition_point(|(data_time, _)| { + *data_time <= TimeInt::min(self.time_range.max(), static_override) + }); + + start_index..end_index + } +} + +impl CachedRangeComponentResults { + /// Returns the component data as a dense vector. + /// + /// Returns an error if the component is missing or cannot be deserialized. + /// + /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of + /// deserializing the data into a single one, if you don't need the extra flexibility. + #[inline] + pub fn to_dense(&self, resolver: &PromiseResolver) -> CachedRangeData<'_, C> { + // It's tracing the deserialization of an entire range query at once -- it's fine. + re_tracing::profile_function!(); + + // --- Step 1: try and upsert pending data (write lock) --- + + thread_local! { + /// Keeps track of reentrancy counts for the current thread. + /// + /// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing + /// environments such as Rayon. + static REENTERING: RefCell = const { RefCell::new(0) }; + } + + REENTERING.with_borrow_mut(|reentering| *reentering = reentering.saturating_add(1)); + + // Manufactured empty result. + if self.time_range == TimeRange::EMPTY { + return CachedRangeData { + indices: None, + data: None, + time_range: TimeRange::EMPTY, + front_status: PromiseResult::Ready(()), + back_status: PromiseResult::Ready(()), + reentering: &REENTERING, + }; + } + + let mut results = if let Some(results) = self.inner.try_write() { + // The lock was free to grab, nothing else to worry about. + Some(results) + } else { + REENTERING.with_borrow_mut(|reentering| { + if *reentering > 1 { + // The lock is busy, and at least one of the lock holders is the current thread from a + // previous stack frame. + // + // Return `None` so that we skip straight to the read-only part of the operation. + // All the data will be there already, since the previous stack frame already + // took care of upserting it. + None + } else { + // The lock is busy, but it is not held by the current thread. + // Just block until it gets released. + Some(self.inner.write()) + } + }) + }; + + if let Some(results) = &mut results { + // NOTE: This is just a lazy initialization of the underlying deque, because we + // just now finally know the expected type! + if results.cached_dense.is_none() { + results.cached_dense = Some(Box::new(FlatVecDeque::::new())); + } + + if !results.promises_front.is_empty() { + re_tracing::profile_scope!("front"); + + let mut resolved_indices = Vec::with_capacity(results.promises_front.len()); + let mut resolved_data = Vec::with_capacity(results.promises_front.len()); + + // Pop the promises from the end so that if we encounter one that has yet to be + // resolved, we can stop right there and know we have a contiguous range of data + // available up to that point in time. + // + // Reminder: promises are sorted in ascending index order. + while let Some(((data_time, row_id), promise)) = results.promises_front.pop() { + let data = match resolver.resolve(&promise) { + PromiseResult::Pending => { + results.front_status = (data_time, PromiseResult::Pending); + break; + } + PromiseResult::Error(err) => { + results.front_status = (data_time, PromiseResult::Error(err)); + break; + } + PromiseResult::Ready(cell) => { + results.front_status = (data_time, PromiseResult::Ready(())); + match cell + .try_to_native::() + .map_err(|err| DeserializationError::DataCellError(err.to_string())) + { + Ok(data) => data, + Err(err) => { + re_log::error!(%err, component=%C::name(), "data deserialization failed -- skipping"); + continue; + } + } + } + }; + + resolved_indices.push((data_time, row_id)); + resolved_data.push(data); + } + + // We resolved the promises in reversed order, so reverse the results back. + resolved_indices.reverse(); + resolved_data.reverse(); + + let results_indices = std::mem::take(&mut results.indices); + results.indices = resolved_indices + .into_iter() + .chain(results_indices) + .collect(); + + let resolved_data = FlatVecDeque::from_vecs(resolved_data); + // Unwraps: the deque is created when entering this function -- we know it's there + // and we know its type. + let cached_dense = results + .cached_dense + .as_mut() + .unwrap() + .as_any_mut() + .downcast_mut::>() + .unwrap(); + cached_dense.push_front_deque(resolved_data); + } + + if !results.promises_back.is_empty() { + re_tracing::profile_scope!("back"); + + let mut resolved_indices = Vec::with_capacity(results.promises_back.len()); + let mut resolved_data = Vec::with_capacity(results.promises_back.len()); + + // Reverse the promises first so we can pop() from the back. + // It's fine, this is a one-time operation in the successful case, and it's extremely fast to do. + // See below why. + // + // Reminder: promises are sorted in ascending index order. + results.promises_back.reverse(); + + // Pop the promises from the end so that if we encounter one that has yet to be + // resolved, we can stop right there and know we have a contiguous range of data + // available up to that point in time. + while let Some(((data_time, index), promise)) = results.promises_back.pop() { + let data = match resolver.resolve(&promise) { + PromiseResult::Pending => { + results.back_status = (data_time, PromiseResult::Pending); + break; + } + PromiseResult::Error(err) => { + results.back_status = (data_time, PromiseResult::Error(err)); + break; + } + PromiseResult::Ready(cell) => { + results.front_status = (data_time, PromiseResult::Ready(())); + match cell + .try_to_native::() + .map_err(|err| DeserializationError::DataCellError(err.to_string())) + { + Ok(data) => data, + Err(err) => { + re_log::error!(%err, "data deserialization failed -- skipping"); + continue; + } + } + } + }; + + resolved_indices.push((data_time, index)); + resolved_data.push(data); + } + + // Reverse our reversal. + results.promises_back.reverse(); + + results.indices.extend(resolved_indices); + + let resolved_data = FlatVecDeque::from_vecs(resolved_data); + // Unwraps: the deque is created when entering this function -- we know it's there + // and we know its type. + let cached_dense = results + .cached_dense + .as_mut() + .unwrap() + .as_any_mut() + .downcast_mut::>() + .unwrap(); + cached_dense.push_back_deque(resolved_data); + } + + results.sanity_check(); + } + + // --- Step 2: fetch cached data (read lock) --- + + let results = if let Some(results) = results { + RwLockWriteGuard::downgrade(results) + } else { + // # Multithreading semantics + // + // We need the reentrant lock because query contexts (i.e. space views) generally run on a + // work-stealing thread-pool and might swap a task on one thread with another task on the + // same thread, where both tasks happen to query the same exact data (e.g. cloned space views). + // + // See `REENTERING` comments above for more details. + self.read_recursive() + }; + + let front_status = { + let (results_front_time, results_front_status) = &results.front_status; + let query_front_time = self.time_range.min(); + if query_front_time < *results_front_time { + // If the query covers a larger time span on its front-side than the resulting data, then + // we should forward the status of the resulting data so the caller can know why it's + // been cropped off. + results_front_status.clone() + } else { + PromiseResult::Ready(()) + } + }; + let back_status = { + let (results_back_time, results_back_status) = &results.back_status; + let query_back_time = self.time_range.max(); + if query_back_time > *results_back_time { + // If the query covers a larger time span on its back-side than the resulting data, then + // we should forward the status of the resulting data so the caller can know why it's + // been cropped off. + results_back_status.clone() + } else { + PromiseResult::Ready(()) + } + }; + + // TODO(Amanieu/parking_lot#289): we need two distinct mapped guards because it's + // impossible to return an owned type in a `parking_lot` guard. + // See . + let indices = RwLockReadGuard::map(results, |results| &results.indices); + let data = RwLockReadGuard::map(self.inner.read_recursive(), |results| { + // Unwraps: the data is created when entering this function -- we know it's there + // and we know its type. + results + .cached_dense + .as_ref() + .unwrap() + .as_any() + .downcast_ref::>() + .unwrap() + }); + + CachedRangeData { + indices: Some(indices), + data: Some(data), + time_range: self.time_range, + front_status, + back_status, + reentering: &REENTERING, + } + } +} + +// --- + +/// Lazily cached results for a particular component when using a cached range query. +pub struct CachedRangeComponentResultsInner { + pub(crate) indices: VecDeque<(TimeInt, RowId)>, + + /// All the pending promises that must resolved in order to fill the missing data on the + /// front-side of the ringbuffer (i.e. further back in time). + /// + /// Always sorted in ascending index order ([`TimeInt`] + [`RowId`] pair). + pub(crate) promises_front: Vec<((TimeInt, RowId), Promise)>, + + /// All the pending promises that must resolved in order to fill the missing data on the + /// back-side of the ringbuffer (i.e. the most recent data). + /// + /// Always sorted in ascending index order ([`TimeInt`] + [`RowId`] pair). + pub(crate) promises_back: Vec<((TimeInt, RowId), Promise)>, + + /// Keeps track of the status of the data on the front-side of the cache. + pub(crate) front_status: (TimeInt, PromiseResult<()>), + + /// Keeps track of the status of the data on the back-side of the cache. + pub(crate) back_status: (TimeInt, PromiseResult<()>), + + /// The resolved, converted, deserialized dense data. + /// + /// This has to be option because we have no way of initializing the underlying trait object + /// until we know what the actual native type that the caller expects is. + pub(crate) cached_dense: Option>, +} + +impl SizeBytes for CachedRangeComponentResultsInner { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self { + indices, + promises_front, + promises_back, + front_status: _, + back_status: _, + cached_dense, + } = self; + + indices.heap_size_bytes() + + promises_front.heap_size_bytes() + + promises_back.heap_size_bytes() + + cached_dense + .as_ref() + .map_or(0, |data| data.dyn_total_size_bytes()) + } +} + +impl std::fmt::Debug for CachedRangeComponentResultsInner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + indices, + promises_front: _, + promises_back: _, + front_status: _, + back_status: _, + cached_dense: _, // we can't, we don't know the type + } = self; + + if indices.is_empty() { + f.write_str("") + } else { + // Unwrap: checked above. + let index_start = indices.front().unwrap(); + let index_end = indices.back().unwrap(); + f.write_fmt(format_args!( + "[{:?}#{} .. {:?}#{}] {}", + index_start.0, + index_start.1, + index_end.0, + index_end.1, + re_format::format_bytes(self.total_size_bytes() as _) + )) + } + } +} + +impl CachedRangeComponentResultsInner { + #[inline] + pub const fn empty() -> Self { + Self { + indices: VecDeque::new(), + promises_front: Vec::new(), + promises_back: Vec::new(), + front_status: (TimeInt::MIN, PromiseResult::Ready(())), + back_status: (TimeInt::MAX, PromiseResult::Ready(())), + cached_dense: None, + } + } + + /// No-op in release. + #[inline] + pub fn sanity_check(&self) { + if !cfg!(debug_assertions) { + return; + } + + let Self { + indices, + promises_front, + promises_back, + front_status: _, + back_status: _, + cached_dense, + } = self; + + assert!( + promises_front.windows(2).all(|promises| { + let index_left = promises[0].0; + let index_right = promises[1].0; + index_left <= index_right + }), + "front promises must always be sorted in ascending index order" + ); + if let (Some(p_index), Some(i_index)) = ( + promises_front.last().map(|(index, _)| index), + indices.front(), + ) { + assert!( + p_index < i_index, + "the rightmost front promise must have an index smaller than the leftmost data index ({p_index:?} < {i_index:?})", + ); + } + + assert!( + promises_back.windows(2).all(|promises| { + let index_left = promises[0].0; + let index_right = promises[1].0; + index_left <= index_right + }), + "back promises must always be sorted in ascending index order" + ); + if let (Some(p_index), Some(i_index)) = + (promises_back.last().map(|(index, _)| index), indices.back()) + { + assert!( + i_index < p_index, + "the leftmost back promise must have an index larger than the rightmost data index ({i_index:?} < {p_index:?})", + ); + } + + if let Some(dense) = cached_dense.as_ref() { + assert_eq!(indices.len(), dense.dyn_num_entries()); + } + } + + /// Returns the time range covered by the cached data. + /// + /// Reminder: [`TimeInt::STATIC`] is never included in [`TimeRange`]s. + #[inline] + pub fn time_range(&self) -> Option { + let first_time = self.indices.front().map(|(t, _)| *t)?; + let last_time = self.indices.back().map(|(t, _)| *t)?; + Some(TimeRange::new(first_time, last_time)) + } + + #[inline] + pub fn contains_data_time(&self, data_time: TimeInt) -> bool { + let first_time = self.indices.front().map_or(&TimeInt::MAX, |(t, _)| t); + let last_time = self.indices.back().map_or(&TimeInt::MIN, |(t, _)| t); + *first_time <= data_time && data_time <= *last_time + } + + /// Removes everything from the bucket that corresponds to a time equal or greater than the + /// specified `threshold`. + /// + /// Returns the number of bytes removed. + #[inline] + pub fn truncate_at_time(&mut self, threshold: TimeInt) { + re_tracing::profile_function!(); + + let time_range = self.time_range(); + + let Self { + indices, + promises_front, + promises_back, + front_status, + back_status, + cached_dense, + } = self; + + if front_status.0 >= threshold { + let time_min = time_range.map_or(TimeInt::MIN, |range| range.min()); + *front_status = (time_min, PromiseResult::Ready(())); + } + if back_status.0 >= threshold { + let time_max = time_range.map_or(TimeInt::MAX, |range| range.max()); + *back_status = (time_max, PromiseResult::Ready(())); + } + + // NOTE: promises are kept ascendingly sorted by index + { + let threshold_idx = + promises_front.partition_point(|((data_time, _), _)| *data_time < threshold); + promises_front.truncate(threshold_idx); + + let threshold_idx = + promises_back.partition_point(|((data_time, _), _)| *data_time < threshold); + promises_back.truncate(threshold_idx); + } + + let threshold_idx = indices.partition_point(|(data_time, _)| data_time < &threshold); + { + indices.truncate(threshold_idx); + if let Some(data) = cached_dense { + data.dyn_truncate(threshold_idx); + } + } + + self.sanity_check(); + } + + #[inline] + pub fn clear(&mut self) { + *self = Self::empty(); + } +} diff --git a/crates/re_query_cache2/tests/latest_at.rs b/crates/re_query_cache2/tests/latest_at.rs index 4af2ba0b8f12..016f1c3d5c80 100644 --- a/crates/re_query_cache2/tests/latest_at.rs +++ b/crates/re_query_cache2/tests/latest_at.rs @@ -494,7 +494,7 @@ fn query_and_compare( let cached_colors = cached.get_or_empty(MyColor::name()); let cached_color_data = cached_colors - .to_sparse::(&resolver) + .to_dense::(&resolver) .flatten() .unwrap(); @@ -513,7 +513,7 @@ fn query_and_compare( let expected_colors = expected.get_or_empty(MyColor::name()); let expected_color_data = expected_colors - .to_sparse::(&resolver) + .to_dense::(&resolver) .flatten() .unwrap(); diff --git a/crates/re_query_cache2/tests/range.rs b/crates/re_query_cache2/tests/range.rs new file mode 100644 index 000000000000..d06a7a8d8b9a --- /dev/null +++ b/crates/re_query_cache2/tests/range.rs @@ -0,0 +1,586 @@ +use itertools::{izip, Itertools as _}; + +use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; +use re_log_types::{ + build_frame_nr, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimePoint, +}; +use re_query_cache2::{Caches, PromiseResolver, PromiseResult}; +use re_types::{components::InstanceKey, Archetype}; +use re_types_core::Loggable as _; + +// --- + +#[test] +fn simple_range() -> anyhow::Result<()> { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + { + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; + insert_and_react(&mut store, &mut caches, &row); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; + insert_and_react(&mut store, &mut caches, &row); + } + + let timepoint2 = [build_frame_nr(223)]; + { + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; + insert_and_react(&mut store, &mut caches, &row); + } + + let timepoint3 = [build_frame_nr(323)]; + { + let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; + insert_and_react(&mut store, &mut caches, &row); + } + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + query_and_compare(&caches, &store, &query, &entity_path); + + // --- Second test: `[timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + query_and_compare(&caches, &store, &query, &entity_path); + + Ok(()) +} + +#[test] +fn static_range() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + { + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + // Insert statically too! + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + } + + let timepoint2 = [build_frame_nr(223)]; + { + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint2, + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + // Insert statically too! + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + } + + let timepoint3 = [build_frame_nr(323)]; + { + // Create some Positions with implicit instances + let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + } + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + query_and_compare(&caches, &store, &query, &entity_path); + + // --- Second test: `[timepoint1, timepoint3]` --- + + // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + query_and_compare(&caches, &store, &query, &entity_path); + + // --- Third test: `[-inf, +inf]` --- + + let query = + re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); + + query_and_compare(&caches, &store, &query, &entity_path); +} + +#[test] +fn simple_splatted_range() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + { + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + // Assign one of them a color with an explicit instance + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + } + + let timepoint2 = [build_frame_nr(223)]; + { + let colors = vec![MyColor::from_rgb(0, 255, 0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + } + + let timepoint3 = [build_frame_nr(323)]; + { + let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + } + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + query_and_compare(&caches, &store, &query, &entity_path); + + // --- Second test: `[timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + query_and_compare(&caches, &store, &query, &entity_path); +} + +#[test] +fn invalidation() { + let entity_path = "point"; + + let test_invalidation = |query: RangeQuery, + present_data_timepoint: TimePoint, + past_data_timepoint: TimePoint, + future_data_timepoint: TimePoint| { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + positions, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let colors = vec![MyColor::from_rgb(1, 2, 3)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 1, + colors, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // --- Modify present --- + + // Modify the PoV component + let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + positions, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint, + 2, + colors, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // --- Modify past --- + + // Modify the PoV component + let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + positions, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + colors, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // --- Modify future --- + + // Modify the PoV component + let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint.clone(), + 2, + positions, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(16, 17, 18)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + }; + + let timeless = TimePoint::default(); + let frame_122 = build_frame_nr(122); + let frame_123 = build_frame_nr(123); + let frame_124 = build_frame_nr(124); + + test_invalidation( + RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), + [frame_123].into(), + [frame_122].into(), + [frame_124].into(), + ); + + test_invalidation( + RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), + [frame_123].into(), + timeless, + [frame_124].into(), + ); +} + +// Test the following scenario: +// ```py +// rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// +// # Do first query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[] +// +// rr.set_time(2) +// rr.log_components("points", rr.components.MyColor(0xFF0000)) +// +// # Do second query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0xFF0000] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x0000FF)) +// +// # Do third query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x0000FF] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x00FF00)) +// +// # Do fourth query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x00FF00] +// ``` +#[test] +fn invalidation_of_future_optionals() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + let frame2 = [build_frame_nr(2)]; + let frame3 = [build_frame_nr(3)]; + + let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); + + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let colors = vec![MyColor::from_rgb(0, 255, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +#[test] +fn invalidation_static() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + + let frame0 = [build_frame_nr(TimeInt::ZERO)]; + let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); + + let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 1, colors).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); + + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors).unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + query_and_compare(&caches, &store, &query, &entity_path.into()); +} + +// --- + +fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { + caches.on_events(&[store.insert_row(row).unwrap()]); +} + +fn query_and_compare( + caches: &Caches, + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, +) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + + for _ in 0..3 { + let cached = caches.range( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_all_points = cached + .get_required(MyPoint::name()) + .unwrap() + .to_dense::(&resolver); + assert!(matches!( + cached_all_points.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_points_indexed = cached_all_points.range_indexed(); + + let cached_all_colors = cached + .get_or_empty(MyColor::name()) + .to_dense::(&resolver); + assert!(matches!( + cached_all_colors.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_colors_indexed = cached_all_colors.range_indexed(); + + let expected = re_query2::range( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let expected_all_points = expected.get_required(MyPoint::name()).unwrap(); + let expected_all_points_indices = expected_all_points.indices(); + let expected_all_points_data = expected_all_points + .to_dense::(&resolver) + .into_iter() + .map(|batch| batch.flatten().unwrap()) + .collect_vec(); + let expected_all_points_indexed = + izip!(expected_all_points_indices, expected_all_points_data); + + let expected_all_colors = expected.get_or_empty(MyColor::name()); + let expected_all_colors_indices = expected_all_colors.indices(); + let expected_all_colors_data = expected_all_colors + .to_dense::(&resolver) + .into_iter() + .map(|batch| batch.flatten().unwrap()) + .collect_vec(); + let expected_all_colors_indexed = + izip!(expected_all_colors_indices, expected_all_colors_data); + + eprintln!("{query:?}"); + eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!( + expected_all_points_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + cached_all_points_indexed + .map(|(index, data)| (*index, data.to_vec())) + .collect_vec(), + ); + + similar_asserts::assert_eq!( + expected_all_colors_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + cached_all_colors_indexed + .map(|(index, data)| (*index, data.to_vec())) + .collect_vec(), + ); + } +} From 1cd97aa0eedb60f28f0bde564077bea03e64ebd7 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:40:20 +0200 Subject: [PATCH 368/508] New data APIs 10: stats and debug tools for new caches (#5990) Title. The new cache being natively component-based makes things much smoothier than before. --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- Cargo.lock | 3 + crates/re_query_cache2/src/cache.rs | 58 ++++++- crates/re_query_cache2/src/cache_stats.rs | 100 ++++++++++++ crates/re_query_cache2/src/latest_at/query.rs | 66 ++++++-- .../re_query_cache2/src/latest_at/results.rs | 47 ++++-- crates/re_query_cache2/src/lib.rs | 26 ++++ crates/re_query_cache2/src/range/results.rs | 6 +- crates/re_viewer/Cargo.toml | 1 + crates/re_viewer/src/app.rs | 6 +- crates/re_viewer/src/ui/memory_panel.rs | 147 ++++++------------ crates/re_viewer_context/Cargo.toml | 2 + .../re_viewer_context/src/space_view/mod.rs | 3 + crates/re_viewer_context/src/store_hub.rs | 6 +- 13 files changed, 322 insertions(+), 149 deletions(-) create mode 100644 crates/re_query_cache2/src/cache_stats.rs diff --git a/Cargo.lock b/Cargo.lock index da19fba00f29..aced4d0dead4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5084,6 +5084,7 @@ dependencies = [ "re_log_types", "re_memory", "re_query_cache", + "re_query_cache2", "re_renderer", "re_smart_channel", "re_space_view", @@ -5143,7 +5144,9 @@ dependencies = [ "re_log", "re_log_types", "re_query", + "re_query2", "re_query_cache", + "re_query_cache2", "re_renderer", "re_smart_channel", "re_string_interner", diff --git a/crates/re_query_cache2/src/cache.rs b/crates/re_query_cache2/src/cache.rs index 6e5278a9f1e5..7f46b49dbfb0 100644 --- a/crates/re_query_cache2/src/cache.rs +++ b/crates/re_query_cache2/src/cache.rs @@ -1,10 +1,13 @@ -use std::{collections::BTreeSet, sync::Arc}; +use std::{ + collections::{BTreeMap, BTreeSet}, + sync::Arc, +}; use ahash::{HashMap, HashSet}; use parking_lot::RwLock; use re_data_store::{DataStore, StoreDiff, StoreEvent, StoreSubscriber, TimeInt}; -use re_log_types::{EntityPath, StoreId, Timeline}; +use re_log_types::{EntityPath, StoreId, TimeRange, Timeline}; use re_types_core::ComponentName; use crate::{LatestAtCache, RangeCache}; @@ -63,7 +66,6 @@ impl CacheKey { } } -#[derive(Debug)] pub struct Caches { /// The [`StoreId`] of the associated [`DataStore`]. pub(crate) store_id: StoreId, @@ -75,6 +77,54 @@ pub struct Caches { pub(crate) range_per_cache_key: RwLock>>>, } +impl std::fmt::Debug for Caches { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { + store_id, + latest_at_per_cache_key, + range_per_cache_key, + } = self; + + let mut strings = Vec::new(); + + strings.push(format!("[LatestAt @ {store_id}]")); + { + let latest_at_per_cache_key = latest_at_per_cache_key.read(); + let latest_at_per_cache_key: BTreeMap<_, _> = latest_at_per_cache_key.iter().collect(); + + for (cache_key, cache) in &latest_at_per_cache_key { + let cache = cache.read(); + strings.push(format!( + " [{cache_key:?} (pending_invalidation_min={:?})]", + cache.pending_invalidations.first().map(|&t| cache_key + .timeline + .format_time_range_utc(&TimeRange::new(t, TimeInt::MAX))), + )); + strings.push(indent::indent_all_by(4, format!("{cache:?}"))); + } + } + + strings.push(format!("[Range @ {store_id}]")); + { + let range_per_cache_key = range_per_cache_key.read(); + let range_per_cache_key: BTreeMap<_, _> = range_per_cache_key.iter().collect(); + + for (cache_key, cache) in &range_per_cache_key { + let cache = cache.read(); + strings.push(format!( + " [{cache_key:?} (pending_invalidation_min={:?})]", + cache.pending_invalidation.map(|t| cache_key + .timeline + .format_time_range_utc(&TimeRange::new(t, TimeInt::MAX))), + )); + strings.push(indent::indent_all_by(4, format!("{cache:?}"))); + } + } + + f.write_str(&strings.join("\n").replace("\n\n", "\n")) + } +} + impl Caches { #[inline] pub fn new(store: &DataStore) -> Self { @@ -164,7 +214,7 @@ impl StoreSubscriber for Caches { // running while we're updating the invalidation flags. { - re_tracing::profile_scope!("timeless"); + re_tracing::profile_scope!("static"); // TODO(cmc): This is horribly stupid and slow and can easily be made faster by adding // yet another layer of caching indirection. diff --git a/crates/re_query_cache2/src/cache_stats.rs b/crates/re_query_cache2/src/cache_stats.rs new file mode 100644 index 000000000000..7c205f5a8321 --- /dev/null +++ b/crates/re_query_cache2/src/cache_stats.rs @@ -0,0 +1,100 @@ +use std::collections::BTreeMap; + +use re_log_types::TimeRange; +use re_types_core::SizeBytes as _; + +use crate::{CacheKey, Caches}; + +// --- + +/// Stats for all primary caches. +/// +/// Fetch them via [`Caches::stats`]. +#[derive(Default, Debug, Clone)] +pub struct CachesStats { + pub latest_at: BTreeMap, + pub range: BTreeMap, CachedComponentStats)>, +} + +impl CachesStats { + #[inline] + pub fn total_size_bytes(&self) -> u64 { + re_tracing::profile_function!(); + + let Self { latest_at, range } = self; + + let latest_at_size_bytes: u64 = + latest_at.values().map(|stats| stats.total_size_bytes).sum(); + let range_size_bytes: u64 = range + .values() + .map(|(_, stats)| stats.total_size_bytes) + .sum(); + + latest_at_size_bytes + range_size_bytes + } +} + +/// Stats for a cached component. +#[derive(Default, Debug, Clone)] +pub struct CachedComponentStats { + pub total_indices: u64, + pub total_instances: u64, + pub total_size_bytes: u64, +} + +impl Caches { + /// Computes the stats for all primary caches. + pub fn stats(&self) -> CachesStats { + re_tracing::profile_function!(); + + let latest_at = { + let latest_at = self.latest_at_per_cache_key.read_recursive().clone(); + // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. + + latest_at + .iter() + .map(|(key, cache)| { + let cache = cache.read_recursive(); + ( + key.clone(), + CachedComponentStats { + total_indices: cache.per_data_time.len() as _, + total_instances: cache + .per_data_time + .values() + .map(|results| results.num_instances()) + .sum(), + total_size_bytes: cache.total_size_bytes(), + }, + ) + }) + .collect() + }; + + let range = { + let range = self.range_per_cache_key.read_recursive().clone(); + // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. + + range + .iter() + .map(|(key, cache)| { + let cache = cache.read_recursive(); + let cache = cache.per_data_time.read_recursive(); + ( + key.clone(), + ( + cache.time_range(), + CachedComponentStats { + total_indices: cache.indices.len() as _, + total_instances: cache.num_instances(), + total_size_bytes: cache.total_size_bytes(), + }, + ), + ) + }) + .collect() + }; + + CachesStats { latest_at, range } + } +} diff --git a/crates/re_query_cache2/src/latest_at/query.rs b/crates/re_query_cache2/src/latest_at/query.rs index b2e9e931d2e3..825830e9a731 100644 --- a/crates/re_query_cache2/src/latest_at/query.rs +++ b/crates/re_query_cache2/src/latest_at/query.rs @@ -1,11 +1,10 @@ use std::collections::BTreeSet; -use std::sync::atomic::AtomicU64; -use std::sync::atomic::Ordering::Relaxed; use std::{collections::BTreeMap, sync::Arc}; -use ahash::HashMap; - +use indexmap::IndexMap; +use itertools::Itertools; use parking_lot::RwLock; + use re_data_store::{DataStore, LatestAtQuery, TimeInt}; use re_log_types::EntityPath; use re_query2::Promise; @@ -108,22 +107,44 @@ impl std::fmt::Debug for LatestAtCache { let mut strings = Vec::new(); - let data_times_per_bucket: HashMap<_, _> = per_data_time + struct StatsPerBucket { + query_times: BTreeSet, + data_time: TimeInt, + total_size_bytes: u64, + } + + let mut buckets: IndexMap<_, _> = per_data_time .iter() - .map(|(time, bucket)| (Arc::as_ptr(bucket), *time)) + .map(|(&data_time, bucket)| { + ( + Arc::as_ptr(bucket), + StatsPerBucket { + query_times: Default::default(), + data_time, + total_size_bytes: bucket.total_size_bytes(), + }, + ) + }) .collect(); - for (query_time, bucket) in per_query_time { - let query_time = cache_key.timeline.typ().format_utc(*query_time); - let data_time = data_times_per_bucket.get(&Arc::as_ptr(bucket)).map_or_else( - || "MISSING?!".to_owned(), - |t| cache_key.timeline.typ().format_utc(*t), - ); + for (&query_time, bucket) in per_query_time { + if let Some(bucket) = buckets.get_mut(&Arc::as_ptr(bucket)) { + bucket.query_times.insert(query_time); + } + } + + for bucket in buckets.values() { strings.push(format!( - "query_time={query_time} -> data_time={data_time} ({})", - re_format::format_bytes(bucket.cached_heap_size_bytes.load(Relaxed) as _), + "query_times=[{}] -> data_time={:?} ({})", + bucket + .query_times + .iter() + .map(|t| cache_key.timeline.typ().format_utc(*t)) + .collect_vec() + .join(", "), + bucket.data_time.as_i64(), + re_format::format_bytes(bucket.total_size_bytes as _), )); - strings.push(indent::indent_all_by(2, format!("{bucket:?}"))); } if strings.is_empty() { @@ -148,7 +169,19 @@ impl SizeBytes for LatestAtCache { .keys() .map(|k| k.total_size_bytes()) .sum::(); - let per_data_time = per_data_time.total_size_bytes(); + // NOTE: per query time buckets are just pointers, don't count them. + + let per_data_time_keys = per_data_time + .keys() + .map(|k| k.total_size_bytes()) + .sum::(); + let per_data_time_values = per_data_time + .values() + // NOTE: make sure to dereference the Arc, else this will account for zero (assumed amortized!) + .map(|arc| (**arc).total_size_bytes()) + .sum::(); + + let per_data_time = per_data_time_keys + per_data_time_values; let pending_invalidations = pending_invalidations.total_size_bytes(); per_query_time + per_data_time + pending_invalidations @@ -217,7 +250,6 @@ impl LatestAtCache { index: (data_time, row_id), promise: Some(Promise::new(cell)), cached_dense: Default::default(), - cached_heap_size_bytes: AtomicU64::new(0), }); // Slowest path: this is a complete cache miss. diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index 4597807f3ec5..0a1bbd714b2d 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -1,7 +1,4 @@ -use std::sync::{ - atomic::{AtomicU64, Ordering::Relaxed}, - Arc, OnceLock, -}; +use std::sync::{Arc, OnceLock}; use nohash_hasher::IntMap; @@ -130,8 +127,6 @@ pub struct CachedLatestAtComponentResults { /// The resolved, converted, deserialized dense data. pub(crate) cached_dense: OnceLock>, - - pub(crate) cached_heap_size_bytes: AtomicU64, } impl CachedLatestAtComponentResults { @@ -141,7 +136,6 @@ impl CachedLatestAtComponentResults { index: (TimeInt::STATIC, RowId::ZERO), promise: None, cached_dense: OnceLock::new(), - cached_heap_size_bytes: AtomicU64::new(0), } } @@ -159,12 +153,37 @@ impl CachedLatestAtComponentResults { pub fn is_static(&self) -> bool { self.index.0 == TimeInt::STATIC } + + /// How many _indices_ across this entire cache? + #[inline] + pub fn num_indices(&self) -> u64 { + _ = self; + 1 + } + + /// How many _instances_ across this entire cache? + #[inline] + pub fn num_instances(&self) -> u64 { + self.cached_dense + .get() + .map_or(0u64, |cached| cached.dyn_num_values() as _) + } } impl SizeBytes for CachedLatestAtComponentResults { #[inline] fn heap_size_bytes(&self) -> u64 { - self.cached_heap_size_bytes.load(Relaxed) + let Self { + index, + promise, + cached_dense, + } = self; + + index.total_size_bytes() + + promise.total_size_bytes() + + cached_dense + .get() + .map_or(0, |data| data.dyn_total_size_bytes()) } } @@ -174,14 +193,13 @@ impl std::fmt::Debug for CachedLatestAtComponentResults { index, promise: _, cached_dense: _, // we can't, we don't know the type - cached_heap_size_bytes, } = self; f.write_fmt(format_args!( "[{:?}#{}] {}", index.0, index.1, - re_format::format_bytes(cached_heap_size_bytes.load(Relaxed) as _) + re_format::format_bytes(self.total_size_bytes() as _) )) } } @@ -256,12 +274,9 @@ impl CachedLatestAtComponentResults { .map_err(|err| DeserializationError::DataCellError(err.to_string()))?; #[allow(clippy::borrowed_box)] - let cached: &Box = - self.cached_dense.get_or_init(move || { - self.cached_heap_size_bytes - .fetch_add(data.total_size_bytes(), Relaxed); - Box::new(FlatVecDeque::from(data)) - }); + let cached: &Box = self + .cached_dense + .get_or_init(move || Box::new(FlatVecDeque::from(data))); downcast(&**cached) } diff --git a/crates/re_query_cache2/src/lib.rs b/crates/re_query_cache2/src/lib.rs index d8965db3cc81..cb995ab447aa 100644 --- a/crates/re_query_cache2/src/lib.rs +++ b/crates/re_query_cache2/src/lib.rs @@ -1,11 +1,13 @@ //! Caching datastructures for `re_query`. mod cache; +mod cache_stats; mod flat_vec_deque; mod latest_at; mod range; pub use self::cache::{CacheKey, Caches}; +pub use self::cache_stats::{CachedComponentStats, CachesStats}; pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; pub use self::latest_at::{ CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, @@ -26,3 +28,27 @@ pub mod external { pub use paste; pub use seq_macro; } + +// --- + +use re_data_store::{LatestAtQuery, RangeQuery}; + +#[derive(Debug)] +pub enum CachedResults { + LatestAt(LatestAtQuery, CachedLatestAtResults), + Range(RangeQuery, CachedRangeResults), +} + +impl From<(LatestAtQuery, CachedLatestAtResults)> for CachedResults { + #[inline] + fn from((query, results): (LatestAtQuery, CachedLatestAtResults)) -> Self { + Self::LatestAt(query, results) + } +} + +impl From<(RangeQuery, CachedRangeResults)> for CachedResults { + #[inline] + fn from((query, results): (RangeQuery, CachedRangeResults)) -> Self { + Self::Range(query, results) + } +} diff --git a/crates/re_query_cache2/src/range/results.rs b/crates/re_query_cache2/src/range/results.rs index cfd804055fc0..98a39eebed52 100644 --- a/crates/re_query_cache2/src/range/results.rs +++ b/crates/re_query_cache2/src/range/results.rs @@ -567,9 +567,9 @@ impl SizeBytes for CachedRangeComponentResultsInner { cached_dense, } = self; - indices.heap_size_bytes() - + promises_front.heap_size_bytes() - + promises_back.heap_size_bytes() + indices.total_size_bytes() + + promises_front.total_size_bytes() + + promises_back.total_size_bytes() + cached_dense .as_ref() .map_or(0, |data| data.dyn_total_size_bytes()) diff --git a/crates/re_viewer/Cargo.toml b/crates/re_viewer/Cargo.toml index 2168bec9fe30..51a91c365277 100644 --- a/crates/re_viewer/Cargo.toml +++ b/crates/re_viewer/Cargo.toml @@ -54,6 +54,7 @@ re_log_encoding = { workspace = true, features = [ re_log_types.workspace = true re_memory.workspace = true re_query_cache.workspace = true +re_query_cache2.workspace = true re_renderer = { workspace = true, default-features = false } re_smart_channel.workspace = true re_space_view.workspace = true diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index fdf4fa9a5cc0..58e2c612b769 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -691,7 +691,7 @@ impl App { #[cfg(not(target_arch = "wasm32"))] UICommand::PrintPrimaryCache => { if let Some(ctx) = store_context { - let text = format!("{:?}", ctx.recording.query_caches()); + let text = format!("{:?}", ctx.recording.query_caches2()); self.re_ui .egui_ctx .output_mut(|o| o.copied_text = text.clone()); @@ -1415,9 +1415,7 @@ impl eframe::App for App { // NOTE: Store and caching stats are very costly to compute: only do so if the memory panel // is opened. - let store_stats = self - .memory_panel_open - .then(|| store_hub.stats(self.memory_panel.primary_cache_detailed_stats_enabled())); + let store_stats = self.memory_panel_open.then(|| store_hub.stats()); // do early, before doing too many allocations self.memory_panel diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index 44d9abf02e5a..36a89ef0e34e 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -1,9 +1,8 @@ -use std::sync::atomic::AtomicBool; - +use itertools::Itertools; use re_data_store::{DataStoreConfig, DataStoreRowStats, DataStoreStats}; use re_format::{format_bytes, format_uint}; use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse}; -use re_query_cache::{CachedComponentStats, CachedEntityStats, CachesStats}; +use re_query_cache2::{CachedComponentStats, CachesStats}; use re_renderer::WgpuResourcePoolStatistics; use re_viewer_context::store_hub::StoreHubStats; @@ -15,13 +14,6 @@ use crate::env_vars::RERUN_TRACK_ALLOCATIONS; pub struct MemoryPanel { history: MemoryHistory, memory_purge_times: Vec, - - /// If `true`, enables the much-more-costly-to-compute per-component stats for the primary - /// cache. - prim_cache_detailed_stats: AtomicBool, - - /// If `true`, will show stats about empty primary caches too, which likely indicates a bug (dangling bucket). - prim_cache_show_empty: AtomicBool, } impl MemoryPanel { @@ -49,12 +41,6 @@ impl MemoryPanel { self.memory_purge_times.push(sec_since_start()); } - #[inline] - pub fn primary_cache_detailed_stats_enabled(&self) -> bool { - self.prim_cache_detailed_stats - .load(std::sync::atomic::Ordering::Relaxed) - } - #[allow(clippy::too_many_arguments)] pub fn ui( &self, @@ -74,7 +60,7 @@ impl MemoryPanel { .min_width(250.0) .default_width(300.0) .show_inside(ui, |ui| { - self.left_side(ui, re_ui, limit, gpu_resource_stats, store_stats); + Self::left_side(ui, re_ui, limit, gpu_resource_stats, store_stats); }); egui::CentralPanel::default().show_inside(ui, |ui| { @@ -84,7 +70,6 @@ impl MemoryPanel { } fn left_side( - &self, ui: &mut egui::Ui, re_ui: &re_ui::ReUi, limit: &MemoryLimit, @@ -115,7 +100,7 @@ impl MemoryPanel { ui.separator(); ui.collapsing("Primary Cache Resources", |ui| { - self.caches_stats(ui, re_ui, &store_stats.recording_cached_stats); + Self::caches_stats(ui, &store_stats.recording_cached_stats); }); ui.separator(); @@ -319,27 +304,15 @@ impl MemoryPanel { }); } - fn caches_stats(&self, ui: &mut egui::Ui, re_ui: &re_ui::ReUi, caches_stats: &CachesStats) { - use std::sync::atomic::Ordering::Relaxed; - - let mut detailed_stats = self.prim_cache_detailed_stats.load(Relaxed); - re_ui - .checkbox(ui, &mut detailed_stats, "Detailed stats") - .on_hover_text("Show detailed statistics when hovering entity paths below.\nThis will slow down the program."); - self.prim_cache_detailed_stats - .store(detailed_stats, Relaxed); - - let mut show_empty = self.prim_cache_show_empty.load(Relaxed); - re_ui - .checkbox(ui, &mut show_empty, "Show empty caches") - .on_hover_text( - "Show empty caches too.\nDangling buckets are generally the result of a bug.", - ); - self.prim_cache_show_empty.store(show_empty, Relaxed); - + fn caches_stats(ui: &mut egui::Ui, caches_stats: &CachesStats) { let CachesStats { latest_at, range } = caches_stats; - if show_empty || !latest_at.is_empty() { + let latest_at = latest_at + .iter() + .filter(|(_, stats)| stats.total_indices > 0) + .collect_vec(); + + if !latest_at.is_empty() { ui.separator(); ui.strong("LatestAt"); egui::ScrollArea::vertical() @@ -350,27 +323,36 @@ impl MemoryPanel { .num_columns(3) .show(ui, |ui| { ui.label(egui::RichText::new("Entity").underline()); - ui.label(egui::RichText::new("Rows").underline()) - .on_hover_text( - "How many distinct data timestamps have been cached?", - ); + ui.label(egui::RichText::new("Component").underline()); + ui.label(egui::RichText::new("Indices").underline()); + ui.label(egui::RichText::new("Instances").underline()); ui.label(egui::RichText::new("Size").underline()); ui.end_row(); - for (entity_path, stats) in latest_at { - if !show_empty && stats.is_empty() { - continue; - } + for (cache_key, stats) in latest_at { + let &CachedComponentStats { + total_indices, + total_instances, + total_size_bytes, + } = stats; - let res = ui.label(entity_path.to_string()); - entity_stats_ui(ui, res, stats); + ui.label(cache_key.entity_path.to_string()); + ui.label(cache_key.component_name.to_string()); + ui.label(re_format::format_uint(total_indices)); + ui.label(re_format::format_uint(total_instances)); + ui.label(re_format::format_bytes(total_size_bytes as _)); ui.end_row(); } }); }); } - if show_empty || !latest_at.is_empty() { + let range = range + .iter() + .filter(|(_, (_, stats))| stats.total_indices > 0) + .collect_vec(); + + if !range.is_empty() { ui.separator(); ui.strong("Range"); egui::ScrollArea::vertical() @@ -381,75 +363,36 @@ impl MemoryPanel { .num_columns(4) .show(ui, |ui| { ui.label(egui::RichText::new("Entity").underline()); - ui.label(egui::RichText::new("Time range").underline()); - ui.label(egui::RichText::new("Rows").underline()) - .on_hover_text( - "How many distinct data timestamps have been cached?", - ); - ui.label(egui::RichText::new("Size").underline()); - ui.end_row(); - - for (entity_path, stats_per_range) in range { - for (timeline, time_range, stats) in stats_per_range { - if !show_empty && stats.is_empty() { - continue; - } - - let res = ui.label(entity_path.to_string()); - ui.label(format!( - "{}({})", - timeline.name(), - timeline.format_time_range_utc(time_range) - )); - entity_stats_ui(ui, res, stats); - ui.end_row(); - } - } - }); - }); - } - - fn entity_stats_ui( - ui: &mut egui::Ui, - hover_response: egui::Response, - entity_stats: &CachedEntityStats, - ) { - let CachedEntityStats { - total_size_bytes, - total_rows, - per_component, - } = entity_stats; - - if let Some(per_component) = per_component.as_ref() { - hover_response.on_hover_ui_at_pointer(|ui| { - egui::Grid::new("component cache stats grid") - .num_columns(3) - .show(ui, |ui| { ui.label(egui::RichText::new("Component").underline()); - ui.label(egui::RichText::new("Rows").underline()); + ui.label(egui::RichText::new("Indices").underline()); ui.label(egui::RichText::new("Instances").underline()); ui.label(egui::RichText::new("Size").underline()); + ui.label(egui::RichText::new("Time range").underline()); ui.end_row(); - for (component_name, stats) in per_component { + for (cache_key, (time_range, stats)) in range { let &CachedComponentStats { - total_rows, + total_indices, total_instances, total_size_bytes, } = stats; - ui.label(component_name.to_string()); - ui.label(re_format::format_uint(total_rows)); + ui.label(cache_key.entity_path.to_string()); + ui.label(cache_key.component_name.to_string()); + ui.label(re_format::format_uint(total_indices)); ui.label(re_format::format_uint(total_instances)); ui.label(re_format::format_bytes(total_size_bytes as _)); + ui.label(format!( + "{}({})", + cache_key.timeline.name(), + time_range.map_or("".to_owned(), |time_range| { + cache_key.timeline.format_time_range_utc(&time_range) + }) + )); ui.end_row(); } }); }); - } - - ui.label(re_format::format_uint(*total_rows)); - ui.label(re_format::format_bytes(*total_size_bytes as _)); } } diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 835b3c5aec4c..16de5cba4b51 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -25,7 +25,9 @@ re_entity_db = { workspace = true, features = ["serde"] } re_log_types.workspace = true re_log.workspace = true re_query_cache.workspace = true +re_query_cache2.workspace = true re_query.workspace = true +re_query2.workspace = true re_renderer.workspace = true re_smart_channel.workspace = true re_string_interner.workspace = true diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index b4da1ba5f82b..61c60dfadf77 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -48,6 +48,9 @@ pub enum SpaceViewSystemExecutionError { #[error(transparent)] QueryError(#[from] re_query::QueryError), + #[error(transparent)] + QueryError2(#[from] re_query2::QueryError), + #[error(transparent)] DeserializationError(#[from] re_types::DeserializationError), diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 2e6c9050a92f..5c3a454babcd 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -7,7 +7,7 @@ use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId, StoreKind}; -use re_query_cache::CachesStats; +use re_query_cache2::CachesStats; use crate::StoreContext; @@ -687,7 +687,7 @@ impl StoreHub { // // TODO(jleibs): We probably want stats for all recordings, not just // the active recording. - pub fn stats(&self, detailed_cache_stats: bool) -> StoreHubStats { + pub fn stats(&self) -> StoreHubStats { re_tracing::profile_function!(); // If we have an app-id, then use it to look up the blueprint. @@ -715,7 +715,7 @@ impl StoreHub { .unwrap_or_default(); let recording_cached_stats = recording - .map(|entity_db| entity_db.query_caches().stats(detailed_cache_stats)) + .map(|entity_db| entity_db.query_caches2().stats()) .unwrap_or_default(); let recording_config = recording From d0e9af09b57bc2e80bacb59a27135310a8146849 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:40:54 +0200 Subject: [PATCH 369/508] =?UTF-8?q?New=20data=20APIs=2011:=20port=20all=20?= =?UTF-8?q?range-only=20views=20(plots,=20logs=E2=80=A6)=20(#5992)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Text logs, line plots and scatter plots. A bit faster than `main`, with a bit less memory overhead. --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- Cargo.lock | 2 + crates/re_space_view_text_log/Cargo.toml | 1 + .../src/visualizer_system.rs | 108 +++++--- crates/re_space_view_time_series/Cargo.toml | 1 + .../src/line_visualizer_system.rs | 182 ++++++++------ .../src/point_visualizer_system.rs | 237 +++++++++++------- 6 files changed, 341 insertions(+), 190 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aced4d0dead4..890586d674d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4847,6 +4847,7 @@ dependencies = [ "re_log", "re_log_types", "re_query_cache", + "re_query_cache2", "re_renderer", "re_tracing", "re_types", @@ -4868,6 +4869,7 @@ dependencies = [ "re_log_types", "re_query", "re_query_cache", + "re_query_cache2", "re_renderer", "re_space_view", "re_tracing", diff --git a/crates/re_space_view_text_log/Cargo.toml b/crates/re_space_view_text_log/Cargo.toml index d1343494859e..f73a87deb47f 100644 --- a/crates/re_space_view_text_log/Cargo.toml +++ b/crates/re_space_view_text_log/Cargo.toml @@ -25,6 +25,7 @@ re_entity_db.workspace = true re_log_types.workspace = true re_log.workspace = true re_query_cache.workspace = true +re_query_cache2.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types.workspace = true diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index 76a46b084151..c9cb50dffd7c 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -1,9 +1,11 @@ use re_data_store::TimeRange; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; +use re_query_cache2::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; use re_types::{ archetypes::TextLog, components::{Color, Text, TextLogLevel}, + Component, Loggable as _, }; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, @@ -46,45 +48,71 @@ impl VisualizerSystem for TextLogSystem { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, _view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let query_caches = ctx.recording().query_caches(); - let store = ctx.recording_store(); + let resolver = ctx.recording().resolver(); + let query = re_data_store::RangeQuery::new(view_query.timeline, TimeRange::EVERYTHING); - for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { + for data_result in view_query.iter_visible_data_results(ctx, Self::identifier()) { re_tracing::profile_scope!("primary", &data_result.entity_path.to_string()); - // We want everything, for all times: - let timeline_query = - re_data_store::RangeQuery::new(query.timeline, TimeRange::EVERYTHING); - - // TODO(cmc): use raw API. - query_caches.query_archetype_pov1_comp2::( - store, - &timeline_query.clone().into(), + let results = ctx.recording().query_caches2().range( + ctx.recording_store(), + &query, &data_result.entity_path, - |((time, row_id), _, bodies, levels, colors)| { - for (body, level, color) in itertools::izip!( - bodies.iter(), - re_query_cache::iter_or_repeat_opt(levels, bodies.len()), - re_query_cache::iter_or_repeat_opt(colors, bodies.len()), - ) { - self.entries.push(Entry { - row_id, - entity_path: data_result.entity_path.clone(), - time, - color: *color, - body: body.clone(), - level: level.clone(), - }); - } - }, - )?; + [Text::name(), TextLogLevel::name(), Color::name()], + ); + + let all_bodies = { + let Some(all_bodies) = results.get(Text::name()) else { + continue; + }; + all_bodies.to_dense::(resolver) + }; + check_range(&all_bodies)?; + + let all_levels = results + .get_or_empty(TextLogLevel::name()) + .to_dense::(resolver); + check_range(&all_levels)?; + + let all_colors = results + .get_or_empty(Color::name()) + .to_dense::(resolver); + check_range(&all_colors)?; + + let all_frames = range_zip_1x2( + all_bodies.range_indexed(), + all_levels.range_indexed(), + all_colors.range_indexed(), + ); + + for (&(data_time, row_id), bodies, levels, colors) in all_frames { + let levels = levels.unwrap_or(&[]).iter().cloned().map(Some); + let colors = colors.unwrap_or(&[]).iter().copied().map(Some); + + let level_default_fn = || None; + let color_default_fn = || None; + + let results = + clamped_zip_1x2(bodies, levels, level_default_fn, colors, color_default_fn); + + for (body, level, color) in results { + self.entries.push(Entry { + row_id, + entity_path: data_result.entity_path.clone(), + time: data_time, + color, + body: body.clone(), + level, + }); + } + } } { - // Sort by currently selected tiemeline + // Sort by currently selected timeline re_tracing::profile_scope!("sort"); self.entries.sort_by_key(|e| e.time); } @@ -96,3 +124,23 @@ impl VisualizerSystem for TextLogSystem { self } } + +// TODO(#5607): what should happen if the promise is still pending? +#[inline] +fn check_range<'a, C: Component>( + results: &'a CachedRangeData<'a, C>, +) -> re_query_cache2::Result<()> { + let (front_status, back_status) = results.status(); + match front_status { + PromiseResult::Pending => return Ok(()), + PromiseResult::Error(err) => return Err(re_query_cache2::QueryError::Other(err.into())), + PromiseResult::Ready(_) => {} + } + match back_status { + PromiseResult::Pending => return Ok(()), + PromiseResult::Error(err) => return Err(re_query_cache2::QueryError::Other(err.into())), + PromiseResult::Ready(_) => {} + } + + Ok(()) +} diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml index 16faadc51266..6a7f0691aba4 100644 --- a/crates/re_space_view_time_series/Cargo.toml +++ b/crates/re_space_view_time_series/Cargo.toml @@ -25,6 +25,7 @@ re_log.workspace = true re_log_types.workspace = true re_query.workspace = true re_query_cache.workspace = true +re_query_cache2.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 43ee7d5049c6..83008a3f169e 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -1,9 +1,9 @@ use itertools::Itertools as _; -use re_query_cache::QueryError; +use re_query_cache2::{PromiseResult, QueryError}; use re_types::archetypes; use re_types::{ archetypes::SeriesLine, - components::{Color, MarkerShape, MarkerSize, Name, Scalar, StrokeWidth}, + components::{Color, Name, Scalar, StrokeWidth}, Archetype as _, ComponentNameSet, Loggable, }; use re_viewer_context::{ @@ -155,8 +155,7 @@ fn load_series( ) -> Result<(), QueryError> { re_tracing::profile_function!(); - let store = ctx.recording_store(); - let query_caches = ctx.recording().query_caches(); + let resolver = ctx.recording().resolver(); let annotation_info = annotations .resolved_class_description(None) @@ -181,7 +180,7 @@ fn load_series( }, }; - let mut points = Vec::new(); + let mut points; let time_range = determine_time_range( ctx, @@ -196,83 +195,122 @@ fn load_series( let entity_path = &data_result.entity_path; let query = re_data_store::RangeQuery::new(query.timeline, time_range); - // TODO(jleibs): need to do a "joined" archetype query - // The `Scalar` archetype queries for `MarkerShape` & `MarkerSize` in the point visualizer, - // and so it must do so here also. - // See https://github.com/rerun-io/rerun/pull/5029 - query_caches.query_archetype_range_pov1_comp4::< - archetypes::Scalar, - Scalar, - Color, - StrokeWidth, - MarkerSize, // unused - MarkerShape, // unused - _, - >( - store, + let results = ctx.recording().query_caches2().range( + ctx.recording_store(), &query, entity_path, - |entry_range, (times, _, scalars, colors, stroke_widths, _, _)| { - let times = times.range(entry_range.clone()).map(|(time, _)| time.as_i64()); - // Allocate all points. - points = times.map(|time| PlotPoint { - time, - ..default_point.clone() - }).collect_vec(); - - // Fill in values. - for (i, scalar) in scalars.range(entry_range.clone()).enumerate() { - if scalar.len() > 1 { - re_log::warn_once!("found a scalar batch in {entity_path:?} -- those have no effect"); - } else if scalar.is_empty() { - points[i].attrs.kind = PlotSeriesKind::Clear; - } else { - points[i].value = scalar.first().map_or(0.0, |s| s.0); - } + [Scalar::name(), Color::name(), StrokeWidth::name()], + ); + + let all_scalars = results + .get_required(Scalar::name())? + .to_dense::(resolver); + let all_scalars_entry_range = all_scalars.entry_range(); + + if !matches!( + all_scalars.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + ) { + // TODO(#5607): what should happen if the promise is still pending? + } + + // Allocate all points. + points = all_scalars + .range_indices(all_scalars_entry_range.clone()) + .map(|(data_time, _)| PlotPoint { + time: data_time.as_i64(), + ..default_point.clone() + }) + .collect_vec(); + + // Fill in values. + for (i, scalars) in all_scalars + .range_data(all_scalars_entry_range.clone()) + .enumerate() + { + if scalars.len() > 1 { + re_log::warn_once!( + "found a scalar batch in {entity_path:?} -- those have no effect" + ); + } else if scalars.is_empty() { + points[i].attrs.kind = PlotSeriesKind::Clear; + } else { + points[i].value = scalars.first().map_or(0.0, |s| s.0); + } + } + + // Make it as clear as possible to the optimizer that some parameters + // go completely unused as soon as overrides have been defined. + + // Fill in colors -- if available _and_ not overridden. + if override_color.is_none() { + if let Some(all_colors) = results.get(Color::name()) { + let all_colors = all_colors.to_dense::(resolver); + + if !matches!( + all_colors.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + ) { + // TODO(#5607): what should happen if the promise is still pending? } - // Make it as clear as possible to the optimizer that some parameters - // go completely unused as soon as overrides have been defined. + let all_scalars_indexed = all_scalars + .range_indices(all_scalars_entry_range.clone()) + .map(|index| (index, ())); - // Fill in colors -- if available _and_ not overridden. - if override_color.is_none() { - if let Some(colors) = colors { - for (i, color) in colors.range(entry_range.clone()).enumerate() { - if i >= points.len() { - re_log::debug_once!("more color attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; - } - if let Some(color) = color.first().copied().flatten().map(|c| { - let [r,g,b,a] = c.to_array(); - if a == 255 { - // Common-case optimization - re_renderer::Color32::from_rgb(r, g, b) - } else { - re_renderer::Color32::from_rgba_unmultiplied(r, g, b, a) - } - }) { - points[i].attrs.color = color; + let all_frames = + re_query_cache2::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) + .enumerate(); + + for (i, (_index, _scalars, colors)) in all_frames { + if let Some(color) = colors.and_then(|colors| { + colors.first().map(|c| { + let [r, g, b, a] = c.to_array(); + if a == 255 { + // Common-case optimization + re_renderer::Color32::from_rgb(r, g, b) + } else { + re_renderer::Color32::from_rgba_unmultiplied(r, g, b, a) } - } + }) + }) { + points[i].attrs.color = color; } } + } + } - // Fill in radii -- if available _and_ not overridden. - if override_stroke_width.is_none() { - if let Some(stroke_widths) = stroke_widths { - for (i, stroke_width) in stroke_widths.range(entry_range.clone()).enumerate() { - if i >= stroke_widths.num_entries() { - re_log::debug_once!("more stroke width attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; - } - if let Some(stroke_width) = stroke_width.first().copied().flatten().map(|r| r.0) { - points[i].attrs.marker_size = stroke_width; - } - } + // Fill in stroke widths -- if available _and_ not overridden. + if override_stroke_width.is_none() { + if let Some(all_stroke_widths) = results.get(StrokeWidth::name()) { + let all_stroke_widths = all_stroke_widths.to_dense::(resolver); + + if !matches!( + all_stroke_widths.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + ) { + // TODO(#5607): what should happen if the promise is still pending? + } + + let all_scalars_indexed = all_scalars + .range_indices(all_scalars_entry_range.clone()) + .map(|index| (index, ())); + + let all_frames = re_query_cache2::range_zip_1x1( + all_scalars_indexed, + all_stroke_widths.range_indexed(), + ) + .enumerate(); + + for (i, (_index, _scalars, stroke_widths)) in all_frames { + if let Some(stroke_width) = + stroke_widths.and_then(|stroke_widths| stroke_widths.first().map(|r| r.0)) + { + points[i].attrs.marker_size = stroke_width; } } - }, - )?; + } + } } // Check for an explicit label if any. @@ -293,7 +331,7 @@ fn load_series( data_result, time_per_pixel, points, - store, + ctx.recording_store(), query, series_name, all_series, diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index ce651cb6f106..5aba1e13589c 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -1,9 +1,9 @@ use itertools::Itertools as _; -use re_query_cache::QueryError; +use re_query_cache2::{PromiseResult, QueryError}; use re_types::{ archetypes::{self, SeriesPoint}, - components::{Color, MarkerShape, MarkerSize, Name, Scalar, StrokeWidth}, + components::{Color, MarkerShape, MarkerSize, Name, Scalar}, Archetype as _, ComponentNameSet, Loggable, }; use re_viewer_context::{ @@ -43,7 +43,6 @@ impl VisualizerSystem for SeriesPointSystem { .map(ToOwned::to_owned) .collect::(); query_info.queried.append(&mut series_point_queried); - query_info.queried.insert(StrokeWidth::name()); query_info.indicators = std::iter::once(SeriesPoint::indicator().name()).collect(); query_info } @@ -100,8 +99,7 @@ impl SeriesPointSystem { ) -> Result<(), QueryError> { re_tracing::profile_function!(); - let query_caches = ctx.recording().query_caches(); - let store = ctx.recording_store(); + let resolver = ctx.recording().resolver(); let (plot_bounds, time_per_pixel) = determine_plot_bounds_and_time_per_pixel(ctx, query); @@ -118,7 +116,7 @@ impl SeriesPointSystem { .map(|c| c.to_array()); let override_series_name = data_result.lookup_override::(ctx).map(|t| t.0); let override_marker_size = data_result.lookup_override::(ctx).map(|r| r.0); - let override_marker = data_result.lookup_override::(ctx); + let override_marker_shape = data_result.lookup_override::(ctx); // All the default values for a `PlotPoint`, accounting for both overrides and default // values. @@ -130,12 +128,12 @@ impl SeriesPointSystem { color: annotation_info.color(override_color, default_color), marker_size: override_marker_size.unwrap_or(DEFAULT_MARKER_SIZE), kind: PlotSeriesKind::Scatter(ScatterAttrs { - marker: override_marker.unwrap_or_default(), + marker: override_marker_shape.unwrap_or_default(), }), }, }; - let mut points = Vec::new(); + let mut points; let time_range = determine_time_range( ctx, @@ -151,99 +149,162 @@ impl SeriesPointSystem { let entity_path = &data_result.entity_path; let query = re_data_store::RangeQuery::new(query.timeline, time_range); - // TODO(jleibs): need to do a "joined" archetype query - // The `Scalar` archetype queries for `StrokeWidth` in the line visualizer, - // and so it must do so here also. - // See https://github.com/rerun-io/rerun/pull/5029 - query_caches.query_archetype_range_pov1_comp4::< - archetypes::Scalar, - Scalar, - Color, - StrokeWidth, // unused - MarkerSize, - MarkerShape, - _, - >( - store, + let results = ctx.recording().query_caches2().range( + ctx.recording_store(), &query, entity_path, - |entry_range, (times, _, scalars, colors, _, marker_sizes, markers)| { - let times = times.range(entry_range.clone()).map(|(time, _)| time.as_i64()); - - // Allocate all points. - points = times.map(|time| PlotPoint { - time, - ..default_point.clone() - }).collect_vec(); - - // Fill in values. - for (i, scalar) in scalars.range(entry_range.clone()).enumerate() { - if scalar.len() > 1 { - re_log::warn_once!("found a scalar batch in {entity_path:?} -- those have no effect"); - } else if scalar.is_empty() { - points[i].attrs.kind = PlotSeriesKind::Clear; - } else { - points[i].value = scalar.first().map_or(0.0, |s| s.0); - } + [ + Scalar::name(), + Color::name(), + MarkerSize::name(), + MarkerShape::name(), + ], + ); + + let all_scalars = results + .get_required(Scalar::name())? + .to_dense::(resolver); + let all_scalars_entry_range = all_scalars.entry_range(); + + if !matches!( + all_scalars.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + ) { + // TODO(#5607): what should happen if the promise is still pending? + } + + // Allocate all points. + points = all_scalars + .range_indices(all_scalars_entry_range.clone()) + .map(|(data_time, _)| PlotPoint { + time: data_time.as_i64(), + ..default_point.clone() + }) + .collect_vec(); + + // Fill in values. + for (i, scalars) in all_scalars + .range_data(all_scalars_entry_range.clone()) + .enumerate() + { + if scalars.len() > 1 { + re_log::warn_once!( + "found a scalar batch in {entity_path:?} -- those have no effect" + ); + } else if scalars.is_empty() { + points[i].attrs.kind = PlotSeriesKind::Clear; + } else { + points[i].value = scalars.first().map_or(0.0, |s| s.0); + } + } + + // Make it as clear as possible to the optimizer that some parameters + // go completely unused as soon as overrides have been defined. + + // Fill in colors -- if available _and_ not overridden. + if override_color.is_none() { + if let Some(all_colors) = results.get(Color::name()) { + let all_colors = all_colors.to_dense::(resolver); + + if !matches!( + all_colors.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + ) { + // TODO(#5607): what should happen if the promise is still pending? } - // Make it as clear as possible to the optimizer that some parameters - // go completely unused as soon as overrides have been defined. + let all_scalars_indexed = all_scalars + .range_indices(all_scalars_entry_range.clone()) + .map(|index| (index, ())); + + let all_frames = re_query_cache2::range_zip_1x1( + all_scalars_indexed, + all_colors.range_indexed(), + ) + .enumerate(); - // Fill in marker sizes -- if available _and_ not overridden. - if override_marker_size.is_none() { - if let Some(marker_sizes) = marker_sizes { - for (i, marker_size) in marker_sizes.range(entry_range.clone()).enumerate() { - if i >= points.len() { - re_log::debug_once!("more marker size attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; + for (i, (_index, _scalars, colors)) in all_frames { + if let Some(color) = colors.and_then(|colors| { + colors.first().map(|c| { + let [r, g, b, a] = c.to_array(); + if a == 255 { + // Common-case optimization + re_renderer::Color32::from_rgb(r, g, b) + } else { + re_renderer::Color32::from_rgba_unmultiplied(r, g, b, a) } - if let Some(marker_size) = marker_size.first().copied().flatten() { - points[i].attrs.marker_size = marker_size.0; - }; - } + }) + }) { + points[i].attrs.color = color; } } + } + } - // Fill in marker shapes -- if available _and_ not overridden. - if override_marker.is_none() { - if let Some(markers) = markers { - for (i, marker) in markers.range(entry_range.clone()).enumerate() { - if i >= points.len() { - re_log::debug_once!("more marker attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; - } - if let Some(marker) = marker.first().copied().flatten() { - points[i].attrs.kind = PlotSeriesKind::Scatter(ScatterAttrs { marker }); - }; - } + // Fill in marker sizes -- if available _and_ not overridden. + if override_marker_size.is_none() { + if let Some(all_marker_sizes) = results.get(MarkerSize::name()) { + let all_marker_sizes = all_marker_sizes.to_dense::(resolver); + + if !matches!( + all_marker_sizes.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + ) { + // TODO(#5607): what should happen if the promise is still pending? + } + + let all_scalars_indexed = all_scalars + .range_indices(all_scalars_entry_range.clone()) + .map(|index| (index, ())); + + let all_frames = re_query_cache2::range_zip_1x1( + all_scalars_indexed, + all_marker_sizes.range_indexed(), + ) + .enumerate(); + + for (i, (_index, _scalars, marker_sizes)) in all_frames { + if let Some(marker_size) = + marker_sizes.and_then(|marker_sizes| marker_sizes.first().copied()) + { + points[i].attrs.marker_size = marker_size.0; } } + } + } - // Fill in colors -- if available _and_ not overridden. - if override_color.is_none() { - if let Some(colors) = colors { - for (i, color) in colors.range(entry_range.clone()).enumerate() { - if i >= points.len() { - re_log::debug_once!("more color attributes than points in {entity_path:?} -- this points to a bug in the query cache"); - break; - } - if let Some(color) = color.first().copied().flatten().map(|c| { - let [r,g,b,a] = c.to_array(); - if a == 255 { - // Common-case optimization - re_renderer::Color32::from_rgb(r, g, b) - } else { - re_renderer::Color32::from_rgba_unmultiplied(r, g, b, a) - } - }) { - points[i].attrs.color = color; - } - } + // Fill in marker shapes -- if available _and_ not overridden. + if override_marker_shape.is_none() { + if let Some(all_marker_shapes) = results.get(MarkerShape::name()) { + let all_marker_shapes = all_marker_shapes.to_dense::(resolver); + + if !matches!( + all_marker_shapes.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())) + ) { + // TODO(#5607): what should happen if the promise is still pending? + } + + let all_scalars_indexed = all_scalars + .range_indices(all_scalars_entry_range.clone()) + .map(|index| (index, ())); + + let all_frames = re_query_cache2::range_zip_1x1( + all_scalars_indexed, + all_marker_shapes.range_indexed(), + ) + .enumerate(); + + for (i, (_index, _scalars, marker_shapes)) in all_frames { + if let Some(marker) = marker_shapes + .and_then(|marker_shapes| marker_shapes.first().copied()) + { + points[i].attrs.kind = + PlotSeriesKind::Scatter(ScatterAttrs { marker }); } } - }, - )?; + } + } } // Check for an explicit label if any. @@ -264,7 +325,7 @@ impl SeriesPointSystem { data_result, time_per_pixel, points, - store, + ctx.recording_store(), query, series_name, &mut self.all_series, From 6d9e23cc6a757fe4ea90262e985e544454a8798a Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:41:31 +0200 Subject: [PATCH 370/508] New data APIs 12: port all spatial views (#5993) Migrate all spatial views that were using the old cache APIs to the new ones. Instance keys are not queried at all anymore. All views are now range-aware by default. Also took the opportunity to somewhat streamline everything. The 10min air-traffic example with full visible range is about 2-2.5x faster than before. I'm sure I broke a few things here and there, I'll run a full check suite once everything's said and done. --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- Cargo.lock | 2 + crates/re_entity_db/src/lib.rs | 2 +- .../re_query_cache2/src/latest_at/results.rs | 6 +- crates/re_query_cache2/src/range/results.rs | 103 ++++- crates/re_space_view/Cargo.toml | 1 + crates/re_space_view/src/visual_time_range.rs | 2 +- crates/re_space_view_spatial/Cargo.toml | 5 +- .../benches/bench_points.rs | 169 -------- .../src/contexts/transform_context.rs | 53 +-- crates/re_space_view_spatial/src/lib.rs | 3 - .../src/visualizers/arrows2d.rs | 336 ++++++++-------- .../src/visualizers/arrows3d.rs | 340 +++++++++-------- .../src/visualizers/boxes2d.rs | 355 ++++++++--------- .../src/visualizers/boxes3d.rs | 360 ++++++++++-------- .../src/visualizers/entity_iterator.rs | 341 ++++++++--------- .../src/visualizers/lines2d.rs | 278 ++++++++------ .../src/visualizers/lines3d.rs | 282 ++++++++------ .../src/visualizers/mod.rs | 199 ++++------ .../src/visualizers/points2d.rs | 326 ++++++++-------- .../src/visualizers/points3d.rs | 355 +++++++---------- .../src/visualizers/results_ext.rs | 151 ++++++++ .../src/visualizers/transform3d_arrows.rs | 17 +- 22 files changed, 1851 insertions(+), 1835 deletions(-) delete mode 100644 crates/re_space_view_spatial/benches/bench_points.rs create mode 100644 crates/re_space_view_spatial/src/visualizers/results_ext.rs diff --git a/Cargo.lock b/Cargo.lock index 890586d674d6..f9703f346a2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4710,6 +4710,7 @@ dependencies = [ "re_log", "re_log_types", "re_query", + "re_query2", "re_tracing", "re_types", "re_types_core", @@ -4779,6 +4780,7 @@ dependencies = [ "re_log_types", "re_query", "re_query_cache", + "re_query_cache2", "re_renderer", "re_space_view", "re_tracing", diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index 859e3af45679..78a87c87a7d2 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -34,7 +34,7 @@ pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents}; use re_log_types::DataTableError; pub use re_log_types::{EntityPath, EntityPathPart, TimeInt, Timeline}; -pub use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +pub use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; #[cfg(feature = "serde")] pub use blueprint::components::EntityPropertiesComponent; diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache2/src/latest_at/results.rs index 0a1bbd714b2d..44691217ac9d 100644 --- a/crates/re_query_cache2/src/latest_at/results.rs +++ b/crates/re_query_cache2/src/latest_at/results.rs @@ -126,7 +126,7 @@ pub struct CachedLatestAtComponentResults { pub(crate) promise: Option, /// The resolved, converted, deserialized dense data. - pub(crate) cached_dense: OnceLock>, + pub(crate) cached_dense: OnceLock>, } impl CachedLatestAtComponentResults { @@ -274,9 +274,9 @@ impl CachedLatestAtComponentResults { .map_err(|err| DeserializationError::DataCellError(err.to_string()))?; #[allow(clippy::borrowed_box)] - let cached: &Box = self + let cached: &Arc = self .cached_dense - .get_or_init(move || Box::new(FlatVecDeque::from(data))); + .get_or_init(move || Arc::new(FlatVecDeque::from(data))); downcast(&**cached) } diff --git a/crates/re_query_cache2/src/range/results.rs b/crates/re_query_cache2/src/range/results.rs index 98a39eebed52..5f9bc83e6255 100644 --- a/crates/re_query_cache2/src/range/results.rs +++ b/crates/re_query_cache2/src/range/results.rs @@ -12,7 +12,10 @@ use re_data_store::RangeQuery; use re_log_types::{RowId, TimeInt, TimeRange}; use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; -use crate::{ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, PromiseResult}; +use crate::{ + CachedLatestAtComponentResults, ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, + PromiseResult, +}; // --- @@ -98,6 +101,14 @@ impl CachedRangeResults { // --- +thread_local! { + /// Keeps track of reentrancy counts for the current thread. + /// + /// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing + /// environments such as Rayon. + static REENTERING: RefCell = const { RefCell::new(0) }; +} + /// Lazily cached results for a particular component when using a cached range query. #[derive(Debug)] pub struct CachedRangeComponentResults { @@ -156,7 +167,47 @@ impl std::ops::Deref for CachedRangeComponentResults { } } +/// Helper datastructure to make it possible to convert latest-at results into ranged results. #[derive(Debug)] +enum Indices<'a> { + Owned(VecDeque<(TimeInt, RowId)>), + Cached(MappedRwLockReadGuard<'a, VecDeque<(TimeInt, RowId)>>), +} + +impl<'a> std::ops::Deref for Indices<'a> { + type Target = VecDeque<(TimeInt, RowId)>; + + #[inline] + fn deref(&self) -> &Self::Target { + match self { + Indices::Owned(data) => data, + Indices::Cached(data) => data, + } + } +} + +/// Helper datastructure to make it possible to convert latest-at results into ranged results. +enum Data<'a, T> { + Owned(Arc), + Cached(MappedRwLockReadGuard<'a, FlatVecDeque>), +} + +impl<'a, T: 'static> std::ops::Deref for Data<'a, T> { + type Target = FlatVecDeque; + + #[inline] + fn deref(&self) -> &Self::Target { + match self { + Data::Owned(data) => { + // Unwrap: only way to instantiate a `Data` is via the `From` impl below which we + // fully control. + data.as_any().downcast_ref().unwrap() + } + Data::Cached(data) => data, + } + } +} + pub struct CachedRangeData<'a, T> { // NOTE: Options so we can represent an empty result without having to somehow conjure a mutex // guard out of thin air. @@ -164,8 +215,9 @@ pub struct CachedRangeData<'a, T> { // TODO(Amanieu/parking_lot#289): we need two distinct mapped guards because it's // impossible to return an owned type in a `parking_lot` guard. // See . - indices: Option>>, - data: Option>>, + // indices: Option>>, + indices: Option>, + data: Option>, time_range: TimeRange, front_status: PromiseResult<()>, @@ -178,6 +230,32 @@ pub struct CachedRangeData<'a, T> { reentering: &'static std::thread::LocalKey>, } +impl<'a, C: Component> CachedRangeData<'a, C> { + /// Useful to abstract over latest-at and ranged results. + #[inline] + pub fn from_latest_at( + resolver: &PromiseResolver, + results: &'a CachedLatestAtComponentResults, + ) -> Self { + let CachedLatestAtComponentResults { + index, + promise: _, + cached_dense, + } = results; + + let status = results.to_dense::(resolver).map(|_| ()); + + Self { + indices: Some(Indices::Owned(vec![*index].into())), + data: cached_dense.get().map(|data| Data::Owned(Arc::clone(data))), + time_range: TimeRange::new(index.0, index.0), + front_status: status.clone(), + back_status: status, + reentering: &REENTERING, + } + } +} + impl<'a, T> Drop for CachedRangeData<'a, T> { #[inline] fn drop(&mut self) { @@ -186,7 +264,7 @@ impl<'a, T> Drop for CachedRangeData<'a, T> { } } -impl<'a, T> CachedRangeData<'a, T> { +impl<'a, T: 'static> CachedRangeData<'a, T> { /// Returns the current status on both ends of the range. /// /// E.g. it is possible that the front-side of the range is still waiting for pending data while @@ -201,10 +279,11 @@ impl<'a, T> CachedRangeData<'a, T> { &self, entry_range: Range, ) -> impl Iterator { - match self.indices.as_ref() { + let indices = match self.indices.as_ref() { Some(indices) => itertools::Either::Left(indices.range(entry_range)), None => itertools::Either::Right(std::iter::empty()), - } + }; + indices } #[inline] @@ -278,14 +357,6 @@ impl CachedRangeComponentResults { // --- Step 1: try and upsert pending data (write lock) --- - thread_local! { - /// Keeps track of reentrancy counts for the current thread. - /// - /// Used to detect and prevent potential deadlocks when using the cached APIs in work-stealing - /// environments such as Rayon. - static REENTERING: RefCell = const { RefCell::new(0) }; - } - REENTERING.with_borrow_mut(|reentering| *reentering = reentering.saturating_add(1)); // Manufactured empty result. @@ -514,8 +585,8 @@ impl CachedRangeComponentResults { }); CachedRangeData { - indices: Some(indices), - data: Some(data), + indices: Some(Indices::Cached(indices)), + data: Some(Data::Cached(data)), time_range: self.time_range, front_status, back_status, diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml index 36b53d591f51..cc5bab4a1c02 100644 --- a/crates/re_space_view/Cargo.toml +++ b/crates/re_space_view/Cargo.toml @@ -27,6 +27,7 @@ re_log_types.workspace = true re_data_store.workspace = true re_entity_db.workspace = true re_query.workspace = true +re_query2.workspace = true re_tracing.workspace = true re_types_core.workspace = true re_types.workspace = true diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index 4a55c27e31f9..cfa4590fbd06 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -8,7 +8,7 @@ //! to reduce the amount of changes in code that is likely to be refactored soon anyways. use re_log_types::TimeRange; -use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; use re_types::blueprint::{ components::VisibleTimeRange, datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index 13782f8730da..4f45589b01fc 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -28,6 +28,7 @@ re_log_types.workspace = true re_log.workspace = true re_query.workspace = true re_query_cache.workspace = true +re_query_cache2.workspace = true re_renderer = { workspace = true, features = [ "import-gltf", "import-obj", @@ -61,7 +62,3 @@ mimalloc.workspace = true [lib] bench = false - -[[bench]] -name = "bench_points" -harness = false diff --git a/crates/re_space_view_spatial/benches/bench_points.rs b/crates/re_space_view_spatial/benches/bench_points.rs deleted file mode 100644 index 36cac5a0bb4c..000000000000 --- a/crates/re_space_view_spatial/benches/bench_points.rs +++ /dev/null @@ -1,169 +0,0 @@ -//! High-level benchmark of the CPU-side of our `Points3D` rendering. - -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{DataRow, EntityPath, RowId, TimeInt, TimePoint, Timeline}; -use re_query_cache::Caches; -use re_space_view_spatial::{LoadedPoints, Points3DComponentData}; -use re_types::{ - archetypes::Points3D, - components::{ClassId, Color, InstanceKey, KeypointId, Position3D, Radius, Text}, - Loggable as _, -}; -use re_viewer_context::Annotations; - -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -criterion::criterion_main!(benches); -criterion::criterion_group!(benches, bench_points); - -// --- - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -mod constants { - pub const NUM_POINTS: usize = 10; -} - -#[cfg(not(debug_assertions))] -mod constants { - pub const NUM_POINTS: usize = 1_000_000; -} - -#[allow(clippy::wildcard_imports)] -use self::constants::*; - -// --- - -/// Mimics `examples/python/open_photogrammetry_format/open_photogrammetry_format.py` -fn bench_points(c: &mut criterion::Criterion) { - let timeline = Timeline::log_time(); - let ent_path = EntityPath::from("points"); - - let store = { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let positions = vec![Position3D::new(0.1, 0.2, 0.3); NUM_POINTS]; - let colors = vec![Color::from(0xffffffff); NUM_POINTS]; - let points = Points3D::new(positions).with_colors(colors); - let mut timepoint = TimePoint::default(); - timepoint.insert(timeline, TimeInt::from_seconds(0.try_into().unwrap())); - let data_row = - DataRow::from_archetype(RowId::new(), timepoint, ent_path.clone(), &points).unwrap(); - store.insert_row(&data_row).unwrap(); - store - }; - let caches = Caches::new(&store); - - let latest_at = LatestAtQuery::latest(timeline); - let at = latest_at.at(); - let latest_at = re_query_cache::AnyQuery::from(latest_at); - let annotations = Annotations::missing(); - - fn bench_name(cached: bool, name: &str) -> String { - format!("{name}/cached={cached}") - } - - { - let mut group = c.benchmark_group("Points3D"); - group.bench_function(bench_name(true, "query_archetype"), |b| { - b.iter(|| { - caches.query_archetype_pov1_comp5::< - Points3D, - Position3D, - Color, - Radius, - Text, - KeypointId, - ClassId, - _, - >( - &store, - &latest_at, - &ent_path, - |(_, keys, _, _, _, _, _, _)| { - assert_eq!(keys.len(), NUM_POINTS); - }, - ) - .unwrap(); - }); - }); - } - - caches.query_archetype_pov1_comp5::< - Points3D, - Position3D, - Color, - Radius, - Text, - KeypointId, - ClassId, - _, - >( - &store, - &latest_at, - &ent_path, - |(_, instance_keys, positions, colors, radii, labels, keypoint_ids, class_ids)| { - let data = Points3DComponentData { - instance_keys, - positions, - colors, - radii, - labels, - keypoint_ids, - class_ids, - }; - assert_eq!(data.instance_keys.len(), NUM_POINTS); - - { - let mut group = c.benchmark_group("Points3D"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - group.bench_function(bench_name(true, "load_all"), |b| { - b.iter(|| { - let points = LoadedPoints::load(&data, &ent_path, at, &annotations); - assert_eq!(points.positions.len(), NUM_POINTS); - assert_eq!(points.colors.len(), NUM_POINTS); - assert_eq!(points.radii.len(), NUM_POINTS); // NOTE: we don't log radii, but we should get a list of defaults! - points - }); - }); - } - - { - let points = LoadedPoints::load(&data, &ent_path, at, &annotations); - - let mut group = c.benchmark_group("Points3D"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - group.bench_function(bench_name(true, "load_colors"), |b| { - b.iter(|| { - let colors = LoadedPoints::load_colors( - &data, - &ent_path, - &points.annotation_infos, - ); - assert_eq!(colors.len(), NUM_POINTS); - colors - }); - }); - } - - // NOTE: we don't log radii! - { - let mut group = c.benchmark_group("Points3D"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - group.bench_function(bench_name(true, "load_radii"), |b| { - b.iter(|| { - let radii = LoadedPoints::load_radii(&data, &ent_path); - assert_eq!(radii.len(), NUM_POINTS); - radii - }); - }); - } - }, - ) - .unwrap(); -} diff --git a/crates/re_space_view_spatial/src/contexts/transform_context.rs b/crates/re_space_view_spatial/src/contexts/transform_context.rs index 2e0487620ea1..24b6131ebdc4 100644 --- a/crates/re_space_view_spatial/src/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/contexts/transform_context.rs @@ -3,7 +3,7 @@ use nohash_hasher::IntMap; use re_data_store::LatestAtQuery; use re_entity_db::{EntityDb, EntityPath, EntityPropertyMap, EntityTree}; use re_types::{ - components::{DisconnectedSpace, PinholeProjection, Resolution, Transform3D, ViewCoordinates}, + components::{DisconnectedSpace, PinholeProjection, Transform3D, ViewCoordinates}, ComponentNameSet, Loggable as _, }; use re_viewer_context::{IdentifiedViewSystem, ViewContextSystem}; @@ -296,17 +296,9 @@ fn get_cached_transform( entity_db: &EntityDb, query: &LatestAtQuery, ) -> Option { - let mut transform3d = None; entity_db - .query_caches() - .query_archetype_latest_at_pov1_comp0::( - entity_db.store(), - query, - entity_path, - |(_, _, transforms)| transform3d = transforms.first().cloned(), - ) - .ok(); - transform3d + .latest_at_component::(entity_path, query) + .map(|res| res.value) } fn get_cached_pinhole( @@ -314,19 +306,16 @@ fn get_cached_pinhole( entity_db: &EntityDb, query: &re_data_store::LatestAtQuery, ) -> Option<(PinholeProjection, ViewCoordinates)> { - let mut result = None; - entity_db.query_caches() - .query_archetype_latest_at_pov1_comp2::( - entity_db.store(), - query, - entity_path, - |(_, _, image_from_camera, _resolution, camera_xyz)| { - result = image_from_camera.first().map(|image_from_camera| - (*image_from_camera, camera_xyz.and_then(|c| c.first()).copied().flatten().unwrap_or(ViewCoordinates::RDF))); - } - ) - .ok(); - result + entity_db + .latest_at_archetype::(entity_path, query) + .ok() + .flatten() + .map(|arch| { + ( + arch.image_from_camera, + arch.camera_xyz.unwrap_or(ViewCoordinates::RDF), + ) + }) } fn transform_at( @@ -390,19 +379,9 @@ fn transform_at( }); let is_disconnect_space = || { - let mut disconnected_space = false; - entity_db.query_caches() - .query_archetype_latest_at_pov1_comp0::( - entity_db.store(), - query, - entity_path, - |(_, _, disconnected_spaces)| { - disconnected_space = disconnected_spaces - .first() .map_or(false, |dp| dp.0); - }, - ) - .ok(); - disconnected_space + entity_db + .latest_at_component::(entity_path, query) + .map_or(false, |res| res.value.0) }; // If there is any other transform, we ignore `DisconnectedSpace`. diff --git a/crates/re_space_view_spatial/src/lib.rs b/crates/re_space_view_spatial/src/lib.rs index 2a2ca322342c..9a5fe950ddc1 100644 --- a/crates/re_space_view_spatial/src/lib.rs +++ b/crates/re_space_view_spatial/src/lib.rs @@ -26,9 +26,6 @@ use re_types::components::{Resolution, TensorData}; pub use space_view_2d::SpatialSpaceView2D; pub use space_view_3d::SpatialSpaceView3D; -#[doc(hidden)] // Public for benchmarks -pub use visualizers::{LoadedPoints, Points3DComponentData}; - // --- mod view_kind { diff --git a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs index 2a6071d0ccee..4f5792346a3b 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs @@ -1,4 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_query_cache2::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows2D, @@ -10,16 +11,19 @@ use re_viewer_context::{ VisualizableEntities, VisualizableFilterContext, VisualizerQueryInfo, VisualizerSystem, }; -use super::{ - process_annotation_and_keypoint_slices, process_color_slice, process_radius_slice, - SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, -}; use crate::{ contexts::{EntityDepthOffsets, SpatialSceneEntityContext}, view_kind::SpatialSpaceViewKind, visualizers::{filter_visualizable_2d_entities, UiLabel, UiLabelTarget}, }; +use super::{ + entity_iterator::clamped, process_annotation_and_keypoint_slices, process_color_slice, + process_radius_slice, SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, +}; + +// --- + pub struct Arrows2DVisualizer { /// If the number of arrows in the batch is > max_labels, don't render point labels. pub max_labels: usize, @@ -35,152 +39,148 @@ impl Default for Arrows2DVisualizer { } } +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Arrows2DVisualizer { fn process_labels<'a>( + entity_path: &'a EntityPath, vectors: &'a [Vector2D], - origins: impl Iterator> + 'a, - labels: &'a [Option], - instance_path_hashes: &'a [InstancePathHash], + origins: impl Iterator + 'a, + labels: &'a [Text], colors: &'a [egui::Color32], annotation_infos: &'a ResolvedAnnotationInfos, world_from_obj: glam::Affine3A, ) -> impl Iterator + 'a { - itertools::izip!( - annotation_infos.iter(), - vectors, - origins, - labels, - colors, - instance_path_hashes, - ) - .filter_map( - move |(annotation_info, vector, origin, label, color, labeled_instance)| { - let origin = origin.unwrap_or(Position2D::ZERO); - let label = annotation_info.label(label.as_ref().map(|l| l.as_str())); - match (vector, label) { - (vector, Some(label)) => { - let midpoint = + let labels = clamped(labels, vectors.len()); + let origins = origins.chain(std::iter::repeat(&Position2D::ZERO)); + itertools::izip!(annotation_infos.iter(), vectors, origins, labels, colors) + .enumerate() + .filter_map( + move |(i, (annotation_info, vector, origin, label, color))| { + let label = annotation_info.label(Some(label.as_str())); + match (vector, label) { + (vector, Some(label)) => { + let midpoint = // `0.45` rather than `0.5` to account for cap and such glam::Vec2::from(origin.0) + glam::Vec2::from(vector.0) * 0.45; - let midpoint = world_from_obj.transform_point3(midpoint.extend(0.0)); - - Some(UiLabel { - text: label, - color: *color, - target: UiLabelTarget::Point2D(egui::pos2(midpoint.x, midpoint.y)), - labeled_instance: *labeled_instance, - }) + let midpoint = world_from_obj.transform_point3(midpoint.extend(0.0)); + + Some(UiLabel { + text: label, + color: *color, + target: UiLabelTarget::Point2D(egui::pos2(midpoint.x, midpoint.y)), + labeled_instance: InstancePathHash::instance( + entity_path, + InstanceKey(i as _), + ), + }) + } + _ => None, } - _ => None, - } - }, - ) + }, + ) } - fn process_data( + fn process_data<'a>( &mut self, line_builder: &mut re_renderer::LineDrawableBuilder<'_>, query: &ViewQuery<'_>, - data: &Arrows2DComponentData<'_>, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, + data: impl Iterator>, ) { - let (annotation_infos, _) = process_annotation_and_keypoint_slices( - query.latest_at, - data.instance_keys, - data.keypoint_ids, - data.class_ids, - data.vectors.iter().map(|_| glam::Vec3::ZERO), - &ent_context.annotations, - ); - - let radii = process_radius_slice(data.radii, data.vectors.len(), ent_path); - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - let origins = || { - data.origins.map_or_else( - || itertools::Either::Left(std::iter::repeat(Some(Position2D::ZERO))), - |origins| itertools::Either::Right(origins.iter().copied()), - ) - }; - - if data.instance_keys.len() <= self.max_labels { - re_tracing::profile_scope!("labels"); + for data in data { + let num_instances = data.vectors.len(); + if num_instances == 0 { + continue; + } - // Max labels is small enough that we can afford iterating on the colors again. - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); + let (annotation_infos, _) = process_annotation_and_keypoint_slices( + query.latest_at, + num_instances, + data.vectors.iter().map(|_| glam::Vec3::ZERO), + data.keypoint_ids, + data.class_ids, + &ent_context.annotations, + ); - let instance_path_hashes_for_picking = { - re_tracing::profile_scope!("instance_hashes"); - data.instance_keys - .iter() - .copied() - .map(|instance_key| InstancePathHash::instance(ent_path, instance_key)) - .collect::>() - }; + let radii = process_radius_slice(entity_path, num_instances, data.radii); + let colors = + process_color_slice(entity_path, num_instances, &annotation_infos, data.colors); - if let Some(labels) = data.labels { + if num_instances <= self.max_labels { + let origins = clamped(data.origins, num_instances); self.data.ui_labels.extend(Self::process_labels( + entity_path, data.vectors, - origins(), - labels, - &instance_path_hashes_for_picking, + origins, + data.labels, &colors, &annotation_infos, ent_context.world_from_entity, )); } - } - let mut line_batch = line_builder - .batch(ent_path.to_string()) - .world_from_obj(ent_context.world_from_entity) - .outline_mask_ids(ent_context.highlight.overall) - .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); - - let mut bounding_box = macaw::BoundingBox::nothing(); - - for (instance_key, vector, origin, radius, color) in - itertools::izip!(data.instance_keys, data.vectors, origins(), radii, colors,) - { - let vector: glam::Vec2 = vector.0.into(); - let origin: glam::Vec2 = origin.unwrap_or(Position2D::ZERO).0.into(); - let end = origin + vector; - - let segment = line_batch - .add_segment_2d(origin, end) - .radius(radius) - .color(color) - .flags( - LineStripFlags::FLAG_CAP_END_TRIANGLE - | LineStripFlags::FLAG_CAP_START_ROUND - | LineStripFlags::FLAG_CAP_START_EXTEND_OUTWARDS, - ) - .picking_instance_id(PickingLayerInstanceId(instance_key.0)); + let mut line_batch = line_builder + .batch(entity_path.to_string()) + .world_from_obj(ent_context.world_from_entity) + .outline_mask_ids(ent_context.highlight.overall) + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); + + let mut bounding_box = macaw::BoundingBox::nothing(); + + let origins = + clamped(data.origins, num_instances).chain(std::iter::repeat(&Position2D::ZERO)); + for (i, (vector, origin, radius, color)) in + itertools::izip!(data.vectors, origins, radii, colors).enumerate() + { + let vector: glam::Vec2 = vector.0.into(); + let origin: glam::Vec2 = origin.0.into(); + let end = origin + vector; + + let segment = line_batch + .add_segment_2d(origin, end) + .radius(radius) + .color(color) + .flags( + LineStripFlags::FLAG_CAP_END_TRIANGLE + | LineStripFlags::FLAG_CAP_START_ROUND + | LineStripFlags::FLAG_CAP_START_EXTEND_OUTWARDS, + ) + .picking_instance_id(PickingLayerInstanceId(i as _)); - if let Some(outline_mask_ids) = ent_context.highlight.instances.get(instance_key) { - segment.outline_mask_ids(*outline_mask_ids); + if let Some(outline_mask_ids) = + ent_context.highlight.instances.get(&InstanceKey(i as _)) + { + segment.outline_mask_ids(*outline_mask_ids); + } + + bounding_box.extend(origin.extend(0.0)); + bounding_box.extend(end.extend(0.0)); } - bounding_box.extend(origin.extend(0.0)); - bounding_box.extend(end.extend(0.0)); + self.data.add_bounding_box( + entity_path.hash(), + bounding_box, + ent_context.world_from_entity, + ); } - - self.data - .add_bounding_box(ent_path.hash(), bounding_box, ent_context.world_from_entity); } } // --- struct Arrows2DComponentData<'a> { - pub instance_keys: &'a [InstanceKey], - pub vectors: &'a [Vector2D], - pub origins: Option<&'a [Option]>, - pub colors: Option<&'a [Option]>, - pub radii: Option<&'a [Option]>, - pub labels: Option<&'a [Option]>, - pub keypoint_ids: Option<&'a [Option]>, - pub class_ids: Option<&'a [Option]>, + // Point of views + vectors: &'a [Vector2D], + + // Clamped to edge + origins: &'a [Position2D], + colors: &'a [Color], + radii: &'a [Radius], + labels: &'a [Text], + keypoint_ids: &'a [KeypointId], + class_ids: &'a [ClassId], } impl IdentifiedViewSystem for Arrows2DVisualizer { @@ -206,64 +206,78 @@ impl VisualizerSystem for Arrows2DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let num_arrows = super::entity_iterator::count_instances_in_archetype_views::< - Arrows2DVisualizer, - Arrows2D, - 8, - >(ctx, query); - - if num_arrows == 0 { - return Ok(Vec::new()); - } - let mut line_builder = LineDrawableBuilder::new(ctx.render_ctx); - line_builder.reserve_strips(num_arrows)?; - line_builder.reserve_vertices(num_arrows * 2)?; line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES); - super::entity_iterator::process_archetype_pov1_comp6::< - Arrows2DVisualizer, - Arrows2D, - Vector2D, - Position2D, - Color, - Radius, - Text, - KeypointId, - ClassId, - _, - >( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |_ctx, - ent_path, - _ent_props, - ent_context, - (_time, _row_id), - instance_keys, - vectors, - origins, - colors, - radii, - labels, - keypoint_ids, - class_ids| { - let data = Arrows2DComponentData { - instance_keys, - vectors, - origins, - colors, - radii, - labels, - keypoint_ids, - class_ids, + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let vectors = match results.get_dense::(resolver) { + Some(vectors) => vectors?, + _ => return Ok(()), }; - self.process_data(&mut line_builder, query, &data, ent_path, ent_context); + + let num_vectors = vectors + .range_indexed() + .map(|(_, vectors)| vectors.len()) + .sum::(); + if num_vectors == 0 { + return Ok(()); + } + + line_builder.reserve_strips(num_vectors)?; + line_builder.reserve_vertices(num_vectors * 2)?; + + let origins = results.get_or_empty_dense(resolver)?; + let colors = results.get_or_empty_dense(resolver)?; + let radii = results.get_or_empty_dense(resolver)?; + let labels = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + let keypoint_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x6( + vectors.range_indexed(), + origins.range_indexed(), + colors.range_indexed(), + radii.range_indexed(), + labels.range_indexed(), + class_ids.range_indexed(), + keypoint_ids.range_indexed(), + ) + .map( + |(_index, vectors, origins, colors, radii, labels, class_ids, keypoint_ids)| { + Arrows2DComponentData { + vectors, + origins: origins.unwrap_or_default(), + colors: colors.unwrap_or_default(), + radii: radii.unwrap_or_default(), + labels: labels.unwrap_or_default(), + class_ids: class_ids.unwrap_or_default(), + keypoint_ids: keypoint_ids.unwrap_or_default(), + } + }, + ); + + self.process_data( + &mut line_builder, + view_query, + entity_path, + spatial_ctx, + data, + ); + Ok(()) }, )?; diff --git a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs index ae515af0d34a..e5e61d400514 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs @@ -1,4 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_query_cache2::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows3D, @@ -10,16 +11,19 @@ use re_viewer_context::{ VisualizableEntities, VisualizableFilterContext, VisualizerQueryInfo, VisualizerSystem, }; -use super::{ - process_annotation_and_keypoint_slices, process_color_slice, process_radius_slice, - SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, -}; use crate::{ contexts::{EntityDepthOffsets, SpatialSceneEntityContext}, view_kind::SpatialSpaceViewKind, visualizers::{filter_visualizable_3d_entities, UiLabel, UiLabelTarget}, }; +use super::{ + entity_iterator::clamped, process_annotation_and_keypoint_slices, process_color_slice, + process_radius_slice, SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, +}; + +// --- + pub struct Arrows3DVisualizer { /// If the number of arrows in the batch is > max_labels, don't render point labels. pub max_labels: usize, @@ -35,153 +39,151 @@ impl Default for Arrows3DVisualizer { } } +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Arrows3DVisualizer { fn process_labels<'a>( + entity_path: &'a EntityPath, vectors: &'a [Vector3D], - origins: impl Iterator> + 'a, - labels: &'a [Option], - instance_path_hashes: &'a [InstancePathHash], + origins: impl Iterator + 'a, + labels: &'a [Text], colors: &'a [egui::Color32], annotation_infos: &'a ResolvedAnnotationInfos, world_from_obj: glam::Affine3A, ) -> impl Iterator + 'a { - itertools::izip!( - annotation_infos.iter(), - vectors, - origins, - labels, - colors, - instance_path_hashes, - ) - .filter_map( - move |(annotation_info, vector, origin, label, color, labeled_instance)| { - let origin = origin.unwrap_or(Position3D::ZERO); - let label = annotation_info.label(label.as_ref().map(|l| l.as_str())); - match (vector, label) { - (vector, Some(label)) => { - let midpoint = + let labels = clamped(labels, vectors.len()); + let origins = origins.chain(std::iter::repeat(&Position3D::ZERO)); + itertools::izip!(annotation_infos.iter(), vectors, origins, labels, colors) + .enumerate() + .filter_map( + move |(i, (annotation_info, vector, origin, label, color))| { + let label = annotation_info.label(Some(label.as_str())); + match (vector, label) { + (vector, Some(label)) => { + let midpoint = // `0.45` rather than `0.5` to account for cap and such (glam::Vec3::from(origin.0) + glam::Vec3::from(vector.0)) * 0.45; - Some(UiLabel { - text: label, - color: *color, - target: UiLabelTarget::Position3D( - world_from_obj.transform_point3(midpoint), - ), - labeled_instance: *labeled_instance, - }) + let midpoint = world_from_obj.transform_point3(midpoint); + + Some(UiLabel { + text: label, + color: *color, + target: UiLabelTarget::Position3D( + world_from_obj.transform_point3(midpoint), + ), + labeled_instance: InstancePathHash::instance( + entity_path, + InstanceKey(i as _), + ), + }) + } + _ => None, } - _ => None, - } - }, - ) + }, + ) } - fn process_data( + fn process_data<'a>( &mut self, line_builder: &mut LineDrawableBuilder<'_>, query: &ViewQuery<'_>, - data: &Arrows3DComponentData<'_>, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, + data: impl Iterator>, ) { - let (annotation_infos, _) = process_annotation_and_keypoint_slices( - query.latest_at, - data.instance_keys, - data.keypoint_ids, - data.class_ids, - data.vectors.iter().map(|_| glam::Vec3::ZERO), - &ent_context.annotations, - ); - - let radii = process_radius_slice(data.radii, data.vectors.len(), ent_path); - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - let origins = || { - data.origins.map_or_else( - || itertools::Either::Left(std::iter::repeat(Some(Position3D::ZERO))), - |origins| itertools::Either::Right(origins.iter().copied()), - ) - }; - - if data.instance_keys.len() <= self.max_labels { - re_tracing::profile_scope!("labels"); + for data in data { + let num_instances = data.vectors.len(); + if num_instances == 0 { + continue; + } - // Max labels is small enough that we can afford iterating on the colors again. - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); + let (annotation_infos, _) = process_annotation_and_keypoint_slices( + query.latest_at, + num_instances, + data.vectors.iter().map(|_| glam::Vec3::ZERO), + data.keypoint_ids, + data.class_ids, + &ent_context.annotations, + ); - let instance_path_hashes_for_picking = { - re_tracing::profile_scope!("instance_hashes"); - data.instance_keys - .iter() - .copied() - .map(|instance_key| InstancePathHash::instance(ent_path, instance_key)) - .collect::>() - }; + let radii = process_radius_slice(entity_path, num_instances, data.radii); + let colors = + process_color_slice(entity_path, num_instances, &annotation_infos, data.colors); - if let Some(labels) = data.labels { + if num_instances <= self.max_labels { + let origins = clamped(data.origins, num_instances); self.data.ui_labels.extend(Self::process_labels( + entity_path, data.vectors, - origins(), - labels, - &instance_path_hashes_for_picking, + origins, + data.labels, &colors, &annotation_infos, ent_context.world_from_entity, )); } - } - let mut line_batch = line_builder - .batch(ent_path.to_string()) - .world_from_obj(ent_context.world_from_entity) - .outline_mask_ids(ent_context.highlight.overall) - .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); - - let mut bounding_box = macaw::BoundingBox::nothing(); - - for (instance_key, vector, origin, radius, color) in - itertools::izip!(data.instance_keys, data.vectors, origins(), radii, colors) - { - let vector: glam::Vec3 = vector.0.into(); - let origin: glam::Vec3 = origin.unwrap_or(Position3D::ZERO).0.into(); - let end = origin + vector; - - let segment = line_batch - .add_segment(origin, end) - .radius(radius) - .color(color) - .flags( - LineStripFlags::FLAG_COLOR_GRADIENT - | LineStripFlags::FLAG_CAP_END_TRIANGLE - | LineStripFlags::FLAG_CAP_START_ROUND - | LineStripFlags::FLAG_CAP_START_EXTEND_OUTWARDS, - ) - .picking_instance_id(PickingLayerInstanceId(instance_key.0)); + let mut line_batch = line_builder + .batch(entity_path.to_string()) + .world_from_obj(ent_context.world_from_entity) + .outline_mask_ids(ent_context.highlight.overall) + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); + + let mut bounding_box = macaw::BoundingBox::nothing(); + + let origins = + clamped(data.origins, num_instances).chain(std::iter::repeat(&Position3D::ZERO)); + for (i, (vector, origin, radius, color)) in + itertools::izip!(data.vectors, origins, radii, colors).enumerate() + { + let vector: glam::Vec3 = vector.0.into(); + let origin: glam::Vec3 = origin.0.into(); + let end = origin + vector; + + let segment = line_batch + .add_segment(origin, end) + .radius(radius) + .color(color) + .flags( + LineStripFlags::FLAG_COLOR_GRADIENT + | LineStripFlags::FLAG_CAP_END_TRIANGLE + | LineStripFlags::FLAG_CAP_START_ROUND + | LineStripFlags::FLAG_CAP_START_EXTEND_OUTWARDS, + ) + .picking_instance_id(PickingLayerInstanceId(i as _)); - if let Some(outline_mask_ids) = ent_context.highlight.instances.get(instance_key) { - segment.outline_mask_ids(*outline_mask_ids); + if let Some(outline_mask_ids) = + ent_context.highlight.instances.get(&InstanceKey(i as _)) + { + segment.outline_mask_ids(*outline_mask_ids); + } + + bounding_box.extend(origin); + bounding_box.extend(end); } - bounding_box.extend(origin); - bounding_box.extend(end); + self.data.add_bounding_box( + entity_path.hash(), + bounding_box, + ent_context.world_from_entity, + ); } - - self.data - .add_bounding_box(ent_path.hash(), bounding_box, ent_context.world_from_entity); } } // --- struct Arrows3DComponentData<'a> { - pub instance_keys: &'a [InstanceKey], - pub vectors: &'a [Vector3D], - pub origins: Option<&'a [Option]>, - pub colors: Option<&'a [Option]>, - pub radii: Option<&'a [Option]>, - pub labels: Option<&'a [Option]>, - pub keypoint_ids: Option<&'a [Option]>, - pub class_ids: Option<&'a [Option]>, + // Point of views + vectors: &'a [Vector3D], + + // Clamped to edge + origins: &'a [Position3D], + colors: &'a [Color], + radii: &'a [Radius], + labels: &'a [Text], + keypoint_ids: &'a [KeypointId], + class_ids: &'a [ClassId], } impl IdentifiedViewSystem for Arrows3DVisualizer { @@ -207,64 +209,78 @@ impl VisualizerSystem for Arrows3DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let num_arrows = super::entity_iterator::count_instances_in_archetype_views::< - Arrows3DVisualizer, - Arrows3D, - 8, - >(ctx, query); - - if num_arrows == 0 { - return Ok(Vec::new()); - } - let mut line_builder = LineDrawableBuilder::new(ctx.render_ctx); - line_builder.reserve_strips(num_arrows)?; - line_builder.reserve_vertices(num_arrows * 2)?; line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES); - super::entity_iterator::process_archetype_pov1_comp6::< - Arrows3DVisualizer, - Arrows3D, - Vector3D, - Position3D, - Color, - Radius, - Text, - KeypointId, - ClassId, - _, - >( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |_ctx, - ent_path, - _ent_props, - ent_context, - (_time, _row_id), - instance_keys, - vectors, - origins, - colors, - radii, - labels, - keypoint_ids, - class_ids| { - let data = Arrows3DComponentData { - instance_keys, - vectors, - origins, - colors, - radii, - labels, - keypoint_ids, - class_ids, + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let vectors = match results.get_dense::(resolver) { + Some(vectors) => vectors?, + _ => return Ok(()), }; - self.process_data(&mut line_builder, query, &data, ent_path, ent_context); + + let num_vectors = vectors + .range_indexed() + .map(|(_, vectors)| vectors.len()) + .sum::(); + if num_vectors == 0 { + return Ok(()); + } + + line_builder.reserve_strips(num_vectors)?; + line_builder.reserve_vertices(num_vectors * 2)?; + + let origins = results.get_or_empty_dense(resolver)?; + let colors = results.get_or_empty_dense(resolver)?; + let radii = results.get_or_empty_dense(resolver)?; + let labels = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + let keypoint_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x6( + vectors.range_indexed(), + origins.range_indexed(), + colors.range_indexed(), + radii.range_indexed(), + labels.range_indexed(), + class_ids.range_indexed(), + keypoint_ids.range_indexed(), + ) + .map( + |(_index, vectors, origins, colors, radii, labels, class_ids, keypoint_ids)| { + Arrows3DComponentData { + vectors, + origins: origins.unwrap_or_default(), + colors: colors.unwrap_or_default(), + radii: radii.unwrap_or_default(), + labels: labels.unwrap_or_default(), + class_ids: class_ids.unwrap_or_default(), + keypoint_ids: keypoint_ids.unwrap_or_default(), + } + }, + ); + + self.process_data( + &mut line_builder, + view_query, + entity_path, + spatial_ctx, + data, + ); + Ok(()) }, )?; diff --git a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs index 33b31ae53c8b..a22b9ed8ebf8 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs @@ -1,5 +1,6 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_renderer::LineDrawableBuilder; +use re_query_cache2::range_zip_1x6; +use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes2D, components::{ClassId, Color, HalfSizes2D, InstanceKey, KeypointId, Position2D, Radius, Text}, @@ -17,11 +18,13 @@ use crate::{ }; use super::{ - filter_visualizable_2d_entities, picking_id_from_instance_key, + entity_iterator::clamped, filter_visualizable_2d_entities, process_annotation_and_keypoint_slices, process_color_slice, process_radius_slice, SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, }; +// --- + pub struct Boxes2DVisualizer { /// If the number of points in the batch is > max_labels, don't render box labels. pub max_labels: usize, @@ -37,155 +40,143 @@ impl Default for Boxes2DVisualizer { } } +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Boxes2DVisualizer { fn process_labels<'a>( - labels: &'a [Option], + entity_path: &'a EntityPath, half_sizes: &'a [HalfSizes2D], - centers: impl Iterator + 'a, - instance_path_hashes: &'a [InstancePathHash], + centers: impl Iterator + 'a, + labels: &'a [Text], colors: &'a [egui::Color32], annotation_infos: &'a ResolvedAnnotationInfos, ) -> impl Iterator + 'a { - itertools::izip!( - annotation_infos.iter(), - half_sizes, - centers, - labels, - colors, - instance_path_hashes, - ) - .filter_map( - move |(annotation_info, half_size, center, label, color, labeled_instance)| { - let label = annotation_info.label(label.as_ref().map(|l| l.as_str())); - let min = half_size.box_min(center); - let max = half_size.box_max(center); - label.map(|label| UiLabel { - text: label, - color: *color, - target: UiLabelTarget::Rect(egui::Rect::from_min_max( - egui::pos2(min.x, min.y), - egui::pos2(max.x, max.y), - )), - labeled_instance: *labeled_instance, - }) - }, - ) + let labels = clamped(labels, half_sizes.len()); + let centers = centers.chain(std::iter::repeat(&Position2D::ZERO)); + itertools::izip!(annotation_infos.iter(), half_sizes, centers, labels, colors) + .enumerate() + .filter_map( + move |(i, (annotation_info, half_size, center, label, color))| { + let label = annotation_info.label(Some(label.as_str())); + match (half_size, label) { + (half_size, Some(label)) => { + let min = half_size.box_min(*center); + let max = half_size.box_max(*center); + Some(UiLabel { + text: label, + color: *color, + target: UiLabelTarget::Rect(egui::Rect::from_min_max( + egui::pos2(min.x, min.y), + egui::pos2(max.x, max.y), + )), + labeled_instance: InstancePathHash::instance( + entity_path, + InstanceKey(i as _), + ), + }) + } + _ => None, + } + }, + ) } - fn process_data( + fn process_data<'a>( &mut self, line_builder: &mut LineDrawableBuilder<'_>, - query: &ViewQuery<'_>, - data: &Boxes2DComponentData<'_>, - ent_path: &EntityPath, + view_query: &ViewQuery<'_>, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, + data: impl Iterator>, ) { - let (annotation_infos, _) = process_annotation_and_keypoint_slices( - query.latest_at, - data.instance_keys, - data.keypoint_ids, - data.class_ids, - data.half_sizes.iter().map(|_| glam::Vec3::ZERO), - &ent_context.annotations, - ); - - let centers = || { - data.centers - .as_ref() - .map_or( - itertools::Either::Left(std::iter::repeat(&None).take(data.half_sizes.len())), - |data| itertools::Either::Right(data.iter()), - ) - .map(|center| center.unwrap_or(Position2D::ZERO)) - }; - - let radii = process_radius_slice(data.radii, data.half_sizes.len(), ent_path); - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - - if data.instance_keys.len() <= self.max_labels { - re_tracing::profile_scope!("labels"); + for data in data { + let num_instances = data.half_sizes.len(); + if num_instances == 0 { + continue; + } - // Max labels is small enough that we can afford iterating on the colors again. - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); + let (annotation_infos, _) = process_annotation_and_keypoint_slices( + view_query.latest_at, + num_instances, + data.half_sizes.iter().map(|_| glam::Vec3::ZERO), + data.keypoint_ids, + data.class_ids, + &ent_context.annotations, + ); - let instance_path_hashes_for_picking = { - re_tracing::profile_scope!("instance_hashes"); - data.instance_keys - .iter() - .copied() - .map(|instance_key| InstancePathHash::instance(ent_path, instance_key)) - .collect::>() - }; + let radii = process_radius_slice(entity_path, num_instances, data.radii); + let colors = + process_color_slice(entity_path, num_instances, &annotation_infos, data.colors); - if let Some(labels) = data.labels { + if num_instances <= self.max_labels { + let centers = clamped(data.centers, num_instances); self.data.ui_labels.extend(Self::process_labels( - labels, + entity_path, data.half_sizes, - centers(), - &instance_path_hashes_for_picking, + centers, + data.labels, &colors, &annotation_infos, )); } - } - let mut line_batch = line_builder - .batch("boxes2d") - .depth_offset(ent_context.depth_offset) - .world_from_obj(ent_context.world_from_entity) - .outline_mask_ids(ent_context.highlight.overall) - .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); - - let mut bounding_box = macaw::BoundingBox::nothing(); - - for (instance_key, half_size, center, radius, color) in itertools::izip!( - data.instance_keys, - data.half_sizes, - centers(), - radii, - colors - ) { - let instance_hash = re_entity_db::InstancePathHash::instance(ent_path, *instance_key); - - let min = half_size.box_min(center); - let max = half_size.box_max(center); - bounding_box.extend(min.extend(0.0)); - bounding_box.extend(max.extend(0.0)); - - let rectangle = line_batch - .add_rectangle_outline_2d( - min, - glam::vec2(half_size.width(), 0.0), - glam::vec2(0.0, half_size.height()), - ) - .color(color) - .radius(radius) - .picking_instance_id(picking_id_from_instance_key(*instance_key)); - if let Some(outline_mask_ids) = ent_context - .highlight - .instances - .get(&instance_hash.instance_key) + let mut line_batch = line_builder + .batch("boxes2d") + .depth_offset(ent_context.depth_offset) + .world_from_obj(ent_context.world_from_entity) + .outline_mask_ids(ent_context.highlight.overall) + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); + + let mut bounding_box = macaw::BoundingBox::nothing(); + + let centers = + clamped(data.centers, num_instances).chain(std::iter::repeat(&Position2D::ZERO)); + for (i, (half_size, center, radius, color)) in + itertools::izip!(data.half_sizes, centers, radii, colors).enumerate() { - rectangle.outline_mask_ids(*outline_mask_ids); + let min = half_size.box_min(*center); + let max = half_size.box_max(*center); + bounding_box.extend(min.extend(0.0)); + bounding_box.extend(max.extend(0.0)); + + let rectangle = line_batch + .add_rectangle_outline_2d( + min, + glam::vec2(half_size.width(), 0.0), + glam::vec2(0.0, half_size.height()), + ) + .color(color) + .radius(radius) + .picking_instance_id(PickingLayerInstanceId(i as _)); + if let Some(outline_mask_ids) = + ent_context.highlight.instances.get(&InstanceKey(i as _)) + { + rectangle.outline_mask_ids(*outline_mask_ids); + } } - } - self.data - .add_bounding_box(ent_path.hash(), bounding_box, ent_context.world_from_entity); + self.data.add_bounding_box( + entity_path.hash(), + bounding_box, + ent_context.world_from_entity, + ); + } } } // --- struct Boxes2DComponentData<'a> { - pub instance_keys: &'a [InstanceKey], - pub half_sizes: &'a [HalfSizes2D], - pub centers: Option<&'a [Option]>, - pub colors: Option<&'a [Option]>, - pub radii: Option<&'a [Option]>, - pub labels: Option<&'a [Option]>, - pub keypoint_ids: Option<&'a [Option]>, - pub class_ids: Option<&'a [Option]>, + // Point of views + half_sizes: &'a [HalfSizes2D], + + // Clamped to edge + centers: &'a [Position2D], + colors: &'a [Color], + radii: &'a [Radius], + labels: &'a [Text], + keypoint_ids: &'a [KeypointId], + class_ids: &'a [ClassId], } impl IdentifiedViewSystem for Boxes2DVisualizer { @@ -211,66 +202,88 @@ impl VisualizerSystem for Boxes2DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let num_boxes = super::entity_iterator::count_instances_in_archetype_views::< - Boxes2DVisualizer, - Boxes2D, - 9, - >(ctx, query); - - if num_boxes == 0 { - return Ok(Vec::new()); - } - let mut line_builder = LineDrawableBuilder::new(ctx.render_ctx); line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES); - // Each box consists of 4 independent lines of 2 vertices each. - line_builder.reserve_strips(num_boxes * 4)?; - line_builder.reserve_vertices(num_boxes * 4 * 2)?; - - super::entity_iterator::process_archetype_pov1_comp6::< - Boxes2DVisualizer, - Boxes2D, - HalfSizes2D, - Position2D, - Color, - Radius, - Text, - re_types::components::KeypointId, - re_types::components::ClassId, - _, - >( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |_ctx, - ent_path, - _ent_props, - ent_context, - (_time, _row_id), - instance_keys, - half_sizes, - centers, - colors, - radii, - labels, - keypoint_ids, - class_ids| { - let data = Boxes2DComponentData { - instance_keys, - half_sizes, - centers, - colors, - radii, - labels, - keypoint_ids, - class_ids, + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let half_sizes = match results.get_dense::(resolver) { + Some(vectors) => vectors?, + _ => return Ok(()), }; - self.process_data(&mut line_builder, query, &data, ent_path, ent_context); + + let num_boxes = half_sizes + .range_indexed() + .map(|(_, vectors)| vectors.len()) + .sum::(); + if num_boxes == 0 { + return Ok(()); + } + + // Each box consists of 4 independent lines of 2 vertices each. + line_builder.reserve_strips(num_boxes * 4)?; + line_builder.reserve_vertices(num_boxes * 4 * 2)?; + + let centers = results.get_or_empty_dense(resolver)?; + let colors = results.get_or_empty_dense(resolver)?; + let radii = results.get_or_empty_dense(resolver)?; + let labels = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + let keypoint_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x6( + half_sizes.range_indexed(), + centers.range_indexed(), + colors.range_indexed(), + radii.range_indexed(), + labels.range_indexed(), + class_ids.range_indexed(), + keypoint_ids.range_indexed(), + ) + .map( + |( + _index, + half_sizes, + centers, + colors, + radii, + labels, + class_ids, + keypoint_ids, + )| { + Boxes2DComponentData { + half_sizes, + centers: centers.unwrap_or_default(), + colors: colors.unwrap_or_default(), + radii: radii.unwrap_or_default(), + labels: labels.unwrap_or_default(), + class_ids: class_ids.unwrap_or_default(), + keypoint_ids: keypoint_ids.unwrap_or_default(), + } + }, + ); + + self.process_data( + &mut line_builder, + view_query, + entity_path, + spatial_ctx, + data, + ); + Ok(()) }, )?; diff --git a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs index 1a5928331216..9df41ce52207 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs @@ -1,5 +1,6 @@ -use re_entity_db::EntityPath; -use re_renderer::LineDrawableBuilder; +use re_entity_db::{EntityPath, InstancePathHash}; +use re_query_cache2::range_zip_1x7; +use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes3D, components::{ @@ -7,9 +8,9 @@ use re_types::{ }, }; use re_viewer_context::{ - ApplicableEntities, IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, - ViewQuery, ViewerContext, VisualizableEntities, VisualizableFilterContext, VisualizerQueryInfo, - VisualizerSystem, + ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, + SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewerContext, + VisualizableEntities, VisualizableFilterContext, VisualizerQueryInfo, VisualizerSystem, }; use crate::{ @@ -19,11 +20,13 @@ use crate::{ }; use super::{ - filter_visualizable_3d_entities, picking_id_from_instance_key, - process_annotation_and_keypoint_slices, process_color_slice, process_label_slice, - process_radius_slice, SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, + entity_iterator::clamped, filter_visualizable_3d_entities, + process_annotation_and_keypoint_slices, process_color_slice, process_radius_slice, + SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, }; +// --- + pub struct Boxes3DVisualizer(SpatialViewVisualizerData); impl Default for Boxes3DVisualizer { @@ -34,118 +37,136 @@ impl Default for Boxes3DVisualizer { } } +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Boxes3DVisualizer { - fn process_data( + fn process_labels<'a>( + entity_path: &'a EntityPath, + half_sizes: &'a [HalfSizes3D], + centers: impl Iterator + 'a, + labels: &'a [Text], + colors: &'a [egui::Color32], + annotation_infos: &'a ResolvedAnnotationInfos, + world_from_entity: glam::Affine3A, + ) -> impl Iterator + 'a { + let labels = clamped(labels, half_sizes.len()); + let centers = centers.chain(std::iter::repeat(&Position3D::ZERO)); + itertools::izip!(annotation_infos.iter(), centers, labels, colors) + .enumerate() + .filter_map(move |(i, (annotation_info, center, label, color))| { + let label = annotation_info.label(Some(label.as_str())); + label.map(|label| UiLabel { + text: label, + color: *color, + target: UiLabelTarget::Position3D( + world_from_entity.transform_point3(center.0.into()), + ), + labeled_instance: InstancePathHash::instance(entity_path, InstanceKey(i as _)), + }) + }) + } + + fn process_data<'a>( &mut self, line_builder: &mut LineDrawableBuilder<'_>, query: &ViewQuery<'_>, - data: &Boxes3DComponentData<'_>, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, + data: impl Iterator>, ) { - let (annotation_infos, _) = process_annotation_and_keypoint_slices( - query.latest_at, - data.instance_keys, - data.keypoint_ids, - data.class_ids, - data.half_sizes.iter().map(|_| glam::Vec3::ZERO), - &ent_context.annotations, - ); - - let centers = || { - data.centers - .as_ref() - .map_or( - itertools::Either::Left(std::iter::repeat(&None).take(data.half_sizes.len())), - |data| itertools::Either::Right(data.iter()), - ) - .map(|center| center.unwrap_or(Position3D::ZERO)) - }; - let rotations = || { - data.rotations - .as_ref() - .map_or( - itertools::Either::Left(std::iter::repeat(&None).take(data.half_sizes.len())), - |data| itertools::Either::Right(data.iter()), - ) - .map(|center| center.clone().unwrap_or(Rotation3D::IDENTITY)) - }; - - let radii = process_radius_slice(data.radii, data.half_sizes.len(), ent_path); - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - let labels = process_label_slice(data.labels, data.half_sizes.len(), &annotation_infos); - - let mut line_batch = line_builder - .batch("boxes3d") - .depth_offset(ent_context.depth_offset) - .world_from_obj(ent_context.world_from_entity) - .outline_mask_ids(ent_context.highlight.overall) - .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); - - let mut bounding_box = macaw::BoundingBox::nothing(); - - for (instance_key, half_size, center, rotation, radius, color, label) in itertools::izip!( - data.instance_keys, - data.half_sizes, - centers(), - rotations(), - radii, - colors, - labels, - ) { - let instance_hash = re_entity_db::InstancePathHash::instance(ent_path, *instance_key); - - bounding_box.extend(half_size.box_min(center)); - bounding_box.extend(half_size.box_max(center)); - - let center = center.into(); - - let box3d = line_batch - .add_box_outline_from_transform(glam::Affine3A::from_scale_rotation_translation( - glam::Vec3::from(*half_size) * 2.0, - rotation.into(), - center, - )) - .color(color) - .radius(radius) - .picking_instance_id(picking_id_from_instance_key(*instance_key)); - if let Some(outline_mask_ids) = ent_context - .highlight - .instances - .get(&instance_hash.instance_key) - { - box3d.outline_mask_ids(*outline_mask_ids); + for data in data { + let num_instances = data.half_sizes.len(); + if num_instances == 0 { + continue; } - if let Some(text) = label { - self.0.ui_labels.push(UiLabel { - text, - color, - target: UiLabelTarget::Position3D( - ent_context.world_from_entity.transform_point3(center), - ), - labeled_instance: instance_hash, - }); + let (annotation_infos, _) = process_annotation_and_keypoint_slices( + query.latest_at, + num_instances, + data.half_sizes.iter().map(|_| glam::Vec3::ZERO), + data.keypoint_ids, + data.class_ids, + &ent_context.annotations, + ); + + let radii = process_radius_slice(entity_path, num_instances, data.radii); + let colors = + process_color_slice(entity_path, num_instances, &annotation_infos, data.colors); + + let centers = clamped(data.centers, num_instances); + self.0.ui_labels.extend(Self::process_labels( + entity_path, + data.half_sizes, + centers, + data.labels, + &colors, + &annotation_infos, + ent_context.world_from_entity, + )); + + let mut line_batch = line_builder + .batch("boxes3d") + .depth_offset(ent_context.depth_offset) + .world_from_obj(ent_context.world_from_entity) + .outline_mask_ids(ent_context.highlight.overall) + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); + + let mut bounding_box = macaw::BoundingBox::nothing(); + + let centers = + clamped(data.centers, num_instances).chain(std::iter::repeat(&Position3D::ZERO)); + let rotations = clamped(data.rotations, num_instances) + .chain(std::iter::repeat(&Rotation3D::IDENTITY)); + for (i, (half_size, ¢er, rotation, radius, color)) in + itertools::izip!(data.half_sizes, centers, rotations, radii, colors).enumerate() + { + bounding_box.extend(half_size.box_min(center)); + bounding_box.extend(half_size.box_max(center)); + + let center = center.into(); + + let box3d = line_batch + .add_box_outline_from_transform( + glam::Affine3A::from_scale_rotation_translation( + glam::Vec3::from(*half_size) * 2.0, + rotation.0.into(), + center, + ), + ) + .color(color) + .radius(radius) + .picking_instance_id(PickingLayerInstanceId(i as _)); + + if let Some(outline_mask_ids) = + ent_context.highlight.instances.get(&InstanceKey(i as _)) + { + box3d.outline_mask_ids(*outline_mask_ids); + } } - } - self.0 - .add_bounding_box(ent_path.hash(), bounding_box, ent_context.world_from_entity); + self.0.add_bounding_box( + entity_path.hash(), + bounding_box, + ent_context.world_from_entity, + ); + } } } // --- struct Boxes3DComponentData<'a> { - pub instance_keys: &'a [InstanceKey], - pub half_sizes: &'a [HalfSizes3D], - pub centers: Option<&'a [Option]>, - pub rotations: Option<&'a [Option]>, - pub colors: Option<&'a [Option]>, - pub radii: Option<&'a [Option]>, - pub labels: Option<&'a [Option]>, - pub keypoint_ids: Option<&'a [Option]>, - pub class_ids: Option<&'a [Option]>, + // Point of views + half_sizes: &'a [HalfSizes3D], + + // Clamped to edge + centers: &'a [Position3D], + rotations: &'a [Rotation3D], + colors: &'a [Color], + radii: &'a [Radius], + labels: &'a [Text], + keypoint_ids: &'a [KeypointId], + class_ids: &'a [ClassId], } impl IdentifiedViewSystem for Boxes3DVisualizer { @@ -171,69 +192,92 @@ impl VisualizerSystem for Boxes3DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let num_boxes = super::entity_iterator::count_instances_in_archetype_views::< - Boxes3DVisualizer, - Boxes3D, - 9, - >(ctx, query); - - if num_boxes == 0 { - return Ok(Vec::new()); - } - let mut line_builder = LineDrawableBuilder::new(ctx.render_ctx); line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES); - // Each box consists of 12 independent lines with 2 vertices each. - line_builder.reserve_strips(num_boxes * 12)?; - line_builder.reserve_vertices(num_boxes * 12 * 2)?; - - super::entity_iterator::process_archetype_pov1_comp7::< - Boxes3DVisualizer, - Boxes3D, - HalfSizes3D, - Position3D, - Rotation3D, - Color, - Radius, - Text, - re_types::components::KeypointId, - re_types::components::ClassId, - _, - >( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |_ctx, - ent_path, - _ent_props, - ent_context, - (_time, _row_id), - instance_keys, - half_sizes, - centers, - rotations, - colors, - radii, - labels, - keypoint_ids, - class_ids| { - let data = Boxes3DComponentData { - instance_keys, - half_sizes, - centers, - rotations, - colors, - radii, - labels, - keypoint_ids, - class_ids, + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let half_sizes = match results.get_dense::(resolver) { + Some(vectors) => vectors?, + _ => return Ok(()), }; - self.process_data(&mut line_builder, query, &data, ent_path, ent_context); + + let num_boxes = half_sizes + .range_indexed() + .map(|(_, vectors)| vectors.len()) + .sum::(); + if num_boxes == 0 { + return Ok(()); + } + + // Each box consists of 12 independent lines with 2 vertices each. + line_builder.reserve_strips(num_boxes * 12)?; + line_builder.reserve_vertices(num_boxes * 12 * 2)?; + + let centers = results.get_or_empty_dense(resolver)?; + let rotations = results.get_or_empty_dense(resolver)?; + let colors = results.get_or_empty_dense(resolver)?; + let radii = results.get_or_empty_dense(resolver)?; + let labels = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + let keypoint_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x7( + half_sizes.range_indexed(), + centers.range_indexed(), + rotations.range_indexed(), + colors.range_indexed(), + radii.range_indexed(), + labels.range_indexed(), + class_ids.range_indexed(), + keypoint_ids.range_indexed(), + ) + .map( + |( + _index, + half_sizes, + centers, + rotations, + colors, + radii, + labels, + class_ids, + keypoint_ids, + )| { + Boxes3DComponentData { + half_sizes, + centers: centers.unwrap_or_default(), + rotations: rotations.unwrap_or_default(), + colors: colors.unwrap_or_default(), + radii: radii.unwrap_or_default(), + labels: labels.unwrap_or_default(), + class_ids: class_ids.unwrap_or_default(), + keypoint_ids: keypoint_ids.unwrap_or_default(), + } + }, + ); + + self.process_data( + &mut line_builder, + view_query, + entity_path, + spatial_ctx, + data, + ); + Ok(()) }, )?; diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 7d89f9f6a2be..c9eec8176a6c 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -1,9 +1,12 @@ -use re_entity_db::EntityProperties; -use re_log_types::{EntityPath, RowId, TimeInt}; -use re_query::{query_archetype_with_history, ArchetypeView, QueryError}; +use itertools::Either; +use re_data_store::{LatestAtQuery, RangeQuery}; +use re_entity_db::{EntityDb, EntityProperties}; +use re_log_types::{EntityPath, TimeInt, Timeline}; +use re_query::{ArchetypeView, QueryError}; +use re_query_cache2::{CachedResults, ExtraQueryHistory}; use re_renderer::DepthOffset; use re_space_view::query_visual_history; -use re_types::{components::InstanceKey, Archetype, Component}; +use re_types::Archetype; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewClass, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewerContext, @@ -17,6 +20,150 @@ use crate::{ SpatialSpaceView3D, }; +// --- + +/// Clamp the latest value in `values` in order to reach a length of `clamped_len`. +/// +/// Returns an empty iterator if values is empty. +#[inline] +pub fn clamped(values: &[T], clamped_len: usize) -> impl Iterator { + let Some(last) = values.last() else { + return Either::Left(std::iter::empty()); + }; + + Either::Right( + values + .iter() + .chain(std::iter::repeat(last)) + .take(clamped_len), + ) +} + +pub fn query_archetype_with_history( + entity_db: &EntityDb, + timeline: &Timeline, + time: &TimeInt, + history: &ExtraQueryHistory, + entity_path: &EntityPath, +) -> CachedResults { + let visible_history = match timeline.typ() { + re_log_types::TimeType::Time => history.nanos, + re_log_types::TimeType::Sequence => history.sequences, + }; + + let time_range = visible_history.time_range(*time); + + let store = entity_db.store(); + let caches = entity_db.query_caches2(); + + if !history.enabled || time_range.min() == time_range.max() { + let latest_query = LatestAtQuery::new(*timeline, time_range.min()); + let results = caches.latest_at( + store, + &latest_query, + entity_path, + A::all_components().iter().copied(), + ); + (latest_query, results).into() + } else { + let range_query = RangeQuery::new(*timeline, time_range); + let results = caches.range( + store, + &range_query, + entity_path, + A::all_components().iter().copied(), + ); + (range_query, results).into() + } +} + +/// Iterates through all entity views for a given archetype. +/// +/// The callback passed in gets passed along an [`SpatialSceneEntityContext`] which contains +/// various useful information about an entity in the context of the current scene. +pub fn process_archetype( + ctx: &ViewerContext<'_>, + query: &ViewQuery<'_>, + view_ctx: &ViewContextCollection, + default_depth_offset: DepthOffset, + mut fun: F, +) -> Result<(), SpaceViewSystemExecutionError> +where + A: Archetype, + F: FnMut( + &ViewerContext<'_>, + &EntityPath, + &EntityProperties, + &SpatialSceneEntityContext<'_>, + &CachedResults, + ) -> Result<(), SpaceViewSystemExecutionError>, +{ + let transforms = view_ctx.get::()?; + let depth_offsets = view_ctx.get::()?; + let annotations = view_ctx.get::()?; + let counter = view_ctx.get::()?; + + for data_result in query.iter_visible_data_results(ctx, System::identifier()) { + // The transform that considers pinholes only makes sense if this is a 3D space-view + let world_from_entity = + if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() { + transforms.reference_from_entity(&data_result.entity_path) + } else { + transforms.reference_from_entity_ignoring_pinhole( + &data_result.entity_path, + ctx.recording(), + &query.latest_at_query(), + ) + }; + + let Some(world_from_entity) = world_from_entity else { + continue; + }; + let entity_context = SpatialSceneEntityContext { + world_from_entity, + depth_offset: *depth_offsets + .per_entity + .get(&data_result.entity_path.hash()) + .unwrap_or(&default_depth_offset), + annotations: annotations.0.find(&data_result.entity_path), + highlight: query + .highlights + .entity_outline_mask(data_result.entity_path.hash()), + space_view_class_identifier: view_ctx.space_view_class_identifier(), + }; + + let extra_history = query_visual_history(ctx, data_result); + + let results = query_archetype_with_history::( + ctx.recording(), + &query.timeline, + &query.latest_at, + &extra_history, + &data_result.entity_path, + ); + + // NOTE: We used to compute the number of primitives across the entire scene here, but that + // seems a bit excessive now that we have promises, as that would require resolving all + // promises across all entities right here right now. + // Also the count doesn't seem to be used for much anyhow. + // + // We'll see how things evolve. + _ = counter; + + fun( + ctx, + &data_result.entity_path, + data_result.accumulated_properties(), + &entity_context, + &results, + )?; + } + + Ok(()) +} + +// --- + /// Iterates through all entity views for a given archetype. /// /// The callback passed in gets passed a long an [`SpatialSceneEntityContext`] which contains @@ -73,8 +220,14 @@ where }; let extra_history = query_visual_history(ctx, data_result); + // TODO(cmc): We need to use the type defined in the old crate interchangeably with the one + // defined in the new crate. They are exactly the same. + // + // This will be fixed in the next PR + #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + let extra_history = unsafe { std::mem::transmute(extra_history) }; - let result = query_archetype_with_history::( + let result = re_query::query_archetype_with_history::( ctx.recording_store(), &query.timeline, &query.latest_at, @@ -111,181 +264,3 @@ where Ok(()) } - -// --- - -use re_query_cache::external::{paste::paste, seq_macro::seq}; - -macro_rules! impl_process_archetype { - (for N=$N:expr, M=$M:expr => povs=[$($pov:ident)+] comps=[$($comp:ident)*]) => { paste! { - #[doc = "Cached implementation of [`process_archetype_views`] for `" $N "` point-of-view components"] - #[doc = "and `" $M "` optional components."] - #[allow(non_snake_case, dead_code)] - pub fn []<'a, S, A, $($pov,)+ $($comp,)* F>( - ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, - view_ctx: &ViewContextCollection, - default_depth_offset: DepthOffset, - mut f: F, - ) -> Result<(), SpaceViewSystemExecutionError> - where - S: IdentifiedViewSystem, - A: Archetype + 'a, - $($pov: Component,)+ - $($comp: Component,)* - F: FnMut( - &ViewerContext<'_>, - &EntityPath, - &EntityProperties, - &SpatialSceneEntityContext<'_>, - (TimeInt, RowId), - &[InstanceKey], - $(&[$pov],)* - $(Option<&[Option<$comp>]>,)* - ) -> Result<(), SpaceViewSystemExecutionError>, - { - // NOTE: not `profile_function!` because we want them merged together. - re_tracing::profile_scope!( - "process_archetype", - format!("arch={} pov={} comp={}", A::name(), $N, $M) - ); - - let transforms = view_ctx.get::()?; - let depth_offsets = view_ctx.get::()?; - let annotations = view_ctx.get::()?; - let counter = view_ctx.get::()?; - - for data_result in query.iter_visible_data_results(ctx, S::identifier()) { - // The transform that considers pinholes only makes sense if this is a 3D space-view - let world_from_entity = if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() { - transforms.reference_from_entity(&data_result.entity_path) - } else { - transforms.reference_from_entity_ignoring_pinhole( - &data_result.entity_path, - ctx.recording(), - &query.latest_at_query(), - ) - }; - - let Some(world_from_entity) = world_from_entity else { - continue; - }; - let entity_context = SpatialSceneEntityContext { - world_from_entity, - depth_offset: *depth_offsets - .per_entity - .get(&data_result.entity_path.hash()) - .unwrap_or(&default_depth_offset), - annotations: annotations.0.find(&data_result.entity_path), - highlight: query - .highlights - .entity_outline_mask(data_result.entity_path.hash()), - space_view_class_identifier: view_ctx.space_view_class_identifier(), - }; - - let extra_history = query_visual_history(ctx, data_result); - - match ctx.recording().query_caches().[]::( - ctx.recording_store(), - &query.timeline, - &query.latest_at, - &extra_history, - &data_result.entity_path, - |(t, keys, $($pov,)+ $($comp,)*)| { - counter - .num_primitives - .fetch_add(keys.len(), std::sync::atomic::Ordering::Relaxed); - - if let Err(err) = f( - ctx, - &data_result.entity_path, - data_result.accumulated_properties(), - &entity_context, - t, - keys, - $($pov,)+ - $($comp.as_deref(),)* - ) { - re_log::error_once!( - "Unexpected error querying {:?}: {err}", - &data_result.entity_path - ); - }; - } - ) { - Ok(_) | Err(QueryError::PrimaryNotFound(_)) => {} - Err(err) => { - re_log::error_once!( - "Unexpected error querying {:?}: {err}", - &data_result.entity_path - ); - } - } - } - - Ok(()) - } } - }; - - // TODO(cmc): Supporting N>1 generically is quite painful due to limitations in declarative macros, - // not that we care at the moment. - (for N=1, M=$M:expr) => { - seq!(COMP in 1..=$M { - impl_process_archetype!(for N=1, M=$M => povs=[R1] comps=[#(C~COMP)*]); - }); - }; -} - -seq!(NUM_COMP in 0..10 { - impl_process_archetype!(for N=1, M=NUM_COMP); -}); - -/// Count the number of primary instances for a given archetype query that should be displayed. -/// -/// Returned value might be conservative and some of the instances may not be displayable after all, -/// e.g. due to invalid transformation etc. -pub fn count_instances_in_archetype_views< - System: IdentifiedViewSystem, - A: Archetype, - const N: usize, ->( - ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, -) -> usize { - assert_eq!(A::all_components().len(), N); - - // TODO(andreas): Use cached code path for this. - // This is right now a bit harder to do and requires knowing all queried components. - // The only thing we really want to pass here are the POV components. - - re_tracing::profile_function!(); - - let mut num_instances = 0; - - for data_result in query.iter_visible_data_results(ctx, System::identifier()) { - let extra_history = query_visual_history(ctx, data_result); - - match query_archetype_with_history::( - ctx.recording_store(), - &query.timeline, - &query.latest_at, - &extra_history, - &data_result.entity_path, - ) - .map(|arch_views| { - for arch_view in arch_views { - num_instances += arch_view.num_instances(); - } - }) { - Ok(_) | Err(QueryError::PrimaryNotFound(_)) => {} - Err(err) => { - re_log::error_once!( - "Unexpected error querying {:?}: {err}", - &data_result.entity_path - ); - } - } - } - - num_instances -} diff --git a/crates/re_space_view_spatial/src/visualizers/lines2d.rs b/crates/re_space_view_spatial/src/visualizers/lines2d.rs index 604fcc4fc99f..bca1670ef291 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines2d.rs @@ -1,5 +1,6 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_renderer::LineDrawableBuilder; +use re_query_cache2::range_zip_1x5; +use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::LineStrips2D, components::{ClassId, Color, InstanceKey, KeypointId, LineStrip2D, Radius, Text}, @@ -17,10 +18,13 @@ use crate::{ }; use super::{ - filter_visualizable_2d_entities, process_annotation_and_keypoint_slices, process_color_slice, - process_radius_slice, SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, + entity_iterator::clamped, filter_visualizable_2d_entities, + process_annotation_and_keypoint_slices, process_color_slice, process_radius_slice, + SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, }; +// --- + pub struct Lines2DVisualizer { /// If the number of arrows in the batch is > max_labels, don't render point labels. pub max_labels: usize, @@ -36,24 +40,21 @@ impl Default for Lines2DVisualizer { } } +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Lines2DVisualizer { fn process_labels<'a>( + entity_path: &'a EntityPath, strips: &'a [LineStrip2D], - labels: &'a [Option], - instance_path_hashes: &'a [InstancePathHash], + labels: &'a [Text], colors: &'a [egui::Color32], annotation_infos: &'a ResolvedAnnotationInfos, ) -> impl Iterator + 'a { - itertools::izip!( - annotation_infos.iter(), - strips, - labels, - colors, - instance_path_hashes, - ) - .filter_map( - move |(annotation_info, strip, label, color, labeled_instance)| { - let label = annotation_info.label(label.as_ref().map(|l| l.as_str())); + let labels = clamped(labels, strips.len()); + itertools::izip!(annotation_infos.iter(), strips, labels, colors,) + .enumerate() + .filter_map(move |(i, (annotation_info, strip, label, color))| { + let label = annotation_info.label(Some(label.as_str())); match (strip, label) { (strip, Some(label)) => { let midpoint = strip @@ -68,107 +69,103 @@ impl Lines2DVisualizer { text: label, color: *color, target: UiLabelTarget::Point2D(egui::pos2(midpoint.x, midpoint.y)), - labeled_instance: *labeled_instance, + labeled_instance: InstancePathHash::instance( + entity_path, + InstanceKey(i as _), + ), }) } _ => None, } - }, - ) + }) } - fn process_data( + fn process_data<'a>( &mut self, line_builder: &mut LineDrawableBuilder<'_>, query: &ViewQuery<'_>, - data: &Lines2DComponentData<'_>, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - ) -> Result<(), SpaceViewSystemExecutionError> { - let (annotation_infos, _) = process_annotation_and_keypoint_slices( - query.latest_at, - data.instance_keys, - data.keypoint_ids, - data.class_ids, - data.strips.iter().map(|_| glam::Vec3::ZERO), - &ent_context.annotations, - ); - - let radii = process_radius_slice(data.radii, data.strips.len(), ent_path); - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - - if data.instance_keys.len() <= self.max_labels { - re_tracing::profile_scope!("labels"); - - // Max labels is small enough that we can afford iterating on the colors again. - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - - let instance_path_hashes_for_picking = { - re_tracing::profile_scope!("instance_hashes"); - data.instance_keys - .iter() - .copied() - .map(|instance_key| InstancePathHash::instance(ent_path, instance_key)) - .collect::>() - }; - - if let Some(labels) = data.labels { + data: impl Iterator>, + ) { + for data in data { + let num_instances = data.strips.len(); + if num_instances == 0 { + continue; + } + + let (annotation_infos, _) = process_annotation_and_keypoint_slices( + query.latest_at, + num_instances, + data.strips.iter().map(|_| glam::Vec3::ZERO), + data.keypoint_ids, + data.class_ids, + &ent_context.annotations, + ); + + let radii = process_radius_slice(entity_path, num_instances, data.radii); + let colors = + process_color_slice(entity_path, num_instances, &annotation_infos, data.colors); + + if num_instances <= self.max_labels { self.data.ui_labels.extend(Self::process_labels( + entity_path, data.strips, - labels, - &instance_path_hashes_for_picking, + data.labels, &colors, &annotation_infos, )); } - } - line_builder.reserve_strips(data.strips.len())?; - line_builder.reserve_vertices(data.strips.iter().map(|s| s.0.len()).sum())?; - - let mut line_batch = line_builder - .batch(ent_path.to_string()) - .depth_offset(ent_context.depth_offset) - .world_from_obj(ent_context.world_from_entity) - .outline_mask_ids(ent_context.highlight.overall) - .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); - - let mut bounding_box = macaw::BoundingBox::nothing(); - for (instance_key, strip, radius, color) in - itertools::izip!(data.instance_keys, data.strips, radii, colors) - { - let lines = line_batch - .add_strip_2d(strip.0.iter().copied().map(Into::into)) - .color(color) - .radius(radius) - .picking_instance_id(re_renderer::PickingLayerInstanceId(instance_key.0)); - - if let Some(outline_mask_ids) = ent_context.highlight.instances.get(instance_key) { - lines.outline_mask_ids(*outline_mask_ids); - } + let mut line_batch = line_builder + .batch(entity_path.to_string()) + .depth_offset(ent_context.depth_offset) + .world_from_obj(ent_context.world_from_entity) + .outline_mask_ids(ent_context.highlight.overall) + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); - for p in &strip.0 { - bounding_box.extend(glam::vec3(p.x(), p.y(), 0.0)); - } - } + let mut bounding_box = macaw::BoundingBox::nothing(); + for (i, (strip, radius, color)) in + itertools::izip!(data.strips, radii, colors).enumerate() + { + let lines = line_batch + .add_strip_2d(strip.0.iter().copied().map(Into::into)) + .color(color) + .radius(radius) + .picking_instance_id(PickingLayerInstanceId(i as _)); - self.data - .add_bounding_box(ent_path.hash(), bounding_box, ent_context.world_from_entity); + if let Some(outline_mask_ids) = + ent_context.highlight.instances.get(&InstanceKey(i as _)) + { + lines.outline_mask_ids(*outline_mask_ids); + } + + for p in &strip.0 { + bounding_box.extend(glam::vec3(p.x(), p.y(), 0.0)); + } + } - Ok(()) + self.data.add_bounding_box( + entity_path.hash(), + bounding_box, + ent_context.world_from_entity, + ); + } } } // --- struct Lines2DComponentData<'a> { - pub instance_keys: &'a [InstanceKey], - pub strips: &'a [LineStrip2D], - pub colors: Option<&'a [Option]>, - pub radii: Option<&'a [Option]>, - pub labels: Option<&'a [Option]>, - pub keypoint_ids: Option<&'a [Option]>, - pub class_ids: Option<&'a [Option]>, + // Point of views + strips: &'a [LineStrip2D], + + // Clamped to edge + colors: &'a [Color], + radii: &'a [Radius], + labels: &'a [Text], + keypoint_ids: &'a [KeypointId], + class_ids: &'a [ClassId], } impl IdentifiedViewSystem for Lines2DVisualizer { @@ -194,51 +191,80 @@ impl VisualizerSystem for Lines2DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - // Counting all lines (strips and vertices) ahead of time is a bit expensive since we need to do a full query for this. - // We choose a semi-dynamic approach here, where we reserve on every new line batch. let mut line_builder = re_renderer::LineDrawableBuilder::new(ctx.render_ctx); line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES); - super::entity_iterator::process_archetype_pov1_comp5::< - Lines2DVisualizer, - LineStrips2D, - LineStrip2D, - Color, - Radius, - Text, - KeypointId, - ClassId, - _, - >( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |_ctx, - ent_path, - _ent_props, - ent_context, - (_time, _row_id), - instance_keys, - strips, - colors, - radii, - labels, - keypoint_ids, - class_ids| { - let data = Lines2DComponentData { - instance_keys, - strips, - colors, - radii, - labels, - keypoint_ids, - class_ids, + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let strips = match results.get_dense::(resolver) { + Some(strips) => strips?, + _ => return Ok(()), }; - self.process_data(&mut line_builder, query, &data, ent_path, ent_context) + + let num_strips = strips + .range_indexed() + .map(|(_, strips)| strips.len()) + .sum::(); + if num_strips == 0 { + return Ok(()); + } + line_builder.reserve_strips(num_strips)?; + + let num_vertices = strips + .range_indexed() + .map(|(_, strips)| strips.iter().map(|strip| strip.0.len()).sum::()) + .sum::(); + line_builder.reserve_vertices(num_vertices)?; + + let colors = results.get_or_empty_dense(resolver)?; + let radii = results.get_or_empty_dense(resolver)?; + let labels = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + let keypoint_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x5( + strips.range_indexed(), + colors.range_indexed(), + radii.range_indexed(), + labels.range_indexed(), + class_ids.range_indexed(), + keypoint_ids.range_indexed(), + ) + .map( + |(_index, strips, colors, radii, labels, class_ids, keypoint_ids)| { + Lines2DComponentData { + strips, + colors: colors.unwrap_or_default(), + radii: radii.unwrap_or_default(), + labels: labels.unwrap_or_default(), + class_ids: class_ids.unwrap_or_default(), + keypoint_ids: keypoint_ids.unwrap_or_default(), + } + }, + ); + + self.process_data( + &mut line_builder, + view_query, + entity_path, + spatial_ctx, + data, + ); + + Ok(()) }, )?; diff --git a/crates/re_space_view_spatial/src/visualizers/lines3d.rs b/crates/re_space_view_spatial/src/visualizers/lines3d.rs index e32520a3f761..442c38dd9724 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines3d.rs @@ -1,4 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_query_cache2::range_zip_1x5; use re_renderer::PickingLayerInstanceId; use re_types::{ archetypes::LineStrips3D, @@ -17,10 +18,13 @@ use crate::{ }; use super::{ - filter_visualizable_3d_entities, process_annotation_and_keypoint_slices, process_color_slice, - process_radius_slice, SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, + entity_iterator::clamped, filter_visualizable_3d_entities, + process_annotation_and_keypoint_slices, process_color_slice, process_radius_slice, + SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES, }; +// --- + pub struct Lines3DVisualizer { /// If the number of arrows in the batch is > max_labels, don't render point labels. pub max_labels: usize, @@ -36,25 +40,22 @@ impl Default for Lines3DVisualizer { } } +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Lines3DVisualizer { fn process_labels<'a>( + entity_path: &'a EntityPath, strips: &'a [LineStrip3D], - labels: &'a [Option], - instance_path_hashes: &'a [InstancePathHash], + labels: &'a [Text], colors: &'a [egui::Color32], annotation_infos: &'a ResolvedAnnotationInfos, world_from_obj: glam::Affine3A, ) -> impl Iterator + 'a { - itertools::izip!( - annotation_infos.iter(), - strips, - labels, - colors, - instance_path_hashes, - ) - .filter_map( - move |(annotation_info, strip, label, color, labeled_instance)| { - let label = annotation_info.label(label.as_ref().map(|l| l.as_str())); + let labels = clamped(labels, strips.len()); + itertools::izip!(annotation_infos.iter(), strips, labels, colors,) + .enumerate() + .filter_map(move |(i, (annotation_info, strip, label, color))| { + let label = annotation_info.label(Some(label.as_str())); match (strip, label) { (strip, Some(label)) => { let midpoint = strip @@ -71,109 +72,109 @@ impl Lines3DVisualizer { target: UiLabelTarget::Position3D( world_from_obj.transform_point3(midpoint), ), - labeled_instance: *labeled_instance, + labeled_instance: InstancePathHash::instance( + entity_path, + InstanceKey(i as _), + ), }) } _ => None, } - }, - ) + }) } - fn process_data( + fn process_data<'a>( &mut self, line_builder: &mut re_renderer::LineDrawableBuilder<'_>, query: &ViewQuery<'_>, - data: &Lines3DComponentData<'_>, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - ) -> Result<(), SpaceViewSystemExecutionError> { - let (annotation_infos, _) = process_annotation_and_keypoint_slices( - query.latest_at, - data.instance_keys, - data.keypoint_ids, - data.class_ids, - data.strips.iter().map(|_| glam::Vec3::ZERO), - &ent_context.annotations, - ); - - let radii = process_radius_slice(data.radii, data.strips.len(), ent_path); - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - - if data.instance_keys.len() <= self.max_labels { - re_tracing::profile_scope!("labels"); - - // Max labels is small enough that we can afford iterating on the colors again. - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - - let instance_path_hashes_for_picking = { - re_tracing::profile_scope!("instance_hashes"); - data.instance_keys - .iter() - .copied() - .map(|instance_key| InstancePathHash::instance(ent_path, instance_key)) - .collect::>() - }; - - if let Some(labels) = data.labels { + data: impl Iterator>, + ) { + for data in data { + let num_instances = data.strips.len(); + if num_instances == 0 { + continue; + } + + let (annotation_infos, _) = process_annotation_and_keypoint_slices( + query.latest_at, + num_instances, + data.strips.iter().map(|_| glam::Vec3::ZERO), + data.keypoint_ids, + data.class_ids, + &ent_context.annotations, + ); + + let radii = process_radius_slice(entity_path, num_instances, data.radii); + let colors = + process_color_slice(entity_path, num_instances, &annotation_infos, data.colors); + + if num_instances <= self.max_labels { self.data.ui_labels.extend(Self::process_labels( + entity_path, data.strips, - labels, - &instance_path_hashes_for_picking, + data.labels, &colors, &annotation_infos, ent_context.world_from_entity, )); } - } - line_builder.reserve_strips(data.strips.len())?; - line_builder.reserve_vertices(data.strips.iter().map(|s| s.0.len()).sum())?; - - let mut line_batch = line_builder - .batch(ent_path.to_string()) - .depth_offset(ent_context.depth_offset) - .world_from_obj(ent_context.world_from_entity) - .outline_mask_ids(ent_context.highlight.overall) - .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); - - let mut bounding_box = macaw::BoundingBox::nothing(); - - for (instance_key, strip, radius, color) in - itertools::izip!(data.instance_keys, data.strips, radii, colors) - { - let lines = line_batch - .add_strip(strip.0.iter().copied().map(Into::into)) - .color(color) - .radius(radius) - .picking_instance_id(PickingLayerInstanceId(instance_key.0)); - - if let Some(outline_mask_ids) = ent_context.highlight.instances.get(instance_key) { - lines.outline_mask_ids(*outline_mask_ids); - } + let mut line_batch = line_builder + .batch(entity_path.to_string()) + .depth_offset(ent_context.depth_offset) + .world_from_obj(ent_context.world_from_entity) + .outline_mask_ids(ent_context.highlight.overall) + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); - for p in &strip.0 { - bounding_box.extend((*p).into()); - } - } + let mut bounding_box = macaw::BoundingBox::nothing(); - self.data - .add_bounding_box(ent_path.hash(), bounding_box, ent_context.world_from_entity); + let mut num_rendered_strips = 0usize; + for (i, (strip, radius, color)) in + itertools::izip!(data.strips, radii, colors).enumerate() + { + let lines = line_batch + .add_strip(strip.0.iter().copied().map(Into::into)) + .color(color) + .radius(radius) + .picking_instance_id(PickingLayerInstanceId(i as _)); + + if let Some(outline_mask_ids) = + ent_context.highlight.instances.get(&InstanceKey(i as _)) + { + lines.outline_mask_ids(*outline_mask_ids); + } + + for p in &strip.0 { + bounding_box.extend((*p).into()); + } - Ok(()) + num_rendered_strips += 1; + } + debug_assert_eq!(data.strips.len(), num_rendered_strips, "the number of renderer strips after all post-processing is done should be equal to {} (got {num_rendered_strips} instead)", data.strips.len()); + + self.data.add_bounding_box( + entity_path.hash(), + bounding_box, + ent_context.world_from_entity, + ); + } } } // --- struct Lines3DComponentData<'a> { - pub instance_keys: &'a [InstanceKey], - pub strips: &'a [LineStrip3D], - pub colors: Option<&'a [Option]>, - pub radii: Option<&'a [Option]>, - pub labels: Option<&'a [Option]>, - pub keypoint_ids: Option<&'a [Option]>, - pub class_ids: Option<&'a [Option]>, + // Point of views + strips: &'a [LineStrip3D], + + // Clamped to edge + colors: &'a [Color], + radii: &'a [Radius], + labels: &'a [Text], + keypoint_ids: &'a [KeypointId], + class_ids: &'a [ClassId], } impl IdentifiedViewSystem for Lines3DVisualizer { @@ -199,51 +200,80 @@ impl VisualizerSystem for Lines3DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - // Counting all lines (strips and vertices) ahead of time is a bit expensive since we need to do a full query for this. - // We choose a semi-dynamic approach here, where we reserve on every new line batch. let mut line_builder = re_renderer::LineDrawableBuilder::new(ctx.render_ctx); line_builder.radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_LINE_OUTLINES); - super::entity_iterator::process_archetype_pov1_comp5::< - Lines3DVisualizer, - LineStrips3D, - LineStrip3D, - Color, - Radius, - Text, - KeypointId, - ClassId, - _, - >( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |_ctx, - ent_path, - _ent_props, - ent_context, - (_time, _row_id), - instance_keys, - strips, - colors, - radii, - labels, - keypoint_ids, - class_ids| { - let data = Lines3DComponentData { - instance_keys, - strips, - colors, - radii, - labels, - keypoint_ids, - class_ids, + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let strips = match results.get_dense::(resolver) { + Some(strips) => strips?, + _ => return Ok(()), }; - self.process_data(&mut line_builder, query, &data, ent_path, ent_context) + + let num_strips = strips + .range_indexed() + .map(|(_, strips)| strips.len()) + .sum::(); + if num_strips == 0 { + return Ok(()); + } + line_builder.reserve_strips(num_strips)?; + + let num_vertices = strips + .range_indexed() + .map(|(_, strips)| strips.iter().map(|strip| strip.0.len()).sum::()) + .sum::(); + line_builder.reserve_vertices(num_vertices)?; + + let colors = results.get_or_empty_dense(resolver)?; + let radii = results.get_or_empty_dense(resolver)?; + let labels = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + let keypoint_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x5( + strips.range_indexed(), + colors.range_indexed(), + radii.range_indexed(), + labels.range_indexed(), + class_ids.range_indexed(), + keypoint_ids.range_indexed(), + ) + .map( + |(_index, strips, colors, radii, labels, class_ids, keypoint_ids)| { + Lines3DComponentData { + strips, + colors: colors.unwrap_or_default(), + radii: radii.unwrap_or_default(), + labels: labels.unwrap_or_default(), + class_ids: class_ids.unwrap_or_default(), + keypoint_ids: keypoint_ids.unwrap_or_default(), + } + }, + ); + + self.process_data( + &mut line_builder, + view_query, + entity_path, + spatial_ctx, + data, + ); + + Ok(()) }, )?; diff --git a/crates/re_space_view_spatial/src/visualizers/mod.rs b/crates/re_space_view_spatial/src/visualizers/mod.rs index fd988d38bed0..98e205ec4ab7 100644 --- a/crates/re_space_view_spatial/src/visualizers/mod.rs +++ b/crates/re_space_view_spatial/src/visualizers/mod.rs @@ -13,6 +13,7 @@ mod lines3d; mod meshes; mod points2d; mod points3d; +mod results_ext; mod spatial_view_visualizer; mod transform3d_arrows; @@ -21,8 +22,9 @@ pub use images::{ImageVisualizer, ViewerImage}; pub use spatial_view_visualizer::SpatialViewVisualizerData; pub use transform3d_arrows::{add_axis_arrows, Transform3DArrowsVisualizer}; -#[doc(hidden)] // Public for benchmarks -pub use points3d::{LoadedPoints, Points3DComponentData}; +pub(crate) use self::results_ext::CachedRangeResultsExt; + +// --- use ahash::HashMap; @@ -101,126 +103,97 @@ pub fn collect_ui_labels(visualizers: &VisualizerCollection) -> Vec { ui_labels } -pub fn picking_id_from_instance_key( - instance_key: InstanceKey, -) -> re_renderer::PickingLayerInstanceId { - re_renderer::PickingLayerInstanceId(instance_key.0) -} - /// Process [`Color`] components using annotations and default colors. pub fn process_color_slice<'a>( - colors: Option<&'a [Option]>, - ent_path: &'a EntityPath, + entity_path: &'a EntityPath, + num_instances: usize, annotation_infos: &'a ResolvedAnnotationInfos, + colors: &'a [Color], ) -> Vec { - // This can be rather slow for colors with transparency, since we need to pre-multiply the alpha. - re_tracing::profile_function!(); - - let default_color = DefaultColor::EntityPath(ent_path); + // NOTE: Do not put tracing scopes here, this is called for every entity/timestamp in a frame. - match (colors, annotation_infos) { - (None, ResolvedAnnotationInfos::Same(count, annotation_info)) => { - re_tracing::profile_scope!("no colors, same annotation"); - let color = annotation_info.color(None, default_color); - vec![color; *count] - } - - (None, ResolvedAnnotationInfos::Many(annotation_infos)) => { - re_tracing::profile_scope!("no-colors, many annotations"); - annotation_infos - .iter() - .map(|annotation_info| annotation_info.color(None, default_color)) - .collect() - } + let default_color = DefaultColor::EntityPath(entity_path); - (Some(colors), ResolvedAnnotationInfos::Same(count, annotation_info)) => { - re_tracing::profile_scope!("many-colors, same annotation"); - debug_assert_eq!(colors.len(), *count); - colors - .iter() - .map(|color| annotation_info.color(color.map(|c| c.to_array()), default_color)) - .collect() + if colors.is_empty() { + match annotation_infos { + ResolvedAnnotationInfos::Same(count, annotation_info) => { + re_tracing::profile_scope!("no colors, same annotation"); + let color = annotation_info.color(None, default_color); + vec![color; *count] + } + ResolvedAnnotationInfos::Many(annotation_info) => { + re_tracing::profile_scope!("no-colors, many annotations"); + annotation_info + .iter() + .map(|annotation_info| annotation_info.color(None, default_color)) + .collect() + } } - - (Some(colors), ResolvedAnnotationInfos::Many(annotation_infos)) => { - re_tracing::profile_scope!("many-colors, many annotations"); - colors - .iter() - .zip(annotation_infos.iter()) - .map(move |(color, annotation_info)| { - annotation_info.color(color.map(|c| c.to_array()), default_color) - }) - .collect() + } else { + let colors = entity_iterator::clamped(colors, num_instances); + match annotation_infos { + ResolvedAnnotationInfos::Same(_count, annotation_info) => { + re_tracing::profile_scope!("many-colors, same annotation"); + colors + .map(|color| annotation_info.color(Some(color.to_array()), default_color)) + .collect() + } + ResolvedAnnotationInfos::Many(annotation_infos) => { + re_tracing::profile_scope!("many-colors, many annotations"); + colors + .zip(annotation_infos.iter()) + .map(move |(color, annotation_info)| { + annotation_info.color(Some(color.to_array()), default_color) + }) + .collect() + } } } } -/// Process `Text` components using annotations. -pub fn process_label_slice( - labels: Option<&[Option]>, - default_len: usize, - annotation_infos: &ResolvedAnnotationInfos, -) -> Vec> { - re_tracing::profile_function!(); - - match labels { - None => vec![None; default_len], - Some(labels) => itertools::izip!(annotation_infos.iter(), labels) - .map(move |(annotation_info, text)| { - annotation_info.label(text.as_ref().map(|t| t.as_str())) - }) - .collect(), - } -} - /// Process [`re_types::components::Radius`] components to [`re_renderer::Size`] using auto size /// where no radius is specified. pub fn process_radius_slice( - radii: Option<&[Option]>, - default_len: usize, - ent_path: &EntityPath, + entity_path: &EntityPath, + num_instances: usize, + radii: &[re_types::components::Radius], ) -> Vec { re_tracing::profile_function!(); - let ent_path = ent_path.clone(); - match radii { - None => { - vec![re_renderer::Size::AUTO; default_len] - } - Some(radii) => radii - .iter() - .map(|radius| process_radius(&ent_path, radius)) - .collect(), + if radii.is_empty() { + vec![re_renderer::Size::AUTO; num_instances] + } else { + entity_iterator::clamped(radii, num_instances) + .map(|radius| process_radius(entity_path, *radius)) + .collect() } } fn process_radius( entity_path: &EntityPath, - radius: &Option, + radius: re_types::components::Radius, ) -> re_renderer::Size { - radius.map_or(re_renderer::Size::AUTO, |r| { - if 0.0 <= r.0 && r.0.is_finite() { - re_renderer::Size::new_scene(r.0) + if 0.0 <= radius.0 && radius.0.is_finite() { + re_renderer::Size::new_scene(radius.0) + } else { + if radius.0 < 0.0 { + re_log::warn_once!("Found negative radius in entity {entity_path}"); + } else if radius.0.is_infinite() { + re_log::warn_once!("Found infinite radius in entity {entity_path}"); } else { - if r.0 < 0.0 { - re_log::warn_once!("Found negative radius in entity {entity_path}"); - } else if r.0.is_infinite() { - re_log::warn_once!("Found infinite radius in entity {entity_path}"); - } else { - re_log::warn_once!("Found NaN radius in entity {entity_path}"); - } - re_renderer::Size::AUTO + re_log::warn_once!("Found NaN radius in entity {entity_path}"); } - }) + re_renderer::Size::AUTO + } } /// Resolves all annotations and keypoints for the given entity view. fn process_annotation_and_keypoint_slices( latest_at: re_log_types::TimeInt, - instance_keys: &[InstanceKey], - keypoint_ids: Option<&[Option]>, - class_ids: Option<&[Option]>, + num_instances: usize, positions: impl Iterator, + keypoint_ids: &[re_types::components::KeypointId], + class_ids: &[re_types::components::ClassId], annotations: &Annotations, ) -> (ResolvedAnnotationInfos, Keypoints) { re_tracing::profile_function!(); @@ -228,42 +201,23 @@ fn process_annotation_and_keypoint_slices( let mut keypoints: Keypoints = HashMap::default(); // No need to process annotations if we don't have class-ids - let Some(class_ids) = class_ids else { + if class_ids.is_empty() { let resolved_annotation = annotations .resolved_class_description(None) .annotation_info(); return ( - ResolvedAnnotationInfos::Same(instance_keys.len(), resolved_annotation), + ResolvedAnnotationInfos::Same(num_instances, resolved_annotation), keypoints, ); }; - if let Some(keypoint_ids) = keypoint_ids { - let annotation_info = itertools::izip!(positions, keypoint_ids, class_ids) - .map(|(positions, &keypoint_id, &class_id)| { - let class_description = annotations.resolved_class_description(class_id); - - if let (Some(keypoint_id), Some(class_id), position) = - (keypoint_id, class_id, positions) - { - keypoints - .entry((class_id, latest_at.as_i64())) - .or_default() - .insert(keypoint_id.0, position); - class_description.annotation_info_with_keypoint(keypoint_id.0) - } else { - class_description.annotation_info() - } - }) - .collect(); + let class_ids = entity_iterator::clamped(class_ids, num_instances); - (ResolvedAnnotationInfos::Many(annotation_info), keypoints) - } else { + if keypoint_ids.is_empty() { let annotation_info = class_ids - .iter() .map(|&class_id| { - let class_description = annotations.resolved_class_description(class_id); + let class_description = annotations.resolved_class_description(Some(class_id)); class_description.annotation_info() }) .collect(); @@ -272,6 +226,21 @@ fn process_annotation_and_keypoint_slices( ResolvedAnnotationInfos::Many(annotation_info), Default::default(), ) + } else { + let keypoint_ids = entity_iterator::clamped(keypoint_ids, num_instances); + let annotation_info = itertools::izip!(positions, keypoint_ids, class_ids) + .map(|(position, keypoint_id, &class_id)| { + let class_description = annotations.resolved_class_description(Some(class_id)); + + keypoints + .entry((class_id, latest_at.as_i64())) + .or_default() + .insert(keypoint_id.0, position); + class_description.annotation_info_with_keypoint(keypoint_id.0) + }) + .collect(); + + (ResolvedAnnotationInfos::Many(annotation_info), keypoints) } } diff --git a/crates/re_space_view_spatial/src/visualizers/points2d.rs b/crates/re_space_view_spatial/src/visualizers/points2d.rs index 202dd9e25a3b..9fe4f1a69039 100644 --- a/crates/re_space_view_spatial/src/visualizers/points2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points2d.rs @@ -1,5 +1,8 @@ +use itertools::Itertools as _; + use re_entity_db::{EntityPath, InstancePathHash}; -use re_renderer::{LineDrawableBuilder, PointCloudBuilder}; +use re_query_cache2::range_zip_1x5; +use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points2D, components::{ClassId, Color, InstanceKey, KeypointId, Position2D, Radius, Text}, @@ -15,12 +18,12 @@ use crate::{ view_kind::SpatialSpaceViewKind, visualizers::{ load_keypoint_connections, process_annotation_and_keypoint_slices, process_color_slice, - UiLabel, UiLabelTarget, + process_radius_slice, UiLabel, UiLabelTarget, }, }; use super::{ - filter_visualizable_2d_entities, SpatialViewVisualizerData, + entity_iterator::clamped, filter_visualizable_2d_entities, SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES, }; @@ -41,127 +44,117 @@ impl Default for Points2DVisualizer { } } +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Points2DVisualizer { fn process_labels<'a>( - labels: &'a [Option], + entity_path: &'a EntityPath, positions: &'a [glam::Vec3], - instance_path_hashes: &'a [InstancePathHash], + labels: &'a [Text], colors: &'a [egui::Color32], annotation_infos: &'a ResolvedAnnotationInfos, ) -> impl Iterator + 'a { - itertools::izip!( - annotation_infos.iter(), - positions, - labels, - colors, - instance_path_hashes, - ) - .filter_map( - move |(annotation_info, point, label, color, labeled_instance)| { - let label = annotation_info.label(label.as_ref().map(|l| l.as_str())); + let labels = clamped(labels, positions.len()); + itertools::izip!(annotation_infos.iter(), positions, labels, colors) + .enumerate() + .filter_map(move |(i, (annotation_info, point, label, color))| { + let label = annotation_info.label(Some(label.as_str())); match (point, label) { (point, Some(label)) => Some(UiLabel { text: label, color: *color, target: UiLabelTarget::Point2D(egui::pos2(point.x, point.y)), - labeled_instance: *labeled_instance, + labeled_instance: InstancePathHash::instance( + entity_path, + InstanceKey(i as _), + ), }), _ => None, } - }, - ) + }) } - fn process_data( + fn process_data<'a>( &mut self, point_builder: &mut PointCloudBuilder<'_>, line_builder: &mut LineDrawableBuilder<'_>, query: &ViewQuery<'_>, - data: &Points2DComponentData<'_>, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, + data: impl Iterator>, ) -> Result<(), SpaceViewSystemExecutionError> { - re_tracing::profile_function!(); + for data in data { + let num_instances = data.positions.len(); + + let positions = data + .positions + .iter() + .map(|p| glam::vec3(p.x(), p.y(), 0.0)) + .collect_vec(); + + let picking_ids = (0..num_instances) + .map(|i| PickingLayerInstanceId(i as _)) + .collect_vec(); + + let (annotation_infos, keypoints) = process_annotation_and_keypoint_slices( + query.latest_at, + num_instances, + positions.iter().copied(), + data.keypoint_ids, + data.class_ids, + &ent_context.annotations, + ); + + let radii = process_radius_slice(entity_path, num_instances, data.radii); + let colors = + process_color_slice(entity_path, num_instances, &annotation_infos, data.colors); - let (annotation_infos, keypoints) = process_annotation_and_keypoint_slices( - query.latest_at, - data.instance_keys, - data.keypoint_ids, - data.class_ids, - data.positions.iter().map(|p| glam::vec3(p.x(), p.y(), 0.0)), - &ent_context.annotations, - ); - - let positions = Self::load_positions(data); - let colors = Self::load_colors(data, ent_path, &annotation_infos); - let radii = Self::load_radii(data, ent_path); - let picking_instance_ids = bytemuck::cast_slice(data.instance_keys); - - { - re_tracing::profile_scope!("to_gpu"); - - let point_batch = point_builder - .batch(ent_path.to_string()) - .depth_offset(ent_context.depth_offset) - .flags( - re_renderer::renderer::PointCloudBatchFlags::FLAG_DRAW_AS_CIRCLES - | re_renderer::renderer::PointCloudBatchFlags::FLAG_ENABLE_SHADING, - ) - .world_from_obj(ent_context.world_from_entity) - .outline_mask_ids(ent_context.highlight.overall) - .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); - - let mut point_range_builder = - point_batch.add_points_2d(&positions, &radii, &colors, picking_instance_ids); - - // Determine if there's any sub-ranges that need extra highlighting. { - re_tracing::profile_scope!("marking additional highlight points"); - for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { - // TODO(andreas, jeremy): We can do this much more efficiently - let highlighted_point_index = data - .instance_keys - .iter() - .position(|key| highlighted_key == key); - if let Some(highlighted_point_index) = highlighted_point_index { - point_range_builder = point_range_builder - .push_additional_outline_mask_ids_for_range( - highlighted_point_index as u32..highlighted_point_index as u32 + 1, - *instance_mask_ids, - ); + let point_batch = point_builder + .batch(entity_path.to_string()) + .depth_offset(ent_context.depth_offset) + .flags( + re_renderer::renderer::PointCloudBatchFlags::FLAG_DRAW_AS_CIRCLES + | re_renderer::renderer::PointCloudBatchFlags::FLAG_ENABLE_SHADING, + ) + .world_from_obj(ent_context.world_from_entity) + .outline_mask_ids(ent_context.highlight.overall) + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); + + let mut point_range_builder = + point_batch.add_points_2d(&positions, &radii, &colors, &picking_ids); + + // Determine if there's any sub-ranges that need extra highlighting. + { + re_tracing::profile_scope!("marking additional highlight points"); + for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { + let highlighted_point_index = + (highlighted_key.0 < num_instances as u64).then_some(highlighted_key.0); + if let Some(highlighted_point_index) = highlighted_point_index { + point_range_builder = point_range_builder + .push_additional_outline_mask_ids_for_range( + highlighted_point_index as u32 + ..highlighted_point_index as u32 + 1, + *instance_mask_ids, + ); + } } } } - }; - - self.data.add_bounding_box_from_points( - ent_path.hash(), - positions.iter().copied(), - ent_context.world_from_entity, - ); - load_keypoint_connections(line_builder, ent_context, ent_path, &keypoints)?; + self.data.add_bounding_box_from_points( + entity_path.hash(), + positions.iter().copied(), + ent_context.world_from_entity, + ); - if data.instance_keys.len() <= self.max_labels { - re_tracing::profile_scope!("labels"); + load_keypoint_connections(line_builder, ent_context, entity_path, &keypoints)?; - // Max labels is small enough that we can afford iterating on the colors again. - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - - let instance_path_hashes_for_picking = { - re_tracing::profile_scope!("instance_hashes"); - data.instance_keys - .iter() - .copied() - .map(|instance_key| InstancePathHash::instance(ent_path, instance_key)) - .collect::>() - }; - - if let Some(labels) = data.labels { + if num_instances <= self.max_labels { self.data.ui_labels.extend(Self::process_labels( - labels, + entity_path, &positions, - &instance_path_hashes_for_picking, + data.labels, &colors, &annotation_infos, )); @@ -170,49 +163,21 @@ impl Points2DVisualizer { Ok(()) } - - #[inline] - pub fn load_positions( - Points2DComponentData { positions, .. }: &Points2DComponentData<'_>, - ) -> Vec { - re_tracing::profile_function!(); - positions - .iter() - .map(|p| glam::vec3(p.x(), p.y(), 0.0)) - .collect() - } - - #[inline] - pub fn load_radii( - &Points2DComponentData { - positions, radii, .. - }: &Points2DComponentData<'_>, - ent_path: &EntityPath, - ) -> Vec { - crate::visualizers::process_radius_slice(radii, positions.len(), ent_path) - } - - #[inline] - pub fn load_colors( - &Points2DComponentData { colors, .. }: &Points2DComponentData<'_>, - ent_path: &EntityPath, - annotation_infos: &ResolvedAnnotationInfos, - ) -> Vec { - crate::visualizers::process_color_slice(colors, ent_path, annotation_infos) - } } // --- #[doc(hidden)] // Public for benchmarks pub struct Points2DComponentData<'a> { - pub instance_keys: &'a [InstanceKey], + // Point of views pub positions: &'a [Position2D], - pub colors: Option<&'a [Option]>, - pub radii: Option<&'a [Option]>, - pub labels: Option<&'a [Option]>, - pub keypoint_ids: Option<&'a [Option]>, - pub class_ids: Option<&'a [Option]>, + + // Clamped to edge + pub colors: &'a [Color], + pub radii: &'a [Radius], + pub labels: &'a [Text], + pub keypoint_ids: &'a [KeypointId], + pub class_ids: &'a [ClassId], } impl IdentifiedViewSystem for Points2DVisualizer { @@ -238,71 +203,80 @@ impl VisualizerSystem for Points2DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let num_points = super::entity_iterator::count_instances_in_archetype_views::< - Points2DVisualizer, - Points2D, - 9, - >(ctx, query); - - if num_points == 0 { - return Ok(Vec::new()); - } - let mut point_builder = PointCloudBuilder::new(ctx.render_ctx); point_builder .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES); - // We need lines from keypoints. The number of lines we'll have is harder to predict, so we'll go with the dynamic allocation approach. + // We need lines from keypoints. The number of lines we'll have is harder to predict, so we'll + // go with the dynamic allocation approach. let mut line_builder = LineDrawableBuilder::new(ctx.render_ctx); line_builder .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES); - super::entity_iterator::process_archetype_pov1_comp5::< - Points2DVisualizer, - Points2D, - Position2D, - Color, - Radius, - Text, - re_types::components::KeypointId, - re_types::components::ClassId, - _, - >( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |_ctx, - ent_path, - _ent_props, - ent_context, - (_time, _row_id), - instance_keys, - positions, - colors, - radii, - labels, - keypoint_ids, - class_ids| { - let data = Points2DComponentData { - instance_keys, - positions, - colors, - radii, - labels, - keypoint_ids, - class_ids, + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let positions = match results.get_dense::(resolver) { + Some(positions) => positions?, + _ => return Ok(()), }; + + let num_positions = positions + .range_indexed() + .map(|(_, positions)| positions.len()) + .sum::(); + if num_positions == 0 { + return Ok(()); + } + + point_builder.reserve(num_positions)?; + + let colors = results.get_or_empty_dense(resolver)?; + let radii = results.get_or_empty_dense(resolver)?; + let labels = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + let keypoint_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x5( + positions.range_indexed(), + colors.range_indexed(), + radii.range_indexed(), + labels.range_indexed(), + class_ids.range_indexed(), + keypoint_ids.range_indexed(), + ) + .map( + |(_index, positions, colors, radii, labels, class_ids, keypoint_ids)| { + Points2DComponentData { + positions, + colors: colors.unwrap_or_default(), + radii: radii.unwrap_or_default(), + labels: labels.unwrap_or_default(), + class_ids: class_ids.unwrap_or_default(), + keypoint_ids: keypoint_ids.unwrap_or_default(), + } + }, + ); + self.process_data( &mut point_builder, &mut line_builder, - query, - &data, - ent_path, - ent_context, + view_query, + entity_path, + spatial_ctx, + data, ) }, )?; diff --git a/crates/re_space_view_spatial/src/visualizers/points3d.rs b/crates/re_space_view_spatial/src/visualizers/points3d.rs index 6e264854a837..a0b62e66b133 100644 --- a/crates/re_space_view_spatial/src/visualizers/points3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points3d.rs @@ -1,12 +1,14 @@ +use itertools::Itertools as _; + use re_entity_db::{EntityPath, InstancePathHash}; -use re_log_types::TimeInt; +use re_query_cache2::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points3D, components::{ClassId, Color, InstanceKey, KeypointId, Position3D, Radius, Text}, }; use re_viewer_context::{ - Annotations, ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, + ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewerContext, VisualizableEntities, VisualizableFilterContext, VisualizerQueryInfo, VisualizerSystem, }; @@ -16,15 +18,17 @@ use crate::{ view_kind::SpatialSpaceViewKind, visualizers::{ load_keypoint_connections, process_annotation_and_keypoint_slices, process_color_slice, - UiLabel, UiLabelTarget, + process_radius_slice, UiLabel, UiLabelTarget, }, }; use super::{ - filter_visualizable_3d_entities, Keypoints, SpatialViewVisualizerData, + entity_iterator::clamped, filter_visualizable_3d_entities, SpatialViewVisualizerData, SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES, }; +// --- + pub struct Points3DVisualizer { /// If the number of points in the batch is > max_labels, don't render point labels. pub max_labels: usize, @@ -40,119 +44,122 @@ impl Default for Points3DVisualizer { } } +struct Points3DComponentData<'a> { + // Point of views + positions: &'a [Position3D], + + // Clamped to edge + colors: &'a [Color], + radii: &'a [Radius], + labels: &'a [Text], + keypoint_ids: &'a [KeypointId], + class_ids: &'a [ClassId], +} + +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Points3DVisualizer { fn process_labels<'a>( - labels: &'a [Option], + entity_path: &'a EntityPath, positions: &'a [glam::Vec3], - instance_path_hashes: &'a [InstancePathHash], + labels: &'a [Text], colors: &'a [egui::Color32], annotation_infos: &'a ResolvedAnnotationInfos, world_from_obj: glam::Affine3A, ) -> impl Iterator + 'a { - re_tracing::profile_function!(); - itertools::izip!( - annotation_infos.iter(), - positions, - labels, - colors, - instance_path_hashes, - ) - .filter_map( - move |(annotation_info, point, label, color, labeled_instance)| { - let label = annotation_info.label(label.as_ref().map(|l| l.as_str())); + let labels = clamped(labels, positions.len()); + itertools::izip!(annotation_infos.iter(), positions, labels, colors) + .enumerate() + .filter_map(move |(i, (annotation_info, point, label, color))| { + let label = annotation_info.label(Some(label.as_str())); match (point, label) { (point, Some(label)) => Some(UiLabel { text: label, color: *color, target: UiLabelTarget::Position3D(world_from_obj.transform_point3(*point)), - labeled_instance: *labeled_instance, + labeled_instance: InstancePathHash::instance( + entity_path, + InstanceKey(i as _), + ), }), _ => None, } - }, - ) + }) } - fn process_data( + fn process_data<'a>( &mut self, point_builder: &mut PointCloudBuilder<'_>, line_builder: &mut LineDrawableBuilder<'_>, query: &ViewQuery<'_>, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - data: &Points3DComponentData<'_>, + data: impl Iterator>, ) -> Result<(), SpaceViewSystemExecutionError> { - re_tracing::profile_function!(); - - let LoadedPoints { - annotation_infos, - keypoints, - positions, - radii, - colors, - picking_instance_ids, - } = LoadedPoints::load(data, ent_path, query.latest_at, &ent_context.annotations); + for data in data { + let num_instances = data.positions.len(); + if num_instances == 0 { + continue; + } - { - re_tracing::profile_scope!("to_gpu"); + let picking_ids = (0..num_instances) + .map(|i| PickingLayerInstanceId(i as _)) + .collect_vec(); - let point_batch = point_builder - .batch(ent_path.to_string()) - .world_from_obj(ent_context.world_from_entity) - .outline_mask_ids(ent_context.highlight.overall) - .picking_object_id(re_renderer::PickingLayerObjectId(ent_path.hash64())); + let (annotation_infos, keypoints) = process_annotation_and_keypoint_slices( + query.latest_at, + num_instances, + data.positions.iter().map(|p| p.0.into()), + data.keypoint_ids, + data.class_ids, + &ent_context.annotations, + ); - let mut point_range_builder = - point_batch.add_points(positions, &radii, &colors, picking_instance_ids); + let positions = bytemuck::cast_slice(data.positions); + let radii = process_radius_slice(entity_path, num_instances, data.radii); + let colors = + process_color_slice(entity_path, num_instances, &annotation_infos, data.colors); - // Determine if there's any sub-ranges that need extra highlighting. { - re_tracing::profile_scope!("marking additional highlight points"); - for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { - // TODO(andreas, jeremy): We can do this much more efficiently - let highlighted_point_index = data - .instance_keys - .iter() - .position(|key| highlighted_key == key); - if let Some(highlighted_point_index) = highlighted_point_index { - point_range_builder = point_range_builder - .push_additional_outline_mask_ids_for_range( - highlighted_point_index as u32..highlighted_point_index as u32 + 1, - *instance_mask_ids, - ); + let point_batch = point_builder + .batch(entity_path.to_string()) + .world_from_obj(ent_context.world_from_entity) + .outline_mask_ids(ent_context.highlight.overall) + .picking_object_id(re_renderer::PickingLayerObjectId(entity_path.hash64())); + + let mut point_range_builder = + point_batch.add_points(positions, &radii, &colors, &picking_ids); + + // Determine if there's any sub-ranges that need extra highlighting. + { + for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { + let highlighted_point_index = + (highlighted_key.0 < num_instances as u64).then_some(highlighted_key.0); + if let Some(highlighted_point_index) = highlighted_point_index { + point_range_builder = point_range_builder + .push_additional_outline_mask_ids_for_range( + highlighted_point_index as u32 + ..highlighted_point_index as u32 + 1, + *instance_mask_ids, + ); + } } } } - } - self.data.add_bounding_box_from_points( - ent_path.hash(), - positions.iter().copied(), - ent_context.world_from_entity, - ); + self.data.add_bounding_box_from_points( + entity_path.hash(), + positions.iter().copied(), + ent_context.world_from_entity, + ); - load_keypoint_connections(line_builder, ent_context, ent_path, &keypoints)?; + load_keypoint_connections(line_builder, ent_context, entity_path, &keypoints)?; - if data.instance_keys.len() <= self.max_labels { - re_tracing::profile_scope!("labels"); - - // Max labels is small enough that we can afford iterating on the colors again. - let colors = process_color_slice(data.colors, ent_path, &annotation_infos); - - let instance_path_hashes_for_picking = { - re_tracing::profile_scope!("instance_hashes"); - data.instance_keys - .iter() - .copied() - .map(|instance_key| InstancePathHash::instance(ent_path, instance_key)) - .collect::>() - }; - - if let Some(labels) = data.labels { + if num_instances <= self.max_labels { self.data.ui_labels.extend(Self::process_labels( - labels, + entity_path, positions, - &instance_path_hashes_for_picking, + data.labels, &colors, &annotation_infos, ent_context.world_from_entity, @@ -187,72 +194,80 @@ impl VisualizerSystem for Points3DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let num_points = super::entity_iterator::count_instances_in_archetype_views::< - Points3DVisualizer, - Points3D, - 8, - >(ctx, query); - - if num_points == 0 { - return Ok(Vec::new()); - } - let mut point_builder = PointCloudBuilder::new(ctx.render_ctx); - point_builder.reserve(num_points)?; point_builder .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES); - // We need lines from keypoints. The number of lines we'll have is harder to predict, so we'll go with the dynamic allocation approach. + // We need lines from keypoints. The number of lines we'll have is harder to predict, so we'll go + // with the dynamic allocation approach. let mut line_builder = LineDrawableBuilder::new(ctx.render_ctx); line_builder .radius_boost_in_ui_points_for_outlines(SIZE_BOOST_IN_POINTS_FOR_POINT_OUTLINES); - super::entity_iterator::process_archetype_pov1_comp5::< - Points3DVisualizer, - Points3D, - Position3D, - Color, - Radius, - Text, - re_types::components::KeypointId, - re_types::components::ClassId, - _, - >( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |_ctx, - ent_path, - _ent_props, - ent_context, - (_time, _row_id), - instance_keys, - positions, - colors, - radii, - labels, - keypoint_ids, - class_ids| { - let data = Points3DComponentData { - instance_keys, - positions, - colors, - radii, - labels, - keypoint_ids, - class_ids, + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let positions = match results.get_dense::(resolver) { + Some(positions) => positions?, + _ => return Ok(()), }; + + let num_positions = positions + .range_indexed() + .map(|(_, positions)| positions.len()) + .sum::(); + if num_positions == 0 { + return Ok(()); + } + + point_builder.reserve(num_positions)?; + + let colors = results.get_or_empty_dense(resolver)?; + let radii = results.get_or_empty_dense(resolver)?; + let labels = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + let keypoint_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x5( + positions.range_indexed(), + colors.range_indexed(), + radii.range_indexed(), + labels.range_indexed(), + class_ids.range_indexed(), + keypoint_ids.range_indexed(), + ) + .map( + |(_index, positions, colors, radii, labels, class_ids, keypoint_ids)| { + Points3DComponentData { + positions, + colors: colors.unwrap_or_default(), + radii: radii.unwrap_or_default(), + labels: labels.unwrap_or_default(), + class_ids: class_ids.unwrap_or_default(), + keypoint_ids: keypoint_ids.unwrap_or_default(), + } + }, + ); + self.process_data( &mut point_builder, &mut line_builder, - query, - ent_path, - ent_context, - &data, + view_query, + entity_path, + spatial_ctx, + data, ) }, )?; @@ -271,83 +286,3 @@ impl VisualizerSystem for Points3DVisualizer { self } } - -// --- - -#[doc(hidden)] // Public for benchmarks -pub struct LoadedPoints<'a> { - pub annotation_infos: ResolvedAnnotationInfos, - pub keypoints: Keypoints, - pub positions: &'a [glam::Vec3], - pub radii: Vec, - pub colors: Vec, - pub picking_instance_ids: &'a [PickingLayerInstanceId], -} - -#[doc(hidden)] // Public for benchmarks -pub struct Points3DComponentData<'a> { - pub instance_keys: &'a [InstanceKey], - pub positions: &'a [Position3D], - pub colors: Option<&'a [Option]>, - pub radii: Option<&'a [Option]>, - pub labels: Option<&'a [Option]>, - pub keypoint_ids: Option<&'a [Option]>, - pub class_ids: Option<&'a [Option]>, -} - -impl<'a> LoadedPoints<'a> { - #[inline] - pub fn load( - data: &'a Points3DComponentData<'_>, - ent_path: &EntityPath, - latest_at: TimeInt, - annotations: &Annotations, - ) -> Self { - re_tracing::profile_function!(); - - let (annotation_infos, keypoints) = process_annotation_and_keypoint_slices( - latest_at, - data.instance_keys, - data.keypoint_ids, - data.class_ids, - data.positions.iter().map(|p| p.0.into()), - annotations, - ); - - let positions = bytemuck::cast_slice(data.positions); - let picking_instance_ids = bytemuck::cast_slice(data.instance_keys); - - let (radii, colors) = rayon::join( - || Self::load_radii(data, ent_path), - || Self::load_colors(data, ent_path, &annotation_infos), - ); - - Self { - annotation_infos, - keypoints, - positions, - radii, - colors, - picking_instance_ids, - } - } - - #[inline] - pub fn load_radii( - &Points3DComponentData { - positions, radii, .. - }: &Points3DComponentData<'_>, - ent_path: &EntityPath, - ) -> Vec { - crate::visualizers::process_radius_slice(radii, positions.len(), ent_path) - } - - #[inline] - pub fn load_colors( - &Points3DComponentData { colors, .. }: &Points3DComponentData<'_>, - ent_path: &EntityPath, - annotation_infos: &ResolvedAnnotationInfos, - ) -> Vec { - crate::visualizers::process_color_slice(colors, ent_path, annotation_infos) - } -} diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs new file mode 100644 index 000000000000..5ef852651964 --- /dev/null +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -0,0 +1,151 @@ +use re_query_cache2::{ + CachedLatestAtResults, CachedRangeData, CachedRangeResults, CachedResults, PromiseResolver, + PromiseResult, +}; +use re_types::Component; + +// --- + +/// Extension traits to abstract query result handling for all spatial space views. +/// +/// Also turns all results into range results, so that views only have to worry about the ranged +/// case. +pub trait CachedRangeResultsExt { + fn get_dense<'a, C: Component>( + &'a self, + resolver: &PromiseResolver, + ) -> Option>>; + + fn get_or_empty_dense<'a, C: Component>( + &'a self, + resolver: &PromiseResolver, + ) -> re_query_cache2::Result>; +} + +impl CachedRangeResultsExt for CachedResults { + fn get_dense<'a, C: Component>( + &'a self, + resolver: &PromiseResolver, + ) -> Option>> { + match self { + CachedResults::LatestAt(_, results) => results.get_dense(resolver), + CachedResults::Range(_, results) => results.get_dense(resolver), + } + } + + fn get_or_empty_dense<'a, C: Component>( + &'a self, + resolver: &PromiseResolver, + ) -> re_query_cache2::Result> { + match self { + CachedResults::LatestAt(_, results) => results.get_or_empty_dense(resolver), + CachedResults::Range(_, results) => results.get_or_empty_dense(resolver), + } + } +} + +impl CachedRangeResultsExt for CachedRangeResults { + #[inline] + fn get_dense<'a, C: Component>( + &'a self, + resolver: &PromiseResolver, + ) -> Option>> { + let results = self.get(C::name())?.to_dense(resolver); + + // TODO(#5607): what should happen if the promise is still pending? + let (front_status, back_status) = results.status(); + match front_status { + PromiseResult::Error(err) => { + return Some(Err(re_query_cache2::QueryError::Other(err.into()))) + } + PromiseResult::Pending | PromiseResult::Ready(_) => {} + } + match back_status { + PromiseResult::Error(err) => { + return Some(Err(re_query_cache2::QueryError::Other(err.into()))) + } + PromiseResult::Pending | PromiseResult::Ready(_) => {} + } + + Some(Ok(results)) + } + + #[inline] + fn get_or_empty_dense<'a, C: Component>( + &'a self, + resolver: &PromiseResolver, + ) -> re_query_cache2::Result> { + let results = self.get_or_empty(C::name()).to_dense(resolver); + + // TODO(#5607): what should happen if the promise is still pending? + let (front_status, back_status) = results.status(); + match front_status { + PromiseResult::Error(err) => { + return Err(re_query_cache2::QueryError::Other(err.into())) + } + PromiseResult::Pending | PromiseResult::Ready(_) => {} + } + match back_status { + PromiseResult::Error(err) => { + return Err(re_query_cache2::QueryError::Other(err.into())) + } + PromiseResult::Pending | PromiseResult::Ready(_) => {} + } + + Ok(results) + } +} + +impl CachedRangeResultsExt for CachedLatestAtResults { + #[inline] + fn get_dense<'a, C: Component>( + &'a self, + resolver: &PromiseResolver, + ) -> Option>> { + let results = self.get(C::name())?; + let data = CachedRangeData::from_latest_at(resolver, results); + + // TODO(#5607): what should happen if the promise is still pending? + let (front_status, back_status) = data.status(); + match front_status { + PromiseResult::Error(err) => { + return Some(Err(re_query_cache2::QueryError::Other(err.into()))) + } + PromiseResult::Pending | PromiseResult::Ready(_) => {} + } + match back_status { + PromiseResult::Error(err) => { + return Some(Err(re_query_cache2::QueryError::Other(err.into()))) + } + PromiseResult::Pending | PromiseResult::Ready(_) => {} + } + + Some(Ok(data)) + } + + #[inline] + fn get_or_empty_dense<'a, C: Component>( + &'a self, + resolver: &PromiseResolver, + ) -> re_query_cache2::Result> { + let results = self.get_or_empty(C::name()); + let data = CachedRangeData::from_latest_at(resolver, results); + + // TODO(#5607): what should happen if the promise is still pending? + let (front_status, back_status) = data.status(); + match front_status { + PromiseResult::Error(err) => { + return Err(re_query_cache2::QueryError::Other(err.into())) + } + PromiseResult::Pending | PromiseResult::Ready(_) => {} + } + match back_status { + PromiseResult::Error(err) => { + return Err(re_query_cache2::QueryError::Other(err.into())) + } + PromiseResult::Pending | PromiseResult::Ready(_) => {} + } + + Ok(data) + } +} diff --git a/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs b/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs index 78d6de34efea..74b8dca7f9df 100644 --- a/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs +++ b/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs @@ -51,9 +51,6 @@ impl VisualizerSystem for Transform3DArrowsVisualizer { ) -> Result, SpaceViewSystemExecutionError> { let transforms = view_ctx.get::()?; - let query_caches = ctx.recording().query_caches(); - let store = ctx.recording_store(); - let latest_at_query = re_data_store::LatestAtQuery::new(query.timeline, query.latest_at); // Counting all transforms ahead of time is a bit wasteful, but we also don't expect a huge amount, @@ -66,16 +63,10 @@ impl VisualizerSystem for Transform3DArrowsVisualizer { continue; } - if query_caches - .query_archetype_latest_at_pov1_comp0::( - store, - &latest_at_query, - &data_result.entity_path, - |_| {}, - ) - // NOTE: Can only fail if the primary component is missing, which is what we - // want to check here (i.e.: there's no transform for this entity!). - .is_err() + if ctx + .recording() + .latest_at_component::(&data_result.entity_path, &latest_at_query) + .is_none() { continue; } From aa044bc91046230b6b734c156368eb3b46d47181 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:43:27 +0200 Subject: [PATCH 371/508] New data APIs 13: sunset legacy cache crate (#5994) `re_query_cache` is gone, `re_query_cache2` takes its place -- simple as that. --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- Cargo.lock | 32 - Cargo.toml | 1 - crates/re_data_ui/src/component.rs | 2 +- crates/re_data_ui/src/component_path.rs | 2 +- .../re_data_ui/src/component_ui_registry.rs | 2 +- crates/re_data_ui/src/editors.rs | 2 +- crates/re_data_ui/src/instance_path.rs | 2 +- crates/re_entity_db/Cargo.toml | 3 +- crates/re_entity_db/src/entity_db.rs | 42 +- crates/re_entity_db/src/lib.rs | 2 +- crates/re_query_cache/Cargo.toml | 23 +- crates/re_query_cache/benches/latest_at.rs | 107 +- .../examples/latest_at.rs | 4 +- .../examples/latest_at_archetype.rs | 6 +- .../examples/range.rs | 4 +- crates/re_query_cache/src/cache.rs | 1083 ++--------------- crates/re_query_cache/src/cache_stats.rs | 204 +--- crates/re_query_cache/src/flat_vec_deque.rs | 11 + crates/re_query_cache/src/latest_at.rs | 332 ----- .../src/latest_at/helpers.rs | 0 .../src/latest_at/mod.rs | 0 .../src/latest_at/query.rs | 0 .../src/latest_at/results.rs | 0 .../src/latest_at/to_archetype/.gitattributes | 0 .../to_archetype/annotation_context.rs | 0 .../src/latest_at/to_archetype/arrows2d.rs | 0 .../src/latest_at/to_archetype/arrows3d.rs | 0 .../src/latest_at/to_archetype/asset3d.rs | 0 .../src/latest_at/to_archetype/background.rs | 0 .../src/latest_at/to_archetype/bar_chart.rs | 0 .../src/latest_at/to_archetype/boxes2d.rs | 0 .../src/latest_at/to_archetype/boxes3d.rs | 0 .../src/latest_at/to_archetype/clear.rs | 0 .../to_archetype/container_blueprint.rs | 0 .../src/latest_at/to_archetype/depth_image.rs | 0 .../to_archetype/disconnected_space.rs | 0 .../src/latest_at/to_archetype/image.rs | 0 .../latest_at/to_archetype/line_strips2d.rs | 0 .../latest_at/to_archetype/line_strips3d.rs | 0 .../src/latest_at/to_archetype/mesh3d.rs | 0 .../src/latest_at/to_archetype/mod.rs | 0 .../latest_at/to_archetype/panel_blueprint.rs | 0 .../src/latest_at/to_archetype/pinhole.rs | 0 .../src/latest_at/to_archetype/plot_legend.rs | 0 .../src/latest_at/to_archetype/points2d.rs | 0 .../src/latest_at/to_archetype/points3d.rs | 0 .../src/latest_at/to_archetype/scalar.rs | 0 .../src/latest_at/to_archetype/scalar_axis.rs | 0 .../to_archetype/segmentation_image.rs | 0 .../src/latest_at/to_archetype/series_line.rs | 0 .../latest_at/to_archetype/series_point.rs | 0 .../to_archetype/space_view_blueprint.rs | 0 .../to_archetype/space_view_contents.rs | 0 .../src/latest_at/to_archetype/tensor.rs | 0 .../latest_at/to_archetype/text_document.rs | 0 .../src/latest_at/to_archetype/text_log.rs | 0 .../src/latest_at/to_archetype/transform3d.rs | 0 .../to_archetype/view_coordinates.rs | 0 .../to_archetype/viewport_blueprint.rs | 0 crates/re_query_cache/src/lib.rs | 44 +- crates/re_query_cache/src/query.rs | 251 ---- crates/re_query_cache/src/range.rs | 334 ----- .../src/range/mod.rs | 0 .../src/range/query.rs | 0 .../src/range/results.rs | 0 crates/re_query_cache/tests/latest_at.rs | 92 +- crates/re_query_cache/tests/range.rs | 301 ++--- crates/re_query_cache2/Cargo.toml | 82 -- crates/re_query_cache2/README.md | 5 - .../re_query_cache2/benches/flat_vec_deque.rs | 333 ----- crates/re_query_cache2/benches/latest_at.rs | 374 ------ crates/re_query_cache2/src/cache.rs | 258 ---- crates/re_query_cache2/src/cache_stats.rs | 100 -- crates/re_query_cache2/src/flat_vec_deque.rs | 945 -------------- crates/re_query_cache2/src/lib.rs | 54 - crates/re_query_cache2/tests/latest_at.rs | 526 -------- crates/re_query_cache2/tests/range.rs | 586 --------- crates/re_space_view/src/sub_archetypes.rs | 2 +- .../src/space_view_class.rs | 2 +- crates/re_space_view_spatial/Cargo.toml | 1 - .../src/visualizers/arrows2d.rs | 2 +- .../src/visualizers/arrows3d.rs | 2 +- .../src/visualizers/boxes2d.rs | 2 +- .../src/visualizers/boxes3d.rs | 2 +- .../src/visualizers/entity_iterator.rs | 4 +- .../src/visualizers/lines2d.rs | 2 +- .../src/visualizers/lines3d.rs | 2 +- .../src/visualizers/points2d.rs | 2 +- .../src/visualizers/points3d.rs | 2 +- .../src/visualizers/results_ext.rs | 42 +- .../src/visualizer_system.rs | 2 +- crates/re_space_view_text_log/Cargo.toml | 1 - .../src/visualizer_system.rs | 10 +- crates/re_space_view_time_series/Cargo.toml | 1 - .../src/line_visualizer_system.rs | 8 +- .../src/point_visualizer_system.rs | 10 +- .../src/codegen/rust/to_archetype.rs | 6 +- crates/re_viewer/Cargo.toml | 1 - crates/re_viewer/src/app.rs | 2 +- crates/re_viewer/src/ui/memory_panel.rs | 2 +- crates/re_viewer/src/ui/override_ui.rs | 4 +- crates/re_viewer_context/Cargo.toml | 1 - .../src/component_ui_registry.rs | 2 +- crates/re_viewer_context/src/store_hub.rs | 4 +- examples/rust/extend_viewer_ui/src/main.rs | 2 +- scripts/lint.py | 2 +- 106 files changed, 567 insertions(+), 5707 deletions(-) rename crates/{re_query_cache2 => re_query_cache}/examples/latest_at.rs (98%) rename crates/{re_query_cache2 => re_query_cache}/examples/latest_at_archetype.rs (94%) rename crates/{re_query_cache2 => re_query_cache}/examples/range.rs (98%) delete mode 100644 crates/re_query_cache/src/latest_at.rs rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/helpers.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/mod.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/query.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/results.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/.gitattributes (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/annotation_context.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/arrows2d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/arrows3d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/asset3d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/background.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/bar_chart.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/boxes2d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/boxes3d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/clear.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/container_blueprint.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/depth_image.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/disconnected_space.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/image.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/line_strips2d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/line_strips3d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/mesh3d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/mod.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/panel_blueprint.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/pinhole.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/plot_legend.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/points2d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/points3d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/scalar.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/scalar_axis.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/segmentation_image.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/series_line.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/series_point.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/space_view_blueprint.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/space_view_contents.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/tensor.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/text_document.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/text_log.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/transform3d.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/view_coordinates.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/latest_at/to_archetype/viewport_blueprint.rs (100%) delete mode 100644 crates/re_query_cache/src/query.rs delete mode 100644 crates/re_query_cache/src/range.rs rename crates/{re_query_cache2 => re_query_cache}/src/range/mod.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/range/query.rs (100%) rename crates/{re_query_cache2 => re_query_cache}/src/range/results.rs (100%) delete mode 100644 crates/re_query_cache2/Cargo.toml delete mode 100644 crates/re_query_cache2/README.md delete mode 100644 crates/re_query_cache2/benches/flat_vec_deque.rs delete mode 100644 crates/re_query_cache2/benches/latest_at.rs delete mode 100644 crates/re_query_cache2/src/cache.rs delete mode 100644 crates/re_query_cache2/src/cache_stats.rs delete mode 100644 crates/re_query_cache2/src/flat_vec_deque.rs delete mode 100644 crates/re_query_cache2/src/lib.rs delete mode 100644 crates/re_query_cache2/tests/latest_at.rs delete mode 100644 crates/re_query_cache2/tests/range.rs diff --git a/Cargo.lock b/Cargo.lock index f9703f346a2d..2ad62e163514 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4310,7 +4310,6 @@ dependencies = [ "re_query", "re_query2", "re_query_cache", - "re_query_cache2", "re_smart_channel", "re_tracing", "re_types", @@ -4515,32 +4514,6 @@ dependencies = [ [[package]] name = "re_query_cache" version = "0.16.0-alpha.2" -dependencies = [ - "ahash", - "criterion", - "indent", - "itertools 0.12.0", - "mimalloc", - "parking_lot", - "paste", - "rand", - "re_data_store", - "re_format", - "re_log", - "re_log_types", - "re_query", - "re_tracing", - "re_types", - "re_types_core", - "seq-macro", - "similar-asserts", - "static_assertions", - "web-time", -] - -[[package]] -name = "re_query_cache2" -version = "0.16.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -4780,7 +4753,6 @@ dependencies = [ "re_log_types", "re_query", "re_query_cache", - "re_query_cache2", "re_renderer", "re_space_view", "re_tracing", @@ -4849,7 +4821,6 @@ dependencies = [ "re_log", "re_log_types", "re_query_cache", - "re_query_cache2", "re_renderer", "re_tracing", "re_types", @@ -4871,7 +4842,6 @@ dependencies = [ "re_log_types", "re_query", "re_query_cache", - "re_query_cache2", "re_renderer", "re_space_view", "re_tracing", @@ -5088,7 +5058,6 @@ dependencies = [ "re_log_types", "re_memory", "re_query_cache", - "re_query_cache2", "re_renderer", "re_smart_channel", "re_space_view", @@ -5150,7 +5119,6 @@ dependencies = [ "re_query", "re_query2", "re_query_cache", - "re_query_cache2", "re_renderer", "re_smart_channel", "re_string_interner", diff --git a/Cargo.toml b/Cargo.toml index 5df25ff9ff7d..d391fc4bcab3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,6 @@ re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.2", defa re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.2", default-features = false } re_query = { path = "crates/re_query", version = "=0.16.0-alpha.2", default-features = false } re_query_cache = { path = "crates/re_query_cache", version = "=0.16.0-alpha.2", default-features = false } -re_query_cache2 = { path = "crates/re_query_cache2", version = "=0.16.0-alpha.2", default-features = false } re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.2", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.2", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.2", default-features = false } diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index e3961b0a1789..6c6e9a2fa4c6 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use egui::NumExt; use re_entity_db::{ - external::re_query_cache2::CachedLatestAtComponentResults, EntityPath, InstancePath, + external::re_query_cache::CachedLatestAtComponentResults, EntityPath, InstancePath, }; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; diff --git a/crates/re_data_ui/src/component_path.rs b/crates/re_data_ui/src/component_path.rs index 35af64c88430..79311a6182f2 100644 --- a/crates/re_data_ui/src/component_path.rs +++ b/crates/re_data_ui/src/component_path.rs @@ -25,7 +25,7 @@ impl DataUi for ComponentPath { )); } else { let results = - db.query_caches2() + db.query_caches() .latest_at(db.store(), query, entity_path, [*component_name]); if let Some(results) = results.components.get(component_name) { crate::EntityLatestAtResults { diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 08b03de31dcf..98e4afbf148d 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache2::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query_cache::CachedLatestAtComponentResults, EntityDb}; use re_log_types::{external::arrow2, EntityPath}; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index 425cbc28eeca..61b96d4eade1 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -2,7 +2,7 @@ use egui::NumExt as _; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache2::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query_cache::CachedLatestAtComponentResults, EntityDb}; use re_log_types::EntityPath; use re_types::{ components::{ diff --git a/crates/re_data_ui/src/instance_path.rs b/crates/re_data_ui/src/instance_path.rs index a3369bc5a2b8..87155fa7ae46 100644 --- a/crates/re_data_ui/src/instance_path.rs +++ b/crates/re_data_ui/src/instance_path.rs @@ -76,7 +76,7 @@ impl DataUi for InstancePath { .num_columns(2) .show(ui, |ui| { for component_name in normal_components { - let results = db.query_caches2().latest_at( + let results = db.query_caches().latest_at( db.store(), query, entity_path, diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index 0b4bb51b6ad5..38e646d205a1 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -35,8 +35,7 @@ re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true re_query.workspace = true re_query2.workspace = true -re_query_cache.workspace = true -re_query_cache2 = { workspace = true, features = ["to_archetype"] } +re_query_cache = { workspace = true, features = ["to_archetype"] } re_smart_channel.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 68de41faeb7a..3027be02373a 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -116,14 +116,11 @@ pub struct EntityDb { /// Stores all components for all entities for all timelines. data_store: DataStore, - /// Query caches for the data in [`Self::data_store`]. - query_caches: re_query_cache::Caches, - /// The active promise resolver for this DB. resolver: re_query2::PromiseResolver, /// Query caches for the data in [`Self::data_store`]. - query_caches2: re_query_cache2::Caches, + query_caches: re_query_cache::Caches, stats: IngestionStatistics, } @@ -136,7 +133,6 @@ impl EntityDb { DataStoreConfig::default(), ); let query_caches = re_query_cache::Caches::new(&data_store); - let query_caches2 = re_query_cache2::Caches::new(&data_store); Self { data_source: None, set_store_info: None, @@ -146,9 +142,8 @@ impl EntityDb { times_per_timeline: Default::default(), tree: crate::EntityTree::root(), data_store, - query_caches, resolver: re_query2::PromiseResolver::default(), - query_caches2, + query_caches, stats: IngestionStatistics::new(store_id), } } @@ -201,11 +196,6 @@ impl EntityDb { &self.query_caches } - #[inline] - pub fn query_caches2(&self) -> &re_query_cache2::Caches { - &self.query_caches2 - } - #[inline] pub fn resolver(&self) -> &re_query2::PromiseResolver { &self.resolver @@ -219,21 +209,21 @@ impl EntityDb { query: &re_data_store::LatestAtQuery, ) -> PromiseResult> where - re_query_cache2::CachedLatestAtResults: re_query_cache2::ToArchetype, + re_query_cache::CachedLatestAtResults: re_query_cache::ToArchetype, { - let results = self.query_caches2().latest_at( + let results = self.query_caches().latest_at( self.store(), query, entity_path, A::all_components().iter().copied(), // no generics! ); - use re_query_cache2::ToArchetype as _; + use re_query_cache::ToArchetype as _; match results.to_archetype(self.resolver()).flatten() { PromiseResult::Pending => PromiseResult::Pending, PromiseResult::Error(err) => { - if let Some(err) = err.downcast_ref::() { - if matches!(err, re_query_cache2::QueryError::PrimaryNotFound(_)) { + if let Some(err) = err.downcast_ref::() { + if matches!(err, re_query_cache::QueryError::PrimaryNotFound(_)) { return PromiseResult::Ready(None); } } @@ -248,8 +238,8 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { - self.query_caches2().latest_at_component::( + ) -> Option> { + self.query_caches().latest_at_component::( self.store(), self.resolver(), entity_path, @@ -262,8 +252,8 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { - self.query_caches2().latest_at_component_quiet::( + ) -> Option> { + self.query_caches().latest_at_component_quiet::( self.store(), self.resolver(), entity_path, @@ -276,8 +266,8 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option<(EntityPath, re_query_cache2::CachedLatestAtMonoResult)> { - self.query_caches2() + ) -> Option<(EntityPath, re_query_cache::CachedLatestAtMonoResult)> { + self.query_caches() .latest_at_component_at_closest_ancestor::( self.store(), self.resolver(), @@ -477,7 +467,6 @@ impl EntityDb { let original_store_events = &[store_event]; self.times_per_timeline.on_events(original_store_events); self.query_caches.on_events(original_store_events); - self.query_caches2.on_events(original_store_events); let clear_cascade = self.tree.on_store_additions(original_store_events); // Second-pass: update the [`DataStore`] by applying the [`ClearCascade`]. @@ -487,7 +476,6 @@ impl EntityDb { let new_store_events = self.on_clear_cascade(clear_cascade); self.times_per_timeline.on_events(&new_store_events); self.query_caches.on_events(&new_store_events); - self.query_caches2.on_events(&new_store_events); let clear_cascade = self.tree.on_store_additions(&new_store_events); // Clears don't affect `Clear` components themselves, therefore we cannot have recursive @@ -643,15 +631,13 @@ impl EntityDb { times_per_timeline, tree, data_store: _, - query_caches, resolver: _, - query_caches2, + query_caches, stats: _, } = self; times_per_timeline.on_events(store_events); query_caches.on_events(store_events); - query_caches2.on_events(store_events); let store_events = store_events.iter().collect_vec(); let compacted = CompactedStoreEvents::new(&store_events); diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index 78a87c87a7d2..92389cc07aeb 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -44,7 +44,7 @@ pub use editable_auto_value::EditableAutoValue; pub mod external { pub use re_data_store; pub use re_query2; - pub use re_query_cache2; + pub use re_query_cache; } // ---------------------------------------------------------------------------- diff --git a/crates/re_query_cache/Cargo.toml b/crates/re_query_cache/Cargo.toml index be8c2adf62af..71a9dfbe35ef 100644 --- a/crates/re_query_cache/Cargo.toml +++ b/crates/re_query_cache/Cargo.toml @@ -20,26 +20,37 @@ all-features = true [features] -default = [] +default = ["to_archetype"] + +## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. +to_archetype = ["dep:re_types", "dep:re_types_blueprint"] [dependencies] # Rerun dependencies: re_data_store.workspace = true +re_error.workspace = true re_format.workspace = true re_log.workspace = true re_log_types.workspace = true -re_query.workspace = true +re_query2.workspace = true re_tracing.workspace = true re_types_core.workspace = true +# Rerun dependencies (optional): +re_types = { workspace = true, optional = true } +re_types_blueprint = { workspace = true, optional = true } + # External dependencies: ahash.workspace = true +anyhow.workspace = true +backtrace.workspace = true indent.workspace = true +indexmap.workspace = true itertools.workspace = true +nohash-hasher.workspace = true parking_lot.workspace = true paste.workspace = true seq-macro.workspace = true -static_assertions.workspace = true web-time.workspace = true @@ -56,11 +67,15 @@ similar-asserts.workspace = true bench = false +[[example]] +name = "latest_at_archetype" +required-features = ["to_archetype"] + + [[bench]] name = "flat_vec_deque" harness = false - [[bench]] name = "latest_at" harness = false diff --git a/crates/re_query_cache/benches/latest_at.rs b/crates/re_query_cache/benches/latest_at.rs index e74a7e0a20df..599c73726ef9 100644 --- a/crates/re_query_cache/benches/latest_at.rs +++ b/crates/re_query_cache/benches/latest_at.rs @@ -6,10 +6,12 @@ use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools; use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query_cache::Caches; +use re_query2::{clamped_zip_1x1, PromiseResolver}; +use re_query_cache::{CachedLatestAtResults, Caches}; use re_types::{ archetypes::Points2D, components::{Color, InstanceKey, Position2D, Text}, + Archetype as _, }; use re_types_core::Loggable as _; @@ -278,33 +280,47 @@ fn query_and_visit_points( store: &DataStore, paths: &[EntityPath], ) -> Vec { + let resolver = PromiseResolver::default(); + let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); - let mut points = Vec::with_capacity(NUM_POINTS as _); + let mut ret = Vec::with_capacity(NUM_POINTS as _); // TODO(jleibs): Add Radius once we have support for it in field_types - for path in paths { - caches - .query_archetype_pov1_comp1::( - store, - &query.clone().into(), - path, - |(_, _, positions, colors)| { - itertools::izip!(positions.iter(), colors.unwrap().iter()).for_each( - |(pos, color)| { - points.push(SavePoint { - _pos: *pos, - _color: *color, - }); - }, - ); - }, - ) - .unwrap(); + for entity_path in paths { + let results: CachedLatestAtResults = caches.latest_at( + store, + &query, + entity_path, + Points2D::all_components().iter().copied(), // no generics! + ); + + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Color::name()); + + let points = points + .iter_dense::(&resolver) + .flatten() + .unwrap() + .copied(); + + let colors = colors + .iter_dense::(&resolver) + .flatten() + .unwrap() + .copied(); + let color_default_fn = || Color::from(0xFF00FFFF); + + for (point, color) in clamped_zip_1x1(points, colors, color_default_fn) { + ret.push(SavePoint { + _pos: point, + _color: Some(color), + }); + } } - assert_eq!(NUM_POINTS as usize, points.len()); - points + assert_eq!(NUM_POINTS as usize, ret.len()); + ret } struct SaveString { @@ -316,28 +332,43 @@ fn query_and_visit_strings( store: &DataStore, paths: &[EntityPath], ) -> Vec { + let resolver = PromiseResolver::default(); + let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); let mut strings = Vec::with_capacity(NUM_STRINGS as _); - for path in paths { - caches - .query_archetype_pov1_comp1::( - store, - &query.clone().into(), - path, - |(_, _, _, labels)| { - for label in labels.unwrap() { - strings.push(SaveString { - _label: label.clone(), - }); - } - }, - ) - .unwrap(); + for entity_path in paths { + let results: CachedLatestAtResults = caches.latest_at( + store, + &query, + entity_path, + Points2D::all_components().iter().copied(), // no generics! + ); + + let points = results.get_required(Position2D::name()).unwrap(); + let colors = results.get_or_empty(Text::name()); + + let points = points + .iter_dense::(&resolver) + .flatten() + .unwrap() + .copied(); + + let labels = colors + .iter_dense::(&resolver) + .flatten() + .unwrap() + .cloned(); + let label_default_fn = || Text(String::new().into()); + + for (_point, label) in clamped_zip_1x1(points, labels, label_default_fn) { + strings.push(SaveString { + _label: Some(label), + }); + } } assert_eq!(NUM_STRINGS as usize, strings.len()); - criterion::black_box(strings) } diff --git a/crates/re_query_cache2/examples/latest_at.rs b/crates/re_query_cache/examples/latest_at.rs similarity index 98% rename from crates/re_query_cache2/examples/latest_at.rs rename to crates/re_query_cache/examples/latest_at.rs index c283aac83f0f..e894e10b63a1 100644 --- a/crates/re_query_cache2/examples/latest_at.rs +++ b/crates/re_query_cache/examples/latest_at.rs @@ -4,7 +4,7 @@ use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache2::{ +use re_query_cache::{ clamped_zip_1x2, CachedLatestAtComponentResults, CachedLatestAtResults, PromiseResolver, PromiseResult, }; @@ -22,7 +22,7 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query_cache2::Caches::new(&store); + let caches = re_query_cache::Caches::new(&store); // First, get the results for this query. // diff --git a/crates/re_query_cache2/examples/latest_at_archetype.rs b/crates/re_query_cache/examples/latest_at_archetype.rs similarity index 94% rename from crates/re_query_cache2/examples/latest_at_archetype.rs rename to crates/re_query_cache/examples/latest_at_archetype.rs index 03931bdeb081..94caab585ce2 100644 --- a/crates/re_query_cache2/examples/latest_at_archetype.rs +++ b/crates/re_query_cache/examples/latest_at_archetype.rs @@ -7,7 +7,7 @@ use re_types::{ }; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache2::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; +use re_query_cache::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; // --- @@ -22,7 +22,7 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query_cache2::Caches::new(&store); + let caches = re_query_cache::Caches::new(&store); // First, get the results for this query. // @@ -37,7 +37,7 @@ fn main() -> anyhow::Result<()> { // Then make use of the `ToArchetype` helper trait in order to query, resolve, deserialize and // cache an entire archetype all at once. - use re_query_cache2::ToArchetype as _; + use re_query_cache::ToArchetype as _; let arch: Points2D = match results.to_archetype(&resolver).flatten() { PromiseResult::Pending => { diff --git a/crates/re_query_cache2/examples/range.rs b/crates/re_query_cache/examples/range.rs similarity index 98% rename from crates/re_query_cache2/examples/range.rs rename to crates/re_query_cache/examples/range.rs index 45d46093beb0..e9bef34822eb 100644 --- a/crates/re_query_cache2/examples/range.rs +++ b/crates/re_query_cache/examples/range.rs @@ -4,7 +4,7 @@ use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache2::{ +use re_query_cache::{ clamped_zip_1x2, range_zip_1x2, CachedRangeComponentResults, CachedRangeResults, PromiseResolver, PromiseResult, }; @@ -22,7 +22,7 @@ fn main() -> anyhow::Result<()> { let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); eprintln!("query:{query:?}"); - let caches = re_query_cache2::Caches::new(&store); + let caches = re_query_cache::Caches::new(&store); // First, get the raw results for this query. // diff --git a/crates/re_query_cache/src/cache.rs b/crates/re_query_cache/src/cache.rs index 6b03a1b2fe5e..6ac7ee9ee433 100644 --- a/crates/re_query_cache/src/cache.rs +++ b/crates/re_query_cache/src/cache.rs @@ -1,194 +1,123 @@ use std::{ - collections::{BTreeMap, VecDeque}, - ops::Range, + collections::{BTreeMap, BTreeSet}, sync::Arc, }; use ahash::{HashMap, HashSet}; -use itertools::Itertools; use parking_lot::RwLock; -use paste::paste; -use seq_macro::seq; -use re_data_store::{DataStore, LatestAtQuery, RangeQuery, StoreDiff, StoreEvent, StoreSubscriber}; -use re_log_types::{EntityPath, RowId, StoreId, TimeInt, TimeRange, Timeline}; -use re_query::ArchetypeView; -use re_types_core::{ - components::InstanceKey, Archetype, ArchetypeName, Component, ComponentName, SizeBytes as _, -}; +use re_data_store::{DataStore, StoreDiff, StoreEvent, StoreSubscriber, TimeInt}; +use re_log_types::{EntityPath, StoreId, TimeRange, Timeline}; +use re_types_core::ComponentName; -use crate::{ErasedFlatVecDeque, FlatVecDeque, LatestAtCache, RangeCache}; +use crate::{LatestAtCache, RangeCache}; // --- -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum AnyQuery { - LatestAt(LatestAtQuery), - Range(RangeQuery), +/// Uniquely identifies cached query results in the [`Caches`]. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct CacheKey { + pub entity_path: EntityPath, + pub timeline: Timeline, + pub component_name: ComponentName, } -impl From for AnyQuery { +impl re_types_core::SizeBytes for CacheKey { #[inline] - fn from(query: LatestAtQuery) -> Self { - Self::LatestAt(query) + fn heap_size_bytes(&self) -> u64 { + let Self { + entity_path, + timeline, + component_name, + } = self; + entity_path.heap_size_bytes() + + timeline.heap_size_bytes() + + component_name.heap_size_bytes() } } -impl From for AnyQuery { +impl std::fmt::Debug for CacheKey { #[inline] - fn from(query: RangeQuery) -> Self { - Self::Range(query) - } -} - -// --- - -/// Maintains the top-level cache mappings. -pub struct Caches { - /// The [`StoreId`] of the associated [`DataStore`]. - store_id: StoreId, - - // NOTE: `Arc` so we can cheaply free the top-level lock early when needed. - per_cache_key: RwLock>>>, -} - -impl std::fmt::Debug for Caches { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { - store_id, - per_cache_key, + entity_path, + timeline, + component_name, } = self; - - let mut strings = Vec::new(); - - strings.push(format!("[Caches({store_id})]")); - - let per_cache_key = per_cache_key.read(); - let per_cache_key: BTreeMap<_, _> = per_cache_key.iter().collect(); - - for (cache_key, caches_per_archetype) in &per_cache_key { - let caches_per_archetype = caches_per_archetype.read(); - strings.push(format!( - " [{cache_key:?} (pending_temporal={:?} pending_timeless={:?})]", - caches_per_archetype - .pending_temporal_invalidation - .map(|t| cache_key - .timeline - .format_time_range_utc(&TimeRange::new(t, TimeInt::MAX))), - caches_per_archetype.pending_static_invalidation, - )); - strings.push(indent::indent_all_by( - 4, - format!("{caches_per_archetype:?}"), - )); - } - - f.write_str(&strings.join("\n").replace("\n\n", "\n")) + f.write_fmt(format_args!( + "{entity_path}:{component_name} on {}", + timeline.name() + )) } } -impl std::ops::Deref for Caches { - type Target = RwLock>>>; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.per_cache_key - } -} - -impl Caches { +impl CacheKey { #[inline] - pub fn new(store: &DataStore) -> Self { + pub fn new( + entity_path: impl Into, + timeline: impl Into, + component_name: impl Into, + ) -> Self { Self { - store_id: store.id().clone(), - per_cache_key: Default::default(), + entity_path: entity_path.into(), + timeline: timeline.into(), + component_name: component_name.into(), } } } -#[derive(Default)] -pub struct CachesPerArchetype { - /// Which [`Archetype`] are we querying for? - /// - /// This is very important because of our data model: we not only query for components, but we - /// query for components from a specific point-of-view (the so-called primary component). - /// Different archetypes have different point-of-views, and therefore can end up with different - /// results, even from the same raw data. - // - // NOTE: `Arc` so we can cheaply free the archetype-level lock early when needed. - // - // TODO(cmc): At some point we should probably just store the PoV and optional components rather - // than an `ArchetypeName`: the query system doesn't care about archetypes. - pub(crate) latest_at_per_archetype: RwLock>>>, - - /// Which [`Archetype`] are we querying for? - /// - /// This is very important because of our data model: we not only query for components, but we - /// query for components from a specific point-of-view (the so-called primary component). - /// Different archetypes have different point-of-views, and therefore can end up with different - /// results, even from the same raw data. - // - // NOTE: `Arc` so we can cheaply free the archetype-level lock early when needed. - // - // TODO(cmc): At some point we should probably just store the PoV and optional components rather - // than an `ArchetypeName`: the query system doesn't care about archetypes. - pub(crate) range_per_archetype: RwLock>>>, +pub struct Caches { + /// The [`StoreId`] of the associated [`DataStore`]. + pub(crate) store_id: StoreId, - /// Everything greater than or equal to this timestamp has been asynchronously invalidated. - /// - /// The next time this cache gets queried, it must remove any entry matching this criteria. - /// `None` indicates that there's no pending invalidation. - /// - /// Invalidation is deferred to query time because it is far more efficient that way: the frame - /// time effectively behaves as a natural micro-batching mechanism. - pending_temporal_invalidation: Option, + // NOTE: `Arc` so we can cheaply free the top-level lock early when needed. + pub(crate) latest_at_per_cache_key: RwLock>>>, - /// If `true`, the timeless data associated with this cache has been asynchronously invalidated. - /// - /// If `true`, this cache must remove all of its timeless entries the next time it gets queried. - /// `false` indicates that there's no pending invalidation. - /// - /// Invalidation is deferred to query time because it is far more efficient that way: the frame - /// time effectively behaves as a natural micro-batching mechanism. - pending_static_invalidation: bool, + // NOTE: `Arc` so we can cheaply free the top-level lock early when needed. + pub(crate) range_per_cache_key: RwLock>>>, } -impl std::fmt::Debug for CachesPerArchetype { +impl std::fmt::Debug for Caches { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let CachesPerArchetype { - latest_at_per_archetype, - range_per_archetype, - pending_temporal_invalidation: _, - pending_static_invalidation: _, + let Self { + store_id, + latest_at_per_cache_key, + range_per_cache_key, } = self; let mut strings = Vec::new(); + strings.push(format!("[LatestAt @ {store_id}]")); { - let latest_at_per_archetype = latest_at_per_archetype.read(); - let latest_at_per_archetype: BTreeMap<_, _> = latest_at_per_archetype.iter().collect(); + let latest_at_per_cache_key = latest_at_per_cache_key.read(); + let latest_at_per_cache_key: BTreeMap<_, _> = latest_at_per_cache_key.iter().collect(); - for (archetype_name, latest_at_cache) in &latest_at_per_archetype { - let latest_at_cache = latest_at_cache.read(); + for (cache_key, cache) in &latest_at_per_cache_key { + let cache = cache.read(); strings.push(format!( - "[latest_at for {archetype_name} ({})]", - re_format::format_bytes(latest_at_cache.total_size_bytes() as _) + " [{cache_key:?} (pending_invalidation_min={:?})]", + cache.pending_invalidations.first().map(|&t| cache_key + .timeline + .format_time_range_utc(&TimeRange::new(t, TimeInt::MAX))), )); - strings.push(indent::indent_all_by(2, format!("{latest_at_cache:?}"))); + strings.push(indent::indent_all_by(4, format!("{cache:?}"))); } } + strings.push(format!("[Range @ {store_id}]")); { - let range_per_archetype = range_per_archetype.read(); - let range_per_archetype: BTreeMap<_, _> = range_per_archetype.iter().collect(); + let range_per_cache_key = range_per_cache_key.read(); + let range_per_cache_key: BTreeMap<_, _> = range_per_cache_key.iter().collect(); - for (archetype_name, range_cache) in &range_per_archetype { - let range_cache = range_cache.read(); + for (cache_key, cache) in &range_per_cache_key { + let cache = cache.read(); strings.push(format!( - "[range for {archetype_name} ({})]", - re_format::format_bytes(range_cache.total_size_bytes() as _) + " [{cache_key:?} (pending_invalidation_min={:?})]", + cache.pending_invalidation.map(|t| cache_key + .timeline + .format_time_range_utc(&TimeRange::new(t, TimeInt::MAX))), )); - strings.push(indent::indent_all_by(2, format!("{range_cache:?}"))); + strings.push(indent::indent_all_by(4, format!("{cache:?}"))); } } @@ -197,236 +126,28 @@ impl std::fmt::Debug for CachesPerArchetype { } impl Caches { - /// Clears all caches. - #[inline] - pub fn clear(&self) { - self.write().clear(); - } - - /// Gives access to the appropriate `LatestAtCache` according to the specified - /// query parameters. - /// - /// `upsert` is a user-defined callback that will be run first, with full mutable access to the cache. - /// `iter` is a user-defined callback that will be run last, with shared access. - /// - /// These callback semantics allow for reentrancy: you can use the same cache from multiple - /// query contexts (i.e. space views), even in a work-stealing environment. - #[inline] - pub fn with_latest_at( - &self, - store: &DataStore, - entity_path: EntityPath, - query: &LatestAtQuery, - mut upsert: F1, - mut iter: F2, - ) -> (Option, R2) - where - A: Archetype, - F1: FnMut(&mut LatestAtCache) -> R1, - F2: FnMut(&LatestAtCache) -> R2, - { - assert!( - self.store_id == *store.id(), - "attempted to use a query cache {} with the wrong datastore ({})", - self.store_id, - store.id(), - ); - - let key = CacheKey::new(entity_path, query.timeline()); - - let cache = { - let caches_per_archetype = Arc::clone(self.write().entry(key.clone()).or_default()); - // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. - - let removed_bytes = caches_per_archetype.write().handle_pending_invalidation(); - // Implicitly releasing archetype-level cache mappings -- concurrent queries using the - // same `CacheKey` but a different `ArchetypeName` can run once again. - if removed_bytes > 0 { - re_log::trace!( - store_id=%self.store_id, - entity_path = %key.entity_path, - removed = removed_bytes, - "invalidated latest-at caches" - ); - } - - let caches_per_archetype = caches_per_archetype.read(); - let mut latest_at_per_archetype = caches_per_archetype.latest_at_per_archetype.write(); - Arc::clone(latest_at_per_archetype.entry(A::name()).or_default()) - // Implicitly releasing bottom-level cache mappings -- identical concurrent queries - // can run once again. - }; - - // # Multithreading semantics - // - // There is only one situation where this `try_write()` might fail: there is another task that - // is already in the process of upserting that specific cache (e.g. a cloned space view). - // - // That task might be on the same thread (due to work-stealing), or a different one. - // Either way, we need to give up trying to upsert the cache in order to prevent a - // deadlock in case the other task is in fact running on the same thread. - // - // It's fine, though: - // - Best case scenario, the data we need is already cached. - // - Worst case scenario, the data is missing and we'll be missing some data for the current - // frame. - // It'll get cached at some point in an upcoming frame (statistically, we're bound to win - // the race at some point). - // - // Data invalidation happens at the per-archetype cache layer, so this won't return - // out-of-date data in either scenario. - // - // There is a lot of complexity we could add to make this whole process more efficient: - // keep track of failed queries in a queue so we don't rely on probabilities, keep track - // of the thread-local reentrancy state to skip this logic when it's not needed, return raw - // data when the lock is busy and the data isn't already cached, etc. - // - // In the end, this is a edge-case inherent to our current "immediate query" model that we - // already know we want -- and have to -- move away from; the extra complexity isn't worth it. - let r1 = cache.try_write().map(|mut cache| upsert(&mut cache)); - // Implicitly releasing the write lock -- if any. - - // # Multithreading semantics - // - // We need the reentrant lock because query contexts (i.e. space views) generally run on a - // work-stealing thread-pool and might swap a task on one thread with another task on the - // same thread, where both tasks happen to query the same exact data (e.g. cloned space views). - // - // See comment above for more details. - let r2 = iter(&cache.read_recursive()); - - (r1, r2) - } - - /// Gives access to the appropriate `RangeCache` according to the specified query parameters. - /// - /// `upsert` is a user-defined callback that will be run first, with full mutable access to the cache. - /// `iter` is a user-defined callback that will be run last, with shared access. - /// - /// These callback semantics allow for reentrancy: you can use the same cache from multiple - /// query contexts (i.e. space views), even in a work-stealing environment. #[inline] - pub fn with_range( - &self, - store: &DataStore, - entity_path: EntityPath, - query: &RangeQuery, - mut upsert: F1, - mut iter: F2, - ) -> (Option, R2) - where - A: Archetype, - F1: FnMut(&mut RangeCache) -> R1, - F2: FnMut(&RangeCache) -> R2, - { - assert!( - self.store_id == *store.id(), - "attempted to use a query cache {} with the wrong datastore ({})", - self.store_id, - store.id(), - ); - - let key = CacheKey::new(entity_path, query.timeline); - - let cache = { - let caches_per_archetype = Arc::clone(self.write().entry(key.clone()).or_default()); - // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. - - let removed_bytes = caches_per_archetype.write().handle_pending_invalidation(); - // Implicitly releasing archetype-level cache mappings -- concurrent queries using the - // same `CacheKey` but a different `ArchetypeName` can run once again. - if removed_bytes > 0 { - re_log::trace!( - store_id=%self.store_id, - entity_path = %key.entity_path, - removed = removed_bytes, - "invalidated range caches" - ); - } - - let caches_per_archetype = caches_per_archetype.read(); - let mut range_per_archetype = caches_per_archetype.range_per_archetype.write(); - Arc::clone(range_per_archetype.entry(A::name()).or_default()) - // Implicitly releasing bottom-level cache mappings -- identical concurrent queries - // can run once again. - }; - - // # Multithreading semantics - // - // There is only one situation where this `try_write()` might fail: there is another task that - // is already in the process of upserting that specific cache (e.g. a cloned space view). - // - // That task might be on the same thread (due to work-stealing), or a different one. - // Either way, we need to give up trying to upsert the cache in order to prevent a - // deadlock in case the other task is in fact running on the same thread. - // - // It's fine, though: - // - Best case scenario, the data we need is already cached. - // - Worst case scenario, the data is missing and we'll be missing some data for the current - // frame. - // It'll get cached at some point in an upcoming frame (statistically, we're bound to win - // the race at some point). - // - // Data invalidation happens at the per-archetype cache layer, so this won't return - // out-of-date data in either scenario. - // - // There is a lot of complexity we could add to make this whole process more efficient: - // keep track of failed queries in a queue so we don't rely on probabilities, keep track - // of the thread-local reentrancy state to skip this logic when it's not needed, keep track - // of min-max timestamp values per entity so we can clamp range queries and thus know - // whether the data is already cached or not, etc. - // - // In the end, this is a edge-case inherent to our current "immediate query" model that we - // already know we want -- and have to -- move away from; the extra complexity isn't worth it. - let r1 = cache.try_write().map(|mut cache| upsert(&mut cache)); - // Implicitly releasing the write lock -- if any. - - // # Multithreading semantics - // - // We need the reentrant lock because query contexts (i.e. space views) generally run on a - // work-stealing thread-pool and might swap a task on one thread with another task on the - // same thread, where both tasks happen to query the same exact data (e.g. cloned space views). - // - // See comment above for more details. - let r2 = iter(&cache.read_recursive()); - - (r1, r2) + pub fn new(store: &DataStore) -> Self { + Self { + store_id: store.id().clone(), + latest_at_per_cache_key: Default::default(), + range_per_cache_key: Default::default(), + } } -} -/// Uniquely identifies cached query results in the [`Caches`]. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct CacheKey { - /// Which [`EntityPath`] is the query targeting? - pub entity_path: EntityPath, - - /// Which [`Timeline`] is the query targeting? - pub timeline: Timeline, -} - -impl std::fmt::Debug for CacheKey { #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + pub fn clear(&self) { let Self { - entity_path, - timeline, + store_id: _, + latest_at_per_cache_key, + range_per_cache_key, } = self; - f.write_fmt(format_args!("{entity_path} on {}", timeline.name())) - } -} -impl CacheKey { - #[inline] - pub fn new(entity_path: impl Into, timeline: impl Into) -> Self { - Self { - entity_path: entity_path.into(), - timeline: timeline.into(), - } + latest_at_per_cache_key.write().clear(); + range_per_cache_key.write().clear(); } } -// --- Invalidation --- - impl StoreSubscriber for Caches { #[inline] fn name(&self) -> String { @@ -446,6 +167,14 @@ impl StoreSubscriber for Caches { fn on_events(&mut self, events: &[StoreEvent]) { re_tracing::profile_function!(format!("num_events={}", events.len())); + #[derive(Default, Debug)] + struct CompactedEvents { + static_: HashSet<(EntityPath, ComponentName)>, + temporal: HashMap>, + } + + let mut compacted = CompactedEvents::default(); + for event in events { let StoreEvent { store_id, @@ -466,620 +195,76 @@ impl StoreSubscriber for Caches { row_id: _, times, entity_path, - cells: _, // Don't care: we invalidate at the entity level, not component level. + cells, } = diff; - #[derive(Default, Debug)] - struct CompactedEvents { - timeless: HashSet, - temporal: HashMap, - } - - let mut compacted = CompactedEvents::default(); { re_tracing::profile_scope!("compact events"); if times.is_empty() { - compacted.timeless.insert(entity_path.clone()); + for component_name in cells.keys() { + compacted + .static_ + .insert((entity_path.clone(), *component_name)); + } } - for &(timeline, time) in times { - let key = CacheKey::new(entity_path.clone(), timeline); - let min_time = compacted.temporal.entry(key).or_insert(TimeInt::MAX); - *min_time = TimeInt::min(*min_time, time); + for &(timeline, data_time) in times { + for component_name in cells.keys() { + let key = CacheKey::new(entity_path.clone(), timeline, *component_name); + let data_times = compacted.temporal.entry(key).or_default(); + data_times.insert(data_time); + } } } + } - let caches = self.write(); - // NOTE: Don't release the top-level lock -- even though this cannot happen yet with - // our current macro-architecture, we want to prevent queries from concurrently - // running while we're updating the invalidation flags. + let caches_latest_at = self.latest_at_per_cache_key.write(); + let caches_range = self.range_per_cache_key.write(); + // NOTE: Don't release the top-level locks -- even though this cannot happen yet with + // our current macro-architecture, we want to prevent queries from concurrently + // running while we're updating the invalidation flags. + + { + re_tracing::profile_scope!("static"); // TODO(cmc): This is horribly stupid and slow and can easily be made faster by adding // yet another layer of caching indirection. // But since this pretty much never happens in practice, let's not go there until we // have metrics showing that show we need to. - { - re_tracing::profile_scope!("timeless"); - - for entity_path in compacted.timeless { - for (key, caches_per_archetype) in caches.iter() { - if key.entity_path == entity_path { - caches_per_archetype.write().pending_static_invalidation = true; - } + for (entity_path, component_name) in compacted.static_ { + for (key, cache) in caches_latest_at.iter() { + if key.entity_path == entity_path && key.component_name == component_name { + cache.write().pending_invalidations.insert(TimeInt::STATIC); } } - } - { - re_tracing::profile_scope!("temporal"); - - for (key, time) in compacted.temporal { - if let Some(caches_per_archetype) = caches.get(&key) { - // NOTE: Do _NOT_ lock from within the if clause itself or the guard will live - // for the remainder of the if statement and hell will ensue. - // is - // supposed to catch that but it doesn't, I don't know why. - let mut caches_per_archetype = caches_per_archetype.write(); - if let Some(min_time) = - caches_per_archetype.pending_temporal_invalidation.as_mut() - { - *min_time = TimeInt::min(*min_time, time); - } else { - caches_per_archetype.pending_temporal_invalidation = Some(time); - } + for (key, cache) in caches_range.iter() { + if key.entity_path == entity_path && key.component_name == component_name { + cache.write().pending_invalidation = Some(TimeInt::STATIC); } } } } - } -} - -impl CachesPerArchetype { - /// Removes all entries from the cache that have been asynchronously invalidated. - /// - /// Invalidation is deferred to query time because it is far more efficient that way: the frame - /// time effectively behaves as a natural micro-batching mechanism. - /// - /// Returns the number of bytes removed. - fn handle_pending_invalidation(&mut self) -> u64 { - let pending_static_invalidation = self.pending_static_invalidation; - let pending_temporal_invalidation = self.pending_temporal_invalidation.is_some(); - - if !pending_static_invalidation && !pending_temporal_invalidation { - return 0; - } - - re_tracing::profile_function!(); - - let time_threshold = self.pending_temporal_invalidation.unwrap_or(TimeInt::MAX); - - self.pending_temporal_invalidation = None; - self.pending_static_invalidation = false; - - // Timeless being infinitely into the past, this effectively invalidates _everything_ with - // the current coarse-grained / archetype-level caching strategy. - if pending_static_invalidation { - re_tracing::profile_scope!("static"); - - let latest_at_removed_bytes = self - .latest_at_per_archetype - .read() - .values() - .map(|latest_at_cache| latest_at_cache.read().total_size_bytes()) - .sum::(); - let range_removed_bytes = self - .range_per_archetype - .read() - .values() - .map(|range_cache| range_cache.read().total_size_bytes()) - .sum::(); - - *self = CachesPerArchetype::default(); - - return latest_at_removed_bytes + range_removed_bytes; - } - - re_tracing::profile_scope!("temporal"); - - let mut removed_bytes = 0u64; - - for latest_at_cache in self.latest_at_per_archetype.read().values() { - let mut latest_at_cache = latest_at_cache.write(); - removed_bytes = - removed_bytes.saturating_add(latest_at_cache.truncate_at_time(time_threshold)); - } - - for range_cache in self.range_per_archetype.read().values() { - let mut range_cache = range_cache.write(); - removed_bytes = - removed_bytes.saturating_add(range_cache.truncate_at_time(time_threshold)); - } - - removed_bytes - } -} - -// --- - -/// Caches the results of any query for an arbitrary range of time. -/// -/// This caches all the steps involved in getting data ready for space views: -/// - index search, -/// - instance key joining, -/// - deserialization. -/// -/// We share the `CacheBucket` implementation between all types of queries to avoid duplication of -/// logic, especially for things that require metaprogramming, to keep the macro madness to a -/// minimum. -/// In the case of `LatestAt` queries, a `CacheBucket` will always contain a single timestamp worth -/// of data. -#[derive(Default)] -pub struct CacheBucket { - /// The _data_ timestamps and [`RowId`]s of all cached rows. - /// - /// This corresponds to the data time and `RowId` returned by `re_query::query_archetype`. - /// - /// This is guaranteed to always be sorted and dense (i.e. there cannot be a hole in the cached - /// data, unless the raw data itself in the store has a hole at that particular point in time). - /// - /// Reminder: within a single timestamp, rows are sorted according to their [`RowId`]s. - /// - /// Invariant: `data_times.len() == pov_instance_keys.num_entries()` - pub(crate) data_times: VecDeque<(TimeInt, RowId)>, - - /// The [`InstanceKey`]s of the point-of-view components. - /// - /// Invariant: `data_times.len() == pov_instance_keys.num_entries()` - pub(crate) pov_instance_keys: FlatVecDeque, - - /// The resulting component data, pre-deserialized, pre-joined. - /// - /// All the contained FlatVecDeques have the same length as `data_times`. - // - // TODO(#4733): Don't denormalize auto-generated instance keys. - // TODO(#4734): Don't denormalize splatted values. - pub(crate) components: BTreeMap>, - - /// The total size in bytes stored in this bucket. - /// - /// Only used so we can decrement the global cache size when the last reference to a bucket - /// gets dropped. - pub(crate) total_size_bytes: u64, - // - // TODO(cmc): secondary cache -} - -impl std::fmt::Debug for CacheBucket { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - data_times: _, - pov_instance_keys: _, - components, - total_size_bytes: _, - } = self; - - let strings = components - .iter() - .filter(|(_, data)| data.dyn_num_values() > 0) - .map(|(name, data)| { - format!( - "{} {name} values spread across {} entries ({})", - data.dyn_num_values(), - data.dyn_num_entries(), - re_format::format_bytes(data.dyn_total_size_bytes() as _), - ) - }) - .collect_vec(); - - f.write_str(&strings.join("\n").replace("\n\n", "\n")) - } -} - -impl CacheBucket { - // Check invariants in debug builds - fn sanity_check(&self) { - if cfg!(debug_assertions) { - assert_eq!(self.data_times.len(), self.pov_instance_keys.num_entries()); - let n = self.data_times.len(); - for (name, data) in &self.components { - assert_eq!(data.dyn_num_entries(), n, "{name}"); - } - } - } - - #[inline] - pub fn time_range(&self) -> Option { - let first_time = self.data_times.front().map(|(t, _)| *t)?; - let last_time = self.data_times.back().map(|(t, _)| *t)?; - Some(TimeRange::new(first_time, last_time)) - } - - #[inline] - pub fn contains_data_time(&self, data_time: TimeInt) -> bool { - let first_time = self.data_times.front().map_or(&TimeInt::MAX, |(t, _)| t); - let last_time = self.data_times.back().map_or(&TimeInt::MIN, |(t, _)| t); - *first_time <= data_time && data_time <= *last_time - } - - #[inline] - pub fn contains_data_row(&self, data_time: TimeInt, row_id: RowId) -> bool { - self.data_times.binary_search(&(data_time, row_id)).is_ok() - } - - /// How many timestamps' worth of data is stored in this bucket? - #[inline] - pub fn num_entries(&self) -> usize { - self.data_times.len() - } - - #[inline] - pub fn is_empty(&self) -> bool { - self.num_entries() == 0 - } - - // --- - - /// Iterate over the timestamps of the point-of-view components. - #[inline] - pub fn iter_data_times(&self) -> impl Iterator { - self.data_times.iter() - } - - /// Iterate over the [`InstanceKey`] batches of the point-of-view components. - #[inline] - pub fn iter_pov_instance_keys(&self) -> impl Iterator { - self.pov_instance_keys.iter() - } - - /// Iterate over the batches of the specified non-optional component. - #[inline] - pub fn iter_component(&self) -> Option> { - let data = self - .components - .get(&C::name()) - .and_then(|data| data.as_any().downcast_ref::>())?; - Some(data.iter()) - } - - /// Iterate over the batches of the specified optional component. - #[inline] - pub fn iter_component_opt(&self) -> Option]>> { - let data = self - .components - .get(&C::name()) - .and_then(|data| data.as_any().downcast_ref::>>())?; - Some(data.iter()) - } - - // --- - - /// Returns the index range that corresponds to the static data (if any). - /// - /// Use the returned range with one of the range iteration methods: - /// - [`Self::range_data_times`] - /// - [`Self::range_pov_instance_keys`] - /// - [`Self::range_component`] - /// - [`Self::range_component_opt`] - /// - /// Make sure that the bucket hasn't been modified in-between! - /// - /// This is `O(2*log(n))`, so make sure to clone the returned range rather than calling this - /// multiple times. - #[inline] - pub fn static_range(&self) -> Range { - static_assertions::const_assert_eq!(TimeInt::STATIC.as_i64(), i64::MIN); - let start_index = 0; - let end_index = self - .data_times - .partition_point(|(data_time, _)| data_time <= &TimeInt::STATIC); - start_index..end_index - } - - /// Returns the index range that corresponds to the specified `time_range`. - /// - /// Use the returned range with one of the range iteration methods: - /// - [`Self::range_data_times`] - /// - [`Self::range_pov_instance_keys`] - /// - [`Self::range_component`] - /// - [`Self::range_component_opt`] - /// - /// Make sure that the bucket hasn't been modified in-between! - /// - /// This is `O(2*log(n))`, so make sure to clone the returned range rather than calling this - /// multiple times. - #[inline] - pub fn entry_range(&self, time_range: TimeRange) -> Range { - let start_index = self - .data_times - .partition_point(|(data_time, _)| data_time < &time_range.min()); - let end_index = self - .data_times - .partition_point(|(data_time, _)| data_time <= &time_range.max()); - start_index..end_index - } - - /// Range over the timestamps of the point-of-view components. - #[inline] - pub fn range_data_times( - &self, - entry_range: Range, - ) -> impl Iterator { - self.data_times.range(entry_range) - } - - /// Range over the [`InstanceKey`] batches of the point-of-view components. - #[inline] - pub fn range_pov_instance_keys( - &self, - entry_range: Range, - ) -> impl Iterator { - self.pov_instance_keys.range(entry_range) - } - - /// Get the raw batches for the specified non-optional component. - #[inline] - pub fn component(&self) -> Option<&FlatVecDeque> { - self.components - .get(&C::name()) - .and_then(|data| data.as_any().downcast_ref::>()) - } - - /// Range over the batches of the specified non-optional component. - #[inline] - pub fn range_component( - &self, - entry_range: Range, - ) -> Option> { - let data = self - .components - .get(&C::name()) - .and_then(|data| data.as_any().downcast_ref::>())?; - Some(data.range(entry_range)) - } - - /// Get the raw batches for the specified optional component. - #[inline] - pub fn component_opt(&self) -> Option<&FlatVecDeque>> { - self.components - .get(&C::name()) - .and_then(|data| data.as_any().downcast_ref::>>()) - } - - /// Range over the batches of the specified optional component. - #[inline] - pub fn range_component_opt( - &self, - entry_range: Range, - ) -> Option]>> { - let data = self - .components - .get(&C::name()) - .and_then(|data| data.as_any().downcast_ref::>>())?; - Some(data.range(entry_range)) - } - - /// Removes everything from the bucket that corresponds to a time equal or greater than the - /// specified `threshold`. - /// - /// Returns the number of bytes removed. - #[inline] - pub fn truncate_at_time(&mut self, threshold: TimeInt) -> u64 { - self.sanity_check(); - - let Self { - data_times, - pov_instance_keys, - components, - total_size_bytes, - } = self; - - let mut removed_bytes = 0u64; - - let threshold_idx = data_times.partition_point(|(data_time, _)| data_time < &threshold); - - { - let total_size_bytes_before = data_times.total_size_bytes(); - data_times.truncate(threshold_idx); - removed_bytes += total_size_bytes_before - data_times.total_size_bytes(); - } { - let total_size_bytes_before = pov_instance_keys.total_size_bytes(); - pov_instance_keys.truncate(threshold_idx); - removed_bytes += total_size_bytes_before - pov_instance_keys.total_size_bytes(); - } - - for data in components.values_mut() { - let total_size_bytes_before = data.dyn_total_size_bytes(); - data.dyn_truncate(threshold_idx); - removed_bytes += total_size_bytes_before - data.dyn_total_size_bytes(); - } - - *total_size_bytes = total_size_bytes - .checked_sub(removed_bytes) - .unwrap_or_else(|| { - re_log::debug!( - current = *total_size_bytes, - removed = removed_bytes, - "book keeping underflowed" - ); - u64::MIN - }); - - self.sanity_check(); - - removed_bytes - } -} - -macro_rules! impl_insert { - (for N=$N:expr, M=$M:expr => povs=[$($pov:ident)+] comps=[$($comp:ident)*]) => { paste! { - #[doc = "Inserts the contents of the given [`ArchetypeView`], which are made of the specified"] - #[doc = "`" $N "` point-of-view components and `" $M "` optional components, to the cache."] - #[doc = ""] - #[doc = "Returns the size in bytes of the data that was cached."] - #[doc = ""] - #[doc = "`query_time` must be the time of query, _not_ of the resulting data."] - pub fn []( - &mut self, - query_time: TimeInt, - arch_view: &ArchetypeView, - ) -> ::re_query::Result - where - A: Archetype, - $($pov: Component,)+ - $($comp: Component,)* - { - // NOTE: not `profile_function!` because we want them merged together. - re_tracing::profile_scope!("CacheBucket::insert", format!("arch={} pov={} comp={}", A::name(), $N, $M)); - - self.sanity_check(); - - let pov_row_id = arch_view.primary_row_id(); - let index = self.data_times.partition_point(|t| t < &(query_time, pov_row_id)); - - let mut added_size_bytes = 0u64; - - self.data_times.insert(index, (query_time, pov_row_id)); - added_size_bytes += (query_time, pov_row_id).total_size_bytes(); + re_tracing::profile_scope!("temporal"); + + for (key, times) in compacted.temporal { + if let Some(cache) = caches_latest_at.get(&key) { + cache + .write() + .pending_invalidations + .extend(times.iter().copied()); + } - { - // The `FlatVecDeque` will have to collect the data one way or another: do it ourselves - // instead, that way we can efficiently compute its size while we're at it. - let added: FlatVecDeque = arch_view - .iter_instance_keys() - .collect::>() - .into(); - added_size_bytes += added.total_size_bytes(); - self.pov_instance_keys.insert_deque(index, added); + if let Some(cache) = caches_range.get(&key) { + let pending_invalidation = &mut cache.write().pending_invalidation; + let min_time = times.first().copied(); + *pending_invalidation = + Option::min(*pending_invalidation, min_time).or(min_time); + } } - - $(added_size_bytes += self.insert_component::(index, arch_view)?;)+ - $(added_size_bytes += self.insert_component_opt::(index, arch_view)?;)* - - self.sanity_check(); - - self.total_size_bytes += added_size_bytes; - - Ok(added_size_bytes) - } } - }; - - // TODO(cmc): Supporting N>1 generically is quite painful due to limitations in declarative macros, - // not that we care at the moment. - (for N=1, M=$M:expr) => { - seq!(COMP in 1..=$M { - impl_insert!(for N=1, M=$M => povs=[R1] comps=[#(C~COMP)*]); - }); - }; -} - -impl CacheBucket { - /// Alias for [`Self::insert_pov1_comp0`]. - #[inline] - #[allow(dead_code)] - fn insert_pov1( - &mut self, - query_time: TimeInt, - arch_view: &ArchetypeView, - ) -> ::re_query::Result - where - A: Archetype, - R1: Component, - { - self.insert_pov1_comp0::(query_time, arch_view) - } - - seq!(NUM_COMP in 0..10 { - impl_insert!(for N=1, M=NUM_COMP); - }); - - #[inline] - fn insert_component( - &mut self, - at: usize, - arch_view: &ArchetypeView, - ) -> re_query::Result { - re_tracing::profile_function!(C::name()); - // no sanity checks here - we are called while in an invariant-breaking state! - - let num_entries = self.data_times.len(); - - let data = self.components.entry(C::name()).or_insert_with(|| { - Box::new(FlatVecDeque::::from_vecs( - std::iter::repeat(vec![]).take( - num_entries - .checked_sub(1) - .expect("We should have been called AFTER inserting to data_times"), - ), - )) - }); - - debug_assert!(at <= data.dyn_num_entries()); - - // The `FlatVecDeque` will have to collect the data one way or another: do it ourselves - // instead, that way we can efficiently compute its size while we're at it. - let added: FlatVecDeque = arch_view - .iter_required_component::()? - .collect::>() - .into(); - let added_size_bytes = added.total_size_bytes(); - - // NOTE: downcast cannot fail, we create it just above. - let data = data.as_any_mut().downcast_mut::>().unwrap(); - data.insert_deque(at, added); - - Ok(added_size_bytes) - } - - /// This will insert an empty slice for a missing component (instead of N `None` values). - #[inline] - fn insert_component_opt( - &mut self, - at: usize, - arch_view: &ArchetypeView, - ) -> re_query::Result { - re_tracing::profile_function!(C::name()); - // no sanity checks here - we are called while in an invariant-breaking state! - - let num_entries = self.num_entries(); - - let data = self.components.entry(C::name()).or_insert_with(|| { - Box::new(FlatVecDeque::>::from_vecs( - std::iter::repeat(vec![]).take( - num_entries - .checked_sub(1) - .expect("We should have been called AFTER inserting to data_times"), - ), - )) - }); - - debug_assert!(at <= data.dyn_num_entries()); - - let added: FlatVecDeque> = if arch_view.has_component::() { - // The `FlatVecDeque` will have to collect the data one way or another: do it ourselves - // instead, that way we can efficiently computes its size while we're at it. - arch_view - .iter_optional_component::()? - .collect::>>() - .into() - } else { - // If an optional component is missing entirely, we just store an empty slice in its - // stead, rather than a bunch of `None` values. - let mut added = FlatVecDeque::>::new(); - added.push_back(std::iter::empty()); - added - }; - let added_size_bytes = added.total_size_bytes(); - - // NOTE: downcast cannot fail, we create it just above. - let data = data - .as_any_mut() - .downcast_mut::>>() - .unwrap(); - data.insert_deque(at, added); - - Ok(added_size_bytes) + } } } diff --git a/crates/re_query_cache/src/cache_stats.rs b/crates/re_query_cache/src/cache_stats.rs index 7c360454f000..7c205f5a8321 100644 --- a/crates/re_query_cache/src/cache_stats.rs +++ b/crates/re_query_cache/src/cache_stats.rs @@ -1,9 +1,9 @@ use std::collections::BTreeMap; -use re_log_types::{EntityPath, TimeRange, Timeline}; -use re_types_core::{components::InstanceKey, ComponentName, Loggable as _, SizeBytes as _}; +use re_log_types::TimeRange; +use re_types_core::SizeBytes as _; -use crate::{cache::CacheBucket, Caches, LatestAtCache, RangeCache}; +use crate::{CacheKey, Caches}; // --- @@ -12,8 +12,8 @@ use crate::{cache::CacheBucket, Caches, LatestAtCache, RangeCache}; /// Fetch them via [`Caches::stats`]. #[derive(Default, Debug, Clone)] pub struct CachesStats { - pub latest_at: BTreeMap, - pub range: BTreeMap>, + pub latest_at: BTreeMap, + pub range: BTreeMap, CachedComponentStats)>, } impl CachesStats { @@ -27,171 +27,73 @@ impl CachesStats { latest_at.values().map(|stats| stats.total_size_bytes).sum(); let range_size_bytes: u64 = range .values() - .flat_map(|all_ranges| { - all_ranges - .iter() - .map(|(_, _, stats)| stats.total_size_bytes) - }) + .map(|(_, stats)| stats.total_size_bytes) .sum(); latest_at_size_bytes + range_size_bytes } } -/// Stats for a cached entity. -#[derive(Debug, Clone)] -pub struct CachedEntityStats { - pub total_rows: u64, - pub total_size_bytes: u64, - - /// Only if `detailed_stats` is `true` (see [`Caches::stats`]). - pub per_component: Option>, -} - -impl CachedEntityStats { - #[inline] - pub fn is_empty(&self) -> bool { - // NOTE: That looks non-sensical, but it can happen if the cache is bugged, which we'd like - // to know. - self.total_rows == 0 && self.total_size_bytes == 0 - } -} - /// Stats for a cached component. #[derive(Default, Debug, Clone)] pub struct CachedComponentStats { - pub total_rows: u64, + pub total_indices: u64, pub total_instances: u64, pub total_size_bytes: u64, } impl Caches { /// Computes the stats for all primary caches. - /// - /// `per_component` toggles per-component stats. - pub fn stats(&self, detailed_stats: bool) -> CachesStats { + pub fn stats(&self) -> CachesStats { re_tracing::profile_function!(); - fn upsert_bucket_stats( - per_component: &mut BTreeMap, - bucket: &CacheBucket, - ) { - let CacheBucket { - data_times, - pov_instance_keys, - components, - total_size_bytes: _, - } = bucket; - - { - let stats: &mut CachedComponentStats = - per_component.entry("".into()).or_default(); - stats.total_rows += data_times.len() as u64; - stats.total_instances += data_times.len() as u64; - stats.total_size_bytes += data_times.total_size_bytes(); - } - - { - let stats: &mut CachedComponentStats = - per_component.entry(InstanceKey::name()).or_default(); - stats.total_rows += pov_instance_keys.num_entries() as u64; - stats.total_instances += pov_instance_keys.num_values() as u64; - stats.total_size_bytes += pov_instance_keys.total_size_bytes(); - } - - for (component_name, data) in components { - let stats: &mut CachedComponentStats = - per_component.entry(*component_name).or_default(); - stats.total_rows += data.dyn_num_entries() as u64; - stats.total_instances += data.dyn_num_values() as u64; - stats.total_size_bytes += data.dyn_total_size_bytes(); - } - } - - let caches = self.read().clone(); - // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. - - let latest_at = caches - .iter() - .map(|(key, caches_per_arch)| { - (key.entity_path.clone(), { - let mut total_size_bytes = 0u64; - let mut total_rows = 0u64; - let mut per_component = detailed_stats.then(BTreeMap::default); - - for latest_at_cache in caches_per_arch - .read() - .latest_at_per_archetype - .read() - .values() - { - let latest_at_cache @ LatestAtCache { - per_query_time: _, - per_data_time, - .. - } = &*latest_at_cache.read(); - - total_size_bytes += latest_at_cache.total_size_bytes(); - total_rows = per_data_time.len() as u64; - - if let Some(per_component) = per_component.as_mut() { - re_tracing::profile_scope!("detailed"); - - for bucket in per_data_time.values() { - upsert_bucket_stats(per_component, bucket); - } - } - } - - CachedEntityStats { - total_size_bytes, - total_rows, - - per_component, - } + let latest_at = { + let latest_at = self.latest_at_per_cache_key.read_recursive().clone(); + // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. + + latest_at + .iter() + .map(|(key, cache)| { + let cache = cache.read_recursive(); + ( + key.clone(), + CachedComponentStats { + total_indices: cache.per_data_time.len() as _, + total_instances: cache + .per_data_time + .values() + .map(|results| results.num_instances()) + .sum(), + total_size_bytes: cache.total_size_bytes(), + }, + ) }) - }) - .collect(); - - let range = caches - .iter() - .map(|(key, caches_per_arch)| { - (key.entity_path.clone(), { - caches_per_arch - .read() - .range_per_archetype - .read() - .values() - .map(|range_cache| { - let range_cache @ RangeCache { - per_data_time, - timeline: _, - } = &*range_cache.read(); - - let total_rows = per_data_time.data_times.len() as u64; - - let mut per_component = detailed_stats.then(BTreeMap::default); - if let Some(per_component) = per_component.as_mut() { - re_tracing::profile_scope!("detailed"); - - upsert_bucket_stats(per_component, per_data_time); - } - - ( - key.timeline, - per_data_time.time_range().unwrap_or(TimeRange::EMPTY), - CachedEntityStats { - total_size_bytes: range_cache.total_size_bytes(), - total_rows, - - per_component, - }, - ) - }) - .collect() + .collect() + }; + + let range = { + let range = self.range_per_cache_key.read_recursive().clone(); + // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. + + range + .iter() + .map(|(key, cache)| { + let cache = cache.read_recursive(); + let cache = cache.per_data_time.read_recursive(); + ( + key.clone(), + ( + cache.time_range(), + CachedComponentStats { + total_indices: cache.indices.len() as _, + total_instances: cache.num_instances(), + total_size_bytes: cache.total_size_bytes(), + }, + ), + ) }) - }) - .collect(); + .collect() + }; CachesStats { latest_at, range } } diff --git a/crates/re_query_cache/src/flat_vec_deque.rs b/crates/re_query_cache/src/flat_vec_deque.rs index 8cc9abc9b1a8..1a89f41628e9 100644 --- a/crates/re_query_cache/src/flat_vec_deque.rs +++ b/crates/re_query_cache/src/flat_vec_deque.rs @@ -165,6 +165,17 @@ impl From> for FlatVecDeque { } } +impl From> for FlatVecDeque { + #[inline] + fn from(values: Vec) -> Self { + let num_values = values.len(); + Self { + values: values.into(), + offsets: std::iter::once(num_values).collect(), + } + } +} + impl Default for FlatVecDeque { #[inline] fn default() -> Self { diff --git a/crates/re_query_cache/src/latest_at.rs b/crates/re_query_cache/src/latest_at.rs deleted file mode 100644 index 4804b513801d..000000000000 --- a/crates/re_query_cache/src/latest_at.rs +++ /dev/null @@ -1,332 +0,0 @@ -use std::{collections::BTreeMap, sync::Arc}; - -use ahash::HashMap; -use paste::paste; -use seq_macro::seq; - -use re_data_store::{DataStore, LatestAtQuery, TimeInt}; -use re_log_types::{EntityPath, RowId, Timeline}; -use re_query::query_archetype; -use re_types_core::{components::InstanceKey, Archetype, Component, SizeBytes}; - -use crate::{CacheBucket, Caches}; - -// --- Data structures --- - -/// Caches the results of `LatestAt` queries. -#[derive(Default)] -pub struct LatestAtCache { - /// Organized by _query_ time. - /// - /// If the data you're looking for isn't in here, try partially running the query and check - /// if there is any data available for the resulting _data_ time in [`Self::per_data_time`]. - // - // NOTE: `Arc` so we can deduplicate buckets across query time & data time. - pub per_query_time: BTreeMap>, - - /// Organized by _data_ time. - /// - /// Due to how our latest-at semantics work, any number of queries at time `T+n` where `n >= 0` - /// can result in a data time of `T`. - // - // NOTE: `Arc` so we can deduplicate buckets across query time & data time. - pub per_data_time: BTreeMap>, - - /// For debugging purposes. - pub(crate) timeline: Timeline, - - /// Total size of the data stored in this cache in bytes. - total_size_bytes: u64, -} - -impl std::fmt::Debug for LatestAtCache { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - per_query_time, - per_data_time, - timeline, - total_size_bytes: _, - } = self; - - let mut strings = Vec::new(); - - let data_times_per_bucket: HashMap<_, _> = per_data_time - .iter() - .map(|(time, bucket)| (Arc::as_ptr(bucket), *time)) - .collect(); - - for (query_time, bucket) in per_query_time { - let query_time = timeline.typ().format_utc(*query_time); - let data_time = data_times_per_bucket - .get(&Arc::as_ptr(bucket)) - .map_or_else(|| "MISSING?!".to_owned(), |t| timeline.typ().format_utc(*t)); - strings.push(format!( - "query_time={query_time} -> data_time={data_time} ({})", - re_format::format_bytes(bucket.total_size_bytes as _), - )); - strings.push(indent::indent_all_by(2, format!("{bucket:?}"))); - } - - f.write_str(&strings.join("\n").replace("\n\n", "\n")) - } -} - -impl SizeBytes for LatestAtCache { - #[inline] - fn heap_size_bytes(&self) -> u64 { - self.total_size_bytes - } -} - -impl LatestAtCache { - /// Removes everything from the cache that corresponds to a time equal or greater than the - /// specified `threshold`. - /// - /// Reminder: invalidating static data is the same as invalidating everything, so just reset - /// the `LatestAtCache` entirely in that case. - /// - /// Returns the number of bytes removed. - #[inline] - pub fn truncate_at_time(&mut self, threshold: TimeInt) -> u64 { - let Self { - per_query_time, - per_data_time, - timeline: _, - total_size_bytes, - } = self; - - let mut removed_bytes = 0u64; - - per_query_time.retain(|&query_time, _| query_time < threshold); - - // Buckets for latest-at queries are guaranteed to only ever contain a single entry, so - // just remove the buckets entirely directly. - per_data_time.retain(|&data_time, bucket| { - if data_time < threshold { - return true; - } - - // Only if that bucket is about to be dropped. - if Arc::strong_count(bucket) == 1 { - removed_bytes += bucket.total_size_bytes; - } - - false - }); - - *total_size_bytes = total_size_bytes - .checked_sub(removed_bytes) - .unwrap_or_else(|| { - re_log::debug!( - current = *total_size_bytes, - removed = removed_bytes, - "book keeping underflowed" - ); - u64::MIN - }); - - removed_bytes - } -} - -// --- Queries --- - -macro_rules! impl_query_archetype_latest_at { - (for N=$N:expr, M=$M:expr => povs=[$($pov:ident)+] comps=[$($comp:ident)*]) => { paste! { - #[doc = "Cached implementation of [`re_query::query_archetype`] and [`re_query::range_archetype`]"] - #[doc = "(combined) for `" $N "` point-of-view components and `" $M "` optional components."] - #[allow(non_snake_case)] - pub fn []<'a, A, $($pov,)+ $($comp,)* F>( - &self, - store: &'a DataStore, - query: &LatestAtQuery, - entity_path: &'a EntityPath, - mut f: F, - ) -> ::re_query::Result<()> - where - A: Archetype + 'a, - $($pov: Component,)+ - $($comp: Component,)* - F: FnMut( - ( - (TimeInt, RowId), - &[InstanceKey], - $(&[$pov],)+ - $(Option<&[Option<$comp>]>,)* - ), - ), - { - let iter_results = |bucket: &crate::CacheBucket, f: &mut F| -> crate::Result<()> { - // Profiling this in isolation can be useful, but adds a lot of noise for small queries. - // re_tracing::profile_scope!("iter"); - - let it = itertools::izip!( - bucket.iter_data_times(), - bucket.iter_pov_instance_keys(), - $(bucket.iter_component::<$pov>() - .ok_or_else(|| re_query::ComponentNotFoundError(<$pov>::name()))?,)+ - $(bucket.iter_component_opt::<$comp>() - .map_or_else( - || itertools::Either::Left(std::iter::repeat(&[] as &[Option<$comp>])), - |it| itertools::Either::Right(it)), - )* - ).map(|((time, row_id), instance_keys, $($pov,)+ $($comp,)*)| { - ( - (*time, *row_id), - instance_keys, - $($pov,)+ - $((!$comp.is_empty()).then_some($comp),)* - ) - }); - - for data in it { - f(data); - } - - Ok(()) - }; - - let create_and_fill_bucket = | - data_time: TimeInt, - arch_view: &::re_query::ArchetypeView, - | -> crate::Result { - re_log::trace!(data_time=?data_time, ?data_time, "fill"); - - // Grabbing the current time is quite costly on web. - #[cfg(not(target_arch = "wasm32"))] - let now = web_time::Instant::now(); - - let mut bucket = crate::CacheBucket::default(); - bucket.[]::(data_time, &arch_view)?; - - #[cfg(not(target_arch = "wasm32"))] - { - let elapsed = now.elapsed(); - ::re_log::trace!( - store_id=%store.id(), - %entity_path, - archetype=%A::name(), - added_size_bytes=bucket.total_size_bytes, - "cached new entry in {elapsed:?} ({:0.3} entries/s)", - 1f64 / elapsed.as_secs_f64() - ); - } - - Ok(bucket) - }; - - let upsert_callback = |query: &LatestAtQuery, latest_at_cache: &mut crate::LatestAtCache| -> crate::Result<()> { - re_tracing::profile_scope!("latest_at", format!("{query:?}")); - - let crate::LatestAtCache { - per_query_time, - per_data_time, - timeline: _, - total_size_bytes, - } = latest_at_cache; - - let query_time_bucket_at_query_time = match per_query_time.entry(query.at()) { - std::collections::btree_map::Entry::Occupied(_) => { - // Fastest path: we have an entry for this exact query time, no need to look any - // further. - re_log::trace!(query_time=?query.at(), "cache hit (query time)"); - return Ok(()); - } - std::collections::btree_map::Entry::Vacant(entry) => entry, - }; - - let arch_view = query_archetype::(store, &query, entity_path)?; - let data_time = arch_view.data_time(); - - // Fast path: we've run the query and realized that we already have the data for the resulting - // _data_ time, so let's use that to avoid join & deserialization costs. - if let Some(data_time_bucket_at_data_time) = per_data_time.get(&data_time) { - re_log::trace!(query_time=?query.at(), ?data_time, "cache hit (data time)"); - - query_time_bucket_at_query_time.insert(Arc::clone(&data_time_bucket_at_data_time)); - - // We now know for a fact that a query at that data time would yield the same - // results: copy the bucket accordingly so that the next cache hit for that query - // time ends up taking the fastest path. - let query_time_bucket_at_data_time = per_query_time.entry(data_time); - query_time_bucket_at_data_time - .and_modify(|v| *v = Arc::clone(&data_time_bucket_at_data_time)) - .or_insert(Arc::clone(&data_time_bucket_at_data_time)); - - return Ok(()); - } - - // Slowest path: this is a complete cache miss. - { - re_log::trace!(query_time=?query.at(), ?data_time, "cache miss"); - - let bucket = Arc::new(create_and_fill_bucket(data_time, &arch_view)?); - *total_size_bytes += bucket.total_size_bytes; - let query_time_bucket_at_query_time = query_time_bucket_at_query_time.insert(bucket); - - let data_time_bucket_at_data_time = per_data_time.entry(data_time); - data_time_bucket_at_data_time - .and_modify(|v| *v = Arc::clone(&query_time_bucket_at_query_time)) - .or_insert(Arc::clone(&query_time_bucket_at_query_time)); - - Ok(()) - } - }; - - let iter_callback = |query: &LatestAtQuery, latest_at_cache: &crate::LatestAtCache, f: &mut F| { - re_tracing::profile_scope!("latest_at", format!("{query:?}")); - - let crate::LatestAtCache { - per_query_time, - per_data_time: _, - timeline: _, - total_size_bytes: _, - } = latest_at_cache; - - // Expected path: cache was properly upserted. - if let Some(query_time_bucket_at_query_time) = per_query_time.get(&query.at()) { - return iter_results(query_time_bucket_at_query_time, f); - } - - re_log::trace!( - store_id = %store.id(), - %entity_path, - ?query, - "either no data exist at this time or we couldn't upsert the cache (write lock was busy)" - ); - - Ok(()) - }; - - - let (res1, res2) = self.with_latest_at::( - store, - entity_path.clone(), - query, - |latest_at_cache| upsert_callback(query, latest_at_cache), - |latest_at_cache| iter_callback(query, latest_at_cache, &mut f), - ); - - if let Some(res1) = res1 { - res1?; - } - res2?; - - Ok(()) - } } - }; - - // TODO(cmc): Supporting N>1 generically is quite painful due to limitations in declarative macros, - // not that we care at the moment. - (for N=1, M=$M:expr) => { - seq!(COMP in 1..=$M { - impl_query_archetype_latest_at!(for N=1, M=$M => povs=[R1] comps=[#(C~COMP)*]); - }); - }; -} - -impl Caches { - seq!(NUM_COMP in 0..10 { - impl_query_archetype_latest_at!(for N=1, M=NUM_COMP); - }); -} diff --git a/crates/re_query_cache2/src/latest_at/helpers.rs b/crates/re_query_cache/src/latest_at/helpers.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/helpers.rs rename to crates/re_query_cache/src/latest_at/helpers.rs diff --git a/crates/re_query_cache2/src/latest_at/mod.rs b/crates/re_query_cache/src/latest_at/mod.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/mod.rs rename to crates/re_query_cache/src/latest_at/mod.rs diff --git a/crates/re_query_cache2/src/latest_at/query.rs b/crates/re_query_cache/src/latest_at/query.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/query.rs rename to crates/re_query_cache/src/latest_at/query.rs diff --git a/crates/re_query_cache2/src/latest_at/results.rs b/crates/re_query_cache/src/latest_at/results.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/results.rs rename to crates/re_query_cache/src/latest_at/results.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes b/crates/re_query_cache/src/latest_at/to_archetype/.gitattributes similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/.gitattributes rename to crates/re_query_cache/src/latest_at/to_archetype/.gitattributes diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/annotation_context.rs rename to crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/arrows2d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/arrows3d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs b/crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/asset3d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/background.rs b/crates/re_query_cache/src/latest_at/to_archetype/background.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/background.rs rename to crates/re_query_cache/src/latest_at/to_archetype/background.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/bar_chart.rs rename to crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/boxes2d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/boxes3d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/clear.rs b/crates/re_query_cache/src/latest_at/to_archetype/clear.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/clear.rs rename to crates/re_query_cache/src/latest_at/to_archetype/clear.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/container_blueprint.rs b/crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/container_blueprint.rs rename to crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs b/crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/depth_image.rs rename to crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/disconnected_space.rs rename to crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/image.rs b/crates/re_query_cache/src/latest_at/to_archetype/image.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/image.rs rename to crates/re_query_cache/src/latest_at/to_archetype/image.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/line_strips2d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/line_strips3d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/mesh3d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/mod.rs b/crates/re_query_cache/src/latest_at/to_archetype/mod.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/mod.rs rename to crates/re_query_cache/src/latest_at/to_archetype/mod.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/panel_blueprint.rs b/crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/panel_blueprint.rs rename to crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs b/crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/pinhole.rs rename to crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/plot_legend.rs b/crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/plot_legend.rs rename to crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs b/crates/re_query_cache/src/latest_at/to_archetype/points2d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/points2d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/points2d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs b/crates/re_query_cache/src/latest_at/to_archetype/points3d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/points3d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/points3d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs b/crates/re_query_cache/src/latest_at/to_archetype/scalar.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/scalar.rs rename to crates/re_query_cache/src/latest_at/to_archetype/scalar.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/scalar_axis.rs b/crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/scalar_axis.rs rename to crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/segmentation_image.rs rename to crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs b/crates/re_query_cache/src/latest_at/to_archetype/series_line.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/series_line.rs rename to crates/re_query_cache/src/latest_at/to_archetype/series_line.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs b/crates/re_query_cache/src/latest_at/to_archetype/series_point.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/series_point.rs rename to crates/re_query_cache/src/latest_at/to_archetype/series_point.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/space_view_blueprint.rs b/crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/space_view_blueprint.rs rename to crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/space_view_contents.rs b/crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/space_view_contents.rs rename to crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs b/crates/re_query_cache/src/latest_at/to_archetype/tensor.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/tensor.rs rename to crates/re_query_cache/src/latest_at/to_archetype/tensor.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs b/crates/re_query_cache/src/latest_at/to_archetype/text_document.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/text_document.rs rename to crates/re_query_cache/src/latest_at/to_archetype/text_document.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs b/crates/re_query_cache/src/latest_at/to_archetype/text_log.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/text_log.rs rename to crates/re_query_cache/src/latest_at/to_archetype/text_log.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs b/crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/transform3d.rs rename to crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/view_coordinates.rs rename to crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs diff --git a/crates/re_query_cache2/src/latest_at/to_archetype/viewport_blueprint.rs b/crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs similarity index 100% rename from crates/re_query_cache2/src/latest_at/to_archetype/viewport_blueprint.rs rename to crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs diff --git a/crates/re_query_cache/src/lib.rs b/crates/re_query_cache/src/lib.rs index df9044b10f42..cb995ab447aa 100644 --- a/crates/re_query_cache/src/lib.rs +++ b/crates/re_query_cache/src/lib.rs @@ -4,23 +4,51 @@ mod cache; mod cache_stats; mod flat_vec_deque; mod latest_at; -mod query; mod range; -pub use self::cache::{AnyQuery, Caches}; -pub use self::cache_stats::{CachedComponentStats, CachedEntityStats, CachesStats}; +pub use self::cache::{CacheKey, Caches}; +pub use self::cache_stats::{CachedComponentStats, CachesStats}; pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; -pub use self::query::iter_or_repeat_opt; +pub use self::latest_at::{ + CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, +}; +pub use self::range::{CachedRangeComponentResults, CachedRangeData, CachedRangeResults}; -pub(crate) use self::cache::CacheBucket; pub(crate) use self::latest_at::LatestAtCache; -pub(crate) use self::range::RangeCache; +pub(crate) use self::range::{CachedRangeComponentResultsInner, RangeCache}; -pub use re_query::{QueryError, Result}; // convenience +pub use re_query2::{ + clamped_zip::*, range_zip::*, ExtraQueryHistory, Promise, PromiseId, PromiseResolver, + PromiseResult, QueryError, Result, ToArchetype, VisibleHistory, VisibleHistoryBoundary, +}; pub mod external { - pub use re_query; + pub use re_query2; pub use paste; pub use seq_macro; } + +// --- + +use re_data_store::{LatestAtQuery, RangeQuery}; + +#[derive(Debug)] +pub enum CachedResults { + LatestAt(LatestAtQuery, CachedLatestAtResults), + Range(RangeQuery, CachedRangeResults), +} + +impl From<(LatestAtQuery, CachedLatestAtResults)> for CachedResults { + #[inline] + fn from((query, results): (LatestAtQuery, CachedLatestAtResults)) -> Self { + Self::LatestAt(query, results) + } +} + +impl From<(RangeQuery, CachedRangeResults)> for CachedResults { + #[inline] + fn from((query, results): (RangeQuery, CachedRangeResults)) -> Self { + Self::Range(query, results) + } +} diff --git a/crates/re_query_cache/src/query.rs b/crates/re_query_cache/src/query.rs deleted file mode 100644 index 50e4036bff32..000000000000 --- a/crates/re_query_cache/src/query.rs +++ /dev/null @@ -1,251 +0,0 @@ -use paste::paste; -use seq_macro::seq; - -use re_data_store::{DataStore, LatestAtQuery, RangeQuery, TimeInt, Timeline}; -use re_log_types::{EntityPath, RowId}; -use re_query::{ExtraQueryHistory, VisibleHistory}; -use re_types_core::{components::InstanceKey, Archetype, Component}; - -use crate::{AnyQuery, Caches}; - -// --- - -/// Iterates over the data of an optional component, or repeat `None` values if it's missing. -#[inline] -pub fn iter_or_repeat_opt( - this: Option<&[Option]>, - len: usize, -) -> impl Iterator> + '_ { - this.as_ref().map_or( - itertools::Either::Left(std::iter::repeat(&None).take(len)), - |data| itertools::Either::Right(data.iter()), - ) -} - -// --- - -/// Cached implementation of [`re_query::query_archetype`] and [`re_query::range_archetype`] -/// (combined) for 1 point-of-view component and no optional components. -/// -/// Alias for [`Self::query_archetype_pov1_comp0`]. -impl Caches { - #[inline] - pub fn query_archetype_pov1<'a, A, R1, F>( - &self, - store: &'a DataStore, - query: &AnyQuery, - entity_path: &'a EntityPath, - f: F, - ) -> ::re_query::Result<()> - where - A: Archetype + 'a, - R1: Component, - F: FnMut(((TimeInt, RowId), &[InstanceKey], &[R1])), - { - self.query_archetype_pov1_comp0::(store, query, entity_path, f) - } -} - -macro_rules! impl_query_archetype { - (for N=$N:expr, M=$M:expr => povs=[$($pov:ident)+] comps=[$($comp:ident)*]) => { paste! { - #[doc = "Cached implementation of [`re_query::query_archetype`] and [`re_query::range_archetype`]"] - #[doc = "(combined) for `" $N "` point-of-view components and `" $M "` optional components."] - #[allow(non_snake_case)] - pub fn []<'a, A, $($pov,)+ $($comp,)* F>( - &self, - store: &'a DataStore, - query: &AnyQuery, - entity_path: &'a EntityPath, - mut f: F, - ) -> ::re_query::Result<()> - where - A: Archetype + 'a, - $($pov: Component,)+ - $($comp: Component,)* - F: FnMut( - ( - (TimeInt, RowId), - &[InstanceKey], - $(&[$pov],)+ - $(Option<&[Option<$comp>]>,)* - ), - ), - { - // NOTE: not `profile_function!` because we want them merged together. - re_tracing::profile_scope!( - "query_archetype", - format!("cached=true arch={} pov={} comp={}", A::name(), $N, $M) - ); - - match &query { - AnyQuery::LatestAt(query) => { - re_tracing::profile_scope!("latest_at", format!("{query:?}")); - - self.[]::( - store, - query, - entity_path, - f, - ) - } - - AnyQuery::Range(query) => { - re_tracing::profile_scope!("range", format!("{query:?}")); - - self.[]::( - store, - query, - entity_path, - |entry_range, (data_times, pov_instance_keys, $($pov,)+ $($comp,)*)| { - let it = itertools::izip!( - data_times.range(entry_range.clone()), - pov_instance_keys.range(entry_range.clone()), - $($pov.range(entry_range.clone()),)+ - $($comp.map_or_else( - || itertools::Either::Left(std::iter::repeat(&[] as &[Option<$comp>])), - |data| itertools::Either::Right(data.range(entry_range.clone()))) - ,)* - ).map(|((time, row_id), instance_keys, $($pov,)+ $($comp,)*)| { - ( - (*time, *row_id), - instance_keys, - $($pov,)+ - $((!$comp.is_empty()).then_some($comp),)* - ) - }); - - for data in it { - f(data); - } - }, - ) - } - } - } } - }; - - // TODO(cmc): Supporting N>1 generically is quite painful due to limitations in declarative macros, - // not that we care at the moment. - (for N=1, M=$M:expr) => { - seq!(COMP in 1..=$M { - impl_query_archetype!(for N=1, M=$M => povs=[R1] comps=[#(C~COMP)*]); - }); - }; -} - -impl Caches { - seq!(NUM_COMP in 0..10 { - impl_query_archetype!(for N=1, M=NUM_COMP); - }); -} - -// --- - -/// Cached implementation of [`re_query::query_archetype_with_history`] for 1 point-of-view component -/// and no optional components. -/// -/// Alias for [`Self::query_archetype_with_history_pov1_comp0`]. -impl Caches { - #[allow(clippy::too_many_arguments)] - #[inline] - pub fn query_archetype_with_history_pov1<'a, A, R1, F>( - &self, - store: &'a DataStore, - timeline: &'a Timeline, - time: &'a TimeInt, - history: &ExtraQueryHistory, - ent_path: &'a EntityPath, - f: F, - ) -> ::re_query::Result<()> - where - A: Archetype + 'a, - R1: Component, - F: FnMut(((TimeInt, RowId), &[InstanceKey], &[R1])), - { - self.query_archetype_with_history_pov1_comp0::( - store, timeline, time, history, ent_path, f, - ) - } -} - -/// Generates a function to cache a (potentially historical) query with N point-of-view components and M -/// other components. -macro_rules! impl_query_archetype_with_history { - (for N=$N:expr, M=$M:expr => povs=[$($pov:ident)+] comps=[$($comp:ident)*]) => { paste! { - #[doc = "Cached implementation of [`re_query::query_archetype_with_history`] for `" $N "` point-of-view"] - #[doc = "components and `" $M "` optional components."] - #[allow(clippy::too_many_arguments)] - pub fn []<'a, A, $($pov,)+ $($comp,)* F>( - &self, - store: &'a DataStore, - timeline: &'a Timeline, - time: &'a TimeInt, - history: &ExtraQueryHistory, - ent_path: &'a EntityPath, - f: F, - ) -> ::re_query::Result<()> - where - A: Archetype + 'a, - $($pov: Component,)+ - $($comp: Component,)* - F: FnMut( - ( - (TimeInt, RowId), - &[InstanceKey], - $(&[$pov],)+ - $(Option<&[Option<$comp>]>,)* - ), - ), - { - - let visible_history = match timeline.typ() { - re_log_types::TimeType::Time => history.nanos, - re_log_types::TimeType::Sequence => history.sequences, - }; - - if !history.enabled || visible_history == VisibleHistory::OFF { - // NOTE: not `profile_function!` because we want them merged together. - re_tracing::profile_scope!( - "query_archetype_with_history", - format!("cached=true arch={} pov={} comp={}", A::name(), $N, $M) - ); - - let query = LatestAtQuery::new(*timeline, *time); - self.[]::( - store, - &query.clone().into(), - ent_path, - f, - ) - } else { - // NOTE: not `profile_function!` because we want them merged together. - re_tracing::profile_scope!( - "query_archetype_with_history", - format!("cached=true arch={} pov={} comp={}", A::name(), $N, $M) - ); - - let query = RangeQuery::new(*timeline, visible_history.time_range(*time)); - self.[]::( - store, - &query.clone().into(), - ent_path, - f, - ) - } - } } - }; - - // TODO(cmc): Supporting N>1 generically is quite painful due to limitations in declarative macros, - // not that we care at the moment. - (for N=1, M=$M:expr) => { - seq!(COMP in 1..=$M { - impl_query_archetype_with_history!(for N=1, M=$M => povs=[R1] comps=[#(C~COMP)*]); - }); - }; -} - -impl Caches { - seq!(NUM_COMP in 0..10 { - impl_query_archetype_with_history!(for N=1, M=NUM_COMP); - }); -} diff --git a/crates/re_query_cache/src/range.rs b/crates/re_query_cache/src/range.rs deleted file mode 100644 index 39ffcc07fd91..000000000000 --- a/crates/re_query_cache/src/range.rs +++ /dev/null @@ -1,334 +0,0 @@ -use paste::paste; -use seq_macro::seq; - -use re_data_store::{DataStore, RangeQuery, TimeInt}; -use re_log_types::{EntityPath, TimeRange, Timeline}; -use re_types_core::{components::InstanceKey, Archetype, Component, SizeBytes}; - -use crate::{CacheBucket, Caches}; - -// --- Data structures --- - -/// Caches the results of `Range` queries. -#[derive(Default)] -pub struct RangeCache { - /// All temporal data, organized by _data_ time. - /// - /// Query time is irrelevant for range queries. - // - // TODO(#4810): bucketize - pub per_data_time: CacheBucket, - - /// For debugging purposes. - pub(crate) timeline: Timeline, -} - -impl std::fmt::Debug for RangeCache { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - per_data_time, - timeline, - } = self; - - let mut strings = Vec::new(); - - let mut data_time_min = TimeInt::MAX; - let mut data_time_max = TimeInt::MIN; - - if !per_data_time.is_empty() { - data_time_min = TimeInt::min( - data_time_min, - per_data_time.data_times.front().map(|(t, _)| *t).unwrap(), - ); - data_time_max = TimeInt::max( - data_time_max, - per_data_time.data_times.back().map(|(t, _)| *t).unwrap(), - ); - } - - strings.push(format!( - "{} ({})", - timeline - .typ() - .format_range_utc(TimeRange::new(data_time_min, data_time_max)), - re_format::format_bytes((per_data_time.total_size_bytes) as _), - )); - strings.push(indent::indent_all_by(2, format!("{per_data_time:?}"))); - - f.write_str(&strings.join("\n").replace("\n\n", "\n")) - } -} - -impl SizeBytes for RangeCache { - #[inline] - fn heap_size_bytes(&self) -> u64 { - let Self { - per_data_time, - timeline: _, - } = self; - - per_data_time.total_size_bytes - } -} - -impl RangeCache { - /// Removes everything from the cache that corresponds to a time equal or greater than the - /// specified `threshold`. - /// - /// Reminder: invalidating static data is the same as invalidating everything, so just reset - /// the `RangeCache` entirely in that case. - /// - /// Returns the number of bytes removed. - #[inline] - pub fn truncate_at_time(&mut self, threshold: TimeInt) -> u64 { - let Self { - per_data_time, - timeline: _, - } = self; - - per_data_time.truncate_at_time(threshold) - } -} - -impl RangeCache { - /// Given a `query`, returns N reduced queries that are sufficient to fill the missing data - /// on both the front & back sides of the cache. - #[inline] - pub fn compute_queries(&self, query: &RangeQuery) -> impl Iterator { - let front = self.compute_front_query(query); - let back = self.compute_back_query(query); - front.into_iter().chain(back) - } - - /// Given a `query`, returns a reduced query that is sufficient to fill the missing data - /// on the front side of the cache, or `None` if all the necessary data is already - /// cached. - pub fn compute_front_query(&self, query: &RangeQuery) -> Option { - let mut reduced_query = query.clone(); - - if self.per_data_time.is_empty() { - return Some(reduced_query); - } - - if let Some(bucket_time_range) = self.per_data_time.time_range() { - reduced_query.range.set_max(i64::min( - reduced_query.range.max().as_i64(), - bucket_time_range.min().as_i64().saturating_sub(1), - )); - } else { - return Some(reduced_query); - } - - if reduced_query.range.max() < reduced_query.range.min() { - return None; - } - - Some(reduced_query) - } - - /// Given a `query`, returns a reduced query that is sufficient to fill the missing data - /// on the back side of the cache, or `None` if all the necessary data is already - /// cached. - pub fn compute_back_query(&self, query: &RangeQuery) -> Option { - let mut reduced_query = query.clone(); - - if let Some(bucket_time_range) = self.per_data_time.time_range() { - reduced_query.range.set_min(i64::max( - reduced_query.range.min().as_i64(), - bucket_time_range.max().as_i64().saturating_add(1), - )); - } else { - return Some(reduced_query); - } - - if reduced_query.range.max() < reduced_query.range.min() { - return None; - } - - Some(reduced_query) - } -} - -// --- Queries --- - -macro_rules! impl_query_archetype_range { - (for N=$N:expr, M=$M:expr => povs=[$($pov:ident)+] comps=[$($comp:ident)*]) => { paste! { - #[doc = "Cached implementation of [`re_query::query_archetype`] and [`re_query::range_archetype`]"] - #[doc = "(combined) for `" $N "` point-of-view components and `" $M "` optional components."] - #[allow(non_snake_case)] - pub fn []<'a, A, $($pov,)+ $($comp,)* F>( - &self, - store: &'a DataStore, - query: &RangeQuery, - entity_path: &'a EntityPath, - mut f: F, - ) -> ::re_query::Result<()> - where - A: Archetype + 'a, - $($pov: Component,)+ - $($comp: Component,)* - F: FnMut( - std::ops::Range, - ( - &'_ std::collections::VecDeque<(re_data_store::TimeInt, re_log_types::RowId)>, - &'_ crate::FlatVecDeque, - $(&'_ crate::FlatVecDeque<$pov>,)+ - $(Option<&'_ crate::FlatVecDeque>>,)* - ) - ), - { - let range_results = | - bucket: &crate::CacheBucket, - time_range: TimeRange, - f: &mut F, - | -> crate::Result<()> { - re_tracing::profile_scope!("iter"); - - // Yield the static data that's available first. - let static_range = bucket.static_range(); - f( - static_range, - ( - &bucket.data_times, - &bucket.pov_instance_keys, - $(bucket.component::<$pov>() - .ok_or_else(|| re_query::ComponentNotFoundError(<$pov>::name()))?,)+ - $(bucket.component_opt::<$comp>(),)* - ) - ); - - let entry_range = bucket.entry_range(time_range); - f( - entry_range, - ( - &bucket.data_times, - &bucket.pov_instance_keys, - $(bucket.component::<$pov>() - .ok_or_else(|| re_query::ComponentNotFoundError(<$pov>::name()))?,)+ - $(bucket.component_opt::<$comp>(),)* - ) - ); - - Ok(()) - }; - - fn upsert_results<'a, A, $($pov,)+ $($comp,)*>( - arch_views: impl Iterator>, - bucket: &mut crate::CacheBucket, - ) -> crate::Result - where - A: Archetype + 'a, - $($pov: Component,)+ - $($comp: Component,)* - { - re_tracing::profile_scope!("fill"); - - // Grabbing the current time is quite costly on web. - #[cfg(not(target_arch = "wasm32"))] - let now = web_time::Instant::now(); - - #[cfg(not(target_arch = "wasm32"))] - let mut added_entries = 0u64; - - let mut added_size_bytes = 0u64; - - for arch_view in arch_views { - let data_time = arch_view.data_time(); - - if bucket.contains_data_row(data_time, arch_view.primary_row_id()) { - continue; - } - - added_size_bytes += bucket.[]::(data_time, &arch_view)?; - - #[cfg(not(target_arch = "wasm32"))] - { - added_entries += 1; - } - } - - #[cfg(not(target_arch = "wasm32"))] - if added_entries > 0 { - let elapsed = now.elapsed(); - ::re_log::trace!( - archetype=%A::name(), - added_size_bytes, - "cached {added_entries} entries in {elapsed:?} ({:0.3} entries/s)", - added_entries as f64 / elapsed.as_secs_f64() - ); - } - - Ok(added_size_bytes) - } - - let upsert_callback = |query: &RangeQuery, range_cache: &mut crate::RangeCache| -> crate::Result<()> { - re_tracing::profile_scope!("range", format!("{query:?}")); - - let mut query = query.clone(); - query.range.set_min(TimeInt::max(TimeInt::MIN, query.range.min())); - - for reduced_query in range_cache.compute_queries(&query) { - // NOTE: `+ 1` because we always grab the instance keys. - let arch_views = ::re_query::range_component_set::( - store, &reduced_query, entity_path, - &[$(<$pov>::name(),)+], - [::name(), $(<$pov>::name(),)+ $(<$comp>::name(),)*], - ); - upsert_results::(arch_views, &mut range_cache.per_data_time)?; - } - - Ok(()) - }; - - let iter_callback = |query: &RangeQuery, range_cache: &crate::RangeCache, f: &mut F| -> crate::Result<()> { - re_tracing::profile_scope!("range", format!("{query:?}")); - - // We don't bother implementing the slow path here (busy write lock), as that would - // require adding a bunch more complexity in order to know whether a range query is - // already cached (how can you know whether `TimeInt::MAX` is cached? you need to - // clamp queries based on store metadata first, etc). - // - // We can add the extra complexity if this proves to be glitchy in real-world - // scenarios -- otherwise all of this is giant hack meant to go away anyhow. - - let mut query = query.clone(); - query.range.set_min(TimeInt::max(TimeInt::MIN, query.range.min())); - - if !range_cache.per_data_time.is_empty() { - range_results(&range_cache.per_data_time, query.range, f)?; - } - - Ok(()) - }; - - let (res1, res2) = self.with_range::( - store, - entity_path.clone(), - query, - |range_cache| upsert_callback(query, range_cache), - |range_cache| iter_callback(query, range_cache, &mut f), - ); - - if let Some(res1) = res1 { - res1?; - } - res2?; - - Ok(()) - } } - }; - - // TODO(cmc): Supporting N>1 generically is quite painful due to limitations in declarative macros, - // not that we care at the moment. - (for N=1, M=$M:expr) => { - seq!(COMP in 1..=$M { - impl_query_archetype_range!(for N=1, M=$M => povs=[R1] comps=[#(C~COMP)*]); - }); - }; -} - -impl Caches { - seq!(NUM_COMP in 0..10 { - impl_query_archetype_range!(for N=1, M=NUM_COMP); - }); -} diff --git a/crates/re_query_cache2/src/range/mod.rs b/crates/re_query_cache/src/range/mod.rs similarity index 100% rename from crates/re_query_cache2/src/range/mod.rs rename to crates/re_query_cache/src/range/mod.rs diff --git a/crates/re_query_cache2/src/range/query.rs b/crates/re_query_cache/src/range/query.rs similarity index 100% rename from crates/re_query_cache2/src/range/query.rs rename to crates/re_query_cache/src/range/query.rs diff --git a/crates/re_query_cache2/src/range/results.rs b/crates/re_query_cache/src/range/results.rs similarity index 100% rename from crates/re_query_cache2/src/range/results.rs rename to crates/re_query_cache/src/range/results.rs diff --git a/crates/re_query_cache/tests/latest_at.rs b/crates/re_query_cache/tests/latest_at.rs index e05d07c05adc..4073c5ec7e53 100644 --- a/crates/re_query_cache/tests/latest_at.rs +++ b/crates/re_query_cache/tests/latest_at.rs @@ -2,15 +2,15 @@ //! - A 1:1 port of the tests in `crates/re_query/tests/archetype_query_tests.rs`, with caching enabled. //! - Invalidation tests. -use itertools::Itertools as _; - use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; use re_log_types::{ build_frame_nr, example_components::{MyColor, MyPoint, MyPoints}, DataRow, EntityPath, RowId, TimePoint, }; +use re_query2::PromiseResolver; use re_query_cache::Caches; +use re_types::Archetype as _; use re_types_core::{components::InstanceKey, Loggable as _}; // --- @@ -68,7 +68,7 @@ fn static_query() { DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); insert_and_react(&mut store, &mut caches, &row); - // Assign one of them a color with an explicit instance.. static_! + // Assign one of them a color with an explicit instance.. statically! let color_instances = vec![InstanceKey(1)]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; let row = DataRow::from_cells2_sized( @@ -409,7 +409,7 @@ fn invalidation_of_future_optionals() { } #[test] -fn invalidation_timeless() { +fn static_invalidation() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), InstanceKey::name(), @@ -476,49 +476,51 @@ fn query_and_compare( ) { re_log::setup_logging(); + let resolver = PromiseResolver::default(); + for _ in 0..3 { - let mut cached_data_time = None; - let mut cached_row_id = None; - let mut cached_instance_keys = Vec::new(); - let mut cached_positions = Vec::new(); - let mut cached_colors = Vec::new(); - caches - .query_archetype_pov1_comp1::( - store, - &query.clone().into(), - entity_path, - |((data_time, row_id), instance_keys, positions, colors)| { - cached_data_time = Some(data_time); - cached_row_id = Some(row_id); - cached_instance_keys.extend(instance_keys.iter().copied()); - cached_positions.extend(positions.iter().copied()); - cached_colors - .extend(re_query_cache::iter_or_repeat_opt(colors, positions.len())); - }, - ) + let cached = caches.latest_at( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_points = cached.get_required(MyPoint::name()).unwrap(); + let cached_point_data = cached_points + .to_dense::(&resolver) + .flatten() + .unwrap(); + + let cached_colors = cached.get_or_empty(MyColor::name()); + let cached_color_data = cached_colors + .to_dense::(&resolver) + .flatten() .unwrap(); - let expected = re_query::query_archetype::(store, query, entity_path).unwrap(); - let expected_data_time = expected.data_time(); - let expected_row_id = expected.primary_row_id(); - - let expected_instance_keys = expected.iter_instance_keys().collect_vec(); - let expected_positions = expected - .iter_required_component::() - .unwrap() - .collect_vec(); - let expected_colors = expected - .iter_optional_component::() - .unwrap() - .collect_vec(); - - // Keep this around for the next unlucky chap. - // eprintln!("i={i} (expected={expected_data_time:?}, cached={cached_data_time:?})"); - - similar_asserts::assert_eq!(Some(expected_data_time), cached_data_time); - similar_asserts::assert_eq!(Some(expected_row_id), cached_row_id); - similar_asserts::assert_eq!(expected_instance_keys, cached_instance_keys); - similar_asserts::assert_eq!(expected_positions, cached_positions); - similar_asserts::assert_eq!(expected_colors, cached_colors); + let expected = re_query2::latest_at( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let expected_points = expected.get_required(MyPoint::name()).unwrap(); + let expected_point_data = expected_points + .to_dense::(&resolver) + .flatten() + .unwrap(); + + let expected_colors = expected.get_or_empty(MyColor::name()); + let expected_color_data = expected_colors + .to_dense::(&resolver) + .flatten() + .unwrap(); + + // eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!(expected.compound_index, cached.compound_index); + similar_asserts::assert_eq!(expected_point_data, cached_point_data); + similar_asserts::assert_eq!(expected_color_data, cached_color_data); } } diff --git a/crates/re_query_cache/tests/range.rs b/crates/re_query_cache/tests/range.rs index 8dd3a76cbbb8..eb7380c8a1d0 100644 --- a/crates/re_query_cache/tests/range.rs +++ b/crates/re_query_cache/tests/range.rs @@ -1,23 +1,19 @@ -//! Contains: -//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_range_tests.rs`, with caching enabled. -//! - Invalidation tests. +use itertools::{izip, Itertools as _}; -use itertools::Itertools as _; - -use re_data_store::{DataStore, RangeQuery, StoreSubscriber}; +use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; use re_log_types::{ build_frame_nr, - example_components::{MyColor, MyLabel, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimeInt, TimePoint, TimeRange, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimePoint, }; -use re_query_cache::Caches; -use re_types::components::InstanceKey; +use re_query_cache::{Caches, PromiseResolver, PromiseResult}; +use re_types::{components::InstanceKey, Archetype}; use re_types_core::Loggable as _; // --- #[test] -fn simple_range() { +fn simple_range() -> anyhow::Result<()> { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), InstanceKey::name(), @@ -29,50 +25,30 @@ fn simple_range() { let timepoint1 = [build_frame_nr(123)]; { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; insert_and_react(&mut store, &mut caches, &row); - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances, colors), - ) - .unwrap(); + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; insert_and_react(&mut store, &mut caches, &row); } let timepoint2 = [build_frame_nr(223)]; { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances, colors), - ) - .unwrap(); + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; insert_and_react(&mut store, &mut caches, &row); } let timepoint3 = [build_frame_nr(323)]; { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; insert_and_react(&mut store, &mut caches, &row); } @@ -87,14 +63,14 @@ fn simple_range() { // --- Second test: `[timepoint1, timepoint3]` --- - // The inclusion of `timepoint1` means latest-at semantics will _not_ kick in! - let query = re_data_store::RangeQuery::new( timepoint1[0].0, TimeRange::new(timepoint1[0].1, timepoint3[0].1), ); query_and_compare(&caches, &store, &query, &entity_path); + + Ok(()) } #[test] @@ -110,34 +86,30 @@ fn static_range() { let timepoint1 = [build_frame_nr(123)]; { - // Create some Positions with implicit instances let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let mut row = - DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint1, 2, positions) + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) .unwrap(); - row.compute_all_size_bytes(); insert_and_react(&mut store, &mut caches, &row); - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( + let row = DataRow::from_cells1_sized( RowId::new(), entity_path.clone(), timepoint1, 1, - (color_instances.clone(), colors.clone()), + colors.clone(), ) .unwrap(); insert_and_react(&mut store, &mut caches, &row); - // Insert timelessly too! - let row = DataRow::from_cells2_sized( + // Insert statically too! + let row = DataRow::from_cells1_sized( RowId::new(), entity_path.clone(), TimePoint::default(), 1, - (color_instances, colors), + colors, ) .unwrap(); insert_and_react(&mut store, &mut caches, &row); @@ -145,26 +117,24 @@ fn static_range() { let timepoint2 = [build_frame_nr(223)]; { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( + let row = DataRow::from_cells1_sized( RowId::new(), entity_path.clone(), timepoint2, 1, - (color_instances.clone(), colors.clone()), + colors.clone(), ) .unwrap(); insert_and_react(&mut store, &mut caches, &row); - // Insert static_ too! - let row = DataRow::from_cells2_sized( + // Insert statically too! + let row = DataRow::from_cells1_sized( RowId::new(), entity_path.clone(), TimePoint::default(), 1, - (color_instances, colors), + colors, ) .unwrap(); insert_and_react(&mut store, &mut caches, &row); @@ -221,7 +191,6 @@ fn simple_splatted_range() { let timepoint1 = [build_frame_nr(123)]; { - // Create some Positions with implicit instances let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; let row = DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) @@ -229,38 +198,24 @@ fn simple_splatted_range() { insert_and_react(&mut store, &mut caches, &row); // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances, colors), - ) - .unwrap(); + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors) + .unwrap(); insert_and_react(&mut store, &mut caches, &row); } let timepoint2 = [build_frame_nr(223)]; { - // Assign one of them a color with a splatted instance - let color_instances = vec![InstanceKey::SPLAT]; let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances, colors), - ) - .unwrap(); + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors) + .unwrap(); insert_and_react(&mut store, &mut caches, &row); } let timepoint3 = [build_frame_nr(323)]; { - // Create some Positions with implicit instances let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; let row = DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) @@ -279,8 +234,6 @@ fn simple_splatted_range() { // --- Second test: `[timepoint1, timepoint3]` --- - // The inclusion of `timepoint1` means latest-at semantics will _not_ kick in! - let query = re_data_store::RangeQuery::new( timepoint1[0].0, TimeRange::new(timepoint1[0].1, timepoint3[0].1), @@ -304,7 +257,6 @@ fn invalidation() { ); let mut caches = Caches::new(&store); - // Create some positions with implicit instances let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; let row = DataRow::from_cells1_sized( RowId::new(), @@ -316,15 +268,13 @@ fn invalidation() { .unwrap(); insert_and_react(&mut store, &mut caches, &row); - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells2_sized( + let row = DataRow::from_cells1_sized( RowId::new(), entity_path, present_data_timepoint.clone(), 1, - (color_instances, colors), + colors, ) .unwrap(); insert_and_react(&mut store, &mut caches, &row); @@ -464,11 +414,6 @@ fn invalidation() { // ``` #[test] fn invalidation_of_future_optionals() { - // TODO(cmc): this test is coming back in the next PR. - if true { - return; - } - let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), InstanceKey::name(), @@ -491,44 +436,20 @@ fn invalidation_of_future_optionals() { query_and_compare(&caches, &store, &query, &entity_path.into()); - let color_instances = vec![InstanceKey::SPLAT]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame2, - 1, - (color_instances, colors), - ) - .unwrap(); + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors).unwrap(); insert_and_react(&mut store, &mut caches, &row); query_and_compare(&caches, &store, &query, &entity_path.into()); - let color_instances = vec![InstanceKey::SPLAT]; let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); insert_and_react(&mut store, &mut caches, &row); query_and_compare(&caches, &store, &query, &entity_path.into()); - let color_instances = vec![InstanceKey::SPLAT]; let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); insert_and_react(&mut store, &mut caches, &row); query_and_compare(&caches, &store, &query, &entity_path.into()); @@ -557,30 +478,15 @@ fn invalidation_static() { query_and_compare(&caches, &store, &query, &entity_path.into()); - let color_instances = vec![InstanceKey::SPLAT]; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 1, colors).unwrap(); insert_and_react(&mut store, &mut caches, &row); query_and_compare(&caches, &store, &query, &entity_path.into()); - let color_instances = vec![InstanceKey::SPLAT]; let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless, - 1, - (color_instances, colors), - ) - .unwrap(); + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors).unwrap(); insert_and_react(&mut store, &mut caches, &row); query_and_compare(&caches, &store, &query, &entity_path.into()); @@ -598,62 +504,83 @@ fn query_and_compare( query: &RangeQuery, entity_path: &EntityPath, ) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + for _ in 0..3 { - let mut cached_data_times = Vec::new(); - let mut cached_instance_keys = Vec::new(); - let mut cached_positions = Vec::new(); - let mut cached_colors = Vec::new(); - caches - .query_archetype_pov1_comp2::( - store, - &query.clone().into(), - entity_path, - |((data_time, _), instance_keys, positions, colors, _)| { - cached_data_times.push(data_time); - cached_instance_keys.push(instance_keys.to_vec()); - cached_positions.push(positions.to_vec()); - cached_colors.push( - re_query_cache::iter_or_repeat_opt(colors, positions.len()) - .copied() - .collect_vec(), - ); - }, - ) - .unwrap(); - - let mut expected_data_times = Vec::new(); - let mut expected_instance_keys = Vec::new(); - let mut expected_positions = Vec::new(); - let mut expected_colors = Vec::new(); - let expected = re_query::range_archetype::( + let cached = caches.range( store, query, entity_path, + MyPoints::all_components().iter().copied(), ); - for arch_view in expected { - expected_data_times.push(arch_view.data_time()); - expected_instance_keys.push(arch_view.iter_instance_keys().collect_vec()); - expected_positions.push( - arch_view - .iter_required_component::() - .unwrap() - .collect_vec(), - ); - expected_colors.push( - arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(), - ); - } - - // Keep this around for the next unlucky chap. - // eprintln!("(expected={expected_data_times:?}, cached={cached_data_times:?})"); + + let cached_all_points = cached + .get_required(MyPoint::name()) + .unwrap() + .to_dense::(&resolver); + assert!(matches!( + cached_all_points.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_points_indexed = cached_all_points.range_indexed(); + + let cached_all_colors = cached + .get_or_empty(MyColor::name()) + .to_dense::(&resolver); + assert!(matches!( + cached_all_colors.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_colors_indexed = cached_all_colors.range_indexed(); + + let expected = re_query2::range( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let expected_all_points = expected.get_required(MyPoint::name()).unwrap(); + let expected_all_points_indices = expected_all_points.indices(); + let expected_all_points_data = expected_all_points + .to_dense::(&resolver) + .into_iter() + .map(|batch| batch.flatten().unwrap()) + .collect_vec(); + let expected_all_points_indexed = + izip!(expected_all_points_indices, expected_all_points_data); + + let expected_all_colors = expected.get_or_empty(MyColor::name()); + let expected_all_colors_indices = expected_all_colors.indices(); + let expected_all_colors_data = expected_all_colors + .to_dense::(&resolver) + .into_iter() + .map(|batch| batch.flatten().unwrap()) + .collect_vec(); + let expected_all_colors_indexed = + izip!(expected_all_colors_indices, expected_all_colors_data); + + eprintln!("{query:?}"); eprintln!("{}", store.to_data_table().unwrap()); - similar_asserts::assert_eq!(expected_data_times, cached_data_times); - similar_asserts::assert_eq!(expected_instance_keys, cached_instance_keys); - similar_asserts::assert_eq!(expected_positions, cached_positions); - similar_asserts::assert_eq!(expected_colors, cached_colors); + similar_asserts::assert_eq!( + expected_all_points_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + cached_all_points_indexed + .map(|(index, data)| (*index, data.to_vec())) + .collect_vec(), + ); + + similar_asserts::assert_eq!( + expected_all_colors_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + cached_all_colors_indexed + .map(|(index, data)| (*index, data.to_vec())) + .collect_vec(), + ); } } diff --git a/crates/re_query_cache2/Cargo.toml b/crates/re_query_cache2/Cargo.toml deleted file mode 100644 index b8b67820c4ee..000000000000 --- a/crates/re_query_cache2/Cargo.toml +++ /dev/null @@ -1,82 +0,0 @@ -[package] -name = "re_query_cache2" -authors.workspace = true -description = "Temporary crate meant to replace re_query_cache" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -# TODO(cmc): Replace re_query with this crate. Never publish this one. -publish = false -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[features] -default = ["to_archetype"] - -## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. -to_archetype = ["dep:re_types", "dep:re_types_blueprint"] - -[dependencies] -# Rerun dependencies: -re_data_store.workspace = true -re_error.workspace = true -re_format.workspace = true -re_log.workspace = true -re_log_types.workspace = true -re_query2.workspace = true -re_tracing.workspace = true -re_types_core.workspace = true - -# Rerun dependencies (optional): -re_types = { workspace = true, optional = true } -re_types_blueprint = { workspace = true, optional = true } - -# External dependencies: -ahash.workspace = true -anyhow.workspace = true -backtrace.workspace = true -indent.workspace = true -indexmap.workspace = true -itertools.workspace = true -nohash-hasher.workspace = true -parking_lot.workspace = true -paste.workspace = true -seq-macro.workspace = true -web-time.workspace = true - - -[dev-dependencies] -re_types = { workspace = true, features = ["datagen"] } - -criterion.workspace = true -mimalloc.workspace = true -rand = { workspace = true, features = ["std", "std_rng"] } -similar-asserts.workspace = true - - -[lib] -bench = false - - -[[example]] -name = "latest_at_archetype" -required-features = ["to_archetype"] - - -[[bench]] -name = "flat_vec_deque" -harness = false - -[[bench]] -name = "latest_at" -harness = false diff --git a/crates/re_query_cache2/README.md b/crates/re_query_cache2/README.md deleted file mode 100644 index db850d204a04..000000000000 --- a/crates/re_query_cache2/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# re_query_cache2 - -Temporary crate for implementing the new cached data APIs. Not published. - -Will replace `re_query_cache2` when ready. diff --git a/crates/re_query_cache2/benches/flat_vec_deque.rs b/crates/re_query_cache2/benches/flat_vec_deque.rs deleted file mode 100644 index f1dec8514b7d..000000000000 --- a/crates/re_query_cache2/benches/flat_vec_deque.rs +++ /dev/null @@ -1,333 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; - -use itertools::Itertools as _; - -use re_query_cache2::FlatVecDeque; - -// --- - -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -criterion_group!( - benches, - range, - insert, - insert_many, - insert_deque, - remove, - remove_range -); -criterion_main!(benches); - -// --- - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -mod constants { - pub const INITIAL_VALUES_PER_ENTRY: usize = 1; - pub const INITIAL_NUM_ENTRIES: usize = 1; - pub const ADDED_VALUES_PER_ENTRY: usize = 1; - pub const ADDED_NUM_ENTRIES: usize = 1; -} - -#[cfg(not(debug_assertions))] -mod constants { - pub const INITIAL_VALUES_PER_ENTRY: usize = 1000; - pub const INITIAL_NUM_ENTRIES: usize = 100; - pub const ADDED_VALUES_PER_ENTRY: usize = 1000; - pub const ADDED_NUM_ENTRIES: usize = 5; -} - -#[allow(clippy::wildcard_imports)] -use self::constants::*; - -// --- - -fn range(c: &mut Criterion) { - if std::env::var("CI").is_ok() { - return; - } - - let mut group = c.benchmark_group("flat_vec_deque"); - group.throughput(criterion::Throughput::Elements( - (ADDED_NUM_ENTRIES * ADDED_VALUES_PER_ENTRY) as _, - )); - - { - group.bench_function("range/prefilled/front", |b| { - let base = create_prefilled(); - b.iter(|| { - let v: FlatVecDeque = base.clone(); - v.range(0..ADDED_NUM_ENTRIES) - .map(ToOwned::to_owned) - .collect_vec() - }); - }); - group.bench_function("range/prefilled/middle", |b| { - let base = create_prefilled(); - b.iter(|| { - let v: FlatVecDeque = base.clone(); - v.range( - INITIAL_NUM_ENTRIES / 2 - ADDED_NUM_ENTRIES / 2 - ..INITIAL_NUM_ENTRIES / 2 + ADDED_NUM_ENTRIES / 2, - ) - .map(ToOwned::to_owned) - .collect_vec() - }); - }); - group.bench_function("range/prefilled/back", |b| { - let base = create_prefilled(); - b.iter(|| { - let v: FlatVecDeque = base.clone(); - v.range(INITIAL_NUM_ENTRIES - ADDED_NUM_ENTRIES..INITIAL_NUM_ENTRIES) - .map(ToOwned::to_owned) - .collect_vec() - }); - }); - } -} - -fn insert(c: &mut Criterion) { - if std::env::var("CI").is_ok() { - return; - } - - let added = (0..ADDED_VALUES_PER_ENTRY as i64).collect_vec(); - - let mut group = c.benchmark_group("flat_vec_deque"); - group.throughput(criterion::Throughput::Elements(added.len() as _)); - - { - group.bench_function("insert/empty", |b| { - b.iter(|| { - let mut v: FlatVecDeque = FlatVecDeque::new(); - v.insert(0, added.clone()); - v - }); - }); - } - - { - group.bench_function("insert/prefilled/front", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert(0, added.clone()); - v - }); - }); - group.bench_function("insert/prefilled/middle", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert(INITIAL_NUM_ENTRIES / 2, added.clone()); - v - }); - }); - group.bench_function("insert/prefilled/back", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert(INITIAL_NUM_ENTRIES, added.clone()); - v - }); - }); - } -} - -fn insert_many(c: &mut Criterion) { - if std::env::var("CI").is_ok() { - return; - } - - let added = (0..ADDED_NUM_ENTRIES as i64) - .map(|_| (0..ADDED_VALUES_PER_ENTRY as i64).collect_vec()) - .collect_vec(); - - let mut group = c.benchmark_group("flat_vec_deque"); - group.throughput(criterion::Throughput::Elements( - (ADDED_NUM_ENTRIES * ADDED_VALUES_PER_ENTRY) as _, - )); - - { - group.bench_function("insert_many/empty", |b| { - b.iter(|| { - let mut v: FlatVecDeque = FlatVecDeque::new(); - v.insert_many(0, added.clone()); - v - }); - }); - } - - { - group.bench_function("insert_many/prefilled/front", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert_many(0, added.clone()); - v - }); - }); - group.bench_function("insert_many/prefilled/middle", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert_many(INITIAL_NUM_ENTRIES / 2, added.clone()); - v - }); - }); - group.bench_function("insert_many/prefilled/back", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert_many(INITIAL_NUM_ENTRIES, added.clone()); - v - }); - }); - } -} - -fn insert_deque(c: &mut Criterion) { - if std::env::var("CI").is_ok() { - return; - } - - let mut added: FlatVecDeque = FlatVecDeque::new(); - for i in 0..ADDED_NUM_ENTRIES { - added.insert(i, (0..ADDED_VALUES_PER_ENTRY as i64).collect_vec()); - } - - let added = FlatVecDeque::from_vecs( - std::iter::repeat_with(|| (0..ADDED_VALUES_PER_ENTRY as i64).collect_vec()) - .take(ADDED_NUM_ENTRIES), - ); - - let mut group = c.benchmark_group("flat_vec_deque"); - group.throughput(criterion::Throughput::Elements( - (ADDED_NUM_ENTRIES * ADDED_VALUES_PER_ENTRY) as _, - )); - - { - group.bench_function("insert_deque/empty", |b| { - b.iter(|| { - let mut v: FlatVecDeque = FlatVecDeque::new(); - v.insert_deque(0, added.clone()); - v - }); - }); - } - - { - group.bench_function("insert_deque/prefilled/front", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert_deque(0, added.clone()); - v - }); - }); - group.bench_function("insert_deque/prefilled/middle", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert_deque(INITIAL_NUM_ENTRIES / 2, added.clone()); - v - }); - }); - group.bench_function("insert_deque/prefilled/back", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.insert_deque(INITIAL_NUM_ENTRIES, added.clone()); - v - }); - }); - } -} - -fn remove(c: &mut Criterion) { - if std::env::var("CI").is_ok() { - return; - } - - let mut group = c.benchmark_group("flat_vec_deque"); - group.throughput(criterion::Throughput::Elements(1)); - - { - group.bench_function("remove/prefilled/front", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.remove(0); - v - }); - }); - group.bench_function("remove/prefilled/middle", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.remove(INITIAL_NUM_ENTRIES / 2); - v - }); - }); - group.bench_function("remove/prefilled/back", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.remove(INITIAL_NUM_ENTRIES - 1); - v - }); - }); - } -} - -fn remove_range(c: &mut Criterion) { - if std::env::var("CI").is_ok() { - return; - } - - let mut group = c.benchmark_group("flat_vec_deque"); - group.throughput(criterion::Throughput::Elements( - (ADDED_NUM_ENTRIES * ADDED_VALUES_PER_ENTRY) as _, - )); - - { - group.bench_function("remove_range/prefilled/front", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.remove_range(0..ADDED_NUM_ENTRIES); - v - }); - }); - group.bench_function("remove_range/prefilled/middle", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.remove_range( - INITIAL_NUM_ENTRIES / 2 - ADDED_NUM_ENTRIES / 2 - ..INITIAL_NUM_ENTRIES / 2 + ADDED_NUM_ENTRIES / 2, - ); - v - }); - }); - group.bench_function("remove_range/prefilled/back", |b| { - let base = create_prefilled(); - b.iter(|| { - let mut v: FlatVecDeque = base.clone(); - v.remove_range(INITIAL_NUM_ENTRIES - ADDED_NUM_ENTRIES..INITIAL_NUM_ENTRIES); - v - }); - }); - } -} - -// --- - -fn create_prefilled() -> FlatVecDeque { - FlatVecDeque::from_vecs( - std::iter::repeat_with(|| (0..INITIAL_VALUES_PER_ENTRY as i64).collect_vec()) - .take(INITIAL_NUM_ENTRIES), - ) -} diff --git a/crates/re_query_cache2/benches/latest_at.rs b/crates/re_query_cache2/benches/latest_at.rs deleted file mode 100644 index cbda2b8826b3..000000000000 --- a/crates/re_query_cache2/benches/latest_at.rs +++ /dev/null @@ -1,374 +0,0 @@ -//! Contains: -//! - A 1:1 port of the benchmarks in `crates/re_query/benches/query_benchmarks.rs`, with caching enabled. - -use criterion::{criterion_group, criterion_main, Criterion}; - -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; -use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query2::{clamped_zip_1x1, PromiseResolver}; -use re_query_cache2::{CachedLatestAtResults, Caches}; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D, Text}, - Archetype as _, -}; -use re_types_core::Loggable as _; - -// --- - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -mod constants { - pub const NUM_FRAMES_POINTS: u32 = 1; - pub const NUM_POINTS: u32 = 1; - pub const NUM_FRAMES_STRINGS: u32 = 1; - pub const NUM_STRINGS: u32 = 1; -} - -#[cfg(not(debug_assertions))] -mod constants { - pub const NUM_FRAMES_POINTS: u32 = 1_000; - pub const NUM_POINTS: u32 = 1_000; - pub const NUM_FRAMES_STRINGS: u32 = 1_000; - pub const NUM_STRINGS: u32 = 1_000; -} - -#[allow(clippy::wildcard_imports)] -use self::constants::*; - -// --- - -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -criterion_group!( - benches, - mono_points, - mono_strings, - batch_points, - batch_strings -); -criterion_main!(benches); - -// --- - -fn mono_points(c: &mut Criterion) { - // Each mono point gets logged at a different path - let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx)) - .collect_vec(); - let msgs = build_points_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - // Mono-insert is slow -- decrease the sample size - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let (caches, store) = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&caches, &store, &paths)); - }); - } -} - -fn mono_strings(c: &mut Criterion) { - // Each mono string gets logged at a different path - let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx)) - .collect_vec(); - let msgs = build_strings_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let (caches, store) = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&caches, &store, &paths)); - }); - } -} - -fn batch_points(c: &mut Criterion) { - // Batch points are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_points_rows(&paths, NUM_POINTS as _); - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let (caches, store) = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&caches, &store, &paths)); - }); - } -} - -fn batch_strings(c: &mut Criterion) { - // Batch strings are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_strings_rows(&paths, NUM_STRINGS as _); - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let (caches, store) = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&caches, &store, &paths)); - }); - } -} - -// --- Helpers --- - -pub fn build_some_point2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) - .collect() -} - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len).map(|i| Color::from(i as u32)).collect() -} - -/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) -} - -pub fn build_some_strings(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - let ilen: usize = rng.gen_range(0..10000); - let s: String = rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(ilen) - .map(char::from) - .collect(); - Text::from(s) - }) - .collect() -} - -fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { - (0..NUM_FRAMES_POINTS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_points as _, - ( - build_some_point2d(num_points), - build_some_colors(num_points), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { - (0..NUM_FRAMES_STRINGS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_strings as _, - // We still need to create points because they are the primary for the - // archetype query we want to do. We won't actually deserialize the points - // during the query -- we just need it for the primary keys. - // TODO(jleibs): switch this to use `TextEntry` once the new type has - // landed. - ( - build_some_point2d(num_strings), - build_some_strings(num_strings), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn insert_rows<'a>(msgs: impl Iterator) -> (Caches, DataStore) { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - msgs.for_each(|row| { - caches.on_events(&[store.insert_row(row).unwrap()]); - }); - - (caches, store) -} - -struct SavePoint { - _pos: Position2D, - _color: Option, -} - -fn query_and_visit_points( - caches: &Caches, - store: &DataStore, - paths: &[EntityPath], -) -> Vec { - let resolver = PromiseResolver::default(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); - - let mut ret = Vec::with_capacity(NUM_POINTS as _); - - // TODO(jleibs): Add Radius once we have support for it in field_types - for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( - store, - &query, - entity_path, - Points2D::all_components().iter().copied(), // no generics! - ); - - let points = results.get_required(Position2D::name()).unwrap(); - let colors = results.get_or_empty(Color::name()); - - let points = points - .iter_dense::(&resolver) - .flatten() - .unwrap() - .copied(); - - let colors = colors - .iter_dense::(&resolver) - .flatten() - .unwrap() - .copied(); - let color_default_fn = || Color::from(0xFF00FFFF); - - for (point, color) in clamped_zip_1x1(points, colors, color_default_fn) { - ret.push(SavePoint { - _pos: point, - _color: Some(color), - }); - } - } - assert_eq!(NUM_POINTS as usize, ret.len()); - ret -} - -struct SaveString { - _label: Option, -} - -fn query_and_visit_strings( - caches: &Caches, - store: &DataStore, - paths: &[EntityPath], -) -> Vec { - let resolver = PromiseResolver::default(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); - - let mut strings = Vec::with_capacity(NUM_STRINGS as _); - - for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( - store, - &query, - entity_path, - Points2D::all_components().iter().copied(), // no generics! - ); - - let points = results.get_required(Position2D::name()).unwrap(); - let colors = results.get_or_empty(Text::name()); - - let points = points - .iter_dense::(&resolver) - .flatten() - .unwrap() - .copied(); - - let labels = colors - .iter_dense::(&resolver) - .flatten() - .unwrap() - .cloned(); - let label_default_fn = || Text(String::new().into()); - - for (_point, label) in clamped_zip_1x1(points, labels, label_default_fn) { - strings.push(SaveString { - _label: Some(label), - }); - } - } - assert_eq!(NUM_STRINGS as usize, strings.len()); - criterion::black_box(strings) -} diff --git a/crates/re_query_cache2/src/cache.rs b/crates/re_query_cache2/src/cache.rs deleted file mode 100644 index 7f46b49dbfb0..000000000000 --- a/crates/re_query_cache2/src/cache.rs +++ /dev/null @@ -1,258 +0,0 @@ -use std::{ - collections::{BTreeMap, BTreeSet}, - sync::Arc, -}; - -use ahash::{HashMap, HashSet}; -use parking_lot::RwLock; - -use re_data_store::{DataStore, StoreDiff, StoreEvent, StoreSubscriber, TimeInt}; -use re_log_types::{EntityPath, StoreId, TimeRange, Timeline}; -use re_types_core::ComponentName; - -use crate::{LatestAtCache, RangeCache}; - -// --- - -/// Uniquely identifies cached query results in the [`Caches`]. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct CacheKey { - pub entity_path: EntityPath, - pub timeline: Timeline, - pub component_name: ComponentName, -} - -impl re_types_core::SizeBytes for CacheKey { - #[inline] - fn heap_size_bytes(&self) -> u64 { - let Self { - entity_path, - timeline, - component_name, - } = self; - entity_path.heap_size_bytes() - + timeline.heap_size_bytes() - + component_name.heap_size_bytes() - } -} - -impl std::fmt::Debug for CacheKey { - #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - entity_path, - timeline, - component_name, - } = self; - f.write_fmt(format_args!( - "{entity_path}:{component_name} on {}", - timeline.name() - )) - } -} - -impl CacheKey { - #[inline] - pub fn new( - entity_path: impl Into, - timeline: impl Into, - component_name: impl Into, - ) -> Self { - Self { - entity_path: entity_path.into(), - timeline: timeline.into(), - component_name: component_name.into(), - } - } -} - -pub struct Caches { - /// The [`StoreId`] of the associated [`DataStore`]. - pub(crate) store_id: StoreId, - - // NOTE: `Arc` so we can cheaply free the top-level lock early when needed. - pub(crate) latest_at_per_cache_key: RwLock>>>, - - // NOTE: `Arc` so we can cheaply free the top-level lock early when needed. - pub(crate) range_per_cache_key: RwLock>>>, -} - -impl std::fmt::Debug for Caches { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { - store_id, - latest_at_per_cache_key, - range_per_cache_key, - } = self; - - let mut strings = Vec::new(); - - strings.push(format!("[LatestAt @ {store_id}]")); - { - let latest_at_per_cache_key = latest_at_per_cache_key.read(); - let latest_at_per_cache_key: BTreeMap<_, _> = latest_at_per_cache_key.iter().collect(); - - for (cache_key, cache) in &latest_at_per_cache_key { - let cache = cache.read(); - strings.push(format!( - " [{cache_key:?} (pending_invalidation_min={:?})]", - cache.pending_invalidations.first().map(|&t| cache_key - .timeline - .format_time_range_utc(&TimeRange::new(t, TimeInt::MAX))), - )); - strings.push(indent::indent_all_by(4, format!("{cache:?}"))); - } - } - - strings.push(format!("[Range @ {store_id}]")); - { - let range_per_cache_key = range_per_cache_key.read(); - let range_per_cache_key: BTreeMap<_, _> = range_per_cache_key.iter().collect(); - - for (cache_key, cache) in &range_per_cache_key { - let cache = cache.read(); - strings.push(format!( - " [{cache_key:?} (pending_invalidation_min={:?})]", - cache.pending_invalidation.map(|t| cache_key - .timeline - .format_time_range_utc(&TimeRange::new(t, TimeInt::MAX))), - )); - strings.push(indent::indent_all_by(4, format!("{cache:?}"))); - } - } - - f.write_str(&strings.join("\n").replace("\n\n", "\n")) - } -} - -impl Caches { - #[inline] - pub fn new(store: &DataStore) -> Self { - Self { - store_id: store.id().clone(), - latest_at_per_cache_key: Default::default(), - range_per_cache_key: Default::default(), - } - } -} - -impl StoreSubscriber for Caches { - #[inline] - fn name(&self) -> String { - "rerun.store_subscribers.QueryCache".into() - } - - #[inline] - fn as_any(&self) -> &dyn std::any::Any { - self - } - - #[inline] - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - - fn on_events(&mut self, events: &[StoreEvent]) { - re_tracing::profile_function!(format!("num_events={}", events.len())); - - #[derive(Default, Debug)] - struct CompactedEvents { - static_: HashSet<(EntityPath, ComponentName)>, - temporal: HashMap>, - } - - let mut compacted = CompactedEvents::default(); - - for event in events { - let StoreEvent { - store_id, - store_generation: _, - event_id: _, - diff, - } = event; - - assert!( - self.store_id == *store_id, - "attempted to use a query cache {} with the wrong datastore ({})", - self.store_id, - store_id, - ); - - let StoreDiff { - kind: _, // Don't care: both additions and deletions invalidate query results. - row_id: _, - times, - entity_path, - cells, - } = diff; - - { - re_tracing::profile_scope!("compact events"); - - if times.is_empty() { - for component_name in cells.keys() { - compacted - .static_ - .insert((entity_path.clone(), *component_name)); - } - } - - for &(timeline, data_time) in times { - for component_name in cells.keys() { - let key = CacheKey::new(entity_path.clone(), timeline, *component_name); - let data_times = compacted.temporal.entry(key).or_default(); - data_times.insert(data_time); - } - } - } - } - - let caches_latest_at = self.latest_at_per_cache_key.write(); - let caches_range = self.range_per_cache_key.write(); - // NOTE: Don't release the top-level locks -- even though this cannot happen yet with - // our current macro-architecture, we want to prevent queries from concurrently - // running while we're updating the invalidation flags. - - { - re_tracing::profile_scope!("static"); - - // TODO(cmc): This is horribly stupid and slow and can easily be made faster by adding - // yet another layer of caching indirection. - // But since this pretty much never happens in practice, let's not go there until we - // have metrics showing that show we need to. - for (entity_path, component_name) in compacted.static_ { - for (key, cache) in caches_latest_at.iter() { - if key.entity_path == entity_path && key.component_name == component_name { - cache.write().pending_invalidations.insert(TimeInt::STATIC); - } - } - - for (key, cache) in caches_range.iter() { - if key.entity_path == entity_path && key.component_name == component_name { - cache.write().pending_invalidation = Some(TimeInt::STATIC); - } - } - } - } - - { - re_tracing::profile_scope!("temporal"); - - for (key, times) in compacted.temporal { - if let Some(cache) = caches_latest_at.get(&key) { - cache - .write() - .pending_invalidations - .extend(times.iter().copied()); - } - - if let Some(cache) = caches_range.get(&key) { - let pending_invalidation = &mut cache.write().pending_invalidation; - let min_time = times.first().copied(); - *pending_invalidation = - Option::min(*pending_invalidation, min_time).or(min_time); - } - } - } - } -} diff --git a/crates/re_query_cache2/src/cache_stats.rs b/crates/re_query_cache2/src/cache_stats.rs deleted file mode 100644 index 7c205f5a8321..000000000000 --- a/crates/re_query_cache2/src/cache_stats.rs +++ /dev/null @@ -1,100 +0,0 @@ -use std::collections::BTreeMap; - -use re_log_types::TimeRange; -use re_types_core::SizeBytes as _; - -use crate::{CacheKey, Caches}; - -// --- - -/// Stats for all primary caches. -/// -/// Fetch them via [`Caches::stats`]. -#[derive(Default, Debug, Clone)] -pub struct CachesStats { - pub latest_at: BTreeMap, - pub range: BTreeMap, CachedComponentStats)>, -} - -impl CachesStats { - #[inline] - pub fn total_size_bytes(&self) -> u64 { - re_tracing::profile_function!(); - - let Self { latest_at, range } = self; - - let latest_at_size_bytes: u64 = - latest_at.values().map(|stats| stats.total_size_bytes).sum(); - let range_size_bytes: u64 = range - .values() - .map(|(_, stats)| stats.total_size_bytes) - .sum(); - - latest_at_size_bytes + range_size_bytes - } -} - -/// Stats for a cached component. -#[derive(Default, Debug, Clone)] -pub struct CachedComponentStats { - pub total_indices: u64, - pub total_instances: u64, - pub total_size_bytes: u64, -} - -impl Caches { - /// Computes the stats for all primary caches. - pub fn stats(&self) -> CachesStats { - re_tracing::profile_function!(); - - let latest_at = { - let latest_at = self.latest_at_per_cache_key.read_recursive().clone(); - // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. - - latest_at - .iter() - .map(|(key, cache)| { - let cache = cache.read_recursive(); - ( - key.clone(), - CachedComponentStats { - total_indices: cache.per_data_time.len() as _, - total_instances: cache - .per_data_time - .values() - .map(|results| results.num_instances()) - .sum(), - total_size_bytes: cache.total_size_bytes(), - }, - ) - }) - .collect() - }; - - let range = { - let range = self.range_per_cache_key.read_recursive().clone(); - // Implicitly releasing top-level cache mappings -- concurrent queries can run once again. - - range - .iter() - .map(|(key, cache)| { - let cache = cache.read_recursive(); - let cache = cache.per_data_time.read_recursive(); - ( - key.clone(), - ( - cache.time_range(), - CachedComponentStats { - total_indices: cache.indices.len() as _, - total_instances: cache.num_instances(), - total_size_bytes: cache.total_size_bytes(), - }, - ), - ) - }) - .collect() - }; - - CachesStats { latest_at, range } - } -} diff --git a/crates/re_query_cache2/src/flat_vec_deque.rs b/crates/re_query_cache2/src/flat_vec_deque.rs deleted file mode 100644 index a5508f0391c1..000000000000 --- a/crates/re_query_cache2/src/flat_vec_deque.rs +++ /dev/null @@ -1,945 +0,0 @@ -use std::{collections::VecDeque, ops::Range}; - -use itertools::Itertools as _; - -use re_types_core::SizeBytes; - -// --- - -/// A [`FlatVecDeque`] that can be erased into a trait object. -/// -/// Methods that don't require monomorphization over `T` are made dynamically dispatchable. -pub trait ErasedFlatVecDeque: std::any::Any { - fn as_any(&self) -> &dyn std::any::Any; - - fn as_any_mut(&mut self) -> &mut dyn std::any::Any; - - fn into_any(self: Box) -> Box; - - /// Dynamically dispatches to [`FlatVecDeque::num_entries`]. - /// - /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to - /// avoid even with explicit syntax and that silently lead to infinite recursions. - fn dyn_num_entries(&self) -> usize; - - /// Dynamically dispatches to [`FlatVecDeque::num_values`]. - /// - /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to - /// avoid even with explicit syntax and that silently lead to infinite recursions. - fn dyn_num_values(&self) -> usize; - - /// Dynamically dispatches to [`FlatVecDeque::remove`]. - /// - /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to - /// avoid even with explicit syntax and that silently lead to infinite recursions. - fn dyn_remove(&mut self, at: usize); - - /// Dynamically dispatches to [`FlatVecDeque::remove`]. - /// - /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to - /// avoid even with explicit syntax and that silently lead to infinite recursions. - fn dyn_remove_range(&mut self, range: Range); - - /// Dynamically dispatches to [`FlatVecDeque::truncate`]. - /// - /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to - /// avoid even with explicit syntax and that silently lead to infinite recursions. - fn dyn_truncate(&mut self, at: usize); - - /// Dynamically dispatches to [` as SizeBytes>::total_size_bytes(self)`]. - /// - /// This is prefixed with `dyn_` to avoid method dispatch ambiguities that are very hard to - /// avoid even with explicit syntax and that silently lead to infinite recursions. - fn dyn_total_size_bytes(&self) -> u64; -} - -impl ErasedFlatVecDeque for FlatVecDeque { - #[inline] - fn as_any(&self) -> &dyn std::any::Any { - self - } - - #[inline] - fn as_any_mut(&mut self) -> &mut dyn std::any::Any { - self - } - - #[inline] - fn into_any(self: Box) -> Box { - self - } - - #[inline] - fn dyn_num_entries(&self) -> usize { - self.num_entries() - } - - #[inline] - fn dyn_num_values(&self) -> usize { - self.num_values() - } - - #[inline] - fn dyn_remove(&mut self, at: usize) { - FlatVecDeque::::remove(self, at); - } - - #[inline] - fn dyn_remove_range(&mut self, range: Range) { - FlatVecDeque::::remove_range(self, range); - } - - #[inline] - fn dyn_truncate(&mut self, at: usize) { - FlatVecDeque::::truncate(self, at); - } - - #[inline] - fn dyn_total_size_bytes(&self) -> u64 { - as SizeBytes>::total_size_bytes(self) - } -} - -// --- - -/// A double-ended queue implemented with a pair of growable ring buffers, where every single -/// entry is a flattened array of values. -/// -/// Logically like a `VecDeque>`, but with a less fragmented memory layout (each `Box<[T]>` -/// gets copied/inlined into the `FlatVecDeque`). -/// `FlatVecDeque` therefore optimizes for reads (cache locality, specifically) while `VecDeque>` -/// optimizes for writes. -/// -/// You can think of this as the native/deserialized version of an Arrow `ListArray`. -/// This is particularly useful when working with many small arrays of data (e.g. Rerun's -/// `TimeSeriesScalar`s). -// -// TODO(cmc): We could even use a bitmap for T=Option, which would bring this that much -// closer to a deserialized version of an Arrow array. -#[derive(Debug, Clone)] -pub struct FlatVecDeque { - /// Stores every value in the `FlatVecDeque` in a flattened `VecDeque`. - /// - /// E.g.: - /// - `FlatVecDeque[]` -> values=`[]`. - /// - `FlatVecDeque[[], [], []]` -> values=`[]`. - /// - `FlatVecDeque[[], [0], [1, 2, 3], [4, 5]]` -> values=`[0, 1, 2, 3, 4, 5]`. - values: VecDeque, - - /// Keeps track of each entry, i.e. logical slices of data. - /// - /// E.g.: - /// - `FlatVecDeque[]` -> offsets=`[]`. - /// - `FlatVecDeque[[], [], []]` -> offsets=`[0, 0, 0]`. - /// - `FlatVecDeque[[], [0], [1, 2, 3], [4, 5]]` -> offsets=`[0, 1, 4, 6]`. - offsets: VecDeque, -} - -impl SizeBytes for FlatVecDeque { - #[inline] - fn heap_size_bytes(&self) -> u64 { - // NOTE: It's all on the heap at this point. - - let values_size_bytes = if T::is_pod() { - (self.num_values() * std::mem::size_of::()) as _ - } else { - self.values - .iter() - .map(SizeBytes::total_size_bytes) - .sum::() - }; - - let offsets_size_bytes = self.num_entries() * std::mem::size_of::(); - - values_size_bytes + offsets_size_bytes as u64 - } -} - -impl From> for FlatVecDeque { - #[inline] - fn from(values: VecDeque) -> Self { - let num_values = values.len(); - Self { - values, - offsets: std::iter::once(num_values).collect(), - } - } -} - -impl From> for FlatVecDeque { - #[inline] - fn from(values: Vec) -> Self { - let num_values = values.len(); - Self { - values: values.into(), - offsets: std::iter::once(num_values).collect(), - } - } -} - -impl Default for FlatVecDeque { - #[inline] - fn default() -> Self { - Self::new() - } -} - -impl FlatVecDeque { - #[inline] - pub const fn new() -> Self { - Self { - values: VecDeque::new(), - offsets: VecDeque::new(), - } - } - - #[inline] - pub fn from_vecs(entries: impl IntoIterator>) -> Self { - let mut this = Self::new(); - - // NOTE: Do not use any of the insertion methods, they rely on `from_vecs` in the first - // place! - let mut value_offset = 0; - for entry in entries { - value_offset += entry.len(); // increment first! - this.offsets.push_back(value_offset); - this.values.extend(entry); - } - - this - } - - /// How many entries are there in the deque? - /// - /// Keep in mind: each entry is itself an array of values. - /// Use [`Self::num_values`] to get the total number of values across all entries. - #[inline] - pub fn num_entries(&self) -> usize { - self.offsets.len() - } - - /// How many values are there in the deque? - /// - /// Keep in mind: each entry in the deque holds an array of values. - /// Use [`Self::num_entries`] to get the total number of entries, irrelevant of how many - /// values each entry holds. - #[inline] - pub fn num_values(&self) -> usize { - self.values.len() - } - - #[inline] - fn value_offset(&self, entry_index: usize) -> usize { - if entry_index == 0 { - 0 - } else { - self.offsets[entry_index - 1] - } - } - - #[inline] - fn iter_offset_ranges(&self) -> impl Iterator> + '_ { - std::iter::once(0) - .chain(self.offsets.iter().copied()) - .tuple_windows::<(_, _)>() - .map(|(start, end)| (start..end)) - } -} - -// --- - -impl FlatVecDeque { - /// Iterates over all the entries in the deque. - /// - /// This is the same as `self.range(0..self.num_entries())`. - /// - /// Keep in mind that each entry is an array of values! - #[inline] - pub fn iter(&self) -> impl Iterator { - self.range(0..self.num_entries()) - } - - /// Iterates over all the entries in the deque in the given `entry_range`. - /// - /// Keep in mind that each entry is an array of values! - #[inline] - pub fn range(&self, entry_range: Range) -> impl Iterator { - let (values_left, values_right) = self.values.as_slices(); - // NOTE: We can't slice into our offsets, we don't even know if they're contiguous in - // memory at this point -> skip() and take(). - self.iter_offset_ranges() - .skip(entry_range.start) - .take(entry_range.len()) - .map(|offsets| { - if offsets.is_empty() { - return &[] as &'_ [T]; - } - - // NOTE: We do not need `make_contiguous` here because we always guarantee - // that a single entry's worth of values is fully contained in either the left or - // right buffer, but never straddling across both. - if offsets.start < values_left.len() { - &values_left[offsets] - } else { - &values_right[offsets] - } - }) - } -} - -#[test] -fn range() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); - - assert_iter_eq(&[&[1, 2, 3]], v.range(0..1)); - assert_iter_eq(&[&[4, 5, 6, 7]], v.range(1..2)); - assert_iter_eq(&[&[8, 9, 10]], v.range(2..3)); - - assert_iter_eq( - &[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], - v.range(0..v.num_entries()), - ); - - assert_iter_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], v.iter()); -} - -// --- - -impl FlatVecDeque { - /// Prepends an entry comprised of `values` to the deque. - /// - /// This is the same as `self.insert(0, values)`. - /// - /// See [`Self::insert`] for more information. - #[inline] - pub fn push_front(&mut self, values: impl IntoIterator) { - self.insert(0, values); - } - - /// Appends an entry comprised of `values` to the deque. - /// - /// This is the same as `self.insert(self.num_entries(), values)`. - /// - /// See [`Self::insert`] for more information. - #[inline] - pub fn push_back(&mut self, values: impl IntoIterator) { - self.insert(self.num_entries(), values); - } - - /// Inserts a single entry at `entry_index`, comprised of the multiple elements given as `values`. - /// - /// This is O(1) if `entry_index` corresponds to either the start or the end of the deque. - /// Otherwise, this requires splitting the deque into two pieces then stitching them back together - /// at both ends of the added data. - /// - /// Panics if `entry_index` is out of bounds. - /// Panics if `values` is empty. - #[inline] - pub fn insert(&mut self, entry_index: usize, values: impl IntoIterator) { - let values: VecDeque = values.into_iter().collect(); - let deque = values.into(); - self.insert_deque(entry_index, deque); - } - - /// Prepends multiple entries, each comprised of the multiple elements given in `entries`, - /// to the deque. - /// - /// This is the same as `self.insert_many(0, entries)`. - /// - /// See [`Self::insert_many`] for more information. - #[inline] - pub fn push_many_front(&mut self, entries: impl IntoIterator>) { - self.insert_many(0, entries); - } - - /// Appends multiple entries, each comprised of the multiple elements given in `entries`, - /// to the deque. - /// - /// This is the same as `self.insert_many(self.num_entries(), entries)`. - /// - /// See [`Self::insert_many`] for more information. - #[inline] - pub fn push_many_back(&mut self, entries: impl IntoIterator>) { - self.insert_many(self.num_entries(), entries); - } - - /// Inserts multiple entries, starting at `entry_index` onwards, each comprised of the multiple elements - /// given in `entries`. - /// - /// This is O(1) if `entry_index` corresponds to either the start or the end of the deque. - /// Otherwise, this requires splitting the deque into two pieces then stitching them back together - /// at both ends of the added data. - /// - /// Panics if `entry_index` is out of bounds. - /// Panics if any of the value arrays in `entries` is empty. - #[inline] - pub fn insert_many(&mut self, entry_index: usize, entries: impl IntoIterator>) { - let deque = Self::from_vecs(entries); - self.insert_deque(entry_index, deque); - } - - /// Prepends another full deque to the deque. - /// - /// This is the same as `self.insert_deque(0, rhs)`. - /// - /// See [`Self::insert_deque`] for more information. - #[inline] - pub fn push_front_deque(&mut self, rhs: FlatVecDeque) { - self.insert_deque(0, rhs); - } - - /// Appends another full deque to the deque. - /// - /// This is the same as `self.insert_deque(0, rhs)`. - /// - /// See [`Self::insert_deque`] for more information. - #[inline] - pub fn push_back_deque(&mut self, rhs: FlatVecDeque) { - self.insert_deque(self.num_entries(), rhs); - } - - /// Inserts another full deque, starting at `entry_index` and onwards. - /// - /// This is O(1) if `entry_index` corresponds to either the start or the end of the deque. - /// Otherwise, this requires splitting the deque into two pieces then stitching them back together - /// at both ends of the added data. - /// - /// Panics if `entry_index` is out of bounds. - /// Panics if any of the value arrays in `entries` is empty. - pub fn insert_deque(&mut self, entry_index: usize, mut rhs: FlatVecDeque) { - // NOTE: We're inserting _beyond_ the last element. - if entry_index == self.num_entries() { - let max_value_offset = self.offsets.back().copied().unwrap_or_default(); - self.offsets - .extend(rhs.offsets.into_iter().map(|o| o + max_value_offset)); - self.values.extend(rhs.values); - return; - } else if entry_index == 0 { - rhs.push_back_deque(std::mem::take(self)); - *self = rhs; - return; - } - - let right = self.split_off(entry_index); - self.push_back_deque(rhs); - self.push_back_deque(right); - - debug_assert!(self.iter_offset_ranges().all(|r| r.start <= r.end)); - } -} - -#[test] -fn insert() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert(0, [1, 2, 3]); - assert_deque_eq(&[&[1, 2, 3]], &v); - - v.insert(0, [4, 5, 6, 7]); - assert_deque_eq(&[&[4, 5, 6, 7], &[1, 2, 3]], &v); - - v.insert(0, [8, 9]); - assert_deque_eq(&[&[8, 9], &[4, 5, 6, 7], &[1, 2, 3]], &v); - - v.insert(2, [10, 11, 12, 13]); - assert_deque_eq(&[&[8, 9], &[4, 5, 6, 7], &[10, 11, 12, 13], &[1, 2, 3]], &v); - - v.insert(v.num_entries(), [14, 15]); - assert_deque_eq( - &[ - &[8, 9], - &[4, 5, 6, 7], - &[10, 11, 12, 13], - &[1, 2, 3], - &[14, 15], - ], - &v, - ); - - v.insert(v.num_entries() - 1, [42]); - assert_deque_eq( - &[ - &[8, 9], - &[4, 5, 6, 7], - &[10, 11, 12, 13], - &[1, 2, 3], - &[42], - &[14, 15], - ], - &v, - ); -} - -#[test] -fn insert_empty() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.push_back([]); - v.push_back([]); - v.push_back([]); - - assert_deque_eq(&[&[], &[], &[]], &v); -} - -// Simulate the bug that was making everything crash on the face tracking example (ultimately -// caused by recursive clears). -#[test] -fn insert_some_and_empty() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.push_back([0]); - v.push_back([]); - - v.push_back([1]); - v.push_back([]); - - v.push_back([2]); - v.push_back([]); - - // That used to crash. - assert_deque_eq(&[&[0], &[], &[1], &[], &[2], &[]], &v); -} - -#[test] -fn insert_many() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); - - v.insert_many(0, [vec![20], vec![21], vec![22]]); - assert_deque_eq( - &[&[20], &[21], &[22], &[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], - &v, - ); - - v.insert_many(4, [vec![41, 42], vec![43]]); - assert_deque_eq( - &[ - &[20], - &[21], - &[22], - &[1, 2, 3], - &[41, 42], - &[43], - &[4, 5, 6, 7], - &[8, 9, 10], - ], - &v, - ); - - v.insert_many(v.num_entries(), [vec![100], vec![200, 300, 400]]); - assert_deque_eq( - &[ - &[20], - &[21], - &[22], - &[1, 2, 3], - &[41, 42], - &[43], - &[4, 5, 6, 7], - &[8, 9, 10], - &[100], - &[200, 300, 400], - ], - &v, - ); -} - -#[test] -fn insert_deque() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert_deque( - 0, - FlatVecDeque::from_vecs([vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]), - ); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); - - v.insert_deque(0, FlatVecDeque::from_vecs([vec![20], vec![21], vec![22]])); - assert_deque_eq( - &[&[20], &[21], &[22], &[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], - &v, - ); - - v.insert_deque(4, FlatVecDeque::from_vecs([vec![41, 42], vec![43]])); - assert_deque_eq( - &[ - &[20], - &[21], - &[22], - &[1, 2, 3], - &[41, 42], - &[43], - &[4, 5, 6, 7], - &[8, 9, 10], - ], - &v, - ); - - v.insert_deque( - v.num_entries(), - FlatVecDeque::from_vecs([vec![100], vec![200, 300, 400]]), - ); - assert_deque_eq( - &[ - &[20], - &[21], - &[22], - &[1, 2, 3], - &[41, 42], - &[43], - &[4, 5, 6, 7], - &[8, 9, 10], - &[100], - &[200, 300, 400], - ], - &v, - ); -} - -// --- - -impl FlatVecDeque { - /// Splits the deque into two at the given index. - /// - /// Returns a newly allocated `FlatVecDeque`. `self` contains entries `[0, entry_index)`, - /// and the returned deque contains entries `[entry_index, num_entries)`. - /// - /// Note that the capacity of `self` does not change. - /// - /// Panics if `entry_index` is out of bounds. - #[inline] - #[must_use = "use `.truncate()` if you don't need the other half"] - pub fn split_off(&mut self, entry_index: usize) -> Self { - let value_offset = self.value_offset(entry_index); - - let mut offsets = self.offsets.split_off(entry_index); - for offset in &mut offsets { - *offset -= value_offset; - } - - Self { - values: self.values.split_off(value_offset), - offsets, - } - } - - /// Shortens the deque, keeping all entries up to `entry_index` (excluded), and - /// dropping the rest. - /// - /// If `entry_index` is greater or equal to [`Self::num_entries`], this has no effect. - #[inline] - pub fn truncate(&mut self, entry_index: usize) { - if entry_index < self.num_entries() { - self.values.truncate(self.value_offset(entry_index)); - self.offsets.truncate(entry_index); - } - } - - /// Removes the entry at `entry_index` from the deque. - /// - /// This is O(1) if `entry_index` corresponds to either the start or the end of the deque. - /// Otherwise, this requires splitting the deque into three pieces, dropping the superfluous - /// one, then stitching the two remaining pices back together. - /// - /// Panics if `entry_index` is out of bounds. - pub fn remove(&mut self, entry_index: usize) { - let (start_offset, end_offset) = ( - self.value_offset(entry_index), - self.value_offset(entry_index + 1), - ); - let offset_count = end_offset - start_offset; - - if entry_index + 1 == self.num_entries() { - self.offsets.truncate(self.num_entries() - 1); - self.values.truncate(self.values.len() - offset_count); - return; - } else if entry_index == 0 { - *self = self.split_off(entry_index + 1); - return; - } - - // NOTE: elegant, but way too slow :) - // let right = self.split_off(entry_index + 1); - // _ = self.split_off(self.num_entries() - 1); - // self.push_back_deque(right); - - _ = self.offsets.remove(entry_index); - for offset in self.offsets.range_mut(entry_index..) { - *offset -= offset_count; - } - - let right = self.values.split_off(end_offset); - self.values.truncate(self.values.len() - offset_count); - self.values.extend(right); - } - - /// Removes all entries within the given `entry_range` from the deque. - /// - /// This is O(1) if `entry_range` either starts at the beginning of the deque, or ends at - /// the end of the deque, or both. - /// Otherwise, this requires splitting the deque into three pieces, dropping the superfluous - /// one, then stitching the two remaining pieces back together. - /// - /// Panics if `entry_range` is either out of bounds or isn't monotonically increasing. - #[inline] - pub fn remove_range(&mut self, entry_range: Range) { - assert!(entry_range.start <= entry_range.end); - - if entry_range.start == entry_range.end { - return; - } - - let (start_offset, end_offset) = ( - self.value_offset(entry_range.start), - self.value_offset(entry_range.end), - ); - let offset_count = end_offset - start_offset; - - // Reminder: `entry_range.end` is exclusive. - if entry_range.end == self.num_entries() { - self.offsets - .truncate(self.num_entries() - entry_range.len()); - self.values.truncate(self.values.len() - offset_count); - return; - } else if entry_range.start == 0 { - *self = self.split_off(entry_range.end); - return; - } - - let right = self.split_off(entry_range.end); - _ = self.split_off(self.num_entries() - entry_range.len()); - self.push_back_deque(right); - } -} - -#[test] -fn truncate() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); - - { - let mut v = v.clone(); - v.truncate(0); - assert_deque_eq(&[], &v); - } - - { - let mut v = v.clone(); - v.truncate(1); - assert_deque_eq(&[&[1, 2, 3]], &v); - } - - { - let mut v = v.clone(); - v.truncate(2); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &v); - } - - { - let mut v = v.clone(); - v.truncate(3); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); - } -} - -#[test] -fn split_off() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); - - { - let mut left = v.clone(); - let right = left.split_off(0); - - assert_deque_eq(&[], &left); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &right); - } - - { - let mut left = v.clone(); - let right = left.split_off(1); - - assert_deque_eq(&[&[1, 2, 3]], &left); - assert_deque_eq(&[&[4, 5, 6, 7], &[8, 9, 10]], &right); - } - - { - let mut left = v.clone(); - let right = left.split_off(2); - - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &left); - assert_deque_eq(&[&[8, 9, 10]], &right); - } - - { - let mut left = v.clone(); - let right = left.split_off(3); - - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &left); - assert_deque_eq(&[], &right); - } -} - -#[test] -fn remove() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert(0, [1, 2, 3]); - assert_deque_eq(&[&[1, 2, 3]], &v); - - v.remove(0); - assert_deque_eq(&[], &v); - - v.insert(0, [1, 2, 3]); - assert_deque_eq(&[&[1, 2, 3]], &v); - - v.insert(1, [4, 5, 6, 7]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &v); - - v.insert(2, [8, 9]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9]], &v); - - v.remove(0); - assert_deque_eq(&[&[4, 5, 6, 7], &[8, 9]], &v); - - v.insert(0, [1, 2, 3]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9]], &v); - - v.remove(1); - assert_deque_eq(&[&[1, 2, 3], &[8, 9]], &v); - - v.insert(1, [4, 5, 6, 7]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9]], &v); - - v.remove(2); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &v); - - v.remove(0); - assert_deque_eq(&[&[4, 5, 6, 7]], &v); - - v.remove(0); - assert_deque_eq(&[], &v); -} - -#[test] -#[should_panic(expected = "Out of bounds access")] -fn remove_empty() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.remove(0); -} - -#[test] -#[should_panic(expected = "Out of bounds access")] -fn remove_oob() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert(0, [1, 2, 3]); - assert_deque_eq(&[&[1, 2, 3]], &v); - - assert_eq!(1, v.num_entries()); - assert_eq!(3, v.num_values()); - - v.remove(1); -} - -#[test] -fn remove_range() { - let mut v: FlatVecDeque = FlatVecDeque::new(); - - assert_eq!(0, v.num_entries()); - assert_eq!(0, v.num_values()); - - v.insert_many(0, [vec![1, 2, 3], vec![4, 5, 6, 7], vec![8, 9, 10]]); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7], &[8, 9, 10]], &v); - - { - let mut v = v.clone(); - v.remove_range(0..1); - assert_deque_eq(&[&[4, 5, 6, 7], &[8, 9, 10]], &v); - } - - { - let mut v = v.clone(); - v.remove_range(1..2); - assert_deque_eq(&[&[1, 2, 3], &[8, 9, 10]], &v); - } - - { - let mut v = v.clone(); - v.remove_range(2..3); - assert_deque_eq(&[&[1, 2, 3], &[4, 5, 6, 7]], &v); - } - - { - let mut v = v.clone(); - v.remove_range(0..2); - assert_deque_eq(&[&[8, 9, 10]], &v); - } - - { - let mut v = v.clone(); - v.remove_range(1..3); - assert_deque_eq(&[&[1, 2, 3]], &v); - } - - { - let mut v = v.clone(); - v.remove_range(0..3); - assert_deque_eq(&[], &v); - } -} - -// --- - -#[cfg(test)] -fn assert_deque_eq(expected: &[&'_ [i64]], got: &FlatVecDeque) { - similar_asserts::assert_eq!(expected, got.iter().collect_vec()); -} - -#[cfg(test)] -fn assert_iter_eq<'a>(expected: &[&'_ [i64]], got: impl Iterator) { - similar_asserts::assert_eq!(expected, got.collect_vec()); -} diff --git a/crates/re_query_cache2/src/lib.rs b/crates/re_query_cache2/src/lib.rs deleted file mode 100644 index cb995ab447aa..000000000000 --- a/crates/re_query_cache2/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Caching datastructures for `re_query`. - -mod cache; -mod cache_stats; -mod flat_vec_deque; -mod latest_at; -mod range; - -pub use self::cache::{CacheKey, Caches}; -pub use self::cache_stats::{CachedComponentStats, CachesStats}; -pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; -pub use self::latest_at::{ - CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, -}; -pub use self::range::{CachedRangeComponentResults, CachedRangeData, CachedRangeResults}; - -pub(crate) use self::latest_at::LatestAtCache; -pub(crate) use self::range::{CachedRangeComponentResultsInner, RangeCache}; - -pub use re_query2::{ - clamped_zip::*, range_zip::*, ExtraQueryHistory, Promise, PromiseId, PromiseResolver, - PromiseResult, QueryError, Result, ToArchetype, VisibleHistory, VisibleHistoryBoundary, -}; - -pub mod external { - pub use re_query2; - - pub use paste; - pub use seq_macro; -} - -// --- - -use re_data_store::{LatestAtQuery, RangeQuery}; - -#[derive(Debug)] -pub enum CachedResults { - LatestAt(LatestAtQuery, CachedLatestAtResults), - Range(RangeQuery, CachedRangeResults), -} - -impl From<(LatestAtQuery, CachedLatestAtResults)> for CachedResults { - #[inline] - fn from((query, results): (LatestAtQuery, CachedLatestAtResults)) -> Self { - Self::LatestAt(query, results) - } -} - -impl From<(RangeQuery, CachedRangeResults)> for CachedResults { - #[inline] - fn from((query, results): (RangeQuery, CachedRangeResults)) -> Self { - Self::Range(query, results) - } -} diff --git a/crates/re_query_cache2/tests/latest_at.rs b/crates/re_query_cache2/tests/latest_at.rs deleted file mode 100644 index 016f1c3d5c80..000000000000 --- a/crates/re_query_cache2/tests/latest_at.rs +++ /dev/null @@ -1,526 +0,0 @@ -//! Contains: -//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_query_tests.rs`, with caching enabled. -//! - Invalidation tests. - -use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_query2::PromiseResolver; -use re_query_cache2::Caches; -use re_types::Archetype as _; -use re_types_core::{components::InstanceKey, Loggable as _}; - -// --- - -#[test] -fn simple_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn static_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance.. statically! - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn no_instance_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign them colors with explicit instances - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn missing_column_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn splatted_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign all of them a color via splat - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn invalidation_xxx() { - let entity_path = "point"; - - let test_invalidation = |query: LatestAtQuery, - present_data_timepoint: TimePoint, - past_data_timepoint: TimePoint, - future_data_timepoint: TimePoint| { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify present --- - - // Modify the PoV component - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint, - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify past --- - - // Modify the PoV component - let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, past_data_timepoint, 2, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify future --- - - // Modify the PoV component - let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - future_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(16, 17, 18)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - }; - - let timeless = TimePoint::default(); - let frame_122 = build_frame_nr(122); - let frame_123 = build_frame_nr(123); - let frame_124 = build_frame_nr(124); - - test_invalidation( - LatestAtQuery::new(frame_123.0, frame_123.1), - [frame_123].into(), - [frame_122].into(), - [frame_124].into(), - ); - - test_invalidation( - LatestAtQuery::new(frame_123.0, frame_123.1), - [frame_123].into(), - timeless, - [frame_124].into(), - ); -} - -// Test the following scenario: -// ```py -// rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// -// # Do first query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[] -// -// rr.set_time(2) -// rr.log_components("points", rr.components.MyColor(0xFF0000)) -// -// # Do second query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0xFF0000] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x0000FF)) -// -// # Do third query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x0000FF] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x00FF00)) -// -// # Do fourth query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x00FF00] -// ``` -#[test] -fn invalidation_of_future_optionals() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - let frame2 = [build_frame_nr(2)]; - let frame3 = [build_frame_nr(3)]; - - let query_time = [build_frame_nr(9999)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame2, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn static_invalidation() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - - let query_time = [build_frame_nr(9999)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -// --- - -fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { - caches.on_events(&[store.insert_row(row).unwrap()]); -} - -fn query_and_compare( - caches: &Caches, - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, -) { - re_log::setup_logging(); - - let resolver = PromiseResolver::default(); - - for _ in 0..3 { - let cached = caches.latest_at( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let cached_points = cached.get_required(MyPoint::name()).unwrap(); - let cached_point_data = cached_points - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let cached_colors = cached.get_or_empty(MyColor::name()); - let cached_color_data = cached_colors - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let expected = re_query2::latest_at( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let expected_points = expected.get_required(MyPoint::name()).unwrap(); - let expected_point_data = expected_points - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let expected_colors = expected.get_or_empty(MyColor::name()); - let expected_color_data = expected_colors - .to_dense::(&resolver) - .flatten() - .unwrap(); - - // eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected.compound_index, cached.compound_index); - similar_asserts::assert_eq!(expected_point_data, cached_point_data); - similar_asserts::assert_eq!(expected_color_data, cached_color_data); - } -} diff --git a/crates/re_query_cache2/tests/range.rs b/crates/re_query_cache2/tests/range.rs deleted file mode 100644 index d06a7a8d8b9a..000000000000 --- a/crates/re_query_cache2/tests/range.rs +++ /dev/null @@ -1,586 +0,0 @@ -use itertools::{izip, Itertools as _}; - -use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_query_cache2::{Caches, PromiseResolver, PromiseResult}; -use re_types::{components::InstanceKey, Archetype}; -use re_types_core::Loggable as _; - -// --- - -#[test] -fn simple_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - Ok(()) -} - -#[test] -fn static_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - colors.clone(), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - colors.clone(), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - query_and_compare(&caches, &store, &query, &entity_path); -} - -#[test] -fn simple_splatted_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); -} - -#[test] -fn invalidation() { - let entity_path = "point"; - - let test_invalidation = |query: RangeQuery, - present_data_timepoint: TimePoint, - past_data_timepoint: TimePoint, - future_data_timepoint: TimePoint| { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify present --- - - // Modify the PoV component - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint, - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify past --- - - // Modify the PoV component - let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify future --- - - // Modify the PoV component - let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - future_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(16, 17, 18)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - }; - - let timeless = TimePoint::default(); - let frame_122 = build_frame_nr(122); - let frame_123 = build_frame_nr(123); - let frame_124 = build_frame_nr(124); - - test_invalidation( - RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), - [frame_123].into(), - [frame_122].into(), - [frame_124].into(), - ); - - test_invalidation( - RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), - [frame_123].into(), - timeless, - [frame_124].into(), - ); -} - -// Test the following scenario: -// ```py -// rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// -// # Do first query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[] -// -// rr.set_time(2) -// rr.log_components("points", rr.components.MyColor(0xFF0000)) -// -// # Do second query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0xFF0000] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x0000FF)) -// -// # Do third query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x0000FF] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x00FF00)) -// -// # Do fourth query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x00FF00] -// ``` -#[test] -fn invalidation_of_future_optionals() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - let frame2 = [build_frame_nr(2)]; - let frame3 = [build_frame_nr(3)]; - - let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn invalidation_static() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - - let frame0 = [build_frame_nr(TimeInt::ZERO)]; - let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -// --- - -fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { - caches.on_events(&[store.insert_row(row).unwrap()]); -} - -fn query_and_compare( - caches: &Caches, - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, -) { - re_log::setup_logging(); - - let resolver = PromiseResolver::default(); - - for _ in 0..3 { - let cached = caches.range( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let cached_all_points = cached - .get_required(MyPoint::name()) - .unwrap() - .to_dense::(&resolver); - assert!(matches!( - cached_all_points.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())), - )); - let cached_all_points_indexed = cached_all_points.range_indexed(); - - let cached_all_colors = cached - .get_or_empty(MyColor::name()) - .to_dense::(&resolver); - assert!(matches!( - cached_all_colors.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())), - )); - let cached_all_colors_indexed = cached_all_colors.range_indexed(); - - let expected = re_query2::range( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let expected_all_points = expected.get_required(MyPoint::name()).unwrap(); - let expected_all_points_indices = expected_all_points.indices(); - let expected_all_points_data = expected_all_points - .to_dense::(&resolver) - .into_iter() - .map(|batch| batch.flatten().unwrap()) - .collect_vec(); - let expected_all_points_indexed = - izip!(expected_all_points_indices, expected_all_points_data); - - let expected_all_colors = expected.get_or_empty(MyColor::name()); - let expected_all_colors_indices = expected_all_colors.indices(); - let expected_all_colors_data = expected_all_colors - .to_dense::(&resolver) - .into_iter() - .map(|batch| batch.flatten().unwrap()) - .collect_vec(); - let expected_all_colors_indexed = - izip!(expected_all_colors_indices, expected_all_colors_data); - - eprintln!("{query:?}"); - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!( - expected_all_points_indexed - .map(|(index, data)| (*index, data)) - .collect_vec(), - cached_all_points_indexed - .map(|(index, data)| (*index, data.to_vec())) - .collect_vec(), - ); - - similar_asserts::assert_eq!( - expected_all_colors_indexed - .map(|(index, data)| (*index, data)) - .collect_vec(), - cached_all_colors_indexed - .map(|(index, data)| (*index, data.to_vec())) - .collect_vec(), - ); - } -} diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index f1fff5423f9b..5838139635a4 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -1,6 +1,6 @@ use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query_cache2::{CachedLatestAtResults, PromiseResult, ToArchetype}, + external::re_query_cache::{CachedLatestAtResults, PromiseResult, ToArchetype}, EntityDb, }; use re_log_types::EntityPath; diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index b6189eb53312..06b619a9bc55 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -160,7 +160,7 @@ impl SpaceViewClass for DataframeSpaceView { // TODO(#4466): make it explicit if that value results // from a splat joint. - let results = ctx.recording().query_caches2().latest_at( + let results = ctx.recording().query_caches().latest_at( ctx.recording_store(), &latest_at_query, &instance.entity_path, diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index 4f45589b01fc..2bf7b4745914 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -28,7 +28,6 @@ re_log_types.workspace = true re_log.workspace = true re_query.workspace = true re_query_cache.workspace = true -re_query_cache2.workspace = true re_renderer = { workspace = true, features = [ "import-gltf", "import-obj", diff --git a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs index 4f5792346a3b..f7ed6472e5de 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache2::range_zip_1x6; +use re_query_cache::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows2D, diff --git a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs index e5e61d400514..05fdb1ef9764 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache2::range_zip_1x6; +use re_query_cache::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows3D, diff --git a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs index a22b9ed8ebf8..07fb7d9b9acd 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache2::range_zip_1x6; +use re_query_cache::range_zip_1x6; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes2D, diff --git a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs index 9df41ce52207..8819231a5aea 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache2::range_zip_1x7; +use re_query_cache::range_zip_1x7; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes3D, diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index c9eec8176a6c..f63691dc3753 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -3,7 +3,7 @@ use re_data_store::{LatestAtQuery, RangeQuery}; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, TimeInt, Timeline}; use re_query::{ArchetypeView, QueryError}; -use re_query_cache2::{CachedResults, ExtraQueryHistory}; +use re_query_cache::{CachedResults, ExtraQueryHistory}; use re_renderer::DepthOffset; use re_space_view::query_visual_history; use re_types::Archetype; @@ -54,7 +54,7 @@ pub fn query_archetype_with_history( let time_range = visible_history.time_range(*time); let store = entity_db.store(); - let caches = entity_db.query_caches2(); + let caches = entity_db.query_caches(); if !history.enabled || time_range.min() == time_range.max() { let latest_query = LatestAtQuery::new(*timeline, time_range.min()); diff --git a/crates/re_space_view_spatial/src/visualizers/lines2d.rs b/crates/re_space_view_spatial/src/visualizers/lines2d.rs index bca1670ef291..e7c688eab4a7 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache2::range_zip_1x5; +use re_query_cache::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::LineStrips2D, diff --git a/crates/re_space_view_spatial/src/visualizers/lines3d.rs b/crates/re_space_view_spatial/src/visualizers/lines3d.rs index 442c38dd9724..9bbb657425f9 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache2::range_zip_1x5; +use re_query_cache::range_zip_1x5; use re_renderer::PickingLayerInstanceId; use re_types::{ archetypes::LineStrips3D, diff --git a/crates/re_space_view_spatial/src/visualizers/points2d.rs b/crates/re_space_view_spatial/src/visualizers/points2d.rs index 9fe4f1a69039..31bc5389316c 100644 --- a/crates/re_space_view_spatial/src/visualizers/points2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points2d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache2::range_zip_1x5; +use re_query_cache::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points2D, diff --git a/crates/re_space_view_spatial/src/visualizers/points3d.rs b/crates/re_space_view_spatial/src/visualizers/points3d.rs index a0b62e66b133..2d70126c2c5b 100644 --- a/crates/re_space_view_spatial/src/visualizers/points3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points3d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache2::range_zip_1x5; +use re_query_cache::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points3D, diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs index 5ef852651964..27474a9cc886 100644 --- a/crates/re_space_view_spatial/src/visualizers/results_ext.rs +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -1,4 +1,4 @@ -use re_query_cache2::{ +use re_query_cache::{ CachedLatestAtResults, CachedRangeData, CachedRangeResults, CachedResults, PromiseResolver, PromiseResult, }; @@ -14,19 +14,19 @@ pub trait CachedRangeResultsExt { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>>; + ) -> Option>>; fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache2::Result>; + ) -> re_query_cache::Result>; } impl CachedRangeResultsExt for CachedResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { match self { CachedResults::LatestAt(_, results) => results.get_dense(resolver), CachedResults::Range(_, results) => results.get_dense(resolver), @@ -36,7 +36,7 @@ impl CachedRangeResultsExt for CachedResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache2::Result> { + ) -> re_query_cache::Result> { match self { CachedResults::LatestAt(_, results) => results.get_or_empty_dense(resolver), CachedResults::Range(_, results) => results.get_or_empty_dense(resolver), @@ -49,20 +49,20 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?.to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { PromiseResult::Error(err) => { - return Some(Err(re_query_cache2::QueryError::Other(err.into()))) + return Some(Err(re_query_cache::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Error(err) => { - return Some(Err(re_query_cache2::QueryError::Other(err.into()))) + return Some(Err(re_query_cache::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -74,21 +74,17 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache2::Result> { + ) -> re_query_cache::Result> { let results = self.get_or_empty(C::name()).to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { - PromiseResult::Error(err) => { - return Err(re_query_cache2::QueryError::Other(err.into())) - } + PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => { - return Err(re_query_cache2::QueryError::Other(err.into())) - } + PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -101,7 +97,7 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?; let data = CachedRangeData::from_latest_at(resolver, results); @@ -109,13 +105,13 @@ impl CachedRangeResultsExt for CachedLatestAtResults { let (front_status, back_status) = data.status(); match front_status { PromiseResult::Error(err) => { - return Some(Err(re_query_cache2::QueryError::Other(err.into()))) + return Some(Err(re_query_cache::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Error(err) => { - return Some(Err(re_query_cache2::QueryError::Other(err.into()))) + return Some(Err(re_query_cache::QueryError::Other(err.into()))) } PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -127,22 +123,18 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache2::Result> { + ) -> re_query_cache::Result> { let results = self.get_or_empty(C::name()); let data = CachedRangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); match front_status { - PromiseResult::Error(err) => { - return Err(re_query_cache2::QueryError::Other(err.into())) - } + PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => { - return Err(re_query_cache2::QueryError::Other(err.into())) - } + PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index 9842a64a8e7f..b22578d5da31 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache2::CachedLatestAtMonoResult, EntityPath}; +use re_entity_db::{external::re_query_cache::CachedLatestAtMonoResult, EntityPath}; use re_log_types::RowId; use re_types::{archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor}; use re_viewer_context::{ diff --git a/crates/re_space_view_text_log/Cargo.toml b/crates/re_space_view_text_log/Cargo.toml index f73a87deb47f..d1343494859e 100644 --- a/crates/re_space_view_text_log/Cargo.toml +++ b/crates/re_space_view_text_log/Cargo.toml @@ -25,7 +25,6 @@ re_entity_db.workspace = true re_log_types.workspace = true re_log.workspace = true re_query_cache.workspace = true -re_query_cache2.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types.workspace = true diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index c9cb50dffd7c..a06212b65488 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -1,7 +1,7 @@ use re_data_store::TimeRange; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache2::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; +use re_query_cache::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; use re_types::{ archetypes::TextLog, components::{Color, Text, TextLogLevel}, @@ -57,7 +57,7 @@ impl VisualizerSystem for TextLogSystem { for data_result in view_query.iter_visible_data_results(ctx, Self::identifier()) { re_tracing::profile_scope!("primary", &data_result.entity_path.to_string()); - let results = ctx.recording().query_caches2().range( + let results = ctx.recording().query_caches().range( ctx.recording_store(), &query, &data_result.entity_path, @@ -129,16 +129,16 @@ impl VisualizerSystem for TextLogSystem { #[inline] fn check_range<'a, C: Component>( results: &'a CachedRangeData<'a, C>, -) -> re_query_cache2::Result<()> { +) -> re_query_cache::Result<()> { let (front_status, back_status) = results.status(); match front_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query_cache2::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query_cache2::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml index 6a7f0691aba4..16faadc51266 100644 --- a/crates/re_space_view_time_series/Cargo.toml +++ b/crates/re_space_view_time_series/Cargo.toml @@ -25,7 +25,6 @@ re_log.workspace = true re_log_types.workspace = true re_query.workspace = true re_query_cache.workspace = true -re_query_cache2.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 83008a3f169e..814f7369d249 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -1,5 +1,5 @@ use itertools::Itertools as _; -use re_query_cache2::{PromiseResult, QueryError}; +use re_query_cache::{PromiseResult, QueryError}; use re_types::archetypes; use re_types::{ archetypes::SeriesLine, @@ -195,7 +195,7 @@ fn load_series( let entity_path = &data_result.entity_path; let query = re_data_store::RangeQuery::new(query.timeline, time_range); - let results = ctx.recording().query_caches2().range( + let results = ctx.recording().query_caches().range( ctx.recording_store(), &query, entity_path, @@ -259,7 +259,7 @@ fn load_series( .map(|index| (index, ())); let all_frames = - re_query_cache2::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) + re_query_cache::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) .enumerate(); for (i, (_index, _scalars, colors)) in all_frames { @@ -296,7 +296,7 @@ fn load_series( .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache2::range_zip_1x1( + let all_frames = re_query_cache::range_zip_1x1( all_scalars_indexed, all_stroke_widths.range_indexed(), ) diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 5aba1e13589c..6b5b0c997ed7 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -1,6 +1,6 @@ use itertools::Itertools as _; -use re_query_cache2::{PromiseResult, QueryError}; +use re_query_cache::{PromiseResult, QueryError}; use re_types::{ archetypes::{self, SeriesPoint}, components::{Color, MarkerShape, MarkerSize, Name, Scalar}, @@ -149,7 +149,7 @@ impl SeriesPointSystem { let entity_path = &data_result.entity_path; let query = re_data_store::RangeQuery::new(query.timeline, time_range); - let results = ctx.recording().query_caches2().range( + let results = ctx.recording().query_caches().range( ctx.recording_store(), &query, entity_path, @@ -217,7 +217,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache2::range_zip_1x1( + let all_frames = re_query_cache::range_zip_1x1( all_scalars_indexed, all_colors.range_indexed(), ) @@ -257,7 +257,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache2::range_zip_1x1( + let all_frames = re_query_cache::range_zip_1x1( all_scalars_indexed, all_marker_sizes.range_indexed(), ) @@ -289,7 +289,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache2::range_zip_1x1( + let all_frames = re_query_cache::range_zip_1x1( all_scalars_indexed, all_marker_shapes.range_indexed(), ) diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs index 740f8ce97090..fac93e1fed22 100644 --- a/crates/re_types_builder/src/codegen/rust/to_archetype.rs +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -1,4 +1,4 @@ -//! Generates code in `re_query_cache2` so that cached results can easily be converted to +//! Generates code in `re_query_cache` so that cached results can easily be converted to //! ready-to-use archetypes. //! //! That code needs to be generated directly in the caching crates as it needs access to the cached @@ -35,7 +35,7 @@ fn generate_mod( files_to_write: &mut BTreeMap, ) { let generated_path = - Utf8PathBuf::from("crates/re_query_cache2/src/latest_at/to_archetype/mod.rs"); + Utf8PathBuf::from("crates/re_query_cache/src/latest_at/to_archetype/mod.rs"); let mut code = String::new(); code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); @@ -62,7 +62,7 @@ fn generate_impls( objects: &Objects, files_to_write: &mut BTreeMap, ) { - let generated_path = Utf8PathBuf::from("crates/re_query_cache2/src/latest_at/to_archetype"); + let generated_path = Utf8PathBuf::from("crates/re_query_cache/src/latest_at/to_archetype"); let quoted_imports = quote! { use std::sync::Arc; diff --git a/crates/re_viewer/Cargo.toml b/crates/re_viewer/Cargo.toml index 51a91c365277..2168bec9fe30 100644 --- a/crates/re_viewer/Cargo.toml +++ b/crates/re_viewer/Cargo.toml @@ -54,7 +54,6 @@ re_log_encoding = { workspace = true, features = [ re_log_types.workspace = true re_memory.workspace = true re_query_cache.workspace = true -re_query_cache2.workspace = true re_renderer = { workspace = true, default-features = false } re_smart_channel.workspace = true re_space_view.workspace = true diff --git a/crates/re_viewer/src/app.rs b/crates/re_viewer/src/app.rs index 58e2c612b769..f86b13586241 100644 --- a/crates/re_viewer/src/app.rs +++ b/crates/re_viewer/src/app.rs @@ -691,7 +691,7 @@ impl App { #[cfg(not(target_arch = "wasm32"))] UICommand::PrintPrimaryCache => { if let Some(ctx) = store_context { - let text = format!("{:?}", ctx.recording.query_caches2()); + let text = format!("{:?}", ctx.recording.query_caches()); self.re_ui .egui_ctx .output_mut(|o| o.copied_text = text.clone()); diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index 36a89ef0e34e..d60b680732b3 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use re_data_store::{DataStoreConfig, DataStoreRowStats, DataStoreStats}; use re_format::{format_bytes, format_uint}; use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse}; -use re_query_cache2::{CachedComponentStats, CachesStats}; +use re_query_cache::{CachedComponentStats, CachesStats}; use re_renderer::WgpuResourcePoolStatistics; use re_viewer_context::store_hub::StoreHubStats; diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index 5c34fdbbecea..6ff2c4b7b794 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -142,7 +142,7 @@ pub fn override_ui( let query = ctx.blueprint_query; ctx.store_context .blueprint - .query_caches2() + .query_caches() .latest_at(store, query, entity_path, [*component_name]) .components .get(component_name) @@ -150,7 +150,7 @@ pub fn override_ui( } StoreKind::Recording => { ctx.recording() - .query_caches2() + .query_caches() .latest_at( ctx.recording_store(), &query, diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 16de5cba4b51..7a328f3578ad 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -25,7 +25,6 @@ re_entity_db = { workspace = true, features = ["serde"] } re_log_types.workspace = true re_log.workspace = true re_query_cache.workspace = true -re_query_cache2.workspace = true re_query.workspace = true re_query2.workspace = true re_renderer.workspace = true diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index f687e5ec6168..85acff5c5f77 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query_cache2::CachedLatestAtComponentResults, EntityDb, EntityPath, + external::re_query_cache::CachedLatestAtComponentResults, EntityDb, EntityPath, }; use re_log_types::DataCell; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 5c3a454babcd..f90c08ee3611 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -7,7 +7,7 @@ use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId, StoreKind}; -use re_query_cache2::CachesStats; +use re_query_cache::CachesStats; use crate::StoreContext; @@ -715,7 +715,7 @@ impl StoreHub { .unwrap_or_default(); let recording_cached_stats = recording - .map(|entity_db| entity_db.query_caches2().stats()) + .map(|entity_db| entity_db.query_caches().stats()) .unwrap_or_default(); let recording_config = recording diff --git a/examples/rust/extend_viewer_ui/src/main.rs b/examples/rust/extend_viewer_ui/src/main.rs index f7cb1533392e..883ca0bdd316 100644 --- a/examples/rust/extend_viewer_ui/src/main.rs +++ b/examples/rust/extend_viewer_ui/src/main.rs @@ -150,7 +150,7 @@ fn component_ui( // just show the last value logged for each component: let query = re_data_store::LatestAtQuery::latest(timeline); - let results = entity_db.query_caches2().latest_at( + let results = entity_db.query_caches().latest_at( entity_db.store(), &query, entity_path, diff --git a/scripts/lint.py b/scripts/lint.py index f2f4cad8073d..51cf334d17db 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -980,7 +980,7 @@ def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: """Make sure ARCHITECTURE.md talks about every single crate we have.""" # These crates will replace existing ones and won't ever be published as-is. - tmp_crates = ["re_query2", "re_query_cache2"] + tmp_crates = ["re_query2"] crates_dir = Path("crates") architecture_md_file = Path("ARCHITECTURE.md") From e58bc19836f3d0e1b757ec49f0090edf374ea90a Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:44:41 +0200 Subject: [PATCH 372/508] New data APIs 14: port everything that used to be uncached (#6035) Migrate every little thing that didn't use to go through the cached APIs. `Image` and `Mesh3D` are temporarily cached even though they shouldn't be, that's taken care of in a follow-up PR. Once again, I probably broke a million edge cases -- I want to get as fast as possible to removing instance keys before doing an in-depth quality pass. --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- Cargo.lock | 7 +- crates/re_entity_db/Cargo.toml | 1 - crates/re_entity_db/src/entity_db.rs | 14 +- crates/re_entity_db/src/lib.rs | 3 +- crates/re_space_view/Cargo.toml | 2 +- crates/re_space_view/src/space_view.rs | 4 +- .../re_space_view/src/space_view_contents.rs | 2 +- crates/re_space_view/src/sub_archetypes.rs | 7 +- crates/re_space_view/src/visual_time_range.rs | 2 +- crates/re_space_view_dataframe/Cargo.toml | 2 + .../src/space_view_class.rs | 11 +- .../src/contexts/transform_context.rs | 2 +- crates/re_space_view_spatial/src/lib.rs | 3 +- .../src/visualizers/assets3d.rs | 175 ++++--- .../src/visualizers/entity_iterator.rs | 106 +--- .../src/visualizers/images.rs | 452 ++++++++++-------- .../src/visualizers/meshes.rs | 271 ++++++----- .../src/visualizer_system.rs | 49 +- crates/re_viewer/src/lib.rs | 4 +- crates/re_viewer_context/Cargo.toml | 1 - crates/re_viewer_context/src/annotations.rs | 50 +- crates/re_viewer_context/src/item.rs | 33 +- .../re_viewer_context/src/selection_state.rs | 2 +- .../re_viewer_context/src/space_view/mod.rs | 2 +- crates/re_viewport/src/container.rs | 4 +- crates/re_viewport/src/viewport_blueprint.rs | 4 +- examples/rust/custom_space_view/Cargo.toml | 1 + .../color_coordinates_visualizer_system.rs | 67 ++- 28 files changed, 668 insertions(+), 613 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ad62e163514..b5a8526152b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,6 +1418,7 @@ version = "0.16.0-alpha.2" dependencies = [ "mimalloc", "re_crash_handler", + "re_query2", "re_sdk_comms", "re_viewer", ] @@ -4308,7 +4309,6 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_query", - "re_query2", "re_query_cache", "re_smart_channel", "re_tracing", @@ -4683,7 +4683,7 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query2", + "re_query_cache", "re_tracing", "re_types", "re_types_core", @@ -4721,8 +4721,10 @@ dependencies = [ "re_entity_db", "re_log_types", "re_query", + "re_query_cache", "re_renderer", "re_tracing", + "re_types_core", "re_ui", "re_viewer_context", ] @@ -5117,7 +5119,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query2", "re_query_cache", "re_renderer", "re_smart_channel", diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index 38e646d205a1..db210bcf7b48 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -34,7 +34,6 @@ re_log.workspace = true re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true re_query.workspace = true -re_query2.workspace = true re_query_cache = { workspace = true, features = ["to_archetype"] } re_smart_channel.workspace = true re_tracing.workspace = true diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 3027be02373a..4d618e81a71a 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -12,7 +12,7 @@ use re_log_types::{ EntityPathHash, LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, TimeRange, TimeRangeF, Timeline, }; -use re_query2::PromiseResult; +use re_query_cache::PromiseResult; use re_types_core::{components::InstanceKey, Archetype, Loggable}; use crate::{ClearCascade, CompactedStoreEvents, Error, TimesPerTimeline}; @@ -117,7 +117,7 @@ pub struct EntityDb { data_store: DataStore, /// The active promise resolver for this DB. - resolver: re_query2::PromiseResolver, + resolver: re_query_cache::PromiseResolver, /// Query caches for the data in [`Self::data_store`]. query_caches: re_query_cache::Caches, @@ -142,7 +142,7 @@ impl EntityDb { times_per_timeline: Default::default(), tree: crate::EntityTree::root(), data_store, - resolver: re_query2::PromiseResolver::default(), + resolver: re_query_cache::PromiseResolver::default(), query_caches, stats: IngestionStatistics::new(store_id), } @@ -197,7 +197,7 @@ impl EntityDb { } #[inline] - pub fn resolver(&self) -> &re_query2::PromiseResolver { + pub fn resolver(&self) -> &re_query_cache::PromiseResolver { &self.resolver } @@ -207,7 +207,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> PromiseResult> + ) -> PromiseResult> where re_query_cache::CachedLatestAtResults: re_query_cache::ToArchetype, { @@ -229,7 +229,9 @@ impl EntityDb { } PromiseResult::Error(err) } - PromiseResult::Ready(arch) => PromiseResult::Ready(Some(arch)), + PromiseResult::Ready(arch) => { + PromiseResult::Ready(Some((results.compound_index, arch))) + } } } diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index 92389cc07aeb..e431475ea747 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -34,7 +34,7 @@ pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents}; use re_log_types::DataTableError; pub use re_log_types::{EntityPath, EntityPathPart, TimeInt, Timeline}; -pub use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +pub use re_query_cache::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; #[cfg(feature = "serde")] pub use blueprint::components::EntityPropertiesComponent; @@ -43,7 +43,6 @@ pub use editable_auto_value::EditableAutoValue; pub mod external { pub use re_data_store; - pub use re_query2; pub use re_query_cache; } diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml index cc5bab4a1c02..441e96bc95ea 100644 --- a/crates/re_space_view/Cargo.toml +++ b/crates/re_space_view/Cargo.toml @@ -27,7 +27,7 @@ re_log_types.workspace = true re_data_store.workspace = true re_entity_db.workspace = true re_query.workspace = true -re_query2.workspace = true +re_query_cache.workspace = true re_tracing.workspace = true re_types_core.workspace = true re_types.workspace = true diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index a590f96203c7..cd9b86fa22d7 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,6 +1,6 @@ use itertools::{FoldWhile, Itertools}; use nohash_hasher::IntMap; -use re_entity_db::external::re_query2::PromiseResult; +use re_entity_db::external::re_query_cache::PromiseResult; use crate::SpaceViewContents; use re_data_store::LatestAtQuery; @@ -127,7 +127,7 @@ impl SpaceViewBlueprint { // TODO(#5607): what should happen if the promise is still pending? None } - PromiseResult::Ready(arch) => arch, + PromiseResult::Ready(arch) => arch.map(|(_, arch)| arch), PromiseResult::Error(err) => { if cfg!(debug_assertions) { re_log::error!("Failed to load SpaceView blueprint: {err}."); diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 4ed247703593..2b4e94cd853e 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -3,7 +3,7 @@ use slotmap::SlotMap; use smallvec::SmallVec; use re_entity_db::{ - external::{re_data_store::LatestAtQuery, re_query2::PromiseResult}, + external::{re_data_store::LatestAtQuery, re_query_cache::PromiseResult}, EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, }; use re_log_types::{ diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 5838139635a4..198f150f1430 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -49,7 +49,12 @@ where CachedLatestAtResults: ToArchetype, { let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); - (blueprint_db.latest_at_archetype(&path, query), path) + ( + blueprint_db + .latest_at_archetype(&path, query) + .map(|res| res.map(|(_, arch)| arch)), + path, + ) } pub fn query_space_view_sub_archetype_or_default( diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index cfa4590fbd06..2c2af59f7363 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -8,7 +8,7 @@ //! to reduce the amount of changes in code that is likely to be refactored soon anyways. use re_log_types::TimeRange; -use re_query2::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +use re_query_cache::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; use re_types::blueprint::{ components::VisibleTimeRange, datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, diff --git a/crates/re_space_view_dataframe/Cargo.toml b/crates/re_space_view_dataframe/Cargo.toml index 37664a49072c..7ba423482c19 100644 --- a/crates/re_space_view_dataframe/Cargo.toml +++ b/crates/re_space_view_dataframe/Cargo.toml @@ -24,8 +24,10 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true re_query.workspace = true +re_query_cache.workspace = true re_renderer.workspace = true re_tracing.workspace = true +re_types_core.workspace = true re_ui.workspace = true re_viewer_context.workspace = true diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index 06b619a9bc55..448ee5e7cb8f 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -6,7 +6,7 @@ use re_data_store::{DataStore, LatestAtQuery}; use re_data_ui::item_ui::instance_path_button; use re_entity_db::{EntityProperties, InstancePath}; use re_log_types::{EntityPath, Timeline}; -use re_query::get_component_with_instances; +use re_types_core::components::InstanceKey; use re_viewer_context::{ SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewState, SpaceViewSystemExecutionError, SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, @@ -243,9 +243,12 @@ fn sorted_instance_paths_for<'a>( .into_iter() .filter(|comp| !comp.is_indicator_component()) .flat_map(|comp| { - get_component_with_instances(store, latest_at_query, entity_path, comp) - .map(|(_, _, comp_inst)| comp_inst.instance_keys()) - .unwrap_or_default() + let num_instances = store + .latest_at(latest_at_query, entity_path, comp, &[comp]) + .map_or(0, |(_, _, cells)| { + cells[0].as_ref().map_or(0, |cell| cell.num_instances()) + }); + (0..num_instances).map(|i| InstanceKey(i as _)) }) .filter(|instance_key| !instance_key.is_splat()) .collect::>() // dedup and sort diff --git a/crates/re_space_view_spatial/src/contexts/transform_context.rs b/crates/re_space_view_spatial/src/contexts/transform_context.rs index 24b6131ebdc4..8a17eb0f7b54 100644 --- a/crates/re_space_view_spatial/src/contexts/transform_context.rs +++ b/crates/re_space_view_spatial/src/contexts/transform_context.rs @@ -310,7 +310,7 @@ fn get_cached_pinhole( .latest_at_archetype::(entity_path, query) .ok() .flatten() - .map(|arch| { + .map(|(_, arch)| { ( arch.image_from_camera, arch.camera_xyz.unwrap_or(ViewCoordinates::RDF), diff --git a/crates/re_space_view_spatial/src/lib.rs b/crates/re_space_view_spatial/src/lib.rs index 9a5fe950ddc1..0af26b974776 100644 --- a/crates/re_space_view_spatial/src/lib.rs +++ b/crates/re_space_view_spatial/src/lib.rs @@ -53,8 +53,7 @@ fn resolution_from_tensor( /// Utility for querying a pinhole archetype instance. /// -/// TODO(andreas): It should be possible to convert [`re_query::ArchetypeView`] to its corresponding Archetype for situations like this. -/// TODO(andreas): This is duplicated into `re_viewport` +// TODO(andreas): This is duplicated into `re_viewport` fn query_pinhole( entity_db: &re_entity_db::EntityDb, query: &re_data_store::LatestAtQuery, diff --git a/crates/re_space_view_spatial/src/visualizers/assets3d.rs b/crates/re_space_view_spatial/src/visualizers/assets3d.rs index 45d201d481a1..fd14f33490a1 100644 --- a/crates/re_space_view_spatial/src/visualizers/assets3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/assets3d.rs @@ -1,5 +1,6 @@ use re_entity_db::EntityPath; -use re_query::{ArchetypeView, QueryError}; +use re_log_types::{RowId, TimeInt}; +use re_query_cache::range_zip_1x2; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Asset3D, @@ -11,10 +12,7 @@ use re_viewer_context::{ VisualizerSystem, }; -use super::{ - entity_iterator::process_archetype_views, filter_visualizable_3d_entities, - SpatialViewVisualizerData, -}; +use super::{filter_visualizable_3d_entities, SpatialViewVisualizerData}; use crate::{ contexts::{EntityDepthOffsets, SpatialSceneEntityContext}, instance_hash_conversions::picking_layer_id_from_instance_path_hash, @@ -32,70 +30,80 @@ impl Default for Asset3DVisualizer { } } +struct Asset3DComponentData<'a> { + index: (TimeInt, RowId), + + blob: &'a Blob, + media_type: Option<&'a MediaType>, + transform: Option<&'a OutOfTreeTransform3D>, +} + +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Asset3DVisualizer { - fn process_arch_view( + fn process_data<'a>( &mut self, ctx: &ViewerContext<'_>, instances: &mut Vec, - arch_view: &ArchetypeView, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - ) -> Result<(), QueryError> { - let entity_from_pose = arch_view.raw_optional_mono_component::()?; - - let media_type = arch_view.raw_optional_mono_component::()?; - - let mesh = Asset3D { - blob: arch_view.required_mono_component::()?, - media_type: media_type.clone(), - // NOTE: Don't even try to cache the transform! - transform: None, - }; - - let primary_row_id = arch_view.primary_row_id(); - let picking_instance_hash = re_entity_db::InstancePathHash::entity_splat(ent_path); - let outline_mask_ids = ent_context.highlight.index_outline_mask(InstanceKey::SPLAT); - - // TODO(#3232): this is subtly wrong, the key should actually be a hash of everything that got - // cached, which includes the media type… - let mesh = ctx.cache.entry(|c: &mut MeshCache| { - c.entry( - &ent_path.to_string(), - MeshCacheKey { - versioned_instance_path_hash: picking_instance_hash.versioned(primary_row_id), - media_type, - }, - AnyMesh::Asset(&mesh), - ctx.render_ctx, - ) - }); - - if let Some(mesh) = mesh { - re_tracing::profile_scope!("mesh instances"); - - let world_from_pose = ent_context.world_from_entity - * entity_from_pose.map_or(glam::Affine3A::IDENTITY, |t| t.0.into()); - - instances.extend(mesh.mesh_instances.iter().map(move |mesh_instance| { - let pose_from_mesh = mesh_instance.world_from_mesh; - let world_from_mesh = world_from_pose * pose_from_mesh; - - MeshInstance { - gpu_mesh: mesh_instance.gpu_mesh.clone(), - world_from_mesh, - outline_mask_ids, - picking_layer_id: picking_layer_id_from_instance_path_hash( - picking_instance_hash, - ), - ..Default::default() - } - })); - - self.0 - .add_bounding_box(ent_path.hash(), mesh.bbox(), world_from_pose); - }; - - Ok(()) + data: impl Iterator>, + ) { + for data in data { + let mesh = Asset3D { + blob: data.blob.clone(), + media_type: data.media_type.cloned(), + + // NOTE: Don't even try to cache the transform! + transform: None, + }; + + let primary_row_id = data.index.1; + let picking_instance_hash = re_entity_db::InstancePathHash::entity_splat(entity_path); + let outline_mask_ids = ent_context.highlight.index_outline_mask(InstanceKey::SPLAT); + + // TODO(#3232): this is subtly wrong, the key should actually be a hash of everything that got + // cached, which includes the media type… + let mesh = ctx.cache.entry(|c: &mut MeshCache| { + c.entry( + &entity_path.to_string(), + MeshCacheKey { + versioned_instance_path_hash: picking_instance_hash + .versioned(primary_row_id), + media_type: data.media_type.cloned(), + }, + AnyMesh::Asset(&mesh), + ctx.render_ctx, + ) + }); + + if let Some(mesh) = mesh { + re_tracing::profile_scope!("mesh instances"); + + let world_from_pose = ent_context.world_from_entity + * data + .transform + .map_or(glam::Affine3A::IDENTITY, |t| t.0.into()); + + instances.extend(mesh.mesh_instances.iter().map(move |mesh_instance| { + let pose_from_mesh = mesh_instance.world_from_mesh; + let world_from_mesh = world_from_pose * pose_from_mesh; + + MeshInstance { + gpu_mesh: mesh_instance.gpu_mesh.clone(), + world_from_mesh, + outline_mask_ids, + picking_layer_id: picking_layer_id_from_instance_path_hash( + picking_instance_hash, + ), + ..Default::default() + } + })); + + self.0 + .add_bounding_box(entity_path.hash(), mesh.bbox(), world_from_pose); + }; + } } } @@ -122,18 +130,47 @@ impl VisualizerSystem for Asset3DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { let mut instances = Vec::new(); - process_archetype_views::( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |ctx, ent_path, _ent_props, arch_view, ent_context| { - self.process_arch_view(ctx, &mut instances, &arch_view, ent_path, ent_context) + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let blobs = match results.get_dense::(resolver) { + Some(blobs) => blobs?, + _ => return Ok(()), + }; + + let media_types = results.get_or_empty_dense(resolver)?; + let transforms = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x2( + blobs.range_indexed(), + media_types.range_indexed(), + transforms.range_indexed(), + ) + .filter_map(|(&index, blobs, media_types, transforms)| { + blobs.first().map(|blob| Asset3DComponentData { + index, + blob, + media_type: media_types.and_then(|media_types| media_types.first()), + transform: transforms.and_then(|transforms| transforms.first()), + }) + }); + + self.process_data(ctx, &mut instances, entity_path, spatial_ctx, data); + Ok(()) }, )?; diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index f63691dc3753..7b341e5064a6 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,7 +2,6 @@ use itertools::Either; use re_data_store::{LatestAtQuery, RangeQuery}; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, TimeInt, Timeline}; -use re_query::{ArchetypeView, QueryError}; use re_query_cache::{CachedResults, ExtraQueryHistory}; use re_renderer::DepthOffset; use re_space_view::query_visual_history; @@ -39,6 +38,8 @@ pub fn clamped(values: &[T], clamped_len: usize) -> impl Iterator ) } +// --- Cached APIs --- + pub fn query_archetype_with_history( entity_db: &EntityDb, timeline: &Timeline, @@ -161,106 +162,3 @@ where Ok(()) } - -// --- - -/// Iterates through all entity views for a given archetype. -/// -/// The callback passed in gets passed a long an [`SpatialSceneEntityContext`] which contains -/// various useful information about an entity in the context of the current scene. -pub fn process_archetype_views<'a, System: IdentifiedViewSystem, A, const N: usize, F>( - ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, - view_ctx: &ViewContextCollection, - default_depth_offset: DepthOffset, - mut fun: F, -) -> Result<(), SpaceViewSystemExecutionError> -where - A: Archetype + 'a, - F: FnMut( - &ViewerContext<'_>, - &EntityPath, - &EntityProperties, - ArchetypeView, - &SpatialSceneEntityContext<'_>, - ) -> Result<(), QueryError>, -{ - let transforms = view_ctx.get::()?; - let depth_offsets = view_ctx.get::()?; - let annotations = view_ctx.get::()?; - let counter = view_ctx.get::()?; - - for data_result in query.iter_visible_data_results(ctx, System::identifier()) { - // The transform that considers pinholes only makes sense if this is a 3D space-view - let world_from_entity = - if view_ctx.space_view_class_identifier() == SpatialSpaceView3D::identifier() { - transforms.reference_from_entity(&data_result.entity_path) - } else { - transforms.reference_from_entity_ignoring_pinhole( - &data_result.entity_path, - ctx.recording(), - &query.latest_at_query(), - ) - }; - - let Some(world_from_entity) = world_from_entity else { - continue; - }; - let entity_context = SpatialSceneEntityContext { - world_from_entity, - depth_offset: *depth_offsets - .per_entity - .get(&data_result.entity_path.hash()) - .unwrap_or(&default_depth_offset), - annotations: annotations.0.find(&data_result.entity_path), - highlight: query - .highlights - .entity_outline_mask(data_result.entity_path.hash()), - space_view_class_identifier: view_ctx.space_view_class_identifier(), - }; - - let extra_history = query_visual_history(ctx, data_result); - // TODO(cmc): We need to use the type defined in the old crate interchangeably with the one - // defined in the new crate. They are exactly the same. - // - // This will be fixed in the next PR - #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] - let extra_history = unsafe { std::mem::transmute(extra_history) }; - - let result = re_query::query_archetype_with_history::( - ctx.recording_store(), - &query.timeline, - &query.latest_at, - &extra_history, - &data_result.entity_path, - ) - .and_then(|arch_views| { - for arch_view in arch_views { - counter.num_primitives.fetch_add( - arch_view.num_instances(), - std::sync::atomic::Ordering::Relaxed, - ); - - fun( - ctx, - &data_result.entity_path, - data_result.accumulated_properties(), - arch_view, - &entity_context, - )?; - } - Ok(()) - }); - match result { - Ok(_) | Err(QueryError::PrimaryNotFound(_)) => {} - Err(err) => { - re_log::error_once!( - "Unexpected error querying {:?}: {err}", - &data_result.entity_path - ); - } - } - } - - Ok(()) -} diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index 7fc8f9671c0c..82ef54742c40 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -5,8 +5,8 @@ use itertools::Itertools as _; use nohash_hasher::IntSet; use re_entity_db::{EntityPath, EntityProperties}; -use re_log_types::{EntityPathHash, RowId}; -use re_query::{ArchetypeView, QueryError}; +use re_log_types::{EntityPathHash, RowId, TimeInt}; +use re_query_cache::range_zip_1x2; use re_renderer::{ renderer::{DepthCloud, DepthClouds, RectangleOptions, TexturedRect}, Colormap, @@ -16,7 +16,7 @@ use re_types::{ archetypes::{DepthImage, Image, SegmentationImage}, components::{Color, DrawOrder, TensorData, ViewCoordinates}, tensor_data::{DecodedTensor, TensorDataMeaning}, - Archetype as _, ComponentNameSet, + Archetype, ComponentNameSet, }; use re_viewer_context::{ gpu_bridge, ApplicableEntities, DefaultColor, IdentifiedViewSystem, SpaceViewClass, @@ -33,7 +33,7 @@ use crate::{ SpatialSpaceView2D, SpatialSpaceView3D, }; -use super::{entity_iterator::process_archetype_views, SpatialViewVisualizerData}; +use super::SpatialViewVisualizerData; pub struct ViewerImage { /// Path to the image (note image instance ids would refer to pixels!) @@ -64,8 +64,6 @@ fn to_textured_rect( meaning: TensorDataMeaning, multiplicative_tint: egui::Rgba, ) -> Option { - re_tracing::profile_function!(); - let [height, width, _] = tensor.image_height_width_channels()?; let debug_name = ent_path.to_string(); @@ -149,10 +147,18 @@ impl Default for ImageVisualizer { } } +struct ImageComponentData<'a> { + index: (TimeInt, RowId), + + tensor: &'a TensorData, + color: Option<&'a Color>, + draw_order: Option<&'a DrawOrder>, +} + +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl ImageVisualizer { fn handle_image_layering(&mut self) { - re_tracing::profile_function!(); - // Rebuild the image list, grouped by "shared plane", identified with camera & draw order. let mut image_groups: BTreeMap> = BTreeMap::new(); for image in self.images.drain(..) { @@ -201,60 +207,50 @@ impl ImageVisualizer { } #[allow(clippy::too_many_arguments)] - fn process_image_arch_view( + fn process_image_data<'a>( &mut self, ctx: &ViewerContext<'_>, transforms: &TransformContext, ent_props: &EntityProperties, - arch_view: &ArchetypeView, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - ) -> Result<(), QueryError> { - re_tracing::profile_function!(); + data: impl Iterator>, + ) { + // If this isn't an image, return + // TODO(jleibs): The ArchetypeView should probably do this for us. + if !ctx.recording_store().entity_has_component( + &ctx.current_query().timeline(), + entity_path, + &Image::indicator().name(), + ) { + return; + } // Parent pinhole should only be relevant to 3D views let parent_pinhole_path = if ent_context.space_view_class_identifier == SpatialSpaceView3D::identifier() { - transforms.parent_pinhole(ent_path) + transforms.parent_pinhole(entity_path) } else { None }; - // If this isn't an image, return - // TODO(jleibs): The ArchetypeView should probably do this for us. - if !ctx.recording_store().entity_has_component( - &ctx.current_query().timeline(), - ent_path, - &Image::indicator().name(), - ) { - return Ok(()); - } // Unknown is currently interpreted as "Some Color" in most cases. // TODO(jleibs): Make this more explicit let meaning = TensorDataMeaning::Unknown; - // Instance ids of tensors refer to entries inside the tensor. - for (tensor, color, draw_order) in itertools::izip!( - arch_view.iter_required_component::()?, - arch_view.iter_optional_component::()?, - arch_view.iter_optional_component::()? - ) { - re_tracing::profile_scope!("loop_iter"); - - if !tensor.is_shaped_like_an_image() { - return Ok(()); + for data in data { + if !data.tensor.is_shaped_like_an_image() { + continue; } - let tensor_data_row_id = arch_view.primary_row_id(); - - let tensor = match ctx - .cache - .entry(|c: &mut TensorDecodeCache| c.entry(tensor_data_row_id, tensor.0)) - { + let tensor_data_row_id = data.index.1; + let tensor = match ctx.cache.entry(|c: &mut TensorDecodeCache| { + c.entry(tensor_data_row_id, data.tensor.0.clone()) + }) { Ok(tensor) => tensor, Err(err) => { re_log::warn_once!( - "Encountered problem decoding tensor at path {ent_path}: {err}" + "Encountered problem decoding tensor at path {entity_path}: {err}" ); continue; } @@ -264,11 +260,11 @@ impl ImageVisualizer { .annotations .resolved_class_description(None) .annotation_info() - .color(color.map(|c| c.to_array()), DefaultColor::OpaqueWhite); + .color(data.color.map(|c| c.to_array()), DefaultColor::OpaqueWhite); if let Some(textured_rect) = to_textured_rect( ctx, - ent_path, + entity_path, ent_context, tensor_data_row_id, &tensor, @@ -284,129 +280,81 @@ impl ImageVisualizer { || !ent_props.pinhole_image_plane_distance.is_auto() { self.data.add_bounding_box( - ent_path.hash(), + entity_path.hash(), Self::compute_bounding_box(&textured_rect), ent_context.world_from_entity, ); } self.images.push(ViewerImage { - ent_path: ent_path.clone(), + ent_path: entity_path.clone(), tensor, meaning, textured_rect, parent_pinhole: parent_pinhole_path.map(|p| p.hash()), - draw_order: draw_order.unwrap_or(DrawOrder::DEFAULT_IMAGE), + draw_order: data.draw_order.copied().unwrap_or(DrawOrder::DEFAULT_IMAGE), }); } } - - Ok(()) } #[allow(clippy::too_many_arguments)] - fn process_depth_image_arch_view( + fn process_segmentation_image_data<'a>( &mut self, ctx: &ViewerContext<'_>, - depth_clouds: &mut Vec, transforms: &TransformContext, ent_props: &EntityProperties, - arch_view: &ArchetypeView, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - ) -> Result<(), QueryError> { - re_tracing::profile_function!(); - + data: impl Iterator>, + ) { // If this isn't an image, return // TODO(jleibs): The ArchetypeView should probably to this for us. if !ctx.recording_store().entity_has_component( &ctx.current_query().timeline(), - ent_path, - &DepthImage::indicator().name(), + entity_path, + &SegmentationImage::indicator().name(), ) { - return Ok(()); + return; } - let meaning = TensorDataMeaning::Depth; // Parent pinhole should only be relevant to 3D views let parent_pinhole_path = if ent_context.space_view_class_identifier == SpatialSpaceView3D::identifier() { - transforms.parent_pinhole(ent_path) + transforms.parent_pinhole(entity_path) } else { None }; - // Instance ids of tensors refer to entries inside the tensor. - for (tensor, color, draw_order) in itertools::izip!( - arch_view.iter_required_component::()?, - arch_view.iter_optional_component::()?, - arch_view.iter_optional_component::()? - ) { - // NOTE: we ignore the `DepthMeter` component here because we get it from - // `EntityProperties::depth_from_world_scale` instead, which is initialized to the - // same value, but the user may have edited it. - re_tracing::profile_scope!("loop_iter"); + let meaning = TensorDataMeaning::ClassId; - if !tensor.is_shaped_like_an_image() { - return Ok(()); + for data in data { + if !data.tensor.is_shaped_like_an_image() { + continue; } - let tensor_data_row_id = arch_view.primary_row_id(); - - let tensor = match ctx - .cache - .entry(|c: &mut TensorDecodeCache| c.entry(tensor_data_row_id, tensor.0)) - { + let tensor_data_row_id = data.index.1; + let tensor = match ctx.cache.entry(|c: &mut TensorDecodeCache| { + c.entry(tensor_data_row_id, data.tensor.0.clone()) + }) { Ok(tensor) => tensor, Err(err) => { re_log::warn_once!( - "Encountered problem decoding tensor at path {ent_path}: {err}" + "Encountered problem decoding tensor at path {entity_path}: {err}" ); continue; } }; - if *ent_props.backproject_depth { - if let Some(parent_pinhole_path) = transforms.parent_pinhole(ent_path) { - // NOTE: we don't pass in `world_from_obj` because this corresponds to the - // transform of the projection plane, which is of no use to us here. - // What we want are the extrinsics of the depth camera! - match Self::process_entity_view_as_depth_cloud( - ctx, - transforms, - ent_context, - ent_props, - tensor_data_row_id, - &tensor, - ent_path, - parent_pinhole_path, - ) { - Ok(cloud) => { - self.data.add_bounding_box( - ent_path.hash(), - cloud.world_space_bbox(), - glam::Affine3A::IDENTITY, - ); - self.depth_cloud_entities.insert(ent_path.hash()); - depth_clouds.push(cloud); - return Ok(()); - } - Err(err) => { - re_log::warn_once!("{err}"); - } - } - }; - } - let color = ent_context .annotations .resolved_class_description(None) .annotation_info() - .color(color.map(|c| c.to_array()), DefaultColor::OpaqueWhite); + .color(data.color.map(|c| c.to_array()), DefaultColor::OpaqueWhite); if let Some(textured_rect) = to_textured_rect( ctx, - ent_path, + entity_path, ent_context, tensor_data_row_id, &tensor, @@ -422,94 +370,118 @@ impl ImageVisualizer { || !ent_props.pinhole_image_plane_distance.is_auto() { self.data.add_bounding_box( - ent_path.hash(), + entity_path.hash(), Self::compute_bounding_box(&textured_rect), ent_context.world_from_entity, ); } self.images.push(ViewerImage { - ent_path: ent_path.clone(), + ent_path: entity_path.clone(), tensor, meaning, textured_rect, parent_pinhole: parent_pinhole_path.map(|p| p.hash()), - draw_order: draw_order.unwrap_or(DrawOrder::DEFAULT_IMAGE), + draw_order: data.draw_order.copied().unwrap_or(DrawOrder::DEFAULT_IMAGE), }); } } - - Ok(()) } #[allow(clippy::too_many_arguments)] - fn process_segmentation_image_arch_view( + fn process_depth_image_data<'a>( &mut self, ctx: &ViewerContext<'_>, + depth_clouds: &mut Vec, transforms: &TransformContext, ent_props: &EntityProperties, - arch_view: &ArchetypeView, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - ) -> Result<(), QueryError> { - re_tracing::profile_function!(); + data: impl Iterator>, + ) { + // If this isn't an image, return + // TODO(jleibs): The ArchetypeView should probably to this for us. + if !ctx.recording_store().entity_has_component( + &ctx.current_query().timeline(), + entity_path, + &DepthImage::indicator().name(), + ) { + return; + } // Parent pinhole should only be relevant to 3D views let parent_pinhole_path = if ent_context.space_view_class_identifier == SpatialSpaceView3D::identifier() { - transforms.parent_pinhole(ent_path) + transforms.parent_pinhole(entity_path) } else { None }; - // If this isn't an image, return - // TODO(jleibs): The ArchetypeView should probably to this for us. - if !ctx.recording_store().entity_has_component( - &ctx.current_query().timeline(), - ent_path, - &SegmentationImage::indicator().name(), - ) { - return Ok(()); - } - - let meaning = TensorDataMeaning::ClassId; + let meaning = TensorDataMeaning::Depth; - // Instance ids of tensors refer to entries inside the tensor. - for (tensor, color, draw_order) in itertools::izip!( - arch_view.iter_required_component::()?, - arch_view.iter_optional_component::()?, - arch_view.iter_optional_component::()? - ) { - re_tracing::profile_scope!("loop_iter"); + for data in data { + // NOTE: we ignore the `DepthMeter` component here because we get it from + // `EntityProperties::depth_from_world_scale` instead, which is initialized to the + // same value, but the user may have edited it. - if !tensor.is_shaped_like_an_image() { - return Ok(()); + if !data.tensor.is_shaped_like_an_image() { + continue; } - let tensor_data_row_id = arch_view.primary_row_id(); - - let tensor = match ctx - .cache - .entry(|c: &mut TensorDecodeCache| c.entry(tensor_data_row_id, tensor.0)) - { + let tensor_data_row_id = data.index.1; + let tensor = match ctx.cache.entry(|c: &mut TensorDecodeCache| { + c.entry(tensor_data_row_id, data.tensor.0.clone()) + }) { Ok(tensor) => tensor, Err(err) => { re_log::warn_once!( - "Encountered problem decoding tensor at path {ent_path}: {err}" + "Encountered problem decoding tensor at path {entity_path}: {err}" ); continue; } }; + if *ent_props.backproject_depth { + if let Some(parent_pinhole_path) = transforms.parent_pinhole(entity_path) { + // NOTE: we don't pass in `world_from_obj` because this corresponds to the + // transform of the projection plane, which is of no use to us here. + // What we want are the extrinsics of the depth camera! + match Self::process_entity_view_as_depth_cloud( + ctx, + transforms, + ent_context, + ent_props, + tensor_data_row_id, + &tensor, + entity_path, + parent_pinhole_path, + ) { + Ok(cloud) => { + self.data.add_bounding_box( + entity_path.hash(), + cloud.world_space_bbox(), + glam::Affine3A::IDENTITY, + ); + self.depth_cloud_entities.insert(entity_path.hash()); + depth_clouds.push(cloud); + return; + } + Err(err) => { + re_log::warn_once!("{err}"); + } + } + }; + } + let color = ent_context .annotations .resolved_class_description(None) .annotation_info() - .color(color.map(|c| c.to_array()), DefaultColor::OpaqueWhite); + .color(data.color.map(|c| c.to_array()), DefaultColor::OpaqueWhite); if let Some(textured_rect) = to_textured_rect( ctx, - ent_path, + entity_path, ent_context, tensor_data_row_id, &tensor, @@ -525,24 +497,22 @@ impl ImageVisualizer { || !ent_props.pinhole_image_plane_distance.is_auto() { self.data.add_bounding_box( - ent_path.hash(), + entity_path.hash(), Self::compute_bounding_box(&textured_rect), ent_context.world_from_entity, ); } self.images.push(ViewerImage { - ent_path: ent_path.clone(), + ent_path: entity_path.clone(), tensor, meaning, textured_rect, parent_pinhole: parent_pinhole_path.map(|p| p.hash()), - draw_order: draw_order.unwrap_or(DrawOrder::DEFAULT_IMAGE), + draw_order: data.draw_order.copied().unwrap_or(DrawOrder::DEFAULT_IMAGE), }); } } - - Ok(()) } #[allow(clippy::too_many_arguments)] @@ -729,67 +699,81 @@ impl VisualizerSystem for ImageVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { let mut depth_clouds = Vec::new(); - let transforms = view_ctx.get::()?; - - process_archetype_views::( + self.process_image_archetype::( ctx, - query, + view_query, view_ctx, - view_ctx.get::()?.image, - |ctx, ent_path, ent_props, ent_view, ent_context| { - self.process_image_arch_view( + &mut depth_clouds, + |visualizer, + ctx, + _depth_clouds, + transforms, + entity_props, + entity_path, + spatial_ctx, + data| { + visualizer.process_image_data( ctx, transforms, - ent_props, - &ent_view, - ent_path, - ent_context, - ) + entity_props, + entity_path, + spatial_ctx, + data, + ); }, )?; - process_archetype_views::< - ImageVisualizer, - SegmentationImage, - { SegmentationImage::NUM_COMPONENTS }, - _, - >( + self.process_image_archetype::( ctx, - query, + view_query, view_ctx, - view_ctx.get::()?.image, - |ctx, ent_path, ent_props, ent_view, ent_context| { - self.process_segmentation_image_arch_view( + &mut depth_clouds, + |visualizer, + ctx, + _depth_clouds, + transforms, + entity_props, + entity_path, + spatial_ctx, + data| { + visualizer.process_segmentation_image_data( ctx, transforms, - ent_props, - &ent_view, - ent_path, - ent_context, - ) + entity_props, + entity_path, + spatial_ctx, + data, + ); }, )?; - process_archetype_views::( + self.process_image_archetype::( ctx, - query, + view_query, view_ctx, - view_ctx.get::()?.image, - |ctx, ent_path, ent_props, ent_view, ent_context| { - self.process_depth_image_arch_view( + &mut depth_clouds, + |visualizer, + ctx, + depth_clouds, + transforms, + entity_props, + entity_path, + spatial_ctx, + data| { + visualizer.process_depth_image_data( ctx, - &mut depth_clouds, + depth_clouds, transforms, - ent_props, - &ent_view, - ent_path, - ent_context, - ) + entity_props, + entity_path, + spatial_ctx, + data, + ); }, )?; @@ -839,3 +823,79 @@ impl VisualizerSystem for ImageVisualizer { self } } + +impl ImageVisualizer { + fn process_image_archetype( + &mut self, + ctx: &ViewerContext<'_>, + view_query: &ViewQuery<'_>, + view_ctx: &ViewContextCollection, + depth_clouds: &mut Vec, + mut f: F, + ) -> Result<(), SpaceViewSystemExecutionError> + where + F: FnMut( + &mut ImageVisualizer, + &ViewerContext<'_>, + &mut Vec, + &TransformContext, + &EntityProperties, + &EntityPath, + &SpatialSceneEntityContext<'_>, + &mut dyn Iterator>, + ), + { + let transforms = view_ctx.get::()?; + + super::entity_iterator::process_archetype::( + ctx, + view_query, + view_ctx, + view_ctx.get::()?.image, + |ctx, entity_path, entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let tensors = match results.get_dense::(resolver) { + Some(tensors) => tensors?, + _ => return Ok(()), + }; + + let colors = results.get_or_empty_dense(resolver)?; + let draw_orders = results.get_or_empty_dense(resolver)?; + + let mut data = range_zip_1x2( + tensors.range_indexed(), + draw_orders.range_indexed(), + colors.range_indexed(), + ) + .filter_map(|(&index, tensors, draw_orders, colors)| { + tensors.first().map(|tensor| ImageComponentData { + index, + tensor, + color: colors.and_then(|colors| colors.first()), + draw_order: draw_orders.and_then(|draw_orders| draw_orders.first()), + }) + }); + + f( + self, + ctx, + depth_clouds, + transforms, + entity_props, + entity_path, + spatial_ctx, + &mut data, + ); + + Ok(()) + }, + )?; + + Ok(()) + } +} diff --git a/crates/re_space_view_spatial/src/visualizers/meshes.rs b/crates/re_space_view_spatial/src/visualizers/meshes.rs index 97f8a15344d7..89d28eadd512 100644 --- a/crates/re_space_view_spatial/src/visualizers/meshes.rs +++ b/crates/re_space_view_spatial/src/visualizers/meshes.rs @@ -1,10 +1,13 @@ +use itertools::Itertools as _; use re_entity_db::EntityPath; -use re_query::{ArchetypeView, QueryError}; +use re_log_types::{RowId, TimeInt}; +use re_query_cache::range_zip_1x7; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Mesh3D, components::{ - Color, InstanceKey, Material, MeshProperties, Position3D, TensorData, Texcoord2D, Vector3D, + ClassId, Color, InstanceKey, Material, MeshProperties, Position3D, TensorData, Texcoord2D, + Vector3D, }, }; use re_viewer_context::{ @@ -13,10 +16,6 @@ use re_viewer_context::{ VisualizerSystem, }; -use super::{ - entity_iterator::process_archetype_views, filter_visualizable_3d_entities, - SpatialViewVisualizerData, -}; use crate::{ contexts::{EntityDepthOffsets, SpatialSceneEntityContext}, instance_hash_conversions::picking_layer_id_from_instance_path_hash, @@ -24,6 +23,10 @@ use crate::{ view_kind::SpatialSpaceViewKind, }; +use super::{entity_iterator::clamped, filter_visualizable_3d_entities, SpatialViewVisualizerData}; + +// --- + pub struct Mesh3DVisualizer(SpatialViewVisualizerData); impl Default for Mesh3DVisualizer { @@ -34,116 +37,98 @@ impl Default for Mesh3DVisualizer { } } +struct Mesh3DComponentData<'a> { + index: (TimeInt, RowId), + + vertex_positions: &'a [Position3D], + vertex_normals: &'a [Vector3D], + vertex_colors: &'a [Color], + vertex_texcoords: &'a [Texcoord2D], + + mesh_properties: Option<&'a MeshProperties>, + mesh_material: Option<&'a Material>, + albedo_texture: Option<&'a TensorData>, + + class_ids: &'a [ClassId], +} + +// NOTE: Do not put profile scopes in these methods. They are called for all entities and all +// timestamps within a time range -- it's _a lot_. impl Mesh3DVisualizer { - fn process_arch_view( + fn process_data<'a>( &mut self, ctx: &ViewerContext<'_>, instances: &mut Vec, - arch_view: &ArchetypeView, - ent_path: &EntityPath, + entity_path: &EntityPath, ent_context: &SpatialSceneEntityContext<'_>, - ) -> Result<(), QueryError> { - re_tracing::profile_function!(); - - let vertex_positions: Vec<_> = { - re_tracing::profile_scope!("vertex_positions"); - arch_view.iter_required_component::()?.collect() - }; - if vertex_positions.is_empty() { - return Ok(()); - } - - let mesh = { - re_tracing::profile_scope!("collect"); - // NOTE: - // - Per-vertex properties are joined using the cluster key as usual. - // - Per-mesh properties are just treated as a "global var", essentially. - Mesh3D { - vertex_positions, - vertex_normals: if arch_view.has_component::() { - re_tracing::profile_scope!("vertex_normals"); - Some( - arch_view - .iter_optional_component::()? - .map(|comp| comp.unwrap_or(Vector3D::ZERO)) - .collect(), - ) - } else { - None - }, - vertex_colors: if arch_view.has_component::() { - re_tracing::profile_scope!("vertex_colors"); - let fallback = Color::new(0xFFFFFFFF); - Some( - arch_view - .iter_optional_component::()? - .map(|comp| comp.unwrap_or(fallback)) - .collect(), - ) - } else { - None - }, - vertex_texcoords: if arch_view.has_component::() { - re_tracing::profile_scope!("vertex_texcoords"); - Some( - arch_view - .iter_optional_component::()? - .map(|comp| comp.unwrap_or(Texcoord2D::ZERO)) - .collect(), - ) - } else { - None - }, - mesh_properties: arch_view.raw_optional_mono_component::()?, - mesh_material: arch_view.raw_optional_mono_component::()?, - albedo_texture: arch_view.raw_optional_mono_component::()?, - class_ids: None, - } - }; - - let primary_row_id = arch_view.primary_row_id(); - let picking_instance_hash = re_entity_db::InstancePathHash::entity_splat(ent_path); - let outline_mask_ids = ent_context.highlight.index_outline_mask(InstanceKey::SPLAT); - - let mesh = ctx.cache.entry(|c: &mut MeshCache| { - let key = MeshCacheKey { - versioned_instance_path_hash: picking_instance_hash.versioned(primary_row_id), - media_type: None, + data: impl Iterator>, + ) { + for data in data { + let primary_row_id = data.index.1; + let picking_instance_hash = re_entity_db::InstancePathHash::entity_splat(entity_path); + let outline_mask_ids = ent_context.highlight.index_outline_mask(InstanceKey::SPLAT); + + let mesh = ctx.cache.entry(|c: &mut MeshCache| { + let key = MeshCacheKey { + versioned_instance_path_hash: picking_instance_hash.versioned(primary_row_id), + media_type: None, + }; + + let vertex_normals = clamped(data.vertex_normals, data.vertex_positions.len()) + .copied() + .collect_vec(); + let vertex_colors = clamped(data.vertex_colors, data.vertex_positions.len()) + .copied() + .collect_vec(); + let vertex_texcoords = clamped(data.vertex_texcoords, data.vertex_positions.len()) + .copied() + .collect_vec(); + + c.entry( + &entity_path.to_string(), + key.clone(), + AnyMesh::Mesh { + mesh: &Mesh3D { + vertex_positions: data.vertex_positions.to_owned(), + mesh_properties: data.mesh_properties.cloned(), + vertex_normals: (!vertex_normals.is_empty()).then_some(vertex_normals), + vertex_colors: (!vertex_colors.is_empty()).then_some(vertex_colors), + vertex_texcoords: (!vertex_texcoords.is_empty()) + .then_some(vertex_texcoords), + mesh_material: data.mesh_material.cloned(), + albedo_texture: data.albedo_texture.cloned(), + class_ids: (!data.class_ids.is_empty()) + .then(|| data.class_ids.to_owned()), + }, + texture_key: re_log_types::hash::Hash64::hash(&key).hash64(), + }, + ctx.render_ctx, + ) + }); + + if let Some(mesh) = mesh { + instances.extend(mesh.mesh_instances.iter().map(move |mesh_instance| { + let entity_from_mesh = mesh_instance.world_from_mesh; + let world_from_mesh = ent_context.world_from_entity * entity_from_mesh; + + MeshInstance { + gpu_mesh: mesh_instance.gpu_mesh.clone(), + world_from_mesh, + outline_mask_ids, + picking_layer_id: picking_layer_id_from_instance_path_hash( + picking_instance_hash, + ), + ..Default::default() + } + })); + + self.0.add_bounding_box( + entity_path.hash(), + mesh.bbox(), + ent_context.world_from_entity, + ); }; - c.entry( - &ent_path.to_string(), - key.clone(), - AnyMesh::Mesh { - mesh: &mesh, - texture_key: re_log_types::hash::Hash64::hash(&key).hash64(), - }, - ctx.render_ctx, - ) - }); - - if let Some(mesh) = mesh { - re_tracing::profile_scope!("mesh instances"); - - instances.extend(mesh.mesh_instances.iter().map(move |mesh_instance| { - let entity_from_mesh = mesh_instance.world_from_mesh; - let world_from_mesh = ent_context.world_from_entity * entity_from_mesh; - - MeshInstance { - gpu_mesh: mesh_instance.gpu_mesh.clone(), - world_from_mesh, - outline_mask_ids, - picking_layer_id: picking_layer_id_from_instance_path_hash( - picking_instance_hash, - ), - ..Default::default() - } - })); - - self.0 - .add_bounding_box(ent_path.hash(), mesh.bbox(), ent_context.world_from_entity); - }; - - Ok(()) + } } } @@ -170,18 +155,74 @@ impl VisualizerSystem for Mesh3DVisualizer { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { let mut instances = Vec::new(); - process_archetype_views::( + super::entity_iterator::process_archetype::( ctx, - query, + view_query, view_ctx, view_ctx.get::()?.points, - |ctx, ent_path, _ent_props, arch_view, ent_context| { - self.process_arch_view(ctx, &mut instances, &arch_view, ent_path, ent_context) + |ctx, entity_path, _entity_props, spatial_ctx, results| { + re_tracing::profile_scope!(format!("{entity_path}")); + + use crate::visualizers::CachedRangeResultsExt as _; + + let resolver = ctx.recording().resolver(); + + let vertex_positions = match results.get_dense::(resolver) { + Some(positions) => positions?, + _ => return Ok(()), + }; + + let vertex_normals = results.get_or_empty_dense(resolver)?; + let vertex_colors = results.get_or_empty_dense(resolver)?; + let vertex_texcoords = results.get_or_empty_dense(resolver)?; + let mesh_properties = results.get_or_empty_dense(resolver)?; + let mesh_materials = results.get_or_empty_dense(resolver)?; + let albedo_textures = results.get_or_empty_dense(resolver)?; + let class_ids = results.get_or_empty_dense(resolver)?; + + let data = range_zip_1x7( + vertex_positions.range_indexed(), + vertex_normals.range_indexed(), + vertex_colors.range_indexed(), + vertex_texcoords.range_indexed(), + mesh_properties.range_indexed(), + mesh_materials.range_indexed(), + albedo_textures.range_indexed(), + class_ids.range_indexed(), + ) + .map( + |( + &index, + vertex_positions, + vertex_normals, + vertex_colors, + vertex_texcoords, + mesh_properties, + mesh_material, + albedo_texture, + class_ids, + )| { + Mesh3DComponentData { + index, + vertex_positions, + vertex_normals: vertex_normals.unwrap_or_default(), + vertex_colors: vertex_colors.unwrap_or_default(), + vertex_texcoords: vertex_texcoords.unwrap_or_default(), + mesh_properties: mesh_properties.and_then(|v| v.first()), + mesh_material: mesh_material.and_then(|v| v.first()), + albedo_texture: albedo_texture.and_then(|v| v.first()), + class_ids: class_ids.unwrap_or_default(), + } + }, + ); + + self.process_data(ctx, &mut instances, entity_path, spatial_ctx, data); + Ok(()) }, )?; diff --git a/crates/re_space_view_text_document/src/visualizer_system.rs b/crates/re_space_view_text_document/src/visualizer_system.rs index ea8b404f0a74..75e06692813c 100644 --- a/crates/re_space_view_text_document/src/visualizer_system.rs +++ b/crates/re_space_view_text_document/src/visualizer_system.rs @@ -1,9 +1,6 @@ use re_data_store::LatestAtQuery; -use re_query::{query_archetype, QueryError}; -use re_types::{ - archetypes::{self, TextDocument}, - components, -}; +use re_space_view::external::re_query_cache::PromiseResult; +use re_types::{archetypes::TextDocument, components}; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewerContext, VisualizerQueryInfo, VisualizerSystem, @@ -37,39 +34,35 @@ impl VisualizerSystem for TextDocumentSystem { fn execute( &mut self, ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + view_query: &ViewQuery<'_>, _view_ctx: &ViewContextCollection, ) -> Result, SpaceViewSystemExecutionError> { - let store = ctx.recording_store(); - - let timeline_query = LatestAtQuery::new(query.timeline, query.latest_at); + let timeline_query = LatestAtQuery::new(view_query.timeline, view_query.latest_at); - for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { - // TODO(#3320): this match can go away once the issue is resolved - match query_archetype::( - store, - &timeline_query, - &data_result.entity_path, - ) { - Ok(arch_view) => { - let bodies = arch_view.iter_required_component::()?; - let media_types = - arch_view.iter_optional_component::()?; - - for (body, media_type) in itertools::izip!(bodies, media_types) { - let media_type = media_type.unwrap_or(components::MediaType::plain_text()); - self.text_entries - .push(TextDocumentEntry { body, media_type }); - } + for data_result in view_query.iter_visible_data_results(ctx, Self::identifier()) { + let TextDocument { text, media_type } = match ctx + .recording() + .latest_at_archetype(&data_result.entity_path, &timeline_query) + { + PromiseResult::Pending | PromiseResult::Ready(None) => { + // TODO(#5607): what should happen if the promise is still pending? + continue; } - Err(QueryError::PrimaryNotFound(_)) => {} - Err(err) => { + PromiseResult::Ready(Some((_, arch))) => arch, + PromiseResult::Error(err) => { re_log::error_once!( "Unexpected error querying {:?}: {err}", &data_result.entity_path ); + continue; } }; + + let media_type = media_type.unwrap_or(components::MediaType::plain_text()); + self.text_entries.push(TextDocumentEntry { + body: text, + media_type, + }); } Ok(Vec::new()) diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 1c9b094191ad..85b2747bf3e1 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -34,8 +34,8 @@ pub mod external { pub use {eframe, egui}; pub use { re_data_store, re_data_store::external::*, re_entity_db, re_log, re_log_types, re_memory, - re_renderer, re_types, re_ui, re_viewer_context, re_viewer_context::external::*, - re_viewport, re_viewport::external::*, + re_query_cache, re_renderer, re_types, re_ui, re_viewer_context, + re_viewer_context::external::*, re_viewport, re_viewport::external::*, }; } diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 7a328f3578ad..835b3c5aec4c 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -26,7 +26,6 @@ re_log_types.workspace = true re_log.workspace = true re_query_cache.workspace = true re_query.workspace = true -re_query2.workspace = true re_renderer.workspace = true re_smart_channel.workspace = true re_string_interner.workspace = true diff --git a/crates/re_viewer_context/src/annotations.rs b/crates/re_viewer_context/src/annotations.rs index 1853690a5e0d..f51010ffb89b 100644 --- a/crates/re_viewer_context/src/annotations.rs +++ b/crates/re_viewer_context/src/annotations.rs @@ -6,7 +6,6 @@ use nohash_hasher::IntSet; use re_data_store::LatestAtQuery; use re_entity_db::EntityPath; use re_log_types::RowId; -use re_query::{query_archetype, ArchetypeView}; use re_types::archetypes::AnnotationContext; use re_types::datatypes::{AnnotationInfo, ClassDescription, ClassId, KeypointId, Utf8}; @@ -38,29 +37,6 @@ impl Annotations { .clone() } - pub fn try_from_view(view: &ArchetypeView) -> Option { - re_tracing::profile_function!(); - - use re_log::ResultExt as _; - - view.optional_mono_component::() - .warn_on_err_once("Failed to load AnnotationContext") - .flatten() - .map(|ctx| Self { - row_id: view.primary_row_id(), - class_map: ctx - .0 - .into_iter() - .map(|elem| { - ( - elem.class_id, - CachedClassDescription::from(elem.class_description), - ) - }) - .collect(), - }) - } - #[inline] pub fn resolved_class_description( &self, @@ -253,8 +229,6 @@ impl AnnotationMap { let mut visited = IntSet::::default(); - let data_store = ctx.recording_store(); - // This logic is borrowed from `iter_ancestor_meta_field`, but using the arrow-store instead // not made generic as `AnnotationContext` was the only user of that function for ent_path in entities { @@ -273,13 +247,27 @@ impl AnnotationMap { // Otherwise check the obj_store for the field. // If we find one, insert it and then we can break. std::collections::btree_map::Entry::Vacant(entry) => { - if query_archetype::(data_store, time_query, &parent) + if let Some(((_, row_id), ann_ctx)) = ctx + .recording() + .latest_at_archetype::(&parent, time_query) .ok() - .and_then(|view| Annotations::try_from_view(&view)) - .map(|annotations| entry.insert(Arc::new(annotations))) - .is_some() + .flatten() { - break; + let annotations = Annotations { + row_id, + class_map: ann_ctx + .context + .0 + .into_iter() + .map(|elem| { + ( + elem.class_id, + CachedClassDescription::from(elem.class_description), + ) + }) + .collect(), + }; + entry.insert(Arc::new(annotations)); } } } diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index e466b0e7e152..0d21d88d3dfd 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -1,4 +1,4 @@ -use re_entity_db::InstancePath; +use re_entity_db::{EntityDb, InstancePath}; use re_log_types::{ComponentPath, DataPath, EntityPath}; use crate::{ContainerId, SpaceViewId}; @@ -151,18 +151,18 @@ impl Item { /// If the given item refers to the first element of an instance with a single element, resolve to a splatted entity path. pub fn resolve_mono_instance_path_item( + entity_db: &EntityDb, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, item: &Item, ) -> Item { // Resolve to entity path if there's only a single instance. match item { Item::InstancePath(instance_path) => { - Item::InstancePath(resolve_mono_instance_path(query, store, instance_path)) + Item::InstancePath(resolve_mono_instance_path(entity_db, query, instance_path)) } Item::DataResult(space_view_id, instance_path) => Item::DataResult( *space_view_id, - resolve_mono_instance_path(query, store, instance_path), + resolve_mono_instance_path(entity_db, query, instance_path), ), Item::AppId(_) | Item::DataSource(_) @@ -175,27 +175,36 @@ pub fn resolve_mono_instance_path_item( /// If the given path refers to the first element of an instance with a single element, resolve to a splatted entity path. pub fn resolve_mono_instance_path( + entity_db: &EntityDb, query: &re_data_store::LatestAtQuery, - store: &re_data_store::DataStore, instance: &re_entity_db::InstancePath, ) -> re_entity_db::InstancePath { re_tracing::profile_function!(); if instance.instance_key.0 == 0 { - let Some(components) = store.all_components(&query.timeline(), &instance.entity_path) + // NOTE: While we normally frown upon direct queries to the datastore, `all_components` is fine. + let Some(components) = entity_db + .store() + .all_components(&query.timeline(), &instance.entity_path) else { // No components at all, return splatted entity. return re_entity_db::InstancePath::entity_splat(instance.entity_path.clone()); }; + for component in components { - if let Some((_, _row_id, instances)) = re_query::get_component_with_instances( - store, + let results = entity_db.query_caches().latest_at( + entity_db.store(), query, &instance.entity_path, - component, - ) { - if instances.len() > 1 { - return instance.clone(); + [component], + ); + if let Some(results) = results.get(component) { + if let re_query_cache::PromiseResult::Ready(cell) = + results.resolved(entity_db.resolver()) + { + if cell.num_instances() > 1 { + return instance.clone(); + } } } } diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index 8a57b8aa0421..54ab55c2c337 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -114,8 +114,8 @@ impl ItemCollection { .map(|(item, space_ctx)| { ( resolve_mono_instance_path_item( + ctx.recording(), &ctx.current_query(), - ctx.recording_store(), &item, ), space_ctx, diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 61c60dfadf77..17632a2aa4ff 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -49,7 +49,7 @@ pub enum SpaceViewSystemExecutionError { QueryError(#[from] re_query::QueryError), #[error(transparent)] - QueryError2(#[from] re_query2::QueryError), + QueryError2(#[from] re_query_cache::QueryError), #[error(transparent)] DeserializationError(#[from] re_types::DeserializationError), diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index 499ab1cb0080..b5e2381ef41f 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -2,7 +2,7 @@ use ahash::HashMap; use egui_tiles::TileId; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query2::PromiseResult, EntityDb}; +use re_entity_db::{external::re_query_cache::PromiseResult, EntityDb}; use re_log::ResultExt; use re_log_types::{DataRow, EntityPath, RowId}; use re_types::blueprint::components::Visible; @@ -59,7 +59,7 @@ impl ContainerBlueprint { // TODO(#5607): what should happen if the promise is still pending? None } - PromiseResult::Ready(arch) => arch, + PromiseResult::Ready(arch) => arch.map(|(_, arch)| arch), PromiseResult::Error(err) => { if cfg!(debug_assertions) { re_log::error!("Failed to load container blueprint: {err}."); diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index 241092034d29..f0cb5f83d587 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -4,10 +4,10 @@ use std::sync::atomic::{AtomicBool, Ordering}; use ahash::HashMap; use egui_tiles::{SimplificationOptions, TileId}; use nohash_hasher::IntSet; -use re_entity_db::external::re_query2::PromiseResult; use smallvec::SmallVec; use re_data_store::LatestAtQuery; +use re_entity_db::external::re_query_cache::PromiseResult; use re_entity_db::EntityPath; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::ViewerRecommendationHash; @@ -80,7 +80,7 @@ impl ViewportBlueprint { // TODO(#5607): what should happen if the promise is still pending? Default::default() } - PromiseResult::Ready(arch) => arch.unwrap_or_default(), + PromiseResult::Ready(arch) => arch.map_or_else(Default::default, |(_, arch)| arch), PromiseResult::Error(err) => { if cfg!(debug_assertions) { re_log::error!("Failed to load viewport blueprint: {err}."); diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index e9d05114dc00..32d7f1bd44a0 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -14,6 +14,7 @@ analytics = ["re_crash_handler/analytics", "re_viewer/analytics"] [dependencies] re_crash_handler = { path = "../../../crates/re_crash_handler" } +re_query2 = { path = "../../../crates/re_query2" } re_viewer = { path = "../../../crates/re_viewer", default-features = false } # We need re_sdk_comms to receive log events from and SDK: diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index 66a37ce5c786..a90e12136fb1 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -1,9 +1,12 @@ use re_viewer::external::{ egui, re_log_types::EntityPath, - re_query::query_archetype, - re_renderer, - re_types::{self, components::InstanceKey, ComponentName, Loggable as _}, + re_query_cache, re_renderer, + re_types::{ + self, + components::{Color, InstanceKey}, + ComponentName, Loggable as _, + }, re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewSystemIdentifier, ViewerContext, VisualizerQueryInfo, VisualizerSystem, @@ -35,6 +38,16 @@ impl re_types::Archetype for ColorArchetype { } } +impl re_query2::ToArchetype for re_query_cache::CachedLatestAtResults { + #[inline] + fn to_archetype( + &self, + _resolver: &re_query2::PromiseResolver, + ) -> re_query2::PromiseResult> { + re_query2::PromiseResult::Ready(Ok(ColorArchetype)) + } +} + impl IdentifiedViewSystem for InstanceColorSystem { fn identifier() -> ViewSystemIdentifier { "InstanceColor".into() @@ -56,30 +69,36 @@ impl VisualizerSystem for InstanceColorSystem { // For each entity in the space view that should be displayed with the `InstanceColorSystem`… for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { // …gather all colors and their instance ids. - if let Ok(arch_view) = query_archetype::( + + let results = re_query2::latest_at( ctx.recording_store(), &ctx.current_query(), &data_result.entity_path, - ) { - if let Ok(colors) = - arch_view.iter_required_component::() - { - self.colors.push(( - data_result.entity_path.clone(), - arch_view - .iter_instance_keys() - .zip(colors) - .map(|(instance_key, color)| { - let [r, g, b, _] = color.to_array(); - ColorWithInstanceKey { - color: egui::Color32::from_rgb(r, g, b), - instance_key, - } - }) - .collect(), - )); - } - } + [Color::name()], + ); + + let Some(colors) = results.get(Color::name()).and_then(|results| { + results + .to_dense::(ctx.recording().resolver()) + .flatten() + .ok() + }) else { + continue; + }; + + self.colors.push(( + data_result.entity_path.clone(), + (0..) + .zip(colors) + .map(|(instance_key, color)| { + let [r, g, b, _] = color.to_array(); + ColorWithInstanceKey { + color: egui::Color32::from_rgb(r, g, b), + instance_key: instance_key.into(), + } + }) + .collect(), + )); } // We're not using `re_renderer` here, so return an empty vector. From 8fe76ad9830151f84dee52e72d694dc70172b5e2 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:46:39 +0200 Subject: [PATCH 373/508] New data APIs 15: one query crate to rule them all (#6036) There is now only one way to query data: `re_query` (well you can still query the datastore directly if you're a monster, but that's for another PR). All queries go through both the query cache and the deserialization cache. There will be a follow-up PR to disable the deserialization cache for specific components. Most of this is just (re)moving stuff around except for the last two commits which take care of porting the cached test suites since they cannot depend on uncached APIs to do comparisons anymore. - Closes #6018 - Closes https://github.com/rerun-io/rerun/issues/3320 --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- ARCHITECTURE.md | 1 - Cargo.lock | 75 +- Cargo.toml | 2 - crates/re_data_ui/src/component.rs | 6 +- .../re_data_ui/src/component_ui_registry.rs | 4 +- crates/re_data_ui/src/editors.rs | 20 +- crates/re_entity_db/Cargo.toml | 5 +- crates/re_entity_db/src/entity_db.rs | 28 +- crates/re_entity_db/src/lib.rs | 4 +- crates/re_query/Cargo.toml | 62 +- crates/re_query/README.md | 2 +- .../benches/flat_vec_deque.rs | 2 +- .../benches/latest_at.rs | 8 +- crates/re_query/benches/query_benchmark.rs | 313 ------- .../examples/latest_at.rs | 15 +- .../examples/latest_at_archetype.rs | 8 +- .../examples/range.rs | 16 +- crates/re_query/src/archetype_view.rs | 669 -------------- .../src/bin/clamped_zip.rs | 2 +- .../src/bin/range_zip.rs | 2 +- .../{re_query_cache => re_query}/src/cache.rs | 0 .../src/cache_stats.rs | 0 .../src/clamped_zip/.gitattributes | 0 .../src/clamped_zip/generated.rs | 2 +- .../src/clamped_zip/mod.rs | 0 .../src/flat_vec_deque.rs | 0 .../src/latest_at/helpers.rs | 20 +- crates/re_query/src/latest_at/mod.rs | 10 + .../src/latest_at/query.rs | 17 +- .../src/latest_at/results.rs | 48 +- .../src/latest_at/to_archetype/.gitattributes | 0 .../to_archetype/annotation_context.rs | 5 +- .../src/latest_at/to_archetype/arrows2d.rs | 5 +- .../src/latest_at/to_archetype/arrows3d.rs | 5 +- .../src/latest_at/to_archetype/asset3d.rs | 5 +- .../src/latest_at/to_archetype/background.rs | 5 +- .../src/latest_at/to_archetype/bar_chart.rs | 5 +- .../src/latest_at/to_archetype/boxes2d.rs | 5 +- .../src/latest_at/to_archetype/boxes3d.rs | 5 +- .../src/latest_at/to_archetype/clear.rs | 5 +- .../to_archetype/container_blueprint.rs | 5 +- .../src/latest_at/to_archetype/depth_image.rs | 5 +- .../to_archetype/disconnected_space.rs | 5 +- .../src/latest_at/to_archetype/image.rs | 5 +- .../latest_at/to_archetype/line_strips2d.rs | 5 +- .../latest_at/to_archetype/line_strips3d.rs | 5 +- .../src/latest_at/to_archetype/mesh3d.rs | 5 +- .../src/latest_at/to_archetype/mod.rs | 0 .../latest_at/to_archetype/panel_blueprint.rs | 5 +- .../src/latest_at/to_archetype/pinhole.rs | 5 +- .../src/latest_at/to_archetype/plot_legend.rs | 5 +- .../src/latest_at/to_archetype/points2d.rs | 5 +- .../src/latest_at/to_archetype/points3d.rs | 5 +- .../src/latest_at/to_archetype/scalar.rs | 5 +- .../src/latest_at/to_archetype/scalar_axis.rs | 5 +- .../to_archetype/segmentation_image.rs | 5 +- .../src/latest_at/to_archetype/series_line.rs | 5 +- .../latest_at/to_archetype/series_point.rs | 5 +- .../to_archetype/space_view_blueprint.rs | 7 +- .../to_archetype/space_view_contents.rs | 7 +- .../src/latest_at/to_archetype/tensor.rs | 5 +- .../latest_at/to_archetype/text_document.rs | 5 +- .../src/latest_at/to_archetype/text_log.rs | 5 +- .../src/latest_at/to_archetype/transform3d.rs | 5 +- .../to_archetype/view_coordinates.rs | 5 +- .../to_archetype/viewport_blueprint.rs | 5 +- crates/re_query/src/lib.rs | 84 +- crates/{re_query2 => re_query}/src/promise.rs | 0 crates/re_query/src/query.rs | 269 ------ crates/re_query/src/range.rs | 170 ---- crates/re_query/src/range/mod.rs | 7 + .../src/range/query.rs | 17 +- .../src/range/results.rs | 88 +- .../src/range_zip/.gitattributes | 0 .../src/range_zip/generated.rs | 2 +- .../src/range_zip/mod.rs | 0 crates/re_query/src/util.rs | 143 --- .../src/visible_history.rs | 0 .../re_query/tests/archetype_query_tests.rs | 336 ------- .../re_query/tests/archetype_range_tests.rs | 675 -------------- .../re_query/tests/archetype_visit_tests.rs | 392 -------- crates/re_query/tests/latest_at.rs | 589 ++++++++++++ crates/re_query/tests/range.rs | 852 ++++++++++++++++++ crates/re_query/tests/store.rs | 73 -- crates/re_query2/Cargo.toml | 87 -- crates/re_query2/README.md | 5 - crates/re_query2/benches/latest_at.rs | 347 ------- crates/re_query2/examples/latest_at.rs | 128 --- crates/re_query2/examples/range.rs | 168 ---- crates/re_query2/src/latest_at/mod.rs | 5 - crates/re_query2/src/latest_at/query.rs | 40 - crates/re_query2/src/latest_at/results.rs | 224 ----- crates/re_query2/src/lib.rs | 81 -- crates/re_query2/src/range/mod.rs | 5 - crates/re_query2/src/range/query.rs | 38 - crates/re_query2/src/range/results.rs | 204 ----- crates/re_query2/tests/latest_at.rs | 217 ----- crates/re_query2/tests/range.rs | 496 ---------- crates/re_query_cache/Cargo.toml | 81 -- crates/re_query_cache/README.md | 10 - crates/re_query_cache/src/latest_at/mod.rs | 10 - crates/re_query_cache/src/lib.rs | 54 -- crates/re_query_cache/src/range/mod.rs | 8 - crates/re_query_cache/tests/latest_at.rs | 526 ----------- crates/re_query_cache/tests/range.rs | 586 ------------ crates/re_space_view/Cargo.toml | 1 - crates/re_space_view/src/space_view.rs | 2 +- .../re_space_view/src/space_view_contents.rs | 2 +- crates/re_space_view/src/sub_archetypes.rs | 6 +- crates/re_space_view/src/visual_time_range.rs | 2 +- crates/re_space_view_dataframe/Cargo.toml | 1 - crates/re_space_view_spatial/Cargo.toml | 1 - .../src/visualizers/arrows2d.rs | 4 +- .../src/visualizers/arrows3d.rs | 4 +- .../src/visualizers/assets3d.rs | 4 +- .../src/visualizers/boxes2d.rs | 4 +- .../src/visualizers/boxes3d.rs | 4 +- .../src/visualizers/entity_iterator.rs | 6 +- .../src/visualizers/images.rs | 4 +- .../src/visualizers/lines2d.rs | 4 +- .../src/visualizers/lines3d.rs | 4 +- .../src/visualizers/meshes.rs | 4 +- .../src/visualizers/mod.rs | 2 +- .../src/visualizers/points2d.rs | 4 +- .../src/visualizers/points3d.rs | 4 +- .../src/visualizers/results_ext.rs | 65 +- .../src/visualizer_system.rs | 4 +- crates/re_space_view_text_document/Cargo.toml | 1 - .../src/visualizer_system.rs | 2 +- crates/re_space_view_text_log/Cargo.toml | 2 +- .../src/visualizer_system.rs | 10 +- crates/re_space_view_time_series/Cargo.toml | 1 - .../src/line_visualizer_system.rs | 12 +- .../src/point_visualizer_system.rs | 8 +- .../src/codegen/rust/to_archetype.rs | 12 +- crates/re_viewer/Cargo.toml | 2 +- crates/re_viewer/src/lib.rs | 4 +- crates/re_viewer/src/ui/memory_panel.rs | 2 +- crates/re_viewer_context/Cargo.toml | 1 - .../src/component_ui_registry.rs | 12 +- crates/re_viewer_context/src/item.rs | 3 +- .../re_viewer_context/src/space_view/mod.rs | 3 - crates/re_viewer_context/src/store_hub.rs | 2 +- crates/re_viewport/src/container.rs | 2 +- crates/re_viewport/src/viewport_blueprint.rs | 2 +- examples/rust/custom_space_view/Cargo.toml | 2 +- .../color_coordinates_visualizer_system.rs | 12 +- scripts/lint.py | 6 - 148 files changed, 1904 insertions(+), 6865 deletions(-) rename crates/{re_query_cache => re_query}/benches/flat_vec_deque.rs (99%) rename crates/{re_query_cache => re_query}/benches/latest_at.rs (98%) delete mode 100644 crates/re_query/benches/query_benchmark.rs rename crates/{re_query_cache => re_query}/examples/latest_at.rs (89%) rename crates/{re_query_cache => re_query}/examples/latest_at_archetype.rs (92%) rename crates/{re_query_cache => re_query}/examples/range.rs (91%) delete mode 100644 crates/re_query/src/archetype_view.rs rename crates/{re_query2 => re_query}/src/bin/clamped_zip.rs (99%) rename crates/{re_query2 => re_query}/src/bin/range_zip.rs (99%) rename crates/{re_query_cache => re_query}/src/cache.rs (100%) rename crates/{re_query_cache => re_query}/src/cache_stats.rs (100%) rename crates/{re_query2 => re_query}/src/clamped_zip/.gitattributes (100%) rename crates/{re_query2 => re_query}/src/clamped_zip/generated.rs (99%) rename crates/{re_query2 => re_query}/src/clamped_zip/mod.rs (100%) rename crates/{re_query_cache => re_query}/src/flat_vec_deque.rs (100%) rename crates/{re_query_cache => re_query}/src/latest_at/helpers.rs (96%) create mode 100644 crates/re_query/src/latest_at/mod.rs rename crates/{re_query_cache => re_query}/src/latest_at/query.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/results.rs (85%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/.gitattributes (100%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/annotation_context.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/arrows2d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/arrows3d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/asset3d.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/background.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/bar_chart.rs (93%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/boxes2d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/boxes3d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/clear.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/container_blueprint.rs (98%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/depth_image.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/disconnected_space.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/image.rs (93%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/line_strips2d.rs (97%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/line_strips3d.rs (97%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/mesh3d.rs (97%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/mod.rs (100%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/panel_blueprint.rs (93%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/pinhole.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/plot_legend.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/points2d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/points3d.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/scalar.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/scalar_axis.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/segmentation_image.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/series_line.rs (93%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/series_point.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/space_view_blueprint.rs (96%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/space_view_contents.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/tensor.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/text_document.rs (95%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/text_log.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/transform3d.rs (91%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/view_coordinates.rs (94%) rename crates/{re_query_cache => re_query}/src/latest_at/to_archetype/viewport_blueprint.rs (97%) rename crates/{re_query2 => re_query}/src/promise.rs (100%) delete mode 100644 crates/re_query/src/query.rs delete mode 100644 crates/re_query/src/range.rs create mode 100644 crates/re_query/src/range/mod.rs rename crates/{re_query_cache => re_query}/src/range/query.rs (96%) rename crates/{re_query_cache => re_query}/src/range/results.rs (92%) rename crates/{re_query2 => re_query}/src/range_zip/.gitattributes (100%) rename crates/{re_query2 => re_query}/src/range_zip/generated.rs (99%) rename crates/{re_query2 => re_query}/src/range_zip/mod.rs (100%) delete mode 100644 crates/re_query/src/util.rs rename crates/{re_query2 => re_query}/src/visible_history.rs (100%) delete mode 100644 crates/re_query/tests/archetype_query_tests.rs delete mode 100644 crates/re_query/tests/archetype_range_tests.rs delete mode 100644 crates/re_query/tests/archetype_visit_tests.rs create mode 100644 crates/re_query/tests/latest_at.rs create mode 100644 crates/re_query/tests/range.rs delete mode 100644 crates/re_query/tests/store.rs delete mode 100644 crates/re_query2/Cargo.toml delete mode 100644 crates/re_query2/README.md delete mode 100644 crates/re_query2/benches/latest_at.rs delete mode 100644 crates/re_query2/examples/latest_at.rs delete mode 100644 crates/re_query2/examples/range.rs delete mode 100644 crates/re_query2/src/latest_at/mod.rs delete mode 100644 crates/re_query2/src/latest_at/query.rs delete mode 100644 crates/re_query2/src/latest_at/results.rs delete mode 100644 crates/re_query2/src/lib.rs delete mode 100644 crates/re_query2/src/range/mod.rs delete mode 100644 crates/re_query2/src/range/query.rs delete mode 100644 crates/re_query2/src/range/results.rs delete mode 100644 crates/re_query2/tests/latest_at.rs delete mode 100644 crates/re_query2/tests/range.rs delete mode 100644 crates/re_query_cache/Cargo.toml delete mode 100644 crates/re_query_cache/README.md delete mode 100644 crates/re_query_cache/src/latest_at/mod.rs delete mode 100644 crates/re_query_cache/src/lib.rs delete mode 100644 crates/re_query_cache/src/range/mod.rs delete mode 100644 crates/re_query_cache/tests/latest_at.rs delete mode 100644 crates/re_query_cache/tests/range.rs diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 0bc22487db3f..f7c54b5dd2da 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -149,7 +149,6 @@ Update instructions: |----------------------|--------------------------------------------------------------------------| | re_entity_db | In-memory storage of Rerun entities | | re_query | Querying data in the re_data_store | -| re_query_cache | Caching datastructures for re_query | | re_types | The built-in Rerun data types, component types, and archetypes. | | re_types_blueprint | The core traits and types that power Rerun's Blueprint sub-system. | | re_log_encoding | Helpers for encoding and transporting Rerun log messages | diff --git a/Cargo.lock b/Cargo.lock index b5a8526152b7..ac78976d7797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,7 +1418,7 @@ version = "0.16.0-alpha.2" dependencies = [ "mimalloc", "re_crash_handler", - "re_query2", + "re_query", "re_sdk_comms", "re_viewer", ] @@ -4309,7 +4309,6 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_query", - "re_query_cache", "re_smart_channel", "re_tracing", "re_types", @@ -4458,62 +4457,6 @@ dependencies = [ [[package]] name = "re_query" version = "0.16.0-alpha.2" -dependencies = [ - "backtrace", - "criterion", - "document-features", - "itertools 0.12.0", - "mimalloc", - "rand", - "re_arrow2", - "re_data_store", - "re_format", - "re_format_arrow", - "re_log", - "re_log_types", - "re_tracing", - "re_types", - "re_types_core", - "serde", - "similar-asserts", - "smallvec", - "thiserror", -] - -[[package]] -name = "re_query2" -version = "0.16.0-alpha.2" -dependencies = [ - "ahash", - "anyhow", - "backtrace", - "criterion", - "document-features", - "itertools 0.12.0", - "mimalloc", - "nohash-hasher", - "rand", - "re_arrow2", - "re_data_store", - "re_format", - "re_format_arrow", - "re_log", - "re_log_types", - "re_tracing", - "re_tuid", - "re_types", - "re_types_core", - "serde", - "similar-asserts", - "smallvec", - "static_assertions", - "thiserror", - "unindent", -] - -[[package]] -name = "re_query_cache" -version = "0.16.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -4527,18 +4470,22 @@ dependencies = [ "parking_lot", "paste", "rand", + "re_arrow2", "re_data_store", "re_error", "re_format", "re_log", "re_log_types", - "re_query2", "re_tracing", + "re_tuid", "re_types", "re_types_blueprint", "re_types_core", "seq-macro", "similar-asserts", + "static_assertions", + "thiserror", + "unindent", "web-time", ] @@ -4683,7 +4630,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", "re_tracing", "re_types", "re_types_core", @@ -4721,7 +4667,6 @@ dependencies = [ "re_entity_db", "re_log_types", "re_query", - "re_query_cache", "re_renderer", "re_tracing", "re_types_core", @@ -4754,7 +4699,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", "re_renderer", "re_space_view", "re_tracing", @@ -4801,7 +4745,6 @@ dependencies = [ "itertools 0.12.0", "re_data_store", "re_log", - "re_query", "re_renderer", "re_space_view", "re_tracing", @@ -4822,7 +4765,7 @@ dependencies = [ "re_entity_db", "re_log", "re_log_types", - "re_query_cache", + "re_query", "re_renderer", "re_tracing", "re_types", @@ -4843,7 +4786,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", "re_renderer", "re_space_view", "re_tracing", @@ -5059,7 +5001,7 @@ dependencies = [ "re_log_encoding", "re_log_types", "re_memory", - "re_query_cache", + "re_query", "re_renderer", "re_smart_channel", "re_space_view", @@ -5119,7 +5061,6 @@ dependencies = [ "re_log", "re_log_types", "re_query", - "re_query_cache", "re_renderer", "re_smart_channel", "re_string_interner", diff --git a/Cargo.toml b/Cargo.toml index d391fc4bcab3..778307ce3fa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,8 +46,6 @@ re_log_encoding = { path = "crates/re_log_encoding", version = "=0.16.0-alpha.2" re_log_types = { path = "crates/re_log_types", version = "=0.16.0-alpha.2", default-features = false } re_memory = { path = "crates/re_memory", version = "=0.16.0-alpha.2", default-features = false } re_query = { path = "crates/re_query", version = "=0.16.0-alpha.2", default-features = false } -re_query_cache = { path = "crates/re_query_cache", version = "=0.16.0-alpha.2", default-features = false } -re_query2 = { path = "crates/re_query2", version = "=0.16.0-alpha.2", default-features = false } re_renderer = { path = "crates/re_renderer", version = "=0.16.0-alpha.2", default-features = false } re_sdk = { path = "crates/re_sdk", version = "=0.16.0-alpha.2", default-features = false } re_sdk_comms = { path = "crates/re_sdk_comms", version = "=0.16.0-alpha.2", default-features = false } diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index 6c6e9a2fa4c6..1fe709c7ea2b 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -2,9 +2,7 @@ use std::sync::Arc; use egui::NumExt; -use re_entity_db::{ - external::re_query_cache::CachedLatestAtComponentResults, EntityPath, InstancePath, -}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityPath, InstancePath}; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; use re_viewer_context::{UiVerbosity, ViewerContext}; @@ -16,7 +14,7 @@ use crate::item_ui; pub struct EntityLatestAtResults { pub entity_path: EntityPath, pub component_name: ComponentName, - pub results: Arc, + pub results: Arc, } impl DataUi for EntityLatestAtResults { diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 98e4afbf148d..19c92ed3c541 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb}; use re_log_types::{external::arrow2, EntityPath}; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; @@ -62,7 +62,7 @@ fn fallback_component_ui( _query: &LatestAtQuery, db: &EntityDb, _entity_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { // TODO(#5607): what should happen if the promise is still pending? diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index 61b96d4eade1..b22499105bce 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -2,7 +2,7 @@ use egui::NumExt as _; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtComponentResults, EntityDb}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb}; use re_log_types::EntityPath; use re_types::{ components::{ @@ -23,7 +23,7 @@ fn edit_color_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_color = component @@ -66,7 +66,7 @@ fn edit_text_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component @@ -106,7 +106,7 @@ fn edit_name_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_text = component @@ -147,7 +147,7 @@ fn edit_scatter_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_scatter = component @@ -196,7 +196,7 @@ fn edit_radius_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_radius = component @@ -243,7 +243,7 @@ fn edit_marker_shape_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker = component @@ -329,7 +329,7 @@ fn edit_stroke_width_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_stroke_width = component @@ -376,7 +376,7 @@ fn edit_marker_size_ui( db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &re_types::components::InstanceKey, ) { let current_marker_size = component @@ -425,7 +425,7 @@ fn register_editor<'a, C: Component + Loggable + 'static>( &EntityDb, &EntityPath, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &re_types::components::InstanceKey, ), ) where diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index db210bcf7b48..178cc0f8e3ee 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -23,7 +23,7 @@ all-features = true default = [] ## Enable (de)serialization using serde. -serde = ["dep:serde", "dep:rmp-serde", "re_log_types/serde", "re_query/serde"] +serde = ["dep:serde", "dep:rmp-serde", "re_log_types/serde"] [dependencies] @@ -33,8 +33,7 @@ re_int_histogram.workspace = true re_log.workspace = true re_log_encoding = { workspace = true, features = ["decoder"] } re_log_types.workspace = true -re_query.workspace = true -re_query_cache = { workspace = true, features = ["to_archetype"] } +re_query = { workspace = true, features = ["to_archetype"] } re_smart_channel.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 4d618e81a71a..2355ce9dfe1b 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -12,7 +12,7 @@ use re_log_types::{ EntityPathHash, LogMsg, RowId, SetStoreInfo, StoreId, StoreInfo, StoreKind, TimePoint, TimeRange, TimeRangeF, Timeline, }; -use re_query_cache::PromiseResult; +use re_query::PromiseResult; use re_types_core::{components::InstanceKey, Archetype, Loggable}; use crate::{ClearCascade, CompactedStoreEvents, Error, TimesPerTimeline}; @@ -117,10 +117,10 @@ pub struct EntityDb { data_store: DataStore, /// The active promise resolver for this DB. - resolver: re_query_cache::PromiseResolver, + resolver: re_query::PromiseResolver, /// Query caches for the data in [`Self::data_store`]. - query_caches: re_query_cache::Caches, + query_caches: re_query::Caches, stats: IngestionStatistics, } @@ -132,7 +132,7 @@ impl EntityDb { InstanceKey::name(), DataStoreConfig::default(), ); - let query_caches = re_query_cache::Caches::new(&data_store); + let query_caches = re_query::Caches::new(&data_store); Self { data_source: None, set_store_info: None, @@ -142,7 +142,7 @@ impl EntityDb { times_per_timeline: Default::default(), tree: crate::EntityTree::root(), data_store, - resolver: re_query_cache::PromiseResolver::default(), + resolver: re_query::PromiseResolver::default(), query_caches, stats: IngestionStatistics::new(store_id), } @@ -192,12 +192,12 @@ impl EntityDb { } #[inline] - pub fn query_caches(&self) -> &re_query_cache::Caches { + pub fn query_caches(&self) -> &re_query::Caches { &self.query_caches } #[inline] - pub fn resolver(&self) -> &re_query_cache::PromiseResolver { + pub fn resolver(&self) -> &re_query::PromiseResolver { &self.resolver } @@ -209,7 +209,7 @@ impl EntityDb { query: &re_data_store::LatestAtQuery, ) -> PromiseResult> where - re_query_cache::CachedLatestAtResults: re_query_cache::ToArchetype, + re_query::LatestAtResults: re_query::ToArchetype, { let results = self.query_caches().latest_at( self.store(), @@ -218,12 +218,12 @@ impl EntityDb { A::all_components().iter().copied(), // no generics! ); - use re_query_cache::ToArchetype as _; + use re_query::ToArchetype as _; match results.to_archetype(self.resolver()).flatten() { PromiseResult::Pending => PromiseResult::Pending, PromiseResult::Error(err) => { - if let Some(err) = err.downcast_ref::() { - if matches!(err, re_query_cache::QueryError::PrimaryNotFound(_)) { + if let Some(err) = err.downcast_ref::() { + if matches!(err, re_query::QueryError::PrimaryNotFound(_)) { return PromiseResult::Ready(None); } } @@ -240,7 +240,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component::( self.store(), self.resolver(), @@ -254,7 +254,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option> { + ) -> Option> { self.query_caches().latest_at_component_quiet::( self.store(), self.resolver(), @@ -268,7 +268,7 @@ impl EntityDb { &self, entity_path: &EntityPath, query: &re_data_store::LatestAtQuery, - ) -> Option<(EntityPath, re_query_cache::CachedLatestAtMonoResult)> { + ) -> Option<(EntityPath, re_query::LatestAtMonoResult)> { self.query_caches() .latest_at_component_at_closest_ancestor::( self.store(), diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index e431475ea747..1d981b4a4d3f 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -34,7 +34,7 @@ pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents}; use re_log_types::DataTableError; pub use re_log_types::{EntityPath, EntityPathPart, TimeInt, Timeline}; -pub use re_query_cache::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +pub use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; #[cfg(feature = "serde")] pub use blueprint::components::EntityPropertiesComponent; @@ -43,7 +43,7 @@ pub use editable_auto_value::EditableAutoValue; pub mod external { pub use re_data_store; - pub use re_query_cache; + pub use re_query; } // ---------------------------------------------------------------------------- diff --git a/crates/re_query/Cargo.toml b/crates/re_query/Cargo.toml index 66c9327a5b16..9d223195d0b5 100644 --- a/crates/re_query/Cargo.toml +++ b/crates/re_query/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "re_query" authors.workspace = true -description = "Querying data in the re_data_store" +description = "High-level query APIs" edition.workspace = true homepage.workspace = true include.workspace = true @@ -20,37 +20,54 @@ all-features = true [features] -default = [] +default = ["to_archetype"] -## Enable (de)serialization using serde. -serde = ["dep:serde"] +## Implements `ToArchetype` for all builtin archetypes on `LatestAtResults`. +to_archetype = ["dep:re_types", "dep:re_types_blueprint"] + +## Enable codegen helper binaries (generates ClampedZip & RangeZip implementations). +codegen = ["unindent"] [dependencies] # Rerun dependencies: re_data_store.workspace = true +re_error.workspace = true re_format.workspace = true -re_format_arrow.workspace = true -re_log_types.workspace = true -re_types_core.workspace = true re_log.workspace = true +re_log_types.workspace = true re_tracing.workspace = true +re_tuid.workspace = true +re_types_core.workspace = true + +# Rerun dependencies (optional): +re_types = { workspace = true, optional = true } +re_types_blueprint = { workspace = true, optional = true } # External dependencies: +ahash.workspace = true +anyhow.workspace = true arrow2.workspace = true backtrace.workspace = true -document-features.workspace = true -itertools = { workspace = true } -serde = { workspace = true, features = ["derive", "rc"], optional = true } -smallvec.workspace = true +indent.workspace = true +indexmap.workspace = true +itertools.workspace = true +nohash-hasher.workspace = true +parking_lot.workspace = true +paste.workspace = true +seq-macro.workspace = true +static_assertions.workspace = true thiserror.workspace = true +web-time.workspace = true + +# External dependencies (optional): +unindent = { workspace = true, optional = true } [dev-dependencies] re_types = { workspace = true, features = ["datagen"] } criterion.workspace = true -itertools = { workspace = true } mimalloc.workspace = true rand = { workspace = true, features = ["std", "std_rng"] } similar-asserts.workspace = true @@ -60,6 +77,25 @@ similar-asserts.workspace = true bench = false +[[example]] +name = "latest_at_archetype" +required-features = ["to_archetype"] + + +[[bin]] +name = "clamped_zip" +required-features = ["codegen"] + + +[[bin]] +name = "range_zip" +required-features = ["codegen"] + + +[[bench]] +name = "flat_vec_deque" +harness = false + [[bench]] -name = "query_benchmark" +name = "latest_at" harness = false diff --git a/crates/re_query/README.md b/crates/re_query/README.md index 79097b9e5cbe..7d0c4241b353 100644 --- a/crates/re_query/README.md +++ b/crates/re_query/README.md @@ -7,4 +7,4 @@ Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. ![MIT](https://img.shields.io/badge/license-MIT-blue.svg) ![Apache](https://img.shields.io/badge/license-Apache-blue.svg) -Querying data in the `re_data_store`. +High-level query APIs. diff --git a/crates/re_query_cache/benches/flat_vec_deque.rs b/crates/re_query/benches/flat_vec_deque.rs similarity index 99% rename from crates/re_query_cache/benches/flat_vec_deque.rs rename to crates/re_query/benches/flat_vec_deque.rs index d12e10293c0e..bce849d9a43c 100644 --- a/crates/re_query_cache/benches/flat_vec_deque.rs +++ b/crates/re_query/benches/flat_vec_deque.rs @@ -2,7 +2,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools as _; -use re_query_cache::FlatVecDeque; +use re_query::FlatVecDeque; // --- diff --git a/crates/re_query_cache/benches/latest_at.rs b/crates/re_query/benches/latest_at.rs similarity index 98% rename from crates/re_query_cache/benches/latest_at.rs rename to crates/re_query/benches/latest_at.rs index 599c73726ef9..feba6dde04f6 100644 --- a/crates/re_query_cache/benches/latest_at.rs +++ b/crates/re_query/benches/latest_at.rs @@ -6,8 +6,8 @@ use criterion::{criterion_group, criterion_main, Criterion}; use itertools::Itertools; use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query2::{clamped_zip_1x1, PromiseResolver}; -use re_query_cache::{CachedLatestAtResults, Caches}; +use re_query::{clamped_zip_1x1, PromiseResolver}; +use re_query::{Caches, LatestAtResults}; use re_types::{ archetypes::Points2D, components::{Color, InstanceKey, Position2D, Text}, @@ -289,7 +289,7 @@ fn query_and_visit_points( // TODO(jleibs): Add Radius once we have support for it in field_types for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( store, &query, entity_path, @@ -340,7 +340,7 @@ fn query_and_visit_strings( let mut strings = Vec::with_capacity(NUM_STRINGS as _); for entity_path in paths { - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( store, &query, entity_path, diff --git a/crates/re_query/benches/query_benchmark.rs b/crates/re_query/benches/query_benchmark.rs deleted file mode 100644 index aa5af0efe07c..000000000000 --- a/crates/re_query/benches/query_benchmark.rs +++ /dev/null @@ -1,313 +0,0 @@ -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -use criterion::{criterion_group, criterion_main, Criterion}; - -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query::query_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D, Text}, -}; -use re_types_core::Loggable as _; - -// --- - -#[cfg(not(debug_assertions))] -const NUM_FRAMES_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_FRAMES_STRINGS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_STRINGS: u32 = 1_000; - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -const NUM_FRAMES_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_FRAMES_STRINGS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_STRINGS: u32 = 1; - -criterion_group!( - benches, - mono_points, - mono_strings, - batch_points, - batch_strings -); -criterion_main!(benches); - -// --- Benchmarks --- - -pub fn build_some_point2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) - .collect() -} - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len).map(|i| Color::from(i as u32)).collect() -} - -/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) -} - -pub fn build_some_strings(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - let ilen: usize = rng.gen_range(0..10000); - let s: String = rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(ilen) - .map(char::from) - .collect(); - Text::from(s) - }) - .collect() -} - -fn mono_points(c: &mut Criterion) { - // Each mono point gets logged at a different path - let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx.to_string())) - .collect_vec(); - let msgs = build_points_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - // Mono-insert is slow -- decrease the sample size - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn mono_strings(c: &mut Criterion) { - // Each mono string gets logged at a different path - let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx.to_string())) - .collect_vec(); - let msgs = build_strings_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -fn batch_points(c: &mut Criterion) { - // Batch points are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_points_rows(&paths, NUM_POINTS as _); - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn batch_strings(c: &mut Criterion) { - // Batch strings are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_strings_rows(&paths, NUM_STRINGS as _); - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -// --- Helpers --- - -fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { - (0..NUM_FRAMES_POINTS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_points as _, - ( - build_some_point2d(num_points), - build_some_colors(num_points), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { - (0..NUM_FRAMES_STRINGS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_strings as _, - // We still need to create points because they are the primary for the - // archetype query we want to do. We won't actually deserialize the points - // during the query -- we just need it for the primary keys. - // TODO(jleibs): switch this to use `TextEntry` once the new type has - // landed. - ( - build_some_point2d(num_strings), - build_some_strings(num_strings), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn insert_rows<'a>(msgs: impl Iterator) -> DataStore { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - msgs.for_each(|row| { - store.insert_row(row).unwrap(); - }); - store -} - -struct SavePoint { - _pos: Position2D, - _color: Option, -} - -fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec { - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); - - let mut points = Vec::with_capacity(NUM_POINTS as _); - - // TODO(jleibs): Add Radius once we have support for it in field_types - for path in paths { - let arch_view = query_archetype::(store, &query, path).unwrap(); - itertools::izip!( - arch_view.iter_required_component::().unwrap(), - arch_view.iter_optional_component::().unwrap() - ) - .for_each(|(pos, color)| { - points.push(SavePoint { - _pos: pos, - _color: color, - }); - }); - } - assert_eq!(NUM_POINTS as usize, points.len()); - points -} - -struct SaveString { - _label: Option, -} - -fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec { - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); - - let mut strings = Vec::with_capacity(NUM_STRINGS as _); - - for path in paths { - let arch_view = query_archetype::(store, &query, path).unwrap(); - arch_view - .iter_optional_component::() - .unwrap() - .for_each(|label| { - strings.push(SaveString { _label: label }); - }); - } - assert_eq!(NUM_STRINGS as usize, strings.len()); - - criterion::black_box(strings) -} diff --git a/crates/re_query_cache/examples/latest_at.rs b/crates/re_query/examples/latest_at.rs similarity index 89% rename from crates/re_query_cache/examples/latest_at.rs rename to crates/re_query/examples/latest_at.rs index e894e10b63a1..eb450f091cc2 100644 --- a/crates/re_query_cache/examples/latest_at.rs +++ b/crates/re_query/examples/latest_at.rs @@ -4,9 +4,8 @@ use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache::{ - clamped_zip_1x2, CachedLatestAtComponentResults, CachedLatestAtResults, PromiseResolver, - PromiseResult, +use re_query::{ + clamped_zip_1x2, LatestAtComponentResults, LatestAtResults, PromiseResolver, PromiseResult, }; // --- @@ -22,13 +21,13 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query_cache::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), @@ -41,9 +40,9 @@ fn main() -> anyhow::Result<()> { // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. - let points: &CachedLatestAtComponentResults = results.get_required(MyPoint::name())?; - let colors: &CachedLatestAtComponentResults = results.get_or_empty(MyColor::name()); - let labels: &CachedLatestAtComponentResults = results.get_or_empty(MyLabel::name()); + let points: &LatestAtComponentResults = results.get_required(MyPoint::name())?; + let colors: &LatestAtComponentResults = results.get_or_empty(MyColor::name()); + let labels: &LatestAtComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query_cache/examples/latest_at_archetype.rs b/crates/re_query/examples/latest_at_archetype.rs similarity index 92% rename from crates/re_query_cache/examples/latest_at_archetype.rs rename to crates/re_query/examples/latest_at_archetype.rs index 94caab585ce2..af3215fdc3bc 100644 --- a/crates/re_query_cache/examples/latest_at_archetype.rs +++ b/crates/re_query/examples/latest_at_archetype.rs @@ -7,7 +7,7 @@ use re_types::{ }; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache::{clamped_zip_1x2, CachedLatestAtResults, PromiseResolver, PromiseResult}; +use re_query::{clamped_zip_1x2, LatestAtResults, PromiseResolver, PromiseResult}; // --- @@ -22,13 +22,13 @@ fn main() -> anyhow::Result<()> { let query = LatestAtQuery::latest(timeline); eprintln!("query:{query:?}"); - let caches = re_query_cache::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedLatestAtResults = caches.latest_at( + let results: LatestAtResults = caches.latest_at( &store, &query, &entity_path.into(), @@ -37,7 +37,7 @@ fn main() -> anyhow::Result<()> { // Then make use of the `ToArchetype` helper trait in order to query, resolve, deserialize and // cache an entire archetype all at once. - use re_query_cache::ToArchetype as _; + use re_query::ToArchetype as _; let arch: Points2D = match results.to_archetype(&resolver).flatten() { PromiseResult::Pending => { diff --git a/crates/re_query_cache/examples/range.rs b/crates/re_query/examples/range.rs similarity index 91% rename from crates/re_query_cache/examples/range.rs rename to crates/re_query/examples/range.rs index e9bef34822eb..0defca92ed8a 100644 --- a/crates/re_query_cache/examples/range.rs +++ b/crates/re_query/examples/range.rs @@ -4,9 +4,9 @@ use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; use re_types_core::{Archetype as _, Loggable as _}; -use re_query_cache::{ - clamped_zip_1x2, range_zip_1x2, CachedRangeComponentResults, CachedRangeResults, - PromiseResolver, PromiseResult, +use re_query::{ + clamped_zip_1x2, range_zip_1x2, PromiseResolver, PromiseResult, RangeComponentResults, + RangeResults, }; // --- @@ -22,13 +22,13 @@ fn main() -> anyhow::Result<()> { let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); eprintln!("query:{query:?}"); - let caches = re_query_cache::Caches::new(&store); + let caches = re_query::Caches::new(&store); // First, get the raw results for this query. // // They might or might not already be cached. We won't know for sure until we try to access // each individual component's data below. - let results: CachedRangeResults = caches.range( + let results: RangeResults = caches.range( &store, &query, &entity_path.into(), @@ -41,9 +41,9 @@ fn main() -> anyhow::Result<()> { // * `get` returns an option // // At this point we still don't know whether they are cached or not. That's the next step. - let all_points: &CachedRangeComponentResults = results.get_required(MyPoint::name())?; - let all_colors: &CachedRangeComponentResults = results.get_or_empty(MyColor::name()); - let all_labels: &CachedRangeComponentResults = results.get_or_empty(MyLabel::name()); + let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; + let all_colors: &RangeComponentResults = results.get_or_empty(MyColor::name()); + let all_labels: &RangeComponentResults = results.get_or_empty(MyLabel::name()); // Then comes the time to resolve/convert and deserialize the data. // These steps have to be done together for efficiency reasons. diff --git a/crates/re_query/src/archetype_view.rs b/crates/re_query/src/archetype_view.rs deleted file mode 100644 index 371bd66dc705..000000000000 --- a/crates/re_query/src/archetype_view.rs +++ /dev/null @@ -1,669 +0,0 @@ -use std::{collections::BTreeMap, marker::PhantomData}; - -use arrow2::array::{Array, PrimitiveArray}; - -use re_log_types::{DataCell, DataCellRow, RowId, TimeInt}; -use re_types_core::{ - components::InstanceKey, Archetype, Component, ComponentName, DeserializationError, - DeserializationResult, Loggable, SerializationResult, -}; - -use crate::QueryError; - -/// A type-erased array of [`Component`] values and the corresponding [`InstanceKey`] keys. -/// -/// See: [`crate::get_component_with_instances`] -#[derive(Clone, Debug)] -pub struct ComponentWithInstances { - pub(crate) instance_keys: DataCell, - pub(crate) values: DataCell, -} - -impl std::fmt::Display for ComponentWithInstances { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let table = re_format_arrow::format_table( - [ - self.instance_keys.as_arrow_ref(), - self.values.as_arrow_ref(), - ], - ["InstanceKey", self.values.component_name().as_ref()], - ); - - f.write_fmt(format_args!("ComponentWithInstances:\n{table}")) - } -} - -impl ComponentWithInstances { - /// Name of the [`Component`] - #[inline] - pub fn name(&self) -> ComponentName { - self.values.component_name() - } - - /// Number of values. 1 for splats. - #[inline] - pub fn len(&self) -> usize { - self.values.num_instances() as _ - } - - #[inline] - /// Whether this [`ComponentWithInstances`] contains any data - pub fn is_empty(&self) -> bool { - self.values.is_empty() - } - - /// Returns the array of [`InstanceKey`]s. - #[inline] - pub fn instance_keys(&self) -> Vec { - re_tracing::profile_function!(); - self.instance_keys.to_native::() - } - - /// Returns the array of values as native [`Component`]s. - #[inline] - pub fn values<'a, C: Component + 'a>(&'a self) -> crate::Result>> { - if C::name() != self.name() { - return Err(QueryError::TypeMismatch { - actual: self.name(), - requested: C::name(), - }); - } - - Ok(self.values.try_to_native_opt::<'a, C>()?) - } - - /// Look up the value that corresponds to a given [`InstanceKey`] and convert to [`Component`] - pub fn lookup(&self, instance_key: &InstanceKey) -> crate::Result { - if C::name() != self.name() { - return Err(QueryError::TypeMismatch { - actual: self.name(), - requested: C::name(), - }); - } - let arr = self - .lookup_arrow(instance_key) - .map_or_else(|| Err(crate::ComponentNotFoundError(C::name())), Ok)?; - - let mut iter = C::from_arrow(arr.as_ref())?.into_iter(); - - let val = iter - .next() - .map_or_else(|| Err(crate::ComponentNotFoundError(C::name())), Ok)?; - Ok(val) - } - - /// Look up the value that corresponds to a given [`InstanceKey`] and return as an arrow [`Array`] - pub fn lookup_arrow(&self, instance_key: &InstanceKey) -> Option> { - let keys = self - .instance_keys - .as_arrow_ref() - .as_any() - .downcast_ref::>()? - .values(); - - // If the value is splatted, return the offset of the splat - let offset = if keys.len() == 1 && keys[0] == InstanceKey::SPLAT.0 { - 0 - } else { - // Otherwise binary search to find the offset of the instance - keys.binary_search(&instance_key.0).ok()? - }; - - (self.len() > offset) - .then(|| self.values.as_arrow_ref().sliced(offset, 1)) - .or_else(|| { - re_log::error_once!("found corrupt cell -- mismatched number of instances"); - None - }) - } - - /// Produce a [`ComponentWithInstances`] from native [`Component`] types - pub fn from_native<'a, C: Component + Clone + 'a>( - instance_keys: impl IntoIterator>>, - values: impl IntoIterator>>, - ) -> SerializationResult { - // Unwrap: If the data is valid for the native types, it's valid in serialized form. - let instance_keys = InstanceKey::to_arrow(instance_keys)?; - let values = C::to_arrow(values)?; - Ok(ComponentWithInstances { - instance_keys: DataCell::from_arrow(InstanceKey::name(), instance_keys), - values: DataCell::from_arrow(C::name(), values), - }) - } - - #[inline] - pub fn into_data_cell_row(self) -> DataCellRow { - let Self { - instance_keys, - values, - } = self; - DataCellRow(smallvec::smallvec![instance_keys, values]) - } -} - -/// Iterator over a single [`Component`] joined onto a primary [`Component`] -/// -/// This is equivalent to a left join between one table made up of the -/// [`InstanceKey`]s from the primary component and another table with the -/// [`InstanceKey`]s and values of the iterated [`Component`]. -/// -/// Instances have a [`InstanceKey::SPLAT`] key that will cause the value to be -/// repeated for the entirety of the join. -/// -/// For example -/// ```text -/// primary -/// +----------+ -/// | instance | -/// +----------+ -/// | key0 | -/// | key1 | -/// | Key2 | -/// -/// component -/// +----------+-------+ -/// | instance | value | -/// +----------+-------+ -/// | key0 | val0 | -/// | Key2 | val2 | -/// -/// SELECT value FROM LEFT JOIN primary.instance = component.instance; -/// -/// output -/// +-------+ -/// | value | -/// +-------+ -/// | val0 | -/// | NULL | -/// | val2 | -/// -/// ``` -pub struct ComponentJoinedIterator { - pub primary_instance_key_iter: IIter1, - pub component_instance_key_iter: IIter2, - pub component_value_iter: VIter, - pub next_component_instance_key: Option, - pub splatted_component_value: Option, -} - -impl Iterator for ComponentJoinedIterator -where - IIter1: Iterator, - IIter2: Iterator, - VIter: Iterator>, - C: Clone, -{ - type Item = Option; - - fn next(&mut self) -> Option> { - // For each value of primary_instance_iter we must find a result - if let Some(primary_key) = self.primary_instance_key_iter.next() { - loop { - match &self.next_component_instance_key { - // If we have a next component key, we either… - Some(instance_key) => { - if instance_key.is_splat() { - if self.splatted_component_value.is_none() { - self.splatted_component_value = - self.component_value_iter.next().flatten(); - } - break Some(self.splatted_component_value.clone()); - } else { - match primary_key.0.cmp(&instance_key.0) { - // Return a None if the primary_key hasn't reached it yet - std::cmp::Ordering::Less => break Some(None), - // Return the value if the keys match - std::cmp::Ordering::Equal => { - self.next_component_instance_key = - self.component_instance_key_iter.next(); - break self.component_value_iter.next(); - } - // Skip this component if the key is behind the primary key - std::cmp::Ordering::Greater => { - _ = self.component_value_iter.next(); - self.next_component_instance_key = - self.component_instance_key_iter.next(); - } - } - } - } - // Otherwise, we ran out of component elements. Just return - // None until the primary iter ends. - None => break Some(None), - }; - } - } else { - None - } - } -} - -impl ExactSizeIterator - for ComponentJoinedIterator -where - IIter1: ExactSizeIterator, - IIter2: ExactSizeIterator, - VIter: ExactSizeIterator>, - C: Clone, -{ -} - -/// A view of an [`Archetype`] at a particular point in time returned by [`crate::get_component_with_instances`]. -/// -/// The required [`Component`]s of an [`ArchetypeView`] determines the length of an entity -/// batch. When iterating over individual components, they will be implicitly joined onto -/// the required [`Component`]s using [`InstanceKey`] values. -#[derive(Clone, Debug)] -pub struct ArchetypeView { - /// The _data_ time of the most recent component in the view (not necessarily the primary!). - pub(crate) data_time: TimeInt, - - /// The [`RowId`] of the primary component in the view. - pub(crate) primary_row_id: RowId, - - pub(crate) components: BTreeMap, - - pub(crate) phantom: PhantomData, -} - -impl std::fmt::Display for ArchetypeView { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let first_required = self.required_comp(); - - let primary_table = re_format_arrow::format_table( - [ - first_required.instance_keys.as_arrow_ref(), - first_required.values.as_arrow_ref(), - ], - ["InstanceId", first_required.name().as_ref()], - ); - - f.write_fmt(format_args!("ArchetypeView:\n{primary_table}")) - } -} - -impl ArchetypeView { - #[inline] - pub fn num_instances(&self) -> usize { - self.required_comp().len() - } - - /// The _data_ time of the most recent component in the view (not necessarily the primary!). - #[inline] - pub fn data_time(&self) -> TimeInt { - self.data_time - } - - /// Returns the [`RowId`] associated with the _primary_ component that was used to drive this - /// entire query. - /// - /// Beware: when using this [`RowId`] for caching/versioning purposes, make sure the component - /// you are about to cache is in fact the primary component of the query! - /// See also . - #[inline] - pub fn primary_row_id(&self) -> RowId { - self.primary_row_id - } -} - -impl ArchetypeView { - #[inline] - fn required_comp(&self) -> &ComponentWithInstances { - // TODO(jleibs): Do all archetypes always have at least 1 required components? - let first_required = A::required_components()[0]; - &self.components[&first_required] - } - - /// Returns an iterator over [`InstanceKey`]s. - #[inline] - pub fn iter_instance_keys(&self) -> impl ExactSizeIterator { - re_tracing::profile_function!(); - // TODO(#2750): Maybe make this an intersection instead - self.required_comp().instance_keys().into_iter() - } - - /// Check if the entity has a component and its not empty - #[inline] - pub fn has_component(&self) -> bool { - let name = C::name(); - self.components.get(&name).map_or(false, |c| !c.is_empty()) - } - - /// Iterate over the values of a required multi-component. - #[inline] - pub fn iter_required_component<'a, C: Component + 'a>( - &'a self, - ) -> DeserializationResult + '_> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(); - - debug_assert!(A::required_components() - .iter() - .any(|c| c.as_ref() == C::name())); - let component = self.components.get(&C::name()); - - if let Some(component) = component { - let component_value_iter = component - .values - .try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string()))? - .into_iter(); - - Ok(component_value_iter) - } else { - Err(DeserializationError::MissingComponent { - component: C::name(), - backtrace: ::backtrace::Backtrace::new_unresolved(), - }) - } - } - - /// Get a single required mono-component. - #[inline] - pub fn required_mono_component(&self) -> DeserializationResult { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(); - - let mut iter = self.iter_required_component::()?; - let value = iter - .next() - .ok_or_else(|| DeserializationError::MissingComponent { - component: C::name(), - backtrace: re_types_core::_Backtrace::new_unresolved(), - })?; - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!("Expected a single value of {} but found {count}", C::name()); - } - Ok(value) - } - - /// Iterate over optional values as native [`Component`]s. - /// - /// Always produces an iterator that matches the length of a primary - /// component by joining on the `InstanceKey` values. - #[inline] - pub fn iter_optional_component<'a, C: Component + Clone + 'a>( - &'a self, - ) -> DeserializationResult> + '_> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(C::name()); - - let component = self.components.get(&C::name()); - - // If the component is found and not empty, run the joining iterator on it. - // Otherwise just output nulls of the length of the primary. - // Note that this guard is specifically a precondition of the inner optimization - // for matched instance keys which will debug_assert if a zero-length component is - // referenced there. - let is_empty = component.map_or(true, |c| c.is_empty()); - if let (Some(component), false) = (component, is_empty) { - // NOTE(1): Autogenerated instance keys are interned behind datacells. - // If two or more rows in the store share the same keys, then they will share - // also the same cells. - // Therefore we can compare those cells, and early out if they match. - // - // NOTE(2): Comparing cells that point to the same backing storage is a simple pointer - // comparison; no data comparison involved. - // If the cells are not interned, this will fall back to a more costly data comparison: - // - If the data is the same, the cost of the comparison will be won back by having a - // faster iterator. - // - If the data isn't the same, the cost of the comparison will be dwarfed by the cost - // of the join anyway. - - if self.required_comp().instance_keys == component.instance_keys { - // This fast iterator is assumed to match the length of the - // primary component We shouldn't hit this since the store - // should enforce matched lengths for non-empty components, and - // the outer if-guard should keep us from reaching this in the - // case of an empty component. - // TODO(#1893): This assert and the implementation both need to - // be addressed when we allow single rows containing splats. - debug_assert_eq!( - self.required_comp().instance_keys.num_instances(), - component.values.num_instances() - ); - - // NOTE: A component instance cannot be optional in itself, and if we're on this - // path then we know for a fact that both batches can be intersected 1-to-1. - // Therefore there cannot be any null values, therefore we can go through the fast - // deserialization path. - let component_value_iter = { - C::from_arrow(component.values.as_arrow_ref())? - .into_iter() - .map(Some) - }; - - return Ok(itertools::Either::Left(itertools::Either::Left( - component_value_iter, - ))); - } - - let component_value_iter = - { C::from_arrow_opt(component.values.as_arrow_ref())?.into_iter() }; - - let primary_instance_key_iter = self.iter_instance_keys(); - let mut component_instance_key_iter = component.instance_keys().into_iter(); - - let next_component_instance_key = component_instance_key_iter.next(); - - Ok(itertools::Either::Left(itertools::Either::Right( - ComponentJoinedIterator { - primary_instance_key_iter, - component_instance_key_iter, - component_value_iter, - next_component_instance_key, - splatted_component_value: None, - }, - ))) - } else { - let primary = self.required_comp(); - let nulls = (0..primary.len()).map(|_| None); - Ok(itertools::Either::Right(nulls)) - } - } - - /// Get a single optional mono-component. - #[inline] - pub fn optional_mono_component(&self) -> DeserializationResult> { - let mut iter = self.iter_optional_component::()?; - if let Some(first_value) = iter.next() { - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!("Expected a single value of {} but found {count}", C::name()); - } - Ok(first_value) - } else { - Ok(None) - } - } - - /// Iterate over optional values as native [`Component`]s. - /// - /// The contents of the cell are returned as-is, without joining with any other component. - #[inline] - pub fn iter_raw_optional_component<'a, C: Component + Clone + 'a>( - &'a self, - ) -> DeserializationResult + '_>> { - // NOTE(#3850): Don't add a profile scope here: the profiler overhead is too big for this fast function. - // re_tracing::profile_function!(C::name()); - - let component = self.components.get(&C::name()); - - if let Some(component) = component { - return Ok(Some( - C::from_arrow(component.values.as_arrow_ref())?.into_iter(), - )); - } - - Ok(None) - } - - /// Get a single optional mono-component. - #[inline] - pub fn raw_optional_mono_component(&self) -> DeserializationResult> { - if let Some(mut iter) = self.iter_raw_optional_component::()? { - if let Some(value) = iter.next() { - let count = 1 + iter.count(); - if count != 1 { - re_log::warn_once!( - "Expected a single value of {} but found {count}", - C::name() - ); - } - Ok(Some(value)) - } else { - Ok(None) - } - } else { - Ok(None) - } - } - - /// Helper function to produce an [`ArchetypeView`] from a collection of [`ComponentWithInstances`]. - #[inline] - pub fn from_components( - data_time: TimeInt, - primary_row_id: RowId, - components: impl IntoIterator, - ) -> Self { - Self { - data_time, - primary_row_id, - components: components - .into_iter() - .map(|comp| (comp.name(), comp)) - .collect(), - phantom: PhantomData, - } - } - - /// Convert an `ArchetypeView` back into a native Archetype instance - pub fn to_archetype(&self) -> crate::Result { - for component in A::required_components().iter() { - if self - .components - .get(component) - .map_or(true, |cwi| cwi.is_empty()) - { - return Err(QueryError::PrimaryNotFound(*component)); - } - } - - Ok(A::from_arrow_components( - self.components - .values() - .map(|comp| (comp.name(), comp.values.to_arrow())), - )?) - } - - /// Useful for tests. - pub fn to_data_cell_row_1< - 'a, - C1: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C1>> + 'a, - >( - &self, - ) -> crate::Result { - let cell0 = DataCell::from_native(self.iter_instance_keys()); - let cell1 = DataCell::from_native_sparse(self.iter_optional_component::()?); - Ok(DataCellRow(smallvec::smallvec![cell0, cell1])) - } - - /// Useful for tests. - pub fn to_data_cell_row_2< - 'a, - C1: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C1>> + 'a, - C2: re_types_core::Component + Clone + Into<::std::borrow::Cow<'a, C2>> + 'a, - >( - &self, - ) -> crate::Result { - let cell0 = DataCell::from_native(self.iter_instance_keys()); - let cell1 = DataCell::from_native_sparse(self.iter_optional_component::()?); - let cell2 = DataCell::from_native_sparse(self.iter_optional_component::()?); - Ok(DataCellRow(smallvec::smallvec![cell0, cell1, cell2])) - } -} - -#[test] -fn lookup_value() { - use re_types::components::{Color, InstanceKey, Position2D}; - - let instance_keys = InstanceKey::from_iter(0..5); - - let points = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, points).unwrap(); - - let missing_value = component.lookup_arrow(&InstanceKey(5)); - assert_eq!(missing_value, None); - - let value = component.lookup_arrow(&InstanceKey(2)).unwrap(); - - let expected_point = [points[2]]; - let expected_arrow = Position2D::to_arrow(expected_point).unwrap(); - - assert_eq!(expected_arrow, value); - - let instance_keys = [ - InstanceKey(17), - InstanceKey(47), - InstanceKey(48), - InstanceKey(99), - InstanceKey(472), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, points).unwrap(); - - let missing_value = component.lookup_arrow(&InstanceKey(46)); - assert_eq!(missing_value, None); - - let value = component.lookup_arrow(&InstanceKey(99)).unwrap(); - - let expected_point = [points[3]]; - let expected_arrow = Position2D::to_arrow(expected_point).unwrap(); - - assert_eq!(expected_arrow, value); - - // Lookups with serialization - - let value = component.lookup::(&InstanceKey(99)).unwrap(); - assert_eq!(expected_point[0], value); - - let missing_value = component.lookup::(&InstanceKey(46)); - assert!(matches!( - missing_value.err().unwrap(), - QueryError::ComponentNotFound(_) - )); - - let missing_value = component.lookup::(&InstanceKey(99)); - assert!(matches!( - missing_value.err().unwrap(), - QueryError::TypeMismatch { .. } - )); -} - -#[test] -fn lookup_splat() { - use re_types::components::{InstanceKey, Position2D}; - let instances = [ - InstanceKey::SPLAT, // - ]; - let points = [ - Position2D::new(1.0, 2.0), // - ]; - - let component = ComponentWithInstances::from_native(instances, points).unwrap(); - - // Any instance we look up will return the slatted value - let value = component.lookup::(&InstanceKey(1)).unwrap(); - assert_eq!(points[0], value); - - let value = component.lookup::(&InstanceKey(99)).unwrap(); - assert_eq!(points[0], value); -} diff --git a/crates/re_query2/src/bin/clamped_zip.rs b/crates/re_query/src/bin/clamped_zip.rs similarity index 99% rename from crates/re_query2/src/bin/clamped_zip.rs rename to crates/re_query/src/bin/clamped_zip.rs index bb4b642f4ac7..571e9b89f27f 100644 --- a/crates/re_query2/src/bin/clamped_zip.rs +++ b/crates/re_query/src/bin/clamped_zip.rs @@ -340,7 +340,7 @@ fn main() { println!( " - // This file was generated using `cargo r -p re_query2 --all-features --bin clamped_zip`. + // This file was generated using `cargo r -p crate --all-features --bin clamped_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query2/src/bin/range_zip.rs b/crates/re_query/src/bin/range_zip.rs similarity index 99% rename from crates/re_query2/src/bin/range_zip.rs rename to crates/re_query/src/bin/range_zip.rs index f4af9aae0276..1a843dd5c215 100644 --- a/crates/re_query2/src/bin/range_zip.rs +++ b/crates/re_query/src/bin/range_zip.rs @@ -486,7 +486,7 @@ fn main() { println!( " - // This file was generated using `cargo r -p re_query2 --all-features --bin range_zip`. + // This file was generated using `cargo r -p crate --all-features --bin range_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query_cache/src/cache.rs b/crates/re_query/src/cache.rs similarity index 100% rename from crates/re_query_cache/src/cache.rs rename to crates/re_query/src/cache.rs diff --git a/crates/re_query_cache/src/cache_stats.rs b/crates/re_query/src/cache_stats.rs similarity index 100% rename from crates/re_query_cache/src/cache_stats.rs rename to crates/re_query/src/cache_stats.rs diff --git a/crates/re_query2/src/clamped_zip/.gitattributes b/crates/re_query/src/clamped_zip/.gitattributes similarity index 100% rename from crates/re_query2/src/clamped_zip/.gitattributes rename to crates/re_query/src/clamped_zip/.gitattributes diff --git a/crates/re_query2/src/clamped_zip/generated.rs b/crates/re_query/src/clamped_zip/generated.rs similarity index 99% rename from crates/re_query2/src/clamped_zip/generated.rs rename to crates/re_query/src/clamped_zip/generated.rs index 7a5c2222b40a..e682a50da861 100644 --- a/crates/re_query2/src/clamped_zip/generated.rs +++ b/crates/re_query/src/clamped_zip/generated.rs @@ -1,4 +1,4 @@ -// This file was generated using `cargo r -p re_query2 --all-features --bin clamped_zip`. +// This file was generated using `cargo r -p crate --all-features --bin clamped_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query2/src/clamped_zip/mod.rs b/crates/re_query/src/clamped_zip/mod.rs similarity index 100% rename from crates/re_query2/src/clamped_zip/mod.rs rename to crates/re_query/src/clamped_zip/mod.rs diff --git a/crates/re_query_cache/src/flat_vec_deque.rs b/crates/re_query/src/flat_vec_deque.rs similarity index 100% rename from crates/re_query_cache/src/flat_vec_deque.rs rename to crates/re_query/src/flat_vec_deque.rs diff --git a/crates/re_query_cache/src/latest_at/helpers.rs b/crates/re_query/src/latest_at/helpers.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/helpers.rs rename to crates/re_query/src/latest_at/helpers.rs index a941fe7b56bd..d850bfc660de 100644 --- a/crates/re_query_cache/src/latest_at/helpers.rs +++ b/crates/re_query/src/latest_at/helpers.rs @@ -3,11 +3,11 @@ use re_log_types::{EntityPath, RowId, TimeInt}; use re_types_core::Component; use re_types_core::{external::arrow2::array::Array, ComponentName}; -use crate::{CachedLatestAtComponentResults, Caches, PromiseResolver, PromiseResult}; +use crate::{Caches, LatestAtComponentResults, PromiseResolver, PromiseResult}; // --- -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { /// Returns the component data as a dense vector. /// /// Logs a warning and returns `None` if the component is missing or cannot be deserialized. @@ -241,12 +241,12 @@ impl CachedLatestAtComponentResults { // --- #[derive(Clone)] -pub struct CachedLatestAtMonoResult { +pub struct LatestAtMonoResult { pub index: (TimeInt, RowId), pub value: C, } -impl CachedLatestAtMonoResult { +impl LatestAtMonoResult { #[inline] pub fn data_time(&self) -> TimeInt { self.index.0 @@ -258,7 +258,7 @@ impl CachedLatestAtMonoResult { } } -impl std::ops::Deref for CachedLatestAtMonoResult { +impl std::ops::Deref for LatestAtMonoResult { type Target = C; #[inline] @@ -287,7 +287,7 @@ impl Caches { entity_path: &EntityPath, query: &LatestAtQuery, level: re_log::Level, - ) -> Option> { + ) -> Option> { re_tracing::profile_function!(); let results = self.latest_at(store, query, entity_path, [C::name()]); @@ -303,7 +303,7 @@ impl Caches { ); None } - PromiseResult::Ready(data) if data.len() == 1 => Some(CachedLatestAtMonoResult { + PromiseResult::Ready(data) if data.len() == 1 => Some(LatestAtMonoResult { index, value: data[0].clone(), }), @@ -343,7 +343,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option> { + ) -> Option> { self.latest_at_component_with_log_level( store, resolver, @@ -368,7 +368,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option> { + ) -> Option> { self.latest_at_component_with_log_level( store, resolver, @@ -385,7 +385,7 @@ impl Caches { resolver: &PromiseResolver, entity_path: &EntityPath, query: &LatestAtQuery, - ) -> Option<(EntityPath, CachedLatestAtMonoResult)> { + ) -> Option<(EntityPath, LatestAtMonoResult)> { re_tracing::profile_function!(); let mut cur_entity_path = Some(entity_path.clone()); diff --git a/crates/re_query/src/latest_at/mod.rs b/crates/re_query/src/latest_at/mod.rs new file mode 100644 index 000000000000..04511f831260 --- /dev/null +++ b/crates/re_query/src/latest_at/mod.rs @@ -0,0 +1,10 @@ +mod helpers; +mod query; +mod results; + +#[cfg(feature = "to_archetype")] +mod to_archetype; + +pub use self::helpers::LatestAtMonoResult; +pub use self::query::LatestAtCache; +pub use self::results::{LatestAtComponentResults, LatestAtResults}; diff --git a/crates/re_query_cache/src/latest_at/query.rs b/crates/re_query/src/latest_at/query.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/query.rs rename to crates/re_query/src/latest_at/query.rs index 825830e9a731..b4ca7cdfe059 100644 --- a/crates/re_query_cache/src/latest_at/query.rs +++ b/crates/re_query/src/latest_at/query.rs @@ -7,18 +7,17 @@ use parking_lot::RwLock; use re_data_store::{DataStore, LatestAtQuery, TimeInt}; use re_log_types::EntityPath; -use re_query2::Promise; use re_types_core::ComponentName; use re_types_core::SizeBytes; -use crate::{CacheKey, CachedLatestAtComponentResults, CachedLatestAtResults, Caches}; +use crate::{CacheKey, Caches, LatestAtComponentResults, LatestAtResults, Promise}; // --- impl Caches { /// Queries for the given `component_names` using latest-at semantics. /// - /// See [`CachedLatestAtResults`] for more information about how to handle the results. + /// See [`LatestAtResults`] for more information about how to handle the results. /// /// This is a cached API -- data will be lazily cached upon access. pub fn latest_at( @@ -27,10 +26,10 @@ impl Caches { query: &LatestAtQuery, entity_path: &EntityPath, component_names: impl IntoIterator, - ) -> CachedLatestAtResults { + ) -> LatestAtResults { re_tracing::profile_function!(entity_path.to_string()); - let mut results = CachedLatestAtResults::default(); + let mut results = LatestAtResults::default(); for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); @@ -65,7 +64,7 @@ pub struct LatestAtCache { /// if there is any data available for the resulting _data_ time in [`Self::per_data_time`]. // // NOTE: `Arc` so we can share buckets across query time & data time. - pub per_query_time: BTreeMap>, + pub per_query_time: BTreeMap>, /// Organized by _data_ time. /// @@ -73,7 +72,7 @@ pub struct LatestAtCache { /// can result in a data time of `T`. // // NOTE: `Arc` so we can share buckets across query time & data time. - pub per_data_time: BTreeMap>, + pub per_data_time: BTreeMap>, /// These timestamps have been invalidated asynchronously. /// @@ -196,7 +195,7 @@ impl LatestAtCache { query: &LatestAtQuery, entity_path: &EntityPath, component_name: ComponentName, - ) -> Option> { + ) -> Option> { re_tracing::profile_scope!("latest_at", format!("{query:?}")); let LatestAtCache { @@ -246,7 +245,7 @@ impl LatestAtCache { return None; }; - let bucket = Arc::new(CachedLatestAtComponentResults { + let bucket = Arc::new(LatestAtComponentResults { index: (data_time, row_id), promise: Some(Promise::new(cell)), cached_dense: Default::default(), diff --git a/crates/re_query_cache/src/latest_at/results.rs b/crates/re_query/src/latest_at/results.rs similarity index 85% rename from crates/re_query_cache/src/latest_at/results.rs rename to crates/re_query/src/latest_at/results.rs index 44691217ac9d..0360a02c1a40 100644 --- a/crates/re_query_cache/src/latest_at/results.rs +++ b/crates/re_query/src/latest_at/results.rs @@ -11,14 +11,14 @@ use crate::{ // --- -/// Cached results for a latest-at query. +/// Results for a latest-at query. /// /// The data is both deserialized and resolved/converted. /// -/// Use [`CachedLatestAtResults::get`], [`CachedLatestAtResults::get_required`] and -/// [`CachedLatestAtResults::get_or_empty`] in order to access the results for each individual component. +/// Use [`LatestAtResults::get`], [`LatestAtResults::get_required`] and +/// [`LatestAtResults::get_or_empty`] in order to access the results for each individual component. #[derive(Debug)] -pub struct CachedLatestAtResults { +pub struct LatestAtResults { /// The compound index of this query result. /// /// A latest-at query is a compound operation that gathers data from many different rows. @@ -27,10 +27,10 @@ pub struct CachedLatestAtResults { pub compound_index: (TimeInt, RowId), /// Results for each individual component. - pub components: IntMap>, + pub components: IntMap>, } -impl Default for CachedLatestAtResults { +impl Default for LatestAtResults { #[inline] fn default() -> Self { Self { @@ -40,31 +40,31 @@ impl Default for CachedLatestAtResults { } } -impl CachedLatestAtResults { +impl LatestAtResults { #[inline] pub fn contains(&self, component_name: impl Into) -> bool { self.components.contains_key(&component_name.into()) } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. #[inline] pub fn get( &self, component_name: impl Into, - ) -> Option<&CachedLatestAtComponentResults> { + ) -> Option<&LatestAtComponentResults> { self.components .get(&component_name.into()) .map(|arc| &**arc) } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] pub fn get_required( &self, component_name: impl Into, - ) -> crate::Result<&CachedLatestAtComponentResults> { + ) -> crate::Result<&LatestAtComponentResults> { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { Ok(component) @@ -73,32 +73,28 @@ impl CachedLatestAtResults { } } - /// Returns the [`CachedLatestAtComponentResults`] for the specified [`Component`]. + /// Returns the [`LatestAtComponentResults`] for the specified [`Component`]. /// /// Returns empty results if the component is not present. #[inline] pub fn get_or_empty( &self, component_name: impl Into, - ) -> &CachedLatestAtComponentResults { + ) -> &LatestAtComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component } else { - static EMPTY: CachedLatestAtComponentResults = CachedLatestAtComponentResults::empty(); + static EMPTY: LatestAtComponentResults = LatestAtComponentResults::empty(); &EMPTY } } } -impl CachedLatestAtResults { +impl LatestAtResults { #[doc(hidden)] #[inline] - pub fn add( - &mut self, - component_name: ComponentName, - cached: Arc, - ) { + pub fn add(&mut self, component_name: ComponentName, cached: Arc) { // NOTE: Since this is a compound API that actually emits multiple queries, the index of the // final result is the most recent index among all of its components, as defined by time // and row-id order. @@ -119,7 +115,7 @@ impl CachedLatestAtResults { // --- /// Lazily cached results for a particular component when using a cached latest-at query. -pub struct CachedLatestAtComponentResults { +pub struct LatestAtComponentResults { pub(crate) index: (TimeInt, RowId), // Option so we can have a constant default value for `Self`. @@ -129,7 +125,7 @@ pub struct CachedLatestAtComponentResults { pub(crate) cached_dense: OnceLock>, } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { #[inline] pub const fn empty() -> Self { Self { @@ -170,7 +166,7 @@ impl CachedLatestAtComponentResults { } } -impl SizeBytes for CachedLatestAtComponentResults { +impl SizeBytes for LatestAtComponentResults { #[inline] fn heap_size_bytes(&self) -> u64 { let Self { @@ -187,7 +183,7 @@ impl SizeBytes for CachedLatestAtComponentResults { } } -impl std::fmt::Debug for CachedLatestAtComponentResults { +impl std::fmt::Debug for LatestAtComponentResults { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { index, @@ -204,7 +200,7 @@ impl std::fmt::Debug for CachedLatestAtComponentResults { } } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { #[inline] pub fn index(&self) -> &(TimeInt, RowId) { &self.index @@ -257,7 +253,7 @@ impl CachedLatestAtComponentResults { } } -impl CachedLatestAtComponentResults { +impl LatestAtComponentResults { fn downcast_dense(&self, cell: &DataCell) -> crate::Result<&[C]> { // `OnceLock::get` is non-blocking -- this is a best-effort fast path in case the // data has already been computed. diff --git a/crates/re_query_cache/src/latest_at/to_archetype/.gitattributes b/crates/re_query/src/latest_at/to_archetype/.gitattributes similarity index 100% rename from crates/re_query_cache/src/latest_at/to_archetype/.gitattributes rename to crates/re_query/src/latest_at/to_archetype/.gitattributes diff --git a/crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs rename to crates/re_query/src/latest_at/to_archetype/annotation_context.rs index 53d7683b3ce8..8afa32ea8561 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/annotation_context.rs +++ b/crates/re_query/src/latest_at/to_archetype/annotation_context.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs rename to crates/re_query/src/latest_at/to_archetype/arrows2d.rs index f040190bd594..5adc4153fe65 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/arrows2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/arrows2d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs rename to crates/re_query/src/latest_at/to_archetype/arrows3d.rs index 4a2a0eb34032..fe4bd99f06c5 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/arrows3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/arrows3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs b/crates/re_query/src/latest_at/to_archetype/asset3d.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs rename to crates/re_query/src/latest_at/to_archetype/asset3d.rs index be8c7893f790..03931257d1ce 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/asset3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/asset3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/background.rs b/crates/re_query/src/latest_at/to_archetype/background.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/background.rs rename to crates/re_query/src/latest_at/to_archetype/background.rs index 2494ac25b0e9..319228ffb294 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/background.rs +++ b/crates/re_query/src/latest_at/to_archetype/background.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs similarity index 93% rename from crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs rename to crates/re_query/src/latest_at/to_archetype/bar_chart.rs index 5e291449999b..7a71bf148d3d 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/bar_chart.rs +++ b/crates/re_query/src/latest_at/to_archetype/bar_chart.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs rename to crates/re_query/src/latest_at/to_archetype/boxes2d.rs index 84559fa17b0f..dd6aeb26070f 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/boxes2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/boxes2d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs rename to crates/re_query/src/latest_at/to_archetype/boxes3d.rs index bc9736f831be..c0790e887012 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/boxes3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/boxes3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/clear.rs b/crates/re_query/src/latest_at/to_archetype/clear.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/clear.rs rename to crates/re_query/src/latest_at/to_archetype/clear.rs index a71abd061fc4..6d4c8f01e4b3 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/clear.rs +++ b/crates/re_query/src/latest_at/to_archetype/clear.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs similarity index 98% rename from crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/container_blueprint.rs index 2e89b1ff2d1d..d6db455e1e7f 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/container_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/container_blueprint.rs @@ -5,13 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs b/crates/re_query/src/latest_at/to_archetype/depth_image.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs rename to crates/re_query/src/latest_at/to_archetype/depth_image.rs index b0a610bc151b..802da9f44971 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/depth_image.rs +++ b/crates/re_query/src/latest_at/to_archetype/depth_image.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs rename to crates/re_query/src/latest_at/to_archetype/disconnected_space.rs index 21bdfadbbc2a..e409fcd63194 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/disconnected_space.rs +++ b/crates/re_query/src/latest_at/to_archetype/disconnected_space.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/image.rs b/crates/re_query/src/latest_at/to_archetype/image.rs similarity index 93% rename from crates/re_query_cache/src/latest_at/to_archetype/image.rs rename to crates/re_query/src/latest_at/to_archetype/image.rs index f5d8ea7d7c6f..ddf966610409 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/image.rs +++ b/crates/re_query/src/latest_at/to_archetype/image.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs rename to crates/re_query/src/latest_at/to_archetype/line_strips2d.rs index ab6216861a69..b51624b9ab28 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/line_strips2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/line_strips2d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs rename to crates/re_query/src/latest_at/to_archetype/line_strips3d.rs index 0954bf35bb5f..a11a49c0eebd 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/line_strips3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/line_strips3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs rename to crates/re_query/src/latest_at/to_archetype/mesh3d.rs index 0b2462e1eb1a..04c3b330042e 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/mesh3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/mesh3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/mod.rs b/crates/re_query/src/latest_at/to_archetype/mod.rs similarity index 100% rename from crates/re_query_cache/src/latest_at/to_archetype/mod.rs rename to crates/re_query/src/latest_at/to_archetype/mod.rs diff --git a/crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs similarity index 93% rename from crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs index 307555ffaa4b..acf76c2788dd 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/panel_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/panel_blueprint.rs @@ -5,13 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs b/crates/re_query/src/latest_at/to_archetype/pinhole.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs rename to crates/re_query/src/latest_at/to_archetype/pinhole.rs index b192479b28d8..34419beb7435 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/pinhole.rs +++ b/crates/re_query/src/latest_at/to_archetype/pinhole.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs rename to crates/re_query/src/latest_at/to_archetype/plot_legend.rs index 241ec44a6840..b5d466095cc1 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/plot_legend.rs +++ b/crates/re_query/src/latest_at/to_archetype/plot_legend.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/points2d.rs b/crates/re_query/src/latest_at/to_archetype/points2d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/points2d.rs rename to crates/re_query/src/latest_at/to_archetype/points2d.rs index ba928c21f306..9fd2be9a01f1 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/points2d.rs +++ b/crates/re_query/src/latest_at/to_archetype/points2d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/points3d.rs b/crates/re_query/src/latest_at/to_archetype/points3d.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/points3d.rs rename to crates/re_query/src/latest_at/to_archetype/points3d.rs index f6802a051736..2525c7ca81bf 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/points3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/points3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/scalar.rs b/crates/re_query/src/latest_at/to_archetype/scalar.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/scalar.rs rename to crates/re_query/src/latest_at/to_archetype/scalar.rs index b14c08327799..3f715f0bba97 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/scalar.rs +++ b/crates/re_query/src/latest_at/to_archetype/scalar.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs rename to crates/re_query/src/latest_at/to_archetype/scalar_axis.rs index 8a7fe1107ad0..67e59fff4a5e 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/scalar_axis.rs +++ b/crates/re_query/src/latest_at/to_archetype/scalar_axis.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs rename to crates/re_query/src/latest_at/to_archetype/segmentation_image.rs index 15cf8e991355..203ca4f697b3 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/segmentation_image.rs +++ b/crates/re_query/src/latest_at/to_archetype/segmentation_image.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/series_line.rs b/crates/re_query/src/latest_at/to_archetype/series_line.rs similarity index 93% rename from crates/re_query_cache/src/latest_at/to_archetype/series_line.rs rename to crates/re_query/src/latest_at/to_archetype/series_line.rs index eae0d8411532..88895798d555 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/series_line.rs +++ b/crates/re_query/src/latest_at/to_archetype/series_line.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/series_point.rs b/crates/re_query/src/latest_at/to_archetype/series_point.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/series_point.rs rename to crates/re_query/src/latest_at/to_archetype/series_point.rs index 4487e290958a..273aca5ac53a 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/series_point.rs +++ b/crates/re_query/src/latest_at/to_archetype/series_point.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs similarity index 96% rename from crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs index 9449705381c6..f4e94c1a4c16 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/space_view_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/space_view_blueprint.rs @@ -5,14 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype - for CachedLatestAtResults -{ +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs rename to crates/re_query/src/latest_at/to_archetype/space_view_contents.rs index 3fa4e0035f65..b35439f90369 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/space_view_contents.rs +++ b/crates/re_query/src/latest_at/to_archetype/space_view_contents.rs @@ -5,14 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype - for CachedLatestAtResults -{ +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/tensor.rs b/crates/re_query/src/latest_at/to_archetype/tensor.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/tensor.rs rename to crates/re_query/src/latest_at/to_archetype/tensor.rs index d275be94b2b4..2b72bef07906 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/tensor.rs +++ b/crates/re_query/src/latest_at/to_archetype/tensor.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/text_document.rs b/crates/re_query/src/latest_at/to_archetype/text_document.rs similarity index 95% rename from crates/re_query_cache/src/latest_at/to_archetype/text_document.rs rename to crates/re_query/src/latest_at/to_archetype/text_document.rs index 25c97086443e..9d4061fff7a9 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/text_document.rs +++ b/crates/re_query/src/latest_at/to_archetype/text_document.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/text_log.rs b/crates/re_query/src/latest_at/to_archetype/text_log.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/text_log.rs rename to crates/re_query/src/latest_at/to_archetype/text_log.rs index 90bff49a5628..4cddf9829b23 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/text_log.rs +++ b/crates/re_query/src/latest_at/to_archetype/text_log.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs b/crates/re_query/src/latest_at/to_archetype/transform3d.rs similarity index 91% rename from crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs rename to crates/re_query/src/latest_at/to_archetype/transform3d.rs index 05abe63d9a59..7f7a1d96a383 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/transform3d.rs +++ b/crates/re_query/src/latest_at/to_archetype/transform3d.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs similarity index 94% rename from crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs rename to crates/re_query/src/latest_at/to_archetype/view_coordinates.rs index db3ad868c8ac..2abff463bb7f 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/view_coordinates.rs +++ b/crates/re_query/src/latest_at/to_archetype/view_coordinates.rs @@ -5,12 +5,11 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; -impl crate::ToArchetype for CachedLatestAtResults { +impl crate::ToArchetype for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs similarity index 97% rename from crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs rename to crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs index 3ba2039dcc99..e5c19cca9fac 100644 --- a/crates/re_query_cache/src/latest_at/to_archetype/viewport_blueprint.rs +++ b/crates/re_query/src/latest_at/to_archetype/viewport_blueprint.rs @@ -5,13 +5,12 @@ #![allow(clippy::clone_on_copy)] #![allow(clippy::cloned_instead_of_copied)] -use crate::CachedLatestAtResults; -use re_query2::{PromiseResolver, PromiseResult}; +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; use std::sync::Arc; impl crate::ToArchetype - for CachedLatestAtResults + for LatestAtResults { #[inline] fn to_archetype( diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs index b888c376abec..d75b866986dd 100644 --- a/crates/re_query/src/lib.rs +++ b/crates/re_query/src/lib.rs @@ -1,20 +1,35 @@ -//! Provide query-centric access to the [`re_data_store`]. +//! Caching datastructures for `re_query`. -mod archetype_view; -mod query; +mod cache; +mod cache_stats; +mod flat_vec_deque; +mod latest_at; +mod promise; mod range; -mod util; - -pub use self::archetype_view::{ArchetypeView, ComponentWithInstances}; -pub use self::query::{get_component_with_instances, query_archetype}; -pub use self::range::{range_archetype, range_component_set}; -pub use self::util::{ - query_archetype_with_history, ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary, -}; +mod visible_history; + +pub mod clamped_zip; +pub mod range_zip; + +pub use self::cache::{CacheKey, Caches}; +pub use self::cache_stats::{CachedComponentStats, CachesStats}; +pub use self::clamped_zip::*; +pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; +pub use self::latest_at::{LatestAtComponentResults, LatestAtMonoResult, LatestAtResults}; +pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; +pub use self::range::{RangeComponentResults, RangeData, RangeResults}; +pub use self::range_zip::*; +pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; + +pub(crate) use self::latest_at::LatestAtCache; +pub(crate) use self::range::{RangeCache, RangeComponentResultsInner}; + +pub mod external { + pub use paste; + pub use seq_macro; +} -// Used for doc-tests -#[doc(hidden)] -pub use self::query::__populate_example_store; +// --- #[derive(Debug, Clone, Copy)] pub struct ComponentNotFoundError(pub re_types_core::ComponentName); @@ -58,6 +73,47 @@ pub enum QueryError { #[error("Not implemented")] NotImplemented, + + #[error(transparent)] + Other(#[from] anyhow::Error), } pub type Result = std::result::Result; + +// --- + +/// Helper extension trait to convert query results into [`re_types_core::Archetype`]s. +pub trait ToArchetype { + /// Converts the result into an [`re_types_core::Archetype`]. + /// + /// Automatically handles all aspects of the query process: deserialization, caching, promise + /// resolution, etc. + fn to_archetype( + &self, + resolver: &crate::PromiseResolver, + ) -> crate::PromiseResult>; +} + +// --- + +use re_data_store::{LatestAtQuery, RangeQuery}; + +#[derive(Debug)] +pub enum Results { + LatestAt(LatestAtQuery, LatestAtResults), + Range(RangeQuery, RangeResults), +} + +impl From<(LatestAtQuery, LatestAtResults)> for Results { + #[inline] + fn from((query, results): (LatestAtQuery, LatestAtResults)) -> Self { + Self::LatestAt(query, results) + } +} + +impl From<(RangeQuery, RangeResults)> for Results { + #[inline] + fn from((query, results): (RangeQuery, RangeResults)) -> Self { + Self::Range(query, results) + } +} diff --git a/crates/re_query2/src/promise.rs b/crates/re_query/src/promise.rs similarity index 100% rename from crates/re_query2/src/promise.rs rename to crates/re_query/src/promise.rs diff --git a/crates/re_query/src/query.rs b/crates/re_query/src/query.rs deleted file mode 100644 index 2580ff33c31f..000000000000 --- a/crates/re_query/src/query.rs +++ /dev/null @@ -1,269 +0,0 @@ -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{EntityPath, RowId, TimeInt}; -use re_types_core::{components::InstanceKey, Archetype, ComponentName, Loggable}; - -use crate::{ArchetypeView, ComponentWithInstances, QueryError}; - -/// Retrieves a [`ComponentWithInstances`] from the [`DataStore`]. -/// -/// Returns `None` if the component is not found. -/// -/// ``` -/// # use re_data_store::LatestAtQuery; -/// # use re_log_types::{Timeline, TimeInt, example_components::{MyColor, MyPoint}}; -/// # use re_types_core::Loggable as _; -/// # let store = re_query::__populate_example_store(); -/// -/// let ent_path = "point"; -/// let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), TimeInt::new_temporal(123)); -/// -/// let (_, _, component) = re_query::get_component_with_instances( -/// &store, -/// &query, -/// &ent_path.into(), -/// MyPoint::name(), -/// ) -/// .unwrap(); -/// -/// //println!("{component}"); -/// ``` -/// -/// Outputs: -/// ```text -/// ┌─────────────┬───────────┐ -/// │ InstanceKey ┆ MyPoint │ -/// │ --- ┆ --- │ -/// │ u64 ┆ struct[2] │ -/// ╞═════════════╪═══════════╡ -/// │ 42 ┆ {1.0,2.0} │ -/// ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ -/// │ 96 ┆ {3.0,4.0} │ -/// └─────────────┴───────────┘ -/// ``` -pub fn get_component_with_instances( - store: &DataStore, - query: &LatestAtQuery, - ent_path: &EntityPath, - component: ComponentName, -) -> Option<(TimeInt, RowId, ComponentWithInstances)> { - debug_assert_eq!(store.cluster_key(), InstanceKey::name()); - - let components = [InstanceKey::name(), component]; - - let (data_time, row_id, mut cells) = - store.latest_at(query, ent_path, component, &components)?; - - Some(( - data_time, - row_id, - ComponentWithInstances { - // NOTE: The unwrap cannot fail, the cluster key's presence is guaranteed - // by the store. - instance_keys: cells[0].take().unwrap(), - values: cells[1].take()?, - }, - )) -} - -/// Retrieve an [`ArchetypeView`] from the `DataStore`, as well as the associated _data_ time of -/// its _most recent component_. -/// -/// If you expect only one instance (e.g. for mono-components like `Transform` `Tensor`] -/// and have no additional components you can use `Caches::latest_at_component` instead. -/// -/// ``` -/// # use re_data_store::LatestAtQuery; -/// # use re_log_types::{Timeline, TimeInt, example_components::{MyColor, MyPoint, MyPoints}}; -/// # use re_types_core::Component; -/// # let store = re_query::__populate_example_store(); -/// -/// let ent_path = "point"; -/// let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), TimeInt::new_temporal(123)); -/// -/// let arch_view = re_query::query_archetype::( -/// &store, -/// &query, -/// &ent_path.into(), -/// ) -/// .unwrap(); -/// -/// //println!("{arch_view:?}"); -/// ``` -/// -/// Outputs: -/// ```text -/// ┌────────────────────┬───────────────┬─────────────────┐ -/// │ InstanceKey ┆ MyPoint ┆ MyColor │ -/// │ --- ┆ --- ┆ --- │ -/// │ u64 ┆ struct[2] ┆ u32 │ -/// ╞════════════════════╪═══════════════╪═════════════════╡ -/// │ 42 ┆ {1.0,2.0} ┆ null │ -/// │ 96 ┆ {3.0,4.0} ┆ 4278190080 │ -/// └────────────────────┴───────────────┴─────────────────┘ -/// ``` -pub fn query_archetype( - store: &DataStore, - query: &LatestAtQuery, - ent_path: &EntityPath, -) -> crate::Result> { - // Profiling this can be useful, but we have many queries of very small archetypes, adding a lot of profiling overhead. - //re_tracing::profile_function!(); - - let required_components: Vec<_> = A::required_components() - .iter() - .map(|component| get_component_with_instances(store, query, ent_path, *component)) - .collect(); - - // NOTE: It's important to use `PrimaryNotFound` here. Any other error will be - // reported to the user. - // - // `query_archetype` is currently run for every archetype on every path in the view - // each path that's missing the primary is then ignored rather than being visited. - for (name, c) in itertools::izip!(A::required_components().iter(), &required_components) { - if c.is_none() { - return crate::Result::Err(QueryError::PrimaryNotFound(*name)); - } - } - - use itertools::Itertools as _; - let (data_times, row_ids, required_components): (Vec<_>, Vec<_>, Vec<_>) = - required_components.into_iter().flatten().multiunzip(); - - // NOTE: Since this is a compound API that actually emits multiple queries, the data time of the - // final result is the most recent data time among all of its components. - let mut max_data_time = data_times.iter().max().copied().unwrap_or(TimeInt::STATIC); - let row_id = row_ids.first().unwrap_or(&RowId::ZERO); - - let recommended_components = A::recommended_components(); - let optional_components = A::optional_components(); - - let other_components = recommended_components - .iter() - .chain(optional_components.iter()) - .filter_map(|component| { - get_component_with_instances(store, query, ent_path, *component).map( - |(data_time, _, component_result)| { - max_data_time = TimeInt::max(max_data_time, data_time); - component_result - }, - ) - }); - - // NOTE: Need to collect so we can compute `max_data_time`. - let cwis: Vec<_> = required_components - .into_iter() - .chain(other_components) - .collect(); - let arch_view = ArchetypeView::from_components(max_data_time, *row_id, cwis); - - Ok(arch_view) -} - -/// Helper used to create an example store we can use for querying in doctests -pub fn __populate_example_store() -> DataStore { - use re_log_types::example_components::{MyColor, MyPoint}; - use re_log_types::{build_frame_nr, DataRow}; - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let instances = vec![InstanceKey(42), InstanceKey(96)]; - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - instances.len() as _, - (&instances, &positions), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - let instances = vec![InstanceKey(96)]; - let colors = vec![MyColor::from(0xff000000)]; - - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - instances.len() as _, - (instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - store -} - -// Minimal test matching the doctest for `get_component_with_instances` -#[test] -fn simple_get_component() { - use smallvec::smallvec; - - use re_data_store::LatestAtQuery; - use re_log_types::{example_components::MyPoint, DataCellRow}; - use re_log_types::{DataCell, Timeline}; - - let store = __populate_example_store(); - - let ent_path = "point"; - let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), 123); - - let (_, _, component) = - get_component_with_instances(&store, &query, &ent_path.into(), MyPoint::name()).unwrap(); - - { - let row = component.into_data_cell_row(); - eprintln!("{row:?}"); - - let instances = vec![Some(InstanceKey(42)), Some(InstanceKey(96))]; - let positions = vec![Some(MyPoint::new(1.0, 2.0)), Some(MyPoint::new(3.0, 4.0))]; - - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - ]); - - assert_eq!(row, expected); - } -} - -// Minimal test matching the doctest for `query_entity_with_primary` -#[test] -fn simple_query_archetype() { - use re_data_store::LatestAtQuery; - use re_log_types::example_components::{MyColor, MyPoint, MyPoints}; - use re_log_types::Timeline; - - let store = __populate_example_store(); - - let ent_path = "point"; - let query = LatestAtQuery::new(Timeline::new_sequence("frame_nr"), 123); - - let arch_view = query_archetype::(&store, &query, &ent_path.into()).unwrap(); - - let expected_positions = [MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = [None, Some(MyColor::from(0xff000000))]; - - let view_positions: Vec<_> = arch_view - .iter_required_component::() - .unwrap() - .collect(); - - let view_colors: Vec<_> = arch_view - .iter_optional_component::() - .unwrap() - .collect(); - - assert_eq!(expected_positions, view_positions.as_slice()); - assert_eq!(expected_colors, view_colors.as_slice()); - - eprintln!("{arch_view:?}"); -} diff --git a/crates/re_query/src/range.rs b/crates/re_query/src/range.rs deleted file mode 100644 index 2e55fca35571..000000000000 --- a/crates/re_query/src/range.rs +++ /dev/null @@ -1,170 +0,0 @@ -use itertools::Itertools as _; -use re_data_store::{DataStore, LatestAtQuery, RangeQuery}; -use re_log_types::{EntityPath, TimeInt}; -use re_types_core::{Archetype, ComponentName}; - -use crate::{get_component_with_instances, ArchetypeView, ComponentWithInstances}; - -// --- - -/// Iterates over the rows of any number of components and their respective cluster keys, all from -/// the point-of-view of the required components, returning an iterator of [`ArchetypeView`]s. -/// -/// The iterator only ever yields entity-views iff a required component has changed: a change -/// affecting only optional components will not yield an entity-view. -/// However, the changes in those secondary components will be accumulated into the next yielded -/// entity-view. -/// -/// This is a streaming-join: every yielded [`ArchetypeView`] will be the result of joining the latest -/// known state of all components, from their respective point-of-views. -/// -/// ⚠ The semantics are subtle! See `examples/range.rs` for an example of use. -pub fn range_archetype<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - query: &RangeQuery, - ent_path: &'a EntityPath, -) -> impl Iterator> + 'a { - re_tracing::profile_function!(); - - // TODO(jleibs) this shim is super gross - let povs: [ComponentName; 1] = A::required_components().into_owned().try_into().unwrap(); - let components: [ComponentName; N] = A::all_components().into_owned().try_into().unwrap(); - - range_component_set::(store, query, ent_path, &povs, components) -} - -/// Iterates over the rows of any number of components and their respective cluster keys, all from -/// the point-of-view of the `povs` components, returning an iterator of [`ArchetypeView`]s. -/// -/// The iterator only ever yields entity-views iff a point-of-view component has changed: a change -/// affecting only optional components will not yield an entity-view. -/// However, the changes in those secondary components will be accumulated into the next yielded -/// entity-view. -/// -/// This is a streaming-join: every yielded [`ArchetypeView`] will be the result of joining the latest -/// known state of all components, from their respective point-of-views. -/// -/// ⚠ The semantics are subtle! See `examples/range.rs` for an example of use. -pub fn range_component_set<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - query: &RangeQuery, - ent_path: &'a EntityPath, - povs: &[ComponentName], - components: [ComponentName; N], -) -> impl Iterator> + 'a { - re_tracing::profile_function!(); - - let primary: ComponentName = povs[0]; - let cluster_key = store.cluster_key(); - - // TODO(cmc): Ideally, we'd want to simply add the cluster and primary key to the `components` - // array if they are missing, yielding either `[ComponentName; N+1]` or `[ComponentName; N+2]`. - // Unfortunately this is not supported on stable at the moment, and requires - // feature(generic_const_exprs) on nightly. - // - // The alternative to these assertions (and thus putting the burden on the caller), for now, - // would be to drop the constant sizes all the way down, which would be way more painful to - // deal with. - assert!(components.contains(&cluster_key), "{components:?}"); - assert!(components.contains(&primary), "{components:?}"); - - let cluster_col = components - .iter() - .find_position(|component| **component == cluster_key) - .map(|(col, _)| col) - .unwrap(); // asserted on entry - let primary_col = components - .iter() - .find_position(|component| **component == primary) - .map(|(col, _)| col) - .unwrap(); // asserted on entry - - let mut state: Vec<_> = std::iter::repeat_with(|| None) - .take(components.len()) - .collect(); - - // NOTE: This will return none for `TimeInt::Min`, i.e. range queries that start infinitely far - // into the past don't have a latest-at state! - let query_time = TimeInt::try_from(query.range.min().as_i64().saturating_sub(1)).ok(); - - let mut cwis_latest = None; - if let Some(query_time) = query_time { - let mut cwis_latest_raw: Vec<_> = std::iter::repeat_with(|| None) - .take(components.len()) - .collect(); - - // Fetch the latest data for every single component from their respective point-of-views, - // this will allow us to build up the initial state and send an initial latest-at - // entity-view if needed. - for (i, primary) in components.iter().enumerate() { - cwis_latest_raw[i] = get_component_with_instances( - store, - &LatestAtQuery::new(query.timeline, query_time), - ent_path, - *primary, - ) - .map(|(_, row_id, cwi)| (row_id, cwi)); - } - - cwis_latest = Some(cwis_latest_raw); - } - - // send the latest-at state before anything else - cwis_latest - .into_iter() - // NOTE: `false` here means we will _not_ yield the latest-at state as an actual - // ArchetypeView! - // That is a very important detail: for overlapping range queries to be correct in a - // multi-tenant cache context, we need to make sure to inherit the latest-at state - // from T-1, while also making sure to _not_ yield the view that comes with that state. - // - // Consider e.g. what happens when one system queries for `range(10, 20)` while another - // queries for `range(9, 20)`: the data at timestamp `10` would differ because of the - // statefulness of range queries! - .map(move |cwis| (query_time.unwrap_or(TimeInt::STATIC), false, cwis)) - .chain(store.range(query, ent_path, components).map( - move |(data_time, row_id, mut cells)| { - // NOTE: The unwrap cannot fail, the cluster key's presence is guaranteed - // by the store. - let instance_keys = cells[cluster_col].take().unwrap(); - let is_primary = cells[primary_col].is_some(); - let cwis = cells - .into_iter() - .map(|cell| { - cell.map(|cell| { - ( - row_id, - ComponentWithInstances { - instance_keys: instance_keys.clone(), /* shallow */ - values: cell, - }, - ) - }) - }) - .collect::>(); - (data_time, is_primary, cwis) - }, - )) - .filter_map(move |(data_time, is_primary, cwis)| { - for (i, cwi) in cwis - .into_iter() - .enumerate() - .filter(|(_, cwi)| cwi.is_some()) - { - state[i] = cwi; - } - - // We only yield if the primary component has been updated! - is_primary.then(|| { - let (row_id, _) = state[primary_col].clone().unwrap(); // shallow - - let components: Vec<_> = state - .clone() - .into_iter() - .filter_map(|cwi| cwi.map(|(_, cwi)| cwi)) - .collect(); - - ArchetypeView::from_components(data_time, row_id, components) - }) - }) -} diff --git a/crates/re_query/src/range/mod.rs b/crates/re_query/src/range/mod.rs new file mode 100644 index 000000000000..f11e2033ff8f --- /dev/null +++ b/crates/re_query/src/range/mod.rs @@ -0,0 +1,7 @@ +mod query; +mod results; + +pub use self::query::RangeCache; +pub use self::results::{ + RangeComponentResults, RangeComponentResultsInner, RangeData, RangeResults, +}; diff --git a/crates/re_query_cache/src/range/query.rs b/crates/re_query/src/range/query.rs similarity index 96% rename from crates/re_query_cache/src/range/query.rs rename to crates/re_query/src/range/query.rs index f04664b96c25..649aa7ef8700 100644 --- a/crates/re_query_cache/src/range/query.rs +++ b/crates/re_query/src/range/query.rs @@ -8,8 +8,7 @@ use re_types_core::ComponentName; use re_types_core::SizeBytes; use crate::{ - CacheKey, CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeResults, - Caches, Promise, + CacheKey, Caches, Promise, RangeComponentResults, RangeComponentResultsInner, RangeResults, }; // --- @@ -17,7 +16,7 @@ use crate::{ impl Caches { /// Queries for the given `component_names` using range semantics. /// - /// See [`CachedRangeResults`] for more information about how to handle the results. + /// See [`RangeResults`] for more information about how to handle the results. /// /// This is a cached API -- data will be lazily cached upon access. pub fn range( @@ -26,10 +25,10 @@ impl Caches { query: &RangeQuery, entity_path: &EntityPath, component_names: impl IntoIterator, - ) -> CachedRangeResults { + ) -> RangeResults { re_tracing::profile_function!(entity_path.to_string()); - let mut results = CachedRangeResults::new(query.clone()); + let mut results = RangeResults::new(query.clone()); for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); @@ -61,7 +60,7 @@ pub struct RangeCache { /// All temporal data, organized by _data_ time. /// /// Query time is irrelevant for range queries. - pub per_data_time: CachedRangeComponentResults, + pub per_data_time: RangeComponentResults, /// Everything greater than or equal to this timestamp has been asynchronously invalidated. /// @@ -78,7 +77,7 @@ impl RangeCache { pub fn new(cache_key: CacheKey) -> Self { Self { cache_key, - per_data_time: CachedRangeComponentResults::default(), + per_data_time: RangeComponentResults::default(), pending_invalidation: None, } } @@ -149,7 +148,7 @@ impl RangeCache { query: &RangeQuery, entity_path: &EntityPath, component_name: ComponentName, - ) -> CachedRangeComponentResults { + ) -> RangeComponentResults { re_tracing::profile_scope!("range", format!("{query:?}")); let RangeCache { @@ -232,7 +231,7 @@ impl RangeCache { // --- -impl CachedRangeComponentResultsInner { +impl RangeComponentResultsInner { /// How many _indices_ across this entire cache? #[inline] pub fn num_indices(&self) -> u64 { diff --git a/crates/re_query_cache/src/range/results.rs b/crates/re_query/src/range/results.rs similarity index 92% rename from crates/re_query_cache/src/range/results.rs rename to crates/re_query/src/range/results.rs index 5f9bc83e6255..cff3abcceabc 100644 --- a/crates/re_query_cache/src/range/results.rs +++ b/crates/re_query/src/range/results.rs @@ -13,25 +13,25 @@ use re_log_types::{RowId, TimeInt, TimeRange}; use re_types_core::{Component, ComponentName, DeserializationError, SizeBytes}; use crate::{ - CachedLatestAtComponentResults, ErasedFlatVecDeque, FlatVecDeque, Promise, PromiseResolver, + ErasedFlatVecDeque, FlatVecDeque, LatestAtComponentResults, Promise, PromiseResolver, PromiseResult, }; // --- -/// Cached results for a range query. +/// Results for a range query. /// /// The data is both deserialized and resolved/converted. /// -/// Use [`CachedRangeResults::get`], [`CachedRangeResults::get_required`] and -/// [`CachedRangeResults::get_or_empty`] in order to access the results for each individual component. +/// Use [`RangeResults::get`], [`RangeResults::get_required`] and +/// [`RangeResults::get_or_empty`] in order to access the results for each individual component. #[derive(Debug)] -pub struct CachedRangeResults { +pub struct RangeResults { pub query: RangeQuery, - pub components: IntMap, + pub components: IntMap, } -impl CachedRangeResults { +impl RangeResults { #[inline] pub(crate) fn new(query: RangeQuery) -> Self { Self { @@ -45,23 +45,20 @@ impl CachedRangeResults { self.components.contains_key(&component_name.into()) } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. #[inline] - pub fn get( - &self, - component_name: impl Into, - ) -> Option<&CachedRangeComponentResults> { + pub fn get(&self, component_name: impl Into) -> Option<&RangeComponentResults> { self.components.get(&component_name.into()) } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. /// /// Returns an error if the component is not present. #[inline] pub fn get_required( &self, component_name: impl Into, - ) -> crate::Result<&CachedRangeComponentResults> { + ) -> crate::Result<&RangeComponentResults> { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { Ok(component) @@ -74,27 +71,24 @@ impl CachedRangeResults { } } - /// Returns the [`CachedRangeComponentResults`] for the specified [`Component`]. + /// Returns the [`RangeComponentResults`] for the specified [`Component`]. /// /// Returns empty results if the component is not present. #[inline] - pub fn get_or_empty( - &self, - component_name: impl Into, - ) -> &CachedRangeComponentResults { + pub fn get_or_empty(&self, component_name: impl Into) -> &RangeComponentResults { let component_name = component_name.into(); if let Some(component) = self.components.get(&component_name) { component } else { - CachedRangeComponentResults::empty() + RangeComponentResults::empty() } } } -impl CachedRangeResults { +impl RangeResults { #[doc(hidden)] #[inline] - pub fn add(&mut self, component_name: ComponentName, cached: CachedRangeComponentResults) { + pub fn add(&mut self, component_name: ComponentName, cached: RangeComponentResults) { self.components.insert(component_name, cached); } } @@ -111,17 +105,17 @@ thread_local! { /// Lazily cached results for a particular component when using a cached range query. #[derive(Debug)] -pub struct CachedRangeComponentResults { +pub struct RangeComponentResults { /// The [`TimeRange`] of the query that was used in order to retrieve these results in the /// first place. /// /// The "original" copy in the cache just stores [`TimeRange::EMPTY`]. It's meaningless. pub(crate) time_range: TimeRange, - pub(crate) inner: Arc>, + pub(crate) inner: Arc>, } -impl CachedRangeComponentResults { +impl RangeComponentResults { /// Clones the results while making sure to stamp them with the [`TimeRange`] of the associated query. #[inline] pub(crate) fn clone_at(&self, time_range: TimeRange) -> Self { @@ -132,15 +126,15 @@ impl CachedRangeComponentResults { } } -impl CachedRangeComponentResults { +impl RangeComponentResults { #[inline] pub fn empty() -> &'static Self { - static EMPTY: OnceLock = OnceLock::new(); - EMPTY.get_or_init(CachedRangeComponentResults::default) + static EMPTY: OnceLock = OnceLock::new(); + EMPTY.get_or_init(RangeComponentResults::default) } } -impl re_types_core::SizeBytes for CachedRangeComponentResults { +impl re_types_core::SizeBytes for RangeComponentResults { #[inline] fn heap_size_bytes(&self) -> u64 { // NOTE: it's all on the heap past this point. @@ -148,18 +142,18 @@ impl re_types_core::SizeBytes for CachedRangeComponentResults { } } -impl Default for CachedRangeComponentResults { +impl Default for RangeComponentResults { #[inline] fn default() -> Self { Self { time_range: TimeRange::EMPTY, - inner: Arc::new(RwLock::new(CachedRangeComponentResultsInner::empty())), + inner: Arc::new(RwLock::new(RangeComponentResultsInner::empty())), } } } -impl std::ops::Deref for CachedRangeComponentResults { - type Target = RwLock; +impl std::ops::Deref for RangeComponentResults { + type Target = RwLock; #[inline] fn deref(&self) -> &Self::Target { @@ -208,7 +202,7 @@ impl<'a, T: 'static> std::ops::Deref for Data<'a, T> { } } -pub struct CachedRangeData<'a, T> { +pub struct RangeData<'a, T> { // NOTE: Options so we can represent an empty result without having to somehow conjure a mutex // guard out of thin air. // @@ -230,14 +224,14 @@ pub struct CachedRangeData<'a, T> { reentering: &'static std::thread::LocalKey>, } -impl<'a, C: Component> CachedRangeData<'a, C> { +impl<'a, C: Component> RangeData<'a, C> { /// Useful to abstract over latest-at and ranged results. #[inline] pub fn from_latest_at( resolver: &PromiseResolver, - results: &'a CachedLatestAtComponentResults, + results: &'a LatestAtComponentResults, ) -> Self { - let CachedLatestAtComponentResults { + let LatestAtComponentResults { index, promise: _, cached_dense, @@ -256,7 +250,7 @@ impl<'a, C: Component> CachedRangeData<'a, C> { } } -impl<'a, T> Drop for CachedRangeData<'a, T> { +impl<'a, T> Drop for RangeData<'a, T> { #[inline] fn drop(&mut self) { self.reentering @@ -264,7 +258,7 @@ impl<'a, T> Drop for CachedRangeData<'a, T> { } } -impl<'a, T: 'static> CachedRangeData<'a, T> { +impl<'a, T: 'static> RangeData<'a, T> { /// Returns the current status on both ends of the range. /// /// E.g. it is possible that the front-side of the range is still waiting for pending data while @@ -343,7 +337,7 @@ impl<'a, T: 'static> CachedRangeData<'a, T> { } } -impl CachedRangeComponentResults { +impl RangeComponentResults { /// Returns the component data as a dense vector. /// /// Returns an error if the component is missing or cannot be deserialized. @@ -351,7 +345,7 @@ impl CachedRangeComponentResults { /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of /// deserializing the data into a single one, if you don't need the extra flexibility. #[inline] - pub fn to_dense(&self, resolver: &PromiseResolver) -> CachedRangeData<'_, C> { + pub fn to_dense(&self, resolver: &PromiseResolver) -> RangeData<'_, C> { // It's tracing the deserialization of an entire range query at once -- it's fine. re_tracing::profile_function!(); @@ -361,7 +355,7 @@ impl CachedRangeComponentResults { // Manufactured empty result. if self.time_range == TimeRange::EMPTY { - return CachedRangeData { + return RangeData { indices: None, data: None, time_range: TimeRange::EMPTY, @@ -584,7 +578,7 @@ impl CachedRangeComponentResults { .unwrap() }); - CachedRangeData { + RangeData { indices: Some(Indices::Cached(indices)), data: Some(Data::Cached(data)), time_range: self.time_range, @@ -598,7 +592,7 @@ impl CachedRangeComponentResults { // --- /// Lazily cached results for a particular component when using a cached range query. -pub struct CachedRangeComponentResultsInner { +pub struct RangeComponentResultsInner { pub(crate) indices: VecDeque<(TimeInt, RowId)>, /// All the pending promises that must resolved in order to fill the missing data on the @@ -626,7 +620,7 @@ pub struct CachedRangeComponentResultsInner { pub(crate) cached_dense: Option>, } -impl SizeBytes for CachedRangeComponentResultsInner { +impl SizeBytes for RangeComponentResultsInner { #[inline] fn heap_size_bytes(&self) -> u64 { let Self { @@ -647,7 +641,7 @@ impl SizeBytes for CachedRangeComponentResultsInner { } } -impl std::fmt::Debug for CachedRangeComponentResultsInner { +impl std::fmt::Debug for RangeComponentResultsInner { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { indices, @@ -676,7 +670,7 @@ impl std::fmt::Debug for CachedRangeComponentResultsInner { } } -impl CachedRangeComponentResultsInner { +impl RangeComponentResultsInner { #[inline] pub const fn empty() -> Self { Self { diff --git a/crates/re_query2/src/range_zip/.gitattributes b/crates/re_query/src/range_zip/.gitattributes similarity index 100% rename from crates/re_query2/src/range_zip/.gitattributes rename to crates/re_query/src/range_zip/.gitattributes diff --git a/crates/re_query2/src/range_zip/generated.rs b/crates/re_query/src/range_zip/generated.rs similarity index 99% rename from crates/re_query2/src/range_zip/generated.rs rename to crates/re_query/src/range_zip/generated.rs index c916479d39f2..2b575176b198 100644 --- a/crates/re_query2/src/range_zip/generated.rs +++ b/crates/re_query/src/range_zip/generated.rs @@ -1,4 +1,4 @@ -// This file was generated using `cargo r -p re_query2 --all-features --bin range_zip`. +// This file was generated using `cargo r -p crate --all-features --bin range_zip`. // DO NOT EDIT. // --- diff --git a/crates/re_query2/src/range_zip/mod.rs b/crates/re_query/src/range_zip/mod.rs similarity index 100% rename from crates/re_query2/src/range_zip/mod.rs rename to crates/re_query/src/range_zip/mod.rs diff --git a/crates/re_query/src/util.rs b/crates/re_query/src/util.rs deleted file mode 100644 index 42831caa9bb5..000000000000 --- a/crates/re_query/src/util.rs +++ /dev/null @@ -1,143 +0,0 @@ -use re_data_store::{DataStore, LatestAtQuery, RangeQuery, TimeInt, TimeRange, Timeline}; -use re_log_types::EntityPath; -use re_types_core::Archetype; - -use crate::{query_archetype, range::range_archetype, ArchetypeView}; - -// --- - -/// One of the boundaries of the visible history. -/// -/// For [`VisibleHistoryBoundary::RelativeToTimeCursor`] and [`VisibleHistoryBoundary::Absolute`], -/// the value are either nanos or frames, depending on the type of timeline. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum VisibleHistoryBoundary { - /// Boundary is a value relative to the time cursor - RelativeToTimeCursor(i64), - - /// Boundary is an absolute value - Absolute(i64), - - /// The boundary extends to infinity. - Infinite, -} - -impl VisibleHistoryBoundary { - /// Value when the boundary is set to the current time cursor. - pub const AT_CURSOR: Self = Self::RelativeToTimeCursor(0); -} - -impl Default for VisibleHistoryBoundary { - fn default() -> Self { - Self::AT_CURSOR - } -} - -/// Visible history bounds. -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -pub struct VisibleHistory { - /// Low time boundary. - pub from: VisibleHistoryBoundary, - - /// High time boundary. - pub to: VisibleHistoryBoundary, -} - -impl VisibleHistory { - /// Value with the visible history feature is disabled. - pub const OFF: Self = Self { - from: VisibleHistoryBoundary::AT_CURSOR, - to: VisibleHistoryBoundary::AT_CURSOR, - }; - - pub const ALL: Self = Self { - from: VisibleHistoryBoundary::Infinite, - to: VisibleHistoryBoundary::Infinite, - }; - - /// Returns the start boundary of the time range given an input cursor position. - /// - /// This is not guaranteed to be lesser than or equal to [`Self::to`]. - /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. - #[doc(hidden)] - pub fn range_start_from_cursor(&self, cursor: TimeInt) -> TimeInt { - match self.from { - VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { - cursor + TimeInt::new_temporal(value) - } - VisibleHistoryBoundary::Infinite => TimeInt::MIN, - } - } - - /// Returns the end boundary of the time range given an input cursor position. - /// - /// This is not guaranteed to be greater than [`Self::from`]. - /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. - #[doc(hidden)] - pub fn range_end_from_cursor(&self, cursor: TimeInt) -> TimeInt { - match self.to { - VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { - cursor + TimeInt::new_temporal(value) - } - VisibleHistoryBoundary::Infinite => TimeInt::MAX, - } - } - - /// Returns a _sanitized_ [`TimeRange`], i.e. guaranteed to be monotonically increasing. - pub fn time_range(&self, cursor: TimeInt) -> TimeRange { - let mut from = self.range_start_from_cursor(cursor); - let mut to = self.range_end_from_cursor(cursor); - - // TODO(#4993): visible time range UI can yield inverted ranges - if from > to { - std::mem::swap(&mut from, &mut to); - } - - TimeRange::new(from, to) - } -} - -/// When showing an entity in the history view, add this much history to it. -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -pub struct ExtraQueryHistory { - /// Is the feature enabled? - pub enabled: bool, - - /// Visible history settings for time timelines - pub nanos: VisibleHistory, - - /// Visible history settings for frame timelines - pub sequences: VisibleHistory, -} - -// --- - -pub fn query_archetype_with_history<'a, A: Archetype + 'a, const N: usize>( - store: &'a DataStore, - timeline: &'a Timeline, - time: &'a TimeInt, - history: &ExtraQueryHistory, - ent_path: &'a EntityPath, -) -> crate::Result> + 'a> { - let visible_history = match timeline.typ() { - re_log_types::TimeType::Time => history.nanos, - re_log_types::TimeType::Sequence => history.sequences, - }; - - let time_range = visible_history.time_range(*time); - - if !history.enabled || time_range.min() == time_range.max() { - let latest_query = LatestAtQuery::new(*timeline, time_range.min()); - let latest = query_archetype::(store, &latest_query, ent_path)?; - - Ok(itertools::Either::Left(std::iter::once(latest))) - } else { - let range_query = RangeQuery::new(*timeline, time_range); - - let range = range_archetype::(store, &range_query, ent_path); - - Ok(itertools::Either::Right(range)) - } -} diff --git a/crates/re_query2/src/visible_history.rs b/crates/re_query/src/visible_history.rs similarity index 100% rename from crates/re_query2/src/visible_history.rs rename to crates/re_query/src/visible_history.rs diff --git a/crates/re_query/tests/archetype_query_tests.rs b/crates/re_query/tests/archetype_query_tests.rs deleted file mode 100644 index 6160aa593a40..000000000000 --- a/crates/re_query/tests/archetype_query_tests.rs +++ /dev/null @@ -1,336 +0,0 @@ -use smallvec::smallvec; - -use re_data_store::DataStore; -use re_log_types::{build_frame_nr, DataCell, DataCellRow, DataRow, RowId, TimePoint}; -use re_query::query_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, -}; -use re_types_core::Loggable as _; - -#[test] -fn simple_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬─────────────┬────────────┐ - // │ instance ┆ positions2D ┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═════════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴─────────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![None, Some(Color::from_rgb(255, 0, 0))]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn static_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance.. statically! - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![None, Some(Color::from_rgb(255, 0, 0))]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn no_instance_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign them colors with explicit instances - let colors = vec![Color::from_rgb(255, 0, 0), Color::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, colors).unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 16711680 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(255, 0, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} - -#[test] -fn missing_column_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // - // ┌──────────┬───────────┐ - // │ instance ┆ Position2D │ - // │ --- ┆ --- │ - // │ u64 ┆ struct[2] │ - // ╞══════════╪═══════════╡ - // │ 0 ┆ {1.0,2.0} │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} │ - // └──────────┴───────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_1::().unwrap(), - &expected - ); - } -} - -#[test] -fn splatted_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let ent_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), ent_path, timepoint, 2, positions).unwrap(); - store.insert_row(&row).unwrap(); - - // Assign all of them a color via splat - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - ent_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Retrieve the view - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - - let arch_view = query_archetype::(&store, &timeline_query, &ent_path.into()).unwrap(); - - // We expect this to generate the following `DataFrame` - // ┌──────────┬───────────┬────────────┐ - // │ instance ┆ Position2D┆ colorrgba │ - // │ --- ┆ --- ┆ --- │ - // │ u64 ┆ struct[2] ┆ u32 │ - // ╞══════════╪═══════════╪════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ 4278190080 │ - // └──────────┴───────────┴────────────┘ - - { - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(255, 0, 0)), - Some(Color::from_rgb(255, 0, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{df:?}"); - //eprintln!("{expected:?}"); - - assert_eq!( - &arch_view.to_data_cell_row_2::().unwrap(), - &expected - ); - } -} diff --git a/crates/re_query/tests/archetype_range_tests.rs b/crates/re_query/tests/archetype_range_tests.rs deleted file mode 100644 index 29c0f56b4754..000000000000 --- a/crates/re_query/tests/archetype_range_tests.rs +++ /dev/null @@ -1,675 +0,0 @@ -use smallvec::smallvec; - -use re_data_store::{DataStore, TimeInt, TimeRange}; -use re_log_types::{build_frame_nr, DataCell, DataCellRow, DataRow, EntityPath, RowId, TimePoint}; -use re_query::range_archetype; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, -}; -use re_types_core::Loggable as _; - -#[test] -fn simple_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌─────────────┬──────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞═════════════╪══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ null │ - // └─────────────┴──────────────┴─────────────────┘ - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - - { - // Frame #123 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors: Vec> = vec![None, None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} - -#[test] -fn static_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let mut row = - DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - row.compute_all_size_bytes(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances.clone(), colors.clone()), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances.clone(), colors.clone()), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Insert statically too! - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // ┌───────────┬──────────┬────────┬─────────────────┬────────────────────┬────────────────────┬────────────────────────────┐ - // │ insert_id ┆ frame_nr ┆ entity ┆ Color ┆ InstanceKey ┆ rerun.row_id ┆ Point2D │ - // ╞═══════════╪══════════╪════════╪═════════════════╪════════════════════╪════════════════════╪════════════════════════════╡ - // │ 4 ┆ null ┆ point ┆ [4278190080] ┆ [1] ┆ [{167328063302246… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ 123 ┆ point ┆ null ┆ [0, 1] ┆ [{167328063302236… ┆ [{1.0,2.0}, {3.0,4.0}] │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 3 ┆ 123 ┆ point ┆ [4278190080] ┆ [1] ┆ [{167328063302245… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 5 ┆ 223 ┆ point ┆ [4278190080] ┆ [0] ┆ [{167328063302247… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 6 ┆ 223 ┆ point ┆ [4278190080] ┆ [0] ┆ [{167328063302248… ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 7 ┆ 323 ┆ point ┆ null ┆ [0, 1] ┆ [{167328063302248… ┆ [{10.0,20.0}, {30.0,40.0}] │ - // └───────────┴──────────┴────────┴─────────────────┴────────────────────┴────────────────────┴────────────────────────────┘ - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #123 (partially static) - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - { - // Frame #123 (partially static) - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - // eprintln!("{arch_view:#?}"); - // eprintln!("{expected:#?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![Some(Color::from_rgb(255, 0, 0)), None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} - -#[test] -fn simple_splatted_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with a splatted instance - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![Color::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances, colors), - ) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![Position2D::new(10.0, 20.0), Position2D::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - store.insert_row(&row).unwrap(); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 16711680 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ 16711680 │ - // └────────────────────┴───────────────┴─────────────────┘ - - assert_eq!(results.len(), 1); - - { - // Frame #323 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(0, 255, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - - let df = arch_view.to_data_cell_row_2::().unwrap(); - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!(&expected, &df); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let arch_views = - range_archetype::(&store, &query, &entity_path); - - let results = arch_views.collect::>(); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {3.0,4.0} ┆ null │ - // └────────────────────┴───────────────┴─────────────────┘ - // - // Frame #323: - // ┌────────────────────┬───────────────┬─────────────────┐ - // │ InstanceKey ┆ Point2D ┆ Color │ - // ╞════════════════════╪═══════════════╪═════════════════╡ - // │ 0 ┆ {10.0,20.0} ┆ 16711680 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 1 ┆ {30.0,40.0} ┆ 16711680 │ - // └────────────────────┴───────────────┴─────────────────┘ - - { - // Frame #123 - - let arch_view = &results[0]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(1.0, 2.0)), - Some(Position2D::new(3.0, 4.0)), - ]; - let colors: Vec> = vec![None, None]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(123), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } - { - // Frame #323 - - let arch_view = &results[1]; - let time = arch_view.data_time(); - - // Build expected df manually - let instances = vec![Some(InstanceKey(0)), Some(InstanceKey(1))]; - let positions = vec![ - Some(Position2D::new(10.0, 20.0)), - Some(Position2D::new(30.0, 40.0)), - ]; - let colors = vec![ - Some(Color::from_rgb(0, 255, 0)), - Some(Color::from_rgb(0, 255, 0)), - ]; - let expected = DataCellRow(smallvec![ - DataCell::from_native_sparse(instances), - DataCell::from_native_sparse(positions), - DataCell::from_native_sparse(colors) - ]); - - //eprintln!("{expected:?}"); - - assert_eq!(TimeInt::new_temporal(323), time); - assert_eq!( - &expected, - &arch_view.to_data_cell_row_2::().unwrap(), - ); - } -} diff --git a/crates/re_query/tests/archetype_visit_tests.rs b/crates/re_query/tests/archetype_visit_tests.rs deleted file mode 100644 index b2cb5660f992..000000000000 --- a/crates/re_query/tests/archetype_visit_tests.rs +++ /dev/null @@ -1,392 +0,0 @@ -use itertools::Itertools; -use re_log_types::{RowId, TimeInt}; -use re_query::{ArchetypeView, ComponentWithInstances}; -use re_types::archetypes::Points2D; -use re_types::components::{Color, InstanceKey, Position2D}; - -#[test] -fn basic_single_iter() { - let instance_keys = InstanceKey::from_iter(0..2); - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - ]; - - let component = ComponentWithInstances::from_native(instance_keys, positions).unwrap(); - - let results = itertools::izip!( - positions.into_iter(), - component.values::().unwrap() - ) - .collect_vec(); - assert_eq!(results.len(), 2); - results - .iter() - .for_each(|(a, b)| assert_eq!(a, b.as_ref().unwrap())); -} - -#[test] -fn directly_joined_iter() { - let instance_keys = InstanceKey::from_iter(0..3); - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let colors = [ - Color::from(0), // - Color::from(1), - Color::from(2), - ]; - - let positions_comp = - ComponentWithInstances::from_native(instance_keys.clone(), positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(instance_keys, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - Some(Color::from(0)), - Some(Color::from(1)), - Some(Color::from(2)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn joined_iter_dense_primary() { - let point_ids = InstanceKey::from_iter(0..3); - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let color_ids = [ - InstanceKey(1), // - InstanceKey(2), - ]; - - let colors = [ - Color::from(1), // - Color::from(2), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [None, Some(Color::from(1)), Some(Color::from(2))]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn joined_iter_dense_secondary() { - let point_ids = [ - InstanceKey(0), // - InstanceKey(2), - InstanceKey(4), - ]; - - let positions = [ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - ]; - - let color_ids = InstanceKey::from_iter(0..5); - - let colors = [ - Color::from(0), // - Color::from(1), - Color::from(2), - Color::from(3), - Color::from(4), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - Some(Color::from(0)), // - Some(Color::from(2)), - Some(Color::from(4)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn complex_joined_iter() { - let point_ids = vec![ - InstanceKey(0), // - InstanceKey(17), - InstanceKey(42), - InstanceKey(96), - ]; - - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - ]; - - let color_ids = vec![ - InstanceKey(17), // - InstanceKey(19), - InstanceKey(44), - InstanceKey(96), - InstanceKey(254), - ]; - - let colors = vec![ - Color::from(17), // - Color::from(19), - Color::from(44), - Color::from(96), - Color::from(254), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let expected_colors = [ - None, - Some(Color::from(17)), // - None, - Some(Color::from(96)), - ]; - - let results = itertools::izip!( - expected_colors.iter(), - arch_view.iter_optional_component::().unwrap() - ) - .collect_vec(); - - assert_eq!(expected_colors.len(), results.len()); - results.iter().for_each(|(a, b)| assert_eq!(*a, b)); -} - -#[test] -fn single_visit() { - let instance_keys = InstanceKey::from_iter(0..4); - let positions = [ - Position2D::new(1.0, 2.0), - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - ]; - - let positions_comp = - ComponentWithInstances::from_native(instance_keys.clone(), positions).unwrap(); - - let arch_view = - ArchetypeView::::from_components(TimeInt::STATIC, RowId::ZERO, [positions_comp]); - - let mut instance_key_out = Vec::::new(); - let mut positions_out = Vec::::new(); - - itertools::izip!( - arch_view.iter_instance_keys(), - arch_view.iter_required_component::().unwrap() - ) - .for_each(|(inst, point)| { - instance_key_out.push(inst); - positions_out.push(point); - }); - - assert_eq!(instance_key_out, instance_keys); - assert_eq!(positions.as_slice(), positions_out.as_slice()); -} - -#[test] -fn joint_visit() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let point_ids = InstanceKey::from_iter(0..5); - - let colors = vec![ - Color::from(0xff000000), // - Color::from(0x00ff0000), - ]; - - let color_ids = vec![ - InstanceKey(2), // - InstanceKey(4), - ]; - - let positions_comp = ComponentWithInstances::from_native(point_ids, positions.clone()).unwrap(); - let colors_comp = ComponentWithInstances::from_native(color_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let mut positions_out = Vec::::new(); - let mut colors_out = Vec::>::new(); - - itertools::izip!( - arch_view.iter_required_component::().unwrap(), - arch_view.iter_optional_component::().unwrap() - ) - .for_each(|(point, color)| { - positions_out.push(point); - colors_out.push(color); - }); - - let expected_colors = vec![ - None, - None, - Some(Color::from(0xff000000)), - None, - Some(Color::from(0x00ff0000)), - ]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} - -#[test] -fn joint_visit_with_empty() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let shared_ids = InstanceKey::from_iter(0..5); - - let colors: Vec = vec![]; - - let positions_comp = - ComponentWithInstances::from_native(shared_ids.clone(), positions.clone()).unwrap(); - let colors_comp = ComponentWithInstances::from_native(shared_ids, colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let positions_out = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let colors_out = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - assert_eq!(positions_out.len(), colors_out.len()); - - let expected_colors = vec![None, None, None, None, None]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} - -#[test] -fn joint_visit_with_splat() { - let positions = vec![ - Position2D::new(1.0, 2.0), // - Position2D::new(3.0, 4.0), - Position2D::new(5.0, 6.0), - Position2D::new(7.0, 8.0), - Position2D::new(9.0, 10.0), - ]; - - let shared_ids = InstanceKey::from_iter(0..5); - - let color = Color::from(0xff000000); - let colors: Vec = vec![color]; - - let positions_comp = - ComponentWithInstances::from_native(shared_ids, positions.clone()).unwrap(); - // TODO(#1893): Replace the instance_keys with shared_ids. - let colors_comp = - ComponentWithInstances::from_native(vec![InstanceKey::SPLAT], colors).unwrap(); - - let arch_view = ArchetypeView::::from_components( - TimeInt::STATIC, - RowId::ZERO, - [positions_comp, colors_comp], - ); - - let positions_out = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let colors_out = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - assert_eq!(positions_out.len(), colors_out.len()); - - let expected_colors = vec![ - Some(color), - Some(color), - Some(color), - Some(color), - Some(color), - ]; - - assert_eq!(positions, positions_out); - assert_eq!(expected_colors, colors_out); -} diff --git a/crates/re_query/tests/latest_at.rs b/crates/re_query/tests/latest_at.rs new file mode 100644 index 000000000000..b5df7aca1826 --- /dev/null +++ b/crates/re_query/tests/latest_at.rs @@ -0,0 +1,589 @@ +use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; +use re_log_types::{ + build_frame_nr, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimeInt, TimePoint, +}; +use re_query::Caches; +use re_query::PromiseResolver; +use re_types::Archetype as _; +use re_types_core::{components::InstanceKey, Loggable as _}; + +// --- + +#[test] +fn simple_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let expected_compound_index = (TimeInt::new_temporal(123), row.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn static_query() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "point"; + let timepoint = [build_frame_nr(123)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + TimePoint::default(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); + let expected_compound_index = (TimeInt::new_temporal(123), row1.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation() { + let entity_path = "point"; + + let test_invalidation = |query: LatestAtQuery, + present_data_timepoint: TimePoint, + past_data_timepoint: TimePoint, + future_data_timepoint: TimePoint| { + let past_timestamp = past_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let present_timestamp = present_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors = vec![MyColor::from_rgb(1, 2, 3)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_compound_index = (present_timestamp, row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify present --- + + // Modify the PoV component + let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_compound_index = (present_timestamp, row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; + let row4 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_compound_index = (present_timestamp, row4.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify past --- + + // Modify the PoV component + let points_past = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; + let row5 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + points_past.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row5); + + let expected_compound_index = (present_timestamp, row4.row_id()); + let expected_points = if past_timestamp.is_static() { + &points_past + } else { + &points + }; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors_past = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; + let row6 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint, + 2, + colors_past.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row6); + + let (expected_compound_index, expected_colors) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &colors_past) + } else { + ((present_timestamp, row4.row_id()), &colors) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // --- Modify future --- + + // Modify the PoV component + let points_future = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; + let row7 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint.clone(), + 2, + points_future.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row7); + + let (expected_compound_index, expected_points) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &points_past) + } else { + ((present_timestamp, row4.row_id()), &points) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors_future = vec![MyColor::from_rgb(16, 17, 18)]; + let row = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint, + 1, + colors_future, + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row); + + let (expected_compound_index, expected_colors) = if past_timestamp.is_static() { + ((past_timestamp, row6.row_id()), &colors_past) + } else { + ((present_timestamp, row4.row_id()), &colors) + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + }; + + let static_ = TimePoint::default(); + let frame_122 = build_frame_nr(122); + let frame_123 = build_frame_nr(123); + let frame_124 = build_frame_nr(124); + + test_invalidation( + LatestAtQuery::new(frame_123.0, frame_123.1), + [frame_123].into(), + [frame_122].into(), + [frame_124].into(), + ); + + test_invalidation( + LatestAtQuery::new(frame_123.0, frame_123.1), + [frame_123].into(), + static_, + [frame_124].into(), + ); +} + +// Test the following scenario: +// ```py +// rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// +// # Do first query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[] +// +// rr.set_time(2) +// rr.log_components("points", rr.components.MyColor(0xFF0000)) +// +// # Do second query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0xFF0000] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x0000FF)) +// +// # Do third query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x0000FF] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x00FF00)) +// +// # Do fourth query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x00FF00] +// ``` +#[test] +fn invalidation_of_future_optionals() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let static_ = TimePoint::default(); + let frame2 = [build_frame_nr(2)]; + let frame3 = [build_frame_nr(3)]; + + let query_time = [build_frame_nr(9999)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = + DataRow::from_cells1_sized(RowId::new(), entity_path, static_, 2, points.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row1.row_id()); + let expected_points = &points; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(2), row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(3), row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 255, 0)]; + let row4 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::new_temporal(3), row4.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +#[test] +fn static_invalidation() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + + let query_time = [build_frame_nr(9999)]; + + let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 2, + points.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row1.row_id()); + let expected_points = &points; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 1, + colors.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row2.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); + + let colors = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); + let expected_compound_index = (TimeInt::STATIC, row3.row_id()); + let expected_points = &points; + let expected_colors = &colors; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_compound_index, + expected_points, + expected_colors, + ); +} + +// --- + +fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { + caches.on_events(&[store.insert_row(row).unwrap()]); +} + +fn query_and_compare( + caches: &Caches, + store: &DataStore, + query: &LatestAtQuery, + entity_path: &EntityPath, + expected_compound_index: (TimeInt, RowId), + expected_points: &[MyPoint], + expected_colors: &[MyColor], +) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + + for _ in 0..3 { + let cached = caches.latest_at( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_points = cached.get_required(MyPoint::name()).unwrap(); + let cached_points = cached_points + .to_dense::(&resolver) + .flatten() + .unwrap(); + + let cached_colors = cached.get_or_empty(MyColor::name()); + let cached_colors = cached_colors + .to_dense::(&resolver) + .flatten() + .unwrap(); + + // eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!(expected_compound_index, cached.compound_index); + similar_asserts::assert_eq!(expected_points, cached_points); + similar_asserts::assert_eq!(expected_colors, cached_colors); + } +} diff --git a/crates/re_query/tests/range.rs b/crates/re_query/tests/range.rs new file mode 100644 index 000000000000..615e48005d29 --- /dev/null +++ b/crates/re_query/tests/range.rs @@ -0,0 +1,852 @@ +use itertools::Itertools as _; + +use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; +use re_log_types::{ + build_frame_nr, + example_components::{MyColor, MyPoint, MyPoints}, + DataRow, EntityPath, RowId, TimePoint, +}; +use re_query::{Caches, PromiseResolver, PromiseResult}; +use re_types::{components::InstanceKey, Archetype}; +use re_types_core::Loggable as _; + +// --- + +#[test] +fn simple_range() -> anyhow::Result<()> { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 2, + points1.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row1_1); + let colors1 = vec![MyColor::from_rgb(255, 0, 0)]; + let row1_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 1, + colors1.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row1_2); + + let timepoint2 = [build_frame_nr(223)]; + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint2, + 1, + colors2.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row2); + + let timepoint3 = [build_frame_nr(323)]; + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint3, + 2, + points3.clone(), + )?; + insert_and_react(&mut store, &mut caches, &row3); + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ( + (TimeInt::new_temporal(223), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Second test: `[timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(123), row1_1.row_id()), + points1.as_slice(), + ), // + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ( + (TimeInt::new_temporal(123), row1_2.row_id()), + colors1.as_slice(), + ), // + ( + (TimeInt::new_temporal(223), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + Ok(()) +} + +#[test] +fn static_range() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path: EntityPath = "point".into(); + + let timepoint1 = [build_frame_nr(123)]; + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_1); + let colors1 = vec![MyColor::from_rgb(255, 0, 0)]; + let row1_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint1, + 1, + colors1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_2); + // Insert statically too! + let row1_3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1_3); + + let timepoint2 = [build_frame_nr(223)]; + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2_1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint2, + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2_1); + // Insert statically too! + let row2_2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + TimePoint::default(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2_2); + + let timepoint3 = [build_frame_nr(323)]; + // Create some Positions with implicit instances + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path.clone(), + timepoint3, + 2, + points3.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + // --- First test: `(timepoint1, timepoint3]` --- + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ((TimeInt::STATIC, row2_2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Second test: `[timepoint1, timepoint3]` --- + + // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! + + let query = re_data_store::RangeQuery::new( + timepoint1[0].0, + TimeRange::new(timepoint1[0].1, timepoint3[0].1), + ); + + let expected_points = &[ + ( + (TimeInt::new_temporal(123), row1_1.row_id()), + points1.as_slice(), + ), // + ( + (TimeInt::new_temporal(323), row3.row_id()), + points3.as_slice(), + ), // + ]; + let expected_colors = &[ + ((TimeInt::STATIC, row2_2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); + + // --- Third test: `[-inf, +inf]` --- + + let query = + re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); + + // same expectations + query_and_compare( + &caches, + &store, + &query, + &entity_path, + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation() { + let entity_path = "point"; + + let test_invalidation = |query: RangeQuery, + present_data_timepoint: TimePoint, + past_data_timepoint: TimePoint, + future_data_timepoint: TimePoint| { + let past_timestamp = past_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let present_timestamp = present_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + let future_timestamp = future_data_timepoint + .get(&query.timeline()) + .copied() + .unwrap_or(TimeInt::STATIC); + + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let colors2 = vec![MyColor::from_rgb(1, 2, 3)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify present --- + + // Modify the PoV component + let points3 = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; + let row3 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint.clone(), + 2, + points3.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors4 = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; + let row4 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + present_data_timepoint, + 2, + colors4.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_points = &[ + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ]; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify past --- + + // Modify the PoV component + let points5 = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; + let row5 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + points5.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row5); + + let expected_points1 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ] as &[_]; + let expected_points2 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ] as &[_]; + let expected_points = if past_data_timepoint.is_static() { + expected_points1 + } else { + expected_points2 + }; + let expected_colors = &[ + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors6 = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; + let row6 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + past_data_timepoint.clone(), + 2, + colors6.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row6); + + let expected_colors1 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ] as &[_]; + let expected_colors2 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ] as &[_]; + let expected_colors = if past_data_timepoint.is_static() { + expected_colors1 + } else { + expected_colors2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // --- Modify future --- + + // Modify the PoV component + let points7 = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; + let row7 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint.clone(), + 2, + points7.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row7); + + let expected_points1 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ] as &[_]; + let expected_points2 = &[ + ((past_timestamp, row5.row_id()), points5.as_slice()), // + ((present_timestamp, row1.row_id()), points1.as_slice()), // + ((present_timestamp, row3.row_id()), points3.as_slice()), // + ((future_timestamp, row7.row_id()), points7.as_slice()), // + ] as &[_]; + let expected_points = if past_data_timepoint.is_static() { + expected_points1 + } else { + expected_points2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + // Modify the optional component + let colors8 = vec![MyColor::from_rgb(16, 17, 18)]; + let row8 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + future_data_timepoint, + 1, + colors8.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row8); + + let expected_colors1 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ] as &[_]; + let expected_colors2 = &[ + ((past_timestamp, row6.row_id()), colors6.as_slice()), // + ((present_timestamp, row2.row_id()), colors2.as_slice()), // + ((present_timestamp, row4.row_id()), colors4.as_slice()), // + ((future_timestamp, row8.row_id()), colors8.as_slice()), // + ] as &[_]; + let expected_colors = if past_data_timepoint.is_static() { + expected_colors1 + } else { + expected_colors2 + }; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + }; + + let timeless = TimePoint::default(); + let frame_122 = build_frame_nr(122); + let frame_123 = build_frame_nr(123); + let frame_124 = build_frame_nr(124); + + test_invalidation( + RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), + [frame_123].into(), + [frame_122].into(), + [frame_124].into(), + ); + + test_invalidation( + RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), + [frame_123].into(), + timeless, + [frame_124].into(), + ); +} + +// Test the following scenario: +// ```py +// rr.log("points", rr.Points3D([1, 2, 3]), static=True) +// +// # Do first query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[] +// +// rr.set_time(2) +// rr.log_components("points", rr.components.MyColor(0xFF0000)) +// +// # Do second query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0xFF0000] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x0000FF)) +// +// # Do third query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x0000FF] +// +// rr.set_time(3) +// rr.log_components("points", rr.components.MyColor(0x00FF00)) +// +// # Do fourth query here: LatestAt(+inf) +// # Expected: points=[[1,2,3]] colors=[0x00FF00] +// ``` +#[test] +fn invalidation_of_future_optionals() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + let frame2 = [build_frame_nr(2)]; + let frame3 = [build_frame_nr(3)]; + + let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, points1.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let expected_points = &[ + ((TimeInt::STATIC, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors2.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors3 = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors3.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row3.row_id()), + colors3.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors4 = vec![MyColor::from_rgb(0, 255, 0)]; + let row4 = + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors4.clone()).unwrap(); + insert_and_react(&mut store, &mut caches, &row4); + + let expected_colors = &[ + ( + (TimeInt::new_temporal(2), row2.row_id()), + colors2.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row3.row_id()), + colors3.as_slice(), + ), // + ( + (TimeInt::new_temporal(3), row4.row_id()), + colors4.as_slice(), + ), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); +} + +#[test] +fn invalidation_static() { + let mut store = DataStore::new( + re_log_types::StoreId::random(re_log_types::StoreKind::Recording), + InstanceKey::name(), + Default::default(), + ); + let mut caches = Caches::new(&store); + + let entity_path = "points"; + + let timeless = TimePoint::default(); + + let frame0 = [build_frame_nr(TimeInt::ZERO)]; + let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); + + let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; + let row1 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 2, + points1.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row1); + + let expected_points = &[ + ((TimeInt::STATIC, row1.row_id()), points1.as_slice()), // + ]; + let expected_colors = &[]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; + let row2 = DataRow::from_cells1_sized( + RowId::new(), + entity_path, + timeless.clone(), + 1, + colors2.clone(), + ) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row2); + + let expected_colors = &[ + ((TimeInt::STATIC, row2.row_id()), colors2.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); + + let colors3 = vec![MyColor::from_rgb(0, 0, 255)]; + let row3 = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors3.clone()) + .unwrap(); + insert_and_react(&mut store, &mut caches, &row3); + + let expected_colors = &[ + ((TimeInt::STATIC, row3.row_id()), colors3.as_slice()), // + ]; + query_and_compare( + &caches, + &store, + &query, + &entity_path.into(), + expected_points, + expected_colors, + ); +} + +// --- + +fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { + caches.on_events(&[store.insert_row(row).unwrap()]); +} + +fn query_and_compare( + caches: &Caches, + store: &DataStore, + query: &RangeQuery, + entity_path: &EntityPath, + expected_all_points_indexed: &[((TimeInt, RowId), &[MyPoint])], + expected_all_colors_indexed: &[((TimeInt, RowId), &[MyColor])], +) { + re_log::setup_logging(); + + let resolver = PromiseResolver::default(); + + for _ in 0..3 { + let cached = caches.range( + store, + query, + entity_path, + MyPoints::all_components().iter().copied(), + ); + + let cached_all_points = cached + .get_required(MyPoint::name()) + .unwrap() + .to_dense::(&resolver); + assert!(matches!( + cached_all_points.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_points_indexed = cached_all_points.range_indexed(); + + let cached_all_colors = cached + .get_or_empty(MyColor::name()) + .to_dense::(&resolver); + assert!(matches!( + cached_all_colors.status(), + (PromiseResult::Ready(()), PromiseResult::Ready(())), + )); + let cached_all_colors_indexed = cached_all_colors.range_indexed(); + + // eprintln!("{query:?}"); + // eprintln!("{}", store.to_data_table().unwrap()); + + similar_asserts::assert_eq!( + expected_all_points_indexed, + cached_all_points_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + ); + + similar_asserts::assert_eq!( + expected_all_colors_indexed, + cached_all_colors_indexed + .map(|(index, data)| (*index, data)) + .collect_vec(), + ); + } +} diff --git a/crates/re_query/tests/store.rs b/crates/re_query/tests/store.rs deleted file mode 100644 index 6f6e87488211..000000000000 --- a/crates/re_query/tests/store.rs +++ /dev/null @@ -1,73 +0,0 @@ -use itertools::Itertools; - -use re_data_store::{test_row, DataStore}; -use re_log_types::EntityPath; -use re_log_types::{build_frame_nr, TimeInt, TimeType, Timeline}; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D}, - datagen::{build_some_colors, build_some_positions2d}, -}; -use re_types_core::Loggable as _; - -// --- - -// This one demonstrates a nasty edge case when stream-joining multiple iterators that happen to -// share the same exact row of data at some point (because, for that specific entry, it turns out -// that those component where inserted together). -// -// When that happens, one must be very careful to not only compare time and index row numbers, but -// also make sure that, if all else if equal, the primary iterator comes last so that it gathers as -// much state as possible! - -#[test] -fn range_join_across_single_row() { - for config in re_data_store::test_util::all_configs() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - config.clone(), - ); - range_join_across_single_row_impl(&mut store); - } -} - -fn range_join_across_single_row_impl(store: &mut DataStore) { - let ent_path = EntityPath::from("this/that"); - - let positions = build_some_positions2d(3); - let colors = build_some_colors(3); - let row = test_row!(ent_path @ [build_frame_nr(42)] => 3; [positions.clone(), colors.clone()]); - store.insert_row(&row).unwrap(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = re_data_store::RangeQuery::new( - timeline_frame_nr, - re_data_store::TimeRange::new(TimeInt::MIN, TimeInt::MAX), - ); - - let mut arch_views = re_query::range_archetype::( - store, &query, &ent_path, - ); - - let arch_view = arch_views.next().unwrap(); - assert!(arch_views.next().is_none()); - - let actual_instance_keys = arch_view.iter_instance_keys().collect_vec(); - let actual_positions = arch_view - .iter_required_component::() - .unwrap() - .collect_vec(); - let actual_colors = arch_view - .iter_optional_component::() - .unwrap() - .collect_vec(); - - let expected_instance_keys = vec![InstanceKey(0), InstanceKey(1), InstanceKey(2)]; - let expected_positions = positions; - let expected_colors = colors.into_iter().map(Some).collect_vec(); - - similar_asserts::assert_eq!(expected_instance_keys, actual_instance_keys); - similar_asserts::assert_eq!(expected_positions, actual_positions); - similar_asserts::assert_eq!(expected_colors, actual_colors); -} diff --git a/crates/re_query2/Cargo.toml b/crates/re_query2/Cargo.toml deleted file mode 100644 index 6953d372cd15..000000000000 --- a/crates/re_query2/Cargo.toml +++ /dev/null @@ -1,87 +0,0 @@ -[package] -name = "re_query2" -authors.workspace = true -description = "Temporary crate meant to replace re_query" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -# TODO(cmc): Replace re_query with this crate. Never publish this one. -publish = false -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[features] -default = [] - -## Enable (de)serialization using serde. -serde = ["dep:serde"] - -## Enable codegen helper binaries (generates ClampedZip & RangeZip implementations). -codegen = ["unindent"] - - -[dependencies] -# Rerun dependencies: -re_data_store.workspace = true -re_format.workspace = true -re_format_arrow.workspace = true -re_log_types.workspace = true -re_types_core.workspace = true -re_log.workspace = true -re_tracing.workspace = true -re_tuid.workspace = true - -# External dependencies: -ahash.workspace = true -anyhow.workspace = true -arrow2.workspace = true -backtrace.workspace = true -document-features.workspace = true -itertools = { workspace = true } -nohash-hasher.workspace = true -serde = { workspace = true, features = ["derive", "rc"], optional = true } -smallvec.workspace = true -static_assertions.workspace = true -thiserror.workspace = true - -# Optional: -unindent = { workspace = true, optional = true } - - -[dev-dependencies] -re_types = { workspace = true, features = ["datagen"] } - -criterion.workspace = true -itertools = { workspace = true } -mimalloc.workspace = true -rand = { workspace = true, features = ["std", "std_rng"] } -similar-asserts.workspace = true - - -[lib] -bench = false - - -[[bin]] -name = "clamped_zip" -required-features = ["codegen"] - - -[[bin]] -name = "range_zip" -required-features = ["codegen"] - - -[[bench]] -name = "latest_at" -harness = false diff --git a/crates/re_query2/README.md b/crates/re_query2/README.md deleted file mode 100644 index 42bcc981d336..000000000000 --- a/crates/re_query2/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# re_query2 - -Temporary crate for implementing the new data APIs. Not published. - -Will replace `re_query` when ready. diff --git a/crates/re_query2/benches/latest_at.rs b/crates/re_query2/benches/latest_at.rs deleted file mode 100644 index 28b9cf14f94e..000000000000 --- a/crates/re_query2/benches/latest_at.rs +++ /dev/null @@ -1,347 +0,0 @@ -#[global_allocator] -static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; - -use criterion::{criterion_group, criterion_main, Criterion}; - -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::{entity_path, DataRow, EntityPath, RowId, TimeInt, TimeType, Timeline}; -use re_query2::{clamped_zip_1x1, LatestAtResults, PromiseResolver}; -use re_types::{ - archetypes::Points2D, - components::{Color, InstanceKey, Position2D, Text}, - Archetype as _, -}; -use re_types_core::Loggable as _; - -// --- - -#[cfg(not(debug_assertions))] -const NUM_FRAMES_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_POINTS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_FRAMES_STRINGS: u32 = 1_000; -#[cfg(not(debug_assertions))] -const NUM_STRINGS: u32 = 1_000; - -// `cargo test` also runs the benchmark setup code, so make sure they run quickly: -#[cfg(debug_assertions)] -const NUM_FRAMES_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_POINTS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_FRAMES_STRINGS: u32 = 1; -#[cfg(debug_assertions)] -const NUM_STRINGS: u32 = 1; - -criterion_group!( - benches, - mono_points, - mono_strings, - batch_points, - batch_strings -); -criterion_main!(benches); - -// --- Benchmarks --- - -pub fn build_some_point2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0))) - .collect() -} - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len).map(|i| Color::from(i as u32)).collect() -} - -/// Build a ([`Timeline`], [`TimeInt`]) tuple from `frame_nr` suitable for inserting in a [`re_log_types::TimePoint`]. -pub fn build_frame_nr(frame_nr: TimeInt) -> (Timeline, TimeInt) { - (Timeline::new("frame_nr", TimeType::Sequence), frame_nr) -} - -pub fn build_some_strings(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - let ilen: usize = rng.gen_range(0..10000); - let s: String = rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(ilen) - .map(char::from) - .collect(); - Text::from(s) - }) - .collect() -} - -fn mono_points(c: &mut Criterion) { - // Each mono point gets logged at a different path - let paths = (0..NUM_POINTS) - .map(move |point_idx| entity_path!("points", point_idx.to_string())) - .collect_vec(); - let msgs = build_points_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - // Mono-insert is slow -- decrease the sample size - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn mono_strings(c: &mut Criterion) { - // Each mono string gets logged at a different path - let paths = (0..NUM_STRINGS) - .map(move |string_idx| entity_path!("strings", string_idx.to_string())) - .collect_vec(); - let msgs = build_strings_rows(&paths, 1); - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.sample_size(10); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_mono_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -fn batch_points(c: &mut Criterion) { - // Batch points are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_points_rows(&paths, NUM_POINTS as _); - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements( - (NUM_POINTS * NUM_FRAMES_POINTS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_points2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_points(&store, &paths)); - }); - } -} - -fn batch_strings(c: &mut Criterion) { - // Batch strings are logged together at a single path - let paths = [EntityPath::from("points")]; - let msgs = build_strings_rows(&paths, NUM_STRINGS as _); - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements( - (NUM_STRINGS * NUM_FRAMES_STRINGS) as _, - )); - group.bench_function("insert", |b| { - b.iter(|| insert_rows(msgs.iter())); - }); - } - - { - let mut group = c.benchmark_group("arrow_batch_strings2"); - group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); - let store = insert_rows(msgs.iter()); - group.bench_function("query", |b| { - b.iter(|| query_and_visit_strings(&store, &paths)); - }); - } -} - -// --- Helpers --- - -fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { - (0..NUM_FRAMES_POINTS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_points as _, - ( - build_some_point2d(num_points), - build_some_colors(num_points), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec { - (0..NUM_FRAMES_STRINGS) - .flat_map(move |frame_idx| { - paths.iter().map(move |path| { - let mut row = DataRow::from_cells2( - RowId::new(), - path.clone(), - [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_strings as _, - // We still need to create points because they are the primary for the - // archetype query we want to do. We won't actually deserialize the points - // during the query -- we just need it for the primary keys. - // TODO(jleibs): switch this to use `TextEntry` once the new type has - // landed. - ( - build_some_point2d(num_strings), - build_some_strings(num_strings), - ), - ) - .unwrap(); - // NOTE: Using unsized cells will crash in debug mode, and benchmarks are run for 1 iteration, - // in debug mode, by the standard test harness. - if cfg!(debug_assertions) { - row.compute_all_size_bytes(); - } - row - }) - }) - .collect() -} - -fn insert_rows<'a>(msgs: impl Iterator) -> DataStore { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - msgs.for_each(|row| { - store.insert_row(row).unwrap(); - }); - store -} - -struct SavePoint { - _pos: Position2D, - _color: Option, -} - -fn query_and_visit_points(store: &DataStore, paths: &[EntityPath]) -> Vec { - let resolver = PromiseResolver::default(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_POINTS as i64 / 2); - - let mut ret = Vec::with_capacity(NUM_POINTS as _); - - // TODO(jleibs): Add Radius once we have support for it in field_types - for entity_path in paths { - let results: LatestAtResults = re_query2::latest_at( - store, - &query, - entity_path, - Points2D::all_components().iter().copied(), // no generics! - ); - - let points = results.get_required(Position2D::name()).unwrap(); - let colors = results.get_or_empty(Color::name()); - - let points = points - .iter_dense::(&resolver) - .flatten() - .unwrap(); - - let colors = colors.iter_dense::(&resolver).flatten().unwrap(); - let color_default_fn = || Color::from(0xFF00FFFF); - - for (point, color) in clamped_zip_1x1(points, colors, color_default_fn) { - ret.push(SavePoint { - _pos: point, - _color: Some(color), - }); - } - } - assert_eq!(NUM_POINTS as usize, ret.len()); - ret -} - -struct SaveString { - _label: Option, -} - -fn query_and_visit_strings(store: &DataStore, paths: &[EntityPath]) -> Vec { - let resolver = PromiseResolver::default(); - - let timeline_frame_nr = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::new(timeline_frame_nr, NUM_FRAMES_STRINGS as i64 / 2); - - let mut strings = Vec::with_capacity(NUM_STRINGS as _); - - for entity_path in paths { - let results: LatestAtResults = re_query2::latest_at( - store, - &query, - entity_path, - Points2D::all_components().iter().copied(), // no generics! - ); - - let points = results.get_required(Position2D::name()).unwrap(); - let colors = results.get_or_empty(Text::name()); - - let points = points - .iter_dense::(&resolver) - .flatten() - .unwrap(); - - let labels = colors.iter_dense::(&resolver).flatten().unwrap(); - let label_default_fn = || Text(String::new().into()); - - for (_point, label) in clamped_zip_1x1(points, labels, label_default_fn) { - strings.push(SaveString { - _label: Some(label), - }); - } - } - assert_eq!(NUM_STRINGS as usize, strings.len()); - - criterion::black_box(strings) -} diff --git a/crates/re_query2/examples/latest_at.rs b/crates/re_query2/examples/latest_at.rs deleted file mode 100644 index dfc7ad286299..000000000000 --- a/crates/re_query2/examples/latest_at.rs +++ /dev/null @@ -1,128 +0,0 @@ -use itertools::Itertools; -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimeType, Timeline}; -use re_types_core::{Archetype as _, Loggable as _}; - -use re_query2::{ - clamped_zip_1x2, LatestAtComponentResults, LatestAtResults, PromiseResolver, PromiseResult, -}; - -// --- - -fn main() -> anyhow::Result<()> { - let store = store()?; - eprintln!("store:\n{}", store.to_data_table()?); - - let resolver = PromiseResolver::default(); - - let entity_path = "points"; - let timeline = Timeline::new("frame_nr", TimeType::Sequence); - let query = LatestAtQuery::latest(timeline); - eprintln!("query:{query:?}"); - - // First, get the raw results for this query. - // - // Raw here means that these results are neither deserialized, nor resolved/converted. - // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. - let results: LatestAtResults = re_query2::latest_at( - &store, - &query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), // no generics! - ); - - // Then, grab the raw results for each individual components. - // - // This is still raw data, but now a choice has been made regarding the nullability of the - // _component batch_ itself (that says nothing about its _instances_!). - // - // * `get_required` returns an error if the component batch is missing - // * `get_or_empty` returns an empty set of results if the component if missing - // * `get` returns an option - let points: &LatestAtComponentResults = results.get_required(MyPoint::name())?; - let colors: &LatestAtComponentResults = results.get_or_empty(MyColor::name()); - let labels: &LatestAtComponentResults = results.get_or_empty(MyLabel::name()); - - // Then comes the time to resolve/convert and deserialize the data. - // These steps have to be done together for efficiency reasons. - // - // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. - // Use `PromiseResult::flatten` to simplify it down to a single result. - // - // A choice now has to be made regarding the nullability of the _component batch's instances_. - // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably - // shouldn't be using anything but `iter_dense`. - - let points = match points.iter_dense::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - let colors = match colors.iter_dense::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - let labels = match labels.iter_sparse::(&resolver).flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - return Ok(()); - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - // With the data now fully resolved/converted and deserialized, the joining logic can be - // applied. - // - // In most cases this will be either a clamped zip, or no joining at all. - - let color_default_fn = || MyColor::from(0xFF00FFFF); - let label_default_fn = || None; - - let results = - clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn).collect_vec(); - - eprintln!("results:\n{results:#?}"); - - Ok(()) -} - -// --- - -fn store() -> anyhow::Result { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), - Default::default(), - ); - - let entity_path = "points"; - - { - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; - store.insert_row(&row)?; - } - - Ok(store) -} diff --git a/crates/re_query2/examples/range.rs b/crates/re_query2/examples/range.rs deleted file mode 100644 index e8c1a5227dc8..000000000000 --- a/crates/re_query2/examples/range.rs +++ /dev/null @@ -1,168 +0,0 @@ -use itertools::{izip, Itertools}; -use re_data_store::{DataStore, RangeQuery}; -use re_log_types::example_components::{MyColor, MyLabel, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimeRange, TimeType, Timeline}; -use re_types_core::{Archetype as _, Loggable as _}; - -use re_query2::{ - clamped_zip_1x2, range_zip_1x2, PromiseResolver, PromiseResult, RangeComponentResults, - RangeResults, -}; - -// --- - -fn main() -> anyhow::Result<()> { - let store = store()?; - eprintln!("store:\n{}", store.to_data_table()?); - - let resolver = PromiseResolver::default(); - - let entity_path = "points"; - let timeline = Timeline::new("frame_nr", TimeType::Sequence); - let query = RangeQuery::new(timeline, TimeRange::EVERYTHING); - eprintln!("query:{query:?}"); - - // First, get the raw results for this query. - // - // Raw here means that these results are neither deserialized, nor resolved/converted. - // I.e. this corresponds to the raw `DataCell`s, straight from our datastore. - let results: RangeResults = re_query2::range( - &store, - &query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), // no generics! - ); - - // Then, grab the raw results for each individual components. - // - // This is still raw data, but now a choice has been made regarding the nullability of the - // _component batch_ itself (that says nothing about its _instances_!). - // - // * `get_required` returns an error if the component batch is missing - // * `get_or_empty` returns an empty set of results if the component if missing - // * `get` returns an option - let all_points: &RangeComponentResults = results.get_required(MyPoint::name())?; - let all_colors: &RangeComponentResults = results.get_or_empty(MyColor::name()); - let all_labels: &RangeComponentResults = results.get_or_empty(MyLabel::name()); - - let all_indexed_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_indexed_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - let all_indexed_labels = izip!( - all_labels.iter_indices(), - all_labels.iter_sparse::(&resolver) - ); - - let all_frames = range_zip_1x2(all_indexed_points, all_indexed_colors, all_indexed_labels); - - // Then comes the time to resolve/convert and deserialize the data, _for each timestamp_. - // These steps have to be done together for efficiency reasons. - // - // Both the resolution and deserialization steps might fail, which is why this returns a `Result>`. - // Use `PromiseResult::flatten` to simplify it down to a single result. - // - // A choice now has to be made regarding the nullability of the _component batch's instances_. - // Our IDL doesn't support nullable instances at the moment -- so for the foreseeable future you probably - // shouldn't be using anything but `iter_dense`. - eprintln!("results:"); - for ((data_time, row_id), points, colors, labels) in all_frames { - let points = match points.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - }; - - let colors = if let Some(colors) = colors { - match colors.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - } - } else { - vec![] - }; - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let labels = if let Some(labels) = labels { - match labels.flatten() { - PromiseResult::Pending => { - // Handle the fact that the data isn't ready appropriately. - continue; - } - PromiseResult::Ready(data) => data, - PromiseResult::Error(err) => return Err(err.into()), - } - } else { - vec![] - }; - let label_default_fn = || None; - - // With the data now fully resolved/converted and deserialized, the joining logic can be - // applied. - // - // In most cases this will be either a clamped zip, or no joining at all. - - let results = clamped_zip_1x2(points, colors, color_default_fn, labels, label_default_fn) - .collect_vec(); - eprintln!("{data_time:?} @ {row_id}:\n {results:?}"); - } - - Ok(()) -} - -// --- - -fn store() -> anyhow::Result { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), - Default::default(), - ); - - let entity_path = "points"; - - { - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; - store.insert_row(&row)?; - } - - { - let timepoint = [build_frame_nr(456)]; - - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let points = vec![ - MyPoint::new(10.0, 20.0), - MyPoint::new(30.0, 40.0), - MyPoint::new(50.0, 60.0), - ]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - } - - Ok(store) -} diff --git a/crates/re_query2/src/latest_at/mod.rs b/crates/re_query2/src/latest_at/mod.rs deleted file mode 100644 index dd86e3d68e3c..000000000000 --- a/crates/re_query2/src/latest_at/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod query; -mod results; - -pub use self::query::latest_at; -pub use self::results::{LatestAtComponentResults, LatestAtResults}; diff --git a/crates/re_query2/src/latest_at/query.rs b/crates/re_query2/src/latest_at/query.rs deleted file mode 100644 index a9da12168890..000000000000 --- a/crates/re_query2/src/latest_at/query.rs +++ /dev/null @@ -1,40 +0,0 @@ -use re_data_store::{DataStore, LatestAtQuery}; -use re_log_types::EntityPath; -use re_types_core::ComponentName; - -use crate::LatestAtResults; - -// --- - -/// Queries for the given `component_names` using latest-at semantics. -/// -/// See [`LatestAtResults`] for more information about how to handle the results. -pub fn latest_at( - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, - component_names: impl IntoIterator, -) -> LatestAtResults { - re_tracing::profile_function!(entity_path.to_string()); - - let mut results = LatestAtResults::default(); - - for component_name in component_names { - let Some((time, row_id, mut cells)) = - store.latest_at(query, entity_path, component_name, &[component_name]) - else { - continue; - }; - - // Soundness: - // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` - // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - if let Some(cell) = cells[0].take() { - results.add(component_name, (time, row_id), cell); - } else { - debug_assert!(cells[0].is_some(), "unreachable: `cells[0]` is missing"); - } - } - - results -} diff --git a/crates/re_query2/src/latest_at/results.rs b/crates/re_query2/src/latest_at/results.rs deleted file mode 100644 index aef7167423dc..000000000000 --- a/crates/re_query2/src/latest_at/results.rs +++ /dev/null @@ -1,224 +0,0 @@ -use nohash_hasher::IntMap; -use re_log_types::{DataCell, RowId, TimeInt}; -use re_types_core::ComponentName; -use re_types_core::{Component, DeserializationError, DeserializationResult}; - -use crate::{Promise, PromiseResolver, PromiseResult}; - -// --- - -/// Raw results for a latest-at query. -/// -/// The data is neither deserialized, nor resolved/converted. -/// It it the raw [`DataCell`]s, straight from our datastore. -/// -/// Use [`LatestAtResults::get`], [`LatestAtResults::get_required`] and [`LatestAtResults::get_or_empty`] -/// in order to access the raw results for each individual component. -#[derive(Debug, Clone)] -pub struct LatestAtResults { - /// The compound index of this query result. - /// - /// A latest-at query is a compound operation that gathers data from many different rows. - /// The index of that compound result corresponds to the index of most the recent row in all the - /// sub-results, as defined by time and row-id order. - pub compound_index: (TimeInt, RowId), - - /// Raw results for each individual component. - pub components: IntMap, -} - -impl Default for LatestAtResults { - #[inline] - fn default() -> Self { - Self { - compound_index: (TimeInt::STATIC, RowId::ZERO), - components: Default::default(), - } - } -} - -impl LatestAtResults { - #[inline] - pub fn contains(&self, component_name: impl Into) -> bool { - self.components.contains_key(&component_name.into()) - } - - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. - #[inline] - pub fn get( - &self, - component_name: impl Into, - ) -> Option<&LatestAtComponentResults> { - self.components.get(&component_name.into()) - } - - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. - /// - /// Returns an error if the component is not present. - #[inline] - pub fn get_required( - &self, - component_name: impl Into, - ) -> crate::Result<&LatestAtComponentResults> { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - Ok(component) - } else { - Err(DeserializationError::MissingComponent { - component: component_name, - backtrace: ::backtrace::Backtrace::new_unresolved(), - } - .into()) - } - } - - /// Returns the [`LatestAtComponentResults`] for the specified `component_name`. - /// - /// Returns empty results if the component is not present. - #[inline] - pub fn get_or_empty( - &self, - component_name: impl Into, - ) -> &LatestAtComponentResults { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - component - } else { - static DEFAULT: LatestAtComponentResults = LatestAtComponentResults::EMPTY; - &DEFAULT - } - } -} - -impl LatestAtResults { - #[doc(hidden)] - #[inline] - pub fn add(&mut self, component_name: ComponentName, index: (TimeInt, RowId), cell: DataCell) { - // NOTE: Since this is a compound API that actually emits multiple queries, the index of the - // final result is the most recent index among all of its components, as defined by time - // and row-id order. - // - // TODO(#5303): We have to ignore the cluster key in this piece of logic for backwards compatibility - // reasons with the legacy instance-key model. This will go away next. - use re_types_core::Loggable as _; - if component_name != re_types_core::components::InstanceKey::name() - && index > self.compound_index - { - self.compound_index = index; - } - - self.components.insert( - component_name, - LatestAtComponentResults { - index, - promise: Some(Promise::new(cell)), - }, - ); - } -} - -// --- - -/// Uncached results for a particular component when using a latest-at query. -#[derive(Debug, Clone)] -pub struct LatestAtComponentResults { - index: (TimeInt, RowId), - - // Option so we can have a constant default value for `Self` for the optional+empty case. - promise: Option, -} - -impl Default for LatestAtComponentResults { - #[inline] - fn default() -> Self { - Self::EMPTY - } -} - -impl LatestAtComponentResults { - const EMPTY: Self = Self { - index: (TimeInt::STATIC, RowId::ZERO), - promise: None, - }; -} - -impl LatestAtComponentResults { - #[inline] - pub fn index(&self) -> &(TimeInt, RowId) { - &self.index - } - - /// Returns the component data as a dense vector. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_dense( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>> { - if let Some(cell) = self.promise.as_ref() { - resolver.resolve(cell).map(|cell| { - cell.try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - } else { - // Manufactured empty result. - PromiseResult::Ready(Ok(vec![])) - } - } - - /// Iterates over the component data, assuming it is dense. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_dense( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>> { - self.to_dense(resolver) - .map(|data| data.map(|data| data.into_iter())) - } - - /// Returns the component data as a sparse vector. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_sparse( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>>> { - if let Some(cell) = self.promise.as_ref() { - resolver.resolve(cell).map(|cell| { - cell.try_to_native_opt() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - } else { - // Manufactured empty result. - PromiseResult::Ready(Ok(vec![])) - } - } - - /// Iterates over the component data, assuming it is sparse. - /// - /// Returns an error if the component is missing or cannot be deserialized. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_sparse( - &self, - resolver: &PromiseResolver, - ) -> PromiseResult>>> { - self.to_sparse(resolver) - .map(|data| data.map(|data| data.into_iter())) - } -} diff --git a/crates/re_query2/src/lib.rs b/crates/re_query2/src/lib.rs deleted file mode 100644 index 94e94a06f803..000000000000 --- a/crates/re_query2/src/lib.rs +++ /dev/null @@ -1,81 +0,0 @@ -//! Provide query-centric access to the [`re_data_store`]. - -mod latest_at; -mod promise; -mod range; -mod visible_history; - -pub mod clamped_zip; -pub mod range_zip; - -pub use self::clamped_zip::*; -pub use self::latest_at::{latest_at, LatestAtComponentResults, LatestAtResults}; -pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; -pub use self::range::{range, RangeComponentResults, RangeResults}; -pub use self::range_zip::*; -pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; - -// --- - -#[derive(Debug, Clone, Copy)] -pub struct ComponentNotFoundError(pub re_types_core::ComponentName); - -impl std::fmt::Display for ComponentNotFoundError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("Could not find component: {}", self.0)) - } -} - -impl std::error::Error for ComponentNotFoundError {} - -#[derive(thiserror::Error, Debug)] -pub enum QueryError { - #[error("Tried to access a column that doesn't exist")] - BadAccess, - - #[error("Could not find primary component: {0}")] - PrimaryNotFound(re_types_core::ComponentName), - - #[error(transparent)] - ComponentNotFound(#[from] ComponentNotFoundError), - - #[error("Tried to access component of type '{actual:?}' using component '{requested:?}'")] - TypeMismatch { - actual: re_types_core::ComponentName, - requested: re_types_core::ComponentName, - }, - - #[error("Error with one or more the underlying data cells: {0}")] - DataCell(#[from] re_log_types::DataCellError), - - #[error("Error deserializing: {0}")] - DeserializationError(#[from] re_types_core::DeserializationError), - - #[error("Error serializing: {0}")] - SerializationError(#[from] re_types_core::SerializationError), - - #[error("Error converting arrow data: {0}")] - ArrowError(#[from] arrow2::error::Error), - - #[error("Not implemented")] - NotImplemented, - - #[error(transparent)] - Other(#[from] anyhow::Error), -} - -pub type Result = std::result::Result; - -// --- - -/// Helper extension trait to convert query results into [`re_types_core::Archetype`]s. -pub trait ToArchetype { - /// Converts the result into an [`re_types_core::Archetype`]. - /// - /// Automatically handles all aspects of the query process: deserialization, caching, promise - /// resolution, etc. - fn to_archetype( - &self, - resolver: &crate::PromiseResolver, - ) -> crate::PromiseResult>; -} diff --git a/crates/re_query2/src/range/mod.rs b/crates/re_query2/src/range/mod.rs deleted file mode 100644 index e4068c918b48..000000000000 --- a/crates/re_query2/src/range/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod query; -mod results; - -pub use self::query::range; -pub use self::results::{RangeComponentResults, RangeResults}; diff --git a/crates/re_query2/src/range/query.rs b/crates/re_query2/src/range/query.rs deleted file mode 100644 index 5c2c821bd846..000000000000 --- a/crates/re_query2/src/range/query.rs +++ /dev/null @@ -1,38 +0,0 @@ -use re_data_store::{DataStore, RangeQuery}; -use re_log_types::EntityPath; -use re_types_core::ComponentName; - -use crate::RangeResults; - -// --- - -/// Queries for the given `component_names` using range semantics. -/// -/// See [`RangeResults`] for more information about how to handle the results. -pub fn range( - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, - component_names: impl IntoIterator, -) -> RangeResults { - re_tracing::profile_function!(entity_path.to_string()); - - let mut results = RangeResults::default(); - - for component_name in component_names { - let data = store.range(query, entity_path, [component_name]).map( - |(data_time, row_id, mut cells)| { - // Unwrap: - // * `cells[0]` is guaranteed to exist since we passed in `&[component_name]` - // * `cells[0]` is guaranteed to be non-null, otherwise this whole result would be null - let cell = cells[0].take().unwrap(); - - ((data_time, row_id), cell) - }, - ); - - results.add(component_name, data); - } - - results -} diff --git a/crates/re_query2/src/range/results.rs b/crates/re_query2/src/range/results.rs deleted file mode 100644 index 2cfe48751a7d..000000000000 --- a/crates/re_query2/src/range/results.rs +++ /dev/null @@ -1,204 +0,0 @@ -use nohash_hasher::IntMap; -use re_log_types::{DataCell, RowId, TimeInt}; -use re_types_core::ComponentName; -use re_types_core::{Component, DeserializationError, DeserializationResult}; - -use crate::{Promise, PromiseResolver, PromiseResult}; - -// --- - -/// Raw results for a range query. -/// -/// The data is neither deserialized, nor resolved/converted. -/// It it the raw [`DataCell`]s, straight from our datastore. -/// -/// Use [`RangeResults::get`], [`RangeResults::get_required`] and [`RangeResults::get_or_empty`] -/// in order to access the raw results for each individual component. -#[derive(Default, Debug, Clone)] -pub struct RangeResults { - /// Raw results for each individual component. - pub components: IntMap, -} - -impl RangeResults { - #[inline] - pub fn contains(&self, component_name: impl Into) -> bool { - self.components.contains_key(&component_name.into()) - } - - /// Returns the [`RangeComponentResults`] for the specified `component_name`. - #[inline] - pub fn get(&self, component_name: impl Into) -> Option<&RangeComponentResults> { - self.components.get(&component_name.into()) - } - - /// Returns the [`RangeComponentResults`] for the specified `component_name`. - /// - /// Returns an error if the component is not present. - #[inline] - pub fn get_required( - &self, - component_name: impl Into, - ) -> crate::Result<&RangeComponentResults> { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - Ok(component) - } else { - Err(DeserializationError::MissingComponent { - component: component_name, - backtrace: ::backtrace::Backtrace::new_unresolved(), - } - .into()) - } - } - - /// Returns the [`RangeComponentResults`] for the specified `component_name`. - /// - /// Returns empty results if the component is not present. - #[inline] - pub fn get_or_empty(&self, component_name: impl Into) -> &RangeComponentResults { - let component_name = component_name.into(); - if let Some(component) = self.components.get(&component_name) { - component - } else { - static DEFAULT: RangeComponentResults = RangeComponentResults::empty(); - &DEFAULT - } - } -} - -impl RangeResults { - #[doc(hidden)] - #[inline] - pub fn add( - &mut self, - component_name: ComponentName, - data: impl Iterator, - ) { - let (indices, cells): (Vec<_>, Vec<_>) = data - .map(|(index, cell)| (index, Promise::new(cell))) - .unzip(); - - let results = RangeComponentResults { - indices, - promises: cells, - }; - results.sanity_check(); - - self.components.insert(component_name, results); - } -} - -// --- - -/// Uncached results for a particular component when using a range query. -#[derive(Debug, Clone)] -pub struct RangeComponentResults { - pub indices: Vec<(TimeInt, RowId)>, - pub promises: Vec, -} - -impl Default for RangeComponentResults { - #[inline] - fn default() -> Self { - Self::empty() - } -} - -impl RangeComponentResults { - #[inline] - pub const fn empty() -> Self { - Self { - indices: Vec::new(), - promises: Vec::new(), - } - } - - /// No-op in release. - #[inline] - pub fn sanity_check(&self) { - let Self { - indices, - promises: cells, - } = self; - if cfg!(debug_assertions) { - assert_eq!(indices.len(), cells.len()); - } - } -} - -impl RangeComponentResults { - #[inline] - pub fn indices(&self) -> &[(TimeInt, RowId)] { - &self.indices - } - - #[inline] - pub fn iter_indices(&self) -> impl ExactSizeIterator + '_ { - self.indices.iter().copied() - } - - /// Returns the component data as a vector of dense vectors. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_dense( - &self, - resolver: &PromiseResolver, - ) -> Vec>>> { - self.promises - .iter() - .map(|cell| { - resolver.resolve(cell).map(|cell| { - cell.try_to_native() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - }) - .collect() - } - - /// Returns the component data as an iterator of dense vectors. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_dense( - &self, - resolver: &PromiseResolver, - ) -> impl ExactSizeIterator>>> { - self.to_dense(resolver).into_iter() - } - - /// Returns the component data as a vector of sparse vectors. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn to_sparse( - &self, - resolver: &PromiseResolver, - ) -> Vec>>>> { - self.promises - .iter() - .map(|cell| { - resolver.resolve(cell).map(|cell| { - cell.try_to_native_opt() - .map_err(|err| DeserializationError::DataCellError(err.to_string())) - }) - }) - .collect() - } - - /// Returns the component data as an iterator of sparse vectors. - /// - /// Use [`PromiseResult::flatten`] to merge the results of resolving the promise and of - /// deserializing the data into a single one, if you don't need the extra flexibility. - #[inline] - pub fn iter_sparse( - &self, - resolver: &PromiseResolver, - ) -> impl ExactSizeIterator>>>> { - self.to_sparse(resolver).into_iter() - } -} diff --git a/crates/re_query2/tests/latest_at.rs b/crates/re_query2/tests/latest_at.rs deleted file mode 100644 index c5c4effde420..000000000000 --- a/crates/re_query2/tests/latest_at.rs +++ /dev/null @@ -1,217 +0,0 @@ -use re_data_store::DataStore; -use re_log_types::example_components::{MyColor, MyPoint, MyPoints}; -use re_log_types::{build_frame_nr, DataRow, RowId, TimePoint}; -use re_query2::PromiseResolver; -use re_types::components::InstanceKey; -use re_types::{Archetype as _, ComponentNameSet}; -use re_types_core::Loggable as _; - -// --- - -#[test] -fn simple_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌─────────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═════════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 4278190080 │ - // └─────────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} - -#[test] -fn static_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, TimePoint::default(), 2, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌───────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═══════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 4278190080 │ - // └───────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} - -#[test] -fn no_instance_join_query() -> anyhow::Result<()> { - let resolver = PromiseResolver::default(); - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors)?; - store.insert_row(&row)?; - - let timeline_query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - let results = re_query2::latest_at( - &store, - &timeline_query, - &entity_path.into(), - MyPoints::all_components().iter().copied(), - ); - - // We expect this to generate the following `DataFrame` - // ┌───────────┬────────────┐ - // │ point ┆ color │ - // │ --- ┆ --- │ - // │ struct[2] ┆ u32 │ - // ╞═══════════╪════════════╡ - // │ {1.0,2.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ 16711680 │ - // └───────────┴────────────┘ - - { - let expected_components: ComponentNameSet = - [MyPoint::name(), MyColor::name()].into_iter().collect(); - let got_components: ComponentNameSet = results.components.keys().copied().collect(); - similar_asserts::assert_eq!(expected_components, got_components); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(0, 255, 0)), - ]; - - let points = results.get_required(MyPoint::name())?; - let point_data = points.iter_dense::(&resolver).flatten().unwrap(); - - let colors = results.get_or_empty(MyColor::name()); - let color_data = colors.iter_sparse::(&resolver).flatten().unwrap(); - let color_default_fn = || Some(MyColor::from(0xFF00FFFF)); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(point_data, color_data, color_default_fn).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} diff --git a/crates/re_query2/tests/range.rs b/crates/re_query2/tests/range.rs deleted file mode 100644 index a000f588b311..000000000000 --- a/crates/re_query2/tests/range.rs +++ /dev/null @@ -1,496 +0,0 @@ -use itertools::izip; -use re_query2::PromiseResolver; -use re_types::{components::InstanceKey, Archetype}; - -use re_data_store::{DataStore, TimeInt, TimeRange}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_types_core::Loggable as _; - -// --- - -#[test] -fn simple_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let resolver = PromiseResolver::default(); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; - store.insert_row(&row)?; - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; - store.insert_row(&row)?; - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; - store.insert_row(&row)?; - } - - let timepoint3 = [build_frame_nr(323)]; - { - let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; - store.insert_row(&row)?; - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #323: - // ┌──────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞══════════════╪═════════════════╡ - // │ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {30.0,40.0} ┆ 4278190080 │ - // └──────────────┴─────────────────┘ - - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - assert!(results.next().is_none()); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - // We expect this to generate the following `DataFrame`s: - // - // Frame #123: - // ┌───────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞═══════════════╪═════════════════╡ - // │ {1.0,2.0} ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {3.0,4.0} ┆ null │ - // └───────────────┴─────────────────┘ - // - // Frame #323: - // ┌───────────────┬─────────────────┐ - // │ MyPoint ┆ MyColor │ - // ╞═══════════════╪═════════════════╡ - // │ {10.0,20.0} ┆ 4278190080 │ - // ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ {30.0,40.0} ┆ 4278190080 │ - // └───────────────┴─────────────────┘ - - { - // Frame #123 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![None, None]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - assert!(results.next().is_none()); - - Ok(()) -} - -#[test] -fn static_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let resolver = PromiseResolver::default(); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let mut row = - DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint1, 2, positions)?; - row.compute_all_size_bytes(); - store.insert_row(&row)?; - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - (color_instances.clone(), colors.clone()), - )?; - store.insert_row(&row)?; - } - - let timepoint2 = [build_frame_nr(223)]; - { - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(0)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - (color_instances.clone(), colors.clone()), - )?; - store.insert_row(&row)?; - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - )?; - store.insert_row(&row)?; - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint3, - 2, - positions, - )?; - store.insert_row(&row)?; - } - - // ┌──────────┬───────────────┬────────────────────────────┐ - // │ frame_nr ┆ MyColor ┆ MyColor │ - // ╞══════════╪═══════════════╪════════════════════════════╡ - // │ null ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 123 ┆ null ┆ [{1.0,2.0}, {3.0,4.0}] │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 123 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 223 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 223 ┆ [4278190080] ┆ null │ - // ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ - // │ 323 ┆ null ┆ [{10.0,20.0}, {30.0,40.0}] │ - // └──────────┴───────────────┴────────────────────────────┘ - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #123 (partially static) - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - let results = re_query2::range( - &store, - &query, - &entity_path, - MyPoints::all_components().iter().copied(), - ); - - let all_points = results.get_required(MyPoint::name())?; - let all_colors = results.get_or_empty(MyColor::name()); - - let all_points = izip!( - all_points.iter_indices(), - all_points.iter_dense::(&resolver) - ); - let all_colors = izip!( - all_colors.iter_indices(), - all_colors.iter_sparse::(&resolver) - ); - - let mut results = re_query2::range_zip_1x1(all_points, all_colors); - - { - // Frame #123 (partially static) - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(123), data_time); - - let expected_points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - { - // Frame #323 - - let ((data_time, _row_id), points, colors) = results.next().unwrap(); - assert_eq!(TimeInt::new_temporal(323), data_time); - - let expected_points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let expected_colors = vec![ - Some(MyColor::from_rgb(255, 0, 0)), - Some(MyColor::from_rgb(255, 0, 0)), - ]; - - let points = points.flatten().unwrap(); - let colors = colors.map_or(vec![], |colors| colors.flatten().unwrap()); - - let (got_points, got_colors): (Vec<_>, Vec<_>) = - re_query2::clamped_zip_1x1(points, colors, || None).unzip(); - - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected_points, got_points); - similar_asserts::assert_eq!(expected_colors, got_colors); - } - - Ok(()) -} diff --git a/crates/re_query_cache/Cargo.toml b/crates/re_query_cache/Cargo.toml deleted file mode 100644 index 71a9dfbe35ef..000000000000 --- a/crates/re_query_cache/Cargo.toml +++ /dev/null @@ -1,81 +0,0 @@ -[package] -name = "re_query_cache" -authors.workspace = true -description = "Caching datastructures for re_query" -edition.workspace = true -homepage.workspace = true -include.workspace = true -license.workspace = true -publish = true -readme = "README.md" -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true - - -[features] -default = ["to_archetype"] - -## Implements `ToArchetype` for all builtin archetypes on `CachedLatestAtResults`. -to_archetype = ["dep:re_types", "dep:re_types_blueprint"] - -[dependencies] -# Rerun dependencies: -re_data_store.workspace = true -re_error.workspace = true -re_format.workspace = true -re_log.workspace = true -re_log_types.workspace = true -re_query2.workspace = true -re_tracing.workspace = true -re_types_core.workspace = true - -# Rerun dependencies (optional): -re_types = { workspace = true, optional = true } -re_types_blueprint = { workspace = true, optional = true } - -# External dependencies: -ahash.workspace = true -anyhow.workspace = true -backtrace.workspace = true -indent.workspace = true -indexmap.workspace = true -itertools.workspace = true -nohash-hasher.workspace = true -parking_lot.workspace = true -paste.workspace = true -seq-macro.workspace = true -web-time.workspace = true - - -[dev-dependencies] -re_types = { workspace = true, features = ["datagen"] } - -criterion.workspace = true -mimalloc.workspace = true -rand = { workspace = true, features = ["std", "std_rng"] } -similar-asserts.workspace = true - - -[lib] -bench = false - - -[[example]] -name = "latest_at_archetype" -required-features = ["to_archetype"] - - -[[bench]] -name = "flat_vec_deque" -harness = false - -[[bench]] -name = "latest_at" -harness = false diff --git a/crates/re_query_cache/README.md b/crates/re_query_cache/README.md deleted file mode 100644 index 70613732471d..000000000000 --- a/crates/re_query_cache/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# re_query_cache - -Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. - -[![Latest version](https://img.shields.io/crates/v/re_query_cache.svg)](https://crates.io/crates/re_query_cache) -[![Documentation](https://docs.rs/re_query/badge.svg)](https://docs.rs/re_query) -![MIT](https://img.shields.io/badge/license-MIT-blue.svg) -![Apache](https://img.shields.io/badge/license-Apache-blue.svg) - -Caching datastructures for `re_query`. diff --git a/crates/re_query_cache/src/latest_at/mod.rs b/crates/re_query_cache/src/latest_at/mod.rs deleted file mode 100644 index 82fd889bce0b..000000000000 --- a/crates/re_query_cache/src/latest_at/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -mod helpers; -mod query; -mod results; - -#[cfg(feature = "to_archetype")] -mod to_archetype; - -pub use self::helpers::CachedLatestAtMonoResult; -pub use self::query::LatestAtCache; -pub use self::results::{CachedLatestAtComponentResults, CachedLatestAtResults}; diff --git a/crates/re_query_cache/src/lib.rs b/crates/re_query_cache/src/lib.rs deleted file mode 100644 index cb995ab447aa..000000000000 --- a/crates/re_query_cache/src/lib.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! Caching datastructures for `re_query`. - -mod cache; -mod cache_stats; -mod flat_vec_deque; -mod latest_at; -mod range; - -pub use self::cache::{CacheKey, Caches}; -pub use self::cache_stats::{CachedComponentStats, CachesStats}; -pub use self::flat_vec_deque::{ErasedFlatVecDeque, FlatVecDeque}; -pub use self::latest_at::{ - CachedLatestAtComponentResults, CachedLatestAtMonoResult, CachedLatestAtResults, -}; -pub use self::range::{CachedRangeComponentResults, CachedRangeData, CachedRangeResults}; - -pub(crate) use self::latest_at::LatestAtCache; -pub(crate) use self::range::{CachedRangeComponentResultsInner, RangeCache}; - -pub use re_query2::{ - clamped_zip::*, range_zip::*, ExtraQueryHistory, Promise, PromiseId, PromiseResolver, - PromiseResult, QueryError, Result, ToArchetype, VisibleHistory, VisibleHistoryBoundary, -}; - -pub mod external { - pub use re_query2; - - pub use paste; - pub use seq_macro; -} - -// --- - -use re_data_store::{LatestAtQuery, RangeQuery}; - -#[derive(Debug)] -pub enum CachedResults { - LatestAt(LatestAtQuery, CachedLatestAtResults), - Range(RangeQuery, CachedRangeResults), -} - -impl From<(LatestAtQuery, CachedLatestAtResults)> for CachedResults { - #[inline] - fn from((query, results): (LatestAtQuery, CachedLatestAtResults)) -> Self { - Self::LatestAt(query, results) - } -} - -impl From<(RangeQuery, CachedRangeResults)> for CachedResults { - #[inline] - fn from((query, results): (RangeQuery, CachedRangeResults)) -> Self { - Self::Range(query, results) - } -} diff --git a/crates/re_query_cache/src/range/mod.rs b/crates/re_query_cache/src/range/mod.rs deleted file mode 100644 index ffb93dd2f720..000000000000 --- a/crates/re_query_cache/src/range/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod query; -mod results; - -pub use self::query::RangeCache; -pub use self::results::{ - CachedRangeComponentResults, CachedRangeComponentResultsInner, CachedRangeData, - CachedRangeResults, -}; diff --git a/crates/re_query_cache/tests/latest_at.rs b/crates/re_query_cache/tests/latest_at.rs deleted file mode 100644 index 4073c5ec7e53..000000000000 --- a/crates/re_query_cache/tests/latest_at.rs +++ /dev/null @@ -1,526 +0,0 @@ -//! Contains: -//! - A 1:1 port of the tests in `crates/re_query/tests/archetype_query_tests.rs`, with caching enabled. -//! - Invalidation tests. - -use re_data_store::{DataStore, LatestAtQuery, StoreSubscriber}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_query2::PromiseResolver; -use re_query_cache::Caches; -use re_types::Archetype as _; -use re_types_core::{components::InstanceKey, Loggable as _}; - -// --- - -#[test] -fn simple_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn static_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance.. statically! - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - TimePoint::default(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn no_instance_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign them colors with explicit instances - let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn missing_column_join_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with an implicit instance - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn splatted_query() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "point"; - let timepoint = [build_frame_nr(123)]; - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign all of them a color via splat - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timepoint, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn invalidation() { - let entity_path = "point"; - - let test_invalidation = |query: LatestAtQuery, - present_data_timepoint: TimePoint, - past_data_timepoint: TimePoint, - future_data_timepoint: TimePoint| { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - // Create some positions with implicit instances - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let color_instances = vec![InstanceKey(1)]; - let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify present --- - - // Modify the PoV component - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint, - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify past --- - - // Modify the PoV component - let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, past_data_timepoint, 2, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify future --- - - // Modify the PoV component - let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - future_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(16, 17, 18)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - }; - - let timeless = TimePoint::default(); - let frame_122 = build_frame_nr(122); - let frame_123 = build_frame_nr(123); - let frame_124 = build_frame_nr(124); - - test_invalidation( - LatestAtQuery::new(frame_123.0, frame_123.1), - [frame_123].into(), - [frame_122].into(), - [frame_124].into(), - ); - - test_invalidation( - LatestAtQuery::new(frame_123.0, frame_123.1), - [frame_123].into(), - timeless, - [frame_124].into(), - ); -} - -// Test the following scenario: -// ```py -// rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// -// # Do first query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[] -// -// rr.set_time(2) -// rr.log_components("points", rr.components.MyColor(0xFF0000)) -// -// # Do second query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0xFF0000] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x0000FF)) -// -// # Do third query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x0000FF] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x00FF00)) -// -// # Do fourth query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x00FF00] -// ``` -#[test] -fn invalidation_of_future_optionals() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - let frame2 = [build_frame_nr(2)]; - let frame3 = [build_frame_nr(3)]; - - let query_time = [build_frame_nr(9999)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame2, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - frame3, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn static_invalidation() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - - let query_time = [build_frame_nr(9999)]; - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless.clone(), - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let color_instances = vec![InstanceKey::SPLAT]; - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells2_sized( - RowId::new(), - entity_path, - timeless, - 1, - (color_instances, colors), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -// --- - -fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { - caches.on_events(&[store.insert_row(row).unwrap()]); -} - -fn query_and_compare( - caches: &Caches, - store: &DataStore, - query: &LatestAtQuery, - entity_path: &EntityPath, -) { - re_log::setup_logging(); - - let resolver = PromiseResolver::default(); - - for _ in 0..3 { - let cached = caches.latest_at( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let cached_points = cached.get_required(MyPoint::name()).unwrap(); - let cached_point_data = cached_points - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let cached_colors = cached.get_or_empty(MyColor::name()); - let cached_color_data = cached_colors - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let expected = re_query2::latest_at( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let expected_points = expected.get_required(MyPoint::name()).unwrap(); - let expected_point_data = expected_points - .to_dense::(&resolver) - .flatten() - .unwrap(); - - let expected_colors = expected.get_or_empty(MyColor::name()); - let expected_color_data = expected_colors - .to_dense::(&resolver) - .flatten() - .unwrap(); - - // eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!(expected.compound_index, cached.compound_index); - similar_asserts::assert_eq!(expected_point_data, cached_point_data); - similar_asserts::assert_eq!(expected_color_data, cached_color_data); - } -} diff --git a/crates/re_query_cache/tests/range.rs b/crates/re_query_cache/tests/range.rs deleted file mode 100644 index eb7380c8a1d0..000000000000 --- a/crates/re_query_cache/tests/range.rs +++ /dev/null @@ -1,586 +0,0 @@ -use itertools::{izip, Itertools as _}; - -use re_data_store::{DataStore, RangeQuery, StoreSubscriber as _, TimeInt, TimeRange}; -use re_log_types::{ - build_frame_nr, - example_components::{MyColor, MyPoint, MyPoints}, - DataRow, EntityPath, RowId, TimePoint, -}; -use re_query_cache::{Caches, PromiseResolver, PromiseResult}; -use re_types::{components::InstanceKey, Archetype}; -use re_types_core::Loggable as _; - -// --- - -#[test] -fn simple_range() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, points)?; - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors)?; - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors)?; - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - let points = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, points)?; - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - Ok(()) -} - -#[test] -fn static_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint1, - 1, - colors.clone(), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - timepoint2, - 1, - colors.clone(), - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Insert statically too! - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path.clone(), - TimePoint::default(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - // Create some Positions with implicit instances - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - // The inclusion of `timepoint1` means latest-at semantics will fall back to timeless data! - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Third test: `[-inf, +inf]` --- - - let query = - re_data_store::RangeQuery::new(timepoint1[0].0, TimeRange::new(TimeInt::MIN, TimeInt::MAX)); - - query_and_compare(&caches, &store, &query, &entity_path); -} - -#[test] -fn simple_splatted_range() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path: EntityPath = "point".into(); - - let timepoint1 = [build_frame_nr(123)]; - { - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - // Assign one of them a color with an explicit instance - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint1, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint2 = [build_frame_nr(223)]; - { - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint2, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - let timepoint3 = [build_frame_nr(323)]; - { - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path.clone(), timepoint3, 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - } - - // --- First test: `(timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1.as_i64() + 1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); - - // --- Second test: `[timepoint1, timepoint3]` --- - - let query = re_data_store::RangeQuery::new( - timepoint1[0].0, - TimeRange::new(timepoint1[0].1, timepoint3[0].1), - ); - - query_and_compare(&caches, &store, &query, &entity_path); -} - -#[test] -fn invalidation() { - let entity_path = "point"; - - let test_invalidation = |query: RangeQuery, - present_data_timepoint: TimePoint, - past_data_timepoint: TimePoint, - future_data_timepoint: TimePoint| { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - let colors = vec![MyColor::from_rgb(1, 2, 3)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 1, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify present --- - - // Modify the PoV component - let positions = vec![MyPoint::new(10.0, 20.0), MyPoint::new(30.0, 40.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(4, 5, 6), MyColor::from_rgb(7, 8, 9)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - present_data_timepoint, - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify past --- - - // Modify the PoV component - let positions = vec![MyPoint::new(100.0, 200.0), MyPoint::new(300.0, 400.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(10, 11, 12), MyColor::from_rgb(13, 14, 15)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - past_data_timepoint.clone(), - 2, - colors, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // --- Modify future --- - - // Modify the PoV component - let positions = vec![MyPoint::new(1000.0, 2000.0), MyPoint::new(3000.0, 4000.0)]; - let row = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - future_data_timepoint.clone(), - 2, - positions, - ) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - // Modify the optional component - let colors = vec![MyColor::from_rgb(16, 17, 18)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, future_data_timepoint, 1, colors) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - }; - - let timeless = TimePoint::default(); - let frame_122 = build_frame_nr(122); - let frame_123 = build_frame_nr(123); - let frame_124 = build_frame_nr(124); - - test_invalidation( - RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), - [frame_123].into(), - [frame_122].into(), - [frame_124].into(), - ); - - test_invalidation( - RangeQuery::new(frame_123.0, TimeRange::EVERYTHING), - [frame_123].into(), - timeless, - [frame_124].into(), - ); -} - -// Test the following scenario: -// ```py -// rr.log("points", rr.Points3D([1, 2, 3]), static=True) -// -// # Do first query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[] -// -// rr.set_time(2) -// rr.log_components("points", rr.components.MyColor(0xFF0000)) -// -// # Do second query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0xFF0000] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x0000FF)) -// -// # Do third query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x0000FF] -// -// rr.set_time(3) -// rr.log_components("points", rr.components.MyColor(0x00FF00)) -// -// # Do fourth query here: LatestAt(+inf) -// # Expected: points=[[1,2,3]] colors=[0x00FF00] -// ``` -#[test] -fn invalidation_of_future_optionals() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - let frame2 = [build_frame_nr(2)]; - let frame3 = [build_frame_nr(3)]; - - let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, positions).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 255, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -#[test] -fn invalidation_static() { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let mut caches = Caches::new(&store); - - let entity_path = "points"; - - let timeless = TimePoint::default(); - - let frame0 = [build_frame_nr(TimeInt::ZERO)]; - let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); - - let positions = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 2, positions) - .unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); - - let colors = vec![MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors).unwrap(); - insert_and_react(&mut store, &mut caches, &row); - - query_and_compare(&caches, &store, &query, &entity_path.into()); -} - -// --- - -fn insert_and_react(store: &mut DataStore, caches: &mut Caches, row: &DataRow) { - caches.on_events(&[store.insert_row(row).unwrap()]); -} - -fn query_and_compare( - caches: &Caches, - store: &DataStore, - query: &RangeQuery, - entity_path: &EntityPath, -) { - re_log::setup_logging(); - - let resolver = PromiseResolver::default(); - - for _ in 0..3 { - let cached = caches.range( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let cached_all_points = cached - .get_required(MyPoint::name()) - .unwrap() - .to_dense::(&resolver); - assert!(matches!( - cached_all_points.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())), - )); - let cached_all_points_indexed = cached_all_points.range_indexed(); - - let cached_all_colors = cached - .get_or_empty(MyColor::name()) - .to_dense::(&resolver); - assert!(matches!( - cached_all_colors.status(), - (PromiseResult::Ready(()), PromiseResult::Ready(())), - )); - let cached_all_colors_indexed = cached_all_colors.range_indexed(); - - let expected = re_query2::range( - store, - query, - entity_path, - MyPoints::all_components().iter().copied(), - ); - - let expected_all_points = expected.get_required(MyPoint::name()).unwrap(); - let expected_all_points_indices = expected_all_points.indices(); - let expected_all_points_data = expected_all_points - .to_dense::(&resolver) - .into_iter() - .map(|batch| batch.flatten().unwrap()) - .collect_vec(); - let expected_all_points_indexed = - izip!(expected_all_points_indices, expected_all_points_data); - - let expected_all_colors = expected.get_or_empty(MyColor::name()); - let expected_all_colors_indices = expected_all_colors.indices(); - let expected_all_colors_data = expected_all_colors - .to_dense::(&resolver) - .into_iter() - .map(|batch| batch.flatten().unwrap()) - .collect_vec(); - let expected_all_colors_indexed = - izip!(expected_all_colors_indices, expected_all_colors_data); - - eprintln!("{query:?}"); - eprintln!("{}", store.to_data_table().unwrap()); - - similar_asserts::assert_eq!( - expected_all_points_indexed - .map(|(index, data)| (*index, data)) - .collect_vec(), - cached_all_points_indexed - .map(|(index, data)| (*index, data.to_vec())) - .collect_vec(), - ); - - similar_asserts::assert_eq!( - expected_all_colors_indexed - .map(|(index, data)| (*index, data)) - .collect_vec(), - cached_all_colors_indexed - .map(|(index, data)| (*index, data.to_vec())) - .collect_vec(), - ); - } -} diff --git a/crates/re_space_view/Cargo.toml b/crates/re_space_view/Cargo.toml index 441e96bc95ea..36b53d591f51 100644 --- a/crates/re_space_view/Cargo.toml +++ b/crates/re_space_view/Cargo.toml @@ -27,7 +27,6 @@ re_log_types.workspace = true re_data_store.workspace = true re_entity_db.workspace = true re_query.workspace = true -re_query_cache.workspace = true re_tracing.workspace = true re_types_core.workspace = true re_types.workspace = true diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index cd9b86fa22d7..8e435edeb682 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,6 +1,6 @@ use itertools::{FoldWhile, Itertools}; use nohash_hasher::IntMap; -use re_entity_db::external::re_query_cache::PromiseResult; +use re_entity_db::external::re_query::PromiseResult; use crate::SpaceViewContents; use re_data_store::LatestAtQuery; diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 2b4e94cd853e..82116aef381e 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -3,7 +3,7 @@ use slotmap::SlotMap; use smallvec::SmallVec; use re_entity_db::{ - external::{re_data_store::LatestAtQuery, re_query_cache::PromiseResult}, + external::{re_data_store::LatestAtQuery, re_query::PromiseResult}, EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, }; use re_log_types::{ diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 198f150f1430..2325aa3b2868 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -1,6 +1,6 @@ use re_data_store::LatestAtQuery; use re_entity_db::{ - external::re_query_cache::{CachedLatestAtResults, PromiseResult, ToArchetype}, + external::re_query::{LatestAtResults, PromiseResult, ToArchetype}, EntityDb, }; use re_log_types::EntityPath; @@ -46,7 +46,7 @@ pub fn query_space_view_sub_archetype( query: &LatestAtQuery, ) -> (PromiseResult>, EntityPath) where - CachedLatestAtResults: ToArchetype, + LatestAtResults: ToArchetype, { let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); ( @@ -63,7 +63,7 @@ pub fn query_space_view_sub_archetype_or_default( query: &LatestAtQuery, ) -> (A, EntityPath) where - CachedLatestAtResults: ToArchetype, + LatestAtResults: ToArchetype, { let (arch, path) = query_space_view_sub_archetype(space_view_id, blueprint_db, query); (arch.ok().flatten().unwrap_or_default(), path) diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index 2c2af59f7363..4a55c27e31f9 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -8,7 +8,7 @@ //! to reduce the amount of changes in code that is likely to be refactored soon anyways. use re_log_types::TimeRange; -use re_query_cache::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; +use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; use re_types::blueprint::{ components::VisibleTimeRange, datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, diff --git a/crates/re_space_view_dataframe/Cargo.toml b/crates/re_space_view_dataframe/Cargo.toml index 7ba423482c19..aab59723a55b 100644 --- a/crates/re_space_view_dataframe/Cargo.toml +++ b/crates/re_space_view_dataframe/Cargo.toml @@ -24,7 +24,6 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true re_query.workspace = true -re_query_cache.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types_core.workspace = true diff --git a/crates/re_space_view_spatial/Cargo.toml b/crates/re_space_view_spatial/Cargo.toml index 2bf7b4745914..57aa3d632a16 100644 --- a/crates/re_space_view_spatial/Cargo.toml +++ b/crates/re_space_view_spatial/Cargo.toml @@ -27,7 +27,6 @@ re_format.workspace = true re_log_types.workspace = true re_log.workspace = true re_query.workspace = true -re_query_cache.workspace = true re_renderer = { workspace = true, features = [ "import-gltf", "import-obj", diff --git a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs index f7ed6472e5de..b274db0b8b97 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows2D, @@ -220,7 +220,7 @@ impl VisualizerSystem for Arrows2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs index 05fdb1ef9764..cf59264e9401 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows3D, @@ -223,7 +223,7 @@ impl VisualizerSystem for Arrows3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/assets3d.rs b/crates/re_space_view_spatial/src/visualizers/assets3d.rs index fd14f33490a1..77d22a2a4d93 100644 --- a/crates/re_space_view_spatial/src/visualizers/assets3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/assets3d.rs @@ -1,6 +1,6 @@ use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::range_zip_1x2; +use re_query::range_zip_1x2; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Asset3D, @@ -143,7 +143,7 @@ impl VisualizerSystem for Asset3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs index 07fb7d9b9acd..dc4588ff9746 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x6; +use re_query::range_zip_1x6; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes2D, @@ -216,7 +216,7 @@ impl VisualizerSystem for Boxes2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs index 8819231a5aea..2dfcd63d95cf 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x7; +use re_query::range_zip_1x7; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes3D, @@ -206,7 +206,7 @@ impl VisualizerSystem for Boxes3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 7b341e5064a6..6b5c39bf70ed 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,7 +2,7 @@ use itertools::Either; use re_data_store::{LatestAtQuery, RangeQuery}; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, TimeInt, Timeline}; -use re_query_cache::{CachedResults, ExtraQueryHistory}; +use re_query::{ExtraQueryHistory, Results}; use re_renderer::DepthOffset; use re_space_view::query_visual_history; use re_types::Archetype; @@ -46,7 +46,7 @@ pub fn query_archetype_with_history( time: &TimeInt, history: &ExtraQueryHistory, entity_path: &EntityPath, -) -> CachedResults { +) -> Results { let visible_history = match timeline.typ() { re_log_types::TimeType::Time => history.nanos, re_log_types::TimeType::Sequence => history.sequences, @@ -96,7 +96,7 @@ where &EntityPath, &EntityProperties, &SpatialSceneEntityContext<'_>, - &CachedResults, + &Results, ) -> Result<(), SpaceViewSystemExecutionError>, { let transforms = view_ctx.get::()?; diff --git a/crates/re_space_view_spatial/src/visualizers/images.rs b/crates/re_space_view_spatial/src/visualizers/images.rs index 82ef54742c40..54fc1a9919e6 100644 --- a/crates/re_space_view_spatial/src/visualizers/images.rs +++ b/crates/re_space_view_spatial/src/visualizers/images.rs @@ -6,7 +6,7 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityPath, EntityProperties}; use re_log_types::{EntityPathHash, RowId, TimeInt}; -use re_query_cache::range_zip_1x2; +use re_query::range_zip_1x2; use re_renderer::{ renderer::{DepthCloud, DepthClouds, RectangleOptions, TexturedRect}, Colormap, @@ -855,7 +855,7 @@ impl ImageVisualizer { |ctx, entity_path, entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/lines2d.rs b/crates/re_space_view_spatial/src/visualizers/lines2d.rs index e7c688eab4a7..bbddd23851d6 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines2d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::LineStrips2D, @@ -205,7 +205,7 @@ impl VisualizerSystem for Lines2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/lines3d.rs b/crates/re_space_view_spatial/src/visualizers/lines3d.rs index 9bbb657425f9..e4da2c12ce24 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines3d.rs @@ -1,5 +1,5 @@ use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::PickingLayerInstanceId; use re_types::{ archetypes::LineStrips3D, @@ -214,7 +214,7 @@ impl VisualizerSystem for Lines3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/meshes.rs b/crates/re_space_view_spatial/src/visualizers/meshes.rs index 89d28eadd512..5ac9b2a3a48b 100644 --- a/crates/re_space_view_spatial/src/visualizers/meshes.rs +++ b/crates/re_space_view_spatial/src/visualizers/meshes.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::range_zip_1x7; +use re_query::range_zip_1x7; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Mesh3D, @@ -168,7 +168,7 @@ impl VisualizerSystem for Mesh3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/mod.rs b/crates/re_space_view_spatial/src/visualizers/mod.rs index 98e205ec4ab7..62745ee750f2 100644 --- a/crates/re_space_view_spatial/src/visualizers/mod.rs +++ b/crates/re_space_view_spatial/src/visualizers/mod.rs @@ -22,7 +22,7 @@ pub use images::{ImageVisualizer, ViewerImage}; pub use spatial_view_visualizer::SpatialViewVisualizerData; pub use transform3d_arrows::{add_axis_arrows, Transform3DArrowsVisualizer}; -pub(crate) use self::results_ext::CachedRangeResultsExt; +pub(crate) use self::results_ext::RangeResultsExt; // --- diff --git a/crates/re_space_view_spatial/src/visualizers/points2d.rs b/crates/re_space_view_spatial/src/visualizers/points2d.rs index 31bc5389316c..3ac152c1184e 100644 --- a/crates/re_space_view_spatial/src/visualizers/points2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points2d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points2D, @@ -224,7 +224,7 @@ impl VisualizerSystem for Points2DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/points3d.rs b/crates/re_space_view_spatial/src/visualizers/points3d.rs index 2d70126c2c5b..98e2ce7da604 100644 --- a/crates/re_space_view_spatial/src/visualizers/points3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points3d.rs @@ -1,7 +1,7 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; -use re_query_cache::range_zip_1x5; +use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points3D, @@ -215,7 +215,7 @@ impl VisualizerSystem for Points3DVisualizer { |ctx, entity_path, _entity_props, spatial_ctx, results| { re_tracing::profile_scope!(format!("{entity_path}")); - use crate::visualizers::CachedRangeResultsExt as _; + use crate::visualizers::RangeResultsExt as _; let resolver = ctx.recording().resolver(); diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs index 27474a9cc886..1b03697315b6 100644 --- a/crates/re_space_view_spatial/src/visualizers/results_ext.rs +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -1,7 +1,4 @@ -use re_query_cache::{ - CachedLatestAtResults, CachedRangeData, CachedRangeResults, CachedResults, PromiseResolver, - PromiseResult, -}; +use re_query::{LatestAtResults, PromiseResolver, PromiseResult, RangeData, RangeResults, Results}; use re_types::Component; // --- @@ -10,60 +7,56 @@ use re_types::Component; /// /// Also turns all results into range results, so that views only have to worry about the ranged /// case. -pub trait CachedRangeResultsExt { +pub trait RangeResultsExt { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>>; + ) -> Option>>; fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result>; + ) -> re_query::Result>; } -impl CachedRangeResultsExt for CachedResults { +impl RangeResultsExt for Results { fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { match self { - CachedResults::LatestAt(_, results) => results.get_dense(resolver), - CachedResults::Range(_, results) => results.get_dense(resolver), + Results::LatestAt(_, results) => results.get_dense(resolver), + Results::Range(_, results) => results.get_dense(resolver), } } fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query::Result> { match self { - CachedResults::LatestAt(_, results) => results.get_or_empty_dense(resolver), - CachedResults::Range(_, results) => results.get_or_empty_dense(resolver), + Results::LatestAt(_, results) => results.get_or_empty_dense(resolver), + Results::Range(_, results) => results.get_or_empty_dense(resolver), } } } -impl CachedRangeResultsExt for CachedRangeResults { +impl RangeResultsExt for RangeResults { #[inline] fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?.to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { - PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -74,17 +67,17 @@ impl CachedRangeResultsExt for CachedRangeResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query::Result> { let results = self.get_or_empty(C::name()).to_dense(resolver); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = results.status(); match front_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -92,27 +85,23 @@ impl CachedRangeResultsExt for CachedRangeResults { } } -impl CachedRangeResultsExt for CachedLatestAtResults { +impl RangeResultsExt for LatestAtResults { #[inline] fn get_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> Option>> { + ) -> Option>> { let results = self.get(C::name())?; - let data = CachedRangeData::from_latest_at(resolver, results); + let data = RangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); match front_status { - PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => { - return Some(Err(re_query_cache::QueryError::Other(err.into()))) - } + PromiseResult::Error(err) => return Some(Err(re_query::QueryError::Other(err.into()))), PromiseResult::Pending | PromiseResult::Ready(_) => {} } @@ -123,18 +112,18 @@ impl CachedRangeResultsExt for CachedLatestAtResults { fn get_or_empty_dense<'a, C: Component>( &'a self, resolver: &PromiseResolver, - ) -> re_query_cache::Result> { + ) -> re_query::Result> { let results = self.get_or_empty(C::name()); - let data = CachedRangeData::from_latest_at(resolver, results); + let data = RangeData::from_latest_at(resolver, results); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); match front_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } match back_status { - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Pending | PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_tensor/src/visualizer_system.rs b/crates/re_space_view_tensor/src/visualizer_system.rs index b22578d5da31..c0f0bfb05018 100644 --- a/crates/re_space_view_tensor/src/visualizer_system.rs +++ b/crates/re_space_view_tensor/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::CachedLatestAtMonoResult, EntityPath}; +use re_entity_db::{external::re_query::LatestAtMonoResult, EntityPath}; use re_log_types::RowId; use re_types::{archetypes::Tensor, components::TensorData, tensor_data::DecodedTensor}; use re_viewer_context::{ @@ -56,7 +56,7 @@ impl TensorSystem { &mut self, ctx: &ViewerContext<'_>, ent_path: &EntityPath, - tensor: CachedLatestAtMonoResult, + tensor: LatestAtMonoResult, ) { let row_id = tensor.row_id(); match ctx diff --git a/crates/re_space_view_text_document/Cargo.toml b/crates/re_space_view_text_document/Cargo.toml index b924d7ab60de..70a369abfa45 100644 --- a/crates/re_space_view_text_document/Cargo.toml +++ b/crates/re_space_view_text_document/Cargo.toml @@ -26,7 +26,6 @@ markdown = ["dep:egui_commonmark"] [dependencies] re_data_store.workspace = true re_log.workspace = true -re_query.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_text_document/src/visualizer_system.rs b/crates/re_space_view_text_document/src/visualizer_system.rs index 75e06692813c..057dc85b1aee 100644 --- a/crates/re_space_view_text_document/src/visualizer_system.rs +++ b/crates/re_space_view_text_document/src/visualizer_system.rs @@ -1,5 +1,5 @@ use re_data_store::LatestAtQuery; -use re_space_view::external::re_query_cache::PromiseResult; +use re_space_view::external::re_query::PromiseResult; use re_types::{archetypes::TextDocument, components}; use re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, diff --git a/crates/re_space_view_text_log/Cargo.toml b/crates/re_space_view_text_log/Cargo.toml index d1343494859e..0d277c329970 100644 --- a/crates/re_space_view_text_log/Cargo.toml +++ b/crates/re_space_view_text_log/Cargo.toml @@ -24,7 +24,7 @@ re_data_ui.workspace = true re_entity_db.workspace = true re_log_types.workspace = true re_log.workspace = true -re_query_cache.workspace = true +re_query.workspace = true re_renderer.workspace = true re_tracing.workspace = true re_types.workspace = true diff --git a/crates/re_space_view_text_log/src/visualizer_system.rs b/crates/re_space_view_text_log/src/visualizer_system.rs index a06212b65488..642a4a023309 100644 --- a/crates/re_space_view_text_log/src/visualizer_system.rs +++ b/crates/re_space_view_text_log/src/visualizer_system.rs @@ -1,7 +1,7 @@ use re_data_store::TimeRange; use re_entity_db::EntityPath; use re_log_types::{RowId, TimeInt}; -use re_query_cache::{clamped_zip_1x2, range_zip_1x2, CachedRangeData, PromiseResult}; +use re_query::{clamped_zip_1x2, range_zip_1x2, PromiseResult, RangeData}; use re_types::{ archetypes::TextLog, components::{Color, Text, TextLogLevel}, @@ -127,18 +127,16 @@ impl VisualizerSystem for TextLogSystem { // TODO(#5607): what should happen if the promise is still pending? #[inline] -fn check_range<'a, C: Component>( - results: &'a CachedRangeData<'a, C>, -) -> re_query_cache::Result<()> { +fn check_range<'a, C: Component>(results: &'a RangeData<'a, C>) -> re_query::Result<()> { let (front_status, back_status) = results.status(); match front_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } match back_status { PromiseResult::Pending => return Ok(()), - PromiseResult::Error(err) => return Err(re_query_cache::QueryError::Other(err.into())), + PromiseResult::Error(err) => return Err(re_query::QueryError::Other(err.into())), PromiseResult::Ready(_) => {} } diff --git a/crates/re_space_view_time_series/Cargo.toml b/crates/re_space_view_time_series/Cargo.toml index 16faadc51266..bcbfc845c815 100644 --- a/crates/re_space_view_time_series/Cargo.toml +++ b/crates/re_space_view_time_series/Cargo.toml @@ -24,7 +24,6 @@ re_format.workspace = true re_log.workspace = true re_log_types.workspace = true re_query.workspace = true -re_query_cache.workspace = true re_renderer.workspace = true re_space_view.workspace = true re_tracing.workspace = true diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 814f7369d249..5525f0ec0db8 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -1,5 +1,5 @@ use itertools::Itertools as _; -use re_query_cache::{PromiseResult, QueryError}; +use re_query::{PromiseResult, QueryError}; use re_types::archetypes; use re_types::{ archetypes::SeriesLine, @@ -259,7 +259,7 @@ fn load_series( .map(|index| (index, ())); let all_frames = - re_query_cache::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) + re_query::range_zip_1x1(all_scalars_indexed, all_colors.range_indexed()) .enumerate(); for (i, (_index, _scalars, colors)) in all_frames { @@ -296,11 +296,9 @@ fn load_series( .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( - all_scalars_indexed, - all_stroke_widths.range_indexed(), - ) - .enumerate(); + let all_frames = + re_query::range_zip_1x1(all_scalars_indexed, all_stroke_widths.range_indexed()) + .enumerate(); for (i, (_index, _scalars, stroke_widths)) in all_frames { if let Some(stroke_width) = diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 6b5b0c997ed7..6bfeca20cd0e 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -1,6 +1,6 @@ use itertools::Itertools as _; -use re_query_cache::{PromiseResult, QueryError}; +use re_query::{PromiseResult, QueryError}; use re_types::{ archetypes::{self, SeriesPoint}, components::{Color, MarkerShape, MarkerSize, Name, Scalar}, @@ -217,7 +217,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_colors.range_indexed(), ) @@ -257,7 +257,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_marker_sizes.range_indexed(), ) @@ -289,7 +289,7 @@ impl SeriesPointSystem { .range_indices(all_scalars_entry_range.clone()) .map(|index| (index, ())); - let all_frames = re_query_cache::range_zip_1x1( + let all_frames = re_query::range_zip_1x1( all_scalars_indexed, all_marker_shapes.range_indexed(), ) diff --git a/crates/re_types_builder/src/codegen/rust/to_archetype.rs b/crates/re_types_builder/src/codegen/rust/to_archetype.rs index fac93e1fed22..af38e603a5d8 100644 --- a/crates/re_types_builder/src/codegen/rust/to_archetype.rs +++ b/crates/re_types_builder/src/codegen/rust/to_archetype.rs @@ -1,4 +1,4 @@ -//! Generates code in `re_query_cache` so that cached results can easily be converted to +//! Generates code in `re_query` so that cached results can easily be converted to //! ready-to-use archetypes. //! //! That code needs to be generated directly in the caching crates as it needs access to the cached @@ -34,8 +34,7 @@ fn generate_mod( objects: &Objects, files_to_write: &mut BTreeMap, ) { - let generated_path = - Utf8PathBuf::from("crates/re_query_cache/src/latest_at/to_archetype/mod.rs"); + let generated_path = Utf8PathBuf::from("crates/re_query/src/latest_at/to_archetype/mod.rs"); let mut code = String::new(); code.push_str(&format!("// {}\n\n", crate::codegen::autogen_warning!())); @@ -62,15 +61,14 @@ fn generate_impls( objects: &Objects, files_to_write: &mut BTreeMap, ) { - let generated_path = Utf8PathBuf::from("crates/re_query_cache/src/latest_at/to_archetype"); + let generated_path = Utf8PathBuf::from("crates/re_query/src/latest_at/to_archetype"); let quoted_imports = quote! { use std::sync::Arc; - use re_query2::{PromiseResolver, PromiseResult}; use re_types_core::{Archetype, Loggable as _}; - use crate::CachedLatestAtResults; + use crate::{LatestAtResults, PromiseResolver, PromiseResult}; }; for obj in objects.ordered_objects(Some(ObjectKind::Archetype)) { @@ -239,7 +237,7 @@ fn quote_to_archetype_impl(objects: &Objects, obj: &Object) -> TokenStream { }); quote! { - impl crate::ToArchetype<#quoted_arch_fqname> for CachedLatestAtResults { + impl crate::ToArchetype<#quoted_arch_fqname> for LatestAtResults { #[inline] fn to_archetype( &self, diff --git a/crates/re_viewer/Cargo.toml b/crates/re_viewer/Cargo.toml index 2168bec9fe30..3db7e4dcebef 100644 --- a/crates/re_viewer/Cargo.toml +++ b/crates/re_viewer/Cargo.toml @@ -53,7 +53,7 @@ re_log_encoding = { workspace = true, features = [ ] } re_log_types.workspace = true re_memory.workspace = true -re_query_cache.workspace = true +re_query.workspace = true re_renderer = { workspace = true, default-features = false } re_smart_channel.workspace = true re_space_view.workspace = true diff --git a/crates/re_viewer/src/lib.rs b/crates/re_viewer/src/lib.rs index 85b2747bf3e1..54344896001c 100644 --- a/crates/re_viewer/src/lib.rs +++ b/crates/re_viewer/src/lib.rs @@ -34,8 +34,8 @@ pub mod external { pub use {eframe, egui}; pub use { re_data_store, re_data_store::external::*, re_entity_db, re_log, re_log_types, re_memory, - re_query_cache, re_renderer, re_types, re_ui, re_viewer_context, - re_viewer_context::external::*, re_viewport, re_viewport::external::*, + re_query, re_renderer, re_types, re_ui, re_viewer_context, re_viewer_context::external::*, + re_viewport, re_viewport::external::*, }; } diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index d60b680732b3..e7a434e77cb0 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -2,7 +2,7 @@ use itertools::Itertools; use re_data_store::{DataStoreConfig, DataStoreRowStats, DataStoreStats}; use re_format::{format_bytes, format_uint}; use re_memory::{util::sec_since_start, MemoryHistory, MemoryLimit, MemoryUse}; -use re_query_cache::{CachedComponentStats, CachesStats}; +use re_query::{CachedComponentStats, CachesStats}; use re_renderer::WgpuResourcePoolStatistics; use re_viewer_context::store_hub::StoreHubStats; diff --git a/crates/re_viewer_context/Cargo.toml b/crates/re_viewer_context/Cargo.toml index 835b3c5aec4c..f90f05f6eb63 100644 --- a/crates/re_viewer_context/Cargo.toml +++ b/crates/re_viewer_context/Cargo.toml @@ -24,7 +24,6 @@ re_data_store.workspace = true re_entity_db = { workspace = true, features = ["serde"] } re_log_types.workspace = true re_log.workspace = true -re_query_cache.workspace = true re_query.workspace = true re_renderer.workspace = true re_smart_channel.workspace = true diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 85acff5c5f77..756870c051ea 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -1,9 +1,7 @@ use std::collections::BTreeMap; use re_data_store::LatestAtQuery; -use re_entity_db::{ - external::re_query_cache::CachedLatestAtComponentResults, EntityDb, EntityPath, -}; +use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb, EntityPath}; use re_log_types::DataCell; use re_types::{components::InstanceKey, ComponentName, Loggable as _}; @@ -42,7 +40,7 @@ type ComponentUiCallback = Box< &LatestAtQuery, &EntityDb, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &InstanceKey, ) + Send + Sync, @@ -57,7 +55,7 @@ type ComponentEditCallback = Box< &EntityDb, &EntityPath, &EntityPath, - &CachedLatestAtComponentResults, + &LatestAtComponentResults, &InstanceKey, ) + Send + Sync, @@ -122,7 +120,7 @@ impl ComponentUiRegistry { query: &LatestAtQuery, db: &EntityDb, entity_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &InstanceKey, ) { let Some(component_name) = component.component_name(db.resolver()) else { @@ -165,7 +163,7 @@ impl ComponentUiRegistry { db: &EntityDb, entity_path: &EntityPath, override_path: &EntityPath, - component: &CachedLatestAtComponentResults, + component: &LatestAtComponentResults, instance_key: &InstanceKey, ) { let Some(component_name) = component.component_name(db.resolver()) else { diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 0d21d88d3dfd..3fbdee8ca299 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -199,8 +199,7 @@ pub fn resolve_mono_instance_path( [component], ); if let Some(results) = results.get(component) { - if let re_query_cache::PromiseResult::Ready(cell) = - results.resolved(entity_db.resolver()) + if let re_query::PromiseResult::Ready(cell) = results.resolved(entity_db.resolver()) { if cell.num_instances() > 1 { return instance.clone(); diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index 17632a2aa4ff..b4da1ba5f82b 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -48,9 +48,6 @@ pub enum SpaceViewSystemExecutionError { #[error(transparent)] QueryError(#[from] re_query::QueryError), - #[error(transparent)] - QueryError2(#[from] re_query_cache::QueryError), - #[error(transparent)] DeserializationError(#[from] re_types::DeserializationError), diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index f90c08ee3611..0160a1a14915 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -7,7 +7,7 @@ use re_data_store::StoreGeneration; use re_data_store::{DataStoreConfig, DataStoreStats}; use re_entity_db::{EntityDb, StoreBundle}; use re_log_types::{ApplicationId, StoreId, StoreKind}; -use re_query_cache::CachesStats; +use re_query::CachesStats; use crate::StoreContext; diff --git a/crates/re_viewport/src/container.rs b/crates/re_viewport/src/container.rs index b5e2381ef41f..15a2f3b83011 100644 --- a/crates/re_viewport/src/container.rs +++ b/crates/re_viewport/src/container.rs @@ -2,7 +2,7 @@ use ahash::HashMap; use egui_tiles::TileId; use re_data_store::LatestAtQuery; -use re_entity_db::{external::re_query_cache::PromiseResult, EntityDb}; +use re_entity_db::{external::re_query::PromiseResult, EntityDb}; use re_log::ResultExt; use re_log_types::{DataRow, EntityPath, RowId}; use re_types::blueprint::components::Visible; diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index f0cb5f83d587..e608e63a6805 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -7,7 +7,7 @@ use nohash_hasher::IntSet; use smallvec::SmallVec; use re_data_store::LatestAtQuery; -use re_entity_db::external::re_query_cache::PromiseResult; +use re_entity_db::external::re_query::PromiseResult; use re_entity_db::EntityPath; use re_space_view::SpaceViewBlueprint; use re_types::blueprint::components::ViewerRecommendationHash; diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index 32d7f1bd44a0..0b773c3de1ca 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -14,7 +14,7 @@ analytics = ["re_crash_handler/analytics", "re_viewer/analytics"] [dependencies] re_crash_handler = { path = "../../../crates/re_crash_handler" } -re_query2 = { path = "../../../crates/re_query2" } +re_query = { path = "../../../crates/re_query" } re_viewer = { path = "../../../crates/re_viewer", default-features = false } # We need re_sdk_comms to receive log events from and SDK: diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index a90e12136fb1..07ef8f083bde 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -1,7 +1,7 @@ use re_viewer::external::{ egui, re_log_types::EntityPath, - re_query_cache, re_renderer, + re_query, re_renderer, re_types::{ self, components::{Color, InstanceKey}, @@ -38,13 +38,13 @@ impl re_types::Archetype for ColorArchetype { } } -impl re_query2::ToArchetype for re_query_cache::CachedLatestAtResults { +impl re_query::ToArchetype for re_query::LatestAtResults { #[inline] fn to_archetype( &self, - _resolver: &re_query2::PromiseResolver, - ) -> re_query2::PromiseResult> { - re_query2::PromiseResult::Ready(Ok(ColorArchetype)) + _resolver: &re_query::PromiseResolver, + ) -> re_query::PromiseResult> { + re_query::PromiseResult::Ready(Ok(ColorArchetype)) } } @@ -70,7 +70,7 @@ impl VisualizerSystem for InstanceColorSystem { for data_result in query.iter_visible_data_results(ctx, Self::identifier()) { // …gather all colors and their instance ids. - let results = re_query2::latest_at( + let results = ctx.recording().query_caches().latest_at( ctx.recording_store(), &ctx.current_query(), &data_result.entity_path, diff --git a/scripts/lint.py b/scripts/lint.py index 51cf334d17db..5cf77fb98bd2 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -979,9 +979,6 @@ def lint_file(filepath: str, args: Any) -> int: def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: """Make sure ARCHITECTURE.md talks about every single crate we have.""" - # These crates will replace existing ones and won't ever be published as-is. - tmp_crates = ["re_query2"] - crates_dir = Path("crates") architecture_md_file = Path("ARCHITECTURE.md") @@ -1002,9 +999,6 @@ def lint_crate_docs(should_ignore: Callable[[Any], bool]) -> int: if crate_name in listed_crates: del listed_crates[crate_name] - if should_ignore(crate) or crate.name in tmp_crates: - continue - if not re.search(r"\b" + crate_name + r"\b", architecture_md): print(f"{architecture_md_file}: missing documentation for crate {crate.name}") error_count += 1 From bc04e355dcd1754d84243ba5b7ae81526d575e16 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 12:47:20 +0200 Subject: [PATCH 374/508] New data APIs 16 (final?!): introduce non-cacheable components (#6037) Make it possible to not cache some components, all while pretending really hard that they've been cached. - Related: #5974 --- Part of a PR series to completely revamp the data APIs in preparation for the removal of instance keys and the introduction of promises: - #5573 - #5574 - #5581 - #5605 - #5606 - #5633 - #5673 - #5679 - #5687 - #5755 - #5990 - #5992 - #5993 - #5994 - #6035 - #6036 - #6037 Builds on top of the static data PR series: - #5534 --- crates/re_query/src/latest_at/query.rs | 19 +++++++++++----- crates/re_query/src/lib.rs | 31 ++++++++++++++++++++++++++ crates/re_query/src/range/query.rs | 18 ++++++++++----- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/crates/re_query/src/latest_at/query.rs b/crates/re_query/src/latest_at/query.rs index b4ca7cdfe059..8107647fc3a1 100644 --- a/crates/re_query/src/latest_at/query.rs +++ b/crates/re_query/src/latest_at/query.rs @@ -33,12 +33,19 @@ impl Caches { for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); - let cache = Arc::clone( - self.latest_at_per_cache_key - .write() - .entry(key.clone()) - .or_insert_with(|| Arc::new(RwLock::new(LatestAtCache::new(key.clone())))), - ); + + let cache = if crate::cacheable(component_name) { + Arc::clone( + self.latest_at_per_cache_key + .write() + .entry(key.clone()) + .or_insert_with(|| Arc::new(RwLock::new(LatestAtCache::new(key.clone())))), + ) + } else { + // If the component shouldn't be cached, simply instantiate a new cache for it. + // It will be dropped when the user is done with it. + Arc::new(RwLock::new(LatestAtCache::new(key.clone()))) + }; let mut cache = cache.write(); cache.handle_pending_invalidation(); diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs index d75b866986dd..1f6d81b4d3b0 100644 --- a/crates/re_query/src/lib.rs +++ b/crates/re_query/src/lib.rs @@ -117,3 +117,34 @@ impl From<(RangeQuery, RangeResults)> for Results { Self::Range(query, results) } } + +// --- + +/// Returns `true` if the specified `component_name` can be cached. +/// +/// Used internally to avoid unnecessarily caching components that are already cached in other +/// places, for historical reasons. +pub fn cacheable(component_name: re_types::ComponentName) -> bool { + use std::sync::OnceLock; + static NOT_CACHEABLE: OnceLock = OnceLock::new(); + + use re_types_core::Loggable as _; + let not_cacheable = NOT_CACHEABLE.get_or_init(|| { + [ + // TODO(#5303): instance keys are on their way out anyhow. + re_types::components::InstanceKey::name(), + // TODO(#5974): tensors might already be cached in the ad-hoc JPEG cache, we don't + // want yet another copy. + re_types::components::TensorData::name(), + // TODO(#5974): meshes are already cached in the ad-hoc mesh cache, we don't + // want yet another copy. + re_types::components::MeshProperties::name(), + // TODO(#5974): blobs are used for assets, which are themselves already cached in + // the ad-hoc mesh cache -- we don't want yet another copy. + re_types::components::Blob::name(), + ] + .into() + }); + + !component_name.is_indicator_component() && !not_cacheable.contains(&component_name) +} diff --git a/crates/re_query/src/range/query.rs b/crates/re_query/src/range/query.rs index 649aa7ef8700..28277cc16e94 100644 --- a/crates/re_query/src/range/query.rs +++ b/crates/re_query/src/range/query.rs @@ -33,12 +33,18 @@ impl Caches { for component_name in component_names { let key = CacheKey::new(entity_path.clone(), query.timeline(), component_name); - let cache = Arc::clone( - self.range_per_cache_key - .write() - .entry(key.clone()) - .or_insert_with(|| Arc::new(RwLock::new(RangeCache::new(key.clone())))), - ); + let cache = if crate::cacheable(component_name) { + Arc::clone( + self.range_per_cache_key + .write() + .entry(key.clone()) + .or_insert_with(|| Arc::new(RwLock::new(RangeCache::new(key.clone())))), + ) + } else { + // If the component shouldn't be cached, simply instantiate a new cache for it. + // It will be dropped when the user is done with it. + Arc::new(RwLock::new(RangeCache::new(key.clone()))) + }; let mut cache = cache.write(); cache.handle_pending_invalidation(); From 893de2f4cf48ea0b16dba9aef47c772169e0e7b5 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 13:03:18 +0200 Subject: [PATCH 375/508] Remove instance keys and explicit splatting everywhere (#6104) Annihilate everything related to instance keys. --- - [x] Remove `InstanceKey` - [x] Remove `NumInstances` - [x] Remove explicit/client-side splats - [x] Remove cluster keys and autogenerated cells - [x] Clean up every other little thing related to any of the above - [x] Update batching docs - [x] Check that Kiss-ICP now works smoothly - [x] Check roundtrips - [x] Check `rerun snippets/*.rrd` - [x] Rebase and run checklist - [x] Run full check bot --- Findings (none blocking, not sure any are new -- to be investigated later): - Depth clouds with visible history are broken in a different way than before - `OutOfTreeTransform` might be broken? (see associated snippet) - Does `DisconnectedSpace` even work? (see associated snippet) - Is something wrong with labels when there are lots of instances? --- - Fixes #5303 - Fixes #1014 - Fixes #1777 - Fixes #1793 - Fixes #1893 - Fixes #5685 - Fixes #1014 --- crates/re_data_store/benches/arrow2.rs | 19 +- crates/re_data_store/benches/data_store.rs | 16 +- crates/re_data_store/benches/gc.rs | 14 +- crates/re_data_store/src/lib.rs | 3 +- crates/re_data_store/src/store.rs | 93 +--------- crates/re_data_store/src/store_arrow.rs | 61 +----- crates/re_data_store/src/store_dump.rs | 29 +-- crates/re_data_store/src/store_event.rs | 76 ++------ crates/re_data_store/src/store_format.rs | 7 - crates/re_data_store/src/store_gc.rs | 88 ++------- crates/re_data_store/src/store_helpers.rs | 2 - crates/re_data_store/src/store_read.rs | 42 +---- crates/re_data_store/src/store_sanity.rs | 33 +--- crates/re_data_store/src/store_stats.rs | 28 +-- crates/re_data_store/src/store_subscriber.rs | 9 +- crates/re_data_store/src/store_write.rs | 159 ++-------------- crates/re_data_store/src/test_util.rs | 9 +- crates/re_data_store/tests/correctness.rs | 104 ++--------- crates/re_data_store/tests/data_store.rs | 122 +++++------- crates/re_data_store/tests/dump.rs | 36 ++-- crates/re_data_store/tests/internals.rs | 17 +- crates/re_data_store/tests/memory_test.rs | 6 +- crates/re_data_ui/src/component.rs | 11 +- .../re_data_ui/src/component_ui_registry.rs | 9 +- crates/re_data_ui/src/editors.rs | 36 ++-- crates/re_data_ui/src/entity_path.rs | 2 +- crates/re_data_ui/src/instance_path.rs | 6 +- crates/re_data_ui/src/item_ui.rs | 30 ++- crates/re_data_ui/src/lib.rs | 2 +- crates/re_entity_db/examples/memory_usage.rs | 2 - crates/re_entity_db/src/entity_db.rs | 11 +- crates/re_entity_db/src/instance_path.rs | 73 ++++---- .../src/versioned_instance_path.rs | 10 +- crates/re_entity_db/tests/clear.rs | 21 +-- crates/re_entity_db/tests/time_histograms.rs | 50 +++-- .../benches/msg_encode_benchmark.rs | 3 - crates/re_log_types/src/data_cell.rs | 39 ---- crates/re_log_types/src/data_row.rs | 49 +---- crates/re_log_types/src/data_table.rs | 105 +++-------- crates/re_log_types/src/example_components.rs | 63 ++++++- crates/re_log_types/src/instance.rs | 80 ++++++++ crates/re_log_types/src/lib.rs | 21 ++- crates/re_log_types/src/num_instances.rs | 92 --------- crates/re_log_types/src/path/data_path.rs | 16 +- crates/re_log_types/src/path/parse_path.rs | 60 +++--- crates/re_query/benches/latest_at.rs | 5 +- crates/re_query/examples/latest_at.rs | 7 +- .../re_query/examples/latest_at_archetype.rs | 9 +- crates/re_query/examples/range.rs | 11 +- crates/re_query/src/latest_at/results.rs | 9 +- crates/re_query/src/lib.rs | 2 - crates/re_query/tests/latest_at.rs | 60 ++---- crates/re_query/tests/range.rs | 61 ++---- crates/re_sdk/src/lib.rs | 2 +- crates/re_sdk/src/recording_stream.rs | 52 +----- crates/re_space_view/src/space_view.rs | 2 - crates/re_space_view/src/sub_archetypes.rs | 3 +- .../src/space_view_class.rs | 24 +-- .../src/instance_hash_conversions.rs | 12 +- crates/re_space_view_spatial/src/picking.rs | 4 +- crates/re_space_view_spatial/src/ui.rs | 15 +- .../src/visualizers/arrows2d.rs | 11 +- .../src/visualizers/arrows3d.rs | 11 +- .../src/visualizers/assets3d.rs | 8 +- .../src/visualizers/boxes2d.rs | 11 +- .../src/visualizers/boxes3d.rs | 16 +- .../src/visualizers/cameras.rs | 9 +- .../src/visualizers/lines2d.rs | 11 +- .../src/visualizers/lines3d.rs | 11 +- .../src/visualizers/meshes.rs | 9 +- .../src/visualizers/mod.rs | 6 +- .../src/visualizers/points2d.rs | 10 +- .../src/visualizers/points3d.rs | 10 +- .../src/visualizers/transform3d_arrows.rs | 6 +- .../re_time_panel/src/data_density_graph.rs | 2 +- crates/re_time_panel/src/lib.rs | 2 +- .../re_types/definitions/rerun/components.fbs | 1 - .../rerun/components/instance_key.fbs | 30 --- .../src/archetypes/annotation_context.rs | 14 +- crates/re_types/src/archetypes/arrows2d.rs | 13 +- crates/re_types/src/archetypes/arrows3d.rs | 13 +- crates/re_types/src/archetypes/asset3d.rs | 19 +- crates/re_types/src/archetypes/bar_chart.rs | 19 +- crates/re_types/src/archetypes/boxes2d.rs | 13 +- crates/re_types/src/archetypes/boxes3d.rs | 13 +- crates/re_types/src/archetypes/depth_image.rs | 13 +- .../src/archetypes/disconnected_space.rs | 14 +- crates/re_types/src/archetypes/image.rs | 19 +- .../re_types/src/archetypes/line_strips2d.rs | 13 +- .../re_types/src/archetypes/line_strips3d.rs | 13 +- crates/re_types/src/archetypes/mesh3d.rs | 13 +- crates/re_types/src/archetypes/pinhole.rs | 19 +- crates/re_types/src/archetypes/points2d.rs | 13 +- crates/re_types/src/archetypes/points3d.rs | 13 +- crates/re_types/src/archetypes/scalar.rs | 14 +- .../src/archetypes/segmentation_image.rs | 19 +- crates/re_types/src/archetypes/series_line.rs | 13 +- .../re_types/src/archetypes/series_point.rs | 13 +- crates/re_types/src/archetypes/tensor.rs | 14 +- .../re_types/src/archetypes/text_document.rs | 19 +- crates/re_types/src/archetypes/text_log.rs | 19 +- crates/re_types/src/archetypes/transform3d.rs | 14 +- .../src/archetypes/view_coordinates.rs | 14 +- .../src/blueprint/archetypes/background.rs | 19 +- .../src/blueprint/archetypes/plot_legend.rs | 13 +- .../src/blueprint/archetypes/scalar_axis.rs | 13 +- .../archetypes/space_view_blueprint.rs | 13 +- .../archetypes/space_view_contents.rs | 19 +- crates/re_types/src/datagen.rs | 25 --- crates/re_types/src/lib.rs | 16 +- .../src/testing/archetypes/affix_fuzzer1.rs | 14 +- .../src/testing/archetypes/affix_fuzzer2.rs | 14 +- .../src/testing/archetypes/affix_fuzzer3.rs | 13 +- .../src/testing/archetypes/affix_fuzzer4.rs | 13 +- .../archetypes/container_blueprint.rs | 13 +- .../blueprint/archetypes/panel_blueprint.rs | 19 +- .../archetypes/viewport_blueprint.rs | 13 +- .../re_types_builder/src/codegen/cpp/mod.rs | 27 --- .../re_types_builder/src/codegen/rust/api.rs | 32 +--- crates/re_types_core/src/archetype.rs | 2 +- crates/re_types_core/src/archetypes/clear.rs | 14 +- .../src/components/.gitattributes | 1 - .../src/components/instance_key.rs | 174 ------------------ .../src/components/instance_key_ext.rs | 60 ------ crates/re_types_core/src/components/mod.rs | 3 - crates/re_types_core/src/lib.rs | 13 -- crates/re_ui/src/syntax_highlighting.rs | 14 +- crates/re_viewer/src/app_blueprint.rs | 9 +- crates/re_viewer/src/ui/memory_panel.rs | 6 - crates/re_viewer/src/ui/override_ui.rs | 26 +-- crates/re_viewer/src/ui/selection_panel.rs | 8 +- .../src/blueprint_helpers.rs | 36 +--- .../src/component_ui_registry.rs | 24 +-- crates/re_viewer_context/src/item.rs | 34 ++-- .../re_viewer_context/src/selection_state.rs | 12 +- .../src/space_view/highlights.rs | 29 ++- .../actions/collapse_expand_all.rs | 2 +- .../src/context_menu/actions/remove.rs | 2 +- .../src/context_menu/actions/show_hide.rs | 2 +- .../src/space_view_entity_picker.rs | 2 +- .../re_viewport/src/viewport_blueprint_ui.rs | 6 +- crates/rerun/src/sdk.rs | 6 +- crates/rerun_c/src/lib.rs | 7 +- crates/rerun_c/src/rerun.h | 4 - docs/content/concepts/batches.md | 19 +- docs/content/getting-started/data-in/cpp.md | 2 +- .../content/getting-started/data-in/python.md | 2 +- docs/content/getting-started/data-in/rust.md | 2 +- docs/content/reference/types/components.md | 1 - .../reference/types/components/.gitattributes | 1 - .../types/components/instance_key.md | 23 --- docs/snippets/all/custom_data.py | 2 +- .../src/color_coordinates_space_view.rs | 14 +- .../color_coordinates_visualizer_system.rs | 20 +- rerun_cpp/src/rerun.hpp | 1 - .../rerun/archetypes/annotation_context.hpp | 5 - rerun_cpp/src/rerun/archetypes/arrows2d.hpp | 5 - rerun_cpp/src/rerun/archetypes/arrows3d.hpp | 5 - rerun_cpp/src/rerun/archetypes/asset3d.hpp | 5 - rerun_cpp/src/rerun/archetypes/bar_chart.hpp | 5 - rerun_cpp/src/rerun/archetypes/boxes2d.hpp | 5 - rerun_cpp/src/rerun/archetypes/boxes3d.hpp | 5 - rerun_cpp/src/rerun/archetypes/clear.hpp | 5 - .../src/rerun/archetypes/depth_image.hpp | 5 - .../rerun/archetypes/disconnected_space.hpp | 5 - rerun_cpp/src/rerun/archetypes/image.hpp | 5 - .../src/rerun/archetypes/line_strips2d.hpp | 5 - .../src/rerun/archetypes/line_strips3d.hpp | 5 - rerun_cpp/src/rerun/archetypes/mesh3d.hpp | 5 - rerun_cpp/src/rerun/archetypes/pinhole.hpp | 5 - rerun_cpp/src/rerun/archetypes/points2d.hpp | 5 - rerun_cpp/src/rerun/archetypes/points3d.hpp | 5 - rerun_cpp/src/rerun/archetypes/scalar.hpp | 5 - .../rerun/archetypes/segmentation_image.hpp | 5 - .../src/rerun/archetypes/series_line.hpp | 5 - .../src/rerun/archetypes/series_point.hpp | 5 - rerun_cpp/src/rerun/archetypes/tensor.hpp | 5 - .../src/rerun/archetypes/text_document.hpp | 5 - rerun_cpp/src/rerun/archetypes/text_log.hpp | 5 - .../src/rerun/archetypes/transform3d.hpp | 5 - .../src/rerun/archetypes/view_coordinates.hpp | 5 - .../rerun/blueprint/archetypes/background.hpp | 5 - .../archetypes/container_blueprint.hpp | 5 - .../blueprint/archetypes/panel_blueprint.hpp | 5 - .../blueprint/archetypes/plot_legend.hpp | 5 - .../blueprint/archetypes/scalar_axis.hpp | 5 - .../archetypes/space_view_blueprint.hpp | 5 - .../archetypes/space_view_contents.hpp | 5 - .../archetypes/viewport_blueprint.hpp | 5 - rerun_cpp/src/rerun/c/rerun.h | 4 - rerun_cpp/src/rerun/components.hpp | 1 - rerun_cpp/src/rerun/components/.gitattributes | 2 - .../src/rerun/components/instance_key.cpp | 57 ------ .../src/rerun/components/instance_key.hpp | 69 ------- rerun_cpp/src/rerun/recording_stream.cpp | 38 +--- rerun_cpp/src/rerun/recording_stream.hpp | 6 +- .../generated/archetypes/affix_fuzzer1.hpp | 5 - .../generated/archetypes/affix_fuzzer2.hpp | 5 - .../generated/archetypes/affix_fuzzer3.hpp | 5 - .../generated/archetypes/affix_fuzzer4.hpp | 5 - rerun_cpp/tests/recording_stream.cpp | 4 +- rerun_py/rerun_sdk/rerun/_baseclasses.py | 7 +- rerun_py/rerun_sdk/rerun/_log.py | 24 +-- rerun_py/rerun_sdk/rerun/any_value.py | 3 - .../rerun_sdk/rerun/components/.gitattributes | 1 - .../rerun_sdk/rerun/components/__init__.py | 6 - .../rerun/components/instance_key.py | 70 ------- .../rerun/components/instance_key_ext.py | 18 -- rerun_py/src/arrow.rs | 11 +- tests/python/test_api/test_api.py | 1 - 210 files changed, 933 insertions(+), 3017 deletions(-) create mode 100644 crates/re_log_types/src/instance.rs delete mode 100644 crates/re_log_types/src/num_instances.rs delete mode 100644 crates/re_types/definitions/rerun/components/instance_key.fbs delete mode 100644 crates/re_types_core/src/components/instance_key.rs delete mode 100644 crates/re_types_core/src/components/instance_key_ext.rs delete mode 100644 docs/content/reference/types/components/instance_key.md delete mode 100644 rerun_cpp/src/rerun/components/instance_key.cpp delete mode 100644 rerun_cpp/src/rerun/components/instance_key.hpp delete mode 100644 rerun_py/rerun_sdk/rerun/components/instance_key.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/instance_key_ext.py diff --git a/crates/re_data_store/benches/arrow2.rs b/crates/re_data_store/benches/arrow2.rs index dee0628802d0..236e3db60c3f 100644 --- a/crates/re_data_store/benches/arrow2.rs +++ b/crates/re_data_store/benches/arrow2.rs @@ -9,10 +9,11 @@ use arrow2::array::{Array, FixedSizeListArray, PrimitiveArray, StructArray}; use criterion::Criterion; use itertools::Itertools; +use re_log_types::example_components::MyIndex; use re_log_types::DataCell; -use re_types::datagen::{build_some_instances, build_some_positions2d}; +use re_types::datagen::build_some_positions2d; use re_types::{ - components::{InstanceKey, Position2D}, + components::Position2D, testing::{build_some_large_structs, LargeStruct}, }; use re_types_core::{Component, SizeBytes}; @@ -40,7 +41,7 @@ const NUM_INSTANCES: usize = 1; #[derive(Debug, Clone, Copy)] enum ArrayKind { - /// E.g. an array of `InstanceKey`. + /// E.g. an array of `MyIndex`. Primitive, /// E.g. an array of `Position2D`. @@ -79,7 +80,7 @@ fn erased_clone(c: &mut Criterion) { match kind { ArrayKind::Primitive => { - let data = build_some_instances(NUM_INSTANCES); + let data = MyIndex::from_iter(0..NUM_INSTANCES as _); bench_arrow(&mut group, &data); bench_native(&mut group, &data); } @@ -198,7 +199,9 @@ fn estimated_size_bytes(c: &mut Criterion) { fn generate_cells(kind: ArrayKind) -> Vec { match kind { ArrayKind::Primitive => (0..NUM_ROWS) - .map(|_| DataCell::from_native(build_some_instances(NUM_INSTANCES).as_slice())) + .map(|_| { + DataCell::from_native(MyIndex::from_iter(0..NUM_INSTANCES as _).as_slice()) + }) .collect(), ArrayKind::Struct => (0..NUM_ROWS) .map(|_| { @@ -312,9 +315,9 @@ fn estimated_size_bytes(c: &mut Criterion) { .collect() } - fn generate_keys() -> Vec> { + fn generate_indices() -> Vec> { (0..NUM_ROWS) - .map(|_| build_some_instances(NUM_INSTANCES)) + .map(|_| MyIndex::from_iter(0..NUM_INSTANCES as _)) .collect() } @@ -325,7 +328,7 @@ fn estimated_size_bytes(c: &mut Criterion) { } match kind { - ArrayKind::Primitive => bench_std(&mut group, generate_keys()), + ArrayKind::Primitive => bench_std(&mut group, generate_indices()), ArrayKind::Struct => bench_std(&mut group, generate_positions()), ArrayKind::StructLarge => bench_std(&mut group, generate_rects()), } diff --git a/crates/re_data_store/benches/data_store.rs b/crates/re_data_store/benches/data_store.rs index 8b95671180a3..4d6b81cb3333 100644 --- a/crates/re_data_store/benches/data_store.rs +++ b/crates/re_data_store/benches/data_store.rs @@ -9,14 +9,10 @@ use re_data_store::{ RangeQuery, TimeInt, TimeRange, }; use re_log_types::{ - build_frame_nr, DataCell, DataRow, DataTable, EntityPath, RowId, TableId, TimePoint, TimeType, - Timeline, -}; -use re_types::datagen::build_some_instances; -use re_types::{ - components::InstanceKey, - testing::{build_some_large_structs, LargeStruct}, + build_frame_nr, example_components::MyIndex, DataCell, DataRow, DataTable, EntityPath, RowId, + TableId, TimePoint, TimeType, Timeline, }; +use re_types::testing::{build_some_large_structs, LargeStruct}; use re_types_core::{ComponentName, Loggable as _}; criterion_group!( @@ -123,7 +119,6 @@ fn insert_same_time_point(c: &mut Criterion) { b.iter(|| { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), DataStoreConfig::default(), ); @@ -398,9 +393,8 @@ fn build_rows_ex( RowId::new(), "large_structs", time_point(frame_idx), - num_instances as _, ( - build_some_instances(num_instances), + MyIndex::from_iter(0..num_instances as _), build_some_large_structs(num_instances), ), ) @@ -432,10 +426,8 @@ fn build_rows_ex( } fn insert_rows(config: DataStoreConfig, rows: &[DataRow]) -> DataStore { - let cluster_key = InstanceKey::name(); let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - cluster_key, config, ); for row in rows { diff --git a/crates/re_data_store/benches/gc.rs b/crates/re_data_store/benches/gc.rs index ea1aaab316ed..3e840aac1c67 100644 --- a/crates/re_data_store/benches/gc.rs +++ b/crates/re_data_store/benches/gc.rs @@ -10,8 +10,7 @@ use re_data_store::{ use re_log_types::{ build_frame_nr, build_log_time, DataRow, DataTable, EntityPath, RowId, TableId, Time, TimePoint, }; -use re_types::components::InstanceKey; -use re_types_core::{AsComponents, ComponentBatch, ComponentName, Loggable as _}; +use re_types_core::{AsComponents, ComponentBatch}; criterion_group!(benches, plotting_dashboard); criterion_main!(benches); @@ -85,13 +84,7 @@ fn plotting_dashboard(c: &mut Criterion) { // Default config group.bench_function("default", |b| { - let store = build_store( - Default::default(), - InstanceKey::name(), - false, - &mut timegen, - &mut datagen, - ); + let store = build_store(Default::default(), false, &mut timegen, &mut datagen); b.iter_batched( || store.clone(), |mut store| { @@ -117,7 +110,6 @@ fn plotting_dashboard(c: &mut Criterion) { indexed_bucket_num_rows: num_rows_per_bucket, ..Default::default() }, - InstanceKey::name(), false, &mut timegen, &mut datagen, @@ -142,7 +134,6 @@ fn plotting_dashboard(c: &mut Criterion) { fn build_store( config: DataStoreConfig, - cluster_key: ComponentName, packed: bool, timegen: &mut FT, datagen: &mut FD, @@ -153,7 +144,6 @@ where { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - cluster_key, config, ); diff --git a/crates/re_data_store/src/lib.rs b/crates/re_data_store/src/lib.rs index 07227c54a0f1..19da79f88717 100644 --- a/crates/re_data_store/src/lib.rs +++ b/crates/re_data_store/src/lib.rs @@ -41,8 +41,7 @@ pub use self::store_subscriber::{StoreSubscriber, StoreSubscriberHandle}; pub use self::store_write::{WriteError, WriteResult}; pub(crate) use self::store::{ - ClusterCellCache, IndexedBucket, IndexedBucketInner, IndexedTable, MetadataRegistry, - StaticCell, StaticTable, + IndexedBucket, IndexedBucketInner, IndexedTable, MetadataRegistry, StaticCell, StaticTable, }; // Re-exports diff --git a/crates/re_data_store/src/store.rs b/crates/re_data_store/src/store.rs index fbf0515b8fcc..528018ee9ba0 100644 --- a/crates/re_data_store/src/store.rs +++ b/crates/re_data_store/src/store.rs @@ -5,8 +5,8 @@ use arrow2::datatypes::DataType; use nohash_hasher::IntMap; use parking_lot::RwLock; use re_log_types::{ - DataCell, DataCellColumn, EntityPath, EntityPathHash, ErasedTimeVec, NumInstances, - NumInstancesVec, RowId, RowIdVec, StoreId, TimeInt, TimePoint, TimeRange, Timeline, + DataCell, DataCellColumn, EntityPath, EntityPathHash, ErasedTimeVec, RowId, RowIdVec, StoreId, + TimeInt, TimePoint, TimeRange, Timeline, }; use re_types_core::{ComponentName, ComponentNameSet, SizeBytes}; @@ -123,27 +123,6 @@ impl std::ops::DerefMut for MetadataRegistry { } } -/// Used to cache auto-generated cluster cells (`[0]`, `[0, 1]`, `[0, 1, 2]`, …) so that they -/// can be properly deduplicated on insertion. -#[derive(Debug, Default, Clone)] -pub struct ClusterCellCache(pub IntMap); - -impl std::ops::Deref for ClusterCellCache { - type Target = IntMap; - - #[inline] - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl std::ops::DerefMut for ClusterCellCache { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - // --- /// Incremented on each edit. @@ -164,20 +143,6 @@ pub struct StoreGeneration { pub struct DataStore { pub(crate) id: StoreId, - /// The cluster key specifies a column/component that is guaranteed to always be present for - /// every single row of data within the store. - /// - /// In addition to always being present, the payload of the cluster key..: - /// - is always increasingly sorted, - /// - is always dense (no validity bitmap), - /// - and never contains duplicate entries. - /// - /// This makes the cluster key a perfect candidate for joining query results together, and - /// doing so as efficiently as possible. - /// - /// See [`Self::insert_row`] for more information. - pub(crate) cluster_key: ComponentName, - /// The configuration of the data store (e.g. bucket sizes). pub(crate) config: DataStoreConfig, @@ -192,10 +157,6 @@ pub struct DataStore { /// Keeps track of arbitrary per-row metadata. pub(crate) metadata_registry: MetadataRegistry<(TimePoint, EntityPathHash)>, - /// Used to cache auto-generated cluster cells (`[0]`, `[0, 1]`, `[0, 1, 2]`, …) - /// so that they can be properly deduplicated on insertion. - pub(crate) cluster_cell_cache: ClusterCellCache, - /// All temporal [`IndexedTable`]s for all entities on all timelines. /// /// See also [`Self::static_tables`]. @@ -227,11 +188,9 @@ impl Clone for DataStore { fn clone(&self) -> Self { Self { id: self.id.clone(), - cluster_key: self.cluster_key, config: self.config.clone(), type_registry: self.type_registry.clone(), metadata_registry: self.metadata_registry.clone(), - cluster_cell_cache: self.cluster_cell_cache.clone(), tables: self.tables.clone(), static_tables: self.static_tables.clone(), insert_id: Default::default(), @@ -243,13 +202,10 @@ impl Clone for DataStore { } impl DataStore { - /// See [`Self::cluster_key`] for more information about the cluster key. - pub fn new(id: StoreId, cluster_key: ComponentName, config: DataStoreConfig) -> Self { + pub fn new(id: StoreId, config: DataStoreConfig) -> Self { Self { id, - cluster_key, config, - cluster_cell_cache: Default::default(), type_registry: Default::default(), metadata_registry: Default::default(), tables: Default::default(), @@ -283,11 +239,6 @@ impl DataStore { } } - /// See [`Self::cluster_key`] for more information about the cluster key. - pub fn cluster_key(&self) -> ComponentName { - self.cluster_key - } - /// See [`DataStoreConfig`] for more information about configuration. pub fn config(&self) -> &DataStoreConfig { &self.config @@ -355,10 +306,6 @@ pub struct IndexedTable { /// The entity this table is related to, for debugging purposes. pub entity_path: EntityPath, - /// Carrying the cluster key around to help with assertions and sanity checks all over the - /// place. - pub cluster_key: ComponentName, - /// The actual buckets, where the data is stored. /// /// The keys of this `BTreeMap` represent the lower bounds of the time-ranges covered by @@ -388,14 +335,13 @@ pub struct IndexedTable { } impl IndexedTable { - pub fn new(cluster_key: ComponentName, timeline: Timeline, entity_path: EntityPath) -> Self { - let bucket = IndexedBucket::new(cluster_key, timeline); + pub fn new(timeline: Timeline, entity_path: EntityPath) -> Self { + let bucket = IndexedBucket::new(timeline); let buckets_size_bytes = bucket.total_size_bytes(); Self { timeline, entity_path, buckets: [(TimeInt::MIN, bucket)].into(), - cluster_key, all_components: Default::default(), buckets_num_rows: 0, buckets_size_bytes, @@ -412,14 +358,13 @@ impl IndexedTable { let Self { timeline, entity_path: _, - cluster_key, buckets, all_components: _, // keep the history on purpose buckets_num_rows, buckets_size_bytes, } = self; - let bucket = IndexedBucket::new(*cluster_key, *timeline); + let bucket = IndexedBucket::new(*timeline); let size_bytes = bucket.total_size_bytes(); *buckets = [(TimeInt::MIN, bucket)].into(); @@ -441,10 +386,6 @@ pub struct IndexedBucket { /// The timeline the bucket's parent table operates in, for debugging purposes. pub timeline: Timeline, - /// Carrying the cluster key around to help with assertions and sanity checks all over the - /// place. - pub cluster_key: ComponentName, - // To simplify interior mutability. pub inner: RwLock, } @@ -453,18 +394,16 @@ impl Clone for IndexedBucket { fn clone(&self) -> Self { Self { timeline: self.timeline, - cluster_key: self.cluster_key, inner: RwLock::new(self.inner.read().clone()), } } } impl IndexedBucket { - pub(crate) fn new(cluster_key: ComponentName, timeline: Timeline) -> Self { + pub(crate) fn new(timeline: Timeline) -> Self { Self { timeline, inner: RwLock::new(IndexedBucketInner::default()), - cluster_key, } } } @@ -503,11 +442,6 @@ pub struct IndexedBucketInner { /// `RowId::ZERO` for empty buckets. pub max_row_id: RowId, - /// The entire column of `num_instances`. - /// - /// Keeps track of the expected number of instances in each row. - pub col_num_instances: NumInstancesVec, - /// All the rows for all the component columns. /// /// The cells are optional since not all rows will have data for every single component @@ -533,7 +467,6 @@ impl Default for IndexedBucketInner { col_insert_id: Default::default(), col_row_id: Default::default(), max_row_id: RowId::ZERO, - col_num_instances: Default::default(), columns: Default::default(), size_bytes: 0, // NOTE: computed below }; @@ -550,10 +483,6 @@ pub struct StaticTable { /// The entity this table is related to, for debugging purposes. pub entity_path: EntityPath, - /// Carrying the cluster key around to help with assertions and sanity checks all over the - /// place. - pub cluster_key: ComponentName, - /// Keeps track of one and only one [`StaticCell`] per component. /// /// Last-write-wins semantics apply, where ordering is defined by `RowId`. @@ -562,10 +491,9 @@ pub struct StaticTable { impl StaticTable { #[inline] - pub fn new(cluster_key: ComponentName, entity_path: EntityPath) -> Self { + pub fn new(entity_path: EntityPath) -> Self { Self { entity_path, - cluster_key, cells: Default::default(), } } @@ -577,10 +505,5 @@ pub struct StaticCell { pub insert_id: Option, pub row_id: RowId, - pub num_instances: NumInstances, pub cell: DataCell, - - // TODO(#5303): We keep track of cluster keys for each static cell for backwards - // compatibility with the legacy instance-key model. This will go away next. - pub cluster_key: DataCell, } diff --git a/crates/re_data_store/src/store_arrow.rs b/crates/re_data_store/src/store_arrow.rs index 60a792fada5c..eb398f1155f7 100644 --- a/crates/re_data_store/src/store_arrow.rs +++ b/crates/re_data_store/src/store_arrow.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, VecDeque}; use arrow2::{array::Array, chunk::Chunk, datatypes::Schema}; use nohash_hasher::IntMap; -use re_log_types::{DataCellColumn, DataTable, DataTableResult, NumInstances, RowId, Timeline}; +use re_log_types::{DataCellColumn, DataTable, DataTableResult, RowId, Timeline}; use re_types_core::ComponentName; use crate::{ @@ -19,17 +19,11 @@ impl IndexedBucket { /// - `insert_id` /// - `row_id` /// - `time` - /// - `num_instances` - /// - `$cluster_key` /// - rest of component columns in ascending lexical order pub fn serialize(&self) -> DataTableResult<(Schema, Chunk>)> { re_tracing::profile_function!(); - let Self { - timeline, - cluster_key, - inner, - } = self; + let Self { timeline, inner } = self; let IndexedBucketInner { is_sorted: _, @@ -38,17 +32,14 @@ impl IndexedBucket { col_insert_id, col_row_id, max_row_id: _, - col_num_instances, columns, size_bytes: _, } = &*inner.read(); serialize( - cluster_key, Some((*timeline, col_time)), col_insert_id, col_row_id, - col_num_instances, columns, ) } @@ -61,15 +52,10 @@ impl StaticTable { /// - `insert_id` /// - `row_id` /// - `time` - /// - `num_instances` - /// - `$cluster_key` /// - rest of component columns in ascending lexical order pub fn serialize(&self) -> DataTableResult<(Schema, Chunk>)> { re_tracing::profile_function!(); - // NOTE: cannot fail, the cluster key _has_ to be there by definition - let cluster_keys = &self.cells[&self.cluster_key]; - let mut cells_per_row_id: BTreeMap> = Default::default(); for static_cell in self.cells.values() { cells_per_row_id @@ -77,9 +63,6 @@ impl StaticTable { .or_default() .push(static_cell.clone()); } - for cells in cells_per_row_id.values_mut() { - cells.push(cluster_keys.clone()); - } let col_insert_id = cells_per_row_id .values() @@ -88,11 +71,6 @@ impl StaticTable { let col_row_id = cells_per_row_id.keys().copied().collect(); - let col_num_instances = cells_per_row_id - .values() - .filter_map(|cells| cells.first().map(|cell| cell.num_instances)) - .collect(); - let component_names: Vec<_> = self .cells .values() @@ -113,25 +91,16 @@ impl StaticTable { } } - serialize( - &self.cluster_key, - None, - &col_insert_id, - &col_row_id, - &col_num_instances, - &columns, - ) + serialize(None, &col_insert_id, &col_row_id, &columns) } } // --- fn serialize( - cluster_key: &ComponentName, col_time: Option<(Timeline, &VecDeque)>, col_insert_id: &VecDeque, col_row_id: &VecDeque, - col_num_instances: &VecDeque, table: &IntMap, ) -> DataTableResult<(Schema, Chunk>)> { re_tracing::profile_function!(); @@ -146,14 +115,14 @@ fn serialize( { let (control_schema, control_columns) = - serialize_control_columns(col_time, col_insert_id, col_row_id, col_num_instances)?; + serialize_control_columns(col_time, col_insert_id, col_row_id)?; schema.fields.extend(control_schema.fields); schema.metadata.extend(control_schema.metadata); columns.extend(control_columns); } { - let (data_schema, data_columns) = serialize_data_columns(cluster_key, table)?; + let (data_schema, data_columns) = serialize_data_columns(table)?; schema.fields.extend(data_schema.fields); schema.metadata.extend(data_schema.metadata); columns.extend(data_columns); @@ -166,7 +135,6 @@ fn serialize_control_columns( col_time: Option<(Timeline, &VecDeque)>, col_insert_id: &VecDeque, col_row_id: &VecDeque, - col_num_instances: &VecDeque, ) -> DataTableResult<(Schema, Vec>)> { re_tracing::profile_function!(); @@ -177,7 +145,6 @@ fn serialize_control_columns( // - insert_id // - row_id // - time - // - num_instances // NOTE: Optional column, so make sure it's actually there: if !col_insert_id.is_empty() { @@ -204,16 +171,10 @@ fn serialize_control_columns( columns.push(time_column); } - let (num_instances_field, num_instances_column) = - DataTable::serialize_control_column(col_num_instances)?; - schema.fields.push(num_instances_field); - columns.push(num_instances_column); - Ok((schema, columns)) } fn serialize_data_columns( - cluster_key: &ComponentName, table: &IntMap, ) -> DataTableResult<(Schema, Vec>)> { re_tracing::profile_function!(); @@ -222,17 +183,7 @@ fn serialize_data_columns( let mut columns = Vec::new(); // NOTE: ordering is taken into account! - let mut table: BTreeMap<_, _> = table.iter().collect(); - - // Cluster column first and foremost! - // - // NOTE: cannot fail, the cluster key _has_ to be there by definition - let cluster_column = table.remove(&cluster_key).unwrap(); - { - let (field, column) = DataTable::serialize_data_column(cluster_key, cluster_column)?; - schema.fields.push(field); - columns.push(column); - } + let table: BTreeMap<_, _> = table.iter().collect(); for (component, column) in table { // NOTE: Don't serialize columns with only null values. diff --git a/crates/re_data_store/src/store_dump.rs b/crates/re_data_store/src/store_dump.rs index f44b31b35128..2e1e24fb9ffc 100644 --- a/crates/re_data_store/src/store_dump.rs +++ b/crates/re_data_store/src/store_dump.rs @@ -63,7 +63,6 @@ impl DataStore { /// Serializes the entire datastore into an iterator of [`DataTable`]s, where each table /// corresponds 1-to-1 to an internal bucket. - // TODO(#1793): This shouldn't dump cluster keys that were autogenerated. pub fn to_data_tables( &self, time_filter: Option<(Timeline, TimeRange)>, @@ -95,14 +94,7 @@ impl DataStore { row_id, TimePoint::default(), static_table.entity_path.clone(), - static_cells - .iter() - .map(|cell| cell.num_instances.0) - .max() - .unwrap_or_default(), - static_cells - .into_iter() - .flat_map(|static_cell| [static_cell.cell, static_cell.cluster_key]), + static_cells.into_iter().map(|static_cell| static_cell.cell), ) .ok() }); @@ -120,11 +112,7 @@ impl DataStore { bucket.sort_indices_if_needed(); - let IndexedBucket { - timeline, - cluster_key: _, - inner, - } = bucket; + let IndexedBucket { timeline, inner } = bucket; let IndexedBucketInner { is_sorted: _, @@ -133,7 +121,6 @@ impl DataStore { col_insert_id: _, col_row_id, max_row_id: _, - col_num_instances, columns, size_bytes: _, } = &*inner.read(); @@ -146,7 +133,6 @@ impl DataStore { col_entity_path: std::iter::repeat_with(|| table.entity_path.clone()) .take(col_row_id.len()) .collect(), - col_num_instances: col_num_instances.clone(), columns: columns.clone().into_iter().collect(), // shallow } }) @@ -171,11 +157,7 @@ impl DataStore { bucket.sort_indices_if_needed(); - let IndexedBucket { - timeline, - cluster_key: _, - inner, - } = bucket; + let IndexedBucket { timeline, inner } = bucket; let IndexedBucketInner { is_sorted: _, @@ -184,7 +166,6 @@ impl DataStore { col_insert_id: _, col_row_id, max_row_id: _, - col_num_instances, columns, size_bytes: _, } = &*inner.read(); @@ -215,9 +196,6 @@ impl DataStore { .take(col_row_id.len()) .collect(); - let col_num_instances = - filter_column(col_time, col_num_instances.iter(), time_filter).collect(); - let mut columns2 = BTreeMap::default(); for (component, column) in columns { let column = filter_column(col_time, column.iter(), time_filter).collect(); @@ -229,7 +207,6 @@ impl DataStore { col_row_id, col_timelines, col_entity_path, - col_num_instances, columns: columns2, }) })) diff --git a/crates/re_data_store/src/store_event.rs b/crates/re_data_store/src/store_event.rs index b4e2b6de4b65..971c47a829bb 100644 --- a/crates/re_data_store/src/store_event.rs +++ b/crates/re_data_store/src/store_event.rs @@ -211,10 +211,10 @@ mod tests { use std::collections::BTreeMap; use re_log_types::{ - example_components::{MyColor, MyPoint}, + example_components::{MyColor, MyIndex, MyPoint}, DataRow, RowId, TimePoint, Timeline, }; - use re_types_core::{components::InstanceKey, Loggable as _}; + use re_types_core::Loggable as _; use crate::{DataStore, GarbageCollectionOptions}; @@ -285,7 +285,6 @@ mod tests { fn store_events() -> anyhow::Result<()> { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); @@ -306,7 +305,7 @@ mod tests { row_id1, timepoint1.clone(), entity_path1.clone(), - [&InstanceKey::from_iter(0..10) as _], + [&MyIndex::from_iter(0..10) as _], )?; view.on_events(&[store.insert_row(&row1)?]); @@ -325,7 +324,7 @@ mod tests { (entity_path1.clone(), 1), // ], [ - (InstanceKey::name(), 1), // + (MyIndex::name(), 1), // ], [ (42.try_into().unwrap(), 1), // @@ -375,9 +374,9 @@ mod tests { (entity_path2.clone(), 1), // ], [ - (InstanceKey::name(), 1), // autogenerated, doesn't change - (MyPoint::name(), 1), // - (MyColor::name(), 1), // + (MyIndex::name(), 1), // autogenerated, doesn't change + (MyPoint::name(), 1), // + (MyColor::name(), 1), // ], [ (42.try_into().unwrap(), 2), // @@ -399,7 +398,7 @@ mod tests { timepoint3.clone(), entity_path2.clone(), [ - &InstanceKey::from_iter(0..num_instances as _) as _, + &MyIndex::from_iter(0..num_instances as _) as _, &colors as _, ], )? @@ -424,9 +423,9 @@ mod tests { (entity_path2.clone(), 2), // ], [ - (InstanceKey::name(), 2), // - (MyPoint::name(), 1), // - (MyColor::name(), 2), // + (MyIndex::name(), 2), // + (MyPoint::name(), 1), // + (MyColor::name(), 2), // ], [ (42.try_into().unwrap(), 2), // @@ -458,9 +457,9 @@ mod tests { (entity_path2.clone(), 1), // static -- no gc ], [ - (InstanceKey::name(), 1), // static -- no gc - (MyPoint::name(), 0), // - (MyColor::name(), 1), // static -- no gc + (MyIndex::name(), 1), // static -- no gc + (MyPoint::name(), 0), // + (MyColor::name(), 1), // static -- no gc ], [ (42.try_into().unwrap(), 0), // @@ -474,51 +473,4 @@ mod tests { Ok(()) } - - #[test] - fn autogenerated_cluster_keys() -> anyhow::Result<()> { - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - - let timeline_frame = Timeline::new_sequence("frame"); - - let row1 = DataRow::from_component_batches( - RowId::new(), - TimePoint::from_iter([(timeline_frame, 42)]), - "entity_a".into(), - [&InstanceKey::from_iter(0..10) as _], - )?; - - // Not autogenerated, should fire. - { - let event = store.insert_row(&row1)?; - assert!(event.cells.contains_key(&store.cluster_key())); - - let (events, _) = store.gc(&GarbageCollectionOptions::gc_everything()); - assert_eq!(1, events.len()); - assert!(events[0].cells.contains_key(&store.cluster_key())); - } - - let row2 = DataRow::from_component_batches( - RowId::new(), - TimePoint::from_iter([(timeline_frame, 42)]), - "entity_b".into(), - [&[MyColor::from(0xAABBCCDD)] as _], - )?; - - // Autogenerated, should _not_ fire. - { - let event = store.insert_row(&row2)?; - assert!(!event.cells.contains_key(&store.cluster_key())); - - let (events, _) = store.gc(&GarbageCollectionOptions::gc_everything()); - assert_eq!(1, events.len()); - assert!(!events[0].cells.contains_key(&store.cluster_key())); - } - - Ok(()) - } } diff --git a/crates/re_data_store/src/store_format.rs b/crates/re_data_store/src/store_format.rs index b3eb183ceea5..38a27854bd43 100644 --- a/crates/re_data_store/src/store_format.rs +++ b/crates/re_data_store/src/store_format.rs @@ -11,9 +11,7 @@ impl std::fmt::Display for DataStore { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { id, - cluster_key, config, - cluster_cell_cache: _, type_registry: _, metadata_registry: _, tables, @@ -27,10 +25,6 @@ impl std::fmt::Display for DataStore { f.write_str("DataStore {\n")?; f.write_str(&indent::indent_all_by(4, format!("id: {id}\n")))?; - f.write_str(&indent::indent_all_by( - 4, - format!("cluster_key: {cluster_key:?}\n"), - ))?; f.write_str(&indent::indent_all_by(4, format!("config: {config:?}\n")))?; { @@ -85,7 +79,6 @@ impl std::fmt::Display for IndexedTable { timeline, entity_path, buckets, - cluster_key: _, all_components: _, buckets_num_rows: _, buckets_size_bytes: _, diff --git a/crates/re_data_store/src/store_gc.rs b/crates/re_data_store/src/store_gc.rs index b199b44e9991..a7331bb12fff 100644 --- a/crates/re_data_store/src/store_gc.rs +++ b/crates/re_data_store/src/store_gc.rs @@ -10,7 +10,7 @@ use re_log_types::{ use re_types_core::{ComponentName, SizeBytes as _}; use crate::{ - store::{ClusterCellCache, IndexedBucketInner, IndexedTable}, + store::{IndexedBucketInner, IndexedTable}, DataStore, DataStoreStats, StoreDiff, StoreDiffKind, StoreEvent, }; @@ -232,9 +232,7 @@ impl DataStore { let mut batch_is_protected = false; let Self { - cluster_key, metadata_registry, - cluster_cell_cache, tables, .. } = self; @@ -254,8 +252,6 @@ impl DataStore { let dropped = Self::drop_batch( options, tables, - cluster_cell_cache, - *cluster_key, &mut num_bytes_to_drop, &batch, batch_is_protected, @@ -297,8 +293,6 @@ impl DataStore { let dropped = Self::drop_batch( options, tables, - cluster_cell_cache, - *cluster_key, &mut num_bytes_to_drop, &batch, batch_is_protected, @@ -341,8 +335,6 @@ impl DataStore { fn drop_batch( options: &GarbageCollectionOptions, tables: &mut BTreeMap<(EntityPathHash, Timeline), IndexedTable>, - cluster_cell_cache: &ClusterCellCache, - cluster_key: ComponentName, num_bytes_to_drop: &mut f64, batch: &[(TimePoint, (EntityPathHash, RowId))], batch_is_protected: bool, @@ -373,8 +365,7 @@ impl DataStore { // NOTE: We _must_ go through all tables no matter what, since the batch might contain // any number of distinct entities. for ((entity_path_hash, _), table) in &mut *tables { - let (removed, num_bytes_removed) = - table.try_drop_bucket(cluster_cell_cache, cluster_key, max_row_id); + let (removed, num_bytes_removed) = table.try_drop_bucket(max_row_id); *num_bytes_to_drop -= num_bytes_removed as f64; @@ -407,8 +398,7 @@ impl DataStore { // find all tables that could possibly contain this `RowId` for (&timeline, &time) in timepoint { if let Some(table) = tables.get_mut(&(*entity_path_hash, timeline)) { - let (removed, num_bytes_removed) = - table.try_drop_row(cluster_cell_cache, *row_id, time); + let (removed, num_bytes_removed) = table.try_drop_row(*row_id, time); if let Some(inner) = diff.as_mut() { if let Some(removed) = removed { inner.times.extend(removed.times); @@ -460,7 +450,6 @@ impl DataStore { let mut components_to_find: HashMap = table .all_components .iter() - .filter(|c| **c != table.cluster_key) .filter(|c| !dont_protect.contains(*c)) .map(|c| (*c, target_count)) .collect(); @@ -506,8 +495,11 @@ impl DataStore { // If any bucket has a non-empty component in any column, we keep it… for bucket in table.buckets.values() { let inner = bucket.inner.read(); - for num in &inner.col_num_instances { - if num.get() != 0 { + for column in inner.columns.values() { + if column + .iter() + .any(|cell| cell.as_ref().map_or(false, |cell| cell.num_instances() > 0)) + { return true; } } @@ -534,7 +526,7 @@ impl DataStore { for column in &mut inner.columns.values_mut() { let cell = column[i].take(); if let Some(cell) = cell { - diff.insert(self.cluster_key, &self.cluster_cell_cache, cell); + diff.insert(cell); } } } @@ -549,12 +541,7 @@ impl DataStore { impl IndexedTable { /// Try to drop an entire bucket at once if it doesn't contain any `RowId` greater than `max_row_id`. - fn try_drop_bucket( - &mut self, - cluster_cache: &ClusterCellCache, - cluster_key: ComponentName, - max_row_id: RowId, - ) -> (Vec, u64) { + fn try_drop_bucket(&mut self, max_row_id: RowId) -> (Vec, u64) { re_tracing::profile_function!(); let entity_path = self.entity_path.clone(); @@ -594,16 +581,6 @@ impl IndexedTable { for (component_name, column) in &mut columns { if let Some(cell) = column.pop_front().flatten() { - if cell.component_name() == cluster_key { - if let Some(cached_cell) = cluster_cache.get(&cell.num_instances()) { - if std::ptr::eq(cell.as_ptr(), cached_cell.as_ptr()) { - // We don't fire events when inserting autogenerated cluster cells, and - // therefore must not fire when removing them either. - continue; - } - } - } - diff.cells.insert(*component_name, cell); } } @@ -630,17 +607,11 @@ impl IndexedTable { /// specified `time`. /// /// Returns how many bytes were actually dropped, or zero if the row wasn't found. - fn try_drop_row( - &mut self, - cluster_cache: &ClusterCellCache, - row_id: RowId, - time: TimeInt, - ) -> (Option, u64) { + fn try_drop_row(&mut self, row_id: RowId, time: TimeInt) -> (Option, u64) { re_tracing::profile_function!(); let entity_path = self.entity_path.clone(); let timeline = self.timeline; - let cluster_key = self.cluster_key; let table_has_more_than_one_bucket = self.buckets.len() > 1; @@ -649,14 +620,7 @@ impl IndexedTable { let (diff, mut dropped_num_bytes) = { let inner = &mut *bucket.inner.write(); - inner.try_drop_row( - cluster_cache, - cluster_key, - row_id, - timeline, - &entity_path, - time, - ) + inner.try_drop_row(row_id, timeline, &entity_path, time) }; // NOTE: We always need to keep at least one bucket alive, otherwise we have @@ -688,8 +652,6 @@ impl IndexedBucketInner { /// Returns how many bytes were actually dropped, or zero if the row wasn't found. fn try_drop_row( &mut self, - cluster_cache: &ClusterCellCache, - cluster_key: ComponentName, row_id: RowId, timeline: Timeline, entity_path: &EntityPath, @@ -704,7 +666,6 @@ impl IndexedBucketInner { col_insert_id, col_row_id, max_row_id, - col_num_instances, columns, size_bytes, } = self; @@ -756,11 +717,6 @@ impl IndexedBucketInner { } } - // col_num_instances - if let Some(num_instances) = col_num_instances.swap_remove(row_index) { - dropped_num_bytes += num_instances.total_size_bytes(); - } - // each data column for column in columns.values_mut() { let cell = column.0.swap_remove(row_index).flatten(); @@ -771,11 +727,10 @@ impl IndexedBucketInner { if let Some(cell) = cell { if let Some(inner) = diff.as_mut() { - inner.insert(cluster_key, cluster_cache, cell); + inner.insert(cell); } else { let mut d = StoreDiff::deletion(removed_row_id, entity_path.clone()); d.at_timestamp(timeline, time); - d.insert(cluster_key, cluster_cache, cell); diff = Some(d); } } @@ -801,22 +756,7 @@ impl IndexedBucketInner { // --- impl StoreDiff { - fn insert( - &mut self, - cluster_key: ComponentName, - cluster_cache: &ClusterCellCache, - cell: DataCell, - ) { - if cell.component_name() == cluster_key { - if let Some(cached_cell) = cluster_cache.get(&cell.num_instances()) { - if std::ptr::eq(cell.as_ptr(), cached_cell.as_ptr()) { - // We don't fire events when inserting of autogenerated cluster cells, and - // therefore must not fire when removing them either. - return; - } - } - } - + fn insert(&mut self, cell: DataCell) { self.cells.insert(cell.component_name(), cell); } } diff --git a/crates/re_data_store/src/store_helpers.rs b/crates/re_data_store/src/store_helpers.rs index d8f07b842cd1..f98b32c09a55 100644 --- a/crates/re_data_store/src/store_helpers.rs +++ b/crates/re_data_store/src/store_helpers.rs @@ -24,7 +24,6 @@ impl DataStore { RowId::new(), entity_path.clone(), timepoint.clone(), - 1, [component], ) { Ok(row) => row, @@ -64,7 +63,6 @@ impl DataStore { RowId::new(), entity_path.clone(), timepoint.clone(), - cell.num_instances(), cell, ) { Ok(row) => row, diff --git a/crates/re_data_store/src/store_read.rs b/crates/re_data_store/src/store_read.rs index ad83948579e4..392363fe85af 100644 --- a/crates/re_data_store/src/store_read.rs +++ b/crates/re_data_store/src/store_read.rs @@ -215,10 +215,6 @@ impl DataStore { self.query_id.fetch_add(1, Ordering::Relaxed); let entity_path_hash = entity_path.hash(); - let cluster_comp_pos = component_names - .iter() - .find_position(|component_name| **component_name == self.cluster_key) - .map(|(pos, _)| pos); let Some(primary_comp_pos) = component_names .iter() .find_position(|component_name| **component_name == primary) @@ -233,12 +229,9 @@ impl DataStore { // querying for their temporal data. let mut component_names_opt = [(); N].map(|_| None); for (i, component_name) in component_names.iter().copied().enumerate() { - // TODO(#5303): We let the cluster key slip through for backwards compatibility with - // the legacy instance-key model. This will go away next. - let has_static_data = component_name != self.cluster_key - && static_table.map_or(false, |static_table| { - static_table.cells.contains_key(&component_name) - }); + let has_static_data = static_table.map_or(false, |static_table| { + static_table.cells.contains_key(&component_name) + }); component_names_opt[i] = (!has_static_data).then_some(component_name); } @@ -262,12 +255,6 @@ impl DataStore { if *component_name == primary { data_time = TimeInt::STATIC; max_row_id = RowId::max(max_row_id, static_cell.row_id); - - // TODO(#5303): We let the cluster key slip through for backwards compatibility with - // the legacy instance-key model. This will go away next. - if let Some(cluster_comp_pos) = cluster_comp_pos { - results[cluster_comp_pos] = Some(static_cell.cluster_key.clone()); - } } } } @@ -306,10 +293,6 @@ impl DataStore { self.query_id.fetch_add(1, Ordering::Relaxed); let entity_path_hash = entity_path.hash(); - let cluster_comp_pos = component_names - .iter() - .find_position(|component_name| **component_name == self.cluster_key) - .map(|(pos, _)| pos); let static_table = self.static_tables.get(&entity_path_hash); @@ -317,12 +300,9 @@ impl DataStore { // querying for their temporal data. let mut component_names_opt = [(); N].map(|_| None); for (i, component_name) in component_names.iter().copied().enumerate() { - // TODO(#5303): We let the cluster key slip through for backwards compatibility with - // the legacy instance-key model. This will go away next. - let has_static_data = component_name != self.cluster_key - && static_table.map_or(false, |static_table| { - static_table.cells.contains_key(&component_name) - }); + let has_static_data = static_table.map_or(false, |static_table| { + static_table.cells.contains_key(&component_name) + }); component_names_opt[i] = (!has_static_data).then_some(component_name); } @@ -340,12 +320,6 @@ impl DataStore { // the returned index. if static_cell.row_id > max_row_id { max_row_id = RowId::max(max_row_id, static_cell.row_id); - - // TODO(#5303): We let the cluster key slip through for backwards compatibility with - // the legacy instance-key model. This will go away next. - if let Some(cluster_comp_pos) = cluster_comp_pos { - results[cluster_comp_pos] = Some(static_cell.cluster_key.clone()); - } } } } @@ -602,7 +576,6 @@ impl IndexedBucket { col_insert_id: _, col_row_id, max_row_id: _, - col_num_instances: _, columns, size_bytes: _, } = &*self.inner.read(); @@ -726,7 +699,6 @@ impl IndexedBucket { col_insert_id: _, col_row_id, max_row_id: _, - col_num_instances: _, columns, size_bytes: _, } = &*self.inner.read(); @@ -845,7 +817,6 @@ impl IndexedBucketInner { col_insert_id, col_row_id, max_row_id: _, - col_num_instances, columns, size_bytes: _, } = self; @@ -898,7 +869,6 @@ impl IndexedBucketInner { reshuffle_control_column(col_insert_id, &swaps); } reshuffle_control_column(col_row_id, &swaps); - reshuffle_control_column(col_num_instances, &swaps); } { diff --git a/crates/re_data_store/src/store_sanity.rs b/crates/re_data_store/src/store_sanity.rs index ab11a3bf14a7..19eab8653ebd 100644 --- a/crates/re_data_store/src/store_sanity.rs +++ b/crates/re_data_store/src/store_sanity.rs @@ -1,6 +1,4 @@ -use re_log_types::{ - DataCellColumn, NumInstances, RowId, TimeInt, TimeRange, VecDequeSortingExt as _, -}; +use re_log_types::{RowId, TimeInt, TimeRange, VecDequeSortingExt as _}; use re_types_core::{ComponentName, Loggable, SizeBytes as _}; use crate::{DataStore, IndexedBucket, IndexedBucketInner, IndexedTable}; @@ -43,12 +41,6 @@ pub enum SanityError { got: u64, }, - #[error("Couldn't find any column for the configured cluster key ('{cluster_key}')")] - ClusterColumnMissing { cluster_key: ComponentName }, - - #[error("The cluster column must be dense, found holes: {cluster_column:?}")] - ClusterColumnSparse { cluster_column: Box }, - #[error("Found overlapping indexed buckets: {t1_max_formatted} ({t1_max}) <-> {t2_max_formatted} ({t2_max})")] OverlappingBuckets { t1_max: i64, @@ -150,11 +142,7 @@ impl IndexedBucket { pub fn sanity_check(&self) -> SanityResult<()> { re_tracing::profile_function!(); - let Self { - timeline: _, - cluster_key, - inner, - } = self; + let Self { timeline: _, inner } = self; { let IndexedBucketInner { @@ -164,7 +152,6 @@ impl IndexedBucket { col_insert_id, col_row_id, max_row_id, - col_num_instances, columns, size_bytes: _, } = &*inner.read(); @@ -216,7 +203,6 @@ impl IndexedBucket { .then(|| (DataStore::insert_id_component_name(), col_insert_id.len())), // Some((COLUMN_TIMEPOINT.into(), col_time.len())), Some((RowId::name(), col_row_id.len())), - Some((NumInstances::name(), col_num_instances.len())), ] .into_iter() .flatten() @@ -237,21 +223,6 @@ impl IndexedBucket { } } } - - // The cluster column must be fully dense. - if self.num_rows() > 0 { - let cluster_column = - columns - .get(cluster_key) - .ok_or(SanityError::ClusterColumnMissing { - cluster_key: *cluster_key, - })?; - if !cluster_column.iter().all(|cell| cell.is_some()) { - return Err(SanityError::ClusterColumnSparse { - cluster_column: cluster_column.clone().into(), - }); - } - } } // Make sure size values aren't out of sync diff --git a/crates/re_data_store/src/store_stats.rs b/crates/re_data_store/src/store_stats.rs index 64dde26eac72..f960a4174d11 100644 --- a/crates/re_data_store/src/store_stats.rs +++ b/crates/re_data_store/src/store_stats.rs @@ -1,10 +1,7 @@ use re_log_types::{EntityPathHash, TimePoint, TimeRange}; use re_types_core::SizeBytes; -use crate::{ - store::IndexedBucketInner, ClusterCellCache, DataStore, IndexedBucket, IndexedTable, - MetadataRegistry, -}; +use crate::{store::IndexedBucketInner, DataStore, IndexedBucket, IndexedTable, MetadataRegistry}; // --- @@ -44,8 +41,6 @@ pub struct DataStoreStats { pub type_registry: DataStoreRowStats, pub metadata_registry: DataStoreRowStats, - pub autogenerated: DataStoreRowStats, - /// `num_rows` is really `num_cells` in this case. pub static_tables: DataStoreRowStats, @@ -62,7 +57,6 @@ impl std::ops::Sub for DataStoreStats { Self { type_registry: self.type_registry - rhs.type_registry, metadata_registry: self.metadata_registry - rhs.metadata_registry, - autogenerated: self.autogenerated - rhs.autogenerated, static_tables: self.static_tables - rhs.static_tables, temporal: self.temporal - rhs.temporal, temporal_buckets: self.temporal_buckets - rhs.temporal_buckets, @@ -78,7 +72,6 @@ impl std::ops::Add for DataStoreStats { Self { type_registry: self.type_registry + rhs.type_registry, metadata_registry: self.metadata_registry + rhs.metadata_registry, - autogenerated: self.autogenerated + rhs.autogenerated, static_tables: self.static_tables + rhs.static_tables, temporal: self.temporal + rhs.temporal, temporal_buckets: self.temporal_buckets + rhs.temporal_buckets, @@ -107,14 +100,6 @@ impl DataStoreStats { } }; - let autogenerated = { - re_tracing::profile_scope!("autogenerated"); - DataStoreRowStats { - num_rows: store.cluster_cell_cache.len() as _, - num_bytes: store.cluster_cell_cache.total_size_bytes(), - } - }; - let static_tables = { re_tracing::profile_scope!("static data"); DataStoreRowStats { @@ -138,7 +123,6 @@ impl DataStoreStats { num_rows: static_tables.num_rows + temporal.num_rows, num_bytes: type_registry.num_bytes + metadata_registry.num_bytes - + autogenerated.num_bytes + static_tables.num_bytes + temporal.num_bytes, }; @@ -146,7 +130,6 @@ impl DataStoreStats { Self { type_registry, metadata_registry, - autogenerated, static_tables, temporal, temporal_buckets, @@ -175,13 +158,6 @@ impl SizeBytes for MetadataRegistry<(TimePoint, EntityPathHash)> { } } -impl SizeBytes for ClusterCellCache { - #[inline] - fn heap_size_bytes(&self) -> u64 { - self.0.heap_size_bytes() - } -} - impl SizeBytes for DataStore { #[inline] fn heap_size_bytes(&self) -> u64 { @@ -392,7 +368,6 @@ impl IndexedBucketInner { col_insert_id, col_row_id, max_row_id, - col_num_instances, columns, size_bytes, } = self; @@ -403,7 +378,6 @@ impl IndexedBucketInner { + col_insert_id.total_size_bytes() + col_row_id.total_size_bytes() + max_row_id.total_size_bytes() - + col_num_instances.total_size_bytes() + columns.total_size_bytes() + size_bytes.total_size_bytes(); diff --git a/crates/re_data_store/src/store_subscriber.rs b/crates/re_data_store/src/store_subscriber.rs index 51bba3528870..f56264164bfe 100644 --- a/crates/re_data_store/src/store_subscriber.rs +++ b/crates/re_data_store/src/store_subscriber.rs @@ -156,10 +156,9 @@ mod tests { use ahash::HashSet; use re_log_types::{ - example_components::{MyColor, MyPoint}, + example_components::{MyColor, MyIndex, MyPoint}, DataRow, RowId, StoreId, TimePoint, Timeline, }; - use re_types_core::{components::InstanceKey, Loggable as _}; use crate::{DataStore, GarbageCollectionOptions, StoreSubscriber}; @@ -209,12 +208,10 @@ mod tests { fn store_subscriber() -> anyhow::Result<()> { let mut store1 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut store2 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); @@ -235,7 +232,7 @@ mod tests { (timeline_yet_another, 1), // ]), "entity_a".into(), - [&InstanceKey::from_iter(0..10) as _], + [&MyIndex::from_iter(0..10) as _], )?; expected_events.extend(store1.insert_row(&row)); @@ -267,7 +264,7 @@ mod tests { TimePoint::default(), "entity_b".into(), [ - &InstanceKey::from_iter(0..num_instances as _) as _, + &MyIndex::from_iter(0..num_instances as _) as _, &colors as _, ], )? diff --git a/crates/re_data_store/src/store_write.rs b/crates/re_data_store/src/store_write.rs index b340d2f64b29..d1b3347f77e4 100644 --- a/crates/re_data_store/src/store_write.rs +++ b/crates/re_data_store/src/store_write.rs @@ -8,9 +8,7 @@ use re_log_types::{ DataCell, DataCellColumn, DataCellError, DataRow, EntityPathHash, RowId, TimeInt, TimePoint, TimeRange, VecDequeRemovalExt as _, }; -use re_types_core::{ - components::InstanceKey, ComponentName, ComponentNameSet, Loggable, SizeBytes as _, -}; +use re_types_core::{ComponentName, ComponentNameSet, SizeBytes as _}; use crate::{ DataStore, DataStoreConfig, IndexedBucket, IndexedBucketInner, IndexedTable, MetadataRegistry, @@ -27,15 +25,6 @@ pub enum WriteError { #[error("Error with one or more the underlying data cells")] DataCell(#[from] DataCellError), - #[error("The cluster component must be dense, got {0:?}")] - SparseClusteringComponent(DataCell), - - #[error( - "The cluster component must be increasingly sorted and not contain \ - any duplicates, got {0:?}" - )] - InvalidClusteringComponent(DataCell), - #[error("The inserted data must contain at least one cell")] Empty, @@ -56,10 +45,6 @@ pub type WriteResult = ::std::result::Result; impl DataStore { /// Inserts a [`DataRow`]'s worth of components into the datastore. - /// - /// If the bundle doesn't carry a payload for the cluster key, one will be auto-generated - /// based on the length of the components in the payload, in the form of an array of - /// monotonically increasing `u64`s going from `0` to `N-1`. pub fn insert_row(&mut self, row: &DataRow) -> WriteResult { // TODO(cmc): kind & insert_id need to somehow propagate through the span system. self.insert_id += 1; @@ -72,7 +57,6 @@ impl DataStore { row_id, timepoint, entity_path, - num_instances, cells, } = row; @@ -90,12 +74,10 @@ impl DataStore { } let entity_path_hash = entity_path.hash(); - let num_instances = *num_instances; trace!( kind = "insert", id = self.insert_id, - cluster_key = %self.cluster_key, timelines = ?timepoint.iter() .map(|(timeline, time)| (timeline.name(), timeline.typ().format_utc(*time))) .collect::>(), @@ -104,46 +86,14 @@ impl DataStore { "insertion started…" ); - let cluster_cell_pos = cells - .iter() - .find_position(|cell| cell.component_name() == self.cluster_key) - .map(|(pos, _)| pos); - - let generated_cluster_cell = if let Some(cluster_cell_pos) = cluster_cell_pos { - // We found a column with a name matching the cluster key's, let's make sure it's - // valid (dense, sorted, no duplicates) and use that if so. - - let cluster_cell = &cells[cluster_cell_pos]; - - // Clustering component must be dense. - if !cluster_cell.is_dense() { - return Err(WriteError::SparseClusteringComponent(cluster_cell.clone())); - } - // Clustering component must be sorted and not contain any duplicates. - if !cluster_cell.is_sorted_and_unique()? { - return Err(WriteError::InvalidClusteringComponent(cluster_cell.clone())); - } - - None - } else { - // The caller has not specified any cluster component, and so we'll have to generate - // one… unless we've already generated one of this exact length in the past, - // in which case we can simply re-use that cell. - - let (cell, _) = self.generate_cluster_cell(num_instances.into()); - - Some(cell) - }; - let insert_id = self.config.store_insert_ids.then_some(self.insert_id); let diff = if timepoint.is_static() { let static_table = self .static_tables .entry(entity_path_hash) - .or_insert_with(|| StaticTable::new(self.cluster_key, entity_path.clone())); + .or_insert_with(|| StaticTable::new(entity_path.clone())); - let cluster_key = self.cluster_key; let cells = row .cells() .iter() @@ -156,25 +106,13 @@ impl DataStore { }) .collect_vec(); - for cell in cells - .iter() - // TODO(#5303): We let the cluster key slip through for backwards compatibility with - // the legacy instance-key model. This will go away next. - .filter(|cell| cell.component_name() != cluster_key) - { + for cell in &cells { static_table.cells.insert( cell.component_name(), StaticCell { insert_id, row_id: *row_id, - num_instances, cell: (*cell).clone(), - // TODO(#5303): We keep track of cluster keys for each static cell for backwards - // compatibility with the legacy instance-key model. This will go away next. - cluster_key: generated_cluster_cell - .as_ref() - .unwrap_or_else(|| cells[cluster_cell_pos.unwrap()]) - .clone(), }, ); } @@ -188,15 +126,9 @@ impl DataStore { let index = self .tables .entry((entity_path_hash, *timeline)) - .or_insert_with(|| IndexedTable::new(self.cluster_key, *timeline, entity_path)); - - index.insert_row( - &self.config, - insert_id, - *time, - generated_cluster_cell.clone(), /* shallow */ - row, - ); + .or_insert_with(|| IndexedTable::new(*timeline, entity_path)); + + index.insert_row(&self.config, insert_id, *time, row); } let mut diff = StoreDiff::addition(*row_id, entity_path.clone()); @@ -205,11 +137,6 @@ impl DataStore { diff }; - // TODO(#4220): should we fire for auto-generated data? - // if let Some(cell) = generated_cluster_cell { - // diff = diff.with_cells([cell]); - // } - let event = StoreEvent { store_id: self.id.clone(), store_generation: self.generation(), @@ -233,35 +160,6 @@ impl DataStore { Ok(event) } - - /// Auto-generates an appropriate cluster cell for the specified number of instances and - /// transparently handles caching. - /// - /// Returns `true` if the cell was returned from cache. - // TODO(#1777): shared slices for auto generated keys - fn generate_cluster_cell(&mut self, num_instances: u32) -> (DataCell, bool) { - re_tracing::profile_function!(); - - if let Some(cell) = self.cluster_cell_cache.get(&num_instances) { - // Cache hit! - - (cell.clone(), true) - } else { - // Cache miss! Craft a new instance keys from the ground up. - - // …so we create it manually instead. - let values = - arrow2::array::UInt64Array::from_vec((0..num_instances as u64).collect_vec()) - .boxed(); - let mut cell = DataCell::from_arrow(InstanceKey::name(), values); - cell.compute_size_bytes(); - - self.cluster_cell_cache - .insert(num_instances, cell.clone() /* shallow */); - - (cell, false) - } - } } impl MetadataRegistry<(TimePoint, EntityPathHash)> { @@ -291,7 +189,6 @@ impl IndexedTable { config: &DataStoreConfig, insert_id: Option, time: TimeInt, - generated_cluster_cell: Option, row: &DataRow, ) { re_tracing::profile_function!(); @@ -326,7 +223,7 @@ impl IndexedTable { self.buckets_size_bytes -= bucket_size_before; self.buckets.insert(min, second_half); - return self.insert_row(config, insert_id, time, generated_cluster_cell, row); + return self.insert_row(config, insert_id, time, row); } // We couldn't split the bucket, either because it's already too small, or because it @@ -383,13 +280,12 @@ impl IndexedTable { TimeInt::new_temporal(new_time_bound), IndexedBucket { timeline, - cluster_key: self.cluster_key, inner: RwLock::new(inner), }, ); self.buckets_size_bytes += inner_size_bytes; - return self.insert_row(config, insert_id, time, generated_cluster_cell, row); + return self.insert_row(config, insert_id, time, row); } } @@ -420,8 +316,7 @@ impl IndexedTable { "inserted into indexed tables" ); - let size_bytes = - bucket.insert_row(insert_id, time, generated_cluster_cell, row, &components); + let size_bytes = bucket.insert_row(insert_id, time, row, &components); self.buckets_size_bytes += size_bytes; self.buckets_num_rows += 1; @@ -436,14 +331,13 @@ impl IndexedBucket { &mut self, insert_id: Option, time: TimeInt, - generated_cluster_cell: Option, row: &DataRow, components: &ComponentNameSet, ) -> u64 { re_tracing::profile_function!(); let mut size_bytes_added = 0u64; - let num_rows = self.num_rows() as usize; + let _num_rows = self.num_rows() as usize; let mut inner = self.inner.write(); let IndexedBucketInner { @@ -453,7 +347,6 @@ impl IndexedBucket { col_insert_id, col_row_id, max_row_id, - col_num_instances, columns, size_bytes, } = &mut *inner; @@ -477,21 +370,6 @@ impl IndexedBucket { col_row_id.push_back(row.row_id()); *max_row_id = RowId::max(*max_row_id, row.row_id()); size_bytes_added += row.row_id().total_size_bytes(); - col_num_instances.push_back(row.num_instances()); - size_bytes_added += row.num_instances().total_size_bytes(); - - // insert auto-generated cluster cell if present - if let Some(cluster_cell) = generated_cluster_cell { - let component_name = cluster_cell.component_name(); - let column = columns.entry(component_name).or_insert_with(|| { - let column = DataCellColumn::empty(num_rows); - size_bytes_added += component_name.total_size_bytes(); - size_bytes_added += column.total_size_bytes(); - column - }); - size_bytes_added += cluster_cell.total_size_bytes(); - column.0.push_back(Some(cluster_cell.clone())); - } // append components to their respective columns (2-way merge) @@ -512,11 +390,6 @@ impl IndexedBucket { // // fill unimpacted columns with null values for (component_name, column) in &mut *columns { - // The cluster key always gets added one way or another, don't try to force fill it! - if *component_name == self.cluster_key { - continue; - } - if !components.contains(component_name) { let none_cell: Option = None; size_bytes_added += none_cell.total_size_bytes(); @@ -559,11 +432,7 @@ impl IndexedBucket { /// cargo test -p re_data_store -- --nocapture datastore_internal_repr /// ``` fn split(&self) -> Option<(TimeInt, Self)> { - let Self { - timeline, - cluster_key: _, - inner, - } = self; + let Self { timeline, inner } = self; let mut inner1 = inner.write(); @@ -588,7 +457,6 @@ impl IndexedBucket { col_insert_id: col_insert_id1, col_row_id: col_row_id1, max_row_id: max_row_id1, - col_num_instances: col_num_instances1, columns: columns1, size_bytes: _, // NOTE: recomputed below } = &mut *inner1; @@ -605,7 +473,7 @@ impl IndexedBucket { }; let split_idx = find_split_index(times1).expect("must be splittable at this point"); - let (time_range2, col_time2, col_insert_id2, col_row_id2, col_num_instances2) = { + let (time_range2, col_time2, col_insert_id2, col_row_id2) = { re_tracing::profile_scope!("control"); // update everything _in place_! ( @@ -613,7 +481,6 @@ impl IndexedBucket { col_time1.split_off_or_default(split_idx), col_insert_id1.split_off_or_default(split_idx), col_row_id1.split_off_or_default(split_idx), - col_num_instances1.split_off_or_default(split_idx), ) }; // NOTE: We _have_ to fullscan here: the bucket is sorted by `(Time, RowId)`, there @@ -648,7 +515,6 @@ impl IndexedBucket { col_insert_id: col_insert_id2, col_row_id: col_row_id2, max_row_id: max_row_id2, - col_num_instances: col_num_instances2, columns: columns2, size_bytes: 0, // NOTE: computed below }; @@ -657,7 +523,6 @@ impl IndexedBucket { }; let bucket2 = Self { timeline, - cluster_key: self.cluster_key, inner: RwLock::new(inner2), }; diff --git a/crates/re_data_store/src/test_util.rs b/crates/re_data_store/src/test_util.rs index 50c568d4a943..f928c4f455a6 100644 --- a/crates/re_data_store/src/test_util.rs +++ b/crates/re_data_store/src/test_util.rs @@ -7,32 +7,29 @@ use crate::{DataStore, DataStoreConfig, WriteError}; #[doc(hidden)] #[macro_export] macro_rules! test_row { - ($entity:ident => $n:expr; [$c0:expr $(,)*]) => {{ + ($entity:ident => [$c0:expr $(,)*]) => {{ ::re_log_types::DataRow::from_cells1_sized( ::re_log_types::RowId::new(), $entity.clone(), ::re_log_types::TimePoint::default(), - $n, $c0, ) .unwrap() }}; - ($entity:ident @ $frames:tt => $n:expr; [$c0:expr $(,)*]) => {{ + ($entity:ident @ $frames:tt => [$c0:expr $(,)*]) => {{ ::re_log_types::DataRow::from_cells1_sized( ::re_log_types::RowId::new(), $entity.clone(), $frames, - $n, $c0, ) .unwrap() }}; - ($entity:ident @ $frames:tt => $n:expr; [$c0:expr, $c1:expr $(,)*]) => {{ + ($entity:ident @ $frames:tt => [$c0:expr, $c1:expr $(,)*]) => {{ ::re_log_types::DataRow::from_cells2_sized( ::re_log_types::RowId::new(), $entity.clone(), $frames, - $n, ($c0, $c1), ) .unwrap() diff --git a/crates/re_data_store/tests/correctness.rs b/crates/re_data_store/tests/correctness.rs index 2d75cf1a69c0..89119b663c15 100644 --- a/crates/re_data_store/tests/correctness.rs +++ b/crates/re_data_store/tests/correctness.rs @@ -8,13 +8,12 @@ use re_data_store::{ test_row, test_util::sanity_unwrap, DataStore, DataStoreConfig, DataStoreStats, GarbageCollectionOptions, LatestAtQuery, WriteError, }; -use re_log_types::example_components::MyPoint; +use re_log_types::example_components::{MyIndex, MyPoint}; use re_log_types::{ - build_frame_nr, build_log_time, DataCell, DataRow, Duration, EntityPath, RowId, Time, TimeInt, - TimePoint, TimeType, Timeline, + build_frame_nr, build_log_time, DataRow, Duration, EntityPath, RowId, Time, TimeInt, TimePoint, + TimeType, Timeline, }; -use re_types::components::InstanceKey; -use re_types::datagen::{build_some_colors, build_some_instances, build_some_positions2d}; +use re_types::datagen::{build_some_colors, build_some_positions2d}; use re_types_core::Loggable as _; // --- @@ -54,7 +53,6 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); @@ -89,7 +87,6 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); @@ -120,7 +117,6 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); @@ -160,7 +156,6 @@ fn row_id_ordering_semantics() -> anyhow::Result<()> { { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); @@ -202,73 +197,16 @@ fn write_errors() { let entity_path = EntityPath::from("this/that"); - { - pub fn build_sparse_instances() -> DataCell { - DataCell::from_component_sparse::([Some(1), None, Some(3)]) - } - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - let row = test_row!(entity_path @ - [build_frame_nr(32), build_log_time(Time::now())] => 3; [ - build_sparse_instances(), build_some_positions2d(3) - ]); - assert!(matches!( - store.insert_row(&row), - Err(WriteError::SparseClusteringComponent(_)), - )); - } - - { - pub fn build_unsorted_instances() -> DataCell { - DataCell::from_component::([1, 3, 2]) - } - - pub fn build_duped_instances() -> DataCell { - DataCell::from_component::([1, 2, 2]) - } - - let mut store = DataStore::new( - re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), - Default::default(), - ); - { - let row = test_row!(entity_path @ - [build_frame_nr(32), build_log_time(Time::now())] => 3; [ - build_unsorted_instances(), build_some_positions2d(3) - ]); - assert!(matches!( - store.insert_row(&row), - Err(WriteError::InvalidClusteringComponent(_)), - )); - } - { - let row = test_row!(entity_path @ - [build_frame_nr(32), build_log_time(Time::now())] => 3; [ - build_duped_instances(), build_some_positions2d(3) - ]); - assert!(matches!( - store.insert_row(&row), - Err(WriteError::InvalidClusteringComponent(_)), - )); - } - } - { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut row = test_row!(entity_path @ [ build_frame_nr(1), build_log_time(Time::now()), - ] => 1; [ build_some_positions2d(1) ]); + ] => [ build_some_positions2d(1) ]); row.row_id = re_log_types::RowId::new(); store.insert_row(&row).unwrap(); @@ -298,7 +236,6 @@ fn latest_at_emptiness_edge_cases() { for config in re_data_store::test_util::all_configs() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); latest_at_emptiness_edge_cases_impl(&mut store); @@ -317,7 +254,7 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { store .insert_row(&test_row!(entity_path @ [ build_log_time(now), build_frame_nr(frame40), - ] => num_instances; [build_some_instances(num_instances as _)])) + ] => [MyIndex::from_iter(0..num_instances as _)])) .unwrap(); sanity_unwrap(store); @@ -332,8 +269,8 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { let cells = store.latest_at( &LatestAtQuery::new(timeline_frame_nr, frame39), &entity_path, - InstanceKey::name(), - &[InstanceKey::name()], + MyIndex::name(), + &[MyIndex::name()], ); assert!(cells.is_none()); } @@ -343,8 +280,8 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { let cells = store.latest_at( &LatestAtQuery::new(timeline_log_time, now_minus_1s_nanos), &entity_path, - InstanceKey::name(), - &[InstanceKey::name()], + MyIndex::name(), + &[MyIndex::name()], ); assert!(cells.is_none()); } @@ -354,8 +291,8 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { let cells = store.latest_at( &LatestAtQuery::new(timeline_frame_nr, frame40), &EntityPath::from("does/not/exist"), - InstanceKey::name(), - &[InstanceKey::name()], + MyIndex::name(), + &[MyIndex::name()], ); assert!(cells.is_none()); } @@ -366,7 +303,7 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { let cells = store.latest_at( &LatestAtQuery::new(timeline_frame_nr, frame40), &entity_path, - InstanceKey::name(), + MyIndex::name(), components, ); assert!(cells.is_none()); @@ -377,7 +314,7 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { let cells = store.latest_at( &LatestAtQuery::new(timeline_frame_nr, frame40), &entity_path, - InstanceKey::name(), + MyIndex::name(), &[], ); assert!(cells.is_none()); @@ -388,8 +325,8 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { let cells = store.latest_at( &LatestAtQuery::new(timeline_wrong_name, frame40), &EntityPath::from("does/not/exist"), - InstanceKey::name(), - &[InstanceKey::name()], + MyIndex::name(), + &[MyIndex::name()], ); assert!(cells.is_none()); } @@ -399,8 +336,8 @@ fn latest_at_emptiness_edge_cases_impl(store: &mut DataStore) { let cells = store.latest_at( &LatestAtQuery::new(timeline_wrong_kind, frame40), &EntityPath::from("does/not/exist"), - InstanceKey::name(), - &[InstanceKey::name()], + MyIndex::name(), + &[MyIndex::name()], ); assert!(cells.is_none()); } @@ -414,7 +351,6 @@ fn gc_correct() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), DataStoreConfig::default(), ); @@ -431,7 +367,7 @@ fn gc_correct() { let num_instances = rng.gen_range(0..=1_000); let row = test_row!(entity_path @ [ build_frame_nr(frame_nr), - ] => num_instances; [ + ] => [ build_some_colors(num_instances as _), ]); store.insert_row(&row).unwrap(); @@ -481,7 +417,6 @@ fn gc_metadata_size() -> anyhow::Result<()> { for enable_batching in [false, true] { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); @@ -529,7 +464,6 @@ fn entity_min_time_correct() -> anyhow::Result<()> { for config in re_data_store::test_util::all_configs() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); entity_min_time_correct_impl(&mut store)?; diff --git a/crates/re_data_store/tests/data_store.rs b/crates/re_data_store/tests/data_store.rs index 2a67aeb307ed..27f8ccd1f492 100644 --- a/crates/re_data_store/tests/data_store.rs +++ b/crates/re_data_store/tests/data_store.rs @@ -10,15 +10,16 @@ use re_data_store::{ DataStore, DataStoreConfig, DataStoreStats, GarbageCollectionOptions, GarbageCollectionTarget, LatestAtQuery, RangeQuery, TimeInt, TimeRange, }; -use re_log_types::{build_frame_nr, DataRow, DataTable, EntityPath, TableId, TimeType, Timeline}; +use re_log_types::{ + build_frame_nr, example_components::MyIndex, DataRow, DataTable, EntityPath, TableId, TimeType, + Timeline, +}; use re_types::{ - components::{Color, InstanceKey, Position2D}, + components::{Color, Position2D}, testing::{build_some_large_structs, LargeStruct}, }; use re_types::{ - datagen::{ - build_some_colors, build_some_instances, build_some_instances_from, build_some_positions2d, - }, + datagen::{build_some_colors, build_some_positions2d}, ComponentNameSet, }; use re_types_core::{ComponentName, Loggable as _}; @@ -41,7 +42,6 @@ fn all_components() { // Stress test save-to-disk & load-from-disk let mut store2 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - store.cluster_key(), store.config().clone(), ); for table in store.to_data_tables(None) { @@ -75,39 +75,35 @@ fn all_components() { { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), DataStoreConfig { indexed_bucket_num_rows: u64::MAX, ..Default::default() }, ); - let cluster_key = store.cluster_key(); let components_a = &[ Color::name(), // added by test, static LargeStruct::name(), // added by test - cluster_key, // always here ]; let components_b = &[ Color::name(), // added by test, static Position2D::name(), // added by test LargeStruct::name(), // added by test - cluster_key, // always here ]; - let row = test_row!(entity_path => 2; [build_some_colors(2)]); + let row = test_row!(entity_path => [build_some_colors(2)]); store.insert_row(&row).unwrap(); let row = - test_row!(entity_path @ [build_frame_nr(frame1)] => 2; [build_some_large_structs(2)]); + test_row!(entity_path @ [build_frame_nr(frame1)] => [build_some_large_structs(2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_a)); let row = test_row!(entity_path @ [ build_frame_nr(frame2), - ] => 2; [build_some_large_structs(2), build_some_positions2d(2)]); + ] => [build_some_large_structs(2), build_some_positions2d(2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_b)); @@ -119,13 +115,11 @@ fn all_components() { { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), DataStoreConfig { indexed_bucket_num_rows: 0, ..Default::default() }, ); - let cluster_key = store.cluster_key(); // ┌──────────┬─────────────┬────────┬───────────┬──────────┐ // │ frame_nr ┆ LargeStruct ┆ row_id ┆ insert_id ┆ instance │ @@ -143,32 +137,29 @@ fn all_components() { let components_a = &[ Color::name(), // added by test, static LargeStruct::name(), // added by test - cluster_key, // always here ]; let components_b = &[ Color::name(), // added by test, static LargeStruct::name(), // ⚠ inherited before the buckets got split apart! Position2D::name(), // added by test - cluster_key, // always here ]; - let row = test_row!(entity_path => 2; [build_some_colors(2)]); + let row = test_row!(entity_path => [build_some_colors(2)]); store.insert_row(&row).unwrap(); let row = - test_row!(entity_path @ [build_frame_nr(frame1)] => 2; [build_some_large_structs(2)]); + test_row!(entity_path @ [build_frame_nr(frame1)] => [build_some_large_structs(2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_a)); - let row = test_row!(entity_path @ [build_frame_nr(frame2)] => 2; [build_some_instances(2)]); + let row = test_row!(entity_path @ [build_frame_nr(frame2)] => [MyIndex::from_iter(0..2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_a)); - let row = - test_row!(entity_path @ [build_frame_nr(frame3)] => 2; [build_some_positions2d(2)]); + let row = test_row!(entity_path @ [build_frame_nr(frame3)] => [build_some_positions2d(2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_b)); @@ -181,13 +172,11 @@ fn all_components() { { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), DataStoreConfig { indexed_bucket_num_rows: 0, ..Default::default() }, ); - let cluster_key = store.cluster_key(); // ┌──────────┬─────────────┬─────────┬────────┬───────────┬──────────┐ // │ frame_nr ┆ LargeStruct ┆ point2d ┆ row_id ┆ insert_id ┆ instance │ @@ -207,39 +196,36 @@ fn all_components() { let components_a = &[ Color::name(), // added by test, static LargeStruct::name(), // added by test - cluster_key, // always here ]; let components_b = &[ Color::name(), // added by test, static Position2D::name(), // added by test but not contained in the second bucket LargeStruct::name(), // added by test - cluster_key, // always here ]; - let row = test_row!(entity_path => 2; [build_some_colors(2)]); + let row = test_row!(entity_path => [build_some_colors(2)]); store.insert_row(&row).unwrap(); let row = - test_row!(entity_path @ [build_frame_nr(frame2)] => 2; [build_some_large_structs(2)]); + test_row!(entity_path @ [build_frame_nr(frame2)] => [build_some_large_structs(2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_a)); let row = - test_row!(entity_path @ [build_frame_nr(frame3)] => 2; [build_some_large_structs(2)]); + test_row!(entity_path @ [build_frame_nr(frame3)] => [build_some_large_structs(2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_a)); let row = - test_row!(entity_path @ [build_frame_nr(frame4)] => 2; [build_some_large_structs(2)]); + test_row!(entity_path @ [build_frame_nr(frame4)] => [build_some_large_structs(2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_a)); - let row = - test_row!(entity_path @ [build_frame_nr(frame1)] => 2; [build_some_positions2d(2)]); + let row = test_row!(entity_path @ [build_frame_nr(frame1)] => [build_some_positions2d(2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_b)); @@ -257,7 +243,6 @@ fn latest_at() { for config in re_data_store::test_util::all_configs() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); latest_at_impl(&mut store); @@ -275,22 +260,21 @@ fn latest_at_impl(store: &mut DataStore) { let frame3 = TimeInt::new_temporal(3); let frame4 = TimeInt::new_temporal(4); - let (instances1, colors1) = (build_some_instances(3), build_some_colors(3)); - let row1 = - test_row!(entity_path @ [build_frame_nr(frame1)] => 3; [instances1.clone(), colors1]); + let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => [instances1.clone(), colors1]); let positions2 = build_some_positions2d(3); - let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => 3; [instances1, positions2]); + let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => [instances1, positions2]); let points3 = build_some_positions2d(10); - let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => 10; [points3]); + let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => [points3]); let colors4 = build_some_colors(5); - let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => 5; [colors4]); + let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => [colors4]); // injecting some static colors let colors5 = build_some_colors(3); - let row5 = test_row!(entity_path => 5; [colors5]); + let row5 = test_row!(entity_path => [colors5]); insert_table_with_retries( store, @@ -309,7 +293,6 @@ fn latest_at_impl(store: &mut DataStore) { // Stress test save-to-disk & load-from-disk let mut store2 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - store.cluster_key(), store.config().clone(), ); for table in store.to_data_tables(None) { @@ -382,7 +365,6 @@ fn range() { for config in re_data_store::test_util::all_configs() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); range_impl(&mut store); @@ -400,39 +382,37 @@ fn range_impl(store: &mut DataStore) { let frame4 = TimeInt::new_temporal(4); let frame5 = TimeInt::new_temporal(5); - let insts1 = build_some_instances(3); + let insts1 = MyIndex::from_iter(0..3); let colors1 = build_some_colors(3); - let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => 3; [insts1.clone(), colors1]); + let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => [insts1.clone(), colors1]); let positions2 = build_some_positions2d(3); - let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => 3; [insts1, positions2]); + let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => [insts1, positions2]); let points3 = build_some_positions2d(10); - let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => 10; [points3]); + let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => [points3]); - let insts4_1 = build_some_instances_from(20..25); + let insts4_1 = MyIndex::from_iter(20..25); let colors4_1 = build_some_colors(5); - let row4_1 = test_row!(entity_path @ [build_frame_nr(frame4)] => 5; [insts4_1, colors4_1]); + let row4_1 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_1, colors4_1]); - let insts4_2 = build_some_instances_from(25..30); + let insts4_2 = MyIndex::from_iter(25..30); let colors4_2 = build_some_colors(5); - let row4_2 = - test_row!(entity_path @ [build_frame_nr(frame4)] => 5; [insts4_2.clone(), colors4_2]); + let row4_2 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_2.clone(), colors4_2]); let points4_25 = build_some_positions2d(5); - let row4_25 = test_row!(entity_path @ [build_frame_nr(frame4)] => 5; [insts4_2, points4_25]); + let row4_25 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_2, points4_25]); - let insts4_3 = build_some_instances_from(30..35); + let insts4_3 = MyIndex::from_iter(30..35); let colors4_3 = build_some_colors(5); - let row4_3 = - test_row!(entity_path @ [build_frame_nr(frame4)] => 5; [insts4_3.clone(), colors4_3]); + let row4_3 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_3.clone(), colors4_3]); let points4_4 = build_some_positions2d(5); - let row4_4 = test_row!(entity_path @ [build_frame_nr(frame4)] => 5; [insts4_3, points4_4]); + let row4_4 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_3, points4_4]); // injecting some static colors let colors5 = build_some_colors(8); - let row5 = test_row!(entity_path => 8; [colors5]); + let row5 = test_row!(entity_path => [colors5]); insert_table_with_retries( store, @@ -466,7 +446,6 @@ fn range_impl(store: &mut DataStore) { // Stress test save-to-disk & load-from-disk let mut store2 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - store.cluster_key(), store.config().clone(), ); for table in store.to_data_tables(None) { @@ -590,7 +569,6 @@ fn gc() { for config in re_data_store::test_util::all_configs() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); gc_impl(&mut store); @@ -611,7 +589,7 @@ fn gc_impl(store: &mut DataStore) { let num_instances = rng.gen_range(0..=1_000); let row = test_row!(entity_path @ [ build_frame_nr(frame_nr) - ] => num_instances; [ + ] => [ build_some_large_structs(num_instances as _), ]); store.insert_row(&row).unwrap(); @@ -660,7 +638,6 @@ fn protected_gc() { for config in re_data_store::test_util::all_configs() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); protected_gc_impl(&mut store); @@ -677,18 +654,17 @@ fn protected_gc_impl(store: &mut DataStore) { let frame3 = TimeInt::new_temporal(3); let frame4 = TimeInt::new_temporal(4); - let (instances1, colors1) = (build_some_instances(3), build_some_colors(3)); - let row1 = - test_row!(entity_path @ [build_frame_nr(frame1)] => 3; [instances1.clone(), colors1]); + let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => [instances1.clone(), colors1]); let positions2 = build_some_positions2d(3); - let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => 3; [instances1, positions2]); + let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => [instances1, positions2]); let points3 = build_some_positions2d(10); - let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => 10; [points3]); + let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => [points3]); let colors4 = build_some_colors(5); - let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => 5; [colors4]); + let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => [colors4]); store.insert_row(&row1).unwrap(); store.insert_row(&row2).unwrap(); @@ -763,7 +739,6 @@ fn protected_gc_clear() { for config in re_data_store::test_util::all_configs() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); protected_gc_clear_impl(&mut store); @@ -781,18 +756,17 @@ fn protected_gc_clear_impl(store: &mut DataStore) { let frame3 = TimeInt::new_temporal(3); let frame4 = TimeInt::new_temporal(4); - let (instances1, colors1) = (build_some_instances(3), build_some_colors(3)); - let row1 = - test_row!(entity_path @ [build_frame_nr(frame1)] => 3; [instances1.clone(), colors1]); + let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => [instances1.clone(), colors1]); let positions2 = build_some_positions2d(3); - let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => 3; [instances1, positions2]); + let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => [instances1, positions2]); let colors2 = build_some_colors(0); - let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => 0; [colors2]); + let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => [colors2]); let points4 = build_some_positions2d(0); - let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => 0; [points4]); + let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => [points4]); // Insert the 3 rows as static let mut static_table = diff --git a/crates/re_data_store/tests/dump.rs b/crates/re_data_store/tests/dump.rs index e3e0b6c5063f..00f1824f4f46 100644 --- a/crates/re_data_store/tests/dump.rs +++ b/crates/re_data_store/tests/dump.rs @@ -7,11 +7,10 @@ use re_data_store::{ DataStore, DataStoreStats, GarbageCollectionOptions, TimeInt, TimeRange, Timeline, }; use re_log_types::{ - build_frame_nr, build_log_time, DataRow, DataTable, EntityPath, RowId, TableId, + build_frame_nr, build_log_time, example_components::MyIndex, DataRow, DataTable, EntityPath, + RowId, TableId, }; -use re_types::components::InstanceKey; -use re_types::datagen::{build_some_colors, build_some_instances, build_some_positions2d}; -use re_types_core::Loggable as _; +use re_types::datagen::{build_some_colors, build_some_positions2d}; // --- @@ -47,7 +46,6 @@ impl RowSet { std::collections::hash_map::Entry::Occupied(mut entry) => { assert_eq!(entry.get().entity_path(), row.entity_path()); assert_eq!(entry.get().cells(), row.cells()); - assert_eq!(entry.get().num_instances(), row.num_instances()); for (timeline, time) in row.timepoint() { entry.get_mut().timepoint.insert(*timeline, *time); } @@ -79,17 +77,14 @@ fn data_store_dump() { let mut store1 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); let mut store2 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); let mut store3 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); @@ -184,12 +179,10 @@ fn data_store_dump_filtered() { let mut store1 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); let mut store2 = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config.clone(), ); @@ -281,25 +274,25 @@ fn create_insert_table(entity_path: impl Into) -> DataTable { let frame3 = TimeInt::new_temporal(3); let frame4 = TimeInt::new_temporal(4); - let (instances1, colors1) = (build_some_instances(3), build_some_colors(3)); + let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); let row1 = test_row!(entity_path @ [ build_frame_nr(frame1), - ] => 3; [instances1.clone(), colors1]); + ] => [instances1.clone(), colors1]); let positions2 = build_some_positions2d(3); let row2 = test_row!(entity_path @ [ build_frame_nr(frame2), - ] => 3; [instances1, positions2]); + ] => [instances1, positions2]); let positions3 = build_some_positions2d(10); let row3 = test_row!(entity_path @ [ build_log_time(frame3.into()) /* ! */, build_frame_nr(frame3), - ] => 10; [positions3]); + ] => [positions3]); let colors4 = build_some_colors(5); let row4 = test_row!(entity_path @ [ build_frame_nr(frame4), - ] => 5; [colors4]); + ] => [colors4]); let mut table = DataTable::from_rows(TableId::new(), [row1, row2, row3, row4]); table.compute_all_size_bytes(); @@ -321,7 +314,6 @@ fn data_store_dump_empty_column() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), config, ); @@ -336,15 +328,15 @@ fn data_store_dump_empty_column_impl(store: &mut DataStore) { // Start by inserting a table with 2 rows, one with colors, and one with points. { - let (instances1, colors1) = (build_some_instances(3), build_some_colors(3)); + let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); let row1 = test_row!(entity_path @ [ build_frame_nr(frame1), - ] => 3; [instances1, colors1]); + ] => [instances1, colors1]); - let (instances2, positions2) = (build_some_instances(3), build_some_positions2d(3)); + let (instances2, positions2) = (MyIndex::from_iter(0..3), build_some_positions2d(3)); let row2 = test_row!(entity_path @ [ build_frame_nr(frame2), - ] => 3; [instances2, positions2]); + ] => [instances2, positions2]); let mut table = DataTable::from_rows(TableId::new(), [row1, row2]); table.compute_all_size_bytes(); insert_table_with_retries(store, &table); @@ -352,10 +344,10 @@ fn data_store_dump_empty_column_impl(store: &mut DataStore) { // Now insert another table with points only. { - let (instances3, positions3) = (build_some_instances(3), build_some_colors(3)); + let (instances3, positions3) = (MyIndex::from_iter(0..3), build_some_colors(3)); let row3 = test_row!(entity_path @ [ build_frame_nr(frame3), - ] => 3; [instances3, positions3]); + ] => [instances3, positions3]); let mut table = DataTable::from_rows(TableId::new(), [row3]); table.compute_all_size_bytes(); insert_table_with_retries(store, &table); diff --git a/crates/re_data_store/tests/internals.rs b/crates/re_data_store/tests/internals.rs index 5449c284626f..b0cb6b5e351c 100644 --- a/crates/re_data_store/tests/internals.rs +++ b/crates/re_data_store/tests/internals.rs @@ -3,9 +3,9 @@ //! They're awful, but sometimes you just have to… use re_data_store::{DataStore, DataStoreConfig}; -use re_log_types::{build_frame_nr, DataRow, EntityPath, RowId, TimePoint}; -use re_types::{components::InstanceKey, datagen::build_some_instances}; -use re_types_core::Loggable as _; +use re_log_types::{ + build_frame_nr, example_components::MyIndex, DataRow, EntityPath, RowId, TimePoint, +}; // --- Internals --- @@ -24,7 +24,6 @@ fn pathological_bucket_topology() { let mut store_forward = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), DataStoreConfig { indexed_bucket_num_rows: 10, ..Default::default() @@ -32,7 +31,6 @@ fn pathological_bucket_topology() { ); let mut store_backward = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), DataStoreConfig { indexed_bucket_num_rows: 10, ..Default::default() @@ -54,8 +52,7 @@ fn pathological_bucket_topology() { RowId::new(), entity_path.clone(), timepoint.clone(), - num_instances, - build_some_instances(num_instances as _), + MyIndex::from_iter(0..num_instances), ) .unwrap(); store_forward.insert_row(&row).unwrap(); @@ -64,8 +61,7 @@ fn pathological_bucket_topology() { RowId::new(), entity_path.clone(), timepoint.clone(), - num_instances, - build_some_instances(num_instances as _), + MyIndex::from_iter(0..num_instances), ) .unwrap(); store_backward.insert_row(&row).unwrap(); @@ -87,8 +83,7 @@ fn pathological_bucket_topology() { RowId::new(), entity_path.clone(), timepoint, - num_instances, - build_some_instances(num_instances as _), + MyIndex::from_iter(0..num_instances), ) .unwrap() }) diff --git a/crates/re_data_store/tests/memory_test.rs b/crates/re_data_store/tests/memory_test.rs index 2b9b1f5c409f..42c34c088a17 100644 --- a/crates/re_data_store/tests/memory_test.rs +++ b/crates/re_data_store/tests/memory_test.rs @@ -57,8 +57,7 @@ fn memory_use(run: impl Fn() -> R) -> usize { use re_data_store::{DataStore, DataStoreConfig}; use re_log_types::{DataRow, RowId, TimePoint, TimeType, Timeline}; -use re_types::components::{InstanceKey, Scalar}; -use re_types_core::Loggable as _; +use re_types::components::Scalar; /// The memory overhead of storing many scalars in the store. #[test] @@ -70,7 +69,6 @@ fn scalar_memory_overhead() { let total_mem_use = memory_use(|| { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), DataStoreConfig::default(), ); @@ -78,12 +76,10 @@ fn scalar_memory_overhead() { let entity_path = re_log_types::entity_path!("scalar"); let timepoint = TimePoint::default().with(Timeline::new("log_time", TimeType::Time), i as i64); - let num_instances = 1; let row = DataRow::from_cells1_sized( RowId::new(), entity_path, timepoint, - num_instances, vec![Scalar(i as f64)], ) .unwrap(); diff --git a/crates/re_data_ui/src/component.rs b/crates/re_data_ui/src/component.rs index 1fe709c7ea2b..ea489a1815f4 100644 --- a/crates/re_data_ui/src/component.rs +++ b/crates/re_data_ui/src/component.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use egui::NumExt; use re_entity_db::{external::re_query::LatestAtComponentResults, EntityPath, InstancePath}; +use re_log_types::Instance; use re_types::ComponentName; use re_ui::SyntaxHighlighting as _; use re_viewer_context::{UiVerbosity, ViewerContext}; @@ -131,7 +132,7 @@ impl DataUi for EntityLatestAtResults { db, &self.entity_path, &self.results, - &re_types::components::InstanceKey(0), + &Instance::from(0), ); } else if one_line { ui.label(format!("{} values", re_format::format_uint(num_instances))); @@ -154,10 +155,10 @@ impl DataUi for EntityLatestAtResults { re_ui::ReUi::setup_table_body(&mut body); let row_height = re_ui::ReUi::table_line_height(); body.rows(row_height, num_displayed_rows, |mut row| { - let instance_key = re_types::components::InstanceKey(row.index() as _); + let instance = Instance::from(row.index() as u64); row.col(|ui| { let instance_path = - InstancePath::instance(self.entity_path.clone(), instance_key); + InstancePath::instance(self.entity_path.clone(), instance); item_ui::instance_path_button_to( ctx, query, @@ -165,7 +166,7 @@ impl DataUi for EntityLatestAtResults { ui, None, &instance_path, - instance_key.syntax_highlighted(ui.style()), + instance.syntax_highlighted(ui.style()), ); }); row.col(|ui| { @@ -177,7 +178,7 @@ impl DataUi for EntityLatestAtResults { db, &self.entity_path, &self.results, - &instance_key, + &instance, ); }); }); diff --git a/crates/re_data_ui/src/component_ui_registry.rs b/crates/re_data_ui/src/component_ui_registry.rs index 19c92ed3c541..066dd461c7c6 100644 --- a/crates/re_data_ui/src/component_ui_registry.rs +++ b/crates/re_data_ui/src/component_ui_registry.rs @@ -1,6 +1,6 @@ use re_data_store::LatestAtQuery; use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb}; -use re_log_types::{external::arrow2, EntityPath}; +use re_log_types::{external::arrow2, EntityPath, Instance}; use re_types::external::arrow2::array::Utf8Array; use re_viewer_context::{ComponentUiRegistry, UiVerbosity, ViewerContext}; @@ -44,7 +44,8 @@ pub fn add_to_registry(registry: &mut Com Box::new( |ctx, ui, verbosity, query, db, entity_path, component, instance| { // TODO(#5607): what should happen if the promise is still pending? - if let Some(component) = component.instance::(db.resolver(), instance.0 as _) { + if let Some(component) = component.instance::(db.resolver(), instance.get() as _) + { component.entity_data_ui(ctx, ui, verbosity, entity_path, query, db); } else { ui.weak("(not found)"); @@ -63,13 +64,13 @@ fn fallback_component_ui( db: &EntityDb, _entity_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { // TODO(#5607): what should happen if the promise is still pending? let value = component .component_name(db.resolver()) .and_then(|component_name| { - component.instance_raw(db.resolver(), component_name, instance_key.0 as _) + component.instance_raw(db.resolver(), component_name, instance.get() as _) }); // No special ui implementation - use a generic one: diff --git a/crates/re_data_ui/src/editors.rs b/crates/re_data_ui/src/editors.rs index b22499105bce..e888ee92a59f 100644 --- a/crates/re_data_ui/src/editors.rs +++ b/crates/re_data_ui/src/editors.rs @@ -3,7 +3,7 @@ use egui::NumExt as _; use re_data_store::LatestAtQuery; use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb}; -use re_log_types::EntityPath; +use re_log_types::{EntityPath, Instance}; use re_types::{ components::{ Color, MarkerShape, MarkerSize, Name, Radius, ScalarScattering, StrokeWidth, Text, @@ -24,11 +24,11 @@ fn edit_color_ui( entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { let current_color = component // TODO(#5607): what should happen if the promise is still pending? - .instance::(db.resolver(), instance_key.0 as _) + .instance::(db.resolver(), instance.get() as _) .unwrap_or_else(|| default_color(ctx, query, db, entity_path)); let current_color = current_color.into(); @@ -67,11 +67,11 @@ fn edit_text_ui( entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { let current_text = component // TODO(#5607): what should happen if the promise is still pending? - .instance::(db.resolver(), instance_key.0 as _) + .instance::(db.resolver(), instance.get() as _) .unwrap_or_else(|| default_text(ctx, query, db, entity_path)); let current_text = current_text.to_string(); @@ -107,11 +107,11 @@ fn edit_name_ui( entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { let current_text = component // TODO(#5607): what should happen if the promise is still pending? - .instance::(db.resolver(), instance_key.0 as _) + .instance::(db.resolver(), instance.get() as _) .unwrap_or_else(|| default_name(ctx, query, db, entity_path)); let current_text = current_text.to_string(); @@ -148,11 +148,11 @@ fn edit_scatter_ui( entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { let current_scatter = component // TODO(#5607): what should happen if the promise is still pending? - .instance::(db.resolver(), instance_key.0 as _) + .instance::(db.resolver(), instance.get() as _) .unwrap_or_else(|| default_scatter(ctx, query, db, entity_path)); let current_scatter = current_scatter.0; @@ -197,11 +197,11 @@ fn edit_radius_ui( entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { let current_radius = component // TODO(#5607): what should happen if the promise is still pending? - .instance::(db.resolver(), instance_key.0 as _) + .instance::(db.resolver(), instance.get() as _) .unwrap_or_else(|| default_radius(ctx, query, db, entity_path)); let current_radius = current_radius.0; @@ -244,11 +244,11 @@ fn edit_marker_shape_ui( entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { let current_marker = component // TODO(#5607): what should happen if the promise is still pending? - .instance::(db.resolver(), instance_key.0 as _) + .instance::(db.resolver(), instance.get() as _) .unwrap_or_else(|| default_marker_shape(ctx, query, db, entity_path)); let mut edit_marker = current_marker; @@ -330,11 +330,11 @@ fn edit_stroke_width_ui( entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { let current_stroke_width = component // TODO(#5607): what should happen if the promise is still pending? - .instance::(db.resolver(), instance_key.0 as _) + .instance::(db.resolver(), instance.get() as _) .unwrap_or_else(|| default_stroke_width(ctx, query, db, entity_path)); let current_stroke_width = current_stroke_width.0; @@ -377,11 +377,11 @@ fn edit_marker_size_ui( entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &re_types::components::InstanceKey, + instance: &Instance, ) { let current_marker_size = component // TODO(#5607): what should happen if the promise is still pending? - .instance::(db.resolver(), instance_key.0 as _) + .instance::(db.resolver(), instance.get() as _) .unwrap_or_else(|| default_marker_size(ctx, query, db, entity_path)); let current_marker_size = current_marker_size.0; @@ -426,7 +426,7 @@ fn register_editor<'a, C: Component + Loggable + 'static>( &EntityPath, &EntityPath, &LatestAtComponentResults, - &re_types::components::InstanceKey, + &Instance, ), ) where C: Into<::std::borrow::Cow<'a, C>>, diff --git a/crates/re_data_ui/src/entity_path.rs b/crates/re_data_ui/src/entity_path.rs index 6348b21ddbac..e010d7fb5860 100644 --- a/crates/re_data_ui/src/entity_path.rs +++ b/crates/re_data_ui/src/entity_path.rs @@ -12,6 +12,6 @@ impl DataUi for re_entity_db::EntityPath { query: &re_data_store::LatestAtQuery, db: &re_entity_db::EntityDb, ) { - InstancePath::entity_splat(self.clone()).data_ui(ctx, ui, verbosity, query, db); + InstancePath::entity_all(self.clone()).data_ui(ctx, ui, verbosity, query, db); } } diff --git a/crates/re_data_ui/src/instance_path.rs b/crates/re_data_ui/src/instance_path.rs index 87155fa7ae46..1970c4acc227 100644 --- a/crates/re_data_ui/src/instance_path.rs +++ b/crates/re_data_ui/src/instance_path.rs @@ -18,7 +18,7 @@ impl DataUi for InstancePath { ) { let Self { entity_path, - instance_key, + instance, } = self; let Some(components) = ctx @@ -93,7 +93,7 @@ impl DataUi for InstancePath { db, ); - if instance_key.is_splat() { + if instance.is_all() { crate::EntityLatestAtResults { entity_path: entity_path.clone(), component_name, @@ -109,7 +109,7 @@ impl DataUi for InstancePath { db, entity_path, results, - instance_key, + instance, ); } diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index ccbc561a538c..88d403ad0f56 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -47,7 +47,7 @@ pub fn entity_path_button( db, ui, space_view_id, - &InstancePath::entity_splat(entity_path.clone()), + &InstancePath::entity_all(entity_path.clone()), entity_path.syntax_highlighted(ui.style()), ) } @@ -67,7 +67,7 @@ pub fn entity_path_parts_buttons( ui.spacing_mut().item_spacing.x = 2.0; // Show one single icon up-front instead: - let instance_path = InstancePath::entity_splat(entity_path.clone()); + let instance_path = InstancePath::entity_all(entity_path.clone()); ui.add(instance_path_icon(&query.timeline(), db, &instance_path).as_image()); let mut accumulated = Vec::new(); @@ -81,7 +81,7 @@ pub fn entity_path_parts_buttons( db, ui, space_view_id, - &InstancePath::entity_splat(accumulated.clone().into()), + &InstancePath::entity_all(accumulated.clone().into()), part.syntax_highlighted(ui.style()), with_icon, ); @@ -106,7 +106,7 @@ pub fn entity_path_button_to( db, ui, space_view_id, - &InstancePath::entity_splat(entity_path.clone()), + &InstancePath::entity_all(entity_path.clone()), text, ) } @@ -140,7 +140,7 @@ pub fn instance_path_icon( db: &re_entity_db::EntityDb, instance_path: &InstancePath, ) -> &'static icons::Icon { - if instance_path.is_splat() { + if instance_path.is_all() { // It is an entity path if db .store() @@ -268,13 +268,13 @@ pub fn instance_path_parts_buttons( db, ui, space_view_id, - &InstancePath::entity_splat(accumulated.clone().into()), + &InstancePath::entity_all(accumulated.clone().into()), part.syntax_highlighted(ui.style()), with_icon, ); } - if !instance_path.instance_key.is_splat() { + if !instance_path.instance.is_all() { ui.weak("["); instance_path_button_to_ex( ctx, @@ -283,7 +283,7 @@ pub fn instance_path_parts_buttons( ui, space_view_id, instance_path, - instance_path.instance_key.syntax_highlighted(ui.style()), + instance_path.instance.syntax_highlighted(ui.style()), with_icon, ); ui.weak("]"); @@ -419,10 +419,7 @@ pub fn data_blueprint_button_to( space_view_id: SpaceViewId, entity_path: &EntityPath, ) -> egui::Response { - let item = Item::DataResult( - space_view_id, - InstancePath::entity_splat(entity_path.clone()), - ); + let item = Item::DataResult(space_view_id, InstancePath::entity_all(entity_path.clone())); let response = ui .selectable_label(ctx.selection().contains_item(&item), text) .on_hover_ui(|ui| { @@ -505,7 +502,8 @@ pub fn cursor_interact_with_selectable( /// Displays the "hover card" (i.e. big tooltip) for an instance or an entity. /// -/// The entity hover card is displayed the provided instance path is a splat. +/// The entity hover card is displayed if the provided instance path doesn't refer to a specific +/// instance. pub fn instance_hover_card_ui( ui: &mut egui::Ui, ctx: &ViewerContext<'_>, @@ -518,7 +516,7 @@ pub fn instance_hover_card_ui( return; } - let subtype_string = if instance_path.instance_key.is_splat() { + let subtype_string = if instance_path.instance.is_all() { "Entity" } else { "Entity instance" @@ -529,7 +527,7 @@ pub fn instance_hover_card_ui( // TODO(emilk): give data_ui an alternate "everything on this timeline" query? // Then we can move the size view into `data_ui`. - if instance_path.instance_key.is_splat() { + if instance_path.instance.is_all() { if let Some(subtree) = ctx.recording().tree().subtree(&instance_path.entity_path) { entity_tree_stats_ui(ui, &query.timeline(), subtree); } @@ -548,7 +546,7 @@ pub fn entity_hover_card_ui( db: &re_entity_db::EntityDb, entity_path: &EntityPath, ) { - let instance_path = InstancePath::entity_splat(entity_path.clone()); + let instance_path = InstancePath::entity_all(entity_path.clone()); instance_hover_card_ui(ui, ctx, query, db, &instance_path); } diff --git a/crates/re_data_ui/src/lib.rs b/crates/re_data_ui/src/lib.rs index 698db4a171f9..6e6b696d4e36 100644 --- a/crates/re_data_ui/src/lib.rs +++ b/crates/re_data_ui/src/lib.rs @@ -59,7 +59,7 @@ pub fn ui_visible_components<'a>( /// Show this component in the UI. pub fn is_component_visible_in_ui(component_name: &ComponentName) -> bool { - const HIDDEN_COMPONENTS: &[&str] = &["rerun.components.InstanceKey"]; + const HIDDEN_COMPONENTS: &[&str] = &[]; !HIDDEN_COMPONENTS.contains(&component_name.as_ref()) } diff --git a/crates/re_entity_db/examples/memory_usage.rs b/crates/re_entity_db/examples/memory_usage.rs index 608ec9d3b0b2..f8431a681d89 100644 --- a/crates/re_entity_db/examples/memory_usage.rs +++ b/crates/re_entity_db/examples/memory_usage.rs @@ -112,7 +112,6 @@ fn log_messages() { RowId::new(), entity_path!("points"), [build_frame_nr(TimeInt::ZERO)], - 1, build_some_positions2d(1), ) .unwrap() @@ -139,7 +138,6 @@ fn log_messages() { RowId::new(), entity_path!("points"), [build_frame_nr(TimeInt::ZERO)], - NUM_POINTS as _, build_some_positions2d(NUM_POINTS), ) .unwrap() diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index 2355ce9dfe1b..c7b7e8f29fd5 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -13,7 +13,7 @@ use re_log_types::{ TimeRange, TimeRangeF, Timeline, }; use re_query::PromiseResult; -use re_types_core::{components::InstanceKey, Archetype, Loggable}; +use re_types_core::{Archetype, Loggable}; use crate::{ClearCascade, CompactedStoreEvents, Error, TimesPerTimeline}; @@ -127,11 +127,8 @@ pub struct EntityDb { impl EntityDb { pub fn new(store_id: StoreId) -> Self { - let data_store = re_data_store::DataStore::new( - store_id.clone(), - InstanceKey::name(), - DataStoreConfig::default(), - ); + let data_store = + re_data_store::DataStore::new(store_id.clone(), DataStoreConfig::default()); let query_caches = re_query::Caches::new(&data_store); Self { data_source: None, @@ -531,7 +528,7 @@ impl EntityDb { // 2. Otherwise we will end up with a flaky row ordering, as we have no way to tie-break // these rows! This flaky ordering will in turn leak through the public // API (e.g. range queries)! - match DataRow::from_cells(row_id, timepoint.clone(), entity_path, 0, cells) { + match DataRow::from_cells(row_id, timepoint.clone(), entity_path, cells) { Ok(row) => { let res = insert_row_with_retries( &mut self.data_store, diff --git a/crates/re_entity_db/src/instance_path.rs b/crates/re_entity_db/src/instance_path.rs index d0d2817c10d5..ffd05a7986fa 100644 --- a/crates/re_entity_db/src/instance_path.rs +++ b/crates/re_entity_db/src/instance_path.rs @@ -1,13 +1,12 @@ use std::{hash::Hash, str::FromStr}; -use re_log_types::{DataPath, EntityPath, EntityPathHash, PathParseError, RowId}; -use re_types_core::components::InstanceKey; +use re_log_types::{DataPath, EntityPath, EntityPathHash, Instance, PathParseError, RowId}; use crate::{EntityDb, VersionedInstancePath, VersionedInstancePathHash}; // ---------------------------------------------------------------------------- -/// The path to either a specific instance of an entity, or the whole entity (splat). +/// The path to either a specific instance of an entity, or the whole entity. #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct InstancePath { @@ -15,36 +14,36 @@ pub struct InstancePath { /// If this is a concrete instance, what instance index are we? /// - /// If we refer to all instance, [`InstanceKey::SPLAT`] is used. - pub instance_key: InstanceKey, + /// If we refer to all instances, [`Instance::ALL`] is used. + pub instance: Instance, } impl From for InstancePath { #[inline] fn from(entity_path: EntityPath) -> Self { - Self::entity_splat(entity_path) + Self::entity_all(entity_path) } } impl InstancePath { - /// Indicate the whole entity (all instances of it) - i.e. a splat. + /// Indicate the whole entity (all instances of it). /// /// For example: the whole point cloud, rather than a specific point. #[inline] - pub fn entity_splat(entity_path: EntityPath) -> Self { + pub fn entity_all(entity_path: EntityPath) -> Self { Self { entity_path, - instance_key: InstanceKey::SPLAT, + instance: Instance::ALL, } } /// Indicate a specific instance of the entity, /// e.g. a specific point in a point cloud entity. #[inline] - pub fn instance(entity_path: EntityPath, instance_key: InstanceKey) -> Self { + pub fn instance(entity_path: EntityPath, instance: Instance) -> Self { Self { entity_path, - instance_key, + instance, } } @@ -52,8 +51,8 @@ impl InstancePath { /// /// For example: the whole point cloud, rather than a specific point. #[inline] - pub fn is_splat(&self) -> bool { - self.instance_key.is_splat() + pub fn is_all(&self) -> bool { + self.instance.is_all() } /// Versions this instance path by stamping it with the specified [`RowId`]. @@ -69,17 +68,17 @@ impl InstancePath { pub fn hash(&self) -> InstancePathHash { InstancePathHash { entity_path_hash: self.entity_path.hash(), - instance_key: self.instance_key, + instance: self.instance, } } } impl std::fmt::Display for InstancePath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.instance_key.is_splat() { + if self.instance.is_all() { self.entity_path.fmt(f) } else { - format!("{}[{}]", self.entity_path, self.instance_key).fmt(f) + format!("{}[{}]", self.entity_path, self.instance).fmt(f) } } } @@ -90,7 +89,7 @@ impl FromStr for InstancePath { fn from_str(s: &str) -> Result { let DataPath { entity_path, - instance_key, + instance, component_name, } = DataPath::from_str(s)?; @@ -98,11 +97,11 @@ impl FromStr for InstancePath { return Err(PathParseError::UnexpectedComponentName(component_name)); } - let instance_key = instance_key.unwrap_or(InstanceKey::SPLAT); + let instance = instance.unwrap_or(Instance::ALL); Ok(InstancePath { entity_path, - instance_key, + instance, }) } } @@ -113,7 +112,7 @@ fn test_parse_instance_path() { InstancePath::from_str("world/points[#123]"), Ok(InstancePath { entity_path: EntityPath::from("world/points"), - instance_key: InstanceKey(123) + instance: Instance::from(123) }) ); } @@ -122,30 +121,30 @@ fn test_parse_instance_path() { /// Hashes of the components of an [`InstancePath`]. /// -/// This is unique to either a specific instance of an entity, or the whole entity (splat). +/// This is unique to either a specific instance of an entity, or the whole entity. #[derive(Clone, Copy, Eq)] pub struct InstancePathHash { pub entity_path_hash: EntityPathHash, /// If this is a concrete instance, what instance index are we? /// - /// If we refer to all instance, [`InstanceKey::SPLAT`] is used. + /// If we refer to all instance, [`Instance::ALL`] is used. /// /// Note that this is NOT hashed, because we don't need to (it's already small). - pub instance_key: InstanceKey, + pub instance: Instance, } impl std::fmt::Debug for InstancePathHash { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { entity_path_hash, - instance_key, + instance, } = self; write!( f, "InstancePathHash({:016X}, {})", entity_path_hash.hash64(), - instance_key.0 + instance.get() ) } } @@ -155,11 +154,11 @@ impl std::hash::Hash for InstancePathHash { fn hash(&self, state: &mut H) { let Self { entity_path_hash, - instance_key, + instance, } = self; state.write_u64(entity_path_hash.hash64()); - state.write_u64(instance_key.0); + state.write_u64(instance.get()); } } @@ -168,37 +167,37 @@ impl std::cmp::PartialEq for InstancePathHash { fn eq(&self, other: &Self) -> bool { let Self { entity_path_hash, - instance_key, + instance, } = self; - entity_path_hash == &other.entity_path_hash && instance_key == &other.instance_key + entity_path_hash == &other.entity_path_hash && instance == &other.instance } } impl InstancePathHash { pub const NONE: Self = Self { entity_path_hash: EntityPathHash::NONE, - instance_key: InstanceKey::SPLAT, + instance: Instance::ALL, }; - /// Indicate the whole entity (all instances of it) - i.e. a splat. + /// Indicate the whole entity (all instances of it). /// /// For example: the whole point cloud, rather than a specific point. #[inline] - pub fn entity_splat(entity_path: &EntityPath) -> Self { + pub fn entity_all(entity_path: &EntityPath) -> Self { Self { entity_path_hash: entity_path.hash(), - instance_key: InstanceKey::SPLAT, + instance: Instance::ALL, } } /// Indicate a specific instance of the entity, /// e.g. a specific point in a point cloud entity. #[inline] - pub fn instance(entity_path: &EntityPath, instance_key: InstanceKey) -> Self { + pub fn instance(entity_path: &EntityPath, instance: Instance) -> Self { Self { entity_path_hash: entity_path.hash(), - instance_key, + instance, } } @@ -226,11 +225,11 @@ impl InstancePathHash { .entity_path_from_hash(&self.entity_path_hash) .cloned()?; - let instance_key = self.instance_key; + let instance = self.instance; Some(InstancePath { entity_path, - instance_key, + instance, }) } } diff --git a/crates/re_entity_db/src/versioned_instance_path.rs b/crates/re_entity_db/src/versioned_instance_path.rs index eedc219b2b2d..e7dc24e4a0a8 100644 --- a/crates/re_entity_db/src/versioned_instance_path.rs +++ b/crates/re_entity_db/src/versioned_instance_path.rs @@ -7,7 +7,7 @@ use crate::{InstancePath, InstancePathHash}; // ---------------------------------------------------------------------------- /// A versioned path (i.e. pinned to a specific [`RowId`]) to either a specific instance of an entity, -/// or the whole entity (splat). +/// or the whole entity. /// /// The easiest way to construct this type is via [`crate::InstancePath::versioned`]. #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -22,8 +22,8 @@ impl VersionedInstancePath { /// /// For example: the whole point cloud, rather than a specific point. #[inline] - pub fn is_splat(&self) -> bool { - self.instance_path.is_splat() + pub fn is_all(&self) -> bool { + self.instance_path.is_all() } #[inline] @@ -75,11 +75,11 @@ impl std::hash::Hash for VersionedInstancePathHash { } = self; let InstancePathHash { entity_path_hash, - instance_key, + instance, } = instance_path_hash; state.write_u64(entity_path_hash.hash64()); - state.write_u64(instance_key.0); + state.write_u64(instance.get()); state.write_u128(row_id.as_u128()); } } diff --git a/crates/re_entity_db/tests/clear.rs b/crates/re_entity_db/tests/clear.rs index 3172536078d4..fb201eb3fd3e 100644 --- a/crates/re_entity_db/tests/clear.rs +++ b/crates/re_entity_db/tests/clear.rs @@ -1,14 +1,10 @@ use re_data_store::{DataStore, LatestAtQuery}; use re_entity_db::EntityDb; use re_log_types::{ - example_components::{MyColor, MyPoint}, + example_components::{MyColor, MyIndex, MyPoint}, DataRow, EntityPath, RowId, StoreId, TimeInt, TimePoint, Timeline, }; -use re_types_core::{ - archetypes::Clear, - components::{ClearIsRecursive, InstanceKey}, - AsComponents, -}; +use re_types_core::{archetypes::Clear, components::ClearIsRecursive, AsComponents}; // --- @@ -222,28 +218,27 @@ fn clears() -> anyhow::Result<()> { { let row_id = RowId::new(); let timepoint = TimePoint::from_iter([(timeline_frame, 9)]); - let instance_key = InstanceKey(0); + let instance = MyIndex(0); let row = DataRow::from_component_batches( row_id, timepoint, entity_path_parent.clone(), - [&[instance_key] as _], + [&[instance] as _], )?; db.add_data_row(row)?; { let query = LatestAtQuery::new(timeline_frame, 9); - let (_, _, got_instance_key) = - query_latest_component::(db.store(), &entity_path_parent, &query) - .unwrap(); - similar_asserts::assert_eq!(instance_key, got_instance_key); + let (_, _, got_instance) = + query_latest_component::(db.store(), &entity_path_parent, &query).unwrap(); + similar_asserts::assert_eq!(instance, got_instance); } { let query = LatestAtQuery::new(timeline_frame, 11); assert!( - query_latest_component::(db.store(), &entity_path_parent, &query) + query_latest_component::(db.store(), &entity_path_parent, &query) .is_none() ); } diff --git a/crates/re_entity_db/tests/time_histograms.rs b/crates/re_entity_db/tests/time_histograms.rs index e62aeaabc2fa..e78efafa6f34 100644 --- a/crates/re_entity_db/tests/time_histograms.rs +++ b/crates/re_entity_db/tests/time_histograms.rs @@ -4,16 +4,10 @@ use re_data_store::GarbageCollectionOptions; use re_entity_db::EntityDb; use re_int_histogram::RangeI64; use re_log_types::{ - example_components::{MyColor, MyPoint}, + example_components::{MyColor, MyIndex, MyPoint}, DataRow, EntityPath, RowId, StoreId, TimeInt, TimePoint, Timeline, }; -use re_types_core::{ - components::{ClearIsRecursive, InstanceKey}, - ComponentName, Loggable, -}; - -// TODO(cmc): This should also test for the timeless counts but right now they're a bit all over -// the place, so need to land new reworked EntityTree etc first. +use re_types_core::{components::ClearIsRecursive, ComponentName, Loggable}; // --- @@ -31,7 +25,7 @@ fn time_histograms() -> anyhow::Result<()> { let entity_grandchild: EntityPath = "parent/child/grandchild".into(); let entity_unrelated: EntityPath = "very/unrelated".into(); - // Single top-level entity, explicitly logged `InstanceKey`s. + // Single top-level entity, explicitly logged `MyIndex`s. { let row = DataRow::from_component_batches( RowId::new(), @@ -41,7 +35,7 @@ fn time_histograms() -> anyhow::Result<()> { (timeline_yet_another, 1), // ]), entity_parent.clone(), - [&InstanceKey::from_iter(0..10) as _], + [&MyIndex::from_iter(0..10) as _], )?; db.add_data_row(row)?; @@ -72,7 +66,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_parent, - InstanceKey::name(), + MyIndex::name(), [ (&timeline_frame, Some(&[(RangeI64::new(42, 42), 1)])), (&timeline_other, Some(&[(RangeI64::new(666, 666), 1)])), @@ -81,7 +75,7 @@ fn time_histograms() -> anyhow::Result<()> { ); } - // Grand-child, multiple components, auto-generated `InstanceKey`s. + // Grand-child, multiple components, auto-generated `MyIndex`s. { let row = { let num_instances = 3; @@ -128,7 +122,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_parent, - InstanceKey::name(), + MyIndex::name(), [ (&timeline_frame, Some(&[(RangeI64::new(42, 42), 1)])), (&timeline_other, Some(&[(RangeI64::new(666, 666), 1)])), @@ -162,7 +156,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_grandchild, - InstanceKey::name(), + MyIndex::name(), [(&timeline_frame, None), (&timeline_yet_another, None)] as [(_, Option<&[_]>); 2], ); assert_histogram_for_component( @@ -212,7 +206,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_grandchild, - InstanceKey::name(), + MyIndex::name(), [(&timeline_frame, None), (&timeline_yet_another, None)] as [(_, Option<&[_]>); 2], ); assert_histogram_for_component( @@ -245,7 +239,7 @@ fn time_histograms() -> anyhow::Result<()> { TimePoint::default(), "entity".into(), [ - &InstanceKey::from_iter(0..num_instances as _) as _, + &MyIndex::from_iter(0..num_instances as _) as _, &colors as _, ], )? @@ -299,7 +293,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_grandchild, - InstanceKey::name(), + MyIndex::name(), [(&timeline_frame, None), (&timeline_yet_another, None)] as [(_, Option<&[_]>); 2], ); assert_histogram_for_component( @@ -339,7 +333,7 @@ fn time_histograms() -> anyhow::Result<()> { ]), entity_unrelated.clone(), [ - &InstanceKey::from_iter(0..num_instances) as _, + &MyIndex::from_iter(0..num_instances) as _, &points as _, &colors as _, ], @@ -382,7 +376,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_parent, - InstanceKey::name(), + MyIndex::name(), [ (&timeline_frame, Some(&[(RangeI64::new(42, 42), 1)])), (&timeline_other, Some(&[(RangeI64::new(666, 666), 1)])), @@ -415,7 +409,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_unrelated, - InstanceKey::name(), + MyIndex::name(), [ (&timeline_frame, Some(&[(RangeI64::new(1234, 1234), 1)])), (&timeline_other, Some(&[(RangeI64::new(1235, 1235), 1)])), @@ -487,8 +481,8 @@ fn time_histograms() -> anyhow::Result<()> { &timeline_frame, Some(&[ (RangeI64::new(42, 42), 5), - // We're clearing the parent's `InstanceKey` as well as the grandchild's - // `MyPoint`, `MyColor` and `InstanceKey`. That's four. + // We're clearing the parent's `MyIndex` as well as the grandchild's + // `MyPoint`, `MyColor` and `MyIndex`. That's four. (RangeI64::new(1000, 1000), 4), (RangeI64::new(1234, 1234), 3), ]), @@ -508,7 +502,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_parent, - InstanceKey::name(), + MyIndex::name(), [ ( &timeline_frame, @@ -523,7 +517,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_grandchild, - InstanceKey::name(), + MyIndex::name(), [ (&timeline_frame, None), (&timeline_other, None), @@ -533,7 +527,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_grandchild, - InstanceKey::name(), + MyIndex::name(), [(&timeline_frame, None), (&timeline_yet_another, None)] as [(_, Option<&[_]>); 2], ); // NOTE: even though the component was logged twice at the same timestamp, the clear will @@ -593,7 +587,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_parent, - InstanceKey::name(), + MyIndex::name(), [ (&timeline_frame, Some(&[])), (&timeline_other, Some(&[])), @@ -605,7 +599,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_grandchild, - InstanceKey::name(), + MyIndex::name(), [ (&timeline_frame, None), (&timeline_other, None), @@ -615,7 +609,7 @@ fn time_histograms() -> anyhow::Result<()> { assert_histogram_for_component( &db, &entity_grandchild, - InstanceKey::name(), + MyIndex::name(), [(&timeline_frame, None), (&timeline_yet_another, None)] as [(_, Option<&[_]>); 2], ); assert_histogram_for_component( diff --git a/crates/re_log_encoding/benches/msg_encode_benchmark.rs b/crates/re_log_encoding/benches/msg_encode_benchmark.rs index df825fffe618..c02bc4cec8e5 100644 --- a/crates/re_log_encoding/benches/msg_encode_benchmark.rs +++ b/crates/re_log_encoding/benches/msg_encode_benchmark.rs @@ -75,7 +75,6 @@ fn mono_points_arrow(c: &mut Criterion) { RowId::ZERO, entity_path!("points", i.to_string()), [build_frame_nr(TimeInt::ZERO)], - 1, (build_some_positions2d(1), build_some_colors(1)), ) .unwrap()], @@ -133,7 +132,6 @@ fn mono_points_arrow_batched(c: &mut Criterion) { RowId::ZERO, entity_path!("points", i.to_string()), [build_frame_nr(TimeInt::ZERO)], - 1, (build_some_positions2d(1), build_some_colors(1)), ) .unwrap() @@ -189,7 +187,6 @@ fn batch_points_arrow(c: &mut Criterion) { RowId::ZERO, entity_path!("points"), [build_frame_nr(TimeInt::ZERO)], - NUM_POINTS as _, ( build_some_positions2d(NUM_POINTS), build_some_colors(NUM_POINTS), diff --git a/crates/re_log_types/src/data_cell.rs b/crates/re_log_types/src/data_cell.rs index 7ab86bba9fcb..9770e56343d9 100644 --- a/crates/re_log_types/src/data_cell.rs +++ b/crates/re_log_types/src/data_cell.rs @@ -667,42 +667,3 @@ impl DataCellInner { + values.total_size_bytes(); } } - -#[test] -fn data_cell_sizes() { - use crate::DataCell; - use arrow2::array::UInt64Array; - use re_types_core::components::InstanceKey; - use re_types_core::Loggable as _; - - // not computed - // NOTE: Unsized cells are illegal in debug mode and will flat out crash. - if !cfg!(debug_assertions) { - let cell = DataCell::from_arrow(InstanceKey::name(), UInt64Array::from_vec(vec![]).boxed()); - assert_eq!(0, cell.heap_size_bytes()); - assert_eq!(0, cell.heap_size_bytes()); - } - - // zero-sized - { - let mut cell = - DataCell::from_arrow(InstanceKey::name(), UInt64Array::from_vec(vec![]).boxed()); - cell.compute_size_bytes(); - - assert_eq!(168, cell.heap_size_bytes()); - assert_eq!(168, cell.heap_size_bytes()); - } - - // anything else - { - let mut cell = DataCell::from_arrow( - InstanceKey::name(), - UInt64Array::from_vec(vec![1, 2, 3]).boxed(), - ); - cell.compute_size_bytes(); - - // zero-sized + 3x u64s - assert_eq!(192, cell.heap_size_bytes()); - assert_eq!(192, cell.heap_size_bytes()); - } -} diff --git a/crates/re_log_types/src/data_row.rs b/crates/re_log_types/src/data_row.rs index c1fdb9c8b72f..d7711c222425 100644 --- a/crates/re_log_types/src/data_row.rs +++ b/crates/re_log_types/src/data_row.rs @@ -4,7 +4,7 @@ use smallvec::SmallVec; use re_types_core::{AsComponents, ComponentName, SizeBytes}; -use crate::{DataCell, DataCellError, DataTable, EntityPath, NumInstances, TableId, TimePoint}; +use crate::{DataCell, DataCellError, DataTable, EntityPath, TableId, TimePoint}; // --- @@ -231,16 +231,15 @@ re_types_core::delegate_arrow_tuid!(RowId as "rerun.controls.RowId"); /// /// ## Layout /// -/// A row is a collection of cells where each cell must either be empty (a clear), unit-lengthed -/// (a splat) or `num_instances` long (standard): `[[C1, C1, C1], [], [C3], [C4, C4, C4], …]`. +/// A row is a collection of cells where each cell can have an arbitrary number of +/// instances: `[[C1, C1, C1], [], [C3], [C4, C4, C4], …]`. /// /// Consider this example: /// ```ignore -/// let num_instances = 2; /// let points: &[MyPoint] = &[[10.0, 10.0].into(), [20.0, 20.0].into()]; /// let colors: &[_] = &[MyColor::from_rgb(128, 128, 128)]; /// let labels: &[MyLabel] = &[]; -/// let row = DataRow::from_cells3(row_id, timepoint, ent_path, num_instances, (points, colors, labels)); +/// let row = DataRow::from_cells3(row_id, timepoint, ent_path, (points, colors, labels)); /// ``` /// /// A row has no arrow representation nor datatype of its own, as it is merely a collection of @@ -269,7 +268,6 @@ re_types_core::delegate_arrow_tuid!(RowId as "rerun.controls.RowId"); /// # (Timeline::new_sequence("clock"), 666), // /// # ]; /// # -/// let num_instances = 2; /// let points: &[MyPoint] = &[MyPoint { x: 10.0, y: 10.0}, MyPoint { x: 20.0, y: 20.0 }]; /// let colors: &[_] = &[MyColor(0xff7f7f7f)]; /// let labels: &[MyLabel] = &[]; @@ -278,7 +276,6 @@ re_types_core::delegate_arrow_tuid!(RowId as "rerun.controls.RowId"); /// row_id, /// "a/b/c", /// timepoint, -/// num_instances, /// (points, colors, labels), /// ).unwrap(); /// eprintln!("{row}"); @@ -297,14 +294,6 @@ pub struct DataRow { /// User-specified [`EntityPath`] for this event. pub entity_path: EntityPath, - /// The expected number of values (== component instances) in each cell. - /// - /// Each cell must have either: - /// - 0 instance (clear), - /// - 1 instance (splat), - /// - `num_instances` instances (standard). - pub num_instances: NumInstances, - /// The actual cells (== columns, == components). pub cells: DataCellRow, } @@ -342,26 +331,18 @@ impl DataRow { .map(DataCell::from_component_batch) .collect::, _>>()?; - // TODO(emilk): should `DataRow::from_cells` calculate `num_instances` instead? - let num_instances = data_cells.iter().map(|cell| cell.num_instances()).max(); - let num_instances = num_instances.unwrap_or(0); - - let mut row = - DataRow::from_cells(row_id, timepoint, entity_path, num_instances, data_cells)?; + let mut row = DataRow::from_cells(row_id, timepoint, entity_path, data_cells)?; row.compute_all_size_bytes(); Ok(row) } /// Builds a new `DataRow` from an iterable of [`DataCell`]s. /// - /// Fails if: - /// - one or more cell isn't 0, 1 or `num_instances` long, - /// - two or more cells share the same component type. + /// Fails if two or more cells share the same component type. pub fn from_cells( row_id: RowId, timepoint: impl Into, entity_path: impl Into, - num_instances: u32, cells: impl IntoIterator, ) -> DataReadResult { let cells = DataCellRow(cells.into_iter().collect()); @@ -385,7 +366,6 @@ impl DataRow { row_id, entity_path, timepoint, - num_instances: num_instances.into(), cells, }) } @@ -412,14 +392,12 @@ impl SizeBytes for DataRow { row_id, timepoint, entity_path, - num_instances, cells, } = self; row_id.heap_size_bytes() + timepoint.heap_size_bytes() + entity_path.heap_size_bytes() - + num_instances.heap_size_bytes() + cells.heap_size_bytes() } } @@ -450,11 +428,6 @@ impl DataRow { self.cells.iter().map(|cell| cell.component_name()) } - #[inline] - pub fn num_instances(&self) -> NumInstances { - self.num_instances - } - #[inline] pub fn cells(&self) -> &DataCellRow { &self.cells @@ -501,7 +474,6 @@ impl DataRow { row_id: RowId, entity_path: impl Into, timepoint: impl Into, - num_instances: u32, into_cells: C0, ) -> DataReadResult where @@ -511,7 +483,6 @@ impl DataRow { row_id, timepoint.into(), entity_path.into(), - num_instances, [into_cells.into()], )?; this.compute_all_size_bytes(); @@ -522,7 +493,6 @@ impl DataRow { row_id: RowId, entity_path: impl Into, timepoint: impl Into, - num_instances: u32, into_cells: C0, ) -> DataRowResult where @@ -533,7 +503,6 @@ impl DataRow { row_id, timepoint.into(), entity_path.into(), - num_instances, [into_cells.try_into()?], )?) } @@ -547,7 +516,6 @@ impl DataRow { row_id: RowId, entity_path: impl Into, timepoint: impl Into, - num_instances: u32, into_cells: (C0, C1), ) -> DataRowResult where @@ -558,7 +526,6 @@ impl DataRow { row_id, timepoint.into(), entity_path.into(), - num_instances, [ into_cells.0.into(), // into_cells.1.into(), // @@ -572,7 +539,6 @@ impl DataRow { row_id: RowId, entity_path: impl Into, timepoint: impl Into, - num_instances: u32, into_cells: (C0, C1), ) -> DataRowResult where @@ -585,7 +551,6 @@ impl DataRow { row_id, timepoint.into(), entity_path.into(), - num_instances, [ into_cells.0.try_into()?, // into_cells.1.try_into()?, // @@ -597,7 +562,6 @@ impl DataRow { row_id: RowId, entity_path: impl Into, timepoint: impl Into, - num_instances: u32, into_cells: (C0, C1, C2), ) -> DataRowResult where @@ -612,7 +576,6 @@ impl DataRow { row_id, timepoint.into(), entity_path.into(), - num_instances, [ into_cells.0.try_into()?, // into_cells.1.try_into()?, // diff --git a/crates/re_log_types/src/data_table.rs b/crates/re_log_types/src/data_table.rs index a079064453b5..fbe2f9ed2b51 100644 --- a/crates/re_log_types/src/data_table.rs +++ b/crates/re_log_types/src/data_table.rs @@ -11,7 +11,7 @@ use re_types_core::{ComponentName, Loggable, SizeBytes}; use crate::{ data_row::DataReadResult, ArrowMsg, DataCell, DataCellError, DataRow, DataRowError, EntityPath, - NumInstances, RowId, TimePoint, Timeline, + RowId, TimePoint, Timeline, }; // --- @@ -63,8 +63,6 @@ pub type ErasedTimeVec = VecDeque; pub type EntityPathVec = VecDeque; -pub type NumInstancesVec = VecDeque; - pub type DataCellOptVec = VecDeque>; /// A column's worth of [`DataCell`]s: a sparse collection of [`DataCell`]s that share the same @@ -229,8 +227,7 @@ re_types_core::delegate_arrow_tuid!(TableId as "rerun.controls.TableId"); /// ## Layout /// /// A table is a collection of sparse rows, which are themselves collections of cells, where each -/// cell must either be empty (a clear), unit-lengthed (a splat) or `num_instances` long -/// (standard): +/// cell can contain an arbitrary number of instances: /// ```text /// [ /// [[C1, C1, C1], [], [C3], [C4, C4, C4], …], @@ -243,22 +240,19 @@ re_types_core::delegate_arrow_tuid!(TableId as "rerun.controls.TableId"); /// Consider this example: /// ```ignore /// let row0 = { -/// let num_instances = 2; /// let points: &[MyPoint] = &[[10.0, 10.0].into(), [20.0, 20.0].into()]; /// let colors: &[_] = &[MyColor::from_rgb(128, 128, 128)]; /// let labels: &[Label] = &[]; -/// DataRow::from_cells3(RowId::new(), "a", timepoint(1, 1), num_instances, (points, colors, labels))? +/// DataRow::from_cells3(RowId::new(), "a", timepoint(1, 1), (points, colors, labels))? /// }; /// let row1 = { -/// let num_instances = 0; /// let colors: &[MyColor] = &[]; -/// DataRow::from_cells1(RowId::new(), "b", timepoint(1, 2), num_instances, colors)? +/// DataRow::from_cells1(RowId::new(), "b", timepoint(1, 2), colors)? /// }; /// let row2 = { -/// let num_instances = 1; /// let colors: &[_] = &[MyColor::from_rgb(255, 255, 255)]; /// let labels: &[_] = &[Label("hey".into())]; -/// DataRow::from_cells2(RowId::new(), "c", timepoint(2, 1), num_instances, (colors, labels))? +/// DataRow::from_cells2(RowId::new(), "c", timepoint(2, 1), (colors, labels))? /// }; /// let table = DataTable::from_rows(table_id, [row0, row1, row2]); /// ``` @@ -268,15 +262,15 @@ re_types_core::delegate_arrow_tuid!(TableId as "rerun.controls.TableId"); /// /// The table above translates to the following, where each column is contiguous in memory: /// ```text -/// ┌──────────┬───────────────────────────────┬──────────────────────────────────┬───────────────────┬─────────────────────┬─────────────┬──────────────────────────────────┬─────────────────┐ -/// │ frame_nr ┆ log_time ┆ rerun.row_id ┆ rerun.entity_path ┆ rerun.num_instances ┆ ┆ rerun.components.Point2D ┆ rerun.components.Color │ -/// ╞══════════╪═══════════════════════════════╪══════════════════════════════════╪═══════════════════╪═════════════════════╪═════════════╪══════════════════════════════════╪═════════════════╡ -/// │ 1 ┆ 2023-04-05 09:36:47.188796402 ┆ 1753004ACBF5D6E651F2983C3DAF260C ┆ a ┆ 2 ┆ [] ┆ [{x: 10, y: 10}, {x: 20, y: 20}] ┆ [2155905279] │ -/// ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -/// │ 1 ┆ 2023-04-05 09:36:47.188852222 ┆ 1753004ACBF5D6E651F2983C3DAF260C ┆ b ┆ 0 ┆ - ┆ - ┆ [] │ -/// ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ -/// │ 2 ┆ 2023-04-05 09:36:47.188855872 ┆ 1753004ACBF5D6E651F2983C3DAF260C ┆ c ┆ 1 ┆ [hey] ┆ - ┆ [4294967295] │ -/// └──────────┴───────────────────────────────┴──────────────────────────────────┴───────────────────┴─────────────────────┴─────────────┴──────────────────────────────────┴─────────────────┘ +/// ┌──────────┬───────────────────────────────┬──────────────────────────────────┬───────────────────┬─────────────┬──────────────────────────────────┬─────────────────┐ +/// │ frame_nr ┆ log_time ┆ rerun.row_id ┆ rerun.entity_path ┆ ┆ rerun.components.Point2D ┆ rerun.components.Color │ +/// ╞══════════╪═══════════════════════════════╪══════════════════════════════════╪═══════════════════╪═════════════╪══════════════════════════════════╪═════════════════╡ +/// │ 1 ┆ 2023-04-05 09:36:47.188796402 ┆ 1753004ACBF5D6E651F2983C3DAF260C ┆ a ┆ [] ┆ [{x: 10, y: 10}, {x: 20, y: 20}] ┆ [2155905279] │ +/// ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +/// │ 1 ┆ 2023-04-05 09:36:47.188852222 ┆ 1753004ACBF5D6E651F2983C3DAF260C ┆ b ┆ - ┆ - ┆ [] │ +/// ├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ +/// │ 2 ┆ 2023-04-05 09:36:47.188855872 ┆ 1753004ACBF5D6E651F2983C3DAF260C ┆ c ┆ [hey] ┆ - ┆ [4294967295] │ +/// └──────────┴───────────────────────────────┴──────────────────────────────────┴───────────────────┴─────────────┴──────────────────────────────────┴─────────────────┘ /// ``` /// /// ## Example @@ -297,7 +291,6 @@ re_types_core::delegate_arrow_tuid!(TableId as "rerun.controls.TableId"); /// # }; /// # /// let row0 = { -/// let num_instances = 2; /// let points: &[MyPoint] = &[MyPoint { x: 10.0, y: 10.0 }, MyPoint { x: 20.0, y: 20.0 }]; /// let colors: &[_] = &[MyColor(0xff7f7f7f)]; /// let labels: &[MyLabel] = &[]; @@ -306,20 +299,17 @@ re_types_core::delegate_arrow_tuid!(TableId as "rerun.controls.TableId"); /// RowId::new(), /// "a", /// timepoint(1, 1), -/// num_instances, /// (points, colors, labels), /// ).unwrap() /// }; /// /// let row1 = { -/// let num_instances = 0; /// let colors: &[MyColor] = &[]; /// -/// DataRow::from_cells1(RowId::new(), "b", timepoint(1, 2), num_instances, colors).unwrap() +/// DataRow::from_cells1(RowId::new(), "b", timepoint(1, 2), colors).unwrap() /// }; /// /// let row2 = { -/// let num_instances = 1; /// let colors: &[_] = &[MyColor(0xff7f7f7f)]; /// let labels: &[_] = &[MyLabel("hey".into())]; /// @@ -327,7 +317,6 @@ re_types_core::delegate_arrow_tuid!(TableId as "rerun.controls.TableId"); /// RowId::new(), /// "c", /// timepoint(2, 1), -/// num_instances, /// (colors, labels), /// ).unwrap() /// }; @@ -368,11 +357,6 @@ pub struct DataTable { /// The entity each row relates to, respectively. pub col_entity_path: EntityPathVec, - /// The entire column of `num_instances`. - /// - /// Keeps track of the expected number of instances in each row. - pub col_num_instances: NumInstancesVec, - /// All the rows for all the component columns. /// /// The cells are optional since not all rows will have data for every single component @@ -388,7 +372,6 @@ impl DataTable { col_row_id: Default::default(), col_timelines: Default::default(), col_entity_path: Default::default(), - col_num_instances: Default::default(), columns: Default::default(), } } @@ -402,11 +385,10 @@ impl DataTable { // Explode all rows into columns, and keep track of which components are involved. let mut components = IntSet::default(); #[allow(clippy::type_complexity)] - let (col_row_id, col_timepoint, col_entity_path, col_num_instances, column): ( + let (col_row_id, col_timepoint, col_entity_path, column): ( RowIdVec, TimePointVec, EntityPathVec, - NumInstancesVec, Vec<_>, ) = rows .map(|row| { @@ -415,10 +397,9 @@ impl DataTable { row_id, timepoint, entity_path, - num_instances, cells, } = row; - (row_id, timepoint, entity_path, num_instances, cells) + (row_id, timepoint, entity_path, cells) }) .multiunzip(); @@ -467,7 +448,6 @@ impl DataTable { col_row_id, col_timelines, col_entity_path, - col_num_instances, columns, } } @@ -489,7 +469,6 @@ impl DataTable { col_row_id, col_timelines, col_entity_path, - col_num_instances, columns, } = self; @@ -509,7 +488,6 @@ impl DataTable { .collect::>(), ), col_entity_path[i].clone(), - col_num_instances[i].into(), cells, ) }) @@ -557,7 +535,6 @@ impl SizeBytes for DataTable { col_row_id, col_timelines, col_entity_path, - col_num_instances, columns, } = self; @@ -565,7 +542,6 @@ impl SizeBytes for DataTable { + col_row_id.heap_size_bytes() + col_timelines.heap_size_bytes() + col_entity_path.heap_size_bytes() - + col_num_instances.heap_size_bytes() + columns.heap_size_bytes() } } @@ -651,7 +627,6 @@ impl DataTable { col_row_id: _, col_timelines, col_entity_path: _, - col_num_instances: _, columns: _, } = self; @@ -680,7 +655,6 @@ impl DataTable { col_row_id, col_timelines: _, col_entity_path, - col_num_instances, columns: _, } = self; @@ -696,11 +670,6 @@ impl DataTable { schema.fields.push(entity_path_field); columns.push(entity_path_column); - let (num_instances_field, num_instances_column) = - Self::serialize_control_column(col_num_instances)?; - schema.fields.push(num_instances_field); - columns.push(num_instances_column); - schema.metadata = [(TableId::name().to_string(), table_id.to_string())].into(); Ok((schema, columns)) @@ -768,7 +737,6 @@ impl DataTable { col_row_id: _, col_timelines: _, col_entity_path: _, - col_num_instances: _, columns: table, } = self; @@ -957,12 +925,6 @@ impl DataTable { .unwrap() .as_ref(), )?; - let col_num_instances = NumInstances::from_arrow( - chunk - .get(control_index(NumInstances::name().as_str())?) - .unwrap() - .as_ref(), - )?; // --- Components --- @@ -993,7 +955,6 @@ impl DataTable { col_row_id: col_row_id.into(), col_timelines, col_entity_path: col_entity_path.into(), - col_num_instances: col_num_instances.into(), columns, }) } @@ -1160,14 +1121,12 @@ impl DataTable { row_id: _, timepoint: timepoint1, entity_path: entity_path1, - num_instances: num_instances1, cells: ref cells1, } = row1; let DataRow { row_id: _, timepoint: timepoint2, entity_path: entity_path2, - num_instances: num_instances2, cells: ref cells2, } = row2; @@ -1244,7 +1203,6 @@ impl DataTable { RowId::ZERO, "cell", TimePoint::default(), - cell.num_instances(), cell, ) .unwrap(); @@ -1286,10 +1244,7 @@ impl DataTable { } anyhow::ensure!( - timepoint1 == timepoint2 - && entity_path1 == entity_path2 - && num_instances1 == num_instances2 - && cells1 == cells2, + timepoint1 == timepoint2 && entity_path1 == entity_path2 && cells1 == cells2, "Found discrepancy in row #{ri}:\n{}\n{}\ \n\nrow1:\n{row1} \n\nrow2:\n{row2}", @@ -1334,41 +1289,25 @@ impl DataTable { }; let row0 = { - let num_instances = 2; let positions: &[MyPoint] = &[MyPoint::new(10.0, 10.0), MyPoint::new(20.0, 20.0)]; let colors: &[_] = &[MyColor(0x8080_80FF)]; let labels: &[MyLabel] = &[]; - DataRow::from_cells3( - RowId::new(), - "a", - timepoint(1), - num_instances, - (positions, colors, labels), - ) - .unwrap() + DataRow::from_cells3(RowId::new(), "a", timepoint(1), (positions, colors, labels)) + .unwrap() }; let row1 = { - let num_instances = 0; let colors: &[MyColor] = &[]; - DataRow::from_cells1(RowId::new(), "b", timepoint(1), num_instances, colors).unwrap() + DataRow::from_cells1(RowId::new(), "b", timepoint(1), colors).unwrap() }; let row2 = { - let num_instances = 1; let colors: &[_] = &[MyColor(0xFFFF_FFFF)]; let labels: &[_] = &[MyLabel("hey".into())]; - DataRow::from_cells2( - RowId::new(), - "c", - timepoint(2), - num_instances, - (colors, labels), - ) - .unwrap() + DataRow::from_cells2(RowId::new(), "c", timepoint(2), (colors, labels)).unwrap() }; let mut table = DataTable::from_rows(table_id, [row0, row1, row2]); diff --git a/crates/re_log_types/src/example_components.rs b/crates/re_log_types/src/example_components.rs index dc7bd44da0ca..2cc5b2ac3cf5 100644 --- a/crates/re_log_types/src/example_components.rs +++ b/crates/re_log_types/src/example_components.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use re_types_core::{components::InstanceKey, Loggable, SizeBytes}; +use re_types_core::{Loggable, SizeBytes}; // ---------------------------------------------------------------------------- @@ -27,7 +27,6 @@ impl re_types_core::Archetype for MyPoints { fn recommended_components() -> std::borrow::Cow<'static, [re_types_core::ComponentName]> { vec![ re_types_core::LoggableBatch::name(&Self::Indicator::default()), - InstanceKey::name(), MyColor::name(), MyLabel::name(), ] @@ -243,3 +242,63 @@ impl Loggable for MyLabel { .collect()) } } + +// ---------------------------------------------------------------------------- + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[repr(transparent)] +pub struct MyIndex(pub u64); + +impl MyIndex { + #[allow(clippy::should_implement_trait)] + #[inline] + pub fn from_iter(it: impl IntoIterator) -> Vec { + it.into_iter().map(Self).collect() + } +} + +re_types_core::macros::impl_into_cow!(MyIndex); + +impl SizeBytes for MyIndex { + #[inline] + fn heap_size_bytes(&self) -> u64 { + let Self(_) = self; + 0 + } +} + +impl Loggable for MyIndex { + type Name = re_types_core::ComponentName; + + fn name() -> Self::Name { + "example.MyIndex".into() + } + + fn arrow_datatype() -> arrow2::datatypes::DataType { + arrow2::datatypes::DataType::UInt64 + } + + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> re_types_core::SerializationResult> + where + Self: 'a, + { + use re_types_core::datatypes::UInt64; + UInt64::to_arrow_opt( + data.into_iter() + .map(|opt| opt.map(Into::into).map(|c| UInt64(c.0))), + ) + } + + fn from_arrow_opt( + data: &dyn arrow2::array::Array, + ) -> re_types_core::DeserializationResult>> { + use re_types_core::datatypes::UInt64; + Ok(UInt64::from_arrow_opt(data)? + .into_iter() + .map(|opt| opt.map(|v| Self(v.0))) + .collect()) + } +} diff --git a/crates/re_log_types/src/instance.rs b/crates/re_log_types/src/instance.rs new file mode 100644 index 000000000000..6c4d28cc3829 --- /dev/null +++ b/crates/re_log_types/src/instance.rs @@ -0,0 +1,80 @@ +/// A unique numeric index for each individual instance within a batch. +/// +/// Use [`Instance::ALL`] to refer to all instances in a batch. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub struct Instance(pub(crate) u64); + +impl From for Instance { + #[inline] + fn from(instance: u64) -> Self { + if cfg!(debug_assertions) && instance == u64::MAX { + re_log::warn!( + "u64::MAX is reserved to refer to all instances: {:#?}", + backtrace::Backtrace::new() + ); + } + Self(instance) + } +} + +impl Instance { + /// Refer to all instances in a batch. + pub const ALL: Self = Self(u64::MAX); + + #[inline] + pub fn get(self) -> u64 { + self.0 + } + + #[allow(clippy::should_implement_trait)] + #[inline] + pub fn from_iter(it: impl IntoIterator>) -> Vec { + it.into_iter().map(Into::into).collect::>() + } + + /// Are we referring to all instances of the entity (e.g. all points in a point cloud entity)? + /// + /// The opposite of [`Self::is_specific`]. + #[inline] + pub fn is_all(self) -> bool { + self == Self::ALL + } + + /// Are we referring to a specific instance of the entity (e.g. a specific point in a point cloud)? + /// + /// The opposite of [`Self::is_all`]. + #[inline] + pub fn is_specific(self) -> bool { + self != Self::ALL + } + + /// Returns `None` if `ALL`, otherwise the index. + #[inline] + pub fn specific_index(self) -> Option { + self.is_specific().then_some(self) + } + + /// Creates a new [`Instance`] that identifies a 2D coordinate. + #[inline] + pub fn from_2d_image_coordinate([x, y]: [u32; 2], image_width: u64) -> Self { + Self((x as u64) + (y as u64) * image_width) + } + + /// Retrieves 2D image coordinates (x, y) encoded in an instance key + #[inline] + pub fn to_2d_image_coordinate(self, image_width: u64) -> [u32; 2] { + [(self.0 % image_width) as u32, (self.0 / image_width) as u32] + } +} + +impl std::fmt::Display for Instance { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.is_all() { + "".fmt(f) + } else { + re_format::format_uint(self.0).fmt(f) + } + } +} diff --git a/crates/re_log_types/src/lib.rs b/crates/re_log_types/src/lib.rs index 46741fd35f0d..f35c5fa314f2 100644 --- a/crates/re_log_types/src/lib.rs +++ b/crates/re_log_types/src/lib.rs @@ -8,8 +8,8 @@ //! Some components, mostly transform related ones, are "mono-components". //! This means that Rerun makes assumptions that depend on this component //! only taking on a singular value for all instances of an Entity. Where possible, -//! exposed APIs will force these components to be logged as a singular instance -//! or a splat. However, it is an error with undefined behavior to manually use lower-level +//! exposed APIs will force these components to be logged as a singular instance. +//! However, it is an error with undefined behavior to manually use lower-level //! APIs to log a batched mono-component. //! //! This requirement is especially apparent with transforms: @@ -18,15 +18,16 @@ //! `foo.transform * foo/bar.transform * foo/bar/baz.transform`. pub mod arrow_msg; -mod data_cell; -mod data_row; -mod data_table; pub mod example_components; pub mod hash; -mod num_instances; pub mod path; -mod time; pub mod time_point; + +mod data_cell; +mod data_row; +mod data_table; +mod instance; +mod time; mod time_range; mod time_real; mod vec_deque_ext; @@ -44,10 +45,10 @@ pub use self::data_row::{ }; pub use self::data_table::{ DataCellColumn, DataCellOptVec, DataTable, DataTableError, DataTableResult, EntityPathVec, - ErasedTimeVec, NumInstancesVec, RowIdVec, TableId, TimePointVec, METADATA_KIND, - METADATA_KIND_CONTROL, METADATA_KIND_DATA, + ErasedTimeVec, RowIdVec, TableId, TimePointVec, METADATA_KIND, METADATA_KIND_CONTROL, + METADATA_KIND_DATA, }; -pub use self::num_instances::NumInstances; +pub use self::instance::Instance; pub use self::path::*; pub use self::time::{Duration, Time, TimeZone}; pub use self::time_point::{ diff --git a/crates/re_log_types/src/num_instances.rs b/crates/re_log_types/src/num_instances.rs deleted file mode 100644 index 0ac0e57fbb60..000000000000 --- a/crates/re_log_types/src/num_instances.rs +++ /dev/null @@ -1,92 +0,0 @@ -use re_types_core::{Loggable, SizeBytes}; - -// --- - -/// Explicit number of instances in a [`crate::DataRow`]. -/// -/// Component batches in that row should have a length of either this number, zero (clear) or one (splat). -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, bytemuck::Pod, bytemuck::Zeroable)] -#[repr(transparent)] -pub struct NumInstances(pub u32); - -impl NumInstances { - #[inline] - pub fn get(self) -> u32 { - self.0 - } -} - -impl From for u32 { - #[inline] - fn from(val: NumInstances) -> Self { - val.0 - } -} - -impl From for NumInstances { - #[inline] - fn from(value: u32) -> Self { - Self(value) - } -} - -impl SizeBytes for NumInstances { - #[inline] - fn heap_size_bytes(&self) -> u64 { - 0 - } - - #[inline] - fn is_pod() -> bool { - true - } -} - -re_types_core::macros::impl_into_cow!(NumInstances); - -impl Loggable for NumInstances { - type Name = re_types_core::ComponentName; - - #[inline] - fn name() -> Self::Name { - "rerun.controls.NumInstances".into() - } - - #[inline] - fn arrow_datatype() -> arrow2::datatypes::DataType { - re_types_core::datatypes::UInt32::arrow_datatype() - } - - fn to_arrow_opt<'a>( - _data: impl IntoIterator>>>, - ) -> re_types_core::SerializationResult> - where - Self: 'a, - { - Err(re_types_core::SerializationError::not_implemented( - Self::name(), - "NumInstances is never nullable, use `to_arrow()` instead", - )) - } - - #[inline] - fn to_arrow<'a>( - data: impl IntoIterator>>, - ) -> re_types_core::SerializationResult> - where - Self: 'a, - { - use re_types_core::datatypes::UInt32; - UInt32::to_arrow(data.into_iter().map(Into::into).map(|c| UInt32(c.0))) - } - - fn from_arrow( - array: &dyn ::arrow2::array::Array, - ) -> re_types_core::DeserializationResult> { - use re_types_core::datatypes::UInt32; - Ok(UInt32::from_arrow(array)? - .into_iter() - .map(|v| Self(v.0)) - .collect()) - } -} diff --git a/crates/re_log_types/src/path/data_path.rs b/crates/re_log_types/src/path/data_path.rs index 68046c88f90a..9b2a928774c5 100644 --- a/crates/re_log_types/src/path/data_path.rs +++ b/crates/re_log_types/src/path/data_path.rs @@ -1,11 +1,11 @@ -use re_types_core::{components::InstanceKey, ComponentName}; +use re_types_core::ComponentName; -use crate::EntityPath; +use crate::{EntityPath, Instance}; /// A general path to some data. /// -/// This always starts with an [`EntityPath`], followed -/// by an optional [`InstanceKey`], followed by an optional [`ComponentName`]. +/// This always starts with an [`EntityPath`], followed by an optional instance index, +/// followed by an optional [`ComponentName`]. /// /// For instance: /// @@ -16,17 +16,15 @@ use crate::EntityPath; #[derive(Clone, Eq, PartialEq, Hash)] pub struct DataPath { pub entity_path: EntityPath, - - pub instance_key: Option, - + pub instance: Option, pub component_name: Option, } impl std::fmt::Display for DataPath { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.entity_path.fmt(f)?; - if let Some(instance_key) = &self.instance_key { - write!(f, "[#{}]", instance_key.0)?; + if let Some(instance) = &self.instance { + write!(f, "[#{instance}]")?; } if let Some(component_name) = &self.component_name { write!(f, ":{component_name:?}")?; diff --git a/crates/re_log_types/src/path/parse_path.rs b/crates/re_log_types/src/path/parse_path.rs index 60928c3e1579..9aeb124c6444 100644 --- a/crates/re_log_types/src/path/parse_path.rs +++ b/crates/re_log_types/src/path/parse_path.rs @@ -1,8 +1,8 @@ use std::str::FromStr; -use re_types_core::{components::InstanceKey, ComponentName}; +use re_types_core::ComponentName; -use crate::{ComponentPath, DataPath, EntityPath, EntityPathPart}; +use crate::{ComponentPath, DataPath, EntityPath, EntityPathPart, Instance}; #[derive(thiserror::Error, Debug, PartialEq, Eq)] pub enum PathParseError { @@ -24,11 +24,11 @@ pub enum PathParseError { #[error("Empty part")] EmptyPart, - #[error("Invalid instance key: {0:?} (expected '[#1234]')")] - BadInstanceKey(String), + #[error("Invalid instance index: {0:?} (expected '[#1234]')")] + BadInstance(String), - #[error("Found an unexpected instance key: [#{}]", 0.0)] - UnexpectedInstanceKey(InstanceKey), + #[error("Found an unexpected instance index: [#{}]", 0)] + UnexpectedInstance(Instance), #[error("Found an unexpected trailing component name: {0:?}")] UnexpectedComponentName(ComponentName), @@ -74,7 +74,7 @@ impl std::str::FromStr for DataPath { let mut tokens = tokenize_data_path(path); let mut component_name = None; - let mut instance_key = None; + let mut instance = None; // Parse `:rerun.components.Color` suffix: if let Some(colon) = tokens.iter().position(|&token| token == ":") { @@ -94,23 +94,19 @@ impl std::str::FromStr for DataPath { // Parse `[#1234]` suffix: if let Some(bracket) = tokens.iter().position(|&token| token == "[") { - let instance_key_tokens = &tokens[bracket..]; - if instance_key_tokens.len() != 3 || instance_key_tokens.last() != Some(&"]") { - return Err(PathParseError::BadInstanceKey(join(instance_key_tokens))); + let instance_tokens = &tokens[bracket..]; + if instance_tokens.len() != 3 || instance_tokens.last() != Some(&"]") { + return Err(PathParseError::BadInstance(join(instance_tokens))); } - let instance_key_token = instance_key_tokens[1]; - if let Some(nr) = instance_key_token.strip_prefix('#') { + let instance_token = instance_tokens[1]; + if let Some(nr) = instance_token.strip_prefix('#') { if let Ok(nr) = u64::from_str(nr) { - instance_key = Some(InstanceKey(nr)); + instance = Some(nr); } else { - return Err(PathParseError::BadInstanceKey( - instance_key_token.to_owned(), - )); + return Err(PathParseError::BadInstance(instance_token.to_owned())); } } else { - return Err(PathParseError::BadInstanceKey( - instance_key_token.to_owned(), - )); + return Err(PathParseError::BadInstance(instance_token.to_owned())); } tokens.truncate(bracket); } @@ -123,7 +119,7 @@ impl std::str::FromStr for DataPath { Ok(Self { entity_path, - instance_key, + instance: instance.map(Into::into), component_name, }) } @@ -148,12 +144,12 @@ impl EntityPath { pub fn parse_strict(input: &str) -> Result { let DataPath { entity_path, - instance_key, + instance, component_name, } = DataPath::from_str(input)?; - if let Some(instance_key) = instance_key { - return Err(PathParseError::UnexpectedInstanceKey(instance_key)); + if let Some(instance) = instance { + return Err(PathParseError::UnexpectedInstance(instance)); } if let Some(component_name) = component_name { return Err(PathParseError::UnexpectedComponentName(component_name)); @@ -196,12 +192,12 @@ impl FromStr for ComponentPath { fn from_str(s: &str) -> Result { let DataPath { entity_path, - instance_key, + instance, component_name, } = DataPath::from_str(s)?; - if let Some(instance_key) = instance_key { - return Err(PathParseError::UnexpectedInstanceKey(instance_key)); + if let Some(instance) = instance { + return Err(PathParseError::UnexpectedInstance(instance)); } let Some(component_name) = component_name else { @@ -366,7 +362,7 @@ fn test_parse_entity_path_strict() { )); assert!(matches!( parse(r#"entity[#123]"#), - Err(PathParseError::UnexpectedInstanceKey(InstanceKey(123))) + Err(PathParseError::UnexpectedInstance(Instance(123))) )); assert_eq!(parse("hallådär"), Ok(entity_path_vec!("hallådär"))); @@ -405,7 +401,7 @@ fn test_parse_component_path() { ); assert_eq!( ComponentPath::from_str("world/points[#42]:rerun.components.Color"), - Err(PathParseError::UnexpectedInstanceKey(InstanceKey(42))) + Err(PathParseError::UnexpectedInstance(Instance(42))) ); } @@ -415,7 +411,7 @@ fn test_parse_data_path() { DataPath::from_str("world/points[#42]:rerun.components.Color"), Ok(DataPath { entity_path: EntityPath::from("world/points"), - instance_key: Some(InstanceKey(42)), + instance: Some(Instance(42)), component_name: Some("rerun.components.Color".into()), }) ); @@ -423,7 +419,7 @@ fn test_parse_data_path() { DataPath::from_str("world/points:rerun.components.Color"), Ok(DataPath { entity_path: EntityPath::from("world/points"), - instance_key: None, + instance: None, component_name: Some("rerun.components.Color".into()), }) ); @@ -431,7 +427,7 @@ fn test_parse_data_path() { DataPath::from_str("world/points[#42]"), Ok(DataPath { entity_path: EntityPath::from("world/points"), - instance_key: Some(InstanceKey(42)), + instance: Some(Instance(42)), component_name: None, }) ); @@ -439,7 +435,7 @@ fn test_parse_data_path() { DataPath::from_str("world/points"), Ok(DataPath { entity_path: EntityPath::from("world/points"), - instance_key: None, + instance: None, component_name: None, }) ); diff --git a/crates/re_query/benches/latest_at.rs b/crates/re_query/benches/latest_at.rs index feba6dde04f6..d0fbf24d9df4 100644 --- a/crates/re_query/benches/latest_at.rs +++ b/crates/re_query/benches/latest_at.rs @@ -10,7 +10,7 @@ use re_query::{clamped_zip_1x1, PromiseResolver}; use re_query::{Caches, LatestAtResults}; use re_types::{ archetypes::Points2D, - components::{Color, InstanceKey, Position2D, Text}, + components::{Color, Position2D, Text}, Archetype as _, }; use re_types_core::Loggable as _; @@ -206,7 +206,6 @@ fn build_points_rows(paths: &[EntityPath], num_points: usize) -> Vec { RowId::new(), path.clone(), [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_points as _, ( build_some_point2d(num_points), build_some_colors(num_points), @@ -232,7 +231,6 @@ fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec RowId::new(), path.clone(), [build_frame_nr((frame_idx as i64).try_into().unwrap())], - num_strings as _, // We still need to create points because they are the primary for the // archetype query we want to do. We won't actually deserialize the points // during the query -- we just need it for the primary keys. @@ -258,7 +256,6 @@ fn build_strings_rows(paths: &[EntityPath], num_strings: usize) -> Vec fn insert_rows<'a>(msgs: impl Iterator) -> (Caches, DataStore) { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); diff --git a/crates/re_query/examples/latest_at.rs b/crates/re_query/examples/latest_at.rs index eb450f091cc2..ab122fce1150 100644 --- a/crates/re_query/examples/latest_at.rs +++ b/crates/re_query/examples/latest_at.rs @@ -106,7 +106,6 @@ fn main() -> anyhow::Result<()> { fn store() -> anyhow::Result { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), Default::default(), ); @@ -116,15 +115,15 @@ fn store() -> anyhow::Result { let timepoint = [build_frame_nr(123)]; let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, points)?; store.insert_row(&row)?; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, colors)?; store.insert_row(&row)?; let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, labels)?; store.insert_row(&row)?; } diff --git a/crates/re_query/examples/latest_at_archetype.rs b/crates/re_query/examples/latest_at_archetype.rs index af3215fdc3bc..c351333c86e7 100644 --- a/crates/re_query/examples/latest_at_archetype.rs +++ b/crates/re_query/examples/latest_at_archetype.rs @@ -5,7 +5,7 @@ use re_types::{ archetypes::Points2D, components::{Color, Position2D, Text}, }; -use re_types_core::{Archetype as _, Loggable as _}; +use re_types_core::Archetype as _; use re_query::{clamped_zip_1x2, LatestAtResults, PromiseResolver, PromiseResult}; @@ -79,7 +79,6 @@ fn main() -> anyhow::Result<()> { fn store() -> anyhow::Result { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), Default::default(), ); @@ -89,15 +88,15 @@ fn store() -> anyhow::Result { let timepoint = [build_frame_nr(123)]; let points = vec![Position2D::new(1.0, 2.0), Position2D::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, points)?; store.insert_row(&row)?; let colors = vec![Color::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, colors)?; store.insert_row(&row)?; let labels = vec![Text("a".into()), Text("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, labels)?; store.insert_row(&row)?; } diff --git a/crates/re_query/examples/range.rs b/crates/re_query/examples/range.rs index 0defca92ed8a..c083159e5ee3 100644 --- a/crates/re_query/examples/range.rs +++ b/crates/re_query/examples/range.rs @@ -109,7 +109,6 @@ fn main() -> anyhow::Result<()> { fn store() -> anyhow::Result { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - re_types::components::InstanceKey::name(), Default::default(), ); @@ -119,15 +118,15 @@ fn store() -> anyhow::Result { let timepoint = [build_frame_nr(123)]; let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, points)?; store.insert_row(&row)?; let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, colors)?; store.insert_row(&row)?; let labels = vec![MyLabel("a".into()), MyLabel("b".into())]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, labels)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, labels)?; store.insert_row(&row)?; } @@ -135,7 +134,7 @@ fn store() -> anyhow::Result { let timepoint = [build_frame_nr(456)]; let colors = vec![MyColor::from_rgb(255, 0, 0), MyColor::from_rgb(0, 0, 255)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, colors)?; store.insert_row(&row)?; let points = vec![ @@ -143,7 +142,7 @@ fn store() -> anyhow::Result { MyPoint::new(30.0, 40.0), MyPoint::new(50.0, 60.0), ]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points)?; + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, points)?; store.insert_row(&row)?; } diff --git a/crates/re_query/src/latest_at/results.rs b/crates/re_query/src/latest_at/results.rs index 0360a02c1a40..40c854efefda 100644 --- a/crates/re_query/src/latest_at/results.rs +++ b/crates/re_query/src/latest_at/results.rs @@ -98,13 +98,8 @@ impl LatestAtResults { // NOTE: Since this is a compound API that actually emits multiple queries, the index of the // final result is the most recent index among all of its components, as defined by time // and row-id order. - // - // TODO(#5303): We have to ignore the cluster key in this piece of logic for backwards compatibility - // reasons with the legacy instance-key model. This will go away next. - use re_types_core::Loggable as _; - if component_name != re_types_core::components::InstanceKey::name() - && cached.index > self.compound_index - { + + if cached.index > self.compound_index { self.compound_index = cached.index; } diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs index 1f6d81b4d3b0..0d9116b54c61 100644 --- a/crates/re_query/src/lib.rs +++ b/crates/re_query/src/lib.rs @@ -131,8 +131,6 @@ pub fn cacheable(component_name: re_types::ComponentName) -> bool { use re_types_core::Loggable as _; let not_cacheable = NOT_CACHEABLE.get_or_init(|| { [ - // TODO(#5303): instance keys are on their way out anyhow. - re_types::components::InstanceKey::name(), // TODO(#5974): tensors might already be cached in the ad-hoc JPEG cache, we don't // want yet another copy. re_types::components::TensorData::name(), diff --git a/crates/re_query/tests/latest_at.rs b/crates/re_query/tests/latest_at.rs index b5df7aca1826..115aa0f7cf6c 100644 --- a/crates/re_query/tests/latest_at.rs +++ b/crates/re_query/tests/latest_at.rs @@ -7,7 +7,7 @@ use re_log_types::{ use re_query::Caches; use re_query::PromiseResolver; use re_types::Archetype as _; -use re_types_core::{components::InstanceKey, Loggable as _}; +use re_types_core::Loggable as _; // --- @@ -15,7 +15,6 @@ use re_types_core::{components::InstanceKey, Loggable as _}; fn simple_query() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -24,13 +23,13 @@ fn simple_query() { let timepoint = [build_frame_nr(123)]; let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points.clone()) - .unwrap(); + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, points.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row); let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, colors.clone()) - .unwrap(); + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, colors.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row); let query = re_data_store::LatestAtQuery::new(timepoint[0].0, timepoint[0].1); @@ -52,7 +51,6 @@ fn simple_query() { fn static_query() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -61,8 +59,8 @@ fn static_query() { let timepoint = [build_frame_nr(123)]; let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row1 = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 2, points.clone()) - .unwrap(); + let row1 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, points.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row1); let colors = vec![MyColor::from_rgb(255, 0, 0)]; @@ -70,7 +68,6 @@ fn static_query() { RowId::new(), entity_path, TimePoint::default(), - 1, colors.clone(), ) .unwrap(); @@ -110,7 +107,6 @@ fn invalidation() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -120,7 +116,6 @@ fn invalidation() { RowId::new(), entity_path, present_data_timepoint.clone(), - 2, points.clone(), ) .unwrap(); @@ -131,7 +126,6 @@ fn invalidation() { RowId::new(), entity_path, present_data_timepoint.clone(), - 1, colors.clone(), ) .unwrap(); @@ -158,7 +152,6 @@ fn invalidation() { RowId::new(), entity_path, present_data_timepoint.clone(), - 2, points.clone(), ) .unwrap(); @@ -183,7 +176,6 @@ fn invalidation() { RowId::new(), entity_path, present_data_timepoint.clone(), - 2, colors.clone(), ) .unwrap(); @@ -210,7 +202,6 @@ fn invalidation() { RowId::new(), entity_path, past_data_timepoint.clone(), - 2, points_past.clone(), ) .unwrap(); @@ -239,7 +230,6 @@ fn invalidation() { RowId::new(), entity_path, past_data_timepoint, - 2, colors_past.clone(), ) .unwrap(); @@ -268,7 +258,6 @@ fn invalidation() { RowId::new(), entity_path, future_data_timepoint.clone(), - 2, points_future.clone(), ) .unwrap(); @@ -295,7 +284,6 @@ fn invalidation() { RowId::new(), entity_path, future_data_timepoint, - 1, colors_future, ) .unwrap(); @@ -366,7 +354,6 @@ fn invalidation() { fn invalidation_of_future_optionals() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -381,7 +368,7 @@ fn invalidation_of_future_optionals() { let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; let row1 = - DataRow::from_cells1_sized(RowId::new(), entity_path, static_, 2, points.clone()).unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path, static_, points.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row1); let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); @@ -400,7 +387,7 @@ fn invalidation_of_future_optionals() { let colors = vec![MyColor::from_rgb(255, 0, 0)]; let row2 = - DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors.clone()).unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, colors.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row2); let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); @@ -419,7 +406,7 @@ fn invalidation_of_future_optionals() { let colors = vec![MyColor::from_rgb(0, 0, 255)]; let row3 = - DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors.clone()).unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, colors.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row3); let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); @@ -438,7 +425,7 @@ fn invalidation_of_future_optionals() { let colors = vec![MyColor::from_rgb(0, 255, 0)]; let row4 = - DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors.clone()).unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, colors.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row4); let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); @@ -460,7 +447,6 @@ fn invalidation_of_future_optionals() { fn static_invalidation() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -472,14 +458,9 @@ fn static_invalidation() { let query_time = [build_frame_nr(9999)]; let points = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row1 = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - timeless.clone(), - 2, - points.clone(), - ) - .unwrap(); + let row1 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), points.clone()) + .unwrap(); insert_and_react(&mut store, &mut caches, &row1); let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); @@ -497,14 +478,9 @@ fn static_invalidation() { ); let colors = vec![MyColor::from_rgb(255, 0, 0)]; - let row2 = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - timeless.clone(), - 1, - colors.clone(), - ) - .unwrap(); + let row2 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), colors.clone()) + .unwrap(); insert_and_react(&mut store, &mut caches, &row2); let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); @@ -523,7 +499,7 @@ fn static_invalidation() { let colors = vec![MyColor::from_rgb(0, 0, 255)]; let row3 = - DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors.clone()).unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, colors.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row3); let query = re_data_store::LatestAtQuery::new(query_time[0].0, query_time[0].1); diff --git a/crates/re_query/tests/range.rs b/crates/re_query/tests/range.rs index 615e48005d29..efcf94683cfb 100644 --- a/crates/re_query/tests/range.rs +++ b/crates/re_query/tests/range.rs @@ -7,7 +7,7 @@ use re_log_types::{ DataRow, EntityPath, RowId, TimePoint, }; use re_query::{Caches, PromiseResolver, PromiseResult}; -use re_types::{components::InstanceKey, Archetype}; +use re_types::Archetype; use re_types_core::Loggable as _; // --- @@ -16,7 +16,6 @@ use re_types_core::Loggable as _; fn simple_range() -> anyhow::Result<()> { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -29,7 +28,6 @@ fn simple_range() -> anyhow::Result<()> { RowId::new(), entity_path.clone(), timepoint1, - 2, points1.clone(), )?; insert_and_react(&mut store, &mut caches, &row1_1); @@ -38,7 +36,6 @@ fn simple_range() -> anyhow::Result<()> { RowId::new(), entity_path.clone(), timepoint1, - 1, colors1.clone(), )?; insert_and_react(&mut store, &mut caches, &row1_2); @@ -49,7 +46,6 @@ fn simple_range() -> anyhow::Result<()> { RowId::new(), entity_path.clone(), timepoint2, - 1, colors2.clone(), )?; insert_and_react(&mut store, &mut caches, &row2); @@ -60,7 +56,6 @@ fn simple_range() -> anyhow::Result<()> { RowId::new(), entity_path.clone(), timepoint3, - 2, points3.clone(), )?; insert_and_react(&mut store, &mut caches, &row3); @@ -136,7 +131,6 @@ fn simple_range() -> anyhow::Result<()> { fn static_range() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -149,7 +143,6 @@ fn static_range() { RowId::new(), entity_path.clone(), timepoint1, - 2, points1.clone(), ) .unwrap(); @@ -159,7 +152,6 @@ fn static_range() { RowId::new(), entity_path.clone(), timepoint1, - 1, colors1.clone(), ) .unwrap(); @@ -169,7 +161,6 @@ fn static_range() { RowId::new(), entity_path.clone(), TimePoint::default(), - 1, colors1.clone(), ) .unwrap(); @@ -181,7 +172,6 @@ fn static_range() { RowId::new(), entity_path.clone(), timepoint2, - 1, colors2.clone(), ) .unwrap(); @@ -191,7 +181,6 @@ fn static_range() { RowId::new(), entity_path.clone(), TimePoint::default(), - 1, colors2.clone(), ) .unwrap(); @@ -204,7 +193,6 @@ fn static_range() { RowId::new(), entity_path.clone(), timepoint3, - 2, points3.clone(), ) .unwrap(); @@ -305,7 +293,6 @@ fn invalidation() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -315,7 +302,6 @@ fn invalidation() { RowId::new(), entity_path, present_data_timepoint.clone(), - 2, points1.clone(), ) .unwrap(); @@ -326,7 +312,6 @@ fn invalidation() { RowId::new(), entity_path, present_data_timepoint.clone(), - 1, colors2.clone(), ) .unwrap(); @@ -355,7 +340,6 @@ fn invalidation() { RowId::new(), entity_path, present_data_timepoint.clone(), - 2, points3.clone(), ) .unwrap(); @@ -383,7 +367,6 @@ fn invalidation() { RowId::new(), entity_path, present_data_timepoint, - 2, colors4.clone(), ) .unwrap(); @@ -414,7 +397,6 @@ fn invalidation() { RowId::new(), entity_path, past_data_timepoint.clone(), - 2, points5.clone(), ) .unwrap(); @@ -452,7 +434,6 @@ fn invalidation() { RowId::new(), entity_path, past_data_timepoint.clone(), - 2, colors6.clone(), ) .unwrap(); @@ -488,7 +469,6 @@ fn invalidation() { RowId::new(), entity_path, future_data_timepoint.clone(), - 2, points7.clone(), ) .unwrap(); @@ -523,7 +503,6 @@ fn invalidation() { RowId::new(), entity_path, future_data_timepoint, - 1, colors8.clone(), ) .unwrap(); @@ -602,7 +581,6 @@ fn invalidation() { fn invalidation_of_future_optionals() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -616,8 +594,8 @@ fn invalidation_of_future_optionals() { let query = re_data_store::RangeQuery::new(frame2[0].0, TimeRange::EVERYTHING); let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row1 = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 2, points1.clone()) - .unwrap(); + let row1 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, points1.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row1); let expected_points = &[ @@ -635,7 +613,7 @@ fn invalidation_of_future_optionals() { let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; let row2 = - DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, 1, colors2.clone()).unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path, frame2, colors2.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row2); let expected_colors = &[ @@ -655,7 +633,7 @@ fn invalidation_of_future_optionals() { let colors3 = vec![MyColor::from_rgb(0, 0, 255)]; let row3 = - DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors3.clone()).unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, colors3.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row3); let expected_colors = &[ @@ -679,7 +657,7 @@ fn invalidation_of_future_optionals() { let colors4 = vec![MyColor::from_rgb(0, 255, 0)]; let row4 = - DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, 1, colors4.clone()).unwrap(); + DataRow::from_cells1_sized(RowId::new(), entity_path, frame3, colors4.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row4); let expected_colors = &[ @@ -710,7 +688,6 @@ fn invalidation_of_future_optionals() { fn invalidation_static() { let mut store = DataStore::new( re_log_types::StoreId::random(re_log_types::StoreKind::Recording), - InstanceKey::name(), Default::default(), ); let mut caches = Caches::new(&store); @@ -723,14 +700,9 @@ fn invalidation_static() { let query = re_data_store::RangeQuery::new(frame0[0].0, TimeRange::EVERYTHING); let points1 = vec![MyPoint::new(1.0, 2.0), MyPoint::new(3.0, 4.0)]; - let row1 = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - timeless.clone(), - 2, - points1.clone(), - ) - .unwrap(); + let row1 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), points1.clone()) + .unwrap(); insert_and_react(&mut store, &mut caches, &row1); let expected_points = &[ @@ -747,14 +719,9 @@ fn invalidation_static() { ); let colors2 = vec![MyColor::from_rgb(255, 0, 0)]; - let row2 = DataRow::from_cells1_sized( - RowId::new(), - entity_path, - timeless.clone(), - 1, - colors2.clone(), - ) - .unwrap(); + let row2 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless.clone(), colors2.clone()) + .unwrap(); insert_and_react(&mut store, &mut caches, &row2); let expected_colors = &[ @@ -770,8 +737,8 @@ fn invalidation_static() { ); let colors3 = vec![MyColor::from_rgb(0, 0, 255)]; - let row3 = DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, 1, colors3.clone()) - .unwrap(); + let row3 = + DataRow::from_cells1_sized(RowId::new(), entity_path, timeless, colors3.clone()).unwrap(); insert_and_react(&mut store, &mut caches, &row3); let expected_colors = &[ diff --git a/crates/re_sdk/src/lib.rs b/crates/re_sdk/src/lib.rs index 21f533a3a113..9c264b489f73 100644 --- a/crates/re_sdk/src/lib.rs +++ b/crates/re_sdk/src/lib.rs @@ -33,7 +33,7 @@ pub use self::recording_stream::{ pub use re_sdk_comms::{default_flush_timeout, default_server_addr}; pub use re_log_types::{ - entity_path, ApplicationId, EntityPath, EntityPathPart, StoreId, StoreKind, + entity_path, ApplicationId, EntityPath, EntityPathPart, Instance, StoreId, StoreKind, }; pub use re_memory::MemoryLimit; diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs index c0affed8233f..659668bc15b9 100644 --- a/crates/re_sdk/src/recording_stream.rs +++ b/crates/re_sdk/src/recording_stream.rs @@ -14,7 +14,7 @@ use re_log_types::{ EntityPath, LogMsg, RowId, StoreId, StoreInfo, StoreKind, StoreSource, Time, TimeInt, TimePoint, TimeType, Timeline, TimelineName, }; -use re_types_core::{components::InstanceKey, AsComponents, ComponentBatch, SerializationError}; +use re_types_core::{AsComponents, ComponentBatch, SerializationError}; #[cfg(feature = "web_viewer")] use re_web_viewer_server::WebViewerServerPort; @@ -1015,11 +1015,9 @@ impl RecordingStream { let ent_path = ent_path.into(); - let mut num_instances = 0; let comp_batches: Result, _> = comp_batches .into_iter() .map(|comp_batch| { - num_instances = usize::max(num_instances, comp_batch.num_instances()); comp_batch .to_arrow() .map(|array| (comp_batch.arrow_field(), array)) @@ -1041,55 +1039,13 @@ impl RecordingStream { .collect(); let cells = cells?; - let mut instanced: Vec = Vec::new(); - let mut splatted: Vec = Vec::new(); - - for cell in cells { - if num_instances > 1 && cell.num_instances() == 1 { - splatted.push(cell); - } else { - instanced.push(cell); - } - } - // NOTE: The timepoint is irrelevant, the `RecordingStream` will overwrite it using its // internal clock. let timepoint = TimePoint::default(); - // TODO(#1893): unsplit splats once new data cells are in - let splatted = if splatted.is_empty() { - None - } else { - splatted.push(DataCell::from_native([InstanceKey::SPLAT])); - Some(DataRow::from_cells( - row_id, - timepoint.clone(), - ent_path.clone(), - 1, - splatted, - )?) - }; - - let instanced = if instanced.is_empty() { - None - } else { - Some(DataRow::from_cells( - row_id.incremented_by(1), // we need a unique RowId from what is used for the splatted data - timepoint, - ent_path, - num_instances as _, - instanced, - )?) - }; - - if let Some(splatted) = splatted { - self.record_row(splatted, !static_); - } - - // Always the primary component last so range-based queries will include the other data. - // Since the primary component can't be splatted it must be in here, see(#1215). - if let Some(instanced) = instanced { - self.record_row(instanced, !static_); + if !cells.is_empty() { + let row = DataRow::from_cells(row_id, timepoint.clone(), ent_path.clone(), cells)?; + self.record_row(row, !static_); } Ok(()) diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 8e435edeb682..94936b7daaa8 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -236,7 +236,6 @@ impl SpaceViewBlueprint { RowId::new(), store_context.blueprint_timepoint_for_writes(), sub_path, - 1, info.components .keys() // It's important that we don't include the SpaceViewBlueprint's components @@ -482,7 +481,6 @@ mod tests { RowId::new(), path.clone(), TimePoint::default(), - 1, DataCell::from([component]), ) .unwrap(); diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 2325aa3b2868..8318470268e1 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -28,7 +28,7 @@ pub fn space_view_sub_archetype( space_view_id: re_viewer_context::SpaceViewId, ) -> Option where - CachedLatestAtResults: ToArchetype, + LatestAtResults: ToArchetype, { let blueprint_db = ctx.store_context.blueprint; let blueprint_query = ctx.blueprint_query; @@ -37,6 +37,7 @@ where .latest_at_archetype(&path, blueprint_query) .ok() .flatten() + .map(|(_index, value)| value) } /// Returns `Ok(None)` if any of the required components are missing. diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index 448ee5e7cb8f..10125fb50df1 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -5,8 +5,7 @@ use egui_extras::Column; use re_data_store::{DataStore, LatestAtQuery}; use re_data_ui::item_ui::instance_path_button; use re_entity_db::{EntityProperties, InstancePath}; -use re_log_types::{EntityPath, Timeline}; -use re_types_core::components::InstanceKey; +use re_log_types::{EntityPath, Instance, Timeline}; use re_viewer_context::{ SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewState, SpaceViewSystemExecutionError, SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, @@ -33,10 +32,7 @@ impl SpaceViewClass for DataframeSpaceView { fn help_text(&self, _re_ui: &re_ui::ReUi) -> egui::WidgetText { "Show the data contained in entities in a table.\n\n\ - Each entity is represented by as many rows as it has instances. This includes out-of-bound \ - instances—instances from secondary components that cannot be joined to the primary \ - component—that are typically not represented in other space views. Also, splats are merged \ - into the entity's instance." + Each entity is represented by as many rows as it has instances." .into() } @@ -148,18 +144,12 @@ impl SpaceViewClass for DataframeSpaceView { let row_ui = |mut row: egui_extras::TableRow<'_, '_>| { let instance = &sorted_instance_paths[row.index()]; - // TODO(#4466): make it explicit if that instance key is "out - // of bounds" (aka cannot be joined to a primary component). - row.col(|ui| { instance_path_button(ctx, &latest_at_query, ctx.recording(), ui, None, instance); }); for component_name in &sorted_components { row.col(|ui| { - // TODO(#4466): make it explicit if that value results - // from a splat joint. - let results = ctx.recording().query_caches().latest_at( ctx.recording_store(), &latest_at_query, @@ -180,7 +170,7 @@ impl SpaceViewClass for DataframeSpaceView { ctx.recording(), &instance.entity_path, results, - &instance.instance_key, + &instance.instance, ); } else { ui.weak("-"); @@ -228,9 +218,6 @@ impl SpaceViewClass for DataframeSpaceView { } /// Returns a sorted, deduplicated iterator of all instance paths for a given entity. -/// -/// This includes _any_ instance key in all components logged under this entity path, excluding -/// splats. fn sorted_instance_paths_for<'a>( entity_path: &'a EntityPath, store: &'a DataStore, @@ -248,10 +235,9 @@ fn sorted_instance_paths_for<'a>( .map_or(0, |(_, _, cells)| { cells[0].as_ref().map_or(0, |cell| cell.num_instances()) }); - (0..num_instances).map(|i| InstanceKey(i as _)) + (0..num_instances).map(|i| Instance::from(i as u64)) }) - .filter(|instance_key| !instance_key.is_splat()) .collect::>() // dedup and sort .into_iter() - .map(|instance_key| InstancePath::instance(entity_path.clone(), instance_key)) + .map(|instance| InstancePath::instance(entity_path.clone(), instance)) } diff --git a/crates/re_space_view_spatial/src/instance_hash_conversions.rs b/crates/re_space_view_spatial/src/instance_hash_conversions.rs index 9a5c89bcb417..d40d148029b0 100644 --- a/crates/re_space_view_spatial/src/instance_hash_conversions.rs +++ b/crates/re_space_view_spatial/src/instance_hash_conversions.rs @@ -1,13 +1,12 @@ use re_entity_db::InstancePathHash; -use re_log_types::EntityPathHash; +use re_log_types::{EntityPathHash, Instance}; use re_renderer::{PickingLayerId, PickingLayerInstanceId, PickingLayerObjectId}; -use re_types::components::InstanceKey; #[inline] pub fn picking_layer_id_from_instance_path_hash(value: InstancePathHash) -> PickingLayerId { PickingLayerId { object: PickingLayerObjectId(value.entity_path_hash.hash64()), - instance: PickingLayerInstanceId(value.instance_key.0), + instance: PickingLayerInstanceId(value.instance.get()), } } @@ -15,6 +14,11 @@ pub fn picking_layer_id_from_instance_path_hash(value: InstancePathHash) -> Pick pub fn instance_path_hash_from_picking_layer_id(value: PickingLayerId) -> InstancePathHash { InstancePathHash { entity_path_hash: EntityPathHash::from_u64(value.object.0), - instance_key: InstanceKey(value.instance.0), + // `PickingLayerId` uses `u64::MAX` to mean "hover and/or select all instances". + instance: if value.instance.0 == u64::MAX { + Instance::ALL + } else { + Instance::from(value.instance.0) + }, } } diff --git a/crates/re_space_view_spatial/src/picking.rs b/crates/re_space_view_spatial/src/picking.rs index a3bc508b6c93..26c289163395 100644 --- a/crates/re_space_view_spatial/src/picking.rs +++ b/crates/re_space_view_spatial/src/picking.rs @@ -2,8 +2,8 @@ use ahash::HashSet; use re_entity_db::InstancePathHash; +use re_log_types::Instance; use re_renderer::PickingLayerProcessor; -use re_types::components::InstanceKey; use crate::visualizers::ViewerImage; use crate::{eye::Eye, instance_hash_conversions::instance_path_hash_from_picking_layer_id}; @@ -269,7 +269,7 @@ fn picking_textured_rects(context: &PickingContext, images: &[ViewerImage]) -> V hits.push(PickingRayHit { instance_path_hash: InstancePathHash { entity_path_hash: image.ent_path.hash(), - instance_key: InstanceKey::from_2d_image_coordinate( + instance: Instance::from_2d_image_coordinate( [(u * width as f32) as u32, (v * height as f32) as u32], width as u64, ), diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 70d750a8106a..7099ccdf2649 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -4,11 +4,12 @@ use macaw::BoundingBox; use re_data_ui::{image_meaning_for_entity, item_ui, DataUi}; use re_data_ui::{show_zoomed_image_region, show_zoomed_image_region_area_outline}; use re_format::format_f32; +use re_log_types::Instance; use re_renderer::OutlineConfig; use re_space_view::ScreenshotMode; use re_types::{ blueprint::archetypes::Background, - components::{Color, DepthMeter, InstanceKey, TensorData, ViewCoordinates}, + components::{Color, DepthMeter, TensorData, ViewCoordinates}, }; use re_types::{blueprint::components::BackgroundKind, tensor_data::TensorDataMeaning}; use re_viewer_context::{ @@ -338,7 +339,7 @@ pub fn create_labels( let highlight = highlights .entity_highlight(label.labeled_instance.entity_path_hash) - .index_highlight(label.labeled_instance.instance_key); + .index_highlight(label.labeled_instance.instance); let fill_color = match highlight.hover { HoverHighlight::None => match highlight.selection { SelectionHighlight::None => parent_ui.style().visuals.widgets.inactive.bg_fill, @@ -484,7 +485,7 @@ pub fn picking( if response.double_clicked() { // Select entire entity on double-click: - instance_path.instance_key = InstanceKey::SPLAT; + instance_path.instance = Instance::ALL; } let interactive = ctx @@ -525,10 +526,8 @@ pub fn picking( } else { let tensor_path_hash = hit.instance_path_hash.versioned(tensor.row_id()); tensor.image_height_width_channels().map(|[_, w, _]| { - let coordinates = hit - .instance_path_hash - .instance_key - .to_2d_image_coordinate(w); + let coordinates = + hit.instance_path_hash.instance.to_2d_image_coordinate(w); (tensor_path_hash, tensor, meaning, coordinates) }) } @@ -538,7 +537,7 @@ pub fn picking( }; if picked_image_with_coords.is_some() { // We don't support selecting pixels yet. - instance_path.instance_key = InstanceKey::SPLAT; + instance_path.instance = Instance::ALL; } hovered_items.push(Item::DataResult(query.space_view_id, instance_path.clone())); diff --git a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs index b274db0b8b97..13b5bd15e395 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows2d.rs @@ -1,9 +1,10 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_log_types::Instance; use re_query::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows2D, - components::{ClassId, Color, InstanceKey, KeypointId, Position2D, Radius, Text, Vector2D}, + components::{ClassId, Color, KeypointId, Position2D, Radius, Text, Vector2D}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, @@ -71,7 +72,7 @@ impl Arrows2DVisualizer { target: UiLabelTarget::Point2D(egui::pos2(midpoint.x, midpoint.y)), labeled_instance: InstancePathHash::instance( entity_path, - InstanceKey(i as _), + Instance::from(i as u64), ), }) } @@ -149,8 +150,10 @@ impl Arrows2DVisualizer { ) .picking_instance_id(PickingLayerInstanceId(i as _)); - if let Some(outline_mask_ids) = - ent_context.highlight.instances.get(&InstanceKey(i as _)) + if let Some(outline_mask_ids) = ent_context + .highlight + .instances + .get(&Instance::from(i as u64)) { segment.outline_mask_ids(*outline_mask_ids); } diff --git a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs index cf59264e9401..d5edf7efed04 100644 --- a/crates/re_space_view_spatial/src/visualizers/arrows3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/arrows3d.rs @@ -1,9 +1,10 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_log_types::Instance; use re_query::range_zip_1x6; use re_renderer::{renderer::LineStripFlags, LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Arrows3D, - components::{ClassId, Color, InstanceKey, KeypointId, Position3D, Radius, Text, Vector3D}, + components::{ClassId, Color, KeypointId, Position3D, Radius, Text, Vector3D}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, @@ -73,7 +74,7 @@ impl Arrows3DVisualizer { ), labeled_instance: InstancePathHash::instance( entity_path, - InstanceKey(i as _), + Instance::from(i as u64), ), }) } @@ -152,8 +153,10 @@ impl Arrows3DVisualizer { ) .picking_instance_id(PickingLayerInstanceId(i as _)); - if let Some(outline_mask_ids) = - ent_context.highlight.instances.get(&InstanceKey(i as _)) + if let Some(outline_mask_ids) = ent_context + .highlight + .instances + .get(&Instance::from(i as u64)) { segment.outline_mask_ids(*outline_mask_ids); } diff --git a/crates/re_space_view_spatial/src/visualizers/assets3d.rs b/crates/re_space_view_spatial/src/visualizers/assets3d.rs index 77d22a2a4d93..66a524ed7942 100644 --- a/crates/re_space_view_spatial/src/visualizers/assets3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/assets3d.rs @@ -1,10 +1,10 @@ use re_entity_db::EntityPath; -use re_log_types::{RowId, TimeInt}; +use re_log_types::{Instance, RowId, TimeInt}; use re_query::range_zip_1x2; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Asset3D, - components::{Blob, InstanceKey, MediaType, OutOfTreeTransform3D}, + components::{Blob, MediaType, OutOfTreeTransform3D}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, @@ -59,8 +59,8 @@ impl Asset3DVisualizer { }; let primary_row_id = data.index.1; - let picking_instance_hash = re_entity_db::InstancePathHash::entity_splat(entity_path); - let outline_mask_ids = ent_context.highlight.index_outline_mask(InstanceKey::SPLAT); + let picking_instance_hash = re_entity_db::InstancePathHash::entity_all(entity_path); + let outline_mask_ids = ent_context.highlight.index_outline_mask(Instance::ALL); // TODO(#3232): this is subtly wrong, the key should actually be a hash of everything that got // cached, which includes the media type… diff --git a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs index dc4588ff9746..b5abf22ea008 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes2d.rs @@ -1,9 +1,10 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_log_types::Instance; use re_query::range_zip_1x6; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes2D, - components::{ClassId, Color, HalfSizes2D, InstanceKey, KeypointId, Position2D, Radius, Text}, + components::{ClassId, Color, HalfSizes2D, KeypointId, Position2D, Radius, Text}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, @@ -71,7 +72,7 @@ impl Boxes2DVisualizer { )), labeled_instance: InstancePathHash::instance( entity_path, - InstanceKey(i as _), + Instance::from(i as u64), ), }) } @@ -148,8 +149,10 @@ impl Boxes2DVisualizer { .color(color) .radius(radius) .picking_instance_id(PickingLayerInstanceId(i as _)); - if let Some(outline_mask_ids) = - ent_context.highlight.instances.get(&InstanceKey(i as _)) + if let Some(outline_mask_ids) = ent_context + .highlight + .instances + .get(&Instance::from(i as u64)) { rectangle.outline_mask_ids(*outline_mask_ids); } diff --git a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs index 2dfcd63d95cf..9161d46b603a 100644 --- a/crates/re_space_view_spatial/src/visualizers/boxes3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/boxes3d.rs @@ -1,11 +1,10 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_log_types::Instance; use re_query::range_zip_1x7; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::Boxes3D, - components::{ - ClassId, Color, HalfSizes3D, InstanceKey, KeypointId, Position3D, Radius, Rotation3D, Text, - }, + components::{ClassId, Color, HalfSizes3D, KeypointId, Position3D, Radius, Rotation3D, Text}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, @@ -61,7 +60,10 @@ impl Boxes3DVisualizer { target: UiLabelTarget::Position3D( world_from_entity.transform_point3(center.0.into()), ), - labeled_instance: InstancePathHash::instance(entity_path, InstanceKey(i as _)), + labeled_instance: InstancePathHash::instance( + entity_path, + Instance::from(i as u64), + ), }) }) } @@ -137,8 +139,10 @@ impl Boxes3DVisualizer { .radius(radius) .picking_instance_id(PickingLayerInstanceId(i as _)); - if let Some(outline_mask_ids) = - ent_context.highlight.instances.get(&InstanceKey(i as _)) + if let Some(outline_mask_ids) = ent_context + .highlight + .instances + .get(&Instance::from(i as u64)) { box3d.outline_mask_ids(*outline_mask_ids); } diff --git a/crates/re_space_view_spatial/src/visualizers/cameras.rs b/crates/re_space_view_spatial/src/visualizers/cameras.rs index 737c384a3d64..054993d8c5c1 100644 --- a/crates/re_space_view_spatial/src/visualizers/cameras.rs +++ b/crates/re_space_view_spatial/src/visualizers/cameras.rs @@ -1,9 +1,10 @@ use glam::vec3; use re_entity_db::{EntityPath, EntityProperties}; +use re_log_types::Instance; use re_renderer::renderer::LineStripFlags; use re_types::{ archetypes::Pinhole, - components::{InstanceKey, Transform3D, ViewCoordinates}, + components::{Transform3D, ViewCoordinates}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, SpaceViewOutlineMasks, SpaceViewSystemExecutionError, @@ -55,7 +56,7 @@ impl CamerasVisualizer { pinhole_view_coordinates: ViewCoordinates, entity_highlight: &SpaceViewOutlineMasks, ) { - let instance_key = InstanceKey(0); + let instance = Instance::from(0); let frustum_length = *props.pinhole_image_plane_distance; @@ -152,7 +153,7 @@ impl CamerasVisualizer { let radius = re_renderer::Size::new_points(1.0); let instance_path_for_picking = - re_entity_db::InstancePathHash::instance(ent_path, instance_key); + re_entity_db::InstancePathHash::instance(ent_path, instance); let instance_layer_id = picking_layer_id_from_instance_path_hash(instance_path_for_picking); let mut batch = line_builder @@ -172,7 +173,7 @@ impl CamerasVisualizer { .flags(LineStripFlags::FLAG_CAP_END_ROUND | LineStripFlags::FLAG_CAP_START_ROUND) .picking_instance_id(instance_layer_id.instance); - if let Some(outline_mask_ids) = entity_highlight.instances.get(&instance_key) { + if let Some(outline_mask_ids) = entity_highlight.instances.get(&instance) { lines.outline_mask_ids(*outline_mask_ids); } diff --git a/crates/re_space_view_spatial/src/visualizers/lines2d.rs b/crates/re_space_view_spatial/src/visualizers/lines2d.rs index bbddd23851d6..c31019723dbc 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines2d.rs @@ -1,9 +1,10 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_log_types::Instance; use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId}; use re_types::{ archetypes::LineStrips2D, - components::{ClassId, Color, InstanceKey, KeypointId, LineStrip2D, Radius, Text}, + components::{ClassId, Color, KeypointId, LineStrip2D, Radius, Text}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, @@ -71,7 +72,7 @@ impl Lines2DVisualizer { target: UiLabelTarget::Point2D(egui::pos2(midpoint.x, midpoint.y)), labeled_instance: InstancePathHash::instance( entity_path, - InstanceKey(i as _), + Instance::from(i as u64), ), }) } @@ -134,8 +135,10 @@ impl Lines2DVisualizer { .radius(radius) .picking_instance_id(PickingLayerInstanceId(i as _)); - if let Some(outline_mask_ids) = - ent_context.highlight.instances.get(&InstanceKey(i as _)) + if let Some(outline_mask_ids) = ent_context + .highlight + .instances + .get(&Instance::from(i as u64)) { lines.outline_mask_ids(*outline_mask_ids); } diff --git a/crates/re_space_view_spatial/src/visualizers/lines3d.rs b/crates/re_space_view_spatial/src/visualizers/lines3d.rs index e4da2c12ce24..0eb63e32d503 100644 --- a/crates/re_space_view_spatial/src/visualizers/lines3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/lines3d.rs @@ -1,9 +1,10 @@ use re_entity_db::{EntityPath, InstancePathHash}; +use re_log_types::Instance; use re_query::range_zip_1x5; use re_renderer::PickingLayerInstanceId; use re_types::{ archetypes::LineStrips3D, - components::{ClassId, Color, InstanceKey, KeypointId, LineStrip3D, Radius, Text}, + components::{ClassId, Color, KeypointId, LineStrip3D, Radius, Text}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, @@ -74,7 +75,7 @@ impl Lines3DVisualizer { ), labeled_instance: InstancePathHash::instance( entity_path, - InstanceKey(i as _), + Instance::from(i as u64), ), }) } @@ -140,8 +141,10 @@ impl Lines3DVisualizer { .radius(radius) .picking_instance_id(PickingLayerInstanceId(i as _)); - if let Some(outline_mask_ids) = - ent_context.highlight.instances.get(&InstanceKey(i as _)) + if let Some(outline_mask_ids) = ent_context + .highlight + .instances + .get(&Instance::from(i as u64)) { lines.outline_mask_ids(*outline_mask_ids); } diff --git a/crates/re_space_view_spatial/src/visualizers/meshes.rs b/crates/re_space_view_spatial/src/visualizers/meshes.rs index 5ac9b2a3a48b..5725800803c5 100644 --- a/crates/re_space_view_spatial/src/visualizers/meshes.rs +++ b/crates/re_space_view_spatial/src/visualizers/meshes.rs @@ -1,13 +1,12 @@ use itertools::Itertools as _; use re_entity_db::EntityPath; -use re_log_types::{RowId, TimeInt}; +use re_log_types::{Instance, RowId, TimeInt}; use re_query::range_zip_1x7; use re_renderer::renderer::MeshInstance; use re_types::{ archetypes::Mesh3D, components::{ - ClassId, Color, InstanceKey, Material, MeshProperties, Position3D, TensorData, Texcoord2D, - Vector3D, + ClassId, Color, Material, MeshProperties, Position3D, TensorData, Texcoord2D, Vector3D, }, }; use re_viewer_context::{ @@ -65,8 +64,8 @@ impl Mesh3DVisualizer { ) { for data in data { let primary_row_id = data.index.1; - let picking_instance_hash = re_entity_db::InstancePathHash::entity_splat(entity_path); - let outline_mask_ids = ent_context.highlight.index_outline_mask(InstanceKey::SPLAT); + let picking_instance_hash = re_entity_db::InstancePathHash::entity_all(entity_path); + let outline_mask_ids = ent_context.highlight.index_outline_mask(Instance::ALL); let mesh = ctx.cache.entry(|c: &mut MeshCache| { let key = MeshCacheKey { diff --git a/crates/re_space_view_spatial/src/visualizers/mod.rs b/crates/re_space_view_spatial/src/visualizers/mod.rs index 62745ee750f2..93bcfa3c892e 100644 --- a/crates/re_space_view_spatial/src/visualizers/mod.rs +++ b/crates/re_space_view_spatial/src/visualizers/mod.rs @@ -30,7 +30,7 @@ use ahash::HashMap; use re_entity_db::{EntityPath, InstancePathHash}; use re_types::{ - components::{Color, InstanceKey}, + components::Color, datatypes::{KeypointId, KeypointPair}, }; use re_viewer_context::{ @@ -333,7 +333,9 @@ pub fn load_keypoint_connections( .color(color) .flags(re_renderer::renderer::LineStripFlags::FLAG_COLOR_GRADIENT) // Select the entire object when clicking any of the lines. - .picking_instance_id(re_renderer::PickingLayerInstanceId(InstanceKey::SPLAT.0)); + .picking_instance_id(re_renderer::PickingLayerInstanceId( + re_log_types::Instance::ALL.get(), + )); } } diff --git a/crates/re_space_view_spatial/src/visualizers/points2d.rs b/crates/re_space_view_spatial/src/visualizers/points2d.rs index 3ac152c1184e..882ba5bb3425 100644 --- a/crates/re_space_view_spatial/src/visualizers/points2d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points2d.rs @@ -1,11 +1,12 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; +use re_log_types::Instance; use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points2D, - components::{ClassId, Color, InstanceKey, KeypointId, Position2D, Radius, Text}, + components::{ClassId, Color, KeypointId, Position2D, Radius, Text}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, @@ -66,7 +67,7 @@ impl Points2DVisualizer { target: UiLabelTarget::Point2D(egui::pos2(point.x, point.y)), labeled_instance: InstancePathHash::instance( entity_path, - InstanceKey(i as _), + Instance::from(i as u64), ), }), _ => None, @@ -128,8 +129,9 @@ impl Points2DVisualizer { { re_tracing::profile_scope!("marking additional highlight points"); for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { - let highlighted_point_index = - (highlighted_key.0 < num_instances as u64).then_some(highlighted_key.0); + let highlighted_point_index = (highlighted_key.get() + < num_instances as u64) + .then_some(highlighted_key.get()); if let Some(highlighted_point_index) = highlighted_point_index { point_range_builder = point_range_builder .push_additional_outline_mask_ids_for_range( diff --git a/crates/re_space_view_spatial/src/visualizers/points3d.rs b/crates/re_space_view_spatial/src/visualizers/points3d.rs index 98e2ce7da604..060011352473 100644 --- a/crates/re_space_view_spatial/src/visualizers/points3d.rs +++ b/crates/re_space_view_spatial/src/visualizers/points3d.rs @@ -1,11 +1,12 @@ use itertools::Itertools as _; use re_entity_db::{EntityPath, InstancePathHash}; +use re_log_types::Instance; use re_query::range_zip_1x5; use re_renderer::{LineDrawableBuilder, PickingLayerInstanceId, PointCloudBuilder}; use re_types::{ archetypes::Points3D, - components::{ClassId, Color, InstanceKey, KeypointId, Position3D, Radius, Text}, + components::{ClassId, Color, KeypointId, Position3D, Radius, Text}, }; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, ResolvedAnnotationInfos, @@ -79,7 +80,7 @@ impl Points3DVisualizer { target: UiLabelTarget::Position3D(world_from_obj.transform_point3(*point)), labeled_instance: InstancePathHash::instance( entity_path, - InstanceKey(i as _), + Instance::from(i as u64), ), }), _ => None, @@ -133,8 +134,9 @@ impl Points3DVisualizer { // Determine if there's any sub-ranges that need extra highlighting. { for (highlighted_key, instance_mask_ids) in &ent_context.highlight.instances { - let highlighted_point_index = - (highlighted_key.0 < num_instances as u64).then_some(highlighted_key.0); + let highlighted_point_index = (highlighted_key.get() + < num_instances as u64) + .then_some(highlighted_key.get()); if let Some(highlighted_point_index) = highlighted_point_index { point_range_builder = point_range_builder .push_additional_outline_mask_ids_for_range( diff --git a/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs b/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs index 74b8dca7f9df..c9efd4216dc5 100644 --- a/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs +++ b/crates/re_space_view_spatial/src/visualizers/transform3d_arrows.rs @@ -1,6 +1,6 @@ use egui::Color32; -use re_log_types::EntityPath; -use re_types::components::{InstanceKey, Transform3D}; +use re_log_types::{EntityPath, Instance}; +use re_types::components::Transform3D; use re_viewer_context::{ ApplicableEntities, IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewerContext, VisualizableEntities, VisualizableFilterContext, VisualizerQueryInfo, @@ -137,7 +137,7 @@ pub fn add_axis_arrows( .picking_object_id(re_renderer::PickingLayerObjectId( ent_path.map_or(0, |p| p.hash64()), )); - let picking_instance_id = re_renderer::PickingLayerInstanceId(InstanceKey::SPLAT.0); + let picking_instance_id = re_renderer::PickingLayerInstanceId(Instance::ALL.get()); line_batch .add_segment(glam::Vec3::ZERO, glam::Vec3::X * axis_length) diff --git a/crates/re_time_panel/src/data_density_graph.rs b/crates/re_time_panel/src/data_density_graph.rs index 858907e25d18..0cd37faae4fb 100644 --- a/crates/re_time_panel/src/data_density_graph.rs +++ b/crates/re_time_panel/src/data_density_graph.rs @@ -557,7 +557,7 @@ fn show_row_ids_tooltip( ui.add_space(8.0); component_path.data_ui(ctx, ui, verbosity, &query, db); } else { - let instance_path = re_entity_db::InstancePath::entity_splat(entity_path.clone()); + let instance_path = re_entity_db::InstancePath::entity_all(entity_path.clone()); item_ui::instance_path_button(ctx, &query, db, ui, None, &instance_path); ui.add_space(8.0); instance_path.data_ui(ctx, ui, verbosity, &query, db); diff --git a/crates/re_time_panel/src/lib.rs b/crates/re_time_panel/src/lib.rs index b56aee1e0e12..8e07405f3298 100644 --- a/crates/re_time_panel/src/lib.rs +++ b/crates/re_time_panel/src/lib.rs @@ -65,7 +65,7 @@ impl TimePanelItem { if let Some(component_name) = component_name { Item::ComponentPath(ComponentPath::new(entity_path.clone(), *component_name)) } else { - Item::InstancePath(InstancePath::entity_splat(entity_path.clone())) + Item::InstancePath(InstancePath::entity_all(entity_path.clone())) } } } diff --git a/crates/re_types/definitions/rerun/components.fbs b/crates/re_types/definitions/rerun/components.fbs index 409cccb3eb59..251b7f943b51 100644 --- a/crates/re_types/definitions/rerun/components.fbs +++ b/crates/re_types/definitions/rerun/components.fbs @@ -8,7 +8,6 @@ include "./components/disconnected_space.fbs"; include "./components/draw_order.fbs"; include "./components/half_sizes2d.fbs"; include "./components/half_sizes3d.fbs"; -include "./components/instance_key.fbs"; include "./components/keypoint_id.fbs"; include "./components/line_strip2d.fbs"; include "./components/line_strip3d.fbs"; diff --git a/crates/re_types/definitions/rerun/components/instance_key.fbs b/crates/re_types/definitions/rerun/components/instance_key.fbs deleted file mode 100644 index d3b639c2e056..000000000000 --- a/crates/re_types/definitions/rerun/components/instance_key.fbs +++ /dev/null @@ -1,30 +0,0 @@ -include "arrow/attributes.fbs"; -include "python/attributes.fbs"; -include "rust/attributes.fbs"; - -include "rerun/datatypes.fbs"; -include "rerun/attributes.fbs"; - -namespace rerun.components; - -// --- - -/// A unique numeric identifier for each individual instance within a batch. -/// -/// Instance keys are automatically assigned by the `rerun` library and should not be set manually. -/// -/// The instance key is just the index of the instance within the batch, -/// i.e. the first point in a point cloud has `InstanceKey = 0`, the second `InstanceKey = 1`, and so on. -/// -/// We plan to remove the `InstanceKey` component in the near future. -struct InstanceKey ( - "attr.python.aliases": "int", - "attr.python.array_aliases": "int, npt.NDArray[np.uint64]", - "attr.rust.custom_clause": - 'cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))', - "attr.rust.derive": "Copy, Hash, PartialEq, Eq, PartialOrd, Ord, ::bytemuck::Pod, ::bytemuck::Zeroable", - "attr.rust.repr": "transparent", - "attr.rust.override_crate": "re_types_core" -) { - value: uint64 (order: 100); -} diff --git a/crates/re_types/src/archetypes/annotation_context.rs b/crates/re_types/src/archetypes/annotation_context.rs index 1c481e7b9d8d..b9fa8ad82e3a 100644 --- a/crates/re_types/src/archetypes/annotation_context.rs +++ b/crates/re_types/src/archetypes/annotation_context.rs @@ -97,20 +97,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.AnnotationContextIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.AnnotationContext".into(), "rerun.components.AnnotationContextIndicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl AnnotationContext { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`AnnotationContext`] [`::re_types_core::Archetype`] @@ -189,11 +188,6 @@ impl ::re_types_core::AsComponents for AnnotationContext { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl AnnotationContext { diff --git a/crates/re_types/src/archetypes/arrows2d.rs b/crates/re_types/src/archetypes/arrows2d.rs index 7065a69feaf3..8097432518ad 100644 --- a/crates/re_types/src/archetypes/arrows2d.rs +++ b/crates/re_types/src/archetypes/arrows2d.rs @@ -113,18 +113,17 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Radius".into(), "rerun.components.Text".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Vector2D".into(), @@ -132,14 +131,13 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = "rerun.components.Position2D".into(), "rerun.components.ClassId".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Radius".into(), "rerun.components.Text".into(), ] }); impl Arrows2D { - pub const NUM_COMPONENTS: usize = 8usize; + pub const NUM_COMPONENTS: usize = 7usize; } /// Indicator component for the [`Arrows2D`] [`::re_types_core::Archetype`] @@ -299,11 +297,6 @@ impl ::re_types_core::AsComponents for Arrows2D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.vectors.len() - } } impl Arrows2D { diff --git a/crates/re_types/src/archetypes/arrows3d.rs b/crates/re_types/src/archetypes/arrows3d.rs index 7799d3e88c23..f3e237d8770a 100644 --- a/crates/re_types/src/archetypes/arrows3d.rs +++ b/crates/re_types/src/archetypes/arrows3d.rs @@ -126,18 +126,17 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Radius".into(), "rerun.components.Text".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Vector3D".into(), @@ -145,14 +144,13 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = "rerun.components.Position3D".into(), "rerun.components.ClassId".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Radius".into(), "rerun.components.Text".into(), ] }); impl Arrows3D { - pub const NUM_COMPONENTS: usize = 8usize; + pub const NUM_COMPONENTS: usize = 7usize; } /// Indicator component for the [`Arrows3D`] [`::re_types_core::Archetype`] @@ -312,11 +310,6 @@ impl ::re_types_core::AsComponents for Arrows3D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.vectors.len() - } } impl Arrows3D { diff --git a/crates/re_types/src/archetypes/asset3d.rs b/crates/re_types/src/archetypes/asset3d.rs index aa63c3e86ebe..2a2ee20afaf7 100644 --- a/crates/re_types/src/archetypes/asset3d.rs +++ b/crates/re_types/src/archetypes/asset3d.rs @@ -105,27 +105,21 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.InstanceKey".into(), - "rerun.components.OutOfTreeTransform3D".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.OutOfTreeTransform3D".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Blob".into(), "rerun.components.Asset3DIndicator".into(), "rerun.components.MediaType".into(), - "rerun.components.InstanceKey".into(), "rerun.components.OutOfTreeTransform3D".into(), ] }); impl Asset3D { - pub const NUM_COMPONENTS: usize = 5usize; + pub const NUM_COMPONENTS: usize = 4usize; } /// Indicator component for the [`Asset3D`] [`::re_types_core::Archetype`] @@ -233,11 +227,6 @@ impl ::re_types_core::AsComponents for Asset3D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl Asset3D { diff --git a/crates/re_types/src/archetypes/bar_chart.rs b/crates/re_types/src/archetypes/bar_chart.rs index f14cdedd9559..776000dd3ccc 100644 --- a/crates/re_types/src/archetypes/bar_chart.rs +++ b/crates/re_types/src/archetypes/bar_chart.rs @@ -77,26 +77,20 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.BarChartIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.Color".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.TensorData".into(), "rerun.components.BarChartIndicator".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), ] }); impl BarChart { - pub const NUM_COMPONENTS: usize = 4usize; + pub const NUM_COMPONENTS: usize = 3usize; } /// Indicator component for the [`BarChart`] [`::re_types_core::Archetype`] @@ -187,11 +181,6 @@ impl ::re_types_core::AsComponents for BarChart { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl BarChart { diff --git a/crates/re_types/src/archetypes/boxes2d.rs b/crates/re_types/src/archetypes/boxes2d.rs index b444e86e4000..157edaad7e6f 100644 --- a/crates/re_types/src/archetypes/boxes2d.rs +++ b/crates/re_types/src/archetypes/boxes2d.rs @@ -117,18 +117,17 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Radius".into(), "rerun.components.Text".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.HalfSizes2D".into(), @@ -137,14 +136,13 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = "rerun.components.Position2D".into(), "rerun.components.ClassId".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Radius".into(), "rerun.components.Text".into(), ] }); impl Boxes2D { - pub const NUM_COMPONENTS: usize = 9usize; + pub const NUM_COMPONENTS: usize = 8usize; } /// Indicator component for the [`Boxes2D`] [`::re_types_core::Archetype`] @@ -317,11 +315,6 @@ impl ::re_types_core::AsComponents for Boxes2D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.half_sizes.len() - } } impl Boxes2D { diff --git a/crates/re_types/src/archetypes/boxes3d.rs b/crates/re_types/src/archetypes/boxes3d.rs index 40706069a234..45b6063b0c4d 100644 --- a/crates/re_types/src/archetypes/boxes3d.rs +++ b/crates/re_types/src/archetypes/boxes3d.rs @@ -124,17 +124,16 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Radius".into(), "rerun.components.Text".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.HalfSizes3D".into(), @@ -143,14 +142,13 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = "rerun.components.Position3D".into(), "rerun.components.Rotation3D".into(), "rerun.components.ClassId".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Radius".into(), "rerun.components.Text".into(), ] }); impl Boxes3D { - pub const NUM_COMPONENTS: usize = 9usize; + pub const NUM_COMPONENTS: usize = 8usize; } /// Indicator component for the [`Boxes3D`] [`::re_types_core::Archetype`] @@ -326,11 +324,6 @@ impl ::re_types_core::AsComponents for Boxes3D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.half_sizes.len() - } } impl Boxes3D { diff --git a/crates/re_types/src/archetypes/depth_image.rs b/crates/re_types/src/archetypes/depth_image.rs index c9da537a2763..4ba9444b8c1f 100644 --- a/crates/re_types/src/archetypes/depth_image.rs +++ b/crates/re_types/src/archetypes/depth_image.rs @@ -104,28 +104,26 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.DepthImageIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.DepthMeter".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.TensorData".into(), "rerun.components.DepthImageIndicator".into(), "rerun.components.DepthMeter".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), ] }); impl DepthImage { - pub const NUM_COMPONENTS: usize = 5usize; + pub const NUM_COMPONENTS: usize = 4usize; } /// Indicator component for the [`DepthImage`] [`::re_types_core::Archetype`] @@ -232,11 +230,6 @@ impl ::re_types_core::AsComponents for DepthImage { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl DepthImage { diff --git a/crates/re_types/src/archetypes/disconnected_space.rs b/crates/re_types/src/archetypes/disconnected_space.rs index 8412af71c0a6..4b79caf832ef 100644 --- a/crates/re_types/src/archetypes/disconnected_space.rs +++ b/crates/re_types/src/archetypes/disconnected_space.rs @@ -88,20 +88,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.DisconnectedSpaceIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.DisconnectedSpace".into(), "rerun.components.DisconnectedSpaceIndicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl DisconnectedSpace { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`DisconnectedSpace`] [`::re_types_core::Archetype`] @@ -180,11 +179,6 @@ impl ::re_types_core::AsComponents for DisconnectedSpace { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl DisconnectedSpace { diff --git a/crates/re_types/src/archetypes/image.rs b/crates/re_types/src/archetypes/image.rs index 2a9c32f743ed..b3636b125a51 100644 --- a/crates/re_types/src/archetypes/image.rs +++ b/crates/re_types/src/archetypes/image.rs @@ -98,26 +98,20 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.ImageIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.DrawOrder".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.TensorData".into(), "rerun.components.ImageIndicator".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), ] }); impl Image { - pub const NUM_COMPONENTS: usize = 4usize; + pub const NUM_COMPONENTS: usize = 3usize; } /// Indicator component for the [`Image`] [`::re_types_core::Archetype`] @@ -208,11 +202,6 @@ impl ::re_types_core::AsComponents for Image { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl Image { diff --git a/crates/re_types/src/archetypes/line_strips2d.rs b/crates/re_types/src/archetypes/line_strips2d.rs index 6b0e10344662..5f99edf23ccf 100644 --- a/crates/re_types/src/archetypes/line_strips2d.rs +++ b/crates/re_types/src/archetypes/line_strips2d.rs @@ -119,17 +119,16 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Text".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.LineStrip2D".into(), @@ -138,13 +137,12 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = "rerun.components.Radius".into(), "rerun.components.ClassId".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Text".into(), ] }); impl LineStrips2D { - pub const NUM_COMPONENTS: usize = 8usize; + pub const NUM_COMPONENTS: usize = 7usize; } /// Indicator component for the [`LineStrips2D`] [`::re_types_core::Archetype`] @@ -301,11 +299,6 @@ impl ::re_types_core::AsComponents for LineStrips2D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.strips.len() - } } impl LineStrips2D { diff --git a/crates/re_types/src/archetypes/line_strips3d.rs b/crates/re_types/src/archetypes/line_strips3d.rs index cdbe1529d700..4cce5d41f8b9 100644 --- a/crates/re_types/src/archetypes/line_strips3d.rs +++ b/crates/re_types/src/archetypes/line_strips3d.rs @@ -114,16 +114,15 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Text".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.LineStrip3D".into(), @@ -131,13 +130,12 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = "rerun.components.LineStrips3DIndicator".into(), "rerun.components.Radius".into(), "rerun.components.ClassId".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Text".into(), ] }); impl LineStrips3D { - pub const NUM_COMPONENTS: usize = 7usize; + pub const NUM_COMPONENTS: usize = 6usize; } /// Indicator component for the [`LineStrips3D`] [`::re_types_core::Archetype`] @@ -281,11 +279,6 @@ impl ::re_types_core::AsComponents for LineStrips3D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.strips.len() - } } impl LineStrips3D { diff --git a/crates/re_types/src/archetypes/mesh3d.rs b/crates/re_types/src/archetypes/mesh3d.rs index 9fe29ce5f58e..a5d8883f3ad3 100644 --- a/crates/re_types/src/archetypes/mesh3d.rs +++ b/crates/re_types/src/archetypes/mesh3d.rs @@ -128,19 +128,18 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Material".into(), "rerun.components.TensorData".into(), "rerun.components.Texcoord2D".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 10usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Position3D".into(), @@ -149,7 +148,6 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 10usize]> = "rerun.components.Vector3D".into(), "rerun.components.ClassId".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Material".into(), "rerun.components.TensorData".into(), "rerun.components.Texcoord2D".into(), @@ -157,7 +155,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 10usize]> = }); impl Mesh3D { - pub const NUM_COMPONENTS: usize = 10usize; + pub const NUM_COMPONENTS: usize = 9usize; } /// Indicator component for the [`Mesh3D`] [`::re_types_core::Archetype`] @@ -343,11 +341,6 @@ impl ::re_types_core::AsComponents for Mesh3D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.vertex_positions.len() - } } impl Mesh3D { diff --git a/crates/re_types/src/archetypes/pinhole.rs b/crates/re_types/src/archetypes/pinhole.rs index 8bb93e7ffc51..bc41635831a9 100644 --- a/crates/re_types/src/archetypes/pinhole.rs +++ b/crates/re_types/src/archetypes/pinhole.rs @@ -157,27 +157,21 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.InstanceKey".into(), - "rerun.components.ViewCoordinates".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.ViewCoordinates".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.PinholeProjection".into(), "rerun.components.PinholeIndicator".into(), "rerun.components.Resolution".into(), - "rerun.components.InstanceKey".into(), "rerun.components.ViewCoordinates".into(), ] }); impl Pinhole { - pub const NUM_COMPONENTS: usize = 5usize; + pub const NUM_COMPONENTS: usize = 4usize; } /// Indicator component for the [`Pinhole`] [`::re_types_core::Archetype`] @@ -285,11 +279,6 @@ impl ::re_types_core::AsComponents for Pinhole { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl Pinhole { diff --git a/crates/re_types/src/archetypes/points2d.rs b/crates/re_types/src/archetypes/points2d.rs index 0f57878f9343..5c90d8f76800 100644 --- a/crates/re_types/src/archetypes/points2d.rs +++ b/crates/re_types/src/archetypes/points2d.rs @@ -129,18 +129,17 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), "rerun.components.KeypointId".into(), "rerun.components.Text".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Position2D".into(), @@ -149,14 +148,13 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = "rerun.components.Radius".into(), "rerun.components.ClassId".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), "rerun.components.KeypointId".into(), "rerun.components.Text".into(), ] }); impl Points2D { - pub const NUM_COMPONENTS: usize = 9usize; + pub const NUM_COMPONENTS: usize = 8usize; } /// Indicator component for the [`Points2D`] [`::re_types_core::Archetype`] @@ -329,11 +327,6 @@ impl ::re_types_core::AsComponents for Points2D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.positions.len() - } } impl Points2D { diff --git a/crates/re_types/src/archetypes/points3d.rs b/crates/re_types/src/archetypes/points3d.rs index 8c88d53e4ccb..618591340e95 100644 --- a/crates/re_types/src/archetypes/points3d.rs +++ b/crates/re_types/src/archetypes/points3d.rs @@ -121,17 +121,16 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClassId".into(), - "rerun.components.InstanceKey".into(), "rerun.components.KeypointId".into(), "rerun.components.Text".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Position3D".into(), @@ -139,14 +138,13 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = "rerun.components.Points3DIndicator".into(), "rerun.components.Radius".into(), "rerun.components.ClassId".into(), - "rerun.components.InstanceKey".into(), "rerun.components.KeypointId".into(), "rerun.components.Text".into(), ] }); impl Points3D { - pub const NUM_COMPONENTS: usize = 8usize; + pub const NUM_COMPONENTS: usize = 7usize; } /// Indicator component for the [`Points3D`] [`::re_types_core::Archetype`] @@ -306,11 +304,6 @@ impl ::re_types_core::AsComponents for Points3D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.positions.len() - } } impl Points3D { diff --git a/crates/re_types/src/archetypes/scalar.rs b/crates/re_types/src/archetypes/scalar.rs index 8de3cd9d838b..2e93e834c1fb 100644 --- a/crates/re_types/src/archetypes/scalar.rs +++ b/crates/re_types/src/archetypes/scalar.rs @@ -83,20 +83,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.ScalarIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Scalar".into(), "rerun.components.ScalarIndicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl Scalar { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`Scalar`] [`::re_types_core::Archetype`] @@ -175,11 +174,6 @@ impl ::re_types_core::AsComponents for Scalar { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl Scalar { diff --git a/crates/re_types/src/archetypes/segmentation_image.rs b/crates/re_types/src/archetypes/segmentation_image.rs index 189fdeaa4c59..1f8eceacd6a4 100644 --- a/crates/re_types/src/archetypes/segmentation_image.rs +++ b/crates/re_types/src/archetypes/segmentation_image.rs @@ -102,26 +102,20 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.SegmentationImageIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.DrawOrder".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.TensorData".into(), "rerun.components.SegmentationImageIndicator".into(), "rerun.components.DrawOrder".into(), - "rerun.components.InstanceKey".into(), ] }); impl SegmentationImage { - pub const NUM_COMPONENTS: usize = 4usize; + pub const NUM_COMPONENTS: usize = 3usize; } /// Indicator component for the [`SegmentationImage`] [`::re_types_core::Archetype`] @@ -212,11 +206,6 @@ impl ::re_types_core::AsComponents for SegmentationImage { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl SegmentationImage { diff --git a/crates/re_types/src/archetypes/series_line.rs b/crates/re_types/src/archetypes/series_line.rs index be4b339aa3a2..db54b4bebbdf 100644 --- a/crates/re_types/src/archetypes/series_line.rs +++ b/crates/re_types/src/archetypes/series_line.rs @@ -109,29 +109,27 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.SeriesLineIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Name".into(), "rerun.components.StrokeWidth".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.SeriesLineIndicator".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Name".into(), "rerun.components.StrokeWidth".into(), ] }); impl SeriesLine { - pub const NUM_COMPONENTS: usize = 5usize; + pub const NUM_COMPONENTS: usize = 4usize; } /// Indicator component for the [`SeriesLine`] [`::re_types_core::Archetype`] @@ -232,11 +230,6 @@ impl ::re_types_core::AsComponents for SeriesLine { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl SeriesLine { diff --git a/crates/re_types/src/archetypes/series_point.rs b/crates/re_types/src/archetypes/series_point.rs index d38f3222ca70..d771aa7c4abe 100644 --- a/crates/re_types/src/archetypes/series_point.rs +++ b/crates/re_types/src/archetypes/series_point.rs @@ -118,23 +118,21 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.SeriesPointIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.MarkerShape".into(), "rerun.components.MarkerSize".into(), "rerun.components.Name".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.SeriesPointIndicator".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), "rerun.components.MarkerShape".into(), "rerun.components.MarkerSize".into(), "rerun.components.Name".into(), @@ -142,7 +140,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = }); impl SeriesPoint { - pub const NUM_COMPONENTS: usize = 6usize; + pub const NUM_COMPONENTS: usize = 5usize; } /// Indicator component for the [`SeriesPoint`] [`::re_types_core::Archetype`] @@ -260,11 +258,6 @@ impl ::re_types_core::AsComponents for SeriesPoint { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl SeriesPoint { diff --git a/crates/re_types/src/archetypes/tensor.rs b/crates/re_types/src/archetypes/tensor.rs index e7e5c13b71a9..a31b81af425e 100644 --- a/crates/re_types/src/archetypes/tensor.rs +++ b/crates/re_types/src/archetypes/tensor.rs @@ -76,20 +76,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.TensorIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.TensorData".into(), "rerun.components.TensorIndicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl Tensor { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`Tensor`] [`::re_types_core::Archetype`] @@ -168,11 +167,6 @@ impl ::re_types_core::AsComponents for Tensor { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl Tensor { diff --git a/crates/re_types/src/archetypes/text_document.rs b/crates/re_types/src/archetypes/text_document.rs index f5a3a5bc6fc0..b653de113ac6 100644 --- a/crates/re_types/src/archetypes/text_document.rs +++ b/crates/re_types/src/archetypes/text_document.rs @@ -124,26 +124,20 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.TextDocumentIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.InstanceKey".into(), - "rerun.components.MediaType".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.MediaType".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Text".into(), "rerun.components.TextDocumentIndicator".into(), - "rerun.components.InstanceKey".into(), "rerun.components.MediaType".into(), ] }); impl TextDocument { - pub const NUM_COMPONENTS: usize = 4usize; + pub const NUM_COMPONENTS: usize = 3usize; } /// Indicator component for the [`TextDocument`] [`::re_types_core::Archetype`] @@ -234,11 +228,6 @@ impl ::re_types_core::AsComponents for TextDocument { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl TextDocument { diff --git a/crates/re_types/src/archetypes/text_log.rs b/crates/re_types/src/archetypes/text_log.rs index 55807ef24b6c..2363dded0b92 100644 --- a/crates/re_types/src/archetypes/text_log.rs +++ b/crates/re_types/src/archetypes/text_log.rs @@ -101,27 +101,21 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = ] }); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.Color".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Text".into(), "rerun.components.TextLogIndicator".into(), "rerun.components.TextLogLevel".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), ] }); impl TextLog { - pub const NUM_COMPONENTS: usize = 5usize; + pub const NUM_COMPONENTS: usize = 4usize; } /// Indicator component for the [`TextLog`] [`::re_types_core::Archetype`] @@ -224,11 +218,6 @@ impl ::re_types_core::AsComponents for TextLog { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl TextLog { diff --git a/crates/re_types/src/archetypes/transform3d.rs b/crates/re_types/src/archetypes/transform3d.rs index 2cb6259e326f..0be5132b9081 100644 --- a/crates/re_types/src/archetypes/transform3d.rs +++ b/crates/re_types/src/archetypes/transform3d.rs @@ -90,20 +90,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.Transform3DIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Transform3D".into(), "rerun.components.Transform3DIndicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl Transform3D { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`Transform3D`] [`::re_types_core::Archetype`] @@ -182,11 +181,6 @@ impl ::re_types_core::AsComponents for Transform3D { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl Transform3D { diff --git a/crates/re_types/src/archetypes/view_coordinates.rs b/crates/re_types/src/archetypes/view_coordinates.rs index a317d3d754ef..83268138ec60 100644 --- a/crates/re_types/src/archetypes/view_coordinates.rs +++ b/crates/re_types/src/archetypes/view_coordinates.rs @@ -83,20 +83,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.ViewCoordinatesIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ViewCoordinates".into(), "rerun.components.ViewCoordinatesIndicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl ViewCoordinates { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`ViewCoordinates`] [`::re_types_core::Archetype`] @@ -175,11 +174,6 @@ impl ::re_types_core::AsComponents for ViewCoordinates { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl ViewCoordinates { diff --git a/crates/re_types/src/blueprint/archetypes/background.rs b/crates/re_types/src/blueprint/archetypes/background.rs index bd03c06267d4..3c11b72d6785 100644 --- a/crates/re_types/src/blueprint/archetypes/background.rs +++ b/crates/re_types/src/blueprint/archetypes/background.rs @@ -53,26 +53,20 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.BackgroundIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.Color".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.BackgroundKind".into(), "rerun.blueprint.components.BackgroundIndicator".into(), "rerun.components.Color".into(), - "rerun.components.InstanceKey".into(), ] }); impl Background { - pub const NUM_COMPONENTS: usize = 4usize; + pub const NUM_COMPONENTS: usize = 3usize; } /// Indicator component for the [`Background`] [`::re_types_core::Archetype`] @@ -163,11 +157,6 @@ impl ::re_types_core::AsComponents for Background { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl Background { diff --git a/crates/re_types/src/blueprint/archetypes/plot_legend.rs b/crates/re_types/src/blueprint/archetypes/plot_legend.rs index 8f146378673d..19d72afe8641 100644 --- a/crates/re_types/src/blueprint/archetypes/plot_legend.rs +++ b/crates/re_types/src/blueprint/archetypes/plot_legend.rs @@ -55,27 +55,25 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.PlotLegendIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.Corner2D".into(), "rerun.blueprint.components.Visible".into(), - "rerun.components.InstanceKey".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.PlotLegendIndicator".into(), "rerun.blueprint.components.Corner2D".into(), "rerun.blueprint.components.Visible".into(), - "rerun.components.InstanceKey".into(), ] }); impl PlotLegend { - pub const NUM_COMPONENTS: usize = 4usize; + pub const NUM_COMPONENTS: usize = 3usize; } /// Indicator component for the [`PlotLegend`] [`::re_types_core::Archetype`] @@ -166,11 +164,6 @@ impl ::re_types_core::AsComponents for PlotLegend { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl PlotLegend { diff --git a/crates/re_types/src/blueprint/archetypes/scalar_axis.rs b/crates/re_types/src/blueprint/archetypes/scalar_axis.rs index 0c1660af0cd9..af7a36b6cae1 100644 --- a/crates/re_types/src/blueprint/archetypes/scalar_axis.rs +++ b/crates/re_types/src/blueprint/archetypes/scalar_axis.rs @@ -53,27 +53,25 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.ScalarAxisIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.LockRangeDuringZoom".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Range1D".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.ScalarAxisIndicator".into(), "rerun.blueprint.components.LockRangeDuringZoom".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Range1D".into(), ] }); impl ScalarAxis { - pub const NUM_COMPONENTS: usize = 4usize; + pub const NUM_COMPONENTS: usize = 3usize; } /// Indicator component for the [`ScalarAxis`] [`::re_types_core::Archetype`] @@ -167,11 +165,6 @@ impl ::re_types_core::AsComponents for ScalarAxis { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl ScalarAxis { diff --git a/crates/re_types/src/blueprint/archetypes/space_view_blueprint.rs b/crates/re_types/src/blueprint/archetypes/space_view_blueprint.rs index 0742019dcd6b..7df38d615475 100644 --- a/crates/re_types/src/blueprint/archetypes/space_view_blueprint.rs +++ b/crates/re_types/src/blueprint/archetypes/space_view_blueprint.rs @@ -72,30 +72,28 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = || ["rerun.blueprint.components.SpaceViewBlueprintIndicator".into()], ); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.SpaceViewOrigin".into(), "rerun.blueprint.components.Visible".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Name".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.SpaceViewClass".into(), "rerun.blueprint.components.SpaceViewBlueprintIndicator".into(), "rerun.blueprint.components.SpaceViewOrigin".into(), "rerun.blueprint.components.Visible".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Name".into(), ] }); impl SpaceViewBlueprint { - pub const NUM_COMPONENTS: usize = 6usize; + pub const NUM_COMPONENTS: usize = 5usize; } /// Indicator component for the [`SpaceViewBlueprint`] [`::re_types_core::Archetype`] @@ -218,11 +216,6 @@ impl ::re_types_core::AsComponents for SpaceViewBlueprint { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl SpaceViewBlueprint { diff --git a/crates/re_types/src/blueprint/archetypes/space_view_contents.rs b/crates/re_types/src/blueprint/archetypes/space_view_contents.rs index 549050ed0249..97b59c85484b 100644 --- a/crates/re_types/src/blueprint/archetypes/space_view_contents.rs +++ b/crates/re_types/src/blueprint/archetypes/space_view_contents.rs @@ -86,25 +86,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.SpaceViewContentsIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.blueprint.components.QueryExpression".into(), - "rerun.components.InstanceKey".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.QueryExpression".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.SpaceViewContentsIndicator".into(), "rerun.blueprint.components.QueryExpression".into(), - "rerun.components.InstanceKey".into(), ] }); impl SpaceViewContents { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`SpaceViewContents`] [`::re_types_core::Archetype`] @@ -182,11 +176,6 @@ impl ::re_types_core::AsComponents for SpaceViewContents { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl SpaceViewContents { diff --git a/crates/re_types/src/datagen.rs b/crates/re_types/src/datagen.rs index 37239d93e51e..d276d78837de 100644 --- a/crates/re_types/src/datagen.rs +++ b/crates/re_types/src/datagen.rs @@ -2,8 +2,6 @@ // TODO(#1810): It really is time for whole module to disappear. -use crate::components::InstanceKey; - /// Create `len` dummy colors pub fn build_some_colors(len: usize) -> Vec { (0..len) @@ -38,26 +36,3 @@ pub fn build_some_vec3d(len: usize) -> Vec { }) .collect() } - -/// Create `len` dummy `InstanceKey` keys. These keys will be sorted. -pub fn build_some_instances(num_instances: usize) -> Vec { - use rand::seq::SliceRandom; - let mut rng = rand::thread_rng(); - - // Allocate pool of 10x the potential instance keys, draw a random sampling, and then sort it - let mut instance_pool = (0..(num_instances * 10)).collect::>(); - let (rand_instances, _) = instance_pool.partial_shuffle(&mut rng, num_instances); - let mut sorted_instances = rand_instances.to_vec(); - sorted_instances.sort(); - - sorted_instances - .into_iter() - .map(|id| InstanceKey(id as u64)) - .collect() -} - -pub fn build_some_instances_from(instances: impl IntoIterator) -> Vec { - let mut instances = instances.into_iter().map(InstanceKey).collect::>(); - instances.sort(); - instances -} diff --git a/crates/re_types/src/lib.rs b/crates/re_types/src/lib.rs index 3bb276d4796b..b954162a4b4b 100644 --- a/crates/re_types/src/lib.rs +++ b/crates/re_types/src/lib.rs @@ -184,10 +184,6 @@ pub const DISPLAY_PRECISION: usize = 3; /// For instance, the [`Points3D`][archetypes::Points3D] archetype contains a /// batch of positions, a batch of colors, etc. /// -/// These component batches are must all have the same length, or one of the special lengths: -/// * 0 - an empty batch -/// * 1 - a "splat" batch, e.g. using the same color for all positions. -/// /// Each entity can consist of many archetypes, but usually each entity will only have one archetype. /// /// A special archetype is [`Clear`][archetypes::Clear] which resets all the components @@ -214,9 +210,9 @@ pub mod archetypes { /// Each component is a wrapper around a [`datatype`][datatypes]. pub mod components { - // Some components (e.g. `InstanceKey`) are so fundamental and used everywhere that we want - // them to be exposed by `re_types_core` directly; that way we don't force a dependency on the - // `re_types` behemoth just so one can use one of these fundamental types. + // Some components are so fundamental and used everywhere that we want them to be exposed + // by `re_types_core` directly; that way we don't force a dependency on the `re_types` + // behemoth just so one can use one of these fundamental types. // // To do so, re-inject `re_types_core`'s components into our own module. @@ -232,9 +228,9 @@ pub mod components { /// They all implement the [`Datatype`] trait. pub mod datatypes { - // Some datatypes (e.g. `InstanceKey`) are so fundamental and used everywhere that we want - // them to be exposed by `re_types_core` directly; that way we don't force a dependency on the - // `re_types` behemoth just so one can use one of these fundamental types. + // Some datatypes are so fundamental and used everywhere that we want them to be exposed + // by `re_types_core` directly; that way we don't force a dependency on the `re_types` + // behemoth just so one can use one of these fundamental types. // // To do so, re-inject `re_types_core`'s datatypes into our own module. diff --git a/crates/re_types/src/testing/archetypes/affix_fuzzer1.rs b/crates/re_types/src/testing/archetypes/affix_fuzzer1.rs index 9668a060d378..bfb7e4919793 100644 --- a/crates/re_types/src/testing/archetypes/affix_fuzzer1.rs +++ b/crates/re_types/src/testing/archetypes/affix_fuzzer1.rs @@ -133,10 +133,10 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 22usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.testing.components.AffixFuzzer1Indicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 24usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 23usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.testing.components.AffixFuzzer1".into(), @@ -162,12 +162,11 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 24usize]> = "rerun.testing.components.AffixFuzzer8".into(), "rerun.testing.components.AffixFuzzer9".into(), "rerun.testing.components.AffixFuzzer1Indicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl AffixFuzzer1 { - pub const NUM_COMPONENTS: usize = 24usize; + pub const NUM_COMPONENTS: usize = 23usize; } /// Indicator component for the [`AffixFuzzer1`] [`::re_types_core::Archetype`] @@ -563,11 +562,6 @@ impl ::re_types_core::AsComponents for AffixFuzzer1 { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl AffixFuzzer1 { diff --git a/crates/re_types/src/testing/archetypes/affix_fuzzer2.rs b/crates/re_types/src/testing/archetypes/affix_fuzzer2.rs index f3e9f6003863..2585277f2fd0 100644 --- a/crates/re_types/src/testing/archetypes/affix_fuzzer2.rs +++ b/crates/re_types/src/testing/archetypes/affix_fuzzer2.rs @@ -121,10 +121,10 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.testing.components.AffixFuzzer2Indicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 21usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 20usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.testing.components.AffixFuzzer1".into(), @@ -147,12 +147,11 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 21usize]> = "rerun.testing.components.AffixFuzzer8".into(), "rerun.testing.components.AffixFuzzer9".into(), "rerun.testing.components.AffixFuzzer2Indicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl AffixFuzzer2 { - pub const NUM_COMPONENTS: usize = 21usize; + pub const NUM_COMPONENTS: usize = 20usize; } /// Indicator component for the [`AffixFuzzer2`] [`::re_types_core::Archetype`] @@ -484,11 +483,6 @@ impl ::re_types_core::AsComponents for AffixFuzzer2 { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - self.fuzz1101.len() - } } impl AffixFuzzer2 { diff --git a/crates/re_types/src/testing/archetypes/affix_fuzzer3.rs b/crates/re_types/src/testing/archetypes/affix_fuzzer3.rs index 34edf9f5ae40..9017b2b7cd08 100644 --- a/crates/re_types/src/testing/archetypes/affix_fuzzer3.rs +++ b/crates/re_types/src/testing/archetypes/affix_fuzzer3.rs @@ -96,10 +96,9 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.testing.components.AffixFuzzer3Indicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 18usize]> = once_cell::sync::Lazy::new(|| { [ - "rerun.components.InstanceKey".into(), "rerun.testing.components.AffixFuzzer1".into(), "rerun.testing.components.AffixFuzzer10".into(), "rerun.testing.components.AffixFuzzer11".into(), @@ -121,11 +120,10 @@ static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 20usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.testing.components.AffixFuzzer3Indicator".into(), - "rerun.components.InstanceKey".into(), "rerun.testing.components.AffixFuzzer1".into(), "rerun.testing.components.AffixFuzzer10".into(), "rerun.testing.components.AffixFuzzer11".into(), @@ -148,7 +146,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 20usize]> = }); impl AffixFuzzer3 { - pub const NUM_COMPONENTS: usize = 20usize; + pub const NUM_COMPONENTS: usize = 19usize; } /// Indicator component for the [`AffixFuzzer3`] [`::re_types_core::Archetype`] @@ -466,11 +464,6 @@ impl ::re_types_core::AsComponents for AffixFuzzer3 { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl AffixFuzzer3 { diff --git a/crates/re_types/src/testing/archetypes/affix_fuzzer4.rs b/crates/re_types/src/testing/archetypes/affix_fuzzer4.rs index 76a85736b4a6..e7707a3f3d44 100644 --- a/crates/re_types/src/testing/archetypes/affix_fuzzer4.rs +++ b/crates/re_types/src/testing/archetypes/affix_fuzzer4.rs @@ -96,10 +96,9 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.testing.components.AffixFuzzer4Indicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 18usize]> = once_cell::sync::Lazy::new(|| { [ - "rerun.components.InstanceKey".into(), "rerun.testing.components.AffixFuzzer1".into(), "rerun.testing.components.AffixFuzzer10".into(), "rerun.testing.components.AffixFuzzer11".into(), @@ -121,11 +120,10 @@ static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 20usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.testing.components.AffixFuzzer4Indicator".into(), - "rerun.components.InstanceKey".into(), "rerun.testing.components.AffixFuzzer1".into(), "rerun.testing.components.AffixFuzzer10".into(), "rerun.testing.components.AffixFuzzer11".into(), @@ -148,7 +146,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 20usize]> = }); impl AffixFuzzer4 { - pub const NUM_COMPONENTS: usize = 20usize; + pub const NUM_COMPONENTS: usize = 19usize; } /// Indicator component for the [`AffixFuzzer4`] [`::re_types_core::Archetype`] @@ -520,11 +518,6 @@ impl ::re_types_core::AsComponents for AffixFuzzer4 { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl AffixFuzzer4 { diff --git a/crates/re_types_blueprint/src/blueprint/archetypes/container_blueprint.rs b/crates/re_types_blueprint/src/blueprint/archetypes/container_blueprint.rs index 92f5c99be9fc..087805a6b078 100644 --- a/crates/re_types_blueprint/src/blueprint/archetypes/container_blueprint.rs +++ b/crates/re_types_blueprint/src/blueprint/archetypes/container_blueprint.rs @@ -100,7 +100,7 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = || ["rerun.blueprint.components.ContainerBlueprintIndicator".into()], ); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.ActiveTab".into(), @@ -109,12 +109,11 @@ static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = "rerun.blueprint.components.IncludedContent".into(), "rerun.blueprint.components.RowShare".into(), "rerun.blueprint.components.Visible".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Name".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 10usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.ContainerKind".into(), @@ -125,13 +124,12 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 10usize]> = "rerun.blueprint.components.IncludedContent".into(), "rerun.blueprint.components.RowShare".into(), "rerun.blueprint.components.Visible".into(), - "rerun.components.InstanceKey".into(), "rerun.components.Name".into(), ] }); impl ContainerBlueprint { - pub const NUM_COMPONENTS: usize = 10usize; + pub const NUM_COMPONENTS: usize = 9usize; } /// Indicator component for the [`ContainerBlueprint`] [`::re_types_core::Archetype`] @@ -319,11 +317,6 @@ impl ::re_types_core::AsComponents for ContainerBlueprint { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl ContainerBlueprint { diff --git a/crates/re_types_blueprint/src/blueprint/archetypes/panel_blueprint.rs b/crates/re_types_blueprint/src/blueprint/archetypes/panel_blueprint.rs index 0de354498ec2..c992d6720620 100644 --- a/crates/re_types_blueprint/src/blueprint/archetypes/panel_blueprint.rs +++ b/crates/re_types_blueprint/src/blueprint/archetypes/panel_blueprint.rs @@ -47,25 +47,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.PanelBlueprintIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = - once_cell::sync::Lazy::new(|| { - [ - "rerun.blueprint.components.PanelExpanded".into(), - "rerun.components.InstanceKey".into(), - ] - }); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.PanelExpanded".into()]); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.PanelBlueprintIndicator".into(), "rerun.blueprint.components.PanelExpanded".into(), - "rerun.components.InstanceKey".into(), ] }); impl PanelBlueprint { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`PanelBlueprint`] [`::re_types_core::Archetype`] @@ -143,11 +137,6 @@ impl ::re_types_core::AsComponents for PanelBlueprint { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl PanelBlueprint { diff --git a/crates/re_types_blueprint/src/blueprint/archetypes/viewport_blueprint.rs b/crates/re_types_blueprint/src/blueprint/archetypes/viewport_blueprint.rs index db96ae055c1d..3cde4b26de05 100644 --- a/crates/re_types_blueprint/src/blueprint/archetypes/viewport_blueprint.rs +++ b/crates/re_types_blueprint/src/blueprint/archetypes/viewport_blueprint.rs @@ -80,7 +80,7 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.ViewportBlueprintIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.AutoLayout".into(), @@ -88,11 +88,10 @@ static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = "rerun.blueprint.components.RootContainer".into(), "rerun.blueprint.components.SpaceViewMaximized".into(), "rerun.blueprint.components.ViewerRecommendationHash".into(), - "rerun.components.InstanceKey".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.ViewportBlueprintIndicator".into(), @@ -101,12 +100,11 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = "rerun.blueprint.components.RootContainer".into(), "rerun.blueprint.components.SpaceViewMaximized".into(), "rerun.blueprint.components.ViewerRecommendationHash".into(), - "rerun.components.InstanceKey".into(), ] }); impl ViewportBlueprint { - pub const NUM_COMPONENTS: usize = 7usize; + pub const NUM_COMPONENTS: usize = 6usize; } /// Indicator component for the [`ViewportBlueprint`] [`::re_types_core::Archetype`] @@ -251,11 +249,6 @@ impl ::re_types_core::AsComponents for ViewportBlueprint { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 0 - } } impl ViewportBlueprint { diff --git a/crates/re_types_builder/src/codegen/cpp/mod.rs b/crates/re_types_builder/src/codegen/cpp/mod.rs index cb84df76d863..ae0046af1348 100644 --- a/crates/re_types_builder/src/codegen/cpp/mod.rs +++ b/crates/re_types_builder/src/codegen/cpp/mod.rs @@ -524,33 +524,6 @@ impl QuotedObject { }); } - // Num instances gives the number of primary instances. - { - let first_required_field = required_component_fields.first(); - let definition_body = if let Some(field) = first_required_field { - let first_required_field_name = &format_ident!("{}", field.name); - if field.typ.is_plural() { - quote!(return #first_required_field_name.size();) - } else { - quote!(return 1;) - } - } else { - quote!(return 0;) - }; - methods.push(Method { - docs: "Returns the number of primary instances of this archetype.".into(), - declaration: MethodDeclaration { - is_static: false, - return_type: quote!(size_t), - name_and_parameters: quote! { - num_instances() const - }, - }, - definition_body, - inline: true, - }); - } - let quoted_namespace = if let Some(scope) = obj.scope() { let scope = format_ident!("{}", scope); quote! { #scope::archetypes } diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index 5787d06b144e..202a0059f3e7 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -1066,23 +1066,6 @@ fn quote_trait_impls_from_obj( (num_components, quoted_components) } - let first_required_comp = obj.fields.iter().find(|field| { - field - .try_get_attr::(ATTR_RERUN_COMPONENT_REQUIRED) - .is_some() - }); - - let num_instances = if let Some(comp) = first_required_comp { - if comp.typ.is_plural() { - let name = format_ident!("{}", comp.name); - quote!(self.#name.len()) - } else { - quote!(1) - } - } else { - quote!(0) - }; - let indicator_name = format!("{}Indicator", obj.name); let indicator_fqname = format!("{}Indicator", obj.fqname).replace("archetypes", "components"); @@ -1095,14 +1078,8 @@ fn quote_trait_impls_from_obj( compute_components(obj, ATTR_RERUN_COMPONENT_REQUIRED, []); let (num_recommended, recommended) = compute_components(obj, ATTR_RERUN_COMPONENT_RECOMMENDED, [indicator_fqname]); - let (num_optional, optional) = compute_components( - obj, - ATTR_RERUN_COMPONENT_OPTIONAL, - // NOTE: Our internal query systems always need to query for instance keys, and - // they need to do so using a compile-time array, so make sure it's there at - // compile-time even for archetypes that don't use it. - ["rerun.components.InstanceKey".to_owned()], - ); + let (num_optional, optional) = + compute_components(obj, ATTR_RERUN_COMPONENT_OPTIONAL, []); let num_all = num_required + num_recommended + num_optional; @@ -1304,11 +1281,6 @@ fn quote_trait_impls_from_obj( [#(#all_component_batches,)*].into_iter().flatten().collect() } - - #[inline] - fn num_instances(&self) -> usize { - #num_instances - } } } } diff --git a/crates/re_types_core/src/archetype.rs b/crates/re_types_core/src/archetype.rs index f34db737595a..23c2337d9b0a 100644 --- a/crates/re_types_core/src/archetype.rs +++ b/crates/re_types_core/src/archetype.rs @@ -25,7 +25,7 @@ pub trait Archetype { /// /// ## Internal representation /// - /// Indicator components are always-splatted null arrays. + /// Indicator components are always unit-length null arrays. /// Their names follow the pattern `rerun.components.{ArchetypeName}Indicator`, e.g. /// `rerun.components.Points3DIndicator`. /// diff --git a/crates/re_types_core/src/archetypes/clear.rs b/crates/re_types_core/src/archetypes/clear.rs index 0b458b85a5fa..da15c9b1b67f 100644 --- a/crates/re_types_core/src/archetypes/clear.rs +++ b/crates/re_types_core/src/archetypes/clear.rs @@ -100,20 +100,19 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.ClearIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.InstanceKey".into()]); +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.ClearIsRecursive".into(), "rerun.components.ClearIndicator".into(), - "rerun.components.InstanceKey".into(), ] }); impl Clear { - pub const NUM_COMPONENTS: usize = 3usize; + pub const NUM_COMPONENTS: usize = 2usize; } /// Indicator component for the [`Clear`] [`crate::Archetype`] @@ -192,11 +191,6 @@ impl crate::AsComponents for Clear { .flatten() .collect() } - - #[inline] - fn num_instances(&self) -> usize { - 1 - } } impl Clear { diff --git a/crates/re_types_core/src/components/.gitattributes b/crates/re_types_core/src/components/.gitattributes index 5678ccfba2c7..38027d5f244a 100644 --- a/crates/re_types_core/src/components/.gitattributes +++ b/crates/re_types_core/src/components/.gitattributes @@ -2,6 +2,5 @@ .gitattributes linguist-generated=true clear_is_recursive.rs linguist-generated=true -instance_key.rs linguist-generated=true mod.rs linguist-generated=true visualizer_overrides.rs linguist-generated=true diff --git a/crates/re_types_core/src/components/instance_key.rs b/crates/re_types_core/src/components/instance_key.rs deleted file mode 100644 index f5708164d78f..000000000000 --- a/crates/re_types_core/src/components/instance_key.rs +++ /dev/null @@ -1,174 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/components/instance_key.fbs". - -#![allow(trivial_numeric_casts)] -#![allow(unused_imports)] -#![allow(unused_parens)] -#![allow(clippy::clone_on_copy)] -#![allow(clippy::cloned_instead_of_copied)] -#![allow(clippy::iter_on_single_items)] -#![allow(clippy::map_flatten)] -#![allow(clippy::match_wildcard_for_single_variants)] -#![allow(clippy::needless_question_mark)] -#![allow(clippy::new_without_default)] -#![allow(clippy::redundant_closure)] -#![allow(clippy::too_many_arguments)] -#![allow(clippy::too_many_lines)] -#![allow(clippy::unnecessary_cast)] - -use crate::external::arrow2; -use crate::ComponentName; -use crate::SerializationResult; -use crate::{ComponentBatch, MaybeOwnedComponentBatch}; -use crate::{DeserializationError, DeserializationResult}; - -/// **Component**: A unique numeric identifier for each individual instance within a batch. -/// -/// Instance keys are automatically assigned by the `rerun` library and should not be set manually. -/// -/// The instance key is just the index of the instance within the batch, -/// i.e. the first point in a point cloud has `InstanceKey = 0`, the second `InstanceKey = 1`, and so on. -/// -/// We plan to remove the `InstanceKey` component in the near future. -#[derive( - Clone, Debug, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, ::bytemuck::Pod, ::bytemuck::Zeroable, -)] -#[repr(transparent)] -#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] -pub struct InstanceKey(pub u64); - -impl crate::SizeBytes for InstanceKey { - #[inline] - fn heap_size_bytes(&self) -> u64 { - self.0.heap_size_bytes() - } - - #[inline] - fn is_pod() -> bool { - ::is_pod() - } -} - -impl From for InstanceKey { - #[inline] - fn from(value: u64) -> Self { - Self(value) - } -} - -impl From for u64 { - #[inline] - fn from(value: InstanceKey) -> Self { - value.0 - } -} - -crate::macros::impl_into_cow!(InstanceKey); - -impl crate::Loggable for InstanceKey { - type Name = crate::ComponentName; - - #[inline] - fn name() -> Self::Name { - "rerun.components.InstanceKey".into() - } - - #[allow(clippy::wildcard_imports)] - #[inline] - fn arrow_datatype() -> arrow2::datatypes::DataType { - use arrow2::datatypes::*; - DataType::UInt64 - } - - #[allow(clippy::wildcard_imports)] - fn to_arrow_opt<'a>( - data: impl IntoIterator>>>, - ) -> SerializationResult> - where - Self: Clone + 'a, - { - use crate::{Loggable as _, ResultExt as _}; - use arrow2::{array::*, datatypes::*}; - Ok({ - let (somes, data0): (Vec<_>, Vec<_>) = data - .into_iter() - .map(|datum| { - let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); - let datum = datum.map(|datum| { - let Self(data0) = datum.into_owned(); - data0 - }); - (datum.is_some(), datum) - }) - .unzip(); - let data0_bitmap: Option = { - let any_nones = somes.iter().any(|some| !*some); - any_nones.then(|| somes.into()) - }; - PrimitiveArray::new( - Self::arrow_datatype(), - data0.into_iter().map(|v| v.unwrap_or_default()).collect(), - data0_bitmap, - ) - .boxed() - }) - } - - #[allow(clippy::wildcard_imports)] - fn from_arrow_opt( - arrow_data: &dyn arrow2::array::Array, - ) -> DeserializationResult>> - where - Self: Sized, - { - use crate::{Loggable as _, ResultExt as _}; - use arrow2::{array::*, buffer::*, datatypes::*}; - Ok(arrow_data - .as_any() - .downcast_ref::() - .ok_or_else(|| { - let expected = Self::arrow_datatype(); - let actual = arrow_data.data_type().clone(); - DeserializationError::datatype_mismatch(expected, actual) - }) - .with_context("rerun.components.InstanceKey#value")? - .into_iter() - .map(|opt| opt.copied()) - .map(|v| v.ok_or_else(DeserializationError::missing_data)) - .map(|res| res.map(|v| Some(Self(v)))) - .collect::>>>() - .with_context("rerun.components.InstanceKey#value") - .with_context("rerun.components.InstanceKey")?) - } - - #[allow(clippy::wildcard_imports)] - #[inline] - fn from_arrow(arrow_data: &dyn arrow2::array::Array) -> DeserializationResult> - where - Self: Sized, - { - use crate::{Loggable as _, ResultExt as _}; - use arrow2::{array::*, buffer::*, datatypes::*}; - if let Some(validity) = arrow_data.validity() { - if validity.unset_bits() != 0 { - return Err(DeserializationError::missing_data()); - } - } - Ok({ - let slice = arrow_data - .as_any() - .downcast_ref::() - .ok_or_else(|| { - let expected = DataType::UInt64; - let actual = arrow_data.data_type().clone(); - DeserializationError::datatype_mismatch(expected, actual) - }) - .with_context("rerun.components.InstanceKey#value")? - .values() - .as_slice(); - { - slice.iter().copied().map(|v| Self(v)).collect::>() - } - }) - } -} diff --git a/crates/re_types_core/src/components/instance_key_ext.rs b/crates/re_types_core/src/components/instance_key_ext.rs deleted file mode 100644 index 1907dcbf0e66..000000000000 --- a/crates/re_types_core/src/components/instance_key_ext.rs +++ /dev/null @@ -1,60 +0,0 @@ -use super::InstanceKey; - -// TODO(cmc): come up with some DSL in our flatbuffers definitions so that we can declare these -// constants directly in there. -impl InstanceKey { - /// Draw order used for images if no draw order was specified. - pub const SPLAT: Self = Self(u64::MAX); -} - -impl InstanceKey { - #[allow(clippy::should_implement_trait)] - #[inline] - pub fn from_iter(it: impl IntoIterator>) -> Vec { - it.into_iter().map(Into::into).collect::>() - } - - /// Are we referring to all instances of the entity (e.g. all points in a point cloud entity)? - /// - /// The opposite of [`Self::is_specific`]. - #[inline] - pub fn is_splat(self) -> bool { - self == Self::SPLAT - } - - /// Are we referring to a specific instance of the entity (e.g. a specific point in a point cloud)? - /// - /// The opposite of [`Self::is_splat`]. - #[inline] - pub fn is_specific(self) -> bool { - self != Self::SPLAT - } - - /// Returns `None` if splat, otherwise the index. - #[inline] - pub fn specific_index(self) -> Option { - self.is_specific().then_some(self) - } - - /// Creates a new [`InstanceKey`] that identifies a 2D coordinate. - pub fn from_2d_image_coordinate([x, y]: [u32; 2], image_width: u64) -> Self { - Self((x as u64) + (y as u64) * image_width) - } - - /// Retrieves 2D image coordinates (x, y) encoded in an instance key - pub fn to_2d_image_coordinate(self, image_width: u64) -> [u32; 2] { - [(self.0 % image_width) as u32, (self.0 / image_width) as u32] - } -} - -impl std::fmt::Display for InstanceKey { - #[inline] - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.is_splat() { - "splat".fmt(f) - } else { - // TODO(emilk): re_format::uint(self.0).fmt(f) (fix cyclic dependency!) - self.0.fmt(f) - } - } -} diff --git a/crates/re_types_core/src/components/mod.rs b/crates/re_types_core/src/components/mod.rs index 3e824dac4f39..d8289127f0c3 100644 --- a/crates/re_types_core/src/components/mod.rs +++ b/crates/re_types_core/src/components/mod.rs @@ -1,10 +1,7 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs mod clear_is_recursive; -mod instance_key; -mod instance_key_ext; mod visualizer_overrides; pub use self::clear_is_recursive::ClearIsRecursive; -pub use self::instance_key::InstanceKey; pub use self::visualizer_overrides::VisualizerOverrides; diff --git a/crates/re_types_core/src/lib.rs b/crates/re_types_core/src/lib.rs index e50b6ef053fe..657d3eaa5cd7 100644 --- a/crates/re_types_core/src/lib.rs +++ b/crates/re_types_core/src/lib.rs @@ -45,19 +45,6 @@ pub trait AsComponents { // depending on their presence (or lack thereof) at runtime anyway. fn as_component_batches(&self) -> Vec>; - /// The number of instances in each batch. - /// - /// If not implemented, the number of instances will be determined by the longest - /// batch in the bundle. - #[inline] - fn num_instances(&self) -> usize { - self.as_component_batches() - .into_iter() - .map(|comp_batch| comp_batch.as_ref().num_instances()) - .max() - .unwrap_or(0) - } - // --- /// Serializes all non-null [`Component`]s of this bundle into Arrow arrays. diff --git a/crates/re_ui/src/syntax_highlighting.rs b/crates/re_ui/src/syntax_highlighting.rs index 3e399234002c..f2b97d0cd266 100644 --- a/crates/re_ui/src/syntax_highlighting.rs +++ b/crates/re_ui/src/syntax_highlighting.rs @@ -1,5 +1,5 @@ use re_entity_db::InstancePath; -use re_log_types::{external::re_types_core::components::InstanceKey, EntityPath, EntityPathPart}; +use re_log_types::{EntityPath, EntityPathPart, Instance}; use egui::{text::LayoutJob, Color32, Style, TextFormat}; @@ -39,12 +39,12 @@ impl SyntaxHighlighting for EntityPathPart { } } -impl SyntaxHighlighting for InstanceKey { +impl SyntaxHighlighting for Instance { fn syntax_highlight_into(&self, style: &Style, job: &mut LayoutJob) { - if self.is_splat() { - job.append("splat", 0.0, text_format(style)); + if self.is_all() { + job.append("all", 0.0, text_format(style)); } else { - job.append(&re_format::format_uint(self.0), 0.0, text_format(style)); + job.append(&re_format::format_uint(self.get()), 0.0, text_format(style)); } } } @@ -65,9 +65,9 @@ impl SyntaxHighlighting for EntityPath { impl SyntaxHighlighting for InstancePath { fn syntax_highlight_into(&self, style: &Style, job: &mut LayoutJob) { self.entity_path.syntax_highlight_into(style, job); - if !self.instance_key.is_splat() { + if !self.instance.is_all() { job.append("[", 0.0, faint_text_format(style)); - self.instance_key.syntax_highlight_into(style, job); + self.instance.syntax_highlight_into(style, job); job.append("]", 0.0, faint_text_format(style)); } } diff --git a/crates/re_viewer/src/app_blueprint.rs b/crates/re_viewer/src/app_blueprint.rs index 987935a1640b..2b8fbc75cf18 100644 --- a/crates/re_viewer/src/app_blueprint.rs +++ b/crates/re_viewer/src/app_blueprint.rs @@ -93,8 +93,8 @@ pub fn setup_welcome_screen_blueprint(welcome_screen_blueprint: &mut EntityDb) { let component = PanelExpanded(is_expanded.into()); - let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, [component]) - .unwrap(); // Can only fail if we have the wrong number of instances for the component, and we don't + let row = + DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, [component]).unwrap(); // Can only fail if we have the wrong number of instances for the component, and we don't welcome_screen_blueprint.add_data_row(row).unwrap(); // Can only fail if we have the wrong number of instances for the component, and we don't } @@ -116,9 +116,8 @@ impl<'a> AppBlueprint<'a> { let component = PanelExpanded(is_expanded.into()); - let row = - DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, 1, [component]) - .unwrap(); // Can only fail if we have the wrong number of instances for the component, and we don't + let row = DataRow::from_cells1_sized(RowId::new(), entity_path, timepoint, [component]) + .unwrap(); // Can only fail if we have the wrong number of instances for the component, and we don't command_sender.send_system(SystemCommand::UpdateBlueprint( store_ctx.blueprint.store_id().clone(), diff --git a/crates/re_viewer/src/ui/memory_panel.rs b/crates/re_viewer/src/ui/memory_panel.rs index e7a434e77cb0..9b896e97a98a 100644 --- a/crates/re_viewer/src/ui/memory_panel.rs +++ b/crates/re_viewer/src/ui/memory_panel.rs @@ -249,7 +249,6 @@ impl MemoryPanel { let DataStoreStats { type_registry, metadata_registry, - autogenerated, static_tables, temporal, temporal_buckets, @@ -282,11 +281,6 @@ impl MemoryPanel { label_row_stats(ui, metadata_registry); ui.end_row(); - ui.label("Cluster cache:"); - ui.label(""); - label_row_stats(ui, autogenerated); - ui.end_row(); - ui.label("Static:"); ui.label(""); label_row_stats(ui, static_tables); diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index 6ff2c4b7b794..8766fa7289e5 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -5,12 +5,9 @@ use itertools::Itertools; use re_data_store::LatestAtQuery; use re_data_ui::is_component_visible_in_ui; use re_entity_db::{EntityDb, InstancePath}; -use re_log_types::{DataCell, DataRow, RowId, StoreKind}; +use re_log_types::{DataRow, RowId, StoreKind}; use re_space_view::{determine_visualizable_entities, SpaceViewBlueprint}; -use re_types_core::{ - components::{InstanceKey, VisualizerOverrides}, - ComponentName, -}; +use re_types_core::{components::VisualizerOverrides, ComponentName}; use re_viewer_context::{ DataResult, OverridePath, SystemCommand, SystemCommandSender as _, UiVerbosity, ViewSystemIdentifier, ViewerContext, @@ -24,7 +21,7 @@ pub fn override_ui( ) { let InstancePath { entity_path, - instance_key, + instance, } = instance_path; // Because of how overrides are implemented the overridden-data must be an entity @@ -173,7 +170,7 @@ pub fn override_ui( path, &overrides.individual_override_path, &results, - instance_key, + instance, ); } else { // TODO(jleibs): Is it possible to set an override to empty and not confuse @@ -239,20 +236,10 @@ pub fn add_new_override( let components = [*component]; - let mut splat_cell: DataCell = [InstanceKey::SPLAT].into(); - splat_cell.compute_size_bytes(); - let Some(mut initial_data) = db .store() .latest_at(query, &data_result.entity_path, *component, &components) .and_then(|result| result.2[0].clone()) - .and_then(|cell| { - if cell.num_instances() == 1 { - Some(cell) - } else { - None - } - }) .or_else(|| { view_systems.get_by_identifier(*viz).ok().and_then(|sys| { sys.initial_override_value( @@ -284,8 +271,7 @@ pub fn add_new_override( RowId::new(), ctx.store_context.blueprint_timepoint_for_writes(), override_path.clone(), - 1, - [splat_cell, initial_data], + [initial_data], ) { Ok(row) => { ctx.command_sender @@ -325,7 +311,7 @@ pub fn override_visualizer_ui( ui.push_id("visualizer_overrides", |ui| { let InstancePath { entity_path, - instance_key: _, + instance: _, } = instance_path; let recording = ctx.recording(); diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index b6599c58e66b..0e0e1622c550 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -430,7 +430,7 @@ fn what_is_selected_ui( &format!("{typ} '{instance_path}'"), ); - let is_instance = !instance_path.instance_key.is_splat(); + let is_instance = !instance_path.instance.is_all(); let parent = if is_instance { Some(instance_path.entity_path.clone()) } else { @@ -466,7 +466,7 @@ fn what_is_selected_ui( ), ); - let is_instance = !instance_path.instance_key.is_splat(); + let is_instance = !instance_path.instance.is_all(); let parent = if is_instance { Some(instance_path.entity_path.clone()) } else { @@ -948,8 +948,8 @@ fn blueprint_ui_for_data_result( instance_path: &InstancePath, ) { if let Some(space_view) = viewport.blueprint.space_view(&space_view_id) { - if instance_path.instance_key.is_splat() { - // splat - the whole entity + if instance_path.instance.is_all() { + // the whole entity let space_view_class = *space_view.class_identifier(); let entity_path = &instance_path.entity_path; diff --git a/crates/re_viewer_context/src/blueprint_helpers.rs b/crates/re_viewer_context/src/blueprint_helpers.rs index 1e77506d20aa..a07e5cc6f140 100644 --- a/crates/re_viewer_context/src/blueprint_helpers.rs +++ b/crates/re_viewer_context/src/blueprint_helpers.rs @@ -1,5 +1,5 @@ use re_log_types::{DataCell, DataRow, EntityPath, RowId, TimeInt, TimePoint, Timeline}; -use re_types::{components::InstanceKey, AsComponents, ComponentBatch, ComponentName}; +use re_types::{AsComponents, ComponentBatch, ComponentName}; use crate::{StoreContext, SystemCommand, SystemCommandSender as _, ViewerContext}; @@ -78,26 +78,12 @@ impl ViewerContext<'_> { entity_path ); - let data_row_result = if num_instances == 1 { - let mut splat_cell: DataCell = [InstanceKey::SPLAT].into(); - splat_cell.compute_size_bytes(); - - DataRow::from_cells( - RowId::new(), - timepoint.clone(), - entity_path.clone(), - num_instances, - [splat_cell, data_cell], - ) - } else { - DataRow::from_cells( - RowId::new(), - timepoint.clone(), - entity_path.clone(), - num_instances, - [data_cell], - ) - }; + let data_row_result = DataRow::from_cells( + RowId::new(), + timepoint.clone(), + entity_path.clone(), + [data_cell], + ); match data_row_result { Ok(row) => self @@ -139,13 +125,7 @@ impl ViewerContext<'_> { let timepoint = self.store_context.blueprint_timepoint_for_writes(); let cell = DataCell::from_arrow_empty(component_name, datatype.clone()); - match DataRow::from_cells1( - RowId::new(), - entity_path.clone(), - timepoint.clone(), - cell.num_instances(), - cell, - ) { + match DataRow::from_cells1(RowId::new(), entity_path.clone(), timepoint.clone(), cell) { Ok(row) => self .command_sender .send_system(SystemCommand::UpdateBlueprint( diff --git a/crates/re_viewer_context/src/component_ui_registry.rs b/crates/re_viewer_context/src/component_ui_registry.rs index 756870c051ea..76f1cf4cdde1 100644 --- a/crates/re_viewer_context/src/component_ui_registry.rs +++ b/crates/re_viewer_context/src/component_ui_registry.rs @@ -2,8 +2,8 @@ use std::collections::BTreeMap; use re_data_store::LatestAtQuery; use re_entity_db::{external::re_query::LatestAtComponentResults, EntityDb, EntityPath}; -use re_log_types::DataCell; -use re_types::{components::InstanceKey, ComponentName, Loggable as _}; +use re_log_types::{DataCell, Instance}; +use re_types::ComponentName; use crate::ViewerContext; @@ -41,7 +41,7 @@ type ComponentUiCallback = Box< &EntityDb, &EntityPath, &LatestAtComponentResults, - &InstanceKey, + &Instance, ) + Send + Sync, >; @@ -56,7 +56,7 @@ type ComponentEditCallback = Box< &EntityPath, &EntityPath, &LatestAtComponentResults, - &InstanceKey, + &Instance, ) + Send + Sync, >; @@ -121,7 +121,7 @@ impl ComponentUiRegistry { db: &EntityDb, entity_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &InstanceKey, + instance: &Instance, ) { let Some(component_name) = component.component_name(db.resolver()) else { // TODO(#5607): what should happen if the promise is still pending? @@ -130,12 +130,6 @@ impl ComponentUiRegistry { re_tracing::profile_function!(component_name.full_name()); - if component_name == InstanceKey::name() { - // The user wants to show a ui for the `InstanceKey` component - well, that's easy: - ui.label(instance_key.to_string()); - return; - } - let ui_callback = self .component_uis .get(&component_name) @@ -148,7 +142,7 @@ impl ComponentUiRegistry { db, entity_path, component, - instance_key, + instance, ); } @@ -164,7 +158,7 @@ impl ComponentUiRegistry { entity_path: &EntityPath, override_path: &EntityPath, component: &LatestAtComponentResults, - instance_key: &InstanceKey, + instance: &Instance, ) { let Some(component_name) = component.component_name(db.resolver()) else { // TODO(#5607): what should happen if the promise is still pending? @@ -183,7 +177,7 @@ impl ComponentUiRegistry { entity_path, override_path, component, - instance_key, + instance, ); } else { // Even if we can't edit the component, it's still helpful to show what the value is. @@ -195,7 +189,7 @@ impl ComponentUiRegistry { db, entity_path, component, - instance_key, + instance, ); } } diff --git a/crates/re_viewer_context/src/item.rs b/crates/re_viewer_context/src/item.rs index 3fbdee8ca299..613774d71785 100644 --- a/crates/re_viewer_context/src/item.rs +++ b/crates/re_viewer_context/src/item.rs @@ -78,26 +78,24 @@ impl std::str::FromStr for Item { fn from_str(s: &str) -> Result { let DataPath { entity_path, - instance_key, + instance, component_name, } = DataPath::from_str(s)?; - match (instance_key, component_name) { - (Some(instance_key), Some(_component_name)) => { + match (instance, component_name) { + (Some(instance), Some(_component_name)) => { // TODO(emilk): support selecting a specific component of a specific instance. - Err(re_log_types::PathParseError::UnexpectedInstanceKey( - instance_key, - )) + Err(re_log_types::PathParseError::UnexpectedInstance(instance)) } - (Some(instance_key), None) => Ok(Item::InstancePath(InstancePath::instance( + (Some(instance), None) => Ok(Item::InstancePath(InstancePath::instance( entity_path, - instance_key, + instance, ))), (None, Some(component_name)) => Ok(Item::ComponentPath(ComponentPath { entity_path, component_name, })), - (None, None) => Ok(Item::InstancePath(InstancePath::entity_splat(entity_path))), + (None, None) => Ok(Item::InstancePath(InstancePath::entity_all(entity_path))), } } } @@ -129,7 +127,7 @@ impl Item { re_log_types::StoreKind::Blueprint => "Blueprint ID", }, Item::InstancePath(instance_path) => { - if instance_path.instance_key.is_specific() { + if instance_path.instance.is_specific() { "Entity instance" } else { "Entity" @@ -139,7 +137,7 @@ impl Item { Item::SpaceView(_) => "Space view", Item::Container(_) => "Container", Item::DataResult(_, instance_path) => { - if instance_path.instance_key.is_specific() { + if instance_path.instance.is_specific() { "Data result instance" } else { "Data result entity" @@ -149,7 +147,7 @@ impl Item { } } -/// If the given item refers to the first element of an instance with a single element, resolve to a splatted entity path. +/// If the given item refers to the first element of an instance with a single element, resolve to a unindexed entity path. pub fn resolve_mono_instance_path_item( entity_db: &EntityDb, query: &re_data_store::LatestAtQuery, @@ -173,7 +171,7 @@ pub fn resolve_mono_instance_path_item( } } -/// If the given path refers to the first element of an instance with a single element, resolve to a splatted entity path. +/// If the given path refers to the first element of an instance with a single element, resolve to a unindexed entity path. pub fn resolve_mono_instance_path( entity_db: &EntityDb, query: &re_data_store::LatestAtQuery, @@ -181,14 +179,14 @@ pub fn resolve_mono_instance_path( ) -> re_entity_db::InstancePath { re_tracing::profile_function!(); - if instance.instance_key.0 == 0 { + if instance.instance.get() == 0 { // NOTE: While we normally frown upon direct queries to the datastore, `all_components` is fine. let Some(components) = entity_db .store() .all_components(&query.timeline(), &instance.entity_path) else { - // No components at all, return splatted entity. - return re_entity_db::InstancePath::entity_splat(instance.entity_path.clone()); + // No components at all, return unindexed entity. + return re_entity_db::InstancePath::entity_all(instance.entity_path.clone()); }; for component in components { @@ -208,8 +206,8 @@ pub fn resolve_mono_instance_path( } } - // All instances had only a single element or less, resolve to splatted entity. - return re_entity_db::InstancePath::entity_splat(instance.entity_path.clone()); + // All instances had only a single element or less, resolve to unindexed entity. + return re_entity_db::InstancePath::entity_all(instance.entity_path.clone()); } instance.clone() diff --git a/crates/re_viewer_context/src/selection_state.rs b/crates/re_viewer_context/src/selection_state.rs index 54ab55c2c337..41d0341e6c23 100644 --- a/crates/re_viewer_context/src/selection_state.rs +++ b/crates/re_viewer_context/src/selection_state.rs @@ -106,7 +106,7 @@ where impl ItemCollection { /// For each item in this selection, if it refers to the first element of an instance with a - /// single element, resolve it to a splatted entity path. + /// single element, resolve it to a unindexed entity path. pub fn into_mono_instance_path_items(self, ctx: &ViewerContext<'_>) -> Self { ItemCollection( self.0 @@ -376,7 +376,7 @@ impl ApplicationSelectionState { } Item::InstancePath(test_instance_path) => { - !test_instance_path.instance_key.is_specific() + !test_instance_path.instance.is_specific() && test_instance_path.entity_path == component_path.entity_path } Item::DataResult(_, test_instance_path) => { @@ -396,8 +396,8 @@ impl ApplicationSelectionState { | Item::DataResult(_, test_instance_path) => { current_instance_path.entity_path == test_instance_path.entity_path && either_none_or_same( - ¤t_instance_path.instance_key.specific_index(), - &test_instance_path.instance_key.specific_index(), + ¤t_instance_path.instance.specific_index(), + &test_instance_path.instance.specific_index(), ) } }, @@ -414,8 +414,8 @@ impl ApplicationSelectionState { | Item::DataResult(_, test_instance_path) => { current_instance_path.entity_path == test_instance_path.entity_path && either_none_or_same( - ¤t_instance_path.instance_key.specific_index(), - &test_instance_path.instance_key.specific_index(), + ¤t_instance_path.instance.specific_index(), + &test_instance_path.instance.specific_index(), ) } }, diff --git a/crates/re_viewer_context/src/space_view/highlights.rs b/crates/re_viewer_context/src/space_view/highlights.rs index 72fbb7afad95..0de5e24c9dd4 100644 --- a/crates/re_viewer_context/src/space_view/highlights.rs +++ b/crates/re_viewer_context/src/space_view/highlights.rs @@ -1,9 +1,8 @@ use nohash_hasher::IntMap; use re_entity_db::InstancePath; -use re_log_types::EntityPathHash; +use re_log_types::{EntityPathHash, Instance}; use re_renderer::OutlineMaskPreference; -use re_types::components::InstanceKey; use crate::{HoverHighlight, InteractionHighlight, SelectionHighlight}; @@ -13,15 +12,14 @@ use crate::{HoverHighlight, InteractionHighlight, SelectionHighlight}; #[derive(Default)] pub struct SpaceViewEntityHighlight { overall: InteractionHighlight, - instances: ahash::HashMap, + instances: ahash::HashMap, } impl SpaceViewEntityHighlight { /// Adds a new highlight to the entity highlight, combining it with existing highlights. #[inline] pub fn add(&mut self, instance: &InstancePath, highlight: InteractionHighlight) { - let highlight_target = if let Some(selected_index) = instance.instance_key.specific_index() - { + let highlight_target = if let Some(selected_index) = instance.instance.specific_index() { self.instances.entry(selected_index).or_default() } else { &mut self.overall @@ -59,11 +57,11 @@ pub struct OptionalSpaceViewEntityHighlight<'a>(Option<&'a SpaceViewEntityHighli impl<'a> OptionalSpaceViewEntityHighlight<'a> { #[inline] - pub fn index_highlight(&self, instance_key: InstanceKey) -> InteractionHighlight { + pub fn index_highlight(&self, instance: Instance) -> InteractionHighlight { match self.0 { Some(entity_highlight) => entity_highlight .instances - .get(&instance_key) + .get(&instance) .copied() .unwrap_or_default() .max(entity_highlight.overall), @@ -75,13 +73,13 @@ impl<'a> OptionalSpaceViewEntityHighlight<'a> { #[derive(Default)] pub struct SpaceViewOutlineMasks { pub overall: OutlineMaskPreference, - pub instances: ahash::HashMap, + pub instances: ahash::HashMap, } impl SpaceViewOutlineMasks { - pub fn index_outline_mask(&self, instance_key: InstanceKey) -> OutlineMaskPreference { + pub fn index_outline_mask(&self, instance: Instance) -> OutlineMaskPreference { self.instances - .get(&instance_key) + .get(&instance) .copied() .unwrap_or_default() .with_fallback_to(self.overall) @@ -89,12 +87,11 @@ impl SpaceViewOutlineMasks { /// Add a new outline mask to this entity path, combining it with existing masks. pub fn add(&mut self, instance: &InstancePath, preference: OutlineMaskPreference) { - let outline_mask_target = - if let Some(selected_index) = instance.instance_key.specific_index() { - self.instances.entry(selected_index).or_default() - } else { - &mut self.overall - }; + let outline_mask_target = if let Some(selected_index) = instance.instance.specific_index() { + self.instances.entry(selected_index).or_default() + } else { + &mut self.overall + }; *outline_mask_target = preference.with_fallback_to(*outline_mask_target); } } diff --git a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs index 1baa7b91f892..43f7cfe39f11 100644 --- a/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs +++ b/crates/re_viewport/src/context_menu/actions/collapse_expand_all.rs @@ -69,7 +69,7 @@ impl ContextMenuAction for CollapseExpandAllAction { self.process_data_result( ctx, space_view_id, - &InstancePath::entity_splat(root_node.data_result.entity_path.clone()), + &InstancePath::entity_all(root_node.data_result.entity_path.clone()), ); } } diff --git a/crates/re_viewport/src/context_menu/actions/remove.rs b/crates/re_viewport/src/context_menu/actions/remove.rs index 838abe636990..fc64df2e0d46 100644 --- a/crates/re_viewport/src/context_menu/actions/remove.rs +++ b/crates/re_viewport/src/context_menu/actions/remove.rs @@ -17,7 +17,7 @@ impl ContextMenuAction for RemoveAction { Item::Container(container_id) => { ctx.viewport_blueprint.root_container != Some(*container_id) } - Item::DataResult(_, instance_path) => instance_path.is_splat(), + Item::DataResult(_, instance_path) => instance_path.is_all(), _ => false, } } diff --git a/crates/re_viewport/src/context_menu/actions/show_hide.rs b/crates/re_viewport/src/context_menu/actions/show_hide.rs index 88de08180776..81900d6ead12 100644 --- a/crates/re_viewport/src/context_menu/actions/show_hide.rs +++ b/crates/re_viewport/src/context_menu/actions/show_hide.rs @@ -118,7 +118,7 @@ fn data_result_visible( instance_path: &InstancePath, ) -> Option { instance_path - .is_splat() + .is_all() .then(|| { let query_result = ctx.viewer_context.lookup_query_result(*space_view_id); query_result diff --git a/crates/re_viewport/src/space_view_entity_picker.rs b/crates/re_viewport/src/space_view_entity_picker.rs index 23c268f67d63..fa63f2e8398a 100644 --- a/crates/re_viewport/src/space_view_entity_picker.rs +++ b/crates/re_viewport/src/space_view_entity_picker.rs @@ -179,7 +179,7 @@ fn add_entities_line_ui( ctx.recording(), ui, Some(space_view.id), - &InstancePath::entity_splat(entity_path.clone()), + &InstancePath::entity_all(entity_path.clone()), widget_text, ); if query_result.contains_entity(entity_path) { diff --git a/crates/re_viewport/src/viewport_blueprint_ui.rs b/crates/re_viewport/src/viewport_blueprint_ui.rs index 602d91c32e0a..3f4043c2434e 100644 --- a/crates/re_viewport/src/viewport_blueprint_ui.rs +++ b/crates/re_viewport/src/viewport_blueprint_ui.rs @@ -140,9 +140,7 @@ impl Viewport<'_, '_> { Item::ComponentPath(component_path) => self.handle_focused_item( ctx, ui, - &Item::InstancePath(InstancePath::entity_splat( - component_path.entity_path.clone(), - )), + &Item::InstancePath(InstancePath::entity_all(component_path.entity_path.clone())), ), } } @@ -539,7 +537,7 @@ impl Viewport<'_, '_> { { ctx.selection_state().set_selection(Item::DataResult( space_view.id, - InstancePath::entity_splat(entity_path.clone()), + InstancePath::entity_all(entity_path.clone()), )); } return; diff --git a/crates/rerun/src/sdk.rs b/crates/rerun/src/sdk.rs index e9fdcb9d85da..a1a299f3e486 100644 --- a/crates/rerun/src/sdk.rs +++ b/crates/rerun/src/sdk.rs @@ -23,9 +23,9 @@ mod prelude { // Also import any component or datatype that has a unique name: pub use re_types::components::{ - Color, HalfSizes2D, HalfSizes3D, InstanceKey, LineStrip2D, LineStrip3D, Material, - MediaType, MeshProperties, OutOfTreeTransform3D, Position2D, Position3D, Radius, Text, - TextLogLevel, Vector2D, Vector3D, + Color, HalfSizes2D, HalfSizes3D, LineStrip2D, LineStrip3D, Material, MediaType, + MeshProperties, OutOfTreeTransform3D, Position2D, Position3D, Radius, Text, TextLogLevel, + Vector2D, Vector3D, }; pub use re_types::datatypes::{ Angle, AnnotationInfo, ClassDescription, Float32, KeypointPair, Mat3x3, Quaternion, Rgba32, diff --git a/crates/rerun_c/src/lib.rs b/crates/rerun_c/src/lib.rs index 75844824e1c3..410d7b21cd1e 100644 --- a/crates/rerun_c/src/lib.rs +++ b/crates/rerun_c/src/lib.rs @@ -166,7 +166,6 @@ pub struct CDataCell { #[repr(C)] pub struct CDataRow { pub entity_path: CStringView, - pub num_instances: u32, pub num_data_cells: u32, pub data_cells: *mut CDataCell, } @@ -631,7 +630,6 @@ fn rr_log_impl( let CDataRow { entity_path, - num_instances, num_data_cells, data_cells, } = data_row; @@ -640,9 +638,7 @@ fn rr_log_impl( let entity_path = EntityPath::parse_forgiving(entity_path); let num_data_cells = num_data_cells as usize; - re_log::debug!( - "rerun_log {entity_path:?}, num_instances: {num_instances}, num_data_cells: {num_data_cells}", - ); + re_log::debug!("rerun_log {entity_path:?}, num_data_cells: {num_data_cells}"); let mut cells = re_log_types::DataCellVec::default(); cells.reserve(num_data_cells); @@ -700,7 +696,6 @@ fn rr_log_impl( row_id, TimePoint::default(), // we use the one in the recording stream for now entity_path, - num_instances, cells, ) .map_err(|err| { diff --git a/crates/rerun_c/src/rerun.h b/crates/rerun_c/src/rerun.h index 3e12fca8543e..2fa9e2f92bcf 100644 --- a/crates/rerun_c/src/rerun.h +++ b/crates/rerun_c/src/rerun.h @@ -202,10 +202,6 @@ typedef struct { /// Where to log to, e.g. `world/camera`. rr_string entity_path; - /// Number of instances of this entity (e.g. number of points in a point - /// cloud). - uint32_t num_instances; - /// Number of components. uint32_t num_data_cells; diff --git a/docs/content/concepts/batches.md b/docs/content/concepts/batches.md index 93bb06d05314..8348c8a3563c 100644 --- a/docs/content/concepts/batches.md +++ b/docs/content/concepts/batches.md @@ -15,9 +15,9 @@ In the Python APIs, the majority of archetypes are named with the plural form, f ## Terminology - An *entity* is a collection of *components* (see [Entities and Components](entity-component.md)). -- When an entity is batched, it's components individual elements are called *instances*. -- When every instance within an entity has the same value for a component, that component is called a *splat*. This - is a common pattern and has dedicated support for it (see the [Splats](#splats) section below). +- When an entity is batched, its components' individual elements are called *instances*. +- When every instance within an entity shares the same value for a component, we say that this component is clamped. This + is a common pattern and has dedicated support for it (see the [Component Clamping](#component-clamping) section below). For instance, you can set all the colors of a point cloud to the same color by passing a single color value to the `color` parameter. - During queries, a batch always has a *primary* component. The primary component is what determines @@ -50,14 +50,11 @@ When querying a batched component, the component-values are joined together base Logically, this happens as a *left-join* using the primary component for the entity. For example, if you log 3 points and then later log 5 colors, you will still only see 3 points in the viewer. +What should happen if you have 5 points and 3 colors then? This is where clamping semantics come into play. -## Splats - -As mentioned, Rerun has special handling for splats within batches. This is what happens when you mix arrays and -single values in an API call. The non-array value is instead logged as a splat. Behind the scenes, the splat is stored -as a single value rather than a full array. Then, when doing the join at lookup time the splat is repeated across -every instance in the batch. - - +## Component clamping +As mentioned, Rerun has special semantics when joining batches of different sizes, for example this is what happens when you mix arrays and single values in an API call. +If the component on the left-side of the join (the so-called primary component) has more instances than the other, then these tail values will simply be ignored. +On the other hand, if the component on the left-side of the join (the so-called primary component) has less instances than the other, then the last instance will be repeated across every instance left in the batch. We call this clamping, in reference to texture sampling (think `CLAMP_TO_EDGE`!). diff --git a/docs/content/getting-started/data-in/cpp.md b/docs/content/getting-started/data-in/cpp.md index c2d7bbfb8cd1..a0d1bbd2fb20 100644 --- a/docs/content/getting-started/data-in/cpp.md +++ b/docs/content/getting-started/data-in/cpp.md @@ -200,7 +200,7 @@ These are [_entity paths_](../../concepts/entity-component.md), which uniquely i One final observation: notice how we're logging a whole batch of points and colors all at once here. [Batches of data](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. -You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _splatting_. +You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _clamping_. --- diff --git a/docs/content/getting-started/data-in/python.md b/docs/content/getting-started/data-in/python.md index 7b587def3bbe..55d289b48069 100644 --- a/docs/content/getting-started/data-in/python.md +++ b/docs/content/getting-started/data-in/python.md @@ -134,7 +134,7 @@ These are [_entity paths_](../../concepts/entity-component.md), which uniquely i One final observation: notice how we're logging a whole batch of points and colors all at once here. [Batches of data](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. -You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _splatting_. +You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _clamping_. --- diff --git a/docs/content/getting-started/data-in/rust.md b/docs/content/getting-started/data-in/rust.md index c6c3ee682228..ae6c9e9c9986 100644 --- a/docs/content/getting-started/data-in/rust.md +++ b/docs/content/getting-started/data-in/rust.md @@ -150,7 +150,7 @@ These are [_entity paths_](../../concepts/entity-component.md), which uniquely i One final observation: notice how we're logging a whole batch of points and colors all at once here. [Batches of data](../../concepts/batches.md) are first-class citizens in Rerun and come with all sorts of performance benefits and dedicated features. -You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _splatting_. +You're looking at one of these dedicated features right now in fact: notice how we're only logging a single radius for all these points, yet somehow it applies to all of them. We call this _clamping_. --- diff --git a/docs/content/reference/types/components.md b/docs/content/reference/types/components.md index d11ab090ef1e..2acb3837ee18 100644 --- a/docs/content/reference/types/components.md +++ b/docs/content/reference/types/components.md @@ -24,7 +24,6 @@ on [Entities and Components](../../concepts/entity-component.md). * [`DrawOrder`](components/draw_order.md): Draw order used for the display order of 2D elements. * [`HalfSizes2D`](components/half_sizes2d.md): Half-sizes (extents) of a 2D box along its local axis, starting at its local origin/center. * [`HalfSizes3D`](components/half_sizes3d.md): Half-sizes (extents) of a 3D box along its local axis, starting at its local origin/center. -* [`InstanceKey`](components/instance_key.md): A unique numeric identifier for each individual instance within a batch. * [`KeypointId`](components/keypoint_id.md): A 16-bit ID representing a type of semantic keypoint within a class. * [`LineStrip2D`](components/line_strip2d.md): A line strip in 2D space. * [`LineStrip3D`](components/line_strip3d.md): A line strip in 3D space. diff --git a/docs/content/reference/types/components/.gitattributes b/docs/content/reference/types/components/.gitattributes index 18d845428ac4..463f9186673f 100644 --- a/docs/content/reference/types/components/.gitattributes +++ b/docs/content/reference/types/components/.gitattributes @@ -11,7 +11,6 @@ disconnected_space.md linguist-generated=true draw_order.md linguist-generated=true half_sizes2d.md linguist-generated=true half_sizes3d.md linguist-generated=true -instance_key.md linguist-generated=true keypoint_id.md linguist-generated=true line_strip2d.md linguist-generated=true line_strip3d.md linguist-generated=true diff --git a/docs/content/reference/types/components/instance_key.md b/docs/content/reference/types/components/instance_key.md deleted file mode 100644 index 099005b47318..000000000000 --- a/docs/content/reference/types/components/instance_key.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "InstanceKey" ---- - -A unique numeric identifier for each individual instance within a batch. - -Instance keys are automatically assigned by the `rerun` library and should not be set manually. - -The instance key is just the index of the instance within the batch, -i.e. the first point in a point cloud has `InstanceKey = 0`, the second `InstanceKey = 1`, and so on. - -We plan to remove the `InstanceKey` component in the near future. - -## Fields - -* value: `u64` - -## Links - * 🌊 [C++ API docs for `InstanceKey`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1InstanceKey.html) - * 🐍 [Python API docs for `InstanceKey`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.InstanceKey) - * 🦀 [Rust API docs for `InstanceKey`](https://docs.rs/rerun/latest/rerun/components/struct.InstanceKey.html) - - diff --git a/docs/snippets/all/custom_data.py b/docs/snippets/all/custom_data.py index 22becf1551d5..2e5661f15cd5 100755 --- a/docs/snippets/all/custom_data.py +++ b/docs/snippets/all/custom_data.py @@ -52,7 +52,7 @@ def log_custom_data() -> None: "left/my_confident_point_cloud", CustomPoints3D( points3d=point_grid, - confidences=[42], # splat + confidences=[42], ), ) diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index 8c4bce111ac9..a02e15e3c4ef 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -13,7 +13,7 @@ use re_viewer::external::{ }, }; -use crate::color_coordinates_visualizer_system::{ColorWithInstanceKey, InstanceColorSystem}; +use crate::color_coordinates_visualizer_system::{ColorWithInstance, InstanceColorSystem}; /// The different modes for displaying color coordinates in the custom space view. #[derive(Default, Debug, PartialEq, Clone, Copy)] @@ -237,12 +237,8 @@ fn color_space_ui( // Circles for the colors in the scene. for (ent_path, colors) in &colors.colors { let ent_highlight = query.highlights.entity_highlight(ent_path.hash()); - for ColorWithInstanceKey { - instance_key, - color, - } in colors - { - let highlight = ent_highlight.index_highlight(*instance_key); + for ColorWithInstance { instance, color } in colors { + let highlight = ent_highlight.index_highlight(*instance); let (x, y) = position_at(*color); let center = egui::pos2( @@ -265,12 +261,12 @@ fn color_space_ui( let interact = ui.interact( egui::Rect::from_center_size(center, egui::Vec2::splat(radius * 2.0)), - ui.id().with(("circle", &ent_path, instance_key)), + ui.id().with(("circle", &ent_path, instance)), egui::Sense::click(), ); // Update the global selection state if the user interacts with a point and show hover ui for the entire keypoint. - let instance = InstancePath::instance(ent_path.clone(), *instance_key); + let instance = InstancePath::instance(ent_path.clone(), *instance); let interact = interact.on_hover_ui_at_pointer(|ui| { item_ui::instance_path_button( ctx, diff --git a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs index 07ef8f083bde..01f85e2f2faa 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_visualizer_system.rs @@ -1,12 +1,8 @@ use re_viewer::external::{ egui, - re_log_types::EntityPath, + re_log_types::{EntityPath, Instance}, re_query, re_renderer, - re_types::{ - self, - components::{Color, InstanceKey}, - ComponentName, Loggable as _, - }, + re_types::{self, components::Color, ComponentName, Loggable as _}, re_viewer_context::{ IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewContextCollection, ViewQuery, ViewSystemIdentifier, ViewerContext, VisualizerQueryInfo, VisualizerSystem, @@ -16,12 +12,12 @@ use re_viewer::external::{ /// Our space view consist of single part which holds a list of egui colors for each entity path. #[derive(Default)] pub struct InstanceColorSystem { - pub colors: Vec<(EntityPath, Vec)>, + pub colors: Vec<(EntityPath, Vec)>, } -pub struct ColorWithInstanceKey { +pub struct ColorWithInstance { pub color: egui::Color32, - pub instance_key: InstanceKey, + pub instance: Instance, } struct ColorArchetype; @@ -90,11 +86,11 @@ impl VisualizerSystem for InstanceColorSystem { data_result.entity_path.clone(), (0..) .zip(colors) - .map(|(instance_key, color)| { + .map(|(instance, color)| { let [r, g, b, _] = color.to_array(); - ColorWithInstanceKey { + ColorWithInstance { color: egui::Color32::from_rgb(r, g, b), - instance_key: instance_key.into(), + instance: instance.into(), } }) .collect(), diff --git a/rerun_cpp/src/rerun.hpp b/rerun_cpp/src/rerun.hpp index d1885d164312..10d087dcf56d 100644 --- a/rerun_cpp/src/rerun.hpp +++ b/rerun_cpp/src/rerun.hpp @@ -32,7 +32,6 @@ namespace rerun { using components::Color; using components::HalfSizes2D; using components::HalfSizes3D; - using components::InstanceKey; using components::LineStrip2D; using components::LineStrip3D; using components::Material; diff --git a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp index 49b8acf083d5..fa34042fb278 100644 --- a/rerun_cpp/src/rerun/archetypes/annotation_context.hpp +++ b/rerun_cpp/src/rerun/archetypes/annotation_context.hpp @@ -77,11 +77,6 @@ namespace rerun::archetypes { explicit AnnotationContext(rerun::components::AnnotationContext _context) : context(std::move(_context)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp index e871a78f3522..2bfab90f4727 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows2d.hpp @@ -132,11 +132,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return vectors.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp index 06857fccfc2c..b801d3996cca 100644 --- a/rerun_cpp/src/rerun/archetypes/arrows3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/arrows3d.hpp @@ -149,11 +149,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return vectors.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/asset3d.hpp b/rerun_cpp/src/rerun/archetypes/asset3d.hpp index 4aa8fdf7f09b..aedac2b608e1 100644 --- a/rerun_cpp/src/rerun/archetypes/asset3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset3d.hpp @@ -133,11 +133,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/bar_chart.hpp b/rerun_cpp/src/rerun/archetypes/bar_chart.hpp index 80bcdbc666af..4a69add9ebc2 100644 --- a/rerun_cpp/src/rerun/archetypes/bar_chart.hpp +++ b/rerun_cpp/src/rerun/archetypes/bar_chart.hpp @@ -174,11 +174,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp index 8496944dc40a..70cc3bf45f9f 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp @@ -176,11 +176,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return half_sizes.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp index dcf58d0fc4e4..f0b11c2ead69 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp @@ -185,11 +185,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return half_sizes.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/clear.hpp b/rerun_cpp/src/rerun/archetypes/clear.hpp index e354dc87cae5..4320ba839795 100644 --- a/rerun_cpp/src/rerun/archetypes/clear.hpp +++ b/rerun_cpp/src/rerun/archetypes/clear.hpp @@ -105,11 +105,6 @@ namespace rerun::archetypes { explicit Clear(rerun::components::ClearIsRecursive _is_recursive) : is_recursive(std::move(_is_recursive)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/depth_image.hpp b/rerun_cpp/src/rerun/archetypes/depth_image.hpp index e51c69ba0b66..ca12f37c3d01 100644 --- a/rerun_cpp/src/rerun/archetypes/depth_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/depth_image.hpp @@ -143,11 +143,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp b/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp index 04328cbff25c..76c1dbc5b894 100644 --- a/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp +++ b/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp @@ -58,11 +58,6 @@ namespace rerun::archetypes { explicit DisconnectedSpace(rerun::components::DisconnectedSpace _disconnected_space) : disconnected_space(std::move(_disconnected_space)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/image.hpp b/rerun_cpp/src/rerun/archetypes/image.hpp index 48c5968463f9..3e45e5bd3630 100644 --- a/rerun_cpp/src/rerun/archetypes/image.hpp +++ b/rerun_cpp/src/rerun/archetypes/image.hpp @@ -132,11 +132,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp index 31a6a3aa7010..ea7590b061ef 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp @@ -127,11 +127,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return strips.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp index 7027d459470a..fe8020809571 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips3d.hpp @@ -122,11 +122,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return strips.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/mesh3d.hpp b/rerun_cpp/src/rerun/archetypes/mesh3d.hpp index 376940831ed1..1a1f90b6ed05 100644 --- a/rerun_cpp/src/rerun/archetypes/mesh3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/mesh3d.hpp @@ -165,11 +165,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return vertex_positions.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/pinhole.hpp b/rerun_cpp/src/rerun/archetypes/pinhole.hpp index a248d1185043..2fcc47bd9f7b 100644 --- a/rerun_cpp/src/rerun/archetypes/pinhole.hpp +++ b/rerun_cpp/src/rerun/archetypes/pinhole.hpp @@ -230,11 +230,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/points2d.hpp b/rerun_cpp/src/rerun/archetypes/points2d.hpp index 00a5cd08702d..536d83b42686 100644 --- a/rerun_cpp/src/rerun/archetypes/points2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points2d.hpp @@ -165,11 +165,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return positions.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/points3d.hpp b/rerun_cpp/src/rerun/archetypes/points3d.hpp index 56316bb7dedb..f586ebf87bf5 100644 --- a/rerun_cpp/src/rerun/archetypes/points3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points3d.hpp @@ -147,11 +147,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return positions.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/scalar.hpp b/rerun_cpp/src/rerun/archetypes/scalar.hpp index 096281f37f75..55f4268652d9 100644 --- a/rerun_cpp/src/rerun/archetypes/scalar.hpp +++ b/rerun_cpp/src/rerun/archetypes/scalar.hpp @@ -62,11 +62,6 @@ namespace rerun::archetypes { Scalar(Scalar&& other) = default; explicit Scalar(rerun::components::Scalar _scalar) : scalar(std::move(_scalar)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp index dd8b33b7b84d..e4cafe102b86 100644 --- a/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp +++ b/rerun_cpp/src/rerun/archetypes/segmentation_image.hpp @@ -136,11 +136,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/series_line.hpp b/rerun_cpp/src/rerun/archetypes/series_line.hpp index cfb37e10062d..316b9b8885d8 100644 --- a/rerun_cpp/src/rerun/archetypes/series_line.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_line.hpp @@ -108,11 +108,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 0; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/series_point.hpp b/rerun_cpp/src/rerun/archetypes/series_point.hpp index a3c4d81b3ea6..2827a59cffb9 100644 --- a/rerun_cpp/src/rerun/archetypes/series_point.hpp +++ b/rerun_cpp/src/rerun/archetypes/series_point.hpp @@ -127,11 +127,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 0; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/tensor.hpp b/rerun_cpp/src/rerun/archetypes/tensor.hpp index 09d293b7b7db..5a2689b689bb 100644 --- a/rerun_cpp/src/rerun/archetypes/tensor.hpp +++ b/rerun_cpp/src/rerun/archetypes/tensor.hpp @@ -90,11 +90,6 @@ namespace rerun::archetypes { Tensor(Tensor&& other) = default; explicit Tensor(rerun::components::TensorData _data) : data(std::move(_data)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/text_document.hpp b/rerun_cpp/src/rerun/archetypes/text_document.hpp index f4a58edcec7f..79b533d5405e 100644 --- a/rerun_cpp/src/rerun/archetypes/text_document.hpp +++ b/rerun_cpp/src/rerun/archetypes/text_document.hpp @@ -112,11 +112,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/text_log.hpp b/rerun_cpp/src/rerun/archetypes/text_log.hpp index b072a3a3b954..3a798321c7d1 100644 --- a/rerun_cpp/src/rerun/archetypes/text_log.hpp +++ b/rerun_cpp/src/rerun/archetypes/text_log.hpp @@ -117,11 +117,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.hpp b/rerun_cpp/src/rerun/archetypes/transform3d.hpp index 439c93f47ef9..3dca5f6b3cd0 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.hpp @@ -242,11 +242,6 @@ namespace rerun::archetypes { explicit Transform3D(rerun::components::Transform3D _transform) : transform(std::move(_transform)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp index 86292efb462f..5a77053bcb5d 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp @@ -130,11 +130,6 @@ namespace rerun::archetypes { ViewCoordinates(ViewCoordinates&& other) = default; explicit ViewCoordinates(rerun::components::ViewCoordinates _xyz) : xyz(std::move(_xyz)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp index f99ff37914e1..09c24deef398 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/background.hpp @@ -49,11 +49,6 @@ namespace rerun::blueprint::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp index 68ea24df18c6..f6c00a057ee8 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/container_blueprint.hpp @@ -150,11 +150,6 @@ namespace rerun::blueprint::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp index 7a903fa0d7a6..5b0c9717af32 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/panel_blueprint.hpp @@ -38,11 +38,6 @@ namespace rerun::blueprint::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 0; - } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp index 9d4579a1e714..faba0b359011 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/plot_legend.hpp @@ -57,11 +57,6 @@ namespace rerun::blueprint::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 0; - } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp index ebe2cd90ef5a..edd76fd99ce6 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/scalar_axis.hpp @@ -55,11 +55,6 @@ namespace rerun::blueprint::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 0; - } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/space_view_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/space_view_blueprint.hpp index af7afab96d44..58bcf19f4808 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/space_view_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/space_view_blueprint.hpp @@ -85,11 +85,6 @@ namespace rerun::blueprint::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp index fbbee2e116fd..1e116634a464 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/space_view_contents.hpp @@ -71,11 +71,6 @@ namespace rerun::blueprint::archetypes { explicit SpaceViewContents(Collection _query) : query(std::move(_query)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return query.size(); - } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp index 3189bf8e2b7c..63dbeedb5d3e 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/viewport_blueprint.hpp @@ -116,11 +116,6 @@ namespace rerun::blueprint::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 0; - } }; } // namespace rerun::blueprint::archetypes diff --git a/rerun_cpp/src/rerun/c/rerun.h b/rerun_cpp/src/rerun/c/rerun.h index 8ff584a5173b..fb3065e41fa3 100644 --- a/rerun_cpp/src/rerun/c/rerun.h +++ b/rerun_cpp/src/rerun/c/rerun.h @@ -202,10 +202,6 @@ typedef struct { /// Where to log to, e.g. `world/camera`. rr_string entity_path; - /// Number of instances of this entity (e.g. number of points in a point - /// cloud). - uint32_t num_instances; - /// Number of components. uint32_t num_data_cells; diff --git a/rerun_cpp/src/rerun/components.hpp b/rerun_cpp/src/rerun/components.hpp index 480b2095fb72..02dcde49398c 100644 --- a/rerun_cpp/src/rerun/components.hpp +++ b/rerun_cpp/src/rerun/components.hpp @@ -12,7 +12,6 @@ #include "components/draw_order.hpp" #include "components/half_sizes2d.hpp" #include "components/half_sizes3d.hpp" -#include "components/instance_key.hpp" #include "components/keypoint_id.hpp" #include "components/line_strip2d.hpp" #include "components/line_strip3d.hpp" diff --git a/rerun_cpp/src/rerun/components/.gitattributes b/rerun_cpp/src/rerun/components/.gitattributes index 41b719504a0d..275437bb55f7 100644 --- a/rerun_cpp/src/rerun/components/.gitattributes +++ b/rerun_cpp/src/rerun/components/.gitattributes @@ -17,8 +17,6 @@ draw_order.cpp linguist-generated=true draw_order.hpp linguist-generated=true half_sizes2d.hpp linguist-generated=true half_sizes3d.hpp linguist-generated=true -instance_key.cpp linguist-generated=true -instance_key.hpp linguist-generated=true keypoint_id.hpp linguist-generated=true line_strip2d.cpp linguist-generated=true line_strip2d.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/instance_key.cpp b/rerun_cpp/src/rerun/components/instance_key.cpp deleted file mode 100644 index c912980cce2b..000000000000 --- a/rerun_cpp/src/rerun/components/instance_key.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/instance_key.fbs". - -#include "instance_key.hpp" - -#include -#include - -namespace rerun::components {} - -namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { - static const auto datatype = arrow::uint64(); - return datatype; - } - - Result> Loggable::to_arrow( - const components::InstanceKey* instances, size_t num_instances - ) { - // TODO(andreas): Allow configuring the memory pool. - arrow::MemoryPool* pool = arrow::default_memory_pool(); - auto datatype = arrow_datatype(); - - ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) - if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); - } - std::shared_ptr array; - ARROW_RETURN_NOT_OK(builder->Finish(&array)); - return array; - } - - rerun::Error Loggable::fill_arrow_array_builder( - arrow::UInt64Builder* builder, const components::InstanceKey* elements, size_t num_elements - ) { - if (builder == nullptr) { - return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); - } - if (elements == nullptr) { - return rerun::Error( - ErrorCode::UnexpectedNullArgument, - "Cannot serialize null pointer to arrow array." - ); - } - - static_assert(sizeof(*elements) == sizeof(elements->value)); - ARROW_RETURN_NOT_OK( - builder->AppendValues(&elements->value, static_cast(num_elements)) - ); - - return Error::ok(); - } -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/instance_key.hpp b/rerun_cpp/src/rerun/components/instance_key.hpp deleted file mode 100644 index c7593674b9c1..000000000000 --- a/rerun_cpp/src/rerun/components/instance_key.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/instance_key.fbs". - -#pragma once - -#include "../result.hpp" - -#include -#include - -namespace arrow { - /// \private - template - class NumericBuilder; - - class Array; - class DataType; - class UInt64Type; - using UInt64Builder = NumericBuilder; -} // namespace arrow - -namespace rerun::components { - /// **Component**: A unique numeric identifier for each individual instance within a batch. - /// - /// Instance keys are automatically assigned by the `rerun` library and should not be set manually. - /// - /// The instance key is just the index of the instance within the batch, - /// i.e. the first point in a point cloud has `InstanceKey = 0`, the second `InstanceKey = 1`, and so on. - /// - /// We plan to remove the `InstanceKey` component in the near future. - struct InstanceKey { - uint64_t value; - - public: - InstanceKey() = default; - - InstanceKey(uint64_t value_) : value(value_) {} - - InstanceKey& operator=(uint64_t value_) { - value = value_; - return *this; - } - }; -} // namespace rerun::components - -namespace rerun { - template - struct Loggable; - - /// \private - template <> - struct Loggable { - static constexpr const char Name[] = "rerun.components.InstanceKey"; - - /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype(); - - /// Serializes an array of `rerun::components::InstanceKey` into an arrow array. - static Result> to_arrow( - const components::InstanceKey* instances, size_t num_instances - ); - - /// Fills an arrow array builder with an array of this type. - static rerun::Error fill_arrow_array_builder( - arrow::UInt64Builder* builder, const components::InstanceKey* elements, - size_t num_elements - ); - }; -} // namespace rerun diff --git a/rerun_cpp/src/rerun/recording_stream.cpp b/rerun_cpp/src/rerun/recording_stream.cpp index e470d62f1b83..05afcb43af90 100644 --- a/rerun_cpp/src/rerun/recording_stream.cpp +++ b/rerun_cpp/src/rerun/recording_stream.cpp @@ -1,6 +1,5 @@ #include "recording_stream.hpp" #include "c/rerun.h" -#include "components/instance_key.hpp" #include "config.hpp" #include "data_cell.hpp" #include "sdk_info.hpp" @@ -12,8 +11,6 @@ #include namespace rerun { - static const auto splat_key = components::InstanceKey(std::numeric_limits::max()); - static rr_store_kind store_kind_to_c(StoreKind store_kind) { switch (store_kind) { case StoreKind::Recording: @@ -194,47 +191,21 @@ namespace rerun { if (!is_enabled()) { return Error::ok(); } - size_t num_instances_max = 0; - for (const auto& batch : batches) { - num_instances_max = std::max(num_instances_max, batch.num_instances); - } std::vector instanced; - std::vector splatted; for (const auto& batch : batches) { - if (num_instances_max > 1 && batch.num_instances == 1) { - splatted.push_back(std::move(batch)); - } else { - instanced.push_back(std::move(batch)); - } + instanced.push_back(std::move(batch)); } bool inject_time = !static_; - if (!splatted.empty()) { - splatted.push_back( - std::move(DataCell::from_loggable(splat_key).value) - ); - auto result = - try_log_data_row(entity_path, 1, splatted.size(), splatted.data(), inject_time); - if (result.is_err()) { - return result; - } - } - - return try_log_data_row( - entity_path, - num_instances_max, - instanced.size(), - instanced.data(), - inject_time - ); + return try_log_data_row(entity_path, instanced.size(), instanced.data(), inject_time); } Error RecordingStream::try_log_data_row( - std::string_view entity_path, size_t num_instances, size_t num_data_cells, - const DataCell* data_cells, bool inject_time + std::string_view entity_path, size_t num_data_cells, const DataCell* data_cells, + bool inject_time ) const { if (!is_enabled()) { return Error::ok(); @@ -247,7 +218,6 @@ namespace rerun { rr_data_row c_data_row; c_data_row.entity_path = detail::to_rr_string(entity_path); - c_data_row.num_instances = static_cast(num_instances); c_data_row.num_data_cells = static_cast(num_data_cells); c_data_row.data_cells = c_data_cells.data(); diff --git a/rerun_cpp/src/rerun/recording_stream.hpp b/rerun_cpp/src/rerun/recording_stream.hpp index 31df9f46374b..421a36bf3dd9 100644 --- a/rerun_cpp/src/rerun/recording_stream.hpp +++ b/rerun_cpp/src/rerun/recording_stream.hpp @@ -531,8 +531,6 @@ namespace rerun { /// In order to use this you need to pass serialized Arrow data cells. /// /// \param entity_path Path to the entity in the space hierarchy. - /// \param num_instances - /// Each cell is expected to hold exactly `num_instances` instances. /// \param num_data_cells Number of data cells passed in. /// \param data_cells The data cells to log. /// \param inject_time @@ -541,8 +539,8 @@ namespace rerun { /// /// \see `try_log_serialized_batches` Error try_log_data_row( - std::string_view entity_path, size_t num_instances, size_t num_data_cells, - const DataCell* data_cells, bool inject_time + std::string_view entity_path, size_t num_data_cells, const DataCell* data_cells, + bool inject_time ) const; /// Logs the file at the given `path` using all `DataLoader`s available. diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp index daed9e4c613a..f4c3a1860b47 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer1.hpp @@ -126,11 +126,6 @@ namespace rerun::archetypes { fuzz1020(std::move(_fuzz1020)), fuzz1021(std::move(_fuzz1021)), fuzz1022(std::move(_fuzz1022)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 1; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp index 17a560cc1b31..1a1714d18eae 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer2.hpp @@ -122,11 +122,6 @@ namespace rerun::archetypes { fuzz1117(std::move(_fuzz1117)), fuzz1118(std::move(_fuzz1118)), fuzz1122(std::move(_fuzz1122)) {} - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return fuzz1101.size(); - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp index 1004ff15c502..c1fbb4577e93 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer3.hpp @@ -188,11 +188,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 0; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp index 4ecf384f7ca5..c113d6bb6854 100644 --- a/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp +++ b/rerun_cpp/tests/generated/archetypes/affix_fuzzer4.hpp @@ -188,11 +188,6 @@ namespace rerun::archetypes { // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - - /// Returns the number of primary instances of this archetype. - size_t num_instances() const { - return 0; - } }; } // namespace rerun::archetypes diff --git a/rerun_cpp/tests/recording_stream.cpp b/rerun_cpp/tests/recording_stream.cpp index 4c6d4ff31d01..c87b52b116fe 100644 --- a/rerun_cpp/tests/recording_stream.cpp +++ b/rerun_cpp/tests/recording_stream.cpp @@ -457,7 +457,7 @@ SCENARIO("Recording stream handles invalid logging gracefully", TEST_TAG) { THEN("try_log_data_row fails with UnexpectedNullArgument") { CHECK( - stream.try_log_data_row(path, 1, 1, &cell, true).code == + stream.try_log_data_row(path, 1, &cell, true).code == rerun::ErrorCode::UnexpectedNullArgument ); } @@ -470,7 +470,7 @@ SCENARIO("Recording stream handles invalid logging gracefully", TEST_TAG) { THEN("try_log_data_row fails with InvalidComponentTypeHandle") { CHECK( - stream.try_log_data_row(path, 1, 1, &cell, true).code == + stream.try_log_data_row(path, 1, &cell, true).code == rerun::ErrorCode::InvalidComponentTypeHandle ); } diff --git a/rerun_py/rerun_sdk/rerun/_baseclasses.py b/rerun_py/rerun_sdk/rerun/_baseclasses.py index ba3c366be759..3edab8fb68a0 100644 --- a/rerun_py/rerun_sdk/rerun/_baseclasses.py +++ b/rerun_py/rerun_sdk/rerun/_baseclasses.py @@ -18,12 +18,7 @@ def component_name(self) -> str: ... def as_arrow_array(self) -> pa.Array: - """ - Returns a `pyarrow.Array` of the component data. - - Each element in the array corresponds to an instance of the component. Single-instanced - components and splats must still be represented as a 1-element array. - """ + """Returns a `pyarrow.Array` of the component data.""" ... diff --git a/rerun_py/rerun_sdk/rerun/_log.py b/rerun_py/rerun_sdk/rerun/_log.py index c22d7bbc57b0..49fa299ac3f9 100644 --- a/rerun_py/rerun_sdk/rerun/_log.py +++ b/rerun_py/rerun_sdk/rerun/_log.py @@ -6,7 +6,6 @@ import pyarrow as pa import rerun_bindings as bindings -from . import components as cmp from ._baseclasses import AsComponents, ComponentBatchLike from .error_utils import _send_warning_or_raise, catch_and_log_exceptions from .recording_stream import RecordingStream @@ -45,13 +44,6 @@ def as_arrow_array(self) -> pa.Array: return self.data -def _splat() -> cmp.InstanceKeyBatch: - """Helper to generate a splat InstanceKeyArray.""" - - _MAX_U64 = 2**64 - 1 - return pa.array([_MAX_U64], type=cmp.InstanceKeyType().storage_type) # type: ignore[no-any-return] - - @catch_and_log_exceptions() def log( entity_path: str | list[str], @@ -267,7 +259,6 @@ def log_components( recording = RecordingStream.to_native(recording) instanced: dict[str, pa.Array] = {} - splats: dict[str, pa.Array] = {} components = list(components) @@ -304,21 +295,8 @@ def log_components( if isinstance(array, pa.ExtensionArray): array = array.storage - if len(array) == 1 and num_instances > 1: - splats[name] = array - else: - instanced[name] = array - - if splats: - splats["rerun.components.InstanceKey"] = _splat() - bindings.log_arrow_msg( # pyright: ignore[reportGeneralTypeIssues] - entity_path, - components=splats, - static_=static, - recording=recording, - ) + instanced[name] = array - # Always log the instanced components last so range-based queries will include the other data. See(#1215) bindings.log_arrow_msg( # pyright: ignore[reportGeneralTypeIssues] entity_path, components=instanced, diff --git a/rerun_py/rerun_sdk/rerun/any_value.py b/rerun_py/rerun_sdk/rerun/any_value.py index 75396f74eed7..9b45fd771139 100644 --- a/rerun_py/rerun_sdk/rerun/any_value.py +++ b/rerun_py/rerun_sdk/rerun/any_value.py @@ -120,9 +120,6 @@ def __init__(self, drop_untyped_nones: bool = True, **kwargs: Any) -> None: general, if you can pass it to [pyarrow.array][] you can log it as a extension component. - All values must either have the same length, or be singular in which - case they will be treated as a splat. - Note: rerun requires that a given component only take on a single type. The first type logged will be the type that is used for all future logs of that component. The API will make a best effort to do type conversion diff --git a/rerun_py/rerun_sdk/rerun/components/.gitattributes b/rerun_py/rerun_sdk/rerun/components/.gitattributes index b7d5749f3dd7..12b4a9826e3c 100644 --- a/rerun_py/rerun_sdk/rerun/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/components/.gitattributes @@ -12,7 +12,6 @@ disconnected_space.py linguist-generated=true draw_order.py linguist-generated=true half_sizes2d.py linguist-generated=true half_sizes3d.py linguist-generated=true -instance_key.py linguist-generated=true keypoint_id.py linguist-generated=true line_strip2d.py linguist-generated=true line_strip3d.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/components/__init__.py b/rerun_py/rerun_sdk/rerun/components/__init__.py index 27cfabb1b894..2710c971bed2 100644 --- a/rerun_py/rerun_sdk/rerun/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/components/__init__.py @@ -30,7 +30,6 @@ from .draw_order import DrawOrder, DrawOrderArrayLike, DrawOrderBatch, DrawOrderLike, DrawOrderType from .half_sizes2d import HalfSizes2D, HalfSizes2DBatch, HalfSizes2DType from .half_sizes3d import HalfSizes3D, HalfSizes3DBatch, HalfSizes3DType -from .instance_key import InstanceKey, InstanceKeyArrayLike, InstanceKeyBatch, InstanceKeyLike, InstanceKeyType from .keypoint_id import KeypointId, KeypointIdBatch, KeypointIdType from .line_strip2d import LineStrip2D, LineStrip2DArrayLike, LineStrip2DBatch, LineStrip2DLike, LineStrip2DType from .line_strip3d import LineStrip3D, LineStrip3DArrayLike, LineStrip3DBatch, LineStrip3DLike, LineStrip3DType @@ -122,11 +121,6 @@ "HalfSizes3D", "HalfSizes3DBatch", "HalfSizes3DType", - "InstanceKey", - "InstanceKeyArrayLike", - "InstanceKeyBatch", - "InstanceKeyLike", - "InstanceKeyType", "KeypointId", "KeypointIdBatch", "KeypointIdType", diff --git a/rerun_py/rerun_sdk/rerun/components/instance_key.py b/rerun_py/rerun_sdk/rerun/components/instance_key.py deleted file mode 100644 index edb361d45a58..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/instance_key.py +++ /dev/null @@ -1,70 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/components/instance_key.fbs". - -# You can extend this class by creating a "InstanceKeyExt" class in "instance_key_ext.py". - -from __future__ import annotations - -from typing import TYPE_CHECKING, Any, Sequence, Union - -import numpy as np -import numpy.typing as npt -import pyarrow as pa -from attrs import define, field - -from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .instance_key_ext import InstanceKeyExt - -__all__ = ["InstanceKey", "InstanceKeyArrayLike", "InstanceKeyBatch", "InstanceKeyLike", "InstanceKeyType"] - - -@define(init=False) -class InstanceKey(InstanceKeyExt): - """ - **Component**: A unique numeric identifier for each individual instance within a batch. - - Instance keys are automatically assigned by the `rerun` library and should not be set manually. - - The instance key is just the index of the instance within the batch, - i.e. the first point in a point cloud has `InstanceKey = 0`, the second `InstanceKey = 1`, and so on. - - We plan to remove the `InstanceKey` component in the near future. - """ - - def __init__(self: Any, value: InstanceKeyLike): - """Create a new instance of the InstanceKey component.""" - - # You can define your own __init__ function as a member of InstanceKeyExt in instance_key_ext.py - self.__attrs_init__(value=value) - - value: int = field(converter=int) - - def __array__(self, dtype: npt.DTypeLike = None) -> npt.NDArray[Any]: - # You can define your own __array__ function as a member of InstanceKeyExt in instance_key_ext.py - return np.asarray(self.value, dtype=dtype) - - def __int__(self) -> int: - return int(self.value) - - -if TYPE_CHECKING: - InstanceKeyLike = Union[InstanceKey, int] -else: - InstanceKeyLike = Any - -InstanceKeyArrayLike = Union[InstanceKey, Sequence[InstanceKeyLike], int, npt.NDArray[np.uint64]] - - -class InstanceKeyType(BaseExtensionType): - _TYPE_NAME: str = "rerun.components.InstanceKey" - - def __init__(self) -> None: - pa.ExtensionType.__init__(self, pa.uint64(), self._TYPE_NAME) - - -class InstanceKeyBatch(BaseBatch[InstanceKeyArrayLike], ComponentBatchMixin): - _ARROW_TYPE = InstanceKeyType() - - @staticmethod - def _native_to_pa_array(data: InstanceKeyArrayLike, data_type: pa.DataType) -> pa.Array: - return InstanceKeyExt.native_to_pa_array_override(data, data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/instance_key_ext.py b/rerun_py/rerun_sdk/rerun/components/instance_key_ext.py deleted file mode 100644 index 560f20dc121f..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/instance_key_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import InstanceKeyArrayLike - - -class InstanceKeyExt: - """Extension for [InstanceKey][rerun.components.InstanceKey].""" - - @staticmethod - def native_to_pa_array_override(data: InstanceKeyArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.uint64).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/src/arrow.rs b/rerun_py/src/arrow.rs index a305cb856e33..23b0e549a1c7 100644 --- a/rerun_py/src/arrow.rs +++ b/rerun_py/src/arrow.rs @@ -68,15 +68,8 @@ pub fn build_data_row_from_components( .map(|(value, field)| DataCell::from_arrow(field.name.into(), value)) .collect_vec(); - let num_instances = cells.first().map_or(0, |cell| cell.num_instances()); - let row = DataRow::from_cells( - row_id, - time_point.clone(), - entity_path.clone(), - num_instances, - cells, - ) - .map_err(|err| PyValueError::new_err(err.to_string()))?; + let row = DataRow::from_cells(row_id, time_point.clone(), entity_path.clone(), cells) + .map_err(|err| PyValueError::new_err(err.to_string()))?; Ok(row) } diff --git a/tests/python/test_api/test_api.py b/tests/python/test_api/test_api.py index e94dc68f98ef..36a41092d67b 100755 --- a/tests/python/test_api/test_api.py +++ b/tests/python/test_api/test_api.py @@ -361,7 +361,6 @@ def run_extension_component() -> None: rr.log("extension_components/point", rr.AnyValues(confidence=0.9)) # Batch points with extension - # Note: each extension component must either be length 1 (a splat) or the same length as the batch rr.set_time_seconds("sim_time", 1) rr.log( "extension_components/points", From 8ede58b6f6bd45b257b71ea3ee8f3c6cec26d0ae Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 26 Apr 2024 15:44:28 +0200 Subject: [PATCH 376/508] Introduce a snippet for Spatial3DView and fix issues related to _RERUN_TEST_FORCE_SAVE (#6120) ### What - Introduce a new snippet that also sends a blueprint It turned out that _RERUN_TEST_FORCE_SAVE is totally broken when using blueprints since the blueprint stream stomps on the recording. - Make it so _RERUN_TEST_FORCE_SAVE works with blueprints - Remove redundant store_kind since this led to bugs opting out blueprint memory recordings from the force-save path. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6120?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6120?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6120) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_data_source/src/load_file.rs | 1 - crates/re_data_ui/src/entity_db.rs | 5 ++-- crates/re_data_ui/src/log_msg.rs | 3 +-- crates/re_entity_db/src/store_bundle.rs | 1 - crates/re_log_encoding/src/decoder/mod.rs | 1 - crates/re_log_encoding/src/decoder/stream.rs | 1 - crates/re_log_types/src/lib.rs | 2 -- crates/re_sdk/src/lib.rs | 1 - crates/re_sdk/src/recording_stream.rs | 20 +++++++--------- docs/snippets/all/spatial3dview.py | 25 ++++++++++++++++++++ docs/snippets/snippets.toml | 1 + rerun_py/src/python_bridge.rs | 2 +- 12 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 docs/snippets/all/spatial3dview.py diff --git a/crates/re_data_source/src/load_file.rs b/crates/re_data_source/src/load_file.rs index a8b653560e7a..a61caaa61afb 100644 --- a/crates/re_data_source/src/load_file.rs +++ b/crates/re_data_source/src/load_file.rs @@ -123,7 +123,6 @@ pub(crate) fn prepare_store_info( is_official_example: false, started: re_log_types::Time::now(), store_source, - store_kind: re_log_types::StoreKind::Recording, }, }) }) diff --git a/crates/re_data_ui/src/entity_db.rs b/crates/re_data_ui/src/entity_db.rs index 57a0007fa6f4..67d9409d2faa 100644 --- a/crates/re_data_ui/src/entity_db.rs +++ b/crates/re_data_ui/src/entity_db.rs @@ -39,12 +39,11 @@ impl crate::DataUi for EntityDb { if let Some(store_info) = self.store_info() { let re_log_types::StoreInfo { application_id, - store_id: _, + store_id, cloned_from, is_official_example: _, started, store_source, - store_kind, } = store_info; if let Some(cloned_from) = cloned_from { @@ -62,7 +61,7 @@ impl crate::DataUi for EntityDb { ui.end_row(); re_ui.grid_left_hand_label(ui, "Kind"); - ui.label(store_kind.to_string()); + ui.label(store_id.kind.to_string()); ui.end_row(); re_ui.grid_left_hand_label(ui, "Created"); diff --git a/crates/re_data_ui/src/log_msg.rs b/crates/re_data_ui/src/log_msg.rs index 86559d0d0e67..338a3b08743d 100644 --- a/crates/re_data_ui/src/log_msg.rs +++ b/crates/re_data_ui/src/log_msg.rs @@ -48,7 +48,6 @@ impl DataUi for SetStoreInfo { started, store_source, is_official_example, - store_kind, } = info; let re_ui = &ctx.re_ui; @@ -83,7 +82,7 @@ impl DataUi for SetStoreInfo { ui.end_row(); re_ui.grid_left_hand_label(ui, "store_kind:"); - ui.label(format!("{store_kind}")); + ui.label(format!("{}", store_id.kind)); ui.end_row(); }); } diff --git a/crates/re_entity_db/src/store_bundle.rs b/crates/re_entity_db/src/store_bundle.rs index e1583074f486..1cf0c21e6e4c 100644 --- a/crates/re_entity_db/src/store_bundle.rs +++ b/crates/re_entity_db/src/store_bundle.rs @@ -107,7 +107,6 @@ impl StoreBundle { is_official_example: false, started: re_log_types::Time::now(), store_source: re_log_types::StoreSource::Other("viewer".to_owned()), - store_kind: StoreKind::Blueprint, }, }); diff --git a/crates/re_log_encoding/src/decoder/mod.rs b/crates/re_log_encoding/src/decoder/mod.rs index 6f742cfa110e..a1ea2fdc1696 100644 --- a/crates/re_log_encoding/src/decoder/mod.rs +++ b/crates/re_log_encoding/src/decoder/mod.rs @@ -239,7 +239,6 @@ fn test_encode_decode() { rustc_version: String::new(), llvm_version: String::new(), }, - store_kind: re_log_types::StoreKind::Recording, }, })]; diff --git a/crates/re_log_encoding/src/decoder/stream.rs b/crates/re_log_encoding/src/decoder/stream.rs index d6b4111130af..3d2d27b86ccc 100644 --- a/crates/re_log_encoding/src/decoder/stream.rs +++ b/crates/re_log_encoding/src/decoder/stream.rs @@ -239,7 +239,6 @@ mod tests { is_official_example: false, started: Time::from_ns_since_epoch(0), store_source: StoreSource::Unknown, - store_kind: StoreKind::Recording, }, }) } diff --git a/crates/re_log_types/src/lib.rs b/crates/re_log_types/src/lib.rs index f35c5fa314f2..c8c79a6d6e08 100644 --- a/crates/re_log_types/src/lib.rs +++ b/crates/re_log_types/src/lib.rs @@ -361,8 +361,6 @@ pub struct StoreInfo { pub started: Time, pub store_source: StoreSource, - - pub store_kind: StoreKind, } impl StoreInfo { diff --git a/crates/re_sdk/src/lib.rs b/crates/re_sdk/src/lib.rs index 9c264b489f73..cccf5b567889 100644 --- a/crates/re_sdk/src/lib.rs +++ b/crates/re_sdk/src/lib.rs @@ -182,7 +182,6 @@ pub fn new_store_info( rustc_version: env!("RE_BUILD_RUSTC_VERSION").into(), llvm_version: env!("RE_BUILD_LLVM_VERSION").into(), }, - store_kind: re_log_types::StoreKind::Recording, } } diff --git a/crates/re_sdk/src/recording_stream.rs b/crates/re_sdk/src/recording_stream.rs index 659668bc15b9..3bc5cfc0275f 100644 --- a/crates/re_sdk/src/recording_stream.rs +++ b/crates/re_sdk/src/recording_stream.rs @@ -198,6 +198,7 @@ impl RecordingStreamBuilder { /// The default is to use a random [`StoreId`]. #[inline] pub fn store_id(mut self, store_id: StoreId) -> Self { + self.store_kind = store_id.kind; self.store_id = Some(store_id); self } @@ -545,7 +546,6 @@ impl RecordingStreamBuilder { is_official_example, started: Time::now(), store_source, - store_kind, }; let batcher_config = @@ -814,11 +814,14 @@ impl RecordingStream { batcher_config: DataTableBatcherConfig, sink: Box, ) -> RecordingStreamResult { - let sink = forced_sink_path().map_or(sink, |path| { - re_log::info!("Forcing FileSink because of env-var {ENV_FORCE_SAVE}={path:?}"); - // `unwrap` is ok since this force sinks are only used in tests. - Box::new(crate::sink::FileSink::new(path).unwrap()) as Box - }); + let sink = (info.store_id.kind == StoreKind::Recording) + .then(forced_sink_path) + .flatten() + .map_or(sink, |path| { + re_log::info!("Forcing FileSink because of env-var {ENV_FORCE_SAVE}={path:?}"); + // `unwrap` is ok since this force sinks are only used in tests. + Box::new(crate::sink::FileSink::new(path).unwrap()) as Box + }); RecordingStreamInner::new(info, batcher_config, sink).map(|inner| Self { inner: Either::Left(Arc::new(Some(inner))), }) @@ -1581,11 +1584,6 @@ impl RecordingStream { let sink = crate::sink::MemorySink::default(); let mut storage = sink.buffer(); - if forced_sink_path().is_some() { - re_log::debug!("Ignored setting new memory sink since _RERUN_FORCE_SINK is set"); - return storage; - } - self.set_sink(Box::new(sink)); storage.rec = Some(self.clone()); diff --git a/docs/snippets/all/spatial3dview.py b/docs/snippets/all/spatial3dview.py new file mode 100644 index 000000000000..bfc69ba21a64 --- /dev/null +++ b/docs/snippets/all/spatial3dview.py @@ -0,0 +1,25 @@ +"""Use a blueprint to customize a Spatial3DView.""" + +import rerun as rr +import rerun.blueprint as rrb +from numpy.random import default_rng + +rr.init("rerun_example_spatial_3d", spawn=True) + +# Create some random points +rng = default_rng(12345) +positions = rng.uniform(-5, 5, size=[10, 3]) +colors = rng.uniform(0, 255, size=[10, 3]) +radii = rng.uniform(0, 1, size=[10]) + +rr.log("points", rr.Points3D(positions, colors=colors, radii=radii)) + +# Create a Spatial3D View +blueprint = rrb.Blueprint( + rrb.Spatial3DView( + origin="/points", + background=[80, 80, 80], + ) +) + +rr.send_blueprint(blueprint) diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index c825a57ce6a8..e46ee92653e1 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -13,6 +13,7 @@ log_line = [ # Not a complete example -- just a single log line "rust", "py", ] +spatial3dview = ["cpp", "rust"] # Missing examples timelines_example = [ # TODO(ab): incomplete code, need hideable stubs, see https://github.com/rerun-io/landing/issues/515 "py", "cpp", diff --git a/rerun_py/src/python_bridge.rs b/rerun_py/src/python_bridge.rs index 2d67d968835e..92306c57d6b7 100644 --- a/rerun_py/src/python_bridge.rs +++ b/rerun_py/src/python_bridge.rs @@ -1062,7 +1062,7 @@ fn send_blueprint( recording.send_blueprint(blueprint.inner.take(), activation_cmd); } else { - re_log::warn!("Provided `default_blueprint` has no store info, cannot send it."); + re_log::warn!("Provided `blueprint` has no store info, cannot send it."); } } From 75d109733ea293204863d6851d5f68471fe01bef Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 26 Apr 2024 16:04:14 +0200 Subject: [PATCH 377/508] Fix broken tests following instance key changes (#6130) --- crates/re_data_store/src/store_gc.rs | 1 + crates/re_data_store/tests/data_store.rs | 5 ----- .../snapshots/memory_test__scalars_on_one_timeline.snap | 5 ++--- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/crates/re_data_store/src/store_gc.rs b/crates/re_data_store/src/store_gc.rs index a7331bb12fff..835b9b6ce007 100644 --- a/crates/re_data_store/src/store_gc.rs +++ b/crates/re_data_store/src/store_gc.rs @@ -731,6 +731,7 @@ impl IndexedBucketInner { } else { let mut d = StoreDiff::deletion(removed_row_id, entity_path.clone()); d.at_timestamp(timeline, time); + d.insert(cell); diff = Some(d); } } diff --git a/crates/re_data_store/tests/data_store.rs b/crates/re_data_store/tests/data_store.rs index 27f8ccd1f492..2099b69d46c4 100644 --- a/crates/re_data_store/tests/data_store.rs +++ b/crates/re_data_store/tests/data_store.rs @@ -154,11 +154,6 @@ fn all_components() { assert_latest_components_at(&mut store, &entity_path, Some(components_a)); - let row = test_row!(entity_path @ [build_frame_nr(frame2)] => [MyIndex::from_iter(0..2)]); - store.insert_row(&row).unwrap(); - - assert_latest_components_at(&mut store, &entity_path, Some(components_a)); - let row = test_row!(entity_path @ [build_frame_nr(frame3)] => [build_some_positions2d(2)]); store.insert_row(&row).unwrap(); diff --git a/crates/re_data_store/tests/snapshots/memory_test__scalars_on_one_timeline.snap b/crates/re_data_store/tests/snapshots/memory_test__scalars_on_one_timeline.snap index 6ba35e5cf106..daab5fba8051 100644 --- a/crates/re_data_store/tests/snapshots/memory_test__scalars_on_one_timeline.snap +++ b/crates/re_data_store/tests/snapshots/memory_test__scalars_on_one_timeline.snap @@ -1,10 +1,9 @@ --- source: crates/re_data_store/tests/memory_test.rs -assertion_line: 96 expression: "[format!(\"{NUM_SCALARS} scalars\"),\n format!(\"{} in total\", re_format::format_bytes(total_mem_use as _)),\n format!(\"{} per row\",\n re_format::format_bytes(total_mem_use as f64 / NUM_SCALARS as\n f64))]" --- [ "1048576 scalars", - "936 MiB in total", - "936 B per row", + "912 MiB in total", + "912 B per row", ] From 2ff6a446737865b983b757d451c7ee3adf0ca9a3 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 26 Apr 2024 17:31:14 +0200 Subject: [PATCH 378/508] Generate doc pages for blueprint views (#6121) ### What - Builds on top of: https://github.com/rerun-io/rerun/pull/6120 - Rebase after merging and then remove `do-no-merge` label. Add blueprint views to the python docs index. Create a reference page for each view with documentation of its view properties and an example when provided. Generating pages for all the blueprint archetypes and cross-linking still felt a bit overwhelming. Since these properties are almost always only used in the context of the view, I decided to inline instead. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6121?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6121?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6121) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../rerun/blueprint/views/spatial3d.fbs | 2 + .../re_types_builder/src/codegen/docs/mod.rs | 174 +++++++++++++----- docs/content/reference/types/.gitattributes | 1 + docs/content/reference/types/views.md | 18 ++ .../reference/types/views/.gitattributes | 10 + .../reference/types/views/bar_chart_view.md | 10 + .../reference/types/views/spatial2d_view.md | 17 ++ .../reference/types/views/spatial3d_view.md | 23 +++ .../reference/types/views/tensor_view.md | 10 + .../types/views/text_document_view.md | 10 + .../reference/types/views/text_log_view.md | 10 + .../reference/types/views/time_series_view.md | 22 +++ rerun_py/docs/gen_common_index.py | 6 + .../rerun/blueprint/views/spatial3d_view.py | 34 +++- 14 files changed, 304 insertions(+), 43 deletions(-) create mode 100644 docs/content/reference/types/views.md create mode 100644 docs/content/reference/types/views/.gitattributes create mode 100644 docs/content/reference/types/views/bar_chart_view.md create mode 100644 docs/content/reference/types/views/spatial2d_view.md create mode 100644 docs/content/reference/types/views/spatial3d_view.md create mode 100644 docs/content/reference/types/views/tensor_view.md create mode 100644 docs/content/reference/types/views/text_document_view.md create mode 100644 docs/content/reference/types/views/text_log_view.md create mode 100644 docs/content/reference/types/views/time_series_view.md diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs index 749bb24d5cbe..1c1278c33a7a 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs @@ -3,6 +3,8 @@ include "rerun/attributes.fbs"; namespace rerun.blueprint.views; /// A Spatial 3D view. +/// +/// \example spatial3dview title="Use a blueprint to customize a Spatial3DView" table Spatial3DView ( "attr.rerun.view_identifier": "3D" ) { diff --git a/crates/re_types_builder/src/codegen/docs/mod.rs b/crates/re_types_builder/src/codegen/docs/mod.rs index 8af4fab66f30..dd8e7b4208ea 100644 --- a/crates/re_types_builder/src/codegen/docs/mod.rs +++ b/crates/re_types_builder/src/codegen/docs/mod.rs @@ -39,7 +39,8 @@ impl CodeGenerator for DocsCodeGenerator { let mut files_to_write = GeneratedFiles::default(); - let (mut archetypes, mut components, mut datatypes) = (Vec::new(), Vec::new(), Vec::new()); + let (mut archetypes, mut components, mut datatypes, mut views) = + (Vec::new(), Vec::new(), Vec::new(), Vec::new()); let object_map = &objects.objects; for object in object_map.values() { // skip test-only archetypes @@ -48,7 +49,7 @@ impl CodeGenerator for DocsCodeGenerator { } // Skip blueprint stuff, too early - if object.scope() == Some("blueprint".to_owned()) { + if object.scope() == Some("blueprint".to_owned()) && object.kind != ObjectKind::View { continue; } @@ -56,10 +57,7 @@ impl CodeGenerator for DocsCodeGenerator { ObjectKind::Datatype => datatypes.push(object), ObjectKind::Component => components.push(object), ObjectKind::Archetype => archetypes.push(object), - ObjectKind::View => { - // TODO(#6082): Implement view docs generation. - continue; - } + ObjectKind::View => views.push(object), } let page = object_page(reporter, object, object_map); @@ -96,6 +94,12 @@ on [Entities and Components](../../concepts/entity-component.md).", r"Data types are the lowest layer of the data model hierarchy. They are re-usable types used by the components.", &datatypes, ), + ( + ObjectKind::View, + 4, + r"Views are the panels shown in the viewer's viewport and the primary means of inspecting & visualizing previously logged data. This page lists all built-in views.", + &views, + ), ] { let page = index_page(kind, order, prelude, objects); let path = self @@ -216,7 +220,8 @@ fn object_page(reporter: &Reporter, object: &Object, object_map: &ObjectMap) -> } ObjectKind::Archetype => write_archetype_fields(&mut page, object, object_map), ObjectKind::View => { - // TODO(#6082): Implement view docs generation. + // TODO(#6082): Views should include the archetypes they know how to show + write_view_properties(reporter, &mut page, object, object_map); } } @@ -226,48 +231,65 @@ fn object_page(reporter: &Reporter, object: &Object, object_map: &ObjectMap) -> } else { "" }; + putln!(page); putln!(page, "## Links"); - let cpp_link = if object.is_enum() { - // Can't link to enums directly 🤷 - format!( - "https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1{}.html", - object.kind.plural_snake_case() - ) + if object.kind == ObjectKind::View { + // More complicated link due to scope + putln!( + page, + " * 🐍 [Python API docs for `{}`](https://ref.rerun.io/docs/python/stable/common/{}_{}{}#rerun.{}.{}.{})", + object.name, + object.scope().unwrap_or_default(), + object.kind.plural_snake_case(), + speculative_marker, + object.scope().unwrap_or_default(), + object.kind.plural_snake_case(), + object.name + ); } else { - // `_1` is doxygen's replacement for ':' - // https://github.com/doxygen/doxygen/blob/Release_1_9_8/src/util.cpp#L3532 - format!( - "https://ref.rerun.io/docs/cpp/stable/structrerun_1_1{}_1_1{}.html", + let cpp_link = if object.is_enum() { + // Can't link to enums directly 🤷 + format!( + "https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1{}.html", + object.kind.plural_snake_case() + ) + } else { + // `_1` is doxygen's replacement for ':' + // https://github.com/doxygen/doxygen/blob/Release_1_9_8/src/util.cpp#L3532 + format!( + "https://ref.rerun.io/docs/cpp/stable/structrerun_1_1{}_1_1{}.html", + object.kind.plural_snake_case(), + object.name + ) + }; + + // In alphabetical order by language. + putln!( + page, + " * 🌊 [C++ API docs for `{}`]({cpp_link}{speculative_marker})", + object.name, + ); + putln!( + page, + " * 🐍 [Python API docs for `{}`](https://ref.rerun.io/docs/python/stable/common/{}{}#rerun.{}.{})", + object.name, + object.kind.plural_snake_case(), + speculative_marker, object.kind.plural_snake_case(), object.name - ) - }; + ); - // In alphabetical order by language. - putln!( - page, - " * 🌊 [C++ API docs for `{}`]({cpp_link}{speculative_marker})", - object.name, - ); - putln!( - page, - " * 🐍 [Python API docs for `{}`](https://ref.rerun.io/docs/python/stable/common/{}{}#rerun.{}.{})", - object.name, - object.kind.plural_snake_case(), - speculative_marker, - object.kind.plural_snake_case(), - object.name - ); - putln!( - page, - " * 🦀 [Rust API docs for `{}`](https://docs.rs/rerun/latest/rerun/{}/{}.{}.html{speculative_marker})", - object.name, - object.kind.plural_snake_case(), - if object.is_struct() { "struct" } else { "enum" }, - object.name, - ); + putln!( + page, + " * 🦀 [Rust API docs for `{}`](https://docs.rs/rerun/latest/rerun/{}/{}.{}.html{speculative_marker})", + object.name, + object.kind.plural_snake_case(), + if object.is_struct() { "struct" } else { "enum" }, + object.name, + ); + } } putln!(page); @@ -476,6 +498,74 @@ fn write_archetype_fields(o: &mut String, object: &Object, object_map: &ObjectMa } } +fn write_view_properties( + reporter: &Reporter, + o: &mut String, + object: &Object, + object_map: &ObjectMap, +) { + if object.fields.is_empty() { + return; + } + + putln!(o, "## Properties"); + putln!(o); + + // Each field in a view should be a property + for field in &object.fields { + let Some(fqname) = field.typ.fqname() else { + continue; + }; + let Some(ty) = object_map.get(fqname) else { + continue; + }; + write_view_property(reporter, o, ty, object_map); + } +} + +fn write_view_property( + reporter: &Reporter, + o: &mut String, + object: &Object, + _object_map: &ObjectMap, +) { + putln!(o, "### `{}`", object.name); + + let top_level_docs = object.docs.untagged(); + + if top_level_docs.is_empty() { + reporter.error( + &object.virtpath, + &object.fqname, + "Undocumented view property", + ); + } + + for line in top_level_docs { + putln!(o, "{line}"); + } + + if object.fields.is_empty() { + return; + } + + let mut fields = Vec::new(); + for field in &object.fields { + fields.push(format!( + "* {}: {}", + field.name, + field.docs.first_line().unwrap_or_default() + )); + } + + if !fields.is_empty() { + putln!(o); + for field in fields { + putln!(o, "{field}"); + } + } +} + fn write_example_list(o: &mut String, examples: &[ExampleInfo<'_>]) { if examples.is_empty() { return; diff --git a/docs/content/reference/types/.gitattributes b/docs/content/reference/types/.gitattributes index bb0c06770dac..ae8095635a15 100644 --- a/docs/content/reference/types/.gitattributes +++ b/docs/content/reference/types/.gitattributes @@ -4,3 +4,4 @@ archetypes.md linguist-generated=true components.md linguist-generated=true datatypes.md linguist-generated=true +views.md linguist-generated=true diff --git a/docs/content/reference/types/views.md b/docs/content/reference/types/views.md new file mode 100644 index 000000000000..b9027b2f6187 --- /dev/null +++ b/docs/content/reference/types/views.md @@ -0,0 +1,18 @@ +--- +title: "Views" +order: 4 +--- + + + +Views are the panels shown in the viewer's viewport and the primary means of inspecting & visualizing previously logged data. This page lists all built-in views. + + +* [`BarChartView`](views/bar_chart_view.md): A bar chart view. +* [`Spatial2DView`](views/spatial2d_view.md): A Spatial 2D view. +* [`Spatial3DView`](views/spatial3d_view.md): A Spatial 3D view. +* [`TensorView`](views/tensor_view.md): A tensor view. +* [`TextDocumentView`](views/text_document_view.md): A text document view. +* [`TextLogView`](views/text_log_view.md): A text log view. +* [`TimeSeriesView`](views/time_series_view.md): A time series view. + diff --git a/docs/content/reference/types/views/.gitattributes b/docs/content/reference/types/views/.gitattributes new file mode 100644 index 000000000000..46e3655854e1 --- /dev/null +++ b/docs/content/reference/types/views/.gitattributes @@ -0,0 +1,10 @@ +# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs + +.gitattributes linguist-generated=true +bar_chart_view.md linguist-generated=true +spatial2d_view.md linguist-generated=true +spatial3d_view.md linguist-generated=true +tensor_view.md linguist-generated=true +text_document_view.md linguist-generated=true +text_log_view.md linguist-generated=true +time_series_view.md linguist-generated=true diff --git a/docs/content/reference/types/views/bar_chart_view.md b/docs/content/reference/types/views/bar_chart_view.md new file mode 100644 index 000000000000..cc05860311d2 --- /dev/null +++ b/docs/content/reference/types/views/bar_chart_view.md @@ -0,0 +1,10 @@ +--- +title: "BarChartView" +--- + +A bar chart view. + + +## Links + * 🐍 [Python API docs for `BarChartView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.BarChartView) + diff --git a/docs/content/reference/types/views/spatial2d_view.md b/docs/content/reference/types/views/spatial2d_view.md new file mode 100644 index 000000000000..fd5050615bc3 --- /dev/null +++ b/docs/content/reference/types/views/spatial2d_view.md @@ -0,0 +1,17 @@ +--- +title: "Spatial2DView" +--- + +A Spatial 2D view. + +## Properties + +### `Background` +Configuration for the background of a view. + +* kind: The type of the background. Defaults to BackgroundKind.GradientDark. +* color: Color used for BackgroundKind.SolidColor. + +## Links + * 🐍 [Python API docs for `Spatial2DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial2DView) + diff --git a/docs/content/reference/types/views/spatial3d_view.md b/docs/content/reference/types/views/spatial3d_view.md new file mode 100644 index 000000000000..c883a6c85ea8 --- /dev/null +++ b/docs/content/reference/types/views/spatial3d_view.md @@ -0,0 +1,23 @@ +--- +title: "Spatial3DView" +--- + +A Spatial 3D view. + +## Properties + +### `Background` +Configuration for the background of a view. + +* kind: The type of the background. Defaults to BackgroundKind.GradientDark. +* color: Color used for BackgroundKind.SolidColor. + +## Links + * 🐍 [Python API docs for `Spatial3DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial3DView) + +## Example + +### Use a blueprint to customize a Spatial3DView + +snippet: spatial3dview + diff --git a/docs/content/reference/types/views/tensor_view.md b/docs/content/reference/types/views/tensor_view.md new file mode 100644 index 000000000000..1de4fc94aa06 --- /dev/null +++ b/docs/content/reference/types/views/tensor_view.md @@ -0,0 +1,10 @@ +--- +title: "TensorView" +--- + +A tensor view. + + +## Links + * 🐍 [Python API docs for `TensorView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TensorView) + diff --git a/docs/content/reference/types/views/text_document_view.md b/docs/content/reference/types/views/text_document_view.md new file mode 100644 index 000000000000..4c7e61db82f7 --- /dev/null +++ b/docs/content/reference/types/views/text_document_view.md @@ -0,0 +1,10 @@ +--- +title: "TextDocumentView" +--- + +A text document view. + + +## Links + * 🐍 [Python API docs for `TextDocumentView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TextDocumentView) + diff --git a/docs/content/reference/types/views/text_log_view.md b/docs/content/reference/types/views/text_log_view.md new file mode 100644 index 000000000000..ca8a69a7d26f --- /dev/null +++ b/docs/content/reference/types/views/text_log_view.md @@ -0,0 +1,10 @@ +--- +title: "TextLogView" +--- + +A text log view. + + +## Links + * 🐍 [Python API docs for `TextLogView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TextLogView) + diff --git a/docs/content/reference/types/views/time_series_view.md b/docs/content/reference/types/views/time_series_view.md new file mode 100644 index 000000000000..5570bcf9e3cc --- /dev/null +++ b/docs/content/reference/types/views/time_series_view.md @@ -0,0 +1,22 @@ +--- +title: "TimeSeriesView" +--- + +A time series view. + +## Properties + +### `ScalarAxis` +Configuration for the scalar axis of a plot. + +* range: The range of the axis. +* lock_range_during_zoom: Whether to lock the range of the axis during zoom. +### `PlotLegend` +Configuration for the legend of a plot. + +* corner: To what corner the legend is aligned. +* visible: Whether the legend is shown at all. + +## Links + * 🐍 [Python API docs for `TimeSeriesView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TimeSeriesView) + diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index 5afcc0ddd83d..b1a152ef47cd 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -280,6 +280,12 @@ class Section: mod_path="rerun.blueprint.components", show_tables=False, ), + Section( + title="Blueprint", + sub_title="Views", + mod_path="rerun.blueprint.views", + show_tables=False, + ), ################################################################################ # Remaining sections Section( diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py index e486bc45895e..3aa3213a2c03 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py @@ -15,7 +15,39 @@ class Spatial3DView(SpaceView): - """**View**: A Spatial 3D view.""" + """ + **View**: A Spatial 3D view. + + Example + ------- + ### Use a blueprint to customize a Spatial3DView: + ```python + import rerun as rr + import rerun.blueprint as rrb + from numpy.random import default_rng + + rr.init("rerun_example_spatial_3d", spawn=True) + + # Create some random points + rng = default_rng(12345) + positions = rng.uniform(-5, 5, size=[10, 3]) + colors = rng.uniform(0, 255, size=[10, 3]) + radii = rng.uniform(0, 1, size=[10]) + + rr.log("points", rr.Points3D(positions, colors=colors, radii=radii)) + + # Create a Spatial3D View + blueprint = rrb.Blueprint( + rrb.Spatial3DView( + origin="/points", + background=[80, 80, 80], + ) + ) + + rr.send_blueprint(blueprint) + ``` + + """ def __init__( self, From 33ec17971108ef1dc473ae65f0b4e4f0a7f80c48 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 26 Apr 2024 20:22:04 +0200 Subject: [PATCH 379/508] Lock the torch version consistently in pixi.toml and our examples (#6137) ### What During nightly: ``` pixi run -e wheel-test build-examples install --channel nightly ``` was causing torch to get upgraded to 2.3 alongside torchvision 0.18. However, the next pixi invocation would then repair torch back to the 2.2.2 version from the lockfile, leading to a torch/torchvision version mismatch. Locking the version in the relevant places to keep this from happening. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6137?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6137?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6137) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- examples/python/controlnet/pyproject.toml | 2 +- .../pyproject.toml | 2 +- .../detect_and_track_objects/pyproject.toml | 2 +- .../segment_anything_model/pyproject.toml | 2 +- pixi.lock | 4332 ++++++++--------- pixi.toml | 4 +- 6 files changed, 2173 insertions(+), 2171 deletions(-) diff --git a/examples/python/controlnet/pyproject.toml b/examples/python/controlnet/pyproject.toml index 37fef7666901..5f81fee14851 100644 --- a/examples/python/controlnet/pyproject.toml +++ b/examples/python/controlnet/pyproject.toml @@ -9,7 +9,7 @@ dependencies = [ "pillow", "diffusers==0.27.2", "numpy", - "torch", + "torch==2.2.2", # This must match the version captured in pixi.toml "transformers", "rerun-sdk", ] diff --git a/examples/python/depth_guided_stable_diffusion/pyproject.toml b/examples/python/depth_guided_stable_diffusion/pyproject.toml index 8da60a58bf06..a925fcb6992c 100644 --- a/examples/python/depth_guided_stable_diffusion/pyproject.toml +++ b/examples/python/depth_guided_stable_diffusion/pyproject.toml @@ -13,7 +13,7 @@ dependencies = [ "requests>=2.31,<3", "rerun-sdk", "scipy", - "torch>1.13.0", + "torch==2.2.2", # This must match the version captured in pixi.toml "transformers>=4.26.0", ] diff --git a/examples/python/detect_and_track_objects/pyproject.toml b/examples/python/detect_and_track_objects/pyproject.toml index 2070e01dbeed..eb52fdfab212 100644 --- a/examples/python/detect_and_track_objects/pyproject.toml +++ b/examples/python/detect_and_track_objects/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "requests>=2.31,<3", "rerun-sdk", "timm==0.9.11", - "torch>=1.13.0", + "torch==2.2.2", # This must match the version captured in pixi.toml "transformers", ] diff --git a/examples/python/segment_anything_model/pyproject.toml b/examples/python/segment_anything_model/pyproject.toml index 5109a79ac805..54861ae16e41 100644 --- a/examples/python/segment_anything_model/pyproject.toml +++ b/examples/python/segment_anything_model/pyproject.toml @@ -8,7 +8,7 @@ dependencies = [ "opencv-python", "requests>=2.31,<3", "rerun-sdk", - "torch", + "torch==2.2.2", # This must match the version captured in pixi.toml "torchvision", "tqdm", ] diff --git a/pixi.lock b/pixi.lock index 7ee3d63d6078..970f1a779c51 100644 --- a/pixi.lock +++ b/pixi.lock @@ -1824,7 +1824,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/2e/abfed7a721928e14aeb900182ff695be474c4ee5f07ef0874cc5ecd5b0b1/betterproto-1.2.5.tar.gz - - pypi: https://files.pythonhosted.org/packages/0a/ef/37666bae20ba77d9a8420867077879fc0fd26e60e734ba5ee5ebc46f72fb/black-24.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/c5/48/34176b522e8cff4620a5d96c2e323ff2413f574870eb25efa8025885e028/black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl @@ -1900,7 +1900,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl @@ -1921,7 +1921,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/50/d8/870c966ced9aae912d113f2ca6a651bdc9db69d1ddf0afb5a87840ce0011/tifffile-2024.4.18-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl @@ -1998,7 +1998,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/2e/abfed7a721928e14aeb900182ff695be474c4ee5f07ef0874cc5ecd5b0b1/betterproto-1.2.5.tar.gz - - pypi: https://files.pythonhosted.org/packages/cb/95/4a02a0fed559bf638001f6bf4e4c9d685111db959d221485e7e27c91e954/black-24.4.0-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9b/f7/591d601c3046ceb65b97291dfe87fa25124cffac3d97aaaba89d0f0d7bdf/black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl @@ -2058,7 +2058,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl @@ -2079,7 +2079,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/50/d8/870c966ced9aae912d113f2ca6a651bdc9db69d1ddf0afb5a87840ce0011/tifffile-2024.4.18-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl - pypi: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl @@ -2155,7 +2155,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/2e/abfed7a721928e14aeb900182ff695be474c4ee5f07ef0874cc5ecd5b0b1/betterproto-1.2.5.tar.gz - - pypi: https://files.pythonhosted.org/packages/97/a6/f5857f79bba7eca05ebdc7e27e3447e3d2fc23898bb04f34bf3ff5dfb2db/black-24.4.0-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/c9/17/5e0036b265bbf6bc44970d93d48febcbc03701b671db3c9603fd43ebc616/black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl @@ -2215,7 +2215,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl @@ -2236,7 +2236,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/50/d8/870c966ced9aae912d113f2ca6a651bdc9db69d1ddf0afb5a87840ce0011/tifffile-2024.4.18-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl @@ -2320,7 +2320,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e0/44/827b2a91a5816512fcaf3cc4ebc465ccd5d598c45cefa6703fcf4a79018f/attrs-23.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ff/2e/abfed7a721928e14aeb900182ff695be474c4ee5f07ef0874cc5ecd5b0b1/betterproto-1.2.5.tar.gz - - pypi: https://files.pythonhosted.org/packages/0f/11/fa05ac9429d971d0fc10da85f24dafc3fa5788733fbd0d1c186b7577cefd/black-24.4.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/74/ce/e8eec1a77edbfa982bee3b5460dcdd4fe0e4e3165fc15d8ec44d04da7776/black-24.4.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl @@ -2384,7 +2384,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz + - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl @@ -2405,7 +2405,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/50/d8/870c966ced9aae912d113f2ca6a651bdc9db69d1ddf0afb5a87840ce0011/tifffile-2024.4.18-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl @@ -3414,23 +3414,23 @@ packages: url: https://files.pythonhosted.org/packages/53/fe/0251ccd9e0015c705e772da0fb2c96cdafd87b1d7dd45dc13dca7ced0eb7/accelerate-0.29.3-py3-none-any.whl sha256: 99d633d4b6126817c5e554487406748be95c8d1d1e659dd2fd60657e35f532dd requires_dist: - - numpy>=1.17 - - packaging>=20.0 + - numpy >=1.17 + - packaging >=20.0 - psutil - pyyaml - - torch>=1.10.0 + - torch >=1.10.0 - huggingface-hub - - safetensors>=0.3.1 - - black~=23.1 ; extra == 'dev' - - hf-doc-builder>=0.3.0 ; extra == 'dev' - - ruff~=0.2.1 ; extra == 'dev' - - pytest<=8.0.0,>=7.2.0 ; extra == 'dev' + - safetensors >=0.3.1 + - black ~=23.1 ; extra == 'dev' + - hf-doc-builder >=0.3.0 ; extra == 'dev' + - ruff ~=0.2.1 ; extra == 'dev' + - pytest <=8.0.0, >=7.2.0 ; extra == 'dev' - pytest-xdist ; extra == 'dev' - pytest-subtests ; extra == 'dev' - parameterized ; extra == 'dev' - datasets ; extra == 'dev' - evaluate ; extra == 'dev' - - torchpippy>=0.2.0 ; extra == 'dev' + - torchpippy >=0.2.0 ; extra == 'dev' - transformers ; extra == 'dev' - scipy ; extra == 'dev' - scikit-learn ; extra == 'dev' @@ -3439,14 +3439,14 @@ packages: - bitsandbytes ; extra == 'dev' - timm ; extra == 'dev' - rich ; extra == 'dev' - - black~=23.1 ; extra == 'quality' - - hf-doc-builder>=0.3.0 ; extra == 'quality' - - ruff~=0.2.1 ; extra == 'quality' + - black ~=23.1 ; extra == 'quality' + - hf-doc-builder >=0.3.0 ; extra == 'quality' + - ruff ~=0.2.1 ; extra == 'quality' - rich ; extra == 'rich' - sagemaker ; extra == 'sagemaker' - datasets ; extra == 'test_dev' - evaluate ; extra == 'test_dev' - - torchpippy>=0.2.0 ; extra == 'test_dev' + - torchpippy >=0.2.0 ; extra == 'test_dev' - transformers ; extra == 'test_dev' - scipy ; extra == 'test_dev' - scikit-learn ; extra == 'test_dev' @@ -3454,7 +3454,7 @@ packages: - tqdm ; extra == 'test_dev' - bitsandbytes ; extra == 'test_dev' - timm ; extra == 'test_dev' - - pytest<=8.0.0,>=7.2.0 ; extra == 'test_prod' + - pytest <=8.0.0, >=7.2.0 ; extra == 'test_prod' - pytest-xdist ; extra == 'test_prod' - pytest-subtests ; extra == 'test_prod' - parameterized ; extra == 'test_prod' @@ -3462,13 +3462,13 @@ packages: - comet-ml ; extra == 'test_trackers' - tensorboard ; extra == 'test_trackers' - dvclive ; extra == 'test_trackers' - - pytest<=8.0.0,>=7.2.0 ; extra == 'testing' + - pytest <=8.0.0, >=7.2.0 ; extra == 'testing' - pytest-xdist ; extra == 'testing' - pytest-subtests ; extra == 'testing' - parameterized ; extra == 'testing' - datasets ; extra == 'testing' - evaluate ; extra == 'testing' - - torchpippy>=0.2.0 ; extra == 'testing' + - torchpippy >=0.2.0 ; extra == 'testing' - transformers ; extra == 'testing' - scipy ; extra == 'testing' - scikit-learn ; extra == 'testing' @@ -3662,7 +3662,7 @@ packages: requires_dist: - importlib-metadata ; python_version < '3.8' - attrs[tests] ; extra == 'cov' - - coverage[toml]>=5.3 ; extra == 'cov' + - coverage[toml] >=5.3 ; extra == 'cov' - attrs[tests] ; extra == 'dev' - pre-commit ; extra == 'dev' - furo ; extra == 'docs' @@ -3674,14 +3674,14 @@ packages: - zope-interface ; extra == 'docs' - attrs[tests-no-zope] ; extra == 'tests' - zope-interface ; extra == 'tests' - - mypy>=1.6 ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' + - mypy >=1.6 ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' - pytest-mypy-plugins ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' - attrs[tests-mypy] ; extra == 'tests-no-zope' - cloudpickle ; platform_python_implementation == 'CPython' and extra == 'tests-no-zope' - hypothesis ; extra == 'tests-no-zope' - pympler ; extra == 'tests-no-zope' - pytest-xdist[psutil] ; extra == 'tests-no-zope' - - pytest>=4.3.0 ; extra == 'tests-no-zope' + - pytest >=4.3.0 ; extra == 'tests-no-zope' requires_python: '>=3.7' - kind: conda name: attrs @@ -6898,7 +6898,7 @@ packages: url: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl sha256: b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed requires_dist: - - soupsieve>1.2 + - soupsieve >1.2 - cchardet ; extra == 'cchardet' - chardet ; extra == 'chardet' - charset-normalizer ; extra == 'charset-normalizer' @@ -7085,83 +7085,83 @@ packages: timestamp: 1710259827989 - kind: pypi name: black - version: 24.4.0 - url: https://files.pythonhosted.org/packages/0a/ef/37666bae20ba77d9a8420867077879fc0fd26e60e734ba5ee5ebc46f72fb/black-24.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 5cd5b4f76056cecce3e69b0d4c228326d2595f506797f40b9233424e2524c070 + version: 24.4.2 + url: https://files.pythonhosted.org/packages/9b/f7/591d601c3046ceb65b97291dfe87fa25124cffac3d97aaaba89d0f0d7bdf/black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 requires_dist: - - click>=8.0.0 - - mypy-extensions>=0.4.3 - - packaging>=22.0 - - pathspec>=0.9.0 - - platformdirs>=2 - - tomli>=1.1.0 ; python_version < '3.11' - - typing-extensions>=4.0.1 ; python_version < '3.11' - - colorama>=0.4.3 ; extra == 'colorama' - - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython>=7.8.0 ; extra == 'jupyter' - - tokenize-rt>=3.2.0 ; extra == 'jupyter' - - uvloop>=0.15.2 ; extra == 'uvloop' + - click >=8.0.0 + - mypy-extensions >=0.4.3 + - packaging >=22.0 + - pathspec >=0.9.0 + - platformdirs >=2 + - tomli >=1.1.0 ; python_version < '3.11' + - typing-extensions >=4.0.1 ; python_version < '3.11' + - colorama >=0.4.3 ; extra == 'colorama' + - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython >=7.8.0 ; extra == 'jupyter' + - tokenize-rt >=3.2.0 ; extra == 'jupyter' + - uvloop >=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black - version: 24.4.0 - url: https://files.pythonhosted.org/packages/97/a6/f5857f79bba7eca05ebdc7e27e3447e3d2fc23898bb04f34bf3ff5dfb2db/black-24.4.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 64e60a7edd71fd542a10a9643bf369bfd2644de95ec71e86790b063aa02ff745 + version: 24.4.2 + url: https://files.pythonhosted.org/packages/c9/17/5e0036b265bbf6bc44970d93d48febcbc03701b671db3c9603fd43ebc616/black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c requires_dist: - - click>=8.0.0 - - mypy-extensions>=0.4.3 - - packaging>=22.0 - - pathspec>=0.9.0 - - platformdirs>=2 - - tomli>=1.1.0 ; python_version < '3.11' - - typing-extensions>=4.0.1 ; python_version < '3.11' - - colorama>=0.4.3 ; extra == 'colorama' - - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython>=7.8.0 ; extra == 'jupyter' - - tokenize-rt>=3.2.0 ; extra == 'jupyter' - - uvloop>=0.15.2 ; extra == 'uvloop' + - click >=8.0.0 + - mypy-extensions >=0.4.3 + - packaging >=22.0 + - pathspec >=0.9.0 + - platformdirs >=2 + - tomli >=1.1.0 ; python_version < '3.11' + - typing-extensions >=4.0.1 ; python_version < '3.11' + - colorama >=0.4.3 ; extra == 'colorama' + - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython >=7.8.0 ; extra == 'jupyter' + - tokenize-rt >=3.2.0 ; extra == 'jupyter' + - uvloop >=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black - version: 24.4.0 - url: https://files.pythonhosted.org/packages/cb/95/4a02a0fed559bf638001f6bf4e4c9d685111db959d221485e7e27c91e954/black-24.4.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8e5537f456a22cf5cfcb2707803431d2feeb82ab3748ade280d6ccd0b40ed2e8 + version: 24.4.2 + url: https://files.pythonhosted.org/packages/c5/48/34176b522e8cff4620a5d96c2e323ff2413f574870eb25efa8025885e028/black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb requires_dist: - - click>=8.0.0 - - mypy-extensions>=0.4.3 - - packaging>=22.0 - - pathspec>=0.9.0 - - platformdirs>=2 - - tomli>=1.1.0 ; python_version < '3.11' - - typing-extensions>=4.0.1 ; python_version < '3.11' - - colorama>=0.4.3 ; extra == 'colorama' - - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython>=7.8.0 ; extra == 'jupyter' - - tokenize-rt>=3.2.0 ; extra == 'jupyter' - - uvloop>=0.15.2 ; extra == 'uvloop' + - click >=8.0.0 + - mypy-extensions >=0.4.3 + - packaging >=22.0 + - pathspec >=0.9.0 + - platformdirs >=2 + - tomli >=1.1.0 ; python_version < '3.11' + - typing-extensions >=4.0.1 ; python_version < '3.11' + - colorama >=0.4.3 ; extra == 'colorama' + - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython >=7.8.0 ; extra == 'jupyter' + - tokenize-rt >=3.2.0 ; extra == 'jupyter' + - uvloop >=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black - version: 24.4.0 - url: https://files.pythonhosted.org/packages/0f/11/fa05ac9429d971d0fc10da85f24dafc3fa5788733fbd0d1c186b7577cefd/black-24.4.0-cp311-cp311-win_amd64.whl - sha256: 64578cf99b6b46a6301bc28bdb89f9d6f9b592b1c5837818a177c98525dbe397 + version: 24.4.2 + url: https://files.pythonhosted.org/packages/74/ce/e8eec1a77edbfa982bee3b5460dcdd4fe0e4e3165fc15d8ec44d04da7776/black-24.4.2-cp311-cp311-win_amd64.whl + sha256: 7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 requires_dist: - - click>=8.0.0 - - mypy-extensions>=0.4.3 - - packaging>=22.0 - - pathspec>=0.9.0 - - platformdirs>=2 - - tomli>=1.1.0 ; python_version < '3.11' - - typing-extensions>=4.0.1 ; python_version < '3.11' - - colorama>=0.4.3 ; extra == 'colorama' - - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython>=7.8.0 ; extra == 'jupyter' - - tokenize-rt>=3.2.0 ; extra == 'jupyter' - - uvloop>=0.15.2 ; extra == 'uvloop' + - click >=8.0.0 + - mypy-extensions >=0.4.3 + - packaging >=22.0 + - pathspec >=0.9.0 + - platformdirs >=2 + - tomli >=1.1.0 ; python_version < '3.11' + - typing-extensions >=4.0.1 ; python_version < '3.11' + - colorama >=0.4.3 ; extra == 'colorama' + - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython >=7.8.0 ; extra == 'jupyter' + - tokenize-rt >=3.2.0 ; extra == 'jupyter' + - uvloop >=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: blueprint @@ -7892,8 +7892,8 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 requires_dist: - pycparser requires_python: '>=3.8' @@ -7908,44 +7908,44 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer @@ -7956,8 +7956,8 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 requires_python: '>=3.7.0' - kind: conda name: charset-normalizer @@ -9147,18 +9147,18 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/ee/c0/9bd123d676eb61750e116a2cd915b06483fc406143cfc36c7f263f0f5368/contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df + url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 requires_dist: - - numpy>=1.20 + - numpy >=1.20 - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' + - sphinx >=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy==1.8.0 ; extra == 'mypy' + - mypy ==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9174,15 +9174,15 @@ packages: url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 requires_dist: - - numpy>=1.20 + - numpy >=1.20 - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' + - sphinx >=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy==1.8.0 ; extra == 'mypy' + - mypy ==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9195,18 +9195,18 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 + url: https://files.pythonhosted.org/packages/ee/c0/9bd123d676eb61750e116a2cd915b06483fc406143cfc36c7f263f0f5368/contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df requires_dist: - - numpy>=1.20 + - numpy >=1.20 - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' + - sphinx >=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy==1.8.0 ; extra == 'mypy' + - mypy ==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9222,15 +9222,15 @@ packages: url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 requires_dist: - - numpy>=1.20 + - numpy >=1.20 - furo ; extra == 'docs' - - sphinx>=7.2 ; extra == 'docs' + - sphinx >=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy==1.8.0 ; extra == 'mypy' + - mypy ==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9244,37 +9244,37 @@ packages: name: controlnet version: 0.1.0 path: examples/python/controlnet - sha256: 655921f31d08f05f5399715d72bd5a5bab6af08b9b04716b0855a7493659acf8 + sha256: 8ae055c0b8b0dd7757e4e666f6163172859044d4090830aecbec3460cdb318ee requires_dist: - accelerate + - diffusers ==0.27.2 + - numpy - opencv-python - pillow - - diffusers==0.27.2 - - numpy - - torch - - transformers - rerun-sdk + - torch ==2.2.2 + - transformers requires_python: '>=3.10' editable: true - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 requires_dist: - - cffi>=1.12 - - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant>=1.6.11 ; extra == 'docstest' - - twine>=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust>=0.11.4 ; extra == 'sdist' - - bcrypt>=3.1.5 ; extra == 'ssh' - - pytest>=6.2.0 ; extra == 'test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9282,7 +9282,7 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography @@ -9290,19 +9290,19 @@ packages: url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d requires_dist: - - cffi>=1.12 - - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant>=1.6.11 ; extra == 'docstest' - - twine>=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust>=0.11.4 ; extra == 'sdist' - - bcrypt>=3.1.5 ; extra == 'ssh' - - pytest>=6.2.0 ; extra == 'test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9310,27 +9310,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 + url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb requires_dist: - - cffi>=1.12 - - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant>=1.6.11 ; extra == 'docstest' - - twine>=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust>=0.11.4 ; extra == 'sdist' - - bcrypt>=3.1.5 ; extra == 'ssh' - - pytest>=6.2.0 ; extra == 'test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9338,27 +9338,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 + url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d requires_dist: - - cffi>=1.12 - - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant>=1.6.11 ; extra == 'docstest' - - twine>=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust>=0.11.4 ; extra == 'sdist' - - bcrypt>=3.1.5 ; extra == 'ssh' - - pytest>=6.2.0 ; extra == 'test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9366,27 +9366,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb + url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 requires_dist: - - cffi>=1.12 - - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant>=1.6.11 ; extra == 'docstest' - - twine>=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust>=0.11.4 ; extra == 'sdist' - - bcrypt>=3.1.5 ; extra == 'ssh' - - pytest>=6.2.0 ; extra == 'test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9394,7 +9394,7 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography @@ -9402,19 +9402,19 @@ packages: url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b requires_dist: - - cffi>=1.12 - - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant>=1.6.11 ; extra == 'docstest' - - twine>=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust>=0.11.4 ; extra == 'sdist' - - bcrypt>=3.1.5 ; extra == 'ssh' - - pytest>=6.2.0 ; extra == 'test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9422,7 +9422,7 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography @@ -9430,19 +9430,19 @@ packages: url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c requires_dist: - - cffi>=1.12 - - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' + - cffi >=1.12 + - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant>=1.6.11 ; extra == 'docstest' - - twine>=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' + - pyenchant >=1.6.11 ; extra == 'docstest' + - twine >=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust>=0.11.4 ; extra == 'sdist' - - bcrypt>=3.1.5 ; extra == 'ssh' - - pytest>=6.2.0 ; extra == 'test' + - setuptools-rust >=0.11.4 ; extra == 'sdist' + - bcrypt >=3.1.5 ; extra == 'ssh' + - pytest >=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9450,7 +9450,7 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' + - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: conda name: cxx-compiler @@ -9530,8 +9530,8 @@ packages: url: https://files.pythonhosted.org/packages/91/ca/7219b838086086972e662c19e908694bdc6744537fb41b70392501b8b5e4/dataclasses_json-0.6.4-py3-none-any.whl sha256: f90578b8a3177f7552f4e1a6e535e84293cd5da421fcce0642d49c0d7bdf8df2 requires_dist: - - marshmallow>=3.18.0,<4.0.0 - - typing-inspect>=0.4.0,<1 + - marshmallow >=3.18.0, <4.0.0 + - typing-inspect >=0.4.0, <1 requires_python: '>=3.7,<4.0' - kind: pypi name: deprecated @@ -9539,27 +9539,27 @@ packages: url: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl sha256: 6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c requires_dist: - - wrapt<2,>=1.10 + - wrapt <2, >=1.10 - tox ; extra == 'dev' - pytest ; extra == 'dev' - pytest-cov ; extra == 'dev' - - bump2version<1 ; extra == 'dev' - - sphinx<2 ; extra == 'dev' + - bump2version <1 ; extra == 'dev' + - sphinx <2 ; extra == 'dev' requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' - kind: pypi name: detect-and-track-objects version: 0.1.0 path: examples/python/detect_and_track_objects - sha256: c8419d3c804263d1287fc17c21419116fe8ae6fec83cc6026162eb521e12437f + sha256: 6c88082f8ff9c5949f5786584edf771078e3f1be6202f7225ad02268f96d9292 requires_dist: - numpy - - opencv-contrib-python>4.6 - - opencv-python>4.6 + - opencv-contrib-python >4.6 + - opencv-python >4.6 - pillow - - requests>=2.31,<3 + - requests <3, >=2.31 - rerun-sdk - - timm==0.9.11 - - torch>=1.13.0 + - timm ==0.9.11 + - torch ==2.2.2 - transformers editable: true - kind: pypi @@ -9568,12 +9568,12 @@ packages: path: examples/python/dicom_mri sha256: 98cb91dc5758ae59e3cd0fb797f86f40fcf627f63e659365806f59feed4618d8 requires_dist: - - dicom-numpy==0.6.2 + - dicom-numpy ==0.6.2 - numpy - - pydicom==2.3.0 - - requests>=2.31,<3 + - pydicom ==2.3.0 + - requests <3, >=2.31 - rerun-sdk - - types-requests>=2.31,<3 + - types-requests <3, >=2.31 editable: true - kind: pypi name: dicom-numpy @@ -9581,7 +9581,7 @@ packages: url: https://files.pythonhosted.org/packages/a4/d2/6d475e8925fa3f46f676263bfc6bdcf1e20273a433b296b1d63abecd2426/dicom_numpy-0.6.2-py2.py3-none-any.whl sha256: 361c8dfc52d625bf3344e5c2745e9c928d263999a4c094fe285d9fe461895ea9 requires_dist: - - pydicom>=1.0 + - pydicom >=1.0 - numpy - check-manifest ; extra == 'dev' - sphinx ; extra == 'dev' @@ -9597,74 +9597,74 @@ packages: requires_dist: - importlib-metadata - filelock - - huggingface-hub>=0.20.2 + - huggingface-hub >=0.20.2 - numpy - - regex!=2019.12.17 + - regex !=2019.12.17 - requests - - safetensors>=0.3.1 + - safetensors >=0.3.1 - pillow - - urllib3<=2.0.0 ; extra == 'dev' - - isort>=5.5.4 ; extra == 'dev' - - ruff==0.1.5 ; extra == 'dev' - - hf-doc-builder>=0.3.0 ; extra == 'dev' - - compel==0.1.8 ; extra == 'dev' - - gitpython<3.1.19 ; extra == 'dev' + - urllib3 <=2.0.0 ; extra == 'dev' + - isort >=5.5.4 ; extra == 'dev' + - ruff ==0.1.5 ; extra == 'dev' + - hf-doc-builder >=0.3.0 ; extra == 'dev' + - compel ==0.1.8 ; extra == 'dev' + - gitpython <3.1.19 ; extra == 'dev' - datasets ; extra == 'dev' - jinja2 ; extra == 'dev' - - invisible-watermark>=0.2.0 ; extra == 'dev' - - k-diffusion>=0.0.12 ; extra == 'dev' + - invisible-watermark >=0.2.0 ; extra == 'dev' + - k-diffusion >=0.0.12 ; extra == 'dev' - librosa ; extra == 'dev' - parameterized ; extra == 'dev' - pytest ; extra == 'dev' - pytest-timeout ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - requests-mock==1.10.0 ; extra == 'dev' - - safetensors>=0.3.1 ; extra == 'dev' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev' + - requests-mock ==1.10.0 ; extra == 'dev' + - safetensors >=0.3.1 ; extra == 'dev' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev' - scipy ; extra == 'dev' - torchvision ; extra == 'dev' - - transformers>=4.25.1 ; extra == 'dev' - - accelerate>=0.11.0 ; extra == 'dev' - - protobuf<4,>=3.20.3 ; extra == 'dev' + - transformers >=4.25.1 ; extra == 'dev' + - accelerate >=0.11.0 ; extra == 'dev' + - protobuf <4, >=3.20.3 ; extra == 'dev' - tensorboard ; extra == 'dev' - - peft>=0.6.0 ; extra == 'dev' - - torch>=1.4 ; extra == 'dev' - - jax>=0.4.1 ; extra == 'dev' - - jaxlib>=0.4.1 ; extra == 'dev' - - flax>=0.4.1 ; extra == 'dev' - - hf-doc-builder>=0.3.0 ; extra == 'docs' - - jax>=0.4.1 ; extra == 'flax' - - jaxlib>=0.4.1 ; extra == 'flax' - - flax>=0.4.1 ; extra == 'flax' - - urllib3<=2.0.0 ; extra == 'quality' - - isort>=5.5.4 ; extra == 'quality' - - ruff==0.1.5 ; extra == 'quality' - - hf-doc-builder>=0.3.0 ; extra == 'quality' - - compel==0.1.8 ; extra == 'test' - - gitpython<3.1.19 ; extra == 'test' + - peft >=0.6.0 ; extra == 'dev' + - torch >=1.4 ; extra == 'dev' + - jax >=0.4.1 ; extra == 'dev' + - jaxlib >=0.4.1 ; extra == 'dev' + - flax >=0.4.1 ; extra == 'dev' + - hf-doc-builder >=0.3.0 ; extra == 'docs' + - jax >=0.4.1 ; extra == 'flax' + - jaxlib >=0.4.1 ; extra == 'flax' + - flax >=0.4.1 ; extra == 'flax' + - urllib3 <=2.0.0 ; extra == 'quality' + - isort >=5.5.4 ; extra == 'quality' + - ruff ==0.1.5 ; extra == 'quality' + - hf-doc-builder >=0.3.0 ; extra == 'quality' + - compel ==0.1.8 ; extra == 'test' + - gitpython <3.1.19 ; extra == 'test' - datasets ; extra == 'test' - jinja2 ; extra == 'test' - - invisible-watermark>=0.2.0 ; extra == 'test' - - k-diffusion>=0.0.12 ; extra == 'test' + - invisible-watermark >=0.2.0 ; extra == 'test' + - k-diffusion >=0.0.12 ; extra == 'test' - librosa ; extra == 'test' - parameterized ; extra == 'test' - pytest ; extra == 'test' - pytest-timeout ; extra == 'test' - pytest-xdist ; extra == 'test' - - requests-mock==1.10.0 ; extra == 'test' - - safetensors>=0.3.1 ; extra == 'test' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'test' + - requests-mock ==1.10.0 ; extra == 'test' + - safetensors >=0.3.1 ; extra == 'test' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'test' - scipy ; extra == 'test' - torchvision ; extra == 'test' - - transformers>=4.25.1 ; extra == 'test' - - torch>=1.4 ; extra == 'torch' - - accelerate>=0.11.0 ; extra == 'torch' - - accelerate>=0.11.0 ; extra == 'training' + - transformers >=4.25.1 ; extra == 'test' + - torch >=1.4 ; extra == 'torch' + - accelerate >=0.11.0 ; extra == 'torch' + - accelerate >=0.11.0 ; extra == 'training' - datasets ; extra == 'training' - - protobuf<4,>=3.20.3 ; extra == 'training' + - protobuf <4, >=3.20.3 ; extra == 'training' - tensorboard ; extra == 'training' - jinja2 ; extra == 'training' - - peft>=0.6.0 ; extra == 'training' + - peft >=0.6.0 ; extra == 'training' requires_python: '>=3.8.0' - kind: pypi name: distlib @@ -9807,10 +9807,10 @@ packages: path: examples/python/face_tracking sha256: b8725fe4d36c11aad2c6c936ba2b57c7f65a856aa179badca5d041db63119d55 requires_dist: - - mediapipe==0.10.11 ; sys_platform != 'darwin' - - mediapipe==0.10.9 ; sys_platform == 'darwin' + - mediapipe ==0.10.11 ; sys_platform != 'darwin' + - mediapipe ==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python>4.6 + - opencv-python >4.6 - requests - rerun-sdk - tqdm @@ -9822,17 +9822,17 @@ packages: url: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl sha256: 404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f requires_dist: - - furo>=2023.9.10 ; extra == 'docs' - - sphinx-autodoc-typehints!=1.23.4,>=1.25.2 ; extra == 'docs' - - sphinx>=7.2.6 ; extra == 'docs' - - covdefaults>=2.3 ; extra == 'testing' - - coverage>=7.3.2 ; extra == 'testing' - - diff-cover>=8.0.1 ; extra == 'testing' - - pytest-cov>=4.1 ; extra == 'testing' - - pytest-mock>=3.12 ; extra == 'testing' - - pytest-timeout>=2.2 ; extra == 'testing' - - pytest>=7.4.3 ; extra == 'testing' - - typing-extensions>=4.8 ; python_version < '3.11' and extra == 'typing' + - furo >=2023.9.10 ; extra == 'docs' + - sphinx-autodoc-typehints !=1.23.4, >=1.25.2 ; extra == 'docs' + - sphinx >=7.2.6 ; extra == 'docs' + - covdefaults >=2.3 ; extra == 'testing' + - coverage >=7.3.2 ; extra == 'testing' + - diff-cover >=8.0.1 ; extra == 'testing' + - pytest-cov >=4.1 ; extra == 'testing' + - pytest-mock >=3.12 ; extra == 'testing' + - pytest-timeout >=2.2 ; extra == 'testing' + - pytest >=7.4.3 ; extra == 'testing' + - typing-extensions >=4.8 ; python_version < '3.11' and extra == 'typing' requires_python: '>=3.8' - kind: pypi name: flatbuffers @@ -9994,39 +9994,39 @@ packages: - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/c6/b5/dc17e93f60567fa1b0fa3720c2f28e0df5293927e2356e066e87af9adaba/fonttools-4.51.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b2b92381f37b39ba2fc98c3a45a9d6383bfc9916a87d66ccb6553f7bdd129097 + url: https://files.pythonhosted.org/packages/84/51/8203a3e6e475e6766ac950638d42f45470f36c6a4f0615ff0a1c1f2ed0d6/fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 8ac27f436e8af7779f0bb4d5425aa3535270494d3bc5459ed27de3f03151e4c2 requires_dist: - - fs<3,>=2.2.0 ; extra == 'all' - - lxml>=4.0 ; extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' + - fs <3, >=2.2.0 ; extra == 'all' + - lxml >=4.0 ; extra == 'all' + - zopfli >=0.1.4 ; extra == 'all' + - lz4 >=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.23.0 ; extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops >=0.5.0 ; extra == 'all' + - uharfbuzz >=0.23.0 ; extra == 'all' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'graphite' + - lz4 >=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml>=4.0 ; extra == 'lxml' - - skia-pathops>=0.5.0 ; extra == 'pathops' + - lxml >=4.0 ; extra == 'lxml' + - skia-pathops >=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz>=0.23.0 ; extra == 'repacker' + - uharfbuzz >=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs<3,>=2.2.0 ; extra == 'ufo' - - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli>=0.1.4 ; extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs <3, >=2.2.0 ; extra == 'ufo' + - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli >=0.1.4 ; extra == 'woff' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools @@ -10034,73 +10034,73 @@ packages: url: https://files.pythonhosted.org/packages/33/47/f2ca671af61757eaaac608963dda5b76ec9100621e45d0fd63a153fd8cd7/fonttools-4.51.0-cp311-cp311-macosx_10_9_universal2.whl sha256: a8feca65bab31479d795b0d16c9a9852902e3a3c0630678efb0b2b7941ea9c74 requires_dist: - - fs<3,>=2.2.0 ; extra == 'all' - - lxml>=4.0 ; extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' + - fs <3, >=2.2.0 ; extra == 'all' + - lxml >=4.0 ; extra == 'all' + - zopfli >=0.1.4 ; extra == 'all' + - lz4 >=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.23.0 ; extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops >=0.5.0 ; extra == 'all' + - uharfbuzz >=0.23.0 ; extra == 'all' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'graphite' + - lz4 >=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml>=4.0 ; extra == 'lxml' - - skia-pathops>=0.5.0 ; extra == 'pathops' + - lxml >=4.0 ; extra == 'lxml' + - skia-pathops >=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz>=0.23.0 ; extra == 'repacker' + - uharfbuzz >=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs<3,>=2.2.0 ; extra == 'ufo' - - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli>=0.1.4 ; extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs <3, >=2.2.0 ; extra == 'ufo' + - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli >=0.1.4 ; extra == 'woff' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/84/51/8203a3e6e475e6766ac950638d42f45470f36c6a4f0615ff0a1c1f2ed0d6/fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8ac27f436e8af7779f0bb4d5425aa3535270494d3bc5459ed27de3f03151e4c2 + url: https://files.pythonhosted.org/packages/c6/b5/dc17e93f60567fa1b0fa3720c2f28e0df5293927e2356e066e87af9adaba/fonttools-4.51.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b2b92381f37b39ba2fc98c3a45a9d6383bfc9916a87d66ccb6553f7bdd129097 requires_dist: - - fs<3,>=2.2.0 ; extra == 'all' - - lxml>=4.0 ; extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' + - fs <3, >=2.2.0 ; extra == 'all' + - lxml >=4.0 ; extra == 'all' + - zopfli >=0.1.4 ; extra == 'all' + - lz4 >=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.23.0 ; extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops >=0.5.0 ; extra == 'all' + - uharfbuzz >=0.23.0 ; extra == 'all' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'graphite' + - lz4 >=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml>=4.0 ; extra == 'lxml' - - skia-pathops>=0.5.0 ; extra == 'pathops' + - lxml >=4.0 ; extra == 'lxml' + - skia-pathops >=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz>=0.23.0 ; extra == 'repacker' + - uharfbuzz >=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs<3,>=2.2.0 ; extra == 'ufo' - - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli>=0.1.4 ; extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs <3, >=2.2.0 ; extra == 'ufo' + - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli >=0.1.4 ; extra == 'woff' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools @@ -10108,48 +10108,48 @@ packages: url: https://files.pythonhosted.org/packages/c5/d4/f426fa1ca42e47bcfff0c878fa9d49d9c03379d00903a7c178f95b97867a/fonttools-4.51.0-cp311-cp311-win_amd64.whl sha256: 0f08c901d3866a8905363619e3741c33f0a83a680d92a9f0e575985c2634fcc1 requires_dist: - - fs<3,>=2.2.0 ; extra == 'all' - - lxml>=4.0 ; extra == 'all' - - zopfli>=0.1.4 ; extra == 'all' - - lz4>=1.7.4.2 ; extra == 'all' + - fs <3, >=2.2.0 ; extra == 'all' + - lxml >=4.0 ; extra == 'all' + - zopfli >=0.1.4 ; extra == 'all' + - lz4 >=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops>=0.5.0 ; extra == 'all' - - uharfbuzz>=0.23.0 ; extra == 'all' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops >=0.5.0 ; extra == 'all' + - uharfbuzz >=0.23.0 ; extra == 'all' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4>=1.7.4.2 ; extra == 'graphite' + - lz4 >=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml>=4.0 ; extra == 'lxml' - - skia-pathops>=0.5.0 ; extra == 'pathops' + - lxml >=4.0 ; extra == 'lxml' + - skia-pathops >=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz>=0.23.0 ; extra == 'repacker' + - uharfbuzz >=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs<3,>=2.2.0 ; extra == 'ufo' - - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli>=0.1.4 ; extra == 'woff' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs <3, >=2.2.0 ; extra == 'ufo' + - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli >=0.1.4 ; extra == 'woff' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: freetype-py version: 2.4.0 - url: https://files.pythonhosted.org/packages/5f/34/76cfe866e482745ea8c9956b0be6198fd72d08d2be77b71596afdb8cd89f/freetype_py-2.4.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl - sha256: ce931f581d5038c4fea1f3d314254e0264e92441a5fdaef6817fe77b7bb888d3 + url: https://files.pythonhosted.org/packages/7c/77/faec42d1ffac2b970f606860a5bb083d606f1c673a5c57ab26382c8efec1/freetype_py-2.4.0-py3-none-macosx_10_9_universal2.whl + sha256: 3e0f5a91bc812f42d98a92137e86bac4ed037a29e43dafdb76d716d5732189e8 requires_python: '>=3.7' - kind: pypi name: freetype-py version: 2.4.0 - url: https://files.pythonhosted.org/packages/7c/77/faec42d1ffac2b970f606860a5bb083d606f1c673a5c57ab26382c8efec1/freetype_py-2.4.0-py3-none-macosx_10_9_universal2.whl - sha256: 3e0f5a91bc812f42d98a92137e86bac4ed037a29e43dafdb76d716d5732189e8 + url: https://files.pythonhosted.org/packages/5f/34/76cfe866e482745ea8c9956b0be6198fd72d08d2be77b71596afdb8cd89f/freetype_py-2.4.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl + sha256: ce931f581d5038c4fea1f3d314254e0264e92441a5fdaef6817fe77b7bb888d3 requires_python: '>=3.7' - kind: pypi name: freetype-py @@ -10263,7 +10263,7 @@ packages: requires_dist: - adlfs ; extra == 'abfs' - adlfs ; extra == 'adl' - - pyarrow>=1 ; extra == 'arrow' + - pyarrow >=1 ; extra == 'arrow' - dask ; extra == 'dask' - distributed ; extra == 'dask' - pytest ; extra == 'devel' @@ -10272,7 +10272,7 @@ packages: - requests ; extra == 'dropbox' - dropbox ; extra == 'dropbox' - adlfs ; extra == 'full' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' + - aiohttp !=4.0.0a0, !=4.0.0a1 ; extra == 'full' - dask ; extra == 'full' - distributed ; extra == 'full' - dropbox ; extra == 'full' @@ -10283,7 +10283,7 @@ packages: - ocifs ; extra == 'full' - panel ; extra == 'full' - paramiko ; extra == 'full' - - pyarrow>=1 ; extra == 'full' + - pyarrow >=1 ; extra == 'full' - pygit2 ; extra == 'full' - requests ; extra == 'full' - s3fs ; extra == 'full' @@ -10295,8 +10295,8 @@ packages: - requests ; extra == 'github' - gcsfs ; extra == 'gs' - panel ; extra == 'gui' - - pyarrow>=1 ; extra == 'hdfs' - - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' + - pyarrow >=1 ; extra == 'hdfs' + - aiohttp !=4.0.0a0, !=4.0.0a1 ; extra == 'http' - libarchive-c ; extra == 'libarchive' - ocifs ; extra == 'oci' - s3fs ; extra == 's3' @@ -10417,11 +10417,11 @@ packages: path: examples/python/gesture_detection sha256: 36dfc4cc822ee47f7aa29ba951bab8a94e96b9fd737daa324a441e6962a620bd requires_dist: - - mediapipe==0.10.11 ; sys_platform != 'darwin' - - mediapipe==0.10.9 ; sys_platform == 'darwin' + - mediapipe ==0.10.11 ; sys_platform != 'darwin' + - mediapipe ==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python>4.9 - - requests>=2.31,<3 + - opencv-python >4.9 + - requests <3, >=2.31 - rerun-sdk - tqdm requires_python: <3.12 @@ -10737,17 +10737,17 @@ packages: url: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl sha256: 5a63aa102e0049abe85b5b88cb9409234c1f70afcda21ce1e40b285b9629c1d6 requires_dist: - - googleapis-common-protos<2.0.dev0,>=1.56.2 - - protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0,>=3.19.5 - - proto-plus<2.0.0.dev0,>=1.22.3 - - google-auth<3.0.dev0,>=2.14.1 - - requests<3.0.0.dev0,>=2.18.0 - - grpcio<2.0.dev0,>=1.33.2 ; extra == 'grpc' - - grpcio-status<2.0.dev0,>=1.33.2 ; extra == 'grpc' - - grpcio<2.0.dev0,>=1.49.1 ; python_version >= '3.11' and extra == 'grpc' - - grpcio-status<2.0.dev0,>=1.49.1 ; python_version >= '3.11' and extra == 'grpc' - - grpcio-gcp<1.0.dev0,>=0.2.2 ; extra == 'grpcgcp' - - grpcio-gcp<1.0.dev0,>=0.2.2 ; extra == 'grpcio-gcp' + - googleapis-common-protos <2.0.dev0, >=1.56.2 + - protobuf !=3.20.0, !=3.20.1, !=4.21.0, !=4.21.1, !=4.21.2, !=4.21.3, !=4.21.4, !=4.21.5, <5.0.0.dev0, >=3.19.5 + - proto-plus <2.0.0.dev0, >=1.22.3 + - google-auth <3.0.dev0, >=2.14.1 + - requests <3.0.0.dev0, >=2.18.0 + - grpcio <2.0.dev0, >=1.33.2 ; extra == 'grpc' + - grpcio-status <2.0.dev0, >=1.33.2 ; extra == 'grpc' + - grpcio <2.0.dev0, >=1.49.1 ; python_version >= '3.11' and extra == 'grpc' + - grpcio-status <2.0.dev0, >=1.49.1 ; python_version >= '3.11' and extra == 'grpc' + - grpcio-gcp <1.0.dev0, >=0.2.2 ; extra == 'grpcgcp' + - grpcio-gcp <1.0.dev0, >=0.2.2 ; extra == 'grpcio-gcp' requires_python: '>=3.7' - kind: pypi name: google-auth @@ -10755,17 +10755,17 @@ packages: url: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl sha256: d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415 requires_dist: - - cachetools<6.0,>=2.0.0 - - pyasn1-modules>=0.2.1 - - rsa<5,>=3.1.4 - - aiohttp<4.0.0.dev0,>=3.6.2 ; extra == 'aiohttp' - - requests<3.0.0.dev0,>=2.20.0 ; extra == 'aiohttp' - - cryptography==36.0.2 ; extra == 'enterprise_cert' - - pyopenssl==22.0.0 ; extra == 'enterprise_cert' - - pyopenssl>=20.0.0 ; extra == 'pyopenssl' - - cryptography>=38.0.3 ; extra == 'pyopenssl' - - pyu2f>=0.1.5 ; extra == 'reauth' - - requests<3.0.0.dev0,>=2.20.0 ; extra == 'requests' + - cachetools <6.0, >=2.0.0 + - pyasn1-modules >=0.2.1 + - rsa <5, >=3.1.4 + - aiohttp <4.0.0.dev0, >=3.6.2 ; extra == 'aiohttp' + - requests <3.0.0.dev0, >=2.20.0 ; extra == 'aiohttp' + - cryptography ==36.0.2 ; extra == 'enterprise_cert' + - pyopenssl ==22.0.0 ; extra == 'enterprise_cert' + - pyopenssl >=20.0.0 ; extra == 'pyopenssl' + - cryptography >=38.0.3 ; extra == 'pyopenssl' + - pyu2f >=0.1.5 ; extra == 'reauth' + - requests <3.0.0.dev0, >=2.20.0 ; extra == 'requests' requires_python: '>=3.7' - kind: pypi name: google-cloud-core @@ -10773,11 +10773,11 @@ packages: url: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl sha256: a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61 requires_dist: - - google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0.dev0,>=1.31.6 - - google-auth<3.0.dev0,>=1.25.0 - - importlib-metadata>1.0.0 ; python_version < '3.8' - - grpcio<2.0.dev0,>=1.38.0 ; extra == 'grpc' - - grpcio-status<2.0.dev0,>=1.38.0 ; extra == 'grpc' + - google-api-core !=2.0.*, !=2.1.*, !=2.2.*, !=2.3.0, <3.0.0.dev0, >=1.31.6 + - google-auth <3.0.dev0, >=1.25.0 + - importlib-metadata >1.0.0 ; python_version < '3.8' + - grpcio <2.0.dev0, >=1.38.0 ; extra == 'grpc' + - grpcio-status <2.0.dev0, >=1.38.0 ; extra == 'grpc' requires_python: '>=3.7' - kind: pypi name: google-cloud-storage @@ -10785,18 +10785,18 @@ packages: url: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl sha256: 83a90447f23d5edd045e0037982c270302e3aeb45fc1288d2c2ca713d27bad94 requires_dist: - - google-auth<3.0.dev0,>=1.25.0 - - google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0.dev0,>=1.31.5 - - google-cloud-core<3.0.dev0,>=2.3.0 - - google-resumable-media>=2.3.2 - - requests<3.0.0.dev0,>=2.18.0 - - protobuf<5.0.0.dev0 ; extra == 'protobuf' + - google-auth <3.0.dev0, >=1.25.0 + - google-api-core !=2.0.*, !=2.1.*, !=2.2.*, !=2.3.0, <3.0.0.dev0, >=1.31.5 + - google-cloud-core <3.0.dev0, >=2.3.0 + - google-resumable-media >=2.3.2 + - requests <3.0.0.dev0, >=2.18.0 + - protobuf <5.0.0.dev0 ; extra == 'protobuf' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -10811,24 +10811,24 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -10838,10 +10838,10 @@ packages: url: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl sha256: 79543cfe433b63fd81c0844b7803aba1bb8950b47bedf7d980c38fa123937e08 requires_dist: - - google-crc32c<2.0.dev0,>=1.0 - - aiohttp<4.0.0.dev0,>=3.6.2 ; extra == 'aiohttp' - - google-auth<2.0.dev0,>=1.22.0 ; extra == 'aiohttp' - - requests<3.0.0.dev0,>=2.18.0 ; extra == 'requests' + - google-crc32c <2.0.dev0, >=1.0 + - aiohttp <4.0.0.dev0, >=3.6.2 ; extra == 'aiohttp' + - google-auth <2.0.dev0, >=1.22.0 ; extra == 'aiohttp' + - requests <3.0.0.dev0, >=2.18.0 ; extra == 'requests' requires_python: '>=3.7' - kind: pypi name: googleapis-common-protos @@ -10849,8 +10849,8 @@ packages: url: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl sha256: ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632 requires_dist: - - protobuf!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0,>=3.19.5 - - grpcio<2.0.0.dev0,>=1.44.0 ; extra == 'grpc' + - protobuf !=3.20.0, !=3.20.1, !=4.21.1, !=4.21.2, !=4.21.3, !=4.21.4, !=4.21.5, <5.0.0.dev0, >=3.19.5 + - grpcio <2.0.0.dev0, >=1.44.0 ; extra == 'grpc' requires_python: '>=3.7' - kind: pypi name: grpclib @@ -10858,9 +10858,9 @@ packages: url: https://files.pythonhosted.org/packages/79/b9/55936e462a5925190d7427e880b3033601d1effd13809b483d13a926061a/grpclib-0.4.7.tar.gz sha256: 2988ef57c02b22b7a2e8e961792c41ccf97efc2ace91ae7a5b0de03c363823c3 requires_dist: - - h2<5,>=3.1.0 + - h2 <5, >=3.1.0 - multidict - - protobuf>=3.20.0 ; extra == 'protobuf' + - protobuf >=3.20.0 ; extra == 'protobuf' requires_python: '>=3.7' - kind: conda name: gxx @@ -10970,8 +10970,8 @@ packages: url: https://files.pythonhosted.org/packages/2a/e5/db6d438da759efbb488c4f3fbdab7764492ff3c3f953132efa6b9f0e9e53/h2-4.1.0-py3-none-any.whl sha256: 03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d requires_dist: - - hyperframe<7,>=6.0 - - hpack<5,>=4.0 + - hyperframe <7, >=6.0 + - hpack <5, >=4.0 requires_python: '>=3.6.1' - kind: pypi name: hpack @@ -10985,12 +10985,12 @@ packages: url: https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl sha256: 0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d requires_dist: - - six>=1.9 + - six >=1.9 - webencodings - genshi ; extra == 'all' - - chardet>=2.2 ; extra == 'all' + - chardet >=2.2 ; extra == 'all' - lxml ; platform_python_implementation == 'CPython' and extra == 'all' - - chardet>=2.2 ; extra == 'chardet' + - chardet >=2.2 ; extra == 'chardet' - genshi ; extra == 'genshi' - lxml ; platform_python_implementation == 'CPython' and extra == 'lxml' requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' @@ -11001,15 +11001,15 @@ packages: sha256: 3429e25f38ccb834d310804a3b711e7e4953db5a9e420cc147a5e194ca90fd17 requires_dist: - filelock - - fsspec>=2023.5.0 - - packaging>=20.9 - - pyyaml>=5.1 + - fsspec >=2023.5.0 + - packaging >=20.9 + - pyyaml >=5.1 - requests - - tqdm>=4.42.1 - - typing-extensions>=3.7.4.3 - - inquirerpy==0.3.4 ; extra == 'all' + - tqdm >=4.42.1 + - typing-extensions >=3.7.4.3 + - inquirerpy ==0.3.4 ; extra == 'all' - aiohttp ; extra == 'all' - - minijinja>=1.0 ; extra == 'all' + - minijinja >=1.0 ; extra == 'all' - jedi ; extra == 'all' - jinja2 ; extra == 'all' - pytest ; extra == 'all' @@ -11019,24 +11019,24 @@ packages: - pytest-vcr ; extra == 'all' - pytest-asyncio ; extra == 'all' - pytest-rerunfailures ; extra == 'all' - - urllib3<2.0 ; extra == 'all' + - urllib3 <2.0 ; extra == 'all' - soundfile ; extra == 'all' - pillow ; extra == 'all' - gradio ; extra == 'all' - numpy ; extra == 'all' - - ruff>=0.3.0 ; extra == 'all' - - mypy==1.5.1 ; extra == 'all' - - typing-extensions>=4.8.0 ; extra == 'all' + - ruff >=0.3.0 ; extra == 'all' + - mypy ==1.5.1 ; extra == 'all' + - typing-extensions >=4.8.0 ; extra == 'all' - types-pyyaml ; extra == 'all' - types-requests ; extra == 'all' - types-simplejson ; extra == 'all' - types-toml ; extra == 'all' - types-tqdm ; extra == 'all' - types-urllib3 ; extra == 'all' - - inquirerpy==0.3.4 ; extra == 'cli' - - inquirerpy==0.3.4 ; extra == 'dev' + - inquirerpy ==0.3.4 ; extra == 'cli' + - inquirerpy ==0.3.4 ; extra == 'dev' - aiohttp ; extra == 'dev' - - minijinja>=1.0 ; extra == 'dev' + - minijinja >=1.0 ; extra == 'dev' - jedi ; extra == 'dev' - jinja2 ; extra == 'dev' - pytest ; extra == 'dev' @@ -11046,14 +11046,14 @@ packages: - pytest-vcr ; extra == 'dev' - pytest-asyncio ; extra == 'dev' - pytest-rerunfailures ; extra == 'dev' - - urllib3<2.0 ; extra == 'dev' + - urllib3 <2.0 ; extra == 'dev' - soundfile ; extra == 'dev' - pillow ; extra == 'dev' - gradio ; extra == 'dev' - numpy ; extra == 'dev' - - ruff>=0.3.0 ; extra == 'dev' - - mypy==1.5.1 ; extra == 'dev' - - typing-extensions>=4.8.0 ; extra == 'dev' + - ruff >=0.3.0 ; extra == 'dev' + - mypy ==1.5.1 ; extra == 'dev' + - typing-extensions >=4.8.0 ; extra == 'dev' - types-pyyaml ; extra == 'dev' - types-requests ; extra == 'dev' - types-simplejson ; extra == 'dev' @@ -11061,21 +11061,21 @@ packages: - types-tqdm ; extra == 'dev' - types-urllib3 ; extra == 'dev' - toml ; extra == 'fastai' - - fastai>=2.4 ; extra == 'fastai' - - fastcore>=1.3.27 ; extra == 'fastai' - - hf-transfer>=0.1.4 ; extra == 'hf_transfer' + - fastai >=2.4 ; extra == 'fastai' + - fastcore >=1.3.27 ; extra == 'fastai' + - hf-transfer >=0.1.4 ; extra == 'hf_transfer' - aiohttp ; extra == 'inference' - - minijinja>=1.0 ; extra == 'inference' - - ruff>=0.3.0 ; extra == 'quality' - - mypy==1.5.1 ; extra == 'quality' + - minijinja >=1.0 ; extra == 'inference' + - ruff >=0.3.0 ; extra == 'quality' + - mypy ==1.5.1 ; extra == 'quality' - tensorflow ; extra == 'tensorflow' - pydot ; extra == 'tensorflow' - graphviz ; extra == 'tensorflow' - tensorflow ; extra == 'tensorflow-testing' - - keras<3.0 ; extra == 'tensorflow-testing' - - inquirerpy==0.3.4 ; extra == 'testing' + - keras <3.0 ; extra == 'tensorflow-testing' + - inquirerpy ==0.3.4 ; extra == 'testing' - aiohttp ; extra == 'testing' - - minijinja>=1.0 ; extra == 'testing' + - minijinja >=1.0 ; extra == 'testing' - jedi ; extra == 'testing' - jinja2 ; extra == 'testing' - pytest ; extra == 'testing' @@ -11085,14 +11085,14 @@ packages: - pytest-vcr ; extra == 'testing' - pytest-asyncio ; extra == 'testing' - pytest-rerunfailures ; extra == 'testing' - - urllib3<2.0 ; extra == 'testing' + - urllib3 <2.0 ; extra == 'testing' - soundfile ; extra == 'testing' - pillow ; extra == 'testing' - gradio ; extra == 'testing' - numpy ; extra == 'testing' - torch ; extra == 'torch' - safetensors ; extra == 'torch' - - typing-extensions>=4.8.0 ; extra == 'typing' + - typing-extensions >=4.8.0 ; extra == 'typing' - types-pyyaml ; extra == 'typing' - types-requests ; extra == 'typing' - types-simplejson ; extra == 'typing' @@ -11106,11 +11106,11 @@ packages: path: examples/python/human_pose_tracking sha256: 8a80b67528d3f6d0c82671dc5c36cf551faa4b879f4434f0d386d8ef85666e86 requires_dist: - - mediapipe==0.10.11 ; sys_platform != 'darwin' - - mediapipe==0.10.9 ; sys_platform == 'darwin' + - mediapipe ==0.10.11 ; sys_platform != 'darwin' + - mediapipe ==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python>4.6 - - requests>=2.31,<3 + - opencv-python >4.6 + - requests <3, >=2.31 - rerun-sdk requires_python: <3.12 editable: true @@ -11214,7 +11214,7 @@ packages: sha256: 408c1d4d62f72c9e8347e7d1ca9bc11d8673328af3913868db3b828e28b40a4c requires_dist: - numpy - - pillow>=8.3.2 + - pillow >=8.3.2 - astropy ; extra == 'all-plugins' - av ; extra == 'all-plugins' - imageio-ffmpeg ; extra == 'all-plugins' @@ -11232,7 +11232,7 @@ packages: - fsspec[github] ; extra == 'dev' - black ; extra == 'dev' - flake8 ; extra == 'dev' - - sphinx<6 ; extra == 'docs' + - sphinx <6 ; extra == 'docs' - numpydoc ; extra == 'docs' - pydata-sphinx-theme ; extra == 'docs' - imageio-ffmpeg ; extra == 'ffmpeg' @@ -11252,7 +11252,7 @@ packages: - pydata-sphinx-theme ; extra == 'full' - pytest ; extra == 'full' - pytest-cov ; extra == 'full' - - sphinx<6 ; extra == 'full' + - sphinx <6 ; extra == 'full' - tifffile ; extra == 'full' - wheel ; extra == 'full' - gdal ; extra == 'gdal' @@ -11272,27 +11272,27 @@ packages: url: https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl sha256: 30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 requires_dist: - - zipp>=0.5 - - typing-extensions>=3.6.4 ; python_version < '3.8' - - sphinx>=3.5 ; extra == 'docs' - - jaraco-packaging>=9.3 ; extra == 'docs' - - rst-linker>=1.9 ; extra == 'docs' + - zipp >=0.5 + - typing-extensions >=3.6.4 ; python_version < '3.8' + - sphinx >=3.5 ; extra == 'docs' + - jaraco-packaging >=9.3 ; extra == 'docs' + - rst-linker >=1.9 ; extra == 'docs' - furo ; extra == 'docs' - sphinx-lint ; extra == 'docs' - - jaraco-tidelift>=1.4 ; extra == 'docs' + - jaraco-tidelift >=1.4 ; extra == 'docs' - ipython ; extra == 'perf' - - pytest>=6 ; extra == 'testing' - - pytest-checkdocs>=2.4 ; extra == 'testing' + - pytest >=6 ; extra == 'testing' + - pytest-checkdocs >=2.4 ; extra == 'testing' - pytest-cov ; extra == 'testing' - - pytest-enabler>=2.2 ; extra == 'testing' - - pytest-ruff>=0.2.1 ; extra == 'testing' + - pytest-enabler >=2.2 ; extra == 'testing' + - pytest-ruff >=0.2.1 ; extra == 'testing' - packaging ; extra == 'testing' - pyfakefs ; extra == 'testing' - flufl-flake8 ; extra == 'testing' - - pytest-perf>=0.9.2 ; extra == 'testing' - - jaraco-test>=5.4 ; extra == 'testing' + - pytest-perf >=0.9.2 ; extra == 'testing' + - jaraco-test >=5.4 ; extra == 'testing' - pytest-mypy ; platform_python_implementation != 'PyPy' and extra == 'testing' - - importlib-resources>=1.3 ; python_version < '3.9' and extra == 'testing' + - importlib-resources >=1.3 ; python_version < '3.9' and extra == 'testing' requires_python: '>=3.8' - kind: pypi name: incremental-logging @@ -11369,46 +11369,46 @@ packages: url: https://files.pythonhosted.org/packages/dc/d9/f387d9dfb2cf00f814b24e0f8bf6f4c68ae01870994dc436993fadd73563/jax-0.4.26-py3-none-any.whl sha256: 50dc795148ee6b0735b48b477e5abc556aa3a4c7af5d6940dad08024a908b02f requires_dist: - - ml-dtypes>=0.2.0 - - numpy>=1.22 + - ml-dtypes >=0.2.0 + - numpy >=1.22 - opt-einsum - - scipy>=1.9 - - importlib-metadata>=4.6 ; python_version < '3.10' - - numpy>=1.23.2 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - scipy>=1.11.1 ; python_version >= '3.12' - - protobuf<4,>=3.13 ; extra == 'australis' - - jaxlib==0.4.25 ; extra == 'ci' - - jaxlib==0.4.26 ; extra == 'cpu' - - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda' - - jaxlib==0.4.26 ; extra == 'cuda12' - - jax-cuda12-plugin==0.4.26 ; extra == 'cuda12' - - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12' - - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12' - - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12' - - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12' - - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12' - - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12' - - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12' - - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12' - - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12' - - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12' - - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_cudnn89' - - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_local' - - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_pip' - - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12_pip' - - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12_pip' - - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12_pip' - - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12_pip' - - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12_pip' - - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12_pip' - - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12_pip' - - jaxlib==0.4.20 ; extra == 'minimum-jaxlib' - - jaxlib==0.4.26 ; extra == 'tpu' - - libtpu-nightly==0.1.dev20240403 ; extra == 'tpu' + - scipy >=1.9 + - importlib-metadata >=4.6 ; python_version < '3.10' + - numpy >=1.23.2 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - scipy >=1.11.1 ; python_version >= '3.12' + - protobuf <4, >=3.13 ; extra == 'australis' + - jaxlib ==0.4.25 ; extra == 'ci' + - jaxlib ==0.4.26 ; extra == 'cpu' + - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda' + - jaxlib ==0.4.26 ; extra == 'cuda12' + - jax-cuda12-plugin ==0.4.26 ; extra == 'cuda12' + - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12' + - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12' + - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12' + - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12' + - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12' + - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12' + - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12' + - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12' + - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12' + - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12' + - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_cudnn89' + - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_local' + - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_pip' + - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12_pip' + - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12_pip' + - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12_pip' + - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12_pip' + - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12_pip' + - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12_pip' + - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - jaxlib ==0.4.20 ; extra == 'minimum-jaxlib' + - jaxlib ==0.4.26 ; extra == 'tpu' + - libtpu-nightly ==0.1.dev20240403 ; extra == 'tpu' - requests ; extra == 'tpu' requires_python: '>=3.9' - kind: pypi @@ -11417,20 +11417,20 @@ packages: url: https://files.pythonhosted.org/packages/a9/41/6bbe0a55e4df1c5d30da02dc3d26be2aea6333af9c35c6d846d431b86c74/jaxlib-0.4.26-cp311-cp311-manylinux2014_x86_64.whl sha256: 3069da7d75f5b4dd15350fffe6e6b86ca09c4b9fde60b10515edb09cef653335 requires_dist: - - scipy>=1.9 - - numpy>=1.22 - - ml-dtypes>=0.2.0 - - scipy>=1.11.1 ; python_version >= '3.12' - - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12_pip' - - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12_pip' - - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12_pip' - - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12_pip' - - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12_pip' - - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12_pip' - - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12_pip' + - scipy >=1.9 + - numpy >=1.22 + - ml-dtypes >=0.2.0 + - scipy >=1.11.1 ; python_version >= '3.12' + - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12_pip' + - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12_pip' + - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12_pip' + - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12_pip' + - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12_pip' + - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12_pip' + - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12_pip' requires_python: '>=3.9' - kind: pypi name: jinja2 @@ -11438,8 +11438,8 @@ packages: url: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl sha256: 7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa requires_dist: - - markupsafe>=2.0 - - babel>=2.7 ; extra == 'i18n' + - markupsafe >=2.0 + - babel >=2.7 ; extra == 'i18n' requires_python: '>=3.7' - kind: conda name: jinja2 @@ -11528,8 +11528,8 @@ packages: - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e + url: https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' @@ -11544,8 +11544,8 @@ packages: - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90 + url: https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' @@ -11654,10 +11654,10 @@ packages: requires_dist: - packaging - importlib-metadata ; python_version < '3.8' - - changelist==0.5 ; extra == 'dev' - - pre-commit==3.7.0 ; extra == 'lint' - - pytest>=7.4 ; extra == 'test' - - pytest-cov>=4.1 ; extra == 'test' + - changelist ==0.5 ; extra == 'dev' + - pre-commit ==3.7.0 ; extra == 'lint' + - pytest >=7.4 ; extra == 'test' + - pytest-cov >=4.1 ; extra == 'test' requires_python: '>=3.7' - kind: conda name: ld64 @@ -20089,8 +20089,8 @@ packages: - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/a4/1f/300788b5eab99aec872ed2f3647386d7d7f7bbf4f99c91e9e023b404ff7f/llvmlite-0.42.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: c5bece0cdf77f22379f19b1959ccd7aee518afa4afbd3656c6365865f84903f9 + url: https://files.pythonhosted.org/packages/13/97/4aac09bdfc1bc35f8eb64e21ff5897224a788170e5e8cab3e62c9eb78efb/llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf requires_python: '>=3.9' - kind: pypi name: llvmlite @@ -20101,8 +20101,8 @@ packages: - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/13/97/4aac09bdfc1bc35f8eb64e21ff5897224a788170e5e8cab3e62c9eb78efb/llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf + url: https://files.pythonhosted.org/packages/a4/1f/300788b5eab99aec872ed2f3647386d7d7f7bbf4f99c91e9e023b404ff7f/llvmlite-0.42.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: c5bece0cdf77f22379f19b1959ccd7aee518afa4afbd3656c6365865f84903f9 requires_python: '>=3.9' - kind: pypi name: llvmlite @@ -20121,14 +20121,14 @@ packages: - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/be/c3/1765e019344d3f042dfe750eb9a424c0ea2fd43deb6b2ac176b5603a436e/lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: 200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095 + url: https://files.pythonhosted.org/packages/95/4c/fc5e63fb41e867f530a70519e1bcab0c14e84a95aa659f697bc97531be96/lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe requires_dist: - - cssselect>=0.7 ; extra == 'cssselect' + - cssselect >=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython>=3.0.10 ; extra == 'source' + - cython >=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml @@ -20136,23 +20136,23 @@ packages: url: https://files.pythonhosted.org/packages/43/43/66a84c2a034f5df2782240cb2f68696a72ad6734d7a91f824e0360cde08b/lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl sha256: 70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867 requires_dist: - - cssselect>=0.7 ; extra == 'cssselect' + - cssselect >=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython>=3.0.10 ; extra == 'source' + - cython >=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/95/4c/fc5e63fb41e867f530a70519e1bcab0c14e84a95aa659f697bc97531be96/lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe + url: https://files.pythonhosted.org/packages/be/c3/1765e019344d3f042dfe750eb9a424c0ea2fd43deb6b2ac176b5603a436e/lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: 200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095 requires_dist: - - cssselect>=0.7 ; extra == 'cssselect' + - cssselect >=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython>=3.0.10 ; extra == 'source' + - cython >=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml @@ -20160,11 +20160,11 @@ packages: url: https://files.pythonhosted.org/packages/df/c5/8b05e69685b48cf11b596fbdd466f76cb3c1e3efe0361d8be0edb9df0325/lxml-5.2.1-cp311-cp311-win_amd64.whl sha256: 5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102 requires_dist: - - cssselect>=0.7 ; extra == 'cssselect' + - cssselect >=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython>=3.0.10 ; extra == 'source' + - cython >=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: conda name: lz4-c @@ -20320,8 +20320,8 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 + url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 requires_python: '>=3.7' - kind: pypi name: markupsafe @@ -20332,8 +20332,8 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 + url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 requires_python: '>=3.7' - kind: pypi name: markupsafe @@ -20448,15 +20448,15 @@ packages: url: https://files.pythonhosted.org/packages/38/04/37055b7013dfaaf66e3a9a51e46857cc9be151476a891b995fa70da7e139/marshmallow-3.21.1-py3-none-any.whl sha256: f085493f79efb0644f270a9bf2892843142d80d7174bbbd2f3713f2a589dc633 requires_dist: - - packaging>=17.0 + - packaging >=17.0 - marshmallow[tests] ; extra == 'dev' - tox ; extra == 'dev' - - pre-commit~=3.5 ; extra == 'dev' - - sphinx==7.2.6 ; extra == 'docs' - - sphinx-issues==4.0.0 ; extra == 'docs' - - alabaster==0.7.16 ; extra == 'docs' - - sphinx-version-warning==1.1.2 ; extra == 'docs' - - autodocsumm==0.2.12 ; extra == 'docs' + - pre-commit ~=3.5 ; extra == 'dev' + - sphinx ==7.2.6 ; extra == 'docs' + - sphinx-issues ==4.0.0 ; extra == 'docs' + - alabaster ==0.7.16 ; extra == 'docs' + - sphinx-version-warning ==1.1.2 ; extra == 'docs' + - autodocsumm ==0.2.12 ; extra == 'docs' - pytest ; extra == 'tests' - pytz ; extra == 'tests' - simplejson ; extra == 'tests' @@ -20464,19 +20464,19 @@ packages: - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/80/3b/e363612ac1a514abfb5505aa209dd5b724b3232a6de98710d7759559706a/matplotlib-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: cc4ccdc64e3039fc303defd119658148f2349239871db72cd74e2eeaa9b80b71 + url: https://files.pythonhosted.org/packages/36/11/62250ea25780d4b59c2c6044ec161235c47cc05a18d0ec0a05657de75b7d/matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661 requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.21 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=2.3.1 - - python-dateutil>=2.7 - - importlib-resources>=3.2.0 ; python_version < '3.10' + - contourpy >=1.0.1 + - cycler >=0.10 + - fonttools >=4.22.0 + - kiwisolver >=1.3.1 + - numpy >=1.21 + - packaging >=20.0 + - pillow >=8 + - pyparsing >=2.3.1 + - python-dateutil >=2.7 + - importlib-resources >=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib @@ -20484,33 +20484,33 @@ packages: url: https://files.pythonhosted.org/packages/14/60/12d4f27b859a74359306662da69c2d08826a2b05cfe7f96e66b490f41573/matplotlib-3.8.4-cp311-cp311-macosx_11_0_arm64.whl sha256: 232ce322bfd020a434caaffbd9a95333f7c2491e59cfc014041d95e38ab90d1c requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.21 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=2.3.1 - - python-dateutil>=2.7 - - importlib-resources>=3.2.0 ; python_version < '3.10' + - contourpy >=1.0.1 + - cycler >=0.10 + - fonttools >=4.22.0 + - kiwisolver >=1.3.1 + - numpy >=1.21 + - packaging >=20.0 + - pillow >=8 + - pyparsing >=2.3.1 + - python-dateutil >=2.7 + - importlib-resources >=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/36/11/62250ea25780d4b59c2c6044ec161235c47cc05a18d0ec0a05657de75b7d/matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661 + url: https://files.pythonhosted.org/packages/80/3b/e363612ac1a514abfb5505aa209dd5b724b3232a6de98710d7759559706a/matplotlib-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: cc4ccdc64e3039fc303defd119658148f2349239871db72cd74e2eeaa9b80b71 requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.21 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=2.3.1 - - python-dateutil>=2.7 - - importlib-resources>=3.2.0 ; python_version < '3.10' + - contourpy >=1.0.1 + - cycler >=0.10 + - fonttools >=4.22.0 + - kiwisolver >=1.3.1 + - numpy >=1.21 + - packaging >=20.0 + - pillow >=8 + - pyparsing >=2.3.1 + - python-dateutil >=2.7 + - importlib-resources >=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib @@ -20518,16 +20518,16 @@ packages: url: https://files.pythonhosted.org/packages/2d/d5/6227732ecab9165586966ccb54301e3164f61b470c954c4cf6940654fbe1/matplotlib-3.8.4-cp311-cp311-win_amd64.whl sha256: 8080d5081a86e690d7688ffa542532e87f224c38a6ed71f8fbed34dd1d9fedae requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.21 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=2.3.1 - - python-dateutil>=2.7 - - importlib-resources>=3.2.0 ; python_version < '3.10' + - contourpy >=1.0.1 + - cycler >=0.10 + - fonttools >=4.22.0 + - kiwisolver >=1.3.1 + - numpy >=1.21 + - packaging >=20.0 + - pillow >=8 + - pyparsing >=2.3.1 + - python-dateutil >=2.7 + - importlib-resources >=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: conda name: maturin @@ -20635,31 +20635,31 @@ packages: - kind: pypi name: mediapipe version: 0.10.9 - url: https://files.pythonhosted.org/packages/a3/3a/f309c6bdebe596cc8c960542e167331cb01ef130ec38f3da46a499718889/mediapipe-0.10.9-cp311-cp311-macosx_11_0_universal2.whl - sha256: 8733735f582e6e6a05bf9b15c48b03a6387a0795793a2530aa1189eecfd33780 + url: https://files.pythonhosted.org/packages/c1/71/38b16b1e4504ff92dff875d455c19e62125fccd73d5ce7e06b560f77fd26/mediapipe-0.10.9-cp311-cp311-macosx_11_0_x86_64.whl + sha256: b7dde54b82732479b9b856c9230b9f7b3da55b0913dde5254a7489e20c2e3c6e requires_dist: - absl-py - - attrs>=19.1.0 - - flatbuffers>=2.0 + - attrs >=19.1.0 + - flatbuffers >=2.0 - matplotlib - numpy - opencv-contrib-python - - protobuf<4,>=3.11 - - sounddevice>=0.4.4 + - protobuf <4, >=3.11 + - sounddevice >=0.4.4 - kind: pypi name: mediapipe version: 0.10.9 - url: https://files.pythonhosted.org/packages/c1/71/38b16b1e4504ff92dff875d455c19e62125fccd73d5ce7e06b560f77fd26/mediapipe-0.10.9-cp311-cp311-macosx_11_0_x86_64.whl - sha256: b7dde54b82732479b9b856c9230b9f7b3da55b0913dde5254a7489e20c2e3c6e + url: https://files.pythonhosted.org/packages/a3/3a/f309c6bdebe596cc8c960542e167331cb01ef130ec38f3da46a499718889/mediapipe-0.10.9-cp311-cp311-macosx_11_0_universal2.whl + sha256: 8733735f582e6e6a05bf9b15c48b03a6387a0795793a2530aa1189eecfd33780 requires_dist: - absl-py - - attrs>=19.1.0 - - flatbuffers>=2.0 + - attrs >=19.1.0 + - flatbuffers >=2.0 - matplotlib - numpy - opencv-contrib-python - - protobuf<4,>=3.11 - - sounddevice>=0.4.4 + - protobuf <4, >=3.11 + - sounddevice >=0.4.4 - kind: pypi name: mediapipe version: 0.10.11 @@ -20667,16 +20667,16 @@ packages: sha256: ea751e043909ba7bbe27e7afdbcdafd79723d50ef4165afcaae431ab428eea13 requires_dist: - absl-py - - attrs>=19.1.0 - - flatbuffers>=2.0 + - attrs >=19.1.0 + - flatbuffers >=2.0 - jax - jaxlib - matplotlib - numpy - torch - opencv-contrib-python - - protobuf<4,>=3.11 - - sounddevice>=0.4.4 + - protobuf <4, >=3.11 + - sounddevice >=0.4.4 - kind: pypi name: mediapipe version: 0.10.11 @@ -20684,14 +20684,14 @@ packages: sha256: 36231eaf23cd795a923a8b015d36bd6e410a8e997c36dd9432db0157b822b181 requires_dist: - absl-py - - attrs>=19.1.0 - - flatbuffers>=2.0 + - attrs >=19.1.0 + - flatbuffers >=2.0 - jax - matplotlib - numpy - opencv-contrib-python - - protobuf<4,>=3.11 - - sounddevice>=0.4.4 + - protobuf <4, >=3.11 + - sounddevice >=0.4.4 - kind: conda name: meilisearch version: 1.5.1 @@ -20790,14 +20790,14 @@ packages: url: https://files.pythonhosted.org/packages/84/17/a936d3dfad84d028ba8539a93167274b7dcd7985e0d9df487e94a62f9428/ml_dtypes-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: e1e2f4237b459a63c97c2c9f449baa637d7e4c20addff6a9bac486f22432f3b6 requires_dist: - - numpy>1.20 - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.23.3 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' + - numpy >1.20 + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.23.3 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' - absl-py ; extra == 'dev' - pytest ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - pylint>=2.6.0 ; extra == 'dev' + - pylint >=2.6.0 ; extra == 'dev' - pyink ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -20806,14 +20806,14 @@ packages: url: https://files.pythonhosted.org/packages/f0/36/290745178e5776f7416818abc1334c1b19afb93c7c87fd1bef3cc99f84ca/ml_dtypes-0.4.0-cp311-cp311-win_amd64.whl sha256: 75b4faf99d0711b81f393db36d210b4255fd419f6f790bc6c1b461f95ffb7a9e requires_dist: - - numpy>1.20 - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.23.3 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' + - numpy >1.20 + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.23.3 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' - absl-py ; extra == 'dev' - pytest ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - pylint>=2.6.0 ; extra == 'dev' + - pylint >=2.6.0 ; extra == 'dev' - pyink ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -20822,14 +20822,14 @@ packages: url: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl sha256: a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c requires_dist: - - pytest>=4.6 ; extra == 'develop' + - pytest >=4.6 ; extra == 'develop' - pycodestyle ; extra == 'develop' - pytest-cov ; extra == 'develop' - codecov ; extra == 'develop' - wheel ; extra == 'develop' - sphinx ; extra == 'docs' - - gmpy2>=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' - - pytest>=4.6 ; extra == 'tests' + - gmpy2 >=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' + - pytest >=4.6 ; extra == 'tests' - kind: conda name: msys2-conda-epoch version: '20160418' @@ -20844,8 +20844,8 @@ packages: - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed + url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e requires_python: '>=3.7' - kind: pypi name: multidict @@ -20856,8 +20856,8 @@ packages: - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e + url: https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed requires_python: '>=3.7' - kind: pypi name: multidict @@ -21262,27 +21262,27 @@ packages: url: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl sha256: 28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2 requires_dist: - - numpy>=1.23 ; extra == 'default' - - scipy!=1.11.0,!=1.11.1,>=1.9 ; extra == 'default' - - matplotlib>=3.6 ; extra == 'default' - - pandas>=1.4 ; extra == 'default' - - changelist==0.5 ; extra == 'developer' - - pre-commit>=3.2 ; extra == 'developer' - - mypy>=1.1 ; extra == 'developer' + - numpy >=1.23 ; extra == 'default' + - scipy !=1.11.0, !=1.11.1, >=1.9 ; extra == 'default' + - matplotlib >=3.6 ; extra == 'default' + - pandas >=1.4 ; extra == 'default' + - changelist ==0.5 ; extra == 'developer' + - pre-commit >=3.2 ; extra == 'developer' + - mypy >=1.1 ; extra == 'developer' - rtoml ; extra == 'developer' - - sphinx>=7 ; extra == 'doc' - - pydata-sphinx-theme>=0.14 ; extra == 'doc' - - sphinx-gallery>=0.14 ; extra == 'doc' - - numpydoc>=1.7 ; extra == 'doc' - - pillow>=9.4 ; extra == 'doc' - - texext>=0.6.7 ; extra == 'doc' - - myst-nb>=1.0 ; extra == 'doc' - - lxml>=4.6 ; extra == 'extra' - - pygraphviz>=1.12 ; extra == 'extra' - - pydot>=2.0 ; extra == 'extra' - - sympy>=1.10 ; extra == 'extra' - - pytest>=7.2 ; extra == 'test' - - pytest-cov>=4.0 ; extra == 'test' + - sphinx >=7 ; extra == 'doc' + - pydata-sphinx-theme >=0.14 ; extra == 'doc' + - sphinx-gallery >=0.14 ; extra == 'doc' + - numpydoc >=1.7 ; extra == 'doc' + - pillow >=9.4 ; extra == 'doc' + - texext >=0.6.7 ; extra == 'doc' + - myst-nb >=1.0 ; extra == 'doc' + - lxml >=4.6 ; extra == 'extra' + - pygraphviz >=1.12 ; extra == 'extra' + - pydot >=2.0 ; extra == 'extra' + - sympy >=1.10 ; extra == 'extra' + - pytest >=7.2 ; extra == 'test' + - pytest-cov >=4.0 ; extra == 'test' requires_python: '>=3.10' - kind: conda name: ninja @@ -21536,25 +21536,25 @@ packages: url: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl sha256: 6492236efa15a460ecb98e7b67562a28b70da006ab0be164e8821177577c0565 requires_dist: - - argcomplete<4.0,>=1.9.4 - - colorlog<7.0.0,>=2.6.1 + - argcomplete <4.0, >=1.9.4 + - colorlog <7.0.0, >=2.6.1 - importlib-metadata ; python_version < '3.8' - - packaging>=20.9 - - tomli>=1 ; python_version < '3.11' - - typing-extensions>=3.7.4 ; python_version < '3.8' - - virtualenv>=20.14.1 + - packaging >=20.9 + - tomli >=1 ; python_version < '3.11' + - typing-extensions >=3.7.4 ; python_version < '3.8' + - virtualenv >=20.14.1 - jinja2 ; extra == 'tox_to_nox' - tox ; extra == 'tox_to_nox' - - uv>=0.1.6 ; extra == 'uv' + - uv >=0.1.6 ; extra == 'uv' requires_python: '>=3.7' - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/54/f2/7d1579037643c874fa73516ea84c07e8d30ea347fb1a88c03b198447655d/numba-0.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - sha256: dd2842fac03be4e5324ebbbd4d2d0c8c0fc6e0df75c09477dd45b288a0777389 + url: https://files.pythonhosted.org/packages/5f/2d/085c21f3086eff0b830e5d03d084a1b4b10dfde0c65feeac6be8c361265c/numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051 requires_dist: - - llvmlite<0.43,>=0.42.0.dev0 - - numpy<1.27,>=1.22 + - llvmlite <0.43, >=0.42.0.dev0 + - numpy <1.27, >=1.22 requires_python: '>=3.9' - kind: pypi name: numba @@ -21562,17 +21562,17 @@ packages: url: https://files.pythonhosted.org/packages/70/7d/0d1419479997319ca72ef735791c2ee50819f9c200adea96142ee7499fae/numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl sha256: 411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966 requires_dist: - - llvmlite<0.43,>=0.42.0.dev0 - - numpy<1.27,>=1.22 + - llvmlite <0.43, >=0.42.0.dev0 + - numpy <1.27, >=1.22 requires_python: '>=3.9' - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/5f/2d/085c21f3086eff0b830e5d03d084a1b4b10dfde0c65feeac6be8c361265c/numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051 + url: https://files.pythonhosted.org/packages/54/f2/7d1579037643c874fa73516ea84c07e8d30ea347fb1a88c03b198447655d/numba-0.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + sha256: dd2842fac03be4e5324ebbbd4d2d0c8c0fc6e0df75c09477dd45b288a0777389 requires_dist: - - llvmlite<0.43,>=0.42.0.dev0 - - numpy<1.27,>=1.22 + - llvmlite <0.43, >=0.42.0.dev0 + - numpy <1.27, >=1.22 requires_python: '>=3.9' - kind: pypi name: numba @@ -21580,14 +21580,14 @@ packages: url: https://files.pythonhosted.org/packages/38/f0/ad848815b0adafcf5f238e728933950034355a8d59969772be1cd57606d8/numba-0.59.1-cp311-cp311-win_amd64.whl sha256: 0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450 requires_dist: - - llvmlite<0.43,>=0.42.0.dev0 - - numpy<1.27,>=1.22 + - llvmlite <0.43, >=0.42.0.dev0 + - numpy <1.27, >=1.22 requires_python: '>=3.9' - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5 + url: https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71 requires_python: '>=3.9' - kind: pypi name: numpy @@ -21598,8 +21598,8 @@ packages: - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71 + url: https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5 requires_python: '>=3.9' - kind: pypi name: numpy @@ -21734,9 +21734,9 @@ packages: path: examples/python/nv12 sha256: c8ca97c5d8c04037cd5eb9a65be7b1e7d667c11d4dba3ee9aad5956ccf926dc4 requires_dist: - - rerun-sdk>=0.10 - - opencv-python - numpy + - opencv-python + - rerun-sdk >=0.10 editable: true - kind: pypi name: nvidia-cublas-cu12 @@ -21826,8 +21826,8 @@ packages: requires_dist: - betterproto[compiler] - numpy - - opencv-python>4.6 - - requests>=2.31,<3 + - opencv-python >4.6 + - requests <3, >=2.31 - rerun-sdk - scipy editable: true @@ -21848,19 +21848,19 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/8a/ea/aea6289058480b93157ad698ecd7f13cae4892ae0a4750abf33b3ac12f91/opencv_contrib_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 89ca1508dd895ae42176640bdd503cac82772f6efa25120738a469a6a69de321 + url: https://files.pythonhosted.org/packages/16/07/bf25df600eeaedddf8fece3f1ff837bf72865b93a03651cf7375ce8172be/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl + sha256: 86078d3653ec3107877536c9178622b1f98b51acf59e554ddbc552785cba55fa requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-contrib-python @@ -21868,33 +21868,33 @@ packages: url: https://files.pythonhosted.org/packages/4c/c3/ccff2e1bfe2bb47a7eaebc4280e93bd2f97ebbe5b3573d48bcfcc0c32387/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl sha256: b52e381144f774b486729ccee69911bdc7d16b5ced4830502e906ad803373ab0 requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-contrib-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/16/07/bf25df600eeaedddf8fece3f1ff837bf72865b93a03651cf7375ce8172be/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl - sha256: 86078d3653ec3107877536c9178622b1f98b51acf59e554ddbc552785cba55fa + url: https://files.pythonhosted.org/packages/8a/ea/aea6289058480b93157ad698ecd7f13cae4892ae0a4750abf33b3ac12f91/opencv_contrib_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 89ca1508dd895ae42176640bdd503cac82772f6efa25120738a469a6a69de321 requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-contrib-python @@ -21902,33 +21902,33 @@ packages: url: https://files.pythonhosted.org/packages/aa/2e/576ac47f21d555b459ca837bb3fb937e50339b8fbfd294945ea2f5290416/opencv_contrib_python-4.9.0.80-cp37-abi3-win_amd64.whl sha256: fdd9b14028f74af8dbb69f90e6e4a956ce2eb5b59947df28ba0b79d337431477 requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl - sha256: 3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0 + url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl + sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3 requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python @@ -21936,67 +21936,67 @@ packages: url: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl sha256: 7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57 + url: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz + sha256: 1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1 requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3 + url: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl + sha256: 3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0 requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz - sha256: 1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1 + url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57 requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python @@ -22004,16 +22004,16 @@ packages: url: https://files.pythonhosted.org/packages/35/69/b657974ddcbba54d59d7d62b01e60a8b815e35f415b996e4d355be0ac7b4/opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl sha256: 7e5f7aa4486651a6ebfa8ed4b594b65bd2d2f41beeb4241a3e4b1b85acbbbadb requires_dist: - - numpy>=1.13.3 ; python_version < '3.7' - - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy>=1.21.2 ; python_version >= '3.10' - - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy>=1.23.5 ; python_version >= '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy>=1.17.0 ; python_version >= '3.7' - - numpy>=1.17.3 ; python_version >= '3.8' - - numpy>=1.19.3 ; python_version >= '3.9' + - numpy >=1.13.3 ; python_version < '3.7' + - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy >=1.21.2 ; python_version >= '3.10' + - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy >=1.23.5 ; python_version >= '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy >=1.17.0 ; python_version >= '3.7' + - numpy >=1.17.3 ; python_version >= '3.8' + - numpy >=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: conda name: openssl @@ -22196,8 +22196,8 @@ packages: url: https://files.pythonhosted.org/packages/bc/19/404708a7e54ad2798907210462fd950c3442ea51acc8790f3da48d2bee8b/opt_einsum-3.3.0-py3-none-any.whl sha256: 2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147 requires_dist: - - numpy>=1.7 - - sphinx==1.2.3 ; extra == 'docs' + - numpy >=1.7 + - sphinx ==1.2.3 ; extra == 'docs' - sphinxcontrib-napoleon ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - numpydoc ; extra == 'docs' @@ -22510,94 +22510,94 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/fc/a5/4d82be566f069d7a9a702dcdf6f9106df0e0b042e738043c0cc7ddd7e3f6/pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee + url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 requires_dist: - - numpy>=1.22.4 ; python_version < '3.11' - - numpy>=1.23.2 ; python_version == '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - python-dateutil>=2.8.2 - - pytz>=2020.1 - - tzdata>=2022.7 - - hypothesis>=6.46.1 ; extra == 'test' - - pytest>=7.3.2 ; extra == 'test' - - pytest-xdist>=2.2.0 ; extra == 'test' - - pyarrow>=10.0.1 ; extra == 'pyarrow' - - bottleneck>=1.3.6 ; extra == 'performance' - - numba>=0.56.4 ; extra == 'performance' - - numexpr>=2.8.4 ; extra == 'performance' - - scipy>=1.10.0 ; extra == 'computation' - - xarray>=2022.12.0 ; extra == 'computation' - - fsspec>=2022.11.0 ; extra == 'fss' - - s3fs>=2022.11.0 ; extra == 'aws' - - gcsfs>=2022.11.0 ; extra == 'gcp' - - pandas-gbq>=0.19.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.0 ; extra == 'excel' - - python-calamine>=0.1.7 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.0.5 ; extra == 'excel' - - pyarrow>=10.0.1 ; extra == 'parquet' - - pyarrow>=10.0.1 ; extra == 'feather' - - tables>=3.8.0 ; extra == 'hdf5' - - pyreadstat>=1.2.0 ; extra == 'spss' - - sqlalchemy>=2.0.0 ; extra == 'postgresql' - - psycopg2>=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.0 ; extra == 'mysql' - - pymysql>=1.0.2 ; extra == 'mysql' - - sqlalchemy>=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' - - beautifulsoup4>=4.11.2 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=4.9.2 ; extra == 'html' - - lxml>=4.9.2 ; extra == 'xml' - - matplotlib>=3.6.3 ; extra == 'plot' - - jinja2>=3.1.2 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.3.0 ; extra == 'clipboard' - - zstandard>=0.19.0 ; extra == 'compression' - - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql>=0.8.0 ; extra == 'all' - - adbc-driver-sqlite>=0.8.0 ; extra == 'all' - - beautifulsoup4>=4.11.2 ; extra == 'all' - - bottleneck>=1.3.6 ; extra == 'all' - - dataframe-api-compat>=0.1.7 ; extra == 'all' - - fastparquet>=2022.12.0 ; extra == 'all' - - fsspec>=2022.11.0 ; extra == 'all' - - gcsfs>=2022.11.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.46.1 ; extra == 'all' - - jinja2>=3.1.2 ; extra == 'all' - - lxml>=4.9.2 ; extra == 'all' - - matplotlib>=3.6.3 ; extra == 'all' - - numba>=0.56.4 ; extra == 'all' - - numexpr>=2.8.4 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.0 ; extra == 'all' - - pandas-gbq>=0.19.0 ; extra == 'all' - - psycopg2>=2.9.6 ; extra == 'all' - - pyarrow>=10.0.1 ; extra == 'all' - - pymysql>=1.0.2 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.0 ; extra == 'all' - - pytest>=7.3.2 ; extra == 'all' - - pytest-xdist>=2.2.0 ; extra == 'all' - - python-calamine>=0.1.7 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.3.0 ; extra == 'all' - - scipy>=1.10.0 ; extra == 'all' - - s3fs>=2022.11.0 ; extra == 'all' - - sqlalchemy>=2.0.0 ; extra == 'all' - - tables>=3.8.0 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2022.12.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.0.5 ; extra == 'all' - - zstandard>=0.19.0 ; extra == 'all' + - numpy >=1.22.4 ; python_version < '3.11' + - numpy >=1.23.2 ; python_version == '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - python-dateutil >=2.8.2 + - pytz >=2020.1 + - tzdata >=2022.7 + - hypothesis >=6.46.1 ; extra == 'test' + - pytest >=7.3.2 ; extra == 'test' + - pytest-xdist >=2.2.0 ; extra == 'test' + - pyarrow >=10.0.1 ; extra == 'pyarrow' + - bottleneck >=1.3.6 ; extra == 'performance' + - numba >=0.56.4 ; extra == 'performance' + - numexpr >=2.8.4 ; extra == 'performance' + - scipy >=1.10.0 ; extra == 'computation' + - xarray >=2022.12.0 ; extra == 'computation' + - fsspec >=2022.11.0 ; extra == 'fss' + - s3fs >=2022.11.0 ; extra == 'aws' + - gcsfs >=2022.11.0 ; extra == 'gcp' + - pandas-gbq >=0.19.0 ; extra == 'gcp' + - odfpy >=1.4.1 ; extra == 'excel' + - openpyxl >=3.1.0 ; extra == 'excel' + - python-calamine >=0.1.7 ; extra == 'excel' + - pyxlsb >=1.0.10 ; extra == 'excel' + - xlrd >=2.0.1 ; extra == 'excel' + - xlsxwriter >=3.0.5 ; extra == 'excel' + - pyarrow >=10.0.1 ; extra == 'parquet' + - pyarrow >=10.0.1 ; extra == 'feather' + - tables >=3.8.0 ; extra == 'hdf5' + - pyreadstat >=1.2.0 ; extra == 'spss' + - sqlalchemy >=2.0.0 ; extra == 'postgresql' + - psycopg2 >=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' + - sqlalchemy >=2.0.0 ; extra == 'mysql' + - pymysql >=1.0.2 ; extra == 'mysql' + - sqlalchemy >=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' + - beautifulsoup4 >=4.11.2 ; extra == 'html' + - html5lib >=1.1 ; extra == 'html' + - lxml >=4.9.2 ; extra == 'html' + - lxml >=4.9.2 ; extra == 'xml' + - matplotlib >=3.6.3 ; extra == 'plot' + - jinja2 >=3.1.2 ; extra == 'output-formatting' + - tabulate >=0.9.0 ; extra == 'output-formatting' + - pyqt5 >=5.15.9 ; extra == 'clipboard' + - qtpy >=2.3.0 ; extra == 'clipboard' + - zstandard >=0.19.0 ; extra == 'compression' + - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql >=0.8.0 ; extra == 'all' + - adbc-driver-sqlite >=0.8.0 ; extra == 'all' + - beautifulsoup4 >=4.11.2 ; extra == 'all' + - bottleneck >=1.3.6 ; extra == 'all' + - dataframe-api-compat >=0.1.7 ; extra == 'all' + - fastparquet >=2022.12.0 ; extra == 'all' + - fsspec >=2022.11.0 ; extra == 'all' + - gcsfs >=2022.11.0 ; extra == 'all' + - html5lib >=1.1 ; extra == 'all' + - hypothesis >=6.46.1 ; extra == 'all' + - jinja2 >=3.1.2 ; extra == 'all' + - lxml >=4.9.2 ; extra == 'all' + - matplotlib >=3.6.3 ; extra == 'all' + - numba >=0.56.4 ; extra == 'all' + - numexpr >=2.8.4 ; extra == 'all' + - odfpy >=1.4.1 ; extra == 'all' + - openpyxl >=3.1.0 ; extra == 'all' + - pandas-gbq >=0.19.0 ; extra == 'all' + - psycopg2 >=2.9.6 ; extra == 'all' + - pyarrow >=10.0.1 ; extra == 'all' + - pymysql >=1.0.2 ; extra == 'all' + - pyqt5 >=5.15.9 ; extra == 'all' + - pyreadstat >=1.2.0 ; extra == 'all' + - pytest >=7.3.2 ; extra == 'all' + - pytest-xdist >=2.2.0 ; extra == 'all' + - python-calamine >=0.1.7 ; extra == 'all' + - pyxlsb >=1.0.10 ; extra == 'all' + - qtpy >=2.3.0 ; extra == 'all' + - scipy >=1.10.0 ; extra == 'all' + - s3fs >=2022.11.0 ; extra == 'all' + - sqlalchemy >=2.0.0 ; extra == 'all' + - tables >=3.8.0 ; extra == 'all' + - tabulate >=0.9.0 ; extra == 'all' + - xarray >=2022.12.0 ; extra == 'all' + - xlrd >=2.0.1 ; extra == 'all' + - xlsxwriter >=3.0.5 ; extra == 'all' + - zstandard >=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas @@ -22605,183 +22605,183 @@ packages: url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 requires_dist: - - numpy>=1.22.4 ; python_version < '3.11' - - numpy>=1.23.2 ; python_version == '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - python-dateutil>=2.8.2 - - pytz>=2020.1 - - tzdata>=2022.7 - - hypothesis>=6.46.1 ; extra == 'test' - - pytest>=7.3.2 ; extra == 'test' - - pytest-xdist>=2.2.0 ; extra == 'test' - - pyarrow>=10.0.1 ; extra == 'pyarrow' - - bottleneck>=1.3.6 ; extra == 'performance' - - numba>=0.56.4 ; extra == 'performance' - - numexpr>=2.8.4 ; extra == 'performance' - - scipy>=1.10.0 ; extra == 'computation' - - xarray>=2022.12.0 ; extra == 'computation' - - fsspec>=2022.11.0 ; extra == 'fss' - - s3fs>=2022.11.0 ; extra == 'aws' - - gcsfs>=2022.11.0 ; extra == 'gcp' - - pandas-gbq>=0.19.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.0 ; extra == 'excel' - - python-calamine>=0.1.7 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.0.5 ; extra == 'excel' - - pyarrow>=10.0.1 ; extra == 'parquet' - - pyarrow>=10.0.1 ; extra == 'feather' - - tables>=3.8.0 ; extra == 'hdf5' - - pyreadstat>=1.2.0 ; extra == 'spss' - - sqlalchemy>=2.0.0 ; extra == 'postgresql' - - psycopg2>=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.0 ; extra == 'mysql' - - pymysql>=1.0.2 ; extra == 'mysql' - - sqlalchemy>=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' - - beautifulsoup4>=4.11.2 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=4.9.2 ; extra == 'html' - - lxml>=4.9.2 ; extra == 'xml' - - matplotlib>=3.6.3 ; extra == 'plot' - - jinja2>=3.1.2 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.3.0 ; extra == 'clipboard' - - zstandard>=0.19.0 ; extra == 'compression' - - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql>=0.8.0 ; extra == 'all' - - adbc-driver-sqlite>=0.8.0 ; extra == 'all' - - beautifulsoup4>=4.11.2 ; extra == 'all' - - bottleneck>=1.3.6 ; extra == 'all' - - dataframe-api-compat>=0.1.7 ; extra == 'all' - - fastparquet>=2022.12.0 ; extra == 'all' - - fsspec>=2022.11.0 ; extra == 'all' - - gcsfs>=2022.11.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.46.1 ; extra == 'all' - - jinja2>=3.1.2 ; extra == 'all' - - lxml>=4.9.2 ; extra == 'all' - - matplotlib>=3.6.3 ; extra == 'all' - - numba>=0.56.4 ; extra == 'all' - - numexpr>=2.8.4 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.0 ; extra == 'all' - - pandas-gbq>=0.19.0 ; extra == 'all' - - psycopg2>=2.9.6 ; extra == 'all' - - pyarrow>=10.0.1 ; extra == 'all' - - pymysql>=1.0.2 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.0 ; extra == 'all' - - pytest>=7.3.2 ; extra == 'all' - - pytest-xdist>=2.2.0 ; extra == 'all' - - python-calamine>=0.1.7 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.3.0 ; extra == 'all' - - scipy>=1.10.0 ; extra == 'all' - - s3fs>=2022.11.0 ; extra == 'all' - - sqlalchemy>=2.0.0 ; extra == 'all' - - tables>=3.8.0 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2022.12.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.0.5 ; extra == 'all' - - zstandard>=0.19.0 ; extra == 'all' + - numpy >=1.22.4 ; python_version < '3.11' + - numpy >=1.23.2 ; python_version == '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - python-dateutil >=2.8.2 + - pytz >=2020.1 + - tzdata >=2022.7 + - hypothesis >=6.46.1 ; extra == 'test' + - pytest >=7.3.2 ; extra == 'test' + - pytest-xdist >=2.2.0 ; extra == 'test' + - pyarrow >=10.0.1 ; extra == 'pyarrow' + - bottleneck >=1.3.6 ; extra == 'performance' + - numba >=0.56.4 ; extra == 'performance' + - numexpr >=2.8.4 ; extra == 'performance' + - scipy >=1.10.0 ; extra == 'computation' + - xarray >=2022.12.0 ; extra == 'computation' + - fsspec >=2022.11.0 ; extra == 'fss' + - s3fs >=2022.11.0 ; extra == 'aws' + - gcsfs >=2022.11.0 ; extra == 'gcp' + - pandas-gbq >=0.19.0 ; extra == 'gcp' + - odfpy >=1.4.1 ; extra == 'excel' + - openpyxl >=3.1.0 ; extra == 'excel' + - python-calamine >=0.1.7 ; extra == 'excel' + - pyxlsb >=1.0.10 ; extra == 'excel' + - xlrd >=2.0.1 ; extra == 'excel' + - xlsxwriter >=3.0.5 ; extra == 'excel' + - pyarrow >=10.0.1 ; extra == 'parquet' + - pyarrow >=10.0.1 ; extra == 'feather' + - tables >=3.8.0 ; extra == 'hdf5' + - pyreadstat >=1.2.0 ; extra == 'spss' + - sqlalchemy >=2.0.0 ; extra == 'postgresql' + - psycopg2 >=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' + - sqlalchemy >=2.0.0 ; extra == 'mysql' + - pymysql >=1.0.2 ; extra == 'mysql' + - sqlalchemy >=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' + - beautifulsoup4 >=4.11.2 ; extra == 'html' + - html5lib >=1.1 ; extra == 'html' + - lxml >=4.9.2 ; extra == 'html' + - lxml >=4.9.2 ; extra == 'xml' + - matplotlib >=3.6.3 ; extra == 'plot' + - jinja2 >=3.1.2 ; extra == 'output-formatting' + - tabulate >=0.9.0 ; extra == 'output-formatting' + - pyqt5 >=5.15.9 ; extra == 'clipboard' + - qtpy >=2.3.0 ; extra == 'clipboard' + - zstandard >=0.19.0 ; extra == 'compression' + - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql >=0.8.0 ; extra == 'all' + - adbc-driver-sqlite >=0.8.0 ; extra == 'all' + - beautifulsoup4 >=4.11.2 ; extra == 'all' + - bottleneck >=1.3.6 ; extra == 'all' + - dataframe-api-compat >=0.1.7 ; extra == 'all' + - fastparquet >=2022.12.0 ; extra == 'all' + - fsspec >=2022.11.0 ; extra == 'all' + - gcsfs >=2022.11.0 ; extra == 'all' + - html5lib >=1.1 ; extra == 'all' + - hypothesis >=6.46.1 ; extra == 'all' + - jinja2 >=3.1.2 ; extra == 'all' + - lxml >=4.9.2 ; extra == 'all' + - matplotlib >=3.6.3 ; extra == 'all' + - numba >=0.56.4 ; extra == 'all' + - numexpr >=2.8.4 ; extra == 'all' + - odfpy >=1.4.1 ; extra == 'all' + - openpyxl >=3.1.0 ; extra == 'all' + - pandas-gbq >=0.19.0 ; extra == 'all' + - psycopg2 >=2.9.6 ; extra == 'all' + - pyarrow >=10.0.1 ; extra == 'all' + - pymysql >=1.0.2 ; extra == 'all' + - pyqt5 >=5.15.9 ; extra == 'all' + - pyreadstat >=1.2.0 ; extra == 'all' + - pytest >=7.3.2 ; extra == 'all' + - pytest-xdist >=2.2.0 ; extra == 'all' + - python-calamine >=0.1.7 ; extra == 'all' + - pyxlsb >=1.0.10 ; extra == 'all' + - qtpy >=2.3.0 ; extra == 'all' + - scipy >=1.10.0 ; extra == 'all' + - s3fs >=2022.11.0 ; extra == 'all' + - sqlalchemy >=2.0.0 ; extra == 'all' + - tables >=3.8.0 ; extra == 'all' + - tabulate >=0.9.0 ; extra == 'all' + - xarray >=2022.12.0 ; extra == 'all' + - xlrd >=2.0.1 ; extra == 'all' + - xlsxwriter >=3.0.5 ; extra == 'all' + - zstandard >=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 + url: https://files.pythonhosted.org/packages/fc/a5/4d82be566f069d7a9a702dcdf6f9106df0e0b042e738043c0cc7ddd7e3f6/pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee requires_dist: - - numpy>=1.22.4 ; python_version < '3.11' - - numpy>=1.23.2 ; python_version == '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - python-dateutil>=2.8.2 - - pytz>=2020.1 - - tzdata>=2022.7 - - hypothesis>=6.46.1 ; extra == 'test' - - pytest>=7.3.2 ; extra == 'test' - - pytest-xdist>=2.2.0 ; extra == 'test' - - pyarrow>=10.0.1 ; extra == 'pyarrow' - - bottleneck>=1.3.6 ; extra == 'performance' - - numba>=0.56.4 ; extra == 'performance' - - numexpr>=2.8.4 ; extra == 'performance' - - scipy>=1.10.0 ; extra == 'computation' - - xarray>=2022.12.0 ; extra == 'computation' - - fsspec>=2022.11.0 ; extra == 'fss' - - s3fs>=2022.11.0 ; extra == 'aws' - - gcsfs>=2022.11.0 ; extra == 'gcp' - - pandas-gbq>=0.19.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.0 ; extra == 'excel' - - python-calamine>=0.1.7 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.0.5 ; extra == 'excel' - - pyarrow>=10.0.1 ; extra == 'parquet' - - pyarrow>=10.0.1 ; extra == 'feather' - - tables>=3.8.0 ; extra == 'hdf5' - - pyreadstat>=1.2.0 ; extra == 'spss' - - sqlalchemy>=2.0.0 ; extra == 'postgresql' - - psycopg2>=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.0 ; extra == 'mysql' - - pymysql>=1.0.2 ; extra == 'mysql' - - sqlalchemy>=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' - - beautifulsoup4>=4.11.2 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=4.9.2 ; extra == 'html' - - lxml>=4.9.2 ; extra == 'xml' - - matplotlib>=3.6.3 ; extra == 'plot' - - jinja2>=3.1.2 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.3.0 ; extra == 'clipboard' - - zstandard>=0.19.0 ; extra == 'compression' - - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql>=0.8.0 ; extra == 'all' - - adbc-driver-sqlite>=0.8.0 ; extra == 'all' - - beautifulsoup4>=4.11.2 ; extra == 'all' - - bottleneck>=1.3.6 ; extra == 'all' - - dataframe-api-compat>=0.1.7 ; extra == 'all' - - fastparquet>=2022.12.0 ; extra == 'all' - - fsspec>=2022.11.0 ; extra == 'all' - - gcsfs>=2022.11.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.46.1 ; extra == 'all' - - jinja2>=3.1.2 ; extra == 'all' - - lxml>=4.9.2 ; extra == 'all' - - matplotlib>=3.6.3 ; extra == 'all' - - numba>=0.56.4 ; extra == 'all' - - numexpr>=2.8.4 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.0 ; extra == 'all' - - pandas-gbq>=0.19.0 ; extra == 'all' - - psycopg2>=2.9.6 ; extra == 'all' - - pyarrow>=10.0.1 ; extra == 'all' - - pymysql>=1.0.2 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.0 ; extra == 'all' - - pytest>=7.3.2 ; extra == 'all' - - pytest-xdist>=2.2.0 ; extra == 'all' - - python-calamine>=0.1.7 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.3.0 ; extra == 'all' - - scipy>=1.10.0 ; extra == 'all' - - s3fs>=2022.11.0 ; extra == 'all' - - sqlalchemy>=2.0.0 ; extra == 'all' - - tables>=3.8.0 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2022.12.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.0.5 ; extra == 'all' - - zstandard>=0.19.0 ; extra == 'all' + - numpy >=1.22.4 ; python_version < '3.11' + - numpy >=1.23.2 ; python_version == '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - python-dateutil >=2.8.2 + - pytz >=2020.1 + - tzdata >=2022.7 + - hypothesis >=6.46.1 ; extra == 'test' + - pytest >=7.3.2 ; extra == 'test' + - pytest-xdist >=2.2.0 ; extra == 'test' + - pyarrow >=10.0.1 ; extra == 'pyarrow' + - bottleneck >=1.3.6 ; extra == 'performance' + - numba >=0.56.4 ; extra == 'performance' + - numexpr >=2.8.4 ; extra == 'performance' + - scipy >=1.10.0 ; extra == 'computation' + - xarray >=2022.12.0 ; extra == 'computation' + - fsspec >=2022.11.0 ; extra == 'fss' + - s3fs >=2022.11.0 ; extra == 'aws' + - gcsfs >=2022.11.0 ; extra == 'gcp' + - pandas-gbq >=0.19.0 ; extra == 'gcp' + - odfpy >=1.4.1 ; extra == 'excel' + - openpyxl >=3.1.0 ; extra == 'excel' + - python-calamine >=0.1.7 ; extra == 'excel' + - pyxlsb >=1.0.10 ; extra == 'excel' + - xlrd >=2.0.1 ; extra == 'excel' + - xlsxwriter >=3.0.5 ; extra == 'excel' + - pyarrow >=10.0.1 ; extra == 'parquet' + - pyarrow >=10.0.1 ; extra == 'feather' + - tables >=3.8.0 ; extra == 'hdf5' + - pyreadstat >=1.2.0 ; extra == 'spss' + - sqlalchemy >=2.0.0 ; extra == 'postgresql' + - psycopg2 >=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' + - sqlalchemy >=2.0.0 ; extra == 'mysql' + - pymysql >=1.0.2 ; extra == 'mysql' + - sqlalchemy >=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' + - beautifulsoup4 >=4.11.2 ; extra == 'html' + - html5lib >=1.1 ; extra == 'html' + - lxml >=4.9.2 ; extra == 'html' + - lxml >=4.9.2 ; extra == 'xml' + - matplotlib >=3.6.3 ; extra == 'plot' + - jinja2 >=3.1.2 ; extra == 'output-formatting' + - tabulate >=0.9.0 ; extra == 'output-formatting' + - pyqt5 >=5.15.9 ; extra == 'clipboard' + - qtpy >=2.3.0 ; extra == 'clipboard' + - zstandard >=0.19.0 ; extra == 'compression' + - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql >=0.8.0 ; extra == 'all' + - adbc-driver-sqlite >=0.8.0 ; extra == 'all' + - beautifulsoup4 >=4.11.2 ; extra == 'all' + - bottleneck >=1.3.6 ; extra == 'all' + - dataframe-api-compat >=0.1.7 ; extra == 'all' + - fastparquet >=2022.12.0 ; extra == 'all' + - fsspec >=2022.11.0 ; extra == 'all' + - gcsfs >=2022.11.0 ; extra == 'all' + - html5lib >=1.1 ; extra == 'all' + - hypothesis >=6.46.1 ; extra == 'all' + - jinja2 >=3.1.2 ; extra == 'all' + - lxml >=4.9.2 ; extra == 'all' + - matplotlib >=3.6.3 ; extra == 'all' + - numba >=0.56.4 ; extra == 'all' + - numexpr >=2.8.4 ; extra == 'all' + - odfpy >=1.4.1 ; extra == 'all' + - openpyxl >=3.1.0 ; extra == 'all' + - pandas-gbq >=0.19.0 ; extra == 'all' + - psycopg2 >=2.9.6 ; extra == 'all' + - pyarrow >=10.0.1 ; extra == 'all' + - pymysql >=1.0.2 ; extra == 'all' + - pyqt5 >=5.15.9 ; extra == 'all' + - pyreadstat >=1.2.0 ; extra == 'all' + - pytest >=7.3.2 ; extra == 'all' + - pytest-xdist >=2.2.0 ; extra == 'all' + - python-calamine >=0.1.7 ; extra == 'all' + - pyxlsb >=1.0.10 ; extra == 'all' + - qtpy >=2.3.0 ; extra == 'all' + - scipy >=1.10.0 ; extra == 'all' + - s3fs >=2022.11.0 ; extra == 'all' + - sqlalchemy >=2.0.0 ; extra == 'all' + - tables >=3.8.0 ; extra == 'all' + - tabulate >=0.9.0 ; extra == 'all' + - xarray >=2022.12.0 ; extra == 'all' + - xlrd >=2.0.1 ; extra == 'all' + - xlsxwriter >=3.0.5 ; extra == 'all' + - zstandard >=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas @@ -22789,91 +22789,91 @@ packages: url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 requires_dist: - - numpy>=1.22.4 ; python_version < '3.11' - - numpy>=1.23.2 ; python_version == '3.11' - - numpy>=1.26.0 ; python_version >= '3.12' - - python-dateutil>=2.8.2 - - pytz>=2020.1 - - tzdata>=2022.7 - - hypothesis>=6.46.1 ; extra == 'test' - - pytest>=7.3.2 ; extra == 'test' - - pytest-xdist>=2.2.0 ; extra == 'test' - - pyarrow>=10.0.1 ; extra == 'pyarrow' - - bottleneck>=1.3.6 ; extra == 'performance' - - numba>=0.56.4 ; extra == 'performance' - - numexpr>=2.8.4 ; extra == 'performance' - - scipy>=1.10.0 ; extra == 'computation' - - xarray>=2022.12.0 ; extra == 'computation' - - fsspec>=2022.11.0 ; extra == 'fss' - - s3fs>=2022.11.0 ; extra == 'aws' - - gcsfs>=2022.11.0 ; extra == 'gcp' - - pandas-gbq>=0.19.0 ; extra == 'gcp' - - odfpy>=1.4.1 ; extra == 'excel' - - openpyxl>=3.1.0 ; extra == 'excel' - - python-calamine>=0.1.7 ; extra == 'excel' - - pyxlsb>=1.0.10 ; extra == 'excel' - - xlrd>=2.0.1 ; extra == 'excel' - - xlsxwriter>=3.0.5 ; extra == 'excel' - - pyarrow>=10.0.1 ; extra == 'parquet' - - pyarrow>=10.0.1 ; extra == 'feather' - - tables>=3.8.0 ; extra == 'hdf5' - - pyreadstat>=1.2.0 ; extra == 'spss' - - sqlalchemy>=2.0.0 ; extra == 'postgresql' - - psycopg2>=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' - - sqlalchemy>=2.0.0 ; extra == 'mysql' - - pymysql>=1.0.2 ; extra == 'mysql' - - sqlalchemy>=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' - - beautifulsoup4>=4.11.2 ; extra == 'html' - - html5lib>=1.1 ; extra == 'html' - - lxml>=4.9.2 ; extra == 'html' - - lxml>=4.9.2 ; extra == 'xml' - - matplotlib>=3.6.3 ; extra == 'plot' - - jinja2>=3.1.2 ; extra == 'output-formatting' - - tabulate>=0.9.0 ; extra == 'output-formatting' - - pyqt5>=5.15.9 ; extra == 'clipboard' - - qtpy>=2.3.0 ; extra == 'clipboard' - - zstandard>=0.19.0 ; extra == 'compression' - - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql>=0.8.0 ; extra == 'all' - - adbc-driver-sqlite>=0.8.0 ; extra == 'all' - - beautifulsoup4>=4.11.2 ; extra == 'all' - - bottleneck>=1.3.6 ; extra == 'all' - - dataframe-api-compat>=0.1.7 ; extra == 'all' - - fastparquet>=2022.12.0 ; extra == 'all' - - fsspec>=2022.11.0 ; extra == 'all' - - gcsfs>=2022.11.0 ; extra == 'all' - - html5lib>=1.1 ; extra == 'all' - - hypothesis>=6.46.1 ; extra == 'all' - - jinja2>=3.1.2 ; extra == 'all' - - lxml>=4.9.2 ; extra == 'all' - - matplotlib>=3.6.3 ; extra == 'all' - - numba>=0.56.4 ; extra == 'all' - - numexpr>=2.8.4 ; extra == 'all' - - odfpy>=1.4.1 ; extra == 'all' - - openpyxl>=3.1.0 ; extra == 'all' - - pandas-gbq>=0.19.0 ; extra == 'all' - - psycopg2>=2.9.6 ; extra == 'all' - - pyarrow>=10.0.1 ; extra == 'all' - - pymysql>=1.0.2 ; extra == 'all' - - pyqt5>=5.15.9 ; extra == 'all' - - pyreadstat>=1.2.0 ; extra == 'all' - - pytest>=7.3.2 ; extra == 'all' - - pytest-xdist>=2.2.0 ; extra == 'all' - - python-calamine>=0.1.7 ; extra == 'all' - - pyxlsb>=1.0.10 ; extra == 'all' - - qtpy>=2.3.0 ; extra == 'all' - - scipy>=1.10.0 ; extra == 'all' - - s3fs>=2022.11.0 ; extra == 'all' - - sqlalchemy>=2.0.0 ; extra == 'all' - - tables>=3.8.0 ; extra == 'all' - - tabulate>=0.9.0 ; extra == 'all' - - xarray>=2022.12.0 ; extra == 'all' - - xlrd>=2.0.1 ; extra == 'all' - - xlsxwriter>=3.0.5 ; extra == 'all' - - zstandard>=0.19.0 ; extra == 'all' + - numpy >=1.22.4 ; python_version < '3.11' + - numpy >=1.23.2 ; python_version == '3.11' + - numpy >=1.26.0 ; python_version >= '3.12' + - python-dateutil >=2.8.2 + - pytz >=2020.1 + - tzdata >=2022.7 + - hypothesis >=6.46.1 ; extra == 'test' + - pytest >=7.3.2 ; extra == 'test' + - pytest-xdist >=2.2.0 ; extra == 'test' + - pyarrow >=10.0.1 ; extra == 'pyarrow' + - bottleneck >=1.3.6 ; extra == 'performance' + - numba >=0.56.4 ; extra == 'performance' + - numexpr >=2.8.4 ; extra == 'performance' + - scipy >=1.10.0 ; extra == 'computation' + - xarray >=2022.12.0 ; extra == 'computation' + - fsspec >=2022.11.0 ; extra == 'fss' + - s3fs >=2022.11.0 ; extra == 'aws' + - gcsfs >=2022.11.0 ; extra == 'gcp' + - pandas-gbq >=0.19.0 ; extra == 'gcp' + - odfpy >=1.4.1 ; extra == 'excel' + - openpyxl >=3.1.0 ; extra == 'excel' + - python-calamine >=0.1.7 ; extra == 'excel' + - pyxlsb >=1.0.10 ; extra == 'excel' + - xlrd >=2.0.1 ; extra == 'excel' + - xlsxwriter >=3.0.5 ; extra == 'excel' + - pyarrow >=10.0.1 ; extra == 'parquet' + - pyarrow >=10.0.1 ; extra == 'feather' + - tables >=3.8.0 ; extra == 'hdf5' + - pyreadstat >=1.2.0 ; extra == 'spss' + - sqlalchemy >=2.0.0 ; extra == 'postgresql' + - psycopg2 >=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' + - sqlalchemy >=2.0.0 ; extra == 'mysql' + - pymysql >=1.0.2 ; extra == 'mysql' + - sqlalchemy >=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' + - beautifulsoup4 >=4.11.2 ; extra == 'html' + - html5lib >=1.1 ; extra == 'html' + - lxml >=4.9.2 ; extra == 'html' + - lxml >=4.9.2 ; extra == 'xml' + - matplotlib >=3.6.3 ; extra == 'plot' + - jinja2 >=3.1.2 ; extra == 'output-formatting' + - tabulate >=0.9.0 ; extra == 'output-formatting' + - pyqt5 >=5.15.9 ; extra == 'clipboard' + - qtpy >=2.3.0 ; extra == 'clipboard' + - zstandard >=0.19.0 ; extra == 'compression' + - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql >=0.8.0 ; extra == 'all' + - adbc-driver-sqlite >=0.8.0 ; extra == 'all' + - beautifulsoup4 >=4.11.2 ; extra == 'all' + - bottleneck >=1.3.6 ; extra == 'all' + - dataframe-api-compat >=0.1.7 ; extra == 'all' + - fastparquet >=2022.12.0 ; extra == 'all' + - fsspec >=2022.11.0 ; extra == 'all' + - gcsfs >=2022.11.0 ; extra == 'all' + - html5lib >=1.1 ; extra == 'all' + - hypothesis >=6.46.1 ; extra == 'all' + - jinja2 >=3.1.2 ; extra == 'all' + - lxml >=4.9.2 ; extra == 'all' + - matplotlib >=3.6.3 ; extra == 'all' + - numba >=0.56.4 ; extra == 'all' + - numexpr >=2.8.4 ; extra == 'all' + - odfpy >=1.4.1 ; extra == 'all' + - openpyxl >=3.1.0 ; extra == 'all' + - pandas-gbq >=0.19.0 ; extra == 'all' + - psycopg2 >=2.9.6 ; extra == 'all' + - pyarrow >=10.0.1 ; extra == 'all' + - pymysql >=1.0.2 ; extra == 'all' + - pyqt5 >=5.15.9 ; extra == 'all' + - pyreadstat >=1.2.0 ; extra == 'all' + - pytest >=7.3.2 ; extra == 'all' + - pytest-xdist >=2.2.0 ; extra == 'all' + - python-calamine >=0.1.7 ; extra == 'all' + - pyxlsb >=1.0.10 ; extra == 'all' + - qtpy >=2.3.0 ; extra == 'all' + - scipy >=1.10.0 ; extra == 'all' + - s3fs >=2022.11.0 ; extra == 'all' + - sqlalchemy >=2.0.0 ; extra == 'all' + - tables >=3.8.0 ; extra == 'all' + - tabulate >=0.9.0 ; extra == 'all' + - xarray >=2022.12.0 ; extra == 'all' + - xlrd >=2.0.1 ; extra == 'all' + - xlsxwriter >=3.0.5 ; extra == 'all' + - zstandard >=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: conda name: patchelf @@ -22904,12 +22904,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22933,7 +22933,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22952,12 +22952,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22976,12 +22976,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23000,12 +23000,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23029,7 +23029,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23053,7 +23053,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23072,12 +23072,12 @@ packages: - kind: pypi name: pillow version: 10.3.0 - url: https://files.pythonhosted.org/packages/81/ff/ad3c942d865f9e45ce84eeb31795e6d4d94e1f1eea51026d5154028510d7/pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: 1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd + url: https://files.pythonhosted.org/packages/e5/51/e4b35e394b4e5ca24983e50361a1db3d7da05b1758074f9c4f5b4be4b22a/pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23105,7 +23105,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23128,12 +23128,12 @@ packages: - kind: pypi name: pillow version: 10.3.0 - url: https://files.pythonhosted.org/packages/e5/51/e4b35e394b4e5ca24983e50361a1db3d7da05b1758074f9c4f5b4be4b22a/pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795 + url: https://files.pythonhosted.org/packages/81/ff/ad3c942d865f9e45ce84eeb31795e6d4d94e1f1eea51026d5154028510d7/pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: 1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23161,7 +23161,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx>=2.4 ; extra == 'docs' + - sphinx >=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23233,15 +23233,15 @@ packages: url: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl sha256: 0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068 requires_dist: - - furo>=2023.9.10 ; extra == 'docs' - - proselint>=0.13 ; extra == 'docs' - - sphinx-autodoc-typehints>=1.25.2 ; extra == 'docs' - - sphinx>=7.2.6 ; extra == 'docs' - - appdirs==1.4.4 ; extra == 'test' - - covdefaults>=2.3 ; extra == 'test' - - pytest-cov>=4.1 ; extra == 'test' - - pytest-mock>=3.12 ; extra == 'test' - - pytest>=7.4.3 ; extra == 'test' + - furo >=2023.9.10 ; extra == 'docs' + - proselint >=0.13 ; extra == 'docs' + - sphinx-autodoc-typehints >=1.25.2 ; extra == 'docs' + - sphinx >=7.2.6 ; extra == 'docs' + - appdirs ==1.4.4 ; extra == 'test' + - covdefaults >=2.3 ; extra == 'test' + - pytest-cov >=4.1 ; extra == 'test' + - pytest-mock >=3.12 ; extra == 'test' + - pytest >=7.4.3 ; extra == 'test' requires_python: '>=3.8' - kind: pypi name: platformdirs @@ -23249,16 +23249,16 @@ packages: url: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl sha256: 17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1 requires_dist: - - furo>=2023.9.10 ; extra == 'docs' - - proselint>=0.13 ; extra == 'docs' - - sphinx-autodoc-typehints>=1.25.2 ; extra == 'docs' - - sphinx>=7.2.6 ; extra == 'docs' - - appdirs==1.4.4 ; extra == 'test' - - covdefaults>=2.3 ; extra == 'test' - - pytest-cov>=4.1 ; extra == 'test' - - pytest-mock>=3.12 ; extra == 'test' - - pytest>=7.4.3 ; extra == 'test' - - mypy>=1.8 ; extra == 'type' + - furo >=2023.9.10 ; extra == 'docs' + - proselint >=0.13 ; extra == 'docs' + - sphinx-autodoc-typehints >=1.25.2 ; extra == 'docs' + - sphinx >=7.2.6 ; extra == 'docs' + - appdirs ==1.4.4 ; extra == 'test' + - covdefaults >=2.3 ; extra == 'test' + - pytest-cov >=4.1 ; extra == 'test' + - pytest-mock >=3.12 ; extra == 'test' + - pytest >=7.4.3 ; extra == 'test' + - mypy >=1.8 ; extra == 'type' requires_python: '>=3.8' - kind: pypi name: plots @@ -23387,8 +23387,8 @@ packages: url: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl sha256: a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c requires_dist: - - protobuf<5.0.0.dev0,>=3.19.0 - - google-api-core[grpc]>=1.31.5 ; extra == 'testing' + - protobuf <5.0.0.dev0, >=3.19.0 + - google-api-core[grpc] >=1.31.5 ; extra == 'testing' requires_python: '>=3.6' - kind: pypi name: protobuf @@ -23399,8 +23399,8 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl - sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 + url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c requires_python: '>=3.8' - kind: pypi name: protobuf @@ -23411,20 +23411,20 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d + url: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl + sha256: 209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8 requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c + url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d requires_python: '>=3.8' - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/c5/4f/0e22aaa246f96d6ac87fe5ebb9c5a693fbe8877f537a1022527c47ca43c5/psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4 + url: https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl + sha256: aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -23447,8 +23447,8 @@ packages: - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl - sha256: aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81 + url: https://files.pythonhosted.org/packages/c5/4f/0e22aaa246f96d6ac87fe5ebb9c5a693fbe8877f537a1022527c47ca43c5/psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -24006,7 +24006,7 @@ packages: url: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl sha256: be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b requires_dist: - - pyasn1<0.7.0,>=0.4.6 + - pyasn1 <0.7.0, >=0.4.6 requires_python: '>=3.8' - kind: pypi name: pycparser @@ -24037,9 +24037,9 @@ packages: sha256: 126bdbae72087d8d038b113aab6b059b4553cb59348e3024bb1a1cae406ace9e requires_dist: - deprecated - - pyjwt[crypto]>=2.4.0 - - pynacl>=1.4.0 - - requests>=2.14.0 + - pyjwt[crypto] >=2.4.0 + - pynacl >=1.4.0 + - requests >=2.14.0 requires_python: '>=3.7' - kind: pypi name: pyglet @@ -24053,7 +24053,7 @@ packages: url: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz sha256: 4f9481f5841b0b8fb7b271b0414b394b503405260a6ee0cf2c330a5420d19b64 requires_dist: - - dataclasses-json>=0.0.25 + - dataclasses-json >=0.0.25 - deprecated - dataclasses ; python_version >= '3.6' and python_version < '3.7' requires_python: '>=3.6' @@ -24064,31 +24064,31 @@ packages: sha256: 59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 requires_dist: - typing-extensions ; python_version <= '3.7' - - cryptography>=3.4.0 ; extra == 'crypto' - - sphinx<5.0.0,>=4.5.0 ; extra == 'dev' + - cryptography >=3.4.0 ; extra == 'crypto' + - sphinx <5.0.0, >=4.5.0 ; extra == 'dev' - sphinx-rtd-theme ; extra == 'dev' - zope-interface ; extra == 'dev' - - cryptography>=3.4.0 ; extra == 'dev' - - pytest<7.0.0,>=6.0.0 ; extra == 'dev' - - coverage[toml]==5.0.4 ; extra == 'dev' + - cryptography >=3.4.0 ; extra == 'dev' + - pytest <7.0.0, >=6.0.0 ; extra == 'dev' + - coverage[toml] ==5.0.4 ; extra == 'dev' - pre-commit ; extra == 'dev' - - sphinx<5.0.0,>=4.5.0 ; extra == 'docs' + - sphinx <5.0.0, >=4.5.0 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - zope-interface ; extra == 'docs' - - pytest<7.0.0,>=6.0.0 ; extra == 'tests' - - coverage[toml]==5.0.4 ; extra == 'tests' + - pytest <7.0.0, >=6.0.0 ; extra == 'tests' + - coverage[toml] ==5.0.4 ; extra == 'tests' requires_python: '>=3.7' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 + url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl + sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 requires_dist: - - cffi>=1.4.1 - - sphinx>=1.6.5 ; extra == 'docs' + - cffi >=1.4.1 + - sphinx >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' - - hypothesis>=3.27.0 ; extra == 'tests' + - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' + - hypothesis >=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl @@ -24096,35 +24096,35 @@ packages: url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 requires_dist: - - cffi>=1.4.1 - - sphinx>=1.6.5 ; extra == 'docs' + - cffi >=1.4.1 + - sphinx >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' - - hypothesis>=3.27.0 ; extra == 'tests' + - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' + - hypothesis >=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d + url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl + sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 requires_dist: - - cffi>=1.4.1 - - sphinx>=1.6.5 ; extra == 'docs' + - cffi >=1.4.1 + - sphinx >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' - - hypothesis>=3.27.0 ; extra == 'tests' + - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' + - hypothesis >=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 + url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl + sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d requires_dist: - - cffi>=1.4.1 - - sphinx>=1.6.5 ; extra == 'docs' + - cffi >=1.4.1 + - sphinx >=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' - - hypothesis>=3.27.0 ; extra == 'tests' + - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' + - hypothesis >=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynndescent @@ -24132,31 +24132,31 @@ packages: url: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl sha256: 9023dc5fea520a4e84d0633ae735db97d2509da927bfa86c897e61f3315473c7 requires_dist: - - scikit-learn>=0.18 - - scipy>=1.0 - - numba>=0.51.2 - - llvmlite>=0.30 - - joblib>=0.11 - - importlib-metadata>=4.8.1 ; python_version < '3.8' + - scikit-learn >=0.18 + - scipy >=1.0 + - numba >=0.51.2 + - llvmlite >=0.30 + - joblib >=0.11 + - importlib-metadata >=4.8.1 ; python_version < '3.8' - kind: pypi name: pyopengl version: 3.1.0 - url: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - sha256: 9b47c5c3a094fa518ca88aeed35ae75834d53e4285512c61879f67a48c94ddaf + url: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + sha256: efa4e39a49b906ccbe66758812ca81ced13a6f26931ab2ba2dba2750c016c0d0 - kind: pypi name: pyopf version: 1.1.1 url: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl sha256: 10971881afcb7ed0dd373f7e88862fa8ad0f70fe4329f2ef5093c152e923831f requires_dist: - - argparse>=1.4.0 - - numpy>=1.24.1 - - pillow>=9.5.0 - - pygltflib>=1.15.3 - - python-dateutil>=2.8.2 - - shapely>=2.0.1 - - tqdm>=4.65.0 - - simplejson>=18.3 ; extra == 'tests' + - argparse >=1.4.0 + - numpy >=1.24.1 + - pillow >=9.5.0 + - pygltflib >=1.15.3 + - python-dateutil >=2.8.2 + - shapely >=2.0.1 + - tqdm >=4.65.0 + - simplejson >=18.3 ; extra == 'tests' requires_python: '>=3.10' - kind: pypi name: pyparsing @@ -24178,8 +24178,8 @@ packages: - networkx - numpy - pillow - - pyglet>=1.4.10 - - pyopengl==3.1.0 + - pyglet >=1.4.10 + - pyopengl ==3.1.0 - scipy - six - trimesh @@ -24576,7 +24576,7 @@ packages: url: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 requires_dist: - - six>=1.5 + - six >=1.5 requires_python: '!=3.0.*,!=3.1.*,!=3.2.*,>=2.7' - kind: conda name: python_abi @@ -24661,8 +24661,8 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 + url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 requires_python: '>=3.6' - kind: pypi name: pyyaml @@ -24673,8 +24673,8 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 + url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 requires_python: '>=3.6' - kind: pypi name: pyyaml @@ -24689,10 +24689,10 @@ packages: sha256: 29d7482ea0dae8ceb7b95c4adeff04bd362cab0842f3f0a9572b2c42013c7656 requires_dist: - numpy - - requests>=2.31,<3 - - rerun-sdk - - trimesh==3.15.2 - pillow + - requests <3, >=2.31 + - rerun-sdk + - trimesh ==3.15.2 editable: true - kind: conda name: rdma-core @@ -24962,8 +24962,8 @@ packages: - kind: pypi name: regex version: 2024.4.16 - url: https://files.pythonhosted.org/packages/8b/9e/05bc55a3295d469ae658e15c7f6edc0f54d39745ad3bd268351ac31be73d/regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0c8290b44d8b0af4e77048646c10c6e3aa583c1ca67f3b5ffb6e06cf0c6f0f89 + url: https://files.pythonhosted.org/packages/fd/b2/8069e8940bc3224d2cef6418aa6de4f2119d59709b841ecab012e3fc1d65/regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd requires_python: '>=3.7' - kind: pypi name: regex @@ -24974,8 +24974,8 @@ packages: - kind: pypi name: regex version: 2024.4.16 - url: https://files.pythonhosted.org/packages/fd/b2/8069e8940bc3224d2cef6418aa6de4f2119d59709b841ecab012e3fc1d65/regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd + url: https://files.pythonhosted.org/packages/8b/9e/05bc55a3295d469ae658e15c7f6edc0f54d39745ad3bd268351ac31be73d/regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0c8290b44d8b0af4e77048646c10c6e3aa583c1ca67f3b5ffb6e06cf0c6f0f89 requires_python: '>=3.7' - kind: pypi name: regex @@ -24989,12 +24989,12 @@ packages: url: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl sha256: 58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f requires_dist: - - charset-normalizer<4,>=2 - - idna<4,>=2.5 - - urllib3<3,>=1.21.1 - - certifi>=2017.4.17 - - pysocks!=1.5.7,>=1.5.6 ; extra == 'socks' - - chardet<6,>=3.0.2 ; extra == 'use_chardet_on_py3' + - charset-normalizer <4, >=2 + - idna <4, >=2.5 + - urllib3 <3, >=1.21.1 + - certifi >=2017.4.17 + - pysocks !=1.5.7, >=1.5.6 ; extra == 'socks' + - chardet <6, >=3.0.2 ; extra == 'use_chardet_on_py3' requires_python: '>=3.7' - kind: conda name: requests @@ -25031,8 +25031,8 @@ packages: sha256: b2ef153b0bedd672c3e0ce89b7be1f64f4344b2b75d71748899faea270383fa2 requires_dist: - numpy - - opencv-python>4.6 - - requests>=2.31,<3 + - opencv-python >4.6 + - requests <3, >=2.31 - rerun-sdk - tqdm editable: true @@ -25103,7 +25103,7 @@ packages: url: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl sha256: 90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 requires_dist: - - pyasn1>=0.1.3 + - pyasn1 >=0.1.3 requires_python: '>=3.6,<4' - kind: conda name: ruff @@ -25285,34 +25285,34 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/d5/85/1e7d2804cbf82204cde462d16f1cb0ff5814b03f559fb46ceaa6b7020db4/safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b + url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a requires_dist: - - numpy>=1.21.6 ; extra == 'numpy' + - numpy >=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch>=1.10 ; extra == 'torch' + - torch >=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow>=2.11.0 ; extra == 'tensorflow' + - tensorflow >=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow==2.11.0 ; extra == 'pinned-tf' + - tensorflow ==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax>=0.6.3 ; extra == 'jax' - - jax>=0.3.25 ; extra == 'jax' - - jaxlib>=0.3.25 ; extra == 'jax' - - mlx>=0.0.9 ; extra == 'mlx' + - flax >=0.6.3 ; extra == 'jax' + - jax >=0.3.25 ; extra == 'jax' + - jaxlib >=0.3.25 ; extra == 'jax' + - mlx >=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' - - black==22.3 ; extra == 'quality' - - click==8.0.4 ; extra == 'quality' - - isort>=5.5.4 ; extra == 'quality' - - flake8>=3.8.3 ; extra == 'quality' + - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' + - black ==22.3 ; extra == 'quality' + - click ==8.0.4 ; extra == 'quality' + - isort >=5.5.4 ; extra == 'quality' + - flake8 >=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py>=3.7.0 ; extra == 'testing' - - huggingface-hub>=0.12.1 ; extra == 'testing' - - setuptools-rust>=1.5.2 ; extra == 'testing' - - pytest>=7.2.0 ; extra == 'testing' - - pytest-benchmark>=4.0.0 ; extra == 'testing' - - hypothesis>=6.70.2 ; extra == 'testing' + - h5py >=3.7.0 ; extra == 'testing' + - huggingface-hub >=0.12.1 ; extra == 'testing' + - setuptools-rust >=1.5.2 ; extra == 'testing' + - pytest >=7.2.0 ; extra == 'testing' + - pytest-benchmark >=4.0.0 ; extra == 'testing' + - hypothesis >=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25328,31 +25328,31 @@ packages: url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe requires_dist: - - numpy>=1.21.6 ; extra == 'numpy' + - numpy >=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch>=1.10 ; extra == 'torch' + - torch >=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow>=2.11.0 ; extra == 'tensorflow' + - tensorflow >=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow==2.11.0 ; extra == 'pinned-tf' + - tensorflow ==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax>=0.6.3 ; extra == 'jax' - - jax>=0.3.25 ; extra == 'jax' - - jaxlib>=0.3.25 ; extra == 'jax' - - mlx>=0.0.9 ; extra == 'mlx' + - flax >=0.6.3 ; extra == 'jax' + - jax >=0.3.25 ; extra == 'jax' + - jaxlib >=0.3.25 ; extra == 'jax' + - mlx >=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' - - black==22.3 ; extra == 'quality' - - click==8.0.4 ; extra == 'quality' - - isort>=5.5.4 ; extra == 'quality' - - flake8>=3.8.3 ; extra == 'quality' + - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' + - black ==22.3 ; extra == 'quality' + - click ==8.0.4 ; extra == 'quality' + - isort >=5.5.4 ; extra == 'quality' + - flake8 >=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py>=3.7.0 ; extra == 'testing' - - huggingface-hub>=0.12.1 ; extra == 'testing' - - setuptools-rust>=1.5.2 ; extra == 'testing' - - pytest>=7.2.0 ; extra == 'testing' - - pytest-benchmark>=4.0.0 ; extra == 'testing' - - hypothesis>=6.70.2 ; extra == 'testing' + - h5py >=3.7.0 ; extra == 'testing' + - huggingface-hub >=0.12.1 ; extra == 'testing' + - setuptools-rust >=1.5.2 ; extra == 'testing' + - pytest >=7.2.0 ; extra == 'testing' + - pytest-benchmark >=4.0.0 ; extra == 'testing' + - hypothesis >=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25365,34 +25365,34 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a + url: https://files.pythonhosted.org/packages/d5/85/1e7d2804cbf82204cde462d16f1cb0ff5814b03f559fb46ceaa6b7020db4/safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b requires_dist: - - numpy>=1.21.6 ; extra == 'numpy' + - numpy >=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch>=1.10 ; extra == 'torch' + - torch >=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow>=2.11.0 ; extra == 'tensorflow' + - tensorflow >=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow==2.11.0 ; extra == 'pinned-tf' + - tensorflow ==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax>=0.6.3 ; extra == 'jax' - - jax>=0.3.25 ; extra == 'jax' - - jaxlib>=0.3.25 ; extra == 'jax' - - mlx>=0.0.9 ; extra == 'mlx' + - flax >=0.6.3 ; extra == 'jax' + - jax >=0.3.25 ; extra == 'jax' + - jaxlib >=0.3.25 ; extra == 'jax' + - mlx >=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' - - black==22.3 ; extra == 'quality' - - click==8.0.4 ; extra == 'quality' - - isort>=5.5.4 ; extra == 'quality' - - flake8>=3.8.3 ; extra == 'quality' + - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' + - black ==22.3 ; extra == 'quality' + - click ==8.0.4 ; extra == 'quality' + - isort >=5.5.4 ; extra == 'quality' + - flake8 >=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py>=3.7.0 ; extra == 'testing' - - huggingface-hub>=0.12.1 ; extra == 'testing' - - setuptools-rust>=1.5.2 ; extra == 'testing' - - pytest>=7.2.0 ; extra == 'testing' - - pytest-benchmark>=4.0.0 ; extra == 'testing' - - hypothesis>=6.70.2 ; extra == 'testing' + - h5py >=3.7.0 ; extra == 'testing' + - huggingface-hub >=0.12.1 ; extra == 'testing' + - setuptools-rust >=1.5.2 ; extra == 'testing' + - pytest >=7.2.0 ; extra == 'testing' + - pytest-benchmark >=4.0.0 ; extra == 'testing' + - hypothesis >=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25408,31 +25408,31 @@ packages: url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 requires_dist: - - numpy>=1.21.6 ; extra == 'numpy' + - numpy >=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch>=1.10 ; extra == 'torch' + - torch >=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow>=2.11.0 ; extra == 'tensorflow' + - tensorflow >=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow==2.11.0 ; extra == 'pinned-tf' + - tensorflow ==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax>=0.6.3 ; extra == 'jax' - - jax>=0.3.25 ; extra == 'jax' - - jaxlib>=0.3.25 ; extra == 'jax' - - mlx>=0.0.9 ; extra == 'mlx' + - flax >=0.6.3 ; extra == 'jax' + - jax >=0.3.25 ; extra == 'jax' + - jaxlib >=0.3.25 ; extra == 'jax' + - mlx >=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' - - black==22.3 ; extra == 'quality' - - click==8.0.4 ; extra == 'quality' - - isort>=5.5.4 ; extra == 'quality' - - flake8>=3.8.3 ; extra == 'quality' + - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' + - black ==22.3 ; extra == 'quality' + - click ==8.0.4 ; extra == 'quality' + - isort >=5.5.4 ; extra == 'quality' + - flake8 >=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py>=3.7.0 ; extra == 'testing' - - huggingface-hub>=0.12.1 ; extra == 'testing' - - setuptools-rust>=1.5.2 ; extra == 'testing' - - pytest>=7.2.0 ; extra == 'testing' - - pytest-benchmark>=4.0.0 ; extra == 'testing' - - hypothesis>=6.70.2 ; extra == 'testing' + - h5py >=3.7.0 ; extra == 'testing' + - huggingface-hub >=0.12.1 ; extra == 'testing' + - setuptools-rust >=1.5.2 ; extra == 'testing' + - pytest >=7.2.0 ; extra == 'testing' + - pytest-benchmark >=4.0.0 ; extra == 'testing' + - hypothesis >=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25445,66 +25445,66 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/0a/40/2c57864acd77c168b96cb6e4e62651b9c98733962793293991ef55e2982c/scikit_image-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fce619a6d84fe40c1208fa579b646e93ce13ef0afc3652a23e9782b2c183291a + url: https://files.pythonhosted.org/packages/78/2b/5f985cf4cf59378f80dc212004a7692b7b49b2a3910c3584d70284db5b89/scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: ee83fdb1843ee938eabdfeb9498623282935ea30aa20dffc5d5d16698efb4b2a requires_dist: - - numpy>=1.23 - - scipy>=1.9 - - networkx>=2.8 - - pillow>=9.1 - - imageio>=2.33 - - tifffile>=2022.8.12 - - packaging>=21 - - lazy-loader>=0.4 - - meson-python>=0.15 ; extra == 'build' + - numpy >=1.23 + - scipy >=1.9 + - networkx >=2.8 + - pillow >=9.1 + - imageio >=2.33 + - tifffile >=2022.8.12 + - packaging >=21 + - lazy-loader >=0.4 + - meson-python >=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools>=67 ; extra == 'build' - - packaging>=21 ; extra == 'build' + - setuptools >=67 ; extra == 'build' + - packaging >=21 ; extra == 'build' - ninja ; extra == 'build' - - cython>=3.0.4 ; extra == 'build' + - cython >=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy>=2.0.0rc1 ; extra == 'build' - - spin==0.8 ; extra == 'build' + - numpy >=2.0.0rc1 ; extra == 'build' + - spin ==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch>=1.6.0 ; extra == 'data' + - pooch >=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx>=7.3 ; extra == 'docs' - - sphinx-gallery>=0.14 ; extra == 'docs' - - numpydoc>=1.7 ; extra == 'docs' + - sphinx >=7.3 ; extra == 'docs' + - sphinx-gallery >=0.14 ; extra == 'docs' + - numpydoc >=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib>=3.6 ; extra == 'docs' - - dask[array]>=2022.9.2 ; extra == 'docs' - - pandas>=1.5 ; extra == 'docs' - - seaborn>=0.11 ; extra == 'docs' - - pooch>=1.6 ; extra == 'docs' - - tifffile>=2022.8.12 ; extra == 'docs' + - matplotlib >=3.6 ; extra == 'docs' + - dask[array] >=2022.9.2 ; extra == 'docs' + - pandas >=1.5 ; extra == 'docs' + - seaborn >=0.11 ; extra == 'docs' + - pooch >=1.6 ; extra == 'docs' + - tifffile >=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly>=5.10 ; extra == 'docs' + - plotly >=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn>=1.1 ; extra == 'docs' - - sphinx-design>=0.5 ; extra == 'docs' - - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' - - pywavelets>=1.1.1 ; extra == 'docs' + - scikit-learn >=1.1 ; extra == 'docs' + - sphinx-design >=0.5 ; extra == 'docs' + - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' + - pywavelets >=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy>=5.0 ; extra == 'optional' - - cloudpickle>=0.2.1 ; extra == 'optional' - - dask[array]>=2021.1.0 ; extra == 'optional' - - matplotlib>=3.6 ; extra == 'optional' - - pooch>=1.6.0 ; extra == 'optional' + - astropy >=5.0 ; extra == 'optional' + - cloudpickle >=0.2.1 ; extra == 'optional' + - dask[array] >=2021.1.0 ; extra == 'optional' + - matplotlib >=3.6 ; extra == 'optional' + - pooch >=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets>=1.1.1 ; extra == 'optional' - - scikit-learn>=1.1 ; extra == 'optional' + - pywavelets >=1.1.1 ; extra == 'optional' + - scikit-learn >=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc>=1.7 ; extra == 'test' - - pooch>=1.6.0 ; extra == 'test' - - pytest>=7.0 ; extra == 'test' - - pytest-cov>=2.11.0 ; extra == 'test' + - numpydoc >=1.7 ; extra == 'test' + - pooch >=1.6.0 ; extra == 'test' + - pytest >=7.0 ; extra == 'test' + - pytest-cov >=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25515,63 +25515,63 @@ packages: url: https://files.pythonhosted.org/packages/b9/cf/9e5828fa29791bf7ac5c3fad3637ebb02f237a1c3de8233bd6a33c2c4aac/scikit_image-0.23.2-cp311-cp311-macosx_12_0_arm64.whl sha256: a158f50d3df4867bbd1c698520ede8bc493e430ad83f54ac1f0d8f57b328779b requires_dist: - - numpy>=1.23 - - scipy>=1.9 - - networkx>=2.8 - - pillow>=9.1 - - imageio>=2.33 - - tifffile>=2022.8.12 - - packaging>=21 - - lazy-loader>=0.4 - - meson-python>=0.15 ; extra == 'build' + - numpy >=1.23 + - scipy >=1.9 + - networkx >=2.8 + - pillow >=9.1 + - imageio >=2.33 + - tifffile >=2022.8.12 + - packaging >=21 + - lazy-loader >=0.4 + - meson-python >=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools>=67 ; extra == 'build' - - packaging>=21 ; extra == 'build' + - setuptools >=67 ; extra == 'build' + - packaging >=21 ; extra == 'build' - ninja ; extra == 'build' - - cython>=3.0.4 ; extra == 'build' + - cython >=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy>=2.0.0rc1 ; extra == 'build' - - spin==0.8 ; extra == 'build' + - numpy >=2.0.0rc1 ; extra == 'build' + - spin ==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch>=1.6.0 ; extra == 'data' + - pooch >=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx>=7.3 ; extra == 'docs' - - sphinx-gallery>=0.14 ; extra == 'docs' - - numpydoc>=1.7 ; extra == 'docs' + - sphinx >=7.3 ; extra == 'docs' + - sphinx-gallery >=0.14 ; extra == 'docs' + - numpydoc >=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib>=3.6 ; extra == 'docs' - - dask[array]>=2022.9.2 ; extra == 'docs' - - pandas>=1.5 ; extra == 'docs' - - seaborn>=0.11 ; extra == 'docs' - - pooch>=1.6 ; extra == 'docs' - - tifffile>=2022.8.12 ; extra == 'docs' + - matplotlib >=3.6 ; extra == 'docs' + - dask[array] >=2022.9.2 ; extra == 'docs' + - pandas >=1.5 ; extra == 'docs' + - seaborn >=0.11 ; extra == 'docs' + - pooch >=1.6 ; extra == 'docs' + - tifffile >=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly>=5.10 ; extra == 'docs' + - plotly >=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn>=1.1 ; extra == 'docs' - - sphinx-design>=0.5 ; extra == 'docs' - - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' - - pywavelets>=1.1.1 ; extra == 'docs' + - scikit-learn >=1.1 ; extra == 'docs' + - sphinx-design >=0.5 ; extra == 'docs' + - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' + - pywavelets >=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy>=5.0 ; extra == 'optional' - - cloudpickle>=0.2.1 ; extra == 'optional' - - dask[array]>=2021.1.0 ; extra == 'optional' - - matplotlib>=3.6 ; extra == 'optional' - - pooch>=1.6.0 ; extra == 'optional' + - astropy >=5.0 ; extra == 'optional' + - cloudpickle >=0.2.1 ; extra == 'optional' + - dask[array] >=2021.1.0 ; extra == 'optional' + - matplotlib >=3.6 ; extra == 'optional' + - pooch >=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets>=1.1.1 ; extra == 'optional' - - scikit-learn>=1.1 ; extra == 'optional' + - pywavelets >=1.1.1 ; extra == 'optional' + - scikit-learn >=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc>=1.7 ; extra == 'test' - - pooch>=1.6.0 ; extra == 'test' - - pytest>=7.0 ; extra == 'test' - - pytest-cov>=2.11.0 ; extra == 'test' + - numpydoc >=1.7 ; extra == 'test' + - pooch >=1.6.0 ; extra == 'test' + - pytest >=7.0 ; extra == 'test' + - pytest-cov >=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25579,66 +25579,66 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/78/2b/5f985cf4cf59378f80dc212004a7692b7b49b2a3910c3584d70284db5b89/scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: ee83fdb1843ee938eabdfeb9498623282935ea30aa20dffc5d5d16698efb4b2a + url: https://files.pythonhosted.org/packages/0a/40/2c57864acd77c168b96cb6e4e62651b9c98733962793293991ef55e2982c/scikit_image-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fce619a6d84fe40c1208fa579b646e93ce13ef0afc3652a23e9782b2c183291a requires_dist: - - numpy>=1.23 - - scipy>=1.9 - - networkx>=2.8 - - pillow>=9.1 - - imageio>=2.33 - - tifffile>=2022.8.12 - - packaging>=21 - - lazy-loader>=0.4 - - meson-python>=0.15 ; extra == 'build' + - numpy >=1.23 + - scipy >=1.9 + - networkx >=2.8 + - pillow >=9.1 + - imageio >=2.33 + - tifffile >=2022.8.12 + - packaging >=21 + - lazy-loader >=0.4 + - meson-python >=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools>=67 ; extra == 'build' - - packaging>=21 ; extra == 'build' + - setuptools >=67 ; extra == 'build' + - packaging >=21 ; extra == 'build' - ninja ; extra == 'build' - - cython>=3.0.4 ; extra == 'build' + - cython >=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy>=2.0.0rc1 ; extra == 'build' - - spin==0.8 ; extra == 'build' + - numpy >=2.0.0rc1 ; extra == 'build' + - spin ==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch>=1.6.0 ; extra == 'data' + - pooch >=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx>=7.3 ; extra == 'docs' - - sphinx-gallery>=0.14 ; extra == 'docs' - - numpydoc>=1.7 ; extra == 'docs' + - sphinx >=7.3 ; extra == 'docs' + - sphinx-gallery >=0.14 ; extra == 'docs' + - numpydoc >=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib>=3.6 ; extra == 'docs' - - dask[array]>=2022.9.2 ; extra == 'docs' - - pandas>=1.5 ; extra == 'docs' - - seaborn>=0.11 ; extra == 'docs' - - pooch>=1.6 ; extra == 'docs' - - tifffile>=2022.8.12 ; extra == 'docs' + - matplotlib >=3.6 ; extra == 'docs' + - dask[array] >=2022.9.2 ; extra == 'docs' + - pandas >=1.5 ; extra == 'docs' + - seaborn >=0.11 ; extra == 'docs' + - pooch >=1.6 ; extra == 'docs' + - tifffile >=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly>=5.10 ; extra == 'docs' + - plotly >=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn>=1.1 ; extra == 'docs' - - sphinx-design>=0.5 ; extra == 'docs' - - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' - - pywavelets>=1.1.1 ; extra == 'docs' + - scikit-learn >=1.1 ; extra == 'docs' + - sphinx-design >=0.5 ; extra == 'docs' + - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' + - pywavelets >=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy>=5.0 ; extra == 'optional' - - cloudpickle>=0.2.1 ; extra == 'optional' - - dask[array]>=2021.1.0 ; extra == 'optional' - - matplotlib>=3.6 ; extra == 'optional' - - pooch>=1.6.0 ; extra == 'optional' + - astropy >=5.0 ; extra == 'optional' + - cloudpickle >=0.2.1 ; extra == 'optional' + - dask[array] >=2021.1.0 ; extra == 'optional' + - matplotlib >=3.6 ; extra == 'optional' + - pooch >=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets>=1.1.1 ; extra == 'optional' - - scikit-learn>=1.1 ; extra == 'optional' + - pywavelets >=1.1.1 ; extra == 'optional' + - scikit-learn >=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc>=1.7 ; extra == 'test' - - pooch>=1.6.0 ; extra == 'test' - - pytest>=7.0 ; extra == 'test' - - pytest-cov>=2.11.0 ; extra == 'test' + - numpydoc >=1.7 ; extra == 'test' + - pooch >=1.6.0 ; extra == 'test' + - pytest >=7.0 ; extra == 'test' + - pytest-cov >=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25649,63 +25649,63 @@ packages: url: https://files.pythonhosted.org/packages/eb/ab/8791ce3063e6d4ac7f8efe3c993fd2e911c9e08f4c7dd05b603eaa2493b2/scikit_image-0.23.2-cp311-cp311-win_amd64.whl sha256: ee65669aa586e110346f567ed5c92d1bd63799a19e951cb83da3f54b0caf7c52 requires_dist: - - numpy>=1.23 - - scipy>=1.9 - - networkx>=2.8 - - pillow>=9.1 - - imageio>=2.33 - - tifffile>=2022.8.12 - - packaging>=21 - - lazy-loader>=0.4 - - meson-python>=0.15 ; extra == 'build' + - numpy >=1.23 + - scipy >=1.9 + - networkx >=2.8 + - pillow >=9.1 + - imageio >=2.33 + - tifffile >=2022.8.12 + - packaging >=21 + - lazy-loader >=0.4 + - meson-python >=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools>=67 ; extra == 'build' - - packaging>=21 ; extra == 'build' + - setuptools >=67 ; extra == 'build' + - packaging >=21 ; extra == 'build' - ninja ; extra == 'build' - - cython>=3.0.4 ; extra == 'build' + - cython >=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy>=2.0.0rc1 ; extra == 'build' - - spin==0.8 ; extra == 'build' + - numpy >=2.0.0rc1 ; extra == 'build' + - spin ==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch>=1.6.0 ; extra == 'data' + - pooch >=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx>=7.3 ; extra == 'docs' - - sphinx-gallery>=0.14 ; extra == 'docs' - - numpydoc>=1.7 ; extra == 'docs' + - sphinx >=7.3 ; extra == 'docs' + - sphinx-gallery >=0.14 ; extra == 'docs' + - numpydoc >=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib>=3.6 ; extra == 'docs' - - dask[array]>=2022.9.2 ; extra == 'docs' - - pandas>=1.5 ; extra == 'docs' - - seaborn>=0.11 ; extra == 'docs' - - pooch>=1.6 ; extra == 'docs' - - tifffile>=2022.8.12 ; extra == 'docs' + - matplotlib >=3.6 ; extra == 'docs' + - dask[array] >=2022.9.2 ; extra == 'docs' + - pandas >=1.5 ; extra == 'docs' + - seaborn >=0.11 ; extra == 'docs' + - pooch >=1.6 ; extra == 'docs' + - tifffile >=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly>=5.10 ; extra == 'docs' + - plotly >=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn>=1.1 ; extra == 'docs' - - sphinx-design>=0.5 ; extra == 'docs' - - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' - - pywavelets>=1.1.1 ; extra == 'docs' + - scikit-learn >=1.1 ; extra == 'docs' + - sphinx-design >=0.5 ; extra == 'docs' + - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' + - pywavelets >=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy>=5.0 ; extra == 'optional' - - cloudpickle>=0.2.1 ; extra == 'optional' - - dask[array]>=2021.1.0 ; extra == 'optional' - - matplotlib>=3.6 ; extra == 'optional' - - pooch>=1.6.0 ; extra == 'optional' + - astropy >=5.0 ; extra == 'optional' + - cloudpickle >=0.2.1 ; extra == 'optional' + - dask[array] >=2021.1.0 ; extra == 'optional' + - matplotlib >=3.6 ; extra == 'optional' + - pooch >=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets>=1.1.1 ; extra == 'optional' - - scikit-learn>=1.1 ; extra == 'optional' + - pywavelets >=1.1.1 ; extra == 'optional' + - scikit-learn >=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc>=1.7 ; extra == 'test' - - pooch>=1.6.0 ; extra == 'test' - - pytest>=7.0 ; extra == 'test' - - pytest-cov>=2.11.0 ; extra == 'test' + - numpydoc >=1.7 ; extra == 'test' + - pooch >=1.6.0 ; extra == 'test' + - pytest >=7.0 ; extra == 'test' + - pytest-cov >=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25713,49 +25713,49 @@ packages: - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/4e/53/14405a47292b59235d811a2af8634aba188ccfd1a38ef4b8042f3447d79a/scikit_learn-1.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 44c62f2b124848a28fd695db5bc4da019287abf390bfce602ddc8aa1ec186aae + url: https://files.pythonhosted.org/packages/59/11/63de36e6933b03490fdfe5cbc9b5a68870a1281d8e705a23b33076dc82fb/scikit_learn-1.4.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 45dee87ac5309bb82e3ea633955030df9bbcb8d2cdb30383c6cd483691c546cc requires_dist: - - numpy>=1.19.5 - - scipy>=1.6.0 - - joblib>=1.2.0 - - threadpoolctl>=2.0.0 - - matplotlib>=3.3.4 ; extra == 'benchmark' - - pandas>=1.1.5 ; extra == 'benchmark' - - memory-profiler>=0.57.0 ; extra == 'benchmark' - - matplotlib>=3.3.4 ; extra == 'docs' - - scikit-image>=0.17.2 ; extra == 'docs' - - pandas>=1.1.5 ; extra == 'docs' - - seaborn>=0.9.0 ; extra == 'docs' - - memory-profiler>=0.57.0 ; extra == 'docs' - - sphinx>=6.0.0 ; extra == 'docs' - - sphinx-copybutton>=0.5.2 ; extra == 'docs' - - sphinx-gallery>=0.15.0 ; extra == 'docs' - - numpydoc>=1.2.0 ; extra == 'docs' - - pillow>=7.1.2 ; extra == 'docs' - - pooch>=1.6.0 ; extra == 'docs' - - sphinx-prompt>=1.3.0 ; extra == 'docs' - - sphinxext-opengraph>=0.4.2 ; extra == 'docs' - - plotly>=5.14.0 ; extra == 'docs' - - matplotlib>=3.3.4 ; extra == 'examples' - - scikit-image>=0.17.2 ; extra == 'examples' - - pandas>=1.1.5 ; extra == 'examples' - - seaborn>=0.9.0 ; extra == 'examples' - - pooch>=1.6.0 ; extra == 'examples' - - plotly>=5.14.0 ; extra == 'examples' - - matplotlib>=3.3.4 ; extra == 'tests' - - scikit-image>=0.17.2 ; extra == 'tests' - - pandas>=1.1.5 ; extra == 'tests' - - pytest>=7.1.2 ; extra == 'tests' - - pytest-cov>=2.9.0 ; extra == 'tests' - - ruff>=0.0.272 ; extra == 'tests' - - black>=23.3.0 ; extra == 'tests' - - mypy>=1.3 ; extra == 'tests' - - pyamg>=4.0.0 ; extra == 'tests' - - polars>=0.19.12 ; extra == 'tests' - - pyarrow>=12.0.0 ; extra == 'tests' - - numpydoc>=1.2.0 ; extra == 'tests' - - pooch>=1.6.0 ; extra == 'tests' + - numpy >=1.19.5 + - scipy >=1.6.0 + - joblib >=1.2.0 + - threadpoolctl >=2.0.0 + - matplotlib >=3.3.4 ; extra == 'benchmark' + - pandas >=1.1.5 ; extra == 'benchmark' + - memory-profiler >=0.57.0 ; extra == 'benchmark' + - matplotlib >=3.3.4 ; extra == 'docs' + - scikit-image >=0.17.2 ; extra == 'docs' + - pandas >=1.1.5 ; extra == 'docs' + - seaborn >=0.9.0 ; extra == 'docs' + - memory-profiler >=0.57.0 ; extra == 'docs' + - sphinx >=6.0.0 ; extra == 'docs' + - sphinx-copybutton >=0.5.2 ; extra == 'docs' + - sphinx-gallery >=0.15.0 ; extra == 'docs' + - numpydoc >=1.2.0 ; extra == 'docs' + - pillow >=7.1.2 ; extra == 'docs' + - pooch >=1.6.0 ; extra == 'docs' + - sphinx-prompt >=1.3.0 ; extra == 'docs' + - sphinxext-opengraph >=0.4.2 ; extra == 'docs' + - plotly >=5.14.0 ; extra == 'docs' + - matplotlib >=3.3.4 ; extra == 'examples' + - scikit-image >=0.17.2 ; extra == 'examples' + - pandas >=1.1.5 ; extra == 'examples' + - seaborn >=0.9.0 ; extra == 'examples' + - pooch >=1.6.0 ; extra == 'examples' + - plotly >=5.14.0 ; extra == 'examples' + - matplotlib >=3.3.4 ; extra == 'tests' + - scikit-image >=0.17.2 ; extra == 'tests' + - pandas >=1.1.5 ; extra == 'tests' + - pytest >=7.1.2 ; extra == 'tests' + - pytest-cov >=2.9.0 ; extra == 'tests' + - ruff >=0.0.272 ; extra == 'tests' + - black >=23.3.0 ; extra == 'tests' + - mypy >=1.3 ; extra == 'tests' + - pyamg >=4.0.0 ; extra == 'tests' + - polars >=0.19.12 ; extra == 'tests' + - pyarrow >=12.0.0 ; extra == 'tests' + - numpydoc >=1.2.0 ; extra == 'tests' + - pooch >=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn @@ -25763,93 +25763,93 @@ packages: url: https://files.pythonhosted.org/packages/f2/30/1299e84d2ba3bc735baf17cebbf5b9d55144243c41b3ec6559ce3cf61e23/scikit_learn-1.4.2-cp311-cp311-macosx_12_0_arm64.whl sha256: 1d0b25d9c651fd050555aadd57431b53d4cf664e749069da77f3d52c5ad14b3b requires_dist: - - numpy>=1.19.5 - - scipy>=1.6.0 - - joblib>=1.2.0 - - threadpoolctl>=2.0.0 - - matplotlib>=3.3.4 ; extra == 'benchmark' - - pandas>=1.1.5 ; extra == 'benchmark' - - memory-profiler>=0.57.0 ; extra == 'benchmark' - - matplotlib>=3.3.4 ; extra == 'docs' - - scikit-image>=0.17.2 ; extra == 'docs' - - pandas>=1.1.5 ; extra == 'docs' - - seaborn>=0.9.0 ; extra == 'docs' - - memory-profiler>=0.57.0 ; extra == 'docs' - - sphinx>=6.0.0 ; extra == 'docs' - - sphinx-copybutton>=0.5.2 ; extra == 'docs' - - sphinx-gallery>=0.15.0 ; extra == 'docs' - - numpydoc>=1.2.0 ; extra == 'docs' - - pillow>=7.1.2 ; extra == 'docs' - - pooch>=1.6.0 ; extra == 'docs' - - sphinx-prompt>=1.3.0 ; extra == 'docs' - - sphinxext-opengraph>=0.4.2 ; extra == 'docs' - - plotly>=5.14.0 ; extra == 'docs' - - matplotlib>=3.3.4 ; extra == 'examples' - - scikit-image>=0.17.2 ; extra == 'examples' - - pandas>=1.1.5 ; extra == 'examples' - - seaborn>=0.9.0 ; extra == 'examples' - - pooch>=1.6.0 ; extra == 'examples' - - plotly>=5.14.0 ; extra == 'examples' - - matplotlib>=3.3.4 ; extra == 'tests' - - scikit-image>=0.17.2 ; extra == 'tests' - - pandas>=1.1.5 ; extra == 'tests' - - pytest>=7.1.2 ; extra == 'tests' - - pytest-cov>=2.9.0 ; extra == 'tests' - - ruff>=0.0.272 ; extra == 'tests' - - black>=23.3.0 ; extra == 'tests' - - mypy>=1.3 ; extra == 'tests' - - pyamg>=4.0.0 ; extra == 'tests' - - polars>=0.19.12 ; extra == 'tests' - - pyarrow>=12.0.0 ; extra == 'tests' - - numpydoc>=1.2.0 ; extra == 'tests' - - pooch>=1.6.0 ; extra == 'tests' + - numpy >=1.19.5 + - scipy >=1.6.0 + - joblib >=1.2.0 + - threadpoolctl >=2.0.0 + - matplotlib >=3.3.4 ; extra == 'benchmark' + - pandas >=1.1.5 ; extra == 'benchmark' + - memory-profiler >=0.57.0 ; extra == 'benchmark' + - matplotlib >=3.3.4 ; extra == 'docs' + - scikit-image >=0.17.2 ; extra == 'docs' + - pandas >=1.1.5 ; extra == 'docs' + - seaborn >=0.9.0 ; extra == 'docs' + - memory-profiler >=0.57.0 ; extra == 'docs' + - sphinx >=6.0.0 ; extra == 'docs' + - sphinx-copybutton >=0.5.2 ; extra == 'docs' + - sphinx-gallery >=0.15.0 ; extra == 'docs' + - numpydoc >=1.2.0 ; extra == 'docs' + - pillow >=7.1.2 ; extra == 'docs' + - pooch >=1.6.0 ; extra == 'docs' + - sphinx-prompt >=1.3.0 ; extra == 'docs' + - sphinxext-opengraph >=0.4.2 ; extra == 'docs' + - plotly >=5.14.0 ; extra == 'docs' + - matplotlib >=3.3.4 ; extra == 'examples' + - scikit-image >=0.17.2 ; extra == 'examples' + - pandas >=1.1.5 ; extra == 'examples' + - seaborn >=0.9.0 ; extra == 'examples' + - pooch >=1.6.0 ; extra == 'examples' + - plotly >=5.14.0 ; extra == 'examples' + - matplotlib >=3.3.4 ; extra == 'tests' + - scikit-image >=0.17.2 ; extra == 'tests' + - pandas >=1.1.5 ; extra == 'tests' + - pytest >=7.1.2 ; extra == 'tests' + - pytest-cov >=2.9.0 ; extra == 'tests' + - ruff >=0.0.272 ; extra == 'tests' + - black >=23.3.0 ; extra == 'tests' + - mypy >=1.3 ; extra == 'tests' + - pyamg >=4.0.0 ; extra == 'tests' + - polars >=0.19.12 ; extra == 'tests' + - pyarrow >=12.0.0 ; extra == 'tests' + - numpydoc >=1.2.0 ; extra == 'tests' + - pooch >=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/59/11/63de36e6933b03490fdfe5cbc9b5a68870a1281d8e705a23b33076dc82fb/scikit_learn-1.4.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 45dee87ac5309bb82e3ea633955030df9bbcb8d2cdb30383c6cd483691c546cc + url: https://files.pythonhosted.org/packages/4e/53/14405a47292b59235d811a2af8634aba188ccfd1a38ef4b8042f3447d79a/scikit_learn-1.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 44c62f2b124848a28fd695db5bc4da019287abf390bfce602ddc8aa1ec186aae requires_dist: - - numpy>=1.19.5 - - scipy>=1.6.0 - - joblib>=1.2.0 - - threadpoolctl>=2.0.0 - - matplotlib>=3.3.4 ; extra == 'benchmark' - - pandas>=1.1.5 ; extra == 'benchmark' - - memory-profiler>=0.57.0 ; extra == 'benchmark' - - matplotlib>=3.3.4 ; extra == 'docs' - - scikit-image>=0.17.2 ; extra == 'docs' - - pandas>=1.1.5 ; extra == 'docs' - - seaborn>=0.9.0 ; extra == 'docs' - - memory-profiler>=0.57.0 ; extra == 'docs' - - sphinx>=6.0.0 ; extra == 'docs' - - sphinx-copybutton>=0.5.2 ; extra == 'docs' - - sphinx-gallery>=0.15.0 ; extra == 'docs' - - numpydoc>=1.2.0 ; extra == 'docs' - - pillow>=7.1.2 ; extra == 'docs' - - pooch>=1.6.0 ; extra == 'docs' - - sphinx-prompt>=1.3.0 ; extra == 'docs' - - sphinxext-opengraph>=0.4.2 ; extra == 'docs' - - plotly>=5.14.0 ; extra == 'docs' - - matplotlib>=3.3.4 ; extra == 'examples' - - scikit-image>=0.17.2 ; extra == 'examples' - - pandas>=1.1.5 ; extra == 'examples' - - seaborn>=0.9.0 ; extra == 'examples' - - pooch>=1.6.0 ; extra == 'examples' - - plotly>=5.14.0 ; extra == 'examples' - - matplotlib>=3.3.4 ; extra == 'tests' - - scikit-image>=0.17.2 ; extra == 'tests' - - pandas>=1.1.5 ; extra == 'tests' - - pytest>=7.1.2 ; extra == 'tests' - - pytest-cov>=2.9.0 ; extra == 'tests' - - ruff>=0.0.272 ; extra == 'tests' - - black>=23.3.0 ; extra == 'tests' - - mypy>=1.3 ; extra == 'tests' - - pyamg>=4.0.0 ; extra == 'tests' - - polars>=0.19.12 ; extra == 'tests' - - pyarrow>=12.0.0 ; extra == 'tests' - - numpydoc>=1.2.0 ; extra == 'tests' - - pooch>=1.6.0 ; extra == 'tests' + - numpy >=1.19.5 + - scipy >=1.6.0 + - joblib >=1.2.0 + - threadpoolctl >=2.0.0 + - matplotlib >=3.3.4 ; extra == 'benchmark' + - pandas >=1.1.5 ; extra == 'benchmark' + - memory-profiler >=0.57.0 ; extra == 'benchmark' + - matplotlib >=3.3.4 ; extra == 'docs' + - scikit-image >=0.17.2 ; extra == 'docs' + - pandas >=1.1.5 ; extra == 'docs' + - seaborn >=0.9.0 ; extra == 'docs' + - memory-profiler >=0.57.0 ; extra == 'docs' + - sphinx >=6.0.0 ; extra == 'docs' + - sphinx-copybutton >=0.5.2 ; extra == 'docs' + - sphinx-gallery >=0.15.0 ; extra == 'docs' + - numpydoc >=1.2.0 ; extra == 'docs' + - pillow >=7.1.2 ; extra == 'docs' + - pooch >=1.6.0 ; extra == 'docs' + - sphinx-prompt >=1.3.0 ; extra == 'docs' + - sphinxext-opengraph >=0.4.2 ; extra == 'docs' + - plotly >=5.14.0 ; extra == 'docs' + - matplotlib >=3.3.4 ; extra == 'examples' + - scikit-image >=0.17.2 ; extra == 'examples' + - pandas >=1.1.5 ; extra == 'examples' + - seaborn >=0.9.0 ; extra == 'examples' + - pooch >=1.6.0 ; extra == 'examples' + - plotly >=5.14.0 ; extra == 'examples' + - matplotlib >=3.3.4 ; extra == 'tests' + - scikit-image >=0.17.2 ; extra == 'tests' + - pandas >=1.1.5 ; extra == 'tests' + - pytest >=7.1.2 ; extra == 'tests' + - pytest-cov >=2.9.0 ; extra == 'tests' + - ruff >=0.0.272 ; extra == 'tests' + - black >=23.3.0 ; extra == 'tests' + - mypy >=1.3 ; extra == 'tests' + - pyamg >=4.0.0 ; extra == 'tests' + - polars >=0.19.12 ; extra == 'tests' + - pyarrow >=12.0.0 ; extra == 'tests' + - numpydoc >=1.2.0 ; extra == 'tests' + - pooch >=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn @@ -25857,54 +25857,54 @@ packages: url: https://files.pythonhosted.org/packages/79/3d/02d5d3ed359498fec3abdf65407d3c07e3b8765af17464969055aaec5171/scikit_learn-1.4.2-cp311-cp311-win_amd64.whl sha256: 5cd7b524115499b18b63f0c96f4224eb885564937a0b3477531b2b63ce331904 requires_dist: - - numpy>=1.19.5 - - scipy>=1.6.0 - - joblib>=1.2.0 - - threadpoolctl>=2.0.0 - - matplotlib>=3.3.4 ; extra == 'benchmark' - - pandas>=1.1.5 ; extra == 'benchmark' - - memory-profiler>=0.57.0 ; extra == 'benchmark' - - matplotlib>=3.3.4 ; extra == 'docs' - - scikit-image>=0.17.2 ; extra == 'docs' - - pandas>=1.1.5 ; extra == 'docs' - - seaborn>=0.9.0 ; extra == 'docs' - - memory-profiler>=0.57.0 ; extra == 'docs' - - sphinx>=6.0.0 ; extra == 'docs' - - sphinx-copybutton>=0.5.2 ; extra == 'docs' - - sphinx-gallery>=0.15.0 ; extra == 'docs' - - numpydoc>=1.2.0 ; extra == 'docs' - - pillow>=7.1.2 ; extra == 'docs' - - pooch>=1.6.0 ; extra == 'docs' - - sphinx-prompt>=1.3.0 ; extra == 'docs' - - sphinxext-opengraph>=0.4.2 ; extra == 'docs' - - plotly>=5.14.0 ; extra == 'docs' - - matplotlib>=3.3.4 ; extra == 'examples' - - scikit-image>=0.17.2 ; extra == 'examples' - - pandas>=1.1.5 ; extra == 'examples' - - seaborn>=0.9.0 ; extra == 'examples' - - pooch>=1.6.0 ; extra == 'examples' - - plotly>=5.14.0 ; extra == 'examples' - - matplotlib>=3.3.4 ; extra == 'tests' - - scikit-image>=0.17.2 ; extra == 'tests' - - pandas>=1.1.5 ; extra == 'tests' - - pytest>=7.1.2 ; extra == 'tests' - - pytest-cov>=2.9.0 ; extra == 'tests' - - ruff>=0.0.272 ; extra == 'tests' - - black>=23.3.0 ; extra == 'tests' - - mypy>=1.3 ; extra == 'tests' - - pyamg>=4.0.0 ; extra == 'tests' - - polars>=0.19.12 ; extra == 'tests' - - pyarrow>=12.0.0 ; extra == 'tests' - - numpydoc>=1.2.0 ; extra == 'tests' - - pooch>=1.6.0 ; extra == 'tests' + - numpy >=1.19.5 + - scipy >=1.6.0 + - joblib >=1.2.0 + - threadpoolctl >=2.0.0 + - matplotlib >=3.3.4 ; extra == 'benchmark' + - pandas >=1.1.5 ; extra == 'benchmark' + - memory-profiler >=0.57.0 ; extra == 'benchmark' + - matplotlib >=3.3.4 ; extra == 'docs' + - scikit-image >=0.17.2 ; extra == 'docs' + - pandas >=1.1.5 ; extra == 'docs' + - seaborn >=0.9.0 ; extra == 'docs' + - memory-profiler >=0.57.0 ; extra == 'docs' + - sphinx >=6.0.0 ; extra == 'docs' + - sphinx-copybutton >=0.5.2 ; extra == 'docs' + - sphinx-gallery >=0.15.0 ; extra == 'docs' + - numpydoc >=1.2.0 ; extra == 'docs' + - pillow >=7.1.2 ; extra == 'docs' + - pooch >=1.6.0 ; extra == 'docs' + - sphinx-prompt >=1.3.0 ; extra == 'docs' + - sphinxext-opengraph >=0.4.2 ; extra == 'docs' + - plotly >=5.14.0 ; extra == 'docs' + - matplotlib >=3.3.4 ; extra == 'examples' + - scikit-image >=0.17.2 ; extra == 'examples' + - pandas >=1.1.5 ; extra == 'examples' + - seaborn >=0.9.0 ; extra == 'examples' + - pooch >=1.6.0 ; extra == 'examples' + - plotly >=5.14.0 ; extra == 'examples' + - matplotlib >=3.3.4 ; extra == 'tests' + - scikit-image >=0.17.2 ; extra == 'tests' + - pandas >=1.1.5 ; extra == 'tests' + - pytest >=7.1.2 ; extra == 'tests' + - pytest-cov >=2.9.0 ; extra == 'tests' + - ruff >=0.0.272 ; extra == 'tests' + - black >=23.3.0 ; extra == 'tests' + - mypy >=1.3 ; extra == 'tests' + - pyamg >=4.0.0 ; extra == 'tests' + - polars >=0.19.12 ; extra == 'tests' + - pyarrow >=12.0.0 ; extra == 'tests' + - numpydoc >=1.2.0 ; extra == 'tests' + - pooch >=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/e8/fb/e5955e2ddbdf2baee461eb53ec8d0adedd20a6dfc5510ef8d5e7e44ba461/scipy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 9ff7dad5d24a8045d836671e082a490848e8639cabb3dbdacb29f943a678683d + url: https://files.pythonhosted.org/packages/be/e3/236639c51636ec7e678f2aa608fe89acb9d02ef64e1fe1d8eb40373bc62b/scipy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 0fbcf8abaf5aa2dc8d6400566c1a727aed338b5fe880cde64907596a89d576fa requires_dist: - - numpy<2.3,>=1.22.4 + - numpy <2.3, >=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25915,26 +25915,26 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' + - hypothesis >=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx>=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' + - sphinx >=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' + - sphinx-design >=0.4.0 ; extra == 'doc' + - matplotlib >=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' + - cython-lint >=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit>=0.36.0 ; extra == 'dev' + - doit >=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -25943,7 +25943,7 @@ packages: url: https://files.pythonhosted.org/packages/51/b6/188c8974d747b2998d672040c5b62a635a72240c515dc4577a28e1dedc80/scipy-1.13.0-cp311-cp311-macosx_12_0_arm64.whl sha256: 5e4a756355522eb60fcd61f8372ac2549073c8788f6114449b37e9e8104f15a5 requires_dist: - - numpy<2.3,>=1.22.4 + - numpy <2.3, >=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25954,35 +25954,35 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' + - hypothesis >=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx>=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' + - sphinx >=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' + - sphinx-design >=0.4.0 ; extra == 'doc' + - matplotlib >=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' + - cython-lint >=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit>=0.36.0 ; extra == 'dev' + - doit >=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/be/e3/236639c51636ec7e678f2aa608fe89acb9d02ef64e1fe1d8eb40373bc62b/scipy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 0fbcf8abaf5aa2dc8d6400566c1a727aed338b5fe880cde64907596a89d576fa + url: https://files.pythonhosted.org/packages/e8/fb/e5955e2ddbdf2baee461eb53ec8d0adedd20a6dfc5510ef8d5e7e44ba461/scipy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 9ff7dad5d24a8045d836671e082a490848e8639cabb3dbdacb29f943a678683d requires_dist: - - numpy<2.3,>=1.22.4 + - numpy <2.3, >=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25993,26 +25993,26 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' + - hypothesis >=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx>=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' + - sphinx >=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' + - sphinx-design >=0.4.0 ; extra == 'doc' + - matplotlib >=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' + - cython-lint >=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit>=0.36.0 ; extra == 'dev' + - doit >=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -26021,7 +26021,7 @@ packages: url: https://files.pythonhosted.org/packages/d4/a1/d4adf25b6d2bef8d0ad1682829dcfcba97f3f96bb5b6f137bc3e41003cc7/scipy-1.13.0-cp311-cp311-win_amd64.whl sha256: a2f471de4d01200718b2b8927f7d76b5d9bde18047ea0fa8bd15c5ba3f26a1d6 requires_dist: - - numpy<2.3,>=1.22.4 + - numpy <2.3, >=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -26032,26 +26032,26 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis>=6.30 ; extra == 'test' + - hypothesis >=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx>=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' - - sphinx-design>=0.4.0 ; extra == 'doc' - - matplotlib>=3.5 ; extra == 'doc' + - sphinx >=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' + - sphinx-design >=0.4.0 ; extra == 'doc' + - matplotlib >=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint>=0.12.2 ; extra == 'dev' + - cython-lint >=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit>=0.36.0 ; extra == 'dev' + - doit >=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -26072,14 +26072,14 @@ packages: name: segment-anything-model version: 0.1.0 path: examples/python/segment_anything_model - sha256: 753b1345fb994adb562c3eb8199c98f90cea10ac5f5a394575854d959ba22424 + sha256: 85bc241bedf212c63a39d0251a9dcc0fb3a435087a024d4eafd7f49342a75926 requires_dist: - - segment-anything @ git+https://github.com/facebookresearch/segment-anything.git - numpy - opencv-python - - requests>=2.31,<3 + - requests <3, >=2.31 - rerun-sdk - - torch + - segment-anything @ git+https://github.com/facebookresearch/segment-anything.git + - torch ==2.2.2 - torchvision - tqdm editable: true @@ -26158,11 +26158,11 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/d5/fb/bcf6a8164ed307c99f1a8fabe5acd86ac99a33f52530a3ca84b0936f95bd/shapely-2.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 4310b5494271e18580d61022c0857eb85d30510d88606fa3b8314790df7f367d + url: https://files.pythonhosted.org/packages/93/fd/b205661ed60294a344406fb04227042fcede9501e81ee1e7018e9159455a/shapely-2.0.4-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7 requires_dist: - - numpy<3,>=1.14 - - numpydoc==1.1.* ; extra == 'docs' + - numpy <3, >=1.14 + - numpydoc ==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26176,8 +26176,8 @@ packages: url: https://files.pythonhosted.org/packages/2a/fb/e3f72b10a90e26bb1a92a38b3f30f3074ebac6d532f87848ac09c3e8a73b/shapely-2.0.4-cp311-cp311-macosx_11_0_arm64.whl sha256: 58b0ecc505bbe49a99551eea3f2e8a9b3b24b3edd2a4de1ac0dc17bc75c9ec07 requires_dist: - - numpy<3,>=1.14 - - numpydoc==1.1.* ; extra == 'docs' + - numpy <3, >=1.14 + - numpydoc ==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26188,11 +26188,11 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/93/fd/b205661ed60294a344406fb04227042fcede9501e81ee1e7018e9159455a/shapely-2.0.4-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7 + url: https://files.pythonhosted.org/packages/d5/fb/bcf6a8164ed307c99f1a8fabe5acd86ac99a33f52530a3ca84b0936f95bd/shapely-2.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 4310b5494271e18580d61022c0857eb85d30510d88606fa3b8314790df7f367d requires_dist: - - numpy<3,>=1.14 - - numpydoc==1.1.* ; extra == 'docs' + - numpy <3, >=1.14 + - numpydoc ==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26206,8 +26206,8 @@ packages: url: https://files.pythonhosted.org/packages/6a/5c/3330f499ca860f0b92db4ceaebd7090096a83c1ea3ae7d8d4c6111761b82/shapely-2.0.4-cp311-cp311-win_amd64.whl sha256: c52ed79f683f721b69a10fb9e3d940a468203f5054927215586c5d49a072de8d requires_dist: - - numpy<3,>=1.14 - - numpydoc==1.1.* ; extra == 'docs' + - numpy <3, >=1.14 + - numpydoc ==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26231,10 +26231,10 @@ packages: requires_dist: - mesh-to-sdf @ git+https://github.com/marian42/mesh_to_sdf.git - numpy - - requests>=2.31,<3 + - requests <3, >=2.31 - rerun-sdk - - scikit-learn>=1.1.3 - - trimesh==3.15.2 + - scikit-learn >=1.1.3 + - trimesh ==3.15.2 editable: true - kind: conda name: sigtool @@ -26445,19 +26445,19 @@ packages: - kind: pypi name: sounddevice version: 0.4.6 - url: https://files.pythonhosted.org/packages/d7/d5/f0a0aba169f23657c7af3f0c878db7413a9a3b113026fc759862a697c611/sounddevice-0.4.6-py3-none-any.whl - sha256: 5de768ba6fe56ad2b5aaa2eea794b76b73e427961c95acad2ee2ed7f866a4b20 + url: https://files.pythonhosted.org/packages/24/5a/c0b9066fcaf783054b3f35254938dcba2d8cf02576ebdc56b6b4e85661f2/sounddevice-0.4.6-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl + sha256: 8b0b806c205dd3e3cd5a97262b2482624fd21db7d47083b887090148a08051c8 requires_dist: - - cffi>=1.0 + - cffi >=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi name: sounddevice version: 0.4.6 - url: https://files.pythonhosted.org/packages/24/5a/c0b9066fcaf783054b3f35254938dcba2d8cf02576ebdc56b6b4e85661f2/sounddevice-0.4.6-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl - sha256: 8b0b806c205dd3e3cd5a97262b2482624fd21db7d47083b887090148a08051c8 + url: https://files.pythonhosted.org/packages/d7/d5/f0a0aba169f23657c7af3f0c878db7413a9a3b113026fc759862a697c611/sounddevice-0.4.6-py3-none-any.whl + sha256: 5de768ba6fe56ad2b5aaa2eea794b76b73e427961c95acad2ee2ed7f866a4b20 requires_dist: - - cffi>=1.0 + - cffi >=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi @@ -26466,7 +26466,7 @@ packages: url: https://files.pythonhosted.org/packages/39/ae/5e84220bfca4256e4ca2a62a174636089ab6ff671b5f9ddd7e8238587acd/sounddevice-0.4.6-py3-none-win_amd64.whl sha256: 7830d4f8f8570f2e5552942f81d96999c5fcd9a0b682d6fc5d5c5529df23be2c requires_dist: - - cffi>=1.0 + - cffi >=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi @@ -26494,9 +26494,9 @@ packages: path: examples/python/structure_from_motion sha256: b20b79aa7bb2b4225b37d3cb28872a70dc7e9ab2ca9ab138b90d60fc8d7b4c15 requires_dist: - - opencv-python>4.6 - numpy - - requests>=2.31,<3 + - opencv-python >4.6 + - requests <3, >=2.31 - rerun-sdk - tqdm editable: true @@ -26506,7 +26506,7 @@ packages: url: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl sha256: c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5 requires_dist: - - mpmath>=0.19 + - mpmath >=0.19 requires_python: '>=3.8' - kind: conda name: sysroot_linux-64 @@ -26692,12 +26692,12 @@ packages: requires_python: '>=3.8' - kind: pypi name: tifffile - version: 2024.4.18 - url: https://files.pythonhosted.org/packages/50/d8/870c966ced9aae912d113f2ca6a651bdc9db69d1ddf0afb5a87840ce0011/tifffile-2024.4.18-py3-none-any.whl - sha256: 72643b5c9ef886669a00a659c9fd60a81f220d2fb6572d184c3e147435ccec43 + version: 2024.4.24 + url: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl + sha256: 8d0b982f4b01ace358835ae6c2beb5a70cb7287f5d3a2e96c318bd5befa97b1f requires_dist: - numpy - - imagecodecs>=2023.8.12 ; extra == 'all' + - imagecodecs >=2023.8.12 ; extra == 'all' - matplotlib ; extra == 'all' - defusedxml ; extra == 'all' - lxml ; extra == 'all' @@ -26710,7 +26710,7 @@ packages: url: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl sha256: 02bba56786633ff46b55ee0ce3b991fa85375556844e500ad18e6b12921dc3da requires_dist: - - torch>=1.7 + - torch >=1.7 - torchvision - pyyaml - huggingface-hub @@ -26864,15 +26864,15 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa + url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 requires_dist: - - huggingface-hub>=0.16.4,<1.0 + - huggingface-hub >=0.16.4, <1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black==22.3 ; extra == 'testing' + - black ==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26885,12 +26885,12 @@ packages: url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 requires_dist: - - huggingface-hub>=0.16.4,<1.0 + - huggingface-hub >=0.16.4, <1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black==22.3 ; extra == 'testing' + - black ==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26900,15 +26900,15 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 + url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa requires_dist: - - huggingface-hub>=0.16.4,<1.0 + - huggingface-hub >=0.16.4, <1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black==22.3 ; extra == 'testing' + - black ==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26921,12 +26921,12 @@ packages: url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 requires_dist: - - huggingface-hub>=0.16.4,<1.0 + - huggingface-hub >=0.16.4, <1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black==22.3 ; extra == 'testing' + - black ==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26978,143 +26978,143 @@ packages: sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 requires_dist: - filelock - - typing-extensions>=4.8.0 + - typing-extensions >=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum>=3.3 ; extra == 'opt-einsum' - - optree>=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf requires_dist: - filelock - - typing-extensions>=4.8.0 + - typing-extensions >=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum>=3.3 ; extra == 'opt-einsum' - - optree>=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl - sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 + url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl + sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb requires_dist: - filelock - - typing-extensions>=4.8.0 + - typing-extensions >=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum>=3.3 ; extra == 'opt-einsum' - - optree>=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb + url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 requires_dist: - filelock - - typing-extensions>=4.8.0 + - typing-extensions >=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum>=3.3 ; extra == 'opt-einsum' - - optree>=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c requires_dist: - filelock - - typing-extensions>=4.8.0 + - typing-extensions >=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum>=3.3 ; extra == 'opt-einsum' - - optree>=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum >=3.3 ; extra == 'opt-einsum' + - optree >=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl - sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 + url: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl + sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 requires_dist: - numpy - - torch==2.2.2 - - pillow!=8.3.*,>=5.3.0 + - torch ==2.2.2 + - pillow !=8.3.*, >=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi @@ -27124,19 +27124,19 @@ packages: sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d requires_dist: - numpy - - torch==2.2.2 - - pillow!=8.3.*,>=5.3.0 + - torch ==2.2.2 + - pillow !=8.3.*, >=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl - sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 + url: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl + sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 requires_dist: - numpy - - torch==2.2.2 - - pillow!=8.3.*,>=5.3.0 + - torch ==2.2.2 + - pillow !=8.3.*, >=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi @@ -27146,8 +27146,8 @@ packages: sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 requires_dist: - numpy - - torch==2.2.2 - - pillow!=8.3.*,>=5.3.0 + - torch ==2.2.2 + - pillow !=8.3.*, >=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi @@ -27157,11 +27157,11 @@ packages: sha256: 1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9 requires_dist: - colorama ; platform_system == 'Windows' - - pytest>=6 ; extra == 'dev' + - pytest >=6 ; extra == 'dev' - pytest-cov ; extra == 'dev' - pytest-timeout ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - ipywidgets>=6 ; extra == 'notebook' + - ipywidgets >=6 ; extra == 'notebook' - slack-sdk ; extra == 'slack' - requests ; extra == 'telegram' requires_python: '>=3.7' @@ -27189,308 +27189,308 @@ packages: sha256: 9d5ee0c8142a60501faf9e49a0b42f8e9cb8611823bce4f195a9325a6816337e requires_dist: - filelock - - huggingface-hub<1.0,>=0.19.3 - - numpy>=1.17 - - packaging>=20.0 - - pyyaml>=5.1 - - regex!=2019.12.17 + - huggingface-hub <1.0, >=0.19.3 + - numpy >=1.17 + - packaging >=20.0 + - pyyaml >=5.1 + - regex !=2019.12.17 - requests - - tokenizers<0.20,>=0.19 - - safetensors>=0.4.1 - - tqdm>=4.27 - - accelerate>=0.21.0 ; extra == 'accelerate' + - tokenizers <0.20, >=0.19 + - safetensors >=0.4.1 + - tqdm >=4.27 + - accelerate >=0.21.0 ; extra == 'accelerate' - diffusers ; extra == 'agents' - - accelerate>=0.21.0 ; extra == 'agents' - - datasets!=2.5.0 ; extra == 'agents' + - accelerate >=0.21.0 ; extra == 'agents' + - datasets !=2.5.0 ; extra == 'agents' - torch ; extra == 'agents' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'agents' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'agents' - opencv-python ; extra == 'agents' - - pillow<=15.0,>=10.0.1 ; extra == 'agents' - - tensorflow<2.16,>=2.6 ; extra == 'all' + - pillow <=15.0, >=10.0.1 ; extra == 'agents' + - tensorflow <2.16, >=2.6 ; extra == 'all' - onnxconverter-common ; extra == 'all' - tf2onnx ; extra == 'all' - - tensorflow-text<2.16 ; extra == 'all' - - keras-nlp>=0.3.1 ; extra == 'all' + - tensorflow-text <2.16 ; extra == 'all' + - keras-nlp >=0.3.1 ; extra == 'all' - torch ; extra == 'all' - - accelerate>=0.21.0 ; extra == 'all' - - jax<=0.4.13,>=0.4.1 ; extra == 'all' - - jaxlib<=0.4.13,>=0.4.1 ; extra == 'all' - - flax<=0.7.0,>=0.4.1 ; extra == 'all' - - optax<=0.1.4,>=0.0.8 ; extra == 'all' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'all' + - accelerate >=0.21.0 ; extra == 'all' + - jax <=0.4.13, >=0.4.1 ; extra == 'all' + - jaxlib <=0.4.13, >=0.4.1 ; extra == 'all' + - flax <=0.7.0, >=0.4.1 ; extra == 'all' + - optax <=0.1.4, >=0.0.8 ; extra == 'all' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'all' - protobuf ; extra == 'all' - - tokenizers<0.20,>=0.19 ; extra == 'all' + - tokenizers <0.20, >=0.19 ; extra == 'all' - torchaudio ; extra == 'all' - librosa ; extra == 'all' - - pyctcdecode>=0.4.0 ; extra == 'all' + - pyctcdecode >=0.4.0 ; extra == 'all' - phonemizer ; extra == 'all' - kenlm ; extra == 'all' - - pillow<=15.0,>=10.0.1 ; extra == 'all' + - pillow <=15.0, >=10.0.1 ; extra == 'all' - optuna ; extra == 'all' - - ray[tune]>=2.7.0 ; extra == 'all' + - ray[tune] >=2.7.0 ; extra == 'all' - sigopt ; extra == 'all' - timm ; extra == 'all' - torchvision ; extra == 'all' - - codecarbon==1.2.0 ; extra == 'all' - - decord==0.6.0 ; extra == 'all' - - av==9.2.0 ; extra == 'all' + - codecarbon ==1.2.0 ; extra == 'all' + - decord ==0.6.0 ; extra == 'all' + - av ==9.2.0 ; extra == 'all' - librosa ; extra == 'audio' - - pyctcdecode>=0.4.0 ; extra == 'audio' + - pyctcdecode >=0.4.0 ; extra == 'audio' - phonemizer ; extra == 'audio' - kenlm ; extra == 'audio' - - codecarbon==1.2.0 ; extra == 'codecarbon' - - deepspeed>=0.9.3 ; extra == 'deepspeed' - - accelerate>=0.21.0 ; extra == 'deepspeed' - - deepspeed>=0.9.3 ; extra == 'deepspeed-testing' - - accelerate>=0.21.0 ; extra == 'deepspeed-testing' - - pytest<8.0.0,>=7.2.0 ; extra == 'deepspeed-testing' + - codecarbon ==1.2.0 ; extra == 'codecarbon' + - deepspeed >=0.9.3 ; extra == 'deepspeed' + - accelerate >=0.21.0 ; extra == 'deepspeed' + - deepspeed >=0.9.3 ; extra == 'deepspeed-testing' + - accelerate >=0.21.0 ; extra == 'deepspeed-testing' + - pytest <8.0.0, >=7.2.0 ; extra == 'deepspeed-testing' - pytest-xdist ; extra == 'deepspeed-testing' - timeout-decorator ; extra == 'deepspeed-testing' - parameterized ; extra == 'deepspeed-testing' - psutil ; extra == 'deepspeed-testing' - - datasets!=2.5.0 ; extra == 'deepspeed-testing' - - dill<0.3.5 ; extra == 'deepspeed-testing' - - evaluate>=0.2.0 ; extra == 'deepspeed-testing' + - datasets !=2.5.0 ; extra == 'deepspeed-testing' + - dill <0.3.5 ; extra == 'deepspeed-testing' + - evaluate >=0.2.0 ; extra == 'deepspeed-testing' - pytest-timeout ; extra == 'deepspeed-testing' - - ruff==0.1.5 ; extra == 'deepspeed-testing' - - sacrebleu<2.0.0,>=1.4.12 ; extra == 'deepspeed-testing' - - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'deepspeed-testing' + - ruff ==0.1.5 ; extra == 'deepspeed-testing' + - sacrebleu <2.0.0, >=1.4.12 ; extra == 'deepspeed-testing' + - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'deepspeed-testing' - nltk ; extra == 'deepspeed-testing' - - gitpython<3.1.19 ; extra == 'deepspeed-testing' - - hf-doc-builder>=0.3.0 ; extra == 'deepspeed-testing' + - gitpython <3.1.19 ; extra == 'deepspeed-testing' + - hf-doc-builder >=0.3.0 ; extra == 'deepspeed-testing' - protobuf ; extra == 'deepspeed-testing' - sacremoses ; extra == 'deepspeed-testing' - rjieba ; extra == 'deepspeed-testing' - beautifulsoup4 ; extra == 'deepspeed-testing' - tensorboard ; extra == 'deepspeed-testing' - pydantic ; extra == 'deepspeed-testing' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'deepspeed-testing' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'deepspeed-testing' - faiss-cpu ; extra == 'deepspeed-testing' - - cookiecutter==1.7.3 ; extra == 'deepspeed-testing' + - cookiecutter ==1.7.3 ; extra == 'deepspeed-testing' - optuna ; extra == 'deepspeed-testing' - - tensorflow<2.16,>=2.6 ; extra == 'dev' + - tensorflow <2.16, >=2.6 ; extra == 'dev' - onnxconverter-common ; extra == 'dev' - tf2onnx ; extra == 'dev' - - tensorflow-text<2.16 ; extra == 'dev' - - keras-nlp>=0.3.1 ; extra == 'dev' + - tensorflow-text <2.16 ; extra == 'dev' + - keras-nlp >=0.3.1 ; extra == 'dev' - torch ; extra == 'dev' - - accelerate>=0.21.0 ; extra == 'dev' - - jax<=0.4.13,>=0.4.1 ; extra == 'dev' - - jaxlib<=0.4.13,>=0.4.1 ; extra == 'dev' - - flax<=0.7.0,>=0.4.1 ; extra == 'dev' - - optax<=0.1.4,>=0.0.8 ; extra == 'dev' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev' + - accelerate >=0.21.0 ; extra == 'dev' + - jax <=0.4.13, >=0.4.1 ; extra == 'dev' + - jaxlib <=0.4.13, >=0.4.1 ; extra == 'dev' + - flax <=0.7.0, >=0.4.1 ; extra == 'dev' + - optax <=0.1.4, >=0.0.8 ; extra == 'dev' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev' - protobuf ; extra == 'dev' - - tokenizers<0.20,>=0.19 ; extra == 'dev' + - tokenizers <0.20, >=0.19 ; extra == 'dev' - torchaudio ; extra == 'dev' - librosa ; extra == 'dev' - - pyctcdecode>=0.4.0 ; extra == 'dev' + - pyctcdecode >=0.4.0 ; extra == 'dev' - phonemizer ; extra == 'dev' - kenlm ; extra == 'dev' - - pillow<=15.0,>=10.0.1 ; extra == 'dev' + - pillow <=15.0, >=10.0.1 ; extra == 'dev' - optuna ; extra == 'dev' - - ray[tune]>=2.7.0 ; extra == 'dev' + - ray[tune] >=2.7.0 ; extra == 'dev' - sigopt ; extra == 'dev' - timm ; extra == 'dev' - torchvision ; extra == 'dev' - - codecarbon==1.2.0 ; extra == 'dev' - - decord==0.6.0 ; extra == 'dev' - - av==9.2.0 ; extra == 'dev' - - pytest<8.0.0,>=7.2.0 ; extra == 'dev' + - codecarbon ==1.2.0 ; extra == 'dev' + - decord ==0.6.0 ; extra == 'dev' + - av ==9.2.0 ; extra == 'dev' + - pytest <8.0.0, >=7.2.0 ; extra == 'dev' - pytest-xdist ; extra == 'dev' - timeout-decorator ; extra == 'dev' - parameterized ; extra == 'dev' - psutil ; extra == 'dev' - - datasets!=2.5.0 ; extra == 'dev' - - dill<0.3.5 ; extra == 'dev' - - evaluate>=0.2.0 ; extra == 'dev' + - datasets !=2.5.0 ; extra == 'dev' + - dill <0.3.5 ; extra == 'dev' + - evaluate >=0.2.0 ; extra == 'dev' - pytest-timeout ; extra == 'dev' - - ruff==0.1.5 ; extra == 'dev' - - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev' - - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev' + - ruff ==0.1.5 ; extra == 'dev' + - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev' + - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev' - nltk ; extra == 'dev' - - gitpython<3.1.19 ; extra == 'dev' - - hf-doc-builder>=0.3.0 ; extra == 'dev' + - gitpython <3.1.19 ; extra == 'dev' + - hf-doc-builder >=0.3.0 ; extra == 'dev' - sacremoses ; extra == 'dev' - rjieba ; extra == 'dev' - beautifulsoup4 ; extra == 'dev' - tensorboard ; extra == 'dev' - pydantic ; extra == 'dev' - faiss-cpu ; extra == 'dev' - - cookiecutter==1.7.3 ; extra == 'dev' - - isort>=5.5.4 ; extra == 'dev' - - urllib3<2.0.0 ; extra == 'dev' - - fugashi>=1.0 ; extra == 'dev' - - ipadic<2.0,>=1.0.0 ; extra == 'dev' - - unidic-lite>=1.0.7 ; extra == 'dev' - - unidic>=1.0.2 ; extra == 'dev' - - sudachipy>=0.6.6 ; extra == 'dev' - - sudachidict-core>=20220729 ; extra == 'dev' - - rhoknp<1.3.1,>=1.1.0 ; extra == 'dev' + - cookiecutter ==1.7.3 ; extra == 'dev' + - isort >=5.5.4 ; extra == 'dev' + - urllib3 <2.0.0 ; extra == 'dev' + - fugashi >=1.0 ; extra == 'dev' + - ipadic <2.0, >=1.0.0 ; extra == 'dev' + - unidic-lite >=1.0.7 ; extra == 'dev' + - unidic >=1.0.2 ; extra == 'dev' + - sudachipy >=0.6.6 ; extra == 'dev' + - sudachidict-core >=20220729 ; extra == 'dev' + - rhoknp <1.3.1, >=1.1.0 ; extra == 'dev' - hf-doc-builder ; extra == 'dev' - scikit-learn ; extra == 'dev' - - pytest<8.0.0,>=7.2.0 ; extra == 'dev-tensorflow' + - pytest <8.0.0, >=7.2.0 ; extra == 'dev-tensorflow' - pytest-xdist ; extra == 'dev-tensorflow' - timeout-decorator ; extra == 'dev-tensorflow' - parameterized ; extra == 'dev-tensorflow' - psutil ; extra == 'dev-tensorflow' - - datasets!=2.5.0 ; extra == 'dev-tensorflow' - - dill<0.3.5 ; extra == 'dev-tensorflow' - - evaluate>=0.2.0 ; extra == 'dev-tensorflow' + - datasets !=2.5.0 ; extra == 'dev-tensorflow' + - dill <0.3.5 ; extra == 'dev-tensorflow' + - evaluate >=0.2.0 ; extra == 'dev-tensorflow' - pytest-timeout ; extra == 'dev-tensorflow' - - ruff==0.1.5 ; extra == 'dev-tensorflow' - - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev-tensorflow' - - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev-tensorflow' + - ruff ==0.1.5 ; extra == 'dev-tensorflow' + - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev-tensorflow' + - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev-tensorflow' - nltk ; extra == 'dev-tensorflow' - - gitpython<3.1.19 ; extra == 'dev-tensorflow' - - hf-doc-builder>=0.3.0 ; extra == 'dev-tensorflow' + - gitpython <3.1.19 ; extra == 'dev-tensorflow' + - hf-doc-builder >=0.3.0 ; extra == 'dev-tensorflow' - protobuf ; extra == 'dev-tensorflow' - sacremoses ; extra == 'dev-tensorflow' - rjieba ; extra == 'dev-tensorflow' - beautifulsoup4 ; extra == 'dev-tensorflow' - tensorboard ; extra == 'dev-tensorflow' - pydantic ; extra == 'dev-tensorflow' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev-tensorflow' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev-tensorflow' - faiss-cpu ; extra == 'dev-tensorflow' - - cookiecutter==1.7.3 ; extra == 'dev-tensorflow' - - tensorflow<2.16,>=2.6 ; extra == 'dev-tensorflow' + - cookiecutter ==1.7.3 ; extra == 'dev-tensorflow' + - tensorflow <2.16, >=2.6 ; extra == 'dev-tensorflow' - onnxconverter-common ; extra == 'dev-tensorflow' - tf2onnx ; extra == 'dev-tensorflow' - - tensorflow-text<2.16 ; extra == 'dev-tensorflow' - - keras-nlp>=0.3.1 ; extra == 'dev-tensorflow' - - tokenizers<0.20,>=0.19 ; extra == 'dev-tensorflow' - - pillow<=15.0,>=10.0.1 ; extra == 'dev-tensorflow' - - isort>=5.5.4 ; extra == 'dev-tensorflow' - - urllib3<2.0.0 ; extra == 'dev-tensorflow' + - tensorflow-text <2.16 ; extra == 'dev-tensorflow' + - keras-nlp >=0.3.1 ; extra == 'dev-tensorflow' + - tokenizers <0.20, >=0.19 ; extra == 'dev-tensorflow' + - pillow <=15.0, >=10.0.1 ; extra == 'dev-tensorflow' + - isort >=5.5.4 ; extra == 'dev-tensorflow' + - urllib3 <2.0.0 ; extra == 'dev-tensorflow' - hf-doc-builder ; extra == 'dev-tensorflow' - scikit-learn ; extra == 'dev-tensorflow' - - onnxruntime>=1.4.0 ; extra == 'dev-tensorflow' - - onnxruntime-tools>=1.4.2 ; extra == 'dev-tensorflow' + - onnxruntime >=1.4.0 ; extra == 'dev-tensorflow' + - onnxruntime-tools >=1.4.2 ; extra == 'dev-tensorflow' - librosa ; extra == 'dev-tensorflow' - - pyctcdecode>=0.4.0 ; extra == 'dev-tensorflow' + - pyctcdecode >=0.4.0 ; extra == 'dev-tensorflow' - phonemizer ; extra == 'dev-tensorflow' - kenlm ; extra == 'dev-tensorflow' - - pytest<8.0.0,>=7.2.0 ; extra == 'dev-torch' + - pytest <8.0.0, >=7.2.0 ; extra == 'dev-torch' - pytest-xdist ; extra == 'dev-torch' - timeout-decorator ; extra == 'dev-torch' - parameterized ; extra == 'dev-torch' - psutil ; extra == 'dev-torch' - - datasets!=2.5.0 ; extra == 'dev-torch' - - dill<0.3.5 ; extra == 'dev-torch' - - evaluate>=0.2.0 ; extra == 'dev-torch' + - datasets !=2.5.0 ; extra == 'dev-torch' + - dill <0.3.5 ; extra == 'dev-torch' + - evaluate >=0.2.0 ; extra == 'dev-torch' - pytest-timeout ; extra == 'dev-torch' - - ruff==0.1.5 ; extra == 'dev-torch' - - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev-torch' - - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev-torch' + - ruff ==0.1.5 ; extra == 'dev-torch' + - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev-torch' + - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev-torch' - nltk ; extra == 'dev-torch' - - gitpython<3.1.19 ; extra == 'dev-torch' - - hf-doc-builder>=0.3.0 ; extra == 'dev-torch' + - gitpython <3.1.19 ; extra == 'dev-torch' + - hf-doc-builder >=0.3.0 ; extra == 'dev-torch' - protobuf ; extra == 'dev-torch' - sacremoses ; extra == 'dev-torch' - rjieba ; extra == 'dev-torch' - beautifulsoup4 ; extra == 'dev-torch' - tensorboard ; extra == 'dev-torch' - pydantic ; extra == 'dev-torch' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev-torch' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev-torch' - faiss-cpu ; extra == 'dev-torch' - - cookiecutter==1.7.3 ; extra == 'dev-torch' + - cookiecutter ==1.7.3 ; extra == 'dev-torch' - torch ; extra == 'dev-torch' - - accelerate>=0.21.0 ; extra == 'dev-torch' - - tokenizers<0.20,>=0.19 ; extra == 'dev-torch' + - accelerate >=0.21.0 ; extra == 'dev-torch' + - tokenizers <0.20, >=0.19 ; extra == 'dev-torch' - torchaudio ; extra == 'dev-torch' - librosa ; extra == 'dev-torch' - - pyctcdecode>=0.4.0 ; extra == 'dev-torch' + - pyctcdecode >=0.4.0 ; extra == 'dev-torch' - phonemizer ; extra == 'dev-torch' - kenlm ; extra == 'dev-torch' - - pillow<=15.0,>=10.0.1 ; extra == 'dev-torch' + - pillow <=15.0, >=10.0.1 ; extra == 'dev-torch' - optuna ; extra == 'dev-torch' - - ray[tune]>=2.7.0 ; extra == 'dev-torch' + - ray[tune] >=2.7.0 ; extra == 'dev-torch' - sigopt ; extra == 'dev-torch' - timm ; extra == 'dev-torch' - torchvision ; extra == 'dev-torch' - - codecarbon==1.2.0 ; extra == 'dev-torch' - - isort>=5.5.4 ; extra == 'dev-torch' - - urllib3<2.0.0 ; extra == 'dev-torch' - - fugashi>=1.0 ; extra == 'dev-torch' - - ipadic<2.0,>=1.0.0 ; extra == 'dev-torch' - - unidic-lite>=1.0.7 ; extra == 'dev-torch' - - unidic>=1.0.2 ; extra == 'dev-torch' - - sudachipy>=0.6.6 ; extra == 'dev-torch' - - sudachidict-core>=20220729 ; extra == 'dev-torch' - - rhoknp<1.3.1,>=1.1.0 ; extra == 'dev-torch' + - codecarbon ==1.2.0 ; extra == 'dev-torch' + - isort >=5.5.4 ; extra == 'dev-torch' + - urllib3 <2.0.0 ; extra == 'dev-torch' + - fugashi >=1.0 ; extra == 'dev-torch' + - ipadic <2.0, >=1.0.0 ; extra == 'dev-torch' + - unidic-lite >=1.0.7 ; extra == 'dev-torch' + - unidic >=1.0.2 ; extra == 'dev-torch' + - sudachipy >=0.6.6 ; extra == 'dev-torch' + - sudachidict-core >=20220729 ; extra == 'dev-torch' + - rhoknp <1.3.1, >=1.1.0 ; extra == 'dev-torch' - hf-doc-builder ; extra == 'dev-torch' - scikit-learn ; extra == 'dev-torch' - - onnxruntime>=1.4.0 ; extra == 'dev-torch' - - onnxruntime-tools>=1.4.2 ; extra == 'dev-torch' - - tensorflow<2.16,>=2.6 ; extra == 'docs' + - onnxruntime >=1.4.0 ; extra == 'dev-torch' + - onnxruntime-tools >=1.4.2 ; extra == 'dev-torch' + - tensorflow <2.16, >=2.6 ; extra == 'docs' - onnxconverter-common ; extra == 'docs' - tf2onnx ; extra == 'docs' - - tensorflow-text<2.16 ; extra == 'docs' - - keras-nlp>=0.3.1 ; extra == 'docs' + - tensorflow-text <2.16 ; extra == 'docs' + - keras-nlp >=0.3.1 ; extra == 'docs' - torch ; extra == 'docs' - - accelerate>=0.21.0 ; extra == 'docs' - - jax<=0.4.13,>=0.4.1 ; extra == 'docs' - - jaxlib<=0.4.13,>=0.4.1 ; extra == 'docs' - - flax<=0.7.0,>=0.4.1 ; extra == 'docs' - - optax<=0.1.4,>=0.0.8 ; extra == 'docs' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'docs' + - accelerate >=0.21.0 ; extra == 'docs' + - jax <=0.4.13, >=0.4.1 ; extra == 'docs' + - jaxlib <=0.4.13, >=0.4.1 ; extra == 'docs' + - flax <=0.7.0, >=0.4.1 ; extra == 'docs' + - optax <=0.1.4, >=0.0.8 ; extra == 'docs' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'docs' - protobuf ; extra == 'docs' - - tokenizers<0.20,>=0.19 ; extra == 'docs' + - tokenizers <0.20, >=0.19 ; extra == 'docs' - torchaudio ; extra == 'docs' - librosa ; extra == 'docs' - - pyctcdecode>=0.4.0 ; extra == 'docs' + - pyctcdecode >=0.4.0 ; extra == 'docs' - phonemizer ; extra == 'docs' - kenlm ; extra == 'docs' - - pillow<=15.0,>=10.0.1 ; extra == 'docs' + - pillow <=15.0, >=10.0.1 ; extra == 'docs' - optuna ; extra == 'docs' - - ray[tune]>=2.7.0 ; extra == 'docs' + - ray[tune] >=2.7.0 ; extra == 'docs' - sigopt ; extra == 'docs' - timm ; extra == 'docs' - torchvision ; extra == 'docs' - - codecarbon==1.2.0 ; extra == 'docs' - - decord==0.6.0 ; extra == 'docs' - - av==9.2.0 ; extra == 'docs' + - codecarbon ==1.2.0 ; extra == 'docs' + - decord ==0.6.0 ; extra == 'docs' + - av ==9.2.0 ; extra == 'docs' - hf-doc-builder ; extra == 'docs' - hf-doc-builder ; extra == 'docs_specific' - - jax<=0.4.13,>=0.4.1 ; extra == 'flax' - - jaxlib<=0.4.13,>=0.4.1 ; extra == 'flax' - - flax<=0.7.0,>=0.4.1 ; extra == 'flax' - - optax<=0.1.4,>=0.0.8 ; extra == 'flax' + - jax <=0.4.13, >=0.4.1 ; extra == 'flax' + - jaxlib <=0.4.13, >=0.4.1 ; extra == 'flax' + - flax <=0.7.0, >=0.4.1 ; extra == 'flax' + - optax <=0.1.4, >=0.0.8 ; extra == 'flax' - librosa ; extra == 'flax-speech' - - pyctcdecode>=0.4.0 ; extra == 'flax-speech' + - pyctcdecode >=0.4.0 ; extra == 'flax-speech' - phonemizer ; extra == 'flax-speech' - kenlm ; extra == 'flax-speech' - ftfy ; extra == 'ftfy' - optuna ; extra == 'integrations' - - ray[tune]>=2.7.0 ; extra == 'integrations' + - ray[tune] >=2.7.0 ; extra == 'integrations' - sigopt ; extra == 'integrations' - - fugashi>=1.0 ; extra == 'ja' - - ipadic<2.0,>=1.0.0 ; extra == 'ja' - - unidic-lite>=1.0.7 ; extra == 'ja' - - unidic>=1.0.2 ; extra == 'ja' - - sudachipy>=0.6.6 ; extra == 'ja' - - sudachidict-core>=20220729 ; extra == 'ja' - - rhoknp<1.3.1,>=1.1.0 ; extra == 'ja' - - cookiecutter==1.7.3 ; extra == 'modelcreation' - - natten<0.15.0,>=0.14.6 ; extra == 'natten' + - fugashi >=1.0 ; extra == 'ja' + - ipadic <2.0, >=1.0.0 ; extra == 'ja' + - unidic-lite >=1.0.7 ; extra == 'ja' + - unidic >=1.0.2 ; extra == 'ja' + - sudachipy >=0.6.6 ; extra == 'ja' + - sudachidict-core >=20220729 ; extra == 'ja' + - rhoknp <1.3.1, >=1.1.0 ; extra == 'ja' + - cookiecutter ==1.7.3 ; extra == 'modelcreation' + - natten <0.15.0, >=0.14.6 ; extra == 'natten' - onnxconverter-common ; extra == 'onnx' - tf2onnx ; extra == 'onnx' - - onnxruntime>=1.4.0 ; extra == 'onnx' - - onnxruntime-tools>=1.4.2 ; extra == 'onnx' - - onnxruntime>=1.4.0 ; extra == 'onnxruntime' - - onnxruntime-tools>=1.4.2 ; extra == 'onnxruntime' + - onnxruntime >=1.4.0 ; extra == 'onnx' + - onnxruntime-tools >=1.4.2 ; extra == 'onnx' + - onnxruntime >=1.4.0 ; extra == 'onnxruntime' + - onnxruntime-tools >=1.4.2 ; extra == 'onnxruntime' - optuna ; extra == 'optuna' - - datasets!=2.5.0 ; extra == 'quality' - - isort>=5.5.4 ; extra == 'quality' - - ruff==0.1.5 ; extra == 'quality' - - gitpython<3.1.19 ; extra == 'quality' - - hf-doc-builder>=0.3.0 ; extra == 'quality' - - urllib3<2.0.0 ; extra == 'quality' - - ray[tune]>=2.7.0 ; extra == 'ray' + - datasets !=2.5.0 ; extra == 'quality' + - isort >=5.5.4 ; extra == 'quality' + - ruff ==0.1.5 ; extra == 'quality' + - gitpython <3.1.19 ; extra == 'quality' + - hf-doc-builder >=0.3.0 ; extra == 'quality' + - urllib3 <2.0.0 ; extra == 'quality' + - ray[tune] >=2.7.0 ; extra == 'ray' - faiss-cpu ; extra == 'retrieval' - - datasets!=2.5.0 ; extra == 'retrieval' - - sagemaker>=2.31.0 ; extra == 'sagemaker' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'sentencepiece' + - datasets !=2.5.0 ; extra == 'retrieval' + - sagemaker >=2.31.0 ; extra == 'sagemaker' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'sentencepiece' - protobuf ; extra == 'sentencepiece' - pydantic ; extra == 'serving' - uvicorn ; extra == 'serving' @@ -27500,73 +27500,73 @@ packages: - scikit-learn ; extra == 'sklearn' - torchaudio ; extra == 'speech' - librosa ; extra == 'speech' - - pyctcdecode>=0.4.0 ; extra == 'speech' + - pyctcdecode >=0.4.0 ; extra == 'speech' - phonemizer ; extra == 'speech' - kenlm ; extra == 'speech' - - pytest<8.0.0,>=7.2.0 ; extra == 'testing' + - pytest <8.0.0, >=7.2.0 ; extra == 'testing' - pytest-xdist ; extra == 'testing' - timeout-decorator ; extra == 'testing' - parameterized ; extra == 'testing' - psutil ; extra == 'testing' - - datasets!=2.5.0 ; extra == 'testing' - - dill<0.3.5 ; extra == 'testing' - - evaluate>=0.2.0 ; extra == 'testing' + - datasets !=2.5.0 ; extra == 'testing' + - dill <0.3.5 ; extra == 'testing' + - evaluate >=0.2.0 ; extra == 'testing' - pytest-timeout ; extra == 'testing' - - ruff==0.1.5 ; extra == 'testing' - - sacrebleu<2.0.0,>=1.4.12 ; extra == 'testing' - - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'testing' + - ruff ==0.1.5 ; extra == 'testing' + - sacrebleu <2.0.0, >=1.4.12 ; extra == 'testing' + - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'testing' - nltk ; extra == 'testing' - - gitpython<3.1.19 ; extra == 'testing' - - hf-doc-builder>=0.3.0 ; extra == 'testing' + - gitpython <3.1.19 ; extra == 'testing' + - hf-doc-builder >=0.3.0 ; extra == 'testing' - protobuf ; extra == 'testing' - sacremoses ; extra == 'testing' - rjieba ; extra == 'testing' - beautifulsoup4 ; extra == 'testing' - tensorboard ; extra == 'testing' - pydantic ; extra == 'testing' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'testing' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'testing' - faiss-cpu ; extra == 'testing' - - cookiecutter==1.7.3 ; extra == 'testing' - - tensorflow<2.16,>=2.6 ; extra == 'tf' + - cookiecutter ==1.7.3 ; extra == 'testing' + - tensorflow <2.16, >=2.6 ; extra == 'tf' - onnxconverter-common ; extra == 'tf' - tf2onnx ; extra == 'tf' - - tensorflow-text<2.16 ; extra == 'tf' - - keras-nlp>=0.3.1 ; extra == 'tf' - - tensorflow-cpu<2.16,>=2.6 ; extra == 'tf-cpu' + - tensorflow-text <2.16 ; extra == 'tf' + - keras-nlp >=0.3.1 ; extra == 'tf' + - tensorflow-cpu <2.16, >=2.6 ; extra == 'tf-cpu' - onnxconverter-common ; extra == 'tf-cpu' - tf2onnx ; extra == 'tf-cpu' - - tensorflow-text<2.16 ; extra == 'tf-cpu' - - keras-nlp>=0.3.1 ; extra == 'tf-cpu' + - tensorflow-text <2.16 ; extra == 'tf-cpu' + - keras-nlp >=0.3.1 ; extra == 'tf-cpu' - librosa ; extra == 'tf-speech' - - pyctcdecode>=0.4.0 ; extra == 'tf-speech' + - pyctcdecode >=0.4.0 ; extra == 'tf-speech' - phonemizer ; extra == 'tf-speech' - kenlm ; extra == 'tf-speech' - timm ; extra == 'timm' - - tokenizers<0.20,>=0.19 ; extra == 'tokenizers' + - tokenizers <0.20, >=0.19 ; extra == 'tokenizers' - torch ; extra == 'torch' - - accelerate>=0.21.0 ; extra == 'torch' + - accelerate >=0.21.0 ; extra == 'torch' - torchaudio ; extra == 'torch-speech' - librosa ; extra == 'torch-speech' - - pyctcdecode>=0.4.0 ; extra == 'torch-speech' + - pyctcdecode >=0.4.0 ; extra == 'torch-speech' - phonemizer ; extra == 'torch-speech' - kenlm ; extra == 'torch-speech' - torchvision ; extra == 'torch-vision' - - pillow<=15.0,>=10.0.1 ; extra == 'torch-vision' + - pillow <=15.0, >=10.0.1 ; extra == 'torch-vision' - filelock ; extra == 'torchhub' - - huggingface-hub<1.0,>=0.19.3 ; extra == 'torchhub' + - huggingface-hub <1.0, >=0.19.3 ; extra == 'torchhub' - importlib-metadata ; extra == 'torchhub' - - numpy>=1.17 ; extra == 'torchhub' - - packaging>=20.0 ; extra == 'torchhub' + - numpy >=1.17 ; extra == 'torchhub' + - packaging >=20.0 ; extra == 'torchhub' - protobuf ; extra == 'torchhub' - - regex!=2019.12.17 ; extra == 'torchhub' + - regex !=2019.12.17 ; extra == 'torchhub' - requests ; extra == 'torchhub' - - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'torchhub' + - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'torchhub' - torch ; extra == 'torchhub' - - tokenizers<0.20,>=0.19 ; extra == 'torchhub' - - tqdm>=4.27 ; extra == 'torchhub' - - decord==0.6.0 ; extra == 'video' - - av==9.2.0 ; extra == 'video' - - pillow<=15.0,>=10.0.1 ; extra == 'vision' + - tokenizers <0.20, >=0.19 ; extra == 'torchhub' + - tqdm >=4.27 ; extra == 'torchhub' + - decord ==0.6.0 ; extra == 'video' + - av ==9.2.0 ; extra == 'video' + - pillow <=15.0, >=10.0.1 ; extra == 'vision' requires_python: '>=3.8.0' - kind: pypi name: trimesh @@ -27629,14 +27629,14 @@ packages: sha256: da58a152bddb62cafa9a857dd2bc1f886dbf9f9c90a2b5da82157cd2b34392b0 requires_dist: - filelock - - cmake>=3.20 ; extra == 'build' + - cmake >=3.20 ; extra == 'build' - lit ; extra == 'build' - autopep8 ; extra == 'tests' - flake8 ; extra == 'tests' - isort ; extra == 'tests' - numpy ; extra == 'tests' - pytest ; extra == 'tests' - - scipy>=1.7.1 ; extra == 'tests' + - scipy >=1.7.1 ; extra == 'tests' - torch ; extra == 'tests' - matplotlib ; extra == 'tutorials' - pandas ; extra == 'tutorials' @@ -27653,7 +27653,7 @@ packages: url: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl sha256: 6216cdac377c6b9a040ac1c0404f7284bd13199c0e1bb235f4324627e8898cf5 requires_dist: - - urllib3>=2 + - urllib3 >=2 requires_python: '>=3.8' - kind: pypi name: typing-extensions @@ -27667,9 +27667,9 @@ packages: url: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl sha256: 9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f requires_dist: - - mypy-extensions>=0.3.0 - - typing-extensions>=3.7.4 - - typing>=3.7.4 ; python_version < '3.5' + - mypy-extensions >=0.3.0 + - typing-extensions >=3.7.4 + - typing >=3.7.4 ; python_version < '3.5' - kind: conda name: typing_extensions version: 4.8.0 @@ -28073,13 +28073,13 @@ packages: url: https://files.pythonhosted.org/packages/d1/1b/46802a050b1c55d10c4f59fc6afd2b45ac9b4f62b2e12092d3f599286f14/umap_learn-0.5.6-py3-none-any.whl sha256: 881cc0c2ee845b790bf0455aa1664f9f68b838d9d0fe12a1291b85c5a559c913 requires_dist: - - numpy>=1.17 - - scipy>=1.3.1 - - scikit-learn>=0.22 - - numba>=0.51.2 - - pynndescent>=0.5 + - numpy >=1.17 + - scipy >=1.3.1 + - scikit-learn >=0.22 + - numba >=0.51.2 + - pynndescent >=0.5 - tqdm - - tensorflow>=2.1 ; extra == 'parametric_umap' + - tensorflow >=2.1 ; extra == 'parametric_umap' - pandas ; extra == 'plot' - matplotlib ; extra == 'plot' - datashader ; extra == 'plot' @@ -28088,18 +28088,18 @@ packages: - colorcet ; extra == 'plot' - seaborn ; extra == 'plot' - scikit-image ; extra == 'plot' - - tbb>=2019.0 ; extra == 'tbb' + - tbb >=2019.0 ; extra == 'tbb' - kind: pypi name: urllib3 version: 2.2.1 url: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl sha256: 450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d requires_dist: - - brotli>=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' - - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' - - h2<5,>=4 ; extra == 'h2' - - pysocks!=1.5.7,<2.0,>=1.5.6 ; extra == 'socks' - - zstandard>=0.18.0 ; extra == 'zstd' + - brotli >=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2 <5, >=4 ; extra == 'h2' + - pysocks !=1.5.7, <2.0, >=1.5.6 ; extra == 'socks' + - zstandard >=0.18.0 ; extra == 'zstd' requires_python: '>=3.8' - kind: conda name: urllib3 @@ -28198,29 +28198,29 @@ packages: url: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl sha256: 6e1281a57849c8a54da89ba82e5eb7c8937b9d057ff01aaf5bc9afaa3552e90f requires_dist: - - distlib<1,>=0.3.7 - - filelock<4,>=3.12.2 - - importlib-metadata>=6.6 ; python_version < '3.8' - - platformdirs<5,>=3.9.1 - - furo>=2023.7.26 ; extra == 'docs' - - proselint>=0.13 ; extra == 'docs' - - sphinx!=7.3,>=7.1.2 ; extra == 'docs' - - sphinx-argparse>=0.4 ; extra == 'docs' - - sphinxcontrib-towncrier>=0.2.1a0 ; extra == 'docs' - - towncrier>=23.6 ; extra == 'docs' - - covdefaults>=2.3 ; extra == 'test' - - coverage-enable-subprocess>=1 ; extra == 'test' - - coverage>=7.2.7 ; extra == 'test' - - flaky>=3.7 ; extra == 'test' - - packaging>=23.1 ; extra == 'test' - - pytest-env>=0.8.2 ; extra == 'test' - - pytest-freezer>=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' - - pytest-mock>=3.11.1 ; extra == 'test' - - pytest-randomly>=3.12 ; extra == 'test' - - pytest-timeout>=2.1 ; extra == 'test' - - pytest>=7.4 ; extra == 'test' - - setuptools>=68 ; extra == 'test' - - time-machine>=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' + - distlib <1, >=0.3.7 + - filelock <4, >=3.12.2 + - importlib-metadata >=6.6 ; python_version < '3.8' + - platformdirs <5, >=3.9.1 + - furo >=2023.7.26 ; extra == 'docs' + - proselint >=0.13 ; extra == 'docs' + - sphinx !=7.3, >=7.1.2 ; extra == 'docs' + - sphinx-argparse >=0.4 ; extra == 'docs' + - sphinxcontrib-towncrier >=0.2.1a0 ; extra == 'docs' + - towncrier >=23.6 ; extra == 'docs' + - covdefaults >=2.3 ; extra == 'test' + - coverage-enable-subprocess >=1 ; extra == 'test' + - coverage >=7.2.7 ; extra == 'test' + - flaky >=3.7 ; extra == 'test' + - packaging >=23.1 ; extra == 'test' + - pytest-env >=0.8.2 ; extra == 'test' + - pytest-freezer >=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' + - pytest-mock >=3.11.1 ; extra == 'test' + - pytest-randomly >=3.12 ; extra == 'test' + - pytest-timeout >=2.1 ; extra == 'test' + - pytest >=7.4 ; extra == 'test' + - setuptools >=68 ; extra == 'test' + - time-machine >=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' requires_python: '>=3.7' - kind: pypi name: virtualenv @@ -28228,29 +28228,29 @@ packages: url: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl sha256: 8aac4332f2ea6ef519c648d0bc48a5b1d324994753519919bddbb1aff25a104e requires_dist: - - distlib<1,>=0.3.7 - - filelock<4,>=3.12.2 - - importlib-metadata>=6.6 ; python_version < '3.8' - - platformdirs<5,>=3.9.1 - - furo>=2023.7.26 ; extra == 'docs' - - proselint>=0.13 ; extra == 'docs' - - sphinx!=7.3,>=7.1.2 ; extra == 'docs' - - sphinx-argparse>=0.4 ; extra == 'docs' - - sphinxcontrib-towncrier>=0.2.1a0 ; extra == 'docs' - - towncrier>=23.6 ; extra == 'docs' - - covdefaults>=2.3 ; extra == 'test' - - coverage-enable-subprocess>=1 ; extra == 'test' - - coverage>=7.2.7 ; extra == 'test' - - flaky>=3.7 ; extra == 'test' - - packaging>=23.1 ; extra == 'test' - - pytest-env>=0.8.2 ; extra == 'test' - - pytest-freezer>=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' - - pytest-mock>=3.11.1 ; extra == 'test' - - pytest-randomly>=3.12 ; extra == 'test' - - pytest-timeout>=2.1 ; extra == 'test' - - pytest>=7.4 ; extra == 'test' - - setuptools>=68 ; extra == 'test' - - time-machine>=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' + - distlib <1, >=0.3.7 + - filelock <4, >=3.12.2 + - importlib-metadata >=6.6 ; python_version < '3.8' + - platformdirs <5, >=3.9.1 + - furo >=2023.7.26 ; extra == 'docs' + - proselint >=0.13 ; extra == 'docs' + - sphinx !=7.3, >=7.1.2 ; extra == 'docs' + - sphinx-argparse >=0.4 ; extra == 'docs' + - sphinxcontrib-towncrier >=0.2.1a0 ; extra == 'docs' + - towncrier >=23.6 ; extra == 'docs' + - covdefaults >=2.3 ; extra == 'test' + - coverage-enable-subprocess >=1 ; extra == 'test' + - coverage >=7.2.7 ; extra == 'test' + - flaky >=3.7 ; extra == 'test' + - packaging >=23.1 ; extra == 'test' + - pytest-env >=0.8.2 ; extra == 'test' + - pytest-freezer >=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' + - pytest-mock >=3.11.1 ; extra == 'test' + - pytest-randomly >=3.12 ; extra == 'test' + - pytest-timeout >=2.1 ; extra == 'test' + - pytest >=7.4 ; extra == 'test' + - setuptools >=68 ; extra == 'test' + - time-machine >=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' requires_python: '>=3.7' - kind: conda name: vs2015_runtime @@ -28376,8 +28376,8 @@ packages: - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl - sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 + url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d requires_python: '>=3.6' - kind: pypi name: wrapt @@ -28388,20 +28388,20 @@ packages: - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 + url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d + url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl + sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 + url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 requires_python: '>=3.6' - kind: conda name: xz @@ -28573,37 +28573,37 @@ packages: url: https://files.pythonhosted.org/packages/d5/b5/70bb98ee38ce532ee29fab76fb668382291fe6e1aa69a8c1ac7e6bc108e7/yfinance-0.2.38-py2.py3-none-any.whl sha256: 07525cf84414272723a3e2b9d4c0a2898ddb60cc0828aa190de26664fac6f676 requires_dist: - - pandas>=1.3.0 - - numpy>=1.16.5 - - requests>=2.31 - - multitasking>=0.0.7 - - lxml>=4.9.1 - - appdirs>=1.4.4 - - pytz>=2022.5 - - frozendict>=2.3.4 - - peewee>=3.16.2 - - beautifulsoup4>=4.11.1 - - html5lib>=1.1 - - requests-cache>=1.0 ; extra == 'nospam' - - requests-ratelimiter>=0.3.1 ; extra == 'nospam' - - scipy>=1.6.3 ; extra == 'repair' + - pandas >=1.3.0 + - numpy >=1.16.5 + - requests >=2.31 + - multitasking >=0.0.7 + - lxml >=4.9.1 + - appdirs >=1.4.4 + - pytz >=2022.5 + - frozendict >=2.3.4 + - peewee >=3.16.2 + - beautifulsoup4 >=4.11.1 + - html5lib >=1.1 + - requests-cache >=1.0 ; extra == 'nospam' + - requests-ratelimiter >=0.3.1 ; extra == 'nospam' + - scipy >=1.6.3 ; extra == 'repair' - kind: pypi name: zipp version: 3.18.1 url: https://files.pythonhosted.org/packages/c2/0a/ba9d0ee9536d3ef73a3448e931776e658b36f128d344e175bc32b092a8bf/zipp-3.18.1-py3-none-any.whl sha256: 206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b requires_dist: - - sphinx>=3.5 ; extra == 'docs' - - jaraco-packaging>=9.3 ; extra == 'docs' - - rst-linker>=1.9 ; extra == 'docs' + - sphinx >=3.5 ; extra == 'docs' + - jaraco-packaging >=9.3 ; extra == 'docs' + - rst-linker >=1.9 ; extra == 'docs' - furo ; extra == 'docs' - sphinx-lint ; extra == 'docs' - - jaraco-tidelift>=1.4 ; extra == 'docs' - - pytest>=6 ; extra == 'testing' - - pytest-checkdocs>=2.4 ; extra == 'testing' + - jaraco-tidelift >=1.4 ; extra == 'docs' + - pytest >=6 ; extra == 'testing' + - pytest-checkdocs >=2.4 ; extra == 'testing' - pytest-cov ; extra == 'testing' - - pytest-enabler>=2.2 ; extra == 'testing' - - pytest-ruff>=0.2.1 ; extra == 'testing' + - pytest-enabler >=2.2 ; extra == 'testing' + - pytest-ruff >=0.2.1 ; extra == 'testing' - jaraco-itertools ; extra == 'testing' - jaraco-functools ; extra == 'testing' - more-itertools ; extra == 'testing' diff --git a/pixi.toml b/pixi.toml index b89fb2ae041e..da7d411af7be 100644 --- a/pixi.toml +++ b/pixi.toml @@ -247,7 +247,9 @@ cpp-fmt = "fd --extension h --extension hpp --extension c --extension cpp --exe cpp-prepare-msvc = "cmake -G 'Visual Studio 17 2022' -B build-msvc -S ." [feature.wheel-test.pypi-dependencies] -torch = ">=2.0.1" +# This dependency is here to get torch into the pixi cache because it's large and installing it +# during the wheel-test task itself is otherwise painful +torch = "==2.2.2" # This must match the torch version in any package we install during `wheel-test` pip = ">=23" [feature.wheel-test.tasks] From 660463dc5eba9bce4005a8511679ceaffbea6765 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 26 Apr 2024 23:30:39 +0200 Subject: [PATCH 380/508] Split visible time range component into two for time & sequence using the same backing data (#6134) ### What * Part of [#6083](https://github.com/rerun-io/rerun/issues/6083) Necessary step on the way towards a `VisibleTimeRange` view property archetype. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6134?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6134?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6134) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- Cargo.lock | 1 + crates/re_space_view/src/visual_time_range.rs | 70 +++---- .../src/space_view_class.rs | 6 +- crates/re_space_view_time_series/src/util.rs | 21 +- .../re_types/definitions/rerun/blueprint.fbs | 3 +- ...ge.fbs => visible_time_range_sequence.fbs} | 4 +- .../components/visible_time_range_time.fbs | 20 ++ .../datatypes/visible_time_range.fbs | 17 +- .../src/blueprint/components/.gitattributes | 3 +- .../re_types/src/blueprint/components/mod.rs | 7 +- .../components/visible_time_range_ext.rs | 6 - ...ange.rs => visible_time_range_sequence.rs} | 42 ++-- .../components/visible_time_range_time.rs | 144 ++++++++++++++ .../blueprint/datatypes/visible_time_range.rs | 179 ++++-------------- .../datatypes/visible_time_range_ext.rs | 12 +- crates/re_types_builder/Cargo.toml | 1 + crates/re_types_builder/src/format/python.rs | 5 +- .../src/blueprint/validation_gen/mod.rs | 6 +- crates/re_viewer/src/ui/visible_history.rs | 67 ++++--- .../src/space_view/space_view_class.rs | 2 +- rerun_cpp/src/rerun/blueprint/components.hpp | 3 +- .../rerun/blueprint/components/.gitattributes | 3 +- .../visible_time_range_sequence.hpp | 61 ++++++ ..._range.hpp => visible_time_range_time.hpp} | 23 +-- .../datatypes/visible_time_range.cpp | 42 +--- .../datatypes/visible_time_range.hpp | 14 +- .../rerun/blueprint/components/.gitattributes | 3 +- .../rerun/blueprint/components/__init__.py | 16 +- .../components/visible_time_range.py | 28 --- .../components/visible_time_range_sequence.py | 28 +++ .../components/visible_time_range_time.py | 28 +++ .../blueprint/datatypes/visible_time_range.py | 78 ++------ 32 files changed, 503 insertions(+), 440 deletions(-) rename crates/re_types/definitions/rerun/blueprint/components/{visible_time_range.fbs => visible_time_range_sequence.fbs} (77%) create mode 100644 crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs delete mode 100644 crates/re_types/src/blueprint/components/visible_time_range_ext.rs rename crates/re_types/src/blueprint/components/{visible_time_range.rs => visible_time_range_sequence.rs} (81%) create mode 100644 crates/re_types/src/blueprint/components/visible_time_range_time.rs create mode 100644 rerun_cpp/src/rerun/blueprint/components/visible_time_range_sequence.hpp rename rerun_cpp/src/rerun/blueprint/components/{visible_time_range.hpp => visible_time_range_time.hpp} (67%) delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_sequence.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_time.py diff --git a/Cargo.lock b/Cargo.lock index ac78976d7797..017c403cf712 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4917,6 +4917,7 @@ dependencies = [ "rayon", "re_arrow2", "re_build_tools", + "re_error", "re_log", "re_tracing", "rust-format", diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index 4a55c27e31f9..ccf1b2ecdd31 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -9,9 +9,8 @@ use re_log_types::TimeRange; use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; -use re_types::blueprint::{ - components::VisibleTimeRange, - datatypes::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}, +use re_types::blueprint::datatypes::{ + VisibleTimeRange, VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind, }; use re_viewer_context::ViewerContext; @@ -48,19 +47,12 @@ pub fn visible_history_boundary_to_time_range_boundary( pub fn visible_time_range_to_time_range( range: &VisibleTimeRange, - time_type: re_log_types::TimeType, cursor: re_log_types::TimeInt, ) -> re_log_types::TimeRange { let cursor = cursor.as_i64().into(); - let mut min = match time_type { - re_log_types::TimeType::Sequence => range.0.from_sequence.start_boundary_time(cursor), - re_log_types::TimeType::Time => range.0.from_time.start_boundary_time(cursor), - }; - let mut max = match time_type { - re_log_types::TimeType::Sequence => range.0.to_sequence.end_boundary_time(cursor), - re_log_types::TimeType::Time => range.0.to_time.end_boundary_time(cursor), - }; + let mut min = range.start.start_boundary_time(cursor); + let mut max = range.end.end_boundary_time(cursor); if min > max { std::mem::swap(&mut min, &mut max); @@ -76,33 +68,31 @@ pub fn query_visual_history( ctx: &ViewerContext<'_>, data_result: &re_viewer_context::DataResult, ) -> ExtraQueryHistory { - let visual_time_range_component = - data_result.lookup_override::(ctx); - if let Some(visual_time_range_component) = visual_time_range_component { - ExtraQueryHistory { - enabled: true, - nanos: VisibleHistory { - from: time_range_boundary_to_visible_history_boundary( - &visual_time_range_component.0.from_time, - ), - to: time_range_boundary_to_visible_history_boundary( - &visual_time_range_component.0.to_time, - ), - }, - sequences: VisibleHistory { - from: time_range_boundary_to_visible_history_boundary( - &visual_time_range_component.0.from_sequence, - ), - to: time_range_boundary_to_visible_history_boundary( - &visual_time_range_component.0.to_sequence, - ), - }, - } - } else { - ExtraQueryHistory { - enabled: false, - nanos: VisibleHistory::default(), - sequences: VisibleHistory::default(), - } + let time_range = + data_result.lookup_override::(ctx); + let sequence_range = data_result + .lookup_override::(ctx); + + let mut history = ExtraQueryHistory { + enabled: false, + nanos: Default::default(), + sequences: Default::default(), + }; + + if let Some(time_range) = time_range { + history.enabled = true; + history.nanos = VisibleHistory { + from: time_range_boundary_to_visible_history_boundary(&time_range.0.start), + to: time_range_boundary_to_visible_history_boundary(&time_range.0.end), + }; } + if let Some(sequence_range) = sequence_range { + history.enabled = true; + history.sequences = VisibleHistory { + from: time_range_boundary_to_visible_history_boundary(&sequence_range.0.start), + to: time_range_boundary_to_visible_history_boundary(&sequence_range.0.end), + }; + } + + history } diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 7b7e5e3e721a..b14ac17b713b 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -6,10 +6,8 @@ use re_data_store::TimeType; use re_format::next_grid_tick_magnitude_ns; use re_log_types::{EntityPath, TimeInt, TimeZone}; use re_space_view::{controls, query_space_view_sub_archetype_or_default}; -use re_types::{ - blueprint::components::{Corner2D, VisibleTimeRange}, - components::Range1D, -}; +use re_types::blueprint::datatypes::VisibleTimeRange; +use re_types::{blueprint::components::Corner2D, components::Range1D}; use re_viewer_context::external::re_entity_db::{ EditableAutoValue, EntityProperties, TimeSeriesAggregator, }; diff --git a/crates/re_space_view_time_series/src/util.rs b/crates/re_space_view_time_series/src/util.rs index 0bb2a2284aea..cebe02da7baf 100644 --- a/crates/re_space_view_time_series/src/util.rs +++ b/crates/re_space_view_time_series/src/util.rs @@ -35,15 +35,18 @@ pub fn determine_time_range( plot_bounds: Option, enable_query_clamping: bool, ) -> TimeRange { - let visible_time_range_override = data_result - .lookup_override::(ctx) - .unwrap_or(TimeSeriesSpaceView::DEFAULT_TIME_RANGE); - - let mut time_range = visible_time_range_to_time_range( - &visible_time_range_override, - query.timeline.typ(), - query.latest_at, - ); + let visible_time_range_override = match query.timeline.typ() { + re_log_types::TimeType::Time => data_result + .lookup_override::(ctx) + .map(|v| v.0), + re_log_types::TimeType::Sequence => data_result + .lookup_override::(ctx) + .map(|v| v.0), + } + .unwrap_or(TimeSeriesSpaceView::DEFAULT_TIME_RANGE); + + let mut time_range = + visible_time_range_to_time_range(&visible_time_range_override, query.latest_at); // TODO(cmc): We would love to reduce the query to match the actual plot bounds, but because // the plot widget handles zoom after we provide it with data for the current frame, diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index 0c53379e36e5..a28b8c19f61f 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -20,7 +20,8 @@ include "./blueprint/components/space_view_class.fbs"; include "./blueprint/components/space_view_maximized.fbs"; include "./blueprint/components/space_view_origin.fbs"; include "./blueprint/components/viewer_recommendation_hash.fbs"; -include "./blueprint/components/visible_time_range.fbs"; +include "./blueprint/components/visible_time_range_sequence.fbs"; +include "./blueprint/components/visible_time_range_time.fbs"; include "./blueprint/components/visible.fbs"; include "./blueprint/archetypes/background.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs similarity index 77% rename from crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs rename to crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs index af8c5262bdd2..0e09bea6761e 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs @@ -9,8 +9,8 @@ namespace rerun.blueprint.components; // --- -/// The range of values that will be included in a space view query. -table VisibleTimeRange ( +/// The range of values on time timelines that will be included in a space view query. +table VisibleTimeRangeSequence ( "attr.arrow.transparent", "attr.rerun.scope": "blueprint", "attr.rust.repr": "transparent", diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs new file mode 100644 index 000000000000..8feab929d0a8 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs @@ -0,0 +1,20 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.components; + +// --- + +/// The range of values on sequence timelines that will be included in a space view query. +table VisibleTimeRangeTime ( + "attr.arrow.transparent", + "attr.rerun.scope": "blueprint", + "attr.rust.repr": "transparent", + "attr.rust.derive": "PartialEq, Eq" +) { + value: rerun.blueprint.datatypes.VisibleTimeRange (order: 100); +} diff --git a/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs b/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs index cb872671480e..db49efad0b78 100644 --- a/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs +++ b/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs @@ -34,22 +34,17 @@ struct VisibleTimeRangeBoundary ( time: rerun.datatypes.TimeInt (order: 200); } -/// Visible time range bounds. +/// Visible time range bounds for a timelines. +/// +/// This datatype does not specify whether it's a time or sequence based timeline. struct VisibleTimeRange ( "attr.rerun.scope": "blueprint", "attr.rust.derive": "PartialEq, Eq" ) { - // TODO(andreas): Split this up into two separate components. - /// Low time boundary for sequence timeline. - from_sequence: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 100); + // Can't call it `from` because it's a reserved keyword in Python. + start: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 100); /// High time boundary for sequence timeline. - to_sequence: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 200); - - /// Low time boundary for time timeline. - from_time: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 300); - - /// High time boundary for time timeline. - to_time: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 400); + end: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 200); } diff --git a/crates/re_types/src/blueprint/components/.gitattributes b/crates/re_types/src/blueprint/components/.gitattributes index bcc6988a5622..a3887de6df83 100644 --- a/crates/re_types/src/blueprint/components/.gitattributes +++ b/crates/re_types/src/blueprint/components/.gitattributes @@ -15,4 +15,5 @@ space_view_class.rs linguist-generated=true space_view_origin.rs linguist-generated=true viewer_recommendation_hash.rs linguist-generated=true visible.rs linguist-generated=true -visible_time_range.rs linguist-generated=true +visible_time_range_sequence.rs linguist-generated=true +visible_time_range_time.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/components/mod.rs b/crates/re_types/src/blueprint/components/mod.rs index 403f8aecde4e..c24270ff5a07 100644 --- a/crates/re_types/src/blueprint/components/mod.rs +++ b/crates/re_types/src/blueprint/components/mod.rs @@ -16,8 +16,8 @@ mod viewer_recommendation_hash; mod viewer_recommendation_hash_ext; mod visible; mod visible_ext; -mod visible_time_range; -mod visible_time_range_ext; +mod visible_time_range_sequence; +mod visible_time_range_time; pub use self::active_tab::ActiveTab; pub use self::background_kind::BackgroundKind; @@ -32,4 +32,5 @@ pub use self::space_view_class::SpaceViewClass; pub use self::space_view_origin::SpaceViewOrigin; pub use self::viewer_recommendation_hash::ViewerRecommendationHash; pub use self::visible::Visible; -pub use self::visible_time_range::VisibleTimeRange; +pub use self::visible_time_range_sequence::VisibleTimeRangeSequence; +pub use self::visible_time_range_time::VisibleTimeRangeTime; diff --git a/crates/re_types/src/blueprint/components/visible_time_range_ext.rs b/crates/re_types/src/blueprint/components/visible_time_range_ext.rs deleted file mode 100644 index 051f3d145a13..000000000000 --- a/crates/re_types/src/blueprint/components/visible_time_range_ext.rs +++ /dev/null @@ -1,6 +0,0 @@ -use super::VisibleTimeRange; - -impl VisibleTimeRange { - pub const EMPTY: Self = Self(crate::blueprint::datatypes::VisibleTimeRange::EMPTY); - pub const EVERYTHING: Self = Self(crate::blueprint::datatypes::VisibleTimeRange::EVERYTHING); -} diff --git a/crates/re_types/src/blueprint/components/visible_time_range.rs b/crates/re_types/src/blueprint/components/visible_time_range_sequence.rs similarity index 81% rename from crates/re_types/src/blueprint/components/visible_time_range.rs rename to crates/re_types/src/blueprint/components/visible_time_range_sequence.rs index 146ca8bd5173..e923ce32eaf6 100644 --- a/crates/re_types/src/blueprint/components/visible_time_range.rs +++ b/crates/re_types/src/blueprint/components/visible_time_range_sequence.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -22,12 +22,12 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Component**: The range of values that will be included in a space view query. +/// **Component**: The range of values on time timelines that will be included in a space view query. #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] -pub struct VisibleTimeRange(pub crate::blueprint::datatypes::VisibleTimeRange); +pub struct VisibleTimeRangeSequence(pub crate::blueprint::datatypes::VisibleTimeRange); -impl ::re_types_core::SizeBytes for VisibleTimeRange { +impl ::re_types_core::SizeBytes for VisibleTimeRangeSequence { #[inline] fn heap_size_bytes(&self) -> u64 { self.0.heap_size_bytes() @@ -39,20 +39,22 @@ impl ::re_types_core::SizeBytes for VisibleTimeRange { } } -impl> From for VisibleTimeRange { +impl> From for VisibleTimeRangeSequence { fn from(v: T) -> Self { Self(v.into()) } } -impl std::borrow::Borrow for VisibleTimeRange { +impl std::borrow::Borrow + for VisibleTimeRangeSequence +{ #[inline] fn borrow(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { &self.0 } } -impl std::ops::Deref for VisibleTimeRange { +impl std::ops::Deref for VisibleTimeRangeSequence { type Target = crate::blueprint::datatypes::VisibleTimeRange; #[inline] @@ -61,14 +63,14 @@ impl std::ops::Deref for VisibleTimeRange { } } -::re_types_core::macros::impl_into_cow!(VisibleTimeRange); +::re_types_core::macros::impl_into_cow!(VisibleTimeRangeSequence); -impl ::re_types_core::Loggable for VisibleTimeRange { +impl ::re_types_core::Loggable for VisibleTimeRangeSequence { type Name = ::re_types_core::ComponentName; #[inline] fn name() -> Self::Name { - "rerun.blueprint.components.VisibleTimeRange".into() + "rerun.blueprint.components.VisibleTimeRangeSequence".into() } #[allow(clippy::wildcard_imports)] @@ -77,22 +79,12 @@ impl ::re_types_core::Loggable for VisibleTimeRange { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ Field::new( - "from_sequence", + "start", ::arrow_datatype(), false, ), Field::new( - "to_sequence", - ::arrow_datatype(), - false, - ), - Field::new( - "from_time", - ::arrow_datatype(), - false, - ), - Field::new( - "to_time", + "end", ::arrow_datatype(), false, ), @@ -142,13 +134,13 @@ impl ::re_types_core::Loggable for VisibleTimeRange { use arrow2::{array::*, buffer::*, datatypes::*}; Ok( crate::blueprint::datatypes::VisibleTimeRange::from_arrow_opt(arrow_data) - .with_context("rerun.blueprint.components.VisibleTimeRange#value")? + .with_context("rerun.blueprint.components.VisibleTimeRangeSequence#value")? .into_iter() .map(|v| v.ok_or_else(DeserializationError::missing_data)) .map(|res| res.map(|v| Some(Self(v)))) .collect::>>>() - .with_context("rerun.blueprint.components.VisibleTimeRange#value") - .with_context("rerun.blueprint.components.VisibleTimeRange")?, + .with_context("rerun.blueprint.components.VisibleTimeRangeSequence#value") + .with_context("rerun.blueprint.components.VisibleTimeRangeSequence")?, ) } } diff --git a/crates/re_types/src/blueprint/components/visible_time_range_time.rs b/crates/re_types/src/blueprint/components/visible_time_range_time.rs new file mode 100644 index 000000000000..a3ac1fc08402 --- /dev/null +++ b/crates/re_types/src/blueprint/components/visible_time_range_time.rs @@ -0,0 +1,144 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: The range of values on sequence timelines that will be included in a space view query. +#[derive(Clone, Debug, PartialEq, Eq)] +#[repr(transparent)] +pub struct VisibleTimeRangeTime(pub crate::blueprint::datatypes::VisibleTimeRange); + +impl ::re_types_core::SizeBytes for VisibleTimeRangeTime { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for VisibleTimeRangeTime { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for VisibleTimeRangeTime { + #[inline] + fn borrow(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + &self.0 + } +} + +impl std::ops::Deref for VisibleTimeRangeTime { + type Target = crate::blueprint::datatypes::VisibleTimeRange; + + #[inline] + fn deref(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + &self.0 + } +} + +::re_types_core::macros::impl_into_cow!(VisibleTimeRangeTime); + +impl ::re_types_core::Loggable for VisibleTimeRangeTime { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.blueprint.components.VisibleTimeRangeTime".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new( + "start", + ::arrow_datatype(), + false, + ), + Field::new( + "end", + ::arrow_datatype(), + false, + ), + ])) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data0): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + let datum = datum.map(|datum| { + let Self(data0) = datum.into_owned(); + data0 + }); + (datum.is_some(), datum) + }) + .unzip(); + let data0_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = data0_bitmap; + crate::blueprint::datatypes::VisibleTimeRange::to_arrow_opt(data0)? + } + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok( + crate::blueprint::datatypes::VisibleTimeRange::from_arrow_opt(arrow_data) + .with_context("rerun.blueprint.components.VisibleTimeRangeTime#value")? + .into_iter() + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.blueprint.components.VisibleTimeRangeTime#value") + .with_context("rerun.blueprint.components.VisibleTimeRangeTime")?, + ) + } +} diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range.rs index e63fc5981329..cafb80d1fbdd 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range.rs +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range.rs @@ -22,37 +22,28 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Datatype**: Visible time range bounds. +/// **Datatype**: Visible time range bounds for a timelines. +/// +/// This datatype does not specify whether it's a time or sequence based timeline. #[derive(Clone, Debug, PartialEq, Eq)] pub struct VisibleTimeRange { /// Low time boundary for sequence timeline. - pub from_sequence: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + pub start: crate::blueprint::datatypes::VisibleTimeRangeBoundary, /// High time boundary for sequence timeline. - pub to_sequence: crate::blueprint::datatypes::VisibleTimeRangeBoundary, - - /// Low time boundary for time timeline. - pub from_time: crate::blueprint::datatypes::VisibleTimeRangeBoundary, - - /// High time boundary for time timeline. - pub to_time: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + pub end: crate::blueprint::datatypes::VisibleTimeRangeBoundary, } impl ::re_types_core::SizeBytes for VisibleTimeRange { #[inline] fn heap_size_bytes(&self) -> u64 { - self.from_sequence.heap_size_bytes() - + self.to_sequence.heap_size_bytes() - + self.from_time.heap_size_bytes() - + self.to_time.heap_size_bytes() + self.start.heap_size_bytes() + self.end.heap_size_bytes() } #[inline] fn is_pod() -> bool { ::is_pod() && ::is_pod() - && ::is_pod() - && ::is_pod() } } @@ -72,22 +63,12 @@ impl ::re_types_core::Loggable for VisibleTimeRange { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ Field::new( - "from_sequence", + "start", ::arrow_datatype(), false, ), Field::new( - "to_sequence", - ::arrow_datatype(), - false, - ), - Field::new( - "from_time", - ::arrow_datatype(), - false, - ), - Field::new( - "to_time", + "end", ::arrow_datatype(), false, ), @@ -119,90 +100,46 @@ impl ::re_types_core::Loggable for VisibleTimeRange { ::arrow_datatype(), vec![ { - let (somes, from_sequence): (Vec<_>, Vec<_>) = data - .iter() - .map(|datum| { - let datum = datum.as_ref().map(|datum| { - let Self { from_sequence, .. } = &**datum; - from_sequence.clone() - }); - (datum.is_some(), datum) - }) - .unzip(); - let from_sequence_bitmap: Option = { - let any_nones = somes.iter().any(|some| !*some); - any_nones.then(|| somes.into()) - }; - { - _ = from_sequence_bitmap; - crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( - from_sequence, - )? - } - }, - { - let (somes, to_sequence): (Vec<_>, Vec<_>) = data - .iter() - .map(|datum| { - let datum = datum.as_ref().map(|datum| { - let Self { to_sequence, .. } = &**datum; - to_sequence.clone() - }); - (datum.is_some(), datum) - }) - .unzip(); - let to_sequence_bitmap: Option = { - let any_nones = somes.iter().any(|some| !*some); - any_nones.then(|| somes.into()) - }; - { - _ = to_sequence_bitmap; - crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( - to_sequence, - )? - } - }, - { - let (somes, from_time): (Vec<_>, Vec<_>) = data + let (somes, start): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum.as_ref().map(|datum| { - let Self { from_time, .. } = &**datum; - from_time.clone() + let Self { start, .. } = &**datum; + start.clone() }); (datum.is_some(), datum) }) .unzip(); - let from_time_bitmap: Option = { + let start_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; { - _ = from_time_bitmap; + _ = start_bitmap; crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( - from_time, + start, )? } }, { - let (somes, to_time): (Vec<_>, Vec<_>) = data + let (somes, end): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum.as_ref().map(|datum| { - let Self { to_time, .. } = &**datum; - to_time.clone() + let Self { end, .. } = &**datum; + end.clone() }); (datum.is_some(), datum) }) .unzip(); - let to_time_bitmap: Option = { + let end_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; { - _ = to_time_bitmap; + _ = end_bitmap; crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( - to_time, + end, )? } }, @@ -242,93 +179,49 @@ impl ::re_types_core::Loggable for VisibleTimeRange { .map(|field| field.name.as_str()) .zip(arrow_data_arrays) .collect(); - let from_sequence = { - if !arrays_by_name.contains_key("from_sequence") { + let start = { + if !arrays_by_name.contains_key("start") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "from_sequence", + "start", )) .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); } - let arrow_data = &**arrays_by_name["from_sequence"]; + let arrow_data = &**arrays_by_name["start"]; crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( arrow_data, ) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange#from_sequence")? + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#start")? .into_iter() }; - let to_sequence = { - if !arrays_by_name.contains_key("to_sequence") { + let end = { + if !arrays_by_name.contains_key("end") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "to_sequence", + "end", )) .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); } - let arrow_data = &**arrays_by_name["to_sequence"]; + let arrow_data = &**arrays_by_name["end"]; crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( arrow_data, ) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange#to_sequence")? - .into_iter() - }; - let from_time = { - if !arrays_by_name.contains_key("from_time") { - return Err(DeserializationError::missing_struct_field( - Self::arrow_datatype(), - "from_time", - )) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); - } - let arrow_data = &**arrays_by_name["from_time"]; - crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( - arrow_data, - ) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange#from_time")? - .into_iter() - }; - let to_time = { - if !arrays_by_name.contains_key("to_time") { - return Err(DeserializationError::missing_struct_field( - Self::arrow_datatype(), - "to_time", - )) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); - } - let arrow_data = &**arrays_by_name["to_time"]; - crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( - arrow_data, - ) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange#to_time")? + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#end")? .into_iter() }; arrow2::bitmap::utils::ZipValidity::new_with_validity( - ::itertools::izip!(from_sequence, to_sequence, from_time, to_time), + ::itertools::izip!(start, end), arrow_data.validity(), ) .map(|opt| { - opt.map(|(from_sequence, to_sequence, from_time, to_time)| { + opt.map(|(start, end)| { Ok(Self { - from_sequence: from_sequence - .ok_or_else(DeserializationError::missing_data) - .with_context( - "rerun.blueprint.datatypes.VisibleTimeRange#from_sequence", - )?, - to_sequence: to_sequence - .ok_or_else(DeserializationError::missing_data) - .with_context( - "rerun.blueprint.datatypes.VisibleTimeRange#to_sequence", - )?, - from_time: from_time + start: start .ok_or_else(DeserializationError::missing_data) - .with_context( - "rerun.blueprint.datatypes.VisibleTimeRange#from_time", - )?, - to_time: to_time + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#start")?, + end: end .ok_or_else(DeserializationError::missing_data) - .with_context( - "rerun.blueprint.datatypes.VisibleTimeRange#to_time", - )?, + .with_context("rerun.blueprint.datatypes.VisibleTimeRange#end")?, }) }) .transpose() diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs index d558b143e343..d1b1dd7ea1d4 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs @@ -2,16 +2,12 @@ use super::{VisibleTimeRange, VisibleTimeRangeBoundary}; impl VisibleTimeRange { pub const EMPTY: Self = Self { - from_sequence: VisibleTimeRangeBoundary::AT_CURSOR, - to_sequence: VisibleTimeRangeBoundary::AT_CURSOR, - from_time: VisibleTimeRangeBoundary::AT_CURSOR, - to_time: VisibleTimeRangeBoundary::AT_CURSOR, + start: VisibleTimeRangeBoundary::AT_CURSOR, + end: VisibleTimeRangeBoundary::AT_CURSOR, }; pub const EVERYTHING: Self = Self { - from_sequence: VisibleTimeRangeBoundary::INFINITE, - to_sequence: VisibleTimeRangeBoundary::INFINITE, - from_time: VisibleTimeRangeBoundary::INFINITE, - to_time: VisibleTimeRangeBoundary::INFINITE, + start: VisibleTimeRangeBoundary::INFINITE, + end: VisibleTimeRangeBoundary::INFINITE, }; } diff --git a/crates/re_types_builder/Cargo.toml b/crates/re_types_builder/Cargo.toml index 6d58ba9da388..8006b6e2eafa 100644 --- a/crates/re_types_builder/Cargo.toml +++ b/crates/re_types_builder/Cargo.toml @@ -22,6 +22,7 @@ all-features = true [dependencies] re_build_tools.workspace = true +re_error.workspace = true re_log = { workspace = true, features = ["setup"] } re_tracing = { workspace = true, features = ["server"] } diff --git a/crates/re_types_builder/src/format/python.rs b/crates/re_types_builder/src/format/python.rs index 3b134264cfab..e98c7fd4e213 100644 --- a/crates/re_types_builder/src/format/python.rs +++ b/crates/re_types_builder/src/format/python.rs @@ -45,7 +45,10 @@ impl CodeFormatter for PythonCodeFormatter { }); if let Err(err) = format_python_dir(&tempdir_path) { - reporter.error_file(&tempdir_path, err); + reporter.error_file( + &tempdir_path, + re_error::format(err.context("python code formatting")), + ); } // Read back and copy to the final destination: diff --git a/crates/re_viewer/src/blueprint/validation_gen/mod.rs b/crates/re_viewer/src/blueprint/validation_gen/mod.rs index c21897873f93..65c60a97365a 100644 --- a/crates/re_viewer/src/blueprint/validation_gen/mod.rs +++ b/crates/re_viewer/src/blueprint/validation_gen/mod.rs @@ -15,7 +15,8 @@ pub use re_types::blueprint::components::SpaceViewClass; pub use re_types::blueprint::components::SpaceViewOrigin; pub use re_types::blueprint::components::ViewerRecommendationHash; pub use re_types::blueprint::components::Visible; -pub use re_types::blueprint::components::VisibleTimeRange; +pub use re_types::blueprint::components::VisibleTimeRangeSequence; +pub use re_types::blueprint::components::VisibleTimeRangeTime; pub use re_types_blueprint::blueprint::components::AutoLayout; pub use re_types_blueprint::blueprint::components::AutoSpaceViews; pub use re_types_blueprint::blueprint::components::ContainerKind; @@ -49,5 +50,6 @@ pub fn is_valid_blueprint(blueprint: &EntityDb) -> bool { && validate_component::(blueprint) && validate_component::(blueprint) && validate_component::(blueprint) - && validate_component::(blueprint) + && validate_component::(blueprint) + && validate_component::(blueprint) } diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index b6e7192e5abf..c00f4118a7fe 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -11,7 +11,7 @@ use re_space_view::{ }; use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D}; use re_space_view_time_series::TimeSeriesSpaceView; -use re_types::blueprint::components::VisibleTimeRange; +use re_types::blueprint::components::{VisibleTimeRangeSequence, VisibleTimeRangeTime}; use re_types_core::Loggable as _; use re_ui::{markdown_ui, ReUi}; use re_viewer_context::{SpaceViewClass, SpaceViewClassIdentifier, ViewerContext}; @@ -59,22 +59,33 @@ pub fn visual_time_range_ui( .space_view_class_registry .get_class_or_log_error(&space_view_class); - let mut resolved_range = data_result - .lookup_override::(ctx) - .unwrap_or(space_view_class.default_visible_time_range()); + let active_time_range_override = match time_type { + TimeType::Time => data_result + .lookup_override::(ctx) + .map(|v| v.0), + TimeType::Sequence => data_result + .lookup_override::(ctx) + .map(|v| v.0), + }; + let mut has_individual_range = if let Some(data_result_tree) = data_result_tree { // If there is a data-tree, we know we have individual settings if we are our own source. - data_result - .component_override_source(data_result_tree, &VisibleTimeRange::name()) - .as_ref() - == Some(&data_result.entity_path) + let component_override_source = match time_type { + TimeType::Time => data_result + .component_override_source(data_result_tree, &VisibleTimeRangeTime::name()), + TimeType::Sequence => data_result + .component_override_source(data_result_tree, &VisibleTimeRangeSequence::name()), + }; + + component_override_source.as_ref() == Some(&data_result.entity_path) } else { // Otherwise we can inspect directly. - data_result - .lookup_override::(ctx) - .is_some() + active_time_range_override.is_some() }; + let mut resolved_range = + active_time_range_override.unwrap_or(space_view_class.default_visible_time_range()); + let collapsing_response = re_ui.collapsing_header(ui, "Visible time range", false, |ui| { let has_individual_range_before = has_individual_range; let resolved_range_before = resolved_range.clone(); @@ -109,17 +120,8 @@ pub fn visual_time_range_ui( .unwrap_or_default() .at_least(*timeline_spec.range.start()); // accounts for timeless time (TimeInt::MIN) - // pick right from/to depending on the timeline type. - let (from, to) = match time_type { - TimeType::Time => ( - &mut resolved_range.0.from_time, - &mut resolved_range.0.to_time, - ), - TimeType::Sequence => ( - &mut resolved_range.0.from_sequence, - &mut resolved_range.0.to_sequence, - ), - }; + let from = &mut resolved_range.start; + let to = &mut resolved_range.end; // Convert to legacy visual history type. let mut visible_history = VisibleHistory { @@ -230,11 +232,22 @@ pub fn visual_time_range_ui( || resolved_range != resolved_range_before { if has_individual_range { - re_log::debug!("override!"); - data_result.save_recursive_override(ctx, &resolved_range); + let resolved_range = resolved_range.clone(); + match time_type { + TimeType::Time => data_result + .save_recursive_override(ctx, &VisibleTimeRangeTime(resolved_range)), + TimeType::Sequence => data_result + .save_recursive_override(ctx, &VisibleTimeRangeSequence(resolved_range)), + }; } else { - re_log::debug!("clear!"); - data_result.clear_recursive_override::(ctx); + match time_type { + TimeType::Time => { + data_result.clear_recursive_override::(ctx); + } + TimeType::Sequence => { + data_result.clear_recursive_override::(ctx); + } + } } } }); @@ -262,7 +275,7 @@ pub fn visual_time_range_ui( if should_display_visible_history { if let Some(current_time) = time_ctrl.time_int() { - let range = visible_time_range_to_time_range(&resolved_range, time_type, current_time); + let range = visible_time_range_to_time_range(&resolved_range, current_time); ctx.rec_cfg.time_ctrl.write().highlighted_range = Some(range); } } diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index e5ab37b493a6..57acd405048e 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -1,7 +1,7 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityProperties, EntityPropertyMap}; use re_log_types::EntityPath; -use re_types::{blueprint::components::VisibleTimeRange, ComponentName}; +use re_types::{blueprint::datatypes::VisibleTimeRange, ComponentName}; use crate::{ IndicatedEntities, PerSystemEntities, PerVisualizer, SmallVisualizerSet, diff --git a/rerun_cpp/src/rerun/blueprint/components.hpp b/rerun_cpp/src/rerun/blueprint/components.hpp index acc1c7879ee7..c684d4e48ed3 100644 --- a/rerun_cpp/src/rerun/blueprint/components.hpp +++ b/rerun_cpp/src/rerun/blueprint/components.hpp @@ -23,4 +23,5 @@ #include "blueprint/components/space_view_origin.hpp" #include "blueprint/components/viewer_recommendation_hash.hpp" #include "blueprint/components/visible.hpp" -#include "blueprint/components/visible_time_range.hpp" +#include "blueprint/components/visible_time_range_sequence.hpp" +#include "blueprint/components/visible_time_range_time.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/components/.gitattributes b/rerun_cpp/src/rerun/blueprint/components/.gitattributes index bea2a6a8f0de..4eaf61272d82 100644 --- a/rerun_cpp/src/rerun/blueprint/components/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/components/.gitattributes @@ -32,4 +32,5 @@ space_view_origin.hpp linguist-generated=true viewer_recommendation_hash.hpp linguist-generated=true visible.cpp linguist-generated=true visible.hpp linguist-generated=true -visible_time_range.hpp linguist-generated=true +visible_time_range_sequence.hpp linguist-generated=true +visible_time_range_time.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/visible_time_range_sequence.hpp b/rerun_cpp/src/rerun/blueprint/components/visible_time_range_sequence.hpp new file mode 100644 index 000000000000..dee892ace385 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/components/visible_time_range_sequence.hpp @@ -0,0 +1,61 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs". + +#pragma once + +#include "../../blueprint/datatypes/visible_time_range.hpp" +#include "../../result.hpp" + +#include +#include + +namespace rerun::blueprint::components { + /// **Component**: The range of values on time timelines that will be included in a space view query. + struct VisibleTimeRangeSequence { + rerun::blueprint::datatypes::VisibleTimeRange value; + + public: + VisibleTimeRangeSequence() = default; + + VisibleTimeRangeSequence(rerun::blueprint::datatypes::VisibleTimeRange value_) + : value(value_) {} + + VisibleTimeRangeSequence& operator=(rerun::blueprint::datatypes::VisibleTimeRange value_) { + value = value_; + return *this; + } + + /// Cast to the underlying VisibleTimeRange datatype + operator rerun::blueprint::datatypes::VisibleTimeRange() const { + return value; + } + }; +} // namespace rerun::blueprint::components + +namespace rerun { + static_assert( + sizeof(rerun::blueprint::datatypes::VisibleTimeRange) == + sizeof(blueprint::components::VisibleTimeRangeSequence) + ); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.VisibleTimeRangeSequence"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::blueprint:: components::VisibleTimeRangeSequence` into an arrow array. + static Result> to_arrow( + const blueprint::components::VisibleTimeRangeSequence* instances, size_t num_instances + ) { + return Loggable::to_arrow( + &instances->value, + num_instances + ); + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp b/rerun_cpp/src/rerun/blueprint/components/visible_time_range_time.hpp similarity index 67% rename from rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp rename to rerun_cpp/src/rerun/blueprint/components/visible_time_range_time.hpp index 572ec3e8003a..478cabff5272 100644 --- a/rerun_cpp/src/rerun/blueprint/components/visible_time_range.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/visible_time_range_time.hpp @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs". #pragma once @@ -10,16 +10,17 @@ #include namespace rerun::blueprint::components { - /// **Component**: The range of values that will be included in a space view query. - struct VisibleTimeRange { + /// **Component**: The range of values on sequence timelines that will be included in a space view query. + struct VisibleTimeRangeTime { rerun::blueprint::datatypes::VisibleTimeRange value; public: - VisibleTimeRange() = default; + VisibleTimeRangeTime() = default; - VisibleTimeRange(rerun::blueprint::datatypes::VisibleTimeRange value_) : value(value_) {} + VisibleTimeRangeTime(rerun::blueprint::datatypes::VisibleTimeRange value_) + : value(value_) {} - VisibleTimeRange& operator=(rerun::blueprint::datatypes::VisibleTimeRange value_) { + VisibleTimeRangeTime& operator=(rerun::blueprint::datatypes::VisibleTimeRange value_) { value = value_; return *this; } @@ -34,22 +35,22 @@ namespace rerun::blueprint::components { namespace rerun { static_assert( sizeof(rerun::blueprint::datatypes::VisibleTimeRange) == - sizeof(blueprint::components::VisibleTimeRange) + sizeof(blueprint::components::VisibleTimeRangeTime) ); /// \private template <> - struct Loggable { - static constexpr const char Name[] = "rerun.blueprint.components.VisibleTimeRange"; + struct Loggable { + static constexpr const char Name[] = "rerun.blueprint.components.VisibleTimeRangeTime"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype() { return Loggable::arrow_datatype(); } - /// Serializes an array of `rerun::blueprint:: components::VisibleTimeRange` into an arrow array. + /// Serializes an array of `rerun::blueprint:: components::VisibleTimeRangeTime` into an arrow array. static Result> to_arrow( - const blueprint::components::VisibleTimeRange* instances, size_t num_instances + const blueprint::components::VisibleTimeRangeTime* instances, size_t num_instances ) { return Loggable::to_arrow( &instances->value, diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp index 36f9e1bdaa5b..d4a26678aa7b 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp @@ -15,22 +15,12 @@ namespace rerun { Loggable::arrow_datatype() { static const auto datatype = arrow::struct_({ arrow::field( - "from_sequence", + "start", Loggable::arrow_datatype(), false ), arrow::field( - "to_sequence", - Loggable::arrow_datatype(), - false - ), - arrow::field( - "from_time", - Loggable::arrow_datatype(), - false - ), - arrow::field( - "to_time", + "end", Loggable::arrow_datatype(), false ), @@ -78,42 +68,20 @@ namespace rerun { { auto field_builder = static_cast(builder->field_builder(0)); ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - RR_RETURN_NOT_OK(Loggable:: - fill_arrow_array_builder( - field_builder, - &elements[elem_idx].from_sequence, - 1 - )); - } - } - { - auto field_builder = static_cast(builder->field_builder(1)); - ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { RR_RETURN_NOT_OK( Loggable:: - fill_arrow_array_builder(field_builder, &elements[elem_idx].to_sequence, 1) + fill_arrow_array_builder(field_builder, &elements[elem_idx].start, 1) ); } } { - auto field_builder = static_cast(builder->field_builder(2)); - ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); - for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - RR_RETURN_NOT_OK( - Loggable:: - fill_arrow_array_builder(field_builder, &elements[elem_idx].from_time, 1) - ); - } - } - { - auto field_builder = static_cast(builder->field_builder(3)); + auto field_builder = static_cast(builder->field_builder(1)); ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { RR_RETURN_NOT_OK( Loggable:: - fill_arrow_array_builder(field_builder, &elements[elem_idx].to_time, 1) + fill_arrow_array_builder(field_builder, &elements[elem_idx].end, 1) ); } } diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp index 6a0dc250edf7..8befacc65f8b 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp +++ b/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp @@ -16,19 +16,15 @@ namespace arrow { } // namespace arrow namespace rerun::blueprint::datatypes { - /// **Datatype**: Visible time range bounds. + /// **Datatype**: Visible time range bounds for a timelines. + /// + /// This datatype does not specify whether it's a time or sequence based timeline. struct VisibleTimeRange { /// Low time boundary for sequence timeline. - rerun::blueprint::datatypes::VisibleTimeRangeBoundary from_sequence; + rerun::blueprint::datatypes::VisibleTimeRangeBoundary start; /// High time boundary for sequence timeline. - rerun::blueprint::datatypes::VisibleTimeRangeBoundary to_sequence; - - /// Low time boundary for time timeline. - rerun::blueprint::datatypes::VisibleTimeRangeBoundary from_time; - - /// High time boundary for time timeline. - rerun::blueprint::datatypes::VisibleTimeRangeBoundary to_time; + rerun::blueprint::datatypes::VisibleTimeRangeBoundary end; public: VisibleTimeRange() = default; diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes index 5f570fe84651..e82ead8d1718 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/.gitattributes @@ -23,4 +23,5 @@ space_view_maximized.py linguist-generated=true space_view_origin.py linguist-generated=true viewer_recommendation_hash.py linguist-generated=true visible.py linguist-generated=true -visible_time_range.py linguist-generated=true +visible_time_range_sequence.py linguist-generated=true +visible_time_range_time.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py index c398116775ac..567443d5f788 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/__init__.py @@ -51,7 +51,12 @@ ViewerRecommendationHashType, ) from .visible import Visible, VisibleArrayLike, VisibleBatch, VisibleLike, VisibleType -from .visible_time_range import VisibleTimeRange, VisibleTimeRangeBatch, VisibleTimeRangeType +from .visible_time_range_sequence import ( + VisibleTimeRangeSequence, + VisibleTimeRangeSequenceBatch, + VisibleTimeRangeSequenceType, +) +from .visible_time_range_time import VisibleTimeRangeTime, VisibleTimeRangeTimeBatch, VisibleTimeRangeTimeType __all__ = [ "ActiveTab", @@ -136,8 +141,11 @@ "VisibleArrayLike", "VisibleBatch", "VisibleLike", - "VisibleTimeRange", - "VisibleTimeRangeBatch", - "VisibleTimeRangeType", + "VisibleTimeRangeSequence", + "VisibleTimeRangeSequenceBatch", + "VisibleTimeRangeSequenceType", + "VisibleTimeRangeTime", + "VisibleTimeRangeTimeBatch", + "VisibleTimeRangeTimeType", "VisibleType", ] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py deleted file mode 100644 index 21c45c02ac84..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range.py +++ /dev/null @@ -1,28 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range.fbs". - -# You can extend this class by creating a "VisibleTimeRangeExt" class in "visible_time_range_ext.py". - -from __future__ import annotations - -from ..._baseclasses import ComponentBatchMixin -from ...blueprint import datatypes as blueprint_datatypes - -__all__ = ["VisibleTimeRange", "VisibleTimeRangeBatch", "VisibleTimeRangeType"] - - -class VisibleTimeRange(blueprint_datatypes.VisibleTimeRange): - """**Component**: The range of values that will be included in a space view query.""" - - # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py - - # Note: there are no fields here because VisibleTimeRange delegates to datatypes.VisibleTimeRange - pass - - -class VisibleTimeRangeType(blueprint_datatypes.VisibleTimeRangeType): - _TYPE_NAME: str = "rerun.blueprint.components.VisibleTimeRange" - - -class VisibleTimeRangeBatch(blueprint_datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): - _ARROW_TYPE = VisibleTimeRangeType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_sequence.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_sequence.py new file mode 100644 index 000000000000..b1b743a16b6f --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_sequence.py @@ -0,0 +1,28 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs". + +# You can extend this class by creating a "VisibleTimeRangeSequenceExt" class in "visible_time_range_sequence_ext.py". + +from __future__ import annotations + +from ..._baseclasses import ComponentBatchMixin +from ...blueprint import datatypes as blueprint_datatypes + +__all__ = ["VisibleTimeRangeSequence", "VisibleTimeRangeSequenceBatch", "VisibleTimeRangeSequenceType"] + + +class VisibleTimeRangeSequence(blueprint_datatypes.VisibleTimeRange): + """**Component**: The range of values on time timelines that will be included in a space view query.""" + + # You can define your own __init__ function as a member of VisibleTimeRangeSequenceExt in visible_time_range_sequence_ext.py + + # Note: there are no fields here because VisibleTimeRangeSequence delegates to datatypes.VisibleTimeRange + pass + + +class VisibleTimeRangeSequenceType(blueprint_datatypes.VisibleTimeRangeType): + _TYPE_NAME: str = "rerun.blueprint.components.VisibleTimeRangeSequence" + + +class VisibleTimeRangeSequenceBatch(blueprint_datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): + _ARROW_TYPE = VisibleTimeRangeSequenceType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_time.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_time.py new file mode 100644 index 000000000000..b83c8a2e642a --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_time.py @@ -0,0 +1,28 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs". + +# You can extend this class by creating a "VisibleTimeRangeTimeExt" class in "visible_time_range_time_ext.py". + +from __future__ import annotations + +from ..._baseclasses import ComponentBatchMixin +from ...blueprint import datatypes as blueprint_datatypes + +__all__ = ["VisibleTimeRangeTime", "VisibleTimeRangeTimeBatch", "VisibleTimeRangeTimeType"] + + +class VisibleTimeRangeTime(blueprint_datatypes.VisibleTimeRange): + """**Component**: The range of values on sequence timelines that will be included in a space view query.""" + + # You can define your own __init__ function as a member of VisibleTimeRangeTimeExt in visible_time_range_time_ext.py + + # Note: there are no fields here because VisibleTimeRangeTime delegates to datatypes.VisibleTimeRange + pass + + +class VisibleTimeRangeTimeType(blueprint_datatypes.VisibleTimeRangeType): + _TYPE_NAME: str = "rerun.blueprint.components.VisibleTimeRangeTime" + + +class VisibleTimeRangeTimeBatch(blueprint_datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): + _ARROW_TYPE = VisibleTimeRangeTimeType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py index a588b0ac926c..8f1561a7bbbe 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py @@ -24,54 +24,42 @@ @define(init=False) class VisibleTimeRange: - """**Datatype**: Visible time range bounds.""" + """ + **Datatype**: Visible time range bounds for a timelines. + + This datatype does not specify whether it's a time or sequence based timeline. + """ def __init__( self: Any, - from_sequence: blueprint_datatypes.VisibleTimeRangeBoundaryLike, - to_sequence: blueprint_datatypes.VisibleTimeRangeBoundaryLike, - from_time: blueprint_datatypes.VisibleTimeRangeBoundaryLike, - to_time: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + start: blueprint_datatypes.VisibleTimeRangeBoundaryLike, + end: blueprint_datatypes.VisibleTimeRangeBoundaryLike, ): """ Create a new instance of the VisibleTimeRange datatype. Parameters ---------- - from_sequence: + start: Low time boundary for sequence timeline. - to_sequence: + end: High time boundary for sequence timeline. - from_time: - Low time boundary for time timeline. - to_time: - High time boundary for time timeline. """ # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py - self.__attrs_init__(from_sequence=from_sequence, to_sequence=to_sequence, from_time=from_time, to_time=to_time) + self.__attrs_init__(start=start, end=end) - from_sequence: blueprint_datatypes.VisibleTimeRangeBoundary = field() + start: blueprint_datatypes.VisibleTimeRangeBoundary = field() # Low time boundary for sequence timeline. # # (Docstring intentionally commented out to hide this field from the docs) - to_sequence: blueprint_datatypes.VisibleTimeRangeBoundary = field() + end: blueprint_datatypes.VisibleTimeRangeBoundary = field() # High time boundary for sequence timeline. # # (Docstring intentionally commented out to hide this field from the docs) - from_time: blueprint_datatypes.VisibleTimeRangeBoundary = field() - # Low time boundary for time timeline. - # - # (Docstring intentionally commented out to hide this field from the docs) - - to_time: blueprint_datatypes.VisibleTimeRangeBoundary = field() - # High time boundary for time timeline. - # - # (Docstring intentionally commented out to hide this field from the docs) - VisibleTimeRangeLike = VisibleTimeRange VisibleTimeRangeArrayLike = Union[ @@ -88,45 +76,7 @@ def __init__(self) -> None: self, pa.struct([ pa.field( - "from_sequence", - pa.struct([ - pa.field( - "kind", - pa.sparse_union([ - pa.field("_null_markers", pa.null(), nullable=True, metadata={}), - pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), - pa.field("Absolute", pa.null(), nullable=True, metadata={}), - pa.field("Infinite", pa.null(), nullable=True, metadata={}), - ]), - nullable=False, - metadata={}, - ), - pa.field("time", pa.int64(), nullable=False, metadata={}), - ]), - nullable=False, - metadata={}, - ), - pa.field( - "to_sequence", - pa.struct([ - pa.field( - "kind", - pa.sparse_union([ - pa.field("_null_markers", pa.null(), nullable=True, metadata={}), - pa.field("RelativeToTimeCursor", pa.null(), nullable=True, metadata={}), - pa.field("Absolute", pa.null(), nullable=True, metadata={}), - pa.field("Infinite", pa.null(), nullable=True, metadata={}), - ]), - nullable=False, - metadata={}, - ), - pa.field("time", pa.int64(), nullable=False, metadata={}), - ]), - nullable=False, - metadata={}, - ), - pa.field( - "from_time", + "start", pa.struct([ pa.field( "kind", @@ -145,7 +95,7 @@ def __init__(self) -> None: metadata={}, ), pa.field( - "to_time", + "end", pa.struct([ pa.field( "kind", From 10c7d4cc09958a9bd12ffdc646d8466613e5d9a4 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 29 Apr 2024 09:43:18 +0200 Subject: [PATCH 381/508] Properly handle cleared primaries in archetype getter (#6145) - Fixes #6048 --- crates/re_entity_db/src/entity_db.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index c7b7e8f29fd5..f298072bc266 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -219,11 +219,20 @@ impl EntityDb { match results.to_archetype(self.resolver()).flatten() { PromiseResult::Pending => PromiseResult::Pending, PromiseResult::Error(err) => { + // Primary component has never been logged. if let Some(err) = err.downcast_ref::() { if matches!(err, re_query::QueryError::PrimaryNotFound(_)) { return PromiseResult::Ready(None); } } + + // Primary component has been cleared. + if let Some(err) = err.downcast_ref::() { + if matches!(err, re_types_core::DeserializationError::MissingData { .. }) { + return PromiseResult::Ready(None); + } + } + PromiseResult::Error(err) } PromiseResult::Ready(arch) => { From 6ae925ae90698ddba7356b04c4a2bf9758b7d2e2 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Mon, 29 Apr 2024 10:24:32 +0200 Subject: [PATCH 382/508] Fix component overrides (#6147) More rebase typos, yay! - Fixes #6085 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6147?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6147?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6147) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_viewer/src/ui/override_ui.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index 8766fa7289e5..b0779fa7c4c0 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -106,8 +106,13 @@ pub fn override_ui( re_ui::ReUi::setup_table_body(&mut body); let row_height = re_ui::ReUi::table_line_height(); body.rows(row_height, components.len(), |mut row| { - if let Some((component_name, OverridePath { store_kind, path })) = - components.get(row.index()) + if let Some(( + component_name, + OverridePath { + store_kind, + path: entity_path_overridden, + }, + )) = components.get(row.index()) { // Remove button row.col(|ui| { @@ -140,7 +145,12 @@ pub fn override_ui( ctx.store_context .blueprint .query_caches() - .latest_at(store, query, entity_path, [*component_name]) + .latest_at( + store, + query, + entity_path_overridden, + [*component_name], + ) .components .get(component_name) .cloned() /* arc */ @@ -151,7 +161,7 @@ pub fn override_ui( .latest_at( ctx.recording_store(), &query, - entity_path, + entity_path_overridden, [*component_name], ) .components @@ -167,7 +177,7 @@ pub fn override_ui( UiVerbosity::Small, &query, ctx.recording(), - path, + entity_path_overridden, &overrides.individual_override_path, &results, instance, From c385066dc126839e1439b89283b17feb7b8929f5 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Mon, 29 Apr 2024 14:09:17 +0200 Subject: [PATCH 383/508] Clarify docs on GH release install & C++ source build, remove reundant rerun_cpp_sdk artifact (#6144) ### What Minor doc cleanup plus removing redundant c++ sdk zip from future artifacts: The less verbose of these will no longer show up in the next release: ![image](https://github.com/rerun-io/rerun/assets/1220815/d1351f0b-74bd-448f-ab9e-908cfa4228a3) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6144?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6144?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6144) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- docs/content/getting-started/installing-viewer.md | 2 +- rerun_cpp/README.md | 8 ++++---- scripts/ci/sync_release_assets.py | 2 -- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/content/getting-started/installing-viewer.md b/docs/content/getting-started/installing-viewer.md index c9be59b52578..f224ae489cd7 100644 --- a/docs/content/getting-started/installing-viewer.md +++ b/docs/content/getting-started/installing-viewer.md @@ -37,7 +37,7 @@ Make sure that your library version matches the version of the Viewer you're usi There are many ways to install the viewer. Please pick whatever works best for your setup: -- Download it from the [GitHub Release artifacts](https://github.com/rerun-io/rerun/releases/latest/) +- Download `rerun-cli` for your platform from the [GitHub Release artifacts](https://github.com/rerun-io/rerun/releases/latest/). - Via Cargo - `cargo binstall rerun-cli` - download binaries via [`cargo binstall`](https://github.com/cargo-bins/cargo-binstall) - `cargo install rerun-cli` - build it from source (this requires Rust 1.76+) diff --git a/rerun_cpp/README.md b/rerun_cpp/README.md index 872b0520ac6c..f463d92bd8a7 100644 --- a/rerun_cpp/README.md +++ b/rerun_cpp/README.md @@ -62,13 +62,13 @@ Check the [general doc page on types](https://www.rerun.io/docs/reference/types) ### Overview -To avoid compatibility issues across different platforms, compiler versions and C++ standard library versions -the C++ SDK is expected to be built from source. - From a build system perspective, the SDK consists of three dependencies: -* [SDK source](https://github.com/rerun-io/rerun/tree/latest/rerun_cpp/src/) +* [C++ SDK source](https://github.com/rerun-io/rerun/tree/latest/rerun_cpp/src/) * This includes **both** source and header files! + * To avoid compatibility issues across different platforms, compiler versions and C++ standard library versions +we recommend to build the C++ SDK directly from source. +Note that this also what happens when you follow the CMake setup in the [quickstart guide](https://www.rerun.io/docs/getting-started/quick-start/cpp). * [rerun_c](https://github.com/rerun-io/rerun/tree/latest/crates/rerun_c/) static libraries * Rerun C is a minimal C SDK and forms the bridge to the shared Rust codebase * Due to the rigidity of the C ABI and lack of complex standard library types in the interface, diff --git a/scripts/ci/sync_release_assets.py b/scripts/ci/sync_release_assets.py index 60bb6ab7ded5..dbfbadc7204c 100644 --- a/scripts/ci/sync_release_assets.py +++ b/scripts/ci/sync_release_assets.py @@ -129,8 +129,6 @@ def fetch_binary_assets( if blob is not None and blob.name is not None: name = blob.name.split("/")[-1] print(f"Found Rerun cross-platform bundle: {name}") - assets[name] = blob - # NOTE: Want a versioned one too. assets[f"rerun_cpp_sdk-{tag}-multiplatform.zip"] = blob else: all_found = False From 845591c53c752900cbc188a0972705e1bda6f1d1 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:35:48 +0200 Subject: [PATCH 384/508] `ListItem` 2.0 (part 0): `re_ui_example` refactor (#6148) ### What The first stage of the `ListItem` 2.0 effort will be to deploy on `re_ui_example`, which is currently a mess. This pure refactor PR splits it into multiple file as a preparatory step. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6148?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6148?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6148) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_ui/examples/re_ui_example.rs | 1227 ----------------- .../examples/re_ui_example/drag_and_drop.rs | 117 ++ .../hierarchical_drag_and_drop.rs | 440 ++++++ crates/re_ui/examples/re_ui_example/main.rs | 523 +++++++ .../examples/re_ui_example/right_panel.rs | 154 +++ 5 files changed, 1234 insertions(+), 1227 deletions(-) delete mode 100644 crates/re_ui/examples/re_ui_example.rs create mode 100644 crates/re_ui/examples/re_ui_example/drag_and_drop.rs create mode 100644 crates/re_ui/examples/re_ui_example/hierarchical_drag_and_drop.rs create mode 100644 crates/re_ui/examples/re_ui_example/main.rs create mode 100644 crates/re_ui/examples/re_ui_example/right_panel.rs diff --git a/crates/re_ui/examples/re_ui_example.rs b/crates/re_ui/examples/re_ui_example.rs deleted file mode 100644 index a035b9a5b2de..000000000000 --- a/crates/re_ui/examples/re_ui_example.rs +++ /dev/null @@ -1,1227 +0,0 @@ -use re_ui::ListItem; -use re_ui::{toasts, CommandPalette, ReUi, UICommand, UICommandSender}; - -/// Sender that queues up the execution of a command. -pub struct CommandSender(std::sync::mpsc::Sender); - -impl UICommandSender for CommandSender { - /// Send a command to be executed. - fn send_ui(&self, command: UICommand) { - // The only way this can fail is if the receiver has been dropped. - self.0.send(command).ok(); - } -} - -/// Receiver for the [`CommandSender`] -pub struct CommandReceiver(std::sync::mpsc::Receiver); - -impl CommandReceiver { - /// Receive a command to be executed if any is queued. - pub fn recv(&self) -> Option { - // The only way this can fail (other than being empty) - // is if the sender has been dropped. - self.0.try_recv().ok() - } -} - -/// Creates a new command channel. -fn command_channel() -> (CommandSender, CommandReceiver) { - let (sender, receiver) = std::sync::mpsc::channel(); - (CommandSender(sender), CommandReceiver(receiver)) -} - -fn main() -> eframe::Result<()> { - re_log::setup_logging(); - - let native_options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default() - .with_app_id("re_ui_example") - .with_decorations(!re_ui::CUSTOM_WINDOW_DECORATIONS) // Maybe hide the OS-specific "chrome" around the window - .with_fullsize_content_view(re_ui::FULLSIZE_CONTENT) - .with_inner_size([1200.0, 800.0]) - .with_title_shown(!re_ui::FULLSIZE_CONTENT) - .with_titlebar_buttons_shown(!re_ui::CUSTOM_WINDOW_DECORATIONS) - .with_titlebar_shown(!re_ui::FULLSIZE_CONTENT) - .with_transparent(re_ui::CUSTOM_WINDOW_DECORATIONS), // To have rounded corners without decorations we need transparency - - follow_system_theme: false, - default_theme: eframe::Theme::Dark, - - ..Default::default() - }; - - eframe::run_native( - "re_ui example app", - native_options, - Box::new(move |cc| { - let re_ui = re_ui::ReUi::load_and_apply(&cc.egui_ctx); - Box::new(ExampleApp::new(re_ui)) - }), - ) -} - -pub struct ExampleApp { - re_ui: re_ui::ReUi, - toasts: toasts::Toasts, - - /// Listens to the local text log stream - text_log_rx: std::sync::mpsc::Receiver, - - tree: egui_tiles::Tree, - - /// regular modal - modal_handler: re_ui::modal::ModalHandler, - - /// modal with full span mode - full_span_modal_handler: re_ui::modal::ModalHandler, - - left_panel: bool, - right_panel: bool, - bottom_panel: bool, - - selected_list_item: Option, - - dummy_bool: bool, - - cmd_palette: CommandPalette, - - /// Commands to run at the end of the frame. - pub command_sender: CommandSender, - command_receiver: CommandReceiver, - latest_cmd: String, - - show_hierarchical_demo: bool, - drag_and_drop: drag_and_drop::ExampleDragAndDrop, - hierarchical_drag_and_drop: hierarchical_drag_and_drop::HierarchicalDragAndDrop, -} - -impl ExampleApp { - fn new(re_ui: re_ui::ReUi) -> Self { - let (logger, text_log_rx) = re_log::ChannelLogger::new(re_log::LevelFilter::Info); - re_log::add_boxed_logger(Box::new(logger)).unwrap(); - - let tree = egui_tiles::Tree::new_tabs("my_tree", vec![1, 2, 3]); - - let (command_sender, command_receiver) = command_channel(); - - Self { - re_ui, - toasts: Default::default(), - text_log_rx, - - tree, - modal_handler: Default::default(), - full_span_modal_handler: Default::default(), - - left_panel: true, - right_panel: true, - bottom_panel: true, - - selected_list_item: None, - - dummy_bool: true, - - cmd_palette: CommandPalette::default(), - command_sender, - command_receiver, - latest_cmd: Default::default(), - - show_hierarchical_demo: true, - drag_and_drop: Default::default(), - hierarchical_drag_and_drop: Default::default(), - } - } - - /// Show recent text log messages to the user as toast notifications. - fn show_text_logs_as_notifications(&mut self) { - while let Ok(re_log::LogMsg { - level, - target: _, - msg, - }) = self.text_log_rx.try_recv() - { - let kind = match level { - re_log::Level::Error => toasts::ToastKind::Error, - re_log::Level::Warn => toasts::ToastKind::Warning, - re_log::Level::Info => toasts::ToastKind::Info, - re_log::Level::Debug | re_log::Level::Trace => { - continue; // too spammy - } - }; - - self.toasts.add(toasts::Toast { - kind, - text: msg, - options: toasts::ToastOptions::with_ttl_in_seconds(4.0), - }); - } - } -} - -impl eframe::App for ExampleApp { - fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] { - [0.0; 4] // transparent so we can get rounded corners when doing [`re_ui::CUSTOM_WINDOW_DECORATIONS`] - } - - fn update(&mut self, egui_ctx: &egui::Context, _frame: &mut eframe::Frame) { - self.show_text_logs_as_notifications(); - self.toasts.show(egui_ctx); - - self.top_bar(egui_ctx); - - egui::TopBottomPanel::bottom("bottom_panel") - .frame(self.re_ui.bottom_panel_frame()) - .show_animated(egui_ctx, self.bottom_panel, |ui| { - ui.strong("Bottom panel"); - }); - - // LEFT PANEL - - egui::SidePanel::left("left_panel") - .default_width(500.0) - .frame(egui::Frame { - fill: egui_ctx.style().visuals.panel_fill, - ..Default::default() - }) - .show_animated(egui_ctx, self.left_panel, |ui| { - // no need to extend `ui.max_rect()` as the enclosing frame doesn't have margins - ui.set_clip_rect(ui.max_rect()); - - egui::TopBottomPanel::top("left_panel_top_bar") - .exact_height(re_ui::ReUi::title_bar_height()) - .frame(egui::Frame { - inner_margin: egui::Margin::symmetric(re_ui::ReUi::view_padding(), 0.0), - ..Default::default() - }) - .show_inside(ui, |ui| { - ui.horizontal_centered(|ui| { - ui.strong("Left bar"); - }); - - if ui.button("Log info").clicked() { - re_log::info!( - "A lot of text on info level.\nA lot of text in fact. So \ - much that we should ideally be auto-wrapping it at some point, much \ - earlier than this." - ); - } - if ui.button("Log warn").clicked() { - re_log::warn!( - "A lot of text on warn level.\nA lot of text in fact. So \ - much that we should ideally be auto-wrapping it at some point, much \ - earlier than this." - ); - } - if ui.button("Log error").clicked() { - re_log::error!( - "A lot of text on error level.\nA lot of text in fact. \ - So much that we should ideally be auto-wrapping it at some point, much \ - earlier than this." - ); - } - }); - - egui::ScrollArea::both() - .auto_shrink([false; 2]) - .show(ui, |ui| { - egui::Frame { - inner_margin: egui::Margin::same(re_ui::ReUi::view_padding()), - ..Default::default() - } - .show(ui, |ui| { - ui.horizontal(|ui| { - ui.label("Toggle switch:"); - ui.add(re_ui::toggle_switch(&mut self.dummy_bool)); - }); - ui.label(format!("Latest command: {}", self.latest_cmd)); - - // --- - - if ui.button("Open modal").clicked() { - self.modal_handler.open(); - } - - self.modal_handler.ui( - &self.re_ui, - ui.ctx(), - || re_ui::modal::Modal::new("Modal window"), - |_, ui, _| ui.label("This is a modal window."), - ); - - // --- - - if ui.button("Open full span modal").clicked() { - self.full_span_modal_handler.open(); - } - - self.full_span_modal_handler.ui( - &self.re_ui, - ui.ctx(), - || re_ui::modal::Modal::new("Modal window").full_span_content(true), - |_, ui, _| { - for idx in 0..10 { - ListItem::new(&self.re_ui, format!("Item {idx}")) - .show_flat(ui); - } - }, - ); - - // --- - - self.re_ui.large_collapsing_header(ui, "Data", true, |ui| { - ui.label("Some data here"); - }); - self.re_ui - .large_collapsing_header(ui, "Blueprint", true, |ui| { - ui.style_mut().wrap = Some(false); - ui.label("Some blueprint stuff here, that might be wide."); - self.re_ui.checkbox(ui, &mut self.dummy_bool, "Checkbox"); - - self.re_ui.collapsing_header( - ui, - "Collapsing header", - true, - |ui| { - ui.label("Some data here"); - self.re_ui.checkbox( - ui, - &mut self.dummy_bool, - "Checkbox", - ); - }, - ); - }); - }); - }); - }); - - // RIGHT PANEL - // - // This is the "idiomatic" panel structure for Rerun: - // - A top-level `SidePanel` without inner margins and which sets the clip rectangle. - // - Every piece of content (title bar, lists, etc.) are wrapped in a `Frame` with inner - // margins set to `ReUi::panel_margins()`. That can be done with `ReUi::panel_content()`. - // - If/when a scroll area is used, it must be applied without margin and outside of the - // `Frame`. - // - // This way, the content (titles, etc.) is properly inset and benefits from a properly set - // clip rectangle for full-span behavior, without interference from the scroll areas. - - let panel_frame = egui::Frame { - fill: egui_ctx.style().visuals.panel_fill, - ..Default::default() - }; - - egui::SidePanel::right("right_panel") - .frame(panel_frame) - .show_animated(egui_ctx, self.right_panel, |ui| { - ui.set_clip_rect(ui.max_rect()); - - // - // First section - Drag and drop demos - // - - ui.scope(|ui| { - ui.spacing_mut().item_spacing.y = 0.0; - - self.re_ui.panel_content(ui, |re_ui, ui| { - re_ui.panel_title_bar_with_buttons(ui, "Drag-and-drop demo", None, |ui| { - ui.add(re_ui::toggle_switch(&mut self.show_hierarchical_demo)); - ui.label("Hierarchical:"); - }); - - if self.show_hierarchical_demo { - self.hierarchical_drag_and_drop.ui(re_ui, ui); - } else { - self.drag_and_drop.ui(re_ui, ui); - } - }); - - ReUi::full_span_separator(ui); - ui.add_space(20.0); - }); - - // - // Second section - no scroll area, so a single outer "panel_content" can be used. - // - - self.re_ui.panel_content(ui, |re_ui, ui| { - re_ui.large_collapsing_header(ui, "Full-Span UI examples", true, |ui| { - ui.label("Some data here"); - ui.label("Some data there"); - - selection_buttons(ui); - }); - }); - - // From now on, it's only `list_items`, so we need to remove the default - // spacing. - ui.scope(|ui| { - ui.spacing_mut().item_spacing.y = 0.0; - - // - // Nested scroll area demo. Multiple `panel_content` must be used. - // - - self.re_ui.panel_content(ui, |re_ui, ui| { - re_ui.panel_title_bar(ui, "Another section", None); - }); - - egui::ScrollArea::both() - .id_source("example_right_panel") - .auto_shrink([false, true]) - .show(ui, |ui| { - self.re_ui.panel_content(ui, |re_ui, ui| { - for i in 0..10 { - let label = if i == 4 { - "That's one heck of a loooooooong label!".to_owned() - } else { - format!("Some item {i}") - }; - - let mut item = re_ui - .list_item(label) - .selected(Some(i) == self.selected_list_item) - .interactive(i != 3) - .with_buttons(|re_ui, ui| { - re_ui.small_icon_button(ui, &re_ui::icons::ADD) - | re_ui.small_icon_button(ui, &re_ui::icons::REMOVE) - }); - - // demo custom icon - item = if i == 6 { - item.with_icon_fn(|_re_ui, ui, rect, visuals| { - ui.painter().circle( - rect.center(), - rect.width() / 2.0, - visuals.fg_stroke.color, - egui::Stroke::NONE, - ); - }) - } else { - item.with_icon(&re_ui::icons::SPACE_VIEW_TEXT) - }; - - if item.show_flat(ui).clicked() { - self.selected_list_item = Some(i); - } - } - }); - }); - - // - // Demo of `ListItem` features. - // - - self.re_ui.panel_content(ui, |re_ui, ui| { - re_ui.panel_title_bar(ui, "Another section", None); - - self.re_ui - .list_item("Collapsing list item with icon") - .with_icon(&re_ui::icons::SPACE_VIEW_2D) - .show_hierarchical_with_content( - ui, - "collapsing example", - true, - |_re_ui, ui| { - self.re_ui.list_item("Sub-item").show_hierarchical(ui); - self.re_ui.list_item("Sub-item").show_hierarchical(ui); - self.re_ui - .list_item("Sub-item with icon") - .with_icon(&re_ui::icons::SPACE_VIEW_TEXT) - .show_hierarchical(ui); - self.re_ui - .list_item("Sub-item") - .show_hierarchical_with_content( - ui, - "sub-collapsing", - true, - |_re_ui, ui| { - self.re_ui - .list_item("Sub-sub-item") - .show_hierarchical(ui) - }, - ); - }, - ); - }); - }); - }); - - egui::CentralPanel::default() - .frame(egui::Frame { - fill: egui_ctx.style().visuals.panel_fill, - ..Default::default() - }) - .show(egui_ctx, |ui| { - tabs_ui(ui, &mut self.tree); - }); - - if let Some(cmd) = self.cmd_palette.show(egui_ctx) { - self.command_sender.send_ui(cmd); - } - if let Some(cmd) = re_ui::UICommand::listen_for_kb_shortcut(egui_ctx) { - self.command_sender.send_ui(cmd); - } - - while let Some(cmd) = self.command_receiver.recv() { - self.latest_cmd = cmd.text().to_owned(); - - #[allow(clippy::single_match)] - match cmd { - UICommand::ToggleCommandPalette => self.cmd_palette.toggle(), - UICommand::ZoomIn => { - let mut zoom_factor = egui_ctx.zoom_factor(); - zoom_factor += 0.1; - egui_ctx.set_zoom_factor(zoom_factor); - } - UICommand::ZoomOut => { - let mut zoom_factor = egui_ctx.zoom_factor(); - zoom_factor -= 0.1; - egui_ctx.set_zoom_factor(zoom_factor); - } - UICommand::ZoomReset => { - egui_ctx.set_zoom_factor(1.0); - } - _ => {} - } - } - } -} - -impl ExampleApp { - fn top_bar(&mut self, egui_ctx: &egui::Context) { - let top_bar_style = self.re_ui.top_bar_style(false); - - egui::TopBottomPanel::top("top_bar") - .frame(self.re_ui.top_panel_frame()) - .exact_height(top_bar_style.height) - .show(egui_ctx, |ui| { - #[cfg(not(target_arch = "wasm32"))] - if !re_ui::NATIVE_WINDOW_BAR { - // Interact with background first, so that buttons in the top bar gets input priority - // (last added widget has priority for input). - let title_bar_response = ui.interact( - ui.max_rect(), - ui.id().with("background"), - egui::Sense::click(), - ); - if title_bar_response.double_clicked() { - let maximized = ui.input(|i| i.viewport().maximized.unwrap_or(false)); - ui.ctx() - .send_viewport_cmd(egui::ViewportCommand::Maximized(!maximized)); - } else if title_bar_response.is_pointer_button_down_on() { - ui.ctx().send_viewport_cmd(egui::ViewportCommand::StartDrag); - } - } - - egui::menu::bar(ui, |ui| { - ui.set_height(top_bar_style.height); - ui.add_space(top_bar_style.indent); - - ui.menu_button("File", |ui| file_menu(ui, &self.command_sender)); - - self.top_bar_ui(ui); - }); - }); - } - - fn top_bar_ui(&mut self, ui: &mut egui::Ui) { - ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - // From right-to-left: - - if re_ui::CUSTOM_WINDOW_DECORATIONS { - ui.add_space(8.0); - re_ui::native_window_buttons_ui(ui); - ui.separator(); - } else { - ui.add_space(16.0); - } - - self.re_ui.medium_icon_toggle_button( - ui, - &re_ui::icons::RIGHT_PANEL_TOGGLE, - &mut self.right_panel, - ); - self.re_ui.medium_icon_toggle_button( - ui, - &re_ui::icons::BOTTOM_PANEL_TOGGLE, - &mut self.bottom_panel, - ); - self.re_ui.medium_icon_toggle_button( - ui, - &re_ui::icons::LEFT_PANEL_TOGGLE, - &mut self.left_panel, - ); - }); - } -} - -fn file_menu(ui: &mut egui::Ui, command_sender: &CommandSender) { - UICommand::SaveRecording.menu_button_ui(ui, command_sender); - UICommand::SaveRecordingSelection.menu_button_ui(ui, command_sender); - UICommand::Open.menu_button_ui(ui, command_sender); - UICommand::Quit.menu_button_ui(ui, command_sender); -} - -fn selection_buttons(ui: &mut egui::Ui) { - use egui_extras::{Size, StripBuilder}; - - const BUTTON_SIZE: f32 = 20.0; - const MIN_COMBOBOX_SIZE: f32 = 100.0; - - ui.horizontal(|ui| { - StripBuilder::new(ui) - .cell_layout(egui::Layout::centered_and_justified( - egui::Direction::TopDown, // whatever - )) - .size(Size::exact(BUTTON_SIZE)) // prev - .size(Size::remainder().at_least(MIN_COMBOBOX_SIZE)) // browser - .size(Size::exact(BUTTON_SIZE)) // next - .horizontal(|mut strip| { - strip.cell(|ui| { - let _ = ui.small_button("⏴"); - }); - - strip.cell(|ui| { - egui::ComboBox::from_id_source("foo") - .width(ui.available_width()) - .selected_text("ComboBox") - .show_ui(ui, |ui| { - ui.label("contents"); - }); - }); - - strip.cell(|ui| { - let _ = ui.small_button("⏵"); - }); - }); - }); -} - -fn tabs_ui(ui: &mut egui::Ui, tree: &mut egui_tiles::Tree) { - tree.ui(&mut MyTileTreeBehavior {}, ui); -} - -pub type Tab = i32; - -struct MyTileTreeBehavior {} - -impl egui_tiles::Behavior for MyTileTreeBehavior { - fn pane_ui( - &mut self, - ui: &mut egui::Ui, - _tile_id: egui_tiles::TileId, - _pane: &mut Tab, - ) -> egui_tiles::UiResponse { - egui::warn_if_debug_build(ui); - ui.label("Hover me for a tooltip") - .on_hover_text("This is a tooltip"); - - ui.label( - egui::RichText::new("Welcome to the ReUi example") - .text_style(ReUi::welcome_screen_h1()), - ); - - Default::default() - } - - fn tab_title_for_pane(&mut self, pane: &Tab) -> egui::WidgetText { - format!("This is tab {pane}").into() - } - - // Styling: - - fn tab_outline_stroke( - &self, - _visuals: &egui::Visuals, - _tiles: &egui_tiles::Tiles, - _tile_id: egui_tiles::TileId, - _active: bool, - ) -> egui::Stroke { - egui::Stroke::NONE - } - - /// The height of the bar holding tab titles. - fn tab_bar_height(&self, _style: &egui::Style) -> f32 { - re_ui::ReUi::title_bar_height() - } - - /// What are the rules for simplifying the tree? - fn simplification_options(&self) -> egui_tiles::SimplificationOptions { - egui_tiles::SimplificationOptions { - all_panes_must_have_tabs: true, - ..Default::default() - } - } -} - -// ============================================================================== -// DRAG AND DROP DEMO - -mod drag_and_drop { - use std::collections::HashSet; - - #[derive(Hash, Clone, Copy, PartialEq, Eq)] - struct ItemId(u32); - - pub struct ExampleDragAndDrop { - items: Vec, - - /// currently selected items - selected_items: HashSet, - } - - impl Default for ExampleDragAndDrop { - fn default() -> Self { - Self { - items: (0..10).map(ItemId).collect(), - selected_items: HashSet::new(), - } - } - } - - impl ExampleDragAndDrop { - pub fn ui(&mut self, re_ui: &crate::ReUi, ui: &mut egui::Ui) { - let mut swap: Option<(usize, usize)> = None; - - for (i, item_id) in self.items.iter().enumerate() { - // - // Draw the item - // - - let label = format!("Item {}", item_id.0); - let response = re_ui - .list_item(label.as_str()) - .selected(self.selected_items.contains(item_id)) - .draggable(true) - .show_flat(ui); - - // - // Handle item selection - // - - // Basic click and cmd/ctr-click - if response.clicked() { - if ui.input(|i| i.modifiers.command) { - if self.selected_items.contains(item_id) { - self.selected_items.remove(item_id); - } else { - self.selected_items.insert(*item_id); - } - } else { - self.selected_items.clear(); - self.selected_items.insert(*item_id); - } - } - - // Drag-and-drop of multiple items not (yet?) supported, so dragging resets selection to single item. - if response.drag_started() { - self.selected_items.clear(); - self.selected_items.insert(*item_id); - - response.dnd_set_drag_payload(i); - } - - // - // Detect drag situation and run the swap if it ends. - // - - let source_item_position_index = egui::DragAndDrop::payload(ui.ctx()).map(|i| *i); - - if let Some(source_item_position_index) = source_item_position_index { - ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing); - - let (top, bottom) = response.rect.split_top_bottom_at_fraction(0.5); - - let (insert_y, target) = if ui.rect_contains_pointer(top) { - (Some(top.top()), Some(i)) - } else if ui.rect_contains_pointer(bottom) { - (Some(bottom.bottom()), Some(i + 1)) - } else { - (None, None) - }; - - if let (Some(insert_y), Some(target)) = (insert_y, target) { - ui.painter().hline( - ui.cursor().x_range(), - insert_y, - (2.0, egui::Color32::WHITE), - ); - - // note: can't use `response.drag_released()` because we not the item which - // started the drag - if ui.input(|i| i.pointer.any_released()) { - swap = Some((source_item_position_index, target)); - - egui::DragAndDrop::clear_payload(ui.ctx()); - } - } - } - } - - // - // Handle the swap command (if any) - // - - if let Some((source, target)) = swap { - if source != target { - let item = self.items.remove(source); - - if source < target { - self.items.insert(target - 1, item); - } else { - self.items.insert(target, item); - } - } - } - } - } -} - -// ============================================================================== -// HIERARCHICAL DRAG AND DROP DEMO - -mod hierarchical_drag_and_drop { - use std::collections::{HashMap, HashSet}; - - use egui::NumExt; - - use re_ui::ReUi; - - #[derive(Hash, Clone, Copy, PartialEq, Eq)] - struct ItemId(u32); - - impl ItemId { - fn new() -> Self { - Self(rand::random()) - } - } - - impl std::fmt::Debug for ItemId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{:04x}", self.0) - } - } - - impl From for egui::Id { - fn from(id: ItemId) -> Self { - Self::new(id) - } - } - - enum Item { - Container(Vec), - Leaf(String), - } - - #[derive(Debug)] - enum Command { - /// Set the selection to the given item. - SetSelection(ItemId), - - /// Toggle the selected state of the given item. - ToggleSelected(ItemId), - - /// Move the currently dragged item to the given container and position. - MoveItem { - moved_item_id: ItemId, - target_container_id: ItemId, - target_position_index: usize, - }, - - /// Specify the currently identified target container to be highlighted. - HighlightTargetContainer(ItemId), - } - - pub struct HierarchicalDragAndDrop { - /// All items - items: HashMap, - - /// Id of the root item (not displayed in the UI) - root_id: ItemId, - - /// Set of all selected items - selected_items: HashSet, - - /// If a drag is ongoing, this is the id of the destination container (if any was identified) - /// - /// This is used to highlight the target container. - target_container: Option, - - /// Channel to receive commands from the UI - command_receiver: std::sync::mpsc::Receiver, - - /// Channel to send commands from the UI - command_sender: std::sync::mpsc::Sender, - } - - impl Default for HierarchicalDragAndDrop { - fn default() -> Self { - let root_item = Item::Container(Vec::new()); - let root_id = ItemId::new(); - - let (command_sender, command_receiver) = std::sync::mpsc::channel(); - - let mut res = Self { - items: std::iter::once((root_id, root_item)).collect(), - root_id, - selected_items: HashSet::new(), - target_container: None, - command_receiver, - command_sender, - }; - - res.populate(); - - res - } - } - - // - // Data stuff - // - impl HierarchicalDragAndDrop { - /// Add a bunch of items in the hierarchy. - fn populate(&mut self) { - let c1 = self.add_container(self.root_id); - let c2 = self.add_container(self.root_id); - let c3 = self.add_container(self.root_id); - self.add_leaf(self.root_id); - self.add_leaf(self.root_id); - - let c11 = self.add_container(c1); - let c12 = self.add_container(c1); - self.add_leaf(c11); - self.add_leaf(c11); - self.add_leaf(c12); - self.add_leaf(c12); - - self.add_leaf(c2); - self.add_leaf(c2); - - self.add_leaf(c3); - } - - fn container(&self, id: ItemId) -> Option<&Vec> { - match self.items.get(&id) { - Some(Item::Container(children)) => Some(children), - _ => None, - } - } - - /// Does some container contain the given item? - /// - /// Used to test if a target location is suitable for a given dragged item. - fn contains(&self, container_id: ItemId, item_id: ItemId) -> bool { - if let Some(children) = self.container(container_id) { - if container_id == item_id { - return true; - } - - if children.contains(&item_id) { - return true; - } - - for child_id in children { - if self.contains(*child_id, item_id) { - return true; - } - } - - return false; - } - - false - } - - /// Move item `item_id` to `container_id` at position `pos`. - fn move_item(&mut self, item_id: ItemId, container_id: ItemId, mut pos: usize) { - println!("Moving {item_id:?} to {container_id:?} at position {pos:?}"); - - // Remove the item from its current location. Note: we must adjust the target position if the item is - // moved within the same container, as the removal might shift the positions by one. - if let Some((source_parent_id, source_pos)) = self.parent_and_pos(item_id) { - if let Some(Item::Container(children)) = self.items.get_mut(&source_parent_id) { - children.remove(source_pos); - } - - if source_parent_id == container_id && source_pos < pos { - pos -= 1; - } - } - - if let Some(Item::Container(children)) = self.items.get_mut(&container_id) { - children.insert(pos.at_most(children.len()), item_id); - } - } - - /// Find the parent of an item, and the index of that item within the parent's children. - fn parent_and_pos(&self, id: ItemId) -> Option<(ItemId, usize)> { - if id == self.root_id { - None - } else { - self.parent_and_pos_impl(id, self.root_id) - } - } - - fn parent_and_pos_impl(&self, id: ItemId, container_id: ItemId) -> Option<(ItemId, usize)> { - if let Some(children) = self.container(container_id) { - for (idx, child_id) in children.iter().enumerate() { - if child_id == &id { - return Some((container_id, idx)); - } else if self.container(*child_id).is_some() { - let res = self.parent_and_pos_impl(id, *child_id); - if res.is_some() { - return res; - } - } - } - } - - None - } - - fn add_container(&mut self, parent_id: ItemId) -> ItemId { - let id = ItemId::new(); - let item = Item::Container(Vec::new()); - - self.items.insert(id, item); - - if let Some(Item::Container(children)) = self.items.get_mut(&parent_id) { - children.push(id); - } - - id - } - - fn add_leaf(&mut self, parent_id: ItemId) { - let id = ItemId::new(); - let item = Item::Leaf(format!("Item {id:?}")); - - self.items.insert(id, item); - - if let Some(Item::Container(children)) = self.items.get_mut(&parent_id) { - children.push(id); - } - } - - fn selected(&self, id: ItemId) -> bool { - self.selected_items.contains(&id) - } - - fn send_command(&self, command: Command) { - // The only way this can fail is if the receiver has been dropped. - self.command_sender.send(command).ok(); - } - } - - // - // UI stuff - // - impl HierarchicalDragAndDrop { - pub fn ui(&mut self, re_ui: &crate::ReUi, ui: &mut egui::Ui) { - if let Some(top_level_items) = self.container(self.root_id) { - self.container_children_ui(re_ui, ui, top_level_items); - } - - // always reset the target container - self.target_container = None; - - while let Ok(command) = self.command_receiver.try_recv() { - //println!("Received command: {command:?}"); - match command { - Command::SetSelection(item_id) => { - self.selected_items.clear(); - self.selected_items.insert(item_id); - } - Command::ToggleSelected(item_id) => { - if self.selected_items.contains(&item_id) { - self.selected_items.remove(&item_id); - } else { - self.selected_items.insert(item_id); - } - } - Command::MoveItem { - moved_item_id, - target_container_id, - target_position_index, - } => self.move_item(moved_item_id, target_container_id, target_position_index), - Command::HighlightTargetContainer(item_id) => { - self.target_container = Some(item_id); - } - } - } - } - - fn container_ui( - &self, - re_ui: &crate::ReUi, - ui: &mut egui::Ui, - item_id: ItemId, - children: &Vec, - ) { - let response = re_ui - .list_item(format!("Container {item_id:?}")) - .subdued(true) - .selected(self.selected(item_id)) - .draggable(true) - .drop_target_style(self.target_container == Some(item_id)) - .show_hierarchical_with_content(ui, item_id, true, |re_ui, ui| { - self.container_children_ui(re_ui, ui, children); - }); - - self.handle_interaction( - ui, - item_id, - true, - &response.item_response, - response.body_response.as_ref().map(|r| &r.response), - ); - } - - fn container_children_ui( - &self, - re_ui: &crate::ReUi, - ui: &mut egui::Ui, - children: &Vec, - ) { - for child_id in children { - match self.items.get(child_id) { - Some(Item::Container(children)) => { - self.container_ui(re_ui, ui, *child_id, children); - } - Some(Item::Leaf(label)) => { - self.leaf_ui(re_ui, ui, *child_id, label); - } - None => {} - } - } - } - - fn leaf_ui(&self, re_ui: &crate::ReUi, ui: &mut egui::Ui, item_id: ItemId, label: &str) { - let response = re_ui - .list_item(label) - .selected(self.selected(item_id)) - .draggable(true) - .show_hierarchical(ui); - - self.handle_interaction(ui, item_id, false, &response, None); - } - - fn handle_interaction( - &self, - ui: &egui::Ui, - item_id: ItemId, - is_container: bool, - response: &egui::Response, - body_response: Option<&egui::Response>, - ) { - // - // basic selection management - // - - if response.clicked() { - if ui.input(|i| i.modifiers.command) { - self.send_command(Command::ToggleSelected(item_id)); - } else { - self.send_command(Command::SetSelection(item_id)); - } - } - - // - // handle drag - // - - if response.drag_started() { - // Here, we support dragging a single item at a time, so we set the selection to the dragged item - // if/when we're dragging it proper. - self.send_command(Command::SetSelection(item_id)); - - egui::DragAndDrop::set_payload(ui.ctx(), item_id); - } - - // - // handle drop - // - - // find the item being dragged - let Some(dragged_item_id) = - egui::DragAndDrop::payload(ui.ctx()).map(|payload| (*payload)) - else { - // nothing is being dragged, we're done here - return; - }; - - ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing); - - let Some((parent_id, position_index_in_parent)) = self.parent_and_pos(item_id) else { - // this shouldn't happen - return; - }; - - let previous_container_id = if position_index_in_parent > 0 { - self.container(parent_id) - .map(|c| c[position_index_in_parent - 1]) - .filter(|id| self.container(*id).is_some()) - } else { - None - }; - - let item_desc = re_ui::drag_and_drop::ItemContext { - id: item_id, - item_kind: if is_container { - re_ui::drag_and_drop::ItemKind::Container { - parent_id, - position_index_in_parent, - } - } else { - re_ui::drag_and_drop::ItemKind::Leaf { - parent_id, - position_index_in_parent, - } - }, - previous_container_id, - }; - - let drop_target = re_ui::drag_and_drop::find_drop_target( - ui, - &item_desc, - response.rect, - body_response.map(|r| r.rect), - ReUi::list_item_height(), - ); - - if let Some(drop_target) = drop_target { - // We cannot allow the target location to be "inside" the dragged item, because that would amount moving - // myself inside of me. - - if self.contains(dragged_item_id, drop_target.target_parent_id) { - return; - } - - ui.painter().hline( - drop_target.indicator_span_x, - drop_target.indicator_position_y, - (2.0, egui::Color32::WHITE), - ); - - // note: can't use `response.drag_released()` because we not the item which - // started the drag - if ui.input(|i| i.pointer.any_released()) { - self.send_command(Command::MoveItem { - moved_item_id: dragged_item_id, - target_container_id: drop_target.target_parent_id, - target_position_index: drop_target.target_position_index, - }); - - egui::DragAndDrop::clear_payload(ui.ctx()); - } else { - self.send_command(Command::HighlightTargetContainer( - drop_target.target_parent_id, - )); - } - } - } - } -} diff --git a/crates/re_ui/examples/re_ui_example/drag_and_drop.rs b/crates/re_ui/examples/re_ui_example/drag_and_drop.rs new file mode 100644 index 000000000000..d31b6e22bb04 --- /dev/null +++ b/crates/re_ui/examples/re_ui_example/drag_and_drop.rs @@ -0,0 +1,117 @@ +use std::collections::HashSet; + +#[derive(Hash, Clone, Copy, PartialEq, Eq)] +struct ItemId(u32); + +pub struct ExampleDragAndDrop { + items: Vec, + + /// currently selected items + selected_items: HashSet, +} + +impl Default for ExampleDragAndDrop { + fn default() -> Self { + Self { + items: (0..10).map(ItemId).collect(), + selected_items: HashSet::new(), + } + } +} + +impl ExampleDragAndDrop { + pub fn ui(&mut self, re_ui: &crate::ReUi, ui: &mut egui::Ui) { + let mut swap: Option<(usize, usize)> = None; + + for (i, item_id) in self.items.iter().enumerate() { + // + // Draw the item + // + + let label = format!("Item {}", item_id.0); + let response = re_ui + .list_item(label.as_str()) + .selected(self.selected_items.contains(item_id)) + .draggable(true) + .show_flat(ui); + + // + // Handle item selection + // + + // Basic click and cmd/ctr-click + if response.clicked() { + if ui.input(|i| i.modifiers.command) { + if self.selected_items.contains(item_id) { + self.selected_items.remove(item_id); + } else { + self.selected_items.insert(*item_id); + } + } else { + self.selected_items.clear(); + self.selected_items.insert(*item_id); + } + } + + // Drag-and-drop of multiple items not (yet?) supported, so dragging resets selection to single item. + if response.drag_started() { + self.selected_items.clear(); + self.selected_items.insert(*item_id); + + response.dnd_set_drag_payload(i); + } + + // + // Detect drag situation and run the swap if it ends. + // + + let source_item_position_index = egui::DragAndDrop::payload(ui.ctx()).map(|i| *i); + + if let Some(source_item_position_index) = source_item_position_index { + ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing); + + let (top, bottom) = response.rect.split_top_bottom_at_fraction(0.5); + + let (insert_y, target) = if ui.rect_contains_pointer(top) { + (Some(top.top()), Some(i)) + } else if ui.rect_contains_pointer(bottom) { + (Some(bottom.bottom()), Some(i + 1)) + } else { + (None, None) + }; + + if let (Some(insert_y), Some(target)) = (insert_y, target) { + ui.painter().hline( + ui.cursor().x_range(), + insert_y, + (2.0, egui::Color32::WHITE), + ); + + // note: can't use `response.drag_released()` because we not the item which + // started the drag + if ui.input(|i| i.pointer.any_released()) { + swap = Some((source_item_position_index, target)); + + egui::DragAndDrop::clear_payload(ui.ctx()); + } + } + } + } + + // + // Handle the swap command (if any) + // + + if let Some((source, target)) = swap { + if source != target { + let item = self.items.remove(source); + + if source < target { + self.items.insert(target - 1, item); + } else { + self.items.insert(target, item); + } + } + } + } +} diff --git a/crates/re_ui/examples/re_ui_example/hierarchical_drag_and_drop.rs b/crates/re_ui/examples/re_ui_example/hierarchical_drag_and_drop.rs new file mode 100644 index 000000000000..aa6b5ddaa1cb --- /dev/null +++ b/crates/re_ui/examples/re_ui_example/hierarchical_drag_and_drop.rs @@ -0,0 +1,440 @@ +use std::collections::{HashMap, HashSet}; + +use egui::NumExt; + +use re_ui::ReUi; + +#[derive(Hash, Clone, Copy, PartialEq, Eq)] +struct ItemId(u32); + +impl ItemId { + fn new() -> Self { + Self(rand::random()) + } +} + +impl std::fmt::Debug for ItemId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "#{:04x}", self.0) + } +} + +impl From for egui::Id { + fn from(id: ItemId) -> Self { + Self::new(id) + } +} + +enum Item { + Container(Vec), + Leaf(String), +} + +#[derive(Debug)] +enum Command { + /// Set the selection to the given item. + SetSelection(ItemId), + + /// Toggle the selected state of the given item. + ToggleSelected(ItemId), + + /// Move the currently dragged item to the given container and position. + MoveItem { + moved_item_id: ItemId, + target_container_id: ItemId, + target_position_index: usize, + }, + + /// Specify the currently identified target container to be highlighted. + HighlightTargetContainer(ItemId), +} + +pub struct HierarchicalDragAndDrop { + /// All items + items: HashMap, + + /// Id of the root item (not displayed in the UI) + root_id: ItemId, + + /// Set of all selected items + selected_items: HashSet, + + /// If a drag is ongoing, this is the id of the destination container (if any was identified) + /// + /// This is used to highlight the target container. + target_container: Option, + + /// Channel to receive commands from the UI + command_receiver: std::sync::mpsc::Receiver, + + /// Channel to send commands from the UI + command_sender: std::sync::mpsc::Sender, +} + +impl Default for HierarchicalDragAndDrop { + fn default() -> Self { + let root_item = Item::Container(Vec::new()); + let root_id = ItemId::new(); + + let (command_sender, command_receiver) = std::sync::mpsc::channel(); + + let mut res = Self { + items: std::iter::once((root_id, root_item)).collect(), + root_id, + selected_items: HashSet::new(), + target_container: None, + command_receiver, + command_sender, + }; + + res.populate(); + + res + } +} + +// +// Data stuff +// +impl HierarchicalDragAndDrop { + /// Add a bunch of items in the hierarchy. + fn populate(&mut self) { + let c1 = self.add_container(self.root_id); + let c2 = self.add_container(self.root_id); + let c3 = self.add_container(self.root_id); + self.add_leaf(self.root_id); + self.add_leaf(self.root_id); + + let c11 = self.add_container(c1); + let c12 = self.add_container(c1); + self.add_leaf(c11); + self.add_leaf(c11); + self.add_leaf(c12); + self.add_leaf(c12); + + self.add_leaf(c2); + self.add_leaf(c2); + + self.add_leaf(c3); + } + + fn container(&self, id: ItemId) -> Option<&Vec> { + match self.items.get(&id) { + Some(Item::Container(children)) => Some(children), + _ => None, + } + } + + /// Does some container contain the given item? + /// + /// Used to test if a target location is suitable for a given dragged item. + fn contains(&self, container_id: ItemId, item_id: ItemId) -> bool { + if let Some(children) = self.container(container_id) { + if container_id == item_id { + return true; + } + + if children.contains(&item_id) { + return true; + } + + for child_id in children { + if self.contains(*child_id, item_id) { + return true; + } + } + + return false; + } + + false + } + + /// Move item `item_id` to `container_id` at position `pos`. + fn move_item(&mut self, item_id: ItemId, container_id: ItemId, mut pos: usize) { + println!("Moving {item_id:?} to {container_id:?} at position {pos:?}"); + + // Remove the item from its current location. Note: we must adjust the target position if the item is + // moved within the same container, as the removal might shift the positions by one. + if let Some((source_parent_id, source_pos)) = self.parent_and_pos(item_id) { + if let Some(Item::Container(children)) = self.items.get_mut(&source_parent_id) { + children.remove(source_pos); + } + + if source_parent_id == container_id && source_pos < pos { + pos -= 1; + } + } + + if let Some(Item::Container(children)) = self.items.get_mut(&container_id) { + children.insert(pos.at_most(children.len()), item_id); + } + } + + /// Find the parent of an item, and the index of that item within the parent's children. + fn parent_and_pos(&self, id: ItemId) -> Option<(ItemId, usize)> { + if id == self.root_id { + None + } else { + self.parent_and_pos_impl(id, self.root_id) + } + } + + fn parent_and_pos_impl(&self, id: ItemId, container_id: ItemId) -> Option<(ItemId, usize)> { + if let Some(children) = self.container(container_id) { + for (idx, child_id) in children.iter().enumerate() { + if child_id == &id { + return Some((container_id, idx)); + } else if self.container(*child_id).is_some() { + let res = self.parent_and_pos_impl(id, *child_id); + if res.is_some() { + return res; + } + } + } + } + + None + } + + fn add_container(&mut self, parent_id: ItemId) -> ItemId { + let id = ItemId::new(); + let item = Item::Container(Vec::new()); + + self.items.insert(id, item); + + if let Some(Item::Container(children)) = self.items.get_mut(&parent_id) { + children.push(id); + } + + id + } + + fn add_leaf(&mut self, parent_id: ItemId) { + let id = ItemId::new(); + let item = Item::Leaf(format!("Item {id:?}")); + + self.items.insert(id, item); + + if let Some(Item::Container(children)) = self.items.get_mut(&parent_id) { + children.push(id); + } + } + + fn selected(&self, id: ItemId) -> bool { + self.selected_items.contains(&id) + } + + fn send_command(&self, command: Command) { + // The only way this can fail is if the receiver has been dropped. + self.command_sender.send(command).ok(); + } +} + +// +// UI stuff +// +impl HierarchicalDragAndDrop { + pub fn ui(&mut self, re_ui: &crate::ReUi, ui: &mut egui::Ui) { + if let Some(top_level_items) = self.container(self.root_id) { + self.container_children_ui(re_ui, ui, top_level_items); + } + + // always reset the target container + self.target_container = None; + + while let Ok(command) = self.command_receiver.try_recv() { + //println!("Received command: {command:?}"); + match command { + Command::SetSelection(item_id) => { + self.selected_items.clear(); + self.selected_items.insert(item_id); + } + Command::ToggleSelected(item_id) => { + if self.selected_items.contains(&item_id) { + self.selected_items.remove(&item_id); + } else { + self.selected_items.insert(item_id); + } + } + Command::MoveItem { + moved_item_id, + target_container_id, + target_position_index, + } => self.move_item(moved_item_id, target_container_id, target_position_index), + Command::HighlightTargetContainer(item_id) => { + self.target_container = Some(item_id); + } + } + } + } + + fn container_ui( + &self, + re_ui: &crate::ReUi, + ui: &mut egui::Ui, + item_id: ItemId, + children: &Vec, + ) { + let response = re_ui + .list_item(format!("Container {item_id:?}")) + .subdued(true) + .selected(self.selected(item_id)) + .draggable(true) + .drop_target_style(self.target_container == Some(item_id)) + .show_hierarchical_with_content(ui, item_id, true, |re_ui, ui| { + self.container_children_ui(re_ui, ui, children); + }); + + self.handle_interaction( + ui, + item_id, + true, + &response.item_response, + response.body_response.as_ref().map(|r| &r.response), + ); + } + + fn container_children_ui( + &self, + re_ui: &crate::ReUi, + ui: &mut egui::Ui, + children: &Vec, + ) { + for child_id in children { + match self.items.get(child_id) { + Some(Item::Container(children)) => { + self.container_ui(re_ui, ui, *child_id, children); + } + Some(Item::Leaf(label)) => { + self.leaf_ui(re_ui, ui, *child_id, label); + } + None => {} + } + } + } + + fn leaf_ui(&self, re_ui: &crate::ReUi, ui: &mut egui::Ui, item_id: ItemId, label: &str) { + let response = re_ui + .list_item(label) + .selected(self.selected(item_id)) + .draggable(true) + .show_hierarchical(ui); + + self.handle_interaction(ui, item_id, false, &response, None); + } + + fn handle_interaction( + &self, + ui: &egui::Ui, + item_id: ItemId, + is_container: bool, + response: &egui::Response, + body_response: Option<&egui::Response>, + ) { + // + // basic selection management + // + + if response.clicked() { + if ui.input(|i| i.modifiers.command) { + self.send_command(Command::ToggleSelected(item_id)); + } else { + self.send_command(Command::SetSelection(item_id)); + } + } + + // + // handle drag + // + + if response.drag_started() { + // Here, we support dragging a single item at a time, so we set the selection to the dragged item + // if/when we're dragging it proper. + self.send_command(Command::SetSelection(item_id)); + + egui::DragAndDrop::set_payload(ui.ctx(), item_id); + } + + // + // handle drop + // + + // find the item being dragged + let Some(dragged_item_id) = egui::DragAndDrop::payload(ui.ctx()).map(|payload| (*payload)) + else { + // nothing is being dragged, we're done here + return; + }; + + ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing); + + let Some((parent_id, position_index_in_parent)) = self.parent_and_pos(item_id) else { + // this shouldn't happen + return; + }; + + let previous_container_id = if position_index_in_parent > 0 { + self.container(parent_id) + .map(|c| c[position_index_in_parent - 1]) + .filter(|id| self.container(*id).is_some()) + } else { + None + }; + + let item_desc = re_ui::drag_and_drop::ItemContext { + id: item_id, + item_kind: if is_container { + re_ui::drag_and_drop::ItemKind::Container { + parent_id, + position_index_in_parent, + } + } else { + re_ui::drag_and_drop::ItemKind::Leaf { + parent_id, + position_index_in_parent, + } + }, + previous_container_id, + }; + + let drop_target = re_ui::drag_and_drop::find_drop_target( + ui, + &item_desc, + response.rect, + body_response.map(|r| r.rect), + ReUi::list_item_height(), + ); + + if let Some(drop_target) = drop_target { + // We cannot allow the target location to be "inside" the dragged item, because that would amount moving + // myself inside of me. + + if self.contains(dragged_item_id, drop_target.target_parent_id) { + return; + } + + ui.painter().hline( + drop_target.indicator_span_x, + drop_target.indicator_position_y, + (2.0, egui::Color32::WHITE), + ); + + // note: can't use `response.drag_released()` because we not the item which + // started the drag + if ui.input(|i| i.pointer.any_released()) { + self.send_command(Command::MoveItem { + moved_item_id: dragged_item_id, + target_container_id: drop_target.target_parent_id, + target_position_index: drop_target.target_position_index, + }); + + egui::DragAndDrop::clear_payload(ui.ctx()); + } else { + self.send_command(Command::HighlightTargetContainer( + drop_target.target_parent_id, + )); + } + } + } +} diff --git a/crates/re_ui/examples/re_ui_example/main.rs b/crates/re_ui/examples/re_ui_example/main.rs new file mode 100644 index 000000000000..89dd1e2ba929 --- /dev/null +++ b/crates/re_ui/examples/re_ui_example/main.rs @@ -0,0 +1,523 @@ +mod drag_and_drop; +mod hierarchical_drag_and_drop; +mod right_panel; + +use re_ui::ListItem; +use re_ui::{toasts, CommandPalette, ReUi, UICommand, UICommandSender}; + +/// Sender that queues up the execution of a command. +pub struct CommandSender(std::sync::mpsc::Sender); + +impl UICommandSender for CommandSender { + /// Send a command to be executed. + fn send_ui(&self, command: UICommand) { + // The only way this can fail is if the receiver has been dropped. + self.0.send(command).ok(); + } +} + +/// Receiver for the [`CommandSender`] +pub struct CommandReceiver(std::sync::mpsc::Receiver); + +impl CommandReceiver { + /// Receive a command to be executed if any is queued. + pub fn recv(&self) -> Option { + // The only way this can fail (other than being empty) + // is if the sender has been dropped. + self.0.try_recv().ok() + } +} + +/// Creates a new command channel. +fn command_channel() -> (CommandSender, CommandReceiver) { + let (sender, receiver) = std::sync::mpsc::channel(); + (CommandSender(sender), CommandReceiver(receiver)) +} + +fn main() -> eframe::Result<()> { + re_log::setup_logging(); + + let native_options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default() + .with_app_id("re_ui_example") + .with_decorations(!re_ui::CUSTOM_WINDOW_DECORATIONS) // Maybe hide the OS-specific "chrome" around the window + .with_fullsize_content_view(re_ui::FULLSIZE_CONTENT) + .with_inner_size([1200.0, 800.0]) + .with_title_shown(!re_ui::FULLSIZE_CONTENT) + .with_titlebar_buttons_shown(!re_ui::CUSTOM_WINDOW_DECORATIONS) + .with_titlebar_shown(!re_ui::FULLSIZE_CONTENT) + .with_transparent(re_ui::CUSTOM_WINDOW_DECORATIONS), // To have rounded corners without decorations we need transparency + + follow_system_theme: false, + default_theme: eframe::Theme::Dark, + + ..Default::default() + }; + + eframe::run_native( + "re_ui example app", + native_options, + Box::new(move |cc| { + let re_ui = re_ui::ReUi::load_and_apply(&cc.egui_ctx); + Box::new(ExampleApp::new(re_ui)) + }), + ) +} + +pub struct ExampleApp { + re_ui: re_ui::ReUi, + toasts: toasts::Toasts, + + /// Listens to the local text log stream + text_log_rx: std::sync::mpsc::Receiver, + + tree: egui_tiles::Tree, + + /// regular modal + modal_handler: re_ui::modal::ModalHandler, + + /// modal with full span mode + full_span_modal_handler: re_ui::modal::ModalHandler, + + show_left_panel: bool, + show_right_panel: bool, + show_bottom_panel: bool, + + right_panel: right_panel::RightPanel, + + dummy_bool: bool, + + cmd_palette: CommandPalette, + + /// Commands to run at the end of the frame. + pub command_sender: CommandSender, + command_receiver: CommandReceiver, + latest_cmd: String, +} + +impl ExampleApp { + fn new(re_ui: re_ui::ReUi) -> Self { + let (logger, text_log_rx) = re_log::ChannelLogger::new(re_log::LevelFilter::Info); + re_log::add_boxed_logger(Box::new(logger)).unwrap(); + + let tree = egui_tiles::Tree::new_tabs("my_tree", vec![1, 2, 3]); + + let (command_sender, command_receiver) = command_channel(); + + Self { + re_ui, + toasts: Default::default(), + text_log_rx, + + tree, + modal_handler: Default::default(), + full_span_modal_handler: Default::default(), + + show_left_panel: true, + show_right_panel: true, + show_bottom_panel: true, + + right_panel: right_panel::RightPanel::default(), + + dummy_bool: true, + + cmd_palette: CommandPalette::default(), + command_sender, + command_receiver, + latest_cmd: Default::default(), + } + } + + /// Show recent text log messages to the user as toast notifications. + fn show_text_logs_as_notifications(&mut self) { + while let Ok(re_log::LogMsg { + level, + target: _, + msg, + }) = self.text_log_rx.try_recv() + { + let kind = match level { + re_log::Level::Error => toasts::ToastKind::Error, + re_log::Level::Warn => toasts::ToastKind::Warning, + re_log::Level::Info => toasts::ToastKind::Info, + re_log::Level::Debug | re_log::Level::Trace => { + continue; // too spammy + } + }; + + self.toasts.add(toasts::Toast { + kind, + text: msg, + options: toasts::ToastOptions::with_ttl_in_seconds(4.0), + }); + } + } +} + +impl eframe::App for ExampleApp { + fn clear_color(&self, _visuals: &egui::Visuals) -> [f32; 4] { + [0.0; 4] // transparent so we can get rounded corners when doing [`re_ui::CUSTOM_WINDOW_DECORATIONS`] + } + + fn update(&mut self, egui_ctx: &egui::Context, _frame: &mut eframe::Frame) { + self.show_text_logs_as_notifications(); + self.toasts.show(egui_ctx); + + self.top_bar(egui_ctx); + + egui::TopBottomPanel::bottom("bottom_panel") + .frame(self.re_ui.bottom_panel_frame()) + .show_animated(egui_ctx, self.show_bottom_panel, |ui| { + ui.strong("Bottom panel"); + }); + + // LEFT PANEL + + egui::SidePanel::left("left_panel") + .default_width(500.0) + .frame(egui::Frame { + fill: egui_ctx.style().visuals.panel_fill, + ..Default::default() + }) + .show_animated(egui_ctx, self.show_left_panel, |ui| { + // no need to extend `ui.max_rect()` as the enclosing frame doesn't have margins + ui.set_clip_rect(ui.max_rect()); + + egui::TopBottomPanel::top("left_panel_top_bar") + .exact_height(re_ui::ReUi::title_bar_height()) + .frame(egui::Frame { + inner_margin: egui::Margin::symmetric(re_ui::ReUi::view_padding(), 0.0), + ..Default::default() + }) + .show_inside(ui, |ui| { + ui.horizontal_centered(|ui| { + ui.strong("Left bar"); + }); + + if ui.button("Log info").clicked() { + re_log::info!( + "A lot of text on info level.\nA lot of text in fact. So \ + much that we should ideally be auto-wrapping it at some point, much \ + earlier than this." + ); + } + if ui.button("Log warn").clicked() { + re_log::warn!( + "A lot of text on warn level.\nA lot of text in fact. So \ + much that we should ideally be auto-wrapping it at some point, much \ + earlier than this." + ); + } + if ui.button("Log error").clicked() { + re_log::error!( + "A lot of text on error level.\nA lot of text in fact. \ + So much that we should ideally be auto-wrapping it at some point, much \ + earlier than this." + ); + } + }); + + egui::ScrollArea::both() + .auto_shrink([false; 2]) + .show(ui, |ui| { + egui::Frame { + inner_margin: egui::Margin::same(re_ui::ReUi::view_padding()), + ..Default::default() + } + .show(ui, |ui| { + ui.horizontal(|ui| { + ui.label("Toggle switch:"); + ui.add(re_ui::toggle_switch(&mut self.dummy_bool)); + }); + ui.label(format!("Latest command: {}", self.latest_cmd)); + + // --- + + if ui.button("Open modal").clicked() { + self.modal_handler.open(); + } + + self.modal_handler.ui( + &self.re_ui, + ui.ctx(), + || re_ui::modal::Modal::new("Modal window"), + |_, ui, _| ui.label("This is a modal window."), + ); + + // --- + + if ui.button("Open full span modal").clicked() { + self.full_span_modal_handler.open(); + } + + self.full_span_modal_handler.ui( + &self.re_ui, + ui.ctx(), + || re_ui::modal::Modal::new("Modal window").full_span_content(true), + |_, ui, _| { + for idx in 0..10 { + ListItem::new(&self.re_ui, format!("Item {idx}")) + .show_flat(ui); + } + }, + ); + + // --- + + self.re_ui.large_collapsing_header(ui, "Data", true, |ui| { + ui.label("Some data here"); + }); + self.re_ui + .large_collapsing_header(ui, "Blueprint", true, |ui| { + ui.style_mut().wrap = Some(false); + ui.label("Some blueprint stuff here, that might be wide."); + self.re_ui.checkbox(ui, &mut self.dummy_bool, "Checkbox"); + + self.re_ui.collapsing_header( + ui, + "Collapsing header", + true, + |ui| { + ui.label("Some data here"); + self.re_ui.checkbox( + ui, + &mut self.dummy_bool, + "Checkbox", + ); + }, + ); + }); + }); + }); + }); + + // RIGHT PANEL + // + // This is the "idiomatic" panel structure for Rerun: + // - A top-level `SidePanel` without inner margins and which sets the clip rectangle. + // - Every piece of content (title bar, lists, etc.) are wrapped in a `Frame` with inner + // margins set to `ReUi::panel_margins()`. That can be done with `ReUi::panel_content()`. + // - If/when a scroll area is used, it must be applied without margin and outside of the + // `Frame`. + // + // This way, the content (titles, etc.) is properly inset and benefits from a properly set + // clip rectangle for full-span behavior, without interference from the scroll areas. + + let panel_frame = egui::Frame { + fill: egui_ctx.style().visuals.panel_fill, + ..Default::default() + }; + + egui::SidePanel::right("right_panel") + .frame(panel_frame) + .show_animated(egui_ctx, self.show_right_panel, |ui| { + self.right_panel.ui(&self.re_ui, ui); + }); + + egui::CentralPanel::default() + .frame(egui::Frame { + fill: egui_ctx.style().visuals.panel_fill, + ..Default::default() + }) + .show(egui_ctx, |ui| { + tabs_ui(ui, &mut self.tree); + }); + + if let Some(cmd) = self.cmd_palette.show(egui_ctx) { + self.command_sender.send_ui(cmd); + } + if let Some(cmd) = re_ui::UICommand::listen_for_kb_shortcut(egui_ctx) { + self.command_sender.send_ui(cmd); + } + + while let Some(cmd) = self.command_receiver.recv() { + self.latest_cmd = cmd.text().to_owned(); + + #[allow(clippy::single_match)] + match cmd { + UICommand::ToggleCommandPalette => self.cmd_palette.toggle(), + UICommand::ZoomIn => { + let mut zoom_factor = egui_ctx.zoom_factor(); + zoom_factor += 0.1; + egui_ctx.set_zoom_factor(zoom_factor); + } + UICommand::ZoomOut => { + let mut zoom_factor = egui_ctx.zoom_factor(); + zoom_factor -= 0.1; + egui_ctx.set_zoom_factor(zoom_factor); + } + UICommand::ZoomReset => { + egui_ctx.set_zoom_factor(1.0); + } + _ => {} + } + } + } +} + +impl ExampleApp { + fn top_bar(&mut self, egui_ctx: &egui::Context) { + let top_bar_style = self.re_ui.top_bar_style(false); + + egui::TopBottomPanel::top("top_bar") + .frame(self.re_ui.top_panel_frame()) + .exact_height(top_bar_style.height) + .show(egui_ctx, |ui| { + #[cfg(not(target_arch = "wasm32"))] + if !re_ui::NATIVE_WINDOW_BAR { + // Interact with background first, so that buttons in the top bar gets input priority + // (last added widget has priority for input). + let title_bar_response = ui.interact( + ui.max_rect(), + ui.id().with("background"), + egui::Sense::click(), + ); + if title_bar_response.double_clicked() { + let maximized = ui.input(|i| i.viewport().maximized.unwrap_or(false)); + ui.ctx() + .send_viewport_cmd(egui::ViewportCommand::Maximized(!maximized)); + } else if title_bar_response.is_pointer_button_down_on() { + ui.ctx().send_viewport_cmd(egui::ViewportCommand::StartDrag); + } + } + + egui::menu::bar(ui, |ui| { + ui.set_height(top_bar_style.height); + ui.add_space(top_bar_style.indent); + + ui.menu_button("File", |ui| file_menu(ui, &self.command_sender)); + + self.top_bar_ui(ui); + }); + }); + } + + fn top_bar_ui(&mut self, ui: &mut egui::Ui) { + ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { + // From right-to-left: + + if re_ui::CUSTOM_WINDOW_DECORATIONS { + ui.add_space(8.0); + re_ui::native_window_buttons_ui(ui); + ui.separator(); + } else { + ui.add_space(16.0); + } + + self.re_ui.medium_icon_toggle_button( + ui, + &re_ui::icons::RIGHT_PANEL_TOGGLE, + &mut self.show_right_panel, + ); + self.re_ui.medium_icon_toggle_button( + ui, + &re_ui::icons::BOTTOM_PANEL_TOGGLE, + &mut self.show_bottom_panel, + ); + self.re_ui.medium_icon_toggle_button( + ui, + &re_ui::icons::LEFT_PANEL_TOGGLE, + &mut self.show_left_panel, + ); + }); + } +} + +fn file_menu(ui: &mut egui::Ui, command_sender: &CommandSender) { + UICommand::SaveRecording.menu_button_ui(ui, command_sender); + UICommand::SaveRecordingSelection.menu_button_ui(ui, command_sender); + UICommand::Open.menu_button_ui(ui, command_sender); + UICommand::Quit.menu_button_ui(ui, command_sender); +} + +fn selection_buttons(ui: &mut egui::Ui) { + use egui_extras::{Size, StripBuilder}; + + const BUTTON_SIZE: f32 = 20.0; + const MIN_COMBOBOX_SIZE: f32 = 100.0; + + ui.horizontal(|ui| { + StripBuilder::new(ui) + .cell_layout(egui::Layout::centered_and_justified( + egui::Direction::TopDown, // whatever + )) + .size(Size::exact(BUTTON_SIZE)) // prev + .size(Size::remainder().at_least(MIN_COMBOBOX_SIZE)) // browser + .size(Size::exact(BUTTON_SIZE)) // next + .horizontal(|mut strip| { + strip.cell(|ui| { + let _ = ui.small_button("⏴"); + }); + + strip.cell(|ui| { + egui::ComboBox::from_id_source("foo") + .width(ui.available_width()) + .selected_text("ComboBox") + .show_ui(ui, |ui| { + ui.label("contents"); + }); + }); + + strip.cell(|ui| { + let _ = ui.small_button("⏵"); + }); + }); + }); +} + +fn tabs_ui(ui: &mut egui::Ui, tree: &mut egui_tiles::Tree) { + tree.ui(&mut MyTileTreeBehavior {}, ui); +} + +pub type Tab = i32; + +struct MyTileTreeBehavior {} + +impl egui_tiles::Behavior for MyTileTreeBehavior { + fn pane_ui( + &mut self, + ui: &mut egui::Ui, + _tile_id: egui_tiles::TileId, + _pane: &mut Tab, + ) -> egui_tiles::UiResponse { + egui::warn_if_debug_build(ui); + ui.label("Hover me for a tooltip") + .on_hover_text("This is a tooltip"); + + ui.label( + egui::RichText::new("Welcome to the ReUi example") + .text_style(ReUi::welcome_screen_h1()), + ); + + Default::default() + } + + fn tab_title_for_pane(&mut self, pane: &Tab) -> egui::WidgetText { + format!("This is tab {pane}").into() + } + + // Styling: + + fn tab_outline_stroke( + &self, + _visuals: &egui::Visuals, + _tiles: &egui_tiles::Tiles, + _tile_id: egui_tiles::TileId, + _active: bool, + ) -> egui::Stroke { + egui::Stroke::NONE + } + + /// The height of the bar holding tab titles. + fn tab_bar_height(&self, _style: &egui::Style) -> f32 { + re_ui::ReUi::title_bar_height() + } + + /// What are the rules for simplifying the tree? + fn simplification_options(&self) -> egui_tiles::SimplificationOptions { + egui_tiles::SimplificationOptions { + all_panes_must_have_tabs: true, + ..Default::default() + } + } +} diff --git a/crates/re_ui/examples/re_ui_example/right_panel.rs b/crates/re_ui/examples/re_ui_example/right_panel.rs new file mode 100644 index 000000000000..eccdceac110a --- /dev/null +++ b/crates/re_ui/examples/re_ui_example/right_panel.rs @@ -0,0 +1,154 @@ +use crate::{drag_and_drop, hierarchical_drag_and_drop, selection_buttons}; +use re_ui::ReUi; + +pub struct RightPanel { + show_hierarchical_demo: bool, + drag_and_drop: drag_and_drop::ExampleDragAndDrop, + hierarchical_drag_and_drop: hierarchical_drag_and_drop::HierarchicalDragAndDrop, + selected_list_item: Option, +} + +impl Default for RightPanel { + fn default() -> Self { + Self { + show_hierarchical_demo: true, + drag_and_drop: drag_and_drop::ExampleDragAndDrop::default(), + hierarchical_drag_and_drop: + hierarchical_drag_and_drop::HierarchicalDragAndDrop::default(), + selected_list_item: None, + } + } +} + +impl RightPanel { + /// Draw the right panel content. + /// + /// Note: the panel's frame must have a zero inner margin! + pub fn ui(&mut self, re_ui: &ReUi, ui: &mut egui::Ui) { + ui.set_clip_rect(ui.max_rect()); + + // + // First section - Drag and drop demos + // + + ui.scope(|ui| { + ui.spacing_mut().item_spacing.y = 0.0; + + re_ui.panel_content(ui, |re_ui, ui| { + re_ui.panel_title_bar_with_buttons(ui, "Drag-and-drop demo", None, |ui| { + ui.add(re_ui::toggle_switch(&mut self.show_hierarchical_demo)); + ui.label("Hierarchical:"); + }); + + if self.show_hierarchical_demo { + self.hierarchical_drag_and_drop.ui(re_ui, ui); + } else { + self.drag_and_drop.ui(re_ui, ui); + } + }); + + ReUi::full_span_separator(ui); + ui.add_space(20.0); + }); + + // + // Second section - no scroll area, so a single outer "panel_content" can be used. + // + + re_ui.panel_content(ui, |re_ui, ui| { + re_ui.large_collapsing_header(ui, "Full-Span UI examples", true, |ui| { + ui.label("Some data here"); + ui.label("Some data there"); + + selection_buttons(ui); + }); + }); + + // From now on, it's only `list_items`, so we need to remove the default + // spacing. + ui.scope(|ui| { + ui.spacing_mut().item_spacing.y = 0.0; + + // + // Nested scroll area demo. Multiple `panel_content` must be used. + // + + re_ui.panel_content(ui, |re_ui, ui| { + re_ui.panel_title_bar(ui, "Another section", None); + }); + + egui::ScrollArea::both() + .id_source("example_right_panel") + .auto_shrink([false, true]) + .show(ui, |ui| { + re_ui.panel_content(ui, |re_ui, ui| { + for i in 0..10 { + let label = if i == 4 { + "That's one heck of a loooooooong label!".to_owned() + } else { + format!("Some item {i}") + }; + + let mut item = re_ui + .list_item(label) + .selected(Some(i) == self.selected_list_item) + .interactive(i != 3) + .with_buttons(|re_ui, ui| { + re_ui.small_icon_button(ui, &re_ui::icons::ADD) + | re_ui.small_icon_button(ui, &re_ui::icons::REMOVE) + }); + + // demo custom icon + item = if i == 6 { + item.with_icon_fn(|_re_ui, ui, rect, visuals| { + ui.painter().circle( + rect.center(), + rect.width() / 2.0, + visuals.fg_stroke.color, + egui::Stroke::NONE, + ); + }) + } else { + item.with_icon(&re_ui::icons::SPACE_VIEW_TEXT) + }; + + if item.show_flat(ui).clicked() { + self.selected_list_item = Some(i); + } + } + }); + }); + + // + // Demo of `ListItem` features. + // + + re_ui.panel_content(ui, |re_ui, ui| { + re_ui.panel_title_bar(ui, "Another section", None); + + re_ui + .list_item("Collapsing list item with icon") + .with_icon(&re_ui::icons::SPACE_VIEW_2D) + .show_hierarchical_with_content( + ui, + "collapsing example", + true, + |_re_ui, ui| { + re_ui.list_item("Sub-item").show_hierarchical(ui); + re_ui.list_item("Sub-item").show_hierarchical(ui); + re_ui + .list_item("Sub-item with icon") + .with_icon(&re_ui::icons::SPACE_VIEW_TEXT) + .show_hierarchical(ui); + re_ui.list_item("Sub-item").show_hierarchical_with_content( + ui, + "sub-collapsing", + true, + |_re_ui, ui| re_ui.list_item("Sub-sub-item").show_hierarchical(ui), + ); + }, + ); + }); + }); + } +} From f7b2bec4183ef6c2c918f23cb940c9601f0e25b0 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 17:15:24 +0200 Subject: [PATCH 385/508] Set visual 2D bounds from code (#6127) ### What * Closes #683 * Closes https://github.com/rerun-io/rerun/issues/6150 Usage: ```py rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[0.0, 0.0], max=[10.0, 20.0])) ``` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6127?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6127?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6127) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Andreas Reich --- Cargo.lock | 1 + crates/re_entity_db/src/entity_db.rs | 16 + crates/re_query/src/latest_at/helpers.rs | 79 ++-- .../src/latest_at/to_archetype/.gitattributes | 1 + .../src/latest_at/to_archetype/mod.rs | 1 + .../latest_at/to_archetype/visual_bounds.rs | 44 ++ crates/re_space_view/src/lib.rs | 5 +- crates/re_space_view/src/space_view.rs | 4 + .../re_space_view/src/space_view_contents.rs | 1 + crates/re_space_view/src/sub_archetypes.rs | 58 ++- .../src/space_view_2d.rs | 48 +- crates/re_space_view_spatial/src/ui.rs | 5 +- crates/re_space_view_spatial/src/ui_2d.rs | 96 ++-- crates/re_types/Cargo.toml | 1 + .../re_types/definitions/rerun/blueprint.fbs | 1 + .../rerun/blueprint/archetypes/background.fbs | 2 - .../blueprint/archetypes/visual_bounds.fbs | 21 + .../rerun/blueprint/views/spatial2d.fbs | 6 + .../re_types/definitions/rerun/components.fbs | 1 + .../definitions/rerun/components/aabb2d.fbs | 18 + .../re_types/definitions/rerun/datatypes.fbs | 1 + .../definitions/rerun/datatypes/aabb2d.fbs | 23 + crates/re_types/src/archetypes/boxes2d.rs | 3 - .../re_types/src/archetypes/line_strips2d.rs | 6 +- crates/re_types/src/archetypes/points2d.rs | 3 +- .../src/blueprint/archetypes/.gitattributes | 1 + .../re_types/src/blueprint/archetypes/mod.rs | 2 + .../src/blueprint/archetypes/visual_bounds.rs | 159 +++++++ crates/re_types/src/components/.gitattributes | 1 + crates/re_types/src/components/aabb2d.rs | 134 ++++++ crates/re_types/src/components/aabb2d_ext.rs | 11 + crates/re_types/src/components/mod.rs | 3 + crates/re_types/src/datatypes/.gitattributes | 1 + crates/re_types/src/datatypes/aabb2d.rs | 436 ++++++++++++++++++ crates/re_types/src/datatypes/aabb2d_ext.rs | 21 + crates/re_types/src/datatypes/mod.rs | 3 + .../re_types_builder/src/codegen/docs/mod.rs | 2 + crates/re_viewer_context/src/store_context.rs | 3 + crates/re_viewer_context/src/store_hub.rs | 26 +- docs/content/reference/types/components.md | 1 + .../reference/types/components/.gitattributes | 1 + .../reference/types/components/aabb2d.md | 16 + docs/content/reference/types/datatypes.md | 1 + .../reference/types/datatypes/.gitattributes | 1 + .../reference/types/datatypes/aabb2d.md | 20 + .../types/datatypes/annotation_info.md | 1 - .../reference/types/datatypes/class_id.md | 2 +- .../reference/types/datatypes/keypoint_id.md | 1 - .../reference/types/datatypes/rgba32.md | 2 +- .../content/reference/types/datatypes/utf8.md | 4 +- .../reference/types/datatypes/vec2d.md | 1 + .../reference/types/datatypes/vec3d.md | 2 +- .../reference/types/views/spatial2d_view.md | 4 + .../snippets/all/annotation_context_rects.cpp | 3 - docs/snippets/all/annotation_context_rects.py | 3 - docs/snippets/all/annotation_context_rects.rs | 3 - docs/snippets/all/box2d_simple.cpp | 3 - docs/snippets/all/box2d_simple.py | 3 - docs/snippets/all/box2d_simple.rs | 3 - docs/snippets/all/extra_values.py | 5 +- docs/snippets/all/line_segments2d_simple.cpp | 3 +- docs/snippets/all/line_segments2d_simple.py | 5 +- docs/snippets/all/line_segments2d_simple.rs | 6 +- docs/snippets/all/line_strip2d_batch.cpp | 3 +- docs/snippets/all/line_strip2d_batch.py | 5 +- docs/snippets/all/line_strip2d_batch.rs | 6 +- docs/snippets/all/line_strip2d_simple.cpp | 3 +- docs/snippets/all/line_strip2d_simple.py | 5 +- docs/snippets/all/line_strip2d_simple.rs | 6 +- docs/snippets/all/point2d_random.cpp | 3 +- docs/snippets/all/point2d_random.py | 5 +- docs/snippets/all/point2d_random.rs | 3 +- docs/snippets/all/point2d_simple.cpp | 3 +- docs/snippets/all/point2d_simple.py | 5 +- docs/snippets/all/point2d_simple.rs | 3 +- rerun_cpp/src/rerun/archetypes/boxes2d.hpp | 3 - .../src/rerun/archetypes/line_strips2d.hpp | 3 +- rerun_cpp/src/rerun/archetypes/points2d.hpp | 3 +- rerun_cpp/src/rerun/blueprint/archetypes.hpp | 1 + .../rerun/blueprint/archetypes/.gitattributes | 2 + .../blueprint/archetypes/visual_bounds.cpp | 33 ++ .../blueprint/archetypes/visual_bounds.hpp | 64 +++ rerun_cpp/src/rerun/components.hpp | 1 + rerun_cpp/src/rerun/components/.gitattributes | 1 + rerun_cpp/src/rerun/components/aabb2d.hpp | 54 +++ rerun_cpp/src/rerun/datatypes.hpp | 1 + rerun_cpp/src/rerun/datatypes/.gitattributes | 2 + rerun_cpp/src/rerun/datatypes/aabb2d.cpp | 83 ++++ rerun_cpp/src/rerun/datatypes/aabb2d.hpp | 54 +++ .../rerun_sdk/rerun/archetypes/boxes2d.py | 3 - .../rerun/archetypes/line_strips2d.py | 5 +- .../rerun_sdk/rerun/archetypes/points2d.py | 5 +- .../rerun_sdk/rerun/blueprint/__init__.py | 1 + .../rerun/blueprint/archetypes/.gitattributes | 1 + .../rerun/blueprint/archetypes/__init__.py | 2 + .../blueprint/archetypes/visual_bounds.py | 49 ++ .../blueprint/archetypes/visual_bounds_ext.py | 35 ++ .../rerun/blueprint/views/spatial2d_view.py | 11 + .../rerun_sdk/rerun/components/.gitattributes | 1 + .../rerun_sdk/rerun/components/__init__.py | 4 + rerun_py/rerun_sdk/rerun/components/aabb2d.py | 29 ++ .../rerun_sdk/rerun/components/aabb2d_ext.py | 31 ++ .../rerun_sdk/rerun/datatypes/.gitattributes | 1 + .../rerun_sdk/rerun/datatypes/__init__.py | 6 + rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py | 101 ++++ .../rerun_sdk/rerun/datatypes/aabb2d_ext.py | 27 ++ 106 files changed, 1809 insertions(+), 200 deletions(-) create mode 100644 crates/re_query/src/latest_at/to_archetype/visual_bounds.rs create mode 100644 crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs create mode 100644 crates/re_types/definitions/rerun/components/aabb2d.fbs create mode 100644 crates/re_types/definitions/rerun/datatypes/aabb2d.fbs create mode 100644 crates/re_types/src/blueprint/archetypes/visual_bounds.rs create mode 100644 crates/re_types/src/components/aabb2d.rs create mode 100644 crates/re_types/src/components/aabb2d_ext.rs create mode 100644 crates/re_types/src/datatypes/aabb2d.rs create mode 100644 crates/re_types/src/datatypes/aabb2d_ext.rs create mode 100644 docs/content/reference/types/components/aabb2d.md create mode 100644 docs/content/reference/types/datatypes/aabb2d.md create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp create mode 100644 rerun_cpp/src/rerun/components/aabb2d.hpp create mode 100644 rerun_cpp/src/rerun/datatypes/aabb2d.cpp create mode 100644 rerun_cpp/src/rerun/datatypes/aabb2d.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py create mode 100644 rerun_py/rerun_sdk/rerun/components/aabb2d.py create mode 100644 rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py diff --git a/Cargo.lock b/Cargo.lock index 017c403cf712..2ce174593648 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4858,6 +4858,7 @@ dependencies = [ "document-features", "ecolor", "egui_plot", + "emath", "glam", "half 2.3.1", "image", diff --git a/crates/re_entity_db/src/entity_db.rs b/crates/re_entity_db/src/entity_db.rs index f298072bc266..5986f86c8389 100644 --- a/crates/re_entity_db/src/entity_db.rs +++ b/crates/re_entity_db/src/entity_db.rs @@ -241,6 +241,14 @@ impl EntityDb { } } + /// Get the latest index and value for a given dense [`re_types_core::Component`]. + /// + /// This assumes that the row we get from the store contains at most one instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// This is a best-effort helper, it will merely log errors on failure. #[inline] pub fn latest_at_component( &self, @@ -255,6 +263,14 @@ impl EntityDb { ) } + /// Get the latest index and value for a given dense [`re_types_core::Component`]. + /// + /// This assumes that the row we get from the store contains at most one instance for this + /// component; it will log a warning otherwise. + /// + /// This should only be used for "mono-components" such as `Transform` and `Tensor`. + /// + /// This is a best-effort helper, and will quietly swallow any errors. #[inline] pub fn latest_at_component_quiet( &self, diff --git a/crates/re_query/src/latest_at/helpers.rs b/crates/re_query/src/latest_at/helpers.rs index d850bfc660de..adce7289eabb 100644 --- a/crates/re_query/src/latest_at/helpers.rs +++ b/crates/re_query/src/latest_at/helpers.rs @@ -62,7 +62,7 @@ impl LatestAtComponentResults { /// Returns the component data of the single instance. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will log a warning otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. @@ -77,14 +77,19 @@ impl LatestAtComponentResults { re_log::debug_once!("Couldn't deserialize {component_name}: promise still pending",); None } - PromiseResult::Ready(data) if data.len() == 1 => Some(data[0].clone()), PromiseResult::Ready(data) => { - re_log::log_once!( - level, - "Couldn't deserialize {component_name}: not a mono-batch (length: {})", - data.len(), - ); - None + match data.len() { + 0 => { + None // Empty list = no data. + } + 1 => Some(data[0].clone()), + len => { + re_log::log_once!(level, + "Couldn't deserialize {component_name}: not a mono-batch (length: {len})" + ); + None + } + } } PromiseResult::Error(err) => { re_log::log_once!( @@ -99,7 +104,7 @@ impl LatestAtComponentResults { /// Returns the component data of the single instance as an arrow array. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will log a warning otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. @@ -118,16 +123,20 @@ impl LatestAtComponentResults { re_log::debug_once!("Couldn't get {component_name}: promise still pending"); None } - PromiseResult::Ready(cell) if cell.as_arrow_ref().len() == 1 => { - Some(cell.as_arrow_ref().sliced(0, 1)) - } PromiseResult::Ready(cell) => { - re_log::log_once!( - level, - "Couldn't get {component_name}: not a mono-batch (length: {})", - cell.as_arrow_ref().len(), - ); - None + match cell.as_arrow_ref().len() { + 0 => { + None // Empty list = no data. + } + 1 => Some(cell.as_arrow_ref().sliced(0, 1)), + len => { + re_log::log_once!( + level, + "Couldn't get {component_name}: not a mono-batch (length: {len})", + ); + None + } + } } PromiseResult::Error(err) => { re_log::log_once!( @@ -272,7 +281,7 @@ impl Caches { /// /// Returns `None` if the data is a promise that has yet to be resolved. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will generate a log message of `level` otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. @@ -303,18 +312,24 @@ impl Caches { ); None } - PromiseResult::Ready(data) if data.len() == 1 => Some(LatestAtMonoResult { - index, - value: data[0].clone(), - }), PromiseResult::Ready(data) => { - re_log::log_once!( - level, - "Couldn't deserialize {entity_path}:{} @ {data_time:?}#{row_id}: not a mono-batch (length: {})", - C::name(), - data.len(), - ); - None + match data.len() { + 0 => { + None // Empty list = no data. + } + 1 => Some(LatestAtMonoResult { + index, + value: data[0].clone(), + }), + len => { + re_log::log_once!( + level, + "Couldn't deserialize {entity_path}:{} @ {data_time:?}#{row_id}: not a mono-batch (length: {len})", + C::name(), + ); + None + } + } } PromiseResult::Error(err) => { re_log::log_once!( @@ -330,7 +345,7 @@ impl Caches { /// Get the latest index and value for a given dense [`re_types_core::Component`]. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will log a warning otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. @@ -355,7 +370,7 @@ impl Caches { /// Get the latest index and value for a given dense [`re_types_core::Component`]. /// - /// This assumes that the row we get from the store only contains a single instance for this + /// This assumes that the row we get from the store contains at most one instance for this /// component; it will return None and log a debug message otherwise. /// /// This should only be used for "mono-components" such as `Transform` and `Tensor`. diff --git a/crates/re_query/src/latest_at/to_archetype/.gitattributes b/crates/re_query/src/latest_at/to_archetype/.gitattributes index d8ec507351e3..e128a891fe94 100644 --- a/crates/re_query/src/latest_at/to_archetype/.gitattributes +++ b/crates/re_query/src/latest_at/to_archetype/.gitattributes @@ -36,3 +36,4 @@ text_log.rs linguist-generated=true transform3d.rs linguist-generated=true view_coordinates.rs linguist-generated=true viewport_blueprint.rs linguist-generated=true +visual_bounds.rs linguist-generated=true diff --git a/crates/re_query/src/latest_at/to_archetype/mod.rs b/crates/re_query/src/latest_at/to_archetype/mod.rs index 62d7ff7df884..4ce8223caddb 100644 --- a/crates/re_query/src/latest_at/to_archetype/mod.rs +++ b/crates/re_query/src/latest_at/to_archetype/mod.rs @@ -34,3 +34,4 @@ mod text_log; mod transform3d; mod view_coordinates; mod viewport_blueprint; +mod visual_bounds; diff --git a/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs b/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs new file mode 100644 index 000000000000..49d60ad0b78e --- /dev/null +++ b/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs @@ -0,0 +1,44 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] + +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for LatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::components::AABB2D; + let visual_bounds = if let Some(visual_bounds) = self.get(::name()) { + match visual_bounds.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::blueprint::archetypes::VisualBounds { visual_bounds }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 25255c2a8358..52b0dcc97b1d 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -18,8 +18,9 @@ pub use screenshot::ScreenshotMode; pub use space_view::SpaceViewBlueprint; pub use space_view_contents::SpaceViewContents; pub use sub_archetypes::{ - entity_path_for_space_view_sub_archetype, query_space_view_sub_archetype, - query_space_view_sub_archetype_or_default, space_view_sub_archetype, + edit_blueprint_component, entity_path_for_space_view_sub_archetype, get_blueprint_component, + query_space_view_sub_archetype, query_space_view_sub_archetype_or_default, + space_view_sub_archetype, }; pub use visual_time_range::{ query_visual_history, time_range_boundary_to_visible_history_boundary, diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 94936b7daaa8..8f700529f154 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -553,6 +553,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &re_viewer_context::StoreHub::test_hub(), @@ -597,6 +598,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &re_viewer_context::StoreHub::test_hub(), @@ -647,6 +649,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &re_viewer_context::StoreHub::test_hub(), @@ -920,6 +923,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &re_viewer_context::StoreHub::test_hub(), diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index 82116aef381e..fa99d65b5068 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -695,6 +695,7 @@ mod tests { let ctx = StoreContext { app_id: re_log_types::ApplicationId::unknown(), blueprint: &blueprint, + default_blueprint: None, recording: &recording, bundle: &Default::default(), hub: &StoreHub::test_hub(), diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index 8318470268e1..a19caa7ea33a 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -5,7 +5,7 @@ use re_entity_db::{ }; use re_log_types::EntityPath; use re_types::Archetype; -use re_viewer_context::{external::re_entity_db::EntityTree, SpaceViewId}; +use re_viewer_context::{external::re_entity_db::EntityTree, SpaceViewId, ViewerContext}; pub fn entity_path_for_space_view_sub_archetype( space_view_id: SpaceViewId, @@ -69,3 +69,59 @@ where let (arch, path) = query_space_view_sub_archetype(space_view_id, blueprint_db, query); (arch.ok().flatten().unwrap_or_default(), path) } + +/// Read a single component of a blueprint archetype in a space view. +pub fn get_blueprint_component( + ctx: &ViewerContext<'_>, + space_view_id: SpaceViewId, +) -> Option { + let blueprint_db = ctx.store_context.blueprint; + let query = ctx.blueprint_query; + let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); + blueprint_db + .latest_at_component::(&path, query) + .map(|x| x.value) +} + +/// Edit a single component of a blueprint archetype in a space view. +/// +/// Set to `None` to reset the value to the value in the default blueprint, if any, +/// else will just store `None` (an empty component list) in the store. +pub fn edit_blueprint_component( + ctx: &ViewerContext<'_>, + space_view_id: SpaceViewId, + edit_component: impl FnOnce(&mut Option) -> R, +) -> R { + let active_blueprint = ctx.store_context.blueprint; + let active_path = + entity_path_for_space_view_sub_archetype::(space_view_id, active_blueprint.tree()); + let original_value: Option = active_blueprint + .latest_at_component::(&active_path, ctx.blueprint_query) + .map(|x| x.value); + + let mut edited_value = original_value.clone(); + let ret = edit_component(&mut edited_value); + + if edited_value != original_value { + if let Some(edited) = edited_value { + ctx.save_blueprint_component(&active_path, &edited); + } else { + // Reset to the value in the default blueprint, if any. + let default_value = ctx + .store_context + .default_blueprint + .and_then(|default_blueprint| { + let default_path = entity_path_for_space_view_sub_archetype::( + space_view_id, + default_blueprint.tree(), + ); + default_blueprint + .latest_at_component::(&default_path, ctx.blueprint_query) + .map(|x| x.value) + }); + ctx.save_blueprint_component(&active_path, &default_value); + } + } + + ret +} diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index 62d07852501c..ea8797981f08 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -6,7 +6,7 @@ use re_format::format_f32; use re_log_types::EntityPath; use re_types::{ archetypes::{DepthImage, Image}, - blueprint::archetypes::Background, + blueprint::archetypes::{Background, VisualBounds}, Archetype, ComponentName, }; use re_viewer_context::{ @@ -254,22 +254,7 @@ impl SpaceViewClass for SpatialSpaceView2D { state.bounding_box_ui(ctx, ui, SpatialSpaceViewKind::TwoD); - { - let visual_bounds = &mut state.state_2d.visual_bounds; - ctx.re_ui - .grid_left_hand_label(ui, "Bounds") - .on_hover_text("The area guaranteed to be visible.\nDepending on the view's current aspect ratio the actually visible area might be larger either horizontally or vertically."); - ui.vertical(|ui| { - ui.style_mut().wrap = Some(false); - let (min, max) = (visual_bounds.min, visual_bounds.max); - ui.label(format!("x [{} - {}]", format_f32(min.x), format_f32(max.x),)); - ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); - if ui.button("Reset bounds").clicked() { - *visual_bounds = egui::Rect::NAN; - } - }); - ui.end_row(); - } + visual_bounds_ui(ctx, space_view_id, ui); }); Ok(()) } @@ -297,6 +282,35 @@ impl SpaceViewClass for SpatialSpaceView2D { } } +fn visual_bounds_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mut egui::Ui) { + let tooltip = "The area guaranteed to be visible.\n\ + Depending on the view's current aspect ratio the actually visible area might be larger either horizontally or vertically."; + re_space_view::edit_blueprint_component::( + ctx, + space_view_id, + |aabb: &mut Option| { + ctx.re_ui + .grid_left_hand_label(ui, "Visible bounds") + .on_hover_text(tooltip); + ui.vertical(|ui| { + ui.style_mut().wrap = Some(false); + + if let Some(aabb) = aabb { + let rect = egui::Rect::from(*aabb); + let (min, max) = (rect.min, rect.max); + ui.label(format!("x [{} - {}]", format_f32(min.x), format_f32(max.x),)); + ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); + } + + if ui.button("Reset visible bounds").clicked() { + *aabb = None; + } + }); + ui.end_row(); + }, + ); +} + // Count the number of image entities with the given component exist that aren't // children of other entities in the bucket. fn count_non_nested_images_with_component( diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 7099ccdf2649..4d8c7198b3b0 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -27,7 +27,7 @@ use crate::{ }; use crate::{eye::EyeMode, heuristics::auto_size_world_heuristic}; -use super::{eye::Eye, ui_2d::View2DState, ui_3d::View3DState}; +use super::{eye::Eye, ui_3d::View3DState}; /// Default auto point radius in UI points. const AUTO_POINT_RADIUS: f32 = 1.5; @@ -52,7 +52,7 @@ impl From for WidgetText { } } -/// TODO(andreas): Should turn this "inside out" - [`SpatialSpaceViewState`] should be used by [`View2DState`]/[`View3DState`], not the other way round. +/// TODO(andreas): Should turn this "inside out" - [`SpatialSpaceViewState`] should be used by [`View3DState`], not the other way round. #[derive(Clone, Default)] pub struct SpatialSpaceViewState { pub bounding_boxes: SceneBoundingBoxes, @@ -63,7 +63,6 @@ pub struct SpatialSpaceViewState { /// Last frame's picking result. pub previous_picking_result: Option, - pub(super) state_2d: View2DState, pub(super) state_3d: View3DState, /// Size of automatically sized objects. None if it wasn't configured. diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index cdd2507c57eb..6574da3e50e5 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -5,11 +5,12 @@ use re_entity_db::EntityPath; use re_renderer::view_builder::{TargetConfiguration, ViewBuilder}; use re_space_view::controls::{DRAG_PAN2D_BUTTON, RESET_VIEW_BUTTON_TEXT, ZOOM_SCROLL_MODIFIER}; use re_types::{ - archetypes::Pinhole, blueprint::archetypes::Background, components::ViewCoordinates, + archetypes::Pinhole, blueprint::archetypes::Background, blueprint::archetypes::VisualBounds, + components::ViewCoordinates, }; use re_viewer_context::{ - gpu_bridge, ItemSpaceContext, SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, - ViewerContext, + gpu_bridge, ItemSpaceContext, SpaceViewId, SpaceViewSystemExecutionError, + SystemExecutionOutput, ViewQuery, ViewerContext, }; use super::{ @@ -25,32 +26,16 @@ use crate::{ // --- -#[derive(Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)] -#[serde(default)] -pub struct View2DState { - /// The visible parts of the scene, in the coordinate space of the scene. - /// - /// Everything within these bounds are guaranteed to be visible. - /// Some thing outside of these bounds may also be visible due to letterboxing. - /// - /// Default: [`Rect::NAN`] (invalid). - /// Invalid bound will be set to the default on the next frame. - /// The default is usually the scene bounding box. - pub visual_bounds: Rect, -} - -impl Default for View2DState { - fn default() -> Self { - Self { - visual_bounds: Rect::NAN, - } - } -} - -impl View2DState { +/// Pan and zoom, and return the current transform. +fn ui_from_scene( + ctx: &ViewerContext<'_>, + space_view_id: SpaceViewId, + response: &egui::Response, + default_scene_rect: Rect, +) -> RectTransform { /// Pan and zoom, and return the current transform. - fn ui_from_scene( - &mut self, + fn update_ui_from_scene_impl( + visual_bounds: &mut Rect, response: &egui::Response, default_scene_rect: Rect, ) -> RectTransform { @@ -58,15 +43,10 @@ impl View2DState { rect.is_finite() && rect.is_positive() } - if response.double_clicked() { - self.visual_bounds = default_scene_rect; // double-click to reset + if !valid_bound(visual_bounds) { + *visual_bounds = default_scene_rect; } - - let bounds = &mut self.visual_bounds; - if !valid_bound(bounds) { - *bounds = default_scene_rect; - } - if !valid_bound(bounds) { + if !valid_bound(visual_bounds) { // Nothing in scene, probably. // Just return something that isn't NaN. let fake_bounds = Rect::from_min_size(Pos2::ZERO, Vec2::splat(1.0)); @@ -76,20 +56,20 @@ impl View2DState { // -------------------------------------------------------------------------- // Expand bounds for uniform scaling (letterboxing): - let mut letterboxed_bounds = *bounds; + let mut letterboxed_bounds = *visual_bounds; // Temporary before applying letterboxing: - let ui_from_scene = RectTransform::from_to(*bounds, response.rect); + let ui_from_scene = RectTransform::from_to(*visual_bounds, response.rect); let scale_aspect = ui_from_scene.scale().x / ui_from_scene.scale().y; if scale_aspect < 1.0 { // Letterbox top/bottom: - let add = bounds.height() * (1.0 / scale_aspect - 1.0); + let add = visual_bounds.height() * (1.0 / scale_aspect - 1.0); letterboxed_bounds.min.y -= 0.5 * add; letterboxed_bounds.max.y += 0.5 * add; } else { // Letterbox sides: - let add = bounds.width() * (scale_aspect - 1.0); + let add = visual_bounds.width() * (scale_aspect - 1.0); letterboxed_bounds.min.x -= 0.5 * add; letterboxed_bounds.max.x += 0.5 * add; } @@ -111,7 +91,7 @@ impl View2DState { pan_delta_in_ui += response.ctx.input(|i| i.raw_scroll_delta); } if pan_delta_in_ui != Vec2::ZERO { - *bounds = bounds.translate(-pan_delta_in_ui / ui_from_scene.scale()); + *visual_bounds = visual_bounds.translate(-pan_delta_in_ui / ui_from_scene.scale()); } if response.hovered() { @@ -125,8 +105,8 @@ impl View2DState { .inverse() .transform_pos(zoom_center_in_ui) .to_vec2(); - *bounds = scale_rect( - bounds.translate(-zoom_center_in_scene), + *visual_bounds = scale_rect( + visual_bounds.translate(-zoom_center_in_scene), Vec2::splat(1.0) / zoom_delta, ) .translate(zoom_center_in_scene); @@ -137,6 +117,34 @@ impl View2DState { RectTransform::from_to(letterboxed_bounds, response.rect) } + + re_space_view::edit_blueprint_component::< + VisualBounds, + re_types::components::AABB2D, + RectTransform, + >( + ctx, + space_view_id, + |aabb: &mut Option| { + // Convert to a Rect + let mut rect: Rect = aabb.map_or(default_scene_rect, Rect::from); + + // Apply pan and zoom based on input + let ui_from_scene = update_ui_from_scene_impl(&mut rect, response, default_scene_rect); + + // Store back the results + *aabb = Some(rect.into()); + + if response.double_clicked() { + // Double-click to reset. + // We put it last so that we reset to the value in the default blueprint + // (which is not the same as `default_scene_rect`). + *aabb = None; + } + + ui_from_scene + }, + ) } fn scale_rect(rect: Rect, factor: Vec2) -> Rect { @@ -212,7 +220,7 @@ pub fn view_2d( ui.allocate_painter(ui.available_size(), egui::Sense::click_and_drag()); // Convert ui coordinates to/from scene coordinates. - let ui_from_scene = state.state_2d.ui_from_scene(&response, default_scene_rect); + let ui_from_scene = ui_from_scene(ctx, query.space_view_id, &response, default_scene_rect); let scene_from_ui = ui_from_scene.inverse(); // TODO(andreas): Use the same eye & transformations as in `setup_target_config`. diff --git a/crates/re_types/Cargo.toml b/crates/re_types/Cargo.toml index 36acbbbb195e..ab360bae3b00 100644 --- a/crates/re_types/Cargo.toml +++ b/crates/re_types/Cargo.toml @@ -68,6 +68,7 @@ arrow2 = { workspace = true, features = [ ] } bytemuck = { workspace = true, features = ["derive", "extern_crate_alloc"] } document-features.workspace = true +emath.workspace = true half = { workspace = true, features = ["bytemuck"] } infer.workspace = true itertools.workspace = true diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index a28b8c19f61f..5d8717d4f60f 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -30,6 +30,7 @@ include "./blueprint/archetypes/panel_blueprint.fbs"; include "./blueprint/archetypes/space_view_blueprint.fbs"; include "./blueprint/archetypes/space_view_contents.fbs"; include "./blueprint/archetypes/viewport_blueprint.fbs"; +include "./blueprint/archetypes/visual_bounds.fbs"; include "./blueprint/archetypes/plot_legend.fbs"; include "./blueprint/archetypes/scalar_axis.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs index bdb5e1546fdf..eb4221620ea5 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/background.fbs @@ -8,8 +8,6 @@ include "rerun/attributes.fbs"; namespace rerun.blueprint.archetypes; -// --- - /// Configuration for the background of a view. table Background ( "attr.python.aliases": "datatypes.Rgba32Like, blueprint_components.BackgroundKindLike", diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs new file mode 100644 index 000000000000..4317e53fbe8e --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs @@ -0,0 +1,21 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.archetypes; + + +/// Controls the visual bounds of a 2D space view. +table VisualBounds ( + "attr.rerun.scope": "blueprint", + "attr.rust.derive": "Copy" +) { + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + visual_bounds: rerun.components.AABB2D ("attr.rerun.component_optional", nullable, order: 1000); +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs index e133d2c41e7d..86063fc7d097 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs @@ -8,4 +8,10 @@ table Spatial2DView ( ) { /// Configuration for the background of the space view. background: rerun.blueprint.archetypes.Background (order: 1000); + + /// The visible parts of the scene, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + visual_bounds: rerun.blueprint.archetypes.VisualBounds (order: 2000); } diff --git a/crates/re_types/definitions/rerun/components.fbs b/crates/re_types/definitions/rerun/components.fbs index 251b7f943b51..8ee16c67e9b4 100644 --- a/crates/re_types/definitions/rerun/components.fbs +++ b/crates/re_types/definitions/rerun/components.fbs @@ -1,3 +1,4 @@ +include "./components/aabb2d.fbs"; include "./components/annotation_context.fbs"; include "./components/blob.fbs"; include "./components/class_id.fbs"; diff --git a/crates/re_types/definitions/rerun/components/aabb2d.fbs b/crates/re_types/definitions/rerun/components/aabb2d.fbs new file mode 100644 index 000000000000..6855c9298a92 --- /dev/null +++ b/crates/re_types/definitions/rerun/components/aabb2d.fbs @@ -0,0 +1,18 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "fbs/attributes.fbs"; +include "rust/attributes.fbs"; + +include "../datatypes/aabb2d.fbs"; + +namespace rerun.components; + +// --- + +/// An Axis-Aligned Bounding Box in 2D space. +struct AABB2D ( + "attr.rust.derive": "Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", + "attr.rust.repr": "transparent" +) { + aabb: rerun.datatypes.AABB2D (order: 100); +} diff --git a/crates/re_types/definitions/rerun/datatypes.fbs b/crates/re_types/definitions/rerun/datatypes.fbs index d1c52a2f654b..23df51535ab2 100644 --- a/crates/re_types/definitions/rerun/datatypes.fbs +++ b/crates/re_types/definitions/rerun/datatypes.fbs @@ -1,3 +1,4 @@ +include "./datatypes/aabb2d.fbs"; include "./datatypes/angle.fbs"; include "./datatypes/annotation_info.fbs"; include "./datatypes/bool.fbs"; diff --git a/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs b/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs new file mode 100644 index 000000000000..2ea946feab57 --- /dev/null +++ b/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs @@ -0,0 +1,23 @@ +include "arrow/attributes.fbs"; +include "cpp/attributes.fbs"; +include "fbs/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "./vec2d.fbs"; + +namespace rerun.datatypes; + +// --- + +/// An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. +struct AABB2D ( + "attr.rust.derive": "Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", + "attr.rust.repr": "C" +) { + /// The minimum bounds; usually left-top corner. + min: rerun.datatypes.Vec2D (order: 100); + + /// The maximum bounds; usually right-bottom corner. + max: rerun.datatypes.Vec2D (order: 200); +} diff --git a/crates/re_types/src/archetypes/boxes2d.rs b/crates/re_types/src/archetypes/boxes2d.rs index 157edaad7e6f..09fe69052890 100644 --- a/crates/re_types/src/archetypes/boxes2d.rs +++ b/crates/re_types/src/archetypes/boxes2d.rs @@ -36,9 +36,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// &rerun::Boxes2D::from_mins_and_sizes([(-1., -1.)], [(2., 2.)]), /// )?; /// -/// // Log an extra rect to set the view bounds -/// rec.log("bounds", &rerun::Boxes2D::from_sizes([(4., 3.)]))?; -/// /// Ok(()) /// } /// ``` diff --git a/crates/re_types/src/archetypes/line_strips2d.rs b/crates/re_types/src/archetypes/line_strips2d.rs index 5f99edf23ccf..a001bb9b97a5 100644 --- a/crates/re_types/src/archetypes/line_strips2d.rs +++ b/crates/re_types/src/archetypes/line_strips2d.rs @@ -42,11 +42,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// .with_labels(["one strip here", "and one strip there"]), /// )?; /// -/// // Log an extra rect to set the view bounds -/// rec.log( -/// "bounds", -/// &rerun::Boxes2D::from_centers_and_sizes([(3.0, 1.5)], [(8.0, 9.0)]), -/// )?; +/// // TODO(#5521): log VisualBounds /// /// Ok(()) /// } diff --git a/crates/re_types/src/archetypes/points2d.rs b/crates/re_types/src/archetypes/points2d.rs index 5c90d8f76800..70993dd824da 100644 --- a/crates/re_types/src/archetypes/points2d.rs +++ b/crates/re_types/src/archetypes/points2d.rs @@ -43,8 +43,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// .with_radii((0..10).map(|_| rng.gen::())), /// )?; /// -/// // Log an extra rect to set the view bounds -/// rec.log("bounds", &rerun::Boxes2D::from_half_sizes([(4., 3.)]))?; +/// // TODO(#5521): log VisualBounds /// /// Ok(()) /// } diff --git a/crates/re_types/src/blueprint/archetypes/.gitattributes b/crates/re_types/src/blueprint/archetypes/.gitattributes index 003fc96d78d4..99631b4ea017 100644 --- a/crates/re_types/src/blueprint/archetypes/.gitattributes +++ b/crates/re_types/src/blueprint/archetypes/.gitattributes @@ -7,3 +7,4 @@ plot_legend.rs linguist-generated=true scalar_axis.rs linguist-generated=true space_view_blueprint.rs linguist-generated=true space_view_contents.rs linguist-generated=true +visual_bounds.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/archetypes/mod.rs b/crates/re_types/src/blueprint/archetypes/mod.rs index 6fcc74f24ee6..bca93c2d48e0 100644 --- a/crates/re_types/src/blueprint/archetypes/mod.rs +++ b/crates/re_types/src/blueprint/archetypes/mod.rs @@ -6,9 +6,11 @@ mod plot_legend; mod scalar_axis; mod space_view_blueprint; mod space_view_contents; +mod visual_bounds; pub use self::background::Background; pub use self::plot_legend::PlotLegend; pub use self::scalar_axis::ScalarAxis; pub use self::space_view_blueprint::SpaceViewBlueprint; pub use self::space_view_contents::SpaceViewContents; +pub use self::visual_bounds::VisualBounds; diff --git a/crates/re_types/src/blueprint/archetypes/visual_bounds.rs b/crates/re_types/src/blueprint/archetypes/visual_bounds.rs new file mode 100644 index 000000000000..f6e3a0c1fc12 --- /dev/null +++ b/crates/re_types/src/blueprint/archetypes/visual_bounds.rs @@ -0,0 +1,159 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Controls the visual bounds of a 2D space view. +#[derive(Clone, Debug, Copy)] +pub struct VisualBounds { + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + pub visual_bounds: Option, +} + +impl ::re_types_core::SizeBytes for VisualBounds { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.visual_bounds.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + } +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.VisualBoundsIndicator".into()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.components.AABB2D".into()]); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.VisualBoundsIndicator".into(), + "rerun.components.AABB2D".into(), + ] + }); + +impl VisualBounds { + pub const NUM_COMPONENTS: usize = 2usize; +} + +/// Indicator component for the [`VisualBounds`] [`::re_types_core::Archetype`] +pub type VisualBoundsIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for VisualBounds { + type Indicator = VisualBoundsIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.VisualBounds".into() + } + + #[inline] + fn indicator() -> MaybeOwnedComponentBatch<'static> { + static INDICATOR: VisualBoundsIndicator = VisualBoundsIndicator::DEFAULT; + MaybeOwnedComponentBatch::Ref(&INDICATOR) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let visual_bounds = if let Some(array) = arrays_by_name.get("rerun.components.AABB2D") { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.VisualBounds#visual_bounds")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { visual_bounds }) + } +} + +impl ::re_types_core::AsComponents for VisualBounds { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + self.visual_bounds + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch).into()), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl VisualBounds { + pub fn new() -> Self { + Self { + visual_bounds: None, + } + } + + #[inline] + pub fn with_visual_bounds( + mut self, + visual_bounds: impl Into, + ) -> Self { + self.visual_bounds = Some(visual_bounds.into()); + self + } +} diff --git a/crates/re_types/src/components/.gitattributes b/crates/re_types/src/components/.gitattributes index 503b4ae31ccd..287ee7843db7 100644 --- a/crates/re_types/src/components/.gitattributes +++ b/crates/re_types/src/components/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.rs linguist-generated=true annotation_context.rs linguist-generated=true blob.rs linguist-generated=true class_id.rs linguist-generated=true diff --git a/crates/re_types/src/components/aabb2d.rs b/crates/re_types/src/components/aabb2d.rs new file mode 100644 index 000000000000..fd332cff360f --- /dev/null +++ b/crates/re_types/src/components/aabb2d.rs @@ -0,0 +1,134 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: An Axis-Aligned Bounding Box in 2D space. +#[derive(Clone, Debug, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] +#[repr(transparent)] +pub struct AABB2D(pub crate::datatypes::AABB2D); + +impl ::re_types_core::SizeBytes for AABB2D { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for AABB2D { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for AABB2D { + #[inline] + fn borrow(&self) -> &crate::datatypes::AABB2D { + &self.0 + } +} + +impl std::ops::Deref for AABB2D { + type Target = crate::datatypes::AABB2D; + + #[inline] + fn deref(&self) -> &crate::datatypes::AABB2D { + &self.0 + } +} + +::re_types_core::macros::impl_into_cow!(AABB2D); + +impl ::re_types_core::Loggable for AABB2D { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.components.AABB2D".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new("min", ::arrow_datatype(), false), + Field::new("max", ::arrow_datatype(), false), + ])) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data0): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + let datum = datum.map(|datum| { + let Self(data0) = datum.into_owned(); + data0 + }); + (datum.is_some(), datum) + }) + .unzip(); + let data0_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + _ = data0_bitmap; + crate::datatypes::AABB2D::to_arrow_opt(data0)? + } + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok(crate::datatypes::AABB2D::from_arrow_opt(arrow_data) + .with_context("rerun.components.AABB2D#aabb")? + .into_iter() + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .map(|res| res.map(|v| Some(Self(v)))) + .collect::>>>() + .with_context("rerun.components.AABB2D#aabb") + .with_context("rerun.components.AABB2D")?) + } +} diff --git a/crates/re_types/src/components/aabb2d_ext.rs b/crates/re_types/src/components/aabb2d_ext.rs new file mode 100644 index 000000000000..0367ab75bb27 --- /dev/null +++ b/crates/re_types/src/components/aabb2d_ext.rs @@ -0,0 +1,11 @@ +use super::AABB2D; + +impl From for emath::Rect { + #[inline] + fn from(v: AABB2D) -> Self { + Self { + min: emath::pos2(v.min[0], v.min[1]), + max: emath::pos2(v.max[0], v.max[1]), + } + } +} diff --git a/crates/re_types/src/components/mod.rs b/crates/re_types/src/components/mod.rs index 0a5d32a77b59..6bbc7bfca394 100644 --- a/crates/re_types/src/components/mod.rs +++ b/crates/re_types/src/components/mod.rs @@ -1,5 +1,7 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +mod aabb2d; +mod aabb2d_ext; mod annotation_context; mod blob; mod blob_ext; @@ -68,6 +70,7 @@ mod vector3d_ext; mod view_coordinates; mod view_coordinates_ext; +pub use self::aabb2d::AABB2D; pub use self::annotation_context::AnnotationContext; pub use self::blob::Blob; pub use self::class_id::ClassId; diff --git a/crates/re_types/src/datatypes/.gitattributes b/crates/re_types/src/datatypes/.gitattributes index bb3603b3cdde..f14598e3fbb4 100644 --- a/crates/re_types/src/datatypes/.gitattributes +++ b/crates/re_types/src/datatypes/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.rs linguist-generated=true angle.rs linguist-generated=true annotation_info.rs linguist-generated=true bool.rs linguist-generated=true diff --git a/crates/re_types/src/datatypes/aabb2d.rs b/crates/re_types/src/datatypes/aabb2d.rs new file mode 100644 index 000000000000..32551e4f92ea --- /dev/null +++ b/crates/re_types/src/datatypes/aabb2d.rs @@ -0,0 +1,436 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. +#[derive(Clone, Debug, Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] +#[repr(C)] +pub struct AABB2D { + /// The minimum bounds; usually left-top corner. + pub min: crate::datatypes::Vec2D, + + /// The maximum bounds; usually right-bottom corner. + pub max: crate::datatypes::Vec2D, +} + +impl ::re_types_core::SizeBytes for AABB2D { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.min.heap_size_bytes() + self.max.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() && ::is_pod() + } +} + +::re_types_core::macros::impl_into_cow!(AABB2D); + +impl ::re_types_core::Loggable for AABB2D { + type Name = ::re_types_core::DatatypeName; + + #[inline] + fn name() -> Self::Name { + "rerun.datatypes.AABB2D".into() + } + + #[allow(clippy::wildcard_imports)] + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + use arrow2::datatypes::*; + DataType::Struct(std::sync::Arc::new(vec![ + Field::new("min", ::arrow_datatype(), false), + Field::new("max", ::arrow_datatype(), false), + ])) + } + + #[allow(clippy::wildcard_imports)] + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, datatypes::*}; + Ok({ + let (somes, data): (Vec<_>, Vec<_>) = data + .into_iter() + .map(|datum| { + let datum: Option<::std::borrow::Cow<'a, Self>> = datum.map(Into::into); + (datum.is_some(), datum) + }) + .unzip(); + let bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + StructArray::new( + ::arrow_datatype(), + vec![ + { + let (somes, min): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { min, .. } = &**datum; + min.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let min_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; + let min_inner_data: Vec<_> = min + .iter() + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::Vec2D(data0) = datum; + data0 + }) + .unwrap_or_default() + }) + .flatten() + .map(Some) + .collect(); + let min_inner_bitmap: Option = + min_bitmap.as_ref().map(|bitmap| { + bitmap + .iter() + .map(|i| std::iter::repeat(i).take(2usize)) + .flatten() + .collect::>() + .into() + }); + FixedSizeListArray::new( + DataType::FixedSizeList( + std::sync::Arc::new(Field::new( + "item", + DataType::Float32, + false, + )), + 2usize, + ), + PrimitiveArray::new( + DataType::Float32, + min_inner_data + .into_iter() + .map(|v| v.unwrap_or_default()) + .collect(), + min_inner_bitmap, + ) + .boxed(), + min_bitmap, + ) + .boxed() + } + }, + { + let (somes, max): (Vec<_>, Vec<_>) = data + .iter() + .map(|datum| { + let datum = datum.as_ref().map(|datum| { + let Self { max, .. } = &**datum; + max.clone() + }); + (datum.is_some(), datum) + }) + .unzip(); + let max_bitmap: Option = { + let any_nones = somes.iter().any(|some| !*some); + any_nones.then(|| somes.into()) + }; + { + use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; + let max_inner_data: Vec<_> = max + .iter() + .map(|datum| { + datum + .map(|datum| { + let crate::datatypes::Vec2D(data0) = datum; + data0 + }) + .unwrap_or_default() + }) + .flatten() + .map(Some) + .collect(); + let max_inner_bitmap: Option = + max_bitmap.as_ref().map(|bitmap| { + bitmap + .iter() + .map(|i| std::iter::repeat(i).take(2usize)) + .flatten() + .collect::>() + .into() + }); + FixedSizeListArray::new( + DataType::FixedSizeList( + std::sync::Arc::new(Field::new( + "item", + DataType::Float32, + false, + )), + 2usize, + ), + PrimitiveArray::new( + DataType::Float32, + max_inner_data + .into_iter() + .map(|v| v.unwrap_or_default()) + .collect(), + max_inner_bitmap, + ) + .boxed(), + max_bitmap, + ) + .boxed() + } + }, + ], + bitmap, + ) + .boxed() + }) + } + + #[allow(clippy::wildcard_imports)] + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + use ::re_types_core::{Loggable as _, ResultExt as _}; + use arrow2::{array::*, buffer::*, datatypes::*}; + Ok({ + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = Self::arrow_datatype(); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let (arrow_data_fields, arrow_data_arrays) = + (arrow_data.fields(), arrow_data.values()); + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data_fields + .iter() + .map(|field| field.name.as_str()) + .zip(arrow_data_arrays) + .collect(); + let min = { + if !arrays_by_name.contains_key("min") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "min", + )) + .with_context("rerun.datatypes.AABB2D"); + } + let arrow_data = &**arrays_by_name["min"]; + { + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::FixedSizeList( + std::sync::Arc::new(Field::new( + "item", + DataType::Float32, + false, + )), + 2usize, + ); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D#min")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let offsets = (0..) + .step_by(2usize) + .zip((2usize..).step_by(2usize).take(arrow_data.len())); + let arrow_data_inner = { + let arrow_data_inner = &**arrow_data.values(); + arrow_data_inner + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::Float32; + let actual = arrow_data_inner.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D#min")? + .into_iter() + .map(|opt| opt.copied()) + .collect::>() + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + offsets, + arrow_data.validity(), + ) + .map(|elem| { + elem.map(|(start, end)| { + debug_assert!(end - start == 2usize); + if end as usize > arrow_data_inner.len() { + return Err(DeserializationError::offset_slice_oob( + (start, end), + arrow_data_inner.len(), + )); + } + + #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + let data = unsafe { + arrow_data_inner.get_unchecked(start as usize..end as usize) + }; + let data = data.iter().cloned().map(Option::unwrap_or_default); + let arr = array_init::from_iter(data).unwrap(); + Ok(arr) + }) + .transpose() + }) + .map(|res_or_opt| { + res_or_opt.map(|res_or_opt| { + res_or_opt.map(|v| crate::datatypes::Vec2D(v)) + }) + }) + .collect::>>>()? + } + .into_iter() + } + }; + let max = { + if !arrays_by_name.contains_key("max") { + return Err(DeserializationError::missing_struct_field( + Self::arrow_datatype(), + "max", + )) + .with_context("rerun.datatypes.AABB2D"); + } + let arrow_data = &**arrays_by_name["max"]; + { + let arrow_data = arrow_data + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::FixedSizeList( + std::sync::Arc::new(Field::new( + "item", + DataType::Float32, + false, + )), + 2usize, + ); + let actual = arrow_data.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D#max")?; + if arrow_data.is_empty() { + Vec::new() + } else { + let offsets = (0..) + .step_by(2usize) + .zip((2usize..).step_by(2usize).take(arrow_data.len())); + let arrow_data_inner = { + let arrow_data_inner = &**arrow_data.values(); + arrow_data_inner + .as_any() + .downcast_ref::() + .ok_or_else(|| { + let expected = DataType::Float32; + let actual = arrow_data_inner.data_type().clone(); + DeserializationError::datatype_mismatch(expected, actual) + }) + .with_context("rerun.datatypes.AABB2D#max")? + .into_iter() + .map(|opt| opt.copied()) + .collect::>() + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + offsets, + arrow_data.validity(), + ) + .map(|elem| { + elem.map(|(start, end)| { + debug_assert!(end - start == 2usize); + if end as usize > arrow_data_inner.len() { + return Err(DeserializationError::offset_slice_oob( + (start, end), + arrow_data_inner.len(), + )); + } + + #[allow(unsafe_code, clippy::undocumented_unsafe_blocks)] + let data = unsafe { + arrow_data_inner.get_unchecked(start as usize..end as usize) + }; + let data = data.iter().cloned().map(Option::unwrap_or_default); + let arr = array_init::from_iter(data).unwrap(); + Ok(arr) + }) + .transpose() + }) + .map(|res_or_opt| { + res_or_opt.map(|res_or_opt| { + res_or_opt.map(|v| crate::datatypes::Vec2D(v)) + }) + }) + .collect::>>>()? + } + .into_iter() + } + }; + arrow2::bitmap::utils::ZipValidity::new_with_validity( + ::itertools::izip!(min, max), + arrow_data.validity(), + ) + .map(|opt| { + opt.map(|(min, max)| { + Ok(Self { + min: min + .ok_or_else(DeserializationError::missing_data) + .with_context("rerun.datatypes.AABB2D#min")?, + max: max + .ok_or_else(DeserializationError::missing_data) + .with_context("rerun.datatypes.AABB2D#max")?, + }) + }) + .transpose() + }) + .collect::>>() + .with_context("rerun.datatypes.AABB2D")? + } + }) + } +} diff --git a/crates/re_types/src/datatypes/aabb2d_ext.rs b/crates/re_types/src/datatypes/aabb2d_ext.rs new file mode 100644 index 000000000000..92c929d7cf55 --- /dev/null +++ b/crates/re_types/src/datatypes/aabb2d_ext.rs @@ -0,0 +1,21 @@ +use super::AABB2D; + +impl From for AABB2D { + #[inline] + fn from(v: emath::Rect) -> Self { + Self { + min: [v.min.x, v.min.y].into(), + max: [v.max.x, v.max.y].into(), + } + } +} + +impl From for emath::Rect { + #[inline] + fn from(v: AABB2D) -> Self { + Self { + min: emath::pos2(v.min[0], v.min[1]), + max: emath::pos2(v.max[0], v.max[1]), + } + } +} diff --git a/crates/re_types/src/datatypes/mod.rs b/crates/re_types/src/datatypes/mod.rs index 02fdfd040b3b..6337fb92fb98 100644 --- a/crates/re_types/src/datatypes/mod.rs +++ b/crates/re_types/src/datatypes/mod.rs @@ -1,5 +1,7 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +mod aabb2d; +mod aabb2d_ext; mod angle; mod angle_ext; mod annotation_info; @@ -61,6 +63,7 @@ mod vec3d_ext; mod vec4d; mod vec4d_ext; +pub use self::aabb2d::AABB2D; pub use self::angle::Angle; pub use self::annotation_info::AnnotationInfo; pub use self::bool::Bool; diff --git a/crates/re_types_builder/src/codegen/docs/mod.rs b/crates/re_types_builder/src/codegen/docs/mod.rs index dd8e7b4208ea..1bab905ca593 100644 --- a/crates/re_types_builder/src/codegen/docs/mod.rs +++ b/crates/re_types_builder/src/codegen/docs/mod.rs @@ -433,6 +433,8 @@ fn write_used_by(o: &mut String, reporter: &Reporter, object: &Object, object_ma } } } + used_by.sort(); + used_by.dedup(); // The same datatype can be used multiple times by the same component if used_by.is_empty() { // NOTE: there are some false positives here, because unions can only diff --git a/crates/re_viewer_context/src/store_context.rs b/crates/re_viewer_context/src/store_context.rs index 45891cd87e12..b401952315eb 100644 --- a/crates/re_viewer_context/src/store_context.rs +++ b/crates/re_viewer_context/src/store_context.rs @@ -11,6 +11,9 @@ pub struct StoreContext<'a> { /// The current active blueprint. pub blueprint: &'a EntityDb, + /// The default blueprint (i.e. the one logged from code), if any. + pub default_blueprint: Option<&'a EntityDb>, + /// The current active recording. /// /// If none is active, this will point to a dummy empty recording. diff --git a/crates/re_viewer_context/src/store_hub.rs b/crates/re_viewer_context/src/store_hub.rs index 0160a1a14915..3ea006b33fdb 100644 --- a/crates/re_viewer_context/src/store_hub.rs +++ b/crates/re_viewer_context/src/store_hub.rs @@ -178,15 +178,22 @@ impl StoreHub { } } - // Get the id is of whatever blueprint is now active, falling back on the "app blueprint" if needed. - let active_blueprint_id = self - .active_blueprint_by_app_id - .entry(app_id.clone()) - .or_insert_with(|| StoreId::from_string(StoreKind::Blueprint, app_id.clone().0)); + let active_blueprint = { + // Get the id is of whatever blueprint is now active, falling back on the "app blueprint" if needed. + let active_blueprint_id = self + .active_blueprint_by_app_id + .entry(app_id.clone()) + .or_insert_with(|| StoreId::from_string(StoreKind::Blueprint, app_id.clone().0)); + + // Get or create the blueprint: + self.store_bundle.blueprint_entry(active_blueprint_id); + self.store_bundle.get(active_blueprint_id)? + }; - // Get or create the blueprint: - self.store_bundle.blueprint_entry(active_blueprint_id); - let blueprint = self.store_bundle.get(active_blueprint_id)?; + let default_blueprint = self + .default_blueprint_by_app_id + .get(&app_id) + .and_then(|id| self.store_bundle.get(id)); let recording = self .active_rec_id @@ -199,7 +206,8 @@ impl StoreHub { Some(StoreContext { app_id, - blueprint, + blueprint: active_blueprint, + default_blueprint, recording: recording.unwrap_or(&EMPTY_ENTITY_DB), bundle: &self.store_bundle, hub: self, diff --git a/docs/content/reference/types/components.md b/docs/content/reference/types/components.md index 2acb3837ee18..554e9e4cb07c 100644 --- a/docs/content/reference/types/components.md +++ b/docs/content/reference/types/components.md @@ -14,6 +14,7 @@ For more information on the relationship between **archetypes** and **components on [Entities and Components](../../concepts/entity-component.md). +* [`AABB2D`](components/aabb2d.md): An Axis-Aligned Bounding Box in 2D space. * [`AnnotationContext`](components/annotation_context.md): The `AnnotationContext` provides additional information on how to display entities. * [`Blob`](components/blob.md): A binary blob of data. * [`ClassId`](components/class_id.md): A 16-bit ID representing a type of semantic class. diff --git a/docs/content/reference/types/components/.gitattributes b/docs/content/reference/types/components/.gitattributes index 463f9186673f..6522ac09f2f0 100644 --- a/docs/content/reference/types/components/.gitattributes +++ b/docs/content/reference/types/components/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.md linguist-generated=true annotation_context.md linguist-generated=true blob.md linguist-generated=true class_id.md linguist-generated=true diff --git a/docs/content/reference/types/components/aabb2d.md b/docs/content/reference/types/components/aabb2d.md new file mode 100644 index 000000000000..e309a3ed3216 --- /dev/null +++ b/docs/content/reference/types/components/aabb2d.md @@ -0,0 +1,16 @@ +--- +title: "AABB2D" +--- + +An Axis-Aligned Bounding Box in 2D space. + +## Fields + +* aabb: [`AABB2D`](../datatypes/aabb2d.md) + +## Links + * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1AABB2D.html) + * 🐍 [Python API docs for `AABB2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.AABB2D) + * 🦀 [Rust API docs for `AABB2D`](https://docs.rs/rerun/latest/rerun/components/struct.AABB2D.html) + + diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index 8b94d62c0251..e56bfd384f06 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -8,6 +8,7 @@ order: 3 Data types are the lowest layer of the data model hierarchy. They are re-usable types used by the components. +* [`AABB2D`](datatypes/aabb2d.md): An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. * [`Angle`](datatypes/angle.md): Angle in either radians or degrees. * [`AnnotationInfo`](datatypes/annotation_info.md): Annotation info annotating a class id or key-point id. * [`Bool`](datatypes/bool.md): A single boolean. diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index e4b7aacfd945..cd80d78a173b 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.md linguist-generated=true angle.md linguist-generated=true annotation_info.md linguist-generated=true bool.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/aabb2d.md b/docs/content/reference/types/datatypes/aabb2d.md new file mode 100644 index 000000000000..dec7dbd29400 --- /dev/null +++ b/docs/content/reference/types/datatypes/aabb2d.md @@ -0,0 +1,20 @@ +--- +title: "AABB2D" +--- + +An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. + +## Fields + +* min: [`Vec2D`](../datatypes/vec2d.md) +* max: [`Vec2D`](../datatypes/vec2d.md) + +## Links + * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1AABB2D.html) + * 🐍 [Python API docs for `AABB2D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.AABB2D) + * 🦀 [Rust API docs for `AABB2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.AABB2D.html) + + +## Used by + +* [`AABB2D`](../components/aabb2d.md) diff --git a/docs/content/reference/types/datatypes/annotation_info.md b/docs/content/reference/types/datatypes/annotation_info.md index 9ed573668f82..54ae74e6291e 100644 --- a/docs/content/reference/types/datatypes/annotation_info.md +++ b/docs/content/reference/types/datatypes/annotation_info.md @@ -22,4 +22,3 @@ The id refers either to a class or key-point id ## Used by * [`ClassDescription`](../datatypes/class_description.md) -* [`ClassDescription`](../datatypes/class_description.md) diff --git a/docs/content/reference/types/datatypes/class_id.md b/docs/content/reference/types/datatypes/class_id.md index 02c6d1e6ef3b..4a39ebf28ae9 100644 --- a/docs/content/reference/types/datatypes/class_id.md +++ b/docs/content/reference/types/datatypes/class_id.md @@ -16,5 +16,5 @@ A 16-bit ID representing a type of semantic class. ## Used by -* [`ClassId`](../components/class_id.md) * [`ClassDescriptionMapElem`](../datatypes/class_description_map_elem.md) +* [`ClassId`](../components/class_id.md) diff --git a/docs/content/reference/types/datatypes/keypoint_id.md b/docs/content/reference/types/datatypes/keypoint_id.md index a22dc294f012..fd53dc3846bb 100644 --- a/docs/content/reference/types/datatypes/keypoint_id.md +++ b/docs/content/reference/types/datatypes/keypoint_id.md @@ -18,4 +18,3 @@ A 16-bit ID representing a type of semantic keypoint within a class. * [`KeypointId`](../components/keypoint_id.md) * [`KeypointPair`](../datatypes/keypoint_pair.md) -* [`KeypointPair`](../datatypes/keypoint_pair.md) diff --git a/docs/content/reference/types/datatypes/rgba32.md b/docs/content/reference/types/datatypes/rgba32.md index 5ade3fd54630..6a9828df9ec4 100644 --- a/docs/content/reference/types/datatypes/rgba32.md +++ b/docs/content/reference/types/datatypes/rgba32.md @@ -19,6 +19,6 @@ byte is `R` and the least significant byte is `A`. ## Used by -* [`Color`](../components/color.md) * [`AnnotationInfo`](../datatypes/annotation_info.md) +* [`Color`](../components/color.md) * [`Material`](../datatypes/material.md) diff --git a/docs/content/reference/types/datatypes/utf8.md b/docs/content/reference/types/datatypes/utf8.md index 711a41681d33..572dadde7d91 100644 --- a/docs/content/reference/types/datatypes/utf8.md +++ b/docs/content/reference/types/datatypes/utf8.md @@ -16,8 +16,8 @@ A string of text, encoded as UTF-8. ## Used by +* [`AnnotationInfo`](../datatypes/annotation_info.md) * [`MediaType`](../components/media_type.md) * [`Name`](../components/name.md) -* [`Text`](../components/text.md) * [`TextLogLevel`](../components/text_log_level.md) -* [`AnnotationInfo`](../datatypes/annotation_info.md) +* [`Text`](../components/text.md) diff --git a/docs/content/reference/types/datatypes/vec2d.md b/docs/content/reference/types/datatypes/vec2d.md index 68aa0b665805..d9055170734a 100644 --- a/docs/content/reference/types/datatypes/vec2d.md +++ b/docs/content/reference/types/datatypes/vec2d.md @@ -16,6 +16,7 @@ A vector in 2D space. ## Used by +* [`AABB2D`](../datatypes/aabb2d.md) * [`HalfSizes2D`](../components/half_sizes2d.md) * [`LineStrip2D`](../components/line_strip2d.md) * [`Position2D`](../components/position2d.md) diff --git a/docs/content/reference/types/datatypes/vec3d.md b/docs/content/reference/types/datatypes/vec3d.md index 4fa7ed4c0c9d..d408e84903e6 100644 --- a/docs/content/reference/types/datatypes/vec3d.md +++ b/docs/content/reference/types/datatypes/vec3d.md @@ -19,8 +19,8 @@ A vector in 3D space. * [`HalfSizes3D`](../components/half_sizes3d.md) * [`LineStrip3D`](../components/line_strip3d.md) * [`Position3D`](../components/position3d.md) -* [`Vector3D`](../components/vector3d.md) * [`RotationAxisAngle`](../datatypes/rotation_axis_angle.md) * [`Scale3D`](../datatypes/scale3d.md) * [`TranslationAndMat3x3`](../datatypes/translation_and_mat3x3.md) * [`TranslationRotationScale3D`](../datatypes/translation_rotation_scale3d.md) +* [`Vector3D`](../components/vector3d.md) diff --git a/docs/content/reference/types/views/spatial2d_view.md b/docs/content/reference/types/views/spatial2d_view.md index fd5050615bc3..065e19d4996d 100644 --- a/docs/content/reference/types/views/spatial2d_view.md +++ b/docs/content/reference/types/views/spatial2d_view.md @@ -11,6 +11,10 @@ Configuration for the background of a view. * kind: The type of the background. Defaults to BackgroundKind.GradientDark. * color: Color used for BackgroundKind.SolidColor. +### `VisualBounds` +Controls the visual bounds of a 2D space view. + +* visual_bounds: The visible parts of a 2D space view, in the coordinate space of the scene. ## Links * 🐍 [Python API docs for `Spatial2DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial2DView) diff --git a/docs/snippets/all/annotation_context_rects.cpp b/docs/snippets/all/annotation_context_rects.cpp index 4ba4c9150708..e8c51745f897 100644 --- a/docs/snippets/all/annotation_context_rects.cpp +++ b/docs/snippets/all/annotation_context_rects.cpp @@ -23,7 +23,4 @@ int main() { {{3.0f, 3.0f}, {2.0f, 2.0f}} ).with_class_ids({1, 2}) ); - - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_half_sizes({{2.5f, 2.5f}})); } diff --git a/docs/snippets/all/annotation_context_rects.py b/docs/snippets/all/annotation_context_rects.py index 1c430116d223..b69c17f0311a 100644 --- a/docs/snippets/all/annotation_context_rects.py +++ b/docs/snippets/all/annotation_context_rects.py @@ -7,6 +7,3 @@ # Log a batch of 2 rectangles with different `class_ids` rr.log("detections", rr.Boxes2D(mins=[[-2, -2], [0, 0]], sizes=[[3, 3], [2, 2]], class_ids=[1, 2])) - -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(half_sizes=[2.5, 2.5])) diff --git a/docs/snippets/all/annotation_context_rects.rs b/docs/snippets/all/annotation_context_rects.rs index 344fc1155dbc..866e037a26ae 100644 --- a/docs/snippets/all/annotation_context_rects.rs +++ b/docs/snippets/all/annotation_context_rects.rs @@ -20,8 +20,5 @@ fn main() -> Result<(), Box> { .with_class_ids([1, 2]), )?; - // Log an extra rect to set the view bounds - rec.log("bounds", &rerun::Boxes2D::from_half_sizes([(2.5, 2.5)]))?; - Ok(()) } diff --git a/docs/snippets/all/box2d_simple.cpp b/docs/snippets/all/box2d_simple.cpp index 1030ceffb9bd..41fd9499ea60 100644 --- a/docs/snippets/all/box2d_simple.cpp +++ b/docs/snippets/all/box2d_simple.cpp @@ -7,7 +7,4 @@ int main() { rec.spawn().exit_on_failure(); rec.log("simple", rerun::Boxes2D::from_mins_and_sizes({{-1.f, -1.f}}, {{2.f, 2.f}})); - - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_sizes({{4.f, 3.f}})); } diff --git a/docs/snippets/all/box2d_simple.py b/docs/snippets/all/box2d_simple.py index 864dbcddb75f..c4d895b3c8cd 100644 --- a/docs/snippets/all/box2d_simple.py +++ b/docs/snippets/all/box2d_simple.py @@ -5,6 +5,3 @@ rr.init("rerun_example_box2d", spawn=True) rr.log("simple", rr.Boxes2D(mins=[-1, -1], sizes=[2, 2])) - -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(sizes=[4.0, 3.0])) diff --git a/docs/snippets/all/box2d_simple.rs b/docs/snippets/all/box2d_simple.rs index ad85656e64e2..e0d785679e36 100644 --- a/docs/snippets/all/box2d_simple.rs +++ b/docs/snippets/all/box2d_simple.rs @@ -8,8 +8,5 @@ fn main() -> Result<(), Box> { &rerun::Boxes2D::from_mins_and_sizes([(-1., -1.)], [(2., 2.)]), )?; - // Log an extra rect to set the view bounds - rec.log("bounds", &rerun::Boxes2D::from_sizes([(4., 3.)]))?; - Ok(()) } diff --git a/docs/snippets/all/extra_values.py b/docs/snippets/all/extra_values.py index 0d477be1c892..0f4ee366ab1b 100644 --- a/docs/snippets/all/extra_values.py +++ b/docs/snippets/all/extra_values.py @@ -1,6 +1,7 @@ """Log extra values with a Points2D.""" import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_extra_values", spawn=True) @@ -12,5 +13,5 @@ ), ) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(sizes=[3, 3])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1.5, -1.5], max=[1.5, 1.5]))) diff --git a/docs/snippets/all/line_segments2d_simple.cpp b/docs/snippets/all/line_segments2d_simple.cpp index e9ea998ceecb..c4bad78d6c66 100644 --- a/docs/snippets/all/line_segments2d_simple.cpp +++ b/docs/snippets/all/line_segments2d_simple.cpp @@ -12,6 +12,5 @@ int main() { }; rec.log("segments", rerun::LineStrips2D(points)); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_centers_and_sizes({{3.0f, 0.0f}}, {{8.0f, 6.0f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/line_segments2d_simple.py b/docs/snippets/all/line_segments2d_simple.py index 1700bdaced31..6676dda3be00 100644 --- a/docs/snippets/all/line_segments2d_simple.py +++ b/docs/snippets/all/line_segments2d_simple.py @@ -2,6 +2,7 @@ import numpy as np import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_line_segments2d", spawn=True) @@ -10,5 +11,5 @@ rr.LineStrips2D(np.array([[[0, 0], [2, 1]], [[4, -1], [6, 0]]])), ) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(centers=[3, 0], half_sizes=[4, 3])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 3]))) diff --git a/docs/snippets/all/line_segments2d_simple.rs b/docs/snippets/all/line_segments2d_simple.rs index 36e6687a217f..9b4d7ad3c51c 100644 --- a/docs/snippets/all/line_segments2d_simple.rs +++ b/docs/snippets/all/line_segments2d_simple.rs @@ -6,11 +6,7 @@ fn main() -> Result<(), Box> { let points = [[0., 0.], [2., 1.], [4., -1.], [6., 0.]]; rec.log("segments", &rerun::LineStrips2D::new(points.chunks(2)))?; - // Log an extra rect to set the view bounds - rec.log( - "bounds", - &rerun::Boxes2D::from_centers_and_sizes([(3.0, 0.0)], [(8.0, 6.0)]), - )?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/docs/snippets/all/line_strip2d_batch.cpp b/docs/snippets/all/line_strip2d_batch.cpp index 91508627b7a6..9df91de80c46 100644 --- a/docs/snippets/all/line_strip2d_batch.cpp +++ b/docs/snippets/all/line_strip2d_batch.cpp @@ -19,6 +19,5 @@ int main() { .with_labels({"one strip here", "and one strip there"}) ); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_centers_and_sizes({{3.0f, 1.5f}}, {{8.0f, 9.0f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/line_strip2d_batch.py b/docs/snippets/all/line_strip2d_batch.py index a71c43f0bbb7..7e72f53e105c 100644 --- a/docs/snippets/all/line_strip2d_batch.py +++ b/docs/snippets/all/line_strip2d_batch.py @@ -1,6 +1,7 @@ """Log a batch of 2D line strips.""" import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d_batch", spawn=True) @@ -17,5 +18,5 @@ ), ) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(centers=[3, 1.5], half_sizes=[4.0, 4.5])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 6]))) diff --git a/docs/snippets/all/line_strip2d_batch.rs b/docs/snippets/all/line_strip2d_batch.rs index d44120ae1473..bb0b27ab793a 100644 --- a/docs/snippets/all/line_strip2d_batch.rs +++ b/docs/snippets/all/line_strip2d_batch.rs @@ -14,11 +14,7 @@ fn main() -> Result<(), Box> { .with_labels(["one strip here", "and one strip there"]), )?; - // Log an extra rect to set the view bounds - rec.log( - "bounds", - &rerun::Boxes2D::from_centers_and_sizes([(3.0, 1.5)], [(8.0, 9.0)]), - )?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/docs/snippets/all/line_strip2d_simple.cpp b/docs/snippets/all/line_strip2d_simple.cpp index 8a5d6faa357e..c58ed459da44 100644 --- a/docs/snippets/all/line_strip2d_simple.cpp +++ b/docs/snippets/all/line_strip2d_simple.cpp @@ -9,6 +9,5 @@ int main() { const auto strip = rerun::LineStrip2D({{0.f, 0.f}, {2.f, 1.f}, {4.f, -1.f}, {6.f, 0.f}}); rec.log("strip", rerun::LineStrips2D(strip)); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_centers_and_sizes({{3.0f, 0.0f}}, {{8.0f, 6.0f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/line_strip2d_simple.py b/docs/snippets/all/line_strip2d_simple.py index 67ca4296e80a..368e50662b5a 100644 --- a/docs/snippets/all/line_strip2d_simple.py +++ b/docs/snippets/all/line_strip2d_simple.py @@ -1,6 +1,7 @@ """Log a simple line strip.""" import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d", spawn=True) @@ -9,5 +10,5 @@ rr.LineStrips2D([[[0, 0], [2, 1], [4, -1], [6, 0]]]), ) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(centers=[3, 0], half_sizes=[4, 3])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 3]))) diff --git a/docs/snippets/all/line_strip2d_simple.rs b/docs/snippets/all/line_strip2d_simple.rs index 6ddd67027d67..1a80c2d218ac 100644 --- a/docs/snippets/all/line_strip2d_simple.rs +++ b/docs/snippets/all/line_strip2d_simple.rs @@ -6,11 +6,7 @@ fn main() -> Result<(), Box> { let points = [[0., 0.], [2., 1.], [4., -1.], [6., 0.]]; rec.log("strip", &rerun::LineStrips2D::new([points]))?; - // Log an extra rect to set the view bounds - rec.log( - "bounds", - &rerun::Boxes2D::from_centers_and_sizes([(3., 0.)], [(8., 6.)]), - )?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/docs/snippets/all/point2d_random.cpp b/docs/snippets/all/point2d_random.cpp index 5199256967a1..26d74f7119d2 100644 --- a/docs/snippets/all/point2d_random.cpp +++ b/docs/snippets/all/point2d_random.cpp @@ -33,6 +33,5 @@ int main() { rec.log("random", rerun::Points2D(points2d).with_colors(colors).with_radii(radii)); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_half_sizes({{4.0f, 3.0f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/point2d_random.py b/docs/snippets/all/point2d_random.py index f4c4fb423be6..fe100265e81a 100644 --- a/docs/snippets/all/point2d_random.py +++ b/docs/snippets/all/point2d_random.py @@ -1,6 +1,7 @@ """Log some random points with color and radii.""" import rerun as rr +import rerun.blueprint as rrb from numpy.random import default_rng rr.init("rerun_example_points2d_random", spawn=True) @@ -12,5 +13,5 @@ rr.log("random", rr.Points2D(positions, colors=colors, radii=radii)) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(half_sizes=[4, 3])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-4, -4], max=[4, 4]))) diff --git a/docs/snippets/all/point2d_random.rs b/docs/snippets/all/point2d_random.rs index 62d2150feae6..d1d77d601172 100644 --- a/docs/snippets/all/point2d_random.rs +++ b/docs/snippets/all/point2d_random.rs @@ -15,8 +15,7 @@ fn main() -> Result<(), Box> { .with_radii((0..10).map(|_| rng.gen::())), )?; - // Log an extra rect to set the view bounds - rec.log("bounds", &rerun::Boxes2D::from_half_sizes([(4., 3.)]))?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/docs/snippets/all/point2d_simple.cpp b/docs/snippets/all/point2d_simple.cpp index 05ecab38b3db..62cc7389c910 100644 --- a/docs/snippets/all/point2d_simple.cpp +++ b/docs/snippets/all/point2d_simple.cpp @@ -8,6 +8,5 @@ int main() { rec.log("points", rerun::Points2D({{0.0f, 0.0f}, {1.0f, 1.0f}})); - // Log an extra rect to set the view bounds - rec.log("bounds", rerun::Boxes2D::from_half_sizes({{2.0f, 1.5f}})); + // TODO(#5520): log VisualBounds } diff --git a/docs/snippets/all/point2d_simple.py b/docs/snippets/all/point2d_simple.py index 86d791ee0675..569e4ab72271 100644 --- a/docs/snippets/all/point2d_simple.py +++ b/docs/snippets/all/point2d_simple.py @@ -1,10 +1,11 @@ """Log some very simple points.""" import rerun as rr +import rerun.blueprint as rrb rr.init("rerun_example_points2d", spawn=True) rr.log("points", rr.Points2D([[0, 0], [1, 1]])) -# Log an extra rect to set the view bounds -rr.log("bounds", rr.Boxes2D(half_sizes=[2, 1.5])) +# Set view bounds: +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -1], max=[2, 2]))) diff --git a/docs/snippets/all/point2d_simple.rs b/docs/snippets/all/point2d_simple.rs index 114027c4f3ed..3b21307e7c31 100644 --- a/docs/snippets/all/point2d_simple.rs +++ b/docs/snippets/all/point2d_simple.rs @@ -5,8 +5,7 @@ fn main() -> Result<(), Box> { rec.log("points", &rerun::Points2D::new([(0.0, 0.0), (1.0, 1.0)]))?; - // Log an extra rect to set the view bounds - rec.log("bounds", &rerun::Boxes2D::from_half_sizes([(2.0, 1.5)]))?; + // TODO(#5521): log VisualBounds Ok(()) } diff --git a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp index 70cc3bf45f9f..8742f92b6cfc 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes2d.hpp @@ -37,9 +37,6 @@ namespace rerun::archetypes { /// rec.spawn().exit_on_failure(); /// /// rec.log("simple", rerun::Boxes2D::from_mins_and_sizes({{-1.f, -1.f}}, {{2.f, 2.f}})); - /// - /// // Log an extra rect to set the view bounds - /// rec.log("bounds", rerun::Boxes2D::from_sizes({{4.f, 3.f}})); /// } /// ``` struct Boxes2D { diff --git a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp index ea7590b061ef..a6b4f5e6b239 100644 --- a/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/line_strips2d.hpp @@ -48,8 +48,7 @@ namespace rerun::archetypes { /// .with_labels({"one strip here", "and one strip there"}) /// ); /// - /// // Log an extra rect to set the view bounds - /// rec.log("bounds", rerun::Boxes2D::from_centers_and_sizes({{3.0f, 1.5f}}, {{8.0f, 9.0f}})); + /// // TODO(#5520): log VisualBounds /// } /// ``` struct LineStrips2D { diff --git a/rerun_cpp/src/rerun/archetypes/points2d.hpp b/rerun_cpp/src/rerun/archetypes/points2d.hpp index 536d83b42686..171718d731f3 100644 --- a/rerun_cpp/src/rerun/archetypes/points2d.hpp +++ b/rerun_cpp/src/rerun/archetypes/points2d.hpp @@ -63,8 +63,7 @@ namespace rerun::archetypes { /// /// rec.log("random", rerun::Points2D(points2d).with_colors(colors).with_radii(radii)); /// - /// // Log an extra rect to set the view bounds - /// rec.log("bounds", rerun::Boxes2D::from_half_sizes({{4.0f, 3.0f}})); + /// // TODO(#5520): log VisualBounds /// } /// ``` struct Points2D { diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index 52de82f4046c..b9d8de9e0b21 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -10,3 +10,4 @@ #include "blueprint/archetypes/space_view_blueprint.hpp" #include "blueprint/archetypes/space_view_contents.hpp" #include "blueprint/archetypes/viewport_blueprint.hpp" +#include "blueprint/archetypes/visual_bounds.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index 70303c75a9ef..5b5e203daeab 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -17,3 +17,5 @@ space_view_contents.cpp linguist-generated=true space_view_contents.hpp linguist-generated=true viewport_blueprint.cpp linguist-generated=true viewport_blueprint.hpp linguist-generated=true +visual_bounds.cpp linguist-generated=true +visual_bounds.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp new file mode 100644 index 000000000000..575ab5c11190 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp @@ -0,0 +1,33 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs". + +#include "visual_bounds.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const blueprint::archetypes::VisualBounds& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(2); + + if (archetype.visual_bounds.has_value()) { + auto result = DataCell::from_loggable(archetype.visual_bounds.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = VisualBounds::IndicatorComponent(); + auto result = DataCell::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp new file mode 100644 index 000000000000..c9c88725f054 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp @@ -0,0 +1,64 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs". + +#pragma once + +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../components/aabb2d.hpp" +#include "../../data_cell.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Controls the visual bounds of a 2D space view. + struct VisualBounds { + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + std::optional visual_bounds; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.VisualBoundsIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + VisualBounds() = default; + VisualBounds(VisualBounds&& other) = default; + + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + VisualBounds with_visual_bounds(rerun::components::AABB2D _visual_bounds) && { + visual_bounds = std::move(_visual_bounds); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::VisualBounds& archetype + ); + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/components.hpp b/rerun_cpp/src/rerun/components.hpp index 02dcde49398c..4e818c0b9b78 100644 --- a/rerun_cpp/src/rerun/components.hpp +++ b/rerun_cpp/src/rerun/components.hpp @@ -2,6 +2,7 @@ #pragma once +#include "components/aabb2d.hpp" #include "components/annotation_context.hpp" #include "components/blob.hpp" #include "components/class_id.hpp" diff --git a/rerun_cpp/src/rerun/components/.gitattributes b/rerun_cpp/src/rerun/components/.gitattributes index 275437bb55f7..1bfb2e511343 100644 --- a/rerun_cpp/src/rerun/components/.gitattributes +++ b/rerun_cpp/src/rerun/components/.gitattributes @@ -1,6 +1,7 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.hpp linguist-generated=true annotation_context.cpp linguist-generated=true annotation_context.hpp linguist-generated=true blob.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/aabb2d.hpp b/rerun_cpp/src/rerun/components/aabb2d.hpp new file mode 100644 index 000000000000..07d00176a8b2 --- /dev/null +++ b/rerun_cpp/src/rerun/components/aabb2d.hpp @@ -0,0 +1,54 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". + +#pragma once + +#include "../datatypes/aabb2d.hpp" +#include "../result.hpp" + +#include +#include + +namespace rerun::components { + /// **Component**: An Axis-Aligned Bounding Box in 2D space. + struct AABB2D { + rerun::datatypes::AABB2D aabb; + + public: + AABB2D() = default; + + AABB2D(rerun::datatypes::AABB2D aabb_) : aabb(aabb_) {} + + AABB2D& operator=(rerun::datatypes::AABB2D aabb_) { + aabb = aabb_; + return *this; + } + + /// Cast to the underlying AABB2D datatype + operator rerun::datatypes::AABB2D() const { + return aabb; + } + }; +} // namespace rerun::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::AABB2D) == sizeof(components::AABB2D)); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.components.AABB2D"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::components::AABB2D` into an arrow array. + static Result> to_arrow( + const components::AABB2D* instances, size_t num_instances + ) { + return Loggable::to_arrow(&instances->aabb, num_instances); + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 6c5f01a1c546..7b47facd6c3e 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -2,6 +2,7 @@ #pragma once +#include "datatypes/aabb2d.hpp" #include "datatypes/angle.hpp" #include "datatypes/annotation_info.hpp" #include "datatypes/bool.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 108c39703f4c..34f722d5efa0 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -1,6 +1,8 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true +aabb2d.cpp linguist-generated=true +aabb2d.hpp linguist-generated=true angle.cpp linguist-generated=true angle.hpp linguist-generated=true annotation_info.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.cpp b/rerun_cpp/src/rerun/datatypes/aabb2d.cpp new file mode 100644 index 000000000000..d960e1a1516d --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/aabb2d.cpp @@ -0,0 +1,83 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". + +#include "aabb2d.hpp" + +#include "vec2d.hpp" + +#include +#include + +namespace rerun::datatypes {} + +namespace rerun { + const std::shared_ptr& Loggable::arrow_datatype() { + static const auto datatype = arrow::struct_({ + arrow::field("min", Loggable::arrow_datatype(), false), + arrow::field("max", Loggable::arrow_datatype(), false), + }); + return datatype; + } + + Result> Loggable::to_arrow( + const datatypes::AABB2D* instances, size_t num_instances + ) { + // TODO(andreas): Allow configuring the memory pool. + arrow::MemoryPool* pool = arrow::default_memory_pool(); + auto datatype = arrow_datatype(); + + ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) + if (instances && num_instances > 0) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); + } + std::shared_ptr array; + ARROW_RETURN_NOT_OK(builder->Finish(&array)); + return array; + } + + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const datatypes::AABB2D* elements, size_t num_elements + ) { + if (builder == nullptr) { + return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); + } + if (elements == nullptr) { + return rerun::Error( + ErrorCode::UnexpectedNullArgument, + "Cannot serialize null pointer to arrow array." + ); + } + + { + auto field_builder = + static_cast(builder->field_builder(0)); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + field_builder, + &elements[elem_idx].min, + 1 + )); + } + } + { + auto field_builder = + static_cast(builder->field_builder(1)); + ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); + for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + field_builder, + &elements[elem_idx].max, + 1 + )); + } + } + ARROW_RETURN_NOT_OK(builder->AppendValues(static_cast(num_elements), nullptr)); + + return Error::ok(); + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.hpp b/rerun_cpp/src/rerun/datatypes/aabb2d.hpp new file mode 100644 index 000000000000..41a751bfed12 --- /dev/null +++ b/rerun_cpp/src/rerun/datatypes/aabb2d.hpp @@ -0,0 +1,54 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". + +#pragma once + +#include "../result.hpp" +#include "vec2d.hpp" + +#include +#include + +namespace arrow { + class Array; + class DataType; + class StructBuilder; +} // namespace arrow + +namespace rerun::datatypes { + /// **Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. + struct AABB2D { + /// The minimum bounds; usually left-top corner. + rerun::datatypes::Vec2D min; + + /// The maximum bounds; usually right-bottom corner. + rerun::datatypes::Vec2D max; + + public: + AABB2D() = default; + }; +} // namespace rerun::datatypes + +namespace rerun { + template + struct Loggable; + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.AABB2D"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype(); + + /// Serializes an array of `rerun::datatypes::AABB2D` into an arrow array. + static Result> to_arrow( + const datatypes::AABB2D* instances, size_t num_instances + ); + + /// Fills an arrow array builder with an array of this type. + static rerun::Error fill_arrow_array_builder( + arrow::StructBuilder* builder, const datatypes::AABB2D* elements, size_t num_elements + ); + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py index e0cf9418dc8d..752998292eb8 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py @@ -28,9 +28,6 @@ class Boxes2D(Boxes2DExt, Archetype): rr.init("rerun_example_box2d", spawn=True) rr.log("simple", rr.Boxes2D(mins=[-1, -1], sizes=[2, 2])) - - # Log an extra rect to set the view bounds - rr.log("bounds", rr.Boxes2D(sizes=[4.0, 3.0])) ```
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py index 735490af70d9..f1995404a11a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py @@ -26,6 +26,7 @@ class LineStrips2D(Archetype): ### `line_strip2d_batch`: ```python import rerun as rr + import rerun.blueprint as rrb rr.init("rerun_example_line_strip2d_batch", spawn=True) @@ -42,8 +43,8 @@ class LineStrips2D(Archetype): ), ) - # Log an extra rect to set the view bounds - rr.log("bounds", rr.Boxes2D(centers=[3, 1.5], half_sizes=[4.0, 4.5])) + # Set view bounds: + rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 6]))) ```
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py index e3348ea916b7..25bcaaaef58c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py @@ -24,6 +24,7 @@ class Points2D(Points2DExt, Archetype): ### Randomly distributed 2D points with varying color and radius: ```python import rerun as rr + import rerun.blueprint as rrb from numpy.random import default_rng rr.init("rerun_example_points2d_random", spawn=True) @@ -35,8 +36,8 @@ class Points2D(Points2DExt, Archetype): rr.log("random", rr.Points2D(positions, colors=colors, radii=radii)) - # Log an extra rect to set the view bounds - rr.log("bounds", rr.Boxes2D(half_sizes=[4, 3])) + # Set view bounds: + rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-4, -4], max=[4, 4]))) ```
diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 507e7b007d05..8a2e7f0e2db0 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -16,6 +16,7 @@ Background, PlotLegend, ScalarAxis, + VisualBounds, ) from .components import ( BackgroundKind, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index e7b8aeea825b..4b50b7734d14 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -10,3 +10,4 @@ scalar_axis.py linguist-generated=true space_view_blueprint.py linguist-generated=true space_view_contents.py linguist-generated=true viewport_blueprint.py linguist-generated=true +visual_bounds.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py index 79504acb3574..45f5321955ab 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -10,6 +10,7 @@ from .space_view_blueprint import SpaceViewBlueprint from .space_view_contents import SpaceViewContents from .viewport_blueprint import ViewportBlueprint +from .visual_bounds import VisualBounds __all__ = [ "Background", @@ -20,4 +21,5 @@ "SpaceViewBlueprint", "SpaceViewContents", "ViewportBlueprint", + "VisualBounds", ] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py new file mode 100644 index 000000000000..c611cd889a5e --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py @@ -0,0 +1,49 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs". + +# You can extend this class by creating a "VisualBoundsExt" class in "visual_bounds_ext.py". + +from __future__ import annotations + +from attrs import define, field + +from ... import components +from ..._baseclasses import Archetype +from .visual_bounds_ext import VisualBoundsExt + +__all__ = ["VisualBounds"] + + +@define(str=False, repr=False, init=False) +class VisualBounds(VisualBoundsExt, Archetype): + """**Archetype**: Controls the visual bounds of a 2D space view.""" + + # __init__ can be found in visual_bounds_ext.py + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + visual_bounds=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> VisualBounds: + """Produce an empty VisualBounds, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + visual_bounds: components.AABB2DBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=components.AABB2DBatch._optional, # type: ignore[misc] + ) + # The visible parts of a 2D space view, in the coordinate space of the scene. + # + # Everything within these bounds are guaranteed to be visible. + # Somethings outside of these bounds may also be visible due to letterboxing. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py new file mode 100644 index 000000000000..9124871c0612 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +from typing import Any + +from ... import components, datatypes +from ...error_utils import catch_and_log_exceptions + + +class VisualBoundsExt: + """Extension for [VisualBounds][rerun.blueprint.archetypes.VisualBounds].""" + + def __init__( + self: Any, + *, + min: datatypes.Vec2DLike, + max: datatypes.Vec2DLike, + ): + """ + Create a new instance of the VisualBounds archetype. + + Parameters + ---------- + min: + The minimum point of the visible parts of a 2D space view, in the coordinate space of the scene. + Usually the left-top corner. + max: + The maximum point of the visible parts of a 2D space view, in the coordinate space of the scene. + Usually the right-bottom corner. + + """ + + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(visual_bounds=components.AABB2D(min=min, max=max)) + return + self.__attrs_clear__() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py index ae31233af77c..fa065d25be70 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py @@ -28,6 +28,7 @@ def __init__( | datatypes.Rgba32Like | blueprint_components.BackgroundKindLike | None = None, + visual_bounds: blueprint_archetypes.VisualBounds | None = None, ) -> None: """ Construct a blueprint for a new Spatial2DView view. @@ -49,6 +50,11 @@ def __init__( Defaults to true if not specified. background: Configuration for the background of the space view. + visual_bounds: + The visible parts of the scene, in the coordinate space of the scene. + + Everything within these bounds are guaranteed to be visible. + Somethings outside of these bounds may also be visible due to letterboxing. """ @@ -58,6 +64,11 @@ def __init__( background = blueprint_archetypes.Background(background) properties["Background"] = background + if visual_bounds is not None: + if not isinstance(visual_bounds, blueprint_archetypes.VisualBounds): + visual_bounds = blueprint_archetypes.VisualBounds(visual_bounds) + properties["VisualBounds"] = visual_bounds + super().__init__( class_identifier="2D", origin=origin, contents=contents, name=name, visible=visible, properties=properties ) diff --git a/rerun_py/rerun_sdk/rerun/components/.gitattributes b/rerun_py/rerun_sdk/rerun/components/.gitattributes index 12b4a9826e3c..f7f22c699975 100644 --- a/rerun_py/rerun_sdk/rerun/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/components/.gitattributes @@ -2,6 +2,7 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true +aabb2d.py linguist-generated=true annotation_context.py linguist-generated=true blob.py linguist-generated=true class_id.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/components/__init__.py b/rerun_py/rerun_sdk/rerun/components/__init__.py index 2710c971bed2..0c7615bd6e34 100644 --- a/rerun_py/rerun_sdk/rerun/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/components/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .aabb2d import AABB2D, AABB2DBatch, AABB2DType from .annotation_context import ( AnnotationContext, AnnotationContextArrayLike, @@ -79,6 +80,9 @@ ) __all__ = [ + "AABB2D", + "AABB2DBatch", + "AABB2DType", "AnnotationContext", "AnnotationContextArrayLike", "AnnotationContextBatch", diff --git a/rerun_py/rerun_sdk/rerun/components/aabb2d.py b/rerun_py/rerun_sdk/rerun/components/aabb2d.py new file mode 100644 index 000000000000..16419767704c --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/aabb2d.py @@ -0,0 +1,29 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". + +# You can extend this class by creating a "AABB2DExt" class in "aabb2d_ext.py". + +from __future__ import annotations + +from .. import datatypes +from .._baseclasses import ComponentBatchMixin +from .aabb2d_ext import AABB2DExt + +__all__ = ["AABB2D", "AABB2DBatch", "AABB2DType"] + + +class AABB2D(AABB2DExt, datatypes.AABB2D): + """**Component**: An Axis-Aligned Bounding Box in 2D space.""" + + # __init__ can be found in aabb2d_ext.py + + # Note: there are no fields here because AABB2D delegates to datatypes.AABB2D + pass + + +class AABB2DType(datatypes.AABB2DType): + _TYPE_NAME: str = "rerun.components.AABB2D" + + +class AABB2DBatch(datatypes.AABB2DBatch, ComponentBatchMixin): + _ARROW_TYPE = AABB2DType() diff --git a/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py b/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py new file mode 100644 index 000000000000..0248277a3262 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from typing import Any + +from ..datatypes import Vec2DLike + + +class AABB2DExt: + """Extension for [AABB2D][rerun.components.AABB2D].""" + + def __init__( + self: Any, + *, + min: Vec2DLike, + max: Vec2DLike, + ): + """ + Create a new instance of the AABB2D component. + + Parameters + ---------- + min: + The minimum point of the visible parts of a 2D space view, in the coordinate space of the scene. + Usually the left-top corner. + max: + The maximum point of the visible parts of a 2D space view, in the coordinate space of the scene. + Usually the right-bottom corner. + + """ + + self.__attrs_init__(min=min, max=max) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index d5a5eadf37f6..9a04afcec6f7 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -2,6 +2,7 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true +aabb2d.py linguist-generated=true angle.py linguist-generated=true annotation_info.py linguist-generated=true bool.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index 58f639584e8b..717aac102f48 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +from .aabb2d import AABB2D, AABB2DArrayLike, AABB2DBatch, AABB2DLike, AABB2DType from .angle import Angle, AngleArrayLike, AngleBatch, AngleLike, AngleType from .annotation_info import ( AnnotationInfo, @@ -89,6 +90,11 @@ from .vec4d import Vec4D, Vec4DArrayLike, Vec4DBatch, Vec4DLike, Vec4DType __all__ = [ + "AABB2D", + "AABB2DArrayLike", + "AABB2DBatch", + "AABB2DLike", + "AABB2DType", "Angle", "AngleArrayLike", "AngleBatch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py new file mode 100644 index 000000000000..df63dfc4b550 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py @@ -0,0 +1,101 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". + +# You can extend this class by creating a "AABB2DExt" class in "aabb2d_ext.py". + +from __future__ import annotations + +from typing import Any, Sequence, Union + +import pyarrow as pa +from attrs import define, field + +from .. import datatypes +from .._baseclasses import BaseBatch, BaseExtensionType +from .aabb2d_ext import AABB2DExt + +__all__ = ["AABB2D", "AABB2DArrayLike", "AABB2DBatch", "AABB2DLike", "AABB2DType"] + + +def _aabb2d__min__special_field_converter_override(x: datatypes.Vec2DLike) -> datatypes.Vec2D: + if isinstance(x, datatypes.Vec2D): + return x + else: + return datatypes.Vec2D(x) + + +def _aabb2d__max__special_field_converter_override(x: datatypes.Vec2DLike) -> datatypes.Vec2D: + if isinstance(x, datatypes.Vec2D): + return x + else: + return datatypes.Vec2D(x) + + +@define(init=False) +class AABB2D(AABB2DExt): + """**Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners.""" + + def __init__(self: Any, min: datatypes.Vec2DLike, max: datatypes.Vec2DLike): + """ + Create a new instance of the AABB2D datatype. + + Parameters + ---------- + min: + The minimum bounds; usually left-top corner. + max: + The maximum bounds; usually right-bottom corner. + + """ + + # You can define your own __init__ function as a member of AABB2DExt in aabb2d_ext.py + self.__attrs_init__(min=min, max=max) + + min: datatypes.Vec2D = field(converter=_aabb2d__min__special_field_converter_override) + # The minimum bounds; usually left-top corner. + # + # (Docstring intentionally commented out to hide this field from the docs) + + max: datatypes.Vec2D = field(converter=_aabb2d__max__special_field_converter_override) + # The maximum bounds; usually right-bottom corner. + # + # (Docstring intentionally commented out to hide this field from the docs) + + +AABB2DLike = AABB2D +AABB2DArrayLike = Union[ + AABB2D, + Sequence[AABB2DLike], +] + + +class AABB2DType(BaseExtensionType): + _TYPE_NAME: str = "rerun.datatypes.AABB2D" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.struct([ + pa.field( + "min", + pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 2), + nullable=False, + metadata={}, + ), + pa.field( + "max", + pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 2), + nullable=False, + metadata={}, + ), + ]), + self._TYPE_NAME, + ) + + +class AABB2DBatch(BaseBatch[AABB2DArrayLike]): + _ARROW_TYPE = AABB2DType() + + @staticmethod + def _native_to_pa_array(data: AABB2DArrayLike, data_type: pa.DataType) -> pa.Array: + return AABB2DExt.native_to_pa_array_override(data, data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py new file mode 100644 index 000000000000..0e3cc2db4259 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import pyarrow as pa + +if TYPE_CHECKING: + from . import AABB2DArrayLike + + +class AABB2DExt: + """Extension for [AABB2D][rerun.datatypes.AABB2D].""" + + @staticmethod + def native_to_pa_array_override(data: AABB2DArrayLike, data_type: pa.DataType) -> pa.Array: + from . import AABB2D, Vec2DBatch + + if isinstance(data, AABB2D): + data = [data] + + return pa.StructArray.from_arrays( + [ + Vec2DBatch._native_to_pa_array([aabb.min for aabb in data], data_type["min"].type), + Vec2DBatch._native_to_pa_array([aabb.max for aabb in data], data_type["min"].type), + ], + fields=list(data_type), + ) From 2faaf68669dc5a3ce032337d21292bfb25c10fe5 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 18:23:35 +0200 Subject: [PATCH 386/508] Refactor codegen of python arrow serialization (#6155) ### What This lets me work on this in parallel, while CI does its bs ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) - [PR Build Summary](https://build.rerun.io/pr/6155) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../src/codegen/python/mod.rs | 181 ++++++++++-------- .../components/entity_properties_component.py | 4 +- .../blueprint/datatypes/visible_time_range.py | 4 +- .../datatypes/visible_time_range_boundary.py | 4 +- .../rerun/components/visualizer_overrides.py | 4 +- rerun_py/rerun_sdk/rerun/datatypes/float32.py | 4 +- rerun_py/rerun_sdk/rerun/datatypes/scale3d.py | 4 +- .../rerun/datatypes/tensor_buffer.py | 4 +- .../rerun/datatypes/tensor_dimension.py | 4 +- .../rerun_sdk/rerun/datatypes/time_int.py | 4 +- .../rerun/datatypes/translation_and_mat3x3.py | 4 +- .../datatypes/translation_rotation_scale3d.py | 4 +- rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py | 4 +- rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py | 4 +- rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py | 4 +- .../test_types/components/affix_fuzzer10.py | 4 +- .../test_types/components/affix_fuzzer11.py | 4 +- .../test_types/components/affix_fuzzer12.py | 4 +- .../test_types/components/affix_fuzzer13.py | 4 +- .../test_types/components/affix_fuzzer16.py | 4 +- .../test_types/components/affix_fuzzer17.py | 4 +- .../test_types/components/affix_fuzzer18.py | 4 +- .../test_types/components/affix_fuzzer7.py | 4 +- .../test_types/components/affix_fuzzer8.py | 4 +- .../test_types/components/affix_fuzzer9.py | 4 +- .../test_types/datatypes/affix_fuzzer1.py | 4 +- .../test_types/datatypes/affix_fuzzer2.py | 4 +- .../test_types/datatypes/affix_fuzzer20.py | 4 +- .../test_types/datatypes/affix_fuzzer21.py | 4 +- .../test_types/datatypes/affix_fuzzer22.py | 4 +- .../test_types/datatypes/affix_fuzzer3.py | 4 +- .../test_types/datatypes/affix_fuzzer4.py | 4 +- .../test_types/datatypes/affix_fuzzer5.py | 4 +- .../test_types/datatypes/flattened_scalar.py | 4 +- .../datatypes/primitive_component.py | 4 +- .../test_types/datatypes/string_component.py | 4 +- 36 files changed, 207 insertions(+), 114 deletions(-) diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index fc606ea0dcc4..28d1c49dfeec 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -778,7 +778,7 @@ fn code_for_struct( ObjectKind::Datatype | ObjectKind::Component => { code.push_indented( 0, - quote_arrow_support_from_obj(arrow_registry, ext_class, objects, obj, None), + quote_arrow_support_from_obj(reporter, arrow_registry, ext_class, objects, obj), 1, ); } @@ -860,63 +860,6 @@ fn code_for_enum( 2, ); - // Generate case-insensitive string-to-enum conversion: - let match_names = obj - .fields - .iter() - .map(|f| { - let newline = '\n'; - let variant = f.pascal_case_name(); - let lowercase_variant = variant.to_lowercase(); - format!( - r#"elif value.lower() == "{lowercase_variant}":{newline} types.append({name}.{variant}.value)"# - ) - }) - .format("\n") - .to_string(); - - let match_names = indent::indent_all_by(8, match_names); - - let num_variants = obj.fields.len(); - - let native_to_pa_array_impl = unindent(&format!( - r##" -if isinstance(data, ({name}, int, str)): - data = [data] - -types: list[int] = [] - -for value in data: - if value is None: - types.append(0) - elif isinstance(value, {name}): - types.append(value.value) # Actual enum value - elif isinstance(value, int): - types.append(value) # By number - elif isinstance(value, str): - if hasattr({name}, value): - types.append({name}[value].value) # fast path -{match_names} - else: - raise ValueError(f"Unknown {name} kind: {{value}}") - else: - raise ValueError(f"Unknown {name} kind: {{value}}") - -buffers = [ - None, - pa.array(types, type=pa.int8()).buffers()[1], -] -children = (1 + {num_variants}) * [pa.nulls(len(data))] - -return pa.UnionArray.from_buffers( - type=data_type, - length=len(data), - buffers=buffers, - children=children, -) - "## - )); - match obj.kind { ObjectKind::Archetype => { reporter.error(&obj.virtpath, &obj.fqname, "An archetype cannot be an enum"); @@ -924,13 +867,7 @@ return pa.UnionArray.from_buffers( ObjectKind::Component | ObjectKind::Datatype => { code.push_indented( 0, - quote_arrow_support_from_obj( - arrow_registry, - ext_class, - objects, - obj, - Some(native_to_pa_array_impl), - ), + quote_arrow_support_from_obj(reporter, arrow_registry, ext_class, objects, obj), 1, ); } @@ -1090,7 +1027,7 @@ fn code_for_union( ObjectKind::Datatype => { code.push_indented( 0, - quote_arrow_support_from_obj(arrow_registry, ext_class, objects, obj, None), + quote_arrow_support_from_obj(reporter, arrow_registry, ext_class, objects, obj), 1, ); } @@ -1762,11 +1699,11 @@ fn quote_type_from_element_type(typ: &ElementType) -> String { /// Generated for Components using native types and Datatypes. Components using a Datatype instead /// delegate to the Datatype's arrow support. fn quote_arrow_support_from_obj( + reporter: &Reporter, arrow_registry: &ArrowRegistry, ext_class: &ExtensionClass, objects: &Objects, obj: &Object, - native_to_pa_array_impl: Option, ) -> String { let Object { fqname, name, .. } = obj; @@ -1807,19 +1744,32 @@ fn quote_arrow_support_from_obj( let extension_batch = format!("{name}Batch"); let extension_type = format!("{name}Type"); - let native_to_pa_array_impl = native_to_pa_array_impl.unwrap_or_else(|| { - if ext_class.has_native_to_pa_array { - format!( - "return {}.{NATIVE_TO_PA_ARRAY_METHOD}(data, data_type)", - ext_class.name - ) - } else { - format!( - "raise NotImplementedError # You need to implement {NATIVE_TO_PA_ARRAY_METHOD} in {}", - ext_class.file_name - ) + let native_to_pa_array_impl = match quote_arrow_serialization(reporter, objects, obj) { + Ok(automatic_arrow_serialization) => { + if ext_class.has_native_to_pa_array { + reporter.warn(&obj.virtpath, &obj.fqname, format!("No need to manually implement {NATIVE_TO_PA_ARRAY_METHOD} in {} - we can autogenerate the code for this", ext_class.file_name)); + format!( + "return {}.{NATIVE_TO_PA_ARRAY_METHOD}(data, data_type)", + ext_class.name + ) + } else { + automatic_arrow_serialization + } + } + Err(err) => { + if ext_class.has_native_to_pa_array { + format!( + "return {}.{NATIVE_TO_PA_ARRAY_METHOD}(data, data_type)", + ext_class.name + ) + } else { + format!( + r#"raise NotImplementedError("Arrow serialization of {name} not implemented: {err}") # You need to implement {NATIVE_TO_PA_ARRAY_METHOD} in {}"#, + ext_class.file_name + ) + } } - }); + }; let type_superclass_decl = if type_superclasses.is_empty() { String::new() @@ -1868,6 +1818,79 @@ fn quote_arrow_support_from_obj( } } +/// Only implemented for some cases. +fn quote_arrow_serialization( + _reporter: &Reporter, + _objects: &Objects, + obj: &Object, +) -> Result { + let Object { name, .. } = obj; + + match obj.class { + ObjectClass::Struct => Err("We lack codegen for arrow-serialization of structs".to_owned()), + + ObjectClass::Enum => { + // Generate case-insensitive string-to-enum conversion: + let match_names = obj + .fields + .iter() + .map(|f| { + let newline = '\n'; + let variant = f.pascal_case_name(); + let lowercase_variant = variant.to_lowercase(); + format!( + r#"elif value.lower() == "{lowercase_variant}":{newline} types.append({name}.{variant}.value)"# + ) + }) + .format("\n") + .to_string(); + + let match_names = indent::indent_all_by(8, match_names); + let num_variants = obj.fields.len(); + + Ok(unindent(&format!( + r##" +if isinstance(data, ({name}, int, str)): + data = [data] + +types: list[int] = [] + +for value in data: + if value is None: + types.append(0) + elif isinstance(value, {name}): + types.append(value.value) # Actual enum value + elif isinstance(value, int): + types.append(value) # By number + elif isinstance(value, str): + if hasattr({name}, value): + types.append({name}[value].value) # fast path +{match_names} + else: + raise ValueError(f"Unknown {name} kind: {{value}}") + else: + raise ValueError(f"Unknown {name} kind: {{value}}") + +buffers = [ + None, + pa.array(types, type=pa.int8()).buffers()[1], +] +children = (1 + {num_variants}) * [pa.nulls(len(data))] + +return pa.UnionArray.from_buffers( + type=data_type, + length=len(data), + buffers=buffers, + children=children, +) + "## + ))) + } + + ObjectClass::Union => Err("We lack codegen for arrow-serialization of unions".to_owned()), + } +} + fn quote_parameter_type_alias( arg_type_fqname: &str, class_fqname: &str, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py b/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py index c8263bc611ae..9b6a417f45f3 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py @@ -64,4 +64,6 @@ class EntityPropertiesComponentBatch(BaseBatch[EntityPropertiesComponentArrayLik @staticmethod def _native_to_pa_array(data: EntityPropertiesComponentArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in entity_properties_component_ext.py + raise NotImplementedError( + "Arrow serialization of EntityPropertiesComponent not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in entity_properties_component_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py index 8f1561a7bbbe..dfafa46aa74b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py @@ -123,4 +123,6 @@ class VisibleTimeRangeBatch(BaseBatch[VisibleTimeRangeArrayLike]): @staticmethod def _native_to_pa_array(data: VisibleTimeRangeArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in visible_time_range_ext.py + raise NotImplementedError( + "Arrow serialization of VisibleTimeRange not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in visible_time_range_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py index 6f5ffdfc9bd0..35a4a27e93c1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py @@ -97,4 +97,6 @@ class VisibleTimeRangeBoundaryBatch(BaseBatch[VisibleTimeRangeBoundaryArrayLike] @staticmethod def _native_to_pa_array(data: VisibleTimeRangeBoundaryArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in visible_time_range_boundary_ext.py + raise NotImplementedError( + "Arrow serialization of VisibleTimeRangeBoundary not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in visible_time_range_boundary_ext.py diff --git a/rerun_py/rerun_sdk/rerun/components/visualizer_overrides.py b/rerun_py/rerun_sdk/rerun/components/visualizer_overrides.py index 781cd19e960f..f454122cd377 100644 --- a/rerun_py/rerun_sdk/rerun/components/visualizer_overrides.py +++ b/rerun_py/rerun_sdk/rerun/components/visualizer_overrides.py @@ -55,4 +55,6 @@ class VisualizerOverridesBatch(BaseBatch[VisualizerOverridesArrayLike], Componen @staticmethod def _native_to_pa_array(data: VisualizerOverridesArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in visualizer_overrides_ext.py + raise NotImplementedError( + "Arrow serialization of VisualizerOverrides not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in visualizer_overrides_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/float32.py b/rerun_py/rerun_sdk/rerun/datatypes/float32.py index 77c62658ade1..42f3295448e1 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/float32.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/float32.py @@ -56,4 +56,6 @@ class Float32Batch(BaseBatch[Float32ArrayLike]): @staticmethod def _native_to_pa_array(data: Float32ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in float32_ext.py + raise NotImplementedError( + "Arrow serialization of Float32 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in float32_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/scale3d.py b/rerun_py/rerun_sdk/rerun/datatypes/scale3d.py index b07f31a7c611..5ace4e7e89e5 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/scale3d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/scale3d.py @@ -89,4 +89,6 @@ class Scale3DBatch(BaseBatch[Scale3DArrayLike]): @staticmethod def _native_to_pa_array(data: Scale3DArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in scale3d_ext.py + raise NotImplementedError( + "Arrow serialization of Scale3D not implemented: We lack codegen for arrow-serialization of unions" + ) # You need to implement native_to_pa_array_override in scale3d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py index 9e61d27392d9..b386bd98efd2 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_buffer.py @@ -284,4 +284,6 @@ class TensorBufferBatch(BaseBatch[TensorBufferArrayLike]): @staticmethod def _native_to_pa_array(data: TensorBufferArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in tensor_buffer_ext.py + raise NotImplementedError( + "Arrow serialization of TensorBuffer not implemented: We lack codegen for arrow-serialization of unions" + ) # You need to implement native_to_pa_array_override in tensor_buffer_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py index e7d11a6a585e..1173c34e4ee7 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py @@ -81,4 +81,6 @@ class TensorDimensionBatch(BaseBatch[TensorDimensionArrayLike]): @staticmethod def _native_to_pa_array(data: TensorDimensionArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in tensor_dimension_ext.py + raise NotImplementedError( + "Arrow serialization of TensorDimension not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in tensor_dimension_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/time_int.py b/rerun_py/rerun_sdk/rerun/datatypes/time_int.py index 56b224544a7c..0dbb7bc83cbf 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/time_int.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/time_int.py @@ -56,4 +56,6 @@ class TimeIntBatch(BaseBatch[TimeIntArrayLike]): @staticmethod def _native_to_pa_array(data: TimeIntArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in time_int_ext.py + raise NotImplementedError( + "Arrow serialization of TimeInt not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in time_int_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py index 16294b40c079..c9ed68e216b9 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py @@ -115,4 +115,6 @@ class TranslationAndMat3x3Batch(BaseBatch[TranslationAndMat3x3ArrayLike]): @staticmethod def _native_to_pa_array(data: TranslationAndMat3x3ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in translation_and_mat3x3_ext.py + raise NotImplementedError( + "Arrow serialization of TranslationAndMat3x3 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in translation_and_mat3x3_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py index 545d80e8ca43..76b41b14c0b5 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py @@ -165,4 +165,6 @@ class TranslationRotationScale3DBatch(BaseBatch[TranslationRotationScale3DArrayL @staticmethod def _native_to_pa_array(data: TranslationRotationScale3DArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in translation_rotation_scale3d_ext.py + raise NotImplementedError( + "Arrow serialization of TranslationRotationScale3D not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in translation_rotation_scale3d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py b/rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py index 781417bb7058..9e916d98c7ce 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py @@ -61,4 +61,6 @@ class UVec2DBatch(BaseBatch[UVec2DArrayLike]): @staticmethod def _native_to_pa_array(data: UVec2DArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in uvec2d_ext.py + raise NotImplementedError( + "Arrow serialization of UVec2D not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in uvec2d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py b/rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py index f028c7daf1c6..8add3e472532 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py @@ -61,4 +61,6 @@ class UVec3DBatch(BaseBatch[UVec3DArrayLike]): @staticmethod def _native_to_pa_array(data: UVec3DArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in uvec3d_ext.py + raise NotImplementedError( + "Arrow serialization of UVec3D not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in uvec3d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py b/rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py index ccefcd41216d..b36f3ff91b5c 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py @@ -61,4 +61,6 @@ class UVec4DBatch(BaseBatch[UVec4DArrayLike]): @staticmethod def _native_to_pa_array(data: UVec4DArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in uvec4d_ext.py + raise NotImplementedError( + "Arrow serialization of UVec4D not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in uvec4d_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer10.py b/rerun_py/tests/test_types/components/affix_fuzzer10.py index 80bbd1ebecc8..2e86a7ae8650 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer10.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer10.py @@ -47,4 +47,6 @@ class AffixFuzzer10Batch(BaseBatch[AffixFuzzer10ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer10ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer10_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer10 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer10_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer11.py b/rerun_py/tests/test_types/components/affix_fuzzer11.py index 432b3a9d277f..e7e04d5a1943 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer11.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer11.py @@ -55,4 +55,6 @@ class AffixFuzzer11Batch(BaseBatch[AffixFuzzer11ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer11ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer11_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer11 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer11_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer12.py b/rerun_py/tests/test_types/components/affix_fuzzer12.py index 93dc4c7d48b3..b27cc453a8c8 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer12.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer12.py @@ -46,4 +46,6 @@ class AffixFuzzer12Batch(BaseBatch[AffixFuzzer12ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer12ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer12_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer12 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer12_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer13.py b/rerun_py/tests/test_types/components/affix_fuzzer13.py index 9603d92b0d2a..2cdb8cd2bc3a 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer13.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer13.py @@ -46,4 +46,6 @@ class AffixFuzzer13Batch(BaseBatch[AffixFuzzer13ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer13ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer13_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer13 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer13_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer16.py b/rerun_py/tests/test_types/components/affix_fuzzer16.py index 817e55f94cf3..5b2ef055cc03 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer16.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer16.py @@ -110,4 +110,6 @@ class AffixFuzzer16Batch(BaseBatch[AffixFuzzer16ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer16ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer16_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer16 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer16_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer17.py b/rerun_py/tests/test_types/components/affix_fuzzer17.py index d80061aadac7..d7c0a364722a 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer17.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer17.py @@ -110,4 +110,6 @@ class AffixFuzzer17Batch(BaseBatch[AffixFuzzer17ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer17ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer17_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer17 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer17_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer18.py b/rerun_py/tests/test_types/components/affix_fuzzer18.py index 2a8fbe788308..feb7a017fd86 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer18.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer18.py @@ -324,4 +324,6 @@ class AffixFuzzer18Batch(BaseBatch[AffixFuzzer18ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer18ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer18_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer18 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer18_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer7.py b/rerun_py/tests/test_types/components/affix_fuzzer7.py index 13adb7102f3d..a3d9e174d717 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer7.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer7.py @@ -87,4 +87,6 @@ class AffixFuzzer7Batch(BaseBatch[AffixFuzzer7ArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: AffixFuzzer7ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer7_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer7 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer7_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer8.py b/rerun_py/tests/test_types/components/affix_fuzzer8.py index a96f67f8149f..6977c4fa66e5 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer8.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer8.py @@ -53,4 +53,6 @@ class AffixFuzzer8Batch(BaseBatch[AffixFuzzer8ArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: AffixFuzzer8ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer8_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer8 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer8_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer9.py b/rerun_py/tests/test_types/components/affix_fuzzer9.py index 7109834c7d1b..864d02790192 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer9.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer9.py @@ -47,4 +47,6 @@ class AffixFuzzer9Batch(BaseBatch[AffixFuzzer9ArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: AffixFuzzer9ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer9_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer9 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer9_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py index 7496d15d1773..3f5e154ec619 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py @@ -128,4 +128,6 @@ class AffixFuzzer1Batch(BaseBatch[AffixFuzzer1ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer1ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer1_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer1 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer1_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer2.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer2.py index c8d427cd9b6a..6329ce692720 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer2.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer2.py @@ -53,4 +53,6 @@ class AffixFuzzer2Batch(BaseBatch[AffixFuzzer2ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer2ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer2_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer2 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer2_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py index af092d58ba59..f05f3041f3ed 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py @@ -70,4 +70,6 @@ class AffixFuzzer20Batch(BaseBatch[AffixFuzzer20ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer20ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer20_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer20 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer20_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py index ab09b21a9bc8..d3484c6538e0 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py @@ -62,4 +62,6 @@ class AffixFuzzer21Batch(BaseBatch[AffixFuzzer21ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer21ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer21_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer21 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer21_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py index 6e732c2ce20e..6cc0f0819dfb 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py @@ -64,4 +64,6 @@ class AffixFuzzer22Batch(BaseBatch[AffixFuzzer22ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer22ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer22_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer22 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer22_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer3.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer3.py index 3030782c0d40..2ed039a59687 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer3.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer3.py @@ -137,4 +137,6 @@ class AffixFuzzer3Batch(BaseBatch[AffixFuzzer3ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer3ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer3_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer3 not implemented: We lack codegen for arrow-serialization of unions" + ) # You need to implement native_to_pa_array_override in affix_fuzzer3_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer4.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer4.py index 672729cd04b2..47e8ef7119db 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer4.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer4.py @@ -289,4 +289,6 @@ class AffixFuzzer4Batch(BaseBatch[AffixFuzzer4ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer4ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer4_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer4 not implemented: We lack codegen for arrow-serialization of unions" + ) # You need to implement native_to_pa_array_override in affix_fuzzer4_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py index 4bd517892ea4..25c760a252d0 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py @@ -337,4 +337,6 @@ class AffixFuzzer5Batch(BaseBatch[AffixFuzzer5ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer5ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in affix_fuzzer5_ext.py + raise NotImplementedError( + "Arrow serialization of AffixFuzzer5 not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in affix_fuzzer5_ext.py diff --git a/rerun_py/tests/test_types/datatypes/flattened_scalar.py b/rerun_py/tests/test_types/datatypes/flattened_scalar.py index d50746fc2a2e..a959d5b950be 100644 --- a/rerun_py/tests/test_types/datatypes/flattened_scalar.py +++ b/rerun_py/tests/test_types/datatypes/flattened_scalar.py @@ -61,4 +61,6 @@ class FlattenedScalarBatch(BaseBatch[FlattenedScalarArrayLike]): @staticmethod def _native_to_pa_array(data: FlattenedScalarArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in flattened_scalar_ext.py + raise NotImplementedError( + "Arrow serialization of FlattenedScalar not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in flattened_scalar_ext.py diff --git a/rerun_py/tests/test_types/datatypes/primitive_component.py b/rerun_py/tests/test_types/datatypes/primitive_component.py index 4fcb8dd0cad6..23ece752f8f4 100644 --- a/rerun_py/tests/test_types/datatypes/primitive_component.py +++ b/rerun_py/tests/test_types/datatypes/primitive_component.py @@ -59,4 +59,6 @@ class PrimitiveComponentBatch(BaseBatch[PrimitiveComponentArrayLike]): @staticmethod def _native_to_pa_array(data: PrimitiveComponentArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in primitive_component_ext.py + raise NotImplementedError( + "Arrow serialization of PrimitiveComponent not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in primitive_component_ext.py diff --git a/rerun_py/tests/test_types/datatypes/string_component.py b/rerun_py/tests/test_types/datatypes/string_component.py index eb896e67ad4a..228105be1dfc 100644 --- a/rerun_py/tests/test_types/datatypes/string_component.py +++ b/rerun_py/tests/test_types/datatypes/string_component.py @@ -53,4 +53,6 @@ class StringComponentBatch(BaseBatch[StringComponentArrayLike]): @staticmethod def _native_to_pa_array(data: StringComponentArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError # You need to implement native_to_pa_array_override in string_component_ext.py + raise NotImplementedError( + "Arrow serialization of StringComponent not implemented: We lack codegen for arrow-serialization of structs" + ) # You need to implement native_to_pa_array_override in string_component_ext.py From 734187c6aed45b3c81edbdc4254f1a9cb6abf953 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 18:44:21 +0200 Subject: [PATCH 387/508] Document all public item in `re_types` (#6146) ### What This is our public API, and keeping it well-documented seems like a low bar. In some places it may seem unnecessary (e.g. describing what a `new` function does, or what `Angle::Degrees` means), but enforcing `#[allow(missing_docs)]` is the only way I know to remind us (and other contributors) to always consider documentation. You can opt-out using `#![allow(missing_docs)]`. While fixing the docs I found a few weird pieces of code that I also fixed. ### Before Screenshot 2024-04-29 at 09 04 28 Screenshot 2024-04-29 at 09 04 22 ### After Screenshot 2024-04-29 at 09 03 34 Screenshot 2024-04-29 at 09 03 56 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6146?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6146?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6146) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Jeremy Leibs Co-authored-by: Andreas Reich --- crates/re_data_ui/src/image.rs | 8 +- .../definitions/rerun/archetypes/boxes3d.fbs | 2 +- .../rerun/archetypes/disconnected_space.fbs | 1 + .../rerun/archetypes/view_coordinates.fbs | 1 + .../rerun/blueprint/components/corner_2d.fbs | 7 + .../rerun/components/marker_shape.fbs | 19 +++ .../definitions/rerun/datatypes/angle.fbs | 6 +- .../rerun/datatypes/tensor_data.fbs | 3 + .../rerun/datatypes/transform3d.fbs | 4 + .../definitions/rerun/datatypes/uuid.fbs | 3 +- .../src/archetypes/annotation_context.rs | 3 + crates/re_types/src/archetypes/arrows2d.rs | 15 ++ crates/re_types/src/archetypes/arrows3d.rs | 15 ++ crates/re_types/src/archetypes/asset3d.rs | 16 +++ crates/re_types/src/archetypes/bar_chart.rs | 4 + crates/re_types/src/archetypes/boxes2d.rs | 15 ++ crates/re_types/src/archetypes/boxes3d.rs | 13 ++ crates/re_types/src/archetypes/depth_image.rs | 10 ++ .../src/archetypes/disconnected_space.rs | 4 + crates/re_types/src/archetypes/image.rs | 6 + .../re_types/src/archetypes/line_strips2d.rs | 12 ++ .../re_types/src/archetypes/line_strips3d.rs | 9 ++ crates/re_types/src/archetypes/mesh3d.rs | 18 +++ crates/re_types/src/archetypes/mesh3d_ext.rs | 4 + crates/re_types/src/archetypes/pinhole.rs | 38 +++++ crates/re_types/src/archetypes/pinhole_ext.rs | 2 + crates/re_types/src/archetypes/points2d.rs | 20 +++ crates/re_types/src/archetypes/points3d.rs | 17 +++ crates/re_types/src/archetypes/scalar.rs | 3 + .../src/archetypes/segmentation_image.rs | 6 + crates/re_types/src/archetypes/series_line.rs | 8 ++ .../re_types/src/archetypes/series_point.rs | 9 ++ crates/re_types/src/archetypes/tensor.rs | 3 + crates/re_types/src/archetypes/tensor_ext.rs | 7 +- .../re_types/src/archetypes/text_document.rs | 10 ++ crates/re_types/src/archetypes/text_log.rs | 7 + crates/re_types/src/archetypes/transform3d.rs | 3 + .../src/archetypes/view_coordinates.rs | 4 + .../src/archetypes/view_coordinates_ext.rs | 123 ++++++++-------- .../src/blueprint/archetypes/background.rs | 6 + .../src/blueprint/archetypes/plot_legend.rs | 9 ++ .../src/blueprint/archetypes/scalar_axis.rs | 7 + .../archetypes/space_view_blueprint.rs | 14 ++ .../archetypes/space_view_contents.rs | 3 + .../src/blueprint/archetypes/visual_bounds.rs | 7 + .../src/blueprint/components/corner2d.rs | 7 + .../visible_time_range_boundary_ext.rs | 5 + .../datatypes/visible_time_range_ext.rs | 5 + crates/re_types/src/blueprint/mod.rs | 5 + crates/re_types/src/components/color_ext.rs | 8 ++ .../src/components/half_sizes2d_ext.rs | 5 +- .../src/components/half_sizes3d_ext.rs | 5 +- .../src/components/line_strip2d_ext.rs | 1 + .../src/components/line_strip3d_ext.rs | 1 + .../re_types/src/components/marker_shape.rs | 19 +++ .../re_types/src/components/material_ext.rs | 1 + .../re_types/src/components/media_type_ext.rs | 1 + .../src/components/mesh_properties_ext.rs | 4 + crates/re_types/src/components/name_ext.rs | 1 + .../src/components/pinhole_projection_ext.rs | 1 + .../re_types/src/components/position2d_ext.rs | 5 +- .../re_types/src/components/position3d_ext.rs | 6 +- crates/re_types/src/components/radius_ext.rs | 3 + crates/re_types/src/components/range1d_ext.rs | 3 + .../re_types/src/components/rotation3d_ext.rs | 1 + .../re_types/src/components/texcoord2d_ext.rs | 6 + crates/re_types/src/components/text_ext.rs | 1 + .../src/components/text_log_level_ext.rs | 1 + .../src/components/transform3d_ext.rs | 9 ++ .../re_types/src/components/vector2d_ext.rs | 3 + .../re_types/src/components/vector3d_ext.rs | 3 + .../src/components/view_coordinates_ext.rs | 131 ++++++++++-------- crates/re_types/src/datatypes/angle.rs | 3 + .../src/datatypes/keypoint_pair_ext.rs | 1 + crates/re_types/src/datatypes/mat3x3_ext.rs | 3 + crates/re_types/src/datatypes/mat4x4_ext.rs | 3 + crates/re_types/src/datatypes/material_ext.rs | 1 + .../src/datatypes/mesh_properties_ext.rs | 1 + .../re_types/src/datatypes/quaternion_ext.rs | 3 + crates/re_types/src/datatypes/rgba32_ext.rs | 7 + .../re_types/src/datatypes/rotation3d_ext.rs | 1 + .../src/datatypes/rotation_axis_angle_ext.rs | 1 + .../src/datatypes/tensor_buffer_ext.rs | 5 + crates/re_types/src/datatypes/tensor_data.rs | 3 + .../re_types/src/datatypes/tensor_data_ext.rs | 61 ++++---- .../src/datatypes/tensor_dimension_ext.rs | 7 +- crates/re_types/src/datatypes/transform3d.rs | 3 + .../re_types/src/datatypes/transform3d_ext.rs | 1 + .../datatypes/translation_and_mat3x3_ext.rs | 5 +- .../translation_rotation_scale3d_ext.rs | 1 + crates/re_types/src/datatypes/uuid.rs | 3 +- crates/re_types/src/datatypes/uvec2d_ext.rs | 6 + crates/re_types/src/datatypes/uvec3d_ext.rs | 7 + crates/re_types/src/datatypes/uvec4d_ext.rs | 8 ++ crates/re_types/src/datatypes/vec2d_ext.rs | 6 + crates/re_types/src/datatypes/vec3d_ext.rs | 7 + crates/re_types/src/datatypes/vec4d_ext.rs | 6 + crates/re_types/src/image.rs | 5 + crates/re_types/src/lib.rs | 3 + crates/re_types/src/tensor_data.rs | 26 +++- .../src/testing/archetypes/affix_fuzzer1.rs | 3 + .../src/testing/archetypes/affix_fuzzer2.rs | 3 + .../src/testing/archetypes/affix_fuzzer3.rs | 3 + .../src/testing/archetypes/affix_fuzzer4.rs | 3 + crates/re_types/src/view_coordinates.rs | 58 ++++++-- .../archetypes/container_blueprint.rs | 26 ++++ .../blueprint/archetypes/panel_blueprint.rs | 4 + .../archetypes/viewport_blueprint.rs | 20 +++ .../re_types_builder/src/codegen/rust/api.rs | 19 ++- .../re_types_builder/src/codegen/rust/util.rs | 5 +- crates/re_types_core/src/archetypes/clear.rs | 3 + docs/content/reference/types/datatypes.md | 2 +- .../content/reference/types/datatypes/uuid.md | 2 +- rerun_cpp/src/rerun/archetypes/boxes3d.hpp | 2 + .../rerun/archetypes/disconnected_space.hpp | 1 + .../src/rerun/archetypes/view_coordinates.hpp | 121 ++++++++++++++++ .../rerun/archetypes/view_coordinates_ext.cpp | 120 ++++++++++++++++ .../rerun/blueprint/components/corner2d.hpp | 4 + .../src/rerun/components/marker_shape.hpp | 10 ++ .../src/rerun/components/view_coordinates.hpp | 120 ++++++++++++++++ .../rerun/components/view_coordinates_ext.cpp | 120 ++++++++++++++++ rerun_cpp/src/rerun/datatypes/angle.hpp | 4 + rerun_cpp/src/rerun/datatypes/tensor_data.hpp | 2 + rerun_cpp/src/rerun/datatypes/transform3d.hpp | 6 + rerun_cpp/src/rerun/datatypes/uuid.hpp | 3 +- .../rerun_sdk/rerun/archetypes/boxes3d.py | 4 + .../rerun/archetypes/disconnected_space.py | 4 + .../rerun/archetypes/view_coordinates.py | 14 +- .../rerun/blueprint/components/corner2d.py | 7 + .../rerun/components/marker_shape.py | 19 +++ .../rerun/components/view_coordinates_ext.py | 120 ++++++++++++++++ rerun_py/rerun_sdk/rerun/datatypes/angle.py | 12 +- .../rerun_sdk/rerun/datatypes/tensor_data.py | 7 + .../rerun_sdk/rerun/datatypes/transform3d.py | 2 + rerun_py/rerun_sdk/rerun/datatypes/uuid.py | 15 +- scripts/generate_view_coordinate_defs.py | 19 ++- 136 files changed, 1619 insertions(+), 200 deletions(-) diff --git a/crates/re_data_ui/src/image.rs b/crates/re_data_ui/src/image.rs index 491320baeb82..28e9dfdb57e8 100644 --- a/crates/re_data_ui/src/image.rs +++ b/crates/re_data_ui/src/image.rs @@ -714,8 +714,12 @@ fn tensor_pixel_value_ui( 3 => { // TODO(jleibs): Track RGB ordering somehow -- don't just assume it if let Some([r, g, b]) = match &tensor.buffer { - TensorBuffer::Nv12(_) => tensor.get_nv12_pixel(x, y), - TensorBuffer::Yuy2(_) => tensor.get_yuy2_pixel(x, y), + TensorBuffer::Nv12(_) => tensor + .get_nv12_pixel(x, y) + .map(|rgb| rgb.map(TensorElement::U8)), + TensorBuffer::Yuy2(_) => tensor + .get_yuy2_pixel(x, y) + .map(|rgb| rgb.map(TensorElement::U8)), _ => { if let [Some(r), Some(g), Some(b)] = [ tensor.get_with_image_coords(x, y, 0), diff --git a/crates/re_types/definitions/rerun/archetypes/boxes3d.fbs b/crates/re_types/definitions/rerun/archetypes/boxes3d.fbs index b23fda975c13..8c76a3fdc03d 100644 --- a/crates/re_types/definitions/rerun/archetypes/boxes3d.fbs +++ b/crates/re_types/definitions/rerun/archetypes/boxes3d.fbs @@ -29,7 +29,7 @@ table Boxes3D ( /// Optional center positions of the boxes. centers: [rerun.components.Position3D] ("attr.rerun.component_recommended", nullable, order: 2000); - // Optional rotations of the boxes. + /// Optional rotations of the boxes. rotations: [rerun.components.Rotation3D] ("attr.rerun.component_recommended", nullable, order: 2100); /// Optional colors for the boxes. diff --git a/crates/re_types/definitions/rerun/archetypes/disconnected_space.fbs b/crates/re_types/definitions/rerun/archetypes/disconnected_space.fbs index 75849dff3047..8b48efb9107f 100644 --- a/crates/re_types/definitions/rerun/archetypes/disconnected_space.fbs +++ b/crates/re_types/definitions/rerun/archetypes/disconnected_space.fbs @@ -16,5 +16,6 @@ namespace rerun.archetypes; table DisconnectedSpace ( "attr.rust.derive": "Copy, PartialEq, Eq" ) { + /// Whether the entity path at which this is logged is disconnected from its parent. disconnected_space: rerun.components.DisconnectedSpace ("attr.rerun.component_required", order: 1000); } diff --git a/crates/re_types/definitions/rerun/archetypes/view_coordinates.fbs b/crates/re_types/definitions/rerun/archetypes/view_coordinates.fbs index 21f876bec85d..37c3775f4feb 100644 --- a/crates/re_types/definitions/rerun/archetypes/view_coordinates.fbs +++ b/crates/re_types/definitions/rerun/archetypes/view_coordinates.fbs @@ -21,5 +21,6 @@ table ViewCoordinates ( "attr.rust.repr": "transparent", "attr.docs.category": "Spatial 3D" ) { + /// The directions of the [x, y, z] axes. xyz: rerun.components.ViewCoordinates ("attr.rerun.component_required", required, order: 1000); } diff --git a/crates/re_types/definitions/rerun/blueprint/components/corner_2d.fbs b/crates/re_types/definitions/rerun/blueprint/components/corner_2d.fbs index 77141f6bcb21..ad50255a0800 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/corner_2d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/corner_2d.fbs @@ -9,8 +9,15 @@ enum Corner2D: byte ( "attr.rerun.scope": "blueprint", "attr.rust.derive": "Copy, PartialEq, Eq" ) { + /// Left top corner. LeftTop, + + /// Right top corner. RightTop, + + /// Left bottom corner. LeftBottom, + + /// Right bottom corner. RightBottom (default), } diff --git a/crates/re_types/definitions/rerun/components/marker_shape.fbs b/crates/re_types/definitions/rerun/components/marker_shape.fbs index df51c2174978..21ffaea616e5 100644 --- a/crates/re_types/definitions/rerun/components/marker_shape.fbs +++ b/crates/re_types/definitions/rerun/components/marker_shape.fbs @@ -10,14 +10,33 @@ namespace rerun.components; /// Shape of a marker. enum MarkerShape: byte { + /// `⏺` Circle (default), + + /// `◆` Diamond, + + /// `◼️` Square, + + /// `x` Cross, + + /// `+` Plus, + + /// `▲` Up, + + /// `▼` Down, + + /// `◀` Left, + + /// `▶` Right, + + /// `*` Asterisk, } diff --git a/crates/re_types/definitions/rerun/datatypes/angle.fbs b/crates/re_types/definitions/rerun/datatypes/angle.fbs index b6c3e0e71207..67c623468211 100644 --- a/crates/re_types/definitions/rerun/datatypes/angle.fbs +++ b/crates/re_types/definitions/rerun/datatypes/angle.fbs @@ -12,9 +12,11 @@ namespace rerun.datatypes; union Angle ( "attr.rust.derive": "Copy, PartialEq" ) { - /// \py 3D rotation angle in radians. Only one of `degrees` or `radians` should be set. + /// Angle in radians. One turn is equal to 2π (or τ) radians. + /// \py Only one of `degrees` or `radians` should be set. Radians: rerun.datatypes.Float32 (transparent), - /// \py 3D rotation angle in degrees. Only one of `degrees` or `radians` should be set. + /// Angle in degrees. One turn is equal to 360 degrees. + /// \py Only one of `degrees` or `radians` should be set. Degrees: rerun.datatypes.Float32 (transparent), } diff --git a/crates/re_types/definitions/rerun/datatypes/tensor_data.fbs b/crates/re_types/definitions/rerun/datatypes/tensor_data.fbs index edf61055db55..dfacbc8ae33c 100644 --- a/crates/re_types/definitions/rerun/datatypes/tensor_data.fbs +++ b/crates/re_types/definitions/rerun/datatypes/tensor_data.fbs @@ -26,6 +26,9 @@ table TensorData ( "attr.python.array_aliases": "npt.ArrayLike", "attr.rust.derive": "PartialEq," ) { + /// The shape of the tensor, including optional names for each dimension. shape: [rerun.datatypes.TensorDimension] (order: 200); + + /// The content/data. buffer: rerun.datatypes.TensorBuffer (order: 300); } diff --git a/crates/re_types/definitions/rerun/datatypes/transform3d.fbs b/crates/re_types/definitions/rerun/datatypes/transform3d.fbs index 05cac11188e1..6494434e5527 100644 --- a/crates/re_types/definitions/rerun/datatypes/transform3d.fbs +++ b/crates/re_types/definitions/rerun/datatypes/transform3d.fbs @@ -12,7 +12,11 @@ namespace rerun.datatypes; union Transform3D ( "attr.rust.derive": "Copy, PartialEq" ) { + /// Translation plus a 3x3 matrix for scale, rotation, skew, etc. TranslationAndMat3x3: TranslationAndMat3x3, + + /// Translation, rotation and scale, decomposed. TranslationRotationScale: TranslationRotationScale3D, + // TODO(andreas): Raw 4x4 matrix. } diff --git a/crates/re_types/definitions/rerun/datatypes/uuid.fbs b/crates/re_types/definitions/rerun/datatypes/uuid.fbs index f25b942795f3..9f910860af7a 100644 --- a/crates/re_types/definitions/rerun/datatypes/uuid.fbs +++ b/crates/re_types/definitions/rerun/datatypes/uuid.fbs @@ -10,7 +10,7 @@ namespace rerun.datatypes; // --- -/// A 16-byte uuid. +/// A 16-byte UUID. struct Uuid ( "attr.arrow.transparent", "attr.python.aliases": "npt.NDArray[Any], npt.ArrayLike, Sequence[int], bytes", @@ -18,5 +18,6 @@ struct Uuid ( "attr.rust.derive": "Default, Copy, PartialEq, Eq", "attr.rust.repr": "transparent" ) { + /// The raw bytes representing the UUID. bytes: [ubyte: 16] (order: 100); } diff --git a/crates/re_types/src/archetypes/annotation_context.rs b/crates/re_types/src/archetypes/annotation_context.rs index b9fa8ad82e3a..2b45d9ce51c5 100644 --- a/crates/re_types/src/archetypes/annotation_context.rs +++ b/crates/re_types/src/archetypes/annotation_context.rs @@ -109,6 +109,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl AnnotationContext { + /// The total number of components in the archetype: 1 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -191,6 +192,8 @@ impl ::re_types_core::AsComponents for AnnotationContext { } impl AnnotationContext { + /// Create a new `AnnotationContext`. + #[inline] pub fn new(context: impl Into) -> Self { Self { context: context.into(), diff --git a/crates/re_types/src/archetypes/arrows2d.rs b/crates/re_types/src/archetypes/arrows2d.rs index 8097432518ad..78a6eb25629c 100644 --- a/crates/re_types/src/archetypes/arrows2d.rs +++ b/crates/re_types/src/archetypes/arrows2d.rs @@ -137,6 +137,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = }); impl Arrows2D { + /// The total number of components in the archetype: 1 required, 2 recommended, 4 optional pub const NUM_COMPONENTS: usize = 7usize; } @@ -300,6 +301,8 @@ impl ::re_types_core::AsComponents for Arrows2D { } impl Arrows2D { + /// Create a new `Arrows2D`. + #[inline] pub(crate) fn new( vectors: impl IntoIterator>, ) -> Self { @@ -313,6 +316,9 @@ impl Arrows2D { } } + /// 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. #[inline] pub fn with_origins( mut self, @@ -322,6 +328,10 @@ impl Arrows2D { self } + /// 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`. #[inline] pub fn with_radii( mut self, @@ -331,6 +341,7 @@ impl Arrows2D { self } + /// Optional colors for the points. #[inline] pub fn with_colors( mut self, @@ -340,6 +351,7 @@ impl Arrows2D { self } + /// Optional text labels for the arrows. #[inline] pub fn with_labels( mut self, @@ -349,6 +361,9 @@ impl Arrows2D { self } + /// Optional class Ids for the points. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, diff --git a/crates/re_types/src/archetypes/arrows3d.rs b/crates/re_types/src/archetypes/arrows3d.rs index f3e237d8770a..183826d278cc 100644 --- a/crates/re_types/src/archetypes/arrows3d.rs +++ b/crates/re_types/src/archetypes/arrows3d.rs @@ -150,6 +150,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = }); impl Arrows3D { + /// The total number of components in the archetype: 1 required, 2 recommended, 4 optional pub const NUM_COMPONENTS: usize = 7usize; } @@ -313,6 +314,8 @@ impl ::re_types_core::AsComponents for Arrows3D { } impl Arrows3D { + /// Create a new `Arrows3D`. + #[inline] pub(crate) fn new( vectors: impl IntoIterator>, ) -> Self { @@ -326,6 +329,9 @@ impl Arrows3D { } } + /// 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. #[inline] pub fn with_origins( mut self, @@ -335,6 +341,10 @@ impl Arrows3D { self } + /// 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`. #[inline] pub fn with_radii( mut self, @@ -344,6 +354,7 @@ impl Arrows3D { self } + /// Optional colors for the points. #[inline] pub fn with_colors( mut self, @@ -353,6 +364,7 @@ impl Arrows3D { self } + /// Optional text labels for the arrows. #[inline] pub fn with_labels( mut self, @@ -362,6 +374,9 @@ impl Arrows3D { self } + /// Optional class Ids for the points. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, diff --git a/crates/re_types/src/archetypes/asset3d.rs b/crates/re_types/src/archetypes/asset3d.rs index 2a2ee20afaf7..2f5bcd75ffd5 100644 --- a/crates/re_types/src/archetypes/asset3d.rs +++ b/crates/re_types/src/archetypes/asset3d.rs @@ -119,6 +119,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = }); impl Asset3D { + /// The total number of components in the archetype: 1 required, 2 recommended, 1 optional pub const NUM_COMPONENTS: usize = 4usize; } @@ -230,6 +231,8 @@ impl ::re_types_core::AsComponents for Asset3D { } impl Asset3D { + /// Create a new `Asset3D`. + #[inline] pub fn new(blob: impl Into) -> Self { Self { blob: blob.into(), @@ -238,12 +241,25 @@ impl Asset3D { } } + /// 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. #[inline] pub fn with_media_type(mut self, media_type: impl Into) -> Self { self.media_type = Some(media_type.into()); self } + /// An out-of-tree transform. + /// + /// Applies a transformation to the asset itself without impacting its children. #[inline] pub fn with_transform( mut self, diff --git a/crates/re_types/src/archetypes/bar_chart.rs b/crates/re_types/src/archetypes/bar_chart.rs index 776000dd3ccc..eff2f19f67a1 100644 --- a/crates/re_types/src/archetypes/bar_chart.rs +++ b/crates/re_types/src/archetypes/bar_chart.rs @@ -90,6 +90,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = }); impl BarChart { + /// The total number of components in the archetype: 1 required, 1 recommended, 1 optional pub const NUM_COMPONENTS: usize = 3usize; } @@ -184,6 +185,8 @@ impl ::re_types_core::AsComponents for BarChart { } impl BarChart { + /// Create a new `BarChart`. + #[inline] pub fn new(values: impl Into) -> Self { Self { values: values.into(), @@ -191,6 +194,7 @@ impl BarChart { } } + /// The color of the bar chart #[inline] pub fn with_color(mut self, color: impl Into) -> Self { self.color = Some(color.into()); diff --git a/crates/re_types/src/archetypes/boxes2d.rs b/crates/re_types/src/archetypes/boxes2d.rs index 09fe69052890..1779da88b05c 100644 --- a/crates/re_types/src/archetypes/boxes2d.rs +++ b/crates/re_types/src/archetypes/boxes2d.rs @@ -139,6 +139,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = }); impl Boxes2D { + /// The total number of components in the archetype: 1 required, 3 recommended, 4 optional pub const NUM_COMPONENTS: usize = 8usize; } @@ -315,6 +316,8 @@ impl ::re_types_core::AsComponents for Boxes2D { } impl Boxes2D { + /// Create a new `Boxes2D`. + #[inline] pub(crate) fn new( half_sizes: impl IntoIterator>, ) -> Self { @@ -329,6 +332,7 @@ impl Boxes2D { } } + /// Optional center positions of the boxes. #[inline] pub fn with_centers( mut self, @@ -338,6 +342,7 @@ impl Boxes2D { self } + /// Optional colors for the boxes. #[inline] pub fn with_colors( mut self, @@ -347,6 +352,7 @@ impl Boxes2D { self } + /// Optional radii for the lines that make up the boxes. #[inline] pub fn with_radii( mut self, @@ -356,6 +362,7 @@ impl Boxes2D { self } + /// Optional text labels for the boxes. #[inline] pub fn with_labels( mut self, @@ -365,12 +372,20 @@ impl Boxes2D { self } + /// 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. #[inline] pub fn with_draw_order(mut self, draw_order: impl Into) -> Self { self.draw_order = Some(draw_order.into()); self } + /// Optional `ClassId`s for the boxes. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, diff --git a/crates/re_types/src/archetypes/boxes3d.rs b/crates/re_types/src/archetypes/boxes3d.rs index 45b6063b0c4d..317e50f6ebc9 100644 --- a/crates/re_types/src/archetypes/boxes3d.rs +++ b/crates/re_types/src/archetypes/boxes3d.rs @@ -70,6 +70,8 @@ pub struct Boxes3D { /// Optional center positions of the boxes. pub centers: Option>, + + /// Optional rotations of the boxes. pub rotations: Option>, /// Optional colors for the boxes. @@ -148,6 +150,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = }); impl Boxes3D { + /// The total number of components in the archetype: 1 required, 4 recommended, 3 optional pub const NUM_COMPONENTS: usize = 8usize; } @@ -327,6 +330,8 @@ impl ::re_types_core::AsComponents for Boxes3D { } impl Boxes3D { + /// Create a new `Boxes3D`. + #[inline] pub(crate) fn new( half_sizes: impl IntoIterator>, ) -> Self { @@ -341,6 +346,7 @@ impl Boxes3D { } } + /// Optional center positions of the boxes. #[inline] pub fn with_centers( mut self, @@ -350,6 +356,7 @@ impl Boxes3D { self } + /// Optional rotations of the boxes. #[inline] pub fn with_rotations( mut self, @@ -359,6 +366,7 @@ impl Boxes3D { self } + /// Optional colors for the boxes. #[inline] pub fn with_colors( mut self, @@ -368,6 +376,7 @@ impl Boxes3D { self } + /// Optional radii for the lines that make up the boxes. #[inline] pub fn with_radii( mut self, @@ -377,6 +386,7 @@ impl Boxes3D { self } + /// Optional text labels for the boxes. #[inline] pub fn with_labels( mut self, @@ -386,6 +396,9 @@ impl Boxes3D { self } + /// Optional `ClassId`s for the boxes. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, diff --git a/crates/re_types/src/archetypes/depth_image.rs b/crates/re_types/src/archetypes/depth_image.rs index 4ba9444b8c1f..9237e478ff24 100644 --- a/crates/re_types/src/archetypes/depth_image.rs +++ b/crates/re_types/src/archetypes/depth_image.rs @@ -123,6 +123,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = }); impl DepthImage { + /// The total number of components in the archetype: 1 required, 1 recommended, 2 optional pub const NUM_COMPONENTS: usize = 4usize; } @@ -233,6 +234,8 @@ impl ::re_types_core::AsComponents for DepthImage { } impl DepthImage { + /// Create a new `DepthImage`. + #[inline] pub fn new(data: impl Into) -> Self { Self { data: data.into(), @@ -241,12 +244,19 @@ impl DepthImage { } } + /// 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). #[inline] pub fn with_meter(mut self, meter: impl Into) -> Self { self.meter = Some(meter.into()); self } + /// An optional floating point value that specifies the 2D drawing order. + /// + /// Objects with higher values are drawn on top of those with lower values. #[inline] pub fn with_draw_order(mut self, draw_order: impl Into) -> Self { self.draw_order = Some(draw_order.into()); diff --git a/crates/re_types/src/archetypes/disconnected_space.rs b/crates/re_types/src/archetypes/disconnected_space.rs index 4b79caf832ef..250af687e884 100644 --- a/crates/re_types/src/archetypes/disconnected_space.rs +++ b/crates/re_types/src/archetypes/disconnected_space.rs @@ -67,6 +67,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; ///
#[derive(Clone, Debug, Copy, PartialEq, Eq)] pub struct DisconnectedSpace { + /// Whether the entity path at which this is logged is disconnected from its parent. pub disconnected_space: crate::components::DisconnectedSpace, } @@ -100,6 +101,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl DisconnectedSpace { + /// The total number of components in the archetype: 1 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -182,6 +184,8 @@ impl ::re_types_core::AsComponents for DisconnectedSpace { } impl DisconnectedSpace { + /// Create a new `DisconnectedSpace`. + #[inline] pub fn new(disconnected_space: impl Into) -> Self { Self { disconnected_space: disconnected_space.into(), diff --git a/crates/re_types/src/archetypes/image.rs b/crates/re_types/src/archetypes/image.rs index b3636b125a51..27a19377dc33 100644 --- a/crates/re_types/src/archetypes/image.rs +++ b/crates/re_types/src/archetypes/image.rs @@ -111,6 +111,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = }); impl Image { + /// The total number of components in the archetype: 1 required, 1 recommended, 1 optional pub const NUM_COMPONENTS: usize = 3usize; } @@ -205,6 +206,8 @@ impl ::re_types_core::AsComponents for Image { } impl Image { + /// Create a new `Image`. + #[inline] pub fn new(data: impl Into) -> Self { Self { data: data.into(), @@ -212,6 +215,9 @@ impl Image { } } + /// An optional floating point value that specifies the 2D drawing order. + /// + /// Objects with higher values are drawn on top of those with lower values. #[inline] pub fn with_draw_order(mut self, draw_order: impl Into) -> Self { self.draw_order = Some(draw_order.into()); diff --git a/crates/re_types/src/archetypes/line_strips2d.rs b/crates/re_types/src/archetypes/line_strips2d.rs index a001bb9b97a5..56586673f41c 100644 --- a/crates/re_types/src/archetypes/line_strips2d.rs +++ b/crates/re_types/src/archetypes/line_strips2d.rs @@ -138,6 +138,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = }); impl LineStrips2D { + /// The total number of components in the archetype: 1 required, 3 recommended, 3 optional pub const NUM_COMPONENTS: usize = 7usize; } @@ -298,6 +299,8 @@ impl ::re_types_core::AsComponents for LineStrips2D { } impl LineStrips2D { + /// Create a new `LineStrips2D`. + #[inline] pub fn new( strips: impl IntoIterator>, ) -> Self { @@ -311,6 +314,7 @@ impl LineStrips2D { } } + /// Optional radii for the line strips. #[inline] pub fn with_radii( mut self, @@ -320,6 +324,7 @@ impl LineStrips2D { self } + /// Optional colors for the line strips. #[inline] pub fn with_colors( mut self, @@ -329,6 +334,7 @@ impl LineStrips2D { self } + /// Optional text labels for the line strips. #[inline] pub fn with_labels( mut self, @@ -338,12 +344,18 @@ impl LineStrips2D { self } + /// 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. #[inline] pub fn with_draw_order(mut self, draw_order: impl Into) -> Self { self.draw_order = Some(draw_order.into()); self } + /// Optional `ClassId`s for the lines. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, diff --git a/crates/re_types/src/archetypes/line_strips3d.rs b/crates/re_types/src/archetypes/line_strips3d.rs index 4cce5d41f8b9..b4a3d968db67 100644 --- a/crates/re_types/src/archetypes/line_strips3d.rs +++ b/crates/re_types/src/archetypes/line_strips3d.rs @@ -135,6 +135,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = }); impl LineStrips3D { + /// The total number of components in the archetype: 1 required, 3 recommended, 2 optional pub const NUM_COMPONENTS: usize = 6usize; } @@ -282,6 +283,8 @@ impl ::re_types_core::AsComponents for LineStrips3D { } impl LineStrips3D { + /// Create a new `LineStrips3D`. + #[inline] pub fn new( strips: impl IntoIterator>, ) -> Self { @@ -294,6 +297,7 @@ impl LineStrips3D { } } + /// Optional radii for the line strips. #[inline] pub fn with_radii( mut self, @@ -303,6 +307,7 @@ impl LineStrips3D { self } + /// Optional colors for the line strips. #[inline] pub fn with_colors( mut self, @@ -312,6 +317,7 @@ impl LineStrips3D { self } + /// Optional text labels for the line strips. #[inline] pub fn with_labels( mut self, @@ -321,6 +327,9 @@ impl LineStrips3D { self } + /// Optional `ClassId`s for the lines. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, diff --git a/crates/re_types/src/archetypes/mesh3d.rs b/crates/re_types/src/archetypes/mesh3d.rs index a5d8883f3ad3..54aee1046583 100644 --- a/crates/re_types/src/archetypes/mesh3d.rs +++ b/crates/re_types/src/archetypes/mesh3d.rs @@ -155,6 +155,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = }); impl Mesh3D { + /// The total number of components in the archetype: 1 required, 3 recommended, 5 optional pub const NUM_COMPONENTS: usize = 9usize; } @@ -344,6 +345,8 @@ impl ::re_types_core::AsComponents for Mesh3D { } impl Mesh3D { + /// Create a new `Mesh3D`. + #[inline] pub fn new( vertex_positions: impl IntoIterator>, ) -> Self { @@ -359,6 +362,7 @@ impl Mesh3D { } } + /// Optional properties for the mesh as a whole (including indexed drawing). #[inline] pub fn with_mesh_properties( mut self, @@ -368,6 +372,9 @@ impl Mesh3D { self } + /// An optional normal for each vertex. + /// + /// If specified, this must have as many elements as `vertex_positions`. #[inline] pub fn with_vertex_normals( mut self, @@ -377,6 +384,7 @@ impl Mesh3D { self } + /// An optional color for each vertex. #[inline] pub fn with_vertex_colors( mut self, @@ -386,6 +394,7 @@ impl Mesh3D { self } + /// An optional uv texture coordinate for each vertex. #[inline] pub fn with_vertex_texcoords( mut self, @@ -395,6 +404,7 @@ impl Mesh3D { self } + /// Optional material properties for the mesh as a whole. #[inline] pub fn with_mesh_material( mut self, @@ -404,6 +414,11 @@ impl Mesh3D { self } + /// Optional albedo texture. + /// + /// Used with `vertex_texcoords` on `Mesh3D`. + /// Currently supports only sRGB(A) textures, ignoring alpha. + /// (meaning that the tensor must have 3 or 4 channels and use the `u8` format) #[inline] pub fn with_albedo_texture( mut self, @@ -413,6 +428,9 @@ impl Mesh3D { self } + /// Optional class Ids for the vertices. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, diff --git a/crates/re_types/src/archetypes/mesh3d_ext.rs b/crates/re_types/src/archetypes/mesh3d_ext.rs index e67dfc13b112..9043c0913994 100644 --- a/crates/re_types/src/archetypes/mesh3d_ext.rs +++ b/crates/re_types/src/archetypes/mesh3d_ext.rs @@ -19,6 +19,8 @@ pub enum Mesh3DError { } impl Mesh3D { + /// Check that this is a valid mesh, e.g. that the vertex indices are within bounds + /// and that we have the same number of positions and normals (if any). pub fn sanity_check(&self) -> Result<(), Mesh3DError> { let num_vertices = self.num_vertices(); @@ -57,11 +59,13 @@ impl Mesh3D { Ok(()) } + /// The total number of vertices. #[inline] pub fn num_vertices(&self) -> usize { self.vertex_positions.len() } + /// The total number of triangles. #[inline] pub fn num_triangles(&self) -> usize { if let Some(indices) = self diff --git a/crates/re_types/src/archetypes/pinhole.rs b/crates/re_types/src/archetypes/pinhole.rs index bc41635831a9..33372ec6d244 100644 --- a/crates/re_types/src/archetypes/pinhole.rs +++ b/crates/re_types/src/archetypes/pinhole.rs @@ -171,6 +171,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = }); impl Pinhole { + /// The total number of components in the archetype: 1 required, 2 recommended, 1 optional pub const NUM_COMPONENTS: usize = 4usize; } @@ -282,6 +283,8 @@ impl ::re_types_core::AsComponents for Pinhole { } impl Pinhole { + /// Create a new `Pinhole`. + #[inline] pub fn new(image_from_camera: impl Into) -> Self { Self { image_from_camera: image_from_camera.into(), @@ -290,12 +293,47 @@ impl Pinhole { } } + /// 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`. #[inline] pub fn with_resolution(mut self, resolution: impl Into) -> Self { self.resolution = Some(resolution.into()); self } + /// Sets the view coordinates for the camera. + /// + /// All common values are available as constants on the `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. #[inline] pub fn with_camera_xyz( mut self, diff --git a/crates/re_types/src/archetypes/pinhole_ext.rs b/crates/re_types/src/archetypes/pinhole_ext.rs index 385bd33f8c1e..787e2b932837 100644 --- a/crates/re_types/src/archetypes/pinhole_ext.rs +++ b/crates/re_types/src/archetypes/pinhole_ext.rs @@ -55,12 +55,14 @@ impl Pinhole { .map(|resolution| 2.0 * (0.5 * resolution[1] / self.image_from_camera.col(1)[1]).atan()) } + /// The resolution of the camera sensor in pixels. #[inline] #[cfg(feature = "glam")] pub fn resolution(&self) -> Option { self.resolution.map(|r| (*r).into()) } + /// Width/height ratio of the camera sensor. #[inline] pub fn aspect_ratio(&self) -> Option { self.resolution.map(|r| r[0] / r[1]) diff --git a/crates/re_types/src/archetypes/points2d.rs b/crates/re_types/src/archetypes/points2d.rs index 70993dd824da..47928995bc07 100644 --- a/crates/re_types/src/archetypes/points2d.rs +++ b/crates/re_types/src/archetypes/points2d.rs @@ -153,6 +153,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 8usize]> = }); impl Points2D { + /// The total number of components in the archetype: 1 required, 3 recommended, 4 optional pub const NUM_COMPONENTS: usize = 8usize; } @@ -329,6 +330,8 @@ impl ::re_types_core::AsComponents for Points2D { } impl Points2D { + /// Create a new `Points2D`. + #[inline] pub fn new( positions: impl IntoIterator>, ) -> Self { @@ -343,6 +346,7 @@ impl Points2D { } } + /// Optional radii for the points, effectively turning them into circles. #[inline] pub fn with_radii( mut self, @@ -352,6 +356,7 @@ impl Points2D { self } + /// Optional colors for the points. #[inline] pub fn with_colors( mut self, @@ -361,6 +366,7 @@ impl Points2D { self } + /// Optional text labels for the points. #[inline] pub fn with_labels( mut self, @@ -370,12 +376,18 @@ impl Points2D { self } + /// An optional floating point value that specifies the 2D drawing order. + /// + /// Objects with higher values are drawn on top of those with lower values. #[inline] pub fn with_draw_order(mut self, draw_order: impl Into) -> Self { self.draw_order = Some(draw_order.into()); self } + /// Optional class Ids for the points. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, @@ -385,6 +397,14 @@ impl Points2D { self } + /// Optional keypoint IDs for the points, identifying them within a class. + /// + /// If keypoint IDs are passed in but no class IDs were specified, the class ID 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. #[inline] pub fn with_keypoint_ids( mut self, diff --git a/crates/re_types/src/archetypes/points3d.rs b/crates/re_types/src/archetypes/points3d.rs index 618591340e95..559e608de088 100644 --- a/crates/re_types/src/archetypes/points3d.rs +++ b/crates/re_types/src/archetypes/points3d.rs @@ -144,6 +144,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 7usize]> = }); impl Points3D { + /// The total number of components in the archetype: 1 required, 3 recommended, 3 optional pub const NUM_COMPONENTS: usize = 7usize; } @@ -307,6 +308,8 @@ impl ::re_types_core::AsComponents for Points3D { } impl Points3D { + /// Create a new `Points3D`. + #[inline] pub fn new( positions: impl IntoIterator>, ) -> Self { @@ -320,6 +323,7 @@ impl Points3D { } } + /// Optional radii for the points, effectively turning them into circles. #[inline] pub fn with_radii( mut self, @@ -329,6 +333,7 @@ impl Points3D { self } + /// Optional colors for the points. #[inline] pub fn with_colors( mut self, @@ -338,6 +343,7 @@ impl Points3D { self } + /// Optional text labels for the points. #[inline] pub fn with_labels( mut self, @@ -347,6 +353,9 @@ impl Points3D { self } + /// Optional class Ids for the points. + /// + /// The class ID provides colors and labels if not specified explicitly. #[inline] pub fn with_class_ids( mut self, @@ -356,6 +365,14 @@ impl Points3D { self } + /// Optional keypoint IDs for the points, identifying them within a class. + /// + /// If keypoint IDs are passed in but no class IDs were specified, the class ID 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. #[inline] pub fn with_keypoint_ids( mut self, diff --git a/crates/re_types/src/archetypes/scalar.rs b/crates/re_types/src/archetypes/scalar.rs index 2e93e834c1fb..e66d402c1f1e 100644 --- a/crates/re_types/src/archetypes/scalar.rs +++ b/crates/re_types/src/archetypes/scalar.rs @@ -95,6 +95,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl Scalar { + /// The total number of components in the archetype: 1 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -177,6 +178,8 @@ impl ::re_types_core::AsComponents for Scalar { } impl Scalar { + /// Create a new `Scalar`. + #[inline] pub fn new(scalar: impl Into) -> Self { Self { scalar: scalar.into(), diff --git a/crates/re_types/src/archetypes/segmentation_image.rs b/crates/re_types/src/archetypes/segmentation_image.rs index 1f8eceacd6a4..1eddd44df7cd 100644 --- a/crates/re_types/src/archetypes/segmentation_image.rs +++ b/crates/re_types/src/archetypes/segmentation_image.rs @@ -115,6 +115,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = }); impl SegmentationImage { + /// The total number of components in the archetype: 1 required, 1 recommended, 1 optional pub const NUM_COMPONENTS: usize = 3usize; } @@ -209,6 +210,8 @@ impl ::re_types_core::AsComponents for SegmentationImage { } impl SegmentationImage { + /// Create a new `SegmentationImage`. + #[inline] pub fn new(data: impl Into) -> Self { Self { data: data.into(), @@ -216,6 +219,9 @@ impl SegmentationImage { } } + /// An optional floating point value that specifies the 2D drawing order. + /// + /// Objects with higher values are drawn on top of those with lower values. #[inline] pub fn with_draw_order(mut self, draw_order: impl Into) -> Self { self.draw_order = Some(draw_order.into()); diff --git a/crates/re_types/src/archetypes/series_line.rs b/crates/re_types/src/archetypes/series_line.rs index db54b4bebbdf..cac01e6ad150 100644 --- a/crates/re_types/src/archetypes/series_line.rs +++ b/crates/re_types/src/archetypes/series_line.rs @@ -129,6 +129,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = }); impl SeriesLine { + /// The total number of components in the archetype: 0 required, 1 recommended, 3 optional pub const NUM_COMPONENTS: usize = 4usize; } @@ -233,6 +234,8 @@ impl ::re_types_core::AsComponents for SeriesLine { } impl SeriesLine { + /// Create a new `SeriesLine`. + #[inline] pub fn new() -> Self { Self { color: None, @@ -241,18 +244,23 @@ impl SeriesLine { } } + /// Color for the corresponding series. #[inline] pub fn with_color(mut self, color: impl Into) -> Self { self.color = Some(color.into()); self } + /// Stroke width for the corresponding series. #[inline] pub fn with_width(mut self, width: impl Into) -> Self { self.width = Some(width.into()); self } + /// Display name of the series. + /// + /// Used in the legend. #[inline] pub fn with_name(mut self, name: impl Into) -> Self { self.name = Some(name.into()); diff --git a/crates/re_types/src/archetypes/series_point.rs b/crates/re_types/src/archetypes/series_point.rs index d771aa7c4abe..2ad90cc31382 100644 --- a/crates/re_types/src/archetypes/series_point.rs +++ b/crates/re_types/src/archetypes/series_point.rs @@ -140,6 +140,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = }); impl SeriesPoint { + /// The total number of components in the archetype: 0 required, 1 recommended, 4 optional pub const NUM_COMPONENTS: usize = 5usize; } @@ -261,6 +262,8 @@ impl ::re_types_core::AsComponents for SeriesPoint { } impl SeriesPoint { + /// Create a new `SeriesPoint`. + #[inline] pub fn new() -> Self { Self { color: None, @@ -270,24 +273,30 @@ impl SeriesPoint { } } + /// Color for the corresponding series. #[inline] pub fn with_color(mut self, color: impl Into) -> Self { self.color = Some(color.into()); self } + /// What shape to use to represent the point #[inline] pub fn with_marker(mut self, marker: impl Into) -> Self { self.marker = Some(marker.into()); self } + /// Display name of the series. + /// + /// Used in the legend. #[inline] pub fn with_name(mut self, name: impl Into) -> Self { self.name = Some(name.into()); self } + /// Size of the marker. #[inline] pub fn with_marker_size( mut self, diff --git a/crates/re_types/src/archetypes/tensor.rs b/crates/re_types/src/archetypes/tensor.rs index a31b81af425e..d667aae4c300 100644 --- a/crates/re_types/src/archetypes/tensor.rs +++ b/crates/re_types/src/archetypes/tensor.rs @@ -88,6 +88,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl Tensor { + /// The total number of components in the archetype: 1 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -170,6 +171,8 @@ impl ::re_types_core::AsComponents for Tensor { } impl Tensor { + /// Create a new `Tensor`. + #[inline] pub fn new(data: impl Into) -> Self { Self { data: data.into() } } diff --git a/crates/re_types/src/archetypes/tensor_ext.rs b/crates/re_types/src/archetypes/tensor_ext.rs index f933cd888adc..5a9e0a1e8496 100644 --- a/crates/re_types/src/archetypes/tensor_ext.rs +++ b/crates/re_types/src/archetypes/tensor_ext.rs @@ -5,7 +5,8 @@ use re_types_core::ArrowString; use super::Tensor; impl Tensor { - pub fn data(&self) -> &crate::datatypes::TensorData { + /// Accessor to the underlying [`TensorData`]. + pub fn data(&self) -> &TensorData { &self.data.0 } @@ -13,7 +14,7 @@ impl Tensor { /// /// This is useful for constructing a tensor from an ndarray. pub fn try_from>(data: T) -> Result { - let data: crate::datatypes::TensorData = data.try_into()?; + let data: TensorData = data.try_into()?; Ok(Self { data: data.into() }) } @@ -34,7 +35,7 @@ impl Tensor { ); } Self { - data: crate::datatypes::TensorData { + data: TensorData { shape: self .data .0 diff --git a/crates/re_types/src/archetypes/text_document.rs b/crates/re_types/src/archetypes/text_document.rs index b653de113ac6..e83498516276 100644 --- a/crates/re_types/src/archetypes/text_document.rs +++ b/crates/re_types/src/archetypes/text_document.rs @@ -137,6 +137,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = }); impl TextDocument { + /// The total number of components in the archetype: 1 required, 1 recommended, 1 optional pub const NUM_COMPONENTS: usize = 3usize; } @@ -231,6 +232,8 @@ impl ::re_types_core::AsComponents for TextDocument { } impl TextDocument { + /// Create a new `TextDocument`. + #[inline] pub fn new(text: impl Into) -> Self { Self { text: text.into(), @@ -238,6 +241,13 @@ impl TextDocument { } } + /// The Media Type of the text. + /// + /// For instance: + /// * `text/plain` + /// * `text/markdown` + /// + /// If omitted, `text/plain` is assumed. #[inline] pub fn with_media_type(mut self, media_type: impl Into) -> Self { self.media_type = Some(media_type.into()); diff --git a/crates/re_types/src/archetypes/text_log.rs b/crates/re_types/src/archetypes/text_log.rs index 2363dded0b92..1ce368311b13 100644 --- a/crates/re_types/src/archetypes/text_log.rs +++ b/crates/re_types/src/archetypes/text_log.rs @@ -115,6 +115,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = }); impl TextLog { + /// The total number of components in the archetype: 1 required, 2 recommended, 1 optional pub const NUM_COMPONENTS: usize = 4usize; } @@ -221,6 +222,8 @@ impl ::re_types_core::AsComponents for TextLog { } impl TextLog { + /// Create a new `TextLog`. + #[inline] pub fn new(text: impl Into) -> Self { Self { text: text.into(), @@ -229,12 +232,16 @@ impl TextLog { } } + /// The verbosity level of the message. + /// + /// This can be used to filter the log messages in the Rerun Viewer. #[inline] pub fn with_level(mut self, level: impl Into) -> Self { self.level = Some(level.into()); self } + /// Optional color to use for the log line in the Rerun Viewer. #[inline] pub fn with_color(mut self, color: impl Into) -> Self { self.color = Some(color.into()); diff --git a/crates/re_types/src/archetypes/transform3d.rs b/crates/re_types/src/archetypes/transform3d.rs index 0be5132b9081..0f32a3481740 100644 --- a/crates/re_types/src/archetypes/transform3d.rs +++ b/crates/re_types/src/archetypes/transform3d.rs @@ -102,6 +102,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl Transform3D { + /// The total number of components in the archetype: 1 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -184,6 +185,8 @@ impl ::re_types_core::AsComponents for Transform3D { } impl Transform3D { + /// Create a new `Transform3D`. + #[inline] pub fn new(transform: impl Into) -> Self { Self { transform: transform.into(), diff --git a/crates/re_types/src/archetypes/view_coordinates.rs b/crates/re_types/src/archetypes/view_coordinates.rs index 83268138ec60..0ec5526a9ec0 100644 --- a/crates/re_types/src/archetypes/view_coordinates.rs +++ b/crates/re_types/src/archetypes/view_coordinates.rs @@ -62,6 +62,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; #[derive(Clone, Debug, Copy, PartialEq, Eq, bytemuck::Pod, bytemuck::Zeroable)] #[repr(transparent)] pub struct ViewCoordinates { + /// The directions of the [x, y, z] axes. pub xyz: crate::components::ViewCoordinates, } @@ -95,6 +96,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl ViewCoordinates { + /// The total number of components in the archetype: 1 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -177,6 +179,8 @@ impl ::re_types_core::AsComponents for ViewCoordinates { } impl ViewCoordinates { + /// Create a new `ViewCoordinates`. + #[inline] pub fn new(xyz: impl Into) -> Self { Self { xyz: xyz.into() } } diff --git a/crates/re_types/src/archetypes/view_coordinates_ext.rs b/crates/re_types/src/archetypes/view_coordinates_ext.rs index 18893c0f38cf..c4c568100810 100644 --- a/crates/re_types/src/archetypes/view_coordinates_ext.rs +++ b/crates/re_types/src/archetypes/view_coordinates_ext.rs @@ -3,7 +3,8 @@ use crate::{components, view_coordinates::ViewDir}; use super::ViewCoordinates; macro_rules! define_coordinates { - ($name:ident => ($x:ident, $y:ident, $z:ident) ) => { + ($docstring:literal, $name:ident => ($x:ident, $y:ident, $z:ident) ) => { + #[doc = $docstring] pub const $name: Self = Self { xyz: components::ViewCoordinates::new(ViewDir::$x, ViewDir::$y, ViewDir::$z), }; @@ -13,65 +14,65 @@ macro_rules! define_coordinates { impl ViewCoordinates { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --rust` - define_coordinates!(ULF => (Up, Left, Forward)); - define_coordinates!(UFL => (Up, Forward, Left)); - define_coordinates!(LUF => (Left, Up, Forward)); - define_coordinates!(LFU => (Left, Forward, Up)); - define_coordinates!(FUL => (Forward, Up, Left)); - define_coordinates!(FLU => (Forward, Left, Up)); - define_coordinates!(ULB => (Up, Left, Back)); - define_coordinates!(UBL => (Up, Back, Left)); - define_coordinates!(LUB => (Left, Up, Back)); - define_coordinates!(LBU => (Left, Back, Up)); - define_coordinates!(BUL => (Back, Up, Left)); - define_coordinates!(BLU => (Back, Left, Up)); - define_coordinates!(URF => (Up, Right, Forward)); - define_coordinates!(UFR => (Up, Forward, Right)); - define_coordinates!(RUF => (Right, Up, Forward)); - define_coordinates!(RFU => (Right, Forward, Up)); - define_coordinates!(FUR => (Forward, Up, Right)); - define_coordinates!(FRU => (Forward, Right, Up)); - define_coordinates!(URB => (Up, Right, Back)); - define_coordinates!(UBR => (Up, Back, Right)); - define_coordinates!(RUB => (Right, Up, Back)); - define_coordinates!(RBU => (Right, Back, Up)); - define_coordinates!(BUR => (Back, Up, Right)); - define_coordinates!(BRU => (Back, Right, Up)); - define_coordinates!(DLF => (Down, Left, Forward)); - define_coordinates!(DFL => (Down, Forward, Left)); - define_coordinates!(LDF => (Left, Down, Forward)); - define_coordinates!(LFD => (Left, Forward, Down)); - define_coordinates!(FDL => (Forward, Down, Left)); - define_coordinates!(FLD => (Forward, Left, Down)); - define_coordinates!(DLB => (Down, Left, Back)); - define_coordinates!(DBL => (Down, Back, Left)); - define_coordinates!(LDB => (Left, Down, Back)); - define_coordinates!(LBD => (Left, Back, Down)); - define_coordinates!(BDL => (Back, Down, Left)); - define_coordinates!(BLD => (Back, Left, Down)); - define_coordinates!(DRF => (Down, Right, Forward)); - define_coordinates!(DFR => (Down, Forward, Right)); - define_coordinates!(RDF => (Right, Down, Forward)); - define_coordinates!(RFD => (Right, Forward, Down)); - define_coordinates!(FDR => (Forward, Down, Right)); - define_coordinates!(FRD => (Forward, Right, Down)); - define_coordinates!(DRB => (Down, Right, Back)); - define_coordinates!(DBR => (Down, Back, Right)); - define_coordinates!(RDB => (Right, Down, Back)); - define_coordinates!(RBD => (Right, Back, Down)); - define_coordinates!(BDR => (Back, Down, Right)); - define_coordinates!(BRD => (Back, Right, Down)); - define_coordinates!(RIGHT_HAND_X_UP => (Up, Right, Forward)); - define_coordinates!(RIGHT_HAND_X_DOWN => (Down, Right, Back)); - define_coordinates!(RIGHT_HAND_Y_UP => (Right, Up, Back)); - define_coordinates!(RIGHT_HAND_Y_DOWN => (Right, Down, Forward)); - define_coordinates!(RIGHT_HAND_Z_UP => (Right, Forward, Up)); - define_coordinates!(RIGHT_HAND_Z_DOWN => (Right, Back, Down)); - define_coordinates!(LEFT_HAND_X_UP => (Up, Right, Back)); - define_coordinates!(LEFT_HAND_X_DOWN => (Down, Right, Forward)); - define_coordinates!(LEFT_HAND_Y_UP => (Right, Up, Forward)); - define_coordinates!(LEFT_HAND_Y_DOWN => (Right, Down, Back)); - define_coordinates!(LEFT_HAND_Z_UP => (Right, Back, Up)); - define_coordinates!(LEFT_HAND_Z_DOWN => (Right, Forward, Down)); + define_coordinates!("X=Up, Y=Left, Z=Forward", ULF => (Up, Left, Forward)); + define_coordinates!("X=Up, Y=Forward, Z=Left", UFL => (Up, Forward, Left)); + define_coordinates!("X=Left, Y=Up, Z=Forward", LUF => (Left, Up, Forward)); + define_coordinates!("X=Left, Y=Forward, Z=Up", LFU => (Left, Forward, Up)); + define_coordinates!("X=Forward, Y=Up, Z=Left", FUL => (Forward, Up, Left)); + define_coordinates!("X=Forward, Y=Left, Z=Up", FLU => (Forward, Left, Up)); + define_coordinates!("X=Up, Y=Left, Z=Back", ULB => (Up, Left, Back)); + define_coordinates!("X=Up, Y=Back, Z=Left", UBL => (Up, Back, Left)); + define_coordinates!("X=Left, Y=Up, Z=Back", LUB => (Left, Up, Back)); + define_coordinates!("X=Left, Y=Back, Z=Up", LBU => (Left, Back, Up)); + define_coordinates!("X=Back, Y=Up, Z=Left", BUL => (Back, Up, Left)); + define_coordinates!("X=Back, Y=Left, Z=Up", BLU => (Back, Left, Up)); + define_coordinates!("X=Up, Y=Right, Z=Forward", URF => (Up, Right, Forward)); + define_coordinates!("X=Up, Y=Forward, Z=Right", UFR => (Up, Forward, Right)); + define_coordinates!("X=Right, Y=Up, Z=Forward", RUF => (Right, Up, Forward)); + define_coordinates!("X=Right, Y=Forward, Z=Up", RFU => (Right, Forward, Up)); + define_coordinates!("X=Forward, Y=Up, Z=Right", FUR => (Forward, Up, Right)); + define_coordinates!("X=Forward, Y=Right, Z=Up", FRU => (Forward, Right, Up)); + define_coordinates!("X=Up, Y=Right, Z=Back", URB => (Up, Right, Back)); + define_coordinates!("X=Up, Y=Back, Z=Right", UBR => (Up, Back, Right)); + define_coordinates!("X=Right, Y=Up, Z=Back", RUB => (Right, Up, Back)); + define_coordinates!("X=Right, Y=Back, Z=Up", RBU => (Right, Back, Up)); + define_coordinates!("X=Back, Y=Up, Z=Right", BUR => (Back, Up, Right)); + define_coordinates!("X=Back, Y=Right, Z=Up", BRU => (Back, Right, Up)); + define_coordinates!("X=Down, Y=Left, Z=Forward", DLF => (Down, Left, Forward)); + define_coordinates!("X=Down, Y=Forward, Z=Left", DFL => (Down, Forward, Left)); + define_coordinates!("X=Left, Y=Down, Z=Forward", LDF => (Left, Down, Forward)); + define_coordinates!("X=Left, Y=Forward, Z=Down", LFD => (Left, Forward, Down)); + define_coordinates!("X=Forward, Y=Down, Z=Left", FDL => (Forward, Down, Left)); + define_coordinates!("X=Forward, Y=Left, Z=Down", FLD => (Forward, Left, Down)); + define_coordinates!("X=Down, Y=Left, Z=Back", DLB => (Down, Left, Back)); + define_coordinates!("X=Down, Y=Back, Z=Left", DBL => (Down, Back, Left)); + define_coordinates!("X=Left, Y=Down, Z=Back", LDB => (Left, Down, Back)); + define_coordinates!("X=Left, Y=Back, Z=Down", LBD => (Left, Back, Down)); + define_coordinates!("X=Back, Y=Down, Z=Left", BDL => (Back, Down, Left)); + define_coordinates!("X=Back, Y=Left, Z=Down", BLD => (Back, Left, Down)); + define_coordinates!("X=Down, Y=Right, Z=Forward", DRF => (Down, Right, Forward)); + define_coordinates!("X=Down, Y=Forward, Z=Right", DFR => (Down, Forward, Right)); + define_coordinates!("X=Right, Y=Down, Z=Forward", RDF => (Right, Down, Forward)); + define_coordinates!("X=Right, Y=Forward, Z=Down", RFD => (Right, Forward, Down)); + define_coordinates!("X=Forward, Y=Down, Z=Right", FDR => (Forward, Down, Right)); + define_coordinates!("X=Forward, Y=Right, Z=Down", FRD => (Forward, Right, Down)); + define_coordinates!("X=Down, Y=Right, Z=Back", DRB => (Down, Right, Back)); + define_coordinates!("X=Down, Y=Back, Z=Right", DBR => (Down, Back, Right)); + define_coordinates!("X=Right, Y=Down, Z=Back", RDB => (Right, Down, Back)); + define_coordinates!("X=Right, Y=Back, Z=Down", RBD => (Right, Back, Down)); + define_coordinates!("X=Back, Y=Down, Z=Right", BDR => (Back, Down, Right)); + define_coordinates!("X=Back, Y=Right, Z=Down", BRD => (Back, Right, Down)); + define_coordinates!("X=Up, Y=Right, Z=Forward", RIGHT_HAND_X_UP => (Up, Right, Forward)); + define_coordinates!("X=Down, Y=Right, Z=Back", RIGHT_HAND_X_DOWN => (Down, Right, Back)); + define_coordinates!("X=Right, Y=Up, Z=Back", RIGHT_HAND_Y_UP => (Right, Up, Back)); + define_coordinates!("X=Right, Y=Down, Z=Forward", RIGHT_HAND_Y_DOWN => (Right, Down, Forward)); + define_coordinates!("X=Right, Y=Forward, Z=Up", RIGHT_HAND_Z_UP => (Right, Forward, Up)); + define_coordinates!("X=Right, Y=Back, Z=Down", RIGHT_HAND_Z_DOWN => (Right, Back, Down)); + define_coordinates!("X=Up, Y=Right, Z=Back", LEFT_HAND_X_UP => (Up, Right, Back)); + define_coordinates!("X=Down, Y=Right, Z=Forward", LEFT_HAND_X_DOWN => (Down, Right, Forward)); + define_coordinates!("X=Right, Y=Up, Z=Forward", LEFT_HAND_Y_UP => (Right, Up, Forward)); + define_coordinates!("X=Right, Y=Down, Z=Back", LEFT_HAND_Y_DOWN => (Right, Down, Back)); + define_coordinates!("X=Right, Y=Back, Z=Up", LEFT_HAND_Z_UP => (Right, Back, Up)); + define_coordinates!("X=Right, Y=Forward, Z=Down", LEFT_HAND_Z_DOWN => (Right, Forward, Down)); // } diff --git a/crates/re_types/src/blueprint/archetypes/background.rs b/crates/re_types/src/blueprint/archetypes/background.rs index 3c11b72d6785..e7f56fed6497 100644 --- a/crates/re_types/src/blueprint/archetypes/background.rs +++ b/crates/re_types/src/blueprint/archetypes/background.rs @@ -66,6 +66,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = }); impl Background { + /// The total number of components in the archetype: 1 required, 1 recommended, 1 optional pub const NUM_COMPONENTS: usize = 3usize; } @@ -160,6 +161,8 @@ impl ::re_types_core::AsComponents for Background { } impl Background { + /// Create a new `Background`. + #[inline] pub fn new(kind: impl Into) -> Self { Self { kind: kind.into(), @@ -167,6 +170,9 @@ impl Background { } } + /// Color used for BackgroundKind.SolidColor. + /// + /// Defaults to White. #[inline] pub fn with_color(mut self, color: impl Into) -> Self { self.color = Some(color.into()); diff --git a/crates/re_types/src/blueprint/archetypes/plot_legend.rs b/crates/re_types/src/blueprint/archetypes/plot_legend.rs index 19d72afe8641..bce489f8ff2e 100644 --- a/crates/re_types/src/blueprint/archetypes/plot_legend.rs +++ b/crates/re_types/src/blueprint/archetypes/plot_legend.rs @@ -73,6 +73,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = }); impl PlotLegend { + /// The total number of components in the archetype: 0 required, 1 recommended, 2 optional pub const NUM_COMPONENTS: usize = 3usize; } @@ -167,6 +168,8 @@ impl ::re_types_core::AsComponents for PlotLegend { } impl PlotLegend { + /// Create a new `PlotLegend`. + #[inline] pub fn new() -> Self { Self { corner: None, @@ -174,6 +177,9 @@ impl PlotLegend { } } + /// To what corner the legend is aligned. + /// + /// Defaults to the right bottom corner. #[inline] pub fn with_corner( mut self, @@ -183,6 +189,9 @@ impl PlotLegend { self } + /// Whether the legend is shown at all. + /// + /// True by default. #[inline] pub fn with_visible( mut self, diff --git a/crates/re_types/src/blueprint/archetypes/scalar_axis.rs b/crates/re_types/src/blueprint/archetypes/scalar_axis.rs index af7a36b6cae1..06f4cf279c94 100644 --- a/crates/re_types/src/blueprint/archetypes/scalar_axis.rs +++ b/crates/re_types/src/blueprint/archetypes/scalar_axis.rs @@ -71,6 +71,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = }); impl ScalarAxis { + /// The total number of components in the archetype: 0 required, 1 recommended, 2 optional pub const NUM_COMPONENTS: usize = 3usize; } @@ -168,6 +169,8 @@ impl ::re_types_core::AsComponents for ScalarAxis { } impl ScalarAxis { + /// Create a new `ScalarAxis`. + #[inline] pub fn new() -> Self { Self { range: None, @@ -175,12 +178,16 @@ impl ScalarAxis { } } + /// The range of the axis. + /// + /// If unset, the range well be automatically determined based on the queried data. #[inline] pub fn with_range(mut self, range: impl Into) -> Self { self.range = Some(range.into()); self } + /// Whether to lock the range of the axis during zoom. #[inline] pub fn with_lock_range_during_zoom( mut self, diff --git a/crates/re_types/src/blueprint/archetypes/space_view_blueprint.rs b/crates/re_types/src/blueprint/archetypes/space_view_blueprint.rs index 7df38d615475..3f5164b7e109 100644 --- a/crates/re_types/src/blueprint/archetypes/space_view_blueprint.rs +++ b/crates/re_types/src/blueprint/archetypes/space_view_blueprint.rs @@ -93,6 +93,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = }); impl SpaceViewBlueprint { + /// The total number of components in the archetype: 1 required, 1 recommended, 3 optional pub const NUM_COMPONENTS: usize = 5usize; } @@ -219,6 +220,8 @@ impl ::re_types_core::AsComponents for SpaceViewBlueprint { } impl SpaceViewBlueprint { + /// Create a new `SpaceViewBlueprint`. + #[inline] pub fn new(class_identifier: impl Into) -> Self { Self { class_identifier: class_identifier.into(), @@ -228,12 +231,20 @@ impl SpaceViewBlueprint { } } + /// The name of the view. #[inline] pub fn with_display_name(mut self, display_name: impl Into) -> Self { self.display_name = Some(display_name.into()); self } + /// The "anchor point" of this space 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 space view. + /// I.e. the position of this entity path in space forms the origin of the coordinate system in this space view. + /// Furthermore, this is the primary indicator for heuristics on what entities we show in this space view. #[inline] pub fn with_space_origin( mut self, @@ -243,6 +254,9 @@ impl SpaceViewBlueprint { self } + /// Whether this space view is visible. + /// + /// Defaults to true if not specified. #[inline] pub fn with_visible( mut self, diff --git a/crates/re_types/src/blueprint/archetypes/space_view_contents.rs b/crates/re_types/src/blueprint/archetypes/space_view_contents.rs index 97b59c85484b..b1020fe1ac28 100644 --- a/crates/re_types/src/blueprint/archetypes/space_view_contents.rs +++ b/crates/re_types/src/blueprint/archetypes/space_view_contents.rs @@ -98,6 +98,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl SpaceViewContents { + /// The total number of components in the archetype: 0 required, 1 recommended, 1 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -179,6 +180,8 @@ impl ::re_types_core::AsComponents for SpaceViewContents { } impl SpaceViewContents { + /// Create a new `SpaceViewContents`. + #[inline] pub fn new( query: impl IntoIterator>, ) -> Self { diff --git a/crates/re_types/src/blueprint/archetypes/visual_bounds.rs b/crates/re_types/src/blueprint/archetypes/visual_bounds.rs index f6e3a0c1fc12..c553273d1308 100644 --- a/crates/re_types/src/blueprint/archetypes/visual_bounds.rs +++ b/crates/re_types/src/blueprint/archetypes/visual_bounds.rs @@ -62,6 +62,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl VisualBounds { + /// The total number of components in the archetype: 0 required, 1 recommended, 1 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -142,12 +143,18 @@ impl ::re_types_core::AsComponents for VisualBounds { } impl VisualBounds { + /// Create a new `VisualBounds`. + #[inline] pub fn new() -> Self { Self { visual_bounds: None, } } + /// The visible parts of a 2D space view, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. #[inline] pub fn with_visual_bounds( mut self, diff --git a/crates/re_types/src/blueprint/components/corner2d.rs b/crates/re_types/src/blueprint/components/corner2d.rs index 4a722007809b..82063ebd8c45 100644 --- a/crates/re_types/src/blueprint/components/corner2d.rs +++ b/crates/re_types/src/blueprint/components/corner2d.rs @@ -25,9 +25,16 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: One of four 2D corners, typically used to align objects. #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] pub enum Corner2D { + /// Left top corner. LeftTop = 1, + + /// Right top corner. RightTop = 2, + + /// Left bottom corner. LeftBottom = 3, + + /// Right bottom corner. #[default] RightBottom = 4, } diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs index a93c32dce2be..d4ce92441b81 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs @@ -2,11 +2,16 @@ use super::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}; use re_types_core::datatypes::TimeInt; impl VisibleTimeRangeBoundary { + /// Put the boundary at the current time cursor. pub const AT_CURSOR: Self = Self { kind: VisibleTimeRangeBoundaryKind::RelativeToTimeCursor, time: TimeInt(0), }; + /// The boundary extends to infinity. + /// + /// For minimum bounds, this mean the minimum time (-∞), + /// and for maximum bounds, this means the maximum time (+∞). pub const INFINITE: Self = Self { kind: VisibleTimeRangeBoundaryKind::Infinite, time: TimeInt(0), diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs index d1b1dd7ea1d4..7de1d58ce394 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs @@ -1,13 +1,18 @@ use super::{VisibleTimeRange, VisibleTimeRangeBoundary}; impl VisibleTimeRange { + /// The empty range, set at the current time cursor. pub const EMPTY: Self = Self { start: VisibleTimeRangeBoundary::AT_CURSOR, end: VisibleTimeRangeBoundary::AT_CURSOR, }; + /// The range encompassing all time, from -∞ to +∞. pub const EVERYTHING: Self = Self { + // This means -∞ start: VisibleTimeRangeBoundary::INFINITE, + + // This means +∞ end: VisibleTimeRangeBoundary::INFINITE, }; } diff --git a/crates/re_types/src/blueprint/mod.rs b/crates/re_types/src/blueprint/mod.rs index 928ed41f1340..e11bdf9dfd53 100644 --- a/crates/re_types/src/blueprint/mod.rs +++ b/crates/re_types/src/blueprint/mod.rs @@ -1,3 +1,8 @@ +/// The blueprint-specific archetypes. pub mod archetypes; + +/// The blueprint-specific components. pub mod components; + +/// The blueprint-specific datatypes. pub mod datatypes; diff --git a/crates/re_types/src/components/color_ext.rs b/crates/re_types/src/components/color_ext.rs index 0f7e52c0410c..d0b2d8b073dc 100644 --- a/crates/re_types/src/components/color_ext.rs +++ b/crates/re_types/src/components/color_ext.rs @@ -1,15 +1,22 @@ use super::Color; impl Color { + /// Black and opaque. pub const BLACK: Self = Self(crate::datatypes::Rgba32::BLACK); + + /// White and opaque. pub const WHITE: Self = Self(crate::datatypes::Rgba32::WHITE); + + /// Fully transparent (invisible). pub const TRANSPARENT: Self = Self(crate::datatypes::Rgba32::TRANSPARENT); + /// From gamma-space sRGB values. #[inline] pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { Self::from([r, g, b, 255]) } + /// From gamma-space sRGB values, with a separate/unmultiplied alpha in linear-space. #[inline] pub fn from_unmultiplied_rgba(r: u8, g: u8, b: u8, a: u8) -> Self { Self::from(crate::datatypes::Rgba32::from_unmultiplied_rgba(r, g, b, a)) @@ -40,6 +47,7 @@ impl Color { } impl Color { + /// Create a new color. #[inline] pub fn new(value: impl Into) -> Self { Self(value.into()) diff --git a/crates/re_types/src/components/half_sizes2d_ext.rs b/crates/re_types/src/components/half_sizes2d_ext.rs index 8fbb2430c7fa..cfd036786228 100644 --- a/crates/re_types/src/components/half_sizes2d_ext.rs +++ b/crates/re_types/src/components/half_sizes2d_ext.rs @@ -3,9 +3,10 @@ use crate::datatypes::Vec2D; use super::HalfSizes2D; impl HalfSizes2D { + /// Create a new half-extent from half-width and half-height. #[inline] - pub const fn new(x: f32, y: f32) -> Self { - Self(Vec2D::new(x, y)) + pub const fn new(half_width: f32, half_height: f32) -> Self { + Self(Vec2D::new(half_width, half_height)) } /// Width of a box using this half-extent. diff --git a/crates/re_types/src/components/half_sizes3d_ext.rs b/crates/re_types/src/components/half_sizes3d_ext.rs index 23fec9fb410c..d5e21ec3faba 100644 --- a/crates/re_types/src/components/half_sizes3d_ext.rs +++ b/crates/re_types/src/components/half_sizes3d_ext.rs @@ -3,9 +3,10 @@ use crate::datatypes::Vec3D; use super::HalfSizes3D; impl HalfSizes3D { + /// Create a new half-extent from half-width, half-height, half-depth. #[inline] - pub const fn new(x: f32, y: f32, z: f32) -> Self { - Self(Vec3D::new(x, y, z)) + pub const fn new(half_width: f32, half_height: f32, half_depth: f32) -> Self { + Self(Vec3D::new(half_width, half_height, half_depth)) } /// Width of a box using this half-extent. diff --git a/crates/re_types/src/components/line_strip2d_ext.rs b/crates/re_types/src/components/line_strip2d_ext.rs index fcd307204bca..b1e5143ca707 100644 --- a/crates/re_types/src/components/line_strip2d_ext.rs +++ b/crates/re_types/src/components/line_strip2d_ext.rs @@ -5,6 +5,7 @@ use super::LineStrip2D; // --- impl LineStrip2D { + /// Create a new line strip from a list of positions. #[allow(clippy::should_implement_trait)] // vanilla `FromIter` is too limiting in what it can express pub fn from_iter(points: impl IntoIterator>) -> Self { Self(points.into_iter().map(Into::into).collect()) diff --git a/crates/re_types/src/components/line_strip3d_ext.rs b/crates/re_types/src/components/line_strip3d_ext.rs index 545b1bacbe4e..9c90f195c826 100644 --- a/crates/re_types/src/components/line_strip3d_ext.rs +++ b/crates/re_types/src/components/line_strip3d_ext.rs @@ -5,6 +5,7 @@ use super::LineStrip3D; // --- impl LineStrip3D { + /// Construct a line strip from a sequence of points. #[allow(clippy::should_implement_trait)] // vanilla `FromIter` is too limiting in what it can express pub fn from_iter(points: impl IntoIterator>) -> Self { Self(points.into_iter().map(Into::into).collect()) diff --git a/crates/re_types/src/components/marker_shape.rs b/crates/re_types/src/components/marker_shape.rs index 3a070752a9b0..7e3604d646cf 100644 --- a/crates/re_types/src/components/marker_shape.rs +++ b/crates/re_types/src/components/marker_shape.rs @@ -25,16 +25,35 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Shape of a marker. #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] pub enum MarkerShape { + /// `⏺` #[default] Circle = 1, + + /// `◆` Diamond = 2, + + /// `◼️` Square = 3, + + /// `x` Cross = 4, + + /// `+` Plus = 5, + + /// `▲` Up = 6, + + /// `▼` Down = 7, + + /// `◀` Left = 8, + + /// `▶` Right = 9, + + /// `*` Asterisk = 10, } diff --git a/crates/re_types/src/components/material_ext.rs b/crates/re_types/src/components/material_ext.rs index bab929d7d4e4..f5a4a1fd2f2e 100644 --- a/crates/re_types/src/components/material_ext.rs +++ b/crates/re_types/src/components/material_ext.rs @@ -3,6 +3,7 @@ use crate::datatypes::Rgba32; use super::Material; impl Material { + /// A new material using a given color multiplier. #[inline] pub fn from_albedo_factor(color: impl Into) -> Self { Self(crate::datatypes::Material::from_albedo_factor(color)) diff --git a/crates/re_types/src/components/media_type_ext.rs b/crates/re_types/src/components/media_type_ext.rs index d64d23b7ba8d..5811a08a7698 100644 --- a/crates/re_types/src/components/media_type_ext.rs +++ b/crates/re_types/src/components/media_type_ext.rs @@ -72,6 +72,7 @@ impl MediaType { } impl MediaType { + /// Returns the media type as a string slice, e.g. "text/plain". #[inline] pub fn as_str(&self) -> &str { self.0.as_str() diff --git a/crates/re_types/src/components/mesh_properties_ext.rs b/crates/re_types/src/components/mesh_properties_ext.rs index 0bb4741f4fef..e8c99dcfa6dc 100644 --- a/crates/re_types/src/components/mesh_properties_ext.rs +++ b/crates/re_types/src/components/mesh_properties_ext.rs @@ -3,6 +3,10 @@ use crate::datatypes::UVec3D; use super::MeshProperties; impl MeshProperties { + /// Create a new [`MeshProperties`] from an iterable of the triangle indices. + /// + /// Each triangle is defined by a [`UVec3D`] (or something that can be converted into it), + /// where the 3 values are the indices of the 3 vertices of the triangle. #[inline] pub fn from_triangle_indices(indices: impl IntoIterator>) -> Self { Self(crate::datatypes::MeshProperties::from_triangle_indices( diff --git a/crates/re_types/src/components/name_ext.rs b/crates/re_types/src/components/name_ext.rs index 8e723adb6160..f66c539e829b 100644 --- a/crates/re_types/src/components/name_ext.rs +++ b/crates/re_types/src/components/name_ext.rs @@ -2,6 +2,7 @@ use super::Name; // TODO(#4536): These should come for free impl Name { + /// Returns the name as a string slice. #[inline] pub fn as_str(&self) -> &str { self.0.as_str() diff --git a/crates/re_types/src/components/pinhole_projection_ext.rs b/crates/re_types/src/components/pinhole_projection_ext.rs index 9895acff5105..28bec2cf8e75 100644 --- a/crates/re_types/src/components/pinhole_projection_ext.rs +++ b/crates/re_types/src/components/pinhole_projection_ext.rs @@ -3,6 +3,7 @@ use crate::datatypes::Vec2D; use super::PinholeProjection; impl PinholeProjection { + /// Create a new pinhole projection matrix from a focal length and principal point. #[inline] pub fn from_focal_length_and_principal_point( focal_length: impl Into, diff --git a/crates/re_types/src/components/position2d_ext.rs b/crates/re_types/src/components/position2d_ext.rs index 782993576868..3b11642b14e6 100644 --- a/crates/re_types/src/components/position2d_ext.rs +++ b/crates/re_types/src/components/position2d_ext.rs @@ -5,19 +5,22 @@ use super::Position2D; // --- impl Position2D { + /// The origin. pub const ZERO: Self = Self::new(0.0, 0.0); - pub const ONE: Self = Self::new(1.0, 1.0); + /// Create a new position. #[inline] pub const fn new(x: f32, y: f32) -> Self { Self(Vec2D::new(x, y)) } + /// The x coordinate, i.e. index 0 #[inline] pub fn x(&self) -> f32 { self.0.x() } + /// The y coordinate, i.e. index 1 #[inline] pub fn y(&self) -> f32 { self.0.y() diff --git a/crates/re_types/src/components/position3d_ext.rs b/crates/re_types/src/components/position3d_ext.rs index 9712ffaeb69e..a28ea7b61c59 100644 --- a/crates/re_types/src/components/position3d_ext.rs +++ b/crates/re_types/src/components/position3d_ext.rs @@ -5,24 +5,28 @@ use super::Position3D; // --- impl Position3D { + /// The origin. pub const ZERO: Self = Self::new(0.0, 0.0, 0.0); - pub const ONE: Self = Self::new(1.0, 1.0, 1.0); + /// Create a new position. #[inline] pub const fn new(x: f32, y: f32, z: f32) -> Self { Self(Vec3D::new(x, y, z)) } + /// The x coordinate, i.e. index 0 #[inline] pub fn x(&self) -> f32 { self.0.x() } + /// The y coordinate, i.e. index 1 #[inline] pub fn y(&self) -> f32 { self.0.y() } + /// The z coordinate, i.e. index 2 #[inline] pub fn z(&self) -> f32 { self.0.z() diff --git a/crates/re_types/src/components/radius_ext.rs b/crates/re_types/src/components/radius_ext.rs index c6562c87a04c..c5f6d08067e0 100644 --- a/crates/re_types/src/components/radius_ext.rs +++ b/crates/re_types/src/components/radius_ext.rs @@ -1,7 +1,10 @@ use super::Radius; impl Radius { + /// Zero radius. pub const ZERO: Self = Self(0.0); + + /// Unit radius. pub const ONE: Self = Self(1.0); } diff --git a/crates/re_types/src/components/range1d_ext.rs b/crates/re_types/src/components/range1d_ext.rs index de5046b2c947..d9c3eb153c3f 100644 --- a/crates/re_types/src/components/range1d_ext.rs +++ b/crates/re_types/src/components/range1d_ext.rs @@ -3,16 +3,19 @@ use crate::datatypes; use super::Range1D; impl Range1D { + /// Create a new range. #[inline] pub fn new(start: f64, end: f64) -> Self { Self(datatypes::Range1D([start, end])) } + /// The start of the range. #[inline] pub fn start(&self) -> f64 { self.0 .0[0] } + /// The end of the range. #[inline] pub fn end(&self) -> f64 { self.0 .0[1] diff --git a/crates/re_types/src/components/rotation3d_ext.rs b/crates/re_types/src/components/rotation3d_ext.rs index d53c966c7b84..f6d8cedc5ea9 100644 --- a/crates/re_types/src/components/rotation3d_ext.rs +++ b/crates/re_types/src/components/rotation3d_ext.rs @@ -3,6 +3,7 @@ use crate::datatypes::{self}; use super::Rotation3D; impl Rotation3D { + /// The identity rotation, i.e. no rotation at all. pub const IDENTITY: Self = Self(datatypes::Rotation3D::IDENTITY); } diff --git a/crates/re_types/src/components/texcoord2d_ext.rs b/crates/re_types/src/components/texcoord2d_ext.rs index 653cb76762d5..c5486005df32 100644 --- a/crates/re_types/src/components/texcoord2d_ext.rs +++ b/crates/re_types/src/components/texcoord2d_ext.rs @@ -5,19 +5,25 @@ use super::Texcoord2D; // --- impl Texcoord2D { + /// The origin. pub const ZERO: Self = Self::new(0.0, 0.0); + + /// The corner opposite the origin. pub const ONE: Self = Self::new(1.0, 1.0); + /// Create a new texture coordinate. #[inline] pub const fn new(u: f32, v: f32) -> Self { Self(Vec2D::new(u, v)) } + /// The first coordinate, i.e. index 0. #[inline] pub fn u(&self) -> f32 { self.0.x() } + /// The second coordinate, i.e. index 1. #[inline] pub fn v(&self) -> f32 { self.0.y() diff --git a/crates/re_types/src/components/text_ext.rs b/crates/re_types/src/components/text_ext.rs index d262379bf37e..aba9142b523b 100644 --- a/crates/re_types/src/components/text_ext.rs +++ b/crates/re_types/src/components/text_ext.rs @@ -1,6 +1,7 @@ use super::Text; impl Text { + /// The text as a string slice. #[inline] pub fn as_str(&self) -> &str { self.0.as_str() diff --git a/crates/re_types/src/components/text_log_level_ext.rs b/crates/re_types/src/components/text_log_level_ext.rs index ac9c5e7d698c..81f8e8e65de6 100644 --- a/crates/re_types/src/components/text_log_level_ext.rs +++ b/crates/re_types/src/components/text_log_level_ext.rs @@ -19,6 +19,7 @@ impl TextLogLevel { /// Designates very low priority, often extremely verbose, information. pub const TRACE: &'static str = "TRACE"; + /// The log level as a string slice, e.g. "INFO". #[inline] pub fn as_str(&self) -> &str { self.0.as_str() diff --git a/crates/re_types/src/components/transform3d_ext.rs b/crates/re_types/src/components/transform3d_ext.rs index 7b59584279d1..18a88dd076b8 100644 --- a/crates/re_types/src/components/transform3d_ext.rs +++ b/crates/re_types/src/components/transform3d_ext.rs @@ -76,6 +76,12 @@ impl Transform3D { #[cfg(feature = "glam")] impl Transform3D { + /// Returns the transform from child space to the parent space. + /// + /// For instance, if we have an entity at position `[1, 2, 3]` in the parent space, + /// then this transform would be the translation `+[1, 2, 3]`, + /// transforming the child's origin `[0, 0, 0]` to its position + /// in parent space (`[1, 2, 3]`). #[inline] pub fn into_parent_from_child_transform(self) -> glam::Affine3A { let transform: glam::Affine3A = self.0.into(); @@ -86,6 +92,9 @@ impl Transform3D { } } + /// Returns the transform from parent space to the child space. + /// + /// This is the inverse of [`Self::into_parent_from_child_transform`]. #[inline] pub fn into_child_from_parent_transform(self) -> glam::Affine3A { let transform: glam::Affine3A = self.0.into(); diff --git a/crates/re_types/src/components/vector2d_ext.rs b/crates/re_types/src/components/vector2d_ext.rs index db487e54e456..d6f48f4550ca 100644 --- a/crates/re_types/src/components/vector2d_ext.rs +++ b/crates/re_types/src/components/vector2d_ext.rs @@ -1,7 +1,10 @@ use super::Vector2D; impl Vector2D { + /// The zero vector, i.e. the additive identity. pub const ZERO: Self = Self(crate::datatypes::Vec2D::ZERO); + + /// `[1, 1]`, i.e. the multiplicative identity. pub const ONE: Self = Self(crate::datatypes::Vec2D::ONE); } diff --git a/crates/re_types/src/components/vector3d_ext.rs b/crates/re_types/src/components/vector3d_ext.rs index 73d380ecb892..543c93ba98b6 100644 --- a/crates/re_types/src/components/vector3d_ext.rs +++ b/crates/re_types/src/components/vector3d_ext.rs @@ -1,7 +1,10 @@ use super::Vector3D; impl Vector3D { + /// The zero vector, i.e. the additive identity. pub const ZERO: Self = Self(crate::datatypes::Vec3D::ZERO); + + /// `[1, 1, 1]`, i.e. the multiplicative identity. pub const ONE: Self = Self(crate::datatypes::Vec3D::ONE); } diff --git a/crates/re_types/src/components/view_coordinates_ext.rs b/crates/re_types/src/components/view_coordinates_ext.rs index 9637441db83a..c9221c42b851 100644 --- a/crates/re_types/src/components/view_coordinates_ext.rs +++ b/crates/re_types/src/components/view_coordinates_ext.rs @@ -56,6 +56,7 @@ impl ViewCoordinates { } } + /// The up-axis. #[inline] pub fn up(&self) -> Option { for (dim, &dir) in self.0.iter().enumerate() { @@ -68,6 +69,7 @@ impl ViewCoordinates { None } + /// The right-axis. #[inline] pub fn right(&self) -> Option { for (dim, &dir) in self.0.iter().enumerate() { @@ -80,6 +82,7 @@ impl ViewCoordinates { None } + /// The forward-axis. #[inline] pub fn forward(&self) -> Option { for (dim, &dir) in self.0.iter().enumerate() { @@ -92,6 +95,7 @@ impl ViewCoordinates { None } + /// Describe using three letters, e.g. `RDF` for X=Right, Y=Down, Z=Forward. pub fn describe_short(&self) -> String { let [x, y, z] = self.0; let x = ViewDir::try_from(x).map(|x| x.short()).unwrap_or("?"); @@ -100,6 +104,7 @@ impl ViewCoordinates { format!("{x}{y}{z}") } + /// A long description of the coordinate system, explicitly writing out all directions. pub fn describe(&self) -> String { let [x, y, z] = self.0; let x_short = ViewDir::try_from(x).map(|x| x.short()).unwrap_or("?"); @@ -216,6 +221,9 @@ impl ViewCoordinates { } } + /// Returns whether or not this coordinate system is left or right handed. + /// + /// If the coordinate system is degenerate, an error is returned. #[cfg(feature = "glam")] #[inline] pub fn handedness(&self) -> Result { @@ -254,7 +262,8 @@ impl std::str::FromStr for ViewCoordinates { // ---------------------------------------------------------------------------- macro_rules! define_coordinates { - ($name:ident => ($x:ident, $y:ident, $z:ident) ) => { + ($docstring:literal, $name:ident => ($x:ident, $y:ident, $z:ident) ) => { + #[doc = $docstring] pub const $name: Self = Self([ViewDir::$x as u8, ViewDir::$y as u8, ViewDir::$z as u8]); }; } @@ -262,65 +271,65 @@ macro_rules! define_coordinates { impl ViewCoordinates { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --rust` - define_coordinates!(ULF => (Up, Left, Forward)); - define_coordinates!(UFL => (Up, Forward, Left)); - define_coordinates!(LUF => (Left, Up, Forward)); - define_coordinates!(LFU => (Left, Forward, Up)); - define_coordinates!(FUL => (Forward, Up, Left)); - define_coordinates!(FLU => (Forward, Left, Up)); - define_coordinates!(ULB => (Up, Left, Back)); - define_coordinates!(UBL => (Up, Back, Left)); - define_coordinates!(LUB => (Left, Up, Back)); - define_coordinates!(LBU => (Left, Back, Up)); - define_coordinates!(BUL => (Back, Up, Left)); - define_coordinates!(BLU => (Back, Left, Up)); - define_coordinates!(URF => (Up, Right, Forward)); - define_coordinates!(UFR => (Up, Forward, Right)); - define_coordinates!(RUF => (Right, Up, Forward)); - define_coordinates!(RFU => (Right, Forward, Up)); - define_coordinates!(FUR => (Forward, Up, Right)); - define_coordinates!(FRU => (Forward, Right, Up)); - define_coordinates!(URB => (Up, Right, Back)); - define_coordinates!(UBR => (Up, Back, Right)); - define_coordinates!(RUB => (Right, Up, Back)); - define_coordinates!(RBU => (Right, Back, Up)); - define_coordinates!(BUR => (Back, Up, Right)); - define_coordinates!(BRU => (Back, Right, Up)); - define_coordinates!(DLF => (Down, Left, Forward)); - define_coordinates!(DFL => (Down, Forward, Left)); - define_coordinates!(LDF => (Left, Down, Forward)); - define_coordinates!(LFD => (Left, Forward, Down)); - define_coordinates!(FDL => (Forward, Down, Left)); - define_coordinates!(FLD => (Forward, Left, Down)); - define_coordinates!(DLB => (Down, Left, Back)); - define_coordinates!(DBL => (Down, Back, Left)); - define_coordinates!(LDB => (Left, Down, Back)); - define_coordinates!(LBD => (Left, Back, Down)); - define_coordinates!(BDL => (Back, Down, Left)); - define_coordinates!(BLD => (Back, Left, Down)); - define_coordinates!(DRF => (Down, Right, Forward)); - define_coordinates!(DFR => (Down, Forward, Right)); - define_coordinates!(RDF => (Right, Down, Forward)); - define_coordinates!(RFD => (Right, Forward, Down)); - define_coordinates!(FDR => (Forward, Down, Right)); - define_coordinates!(FRD => (Forward, Right, Down)); - define_coordinates!(DRB => (Down, Right, Back)); - define_coordinates!(DBR => (Down, Back, Right)); - define_coordinates!(RDB => (Right, Down, Back)); - define_coordinates!(RBD => (Right, Back, Down)); - define_coordinates!(BDR => (Back, Down, Right)); - define_coordinates!(BRD => (Back, Right, Down)); - define_coordinates!(RIGHT_HAND_X_UP => (Up, Right, Forward)); - define_coordinates!(RIGHT_HAND_X_DOWN => (Down, Right, Back)); - define_coordinates!(RIGHT_HAND_Y_UP => (Right, Up, Back)); - define_coordinates!(RIGHT_HAND_Y_DOWN => (Right, Down, Forward)); - define_coordinates!(RIGHT_HAND_Z_UP => (Right, Forward, Up)); - define_coordinates!(RIGHT_HAND_Z_DOWN => (Right, Back, Down)); - define_coordinates!(LEFT_HAND_X_UP => (Up, Right, Back)); - define_coordinates!(LEFT_HAND_X_DOWN => (Down, Right, Forward)); - define_coordinates!(LEFT_HAND_Y_UP => (Right, Up, Forward)); - define_coordinates!(LEFT_HAND_Y_DOWN => (Right, Down, Back)); - define_coordinates!(LEFT_HAND_Z_UP => (Right, Back, Up)); - define_coordinates!(LEFT_HAND_Z_DOWN => (Right, Forward, Down)); + define_coordinates!("X=Up, Y=Left, Z=Forward", ULF => (Up, Left, Forward)); + define_coordinates!("X=Up, Y=Forward, Z=Left", UFL => (Up, Forward, Left)); + define_coordinates!("X=Left, Y=Up, Z=Forward", LUF => (Left, Up, Forward)); + define_coordinates!("X=Left, Y=Forward, Z=Up", LFU => (Left, Forward, Up)); + define_coordinates!("X=Forward, Y=Up, Z=Left", FUL => (Forward, Up, Left)); + define_coordinates!("X=Forward, Y=Left, Z=Up", FLU => (Forward, Left, Up)); + define_coordinates!("X=Up, Y=Left, Z=Back", ULB => (Up, Left, Back)); + define_coordinates!("X=Up, Y=Back, Z=Left", UBL => (Up, Back, Left)); + define_coordinates!("X=Left, Y=Up, Z=Back", LUB => (Left, Up, Back)); + define_coordinates!("X=Left, Y=Back, Z=Up", LBU => (Left, Back, Up)); + define_coordinates!("X=Back, Y=Up, Z=Left", BUL => (Back, Up, Left)); + define_coordinates!("X=Back, Y=Left, Z=Up", BLU => (Back, Left, Up)); + define_coordinates!("X=Up, Y=Right, Z=Forward", URF => (Up, Right, Forward)); + define_coordinates!("X=Up, Y=Forward, Z=Right", UFR => (Up, Forward, Right)); + define_coordinates!("X=Right, Y=Up, Z=Forward", RUF => (Right, Up, Forward)); + define_coordinates!("X=Right, Y=Forward, Z=Up", RFU => (Right, Forward, Up)); + define_coordinates!("X=Forward, Y=Up, Z=Right", FUR => (Forward, Up, Right)); + define_coordinates!("X=Forward, Y=Right, Z=Up", FRU => (Forward, Right, Up)); + define_coordinates!("X=Up, Y=Right, Z=Back", URB => (Up, Right, Back)); + define_coordinates!("X=Up, Y=Back, Z=Right", UBR => (Up, Back, Right)); + define_coordinates!("X=Right, Y=Up, Z=Back", RUB => (Right, Up, Back)); + define_coordinates!("X=Right, Y=Back, Z=Up", RBU => (Right, Back, Up)); + define_coordinates!("X=Back, Y=Up, Z=Right", BUR => (Back, Up, Right)); + define_coordinates!("X=Back, Y=Right, Z=Up", BRU => (Back, Right, Up)); + define_coordinates!("X=Down, Y=Left, Z=Forward", DLF => (Down, Left, Forward)); + define_coordinates!("X=Down, Y=Forward, Z=Left", DFL => (Down, Forward, Left)); + define_coordinates!("X=Left, Y=Down, Z=Forward", LDF => (Left, Down, Forward)); + define_coordinates!("X=Left, Y=Forward, Z=Down", LFD => (Left, Forward, Down)); + define_coordinates!("X=Forward, Y=Down, Z=Left", FDL => (Forward, Down, Left)); + define_coordinates!("X=Forward, Y=Left, Z=Down", FLD => (Forward, Left, Down)); + define_coordinates!("X=Down, Y=Left, Z=Back", DLB => (Down, Left, Back)); + define_coordinates!("X=Down, Y=Back, Z=Left", DBL => (Down, Back, Left)); + define_coordinates!("X=Left, Y=Down, Z=Back", LDB => (Left, Down, Back)); + define_coordinates!("X=Left, Y=Back, Z=Down", LBD => (Left, Back, Down)); + define_coordinates!("X=Back, Y=Down, Z=Left", BDL => (Back, Down, Left)); + define_coordinates!("X=Back, Y=Left, Z=Down", BLD => (Back, Left, Down)); + define_coordinates!("X=Down, Y=Right, Z=Forward", DRF => (Down, Right, Forward)); + define_coordinates!("X=Down, Y=Forward, Z=Right", DFR => (Down, Forward, Right)); + define_coordinates!("X=Right, Y=Down, Z=Forward", RDF => (Right, Down, Forward)); + define_coordinates!("X=Right, Y=Forward, Z=Down", RFD => (Right, Forward, Down)); + define_coordinates!("X=Forward, Y=Down, Z=Right", FDR => (Forward, Down, Right)); + define_coordinates!("X=Forward, Y=Right, Z=Down", FRD => (Forward, Right, Down)); + define_coordinates!("X=Down, Y=Right, Z=Back", DRB => (Down, Right, Back)); + define_coordinates!("X=Down, Y=Back, Z=Right", DBR => (Down, Back, Right)); + define_coordinates!("X=Right, Y=Down, Z=Back", RDB => (Right, Down, Back)); + define_coordinates!("X=Right, Y=Back, Z=Down", RBD => (Right, Back, Down)); + define_coordinates!("X=Back, Y=Down, Z=Right", BDR => (Back, Down, Right)); + define_coordinates!("X=Back, Y=Right, Z=Down", BRD => (Back, Right, Down)); + define_coordinates!("X=Up, Y=Right, Z=Forward", RIGHT_HAND_X_UP => (Up, Right, Forward)); + define_coordinates!("X=Down, Y=Right, Z=Back", RIGHT_HAND_X_DOWN => (Down, Right, Back)); + define_coordinates!("X=Right, Y=Up, Z=Back", RIGHT_HAND_Y_UP => (Right, Up, Back)); + define_coordinates!("X=Right, Y=Down, Z=Forward", RIGHT_HAND_Y_DOWN => (Right, Down, Forward)); + define_coordinates!("X=Right, Y=Forward, Z=Up", RIGHT_HAND_Z_UP => (Right, Forward, Up)); + define_coordinates!("X=Right, Y=Back, Z=Down", RIGHT_HAND_Z_DOWN => (Right, Back, Down)); + define_coordinates!("X=Up, Y=Right, Z=Back", LEFT_HAND_X_UP => (Up, Right, Back)); + define_coordinates!("X=Down, Y=Right, Z=Forward", LEFT_HAND_X_DOWN => (Down, Right, Forward)); + define_coordinates!("X=Right, Y=Up, Z=Forward", LEFT_HAND_Y_UP => (Right, Up, Forward)); + define_coordinates!("X=Right, Y=Down, Z=Back", LEFT_HAND_Y_DOWN => (Right, Down, Back)); + define_coordinates!("X=Right, Y=Back, Z=Up", LEFT_HAND_Z_UP => (Right, Back, Up)); + define_coordinates!("X=Right, Y=Forward, Z=Down", LEFT_HAND_Z_DOWN => (Right, Forward, Down)); // } diff --git a/crates/re_types/src/datatypes/angle.rs b/crates/re_types/src/datatypes/angle.rs index 3107c2135296..1f87ff0bc0cf 100644 --- a/crates/re_types/src/datatypes/angle.rs +++ b/crates/re_types/src/datatypes/angle.rs @@ -25,7 +25,10 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Datatype**: Angle in either radians or degrees. #[derive(Clone, Debug, Copy, PartialEq)] pub enum Angle { + /// Angle in radians. One turn is equal to 2π (or τ) radians. Radians(f32), + + /// Angle in degrees. One turn is equal to 360 degrees. Degrees(f32), } diff --git a/crates/re_types/src/datatypes/keypoint_pair_ext.rs b/crates/re_types/src/datatypes/keypoint_pair_ext.rs index 1eb608ca4c40..8222e336ff51 100644 --- a/crates/re_types/src/datatypes/keypoint_pair_ext.rs +++ b/crates/re_types/src/datatypes/keypoint_pair_ext.rs @@ -19,6 +19,7 @@ impl From<(KeypointId, KeypointId)> for KeypointPair { } impl KeypointPair { + /// Create a vector of [`KeypointPair`] from an array of tuples. pub fn vec_from, const N: usize>(value: [T; N]) -> Vec { value.into_iter().map(|v| v.into()).collect() } diff --git a/crates/re_types/src/datatypes/mat3x3_ext.rs b/crates/re_types/src/datatypes/mat3x3_ext.rs index dbc22211a002..045a1279aa5d 100644 --- a/crates/re_types/src/datatypes/mat3x3_ext.rs +++ b/crates/re_types/src/datatypes/mat3x3_ext.rs @@ -3,6 +3,9 @@ use super::Mat3x3; use crate::datatypes::Vec3D; impl Mat3x3 { + /// The identity matrix. + /// + /// The multiplicative identity, representing no transform. #[rustfmt::skip] pub const IDENTITY: Mat3x3 = Mat3x3([ 1.0, 0.0, 0.0, diff --git a/crates/re_types/src/datatypes/mat4x4_ext.rs b/crates/re_types/src/datatypes/mat4x4_ext.rs index 6c056ce6a200..538101a7d86c 100644 --- a/crates/re_types/src/datatypes/mat4x4_ext.rs +++ b/crates/re_types/src/datatypes/mat4x4_ext.rs @@ -4,6 +4,9 @@ use crate::datatypes::Vec4D; impl Mat4x4 { #[rustfmt::skip] + /// The identity matrix. + /// + /// The multiplicative identity, representing no transform. pub const IDENTITY: Mat4x4 = Mat4x4([ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, diff --git a/crates/re_types/src/datatypes/material_ext.rs b/crates/re_types/src/datatypes/material_ext.rs index eed456f3bc51..41a5951ccb90 100644 --- a/crates/re_types/src/datatypes/material_ext.rs +++ b/crates/re_types/src/datatypes/material_ext.rs @@ -3,6 +3,7 @@ use crate::datatypes::Rgba32; use super::Material; impl Material { + /// A new material using a given color multiplier. #[inline] pub fn from_albedo_factor(color: impl Into) -> Self { Self { diff --git a/crates/re_types/src/datatypes/mesh_properties_ext.rs b/crates/re_types/src/datatypes/mesh_properties_ext.rs index 98d8c5acabb6..628bb66576d3 100644 --- a/crates/re_types/src/datatypes/mesh_properties_ext.rs +++ b/crates/re_types/src/datatypes/mesh_properties_ext.rs @@ -3,6 +3,7 @@ use crate::datatypes::UVec3D; use super::MeshProperties; impl MeshProperties { + /// The triangle indices of the mesh. #[inline] pub fn from_triangle_indices(indices: impl IntoIterator>) -> Self { Self { diff --git a/crates/re_types/src/datatypes/quaternion_ext.rs b/crates/re_types/src/datatypes/quaternion_ext.rs index c8a8eaf115d6..389ab5185a26 100644 --- a/crates/re_types/src/datatypes/quaternion_ext.rs +++ b/crates/re_types/src/datatypes/quaternion_ext.rs @@ -10,13 +10,16 @@ impl Default for Quaternion { } impl Quaternion { + /// The identity quaternion representing no rotation. pub const IDENTITY: Self = Self([0.0, 0.0, 0.0, 1.0]); + /// From XYZW. #[inline] pub const fn from_xyzw(xyzw: [f32; 4]) -> Self { Self(xyzw) } + /// From WXYZ. #[inline] pub const fn from_wxyz([w, x, y, z]: [f32; 4]) -> Self { Self([x, y, z, w]) diff --git a/crates/re_types/src/datatypes/rgba32_ext.rs b/crates/re_types/src/datatypes/rgba32_ext.rs index 674e850475ae..be83d3aa1afb 100644 --- a/crates/re_types/src/datatypes/rgba32_ext.rs +++ b/crates/re_types/src/datatypes/rgba32_ext.rs @@ -1,15 +1,22 @@ use super::Rgba32; impl Rgba32 { + /// Black and opaque. pub const BLACK: Self = Self::from_rgb(0, 0, 0); + + /// White and opaque. pub const WHITE: Self = Self::from_rgb(255, 255, 255); + + /// Fully transparent (invisible). pub const TRANSPARENT: Self = Self::from_unmultiplied_rgba(0, 0, 0, 0); + /// From gamma-space sRGB values. #[inline] pub const fn from_rgb(r: u8, g: u8, b: u8) -> Self { Self::from_unmultiplied_rgba(r, g, b, 255) } + /// From gamma-space sRGB values, with a separate/unmultiplied alpha in linear-space. #[inline] pub const fn from_unmultiplied_rgba(r: u8, g: u8, b: u8, a: u8) -> Self { let [r, g, b, a] = [r as u32, g as u32, b as u32, a as u32]; diff --git a/crates/re_types/src/datatypes/rotation3d_ext.rs b/crates/re_types/src/datatypes/rotation3d_ext.rs index 5e57dfb2507f..29ea662fcb30 100644 --- a/crates/re_types/src/datatypes/rotation3d_ext.rs +++ b/crates/re_types/src/datatypes/rotation3d_ext.rs @@ -3,6 +3,7 @@ use crate::datatypes::Quaternion; use super::Rotation3D; impl Rotation3D { + /// The identity rotation, representing no rotation. pub const IDENTITY: Rotation3D = Rotation3D::Quaternion(Quaternion::IDENTITY); } diff --git a/crates/re_types/src/datatypes/rotation_axis_angle_ext.rs b/crates/re_types/src/datatypes/rotation_axis_angle_ext.rs index 52cb72be0898..d6439b5dfb73 100644 --- a/crates/re_types/src/datatypes/rotation_axis_angle_ext.rs +++ b/crates/re_types/src/datatypes/rotation_axis_angle_ext.rs @@ -3,6 +3,7 @@ use super::RotationAxisAngle; use crate::datatypes::{Angle, Vec3D}; impl RotationAxisAngle { + /// Create a new rotation from an axis and an angle. #[inline] pub fn new(axis: impl Into, angle: impl Into) -> Self { Self { diff --git a/crates/re_types/src/datatypes/tensor_buffer_ext.rs b/crates/re_types/src/datatypes/tensor_buffer_ext.rs index a69baa96fddb..e58293e9309d 100644 --- a/crates/re_types/src/datatypes/tensor_buffer_ext.rs +++ b/crates/re_types/src/datatypes/tensor_buffer_ext.rs @@ -3,6 +3,7 @@ use crate::tensor_data::TensorDataType; use super::TensorBuffer; impl TensorBuffer { + /// The underlying data type of the buffer. #[allow(clippy::match_same_arms)] pub fn dtype(&self) -> TensorDataType { match self { @@ -23,6 +24,7 @@ impl TensorBuffer { } } + /// The size of the buffer in bytes. #[allow(clippy::match_same_arms)] pub fn size_in_bytes(&self) -> usize { match self { @@ -43,10 +45,13 @@ impl TensorBuffer { } } + /// Is this buffer empty? pub fn is_empty(&self) -> bool { self.size_in_bytes() == 0 } + /// Is this tensor represented by a compressed image format + /// (JPEG, NV12, YUY2)? pub fn is_compressed_image(&self) -> bool { match self { Self::U8(_) diff --git a/crates/re_types/src/datatypes/tensor_data.rs b/crates/re_types/src/datatypes/tensor_data.rs index b01fafd958b0..188bdcf6c2e8 100644 --- a/crates/re_types/src/datatypes/tensor_data.rs +++ b/crates/re_types/src/datatypes/tensor_data.rs @@ -37,7 +37,10 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// the shape has to be the shape of the decoded image. #[derive(Clone, Debug, PartialEq)] pub struct TensorData { + /// The shape of the tensor, including optional names for each dimension. pub shape: Vec, + + /// The content/data. pub buffer: crate::datatypes::TensorBuffer, } diff --git a/crates/re_types/src/datatypes/tensor_data_ext.rs b/crates/re_types/src/datatypes/tensor_data_ext.rs index 0dea58904bb3..f66c5051fc4d 100644 --- a/crates/re_types/src/datatypes/tensor_data_ext.rs +++ b/crates/re_types/src/datatypes/tensor_data_ext.rs @@ -11,11 +11,13 @@ use super::{TensorBuffer, TensorData, TensorDimension}; // ---------------------------------------------------------------------------- impl TensorData { + /// Create a new tensor. #[inline] pub fn new(shape: Vec, buffer: TensorBuffer) -> Self { Self { shape, buffer } } + /// The shape of the tensor, including optional dimension names. #[inline] pub fn shape(&self) -> &[TensorDimension] { self.shape.as_slice() @@ -35,6 +37,9 @@ impl TensorData { } } + /// The number of dimensions of the tensor. + /// + /// An image tensor will usually have two (height, width) or three (height, width, channels) dimensions. #[inline] pub fn num_dim(&self) -> usize { self.shape.len() @@ -118,7 +123,7 @@ impl TensorData { /// Query with x, y, channel indices. /// - /// Allows to query values for any image like tensor even if it has more or less dimensions than 3. + /// Allows to query values for any image-like tensor even if it has more or less dimensions than 3. /// (useful for sampling e.g. `N x M x C x 1` tensor which is a valid image) #[inline] pub fn get_with_image_coords(&self, x: u64, y: u64, channel: u64) -> Option { @@ -157,6 +162,9 @@ impl TensorData { } } + /// Get the value of the element at the given index. + /// + /// Return `None` if out-of-bounds, or if the tensor is encoded (e.g. [`TensorBuffer::Jpeg`]). pub fn get(&self, index: &[u64]) -> Option { let mut stride: usize = 1; let mut offset: usize = 0; @@ -187,10 +195,7 @@ impl TensorData { let [y, x] = index else { return None; }; - if let Some( - [TensorElement::U8(r), TensorElement::U8(g), TensorElement::U8(b)], - ) = self.get_nv12_pixel(*x, *y) - { + if let Some([r, g, b]) = self.get_nv12_pixel(*x, *y) { let mut rgba = 0; rgba |= (r as u32) << 24; rgba |= (g as u32) << 16; @@ -209,10 +214,7 @@ impl TensorData { return None; }; - if let Some( - [TensorElement::U8(r), TensorElement::U8(g), TensorElement::U8(b)], - ) = self.get_yuy2_pixel(*x, *y) - { + if let Some([r, g, b]) = self.get_yuy2_pixel(*x, *y) { let mut rgba = 0; rgba |= (r as u32) << 24; rgba |= (g as u32) << 16; @@ -227,8 +229,12 @@ impl TensorData { } } - /// Returns decoded RGB8 value at the given image coordinates if this tensor is a valid NV12 image. - pub fn get_nv12_pixel(&self, x: u64, y: u64) -> Option<[TensorElement; 3]> { + /// Returns decoded RGB8 value at the given image coordinates if this tensor is a NV12 image. + /// + /// If the tensor is not [`TensorBuffer::Nv12`], `None` is returned. + /// + /// It is undefined what happens if the coordinate is out-of-bounds. + pub fn get_nv12_pixel(&self, x: u64, y: u64) -> Option<[u8; 3]> { let TensorBuffer::Nv12(buf) = &self.buffer else { return None; }; @@ -239,19 +245,18 @@ impl TensorData { let u = buf[(uv_offset + (y / 2) * w + x) as usize]; let v = buf[(uv_offset + (y / 2) * w + x) as usize + 1]; - let (r, g, b) = Self::set_color_standard(luma, u, v); - - Some([ - TensorElement::U8(r), - TensorElement::U8(g), - TensorElement::U8(b), - ]) + Some(Self::set_color_standard(luma, u, v)) } _ => None, } } - pub fn get_yuy2_pixel(&self, x: u64, y: u64) -> Option<[TensorElement; 3]> { + /// Returns decoded RGB8 value at the given image coordinates if this tensor is a YUY2 image. + /// + /// If the tensor is not [`TensorBuffer::Yuy2`], `None` is returned. + /// + /// It is undefined what happens if the coordinate is out-of-bounds. + pub fn get_yuy2_pixel(&self, x: u64, y: u64) -> Option<[u8; 3]> { let TensorBuffer::Yuy2(buf) = &self.buffer else { return None; }; @@ -266,13 +271,7 @@ impl TensorData { (buf[index], buf[index - 1], buf[index + 1]) }; - let (r, g, b) = Self::set_color_standard(luma, u, v); - - Some([ - TensorElement::U8(r), - TensorElement::U8(g), - TensorElement::U8(b), - ]) + Some(Self::set_color_standard(luma, u, v)) } _ => None, } @@ -283,7 +282,7 @@ impl TensorData { /// This conversion mirrors the function of the same name in `crates/re_renderer/shader/decodings.wgsl` /// /// Specifying the color standard should be exposed in the future [#3541](https://github.com/rerun-io/rerun/pull/3541) - fn set_color_standard(y: u8, u: u8, v: u8) -> (u8, u8, u8) { + fn set_color_standard(y: u8, u: u8, v: u8) -> [u8; 3] { let (y, u, v) = (y as f32, u as f32, v as f32); // rescale YUV values @@ -301,18 +300,20 @@ impl TensorData { // let g = y - 0.187 * u - 0.468 * v; // let b = y + 1.856 * u; - ( + [ (255.0 * r).clamp(0.0, 255.0) as u8, (255.0 * g).clamp(0.0, 255.0) as u8, (255.0 * b).clamp(0.0, 255.0) as u8, - ) + ] } + /// The datatype of the tensor. #[inline] pub fn dtype(&self) -> TensorDataType { self.buffer.dtype() } + /// The size of the tensor data, in bytes. #[inline] pub fn size_in_bytes(&self) -> usize { self.buffer.size_in_bytes() @@ -587,6 +588,7 @@ impl TensorData { Self::from_jpeg_bytes(jpeg_bytes) } + /// Construct a new tensor from the contents of a `.jpeg` file at the given path. #[deprecated = "Renamed 'from_jpeg_file'"] #[cfg(not(target_arch = "wasm32"))] #[inline] @@ -638,6 +640,7 @@ impl TensorData { }) } + /// Construct a new tensor from the contents of a `.jpeg` file. #[deprecated = "Renamed 'from_jpeg_bytes'"] #[cfg(not(target_arch = "wasm32"))] #[inline] diff --git a/crates/re_types/src/datatypes/tensor_dimension_ext.rs b/crates/re_types/src/datatypes/tensor_dimension_ext.rs index e264a38d5214..8f50ab11ecd9 100644 --- a/crates/re_types/src/datatypes/tensor_dimension_ext.rs +++ b/crates/re_types/src/datatypes/tensor_dimension_ext.rs @@ -5,29 +5,34 @@ impl TensorDimension { const DEFAULT_NAME_HEIGHT: &'static str = "height"; const DEFAULT_NAME_DEPTH: &'static str = "depth"; + /// Create a new dimension with a given size, and the name "height". #[inline] pub fn height(size: u64) -> Self { Self::named(size, String::from(Self::DEFAULT_NAME_HEIGHT)) } + /// Create a new dimension with a given size, and the name "width". #[inline] pub fn width(size: u64) -> Self { Self::named(size, String::from(Self::DEFAULT_NAME_WIDTH)) } + /// Create a new dimension with a given size, and the name "depth". #[inline] pub fn depth(size: u64) -> Self { Self::named(size, String::from(Self::DEFAULT_NAME_DEPTH)) } + /// Create a named dimension. #[inline] - pub fn named(size: u64, name: String) -> Self { + pub fn named(size: u64, name: impl Into) -> Self { Self { size, name: Some(name.into()), } } + /// Create an unnamed dimension. #[inline] pub fn unnamed(size: u64) -> Self { Self { size, name: None } diff --git a/crates/re_types/src/datatypes/transform3d.rs b/crates/re_types/src/datatypes/transform3d.rs index 6171d7e22515..b2b2592b47dc 100644 --- a/crates/re_types/src/datatypes/transform3d.rs +++ b/crates/re_types/src/datatypes/transform3d.rs @@ -28,7 +28,10 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// directly to `Transform3D::child_from_parent` or `Transform3D::parent_from_child`. #[derive(Clone, Debug, Copy, PartialEq)] pub enum Transform3D { + /// Translation plus a 3x3 matrix for scale, rotation, skew, etc. TranslationAndMat3x3(crate::datatypes::TranslationAndMat3x3), + + /// Translation, rotation and scale, decomposed. TranslationRotationScale(crate::datatypes::TranslationRotationScale3D), } diff --git a/crates/re_types/src/datatypes/transform3d_ext.rs b/crates/re_types/src/datatypes/transform3d_ext.rs index 6da7762b57ca..c492cb84c6d3 100644 --- a/crates/re_types/src/datatypes/transform3d_ext.rs +++ b/crates/re_types/src/datatypes/transform3d_ext.rs @@ -5,6 +5,7 @@ use crate::datatypes::{ }; impl Transform3D { + /// The identity transform, representing no transform. pub const IDENTITY: Self = Self::TranslationRotationScale(TranslationRotationScale3D::IDENTITY); /// From a translation. diff --git a/crates/re_types/src/datatypes/translation_and_mat3x3_ext.rs b/crates/re_types/src/datatypes/translation_and_mat3x3_ext.rs index 0871ce256811..11ef2941fc87 100644 --- a/crates/re_types/src/datatypes/translation_and_mat3x3_ext.rs +++ b/crates/re_types/src/datatypes/translation_and_mat3x3_ext.rs @@ -9,13 +9,14 @@ impl Default for TranslationAndMat3x3 { } impl TranslationAndMat3x3 { + /// The identity transform, representing no translation or rotation. pub const IDENTITY: Self = Self { translation: None, mat3x3: None, from_parent: false, }; - /// Create a new `TranslationAndMat3`. + /// Create a new [`TranslationAndMat3x3`] from a translation and a 3x3 matrix. #[inline] pub fn new, M: Into>(translation: T, mat3x3: M) -> Self { Self { @@ -25,6 +26,7 @@ impl TranslationAndMat3x3 { } } + /// Create a new [`TranslationAndMat3x3`] with just the translation. #[inline] pub fn from_translation>(translation: T) -> Self { Self { @@ -34,6 +36,7 @@ impl TranslationAndMat3x3 { } } + /// Create a new [`TranslationAndMat3x3`] with just the 3x3 matrix. #[inline] pub fn from_mat3x3>(mat3x3: M) -> Self { Self { diff --git a/crates/re_types/src/datatypes/translation_rotation_scale3d_ext.rs b/crates/re_types/src/datatypes/translation_rotation_scale3d_ext.rs index 29f121e32a3a..091acf343ef0 100644 --- a/crates/re_types/src/datatypes/translation_rotation_scale3d_ext.rs +++ b/crates/re_types/src/datatypes/translation_rotation_scale3d_ext.rs @@ -3,6 +3,7 @@ use super::TranslationRotationScale3D; use crate::datatypes::{Rotation3D, Scale3D, Vec3D}; impl TranslationRotationScale3D { + /// The identity transform, representing no transform. pub const IDENTITY: Self = Self { translation: None, rotation: None, diff --git a/crates/re_types/src/datatypes/uuid.rs b/crates/re_types/src/datatypes/uuid.rs index 1ca03976a46c..4a11a7f5a99d 100644 --- a/crates/re_types/src/datatypes/uuid.rs +++ b/crates/re_types/src/datatypes/uuid.rs @@ -22,10 +22,11 @@ use ::re_types_core::SerializationResult; use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; -/// **Datatype**: A 16-byte uuid. +/// **Datatype**: A 16-byte UUID. #[derive(Clone, Debug, Default, Copy, PartialEq, Eq)] #[repr(transparent)] pub struct Uuid { + /// The raw bytes representing the UUID. pub bytes: [u8; 16usize], } diff --git a/crates/re_types/src/datatypes/uvec2d_ext.rs b/crates/re_types/src/datatypes/uvec2d_ext.rs index 1f800d1ecf53..160769ee75af 100644 --- a/crates/re_types/src/datatypes/uvec2d_ext.rs +++ b/crates/re_types/src/datatypes/uvec2d_ext.rs @@ -1,19 +1,25 @@ use super::UVec2D; impl UVec2D { + /// The zero vector, i.e. the additive identity. pub const ZERO: Self = Self([0; 2]); + + /// The unit vector `[1, 1]`, i.e. the multiplicative identity. pub const ONE: Self = Self([1; 2]); + /// Create a new vector. #[inline] pub const fn new(x: u32, y: u32) -> Self { Self([x, y]) } + /// The x-coordinate, i.e. index 0. #[inline] pub fn x(&self) -> u32 { self.0[0] } + /// The y-coordinate, i.e. index 1. #[inline] pub fn y(&self) -> u32 { self.0[1] diff --git a/crates/re_types/src/datatypes/uvec3d_ext.rs b/crates/re_types/src/datatypes/uvec3d_ext.rs index 685ffe900147..08e1895b1fe8 100644 --- a/crates/re_types/src/datatypes/uvec3d_ext.rs +++ b/crates/re_types/src/datatypes/uvec3d_ext.rs @@ -1,24 +1,31 @@ use super::UVec3D; impl UVec3D { + /// The zero vector, i.e. the additive identity. pub const ZERO: Self = Self([0; 3]); + + /// The unit vector `[1, 1, 1]`, i.e. the multiplicative identity. pub const ONE: Self = Self([1; 3]); + /// Create a new vector. #[inline] pub const fn new(x: u32, y: u32, z: u32) -> Self { Self([x, y, z]) } + /// The x-coordinate, i.e. index 0. #[inline] pub fn x(&self) -> u32 { self.0[0] } + /// The y-coordinate, i.e. index 1. #[inline] pub fn y(&self) -> u32 { self.0[1] } + /// The z-coordinate, i.e. index 2. #[inline] pub fn z(&self) -> u32 { self.0[2] diff --git a/crates/re_types/src/datatypes/uvec4d_ext.rs b/crates/re_types/src/datatypes/uvec4d_ext.rs index 6b22ff3ab1ea..2631389e2898 100644 --- a/crates/re_types/src/datatypes/uvec4d_ext.rs +++ b/crates/re_types/src/datatypes/uvec4d_ext.rs @@ -1,29 +1,37 @@ use super::UVec4D; impl UVec4D { + /// The zero vector, i.e. the additive identity. pub const ZERO: Self = Self([0; 4]); + + /// The unit vector `[1, 1, 1]`, i.e. the multiplicative identity. pub const ONE: Self = Self([1; 4]); + /// Create a new vector. #[inline] pub const fn new(x: u32, y: u32, z: u32, w: u32) -> Self { Self([x, y, z, w]) } + /// The x-coordinate, i.e. index 0. #[inline] pub fn x(&self) -> u32 { self.0[0] } + /// The y-coordinate, i.e. index 1. #[inline] pub fn y(&self) -> u32 { self.0[1] } + /// The z-coordinate, i.e. index 2. #[inline] pub fn z(&self) -> u32 { self.0[2] } + /// The w-coordinate, i.e. index 3. #[inline] pub fn w(&self) -> u32 { self.0[2] diff --git a/crates/re_types/src/datatypes/vec2d_ext.rs b/crates/re_types/src/datatypes/vec2d_ext.rs index a13dbccc3913..9b3846cca099 100644 --- a/crates/re_types/src/datatypes/vec2d_ext.rs +++ b/crates/re_types/src/datatypes/vec2d_ext.rs @@ -1,19 +1,25 @@ use super::Vec2D; impl Vec2D { + /// The zero vector, i.e. the additive identity. pub const ZERO: Self = Self::new(0.0, 0.0); + + /// The unit vector `[1, 1]`, i.e. the multiplicative identity. pub const ONE: Self = Self::new(1.0, 1.0); + /// Create a new vector. #[inline] pub const fn new(x: f32, y: f32) -> Self { Self([x, y]) } + /// The x-coordinate, i.e. index 0. #[inline] pub fn x(&self) -> f32 { self.0[0] } + /// The y-coordinate, i.e. index 1. #[inline] pub fn y(&self) -> f32 { self.0[1] diff --git a/crates/re_types/src/datatypes/vec3d_ext.rs b/crates/re_types/src/datatypes/vec3d_ext.rs index 5147c5fbcfec..4a64b60853b6 100644 --- a/crates/re_types/src/datatypes/vec3d_ext.rs +++ b/crates/re_types/src/datatypes/vec3d_ext.rs @@ -1,24 +1,31 @@ use super::Vec3D; impl Vec3D { + /// The zero vector, i.e. the additive identity. pub const ZERO: Vec3D = Vec3D([0.0; 3]); + + /// `[1, 1, 1]`, i.e. the multiplicative identity. pub const ONE: Vec3D = Vec3D([1.0; 3]); + /// Create a new vector. #[inline] pub const fn new(x: f32, y: f32, z: f32) -> Self { Self([x, y, z]) } + /// The x-coordinate, i.e. index 0. #[inline] pub fn x(&self) -> f32 { self.0[0] } + /// The y-coordinate, i.e. index 1. #[inline] pub fn y(&self) -> f32 { self.0[1] } + /// The z-coordinate, i.e. index 2. #[inline] pub fn z(&self) -> f32 { self.0[2] diff --git a/crates/re_types/src/datatypes/vec4d_ext.rs b/crates/re_types/src/datatypes/vec4d_ext.rs index 89a650362d73..a48b6c97abee 100644 --- a/crates/re_types/src/datatypes/vec4d_ext.rs +++ b/crates/re_types/src/datatypes/vec4d_ext.rs @@ -1,28 +1,34 @@ use super::Vec4D; impl Vec4D { + /// The zero vector, i.e. the additive identity. pub const ZERO: Vec4D = Vec4D([0.0; 4]); + /// Create a new vector. #[inline] pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self { Self([x, y, z, w]) } + /// The x-coordinate, i.e. index 0. #[inline] pub fn x(&self) -> f32 { self.0[0] } + /// The y-coordinate, i.e. index 1. #[inline] pub fn y(&self) -> f32 { self.0[1] } + /// The z-coordinate, i.e. index 2. #[inline] pub fn z(&self) -> f32 { self.0[2] } + /// The w-coordinate, i.e. index 3. #[inline] pub fn w(&self) -> f32 { self.0[3] diff --git a/crates/re_types/src/image.rs b/crates/re_types/src/image.rs index f25aa3d41161..7dfc31666169 100644 --- a/crates/re_types/src/image.rs +++ b/crates/re_types/src/image.rs @@ -1,15 +1,20 @@ +//! Image-related utilities. + use smallvec::{smallvec, SmallVec}; use crate::datatypes::{TensorData, TensorDimension}; +/// Error returned when trying to interpret a tensor as an image. #[derive(thiserror::Error, Clone, Debug)] pub enum ImageConstructionError> where T::Error: std::error::Error, { + /// Could not convert source to [`TensorData`]. #[error("Could not convert source to TensorData: {0}")] TensorDataConversion(T::Error), + /// The tensor did not have the right shape for an image (e.g. had too many dimensions). #[error("Could not create Image from TensorData with shape {0:?}")] BadImageShape(Vec), } diff --git a/crates/re_types/src/lib.rs b/crates/re_types/src/lib.rs index b954162a4b4b..345fcd9a7c25 100644 --- a/crates/re_types/src/lib.rs +++ b/crates/re_types/src/lib.rs @@ -171,6 +171,8 @@ #![doc = document_features::document_features!()] //! +#![warn(missing_docs)] // Let's keep the this crate well-documented! + // --- /// Number of decimals shown for all vector display methods. @@ -257,6 +259,7 @@ pub use re_types_core::*; // --- +/// Re-exports of external crates that are used throughout the codebase. pub mod external { pub use re_types_core; diff --git a/crates/re_types/src/tensor_data.rs b/crates/re_types/src/tensor_data.rs index 8d7ea54d7ad1..c45487616df2 100644 --- a/crates/re_types/src/tensor_data.rs +++ b/crates/re_types/src/tensor_data.rs @@ -1,3 +1,6 @@ +//! Internal helpers; not part of the public API. +#![allow(missing_docs)] + use half::f16; use crate::datatypes::{TensorBuffer, TensorData}; @@ -146,11 +149,13 @@ impl TensorDataType { } } + /// Is this datatype an integer? #[inline] pub fn is_integer(&self) -> bool { !self.is_float() } + /// Is this datatype a floating point number? #[inline] pub fn is_float(&self) -> bool { match self { @@ -166,6 +171,7 @@ impl TensorDataType { } } + /// What is the minimum value representable by this datatype? #[inline] pub fn min_value(&self) -> f64 { match self { @@ -185,6 +191,7 @@ impl TensorDataType { } } + /// What is the maximum value representable by this datatype? #[inline] pub fn max_value(&self) -> f64 { match self { @@ -320,6 +327,10 @@ pub enum TensorElement { } impl TensorElement { + /// Get the value as a 64-bit floating point number. + /// + /// Note that this may cause rounding for large 64-bit integers, + /// as `f64` can only represent integers up to 2^53 exactly. #[inline] pub fn as_f64(&self) -> f64 { match self { @@ -339,6 +350,8 @@ impl TensorElement { } } + /// Convert the value to a `u16`, but only if it can be represented + /// exactly as a `u16`, without any rounding or clamping. #[inline] pub fn try_as_u16(&self) -> Option { fn u16_from_f64(f: f64) -> Option { @@ -518,6 +531,8 @@ impl DecodedTensor { Ok(DecodedTensor(tensor)) } + /// Try to decode this tensor, if it was encoded as a JPEG, + /// otherwise just return the tensor. pub fn try_decode(maybe_encoded_tensor: TensorData) -> Result { match &maybe_encoded_tensor.buffer { TensorBuffer::U8(_) @@ -543,13 +558,16 @@ impl DecodedTensor { ) })?; - Self::decode_jpeg_bytes(jpeg_bytes, [h, w, c]) + Self::decode_jpeg_bytes(jpeg_bytes.as_slice(), [h, w, c]) } } } - pub fn decode_jpeg_bytes( - jpeg_bytes: &::re_types_core::ArrowBuffer, + /// Decode the contents of a JPEG file, with the given expected size. + /// + /// Returns an error if the size does not match. + fn decode_jpeg_bytes( + jpeg_bytes: &[u8], [expected_height, expected_width, expected_channels]: [u64; 3], ) -> Result { re_tracing::profile_function!(format!("{expected_width}x{expected_height}")); @@ -569,7 +587,7 @@ impl DecodedTensor { 4 }; - let mut decoder = JpegDecoder::new_with_options(jpeg_bytes.as_slice(), options); + let mut decoder = JpegDecoder::new_with_options(jpeg_bytes, options); let pixels = decoder.decode()?; let (w, h) = decoder.dimensions().unwrap(); // Can't fail after a successful decode diff --git a/crates/re_types/src/testing/archetypes/affix_fuzzer1.rs b/crates/re_types/src/testing/archetypes/affix_fuzzer1.rs index bfb7e4919793..7d2c57801e37 100644 --- a/crates/re_types/src/testing/archetypes/affix_fuzzer1.rs +++ b/crates/re_types/src/testing/archetypes/affix_fuzzer1.rs @@ -166,6 +166,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 23usize]> = }); impl AffixFuzzer1 { + /// The total number of components in the archetype: 22 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 23usize; } @@ -565,6 +566,8 @@ impl ::re_types_core::AsComponents for AffixFuzzer1 { } impl AffixFuzzer1 { + /// Create a new `AffixFuzzer1`. + #[inline] pub fn new( fuzz1001: impl Into, fuzz1002: impl Into, diff --git a/crates/re_types/src/testing/archetypes/affix_fuzzer2.rs b/crates/re_types/src/testing/archetypes/affix_fuzzer2.rs index 2585277f2fd0..51a49dce8e96 100644 --- a/crates/re_types/src/testing/archetypes/affix_fuzzer2.rs +++ b/crates/re_types/src/testing/archetypes/affix_fuzzer2.rs @@ -151,6 +151,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 20usize]> = }); impl AffixFuzzer2 { + /// The total number of components in the archetype: 19 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 20usize; } @@ -486,6 +487,8 @@ impl ::re_types_core::AsComponents for AffixFuzzer2 { } impl AffixFuzzer2 { + /// Create a new `AffixFuzzer2`. + #[inline] pub fn new( fuzz1101: impl IntoIterator>, fuzz1102: impl IntoIterator>, diff --git a/crates/re_types/src/testing/archetypes/affix_fuzzer3.rs b/crates/re_types/src/testing/archetypes/affix_fuzzer3.rs index 9017b2b7cd08..9d4dc47431f5 100644 --- a/crates/re_types/src/testing/archetypes/affix_fuzzer3.rs +++ b/crates/re_types/src/testing/archetypes/affix_fuzzer3.rs @@ -146,6 +146,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = }); impl AffixFuzzer3 { + /// The total number of components in the archetype: 0 required, 1 recommended, 18 optional pub const NUM_COMPONENTS: usize = 19usize; } @@ -467,6 +468,8 @@ impl ::re_types_core::AsComponents for AffixFuzzer3 { } impl AffixFuzzer3 { + /// Create a new `AffixFuzzer3`. + #[inline] pub fn new() -> Self { Self { fuzz2001: None, diff --git a/crates/re_types/src/testing/archetypes/affix_fuzzer4.rs b/crates/re_types/src/testing/archetypes/affix_fuzzer4.rs index e7707a3f3d44..14056381ef2d 100644 --- a/crates/re_types/src/testing/archetypes/affix_fuzzer4.rs +++ b/crates/re_types/src/testing/archetypes/affix_fuzzer4.rs @@ -146,6 +146,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 19usize]> = }); impl AffixFuzzer4 { + /// The total number of components in the archetype: 0 required, 1 recommended, 18 optional pub const NUM_COMPONENTS: usize = 19usize; } @@ -521,6 +522,8 @@ impl ::re_types_core::AsComponents for AffixFuzzer4 { } impl AffixFuzzer4 { + /// Create a new `AffixFuzzer4`. + #[inline] pub fn new() -> Self { Self { fuzz2101: None, diff --git a/crates/re_types/src/view_coordinates.rs b/crates/re_types/src/view_coordinates.rs index f8cf69f34edb..1819f43bba0d 100644 --- a/crates/re_types/src/view_coordinates.rs +++ b/crates/re_types/src/view_coordinates.rs @@ -1,3 +1,5 @@ +#![allow(missing_docs)] + /// The six cardinal directions for 3D view-space and image-space. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum ViewDir { @@ -27,6 +29,14 @@ impl TryFrom for ViewDir { } impl ViewDir { + /// Convert an upper case letter to one of the six cardinal directions. + /// + /// * 'U' => [`Self::Up`] + /// * 'D' => [`Self::Down`] + /// * 'R' => [`Self::Right`] + /// * 'L' => [`Self::Left`] + /// * 'F' => [`Self::Forward`] + /// * 'B' => [`Self::Back`] #[inline] pub fn from_ascii_char(c: u8) -> Result { match c { @@ -40,6 +50,14 @@ impl ViewDir { } } + /// Represent this direction as the first letter of the direction's name, in uppercase. + /// + /// * [`Self::Up`] => 'U' + /// * [`Self::Down`] => 'D' + /// * [`Self::Right`] => 'R' + /// * [`Self::Left`] => 'L' + /// * [`Self::Forward`] => 'F' + /// * [`Self::Back`] => 'B' #[inline] pub fn short(&self) -> &'static str { match self { @@ -52,6 +70,7 @@ impl ViewDir { } } + /// Long description of the direction, e.g. "Up", "Down", "Right", "Left", "Forward", "Back". #[inline] pub fn long(&self) -> &'static str { match self { @@ -75,6 +94,11 @@ pub enum Axis3 { } impl Axis3 { + /// Convert a dimension index to an axis. + /// + /// * 0 => [`Self::X`] + /// * 1 => [`Self::Y`] + /// * 2 => [`Self::Z`] #[inline] pub fn from_dim(dim: usize) -> Self { match dim { @@ -112,16 +136,30 @@ pub enum Sign { /// i.e. one of the six cardinal direction in 3D space. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct SignedAxis3 { + /// Positive or negative. pub sign: Sign, + + /// One of `X`, `Y`, `Z`. pub axis: Axis3, } impl SignedAxis3 { + /// +X pub const POSITIVE_X: Self = Self::new(Sign::Positive, Axis3::X); + + /// -X pub const NEGATIVE_X: Self = Self::new(Sign::Negative, Axis3::X); + + /// +Y pub const POSITIVE_Y: Self = Self::new(Sign::Positive, Axis3::Y); + + /// -Y pub const NEGATIVE_Y: Self = Self::new(Sign::Negative, Axis3::Y); + + /// +Z pub const POSITIVE_Z: Self = Self::new(Sign::Positive, Axis3::Z); + + /// -Z pub const NEGATIVE_Z: Self = Self::new(Sign::Negative, Axis3::Z); #[inline] @@ -129,6 +167,7 @@ impl SignedAxis3 { Self { sign, axis } } + /// Convert to a unit-length 3D vector. #[inline] pub fn as_vec3(&self) -> [f32; 3] { match (self.sign, self.axis) { @@ -182,11 +221,20 @@ impl From for glam::Vec3 { /// Left or right handedness. Used to describe a coordinate system. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Handedness { + /// Right-handed coordinate system. Right, - Left, + + /// Left-handed coordinate system. + /// + /// Rerun does not yet support this, + /// see . + Left, // TODO(#5032): Support left-handed coordinate systems. } impl Handedness { + /// Create a `Handedness` from a boolean. + /// + /// If `true`, returns `Right`, otherwise `Left`. #[inline] pub const fn from_right_handed(right_handed: bool) -> Self { if right_handed { @@ -195,12 +243,4 @@ impl Handedness { Handedness::Left } } - - #[inline] - pub fn describe(&self) -> &'static str { - match self { - Self::Left => "left handed", - Self::Right => "right handed", - } - } } diff --git a/crates/re_types_blueprint/src/blueprint/archetypes/container_blueprint.rs b/crates/re_types_blueprint/src/blueprint/archetypes/container_blueprint.rs index 087805a6b078..7fefd874f484 100644 --- a/crates/re_types_blueprint/src/blueprint/archetypes/container_blueprint.rs +++ b/crates/re_types_blueprint/src/blueprint/archetypes/container_blueprint.rs @@ -129,6 +129,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 9usize]> = }); impl ContainerBlueprint { + /// The total number of components in the archetype: 1 required, 1 recommended, 7 optional pub const NUM_COMPONENTS: usize = 9usize; } @@ -320,6 +321,8 @@ impl ::re_types_core::AsComponents for ContainerBlueprint { } impl ContainerBlueprint { + /// Create a new `ContainerBlueprint`. + #[inline] pub fn new(container_kind: impl Into) -> Self { Self { container_kind: container_kind.into(), @@ -333,12 +336,14 @@ impl ContainerBlueprint { } } + /// The name of the container. #[inline] pub fn with_display_name(mut self, display_name: impl Into) -> Self { self.display_name = Some(display_name.into()); self } + /// `ContainerIds`s or `SpaceViewId`s that are children of this container. #[inline] pub fn with_contents( mut self, @@ -348,6 +353,11 @@ impl ContainerBlueprint { self } + /// The layout shares of each column in the container. + /// + /// For `Horizontal` containers, the length of this list should always match the number of contents. + /// + /// Ignored for `Vertical` containers. #[inline] pub fn with_col_shares( mut self, @@ -357,6 +367,11 @@ impl ContainerBlueprint { self } + /// The layout shares of each row of the container. + /// + /// For `Vertical` containers, the length of this list should always match the number of contents. + /// + /// Ignored for `Horizontal` containers. #[inline] pub fn with_row_shares( mut self, @@ -366,6 +381,9 @@ impl ContainerBlueprint { self } + /// Which tab is active. + /// + /// Only applies to `Tabs` containers. #[inline] pub fn with_active_tab( mut self, @@ -375,6 +393,9 @@ impl ContainerBlueprint { self } + /// Whether this container is visible. + /// + /// Defaults to true if not specified. #[inline] pub fn with_visible( mut self, @@ -384,6 +405,11 @@ impl ContainerBlueprint { self } + /// How many columns this grid should have. + /// + /// If unset, the grid layout will be auto. + /// + /// Ignored for `Horizontal`/`Vertical` containers. #[inline] pub fn with_grid_columns( mut self, diff --git a/crates/re_types_blueprint/src/blueprint/archetypes/panel_blueprint.rs b/crates/re_types_blueprint/src/blueprint/archetypes/panel_blueprint.rs index c992d6720620..32b8ecccab84 100644 --- a/crates/re_types_blueprint/src/blueprint/archetypes/panel_blueprint.rs +++ b/crates/re_types_blueprint/src/blueprint/archetypes/panel_blueprint.rs @@ -59,6 +59,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl PanelBlueprint { + /// The total number of components in the archetype: 0 required, 1 recommended, 1 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -140,10 +141,13 @@ impl ::re_types_core::AsComponents for PanelBlueprint { } impl PanelBlueprint { + /// Create a new `PanelBlueprint`. + #[inline] pub fn new() -> Self { Self { expanded: None } } + /// Whether or not the panel is expanded. #[inline] pub fn with_expanded( mut self, diff --git a/crates/re_types_blueprint/src/blueprint/archetypes/viewport_blueprint.rs b/crates/re_types_blueprint/src/blueprint/archetypes/viewport_blueprint.rs index 3cde4b26de05..a8c267ddf018 100644 --- a/crates/re_types_blueprint/src/blueprint/archetypes/viewport_blueprint.rs +++ b/crates/re_types_blueprint/src/blueprint/archetypes/viewport_blueprint.rs @@ -104,6 +104,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = }); impl ViewportBlueprint { + /// The total number of components in the archetype: 0 required, 1 recommended, 5 optional pub const NUM_COMPONENTS: usize = 6usize; } @@ -252,6 +253,8 @@ impl ::re_types_core::AsComponents for ViewportBlueprint { } impl ViewportBlueprint { + /// Create a new `ViewportBlueprint`. + #[inline] pub fn new() -> Self { Self { root_container: None, @@ -262,6 +265,7 @@ impl ViewportBlueprint { } } + /// The layout of the space-views #[inline] pub fn with_root_container( mut self, @@ -271,6 +275,7 @@ impl ViewportBlueprint { self } + /// Show one tab as maximized? #[inline] pub fn with_maximized( mut self, @@ -280,6 +285,10 @@ impl ViewportBlueprint { self } + /// Whether the viewport layout is determined automatically. + /// + /// If `true`, the container layout will be reset whenever a new space view is added or removed. + /// This defaults to `false` and is automatically set to `false` when there is user determined layout. #[inline] pub fn with_auto_layout( mut self, @@ -289,6 +298,11 @@ impl ViewportBlueprint { self } + /// Whether or not space views should be created automatically. + /// + /// If `true`, the viewer will only add space views that it hasn't considered previously (as identified by `past_viewer_recommendations`) + /// and which aren't deemed redundant to existing space views. + /// This defaults to `false` and is automatically set to `false` when the user adds space views manually in the viewer. #[inline] pub fn with_auto_space_views( mut self, @@ -298,6 +312,12 @@ impl ViewportBlueprint { self } + /// Hashes of all recommended space 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 space views, you should set `auto_space_views` to `false`. + /// + /// The viewer uses this to determine whether it should keep adding space views. #[inline] pub fn with_past_viewer_recommendations( mut self, diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index 202a0059f3e7..c32ffaa0aa4b 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -391,7 +391,7 @@ fn quote_struct( let quoted_trait_impls = quote_trait_impls_from_obj(arrow_registry, objects, obj); - let quoted_builder = quote_builder_from_obj(obj); + let quoted_builder = quote_builder_from_obj(reporter, obj); let quoted_heap_size_bytes = if obj .fields @@ -789,6 +789,11 @@ fn doc_as_lines(reporter: &Reporter, virtpath: &str, fqname: &str, docs: &Docs) lines } +fn quote_doc_line(line: &str) -> TokenStream { + let line = format!(" {line}"); // add space between `///` and comment + quote!(# [doc = #line]) +} + fn quote_doc_lines(lines: &[String]) -> TokenStream { struct DocCommentTokenizer<'a>(&'a [String]); @@ -1081,6 +1086,9 @@ fn quote_trait_impls_from_obj( let (num_optional, optional) = compute_components(obj, ATTR_RERUN_COMPONENT_OPTIONAL, []); + let num_components_docstring = quote_doc_line(&format!( + "The total number of components in the archetype: {num_required} required, {num_recommended} recommended, {num_optional} optional" + )); let num_all = num_required + num_recommended + num_optional; let quoted_field_names = obj @@ -1206,6 +1214,7 @@ fn quote_trait_impls_from_obj( once_cell::sync::Lazy::new(|| {[#required #recommended #optional]}); impl #name { + #num_components_docstring pub const NUM_COMPONENTS: usize = #num_all; } @@ -1404,7 +1413,7 @@ fn quote_from_impl_from_obj(obj: &Object) -> TokenStream { } /// Only makes sense for archetypes. -fn quote_builder_from_obj(obj: &Object) -> TokenStream { +fn quote_builder_from_obj(reporter: &Reporter, obj: &Object) -> TokenStream { if obj.kind != ObjectKind::Archetype { return TokenStream::new(); } @@ -1457,7 +1466,10 @@ fn quote_builder_from_obj(obj: &Object) -> TokenStream { } else { quote!(pub) }; + let fn_new_docstring = quote_doc_line(&format!("Create a new `{name}`.")); let fn_new = quote! { + #fn_new_docstring + #[inline] #fn_new_pub fn new(#(#quoted_params,)*) -> Self { Self { #(#quoted_required,)* @@ -1472,10 +1484,12 @@ fn quote_builder_from_obj(obj: &Object) -> TokenStream { let field_name = format_ident!("{}", field.name); let method_name = format_ident!("with_{field_name}"); let (typ, unwrapped) = quote_field_type_from_typ(&field.typ, true); + let docstring = quote_field_docs(reporter, field); if unwrapped { // This was originally a vec/array! quote! { + #docstring #[inline] pub fn #method_name(mut self, #field_name: impl IntoIterator>) -> Self { self.#field_name = Some(#field_name.into_iter().map(Into::into).collect()); @@ -1484,6 +1498,7 @@ fn quote_builder_from_obj(obj: &Object) -> TokenStream { } } else { quote! { + #docstring #[inline] pub fn #method_name(mut self, #field_name: impl Into<#typ>) -> Self { self.#field_name = Some(#field_name.into()); diff --git a/crates/re_types_builder/src/codegen/rust/util.rs b/crates/re_types_builder/src/codegen/rust/util.rs index c6a1c6990aa0..f73c8b2d02e9 100644 --- a/crates/re_types_builder/src/codegen/rust/util.rs +++ b/crates/re_types_builder/src/codegen/rust/util.rs @@ -72,6 +72,7 @@ pub fn string_from_quoted(acc: &TokenStream) -> String { let mut output = String::default(); let mut is_in_docstring = false; + let mut prev_line_was_docstring = false; let mut prev_line_was_attr = false; for line in string.split('\n') { @@ -94,6 +95,7 @@ pub fn string_from_quoted(acc: &TokenStream) -> String { prev_line_was_attr = false; is_in_docstring = true; + prev_line_was_docstring = true; continue; } @@ -106,7 +108,7 @@ pub fn string_from_quoted(acc: &TokenStream) -> String { let line_is_attr = trimmed.starts_with("#[allow(") || trimmed.starts_with("#[inline]"); - if !prev_line_was_attr && line_is_attr { + if line_is_attr && (!prev_line_was_attr && !prev_line_was_docstring) { output.push('\n'); } @@ -125,6 +127,7 @@ pub fn string_from_quoted(acc: &TokenStream) -> String { output.push_str(line); output.push('\n'); prev_line_was_attr = line_is_attr; + prev_line_was_docstring = false; } output diff --git a/crates/re_types_core/src/archetypes/clear.rs b/crates/re_types_core/src/archetypes/clear.rs index da15c9b1b67f..9c26eeb918c2 100644 --- a/crates/re_types_core/src/archetypes/clear.rs +++ b/crates/re_types_core/src/archetypes/clear.rs @@ -112,6 +112,7 @@ static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = }); impl Clear { + /// The total number of components in the archetype: 1 required, 1 recommended, 0 optional pub const NUM_COMPONENTS: usize = 2usize; } @@ -194,6 +195,8 @@ impl crate::AsComponents for Clear { } impl Clear { + /// Create a new `Clear`. + #[inline] pub fn new(is_recursive: impl Into) -> Self { Self { is_recursive: is_recursive.into(), diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index e56bfd384f06..d47defada3ff 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -42,7 +42,7 @@ Data types are the lowest layer of the data model hierarchy. They are re-usable * [`UVec3D`](datatypes/uvec3d.md): A uint32 vector in 3D space. * [`UVec4D`](datatypes/uvec4d.md): A uint vector in 4D space. * [`Utf8`](datatypes/utf8.md): A string of text, encoded as UTF-8. -* [`Uuid`](datatypes/uuid.md): A 16-byte uuid. +* [`Uuid`](datatypes/uuid.md): A 16-byte UUID. * [`Vec2D`](datatypes/vec2d.md): A vector in 2D space. * [`Vec3D`](datatypes/vec3d.md): A vector in 3D space. * [`Vec4D`](datatypes/vec4d.md): A vector in 4D space. diff --git a/docs/content/reference/types/datatypes/uuid.md b/docs/content/reference/types/datatypes/uuid.md index 0350677ceb1b..1dc588838df7 100644 --- a/docs/content/reference/types/datatypes/uuid.md +++ b/docs/content/reference/types/datatypes/uuid.md @@ -2,7 +2,7 @@ title: "Uuid" --- -A 16-byte uuid. +A 16-byte UUID. ## Fields diff --git a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp index f0b11c2ead69..195eb5421a94 100644 --- a/rerun_cpp/src/rerun/archetypes/boxes3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/boxes3d.hpp @@ -65,6 +65,7 @@ namespace rerun::archetypes { /// Optional center positions of the boxes. std::optional> centers; + /// Optional rotations of the boxes. std::optional> rotations; /// Optional colors for the boxes. @@ -150,6 +151,7 @@ namespace rerun::archetypes { RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } + /// Optional rotations of the boxes. Boxes3D with_rotations(Collection _rotations) && { rotations = std::move(_rotations); // See: https://github.com/rerun-io/rerun/issues/4027 diff --git a/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp b/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp index 76c1dbc5b894..c050d416d70a 100644 --- a/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp +++ b/rerun_cpp/src/rerun/archetypes/disconnected_space.hpp @@ -43,6 +43,7 @@ namespace rerun::archetypes { /// } /// ``` struct DisconnectedSpace { + /// Whether the entity path at which this is logged is disconnected from its parent. rerun::components::DisconnectedSpace disconnected_space; public: diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp index 5a77053bcb5d..ff4a42d137c9 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp @@ -45,6 +45,7 @@ namespace rerun::archetypes { /// } /// ``` struct ViewCoordinates { + /// The directions of the [x, y, z] axes. rerun::components::ViewCoordinates xyz; public: @@ -63,66 +64,186 @@ namespace rerun::archetypes { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` + /// X=Up, Y=Left, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULF; + + /// X=Up, Y=Forward, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFL; + + /// X=Left, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUF; + + /// X=Left, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFU; + + /// X=Forward, Y=Up, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUL; + + /// X=Forward, Y=Left, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLU; + + /// X=Up, Y=Left, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULB; + + /// X=Up, Y=Back, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBL; + + /// X=Left, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUB; + + /// X=Left, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBU; + + /// X=Back, Y=Up, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUL; + + /// X=Back, Y=Left, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLU; + + /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URF; + + /// X=Up, Y=Forward, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFR; + + /// X=Right, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUF; + + /// X=Right, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFU; + + /// X=Forward, Y=Up, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUR; + + /// X=Forward, Y=Right, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRU; + + /// X=Up, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URB; + + /// X=Up, Y=Back, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBR; + + /// X=Right, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUB; + + /// X=Right, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBU; + + /// X=Back, Y=Up, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUR; + + /// X=Back, Y=Right, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRU; + + /// X=Down, Y=Left, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLF; + + /// X=Down, Y=Forward, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFL; + + /// X=Left, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDF; + + /// X=Left, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFD; + + /// X=Forward, Y=Down, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDL; + + /// X=Forward, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLD; + + /// X=Down, Y=Left, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLB; + + /// X=Down, Y=Back, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBL; + + /// X=Left, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDB; + + /// X=Left, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBD; + + /// X=Back, Y=Down, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDL; + + /// X=Back, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLD; + + /// X=Down, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRF; + + /// X=Down, Y=Forward, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFR; + + /// X=Right, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDF; + + /// X=Right, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFD; + + /// X=Forward, Y=Down, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDR; + + /// X=Forward, Y=Right, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRD; + + /// X=Down, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRB; + + /// X=Down, Y=Back, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBR; + + /// X=Right, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDB; + + /// X=Right, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBD; + + /// X=Back, Y=Down, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDR; + + /// X=Back, Y=Right, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRD; + + /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_UP; + + /// X=Down, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_DOWN; + + /// X=Right, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_UP; + + /// X=Right, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_DOWN; + + /// X=Right, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_UP; + + /// X=Right, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_DOWN; + + /// X=Up, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_UP; + + /// X=Down, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_DOWN; + + /// X=Right, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_UP; + + /// X=Right, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_DOWN; + + /// X=Right, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_UP; + + /// X=Right, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_DOWN; + // public: diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp b/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp index 5693f3249d19..31de3b47e54b 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp @@ -24,66 +24,186 @@ namespace rerun { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` + /// X=Up, Y=Left, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULF; + + /// X=Up, Y=Forward, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFL; + + /// X=Left, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUF; + + /// X=Left, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFU; + + /// X=Forward, Y=Up, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUL; + + /// X=Forward, Y=Left, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLU; + + /// X=Up, Y=Left, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULB; + + /// X=Up, Y=Back, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBL; + + /// X=Left, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUB; + + /// X=Left, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBU; + + /// X=Back, Y=Up, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUL; + + /// X=Back, Y=Left, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLU; + + /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URF; + + /// X=Up, Y=Forward, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFR; + + /// X=Right, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUF; + + /// X=Right, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFU; + + /// X=Forward, Y=Up, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUR; + + /// X=Forward, Y=Right, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRU; + + /// X=Up, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URB; + + /// X=Up, Y=Back, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBR; + + /// X=Right, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUB; + + /// X=Right, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBU; + + /// X=Back, Y=Up, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUR; + + /// X=Back, Y=Right, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRU; + + /// X=Down, Y=Left, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLF; + + /// X=Down, Y=Forward, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFL; + + /// X=Left, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDF; + + /// X=Left, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFD; + + /// X=Forward, Y=Down, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDL; + + /// X=Forward, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLD; + + /// X=Down, Y=Left, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLB; + + /// X=Down, Y=Back, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBL; + + /// X=Left, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDB; + + /// X=Left, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBD; + + /// X=Back, Y=Down, Z=Left RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDL; + + /// X=Back, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLD; + + /// X=Down, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRF; + + /// X=Down, Y=Forward, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFR; + + /// X=Right, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDF; + + /// X=Right, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFD; + + /// X=Forward, Y=Down, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDR; + + /// X=Forward, Y=Right, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRD; + + /// X=Down, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRB; + + /// X=Down, Y=Back, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBR; + + /// X=Right, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDB; + + /// X=Right, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBD; + + /// X=Back, Y=Down, Z=Right RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDR; + + /// X=Back, Y=Right, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRD; + + /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_UP; + + /// X=Down, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_X_DOWN; + + /// X=Right, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_UP; + + /// X=Right, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Y_DOWN; + + /// X=Right, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_UP; + + /// X=Right, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_DOWN; + + /// X=Up, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_UP; + + /// X=Down, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_DOWN; + + /// X=Right, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_UP; + + /// X=Right, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_DOWN; + + /// X=Right, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_UP; + + /// X=Right, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_DOWN; + // // diff --git a/rerun_cpp/src/rerun/blueprint/components/corner2d.hpp b/rerun_cpp/src/rerun/blueprint/components/corner2d.hpp index 2f7559b458f4..9fc940c252ef 100644 --- a/rerun_cpp/src/rerun/blueprint/components/corner2d.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/corner2d.hpp @@ -18,12 +18,16 @@ namespace rerun::blueprint::components { /// **Component**: One of four 2D corners, typically used to align objects. enum class Corner2D : uint8_t { + /// Left top corner. LeftTop = 1, + /// Right top corner. RightTop = 2, + /// Left bottom corner. LeftBottom = 3, + /// Right bottom corner. RightBottom = 4, }; } // namespace rerun::blueprint::components diff --git a/rerun_cpp/src/rerun/components/marker_shape.hpp b/rerun_cpp/src/rerun/components/marker_shape.hpp index d1508f483dcb..599edac6e665 100644 --- a/rerun_cpp/src/rerun/components/marker_shape.hpp +++ b/rerun_cpp/src/rerun/components/marker_shape.hpp @@ -18,24 +18,34 @@ namespace rerun::components { /// **Component**: Shape of a marker. enum class MarkerShape : uint8_t { + /// `⏺` Circle = 1, + /// `◆` Diamond = 2, + /// `◼\u{fe0f}` Square = 3, + /// `x` Cross = 4, + /// `+` Plus = 5, + /// `▲` Up = 6, + /// `▼` Down = 7, + /// `◀` Left = 8, + /// `▶` Right = 9, + /// `*` Asterisk = 10, }; } // namespace rerun::components diff --git a/rerun_cpp/src/rerun/components/view_coordinates.hpp b/rerun_cpp/src/rerun/components/view_coordinates.hpp index 276ae58cd951..9e90da3616c7 100644 --- a/rerun_cpp/src/rerun/components/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/components/view_coordinates.hpp @@ -59,66 +59,186 @@ namespace rerun::components { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` + /// X=Up, Y=Left, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULF; + + /// X=Up, Y=Forward, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFL; + + /// X=Left, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUF; + + /// X=Left, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFU; + + /// X=Forward, Y=Up, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUL; + + /// X=Forward, Y=Left, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLU; + + /// X=Up, Y=Left, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULB; + + /// X=Up, Y=Back, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBL; + + /// X=Left, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUB; + + /// X=Left, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBU; + + /// X=Back, Y=Up, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUL; + + /// X=Back, Y=Left, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLU; + + /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URF; + + /// X=Up, Y=Forward, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFR; + + /// X=Right, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUF; + + /// X=Right, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFU; + + /// X=Forward, Y=Up, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUR; + + /// X=Forward, Y=Right, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRU; + + /// X=Up, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URB; + + /// X=Up, Y=Back, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBR; + + /// X=Right, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUB; + + /// X=Right, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBU; + + /// X=Back, Y=Up, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUR; + + /// X=Back, Y=Right, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRU; + + /// X=Down, Y=Left, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLF; + + /// X=Down, Y=Forward, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFL; + + /// X=Left, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDF; + + /// X=Left, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFD; + + /// X=Forward, Y=Down, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDL; + + /// X=Forward, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLD; + + /// X=Down, Y=Left, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLB; + + /// X=Down, Y=Back, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBL; + + /// X=Left, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDB; + + /// X=Left, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBD; + + /// X=Back, Y=Down, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDL; + + /// X=Back, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLD; + + /// X=Down, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRF; + + /// X=Down, Y=Forward, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFR; + + /// X=Right, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDF; + + /// X=Right, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFD; + + /// X=Forward, Y=Down, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDR; + + /// X=Forward, Y=Right, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRD; + + /// X=Down, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRB; + + /// X=Down, Y=Back, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBR; + + /// X=Right, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDB; + + /// X=Right, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBD; + + /// X=Back, Y=Down, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDR; + + /// X=Back, Y=Right, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRD; + + /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_X_UP; + + /// X=Down, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_X_DOWN; + + /// X=Right, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Y_UP; + + /// X=Right, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Y_DOWN; + + /// X=Right, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_UP; + + /// X=Right, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_DOWN; + + /// X=Up, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_UP; + + /// X=Down, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_DOWN; + + /// X=Right, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_UP; + + /// X=Right, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_DOWN; + + /// X=Right, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_UP; + + /// X=Right, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_DOWN; + // public: diff --git a/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp b/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp index f3ab06329086..17b88072237a 100644 --- a/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp +++ b/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp @@ -37,66 +37,186 @@ namespace rerun { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` + /// X=Up, Y=Left, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULF; + + /// X=Up, Y=Forward, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFL; + + /// X=Left, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUF; + + /// X=Left, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFU; + + /// X=Forward, Y=Up, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUL; + + /// X=Forward, Y=Left, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLU; + + /// X=Up, Y=Left, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULB; + + /// X=Up, Y=Back, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBL; + + /// X=Left, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUB; + + /// X=Left, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBU; + + /// X=Back, Y=Up, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUL; + + /// X=Back, Y=Left, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLU; + + /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URF; + + /// X=Up, Y=Forward, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFR; + + /// X=Right, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUF; + + /// X=Right, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFU; + + /// X=Forward, Y=Up, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUR; + + /// X=Forward, Y=Right, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRU; + + /// X=Up, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URB; + + /// X=Up, Y=Back, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBR; + + /// X=Right, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUB; + + /// X=Right, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBU; + + /// X=Back, Y=Up, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUR; + + /// X=Back, Y=Right, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRU; + + /// X=Down, Y=Left, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLF; + + /// X=Down, Y=Forward, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFL; + + /// X=Left, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDF; + + /// X=Left, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFD; + + /// X=Forward, Y=Down, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDL; + + /// X=Forward, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLD; + + /// X=Down, Y=Left, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLB; + + /// X=Down, Y=Back, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBL; + + /// X=Left, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDB; + + /// X=Left, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBD; + + /// X=Back, Y=Down, Z=Left RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDL; + + /// X=Back, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLD; + + /// X=Down, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRF; + + /// X=Down, Y=Forward, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFR; + + /// X=Right, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDF; + + /// X=Right, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFD; + + /// X=Forward, Y=Down, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDR; + + /// X=Forward, Y=Right, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRD; + + /// X=Down, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRB; + + /// X=Down, Y=Back, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBR; + + /// X=Right, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDB; + + /// X=Right, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBD; + + /// X=Back, Y=Down, Z=Right RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDR; + + /// X=Back, Y=Right, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRD; + + /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_X_UP; + + /// X=Down, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_X_DOWN; + + /// X=Right, Y=Up, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Y_UP; + + /// X=Right, Y=Down, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Y_DOWN; + + /// X=Right, Y=Forward, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_UP; + + /// X=Right, Y=Back, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_DOWN; + + /// X=Up, Y=Right, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_UP; + + /// X=Down, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_DOWN; + + /// X=Right, Y=Up, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_UP; + + /// X=Right, Y=Down, Z=Back RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_DOWN; + + /// X=Right, Y=Back, Z=Up RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_UP; + + /// X=Right, Y=Forward, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_DOWN; + // // diff --git a/rerun_cpp/src/rerun/datatypes/angle.hpp b/rerun_cpp/src/rerun/datatypes/angle.hpp index 8a907dd04158..53c6bd9dbfd3 100644 --- a/rerun_cpp/src/rerun/datatypes/angle.hpp +++ b/rerun_cpp/src/rerun/datatypes/angle.hpp @@ -29,8 +29,10 @@ namespace rerun::datatypes { /// \private union AngleData { + /// Angle in radians. One turn is equal to 2π (or τ) radians. float radians; + /// Angle in degrees. One turn is equal to 360 degrees. float degrees; AngleData() { @@ -82,6 +84,7 @@ namespace rerun::datatypes { this->_data.swap(other._data); } + /// Angle in radians. One turn is equal to 2π (or τ) radians. static Angle radians(float radians) { Angle self; self._tag = detail::AngleTag::Radians; @@ -89,6 +92,7 @@ namespace rerun::datatypes { return self; } + /// Angle in degrees. One turn is equal to 360 degrees. static Angle degrees(float degrees) { Angle self; self._tag = detail::AngleTag::Degrees; diff --git a/rerun_cpp/src/rerun/datatypes/tensor_data.hpp b/rerun_cpp/src/rerun/datatypes/tensor_data.hpp index ec8c20e75b52..d24f78cecb5b 100644 --- a/rerun_cpp/src/rerun/datatypes/tensor_data.hpp +++ b/rerun_cpp/src/rerun/datatypes/tensor_data.hpp @@ -32,8 +32,10 @@ namespace rerun::datatypes { /// For file formats, the shape is used as a hint, for chroma downsampled format /// the shape has to be the shape of the decoded image. struct TensorData { + /// The shape of the tensor, including optional names for each dimension. rerun::Collection shape; + /// The content/data. rerun::datatypes::TensorBuffer buffer; public: diff --git a/rerun_cpp/src/rerun/datatypes/transform3d.hpp b/rerun_cpp/src/rerun/datatypes/transform3d.hpp index d55fa89e42bd..33de28face4d 100644 --- a/rerun_cpp/src/rerun/datatypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/datatypes/transform3d.hpp @@ -31,8 +31,10 @@ namespace rerun::datatypes { /// \private union Transform3DData { + /// Translation plus a 3x3 matrix for scale, rotation, skew, etc. rerun::datatypes::TranslationAndMat3x3 translation_and_mat3x3; + /// Translation, rotation and scale, decomposed. rerun::datatypes::TranslationRotationScale3D translation_rotation_scale; Transform3DData() { @@ -84,15 +86,18 @@ namespace rerun::datatypes { this->_data.swap(other._data); } + /// Translation plus a 3x3 matrix for scale, rotation, skew, etc. Transform3D(rerun::datatypes::TranslationAndMat3x3 translation_and_mat3x3) : Transform3D() { *this = Transform3D::translation_and_mat3x3(std::move(translation_and_mat3x3)); } + /// Translation, rotation and scale, decomposed. Transform3D(rerun::datatypes::TranslationRotationScale3D translation_rotation_scale) : Transform3D() { *this = Transform3D::translation_rotation_scale(std::move(translation_rotation_scale)); } + /// Translation plus a 3x3 matrix for scale, rotation, skew, etc. static Transform3D translation_and_mat3x3( rerun::datatypes::TranslationAndMat3x3 translation_and_mat3x3 ) { @@ -103,6 +108,7 @@ namespace rerun::datatypes { return self; } + /// Translation, rotation and scale, decomposed. static Transform3D translation_rotation_scale( rerun::datatypes::TranslationRotationScale3D translation_rotation_scale ) { diff --git a/rerun_cpp/src/rerun/datatypes/uuid.hpp b/rerun_cpp/src/rerun/datatypes/uuid.hpp index 30328284ded6..93975fb83466 100644 --- a/rerun_cpp/src/rerun/datatypes/uuid.hpp +++ b/rerun_cpp/src/rerun/datatypes/uuid.hpp @@ -16,8 +16,9 @@ namespace arrow { } // namespace arrow namespace rerun::datatypes { - /// **Datatype**: A 16-byte uuid. + /// **Datatype**: A 16-byte UUID. struct Uuid { + /// The raw bytes representing the UUID. std::array bytes; public: diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py index 81e214b7bdee..1e6344d3e954 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py @@ -99,6 +99,10 @@ def _clear(cls) -> Boxes3D: default=None, converter=components.Rotation3DBatch._optional, # type: ignore[misc] ) + # Optional rotations of the boxes. + # + # (Docstring intentionally commented out to hide this field from the docs) + colors: components.ColorBatch | None = field( metadata={"component": "optional"}, default=None, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/disconnected_space.py b/rerun_py/rerun_sdk/rerun/archetypes/disconnected_space.py index 7c8502be84bd..81cee41c8624 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/disconnected_space.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/disconnected_space.py @@ -71,5 +71,9 @@ def _clear(cls) -> DisconnectedSpace: metadata={"component": "required"}, converter=components.DisconnectedSpaceBatch._required, # type: ignore[misc] ) + # Whether the entity path at which this is logged is disconnected from its parent. + # + # (Docstring intentionally commented out to hide this field from the docs) + __str__ = Archetype.__str__ __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py index 803d9b2490f2..fbd722bfd5ec 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py @@ -59,7 +59,15 @@ class ViewCoordinates(ViewCoordinatesExt, Archetype): """ def __init__(self: Any, xyz: components.ViewCoordinatesLike): - """Create a new instance of the ViewCoordinates archetype.""" + """ + Create a new instance of the ViewCoordinates archetype. + + Parameters + ---------- + xyz: + The directions of the [x, y, z] axes. + + """ # You can define your own __init__ function as a member of ViewCoordinatesExt in view_coordinates_ext.py with catch_and_log_exceptions(context=self.__class__.__name__): @@ -84,6 +92,10 @@ def _clear(cls) -> ViewCoordinates: metadata={"component": "required"}, converter=components.ViewCoordinatesBatch._required, # type: ignore[misc] ) + # The directions of the [x, y, z] axes. + # + # (Docstring intentionally commented out to hide this field from the docs) + __str__ = Archetype.__str__ __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/corner2d.py b/rerun_py/rerun_sdk/rerun/blueprint/components/corner2d.py index a682ad577fe8..a316f43cc4c7 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/corner2d.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/corner2d.py @@ -21,9 +21,16 @@ class Corner2D(Enum): """**Component**: One of four 2D corners, typically used to align objects.""" LeftTop = 1 + """Left top corner.""" + RightTop = 2 + """Right top corner.""" + LeftBottom = 3 + """Left bottom corner.""" + RightBottom = 4 + """Right bottom corner.""" Corner2DLike = Union[Corner2D, str] diff --git a/rerun_py/rerun_sdk/rerun/components/marker_shape.py b/rerun_py/rerun_sdk/rerun/components/marker_shape.py index e945fa04f9cc..108c5748e985 100644 --- a/rerun_py/rerun_sdk/rerun/components/marker_shape.py +++ b/rerun_py/rerun_sdk/rerun/components/marker_shape.py @@ -21,15 +21,34 @@ class MarkerShape(Enum): """**Component**: Shape of a marker.""" Circle = 1 + """`⏺`""" + Diamond = 2 + """`◆`""" + Square = 3 + """`◼️`""" + Cross = 4 + """`x`""" + Plus = 5 + """`+`""" + Up = 6 + """`▲`""" + Down = 7 + """`▼`""" + Left = 8 + """`◀`""" + Right = 9 + """`▶`""" + Asterisk = 10 + """`*`""" MarkerShapeLike = Union[MarkerShape, str] diff --git a/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py b/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py index 5d1ef67a7454..e889fa680cb5 100644 --- a/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py +++ b/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py @@ -78,65 +78,185 @@ def num_instances(self) -> int: # This section is generated by running `scripts/generate_view_coordinate_defs.py --python` # The following declarations are replaced in `deferred_patch_class`. ULF: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Left, Z=Forward""" + UFL: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Forward, Z=Left""" + LUF: ViewCoordinates = None # type: ignore[assignment] + """X=Left, Y=Up, Z=Forward""" + LFU: ViewCoordinates = None # type: ignore[assignment] + """X=Left, Y=Forward, Z=Up""" + FUL: ViewCoordinates = None # type: ignore[assignment] + """X=Forward, Y=Up, Z=Left""" + FLU: ViewCoordinates = None # type: ignore[assignment] + """X=Forward, Y=Left, Z=Up""" + ULB: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Left, Z=Back""" + UBL: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Back, Z=Left""" + LUB: ViewCoordinates = None # type: ignore[assignment] + """X=Left, Y=Up, Z=Back""" + LBU: ViewCoordinates = None # type: ignore[assignment] + """X=Left, Y=Back, Z=Up""" + BUL: ViewCoordinates = None # type: ignore[assignment] + """X=Back, Y=Up, Z=Left""" + BLU: ViewCoordinates = None # type: ignore[assignment] + """X=Back, Y=Left, Z=Up""" + URF: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Right, Z=Forward""" + UFR: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Forward, Z=Right""" + RUF: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Up, Z=Forward""" + RFU: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Forward, Z=Up""" + FUR: ViewCoordinates = None # type: ignore[assignment] + """X=Forward, Y=Up, Z=Right""" + FRU: ViewCoordinates = None # type: ignore[assignment] + """X=Forward, Y=Right, Z=Up""" + URB: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Right, Z=Back""" + UBR: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Back, Z=Right""" + RUB: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Up, Z=Back""" + RBU: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Back, Z=Up""" + BUR: ViewCoordinates = None # type: ignore[assignment] + """X=Back, Y=Up, Z=Right""" + BRU: ViewCoordinates = None # type: ignore[assignment] + """X=Back, Y=Right, Z=Up""" + DLF: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Left, Z=Forward""" + DFL: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Forward, Z=Left""" + LDF: ViewCoordinates = None # type: ignore[assignment] + """X=Left, Y=Down, Z=Forward""" + LFD: ViewCoordinates = None # type: ignore[assignment] + """X=Left, Y=Forward, Z=Down""" + FDL: ViewCoordinates = None # type: ignore[assignment] + """X=Forward, Y=Down, Z=Left""" + FLD: ViewCoordinates = None # type: ignore[assignment] + """X=Forward, Y=Left, Z=Down""" + DLB: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Left, Z=Back""" + DBL: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Back, Z=Left""" + LDB: ViewCoordinates = None # type: ignore[assignment] + """X=Left, Y=Down, Z=Back""" + LBD: ViewCoordinates = None # type: ignore[assignment] + """X=Left, Y=Back, Z=Down""" + BDL: ViewCoordinates = None # type: ignore[assignment] + """X=Back, Y=Down, Z=Left""" + BLD: ViewCoordinates = None # type: ignore[assignment] + """X=Back, Y=Left, Z=Down""" + DRF: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Right, Z=Forward""" + DFR: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Forward, Z=Right""" + RDF: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Down, Z=Forward""" + RFD: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Forward, Z=Down""" + FDR: ViewCoordinates = None # type: ignore[assignment] + """X=Forward, Y=Down, Z=Right""" + FRD: ViewCoordinates = None # type: ignore[assignment] + """X=Forward, Y=Right, Z=Down""" + DRB: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Right, Z=Back""" + DBR: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Back, Z=Right""" + RDB: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Down, Z=Back""" + RBD: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Back, Z=Down""" + BDR: ViewCoordinates = None # type: ignore[assignment] + """X=Back, Y=Down, Z=Right""" + BRD: ViewCoordinates = None # type: ignore[assignment] + """X=Back, Y=Right, Z=Down""" + RIGHT_HAND_X_UP: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Right, Z=Forward""" + RIGHT_HAND_X_DOWN: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Right, Z=Back""" + RIGHT_HAND_Y_UP: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Up, Z=Back""" + RIGHT_HAND_Y_DOWN: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Down, Z=Forward""" + RIGHT_HAND_Z_UP: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Forward, Z=Up""" + RIGHT_HAND_Z_DOWN: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Back, Z=Down""" + LEFT_HAND_X_UP: ViewCoordinates = None # type: ignore[assignment] + """X=Up, Y=Right, Z=Back""" + LEFT_HAND_X_DOWN: ViewCoordinates = None # type: ignore[assignment] + """X=Down, Y=Right, Z=Forward""" + LEFT_HAND_Y_UP: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Up, Z=Forward""" + LEFT_HAND_Y_DOWN: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Down, Z=Back""" + LEFT_HAND_Z_UP: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Back, Z=Up""" + LEFT_HAND_Z_DOWN: ViewCoordinates = None # type: ignore[assignment] + """X=Right, Y=Forward, Z=Down""" + # @staticmethod diff --git a/rerun_py/rerun_sdk/rerun/datatypes/angle.py b/rerun_py/rerun_sdk/rerun/datatypes/angle.py index 6d298b1337b7..810b90ada2b6 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/angle.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/angle.py @@ -27,10 +27,12 @@ class Angle(AngleExt): Must be one of: * Radians (float): - 3D rotation angle in radians. Only one of `degrees` or `radians` should be set. + Angle in radians. One turn is equal to 2π (or τ) radians. + Only one of `degrees` or `radians` should be set. * Degrees (float): - 3D rotation angle in degrees. Only one of `degrees` or `radians` should be set. + Angle in degrees. One turn is equal to 360 degrees. + Only one of `degrees` or `radians` should be set. """ kind: Literal["radians", "degrees"] = field(default="radians") @@ -38,10 +40,12 @@ class Angle(AngleExt): Possible values: * "Radians": - 3D rotation angle in radians. Only one of `degrees` or `radians` should be set. + Angle in radians. One turn is equal to 2π (or τ) radians. + Only one of `degrees` or `radians` should be set. * "Degrees": - 3D rotation angle in degrees. Only one of `degrees` or `radians` should be set. + Angle in degrees. One turn is equal to 360 degrees. + Only one of `degrees` or `radians` should be set. """ diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py index 35b34f38da33..7290ae847421 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_data.py @@ -46,7 +46,14 @@ class TensorData(TensorDataExt): # __init__ can be found in tensor_data_ext.py shape: list[datatypes.TensorDimension] = field() + # The shape of the tensor, including optional names for each dimension. + # + # (Docstring intentionally commented out to hide this field from the docs) + buffer: datatypes.TensorBuffer = field(converter=_tensor_data__buffer__special_field_converter_override) + # The content/data. + # + # (Docstring intentionally commented out to hide this field from the docs) if TYPE_CHECKING: diff --git a/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py b/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py index e10448ac7c09..885e6f1cb11f 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/transform3d.py @@ -28,8 +28,10 @@ class Transform3D(Transform3DExt): Must be one of: * TranslationAndMat3x3 (datatypes.TranslationAndMat3x3): + Translation plus a 3x3 matrix for scale, rotation, skew, etc. * TranslationRotationScale (datatypes.TranslationRotationScale3D): + Translation, rotation and scale, decomposed. """ diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uuid.py b/rerun_py/rerun_sdk/rerun/datatypes/uuid.py index 401259e36d95..b7dc3cda881a 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uuid.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uuid.py @@ -23,15 +23,26 @@ @define(init=False) class Uuid(UuidExt): - """**Datatype**: A 16-byte uuid.""" + """**Datatype**: A 16-byte UUID.""" def __init__(self: Any, bytes: UuidLike): - """Create a new instance of the Uuid datatype.""" + """ + Create a new instance of the Uuid datatype. + + Parameters + ---------- + bytes: + The raw bytes representing the UUID. + + """ # You can define your own __init__ function as a member of UuidExt in uuid_ext.py self.__attrs_init__(bytes=bytes) bytes: npt.NDArray[np.uint8] = field(converter=to_np_uint8) + # The raw bytes representing the UUID. + # + # (Docstring intentionally commented out to hide this field from the docs) def __array__(self, dtype: npt.DTypeLike = None) -> npt.NDArray[Any]: # You can define your own __array__ function as a member of UuidExt in uuid_ext.py diff --git a/scripts/generate_view_coordinate_defs.py b/scripts/generate_view_coordinate_defs.py index d11da8b01ce7..adaa800e7ae1 100755 --- a/scripts/generate_view_coordinate_defs.py +++ b/scripts/generate_view_coordinate_defs.py @@ -31,6 +31,11 @@ class ViewCoordinates: z: str +def docstring(coords: ViewCoordinates) -> str: + # TODO(emilk): warn about left-handed coordinate systems + return f"X={coords.x}, Y={coords.y}, Z={coords.z}" + + def generate_view_permutations() -> Iterable[ViewCoordinates]: D1 = ["Up", "Down"] D2 = ["Left", "Right"] @@ -66,7 +71,7 @@ def generate_up_handed_permutations() -> Iterable[ViewCoordinates]: def rust_arch_decl(coords: ViewCoordinates) -> str: - return f"define_coordinates!({coords.name} => ({coords.x}, {coords.y}, {coords.z}));\n" + return f'define_coordinates!("{docstring(coords)}", {coords.name} => ({coords.x}, {coords.y}, {coords.z}));\n' def gen_rust_arch_decl() -> list[str]: @@ -86,7 +91,7 @@ def gen_rust_arch_decl() -> list[str]: def rust_cmp_decl(coords: ViewCoordinates) -> str: - return f"define_coordinates!({coords.name} => ({coords.x}, {coords.y}, {coords.z}));\n" + return f'define_coordinates!("{docstring(coords)}", {coords.name} => ({coords.x}, {coords.y}, {coords.z}));\n' def gen_rust_cmp_decl() -> list[str]: @@ -146,7 +151,7 @@ def gen_py_arch_def() -> list[str]: def py_cmp_decl(coords: ViewCoordinates) -> str: - return f"{coords.name}: ViewCoordinates = None # type: ignore[assignment]\n" + return f'{coords.name}: ViewCoordinates = None # type: ignore[assignment]\n """{docstring(coords)}"""\n\n' def gen_py_cmp_decl() -> list[str]: @@ -184,7 +189,9 @@ def gen_py_cmp_def() -> list[str]: def cpp_arch_decl(coords: ViewCoordinates) -> str: - return f"RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates {coords.name};\n" + return ( + f"/// {docstring(coords)}\nRERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates {coords.name};\n\n" + ) def gen_cpp_arch_decl() -> list[str]: @@ -225,7 +232,9 @@ def gen_cpp_arch_def() -> list[str]: def cpp_cmp_decl(coords: ViewCoordinates) -> str: - return f"RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates {coords.name};\n" + return ( + f"/// {docstring(coords)}\nRERUN_SDK_EXPORT static const rerun::components::ViewCoordinates {coords.name};\n\n" + ) def gen_cpp_cmp_decl() -> list[str]: From 793090f55f8f76915be6aa04f1410bb57a080b4d Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 19:58:04 +0200 Subject: [PATCH 388/508] Codegen python arrow serialization of simple native types (#6159) ### What Codegen arrow serialization for Python for simple cases of arrow-transparent objects of simple, native types. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6159?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6159?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6159) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../rerun/components/disconnected_space.fbs | 3 + .../definitions/rerun/datatypes/float32.fbs | 1 + .../definitions/rerun/datatypes/time_int.fbs | 5 +- .../src/components/disconnected_space.rs | 3 + .../src/codegen/python/mod.rs | 66 ++++++++++++++++++- .../rerun/components/disconnected_space.hpp | 3 + .../rerun/blueprint/components/auto_layout.py | 7 +- .../blueprint/components/auto_layout_ext.py | 18 ----- .../blueprint/components/auto_space_views.py | 7 +- .../components/auto_space_views_ext.py | 18 ----- .../blueprint/components/column_share.py | 6 +- .../blueprint/components/column_share_ext.py | 18 ----- .../blueprint/components/grid_columns.py | 6 +- .../blueprint/components/grid_columns_ext.py | 18 ----- .../rerun/blueprint/components/row_share.py | 6 +- .../blueprint/components/row_share_ext.py | 18 ----- .../rerun/blueprint/components/visible.py | 7 +- .../rerun/blueprint/components/visible_ext.py | 18 ----- .../rerun/components/clear_is_recursive.py | 6 +- .../components/clear_is_recursive_ext.py | 18 ----- .../rerun_sdk/rerun/components/depth_meter.py | 6 +- .../rerun/components/depth_meter_ext.py | 18 ----- .../rerun/components/disconnected_space.py | 6 +- .../components/disconnected_space_ext.py | 13 +--- .../rerun_sdk/rerun/components/draw_order.py | 6 +- .../rerun/components/draw_order_ext.py | 18 ----- .../rerun_sdk/rerun/components/marker_size.py | 6 +- .../rerun/components/marker_size_ext.py | 18 ----- rerun_py/rerun_sdk/rerun/components/radius.py | 6 +- .../rerun_sdk/rerun/components/radius_ext.py | 18 ----- rerun_py/rerun_sdk/rerun/components/scalar.py | 6 +- .../rerun_sdk/rerun/components/scalar_ext.py | 18 ----- .../rerun/components/scalar_scattering.py | 6 +- .../rerun/components/scalar_scattering_ext.py | 18 ----- .../rerun/components/stroke_width.py | 6 +- .../rerun/components/stroke_width_ext.py | 18 ----- rerun_py/rerun_sdk/rerun/datatypes/bool.py | 7 +- .../rerun_sdk/rerun/datatypes/bool_ext.py | 18 ----- .../rerun_sdk/rerun/datatypes/class_id.py | 6 +- .../rerun_sdk/rerun/datatypes/class_id_ext.py | 18 ----- .../rerun_sdk/rerun/datatypes/entity_path.py | 12 +++- .../rerun/datatypes/entity_path_ext.py | 23 ------- rerun_py/rerun_sdk/rerun/datatypes/float32.py | 13 ++-- .../rerun_sdk/rerun/datatypes/keypoint_id.py | 6 +- .../rerun/datatypes/keypoint_id_ext.py | 18 ----- .../rerun_sdk/rerun/datatypes/time_int.py | 13 ++-- rerun_py/rerun_sdk/rerun/datatypes/uint32.py | 6 +- .../rerun_sdk/rerun/datatypes/uint32_ext.py | 18 ----- rerun_py/rerun_sdk/rerun/datatypes/uint64.py | 6 +- .../rerun_sdk/rerun/datatypes/uint64_ext.py | 18 ----- rerun_py/rerun_sdk/rerun/datatypes/utf8.py | 12 +++- .../rerun_sdk/rerun/datatypes/utf8_ext.py | 23 ------- .../test_types/components/affix_fuzzer10.py | 11 +++- .../test_types/components/affix_fuzzer9.py | 11 +++- .../test_types/datatypes/string_component.py | 11 +++- 55 files changed, 202 insertions(+), 487 deletions(-) delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/column_share_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/grid_columns_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/row_share_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/components/visible_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/clear_is_recursive_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/depth_meter_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/draw_order_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/marker_size_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/radius_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/scalar_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/scalar_scattering_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/stroke_width_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/bool_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/class_id_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/entity_path_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/keypoint_id_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/uint32_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/uint64_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/utf8_ext.py diff --git a/crates/re_types/definitions/rerun/components/disconnected_space.fbs b/crates/re_types/definitions/rerun/components/disconnected_space.fbs index af256ad1694f..8138b358d7b2 100644 --- a/crates/re_types/definitions/rerun/components/disconnected_space.fbs +++ b/crates/re_types/definitions/rerun/components/disconnected_space.fbs @@ -21,5 +21,8 @@ struct DisconnectedSpace ( "attr.rust.derive": "Copy, PartialEq, Eq" ) { /// Whether the entity path at which this is logged is disconnected from its parent. + /// + /// Set to true to disconnect the entity from its parent. + /// Set to false to disable the effects of this component, (re-)connecting the entity to its parent again. is_disconnected: bool (order: 100); } diff --git a/crates/re_types/definitions/rerun/datatypes/float32.fbs b/crates/re_types/definitions/rerun/datatypes/float32.fbs index 758d98e19086..92c1861373d5 100644 --- a/crates/re_types/definitions/rerun/datatypes/float32.fbs +++ b/crates/re_types/definitions/rerun/datatypes/float32.fbs @@ -8,6 +8,7 @@ namespace rerun.datatypes; /// A single-precision 32-bit IEEE 754 floating point number. struct Float32 ( "attr.arrow.transparent", + "attr.python.aliases": "float", "attr.rust.derive": "Copy, PartialEq, PartialOrd", "attr.rust.override_crate": "re_types_core", "attr.rust.tuple_struct" diff --git a/crates/re_types/definitions/rerun/datatypes/time_int.fbs b/crates/re_types/definitions/rerun/datatypes/time_int.fbs index 1694afa47197..794f36f83c65 100644 --- a/crates/re_types/definitions/rerun/datatypes/time_int.fbs +++ b/crates/re_types/definitions/rerun/datatypes/time_int.fbs @@ -10,9 +10,10 @@ namespace rerun.datatypes; /// A 64-bit number describing either nanoseconds OR sequence numbers. struct TimeInt ( "attr.arrow.transparent", + "attr.python.aliases": "int", "attr.rust.derive": "Copy, PartialEq, Eq, PartialOrd, Ord", - "attr.rust.tuple_struct", - "attr.rust.override_crate": "re_types_core" + "attr.rust.override_crate": "re_types_core", + "attr.rust.tuple_struct" ) { value: long (order: 100); } diff --git a/crates/re_types/src/components/disconnected_space.rs b/crates/re_types/src/components/disconnected_space.rs index 3b8cc1749e5c..777a8c1f4b98 100644 --- a/crates/re_types/src/components/disconnected_space.rs +++ b/crates/re_types/src/components/disconnected_space.rs @@ -31,6 +31,9 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; #[derive(Clone, Debug, Copy, PartialEq, Eq)] pub struct DisconnectedSpace( /// Whether the entity path at which this is logged is disconnected from its parent. + /// + /// Set to true to disconnect the entity from its parent. + /// Set to false to disable the effects of this component, (re-)connecting the entity to its parent again. pub bool, ); diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index 28d1c49dfeec..2b4afb9a85eb 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -1818,16 +1818,78 @@ fn quote_arrow_support_from_obj( } } +fn np_dtype_from_type(t: &Type) -> Option<&'static str> { + match t { + Type::UInt8 => Some("np.uint8"), + Type::UInt16 => Some("np.uint16"), + Type::UInt32 => Some("np.uint32"), + Type::UInt64 => Some("np.uint64"), + Type::Int8 => Some("np.int8"), + Type::Int16 => Some("np.int16"), + Type::Int32 => Some("np.int32"), + Type::Int64 => Some("np.int64"), + Type::Bool => Some("np.bool_"), + Type::Float16 => Some("np.float16"), + Type::Float32 => Some("np.float32"), + Type::Float64 => Some("np.float64"), + Type::Unit | Type::String | Type::Array { .. } | Type::Vector { .. } | Type::Object(_) => { + None + } + } +} + /// Only implemented for some cases. fn quote_arrow_serialization( - _reporter: &Reporter, + reporter: &Reporter, _objects: &Objects, obj: &Object, ) -> Result { let Object { name, .. } = obj; match obj.class { - ObjectClass::Struct => Err("We lack codegen for arrow-serialization of structs".to_owned()), + ObjectClass::Struct => { + if obj.is_arrow_transparent() { + if obj.fields.len() != 1 { + reporter.error( + &obj.virtpath, + &obj.fqname, + "Arrow-transparent structs must have exactly one field", + ); + } else if obj.fields[0].typ == Type::String { + return Ok(unindent( + r##" + if isinstance(data, str): + array = [data] + elif isinstance(data, Sequence): + array = [str(datum) for datum in data] + else: + array = [str(data)] + + return pa.array(array, type=data_type) + "##, + )); + } else if let Some(np_dtype) = np_dtype_from_type(&obj.fields[0].typ) { + if !obj.is_attr_set(ATTR_PYTHON_ALIASES) { + if !obj.is_testing() { + reporter.warn( + &obj.virtpath, + &obj.fqname, + format!("Expected this to have {ATTR_PYTHON_ALIASES} set"), + ); + } + } else { + return Ok(unindent(&format!( + r##" + array = np.asarray(data, dtype={np_dtype}).flatten() + return pa.array(array, type=data_type) + "## + ))); + } + } + } + + Err("We lack codegen for arrow-serialization of structs".to_owned()) + } ObjectClass::Enum => { // Generate case-insensitive string-to-enum conversion: diff --git a/rerun_cpp/src/rerun/components/disconnected_space.hpp b/rerun_cpp/src/rerun/components/disconnected_space.hpp index d6201da79e89..bf6564523d3c 100644 --- a/rerun_cpp/src/rerun/components/disconnected_space.hpp +++ b/rerun_cpp/src/rerun/components/disconnected_space.hpp @@ -23,6 +23,9 @@ namespace rerun::components { /// This is useful for specifying that a subgraph is independent of the rest of the scene. struct DisconnectedSpace { /// Whether the entity path at which this is logged is disconnected from its parent. + /// + /// Set to true to disconnect the entity from its parent. + /// Set to false to disable the effects of this component, (re-)connecting the entity to its parent again. bool is_disconnected; public: diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout.py b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout.py index d3400a4a65e7..f4b14b9dfee9 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout.py @@ -7,17 +7,17 @@ from typing import TYPE_CHECKING, Any, Sequence, Union +import numpy as np import pyarrow as pa from attrs import define, field from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .auto_layout_ext import AutoLayoutExt __all__ = ["AutoLayout", "AutoLayoutArrayLike", "AutoLayoutBatch", "AutoLayoutLike", "AutoLayoutType"] @define(init=False) -class AutoLayout(AutoLayoutExt): +class AutoLayout: """**Component**: Whether the viewport layout is determined automatically.""" def __init__(self: Any, auto_layout: AutoLayoutLike): @@ -55,4 +55,5 @@ class AutoLayoutBatch(BaseBatch[AutoLayoutArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: AutoLayoutArrayLike, data_type: pa.DataType) -> pa.Array: - return AutoLayoutExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.bool_).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout_ext.py deleted file mode 100644 index 98b91b85183c..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_layout_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import AutoLayoutArrayLike - - -class AutoLayoutExt: - """Extension for [AutoLayout][rerun.blueprint.components.AutoLayout].""" - - @staticmethod - def native_to_pa_array_override(data: AutoLayoutArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.bool_).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views.py b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views.py index f39878bc24ff..2b865268f3d1 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views.py @@ -7,11 +7,11 @@ from typing import TYPE_CHECKING, Any, Sequence, Union +import numpy as np import pyarrow as pa from attrs import define, field from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .auto_space_views_ext import AutoSpaceViewsExt __all__ = [ "AutoSpaceViews", @@ -23,7 +23,7 @@ @define(init=False) -class AutoSpaceViews(AutoSpaceViewsExt): +class AutoSpaceViews: """**Component**: Whether or not space views should be created automatically.""" def __init__(self: Any, auto_space_views: AutoSpaceViewsLike): @@ -61,4 +61,5 @@ class AutoSpaceViewsBatch(BaseBatch[AutoSpaceViewsArrayLike], ComponentBatchMixi @staticmethod def _native_to_pa_array(data: AutoSpaceViewsArrayLike, data_type: pa.DataType) -> pa.Array: - return AutoSpaceViewsExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.bool_).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views_ext.py deleted file mode 100644 index aab4046e142a..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/auto_space_views_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import AutoSpaceViewsArrayLike - - -class AutoSpaceViewsExt: - """Extension for [AutoSpaceViews][rerun.blueprint.components.AutoSpaceViews].""" - - @staticmethod - def native_to_pa_array_override(data: AutoSpaceViewsArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.bool_).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/column_share.py b/rerun_py/rerun_sdk/rerun/blueprint/components/column_share.py index 7c6c6aadcb63..abd28beb0695 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/column_share.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/column_share.py @@ -13,13 +13,12 @@ from attrs import define, field from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .column_share_ext import ColumnShareExt __all__ = ["ColumnShare", "ColumnShareArrayLike", "ColumnShareBatch", "ColumnShareLike", "ColumnShareType"] @define(init=False) -class ColumnShare(ColumnShareExt): +class ColumnShare: """**Component**: The layout share of a column in the container.""" def __init__(self: Any, share: ColumnShareLike): @@ -69,4 +68,5 @@ class ColumnShareBatch(BaseBatch[ColumnShareArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: ColumnShareArrayLike, data_type: pa.DataType) -> pa.Array: - return ColumnShareExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.float32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/column_share_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/components/column_share_ext.py deleted file mode 100644 index 66e95db200cb..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/column_share_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import ColumnShareArrayLike - - -class ColumnShareExt: - """Extension for [ColumnShare][rerun.blueprint.components.ColumnShare].""" - - @staticmethod - def native_to_pa_array_override(data: ColumnShareArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.float32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/grid_columns.py b/rerun_py/rerun_sdk/rerun/blueprint/components/grid_columns.py index 0af7deb95bcf..31827791bf29 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/grid_columns.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/grid_columns.py @@ -13,13 +13,12 @@ from attrs import define, field from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .grid_columns_ext import GridColumnsExt __all__ = ["GridColumns", "GridColumnsArrayLike", "GridColumnsBatch", "GridColumnsLike", "GridColumnsType"] @define(init=False) -class GridColumns(GridColumnsExt): +class GridColumns: """**Component**: How many columns a grid container should have.""" def __init__(self: Any, columns: GridColumnsLike): @@ -72,4 +71,5 @@ class GridColumnsBatch(BaseBatch[GridColumnsArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: GridColumnsArrayLike, data_type: pa.DataType) -> pa.Array: - return GridColumnsExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.uint32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/grid_columns_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/components/grid_columns_ext.py deleted file mode 100644 index be2e87f08ec1..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/grid_columns_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import GridColumnsArrayLike - - -class GridColumnsExt: - """Extension for [GridColumns][rerun.blueprint.components.GridColumns].""" - - @staticmethod - def native_to_pa_array_override(data: GridColumnsArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.uint32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/row_share.py b/rerun_py/rerun_sdk/rerun/blueprint/components/row_share.py index 49b16cbd59d6..387cdcab7af2 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/row_share.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/row_share.py @@ -13,13 +13,12 @@ from attrs import define, field from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .row_share_ext import RowShareExt __all__ = ["RowShare", "RowShareArrayLike", "RowShareBatch", "RowShareLike", "RowShareType"] @define(init=False) -class RowShare(RowShareExt): +class RowShare: """**Component**: The layout share of a row in the container.""" def __init__(self: Any, share: RowShareLike): @@ -69,4 +68,5 @@ class RowShareBatch(BaseBatch[RowShareArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: RowShareArrayLike, data_type: pa.DataType) -> pa.Array: - return RowShareExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.float32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/row_share_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/components/row_share_ext.py deleted file mode 100644 index bcde753ceeab..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/row_share_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import RowShareArrayLike - - -class RowShareExt: - """Extension for [RowShare][rerun.blueprint.components.RowShare].""" - - @staticmethod - def native_to_pa_array_override(data: RowShareArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.float32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible.py index 35b280ba3cf4..59d3fbc9a6e5 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/visible.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible.py @@ -7,17 +7,17 @@ from typing import TYPE_CHECKING, Any, Sequence, Union +import numpy as np import pyarrow as pa from attrs import define, field from ..._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .visible_ext import VisibleExt __all__ = ["Visible", "VisibleArrayLike", "VisibleBatch", "VisibleLike", "VisibleType"] @define(init=False) -class Visible(VisibleExt): +class Visible: """**Component**: Whether the container, space view, entity or instance is currently visible.""" def __init__(self: Any, visible: VisibleLike): @@ -55,4 +55,5 @@ class VisibleBatch(BaseBatch[VisibleArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: VisibleArrayLike, data_type: pa.DataType) -> pa.Array: - return VisibleExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.bool_).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_ext.py deleted file mode 100644 index 4511f17a5d30..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import VisibleArrayLike - - -class VisibleExt: - """Extension for [Visible][rerun.blueprint.components.Visible].""" - - @staticmethod - def native_to_pa_array_override(data: VisibleArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.bool_).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/clear_is_recursive.py b/rerun_py/rerun_sdk/rerun/components/clear_is_recursive.py index f6aaef5e515d..2083fa66f7c9 100644 --- a/rerun_py/rerun_sdk/rerun/components/clear_is_recursive.py +++ b/rerun_py/rerun_sdk/rerun/components/clear_is_recursive.py @@ -13,7 +13,6 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .clear_is_recursive_ext import ClearIsRecursiveExt __all__ = [ "ClearIsRecursive", @@ -25,7 +24,7 @@ @define(init=False) -class ClearIsRecursive(ClearIsRecursiveExt): +class ClearIsRecursive: """**Component**: Configures how a clear operation should behave - recursive or not.""" def __init__(self: Any, recursive: ClearIsRecursiveLike): @@ -71,4 +70,5 @@ class ClearIsRecursiveBatch(BaseBatch[ClearIsRecursiveArrayLike], ComponentBatch @staticmethod def _native_to_pa_array(data: ClearIsRecursiveArrayLike, data_type: pa.DataType) -> pa.Array: - return ClearIsRecursiveExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.bool_).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/clear_is_recursive_ext.py b/rerun_py/rerun_sdk/rerun/components/clear_is_recursive_ext.py deleted file mode 100644 index 4c1d0f275898..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/clear_is_recursive_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import ClearIsRecursiveArrayLike - - -class ClearIsRecursiveExt: - """Extension for [ClearIsRecursive][rerun.components.ClearIsRecursive].""" - - @staticmethod - def native_to_pa_array_override(data: ClearIsRecursiveArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.bool_).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/depth_meter.py b/rerun_py/rerun_sdk/rerun/components/depth_meter.py index c63b7b972853..34bd50f3f9ee 100644 --- a/rerun_py/rerun_sdk/rerun/components/depth_meter.py +++ b/rerun_py/rerun_sdk/rerun/components/depth_meter.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .depth_meter_ext import DepthMeterExt __all__ = ["DepthMeter", "DepthMeterArrayLike", "DepthMeterBatch", "DepthMeterLike", "DepthMeterType"] @define(init=False) -class DepthMeter(DepthMeterExt): +class DepthMeter: """**Component**: A component indicating how long a meter is, expressed in native units.""" def __init__(self: Any, value: DepthMeterLike): @@ -58,4 +57,5 @@ class DepthMeterBatch(BaseBatch[DepthMeterArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: DepthMeterArrayLike, data_type: pa.DataType) -> pa.Array: - return DepthMeterExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.float32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/depth_meter_ext.py b/rerun_py/rerun_sdk/rerun/components/depth_meter_ext.py deleted file mode 100644 index ac4861a6b6e8..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/depth_meter_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import DepthMeterArrayLike - - -class DepthMeterExt: - """Extension for [DepthMeter][rerun.components.DepthMeter].""" - - @staticmethod - def native_to_pa_array_override(data: DepthMeterArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.float32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/disconnected_space.py b/rerun_py/rerun_sdk/rerun/components/disconnected_space.py index c5c05849852d..d4b84c209e32 100644 --- a/rerun_py/rerun_sdk/rerun/components/disconnected_space.py +++ b/rerun_py/rerun_sdk/rerun/components/disconnected_space.py @@ -43,6 +43,9 @@ def __bool__(self) -> bool: is_disconnected: bool = field(converter=bool) # Whether the entity path at which this is logged is disconnected from its parent. # + # Set to true to disconnect the entity from its parent. + # Set to false to disable the effects of this component, (re-)connecting the entity to its parent again. + # # (Docstring intentionally commented out to hide this field from the docs) @@ -66,4 +69,5 @@ class DisconnectedSpaceBatch(BaseBatch[DisconnectedSpaceArrayLike], ComponentBat @staticmethod def _native_to_pa_array(data: DisconnectedSpaceArrayLike, data_type: pa.DataType) -> pa.Array: - return DisconnectedSpaceExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.bool_).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/disconnected_space_ext.py b/rerun_py/rerun_sdk/rerun/components/disconnected_space_ext.py index 323a7385fce7..e18efb13f32a 100644 --- a/rerun_py/rerun_sdk/rerun/components/disconnected_space_ext.py +++ b/rerun_py/rerun_sdk/rerun/components/disconnected_space_ext.py @@ -1,12 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import DisconnectedSpaceArrayLike +from typing import Any class DisconnectedSpaceExt: @@ -28,8 +22,3 @@ def __init__( """ self.__attrs_init__(is_disconnected=is_disconnected) - - @staticmethod - def native_to_pa_array_override(data: DisconnectedSpaceArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.bool_).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/draw_order.py b/rerun_py/rerun_sdk/rerun/components/draw_order.py index f3b0d19deec6..a4e6ae18afe9 100644 --- a/rerun_py/rerun_sdk/rerun/components/draw_order.py +++ b/rerun_py/rerun_sdk/rerun/components/draw_order.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .draw_order_ext import DrawOrderExt __all__ = ["DrawOrder", "DrawOrderArrayLike", "DrawOrderBatch", "DrawOrderLike", "DrawOrderType"] @define(init=False) -class DrawOrder(DrawOrderExt): +class DrawOrder: """ **Component**: Draw order used for the display order of 2D elements. @@ -66,4 +65,5 @@ class DrawOrderBatch(BaseBatch[DrawOrderArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: DrawOrderArrayLike, data_type: pa.DataType) -> pa.Array: - return DrawOrderExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.float32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/draw_order_ext.py b/rerun_py/rerun_sdk/rerun/components/draw_order_ext.py deleted file mode 100644 index 1d4a4197329c..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/draw_order_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import DrawOrderArrayLike - - -class DrawOrderExt: - """Extension for [DrawOrder][rerun.components.DrawOrder].""" - - @staticmethod - def native_to_pa_array_override(data: DrawOrderArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.float32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/marker_size.py b/rerun_py/rerun_sdk/rerun/components/marker_size.py index da8a18add800..b11bd77bed18 100644 --- a/rerun_py/rerun_sdk/rerun/components/marker_size.py +++ b/rerun_py/rerun_sdk/rerun/components/marker_size.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .marker_size_ext import MarkerSizeExt __all__ = ["MarkerSize", "MarkerSizeArrayLike", "MarkerSizeBatch", "MarkerSizeLike", "MarkerSizeType"] @define(init=False) -class MarkerSize(MarkerSizeExt): +class MarkerSize: """**Component**: Size of a marker in UI points.""" def __init__(self: Any, value: MarkerSizeLike): @@ -58,4 +57,5 @@ class MarkerSizeBatch(BaseBatch[MarkerSizeArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: MarkerSizeArrayLike, data_type: pa.DataType) -> pa.Array: - return MarkerSizeExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.float32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/marker_size_ext.py b/rerun_py/rerun_sdk/rerun/components/marker_size_ext.py deleted file mode 100644 index 1d20395c371a..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/marker_size_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import MarkerSizeArrayLike - - -class MarkerSizeExt: - """Extension for [MarkerSize][rerun.components.MarkerSize].""" - - @staticmethod - def native_to_pa_array_override(data: MarkerSizeArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.float32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/radius.py b/rerun_py/rerun_sdk/rerun/components/radius.py index 5740c70285b9..69f66771094c 100644 --- a/rerun_py/rerun_sdk/rerun/components/radius.py +++ b/rerun_py/rerun_sdk/rerun/components/radius.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .radius_ext import RadiusExt __all__ = ["Radius", "RadiusArrayLike", "RadiusBatch", "RadiusLike", "RadiusType"] @define(init=False) -class Radius(RadiusExt): +class Radius: """**Component**: A Radius component.""" def __init__(self: Any, value: RadiusLike): @@ -58,4 +57,5 @@ class RadiusBatch(BaseBatch[RadiusArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: RadiusArrayLike, data_type: pa.DataType) -> pa.Array: - return RadiusExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.float32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/radius_ext.py b/rerun_py/rerun_sdk/rerun/components/radius_ext.py deleted file mode 100644 index bfeddc88181a..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/radius_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import RadiusArrayLike - - -class RadiusExt: - """Extension for [Radius][rerun.components.Radius].""" - - @staticmethod - def native_to_pa_array_override(data: RadiusArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.float32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/scalar.py b/rerun_py/rerun_sdk/rerun/components/scalar.py index 74d287ce5aa6..397fed9b30c6 100644 --- a/rerun_py/rerun_sdk/rerun/components/scalar.py +++ b/rerun_py/rerun_sdk/rerun/components/scalar.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .scalar_ext import ScalarExt __all__ = ["Scalar", "ScalarArrayLike", "ScalarBatch", "ScalarLike", "ScalarType"] @define(init=False) -class Scalar(ScalarExt): +class Scalar: """ **Component**: A double-precision scalar. @@ -62,4 +61,5 @@ class ScalarBatch(BaseBatch[ScalarArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: ScalarArrayLike, data_type: pa.DataType) -> pa.Array: - return ScalarExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.float64).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/scalar_ext.py b/rerun_py/rerun_sdk/rerun/components/scalar_ext.py deleted file mode 100644 index 2c44f28ddb89..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/scalar_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import ScalarArrayLike - - -class ScalarExt: - """Extension for [Scalar][rerun.components.Scalar].""" - - @staticmethod - def native_to_pa_array_override(data: ScalarArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.float64).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/scalar_scattering.py b/rerun_py/rerun_sdk/rerun/components/scalar_scattering.py index 0759e4a512df..35a45dc5c63e 100644 --- a/rerun_py/rerun_sdk/rerun/components/scalar_scattering.py +++ b/rerun_py/rerun_sdk/rerun/components/scalar_scattering.py @@ -13,7 +13,6 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .scalar_scattering_ext import ScalarScatteringExt __all__ = [ "ScalarScattering", @@ -25,7 +24,7 @@ @define(init=False) -class ScalarScattering(ScalarScatteringExt): +class ScalarScattering: """**Component**: If true, a scalar will be shown as individual point in a scatter plot.""" def __init__(self: Any, scattered: ScalarScatteringLike): @@ -60,4 +59,5 @@ class ScalarScatteringBatch(BaseBatch[ScalarScatteringArrayLike], ComponentBatch @staticmethod def _native_to_pa_array(data: ScalarScatteringArrayLike, data_type: pa.DataType) -> pa.Array: - return ScalarScatteringExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.bool_).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/scalar_scattering_ext.py b/rerun_py/rerun_sdk/rerun/components/scalar_scattering_ext.py deleted file mode 100644 index d885dcb3321e..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/scalar_scattering_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import ScalarScatteringArrayLike - - -class ScalarScatteringExt: - """Extension for [ScalarScattering][rerun.components.ScalarScattering].""" - - @staticmethod - def native_to_pa_array_override(data: ScalarScatteringArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.bool_).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/stroke_width.py b/rerun_py/rerun_sdk/rerun/components/stroke_width.py index 51aa3af9e2c8..cf112f59fc19 100644 --- a/rerun_py/rerun_sdk/rerun/components/stroke_width.py +++ b/rerun_py/rerun_sdk/rerun/components/stroke_width.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType, ComponentBatchMixin -from .stroke_width_ext import StrokeWidthExt __all__ = ["StrokeWidth", "StrokeWidthArrayLike", "StrokeWidthBatch", "StrokeWidthLike", "StrokeWidthType"] @define(init=False) -class StrokeWidth(StrokeWidthExt): +class StrokeWidth: """**Component**: The width of a stroke specified in UI points.""" def __init__(self: Any, width: StrokeWidthLike): @@ -58,4 +57,5 @@ class StrokeWidthBatch(BaseBatch[StrokeWidthArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: StrokeWidthArrayLike, data_type: pa.DataType) -> pa.Array: - return StrokeWidthExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.float32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/components/stroke_width_ext.py b/rerun_py/rerun_sdk/rerun/components/stroke_width_ext.py deleted file mode 100644 index 18bb806ad713..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/stroke_width_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import StrokeWidthArrayLike - - -class StrokeWidthExt: - """Extension for [StrokeWidth][rerun.components.StrokeWidth].""" - - @staticmethod - def native_to_pa_array_override(data: StrokeWidthArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.float32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/bool.py b/rerun_py/rerun_sdk/rerun/datatypes/bool.py index cefabcb36551..73007807af0b 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/bool.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/bool.py @@ -7,17 +7,17 @@ from typing import TYPE_CHECKING, Any, Sequence, Union +import numpy as np import pyarrow as pa from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType -from .bool_ext import BoolExt __all__ = ["Bool", "BoolArrayLike", "BoolBatch", "BoolLike", "BoolType"] @define(init=False) -class Bool(BoolExt): +class Bool: """**Datatype**: A single boolean.""" def __init__(self: Any, value: BoolLike): @@ -55,4 +55,5 @@ class BoolBatch(BaseBatch[BoolArrayLike]): @staticmethod def _native_to_pa_array(data: BoolArrayLike, data_type: pa.DataType) -> pa.Array: - return BoolExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.bool_).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/bool_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/bool_ext.py deleted file mode 100644 index da47a8526287..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/bool_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import BoolArrayLike - - -class BoolExt: - """Extension for [Bool][rerun.datatypes.Bool].""" - - @staticmethod - def native_to_pa_array_override(data: BoolArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.bool_).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/class_id.py b/rerun_py/rerun_sdk/rerun/datatypes/class_id.py index ad41012b5f45..a6fd233bde10 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/class_id.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/class_id.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType -from .class_id_ext import ClassIdExt __all__ = ["ClassId", "ClassIdArrayLike", "ClassIdBatch", "ClassIdLike", "ClassIdType"] @define(init=False) -class ClassId(ClassIdExt): +class ClassId: """**Datatype**: A 16-bit ID representing a type of semantic class.""" def __init__(self: Any, id: ClassIdLike): @@ -58,4 +57,5 @@ class ClassIdBatch(BaseBatch[ClassIdArrayLike]): @staticmethod def _native_to_pa_array(data: ClassIdArrayLike, data_type: pa.DataType) -> pa.Array: - return ClassIdExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.uint16).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/class_id_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/class_id_ext.py deleted file mode 100644 index 16c62c0e3994..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/class_id_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import ClassIdArrayLike - - -class ClassIdExt: - """Extension for [ClassId][rerun.datatypes.ClassId].""" - - @staticmethod - def native_to_pa_array_override(data: ClassIdArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.uint16).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/entity_path.py b/rerun_py/rerun_sdk/rerun/datatypes/entity_path.py index 989a5ad40854..2e816c1f0764 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/entity_path.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/entity_path.py @@ -11,13 +11,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType -from .entity_path_ext import EntityPathExt __all__ = ["EntityPath", "EntityPathArrayLike", "EntityPathBatch", "EntityPathLike", "EntityPathType"] @define(init=False) -class EntityPath(EntityPathExt): +class EntityPath: """**Datatype**: A path to an entity in the `DataStore`.""" def __init__(self: Any, path: EntityPathLike): @@ -52,4 +51,11 @@ class EntityPathBatch(BaseBatch[EntityPathArrayLike]): @staticmethod def _native_to_pa_array(data: EntityPathArrayLike, data_type: pa.DataType) -> pa.Array: - return EntityPathExt.native_to_pa_array_override(data, data_type) + if isinstance(data, str): + array = [data] + elif isinstance(data, Sequence): + array = [str(datum) for datum in data] + else: + array = [str(data)] + + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/entity_path_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/entity_path_ext.py deleted file mode 100644 index 9d372555cec7..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/entity_path_ext.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Sequence - -import pyarrow as pa - -if TYPE_CHECKING: - from . import EntityPathArrayLike - - -class EntityPathExt: - """Extension for [EntityPath][rerun.datatypes.EntityPath].""" - - @staticmethod - def native_to_pa_array_override(data: EntityPathArrayLike, data_type: pa.DataType) -> pa.Array: - if isinstance(data, str): - array = [data] - elif isinstance(data, Sequence): - array = [str(datum) for datum in data] - else: - array = [str(data)] - - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/float32.py b/rerun_py/rerun_sdk/rerun/datatypes/float32.py index 42f3295448e1..f705bbcdb2b3 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/float32.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/float32.py @@ -5,7 +5,7 @@ from __future__ import annotations -from typing import Any, Sequence, Union +from typing import TYPE_CHECKING, Any, Sequence, Union import numpy as np import numpy.typing as npt @@ -37,7 +37,11 @@ def __float__(self) -> float: return float(self.value) -Float32Like = Float32 +if TYPE_CHECKING: + Float32Like = Union[Float32, float] +else: + Float32Like = Any + Float32ArrayLike = Union[ Float32, Sequence[Float32Like], @@ -56,6 +60,5 @@ class Float32Batch(BaseBatch[Float32ArrayLike]): @staticmethod def _native_to_pa_array(data: Float32ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of Float32 not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in float32_ext.py + array = np.asarray(data, dtype=np.float32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/keypoint_id.py b/rerun_py/rerun_sdk/rerun/datatypes/keypoint_id.py index acafbb438f65..8a3ac5dc5bd3 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/keypoint_id.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/keypoint_id.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType -from .keypoint_id_ext import KeypointIdExt __all__ = ["KeypointId", "KeypointIdArrayLike", "KeypointIdBatch", "KeypointIdLike", "KeypointIdType"] @define(init=False) -class KeypointId(KeypointIdExt): +class KeypointId: """ **Datatype**: A 16-bit ID representing a type of semantic keypoint within a class. @@ -65,4 +64,5 @@ class KeypointIdBatch(BaseBatch[KeypointIdArrayLike]): @staticmethod def _native_to_pa_array(data: KeypointIdArrayLike, data_type: pa.DataType) -> pa.Array: - return KeypointIdExt.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.uint16).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/keypoint_id_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/keypoint_id_ext.py deleted file mode 100644 index 36a990c7872d..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/keypoint_id_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import KeypointIdArrayLike - - -class KeypointIdExt: - """Extension for [KeypointId][rerun.datatypes.KeypointId].""" - - @staticmethod - def native_to_pa_array_override(data: KeypointIdArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.uint16).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/time_int.py b/rerun_py/rerun_sdk/rerun/datatypes/time_int.py index 0dbb7bc83cbf..ff7ea65764d5 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/time_int.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/time_int.py @@ -5,7 +5,7 @@ from __future__ import annotations -from typing import Any, Sequence, Union +from typing import TYPE_CHECKING, Any, Sequence, Union import numpy as np import numpy.typing as npt @@ -37,7 +37,11 @@ def __int__(self) -> int: return int(self.value) -TimeIntLike = TimeInt +if TYPE_CHECKING: + TimeIntLike = Union[TimeInt, int] +else: + TimeIntLike = Any + TimeIntArrayLike = Union[ TimeInt, Sequence[TimeIntLike], @@ -56,6 +60,5 @@ class TimeIntBatch(BaseBatch[TimeIntArrayLike]): @staticmethod def _native_to_pa_array(data: TimeIntArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of TimeInt not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in time_int_ext.py + array = np.asarray(data, dtype=np.int64).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uint32.py b/rerun_py/rerun_sdk/rerun/datatypes/uint32.py index 3856c9707bbe..8accc3696ad5 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uint32.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uint32.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType -from .uint32_ext import UInt32Ext __all__ = ["UInt32", "UInt32ArrayLike", "UInt32Batch", "UInt32Like", "UInt32Type"] @define(init=False) -class UInt32(UInt32Ext): +class UInt32: """**Datatype**: A 32bit unsigned integer.""" def __init__(self: Any, value: UInt32Like): @@ -58,4 +57,5 @@ class UInt32Batch(BaseBatch[UInt32ArrayLike]): @staticmethod def _native_to_pa_array(data: UInt32ArrayLike, data_type: pa.DataType) -> pa.Array: - return UInt32Ext.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.uint32).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uint32_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/uint32_ext.py deleted file mode 100644 index 85a4067464fc..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/uint32_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import UInt32ArrayLike - - -class UInt32Ext: - """Extension for [UInt32][rerun.datatypes.UInt32].""" - - @staticmethod - def native_to_pa_array_override(data: UInt32ArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.uint32).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uint64.py b/rerun_py/rerun_sdk/rerun/datatypes/uint64.py index 5a56ad7761b7..2dc9ad1f70aa 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uint64.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uint64.py @@ -13,13 +13,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType -from .uint64_ext import UInt64Ext __all__ = ["UInt64", "UInt64ArrayLike", "UInt64Batch", "UInt64Like", "UInt64Type"] @define(init=False) -class UInt64(UInt64Ext): +class UInt64: """**Datatype**: A 64bit unsigned integer.""" def __init__(self: Any, value: UInt64Like): @@ -58,4 +57,5 @@ class UInt64Batch(BaseBatch[UInt64ArrayLike]): @staticmethod def _native_to_pa_array(data: UInt64ArrayLike, data_type: pa.DataType) -> pa.Array: - return UInt64Ext.native_to_pa_array_override(data, data_type) + array = np.asarray(data, dtype=np.uint64).flatten() + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uint64_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/uint64_ext.py deleted file mode 100644 index 87dc951c3129..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/uint64_ext.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import numpy as np -import pyarrow as pa - -if TYPE_CHECKING: - from . import UInt64ArrayLike - - -class UInt64Ext: - """Extension for [UInt64][rerun.datatypes.UInt64].""" - - @staticmethod - def native_to_pa_array_override(data: UInt64ArrayLike, data_type: pa.DataType) -> pa.Array: - array = np.asarray(data, dtype=np.uint64).flatten() - return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/utf8.py b/rerun_py/rerun_sdk/rerun/datatypes/utf8.py index 6777d1ec564f..e401e4ca5ecf 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/utf8.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/utf8.py @@ -11,13 +11,12 @@ from attrs import define, field from .._baseclasses import BaseBatch, BaseExtensionType -from .utf8_ext import Utf8Ext __all__ = ["Utf8", "Utf8ArrayLike", "Utf8Batch", "Utf8Like", "Utf8Type"] @define(init=False) -class Utf8(Utf8Ext): +class Utf8: """**Datatype**: A string of text, encoded as UTF-8.""" def __init__(self: Any, value: Utf8Like): @@ -52,4 +51,11 @@ class Utf8Batch(BaseBatch[Utf8ArrayLike]): @staticmethod def _native_to_pa_array(data: Utf8ArrayLike, data_type: pa.DataType) -> pa.Array: - return Utf8Ext.native_to_pa_array_override(data, data_type) + if isinstance(data, str): + array = [data] + elif isinstance(data, Sequence): + array = [str(datum) for datum in data] + else: + array = [str(data)] + + return pa.array(array, type=data_type) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/utf8_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/utf8_ext.py deleted file mode 100644 index f0c243d1f182..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/utf8_ext.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Sequence - -import pyarrow as pa - -if TYPE_CHECKING: - from . import Utf8ArrayLike - - -class Utf8Ext: - """Extension for [Utf8][rerun.datatypes.Utf8].""" - - @staticmethod - def native_to_pa_array_override(data: Utf8ArrayLike, data_type: pa.DataType) -> pa.Array: - if isinstance(data, str): - array = [data] - elif isinstance(data, Sequence): - array = [str(datum) for datum in data] - else: - array = [str(data)] - - return pa.array(array, type=data_type) diff --git a/rerun_py/tests/test_types/components/affix_fuzzer10.py b/rerun_py/tests/test_types/components/affix_fuzzer10.py index 2e86a7ae8650..d52107e682db 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer10.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer10.py @@ -47,6 +47,11 @@ class AffixFuzzer10Batch(BaseBatch[AffixFuzzer10ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer10ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of AffixFuzzer10 not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in affix_fuzzer10_ext.py + if isinstance(data, str): + array = [data] + elif isinstance(data, Sequence): + array = [str(datum) for datum in data] + else: + array = [str(data)] + + return pa.array(array, type=data_type) diff --git a/rerun_py/tests/test_types/components/affix_fuzzer9.py b/rerun_py/tests/test_types/components/affix_fuzzer9.py index 864d02790192..97796d775508 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer9.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer9.py @@ -47,6 +47,11 @@ class AffixFuzzer9Batch(BaseBatch[AffixFuzzer9ArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: AffixFuzzer9ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of AffixFuzzer9 not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in affix_fuzzer9_ext.py + if isinstance(data, str): + array = [data] + elif isinstance(data, Sequence): + array = [str(datum) for datum in data] + else: + array = [str(data)] + + return pa.array(array, type=data_type) diff --git a/rerun_py/tests/test_types/datatypes/string_component.py b/rerun_py/tests/test_types/datatypes/string_component.py index 228105be1dfc..a7fe617962ac 100644 --- a/rerun_py/tests/test_types/datatypes/string_component.py +++ b/rerun_py/tests/test_types/datatypes/string_component.py @@ -53,6 +53,11 @@ class StringComponentBatch(BaseBatch[StringComponentArrayLike]): @staticmethod def _native_to_pa_array(data: StringComponentArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of StringComponent not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in string_component_ext.py + if isinstance(data, str): + array = [data] + elif isinstance(data, Sequence): + array = [str(datum) for datum in data] + else: + array = [str(data)] + + return pa.array(array, type=data_type) From e4a86aa50b50ecdd0d62155b800bd7efedcf808e Mon Sep 17 00:00:00 2001 From: Leonard Bruns Date: Mon, 29 Apr 2024 21:41:58 +0200 Subject: [PATCH 389/508] Add ROS 2 bridge example (#6163) ### What Add external [ROS 2 bridge](https://github.com/rerun-io/cpp-example-ros2-bridge) (with CARLA simulator example) to examples. https://github.com/rerun-io/rerun/assets/9785832/39a026d8-d47b-4563-b0ea-0c8f53a4c575 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG --- examples/cpp/ros2_bridge/README.md | 27 +++++++++++++++++++++++++++ examples/cpp/ros_bridge/README.md | 4 +++- examples/manifest.toml | 2 ++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 examples/cpp/ros2_bridge/README.md diff --git a/examples/cpp/ros2_bridge/README.md b/examples/cpp/ros2_bridge/README.md new file mode 100644 index 000000000000..292f557b7ce8 --- /dev/null +++ b/examples/cpp/ros2_bridge/README.md @@ -0,0 +1,27 @@ + + +A proof-of-concept Rerun bridge for ROS 2 that subscribes to all supported topics and visualizes the messages in Rerun. + +https://vimeo.com/940929187?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=2696:1552 + +## Background + +This is an example that shows how to use Rerun's C++ API to log and visualize [ROS 2](https://www.ros.org/) messages. + +It works by subscribing to all topics with supported types, converting the messages, and logging the data to Rerun. It further allows to remap topic names to specific entity paths, specify additional timeless transforms, and pinhole parameters via an external config file. See the [launch](https://github.com/rerun-io/cpp-example-ros2-bridge/tree/main/rerun_bridge/launch) directory for usage examples. + +## Run the code + +This is an external example, check the [repository](https://github.com/rerun-io/cpp-example-ros2-bridge) for more information. + +In a nutshell, clone the repo and run a demo with: + +``` +pixi run carla_example +``` diff --git a/examples/cpp/ros_bridge/README.md b/examples/cpp/ros_bridge/README.md index 82c4221e1b16..7c808a88a771 100644 --- a/examples/cpp/ros_bridge/README.md +++ b/examples/cpp/ros_bridge/README.md @@ -6,6 +6,8 @@ thumbnail = "https://static.rerun.io/ros_bridge/121f72ebaea57a1b895196a5587fd1a4 thumbnail_dimensions = [480, 480] --> +A proof-of-concept Rerun bridge for ROS 1 that subscribes to all supported topics and visualizes the messages in Rerun. + ## Background This is an example that shows how to use Rerun's C++ API to log and visualize [ROS](https://www.ros.org/) messages. @@ -28,7 +30,7 @@ This is an external example, check the [repository](https://github.com/rerun-io/ In a nutshell, clone the repo and run a demo with: ``` -pixi run example +pixi run {spot_,drone_}example ``` Note that this example currently supports Linux only. diff --git a/examples/manifest.toml b/examples/manifest.toml index beaeb4231d75..e07bf505659c 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -34,6 +34,7 @@ examples = [ # display order, most interesting first "ros_node", "nuscenes_dataset", + "ros2_bridge", "ros_bridge", "kiss-icp", "urdf_loader", @@ -102,6 +103,7 @@ Integration with 3rd party tools, formats, libraries, and APIs. examples = [ # display order, most interesting first "ros_node", + "ros2_bridge", "ros_bridge", "urdf_loader", "vrs", From 8760aa9a1c19808800321b73079afdc19d9b0b83 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 29 Apr 2024 22:18:37 +0200 Subject: [PATCH 390/508] Codegen more of our Python arrow serialization (#6154) ### What This implements codegen of python arrow serialization in cases where we can just delegate to our datatypes. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6154?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6154?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6154) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../src/codegen/python/mod.rs | 48 ++++++++++++++++++- .../components/entity_properties_component.py | 2 +- .../blueprint/datatypes/visible_time_range.py | 15 ++++-- .../datatypes/visible_time_range_boundary.py | 16 +++++-- .../rerun/components/visualizer_overrides.py | 2 +- rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py | 16 +++++-- .../rerun_sdk/rerun/datatypes/aabb2d_ext.py | 27 ----------- .../rerun/datatypes/rotation_axis_angle.py | 13 ++++- .../datatypes/rotation_axis_angle_ext.py | 22 +-------- .../rerun/datatypes/tensor_dimension.py | 2 +- .../rerun/datatypes/translation_and_mat3x3.py | 2 +- .../datatypes/translation_rotation_scale3d.py | 2 +- rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py | 2 +- rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py | 2 +- rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py | 2 +- .../test_types/components/affix_fuzzer11.py | 2 +- .../test_types/components/affix_fuzzer12.py | 2 +- .../test_types/components/affix_fuzzer13.py | 2 +- .../test_types/components/affix_fuzzer16.py | 2 +- .../test_types/components/affix_fuzzer17.py | 2 +- .../test_types/components/affix_fuzzer18.py | 2 +- .../test_types/components/affix_fuzzer7.py | 2 +- .../test_types/components/affix_fuzzer8.py | 2 +- .../test_types/datatypes/affix_fuzzer1.py | 2 +- .../test_types/datatypes/affix_fuzzer2.py | 2 +- .../test_types/datatypes/affix_fuzzer20.py | 15 ++++-- .../test_types/datatypes/affix_fuzzer21.py | 2 +- .../test_types/datatypes/affix_fuzzer22.py | 2 +- .../test_types/datatypes/affix_fuzzer5.py | 14 ++++-- .../test_types/datatypes/flattened_scalar.py | 2 +- .../datatypes/primitive_component.py | 2 +- 31 files changed, 142 insertions(+), 88 deletions(-) delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py diff --git a/crates/re_types_builder/src/codegen/python/mod.rs b/crates/re_types_builder/src/codegen/python/mod.rs index 2b4afb9a85eb..12793f62a67a 100644 --- a/crates/re_types_builder/src/codegen/python/mod.rs +++ b/crates/re_types_builder/src/codegen/python/mod.rs @@ -1841,7 +1841,7 @@ fn np_dtype_from_type(t: &Type) -> Option<&'static str> { /// Only implemented for some cases. fn quote_arrow_serialization( reporter: &Reporter, - _objects: &Objects, + objects: &Objects, obj: &Object, ) -> Result { let Object { name, .. } = obj; @@ -1888,7 +1888,51 @@ fn quote_arrow_serialization( } } - Err("We lack codegen for arrow-serialization of structs".to_owned()) + let mut code = String::new(); + + for field in &obj.fields { + let Type::Object(field_fqname) = &field.typ else { + return Err( + "We lack codegen for arrow-serialization of general structs".to_owned() + ); + }; + if let Some(last_dot) = field_fqname.rfind('.') { + let mod_path = &field_fqname[..last_dot]; + let field_type_name = &field_fqname[last_dot + 1..]; + code.push_indented( + 0, + format!("from {mod_path} import {field_type_name}Batch"), + 2, + ); + } + } + + code.push_indented(0, &format!("if isinstance(data, {name}):"), 1); + code.push_indented(1, "data = [data]", 2); + + code.push_indented(0, "return pa.StructArray.from_arrays(", 1); + code.push_indented(1, "[", 1); + for field in &obj.fields { + let Type::Object(field_fqname) = &field.typ else { + return Err( + "We lack codegen for arrow-serialization of general structs".to_owned() + ); + }; + let field_obj = &objects[field_fqname]; + let field_type_name = &field_obj.name; + let field_name = &field.name; + let field_batch_type = format!("{field_type_name}Batch"); + // let field_batch_type = format!("datatypes.{field_type_name}Batch"); + let field_array = format!("[x.{field_name} for x in data]"); + let field_fwd = + format!("{field_batch_type}({field_array}).as_arrow_array().storage,"); + code.push_indented(2, &field_fwd, 1); + } + code.push_indented(1, "],", 1); + code.push_indented(1, "fields=list(data_type),", 1); + code.push_indented(0, ")", 1); + + Ok(code) } ObjectClass::Enum => { diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py b/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py index 9b6a417f45f3..c2e19b0940e9 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/entity_properties_component.py @@ -65,5 +65,5 @@ class EntityPropertiesComponentBatch(BaseBatch[EntityPropertiesComponentArrayLik @staticmethod def _native_to_pa_array(data: EntityPropertiesComponentArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of EntityPropertiesComponent not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of EntityPropertiesComponent not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in entity_properties_component_ext.py diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py index dfafa46aa74b..6b1eae02178c 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py @@ -123,6 +123,15 @@ class VisibleTimeRangeBatch(BaseBatch[VisibleTimeRangeArrayLike]): @staticmethod def _native_to_pa_array(data: VisibleTimeRangeArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of VisibleTimeRange not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in visible_time_range_ext.py + from rerun.blueprint.datatypes import VisibleTimeRangeBoundaryBatch + + if isinstance(data, VisibleTimeRange): + data = [data] + + return pa.StructArray.from_arrays( + [ + VisibleTimeRangeBoundaryBatch([x.start for x in data]).as_arrow_array().storage, + VisibleTimeRangeBoundaryBatch([x.end for x in data]).as_arrow_array().storage, + ], + fields=list(data_type), + ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py index 35a4a27e93c1..c0813717e445 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py @@ -97,6 +97,16 @@ class VisibleTimeRangeBoundaryBatch(BaseBatch[VisibleTimeRangeBoundaryArrayLike] @staticmethod def _native_to_pa_array(data: VisibleTimeRangeBoundaryArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of VisibleTimeRangeBoundary not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in visible_time_range_boundary_ext.py + from rerun.blueprint.datatypes import VisibleTimeRangeBoundaryKindBatch + from rerun.datatypes import TimeIntBatch + + if isinstance(data, VisibleTimeRangeBoundary): + data = [data] + + return pa.StructArray.from_arrays( + [ + VisibleTimeRangeBoundaryKindBatch([x.kind for x in data]).as_arrow_array().storage, + TimeIntBatch([x.time for x in data]).as_arrow_array().storage, + ], + fields=list(data_type), + ) diff --git a/rerun_py/rerun_sdk/rerun/components/visualizer_overrides.py b/rerun_py/rerun_sdk/rerun/components/visualizer_overrides.py index f454122cd377..261c0992801d 100644 --- a/rerun_py/rerun_sdk/rerun/components/visualizer_overrides.py +++ b/rerun_py/rerun_sdk/rerun/components/visualizer_overrides.py @@ -56,5 +56,5 @@ class VisualizerOverridesBatch(BaseBatch[VisualizerOverridesArrayLike], Componen @staticmethod def _native_to_pa_array(data: VisualizerOverridesArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of VisualizerOverrides not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of VisualizerOverrides not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in visualizer_overrides_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py index df63dfc4b550..60d0923f214f 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py @@ -12,7 +12,6 @@ from .. import datatypes from .._baseclasses import BaseBatch, BaseExtensionType -from .aabb2d_ext import AABB2DExt __all__ = ["AABB2D", "AABB2DArrayLike", "AABB2DBatch", "AABB2DLike", "AABB2DType"] @@ -32,7 +31,7 @@ def _aabb2d__max__special_field_converter_override(x: datatypes.Vec2DLike) -> da @define(init=False) -class AABB2D(AABB2DExt): +class AABB2D: """**Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners.""" def __init__(self: Any, min: datatypes.Vec2DLike, max: datatypes.Vec2DLike): @@ -98,4 +97,15 @@ class AABB2DBatch(BaseBatch[AABB2DArrayLike]): @staticmethod def _native_to_pa_array(data: AABB2DArrayLike, data_type: pa.DataType) -> pa.Array: - return AABB2DExt.native_to_pa_array_override(data, data_type) + from rerun.datatypes import Vec2DBatch + + if isinstance(data, AABB2D): + data = [data] + + return pa.StructArray.from_arrays( + [ + Vec2DBatch([x.min for x in data]).as_arrow_array().storage, + Vec2DBatch([x.max for x in data]).as_arrow_array().storage, + ], + fields=list(data_type), + ) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py deleted file mode 100644 index 0e3cc2db4259..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d_ext.py +++ /dev/null @@ -1,27 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING - -import pyarrow as pa - -if TYPE_CHECKING: - from . import AABB2DArrayLike - - -class AABB2DExt: - """Extension for [AABB2D][rerun.datatypes.AABB2D].""" - - @staticmethod - def native_to_pa_array_override(data: AABB2DArrayLike, data_type: pa.DataType) -> pa.Array: - from . import AABB2D, Vec2DBatch - - if isinstance(data, AABB2D): - data = [data] - - return pa.StructArray.from_arrays( - [ - Vec2DBatch._native_to_pa_array([aabb.min for aabb in data], data_type["min"].type), - Vec2DBatch._native_to_pa_array([aabb.max for aabb in data], data_type["min"].type), - ], - fields=list(data_type), - ) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle.py b/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle.py index 209b57e16c92..9e2875a23abe 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle.py @@ -93,4 +93,15 @@ class RotationAxisAngleBatch(BaseBatch[RotationAxisAngleArrayLike]): @staticmethod def _native_to_pa_array(data: RotationAxisAngleArrayLike, data_type: pa.DataType) -> pa.Array: - return RotationAxisAngleExt.native_to_pa_array_override(data, data_type) + from rerun.datatypes import AngleBatch, Vec3DBatch + + if isinstance(data, RotationAxisAngle): + data = [data] + + return pa.StructArray.from_arrays( + [ + Vec3DBatch([x.axis for x in data]).as_arrow_array().storage, + AngleBatch([x.angle for x in data]).as_arrow_array().storage, + ], + fields=list(data_type), + ) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle_ext.py index 800da7f781af..a80d1c098b44 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/rotation_axis_angle_ext.py @@ -2,10 +2,8 @@ from typing import TYPE_CHECKING, Any -import pyarrow as pa - if TYPE_CHECKING: - from . import Angle, AngleLike, RotationAxisAngleArrayLike, Vec3DLike + from . import Angle, AngleLike, Vec3DLike class RotationAxisAngleExt: @@ -58,21 +56,3 @@ def angle__field_converter_override(x: AngleLike) -> Angle: return x else: return Angle(rad=x) - - @staticmethod - def native_to_pa_array_override(data: RotationAxisAngleArrayLike, data_type: pa.DataType) -> pa.Array: - from . import AngleBatch, RotationAxisAngle, Vec3DBatch - - if isinstance(data, RotationAxisAngle): - data = [data] - - axis_pa_array = Vec3DBatch._native_to_pa_array([rotation.axis for rotation in data], data_type["axis"].type) - angle_pa_arr = AngleBatch._native_to_pa_array([rotation.angle for rotation in data], data_type["angle"].type) - - return pa.StructArray.from_arrays( - [ - axis_pa_array, - angle_pa_arr, - ], - fields=list(data_type), - ) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py b/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py index 1173c34e4ee7..a89d3db305bc 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/tensor_dimension.py @@ -82,5 +82,5 @@ class TensorDimensionBatch(BaseBatch[TensorDimensionArrayLike]): @staticmethod def _native_to_pa_array(data: TensorDimensionArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of TensorDimension not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of TensorDimension not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in tensor_dimension_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py index c9ed68e216b9..9b18be25296d 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_and_mat3x3.py @@ -116,5 +116,5 @@ class TranslationAndMat3x3Batch(BaseBatch[TranslationAndMat3x3ArrayLike]): @staticmethod def _native_to_pa_array(data: TranslationAndMat3x3ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of TranslationAndMat3x3 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of TranslationAndMat3x3 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in translation_and_mat3x3_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py b/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py index 76b41b14c0b5..2b424afba61d 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/translation_rotation_scale3d.py @@ -166,5 +166,5 @@ class TranslationRotationScale3DBatch(BaseBatch[TranslationRotationScale3DArrayL @staticmethod def _native_to_pa_array(data: TranslationRotationScale3DArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of TranslationRotationScale3D not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of TranslationRotationScale3D not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in translation_rotation_scale3d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py b/rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py index 9e916d98c7ce..d0ae0abc5526 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uvec2d.py @@ -62,5 +62,5 @@ class UVec2DBatch(BaseBatch[UVec2DArrayLike]): @staticmethod def _native_to_pa_array(data: UVec2DArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of UVec2D not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of UVec2D not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in uvec2d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py b/rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py index 8add3e472532..e266442c593c 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uvec3d.py @@ -62,5 +62,5 @@ class UVec3DBatch(BaseBatch[UVec3DArrayLike]): @staticmethod def _native_to_pa_array(data: UVec3DArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of UVec3D not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of UVec3D not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in uvec3d_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py b/rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py index b36f3ff91b5c..987b90a10854 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/uvec4d.py @@ -62,5 +62,5 @@ class UVec4DBatch(BaseBatch[UVec4DArrayLike]): @staticmethod def _native_to_pa_array(data: UVec4DArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of UVec4D not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of UVec4D not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in uvec4d_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer11.py b/rerun_py/tests/test_types/components/affix_fuzzer11.py index e7e04d5a1943..244f06cf5ac7 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer11.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer11.py @@ -56,5 +56,5 @@ class AffixFuzzer11Batch(BaseBatch[AffixFuzzer11ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer11ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer11 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer11 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer11_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer12.py b/rerun_py/tests/test_types/components/affix_fuzzer12.py index b27cc453a8c8..4dc7fd1c6c62 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer12.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer12.py @@ -47,5 +47,5 @@ class AffixFuzzer12Batch(BaseBatch[AffixFuzzer12ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer12ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer12 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer12 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer12_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer13.py b/rerun_py/tests/test_types/components/affix_fuzzer13.py index 2cdb8cd2bc3a..5cf2de6bea60 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer13.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer13.py @@ -47,5 +47,5 @@ class AffixFuzzer13Batch(BaseBatch[AffixFuzzer13ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer13ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer13 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer13 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer13_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer16.py b/rerun_py/tests/test_types/components/affix_fuzzer16.py index 5b2ef055cc03..f66e944131a9 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer16.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer16.py @@ -111,5 +111,5 @@ class AffixFuzzer16Batch(BaseBatch[AffixFuzzer16ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer16ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer16 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer16 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer16_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer17.py b/rerun_py/tests/test_types/components/affix_fuzzer17.py index d7c0a364722a..87379bfd1240 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer17.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer17.py @@ -111,5 +111,5 @@ class AffixFuzzer17Batch(BaseBatch[AffixFuzzer17ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer17ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer17 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer17 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer17_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer18.py b/rerun_py/tests/test_types/components/affix_fuzzer18.py index feb7a017fd86..3a178fab85f6 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer18.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer18.py @@ -325,5 +325,5 @@ class AffixFuzzer18Batch(BaseBatch[AffixFuzzer18ArrayLike], ComponentBatchMixin) @staticmethod def _native_to_pa_array(data: AffixFuzzer18ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer18 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer18 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer18_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer7.py b/rerun_py/tests/test_types/components/affix_fuzzer7.py index a3d9e174d717..56b50b5a6435 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer7.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer7.py @@ -88,5 +88,5 @@ class AffixFuzzer7Batch(BaseBatch[AffixFuzzer7ArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: AffixFuzzer7ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer7 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer7 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer7_ext.py diff --git a/rerun_py/tests/test_types/components/affix_fuzzer8.py b/rerun_py/tests/test_types/components/affix_fuzzer8.py index 6977c4fa66e5..c0b64f64bd87 100644 --- a/rerun_py/tests/test_types/components/affix_fuzzer8.py +++ b/rerun_py/tests/test_types/components/affix_fuzzer8.py @@ -54,5 +54,5 @@ class AffixFuzzer8Batch(BaseBatch[AffixFuzzer8ArrayLike], ComponentBatchMixin): @staticmethod def _native_to_pa_array(data: AffixFuzzer8ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer8 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer8 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer8_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py index 3f5e154ec619..9f03af752197 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer1.py @@ -129,5 +129,5 @@ class AffixFuzzer1Batch(BaseBatch[AffixFuzzer1ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer1ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer1 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer1 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer1_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer2.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer2.py index 6329ce692720..b070fc31b786 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer2.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer2.py @@ -54,5 +54,5 @@ class AffixFuzzer2Batch(BaseBatch[AffixFuzzer2ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer2ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer2 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer2 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer2_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py index f05f3041f3ed..52bd084e7e4f 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer20.py @@ -70,6 +70,15 @@ class AffixFuzzer20Batch(BaseBatch[AffixFuzzer20ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer20ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of AffixFuzzer20 not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in affix_fuzzer20_ext.py + from rerun.testing.datatypes import PrimitiveComponentBatch, StringComponentBatch + + if isinstance(data, AffixFuzzer20): + data = [data] + + return pa.StructArray.from_arrays( + [ + PrimitiveComponentBatch([x.p for x in data]).as_arrow_array().storage, + StringComponentBatch([x.s for x in data]).as_arrow_array().storage, + ], + fields=list(data_type), + ) diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py index d3484c6538e0..2e489c2faf4f 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer21.py @@ -63,5 +63,5 @@ class AffixFuzzer21Batch(BaseBatch[AffixFuzzer21ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer21ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer21 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer21 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer21_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py index 6cc0f0819dfb..0637fdebc2bb 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer22.py @@ -65,5 +65,5 @@ class AffixFuzzer22Batch(BaseBatch[AffixFuzzer22ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer22ArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of AffixFuzzer22 not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of AffixFuzzer22 not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in affix_fuzzer22_ext.py diff --git a/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py b/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py index 25c760a252d0..6a36646ff8d5 100644 --- a/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py +++ b/rerun_py/tests/test_types/datatypes/affix_fuzzer5.py @@ -337,6 +337,14 @@ class AffixFuzzer5Batch(BaseBatch[AffixFuzzer5ArrayLike]): @staticmethod def _native_to_pa_array(data: AffixFuzzer5ArrayLike, data_type: pa.DataType) -> pa.Array: - raise NotImplementedError( - "Arrow serialization of AffixFuzzer5 not implemented: We lack codegen for arrow-serialization of structs" - ) # You need to implement native_to_pa_array_override in affix_fuzzer5_ext.py + from rerun.testing.datatypes import AffixFuzzer4Batch + + if isinstance(data, AffixFuzzer5): + data = [data] + + return pa.StructArray.from_arrays( + [ + AffixFuzzer4Batch([x.single_optional_union for x in data]).as_arrow_array().storage, + ], + fields=list(data_type), + ) diff --git a/rerun_py/tests/test_types/datatypes/flattened_scalar.py b/rerun_py/tests/test_types/datatypes/flattened_scalar.py index a959d5b950be..d58eaee92468 100644 --- a/rerun_py/tests/test_types/datatypes/flattened_scalar.py +++ b/rerun_py/tests/test_types/datatypes/flattened_scalar.py @@ -62,5 +62,5 @@ class FlattenedScalarBatch(BaseBatch[FlattenedScalarArrayLike]): @staticmethod def _native_to_pa_array(data: FlattenedScalarArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of FlattenedScalar not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of FlattenedScalar not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in flattened_scalar_ext.py diff --git a/rerun_py/tests/test_types/datatypes/primitive_component.py b/rerun_py/tests/test_types/datatypes/primitive_component.py index 23ece752f8f4..375d73b31fc7 100644 --- a/rerun_py/tests/test_types/datatypes/primitive_component.py +++ b/rerun_py/tests/test_types/datatypes/primitive_component.py @@ -60,5 +60,5 @@ class PrimitiveComponentBatch(BaseBatch[PrimitiveComponentArrayLike]): @staticmethod def _native_to_pa_array(data: PrimitiveComponentArrayLike, data_type: pa.DataType) -> pa.Array: raise NotImplementedError( - "Arrow serialization of PrimitiveComponent not implemented: We lack codegen for arrow-serialization of structs" + "Arrow serialization of PrimitiveComponent not implemented: We lack codegen for arrow-serialization of general structs" ) # You need to implement native_to_pa_array_override in primitive_component_ext.py From a10de1e369c175879335ed92a568686ff8b23eab Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 30 Apr 2024 09:38:23 +0200 Subject: [PATCH 391/508] Don't bench the re_query binaries (#6160) ### What This was causing nightly to fail with: ``` error: Unrecognized option: 'output-format' error: bench failed, to rerun pass `-p re_query --bin clamped_zip` ``` --- crates/re_query/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/re_query/Cargo.toml b/crates/re_query/Cargo.toml index 9d223195d0b5..f30c9c4e7dc1 100644 --- a/crates/re_query/Cargo.toml +++ b/crates/re_query/Cargo.toml @@ -85,11 +85,13 @@ required-features = ["to_archetype"] [[bin]] name = "clamped_zip" required-features = ["codegen"] +bench = false [[bin]] name = "range_zip" required-features = ["codegen"] +bench = false [[bench]] From 764c4afb6e5983c91159c20a326a640fd361b61e Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 30 Apr 2024 09:38:53 +0200 Subject: [PATCH 392/508] Avoid using re_types in re_query when to_archetypes feature is not enabled (#6162) ### What Without these changes `cargo check --quiet --no-default-features -p re_query` was failing nightly. --------- Co-authored-by: Clement Rey --- crates/re_query/src/lib.rs | 39 +++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs index 0d9116b54c61..a4dd0a7f188e 100644 --- a/crates/re_query/src/lib.rs +++ b/crates/re_query/src/lib.rs @@ -124,12 +124,27 @@ impl From<(RangeQuery, RangeResults)> for Results { /// /// Used internally to avoid unnecessarily caching components that are already cached in other /// places, for historical reasons. -pub fn cacheable(component_name: re_types::ComponentName) -> bool { +pub fn cacheable(component_name: re_types_core::ComponentName) -> bool { use std::sync::OnceLock; - static NOT_CACHEABLE: OnceLock = OnceLock::new(); - - use re_types_core::Loggable as _; - let not_cacheable = NOT_CACHEABLE.get_or_init(|| { + static NOT_CACHEABLE: OnceLock = OnceLock::new(); + + #[cfg(feature = "to_archetype")] + let component_names = { + // Make sure to break if these names change, so people know to update the fallback path below. + #[cfg(debug_assertions)] + { + assert_eq!( + re_types::components::TensorData::name(), + "rerun.components.TensorData" + ); + assert_eq!( + re_types::components::MeshProperties::name(), + "rerun.components.MeshProperties" + ); + assert_eq!(re_types::components::Blob::name(), "rerun.components.Blob"); + } + + use re_types_core::Loggable as _; [ // TODO(#5974): tensors might already be cached in the ad-hoc JPEG cache, we don't // want yet another copy. @@ -141,8 +156,18 @@ pub fn cacheable(component_name: re_types::ComponentName) -> bool { // the ad-hoc mesh cache -- we don't want yet another copy. re_types::components::Blob::name(), ] - .into() - }); + }; + + // Horrible hack so we can still make this work when features are disabled. + // Not great, but this all a hack anyhow. + #[cfg(not(feature = "to_archetype"))] + let component_names = [ + "rerun.components.TensorData".into(), + "rerun.components.MeshProperties".into(), + "rerun.components.Blob".into(), + ]; + + let not_cacheable = NOT_CACHEABLE.get_or_init(|| component_names.into()); !component_name.is_indicator_component() && !not_cacheable.contains(&component_name) } From 27f8a3528aea06c7c01ebdd85869540dd982348d Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Tue, 30 Apr 2024 09:55:04 +0200 Subject: [PATCH 393/508] Start codegen'ing view objects in rust (#6165) ### What First baby-step towards being able to generically dispatch to view property editors is having a view object that we can reference. This just sets up the initial code-gen scaffolding, introduces a `View` trait, and exposes a generated Identifier from it. This has the added benefit of now guaranteeing our python and rust sides will agree on the identifier used to refer to a view. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/{{pr.number}}?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/{{pr.number}}) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_space_view/src/space_view.rs | 6 +- .../re_space_view/src/space_view_contents.rs | 6 +- .../src/space_view_class.rs | 11 ++- .../src/space_view_class.rs | 5 +- .../re_space_view_spatial/src/contexts/mod.rs | 4 +- .../re_space_view_spatial/src/heuristics.rs | 6 +- .../src/space_view_2d.rs | 14 ++-- .../src/space_view_3d.rs | 14 ++-- .../src/space_view_class.rs | 12 ++- .../src/space_view_class.rs | 7 +- .../src/space_view_class.rs | 11 ++- .../src/space_view_class.rs | 10 ++- crates/re_types/src/blueprint/mod.rs | 3 + .../src/blueprint/views/.gitattributes | 11 +++ .../src/blueprint/views/bar_chart_view.rs | 46 ++++++++++++ crates/re_types/src/blueprint/views/mod.rs | 17 +++++ .../src/blueprint/views/spatial2d_view.rs | 56 ++++++++++++++ .../src/blueprint/views/spatial3d_view.rs | 73 +++++++++++++++++++ .../src/blueprint/views/tensor_view.rs | 46 ++++++++++++ .../src/blueprint/views/text_document_view.rs | 46 ++++++++++++ .../src/blueprint/views/text_log_view.rs | 46 ++++++++++++ .../src/blueprint/views/time_series_view.rs | 53 ++++++++++++++ .../re_types_builder/src/codegen/rust/api.rs | 54 ++++++++++---- crates/re_types_core/src/lib.rs | 2 + crates/re_types_core/src/view.rs | 22 ++++++ crates/re_viewer/src/ui/selection_panel.rs | 4 +- crates/re_viewer/src/ui/visible_history.rs | 7 +- crates/re_viewer_context/src/lib.rs | 13 ++-- .../re_viewer_context/src/space_view/mod.rs | 4 +- .../src/space_view/space_view_class.rs | 14 +--- .../space_view_class_placeholder.rs | 7 +- .../space_view/space_view_class_registry.rs | 5 +- .../src/space_view/spawn_heuristics.rs | 3 +- .../src/space_view/view_context_system.rs | 6 +- crates/re_viewport/src/auto_layout.rs | 3 +- .../actions/add_entities_to_new_space_view.rs | 3 +- .../context_menu/actions/add_space_view.rs | 3 +- crates/re_viewport/src/system_execution.rs | 5 +- crates/re_viewport/src/viewport.rs | 6 +- crates/re_viewport/src/viewport_blueprint.rs | 5 +- .../src/color_coordinates_space_view.rs | 9 ++- 41 files changed, 570 insertions(+), 108 deletions(-) create mode 100644 crates/re_types/src/blueprint/views/.gitattributes create mode 100644 crates/re_types/src/blueprint/views/bar_chart_view.rs create mode 100644 crates/re_types/src/blueprint/views/mod.rs create mode 100644 crates/re_types/src/blueprint/views/spatial2d_view.rs create mode 100644 crates/re_types/src/blueprint/views/spatial3d_view.rs create mode 100644 crates/re_types/src/blueprint/views/tensor_view.rs create mode 100644 crates/re_types/src/blueprint/views/text_document_view.rs create mode 100644 crates/re_types/src/blueprint/views/text_log_view.rs create mode 100644 crates/re_types/src/blueprint/views/time_series_view.rs create mode 100644 crates/re_types_core/src/view.rs diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index 8f700529f154..c0f965c23bc3 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,6 +1,7 @@ use itertools::{FoldWhile, Itertools}; use nohash_hasher::IntMap; use re_entity_db::external::re_query::PromiseResult; +use re_types::SpaceViewClassIdentifier; use crate::SpaceViewContents; use re_data_store::LatestAtQuery; @@ -15,9 +16,8 @@ use re_types_core::archetypes::Clear; use re_types_core::Archetype as _; use re_viewer_context::{ ContentsName, DataResult, OverridePath, PerSystemEntities, PropertyOverrides, - RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, SpaceViewState, - StoreContext, SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, - ViewerContext, + RecommendedSpaceView, SpaceViewClass, SpaceViewId, SpaceViewState, StoreContext, SystemCommand, + SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, }; /// A view of a space. diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index fa99d65b5068..fb55085ad1e2 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -11,13 +11,13 @@ use re_log_types::{ }; use re_types::{ blueprint::{archetypes as blueprint_archetypes, components::QueryExpression}, - Archetype as _, + Archetype as _, SpaceViewClassIdentifier, }; use re_types_core::{components::VisualizerOverrides, ComponentName}; use re_viewer_context::{ DataQueryResult, DataResult, DataResultHandle, DataResultNode, DataResultTree, - IndicatedEntities, OverridePath, PerVisualizer, PropertyOverrides, SpaceViewClassIdentifier, - SpaceViewId, StoreContext, ViewerContext, VisualizableEntities, + IndicatedEntities, OverridePath, PerVisualizer, PropertyOverrides, SpaceViewId, StoreContext, + ViewerContext, VisualizableEntities, }; use crate::{ diff --git a/crates/re_space_view_bar_chart/src/space_view_class.rs b/crates/re_space_view_bar_chart/src/space_view_class.rs index fe408e003fae..56863531807b 100644 --- a/crates/re_space_view_bar_chart/src/space_view_class.rs +++ b/crates/re_space_view_bar_chart/src/space_view_class.rs @@ -2,11 +2,11 @@ use egui::{ahash::HashMap, util::hash}; use re_entity_db::{EditableAutoValue, EntityProperties, LegendCorner}; use re_log_types::EntityPath; use re_space_view::{controls, suggest_space_view_for_each_entity}; -use re_types::datatypes::TensorBuffer; +use re_types::{datatypes::TensorBuffer, SpaceViewClassIdentifier}; use re_viewer_context::{ auto_color, IdentifiedViewSystem as _, IndicatedEntities, PerVisualizer, SpaceViewClass, - SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, - SpaceViewSystemExecutionError, ViewQuery, ViewerContext, VisualizableEntities, + SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, SpaceViewSystemExecutionError, + ViewQuery, ViewerContext, VisualizableEntities, }; use super::visualizer_system::BarChartVisualizerSystem; @@ -14,9 +14,12 @@ use super::visualizer_system::BarChartVisualizerSystem; #[derive(Default)] pub struct BarChartSpaceView; +use re_types::View; +type ViewType = re_types::blueprint::views::BarChartView; + impl SpaceViewClass for BarChartSpaceView { fn identifier() -> SpaceViewClassIdentifier { - "BarChart".into() + ViewType::identifier() } fn display_name(&self) -> &'static str { diff --git a/crates/re_space_view_dataframe/src/space_view_class.rs b/crates/re_space_view_dataframe/src/space_view_class.rs index 10125fb50df1..17f4499c828e 100644 --- a/crates/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/re_space_view_dataframe/src/space_view_class.rs @@ -6,9 +6,10 @@ use re_data_store::{DataStore, LatestAtQuery}; use re_data_ui::item_ui::instance_path_button; use re_entity_db::{EntityProperties, InstancePath}; use re_log_types::{EntityPath, Instance, Timeline}; +use re_types_core::SpaceViewClassIdentifier; use re_viewer_context::{ - SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewState, - SpaceViewSystemExecutionError, SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, + SpaceViewClass, SpaceViewClassRegistryError, SpaceViewState, SpaceViewSystemExecutionError, + SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, }; use crate::visualizer_system::EmptySystem; diff --git a/crates/re_space_view_spatial/src/contexts/mod.rs b/crates/re_space_view_spatial/src/contexts/mod.rs index ee4183cc0935..17185a15ebbc 100644 --- a/crates/re_space_view_spatial/src/contexts/mod.rs +++ b/crates/re_space_view_spatial/src/contexts/mod.rs @@ -6,14 +6,14 @@ use std::sync::atomic::AtomicUsize; pub use annotation_context::AnnotationSceneContext; pub use depth_offsets::EntityDepthOffsets; +use re_types::SpaceViewClassIdentifier; pub use transform_context::TransformContext; // ----------------------------------------------------------------------------- use re_renderer::DepthOffset; use re_viewer_context::{ - Annotations, IdentifiedViewSystem, SpaceViewClassIdentifier, SpaceViewClassRegistryError, - ViewContextSystem, + Annotations, IdentifiedViewSystem, SpaceViewClassRegistryError, ViewContextSystem, }; /// Context objects for a single entity in a spatial scene. diff --git a/crates/re_space_view_spatial/src/heuristics.rs b/crates/re_space_view_spatial/src/heuristics.rs index b9f02b074f61..2340ee864412 100644 --- a/crates/re_space_view_spatial/src/heuristics.rs +++ b/crates/re_space_view_spatial/src/heuristics.rs @@ -9,11 +9,9 @@ use re_log_types::EntityPath; use re_types::{ components::{DepthMeter, TensorData}, tensor_data::TensorDataMeaning, - Archetype as _, -}; -use re_viewer_context::{ - IdentifiedViewSystem, PerSystemEntities, SpaceViewClassIdentifier, ViewerContext, + Archetype as _, SpaceViewClassIdentifier, }; +use re_viewer_context::{IdentifiedViewSystem, PerSystemEntities, ViewerContext}; use crate::{ query_pinhole, diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index ea8797981f08..f219d35acda3 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -7,13 +7,12 @@ use re_log_types::EntityPath; use re_types::{ archetypes::{DepthImage, Image}, blueprint::archetypes::{Background, VisualBounds}, - Archetype, ComponentName, + Archetype, ComponentName, SpaceViewClassIdentifier, }; use re_viewer_context::{ - PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, - SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, - SpaceViewStateExt as _, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, - VisualizableFilterContext, + PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassRegistryError, + SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt as _, + SpaceViewSystemExecutionError, ViewQuery, ViewerContext, VisualizableFilterContext, }; use crate::{ @@ -44,9 +43,12 @@ impl VisualizableFilterContext for VisualizableFilterContext2D { #[derive(Default)] pub struct SpatialSpaceView2D; +use re_types::View; +type ViewType = re_types::blueprint::views::Spatial2DView; + impl SpaceViewClass for SpatialSpaceView2D { fn identifier() -> SpaceViewClassIdentifier { - "2D".into() + ViewType::identifier() } fn display_name(&self) -> &'static str { diff --git a/crates/re_space_view_spatial/src/space_view_3d.rs b/crates/re_space_view_spatial/src/space_view_3d.rs index 164fa47569f1..c346adccd089 100644 --- a/crates/re_space_view_spatial/src/space_view_3d.rs +++ b/crates/re_space_view_spatial/src/space_view_3d.rs @@ -3,12 +3,11 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::EntityPath; -use re_types::{components::ViewCoordinates, Loggable}; +use re_types::{components::ViewCoordinates, Loggable, SpaceViewClassIdentifier}; use re_viewer_context::{ - PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassIdentifier, - SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, - SpaceViewStateExt as _, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, - VisualizableFilterContext, + PerSystemEntities, RecommendedSpaceView, SpaceViewClass, SpaceViewClassRegistryError, + SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt as _, + SpaceViewSystemExecutionError, ViewQuery, ViewerContext, VisualizableFilterContext, }; use crate::{ @@ -38,9 +37,12 @@ impl VisualizableFilterContext for VisualizableFilterContext3D { #[derive(Default)] pub struct SpatialSpaceView3D; +use re_types::View; +type ViewType = re_types::blueprint::views::Spatial3DView; + impl SpaceViewClass for SpatialSpaceView3D { fn identifier() -> SpaceViewClassIdentifier { - "3D".into() + ViewType::identifier() } fn display_name(&self) -> &'static str { diff --git a/crates/re_space_view_tensor/src/space_view_class.rs b/crates/re_space_view_tensor/src/space_view_class.rs index 022840280a8b..8670156336a9 100644 --- a/crates/re_space_view_tensor/src/space_view_class.rs +++ b/crates/re_space_view_tensor/src/space_view_class.rs @@ -12,13 +12,14 @@ use re_renderer::Colormap; use re_types::{ datatypes::{TensorData, TensorDimension}, tensor_data::{DecodedTensor, TensorDataMeaning}, + SpaceViewClassIdentifier, }; use re_viewer_context::{ gpu_bridge::{self, colormap_dropdown_button_ui}, IdentifiedViewSystem as _, IndicatedEntities, PerVisualizer, SpaceViewClass, - SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, - SpaceViewStateExt as _, SpaceViewSystemExecutionError, TensorStatsCache, ViewQuery, - ViewerContext, VisualizableEntities, + SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, SpaceViewStateExt as _, + SpaceViewSystemExecutionError, TensorStatsCache, ViewQuery, ViewerContext, + VisualizableEntities, }; use crate::{tensor_dimension_mapper::dimension_mapping_ui, visualizer_system::TensorSystem}; @@ -26,6 +27,9 @@ use crate::{tensor_dimension_mapper::dimension_mapping_ui, visualizer_system::Te #[derive(Default)] pub struct TensorSpaceView; +use re_types::View; +type ViewType = re_types::blueprint::views::TensorView; + #[derive(Default)] pub struct ViewTensorState { /// Selects in [`Self::state_tensors`]. @@ -138,7 +142,7 @@ impl PerTensorState { impl SpaceViewClass for TensorSpaceView { fn identifier() -> SpaceViewClassIdentifier { - "Tensor".into() + ViewType::identifier() } fn display_name(&self) -> &'static str { diff --git a/crates/re_space_view_text_document/src/space_view_class.rs b/crates/re_space_view_text_document/src/space_view_class.rs index 28d1d61642a7..529a348a1b9a 100644 --- a/crates/re_space_view_text_document/src/space_view_class.rs +++ b/crates/re_space_view_text_document/src/space_view_class.rs @@ -1,8 +1,8 @@ use egui::Label; use re_space_view::suggest_space_view_for_each_entity; +use re_types::SpaceViewClassIdentifier; use re_viewer_context::external::re_entity_db::EntityProperties; -use re_viewer_context::SpaceViewClassIdentifier; use re_viewer_context::{ external::re_log_types::EntityPath, SpaceViewClass, SpaceViewClassRegistryError, SpaceViewId, SpaceViewState, SpaceViewStateExt as _, SpaceViewSystemExecutionError, ViewQuery, @@ -46,9 +46,12 @@ impl SpaceViewState for TextDocumentSpaceViewState { #[derive(Default)] pub struct TextDocumentSpaceView; +use re_types::View; +type ViewType = re_types::blueprint::views::TextDocumentView; + impl SpaceViewClass for TextDocumentSpaceView { fn identifier() -> SpaceViewClassIdentifier { - "TextDocument".into() + ViewType::identifier() } fn display_name(&self) -> &'static str { diff --git a/crates/re_space_view_text_log/src/space_view_class.rs b/crates/re_space_view_text_log/src/space_view_class.rs index ca5d0ae97848..af23aa113a2b 100644 --- a/crates/re_space_view_text_log/src/space_view_class.rs +++ b/crates/re_space_view_text_log/src/space_view_class.rs @@ -3,11 +3,11 @@ use std::collections::BTreeMap; use re_data_ui::item_ui; use re_log_types::{EntityPath, TimePoint, Timeline}; -use re_types::components::TextLogLevel; +use re_types::{components::TextLogLevel, SpaceViewClassIdentifier}; use re_viewer_context::{ level_to_rich_text, IdentifiedViewSystem as _, RecommendedSpaceView, SpaceViewClass, - SpaceViewClassIdentifier, SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, - SpaceViewState, SpaceViewStateExt, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, + SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, + SpaceViewStateExt, SpaceViewSystemExecutionError, ViewQuery, ViewerContext, }; use super::visualizer_system::{Entry, TextLogSystem}; @@ -39,9 +39,12 @@ impl SpaceViewState for TextSpaceViewState { #[derive(Default)] pub struct TextSpaceView; +use re_types::View; +type ViewType = re_types::blueprint::views::TextLogView; + impl SpaceViewClass for TextSpaceView { fn identifier() -> SpaceViewClassIdentifier { - "TextLog".into() + ViewType::identifier() } fn display_name(&self) -> &'static str { diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index b14ac17b713b..6eddd010b98a 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -7,14 +7,15 @@ use re_format::next_grid_tick_magnitude_ns; use re_log_types::{EntityPath, TimeInt, TimeZone}; use re_space_view::{controls, query_space_view_sub_archetype_or_default}; use re_types::blueprint::datatypes::VisibleTimeRange; +use re_types::SpaceViewClassIdentifier; use re_types::{blueprint::components::Corner2D, components::Range1D}; use re_viewer_context::external::re_entity_db::{ EditableAutoValue, EntityProperties, TimeSeriesAggregator, }; use re_viewer_context::{ IdentifiedViewSystem, IndicatedEntities, PerVisualizer, RecommendedSpaceView, - SmallVisualizerSet, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, - SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt as _, + SmallVisualizerSet, SpaceViewClass, SpaceViewClassRegistryError, SpaceViewId, + SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt as _, SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, ViewSystemIdentifier, ViewerContext, VisualizableEntities, }; @@ -72,6 +73,9 @@ impl SpaceViewState for TimeSeriesSpaceViewState { #[derive(Default)] pub struct TimeSeriesSpaceView; +use re_types::View; +type ViewType = re_types::blueprint::views::TimeSeriesView; + const DEFAULT_LEGEND_CORNER: egui_plot::Corner = egui_plot::Corner::RightBottom; impl TimeSeriesSpaceView { @@ -80,7 +84,7 @@ impl TimeSeriesSpaceView { impl SpaceViewClass for TimeSeriesSpaceView { fn identifier() -> SpaceViewClassIdentifier { - "TimeSeries".into() + ViewType::identifier() } fn display_name(&self) -> &'static str { diff --git a/crates/re_types/src/blueprint/mod.rs b/crates/re_types/src/blueprint/mod.rs index e11bdf9dfd53..6dbc2b84ebd7 100644 --- a/crates/re_types/src/blueprint/mod.rs +++ b/crates/re_types/src/blueprint/mod.rs @@ -6,3 +6,6 @@ pub mod components; /// The blueprint-specific datatypes. pub mod datatypes; + +/// The blueprint-specific views. +pub mod views; diff --git a/crates/re_types/src/blueprint/views/.gitattributes b/crates/re_types/src/blueprint/views/.gitattributes new file mode 100644 index 000000000000..db6bb1f285b3 --- /dev/null +++ b/crates/re_types/src/blueprint/views/.gitattributes @@ -0,0 +1,11 @@ +# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs + +.gitattributes linguist-generated=true +bar_chart_view.rs linguist-generated=true +mod.rs linguist-generated=true +spatial2d_view.rs linguist-generated=true +spatial3d_view.rs linguist-generated=true +tensor_view.rs linguist-generated=true +text_document_view.rs linguist-generated=true +text_log_view.rs linguist-generated=true +time_series_view.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/views/bar_chart_view.rs b/crates/re_types/src/blueprint/views/bar_chart_view.rs new file mode 100644 index 000000000000..ab283545b8d8 --- /dev/null +++ b/crates/re_types/src/blueprint/views/bar_chart_view.rs @@ -0,0 +1,46 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/views/bar_chart.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **View**: A bar chart view. +#[derive(Clone, Debug)] +pub struct BarChartView {} + +impl ::re_types_core::SizeBytes for BarChartView { + #[inline] + fn heap_size_bytes(&self) -> u64 { + 0 + } + + #[inline] + fn is_pod() -> bool { + true + } +} + +impl ::re_types_core::View for BarChartView { + #[inline] + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + "BarChart".into() + } +} diff --git a/crates/re_types/src/blueprint/views/mod.rs b/crates/re_types/src/blueprint/views/mod.rs new file mode 100644 index 000000000000..3005f11302c0 --- /dev/null +++ b/crates/re_types/src/blueprint/views/mod.rs @@ -0,0 +1,17 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs + +mod bar_chart_view; +mod spatial2d_view; +mod spatial3d_view; +mod tensor_view; +mod text_document_view; +mod text_log_view; +mod time_series_view; + +pub use self::bar_chart_view::BarChartView; +pub use self::spatial2d_view::Spatial2DView; +pub use self::spatial3d_view::Spatial3DView; +pub use self::tensor_view::TensorView; +pub use self::text_document_view::TextDocumentView; +pub use self::text_log_view::TextLogView; +pub use self::time_series_view::TimeSeriesView; diff --git a/crates/re_types/src/blueprint/views/spatial2d_view.rs b/crates/re_types/src/blueprint/views/spatial2d_view.rs new file mode 100644 index 000000000000..c77bca3cdbe8 --- /dev/null +++ b/crates/re_types/src/blueprint/views/spatial2d_view.rs @@ -0,0 +1,56 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **View**: A Spatial 2D view. +#[derive(Clone, Debug)] +pub struct Spatial2DView { + /// Configuration for the background of the space view. + pub background: crate::blueprint::archetypes::Background, + + /// The visible parts of the scene, in the coordinate space of the scene. + /// + /// Everything within these bounds are guaranteed to be visible. + /// Somethings outside of these bounds may also be visible due to letterboxing. + pub visual_bounds: crate::blueprint::archetypes::VisualBounds, +} + +impl ::re_types_core::SizeBytes for Spatial2DView { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.background.heap_size_bytes() + self.visual_bounds.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + && ::is_pod() + } +} + +impl ::re_types_core::View for Spatial2DView { + #[inline] + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + "2D".into() + } +} diff --git a/crates/re_types/src/blueprint/views/spatial3d_view.rs b/crates/re_types/src/blueprint/views/spatial3d_view.rs new file mode 100644 index 000000000000..b3fbf3be8a00 --- /dev/null +++ b/crates/re_types/src/blueprint/views/spatial3d_view.rs @@ -0,0 +1,73 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **View**: A Spatial 3D view. +#[derive(Clone, Debug)] +pub struct Spatial3DView { + /// Configuration for the background of the space view. + pub background: crate::blueprint::archetypes::Background, +} + +impl ::re_types_core::SizeBytes for Spatial3DView { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.background.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for Spatial3DView { + fn from(v: T) -> Self { + Self { + background: v.into(), + } + } +} + +impl std::borrow::Borrow for Spatial3DView { + #[inline] + fn borrow(&self) -> &crate::blueprint::archetypes::Background { + &self.background + } +} + +impl std::ops::Deref for Spatial3DView { + type Target = crate::blueprint::archetypes::Background; + + #[inline] + fn deref(&self) -> &crate::blueprint::archetypes::Background { + &self.background + } +} + +impl ::re_types_core::View for Spatial3DView { + #[inline] + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + "3D".into() + } +} diff --git a/crates/re_types/src/blueprint/views/tensor_view.rs b/crates/re_types/src/blueprint/views/tensor_view.rs new file mode 100644 index 000000000000..f2515bff86a8 --- /dev/null +++ b/crates/re_types/src/blueprint/views/tensor_view.rs @@ -0,0 +1,46 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/views/tensor.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **View**: A tensor view. +#[derive(Clone, Debug)] +pub struct TensorView {} + +impl ::re_types_core::SizeBytes for TensorView { + #[inline] + fn heap_size_bytes(&self) -> u64 { + 0 + } + + #[inline] + fn is_pod() -> bool { + true + } +} + +impl ::re_types_core::View for TensorView { + #[inline] + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + "Tensor".into() + } +} diff --git a/crates/re_types/src/blueprint/views/text_document_view.rs b/crates/re_types/src/blueprint/views/text_document_view.rs new file mode 100644 index 000000000000..1b39d1535ffb --- /dev/null +++ b/crates/re_types/src/blueprint/views/text_document_view.rs @@ -0,0 +1,46 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/views/text_document.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **View**: A text document view. +#[derive(Clone, Debug)] +pub struct TextDocumentView {} + +impl ::re_types_core::SizeBytes for TextDocumentView { + #[inline] + fn heap_size_bytes(&self) -> u64 { + 0 + } + + #[inline] + fn is_pod() -> bool { + true + } +} + +impl ::re_types_core::View for TextDocumentView { + #[inline] + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + "TextDocument".into() + } +} diff --git a/crates/re_types/src/blueprint/views/text_log_view.rs b/crates/re_types/src/blueprint/views/text_log_view.rs new file mode 100644 index 000000000000..f96ec96b7ba2 --- /dev/null +++ b/crates/re_types/src/blueprint/views/text_log_view.rs @@ -0,0 +1,46 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/views/text_log.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **View**: A text log view. +#[derive(Clone, Debug)] +pub struct TextLogView {} + +impl ::re_types_core::SizeBytes for TextLogView { + #[inline] + fn heap_size_bytes(&self) -> u64 { + 0 + } + + #[inline] + fn is_pod() -> bool { + true + } +} + +impl ::re_types_core::View for TextLogView { + #[inline] + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + "TextLog".into() + } +} diff --git a/crates/re_types/src/blueprint/views/time_series_view.rs b/crates/re_types/src/blueprint/views/time_series_view.rs new file mode 100644 index 000000000000..beba05c1634f --- /dev/null +++ b/crates/re_types/src/blueprint/views/time_series_view.rs @@ -0,0 +1,53 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/views/time_series.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **View**: A time series view. +#[derive(Clone, Debug)] +pub struct TimeSeriesView { + /// Configures the vertical axis of the plot. + pub axis_y: crate::blueprint::archetypes::ScalarAxis, + + /// Configures the legend of the plot. + pub plot_legend: crate::blueprint::archetypes::PlotLegend, +} + +impl ::re_types_core::SizeBytes for TimeSeriesView { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.axis_y.heap_size_bytes() + self.plot_legend.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + && ::is_pod() + } +} + +impl ::re_types_core::View for TimeSeriesView { + #[inline] + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + "TimeSeries".into() + } +} diff --git a/crates/re_types_builder/src/codegen/rust/api.rs b/crates/re_types_builder/src/codegen/rust/api.rs index c32ffaa0aa4b..9fce88796dd0 100644 --- a/crates/re_types_builder/src/codegen/rust/api.rs +++ b/crates/re_types_builder/src/codegen/rust/api.rs @@ -25,8 +25,8 @@ use crate::{ objects::ObjectClass, ArrowRegistry, CodeGenerator, Docs, ElementType, Object, ObjectField, ObjectKind, Objects, Reporter, Type, ATTR_DEFAULT, ATTR_RERUN_COMPONENT_OPTIONAL, ATTR_RERUN_COMPONENT_RECOMMENDED, - ATTR_RERUN_COMPONENT_REQUIRED, ATTR_RUST_CUSTOM_CLAUSE, ATTR_RUST_DERIVE, - ATTR_RUST_DERIVE_ONLY, ATTR_RUST_NEW_PUB_CRATE, ATTR_RUST_REPR, + ATTR_RERUN_COMPONENT_REQUIRED, ATTR_RERUN_VIEW_IDENTIFIER, ATTR_RUST_CUSTOM_CLAUSE, + ATTR_RUST_DERIVE, ATTR_RUST_DERIVE_ONLY, ATTR_RUST_NEW_PUB_CRATE, ATTR_RUST_REPR, }; use super::{ @@ -62,11 +62,6 @@ impl CodeGenerator for RustCodeGenerator { let mut files_to_write: BTreeMap = Default::default(); for object_kind in ObjectKind::ALL { - if object_kind == ObjectKind::View { - // TODO(#5521): Implement view codegen for Rust. - continue; - } - self.generate_folder( reporter, objects, @@ -389,7 +384,7 @@ fn quote_struct( let quoted_from_impl = quote_from_impl_from_obj(obj); - let quoted_trait_impls = quote_trait_impls_from_obj(arrow_registry, objects, obj); + let quoted_trait_impls = quote_trait_impls_from_obj(reporter, arrow_registry, objects, obj); let quoted_builder = quote_builder_from_obj(reporter, obj); @@ -403,6 +398,8 @@ fn quote_struct( } else { let heap_size_bytes_impl = if is_tuple_struct_from_obj(obj) { quote!(self.0.heap_size_bytes()) + } else if obj.fields.is_empty() { + quote!(0) } else { let quoted_heap_size_bytes = obj.fields.iter().map(|obj_field| { let field_name = format_ident!("{}", obj_field.name); @@ -411,7 +408,9 @@ fn quote_struct( quote!(#(#quoted_heap_size_bytes)+*) }; - let is_pod_impl = { + let is_pod_impl = if obj.fields.is_empty() { + quote!(true) + } else { let quoted_is_pods = obj.fields.iter().map(|obj_field| { let quoted_field_type = quote_field_type_from_object_field(obj_field); quote!(<#quoted_field_type>::is_pod()) @@ -494,7 +493,7 @@ fn quote_union( } }); - let quoted_trait_impls = quote_trait_impls_from_obj(arrow_registry, objects, obj); + let quoted_trait_impls = quote_trait_impls_from_obj(reporter, arrow_registry, objects, obj); let quoted_heap_size_bytes = if obj .fields @@ -614,7 +613,7 @@ fn quote_enum( } }); - let quoted_trait_impls = quote_trait_impls_from_obj(arrow_registry, objects, obj); + let quoted_trait_impls = quote_trait_impls_from_obj(reporter, arrow_registry, objects, obj); let count = Literal::usize_unsuffixed(fields.len()); let all = fields.iter().map(|field| { @@ -723,9 +722,13 @@ fn quote_obj_docs(reporter: &Reporter, obj: &Object) -> TokenStream { fn doc_as_lines(reporter: &Reporter, virtpath: &str, fqname: &str, docs: &Docs) -> Vec { let mut lines = docs.doc_lines_for_untagged_and("rs"); - let examples = collect_snippets_for_api_docs(docs, "rs", true) - .map_err(|err| reporter.error(virtpath, fqname, err)) - .unwrap_or_default(); + let examples = if !fqname.starts_with("rerun.blueprint.views") { + collect_snippets_for_api_docs(docs, "rs", true) + .map_err(|err| reporter.error(virtpath, fqname, err)) + .unwrap_or_default() + } else { + Vec::new() + }; if !examples.is_empty() { lines.push(Default::default()); @@ -934,6 +937,7 @@ fn quote_meta_clause_from_obj(obj: &Object, attr: &str, clause: &str) -> TokenSt } fn quote_trait_impls_from_obj( + reporter: &Reporter, arrow_registry: &ArrowRegistry, objects: &Objects, obj: &Object, @@ -1293,7 +1297,27 @@ fn quote_trait_impls_from_obj( } } } - ObjectKind::View => unimplemented!(), + ObjectKind::View => { + let Some(identifier): Option = obj.try_get_attr(ATTR_RERUN_VIEW_IDENTIFIER) + else { + reporter.error( + &obj.virtpath, + &obj.fqname, + format!("Missing {ATTR_RERUN_VIEW_IDENTIFIER} attribute for view"), + ); + return TokenStream::new(); + }; + + quote! { + impl ::re_types_core::View for #name { + #[inline] + fn identifier() -> ::re_types_core::SpaceViewClassIdentifier { + #identifier .into() + } + + } + } + } } } diff --git a/crates/re_types_core/src/lib.rs b/crates/re_types_core/src/lib.rs index 657d3eaa5cd7..08dea18b9868 100644 --- a/crates/re_types_core/src/lib.rs +++ b/crates/re_types_core/src/lib.rs @@ -77,6 +77,7 @@ mod loggable_batch; mod result; mod size_bytes; mod tuid; +mod view; pub use self::archetype::{ Archetype, ArchetypeName, GenericIndicatorComponent, NamedIndicatorComponent, @@ -92,6 +93,7 @@ pub use self::result::{ SerializationResult, _Backtrace, }; pub use self::size_bytes::SizeBytes; +pub use self::view::{SpaceViewClassIdentifier, View}; /// Fundamental [`Archetype`]s that are implemented in `re_types_core` directly for convenience and /// dependency optimization. diff --git a/crates/re_types_core/src/view.rs b/crates/re_types_core/src/view.rs new file mode 100644 index 000000000000..fc6d3da60c5e --- /dev/null +++ b/crates/re_types_core/src/view.rs @@ -0,0 +1,22 @@ +// --- +re_string_interner::declare_new_type!( + /// The unique name of a space view type. + pub struct SpaceViewClassIdentifier; +); + +impl SpaceViewClassIdentifier { + pub fn invalid() -> Self { + Self::from("invalid") + } +} + +/// Views are the panels shown in the viewer's viewport and the primary means of +/// inspecting & visualizing previously logged data. +/// +/// In addition to the data that it contains via `SpaceViewContents`, each view +/// has several view properties that configure how it behaves. Each view property +/// is a [`crate::Archetype`] that is stored in the viewer's blueprint database. + +pub trait View { + fn identifier() -> SpaceViewClassIdentifier; +} diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 0e0e1622c550..97aef089d2f8 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -13,13 +13,13 @@ use re_space_view_time_series::TimeSeriesSpaceView; use re_types::{ components::{PinholeProjection, Transform3D}, tensor_data::TensorDataMeaning, + SpaceViewClassIdentifier, }; use re_ui::{icons, list_item::ListItem}; use re_ui::{ReUi, SyntaxHighlighting as _}; use re_viewer_context::{ gpu_bridge::colormap_dropdown_button_ui, ContainerId, Contents, DataQueryResult, - HoverHighlight, Item, SpaceViewClass, SpaceViewClassIdentifier, SpaceViewId, UiVerbosity, - ViewerContext, + HoverHighlight, Item, SpaceViewClass, SpaceViewId, UiVerbosity, ViewerContext, }; use re_viewport::{ contents_name_style, context_menu_ui_for_item, icon_for_container_kind, diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visible_history.rs index c00f4118a7fe..50a2260dd1a6 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visible_history.rs @@ -11,10 +11,13 @@ use re_space_view::{ }; use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D}; use re_space_view_time_series::TimeSeriesSpaceView; -use re_types::blueprint::components::{VisibleTimeRangeSequence, VisibleTimeRangeTime}; +use re_types::{ + blueprint::components::{VisibleTimeRangeSequence, VisibleTimeRangeTime}, + SpaceViewClassIdentifier, +}; use re_types_core::Loggable as _; use re_ui::{markdown_ui, ReUi}; -use re_viewer_context::{SpaceViewClass, SpaceViewClassIdentifier, ViewerContext}; +use re_viewer_context::{SpaceViewClass, ViewerContext}; /// These space views support the Visible History feature. static VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS: once_cell::sync::Lazy< diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index a8413981515f..5a2a767ac631 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -50,13 +50,12 @@ pub use selection_state::{ pub use space_view::{ DataResult, IdentifiedViewSystem, OverridePath, PerSystemDataResults, PerSystemEntities, PropertyOverrides, RecommendedSpaceView, SmallVisualizerSet, SpaceViewClass, - SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, SpaceViewClassRegistry, - SpaceViewClassRegistryError, SpaceViewEntityHighlight, SpaceViewHighlights, - SpaceViewOutlineMasks, SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt, - SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, SystemExecutionOutput, - ViewContextCollection, ViewContextSystem, ViewQuery, ViewSystemIdentifier, - VisualizableFilterContext, VisualizerAdditionalApplicabilityFilter, VisualizerCollection, - VisualizerQueryInfo, VisualizerSystem, + SpaceViewClassLayoutPriority, SpaceViewClassRegistry, SpaceViewClassRegistryError, + SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks, SpaceViewSpawnHeuristics, + SpaceViewState, SpaceViewStateExt, SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, + SystemExecutionOutput, ViewContextCollection, ViewContextSystem, ViewQuery, + ViewSystemIdentifier, VisualizableFilterContext, VisualizerAdditionalApplicabilityFilter, + VisualizerCollection, VisualizerQueryInfo, VisualizerSystem, }; pub use store_context::StoreContext; pub use store_hub::StoreHub; diff --git a/crates/re_viewer_context/src/space_view/mod.rs b/crates/re_viewer_context/src/space_view/mod.rs index b4da1ba5f82b..ac20da8ddf52 100644 --- a/crates/re_viewer_context/src/space_view/mod.rs +++ b/crates/re_viewer_context/src/space_view/mod.rs @@ -19,8 +19,8 @@ mod visualizer_system; pub use highlights::{SpaceViewEntityHighlight, SpaceViewHighlights, SpaceViewOutlineMasks}; pub use named_system::{IdentifiedViewSystem, PerSystemEntities, ViewSystemIdentifier}; pub use space_view_class::{ - SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, SpaceViewState, - SpaceViewStateExt, VisualizableFilterContext, + SpaceViewClass, SpaceViewClassLayoutPriority, SpaceViewState, SpaceViewStateExt, + VisualizableFilterContext, }; pub use space_view_class_registry::{ SpaceViewClassRegistry, SpaceViewClassRegistryError, SpaceViewSystemRegistrator, diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index 57acd405048e..4a5a29f1330e 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -1,7 +1,7 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityProperties, EntityPropertyMap}; use re_log_types::EntityPath; -use re_types::{blueprint::datatypes::VisibleTimeRange, ComponentName}; +use re_types::{blueprint::datatypes::VisibleTimeRange, ComponentName, SpaceViewClassIdentifier}; use crate::{ IndicatedEntities, PerSystemEntities, PerVisualizer, SmallVisualizerSet, @@ -10,18 +10,6 @@ use crate::{ ViewerContext, VisualizableEntities, }; -re_string_interner::declare_new_type!( - /// The unique name of a space view type. - #[derive(serde::Deserialize, serde::Serialize)] - pub struct SpaceViewClassIdentifier; -); - -impl SpaceViewClassIdentifier { - pub fn invalid() -> Self { - Self::from("invalid") - } -} - #[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd, Ord, Eq)] pub enum SpaceViewClassLayoutPriority { /// This space view can share space with others diff --git a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs index 2d64e1f5c31c..550a8a507fee 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_placeholder.rs @@ -1,9 +1,10 @@ use crate::{ - SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassRegistryError, - SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewSystemExecutionError, - SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, ViewerContext, + SpaceViewClass, SpaceViewClassRegistryError, SpaceViewSpawnHeuristics, SpaceViewState, + SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, + ViewerContext, }; use re_entity_db::EntityProperties; +use re_types::SpaceViewClassIdentifier; /// A placeholder space view class that can be used when the actual class is not registered. #[derive(Default)] diff --git a/crates/re_viewer_context/src/space_view/space_view_class_registry.rs b/crates/re_viewer_context/src/space_view/space_view_class_registry.rs index d15450ab8681..6d00ba61ee9a 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class_registry.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class_registry.rs @@ -1,10 +1,11 @@ use ahash::{HashMap, HashSet}; use re_data_store::DataStore; +use re_types::SpaceViewClassIdentifier; use crate::{ ApplicableEntities, IdentifiedViewSystem, IndicatedEntities, PerVisualizer, SpaceViewClass, - SpaceViewClassIdentifier, ViewContextCollection, ViewContextSystem, ViewSystemIdentifier, - VisualizerCollection, VisualizerSystem, + ViewContextCollection, ViewContextSystem, ViewSystemIdentifier, VisualizerCollection, + VisualizerSystem, }; use super::{ diff --git a/crates/re_viewer_context/src/space_view/spawn_heuristics.rs b/crates/re_viewer_context/src/space_view/spawn_heuristics.rs index 7da42a08ddf5..edaf7bbec7fd 100644 --- a/crates/re_viewer_context/src/space_view/spawn_heuristics.rs +++ b/crates/re_viewer_context/src/space_view/spawn_heuristics.rs @@ -1,6 +1,5 @@ use re_log_types::{hash::Hash64, EntityPath, EntityPathFilter, EntityPathSubs}; - -use crate::SpaceViewClassIdentifier; +use re_types::SpaceViewClassIdentifier; /// Properties of a space view that as recommended to be spawned by default via space view spawn heuristics. #[derive(Debug, Clone)] diff --git a/crates/re_viewer_context/src/space_view/view_context_system.rs b/crates/re_viewer_context/src/space_view/view_context_system.rs index c1cfb2a8d31f..c9a55b9a5775 100644 --- a/crates/re_viewer_context/src/space_view/view_context_system.rs +++ b/crates/re_viewer_context/src/space_view/view_context_system.rs @@ -1,10 +1,10 @@ use ahash::HashMap; -use re_types::ComponentNameSet; +use re_types::{ComponentNameSet, SpaceViewClassIdentifier}; use crate::{ - IdentifiedViewSystem, SpaceViewClassIdentifier, SpaceViewSystemExecutionError, ViewQuery, - ViewSystemIdentifier, ViewerContext, + IdentifiedViewSystem, SpaceViewSystemExecutionError, ViewQuery, ViewSystemIdentifier, + ViewerContext, }; /// View context that can be used by view parts and ui methods to retrieve information about the scene as a whole. diff --git a/crates/re_viewport/src/auto_layout.rs b/crates/re_viewport/src/auto_layout.rs index 351590644f76..8252d57f1b1e 100644 --- a/crates/re_viewport/src/auto_layout.rs +++ b/crates/re_viewport/src/auto_layout.rs @@ -6,7 +6,8 @@ use std::collections::BTreeMap; use itertools::Itertools as _; -use re_viewer_context::{SpaceViewClassIdentifier, SpaceViewId}; +use re_types::SpaceViewClassIdentifier; +use re_viewer_context::SpaceViewId; use re_space_view::SpaceViewBlueprint; diff --git a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs index b224f7583c64..ba9e2569fd06 100644 --- a/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs +++ b/crates/re_viewport/src/context_menu/actions/add_entities_to_new_space_view.rs @@ -4,7 +4,8 @@ use nohash_hasher::IntSet; use re_log_types::{EntityPath, EntityPathFilter, EntityPathRule, RuleEffect}; use re_space_view::{determine_visualizable_entities, SpaceViewBlueprint}; -use re_viewer_context::{Item, RecommendedSpaceView, SpaceViewClassIdentifier}; +use re_types::SpaceViewClassIdentifier; +use re_viewer_context::{Item, RecommendedSpaceView}; use crate::context_menu::{ContextMenuAction, ContextMenuContext}; diff --git a/crates/re_viewport/src/context_menu/actions/add_space_view.rs b/crates/re_viewport/src/context_menu/actions/add_space_view.rs index 51b8da5ff5c1..00de7bd5426e 100644 --- a/crates/re_viewport/src/context_menu/actions/add_space_view.rs +++ b/crates/re_viewport/src/context_menu/actions/add_space_view.rs @@ -1,5 +1,6 @@ use re_space_view::SpaceViewBlueprint; -use re_viewer_context::{ContainerId, Item, RecommendedSpaceView, SpaceViewClassIdentifier}; +use re_types::SpaceViewClassIdentifier; +use re_viewer_context::{ContainerId, Item, RecommendedSpaceView}; use crate::context_menu::{ContextMenuAction, ContextMenuContext}; diff --git a/crates/re_viewport/src/system_execution.rs b/crates/re_viewport/src/system_execution.rs index 155be6fec181..5fbaf9b3ff9f 100644 --- a/crates/re_viewport/src/system_execution.rs +++ b/crates/re_viewport/src/system_execution.rs @@ -4,9 +4,10 @@ use ahash::HashMap; use rayon::prelude::*; use re_log_types::TimeInt; +use re_types::SpaceViewClassIdentifier; use re_viewer_context::{ - PerSystemDataResults, SpaceViewClassIdentifier, SpaceViewHighlights, SpaceViewId, - SystemExecutionOutput, ViewQuery, ViewerContext, + PerSystemDataResults, SpaceViewHighlights, SpaceViewId, SystemExecutionOutput, ViewQuery, + ViewerContext, }; use crate::space_view_highlights::highlights_for_space_view; diff --git a/crates/re_viewport/src/viewport.rs b/crates/re_viewport/src/viewport.rs index 7b74062efd99..29cad3cbae65 100644 --- a/crates/re_viewport/src/viewport.rs +++ b/crates/re_viewport/src/viewport.rs @@ -8,11 +8,11 @@ use once_cell::sync::Lazy; use re_entity_db::EntityPropertyMap; use re_renderer::ScreenshotProcessor; +use re_types::SpaceViewClassIdentifier; use re_ui::{Icon, ReUi}; use re_viewer_context::{ - blueprint_id_to_tile_id, ContainerId, Contents, Item, SpaceViewClassIdentifier, - SpaceViewClassRegistry, SpaceViewId, SpaceViewState, SystemExecutionOutput, ViewQuery, - ViewerContext, + blueprint_id_to_tile_id, ContainerId, Contents, Item, SpaceViewClassRegistry, SpaceViewId, + SpaceViewState, SystemExecutionOutput, ViewQuery, ViewerContext, }; use crate::screenshot::handle_pending_space_view_screenshots; diff --git a/crates/re_viewport/src/viewport_blueprint.rs b/crates/re_viewport/src/viewport_blueprint.rs index e608e63a6805..278f32a33fbd 100644 --- a/crates/re_viewport/src/viewport_blueprint.rs +++ b/crates/re_viewport/src/viewport_blueprint.rs @@ -4,6 +4,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use ahash::HashMap; use egui_tiles::{SimplificationOptions, TileId}; use nohash_hasher::IntSet; +use re_types::SpaceViewClassIdentifier; use smallvec::SmallVec; use re_data_store::LatestAtQuery; @@ -15,8 +16,8 @@ use re_types_blueprint::blueprint::components::{ AutoLayout, AutoSpaceViews, IncludedSpaceView, RootContainer, SpaceViewMaximized, }; use re_viewer_context::{ - blueprint_id_to_tile_id, ContainerId, Contents, Item, SpaceViewClassIdentifier, SpaceViewId, - SpaceViewSpawnHeuristics, ViewerContext, + blueprint_id_to_tile_id, ContainerId, Contents, Item, SpaceViewId, SpaceViewSpawnHeuristics, + ViewerContext, }; use crate::{container::ContainerBlueprint, viewport::TreeAction, VIEWPORT_PATH}; diff --git a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs index a02e15e3c4ef..0fe1b099f3eb 100644 --- a/examples/rust/custom_space_view/src/color_coordinates_space_view.rs +++ b/examples/rust/custom_space_view/src/color_coordinates_space_view.rs @@ -3,13 +3,14 @@ use re_viewer::external::{ re_data_ui::{item_ui, DataUi}, re_entity_db::{EntityProperties, InstancePath}, re_log_types::EntityPath, + re_types::SpaceViewClassIdentifier, re_ui, re_viewer_context::{ HoverHighlight, IdentifiedViewSystem as _, Item, RecommendedSpaceView, SelectionHighlight, - SpaceViewClass, SpaceViewClassIdentifier, SpaceViewClassLayoutPriority, - SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, - SpaceViewStateExt as _, SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, - SystemExecutionOutput, UiVerbosity, ViewQuery, ViewerContext, + SpaceViewClass, SpaceViewClassLayoutPriority, SpaceViewClassRegistryError, SpaceViewId, + SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt as _, + SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, SystemExecutionOutput, + UiVerbosity, ViewQuery, ViewerContext, }, }; From b7a72cb611612efb22bf80b773757e4b276d762d Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 30 Apr 2024 12:09:58 +0200 Subject: [PATCH 394/508] Make visual time range on views a view property that can be set from python code (#6164) ### What * Part of [#6083](https://github.com/rerun-io/rerun/issues/6083) And _some_ related refactors that I got engulfed with on this quest: * document fate of remaining `EntityProperties` * simplify `DataResult` formation by dropping overrides from the `OverrideContext` * took the opportunity to call out `EntityProperties` as `legacy_properties` in a lot of places which makes it easier to read these changes * make it explicit when we want to use latest-at query by introducing `QueryRange` type Python API not great yet, will improve and provide examples in an upcoming iteration. Planned direct follow-ups to this PR: * finally remove old History types that we still convert to * should fix the rest of https://github.com/rerun-io/rerun/issues/6135 if it isn't already by this PR * make python interface actually nice * add examples & more docs ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6164?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6164?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6164) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_entity_db/src/entity_properties.rs | 25 +- .../src/latest_at/to_archetype/.gitattributes | 1 + .../src/latest_at/to_archetype/mod.rs | 1 + .../to_archetype/visible_time_range.rs | 58 +++ crates/re_space_view/src/data_query.rs | 23 +- crates/re_space_view/src/lib.rs | 10 +- crates/re_space_view/src/space_view.rs | 165 ++++--- .../re_space_view/src/space_view_contents.rs | 405 ++++++++-------- crates/re_space_view/src/sub_archetypes.rs | 25 +- crates/re_space_view/src/visual_time_range.rs | 61 +-- crates/re_space_view_spatial/src/ui.rs | 2 +- crates/re_space_view_spatial/src/ui_2d.rs | 5 +- crates/re_space_view_spatial/src/ui_3d.rs | 5 +- .../src/visualizers/entity_iterator.rs | 2 +- .../src/line_visualizer_system.rs | 3 +- .../src/point_visualizer_system.rs | 3 +- .../src/space_view_class.rs | 37 +- crates/re_space_view_time_series/src/util.rs | 40 +- .../re_types/definitions/rerun/blueprint.fbs | 1 + .../archetypes/visible_time_range.fbs | 32 ++ .../rerun/blueprint/views/spatial2d.fbs | 4 + .../rerun/blueprint/views/spatial3d.fbs | 3 + .../rerun/blueprint/views/time_series.fbs | 3 + .../src/blueprint/archetypes/.gitattributes | 1 + .../re_types/src/blueprint/archetypes/mod.rs | 2 + .../archetypes/visible_time_range.rs | 207 ++++++++ .../datatypes/visible_time_range_ext.rs | 6 - .../src/blueprint/views/spatial2d_view.rs | 8 +- .../src/blueprint/views/spatial3d_view.rs | 30 +- .../src/blueprint/views/time_series_view.rs | 8 +- crates/re_viewer/src/app_state.rs | 10 +- crates/re_viewer/src/ui/mod.rs | 2 +- crates/re_viewer/src/ui/selection_panel.rs | 49 +- ...isible_history.rs => visual_time_range.rs} | 441 ++++++++++-------- crates/re_viewer_context/src/lib.rs | 2 + crates/re_viewer_context/src/query_range.rs | 10 + .../src/space_view/space_view_class.rs | 11 +- .../src/space_view/view_query.rs | 30 +- .../reference/types/views/spatial2d_view.md | 15 + .../reference/types/views/spatial3d_view.md | 15 + .../reference/types/views/time_series_view.md | 15 + rerun_cpp/src/rerun/blueprint/archetypes.hpp | 1 + .../rerun/blueprint/archetypes/.gitattributes | 2 + .../archetypes/visible_time_range.cpp | 38 ++ .../archetypes/visible_time_range.hpp | 81 ++++ .../rerun_sdk/rerun/blueprint/__init__.py | 2 + .../rerun/blueprint/archetypes/.gitattributes | 1 + .../rerun/blueprint/archetypes/__init__.py | 2 + .../archetypes/visible_time_range.py | 93 ++++ .../rerun/blueprint/views/spatial2d_view.py | 8 + .../rerun/blueprint/views/spatial3d_view.py | 8 + .../rerun/blueprint/views/time_series_view.py | 8 + 52 files changed, 1351 insertions(+), 669 deletions(-) create mode 100644 crates/re_query/src/latest_at/to_archetype/visible_time_range.rs create mode 100644 crates/re_types/definitions/rerun/blueprint/archetypes/visible_time_range.fbs create mode 100644 crates/re_types/src/blueprint/archetypes/visible_time_range.rs rename crates/re_viewer/src/ui/{visible_history.rs => visual_time_range.rs} (66%) create mode 100644 crates/re_viewer_context/src/query_range.rs create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/visible_time_range.cpp create mode 100644 rerun_cpp/src/rerun/blueprint/archetypes/visible_time_range.hpp create mode 100644 rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_range.py diff --git a/crates/re_entity_db/src/entity_properties.rs b/crates/re_entity_db/src/entity_properties.rs index fb50dc0d39bc..58e2646ab495 100644 --- a/crates/re_entity_db/src/entity_properties.rs +++ b/crates/re_entity_db/src/entity_properties.rs @@ -94,48 +94,53 @@ impl FromIterator<(EntityPath, EntityProperties)> for EntityPropertyMap { #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[cfg_attr(feature = "serde", serde(default))] pub struct EntityProperties { - pub interactive: bool, + pub interactive: bool, // TODO(andreas): similar to `visible`, needs to become a regular (slightly special - doesn't show up in archetypes) component. /// What kind of color mapping should be applied (none, map, texture, transfer..)? - pub color_mapper: EditableAutoValue, + pub color_mapper: EditableAutoValue, // TODO(andreas): should become a component and be part of the DepthImage and regular Images (with limitation to mono channel image). /// Distance of the projection plane (frustum far plane). /// /// Only applies to pinhole cameras when in a spatial view, using 3D navigation. - pub pinhole_image_plane_distance: EditableAutoValue, + pub pinhole_image_plane_distance: EditableAutoValue, // TODO(#6084): should be a regular component on the Pinhole archetype. /// Should the depth texture be backprojected into a point cloud? /// /// Only applies to tensors with meaning=depth that are affected by a pinhole transform. /// /// The default for 3D views is `true`, but for 2D views it is `false`. - pub backproject_depth: EditableAutoValue, + pub backproject_depth: EditableAutoValue, // TODO(andreas): should be a component on the DepthImage archetype. /// How many depth units per world-space unit. e.g. 1000 for millimeters. /// /// This corresponds to `re_components::Tensor::meter`. - pub depth_from_world_scale: EditableAutoValue, + pub depth_from_world_scale: EditableAutoValue, // TODO(andreas): Just remove once we can edit meter & be able to set semi-clever defaults per visualizer. /// Used to scale the radii of the points in the resulting point cloud. - pub backproject_radius_scale: EditableAutoValue, + pub backproject_radius_scale: EditableAutoValue, // TODO(andreas): should be a component on the DepthImage archetype. /// Whether to show the 3D transform visualization at all. + // TODO(andreas): should go away once we can disable visualizer. Revisit how to collectively enable/disable these on an entire view. + // To consider: Make a TransformAxis archetype whose indicator is what enables the visualizer + // -> size etc. are now part of this archetype, not the `Transform` archetype + // -> `TransformAxis` itself doesn't have a required component, but the visualizer has. Just like in SeriesLines & Scalar. + // TODO(andreas)/TODO(jleibs): There's a pattern here that we should capture & formalize in the API / codegen / definitions. pub transform_3d_visible: EditableAutoValue, /// The length of the arrows in the entity's own coordinate system (space). - pub transform_3d_size: EditableAutoValue, + pub transform_3d_size: EditableAutoValue, // TODO(andreas): should be a component on the Transform3D/TransformAxis archetype. /// Should the legend be shown (for plot space views). - pub show_legend: EditableAutoValue, + pub show_legend: EditableAutoValue, // TODO(andreas): BarChart is still using it, we already have the legend archteype! /// The location of the legend (for plot space views). /// /// This is an Option instead of an EditableAutoValue to let each space view class decide on /// what's the best default. - pub legend_location: Option, + pub legend_location: Option, // TODO(andreas): BarChart is still using it, we already have the legend archteype! /// What kind of data aggregation to perform (for plot space views). - pub time_series_aggregator: EditableAutoValue, + pub time_series_aggregator: EditableAutoValue, // TODO(andreas): Should be a component probably on SeriesLine, but today it would become a view property. } #[cfg(feature = "serde")] diff --git a/crates/re_query/src/latest_at/to_archetype/.gitattributes b/crates/re_query/src/latest_at/to_archetype/.gitattributes index e128a891fe94..dbd97e14fb15 100644 --- a/crates/re_query/src/latest_at/to_archetype/.gitattributes +++ b/crates/re_query/src/latest_at/to_archetype/.gitattributes @@ -36,4 +36,5 @@ text_log.rs linguist-generated=true transform3d.rs linguist-generated=true view_coordinates.rs linguist-generated=true viewport_blueprint.rs linguist-generated=true +visible_time_range.rs linguist-generated=true visual_bounds.rs linguist-generated=true diff --git a/crates/re_query/src/latest_at/to_archetype/mod.rs b/crates/re_query/src/latest_at/to_archetype/mod.rs index 4ce8223caddb..bedfffd12055 100644 --- a/crates/re_query/src/latest_at/to_archetype/mod.rs +++ b/crates/re_query/src/latest_at/to_archetype/mod.rs @@ -34,4 +34,5 @@ mod text_log; mod transform3d; mod view_coordinates; mod viewport_blueprint; +mod visible_time_range; mod visual_bounds; diff --git a/crates/re_query/src/latest_at/to_archetype/visible_time_range.rs b/crates/re_query/src/latest_at/to_archetype/visible_time_range.rs new file mode 100644 index 000000000000..b32ecacc8fee --- /dev/null +++ b/crates/re_query/src/latest_at/to_archetype/visible_time_range.rs @@ -0,0 +1,58 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/to_archetype.rs + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] + +use crate::{LatestAtResults, PromiseResolver, PromiseResult}; +use re_types_core::{Archetype, Loggable as _}; +use std::sync::Arc; + +impl crate::ToArchetype for LatestAtResults { + #[inline] + fn to_archetype( + &self, + resolver: &PromiseResolver, + ) -> PromiseResult> { + re_tracing::profile_function!(::name()); + + // --- Required --- + + // --- Recommended/Optional --- + + use re_types::blueprint::components::VisibleTimeRangeSequence; + let sequence = if let Some(sequence) = self.get(::name()) { + match sequence.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + use re_types::blueprint::components::VisibleTimeRangeTime; + let time = if let Some(time) = self.get(::name()) { + match time.to_dense::(resolver) { + PromiseResult::Pending => return PromiseResult::Pending, + PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), + PromiseResult::Ready(query_res) => match query_res { + Ok(data) => data.first().cloned(), + Err(query_err) => return PromiseResult::Ready(Err(query_err)), + }, + } + } else { + None + }; + + // --- + + let arch = re_types::blueprint::archetypes::VisibleTimeRange { sequence, time }; + + PromiseResult::Ready(Ok(arch)) + } +} diff --git a/crates/re_space_view/src/data_query.rs b/crates/re_space_view/src/data_query.rs index 7cf3fcb141fd..30372e7917ee 100644 --- a/crates/re_space_view/src/data_query.rs +++ b/crates/re_space_view/src/data_query.rs @@ -1,18 +1,15 @@ -use nohash_hasher::IntMap; - -use re_entity_db::{external::re_data_store::LatestAtQuery, EntityProperties, EntityPropertyMap}; -use re_types::ComponentName; +use re_entity_db::{external::re_data_store::LatestAtQuery, EntityDb, EntityProperties}; +use re_log_types::Timeline; use re_viewer_context::{ - DataQueryResult, OverridePath, PerVisualizer, StoreContext, VisualizableEntities, + DataQueryResult, PerVisualizer, QueryRange, SpaceViewClassRegistry, StoreContext, + VisualizableEntities, }; pub struct EntityOverrideContext { - pub root: EntityProperties, - pub individual: EntityPropertyMap, - pub recursive: EntityPropertyMap, + pub legacy_space_view_properties: EntityProperties, - /// Base component overrides that are inherited by all entities. - pub root_component_overrides: IntMap, + /// Query range that data results should fall back to if they don't specify their own. + pub default_query_range: QueryRange, } /// Trait for resolving properties needed by most implementations of [`DataQuery`] @@ -22,8 +19,10 @@ pub struct EntityOverrideContext { pub trait PropertyResolver { fn update_overrides( &self, - ctx: &StoreContext<'_>, - query: &LatestAtQuery, + blueprint: &EntityDb, + blueprint_query: &LatestAtQuery, + active_timeline: &Timeline, + space_view_class_registry: &SpaceViewClassRegistry, query_result: &mut DataQueryResult, ); } diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 52b0dcc97b1d..2de1e10273ea 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -18,13 +18,13 @@ pub use screenshot::ScreenshotMode; pub use space_view::SpaceViewBlueprint; pub use space_view_contents::SpaceViewContents; pub use sub_archetypes::{ - edit_blueprint_component, entity_path_for_space_view_sub_archetype, get_blueprint_component, - query_space_view_sub_archetype, query_space_view_sub_archetype_or_default, - space_view_sub_archetype, + edit_blueprint_component, entity_path_for_view_property, get_blueprint_component, + query_view_property, query_view_property_or_default, view_property, }; pub use visual_time_range::{ - query_visual_history, time_range_boundary_to_visible_history_boundary, - visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, + query_visual_history, time_range_from_visible_time_range, + visible_history_boundary_from_time_range_boundary, + visible_history_boundary_to_time_range_boundary, }; pub use visualizable::determine_visualizable_entities; diff --git a/crates/re_space_view/src/space_view.rs b/crates/re_space_view/src/space_view.rs index c0f965c23bc3..3ced06b1fa43 100644 --- a/crates/re_space_view/src/space_view.rs +++ b/crates/re_space_view/src/space_view.rs @@ -1,22 +1,23 @@ use itertools::{FoldWhile, Itertools}; -use nohash_hasher::IntMap; -use re_entity_db::external::re_query::PromiseResult; +use re_entity_db::{external::re_query::PromiseResult, EntityProperties}; use re_types::SpaceViewClassIdentifier; use crate::SpaceViewContents; use re_data_store::LatestAtQuery; use re_entity_db::{EntityDb, EntityPath, EntityPropertiesComponent, EntityPropertyMap}; -use re_log_types::{DataRow, EntityPathSubs, RowId}; -use re_types::blueprint::archetypes as blueprint_archetypes; +use re_log_types::{DataRow, EntityPathSubs, RowId, Timeline}; use re_types::{ - blueprint::components::{SpaceViewOrigin, Visible}, + blueprint::{ + archetypes::{self as blueprint_archetypes}, + components::{SpaceViewOrigin, Visible}, + }, components::Name, }; use re_types_core::archetypes::Clear; use re_types_core::Archetype as _; use re_viewer_context::{ - ContentsName, DataResult, OverridePath, PerSystemEntities, PropertyOverrides, - RecommendedSpaceView, SpaceViewClass, SpaceViewId, SpaceViewState, StoreContext, SystemCommand, + ContentsName, DataResult, PerSystemEntities, QueryRange, RecommendedSpaceView, SpaceViewClass, + SpaceViewClassRegistry, SpaceViewId, SpaceViewState, StoreContext, SystemCommand, SystemCommandSender as _, SystemExecutionOutput, ViewQuery, ViewerContext, }; @@ -368,12 +369,7 @@ impl SpaceViewBlueprint { let class = self.class(ctx.space_view_class_registry); - let space_view_data_result = - self.space_view_data_result(ctx.store_context, ctx.blueprint_query); - let props = space_view_data_result - .individual_properties() - .cloned() - .unwrap_or_default(); + let props = self.legacy_properties(ctx.store_context.blueprint, ctx.blueprint_query); ui.scope(|ui| { class @@ -393,68 +389,68 @@ impl SpaceViewBlueprint { self.id.as_entity_path() } - /// A special data result for the space view that sits "above" the [`SpaceViewContents`]. - /// - /// This allows us to use interfaces that take a [`DataResult`] to modify things on the - /// space view that can then be inherited into the contents. For example, controlling - /// visible history. - pub fn space_view_data_result( + /// Legacy `EntityProperties` used by a hand ful of view properties that aren't blueprint view properties yet. + pub fn legacy_properties( &self, - ctx: &StoreContext<'_>, - query: &LatestAtQuery, - ) -> DataResult { + blueprint: &EntityDb, + blueprint_query: &LatestAtQuery, + ) -> EntityProperties { let base_override_root = self.entity_path(); let individual_override_path = base_override_root.join(&DataResult::INDIVIDUAL_OVERRIDES_PREFIX.into()); - let recursive_override_path = - base_override_root.join(&DataResult::RECURSIVE_OVERRIDES_PREFIX.into()); - // TODO(#5607): what should happen if the promise is still pending? - let individual_properties = ctx - .blueprint + blueprint .latest_at_component_quiet::( &individual_override_path, - query, + blueprint_query, ) - .map(|result| result.value.0); - let accumulated_properties = individual_properties.clone().unwrap_or_default(); - - // Gather recursive component overrides. - // Ignore individual overrides on SpaceView root. - let mut recursive_component_overrides = IntMap::default(); - if let Some(recursive_override_subtree) = - ctx.blueprint.tree().subtree(&recursive_override_path) - { - for component in recursive_override_subtree.entity.components.keys() { - if let Some(component_data) = ctx - .blueprint - .store() - .latest_at(query, &recursive_override_path, *component, &[*component]) - .and_then(|(_, _, cells)| cells[0].clone()) - { - if !component_data.is_empty() { - recursive_component_overrides.insert( - *component, - OverridePath::blueprint_path(recursive_override_path.clone()), - ); - } - } - } - } + .map(|result| result.value.0) + .unwrap_or_default() + } + + pub fn save_legacy_properties(&self, ctx: &ViewerContext<'_>, props: EntityProperties) { + let base_override_root = self.entity_path(); + let individual_override_path = + base_override_root.join(&DataResult::INDIVIDUAL_OVERRIDES_PREFIX.into()); - DataResult { - entity_path: base_override_root, - visualizers: Default::default(), - tree_prefix_only: false, - property_overrides: Some(PropertyOverrides { - accumulated_properties, - individual_properties, - recursive_properties: Default::default(), - resolved_component_overrides: recursive_component_overrides, - recursive_override_path, - individual_override_path, - }), + ctx.save_blueprint_component(&individual_override_path, &EntityPropertiesComponent(props)); + } + + pub fn query_range( + &self, + blueprint: &EntityDb, + blueprint_query: &LatestAtQuery, + active_timeline: &Timeline, + space_view_class_registry: &SpaceViewClassRegistry, + ) -> QueryRange { + // Visual time range works with regular overrides for the most part but it's a bit special: + // * we need it for all entities unconditionally + // * default does not vary per visualizer + // * can't be specified in the data store + // Here, we query the visual time range that serves as the default for all entities in this space. + let (visible_time_range_archetype, _) = crate::query_view_property::< + blueprint_archetypes::VisibleTimeRange, + >(self.id, blueprint, blueprint_query); // Don't need to query the entire archetype but doesn't cost much and is convenient. + + let visible_time_range_archetype = visible_time_range_archetype.ok().flatten(); + + match active_timeline.typ() { + re_log_types::TimeType::Time => { + visible_time_range_archetype.map(|arch| arch.time.map(|s| s.0)) + } + re_log_types::TimeType::Sequence => { + visible_time_range_archetype.map(|arch| arch.sequence.map(|s| s.0)) + } } + .flatten() + .map_or_else( + || { + let space_view_class = + space_view_class_registry.get_class_or_log_error(&self.class_identifier); + space_view_class.default_query_range() + }, + QueryRange::TimeRange, + ) } } @@ -491,6 +487,7 @@ mod tests { #[test] fn test_entity_properties() { let space_view_class_registry = SpaceViewClassRegistry::default(); + let timeline = Timeline::new("time", re_log_types::TimeType::Time); let mut recording = EntityDb::new(StoreId::random(re_log_types::StoreKind::Recording)); let mut blueprint = EntityDb::new(StoreId::random(re_log_types::StoreKind::Blueprint)); @@ -513,8 +510,6 @@ mod tests { let space_view = SpaceViewBlueprint::new("3D".into(), recommended); - let auto_properties = Default::default(); - let mut visualizable_entities = PerVisualizer::::default(); visualizable_entities .0 @@ -543,7 +538,6 @@ mod tests { let resolver = contents.build_resolver( &space_view_class_registry, &space_view, - &auto_properties, &visualizable_entities, &indicated_entities_per_visualizer, ); @@ -560,7 +554,13 @@ mod tests { }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); - resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); + resolver.update_overrides( + &blueprint, + &blueprint_query, + &timeline, + &space_view_class_registry, + &mut query_result, + ); let parent = query_result .tree @@ -605,7 +605,13 @@ mod tests { }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); - resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); + resolver.update_overrides( + &blueprint, + &blueprint_query, + &timeline, + &space_view_class_registry, + &mut query_result, + ); let parent_group = query_result .tree @@ -656,7 +662,13 @@ mod tests { }; let mut query_result = contents.execute_query(&ctx, &visualizable_entities); - resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); + resolver.update_overrides( + &blueprint, + &blueprint_query, + &timeline, + &space_view_class_registry, + &mut query_result, + ); let parent = query_result .tree @@ -680,6 +692,7 @@ mod tests { #[test] fn test_component_overrides() { let space_view_class_registry = SpaceViewClassRegistry::default(); + let timeline = Timeline::new("time", re_log_types::TimeType::Time); let mut recording = EntityDb::new(StoreId::random(re_log_types::StoreKind::Recording)); let mut visualizable_entities_per_visualizer = PerVisualizer::::default(); @@ -721,12 +734,10 @@ mod tests { .join(&DataResult::RECURSIVE_OVERRIDES_PREFIX.into()); // Things needed to resolve properties: - let auto_properties = EntityPropertyMap::default(); let indicated_entities_per_visualizer = PerVisualizer::::default(); // Don't care about indicated entities. let resolver = space_view.contents.build_resolver( &space_view_class_registry, &space_view, - &auto_properties, &visualizable_entities_per_visualizer, &indicated_entities_per_visualizer, ); @@ -932,7 +943,13 @@ mod tests { .contents .execute_query(&ctx, &visualizable_entities_per_visualizer); let blueprint_query = LatestAtQuery::latest(blueprint_timeline()); - resolver.update_overrides(&ctx, &blueprint_query, &mut query_result); + resolver.update_overrides( + &blueprint, + &blueprint_query, + &timeline, + &space_view_class_registry, + &mut query_result, + ); // Extract component overrides for testing. let mut visited: HashMap> = diff --git a/crates/re_space_view/src/space_view_contents.rs b/crates/re_space_view/src/space_view_contents.rs index fb55085ad1e2..7abbad351818 100644 --- a/crates/re_space_view/src/space_view_contents.rs +++ b/crates/re_space_view/src/space_view_contents.rs @@ -4,25 +4,27 @@ use smallvec::SmallVec; use re_entity_db::{ external::{re_data_store::LatestAtQuery, re_query::PromiseResult}, - EntityDb, EntityProperties, EntityPropertiesComponent, EntityPropertyMap, EntityTree, + EntityDb, EntityProperties, EntityPropertiesComponent, EntityTree, }; use re_log_types::{ - path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule, EntityPathSubs, + path::RuleEffect, EntityPath, EntityPathFilter, EntityPathRule, EntityPathSubs, Timeline, }; use re_types::{ - blueprint::{archetypes as blueprint_archetypes, components::QueryExpression}, + blueprint::{ + archetypes as blueprint_archetypes, components as blueprint_components, + components::QueryExpression, + }, Archetype as _, SpaceViewClassIdentifier, }; use re_types_core::{components::VisualizerOverrides, ComponentName}; use re_viewer_context::{ DataQueryResult, DataResult, DataResultHandle, DataResultNode, DataResultTree, - IndicatedEntities, OverridePath, PerVisualizer, PropertyOverrides, SpaceViewId, StoreContext, - ViewerContext, VisualizableEntities, + IndicatedEntities, OverridePath, PerVisualizer, PropertyOverrides, QueryRange, + SpaceViewClassRegistry, SpaceViewId, ViewerContext, VisualizableEntities, }; use crate::{ - query_space_view_sub_archetype, DataQuery, EntityOverrideContext, PropertyResolver, - SpaceViewBlueprint, + query_view_property, DataQuery, EntityOverrideContext, PropertyResolver, SpaceViewBlueprint, }; /// An implementation of [`DataQuery`] that is built from a [`blueprint_archetypes::SpaceViewContents`]. @@ -101,9 +103,8 @@ impl SpaceViewContents { space_view_class_identifier: SpaceViewClassIdentifier, space_env: &EntityPathSubs, ) -> Self { - let (contents, blueprint_entity_path) = query_space_view_sub_archetype::< - blueprint_archetypes::SpaceViewContents, - >(id, blueprint_db, query); + let (contents, blueprint_entity_path) = + query_view_property::(id, blueprint_db, query); let blueprint_archetypes::SpaceViewContents { query } = match contents { PromiseResult::Pending => { @@ -178,7 +179,6 @@ impl SpaceViewContents { &self, space_view_class_registry: &'a re_viewer_context::SpaceViewClassRegistry, space_view: &'a SpaceViewBlueprint, - auto_properties: &'a EntityPropertyMap, visualizable_entities_per_visualizer: &'a PerVisualizer, indicated_entities_per_visualizer: &'a PerVisualizer, ) -> DataQueryPropertyResolver<'a> { @@ -190,8 +190,6 @@ impl SpaceViewContents { DataQueryPropertyResolver { space_view_class_registry, space_view, - auto_properties, - default_stack: vec![space_view.entity_path(), self.blueprint_entity_path.clone()], individual_override_root, recursive_override_root, visualizable_entities_per_visualizer, @@ -374,8 +372,6 @@ impl<'a> QueryExpressionEvaluator<'a> { pub struct DataQueryPropertyResolver<'a> { space_view_class_registry: &'a re_viewer_context::SpaceViewClassRegistry, space_view: &'a SpaceViewBlueprint, - auto_properties: &'a EntityPropertyMap, - default_stack: Vec, individual_override_root: EntityPath, recursive_override_root: EntityPath, visualizable_entities_per_visualizer: &'a PerVisualizer, @@ -392,79 +388,29 @@ impl DataQueryPropertyResolver<'_> { /// - The recursive overrides are found by walking an override subtree under the `data_query//recursive_overrides` fn build_override_context( &self, - ctx: &StoreContext<'_>, - query: &LatestAtQuery, + blueprint: &EntityDb, + blueprint_query: &LatestAtQuery, + active_timeline: &Timeline, + space_view_class_registry: &SpaceViewClassRegistry, ) -> EntityOverrideContext { re_tracing::profile_function!(); - // TODO(#4194): We always start the override context with the root_data_result from - // the space-view. This isn't totally generic once we add container overrides, but it's a start. - let (mut root_entity_properties, root_component_overrides) = self + let legacy_space_view_properties = self .space_view - .space_view_data_result(ctx, query) - .property_overrides - .map(|p| (p.accumulated_properties, p.resolved_component_overrides)) - .unwrap_or_default(); - - for prefix in &self.default_stack { - // TODO(#5607): what should happen if the promise is still pending? - if let Some(overrides) = ctx - .blueprint - .latest_at_component::(prefix, query) - { - root_entity_properties = root_entity_properties.with_child(&overrides.value.0); - } - } - - // TODO(jleibs): Should pass through an initial `ComponentOverrides` here - // if we were to support incrementally inheriting overrides from parent - // contexts such as the `SpaceView` or `Container`. - EntityOverrideContext { - root: root_entity_properties, - individual: self.resolve_entity_overrides_for_path( - ctx, - query, - &self.individual_override_root, - ), - recursive: self.resolve_entity_overrides_for_path( - ctx, - query, - &self.recursive_override_root, - ), - root_component_overrides, - } - } - - /// Find all of the overrides for a given path. - /// - /// These overrides are full entity-paths prefixed by the override root. - /// - /// For example the individual override for `world/points` in the context of the query-id `1234` - /// would be found at: `data_query/1234/individual_overrides/world/points`. - fn resolve_entity_overrides_for_path( - &self, - ctx: &StoreContext<'_>, - query: &LatestAtQuery, - override_root: &EntityPath, - ) -> EntityPropertyMap { - re_tracing::profile_function!(); - let blueprint = ctx.blueprint; + .legacy_properties(blueprint, blueprint_query); - let mut prop_map = self.auto_properties.clone(); + let default_query_range = self.space_view.query_range( + blueprint, + blueprint_query, + active_timeline, + space_view_class_registry, + ); - if let Some(tree) = blueprint.tree().subtree(override_root) { - tree.visit_children_recursively(&mut |path: &EntityPath, _| { - // TODO(#5607): what should happen if the promise is still pending? - if let Some(props) = - blueprint.latest_at_component_quiet::(path, query) - { - let overridden_path = - EntityPath::from(&path.as_slice()[override_root.len()..path.len()]); - prop_map.update(overridden_path, props.value.0); - } - }); + // TODO(#4194): Once supported, default entity properties should be passe through here. + EntityOverrideContext { + legacy_space_view_properties, + default_query_range, } - prop_map } /// Recursively walk the [`DataResultTree`] and update the [`PropertyOverrides`] for each node. @@ -474,141 +420,181 @@ impl DataQueryPropertyResolver<'_> { #[allow(clippy::too_many_arguments)] // This will be a lot simpler and smaller once `EntityProperties` are gone! fn update_overrides_recursive( &self, - ctx: &StoreContext<'_>, - query: &LatestAtQuery, + blueprint: &EntityDb, + blueprint_query: &LatestAtQuery, + active_timeline: &Timeline, query_result: &mut DataQueryResult, override_context: &EntityOverrideContext, - accumulated: &EntityProperties, + recursive_accumulated_legacy_properties: &EntityProperties, recursive_property_overrides: &IntMap, handle: DataResultHandle, ) { - if let Some((child_handles, accumulated, recursive_property_overrides)) = - query_result.tree.lookup_node_mut(handle).map(|node| { - let recursive_properties = override_context - .recursive - .get_opt(&node.data_result.entity_path); - let accumulated_recursive_properties = - if let Some(overridden) = recursive_properties { - accumulated.with_child(overridden) - } else { - accumulated.clone() - }; - - let individual_properties = override_context - .individual - .get_opt(&node.data_result.entity_path); - let accumulated_properties = - if let Some(individual_override) = individual_properties { - accumulated_recursive_properties.with_child(individual_override) - } else { - accumulated_recursive_properties.clone() - }; - - let individual_override_path = self - .individual_override_root - .join(&node.data_result.entity_path); - let recursive_override_path = self - .recursive_override_root - .join(&node.data_result.entity_path); - - if !node.data_result.visualizers.is_empty() { - re_tracing::profile_scope!("Update visualizers from overrides"); - - // If the user has overridden the visualizers, update which visualizers are used. - // TODO(#5607): what should happen if the promise is still pending? - if let Some(viz_override) = ctx - .blueprint - .latest_at_component::( - &individual_override_path, - query, + if let Some(( + child_handles, + recursive_accumulated_legacy_properties, + recursive_property_overrides, + )) = query_result.tree.lookup_node_mut(handle).map(|node| { + let individual_override_path = self + .individual_override_root + .join(&node.data_result.entity_path); + let recursive_override_path = self + .recursive_override_root + .join(&node.data_result.entity_path); + + // Special handling for legacy overrides. + let recursive_legacy_properties = blueprint + .latest_at_component_quiet::( + &recursive_override_path, + blueprint_query, + ) + .map(|result| result.value.0); + let individual_legacy_properties = blueprint + .latest_at_component_quiet::( + &individual_override_path, + blueprint_query, + ) + .map(|result| result.value.0); + + let recursive_accumulated_legacy_properties = + if let Some(recursive_legacy_properties) = recursive_legacy_properties.as_ref() { + recursive_accumulated_legacy_properties.with_child(recursive_legacy_properties) + } else { + recursive_accumulated_legacy_properties.clone() + }; + let accumulated_legacy_properties = + if let Some(individual) = individual_legacy_properties.as_ref() { + recursive_accumulated_legacy_properties.with_child(individual) + } else { + recursive_accumulated_legacy_properties.clone() + }; + + // Update visualizers from overrides. + if !node.data_result.visualizers.is_empty() { + re_tracing::profile_scope!("Update visualizers from overrides"); + + // If the user has overridden the visualizers, update which visualizers are used. + // TODO(#5607): what should happen if the promise is still pending? + if let Some(viz_override) = blueprint + .latest_at_component::( + &individual_override_path, + blueprint_query, + ) + .map(|c| c.value) + { + node.data_result.visualizers = + viz_override.0.iter().map(|v| v.as_str().into()).collect(); + } else { + // Otherwise ask the `SpaceViewClass` to choose. + node.data_result.visualizers = self + .space_view + .class(self.space_view_class_registry) + .choose_default_visualizers( + &node.data_result.entity_path, + self.visualizable_entities_per_visualizer, + self.indicated_entities_per_visualizer, + ); + } + } + + // First, gather recursive overrides. Previous recursive overrides are the base for the next. + // We assume that most of the time there's no new recursive overrides, so clone the map lazily. + let mut recursive_property_overrides = + std::borrow::Cow::Borrowed(recursive_property_overrides); + if let Some(recursive_override_subtree) = + blueprint.tree().subtree(&recursive_override_path) + { + for component in recursive_override_subtree.entity.components.keys() { + if let Some(component_data) = blueprint + .store() + .latest_at( + blueprint_query, + &recursive_override_path, + *component, + &[*component], ) - .map(|c| c.value) + .and_then(|(_, _, cells)| cells[0].clone()) { - node.data_result.visualizers = - viz_override.0.iter().map(|v| v.as_str().into()).collect(); - } else { - // Otherwise ask the `SpaceViewClass` to choose. - node.data_result.visualizers = self - .space_view - .class(self.space_view_class_registry) - .choose_default_visualizers( - &node.data_result.entity_path, - self.visualizable_entities_per_visualizer, - self.indicated_entities_per_visualizer, + if !component_data.is_empty() { + recursive_property_overrides.to_mut().insert( + *component, + OverridePath::blueprint_path(recursive_override_path.clone()), ); - } - } - - // First, gather recursive overrides. Previous recursive overrides are the base for the next. - // We assume that most of the time there's no new recursive overrides, so clone the map lazily. - let mut recursive_property_overrides = - std::borrow::Cow::Borrowed(recursive_property_overrides); - if let Some(recursive_override_subtree) = - ctx.blueprint.tree().subtree(&recursive_override_path) - { - for component in recursive_override_subtree.entity.components.keys() { - if let Some(component_data) = ctx - .blueprint - .store() - .latest_at(query, &recursive_override_path, *component, &[*component]) - .and_then(|(_, _, cells)| cells[0].clone()) - { - if !component_data.is_empty() { - recursive_property_overrides.to_mut().insert( - *component, - OverridePath::blueprint_path(recursive_override_path.clone()), - ); - } } } } + } - // Then, gather individual overrides - these may override the recursive ones again, - // but recursive overrides are still inherited to children. - let mut resolved_component_overrides = (*recursive_property_overrides).clone(); - if let Some(individual_override_subtree) = - ctx.blueprint.tree().subtree(&individual_override_path) - { - for component in individual_override_subtree.entity.components.keys() { - if let Some(component_data) = ctx - .blueprint - .store() - .latest_at(query, &individual_override_path, *component, &[*component]) - .and_then(|(_, _, cells)| cells[0].clone()) - { - if !component_data.is_empty() { - resolved_component_overrides.insert( - *component, - OverridePath::blueprint_path(individual_override_path.clone()), - ); - } + // Then, gather individual overrides - these may override the recursive ones again, + // but recursive overrides are still inherited to children. + let mut resolved_component_overrides = (*recursive_property_overrides).clone(); + if let Some(individual_override_subtree) = + blueprint.tree().subtree(&individual_override_path) + { + for component in individual_override_subtree.entity.components.keys() { + if let Some(component_data) = blueprint + .store() + .latest_at( + blueprint_query, + &individual_override_path, + *component, + &[*component], + ) + .and_then(|(_, _, cells)| cells[0].clone()) + { + if !component_data.is_empty() { + resolved_component_overrides.insert( + *component, + OverridePath::blueprint_path(individual_override_path.clone()), + ); } } } + } - node.data_result.property_overrides = Some(PropertyOverrides { - accumulated_properties, - individual_properties: individual_properties.cloned(), - recursive_properties: recursive_properties.cloned(), - resolved_component_overrides, - recursive_override_path, - individual_override_path, - }); - - ( - node.children.clone(), - accumulated_recursive_properties, - recursive_property_overrides, - ) - }) - { + // Figure out relevant visual time range. + let visual_time_range_overrides = match active_timeline.typ() { + re_log_types::TimeType::Time => blueprint + .latest_at_component_quiet::( + &recursive_override_path, + blueprint_query, + ) + .map(|result| result.value.0), + re_log_types::TimeType::Sequence => blueprint + .latest_at_component_quiet::( + &recursive_override_path, + blueprint_query, + ) + .map(|result| result.value.0), + }; + let query_range = visual_time_range_overrides.map_or_else( + || override_context.default_query_range.clone(), + QueryRange::TimeRange, + ); + + node.data_result.property_overrides = Some(PropertyOverrides { + accumulated_properties: accumulated_legacy_properties, + individual_properties: individual_legacy_properties, + recursive_properties: recursive_legacy_properties, + resolved_component_overrides, + recursive_override_path, + individual_override_path, + query_range, + }); + + ( + node.children.clone(), + recursive_accumulated_legacy_properties, + recursive_property_overrides, + ) + }) { for child in child_handles { self.update_overrides_recursive( - ctx, - query, + blueprint, + blueprint_query, + active_timeline, query_result, override_context, - &accumulated, + &recursive_accumulated_legacy_properties, &recursive_property_overrides, child, ); @@ -621,21 +607,32 @@ impl<'a> PropertyResolver for DataQueryPropertyResolver<'a> { /// Recursively walk the [`DataResultTree`] and update the [`PropertyOverrides`] for each node. fn update_overrides( &self, - ctx: &StoreContext<'_>, - query: &LatestAtQuery, + blueprint: &EntityDb, + blueprint_query: &LatestAtQuery, + active_timeline: &Timeline, + space_view_class_registry: &SpaceViewClassRegistry, query_result: &mut DataQueryResult, ) { re_tracing::profile_function!(); - let entity_overrides = self.build_override_context(ctx, query); + let override_context = self.build_override_context( + blueprint, + blueprint_query, + active_timeline, + space_view_class_registry, + ); if let Some(root) = query_result.tree.root_handle() { + let accumulated_legacy_properties = EntityProperties::default(); + let recursive_property_overrides = Default::default(); + self.update_overrides_recursive( - ctx, - query, + blueprint, + blueprint_query, + active_timeline, query_result, - &entity_overrides, - &entity_overrides.root, - &entity_overrides.root_component_overrides, + &override_context, + &accumulated_legacy_properties, + &recursive_property_overrides, root, ); } diff --git a/crates/re_space_view/src/sub_archetypes.rs b/crates/re_space_view/src/sub_archetypes.rs index a19caa7ea33a..9a137a3688f1 100644 --- a/crates/re_space_view/src/sub_archetypes.rs +++ b/crates/re_space_view/src/sub_archetypes.rs @@ -7,7 +7,7 @@ use re_log_types::EntityPath; use re_types::Archetype; use re_viewer_context::{external::re_entity_db::EntityTree, SpaceViewId, ViewerContext}; -pub fn entity_path_for_space_view_sub_archetype( +pub fn entity_path_for_view_property( space_view_id: SpaceViewId, _blueprint_entity_tree: &EntityTree, ) -> EntityPath { @@ -23,7 +23,7 @@ pub fn entity_path_for_space_view_sub_archetype( } /// Return the archetype value for the given space view, or `None` if it doesn't exist. -pub fn space_view_sub_archetype( +pub fn view_property( ctx: &re_viewer_context::ViewerContext<'_>, space_view_id: re_viewer_context::SpaceViewId, ) -> Option
@@ -32,7 +32,7 @@ where { let blueprint_db = ctx.store_context.blueprint; let blueprint_query = ctx.blueprint_query; - let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); + let path = entity_path_for_view_property::(space_view_id, blueprint_db.tree()); blueprint_db .latest_at_archetype(&path, blueprint_query) .ok() @@ -41,7 +41,7 @@ where } /// Returns `Ok(None)` if any of the required components are missing. -pub fn query_space_view_sub_archetype( +pub fn query_view_property( space_view_id: SpaceViewId, blueprint_db: &EntityDb, query: &LatestAtQuery, @@ -49,7 +49,7 @@ pub fn query_space_view_sub_archetype( where LatestAtResults: ToArchetype, { - let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); + let path = entity_path_for_view_property::(space_view_id, blueprint_db.tree()); ( blueprint_db .latest_at_archetype(&path, query) @@ -58,7 +58,7 @@ where ) } -pub fn query_space_view_sub_archetype_or_default( +pub fn query_view_property_or_default( space_view_id: SpaceViewId, blueprint_db: &EntityDb, query: &LatestAtQuery, @@ -66,7 +66,7 @@ pub fn query_space_view_sub_archetype_or_default( where LatestAtResults: ToArchetype, { - let (arch, path) = query_space_view_sub_archetype(space_view_id, blueprint_db, query); + let (arch, path) = query_view_property(space_view_id, blueprint_db, query); (arch.ok().flatten().unwrap_or_default(), path) } @@ -77,7 +77,7 @@ pub fn get_blueprint_component( ) -> Option { let blueprint_db = ctx.store_context.blueprint; let query = ctx.blueprint_query; - let path = entity_path_for_space_view_sub_archetype::(space_view_id, blueprint_db.tree()); + let path = entity_path_for_view_property::(space_view_id, blueprint_db.tree()); blueprint_db .latest_at_component::(&path, query) .map(|x| x.value) @@ -93,8 +93,7 @@ pub fn edit_blueprint_component) -> R, ) -> R { let active_blueprint = ctx.store_context.blueprint; - let active_path = - entity_path_for_space_view_sub_archetype::(space_view_id, active_blueprint.tree()); + let active_path = entity_path_for_view_property::(space_view_id, active_blueprint.tree()); let original_value: Option = active_blueprint .latest_at_component::(&active_path, ctx.blueprint_query) .map(|x| x.value); @@ -111,10 +110,8 @@ pub fn edit_blueprint_component( - space_view_id, - default_blueprint.tree(), - ); + let default_path = + entity_path_for_view_property::(space_view_id, default_blueprint.tree()); default_blueprint .latest_at_component::(&default_path, ctx.blueprint_query) .map(|x| x.value) diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs index ccf1b2ecdd31..71754e259e8d 100644 --- a/crates/re_space_view/src/visual_time_range.rs +++ b/crates/re_space_view/src/visual_time_range.rs @@ -14,7 +14,7 @@ use re_types::blueprint::datatypes::{ }; use re_viewer_context::ViewerContext; -pub fn time_range_boundary_to_visible_history_boundary( +pub fn visible_history_boundary_from_time_range_boundary( boundary: &VisibleTimeRangeBoundary, ) -> VisibleHistoryBoundary { match boundary.kind { @@ -45,7 +45,7 @@ pub fn visible_history_boundary_to_time_range_boundary( } } -pub fn visible_time_range_to_time_range( +pub fn time_range_from_visible_time_range( range: &VisibleTimeRange, cursor: re_log_types::TimeInt, ) -> re_log_types::TimeRange { @@ -68,31 +68,40 @@ pub fn query_visual_history( ctx: &ViewerContext<'_>, data_result: &re_viewer_context::DataResult, ) -> ExtraQueryHistory { - let time_range = - data_result.lookup_override::(ctx); - let sequence_range = data_result - .lookup_override::(ctx); - - let mut history = ExtraQueryHistory { - enabled: false, - nanos: Default::default(), - sequences: Default::default(), + let Some(overrides) = data_result.property_overrides.as_ref() else { + re_log::error!("No overrides found for visual history"); + return ExtraQueryHistory { + enabled: false, + nanos: Default::default(), + sequences: Default::default(), + }; }; - if let Some(time_range) = time_range { - history.enabled = true; - history.nanos = VisibleHistory { - from: time_range_boundary_to_visible_history_boundary(&time_range.0.start), - to: time_range_boundary_to_visible_history_boundary(&time_range.0.end), - }; - } - if let Some(sequence_range) = sequence_range { - history.enabled = true; - history.sequences = VisibleHistory { - from: time_range_boundary_to_visible_history_boundary(&sequence_range.0.start), - to: time_range_boundary_to_visible_history_boundary(&sequence_range.0.end), - }; + match &overrides.query_range { + re_viewer_context::QueryRange::TimeRange(time_range) => { + match ctx.rec_cfg.time_ctrl.read().time_type() { + re_log_types::TimeType::Time => ExtraQueryHistory { + enabled: true, + nanos: VisibleHistory { + from: visible_history_boundary_from_time_range_boundary(&time_range.start), + to: visible_history_boundary_from_time_range_boundary(&time_range.end), + }, + sequences: Default::default(), + }, + re_log_types::TimeType::Sequence => ExtraQueryHistory { + enabled: true, + nanos: Default::default(), + sequences: VisibleHistory { + from: visible_history_boundary_from_time_range_boundary(&time_range.start), + to: visible_history_boundary_from_time_range_boundary(&time_range.end), + }, + }, + } + } + re_viewer_context::QueryRange::LatestAt => ExtraQueryHistory { + enabled: false, + nanos: Default::default(), + sequences: Default::default(), + }, } - - history } diff --git a/crates/re_space_view_spatial/src/ui.rs b/crates/re_space_view_spatial/src/ui.rs index 4d8c7198b3b0..d500775ee89c 100644 --- a/crates/re_space_view_spatial/src/ui.rs +++ b/crates/re_space_view_spatial/src/ui.rs @@ -779,7 +779,7 @@ pub fn background_ui( let blueprint_db = ctx.store_context.blueprint; let blueprint_query = ctx.blueprint_query; let (archetype, blueprint_path) = - re_space_view::query_space_view_sub_archetype(space_view_id, blueprint_db, blueprint_query); + re_space_view::query_view_property(space_view_id, blueprint_db, blueprint_query); let Background { color, mut kind } = archetype.ok().flatten().unwrap_or(default_background); diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index 6574da3e50e5..e67a99dcb48c 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -275,9 +275,8 @@ pub fn view_2d( view_builder.queue_draw(draw_data); } - let background = - re_space_view::space_view_sub_archetype::(ctx, query.space_view_id) - .unwrap_or(Background::DEFAULT_2D); + let background = re_space_view::view_property::(ctx, query.space_view_id) + .unwrap_or(Background::DEFAULT_2D); let (background_drawable, clear_color) = crate::configure_background(ctx, background); if let Some(background_drawable) = background_drawable { view_builder.queue_draw(background_drawable); diff --git a/crates/re_space_view_spatial/src/ui_3d.rs b/crates/re_space_view_spatial/src/ui_3d.rs index 6f882cd0de51..13b91d24d883 100644 --- a/crates/re_space_view_spatial/src/ui_3d.rs +++ b/crates/re_space_view_spatial/src/ui_3d.rs @@ -665,9 +665,8 @@ pub fn view_3d( // Commit ui induced lines. view_builder.queue_draw(line_builder.into_draw_data()?); - let background = - re_space_view::space_view_sub_archetype::(ctx, query.space_view_id) - .unwrap_or(Background::DEFAULT_3D); + let background = re_space_view::view_property::(ctx, query.space_view_id) + .unwrap_or(Background::DEFAULT_3D); let (background_drawable, clear_color) = crate::configure_background(ctx, background); if let Some(background_drawable) = background_drawable { diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index 6b5c39bf70ed..a5a6b7d68347 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -44,7 +44,7 @@ pub fn query_archetype_with_history( entity_db: &EntityDb, timeline: &Timeline, time: &TimeInt, - history: &ExtraQueryHistory, + history: &ExtraQueryHistory, // TODO(andreas): don't take extra history, take something like `re_viewer_context::QueryRange` so we don't need to convert. entity_path: &EntityPath, ) -> Results { let visible_history = match timeline.typ() { diff --git a/crates/re_space_view_time_series/src/line_visualizer_system.rs b/crates/re_space_view_time_series/src/line_visualizer_system.rs index 5525f0ec0db8..9e7fd7d869c2 100644 --- a/crates/re_space_view_time_series/src/line_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/line_visualizer_system.rs @@ -183,8 +183,7 @@ fn load_series( let mut points; let time_range = determine_time_range( - ctx, - query, + query.latest_at, data_result, plot_bounds, ctx.app_options.experimental_plot_query_clamping, diff --git a/crates/re_space_view_time_series/src/point_visualizer_system.rs b/crates/re_space_view_time_series/src/point_visualizer_system.rs index 6bfeca20cd0e..f41153a15cda 100644 --- a/crates/re_space_view_time_series/src/point_visualizer_system.rs +++ b/crates/re_space_view_time_series/src/point_visualizer_system.rs @@ -136,8 +136,7 @@ impl SeriesPointSystem { let mut points; let time_range = determine_time_range( - ctx, - query, + query.latest_at, data_result, plot_bounds, ctx.app_options.experimental_plot_query_clamping, diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 6eddd010b98a..479239f9239d 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -5,15 +5,17 @@ use egui_plot::{Legend, Line, Plot, PlotPoint, Points}; use re_data_store::TimeType; use re_format::next_grid_tick_magnitude_ns; use re_log_types::{EntityPath, TimeInt, TimeZone}; -use re_space_view::{controls, query_space_view_sub_archetype_or_default}; -use re_types::blueprint::datatypes::VisibleTimeRange; -use re_types::SpaceViewClassIdentifier; -use re_types::{blueprint::components::Corner2D, components::Range1D}; +use re_space_view::{controls, query_view_property_or_default}; +use re_types::{ + blueprint::{components::Corner2D, datatypes::VisibleTimeRange}, + components::Range1D, + SpaceViewClassIdentifier, View, +}; use re_viewer_context::external::re_entity_db::{ EditableAutoValue, EntityProperties, TimeSeriesAggregator, }; use re_viewer_context::{ - IdentifiedViewSystem, IndicatedEntities, PerVisualizer, RecommendedSpaceView, + IdentifiedViewSystem, IndicatedEntities, PerVisualizer, QueryRange, RecommendedSpaceView, SmallVisualizerSet, SpaceViewClass, SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewState, SpaceViewStateExt as _, SpaceViewSystemExecutionError, SystemExecutionOutput, ViewQuery, ViewSystemIdentifier, @@ -73,15 +75,10 @@ impl SpaceViewState for TimeSeriesSpaceViewState { #[derive(Default)] pub struct TimeSeriesSpaceView; -use re_types::View; type ViewType = re_types::blueprint::views::TimeSeriesView; const DEFAULT_LEGEND_CORNER: egui_plot::Corner = egui_plot::Corner::RightBottom; -impl TimeSeriesSpaceView { - pub const DEFAULT_TIME_RANGE: VisibleTimeRange = VisibleTimeRange::EVERYTHING; -} - impl SpaceViewClass for TimeSeriesSpaceView { fn identifier() -> SpaceViewClassIdentifier { ViewType::identifier() @@ -145,8 +142,8 @@ impl SpaceViewClass for TimeSeriesSpaceView { re_viewer_context::SpaceViewClassLayoutPriority::Low } - fn default_visible_time_range(&self) -> VisibleTimeRange { - Self::DEFAULT_TIME_RANGE.clone() + fn default_query_range(&self) -> QueryRange { + QueryRange::TimeRange(VisibleTimeRange::EVERYTHING) } fn selection_ui( @@ -321,11 +318,7 @@ It can greatly improve performance (and readability) in such situations as it pr corner: legend_corner, }, _, - ) = query_space_view_sub_archetype_or_default( - query.space_view_id, - blueprint_db, - blueprint_query, - ); + ) = query_view_property_or_default(query.space_view_id, blueprint_db, blueprint_query); let ( re_types::blueprint::archetypes::ScalarAxis { @@ -333,11 +326,7 @@ It can greatly improve performance (and readability) in such situations as it pr lock_range_during_zoom: y_lock_range_during_zoom, }, _, - ) = query_space_view_sub_archetype_or_default( - query.space_view_id, - blueprint_db, - blueprint_query, - ); + ) = query_view_property_or_default(query.space_view_id, blueprint_db, blueprint_query); let (current_time, time_type, timeline) = { // Avoid holding the lock for long @@ -632,7 +621,7 @@ fn legend_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mut egui: let blueprint_db = ctx.store_context.blueprint; let blueprint_query = ctx.blueprint_query; let (re_types::blueprint::archetypes::PlotLegend { visible, corner }, blueprint_path) = - query_space_view_sub_archetype_or_default(space_view_id, blueprint_db, blueprint_query); + query_view_property_or_default(space_view_id, blueprint_db, blueprint_query); ctx.re_ui .selection_grid(ui, "time_series_selection_ui_legend") @@ -699,7 +688,7 @@ fn axis_ui( lock_range_during_zoom: y_lock_range_during_zoom, }, blueprint_path, - ) = query_space_view_sub_archetype_or_default( + ) = query_view_property_or_default( space_view_id, ctx.store_context.blueprint, ctx.blueprint_query, diff --git a/crates/re_space_view_time_series/src/util.rs b/crates/re_space_view_time_series/src/util.rs index cebe02da7baf..89cfd4560123 100644 --- a/crates/re_space_view_time_series/src/util.rs +++ b/crates/re_space_view_time_series/src/util.rs @@ -1,11 +1,14 @@ use re_log_types::{EntityPath, TimeRange}; -use re_space_view::visible_time_range_to_time_range; -use re_types::datatypes::Utf8; +use re_space_view::time_range_from_visible_time_range; +use re_types::{ + blueprint::datatypes::{VisibleTimeRange, VisibleTimeRangeBoundary}, + datatypes::Utf8, +}; use re_viewer_context::{external::re_entity_db::TimeSeriesAggregator, ViewQuery, ViewerContext}; use crate::{ aggregation::{AverageAggregator, MinMaxAggregator}, - PlotPoint, PlotSeries, PlotSeriesKind, ScatterAttrs, TimeSeriesSpaceView, + PlotPoint, PlotSeries, PlotSeriesKind, ScatterAttrs, }; /// Find the plot bounds and the per-ui-point delta from egui. @@ -29,24 +32,29 @@ pub fn determine_plot_bounds_and_time_per_pixel( } pub fn determine_time_range( - ctx: &ViewerContext<'_>, - query: &ViewQuery<'_>, + time_cursor: re_log_types::TimeInt, data_result: &re_viewer_context::DataResult, plot_bounds: Option, enable_query_clamping: bool, ) -> TimeRange { - let visible_time_range_override = match query.timeline.typ() { - re_log_types::TimeType::Time => data_result - .lookup_override::(ctx) - .map(|v| v.0), - re_log_types::TimeType::Sequence => data_result - .lookup_override::(ctx) - .map(|v| v.0), - } - .unwrap_or(TimeSeriesSpaceView::DEFAULT_TIME_RANGE); + let query_range = data_result.query_range(); + + // Latest-at doesn't make sense for time series and should also never happen. + let visible_time_range = match query_range { + re_viewer_context::QueryRange::TimeRange(time_range) => time_range.clone(), + re_viewer_context::QueryRange::LatestAt => { + re_log::error_once!( + "Unexexpected LatestAt query for time series data result at path {:?}", + data_result.entity_path + ); + VisibleTimeRange { + start: VisibleTimeRangeBoundary::AT_CURSOR, + end: VisibleTimeRangeBoundary::AT_CURSOR, + } + } + }; - let mut time_range = - visible_time_range_to_time_range(&visible_time_range_override, query.latest_at); + let mut time_range = time_range_from_visible_time_range(&visible_time_range, time_cursor); // TODO(cmc): We would love to reduce the query to match the actual plot bounds, but because // the plot widget handles zoom after we provide it with data for the current frame, diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index 5d8717d4f60f..7eeb9a27feba 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -30,6 +30,7 @@ include "./blueprint/archetypes/panel_blueprint.fbs"; include "./blueprint/archetypes/space_view_blueprint.fbs"; include "./blueprint/archetypes/space_view_contents.fbs"; include "./blueprint/archetypes/viewport_blueprint.fbs"; +include "./blueprint/archetypes/visible_time_range.fbs"; include "./blueprint/archetypes/visual_bounds.fbs"; include "./blueprint/archetypes/plot_legend.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/visible_time_range.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/visible_time_range.fbs new file mode 100644 index 000000000000..23c170476014 --- /dev/null +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/visible_time_range.fbs @@ -0,0 +1,32 @@ +include "arrow/attributes.fbs"; +include "python/attributes.fbs"; +include "rust/attributes.fbs"; + +include "rerun/datatypes.fbs"; +include "rerun/attributes.fbs"; + +namespace rerun.blueprint.archetypes; + +// --- + +/// Configures what range of the timeline is shown on a view. +/// +/// Whenever no visual time range applies, queries are done with "latest at" semantics. +/// This means that the view will, starting from the time cursor position, +/// query the latest data available for each component type. +/// +/// The default visual time range depends on the type of view this property applies to: +/// - For time series views, the default is to show the entire timeline. +/// - For any other view, the default is to apply latest-at semantics. +/// +/// The visual time range can be overridden also individually per entity. +table VisibleTimeRange ( + "attr.rerun.scope": "blueprint", + "attr.rust.derive": "Default" +) { + /// The range of time to show for timelines based on sequence numbers. + sequence: rerun.blueprint.components.VisibleTimeRangeSequence ("attr.rerun.component_optional", nullable, order: 1000); + + /// The range of time to show for timelines based on time. + time: rerun.blueprint.components.VisibleTimeRangeTime ("attr.rerun.component_optional", nullable, order: 2000); +} diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs index 86063fc7d097..1b76155252c6 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial2d.fbs @@ -14,4 +14,8 @@ table Spatial2DView ( /// Everything within these bounds are guaranteed to be visible. /// Somethings outside of these bounds may also be visible due to letterboxing. visual_bounds: rerun.blueprint.archetypes.VisualBounds (order: 2000); + + /// Configures the range on the timeline shown by this view (unless specified differently per entity). + time_range: rerun.blueprint.archetypes.VisibleTimeRange (order: 10000); + } diff --git a/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs b/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs index 1c1278c33a7a..27727f729b19 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/spatial3d.fbs @@ -10,4 +10,7 @@ table Spatial3DView ( ) { /// Configuration for the background of the space view. background: rerun.blueprint.archetypes.Background (order: 1000); + + /// Configures the range on the timeline shown by this view (unless specified differently per entity). + time_range: rerun.blueprint.archetypes.VisibleTimeRange (order: 2000); } diff --git a/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs b/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs index a4391c61dc61..802aa9e7c399 100644 --- a/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs +++ b/crates/re_types/definitions/rerun/blueprint/views/time_series.fbs @@ -11,4 +11,7 @@ table TimeSeriesView ( /// Configures the legend of the plot. plot_legend: rerun.blueprint.archetypes.PlotLegend (order: 2000); + + /// Configures the time range the plot covers (unless specified differently per entity). + time_range: rerun.blueprint.archetypes.VisibleTimeRange (order: 3000); } diff --git a/crates/re_types/src/blueprint/archetypes/.gitattributes b/crates/re_types/src/blueprint/archetypes/.gitattributes index 99631b4ea017..68aaa951e26e 100644 --- a/crates/re_types/src/blueprint/archetypes/.gitattributes +++ b/crates/re_types/src/blueprint/archetypes/.gitattributes @@ -7,4 +7,5 @@ plot_legend.rs linguist-generated=true scalar_axis.rs linguist-generated=true space_view_blueprint.rs linguist-generated=true space_view_contents.rs linguist-generated=true +visible_time_range.rs linguist-generated=true visual_bounds.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/archetypes/mod.rs b/crates/re_types/src/blueprint/archetypes/mod.rs index bca93c2d48e0..38f1706c4582 100644 --- a/crates/re_types/src/blueprint/archetypes/mod.rs +++ b/crates/re_types/src/blueprint/archetypes/mod.rs @@ -6,6 +6,7 @@ mod plot_legend; mod scalar_axis; mod space_view_blueprint; mod space_view_contents; +mod visible_time_range; mod visual_bounds; pub use self::background::Background; @@ -13,4 +14,5 @@ pub use self::plot_legend::PlotLegend; pub use self::scalar_axis::ScalarAxis; pub use self::space_view_blueprint::SpaceViewBlueprint; pub use self::space_view_contents::SpaceViewContents; +pub use self::visible_time_range::VisibleTimeRange; pub use self::visual_bounds::VisualBounds; diff --git a/crates/re_types/src/blueprint/archetypes/visible_time_range.rs b/crates/re_types/src/blueprint/archetypes/visible_time_range.rs new file mode 100644 index 000000000000..016a56c8dd65 --- /dev/null +++ b/crates/re_types/src/blueprint/archetypes/visible_time_range.rs @@ -0,0 +1,207 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visible_time_range.fbs". + +#![allow(trivial_numeric_casts)] +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::iter_on_single_items)] +#![allow(clippy::map_flatten)] +#![allow(clippy::match_wildcard_for_single_variants)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] +#![allow(clippy::unnecessary_cast)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Archetype**: Configures what range of the timeline is shown on a view. +/// +/// Whenever no visual time range applies, queries are done with "latest at" semantics. +/// This means that the view will, starting from the time cursor position, +/// query the latest data available for each component type. +/// +/// The default visual time range depends on the type of view this property applies to: +/// - For time series views, the default is to show the entire timeline. +/// - For any other view, the default is to apply latest-at semantics. +/// +/// The visual time range can be overridden also individually per entity. +#[derive(Clone, Debug, Default)] +pub struct VisibleTimeRange { + /// The range of time to show for timelines based on sequence numbers. + pub sequence: Option, + + /// The range of time to show for timelines based on time. + pub time: Option, +} + +impl ::re_types_core::SizeBytes for VisibleTimeRange { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.sequence.heap_size_bytes() + self.time.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + >::is_pod() + && >::is_pod() + } +} + +static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = + once_cell::sync::Lazy::new(|| []); + +static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = + once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.VisibleTimeRangeIndicator".into()]); + +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.VisibleTimeRangeSequence".into(), + "rerun.blueprint.components.VisibleTimeRangeTime".into(), + ] + }); + +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 3usize]> = + once_cell::sync::Lazy::new(|| { + [ + "rerun.blueprint.components.VisibleTimeRangeIndicator".into(), + "rerun.blueprint.components.VisibleTimeRangeSequence".into(), + "rerun.blueprint.components.VisibleTimeRangeTime".into(), + ] + }); + +impl VisibleTimeRange { + /// The total number of components in the archetype: 0 required, 1 recommended, 2 optional + pub const NUM_COMPONENTS: usize = 3usize; +} + +/// Indicator component for the [`VisibleTimeRange`] [`::re_types_core::Archetype`] +pub type VisibleTimeRangeIndicator = ::re_types_core::GenericIndicatorComponent; + +impl ::re_types_core::Archetype for VisibleTimeRange { + type Indicator = VisibleTimeRangeIndicator; + + #[inline] + fn name() -> ::re_types_core::ArchetypeName { + "rerun.blueprint.archetypes.VisibleTimeRange".into() + } + + #[inline] + fn indicator() -> MaybeOwnedComponentBatch<'static> { + static INDICATOR: VisibleTimeRangeIndicator = VisibleTimeRangeIndicator::DEFAULT; + MaybeOwnedComponentBatch::Ref(&INDICATOR) + } + + #[inline] + fn required_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + REQUIRED_COMPONENTS.as_slice().into() + } + + #[inline] + fn recommended_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + RECOMMENDED_COMPONENTS.as_slice().into() + } + + #[inline] + fn optional_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + OPTIONAL_COMPONENTS.as_slice().into() + } + + #[inline] + fn all_components() -> ::std::borrow::Cow<'static, [ComponentName]> { + ALL_COMPONENTS.as_slice().into() + } + + #[inline] + fn from_arrow_components( + arrow_data: impl IntoIterator)>, + ) -> DeserializationResult { + re_tracing::profile_function!(); + use ::re_types_core::{Loggable as _, ResultExt as _}; + let arrays_by_name: ::std::collections::HashMap<_, _> = arrow_data + .into_iter() + .map(|(name, array)| (name.full_name(), array)) + .collect(); + let sequence = if let Some(array) = + arrays_by_name.get("rerun.blueprint.components.VisibleTimeRangeSequence") + { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.VisibleTimeRange#sequence")? + .into_iter() + .next() + .flatten() + } else { + None + }; + let time = if let Some(array) = + arrays_by_name.get("rerun.blueprint.components.VisibleTimeRangeTime") + { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.VisibleTimeRange#time")? + .into_iter() + .next() + .flatten() + } else { + None + }; + Ok(Self { sequence, time }) + } +} + +impl ::re_types_core::AsComponents for VisibleTimeRange { + fn as_component_batches(&self) -> Vec> { + re_tracing::profile_function!(); + use ::re_types_core::Archetype as _; + [ + Some(Self::indicator()), + self.sequence + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch).into()), + self.time + .as_ref() + .map(|comp| (comp as &dyn ComponentBatch).into()), + ] + .into_iter() + .flatten() + .collect() + } +} + +impl VisibleTimeRange { + /// Create a new `VisibleTimeRange`. + #[inline] + pub fn new() -> Self { + Self { + sequence: None, + time: None, + } + } + + /// The range of time to show for timelines based on sequence numbers. + #[inline] + pub fn with_sequence( + mut self, + sequence: impl Into, + ) -> Self { + self.sequence = Some(sequence.into()); + self + } + + /// The range of time to show for timelines based on time. + #[inline] + pub fn with_time( + mut self, + time: impl Into, + ) -> Self { + self.time = Some(time.into()); + self + } +} diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs index 7de1d58ce394..218dc2797777 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs +++ b/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs @@ -1,12 +1,6 @@ use super::{VisibleTimeRange, VisibleTimeRangeBoundary}; impl VisibleTimeRange { - /// The empty range, set at the current time cursor. - pub const EMPTY: Self = Self { - start: VisibleTimeRangeBoundary::AT_CURSOR, - end: VisibleTimeRangeBoundary::AT_CURSOR, - }; - /// The range encompassing all time, from -∞ to +∞. pub const EVERYTHING: Self = Self { // This means -∞ diff --git a/crates/re_types/src/blueprint/views/spatial2d_view.rs b/crates/re_types/src/blueprint/views/spatial2d_view.rs index c77bca3cdbe8..75b6e96f4b36 100644 --- a/crates/re_types/src/blueprint/views/spatial2d_view.rs +++ b/crates/re_types/src/blueprint/views/spatial2d_view.rs @@ -33,18 +33,24 @@ pub struct Spatial2DView { /// Everything within these bounds are guaranteed to be visible. /// Somethings outside of these bounds may also be visible due to letterboxing. pub visual_bounds: crate::blueprint::archetypes::VisualBounds, + + /// Configures the range on the timeline shown by this view (unless specified differently per entity). + pub time_range: crate::blueprint::archetypes::VisibleTimeRange, } impl ::re_types_core::SizeBytes for Spatial2DView { #[inline] fn heap_size_bytes(&self) -> u64 { - self.background.heap_size_bytes() + self.visual_bounds.heap_size_bytes() + self.background.heap_size_bytes() + + self.visual_bounds.heap_size_bytes() + + self.time_range.heap_size_bytes() } #[inline] fn is_pod() -> bool { ::is_pod() && ::is_pod() + && ::is_pod() } } diff --git a/crates/re_types/src/blueprint/views/spatial3d_view.rs b/crates/re_types/src/blueprint/views/spatial3d_view.rs index b3fbf3be8a00..4311b60d514d 100644 --- a/crates/re_types/src/blueprint/views/spatial3d_view.rs +++ b/crates/re_types/src/blueprint/views/spatial3d_view.rs @@ -27,41 +27,21 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; pub struct Spatial3DView { /// Configuration for the background of the space view. pub background: crate::blueprint::archetypes::Background, + + /// Configures the range on the timeline shown by this view (unless specified differently per entity). + pub time_range: crate::blueprint::archetypes::VisibleTimeRange, } impl ::re_types_core::SizeBytes for Spatial3DView { #[inline] fn heap_size_bytes(&self) -> u64 { - self.background.heap_size_bytes() + self.background.heap_size_bytes() + self.time_range.heap_size_bytes() } #[inline] fn is_pod() -> bool { ::is_pod() - } -} - -impl> From for Spatial3DView { - fn from(v: T) -> Self { - Self { - background: v.into(), - } - } -} - -impl std::borrow::Borrow for Spatial3DView { - #[inline] - fn borrow(&self) -> &crate::blueprint::archetypes::Background { - &self.background - } -} - -impl std::ops::Deref for Spatial3DView { - type Target = crate::blueprint::archetypes::Background; - - #[inline] - fn deref(&self) -> &crate::blueprint::archetypes::Background { - &self.background + && ::is_pod() } } diff --git a/crates/re_types/src/blueprint/views/time_series_view.rs b/crates/re_types/src/blueprint/views/time_series_view.rs index beba05c1634f..dd90930c629f 100644 --- a/crates/re_types/src/blueprint/views/time_series_view.rs +++ b/crates/re_types/src/blueprint/views/time_series_view.rs @@ -30,18 +30,24 @@ pub struct TimeSeriesView { /// Configures the legend of the plot. pub plot_legend: crate::blueprint::archetypes::PlotLegend, + + /// Configures the time range the plot covers (unless specified differently per entity). + pub time_range: crate::blueprint::archetypes::VisibleTimeRange, } impl ::re_types_core::SizeBytes for TimeSeriesView { #[inline] fn heap_size_bytes(&self) -> u64 { - self.axis_y.heap_size_bytes() + self.plot_legend.heap_size_bytes() + self.axis_y.heap_size_bytes() + + self.plot_legend.heap_size_bytes() + + self.time_range.heap_size_bytes() } #[inline] fn is_pod() -> bool { ::is_pod() && ::is_pod() + && ::is_pod() } } diff --git a/crates/re_viewer/src/app_state.rs b/crates/re_viewer/src/app_state.rs index 3898c891b12e..59ad0f8294e3 100644 --- a/crates/re_viewer/src/app_state.rs +++ b/crates/re_viewer/src/app_state.rs @@ -261,15 +261,19 @@ impl AppState { &space_view.space_origin, ); - let props = viewport.state.space_view_props(space_view.id); let resolver = space_view.contents.build_resolver( space_view_class_registry, space_view, - props, &visualizable_entities, &indicated_entities_per_visualizer, ); - resolver.update_overrides(store_context, &blueprint_query, query_result); + resolver.update_overrides( + store_context.blueprint, + &blueprint_query, + rec_cfg.time_ctrl.read().timeline(), + space_view_class_registry, + query_result, + ); } } }; diff --git a/crates/re_viewer/src/ui/mod.rs b/crates/re_viewer/src/ui/mod.rs index b9a48af02fc4..4afbd2cc5900 100644 --- a/crates/re_viewer/src/ui/mod.rs +++ b/crates/re_viewer/src/ui/mod.rs @@ -10,7 +10,7 @@ mod welcome_screen; pub(crate) mod memory_panel; pub(crate) mod selection_panel; pub(crate) mod space_view_space_origin_ui; -pub(crate) mod visible_history; +pub(crate) mod visual_time_range; pub use blueprint_panel::blueprint_panel_ui; pub use recordings_panel::recordings_panel_ui; diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 97aef089d2f8..d1eb4de03bbf 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -13,7 +13,6 @@ use re_space_view_time_series::TimeSeriesSpaceView; use re_types::{ components::{PinholeProjection, Transform3D}, tensor_data::TensorDataMeaning, - SpaceViewClassIdentifier, }; use re_ui::{icons, list_item::ListItem}; use re_ui::{ReUi, SyntaxHighlighting as _}; @@ -29,7 +28,10 @@ use re_viewport::{ use crate::ui::override_ui::override_visualizer_ui; use crate::{app_state::default_selection_panel_width, ui::override_ui::override_ui}; -use super::{selection_history_ui::SelectionHistoryUi, visible_history::visual_time_range_ui}; +use super::{ + selection_history_ui::SelectionHistoryUi, visual_time_range::visual_time_range_ui_data_result, + visual_time_range::visual_time_range_ui_space_view, +}; // --- @@ -902,23 +904,12 @@ fn blueprint_ui_for_space_view( &class_identifier, ); - // Space View don't inherit properties. - let space_view_data_result = - space_view.space_view_data_result(ctx.store_context, ctx.blueprint_query); - - visual_time_range_ui( - ctx, - ui, - None, // There is no tree above the space view yet - &space_view_data_result, - class_identifier, - true, - ); + visual_time_range_ui_space_view(ctx, ui, space_view); - let mut props = space_view_data_result - .individual_properties() - .cloned() - .unwrap_or_default(); + // Space View don't inherit (legacy) properties. + let mut props = + space_view.legacy_properties(ctx.store_context.blueprint, ctx.blueprint_query); + let props_before = props.clone(); let space_view_class = space_view.class(ctx.space_view_class_registry); if let Err(err) = space_view_class.selection_ui( @@ -936,7 +927,9 @@ fn blueprint_ui_for_space_view( ); } - space_view_data_result.save_individual_override_properties(ctx, Some(props)); + if props_before != props { + space_view.save_legacy_properties(ctx, props); + } } } @@ -950,7 +943,6 @@ fn blueprint_ui_for_data_result( if let Some(space_view) = viewport.blueprint.space_view(&space_view_id) { if instance_path.instance.is_all() { // the whole entity - let space_view_class = *space_view.class_identifier(); let entity_path = &instance_path.entity_path; let query_result = ctx.lookup_query_result(space_view.id); @@ -968,7 +960,6 @@ fn blueprint_ui_for_data_result( ctx, ui, ctx.lookup_query_result(space_view_id), - &space_view_class, entity_path, &mut props, ); @@ -1143,7 +1134,6 @@ fn entity_props_ui( ctx: &ViewerContext<'_>, ui: &mut egui::Ui, query_result: &DataQueryResult, - space_view_class: &SpaceViewClassIdentifier, entity_path: &EntityPath, entity_props: &mut EntityProperties, ) { @@ -1156,7 +1146,7 @@ fn entity_props_ui( }; { - let visible_before = data_result.lookup_override_or_default::(ctx); + let visible_before = data_result.is_visible(ctx); let mut visible = visible_before; let override_source = @@ -1165,7 +1155,7 @@ fn entity_props_ui( override_source.is_some() && override_source.as_ref() != Some(entity_path); ui.horizontal(|ui| { - re_ui.checkbox(ui, &mut visible.0, "Visible"); + re_ui.checkbox(ui, &mut visible, "Visible"); if is_inherited { ui.label("(inherited)"); } @@ -1175,7 +1165,7 @@ fn entity_props_ui( data_result.save_recursive_override_or_clear_if_redundant( ctx, &query_result.tree, - &visible, + &Visible(visible), ); } } @@ -1184,14 +1174,7 @@ fn entity_props_ui( .checkbox(ui, &mut entity_props.interactive, "Interactive") .on_hover_text("If disabled, the entity will not react to any mouse interaction"); - visual_time_range_ui( - ctx, - ui, - Some(&query_result.tree), - data_result, - *space_view_class, - false, - ); + visual_time_range_ui_data_result(ctx, ui, &query_result.tree, data_result); egui::Grid::new("entity_properties") .num_columns(2) diff --git a/crates/re_viewer/src/ui/visible_history.rs b/crates/re_viewer/src/ui/visual_time_range.rs similarity index 66% rename from crates/re_viewer/src/ui/visible_history.rs rename to crates/re_viewer/src/ui/visual_time_range.rs index 50a2260dd1a6..beb69d6f4b1b 100644 --- a/crates/re_viewer/src/ui/visible_history.rs +++ b/crates/re_viewer/src/ui/visual_time_range.rs @@ -4,20 +4,25 @@ use std::ops::RangeInclusive; use egui::{NumExt as _, Response, Ui}; use re_entity_db::{TimeHistogram, VisibleHistory, VisibleHistoryBoundary}; -use re_log_types::{TimeInt, TimeType, TimeZone}; +use re_log_types::{EntityPath, TimeInt, TimeType, TimeZone}; use re_space_view::{ - time_range_boundary_to_visible_history_boundary, - visible_history_boundary_to_time_range_boundary, visible_time_range_to_time_range, + query_view_property, time_range_from_visible_time_range, + visible_history_boundary_from_time_range_boundary, + visible_history_boundary_to_time_range_boundary, SpaceViewBlueprint, }; use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D}; use re_space_view_time_series::TimeSeriesSpaceView; use re_types::{ - blueprint::components::{VisibleTimeRangeSequence, VisibleTimeRangeTime}, + blueprint::{ + archetypes::VisibleTimeRange, + components::{VisibleTimeRangeSequence, VisibleTimeRangeTime}, + datatypes::VisibleTimeRangeBoundary, + }, SpaceViewClassIdentifier, }; use re_types_core::Loggable as _; use re_ui::{markdown_ui, ReUi}; -use re_viewer_context::{SpaceViewClass, ViewerContext}; +use re_viewer_context::{QueryRange, SpaceViewClass, ViewerContext}; /// These space views support the Visible History feature. static VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS: once_cell::sync::Lazy< @@ -38,222 +43,294 @@ fn space_view_with_visible_history(space_view_class: SpaceViewClassIdentifier) - VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS.contains(&space_view_class) } -pub fn visual_time_range_ui( +pub fn visual_time_range_ui_space_view( ctx: &ViewerContext<'_>, ui: &mut Ui, - data_result_tree: Option<&re_viewer_context::DataResultTree>, - data_result: &re_viewer_context::DataResult, - space_view_class: SpaceViewClassIdentifier, - is_space_view: bool, + space_view: &SpaceViewBlueprint, ) { - let time_ctrl = ctx.rec_cfg.time_ctrl.read().clone(); - - if is_space_view && !space_view_with_visible_history(space_view_class) { + if !space_view_with_visible_history(*space_view.class_identifier()) { return; } - let re_ui = ctx.re_ui; - + let time_ctrl = ctx.rec_cfg.time_ctrl.read().clone(); let time_type = time_ctrl.timeline().typ(); - let mut interacting_with_controls = false; + let (property, property_path) = query_view_property::( + space_view.id, + ctx.store_context.blueprint, + ctx.blueprint_query, + ); + + let has_individual_range = match time_type { + TimeType::Time => property.ok().flatten().map_or(false, |v| v.time.is_some()), + TimeType::Sequence => property + .ok() + .flatten() + .map_or(false, |v| v.sequence.is_some()), + }; + + let query_range = space_view.query_range( + ctx.store_context.blueprint, + ctx.blueprint_query, + ctx.rec_cfg.time_ctrl.read().timeline(), + ctx.space_view_class_registry, + ); + + let is_space_view = true; + visual_time_range_ui( + ctx, + ui, + &query_range, + has_individual_range, + is_space_view, + &property_path, + ); +} - let space_view_class = ctx - .space_view_class_registry - .get_class_or_log_error(&space_view_class); +pub fn visual_time_range_ui_data_result( + ctx: &ViewerContext<'_>, + ui: &mut Ui, + data_result_tree: &re_viewer_context::DataResultTree, + data_result: &re_viewer_context::DataResult, +) { + let time_type = ctx.rec_cfg.time_ctrl.read().timeline().typ(); - let active_time_range_override = match time_type { - TimeType::Time => data_result - .lookup_override::(ctx) - .map(|v| v.0), + let has_individual_range = match time_type { + TimeType::Time => { + data_result.component_override_source(data_result_tree, &VisibleTimeRangeTime::name()) + } TimeType::Sequence => data_result - .lookup_override::(ctx) - .map(|v| v.0), + .component_override_source(data_result_tree, &VisibleTimeRangeSequence::name()), + } + .is_some(); + + let Some(override_path) = data_result.recursive_override_path() else { + re_log::error_once!("No override computed yet for entity"); + return; + }; + let Some(overrides) = data_result.property_overrides.as_ref() else { + re_log::error_once!("No override computed yet for entity"); + return; }; - let mut has_individual_range = if let Some(data_result_tree) = data_result_tree { - // If there is a data-tree, we know we have individual settings if we are our own source. - let component_override_source = match time_type { - TimeType::Time => data_result - .component_override_source(data_result_tree, &VisibleTimeRangeTime::name()), - TimeType::Sequence => data_result - .component_override_source(data_result_tree, &VisibleTimeRangeSequence::name()), - }; + let is_space_view = false; + visual_time_range_ui( + ctx, + ui, + &overrides.query_range, + has_individual_range, + is_space_view, + override_path, + ); +} - component_override_source.as_ref() == Some(&data_result.entity_path) - } else { - // Otherwise we can inspect directly. - active_time_range_override.is_some() - }; +fn visual_time_range_ui( + ctx: &ViewerContext<'_>, + ui: &mut Ui, + resolved_range: &QueryRange, + mut has_individual_range: bool, + is_space_view: bool, + property_override_path: &EntityPath, +) { + let re_ui = ctx.re_ui; + let time_ctrl = ctx.rec_cfg.time_ctrl.read().clone(); + let time_type = time_ctrl.timeline().typ(); - let mut resolved_range = - active_time_range_override.unwrap_or(space_view_class.default_visible_time_range()); + let mut interacting_with_controls = false; - let collapsing_response = re_ui.collapsing_header(ui, "Visible time range", false, |ui| { - let has_individual_range_before = has_individual_range; - let resolved_range_before = resolved_range.clone(); + let mut resolved_range = match resolved_range { + QueryRange::TimeRange(range) => range.clone(), + QueryRange::LatestAt => { + if has_individual_range { + re_log::error_once!("Visible time range is set but no time range is provided"); + } + // TODO(andreas): Should print a string that we're using the latest time. + re_types::blueprint::datatypes::VisibleTimeRange { + start: VisibleTimeRangeBoundary::AT_CURSOR, + end: VisibleTimeRangeBoundary::AT_CURSOR, + } + } + }; - ui.horizontal(|ui| { - re_ui - .radio_value(ui, &mut has_individual_range, false, "Default") - .on_hover_text(if is_space_view { - "Default visible time range settings for this kind of space view" - } else { - "Visible time range settings inherited from parent Entity or enclosing \ + let collapsing_response = ctx + .re_ui + .collapsing_header(ui, "Visible time range", false, |ui| { + let has_individual_range_before = has_individual_range; + let resolved_range_before = resolved_range.clone(); + + ui.horizontal(|ui| { + re_ui + .radio_value(ui, &mut has_individual_range, false, "Default") + .on_hover_text(if is_space_view { + "Default visible time range settings for this kind of space view" + } else { + "Visible time range settings inherited from parent Entity or enclosing \ space view" - }); - re_ui - .radio_value(ui, &mut has_individual_range, true, "Override") - .on_hover_text(if is_space_view { - "Set visible time range settings for the contents of this space view" + }); + re_ui + .radio_value(ui, &mut has_individual_range, true, "Override") + .on_hover_text(if is_space_view { + "Set visible time range settings for the contents of this space view" + } else { + "Set visible time range settings for this entity" + }); + }); + + let timeline_spec = + if let Some(times) = ctx.recording().time_histogram(time_ctrl.timeline()) { + TimelineSpec::from_time_histogram(times) } else { - "Set visible time range settings for this entity" - }); - }); + TimelineSpec::from_time_range(0..=0) + }; - let timeline_spec = - if let Some(times) = ctx.recording().time_histogram(time_ctrl.timeline()) { - TimelineSpec::from_time_histogram(times) - } else { - TimelineSpec::from_time_range(0..=0) - }; + let current_time = time_ctrl + .time_i64() + .unwrap_or_default() + .at_least(*timeline_spec.range.start()); // accounts for timeless time (TimeInt::MIN) - let current_time = time_ctrl - .time_i64() - .unwrap_or_default() - .at_least(*timeline_spec.range.start()); // accounts for timeless time (TimeInt::MIN) + let from = &mut resolved_range.start; + let to = &mut resolved_range.end; - let from = &mut resolved_range.start; - let to = &mut resolved_range.end; + // Convert to legacy visual history type. + let mut visible_history = VisibleHistory { + from: visible_history_boundary_from_time_range_boundary(from), + to: visible_history_boundary_from_time_range_boundary(to), + }; - // Convert to legacy visual history type. - let mut visible_history = VisibleHistory { - from: time_range_boundary_to_visible_history_boundary(from), - to: time_range_boundary_to_visible_history_boundary(to), - }; + if has_individual_range { + let current_from = visible_history + .range_start_from_cursor(TimeInt::new_temporal(current_time)) + .as_i64(); + let current_to = visible_history + .range_end_from_cursor(TimeInt::new_temporal(current_time)) + .as_i64(); + + egui::Grid::new("from_to_editable").show(ui, |ui| { + re_ui.grid_left_hand_label(ui, "From"); + interacting_with_controls |= ui + .horizontal(|ui| { + visible_history_boundary_ui( + ctx, + ui, + &mut visible_history.from, + time_type, + current_time, + &timeline_spec, + true, + current_to, + ) + }) + .inner; + ui.end_row(); - if has_individual_range { - let current_from = visible_history - .range_start_from_cursor(TimeInt::new_temporal(current_time)) - .as_i64(); - let current_to = visible_history - .range_end_from_cursor(TimeInt::new_temporal(current_time)) - .as_i64(); - - egui::Grid::new("from_to_editable").show(ui, |ui| { - re_ui.grid_left_hand_label(ui, "From"); - interacting_with_controls |= ui - .horizontal(|ui| { - visible_history_boundary_ui( + re_ui.grid_left_hand_label(ui, "To"); + interacting_with_controls |= ui + .horizontal(|ui| { + visible_history_boundary_ui( + ctx, + ui, + &mut visible_history.to, + time_type, + current_time, + &timeline_spec, + false, + current_from, + ) + }) + .inner; + ui.end_row(); + }); + + current_range_ui(ctx, ui, current_time, time_type, &visible_history); + } else { + // Show the resolved visible range as labels (user can't edit them): + + if visible_history.from == VisibleHistoryBoundary::Infinite + && visible_history.to == VisibleHistoryBoundary::Infinite + { + ui.label("Entire timeline"); + } else if visible_history.from == VisibleHistoryBoundary::AT_CURSOR + && visible_history.to == VisibleHistoryBoundary::AT_CURSOR + { + let current_time = time_type.format( + TimeInt::new_temporal(current_time), + ctx.app_options.time_zone, + ); + match time_type { + TimeType::Time => { + ui.label(format!("At current time: {current_time}")); + } + TimeType::Sequence => { + ui.label(format!("At current frame: {current_time}")); + } + } + } else { + egui::Grid::new("from_to_labels").show(ui, |ui| { + re_ui.grid_left_hand_label(ui, "From"); + resolved_visible_history_boundary_ui( ctx, ui, - &mut visible_history.from, + &visible_history.from, time_type, - current_time, - &timeline_spec, true, - current_to, - ) - }) - .inner; - ui.end_row(); - - re_ui.grid_left_hand_label(ui, "To"); - interacting_with_controls |= ui - .horizontal(|ui| { - visible_history_boundary_ui( + ); + ui.end_row(); + + re_ui.grid_left_hand_label(ui, "To"); + resolved_visible_history_boundary_ui( ctx, ui, - &mut visible_history.to, + &visible_history.to, time_type, - current_time, - &timeline_spec, false, - current_from, - ) - }) - .inner; - ui.end_row(); - }); - - current_range_ui(ctx, ui, current_time, time_type, &visible_history); - } else { - // Show the resolved visible range as labels (user can't edit them): + ); + ui.end_row(); + }); - if visible_history.from == VisibleHistoryBoundary::Infinite - && visible_history.to == VisibleHistoryBoundary::Infinite - { - ui.label("Entire timeline"); - } else if visible_history.from == VisibleHistoryBoundary::AT_CURSOR - && visible_history.to == VisibleHistoryBoundary::AT_CURSOR - { - let current_time = time_type.format( - TimeInt::new_temporal(current_time), - ctx.app_options.time_zone, - ); - match time_type { - TimeType::Time => { - ui.label(format!("At current time: {current_time}")); - } - TimeType::Sequence => { - ui.label(format!("At current frame: {current_time}")); - } + current_range_ui(ctx, ui, current_time, time_type, &visible_history); } - } else { - egui::Grid::new("from_to_labels").show(ui, |ui| { - re_ui.grid_left_hand_label(ui, "From"); - resolved_visible_history_boundary_ui( - ctx, - ui, - &visible_history.from, - time_type, - true, - ); - ui.end_row(); - - re_ui.grid_left_hand_label(ui, "To"); - resolved_visible_history_boundary_ui( - ctx, - ui, - &visible_history.to, - time_type, - false, - ); - ui.end_row(); - }); - - current_range_ui(ctx, ui, current_time, time_type, &visible_history); } - } - // Convert back from visual history type. - *from = visible_history_boundary_to_time_range_boundary(&visible_history.from); - *to = visible_history_boundary_to_time_range_boundary(&visible_history.to); + // Convert back from visual history type. + *from = visible_history_boundary_to_time_range_boundary(&visible_history.from); + *to = visible_history_boundary_to_time_range_boundary(&visible_history.to); - // Save to blueprint store if anything has changed. - if has_individual_range != has_individual_range_before - || resolved_range != resolved_range_before - { - if has_individual_range { - let resolved_range = resolved_range.clone(); - match time_type { - TimeType::Time => data_result - .save_recursive_override(ctx, &VisibleTimeRangeTime(resolved_range)), - TimeType::Sequence => data_result - .save_recursive_override(ctx, &VisibleTimeRangeSequence(resolved_range)), - }; - } else { - match time_type { - TimeType::Time => { - data_result.clear_recursive_override::(ctx); - } - TimeType::Sequence => { - data_result.clear_recursive_override::(ctx); + // Save to blueprint store if anything has changed. + if has_individual_range != has_individual_range_before + || resolved_range != resolved_range_before + { + if has_individual_range { + let resolved_range = resolved_range.clone(); + match time_type { + TimeType::Time => { + ctx.save_blueprint_component( + property_override_path, + &VisibleTimeRangeTime(resolved_range), + ); + } + TimeType::Sequence => { + ctx.save_blueprint_component( + property_override_path, + &VisibleTimeRangeSequence(resolved_range), + ); + } + }; + } else { + match time_type { + TimeType::Time => { + ctx.save_empty_blueprint_component::( + property_override_path, + ); + } + TimeType::Sequence => { + ctx.save_empty_blueprint_component::( + property_override_path, + ); + } } } } - } - }); + }); // Add spacer after the visible history section. //TODO(ab): figure out why `item_spacing.y` is added _only_ in collapsed state. @@ -278,7 +355,7 @@ pub fn visual_time_range_ui( if should_display_visible_history { if let Some(current_time) = time_ctrl.time_int() { - let range = visible_time_range_to_time_range(&resolved_range, current_time); + let range = time_range_from_visible_time_range(&resolved_range, current_time); ctx.rec_cfg.time_ctrl.write().highlighted_range = Some(range); } } diff --git a/crates/re_viewer_context/src/lib.rs b/crates/re_viewer_context/src/lib.rs index 5a2a767ac631..e35fa2ff24da 100644 --- a/crates/re_viewer_context/src/lib.rs +++ b/crates/re_viewer_context/src/lib.rs @@ -13,6 +13,7 @@ mod component_ui_registry; mod contents; mod item; mod query_context; +mod query_range; mod selection_history; mod selection_state; mod space_view; @@ -42,6 +43,7 @@ pub use component_ui_registry::{ComponentUiRegistry, UiVerbosity}; pub use contents::{blueprint_id_to_tile_id, Contents, ContentsName}; pub use item::Item; pub use query_context::{DataQueryResult, DataResultHandle, DataResultNode, DataResultTree}; +pub use query_range::QueryRange; pub use selection_history::SelectionHistory; pub use selection_state::{ ApplicationSelectionState, HoverHighlight, InteractionHighlight, ItemCollection, diff --git a/crates/re_viewer_context/src/query_range.rs b/crates/re_viewer_context/src/query_range.rs new file mode 100644 index 000000000000..e0415a6749f7 --- /dev/null +++ b/crates/re_viewer_context/src/query_range.rs @@ -0,0 +1,10 @@ +/// Range & type of data store query. +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub enum QueryRange { + /// Use a time range on the currently active timeline. + TimeRange(re_types::blueprint::datatypes::VisibleTimeRange), + + /// Use latest-at semantics. + #[default] + LatestAt, +} diff --git a/crates/re_viewer_context/src/space_view/space_view_class.rs b/crates/re_viewer_context/src/space_view/space_view_class.rs index 4a5a29f1330e..249767c0b6ca 100644 --- a/crates/re_viewer_context/src/space_view/space_view_class.rs +++ b/crates/re_viewer_context/src/space_view/space_view_class.rs @@ -1,10 +1,10 @@ use nohash_hasher::IntSet; use re_entity_db::{EntityProperties, EntityPropertyMap}; use re_log_types::EntityPath; -use re_types::{blueprint::datatypes::VisibleTimeRange, ComponentName, SpaceViewClassIdentifier}; +use re_types::{ComponentName, SpaceViewClassIdentifier}; use crate::{ - IndicatedEntities, PerSystemEntities, PerVisualizer, SmallVisualizerSet, + IndicatedEntities, PerSystemEntities, PerVisualizer, QueryRange, SmallVisualizerSet, SpaceViewClassRegistryError, SpaceViewId, SpaceViewSpawnHeuristics, SpaceViewSystemExecutionError, SpaceViewSystemRegistrator, SystemExecutionOutput, ViewQuery, ViewerContext, VisualizableEntities, @@ -93,10 +93,9 @@ pub trait SpaceViewClass: Send + Sync { /// Controls how likely this space view will get a large tile in the ui. fn layout_priority(&self) -> SpaceViewClassLayoutPriority; - /// Determines the default time range for this space view class. - // TODO(#4194): This should be generalized to allow arbitrary property defaults. - fn default_visible_time_range(&self) -> VisibleTimeRange { - VisibleTimeRange::EMPTY.clone() + /// Default query range for this space view. + fn default_query_range(&self) -> QueryRange { + QueryRange::LatestAt } /// Determines a suitable origin given the provided set of entities. diff --git a/crates/re_viewer_context/src/space_view/view_query.rs b/crates/re_viewer_context/src/space_view/view_query.rs index 98c3ef7dc4a9..30bc8568001d 100644 --- a/crates/re_viewer_context/src/space_view/view_query.rs +++ b/crates/re_viewer_context/src/space_view/view_query.rs @@ -3,15 +3,16 @@ use std::collections::BTreeMap; use itertools::Itertools; use nohash_hasher::IntMap; use once_cell::sync::Lazy; +use smallvec::SmallVec; use re_data_store::LatestAtQuery; use re_entity_db::{EntityPath, EntityProperties, EntityPropertiesComponent, TimeInt, Timeline}; use re_log_types::StoreKind; use re_types::ComponentName; -use smallvec::SmallVec; use crate::{ - DataResultTree, SpaceViewHighlights, SpaceViewId, ViewSystemIdentifier, ViewerContext, + DataResultTree, QueryRange, SpaceViewHighlights, SpaceViewId, ViewSystemIdentifier, + ViewerContext, }; /// Path to a specific entity in a specific store used for overrides. @@ -62,6 +63,9 @@ pub struct PropertyOverrides { /// `EntityPath` in the Blueprint store where updated overrides should be written back /// for properties that apply to the individual entity only. pub individual_override_path: EntityPath, + + /// What range is queried on the data store. + pub query_range: QueryRange, } pub type SmallVisualizerSet = SmallVec<[ViewSystemIdentifier; 4]>; @@ -70,9 +74,6 @@ pub type SmallVisualizerSet = SmallVec<[ViewSystemIdentifier; 4]>; /// /// It contains everything necessary to properly use this data in the context of the /// `ViewSystem`s that it is a part of. -/// -/// In the future `accumulated_properties` will be replaced by a `StoreView` that contains -/// the relevant data overrides for the given query. #[derive(Clone, Debug, PartialEq)] pub struct DataResult { /// Where to retrieve the data from. @@ -332,14 +333,6 @@ impl DataResult { .map(|c| c.value) } - #[inline] - pub fn lookup_override_or_default( - &self, - ctx: &ViewerContext<'_>, - ) -> C { - self.lookup_override(ctx).unwrap_or_default() - } - /// Returns from which entity path an override originates from. /// /// Returns None if there was no override at all. @@ -391,9 +384,18 @@ impl DataResult { // TODO(andreas): Should the result be cached, this might be a very common operation? #[inline] pub fn is_visible(&self, ctx: &ViewerContext<'_>) -> bool { - self.lookup_override_or_default::(ctx) + self.lookup_override::(ctx) + .unwrap_or_default() .0 } + + /// Returns the query range for this data result. + pub fn query_range(&self) -> &QueryRange { + const DEFAULT_RANGE: QueryRange = QueryRange::LatestAt; + self.property_overrides + .as_ref() + .map_or(&DEFAULT_RANGE, |p| &p.query_range) + } } pub type PerSystemDataResults<'a> = BTreeMap>; diff --git a/docs/content/reference/types/views/spatial2d_view.md b/docs/content/reference/types/views/spatial2d_view.md index 065e19d4996d..c55daa1e93a8 100644 --- a/docs/content/reference/types/views/spatial2d_view.md +++ b/docs/content/reference/types/views/spatial2d_view.md @@ -15,6 +15,21 @@ Configuration for the background of a view. Controls the visual bounds of a 2D space view. * visual_bounds: The visible parts of a 2D space view, in the coordinate space of the scene. +### `VisibleTimeRange` +Configures what range of the timeline is shown on a view. + +Whenever no visual time range applies, queries are done with "latest at" semantics. +This means that the view will, starting from the time cursor position, +query the latest data available for each component type. + +The default visual time range depends on the type of view this property applies to: +- For time series views, the default is to show the entire timeline. +- For any other view, the default is to apply latest-at semantics. + +The visual time range can be overridden also individually per entity. + +* sequence: The range of time to show for timelines based on sequence numbers. +* time: The range of time to show for timelines based on time. ## Links * 🐍 [Python API docs for `Spatial2DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial2DView) diff --git a/docs/content/reference/types/views/spatial3d_view.md b/docs/content/reference/types/views/spatial3d_view.md index c883a6c85ea8..351a1e71233a 100644 --- a/docs/content/reference/types/views/spatial3d_view.md +++ b/docs/content/reference/types/views/spatial3d_view.md @@ -11,6 +11,21 @@ Configuration for the background of a view. * kind: The type of the background. Defaults to BackgroundKind.GradientDark. * color: Color used for BackgroundKind.SolidColor. +### `VisibleTimeRange` +Configures what range of the timeline is shown on a view. + +Whenever no visual time range applies, queries are done with "latest at" semantics. +This means that the view will, starting from the time cursor position, +query the latest data available for each component type. + +The default visual time range depends on the type of view this property applies to: +- For time series views, the default is to show the entire timeline. +- For any other view, the default is to apply latest-at semantics. + +The visual time range can be overridden also individually per entity. + +* sequence: The range of time to show for timelines based on sequence numbers. +* time: The range of time to show for timelines based on time. ## Links * 🐍 [Python API docs for `Spatial3DView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.Spatial3DView) diff --git a/docs/content/reference/types/views/time_series_view.md b/docs/content/reference/types/views/time_series_view.md index 5570bcf9e3cc..96db0d248fc8 100644 --- a/docs/content/reference/types/views/time_series_view.md +++ b/docs/content/reference/types/views/time_series_view.md @@ -16,6 +16,21 @@ Configuration for the legend of a plot. * corner: To what corner the legend is aligned. * visible: Whether the legend is shown at all. +### `VisibleTimeRange` +Configures what range of the timeline is shown on a view. + +Whenever no visual time range applies, queries are done with "latest at" semantics. +This means that the view will, starting from the time cursor position, +query the latest data available for each component type. + +The default visual time range depends on the type of view this property applies to: +- For time series views, the default is to show the entire timeline. +- For any other view, the default is to apply latest-at semantics. + +The visual time range can be overridden also individually per entity. + +* sequence: The range of time to show for timelines based on sequence numbers. +* time: The range of time to show for timelines based on time. ## Links * 🐍 [Python API docs for `TimeSeriesView`](https://ref.rerun.io/docs/python/stable/common/blueprint_views#rerun.blueprint.views.TimeSeriesView) diff --git a/rerun_cpp/src/rerun/blueprint/archetypes.hpp b/rerun_cpp/src/rerun/blueprint/archetypes.hpp index b9d8de9e0b21..c3f26abe3185 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes.hpp @@ -10,4 +10,5 @@ #include "blueprint/archetypes/space_view_blueprint.hpp" #include "blueprint/archetypes/space_view_contents.hpp" #include "blueprint/archetypes/viewport_blueprint.hpp" +#include "blueprint/archetypes/visible_time_range.hpp" #include "blueprint/archetypes/visual_bounds.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes index 5b5e203daeab..a6bc694440b2 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/archetypes/.gitattributes @@ -17,5 +17,7 @@ space_view_contents.cpp linguist-generated=true space_view_contents.hpp linguist-generated=true viewport_blueprint.cpp linguist-generated=true viewport_blueprint.hpp linguist-generated=true +visible_time_range.cpp linguist-generated=true +visible_time_range.hpp linguist-generated=true visual_bounds.cpp linguist-generated=true visual_bounds.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_range.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_range.cpp new file mode 100644 index 000000000000..165ba5922fe6 --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_range.cpp @@ -0,0 +1,38 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visible_time_range.fbs". + +#include "visible_time_range.hpp" + +#include "../../collection_adapter_builtins.hpp" + +namespace rerun::blueprint::archetypes {} + +namespace rerun { + + Result> AsComponents::serialize( + const blueprint::archetypes::VisibleTimeRange& archetype + ) { + using namespace blueprint::archetypes; + std::vector cells; + cells.reserve(3); + + if (archetype.sequence.has_value()) { + auto result = DataCell::from_loggable(archetype.sequence.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.time.has_value()) { + auto result = DataCell::from_loggable(archetype.time.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + { + auto indicator = VisibleTimeRange::IndicatorComponent(); + auto result = DataCell::from_loggable(indicator); + RR_RETURN_NOT_OK(result.error); + cells.emplace_back(std::move(result.value)); + } + + return cells; + } +} // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_range.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_range.hpp new file mode 100644 index 000000000000..039d98a2358f --- /dev/null +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visible_time_range.hpp @@ -0,0 +1,81 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visible_time_range.fbs". + +#pragma once + +#include "../../blueprint/components/visible_time_range_sequence.hpp" +#include "../../blueprint/components/visible_time_range_time.hpp" +#include "../../collection.hpp" +#include "../../compiler_utils.hpp" +#include "../../data_cell.hpp" +#include "../../indicator_component.hpp" +#include "../../result.hpp" + +#include +#include +#include +#include + +namespace rerun::blueprint::archetypes { + /// **Archetype**: Configures what range of the timeline is shown on a view. + /// + /// Whenever no visual time range applies, queries are done with "latest at" semantics. + /// This means that the view will, starting from the time cursor position, + /// query the latest data available for each component type. + /// + /// The default visual time range depends on the type of view this property applies to: + /// - For time series views, the default is to show the entire timeline. + /// - For any other view, the default is to apply latest-at semantics. + /// + /// The visual time range can be overridden also individually per entity. + struct VisibleTimeRange { + /// The range of time to show for timelines based on sequence numbers. + std::optional sequence; + + /// The range of time to show for timelines based on time. + std::optional time; + + public: + static constexpr const char IndicatorComponentName[] = + "rerun.blueprint.components.VisibleTimeRangeIndicator"; + + /// Indicator component, used to identify the archetype when converting to a list of components. + using IndicatorComponent = rerun::components::IndicatorComponent; + + public: + VisibleTimeRange() = default; + VisibleTimeRange(VisibleTimeRange&& other) = default; + + /// The range of time to show for timelines based on sequence numbers. + VisibleTimeRange with_sequence( + rerun::blueprint::components::VisibleTimeRangeSequence _sequence + ) && { + sequence = std::move(_sequence); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// The range of time to show for timelines based on time. + VisibleTimeRange with_time(rerun::blueprint::components::VisibleTimeRangeTime _time) && { + time = std::move(_time); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + }; + +} // namespace rerun::blueprint::archetypes + +namespace rerun { + /// \private + template + struct AsComponents; + + /// \private + template <> + struct AsComponents { + /// Serialize all set component batches. + static Result> serialize( + const blueprint::archetypes::VisibleTimeRange& archetype + ); + }; +} // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index 8a2e7f0e2db0..d769547b059f 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -16,6 +16,7 @@ Background, PlotLegend, ScalarAxis, + VisibleTimeRange, VisualBounds, ) from .components import ( @@ -24,6 +25,7 @@ LockRangeDuringZoom, ) from .containers import Grid, Horizontal, Tabs, Vertical +from .datatypes import VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind from .views import ( BarChartView, Spatial2DView, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes index 4b50b7734d14..d5870692f061 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/.gitattributes @@ -10,4 +10,5 @@ scalar_axis.py linguist-generated=true space_view_blueprint.py linguist-generated=true space_view_contents.py linguist-generated=true viewport_blueprint.py linguist-generated=true +visible_time_range.py linguist-generated=true visual_bounds.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py index 45f5321955ab..2b35827d41c8 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/__init__.py @@ -10,6 +10,7 @@ from .space_view_blueprint import SpaceViewBlueprint from .space_view_contents import SpaceViewContents from .viewport_blueprint import ViewportBlueprint +from .visible_time_range import VisibleTimeRange from .visual_bounds import VisualBounds __all__ = [ @@ -21,5 +22,6 @@ "SpaceViewBlueprint", "SpaceViewContents", "ViewportBlueprint", + "VisibleTimeRange", "VisualBounds", ] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_range.py new file mode 100644 index 000000000000..4a09cf0aaf36 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_range.py @@ -0,0 +1,93 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/blueprint/archetypes/visible_time_range.fbs". + +# You can extend this class by creating a "VisibleTimeRangeExt" class in "visible_time_range_ext.py". + +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from ..._baseclasses import Archetype +from ...blueprint import components as blueprint_components +from ...blueprint import datatypes as blueprint_datatypes +from ...error_utils import catch_and_log_exceptions + +__all__ = ["VisibleTimeRange"] + + +@define(str=False, repr=False, init=False) +class VisibleTimeRange(Archetype): + """ + **Archetype**: Configures what range of the timeline is shown on a view. + + Whenever no visual time range applies, queries are done with "latest at" semantics. + This means that the view will, starting from the time cursor position, + query the latest data available for each component type. + + The default visual time range depends on the type of view this property applies to: + - For time series views, the default is to show the entire timeline. + - For any other view, the default is to apply latest-at semantics. + + The visual time range can be overridden also individually per entity. + """ + + def __init__( + self: Any, + *, + sequence: blueprint_datatypes.VisibleTimeRangeLike | None = None, + time: blueprint_datatypes.VisibleTimeRangeLike | None = None, + ): + """ + Create a new instance of the VisibleTimeRange archetype. + + Parameters + ---------- + sequence: + The range of time to show for timelines based on sequence numbers. + time: + The range of time to show for timelines based on time. + + """ + + # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py + with catch_and_log_exceptions(context=self.__class__.__name__): + self.__attrs_init__(sequence=sequence, time=time) + return + self.__attrs_clear__() + + def __attrs_clear__(self) -> None: + """Convenience method for calling `__attrs_init__` with all `None`s.""" + self.__attrs_init__( + sequence=None, # type: ignore[arg-type] + time=None, # type: ignore[arg-type] + ) + + @classmethod + def _clear(cls) -> VisibleTimeRange: + """Produce an empty VisibleTimeRange, bypassing `__init__`.""" + inst = cls.__new__(cls) + inst.__attrs_clear__() + return inst + + sequence: blueprint_components.VisibleTimeRangeSequenceBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.VisibleTimeRangeSequenceBatch._optional, # type: ignore[misc] + ) + # The range of time to show for timelines based on sequence numbers. + # + # (Docstring intentionally commented out to hide this field from the docs) + + time: blueprint_components.VisibleTimeRangeTimeBatch | None = field( + metadata={"component": "optional"}, + default=None, + converter=blueprint_components.VisibleTimeRangeTimeBatch._optional, # type: ignore[misc] + ) + # The range of time to show for timelines based on time. + # + # (Docstring intentionally commented out to hide this field from the docs) + + __str__ = Archetype.__str__ + __repr__ = Archetype.__repr__ # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py index fa065d25be70..c527278b1b63 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial2d_view.py @@ -29,6 +29,7 @@ def __init__( | blueprint_components.BackgroundKindLike | None = None, visual_bounds: blueprint_archetypes.VisualBounds | None = None, + time_range: blueprint_archetypes.VisibleTimeRange | None = None, ) -> None: """ Construct a blueprint for a new Spatial2DView view. @@ -55,6 +56,8 @@ def __init__( Everything within these bounds are guaranteed to be visible. Somethings outside of these bounds may also be visible due to letterboxing. + time_range: + Configures the range on the timeline shown by this view (unless specified differently per entity). """ @@ -69,6 +72,11 @@ def __init__( visual_bounds = blueprint_archetypes.VisualBounds(visual_bounds) properties["VisualBounds"] = visual_bounds + if time_range is not None: + if not isinstance(time_range, blueprint_archetypes.VisibleTimeRange): + time_range = blueprint_archetypes.VisibleTimeRange(time_range) + properties["VisibleTimeRange"] = time_range + super().__init__( class_identifier="2D", origin=origin, contents=contents, name=name, visible=visible, properties=properties ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py index 3aa3213a2c03..a0a2b6ed385c 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/spatial3d_view.py @@ -60,6 +60,7 @@ def __init__( | datatypes.Rgba32Like | blueprint_components.BackgroundKindLike | None = None, + time_range: blueprint_archetypes.VisibleTimeRange | None = None, ) -> None: """ Construct a blueprint for a new Spatial3DView view. @@ -81,6 +82,8 @@ def __init__( Defaults to true if not specified. background: Configuration for the background of the space view. + time_range: + Configures the range on the timeline shown by this view (unless specified differently per entity). """ @@ -90,6 +93,11 @@ def __init__( background = blueprint_archetypes.Background(background) properties["Background"] = background + if time_range is not None: + if not isinstance(time_range, blueprint_archetypes.VisibleTimeRange): + time_range = blueprint_archetypes.VisibleTimeRange(time_range) + properties["VisibleTimeRange"] = time_range + super().__init__( class_identifier="3D", origin=origin, contents=contents, name=name, visible=visible, properties=properties ) diff --git a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py index 37b42559b0a0..a741f8d67670 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/views/time_series_view.py @@ -25,6 +25,7 @@ def __init__( visible: blueprint_components.VisibleLike | None = None, axis_y: blueprint_archetypes.ScalarAxis | None = None, plot_legend: blueprint_archetypes.PlotLegend | blueprint_components.Corner2D | None = None, + time_range: blueprint_archetypes.VisibleTimeRange | None = None, ) -> None: """ Construct a blueprint for a new TimeSeriesView view. @@ -48,6 +49,8 @@ def __init__( Configures the vertical axis of the plot. plot_legend: Configures the legend of the plot. + time_range: + Configures the time range the plot covers (unless specified differently per entity). """ @@ -62,6 +65,11 @@ def __init__( plot_legend = blueprint_archetypes.PlotLegend(plot_legend) properties["PlotLegend"] = plot_legend + if time_range is not None: + if not isinstance(time_range, blueprint_archetypes.VisibleTimeRange): + time_range = blueprint_archetypes.VisibleTimeRange(time_range) + properties["VisibleTimeRange"] = time_range + super().__init__( class_identifier="TimeSeries", origin=origin, From c672f980d296bc512cd424fda19f163b6f6b54b4 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Tue, 30 Apr 2024 13:32:39 +0200 Subject: [PATCH 395/508] Add some static data to the store dump test suite (#6167) I cannot reproduce https://github.com/rerun-io/rerun/issues/6094, see https://github.com/rerun-io/rerun/issues/6094#issuecomment-2084709242: > I actually cannot repro this. I tried: > - Saving entire timeline, `0.15.1` > - Saving time selection, `0.15.1` > - Saving entire timeline, `main` > - Saving time selection, `main` For now the best I can think of is to add some static data to the test suite and call it a day... ~Marking as do not merge until the situation is clarified.~ - Closes https://github.com/rerun-io/rerun/issues/6094 --- crates/re_data_store/tests/dump.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/re_data_store/tests/dump.rs b/crates/re_data_store/tests/dump.rs index 00f1824f4f46..2db97deda2d8 100644 --- a/crates/re_data_store/tests/dump.rs +++ b/crates/re_data_store/tests/dump.rs @@ -8,7 +8,7 @@ use re_data_store::{ }; use re_log_types::{ build_frame_nr, build_log_time, example_components::MyIndex, DataRow, DataTable, EntityPath, - RowId, TableId, + RowId, TableId, TimePoint, }; use re_types::datagen::{build_some_colors, build_some_positions2d}; @@ -269,6 +269,7 @@ fn data_store_dump_filtered_impl(store1: &mut DataStore, store2: &mut DataStore) fn create_insert_table(entity_path: impl Into) -> DataTable { let entity_path = entity_path.into(); + let timeless = TimePoint::default(); let frame1 = TimeInt::new_temporal(1); let frame2 = TimeInt::new_temporal(2); let frame3 = TimeInt::new_temporal(3); @@ -282,7 +283,7 @@ fn create_insert_table(entity_path: impl Into) -> DataTable { let positions2 = build_some_positions2d(3); let row2 = test_row!(entity_path @ [ build_frame_nr(frame2), - ] => [instances1, positions2]); + ] => [instances1, positions2.clone()]); let positions3 = build_some_positions2d(10); let row3 = test_row!(entity_path @ [ @@ -292,9 +293,11 @@ fn create_insert_table(entity_path: impl Into) -> DataTable { let colors4 = build_some_colors(5); let row4 = test_row!(entity_path @ [ build_frame_nr(frame4), - ] => [colors4]); + ] => [colors4.clone()]); - let mut table = DataTable::from_rows(TableId::new(), [row1, row2, row3, row4]); + let row0 = test_row!(entity_path @ timeless => [positions2, colors4]); + + let mut table = DataTable::from_rows(TableId::new(), [row0, row1, row2, row3, row4]); table.compute_all_size_bytes(); table From 0822dc6c8538b2f4e18fee69cf44ae1cdb88429b Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 30 Apr 2024 13:58:43 +0200 Subject: [PATCH 396/508] Rename AABB2D to Range2D (#6166) ### What * Closes https://github.com/rerun-io/rerun/issues/6158 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6166?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6166?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6166) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../latest_at/to_archetype/visual_bounds.rs | 8 +- .../src/space_view_2d.rs | 10 +- crates/re_space_view_spatial/src/ui_2d.rs | 10 +- .../blueprint/archetypes/visual_bounds.fbs | 2 +- .../re_types/definitions/rerun/components.fbs | 2 +- .../components/{aabb2d.fbs => range2d.fbs} | 6 +- .../re_types/definitions/rerun/datatypes.fbs | 2 +- .../datatypes/{aabb2d.fbs => range2d.fbs} | 10 +- .../src/blueprint/archetypes/visual_bounds.rs | 31 ++-- crates/re_types/src/components/.gitattributes | 2 +- crates/re_types/src/components/aabb2d_ext.rs | 11 -- crates/re_types/src/components/mod.rs | 6 +- crates/re_types/src/components/range1d_ext.rs | 7 + .../src/components/{aabb2d.rs => range2d.rs} | 48 +++--- crates/re_types/src/components/range2d_ext.rs | 8 + crates/re_types/src/datatypes/.gitattributes | 2 +- crates/re_types/src/datatypes/aabb2d_ext.rs | 21 --- crates/re_types/src/datatypes/mod.rs | 7 +- crates/re_types/src/datatypes/range1d_ext.rs | 18 +++ .../src/datatypes/{aabb2d.rs => range2d.rs} | 150 +++++++++--------- crates/re_types/src/datatypes/range2d_ext.rs | 18 +++ docs/content/reference/types/components.md | 2 +- .../reference/types/components/.gitattributes | 2 +- .../reference/types/components/aabb2d.md | 16 -- .../reference/types/components/range2d.md | 16 ++ docs/content/reference/types/datatypes.md | 2 +- .../reference/types/datatypes/.gitattributes | 2 +- .../reference/types/datatypes/aabb2d.md | 20 --- .../reference/types/datatypes/range1d.md | 1 + .../reference/types/datatypes/range2d.md | 20 +++ .../reference/types/datatypes/vec2d.md | 1 - .../reference/types/views/spatial2d_view.md | 2 +- docs/snippets/all/extra_values.py | 2 +- docs/snippets/all/line_segments2d_simple.py | 2 +- docs/snippets/all/line_strip2d_batch.py | 2 +- docs/snippets/all/line_strip2d_simple.py | 2 +- docs/snippets/all/point2d_random.py | 2 +- docs/snippets/all/point2d_simple.py | 2 +- .../blueprint/archetypes/visual_bounds.cpp | 4 +- .../blueprint/archetypes/visual_bounds.hpp | 8 +- rerun_cpp/src/rerun/components.hpp | 2 +- rerun_cpp/src/rerun/components/.gitattributes | 2 +- rerun_cpp/src/rerun/components/aabb2d.hpp | 54 ------- rerun_cpp/src/rerun/components/range2d.hpp | 57 +++++++ rerun_cpp/src/rerun/datatypes.hpp | 2 +- rerun_cpp/src/rerun/datatypes/.gitattributes | 4 +- .../datatypes/{aabb2d.cpp => range2d.cpp} | 30 ++-- .../datatypes/{aabb2d.hpp => range2d.hpp} | 26 +-- .../rerun/archetypes/line_strips2d.py | 2 +- .../rerun_sdk/rerun/archetypes/points2d.py | 2 +- .../blueprint/archetypes/visual_bounds.py | 6 +- .../blueprint/archetypes/visual_bounds_ext.py | 16 +- .../rerun_sdk/rerun/components/.gitattributes | 2 +- .../rerun_sdk/rerun/components/__init__.py | 8 +- rerun_py/rerun_sdk/rerun/components/aabb2d.py | 29 ---- .../rerun_sdk/rerun/components/aabb2d_ext.py | 31 ---- .../rerun_sdk/rerun/components/range2d.py | 29 ++++ .../rerun_sdk/rerun/components/range2d_ext.py | 29 ++++ .../rerun_sdk/rerun/datatypes/.gitattributes | 2 +- .../rerun_sdk/rerun/datatypes/__init__.py | 12 +- rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py | 111 ------------- rerun_py/rerun_sdk/rerun/datatypes/range2d.py | 111 +++++++++++++ 62 files changed, 542 insertions(+), 512 deletions(-) rename crates/re_types/definitions/rerun/components/{aabb2d.fbs => range2d.fbs} (76%) rename crates/re_types/definitions/rerun/datatypes/{aabb2d.fbs => range2d.fbs} (63%) delete mode 100644 crates/re_types/src/components/aabb2d_ext.rs rename crates/re_types/src/components/{aabb2d.rs => range2d.rs} (71%) create mode 100644 crates/re_types/src/components/range2d_ext.rs delete mode 100644 crates/re_types/src/datatypes/aabb2d_ext.rs create mode 100644 crates/re_types/src/datatypes/range1d_ext.rs rename crates/re_types/src/datatypes/{aabb2d.rs => range2d.rs} (80%) create mode 100644 crates/re_types/src/datatypes/range2d_ext.rs delete mode 100644 docs/content/reference/types/components/aabb2d.md create mode 100644 docs/content/reference/types/components/range2d.md delete mode 100644 docs/content/reference/types/datatypes/aabb2d.md create mode 100644 docs/content/reference/types/datatypes/range2d.md delete mode 100644 rerun_cpp/src/rerun/components/aabb2d.hpp create mode 100644 rerun_cpp/src/rerun/components/range2d.hpp rename rerun_cpp/src/rerun/datatypes/{aabb2d.cpp => range2d.cpp} (68%) rename rerun_cpp/src/rerun/datatypes/{aabb2d.hpp => range2d.hpp} (56%) delete mode 100644 rerun_py/rerun_sdk/rerun/components/aabb2d.py delete mode 100644 rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py create mode 100644 rerun_py/rerun_sdk/rerun/components/range2d.py create mode 100644 rerun_py/rerun_sdk/rerun/components/range2d_ext.py delete mode 100644 rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py create mode 100644 rerun_py/rerun_sdk/rerun/datatypes/range2d.py diff --git a/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs b/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs index 49d60ad0b78e..e48c84259e32 100644 --- a/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs +++ b/crates/re_query/src/latest_at/to_archetype/visual_bounds.rs @@ -21,9 +21,9 @@ impl crate::ToArchetype for Lates // --- Recommended/Optional --- - use re_types::components::AABB2D; - let visual_bounds = if let Some(visual_bounds) = self.get(::name()) { - match visual_bounds.to_dense::(resolver) { + use re_types::components::Range2D; + let range2d = if let Some(range2d) = self.get(::name()) { + match range2d.to_dense::(resolver) { PromiseResult::Pending => return PromiseResult::Pending, PromiseResult::Error(promise_err) => return PromiseResult::Error(promise_err), PromiseResult::Ready(query_res) => match query_res { @@ -37,7 +37,7 @@ impl crate::ToArchetype for Lates // --- - let arch = re_types::blueprint::archetypes::VisualBounds { visual_bounds }; + let arch = re_types::blueprint::archetypes::VisualBounds { range2d }; PromiseResult::Ready(Ok(arch)) } diff --git a/crates/re_space_view_spatial/src/space_view_2d.rs b/crates/re_space_view_spatial/src/space_view_2d.rs index f219d35acda3..fc0729e69f2d 100644 --- a/crates/re_space_view_spatial/src/space_view_2d.rs +++ b/crates/re_space_view_spatial/src/space_view_2d.rs @@ -287,25 +287,25 @@ impl SpaceViewClass for SpatialSpaceView2D { fn visual_bounds_ui(ctx: &ViewerContext<'_>, space_view_id: SpaceViewId, ui: &mut egui::Ui) { let tooltip = "The area guaranteed to be visible.\n\ Depending on the view's current aspect ratio the actually visible area might be larger either horizontally or vertically."; - re_space_view::edit_blueprint_component::( + re_space_view::edit_blueprint_component::( ctx, space_view_id, - |aabb: &mut Option| { + |range2d: &mut Option| { ctx.re_ui .grid_left_hand_label(ui, "Visible bounds") .on_hover_text(tooltip); ui.vertical(|ui| { ui.style_mut().wrap = Some(false); - if let Some(aabb) = aabb { - let rect = egui::Rect::from(*aabb); + if let Some(range2d) = range2d { + let rect = egui::Rect::from(*range2d); let (min, max) = (rect.min, rect.max); ui.label(format!("x [{} - {}]", format_f32(min.x), format_f32(max.x),)); ui.label(format!("y [{} - {}]", format_f32(min.y), format_f32(max.y),)); } if ui.button("Reset visible bounds").clicked() { - *aabb = None; + *range2d = None; } }); ui.end_row(); diff --git a/crates/re_space_view_spatial/src/ui_2d.rs b/crates/re_space_view_spatial/src/ui_2d.rs index e67a99dcb48c..65338734a5d3 100644 --- a/crates/re_space_view_spatial/src/ui_2d.rs +++ b/crates/re_space_view_spatial/src/ui_2d.rs @@ -120,26 +120,26 @@ fn ui_from_scene( re_space_view::edit_blueprint_component::< VisualBounds, - re_types::components::AABB2D, + re_types::components::Range2D, RectTransform, >( ctx, space_view_id, - |aabb: &mut Option| { + |range2d: &mut Option| { // Convert to a Rect - let mut rect: Rect = aabb.map_or(default_scene_rect, Rect::from); + let mut rect: Rect = range2d.map_or(default_scene_rect, Rect::from); // Apply pan and zoom based on input let ui_from_scene = update_ui_from_scene_impl(&mut rect, response, default_scene_rect); // Store back the results - *aabb = Some(rect.into()); + *range2d = Some(rect.into()); if response.double_clicked() { // Double-click to reset. // We put it last so that we reset to the value in the default blueprint // (which is not the same as `default_scene_rect`). - *aabb = None; + *range2d = None; } ui_from_scene diff --git a/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs b/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs index 4317e53fbe8e..bf25d9641188 100644 --- a/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs +++ b/crates/re_types/definitions/rerun/blueprint/archetypes/visual_bounds.fbs @@ -17,5 +17,5 @@ table VisualBounds ( /// /// Everything within these bounds are guaranteed to be visible. /// Somethings outside of these bounds may also be visible due to letterboxing. - visual_bounds: rerun.components.AABB2D ("attr.rerun.component_optional", nullable, order: 1000); + range2d: rerun.components.Range2D ("attr.rerun.component_optional", nullable, order: 1000); } diff --git a/crates/re_types/definitions/rerun/components.fbs b/crates/re_types/definitions/rerun/components.fbs index 8ee16c67e9b4..746d36eff0b0 100644 --- a/crates/re_types/definitions/rerun/components.fbs +++ b/crates/re_types/definitions/rerun/components.fbs @@ -1,4 +1,3 @@ -include "./components/aabb2d.fbs"; include "./components/annotation_context.fbs"; include "./components/blob.fbs"; include "./components/class_id.fbs"; @@ -24,6 +23,7 @@ include "./components/position2d.fbs"; include "./components/position3d.fbs"; include "./components/radius.fbs"; include "./components/range1d.fbs"; +include "./components/range2d.fbs"; include "./components/resolution.fbs"; include "./components/rotation3d.fbs"; include "./components/scalar_scattering.fbs"; diff --git a/crates/re_types/definitions/rerun/components/aabb2d.fbs b/crates/re_types/definitions/rerun/components/range2d.fbs similarity index 76% rename from crates/re_types/definitions/rerun/components/aabb2d.fbs rename to crates/re_types/definitions/rerun/components/range2d.fbs index 6855c9298a92..83f8f33741fd 100644 --- a/crates/re_types/definitions/rerun/components/aabb2d.fbs +++ b/crates/re_types/definitions/rerun/components/range2d.fbs @@ -3,16 +3,16 @@ include "python/attributes.fbs"; include "fbs/attributes.fbs"; include "rust/attributes.fbs"; -include "../datatypes/aabb2d.fbs"; +include "../datatypes/range2d.fbs"; namespace rerun.components; // --- /// An Axis-Aligned Bounding Box in 2D space. -struct AABB2D ( +struct Range2D ( "attr.rust.derive": "Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", "attr.rust.repr": "transparent" ) { - aabb: rerun.datatypes.AABB2D (order: 100); + range2d: rerun.datatypes.Range2D (order: 100); } diff --git a/crates/re_types/definitions/rerun/datatypes.fbs b/crates/re_types/definitions/rerun/datatypes.fbs index 23df51535ab2..ebe1ef3c634c 100644 --- a/crates/re_types/definitions/rerun/datatypes.fbs +++ b/crates/re_types/definitions/rerun/datatypes.fbs @@ -1,4 +1,3 @@ -include "./datatypes/aabb2d.fbs"; include "./datatypes/angle.fbs"; include "./datatypes/annotation_info.fbs"; include "./datatypes/bool.fbs"; @@ -15,6 +14,7 @@ include "./datatypes/material.fbs"; include "./datatypes/mesh_properties.fbs"; include "./datatypes/quaternion.fbs"; include "./datatypes/range1d.fbs"; +include "./datatypes/range2d.fbs"; include "./datatypes/rgba32.fbs"; include "./datatypes/rotation_axis_angle.fbs"; include "./datatypes/rotation3d.fbs"; diff --git a/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs b/crates/re_types/definitions/rerun/datatypes/range2d.fbs similarity index 63% rename from crates/re_types/definitions/rerun/datatypes/aabb2d.fbs rename to crates/re_types/definitions/rerun/datatypes/range2d.fbs index 2ea946feab57..afc340d21d64 100644 --- a/crates/re_types/definitions/rerun/datatypes/aabb2d.fbs +++ b/crates/re_types/definitions/rerun/datatypes/range2d.fbs @@ -11,13 +11,13 @@ namespace rerun.datatypes; // --- /// An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. -struct AABB2D ( +struct Range2D ( "attr.rust.derive": "Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", "attr.rust.repr": "C" ) { - /// The minimum bounds; usually left-top corner. - min: rerun.datatypes.Vec2D (order: 100); + /// The range of the X-axis (usually left and right bounds). + x_range: rerun.datatypes.Range1D (order: 100); - /// The maximum bounds; usually right-bottom corner. - max: rerun.datatypes.Vec2D (order: 200); + /// The range of the Y-axis (usually top and bottom bounds). + y_range: rerun.datatypes.Range1D (order: 200); } diff --git a/crates/re_types/src/blueprint/archetypes/visual_bounds.rs b/crates/re_types/src/blueprint/archetypes/visual_bounds.rs index c553273d1308..e4b3eb5961bc 100644 --- a/crates/re_types/src/blueprint/archetypes/visual_bounds.rs +++ b/crates/re_types/src/blueprint/archetypes/visual_bounds.rs @@ -29,18 +29,18 @@ pub struct VisualBounds { /// /// Everything within these bounds are guaranteed to be visible. /// Somethings outside of these bounds may also be visible due to letterboxing. - pub visual_bounds: Option, + pub range2d: Option, } impl ::re_types_core::SizeBytes for VisualBounds { #[inline] fn heap_size_bytes(&self) -> u64 { - self.visual_bounds.heap_size_bytes() + self.range2d.heap_size_bytes() } #[inline] fn is_pod() -> bool { - >::is_pod() + >::is_pod() } } @@ -51,13 +51,13 @@ static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.blueprint.components.VisualBoundsIndicator".into()]); static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = - once_cell::sync::Lazy::new(|| ["rerun.components.AABB2D".into()]); + once_cell::sync::Lazy::new(|| ["rerun.components.Range2D".into()]); static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 2usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.blueprint.components.VisualBoundsIndicator".into(), - "rerun.components.AABB2D".into(), + "rerun.components.Range2D".into(), ] }); @@ -113,16 +113,16 @@ impl ::re_types_core::Archetype for VisualBounds { .into_iter() .map(|(name, array)| (name.full_name(), array)) .collect(); - let visual_bounds = if let Some(array) = arrays_by_name.get("rerun.components.AABB2D") { - ::from_arrow_opt(&**array) - .with_context("rerun.blueprint.archetypes.VisualBounds#visual_bounds")? + let range2d = if let Some(array) = arrays_by_name.get("rerun.components.Range2D") { + ::from_arrow_opt(&**array) + .with_context("rerun.blueprint.archetypes.VisualBounds#range2d")? .into_iter() .next() .flatten() } else { None }; - Ok(Self { visual_bounds }) + Ok(Self { range2d }) } } @@ -132,7 +132,7 @@ impl ::re_types_core::AsComponents for VisualBounds { use ::re_types_core::Archetype as _; [ Some(Self::indicator()), - self.visual_bounds + self.range2d .as_ref() .map(|comp| (comp as &dyn ComponentBatch).into()), ] @@ -146,9 +146,7 @@ impl VisualBounds { /// Create a new `VisualBounds`. #[inline] pub fn new() -> Self { - Self { - visual_bounds: None, - } + Self { range2d: None } } /// The visible parts of a 2D space view, in the coordinate space of the scene. @@ -156,11 +154,8 @@ impl VisualBounds { /// Everything within these bounds are guaranteed to be visible. /// Somethings outside of these bounds may also be visible due to letterboxing. #[inline] - pub fn with_visual_bounds( - mut self, - visual_bounds: impl Into, - ) -> Self { - self.visual_bounds = Some(visual_bounds.into()); + pub fn with_range2d(mut self, range2d: impl Into) -> Self { + self.range2d = Some(range2d.into()); self } } diff --git a/crates/re_types/src/components/.gitattributes b/crates/re_types/src/components/.gitattributes index 287ee7843db7..14f400a24257 100644 --- a/crates/re_types/src/components/.gitattributes +++ b/crates/re_types/src/components/.gitattributes @@ -1,7 +1,6 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -aabb2d.rs linguist-generated=true annotation_context.rs linguist-generated=true blob.rs linguist-generated=true class_id.rs linguist-generated=true @@ -27,6 +26,7 @@ position2d.rs linguist-generated=true position3d.rs linguist-generated=true radius.rs linguist-generated=true range1d.rs linguist-generated=true +range2d.rs linguist-generated=true resolution.rs linguist-generated=true rotation3d.rs linguist-generated=true scalar.rs linguist-generated=true diff --git a/crates/re_types/src/components/aabb2d_ext.rs b/crates/re_types/src/components/aabb2d_ext.rs deleted file mode 100644 index 0367ab75bb27..000000000000 --- a/crates/re_types/src/components/aabb2d_ext.rs +++ /dev/null @@ -1,11 +0,0 @@ -use super::AABB2D; - -impl From for emath::Rect { - #[inline] - fn from(v: AABB2D) -> Self { - Self { - min: emath::pos2(v.min[0], v.min[1]), - max: emath::pos2(v.max[0], v.max[1]), - } - } -} diff --git a/crates/re_types/src/components/mod.rs b/crates/re_types/src/components/mod.rs index 6bbc7bfca394..feb97c2c2906 100644 --- a/crates/re_types/src/components/mod.rs +++ b/crates/re_types/src/components/mod.rs @@ -1,7 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -mod aabb2d; -mod aabb2d_ext; mod annotation_context; mod blob; mod blob_ext; @@ -47,6 +45,8 @@ mod radius; mod radius_ext; mod range1d; mod range1d_ext; +mod range2d; +mod range2d_ext; mod resolution; mod rotation3d; mod rotation3d_ext; @@ -70,7 +70,6 @@ mod vector3d_ext; mod view_coordinates; mod view_coordinates_ext; -pub use self::aabb2d::AABB2D; pub use self::annotation_context::AnnotationContext; pub use self::blob::Blob; pub use self::class_id::ClassId; @@ -95,6 +94,7 @@ pub use self::position2d::Position2D; pub use self::position3d::Position3D; pub use self::radius::Radius; pub use self::range1d::Range1D; +pub use self::range2d::Range2D; pub use self::resolution::Resolution; pub use self::rotation3d::Rotation3D; pub use self::scalar::Scalar; diff --git a/crates/re_types/src/components/range1d_ext.rs b/crates/re_types/src/components/range1d_ext.rs index d9c3eb153c3f..1e7e25b3cdf7 100644 --- a/crates/re_types/src/components/range1d_ext.rs +++ b/crates/re_types/src/components/range1d_ext.rs @@ -21,3 +21,10 @@ impl Range1D { self.0 .0[1] } } + +impl From for emath::Rangef { + #[inline] + fn from(range2d: Range1D) -> Self { + Self::from(range2d.0) + } +} diff --git a/crates/re_types/src/components/aabb2d.rs b/crates/re_types/src/components/range2d.rs similarity index 71% rename from crates/re_types/src/components/aabb2d.rs rename to crates/re_types/src/components/range2d.rs index fd332cff360f..c26327d80416 100644 --- a/crates/re_types/src/components/aabb2d.rs +++ b/crates/re_types/src/components/range2d.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". +// Based on "crates/re_types/definitions/rerun/components/range2d.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -25,9 +25,9 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: An Axis-Aligned Bounding Box in 2D space. #[derive(Clone, Debug, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] #[repr(transparent)] -pub struct AABB2D(pub crate::datatypes::AABB2D); +pub struct Range2D(pub crate::datatypes::Range2D); -impl ::re_types_core::SizeBytes for AABB2D { +impl ::re_types_core::SizeBytes for Range2D { #[inline] fn heap_size_bytes(&self) -> u64 { self.0.heap_size_bytes() @@ -35,40 +35,40 @@ impl ::re_types_core::SizeBytes for AABB2D { #[inline] fn is_pod() -> bool { - ::is_pod() + ::is_pod() } } -impl> From for AABB2D { +impl> From for Range2D { fn from(v: T) -> Self { Self(v.into()) } } -impl std::borrow::Borrow for AABB2D { +impl std::borrow::Borrow for Range2D { #[inline] - fn borrow(&self) -> &crate::datatypes::AABB2D { + fn borrow(&self) -> &crate::datatypes::Range2D { &self.0 } } -impl std::ops::Deref for AABB2D { - type Target = crate::datatypes::AABB2D; +impl std::ops::Deref for Range2D { + type Target = crate::datatypes::Range2D; #[inline] - fn deref(&self) -> &crate::datatypes::AABB2D { + fn deref(&self) -> &crate::datatypes::Range2D { &self.0 } } -::re_types_core::macros::impl_into_cow!(AABB2D); +::re_types_core::macros::impl_into_cow!(Range2D); -impl ::re_types_core::Loggable for AABB2D { +impl ::re_types_core::Loggable for Range2D { type Name = ::re_types_core::ComponentName; #[inline] fn name() -> Self::Name { - "rerun.components.AABB2D".into() + "rerun.components.Range2D".into() } #[allow(clippy::wildcard_imports)] @@ -76,8 +76,16 @@ impl ::re_types_core::Loggable for AABB2D { fn arrow_datatype() -> arrow2::datatypes::DataType { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ - Field::new("min", ::arrow_datatype(), false), - Field::new("max", ::arrow_datatype(), false), + Field::new( + "x_range", + ::arrow_datatype(), + false, + ), + Field::new( + "y_range", + ::arrow_datatype(), + false, + ), ])) } @@ -108,7 +116,7 @@ impl ::re_types_core::Loggable for AABB2D { }; { _ = data0_bitmap; - crate::datatypes::AABB2D::to_arrow_opt(data0)? + crate::datatypes::Range2D::to_arrow_opt(data0)? } }) } @@ -122,13 +130,13 @@ impl ::re_types_core::Loggable for AABB2D { { use ::re_types_core::{Loggable as _, ResultExt as _}; use arrow2::{array::*, buffer::*, datatypes::*}; - Ok(crate::datatypes::AABB2D::from_arrow_opt(arrow_data) - .with_context("rerun.components.AABB2D#aabb")? + Ok(crate::datatypes::Range2D::from_arrow_opt(arrow_data) + .with_context("rerun.components.Range2D#range2d")? .into_iter() .map(|v| v.ok_or_else(DeserializationError::missing_data)) .map(|res| res.map(|v| Some(Self(v)))) .collect::>>>() - .with_context("rerun.components.AABB2D#aabb") - .with_context("rerun.components.AABB2D")?) + .with_context("rerun.components.Range2D#range2d") + .with_context("rerun.components.Range2D")?) } } diff --git a/crates/re_types/src/components/range2d_ext.rs b/crates/re_types/src/components/range2d_ext.rs new file mode 100644 index 000000000000..eae3cfe20fe3 --- /dev/null +++ b/crates/re_types/src/components/range2d_ext.rs @@ -0,0 +1,8 @@ +use super::Range2D; + +impl From for emath::Rect { + #[inline] + fn from(v: Range2D) -> Self { + Self::from(v.0) + } +} diff --git a/crates/re_types/src/datatypes/.gitattributes b/crates/re_types/src/datatypes/.gitattributes index f14598e3fbb4..2b8f343bbb99 100644 --- a/crates/re_types/src/datatypes/.gitattributes +++ b/crates/re_types/src/datatypes/.gitattributes @@ -1,7 +1,6 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -aabb2d.rs linguist-generated=true angle.rs linguist-generated=true annotation_info.rs linguist-generated=true bool.rs linguist-generated=true @@ -17,6 +16,7 @@ mesh_properties.rs linguist-generated=true mod.rs linguist-generated=true quaternion.rs linguist-generated=true range1d.rs linguist-generated=true +range2d.rs linguist-generated=true rgba32.rs linguist-generated=true rotation3d.rs linguist-generated=true rotation_axis_angle.rs linguist-generated=true diff --git a/crates/re_types/src/datatypes/aabb2d_ext.rs b/crates/re_types/src/datatypes/aabb2d_ext.rs deleted file mode 100644 index 92c929d7cf55..000000000000 --- a/crates/re_types/src/datatypes/aabb2d_ext.rs +++ /dev/null @@ -1,21 +0,0 @@ -use super::AABB2D; - -impl From for AABB2D { - #[inline] - fn from(v: emath::Rect) -> Self { - Self { - min: [v.min.x, v.min.y].into(), - max: [v.max.x, v.max.y].into(), - } - } -} - -impl From for emath::Rect { - #[inline] - fn from(v: AABB2D) -> Self { - Self { - min: emath::pos2(v.min[0], v.min[1]), - max: emath::pos2(v.max[0], v.max[1]), - } - } -} diff --git a/crates/re_types/src/datatypes/mod.rs b/crates/re_types/src/datatypes/mod.rs index 6337fb92fb98..07669a84ecc1 100644 --- a/crates/re_types/src/datatypes/mod.rs +++ b/crates/re_types/src/datatypes/mod.rs @@ -1,7 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -mod aabb2d; -mod aabb2d_ext; mod angle; mod angle_ext; mod annotation_info; @@ -28,6 +26,9 @@ mod mesh_properties_ext; mod quaternion; mod quaternion_ext; mod range1d; +mod range1d_ext; +mod range2d; +mod range2d_ext; mod rgba32; mod rgba32_ext; mod rotation3d; @@ -63,7 +64,6 @@ mod vec3d_ext; mod vec4d; mod vec4d_ext; -pub use self::aabb2d::AABB2D; pub use self::angle::Angle; pub use self::annotation_info::AnnotationInfo; pub use self::bool::Bool; @@ -78,6 +78,7 @@ pub use self::material::Material; pub use self::mesh_properties::MeshProperties; pub use self::quaternion::Quaternion; pub use self::range1d::Range1D; +pub use self::range2d::Range2D; pub use self::rgba32::Rgba32; pub use self::rotation3d::Rotation3D; pub use self::rotation_axis_angle::RotationAxisAngle; diff --git a/crates/re_types/src/datatypes/range1d_ext.rs b/crates/re_types/src/datatypes/range1d_ext.rs new file mode 100644 index 000000000000..c0c1825b61cb --- /dev/null +++ b/crates/re_types/src/datatypes/range1d_ext.rs @@ -0,0 +1,18 @@ +use super::Range1D; + +impl From for Range1D { + #[inline] + fn from(rangef: emath::Rangef) -> Self { + Self([rangef.min as f64, rangef.max as f64]) + } +} + +impl From for emath::Rangef { + #[inline] + fn from(range1d: Range1D) -> Self { + emath::Rangef { + min: range1d.0[0] as f32, + max: range1d.0[1] as f32, + } + } +} diff --git a/crates/re_types/src/datatypes/aabb2d.rs b/crates/re_types/src/datatypes/range2d.rs similarity index 80% rename from crates/re_types/src/datatypes/aabb2d.rs rename to crates/re_types/src/datatypes/range2d.rs index 32551e4f92ea..4f5afdaebf1a 100644 --- a/crates/re_types/src/datatypes/aabb2d.rs +++ b/crates/re_types/src/datatypes/range2d.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/range2d.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -25,34 +25,34 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. #[derive(Clone, Debug, Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] #[repr(C)] -pub struct AABB2D { - /// The minimum bounds; usually left-top corner. - pub min: crate::datatypes::Vec2D, +pub struct Range2D { + /// The range of the X-axis (usually left and right bounds). + pub x_range: crate::datatypes::Range1D, - /// The maximum bounds; usually right-bottom corner. - pub max: crate::datatypes::Vec2D, + /// The range of the Y-axis (usually top and bottom bounds). + pub y_range: crate::datatypes::Range1D, } -impl ::re_types_core::SizeBytes for AABB2D { +impl ::re_types_core::SizeBytes for Range2D { #[inline] fn heap_size_bytes(&self) -> u64 { - self.min.heap_size_bytes() + self.max.heap_size_bytes() + self.x_range.heap_size_bytes() + self.y_range.heap_size_bytes() } #[inline] fn is_pod() -> bool { - ::is_pod() && ::is_pod() + ::is_pod() && ::is_pod() } } -::re_types_core::macros::impl_into_cow!(AABB2D); +::re_types_core::macros::impl_into_cow!(Range2D); -impl ::re_types_core::Loggable for AABB2D { +impl ::re_types_core::Loggable for Range2D { type Name = ::re_types_core::DatatypeName; #[inline] fn name() -> Self::Name { - "rerun.datatypes.AABB2D".into() + "rerun.datatypes.Range2D".into() } #[allow(clippy::wildcard_imports)] @@ -60,8 +60,16 @@ impl ::re_types_core::Loggable for AABB2D { fn arrow_datatype() -> arrow2::datatypes::DataType { use arrow2::datatypes::*; DataType::Struct(std::sync::Arc::new(vec![ - Field::new("min", ::arrow_datatype(), false), - Field::new("max", ::arrow_datatype(), false), + Field::new( + "x_range", + ::arrow_datatype(), + false, + ), + Field::new( + "y_range", + ::arrow_datatype(), + false, + ), ])) } @@ -87,31 +95,31 @@ impl ::re_types_core::Loggable for AABB2D { any_nones.then(|| somes.into()) }; StructArray::new( - ::arrow_datatype(), + ::arrow_datatype(), vec![ { - let (somes, min): (Vec<_>, Vec<_>) = data + let (somes, x_range): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum.as_ref().map(|datum| { - let Self { min, .. } = &**datum; - min.clone() + let Self { x_range, .. } = &**datum; + x_range.clone() }); (datum.is_some(), datum) }) .unzip(); - let min_bitmap: Option = { + let x_range_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; { use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; - let min_inner_data: Vec<_> = min + let x_range_inner_data: Vec<_> = x_range .iter() .map(|datum| { datum .map(|datum| { - let crate::datatypes::Vec2D(data0) = datum; + let crate::datatypes::Range1D(data0) = datum; data0 }) .unwrap_or_default() @@ -119,8 +127,8 @@ impl ::re_types_core::Loggable for AABB2D { .flatten() .map(Some) .collect(); - let min_inner_bitmap: Option = - min_bitmap.as_ref().map(|bitmap| { + let x_range_inner_bitmap: Option = + x_range_bitmap.as_ref().map(|bitmap| { bitmap .iter() .map(|i| std::iter::repeat(i).take(2usize)) @@ -132,48 +140,48 @@ impl ::re_types_core::Loggable for AABB2D { DataType::FixedSizeList( std::sync::Arc::new(Field::new( "item", - DataType::Float32, + DataType::Float64, false, )), 2usize, ), PrimitiveArray::new( - DataType::Float32, - min_inner_data + DataType::Float64, + x_range_inner_data .into_iter() .map(|v| v.unwrap_or_default()) .collect(), - min_inner_bitmap, + x_range_inner_bitmap, ) .boxed(), - min_bitmap, + x_range_bitmap, ) .boxed() } }, { - let (somes, max): (Vec<_>, Vec<_>) = data + let (somes, y_range): (Vec<_>, Vec<_>) = data .iter() .map(|datum| { let datum = datum.as_ref().map(|datum| { - let Self { max, .. } = &**datum; - max.clone() + let Self { y_range, .. } = &**datum; + y_range.clone() }); (datum.is_some(), datum) }) .unzip(); - let max_bitmap: Option = { + let y_range_bitmap: Option = { let any_nones = somes.iter().any(|some| !*some); any_nones.then(|| somes.into()) }; { use arrow2::{buffer::Buffer, offset::OffsetsBuffer}; - let max_inner_data: Vec<_> = max + let y_range_inner_data: Vec<_> = y_range .iter() .map(|datum| { datum .map(|datum| { - let crate::datatypes::Vec2D(data0) = datum; + let crate::datatypes::Range1D(data0) = datum; data0 }) .unwrap_or_default() @@ -181,8 +189,8 @@ impl ::re_types_core::Loggable for AABB2D { .flatten() .map(Some) .collect(); - let max_inner_bitmap: Option = - max_bitmap.as_ref().map(|bitmap| { + let y_range_inner_bitmap: Option = + y_range_bitmap.as_ref().map(|bitmap| { bitmap .iter() .map(|i| std::iter::repeat(i).take(2usize)) @@ -194,21 +202,21 @@ impl ::re_types_core::Loggable for AABB2D { DataType::FixedSizeList( std::sync::Arc::new(Field::new( "item", - DataType::Float32, + DataType::Float64, false, )), 2usize, ), PrimitiveArray::new( - DataType::Float32, - max_inner_data + DataType::Float64, + y_range_inner_data .into_iter() .map(|v| v.unwrap_or_default()) .collect(), - max_inner_bitmap, + y_range_inner_bitmap, ) .boxed(), - max_bitmap, + y_range_bitmap, ) .boxed() } @@ -238,7 +246,7 @@ impl ::re_types_core::Loggable for AABB2D { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D")?; + .with_context("rerun.datatypes.Range2D")?; if arrow_data.is_empty() { Vec::new() } else { @@ -249,15 +257,15 @@ impl ::re_types_core::Loggable for AABB2D { .map(|field| field.name.as_str()) .zip(arrow_data_arrays) .collect(); - let min = { - if !arrays_by_name.contains_key("min") { + let x_range = { + if !arrays_by_name.contains_key("x_range") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "min", + "x_range", )) - .with_context("rerun.datatypes.AABB2D"); + .with_context("rerun.datatypes.Range2D"); } - let arrow_data = &**arrays_by_name["min"]; + let arrow_data = &**arrays_by_name["x_range"]; { let arrow_data = arrow_data .as_any() @@ -266,7 +274,7 @@ impl ::re_types_core::Loggable for AABB2D { let expected = DataType::FixedSizeList( std::sync::Arc::new(Field::new( "item", - DataType::Float32, + DataType::Float64, false, )), 2usize, @@ -274,7 +282,7 @@ impl ::re_types_core::Loggable for AABB2D { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D#min")?; + .with_context("rerun.datatypes.Range2D#x_range")?; if arrow_data.is_empty() { Vec::new() } else { @@ -285,13 +293,13 @@ impl ::re_types_core::Loggable for AABB2D { let arrow_data_inner = &**arrow_data.values(); arrow_data_inner .as_any() - .downcast_ref::() + .downcast_ref::() .ok_or_else(|| { - let expected = DataType::Float32; + let expected = DataType::Float64; let actual = arrow_data_inner.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D#min")? + .with_context("rerun.datatypes.Range2D#x_range")? .into_iter() .map(|opt| opt.copied()) .collect::>() @@ -322,7 +330,7 @@ impl ::re_types_core::Loggable for AABB2D { }) .map(|res_or_opt| { res_or_opt.map(|res_or_opt| { - res_or_opt.map(|v| crate::datatypes::Vec2D(v)) + res_or_opt.map(|v| crate::datatypes::Range1D(v)) }) }) .collect::>>>()? @@ -330,15 +338,15 @@ impl ::re_types_core::Loggable for AABB2D { .into_iter() } }; - let max = { - if !arrays_by_name.contains_key("max") { + let y_range = { + if !arrays_by_name.contains_key("y_range") { return Err(DeserializationError::missing_struct_field( Self::arrow_datatype(), - "max", + "y_range", )) - .with_context("rerun.datatypes.AABB2D"); + .with_context("rerun.datatypes.Range2D"); } - let arrow_data = &**arrays_by_name["max"]; + let arrow_data = &**arrays_by_name["y_range"]; { let arrow_data = arrow_data .as_any() @@ -347,7 +355,7 @@ impl ::re_types_core::Loggable for AABB2D { let expected = DataType::FixedSizeList( std::sync::Arc::new(Field::new( "item", - DataType::Float32, + DataType::Float64, false, )), 2usize, @@ -355,7 +363,7 @@ impl ::re_types_core::Loggable for AABB2D { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D#max")?; + .with_context("rerun.datatypes.Range2D#y_range")?; if arrow_data.is_empty() { Vec::new() } else { @@ -366,13 +374,13 @@ impl ::re_types_core::Loggable for AABB2D { let arrow_data_inner = &**arrow_data.values(); arrow_data_inner .as_any() - .downcast_ref::() + .downcast_ref::() .ok_or_else(|| { - let expected = DataType::Float32; + let expected = DataType::Float64; let actual = arrow_data_inner.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.datatypes.AABB2D#max")? + .with_context("rerun.datatypes.Range2D#y_range")? .into_iter() .map(|opt| opt.copied()) .collect::>() @@ -403,7 +411,7 @@ impl ::re_types_core::Loggable for AABB2D { }) .map(|res_or_opt| { res_or_opt.map(|res_or_opt| { - res_or_opt.map(|v| crate::datatypes::Vec2D(v)) + res_or_opt.map(|v| crate::datatypes::Range1D(v)) }) }) .collect::>>>()? @@ -412,24 +420,24 @@ impl ::re_types_core::Loggable for AABB2D { } }; arrow2::bitmap::utils::ZipValidity::new_with_validity( - ::itertools::izip!(min, max), + ::itertools::izip!(x_range, y_range), arrow_data.validity(), ) .map(|opt| { - opt.map(|(min, max)| { + opt.map(|(x_range, y_range)| { Ok(Self { - min: min + x_range: x_range .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.datatypes.AABB2D#min")?, - max: max + .with_context("rerun.datatypes.Range2D#x_range")?, + y_range: y_range .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.datatypes.AABB2D#max")?, + .with_context("rerun.datatypes.Range2D#y_range")?, }) }) .transpose() }) .collect::>>() - .with_context("rerun.datatypes.AABB2D")? + .with_context("rerun.datatypes.Range2D")? } }) } diff --git a/crates/re_types/src/datatypes/range2d_ext.rs b/crates/re_types/src/datatypes/range2d_ext.rs new file mode 100644 index 000000000000..2a6b5fcfecb6 --- /dev/null +++ b/crates/re_types/src/datatypes/range2d_ext.rs @@ -0,0 +1,18 @@ +use super::Range2D; + +impl From for Range2D { + #[inline] + fn from(rect: emath::Rect) -> Self { + Self { + x_range: rect.x_range().into(), + y_range: rect.y_range().into(), + } + } +} + +impl From for emath::Rect { + #[inline] + fn from(range2d: Range2D) -> Self { + emath::Rect::from_x_y_ranges(range2d.x_range, range2d.y_range) + } +} diff --git a/docs/content/reference/types/components.md b/docs/content/reference/types/components.md index 554e9e4cb07c..e4abbceac588 100644 --- a/docs/content/reference/types/components.md +++ b/docs/content/reference/types/components.md @@ -14,7 +14,6 @@ For more information on the relationship between **archetypes** and **components on [Entities and Components](../../concepts/entity-component.md). -* [`AABB2D`](components/aabb2d.md): An Axis-Aligned Bounding Box in 2D space. * [`AnnotationContext`](components/annotation_context.md): The `AnnotationContext` provides additional information on how to display entities. * [`Blob`](components/blob.md): A binary blob of data. * [`ClassId`](components/class_id.md): A 16-bit ID representing a type of semantic class. @@ -40,6 +39,7 @@ on [Entities and Components](../../concepts/entity-component.md). * [`Position3D`](components/position3d.md): A position in 3D space. * [`Radius`](components/radius.md): A Radius component. * [`Range1D`](components/range1d.md): A 1D range, specifying a lower and upper bound. +* [`Range2D`](components/range2d.md): An Axis-Aligned Bounding Box in 2D space. * [`Resolution`](components/resolution.md): Pixel resolution width & height, e.g. of a camera sensor. * [`Rotation3D`](components/rotation3d.md): A 3D rotation, represented either by a quaternion or a rotation around axis. * [`Scalar`](components/scalar.md): A double-precision scalar. diff --git a/docs/content/reference/types/components/.gitattributes b/docs/content/reference/types/components/.gitattributes index 6522ac09f2f0..c5a9dac0d321 100644 --- a/docs/content/reference/types/components/.gitattributes +++ b/docs/content/reference/types/components/.gitattributes @@ -1,7 +1,6 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -aabb2d.md linguist-generated=true annotation_context.md linguist-generated=true blob.md linguist-generated=true class_id.md linguist-generated=true @@ -27,6 +26,7 @@ position2d.md linguist-generated=true position3d.md linguist-generated=true radius.md linguist-generated=true range1d.md linguist-generated=true +range2d.md linguist-generated=true resolution.md linguist-generated=true rotation3d.md linguist-generated=true scalar.md linguist-generated=true diff --git a/docs/content/reference/types/components/aabb2d.md b/docs/content/reference/types/components/aabb2d.md deleted file mode 100644 index e309a3ed3216..000000000000 --- a/docs/content/reference/types/components/aabb2d.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "AABB2D" ---- - -An Axis-Aligned Bounding Box in 2D space. - -## Fields - -* aabb: [`AABB2D`](../datatypes/aabb2d.md) - -## Links - * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1AABB2D.html) - * 🐍 [Python API docs for `AABB2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.AABB2D) - * 🦀 [Rust API docs for `AABB2D`](https://docs.rs/rerun/latest/rerun/components/struct.AABB2D.html) - - diff --git a/docs/content/reference/types/components/range2d.md b/docs/content/reference/types/components/range2d.md new file mode 100644 index 000000000000..e17277fd873d --- /dev/null +++ b/docs/content/reference/types/components/range2d.md @@ -0,0 +1,16 @@ +--- +title: "Range2D" +--- + +An Axis-Aligned Bounding Box in 2D space. + +## Fields + +* range2d: [`Range2D`](../datatypes/range2d.md) + +## Links + * 🌊 [C++ API docs for `Range2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Range2D.html) + * 🐍 [Python API docs for `Range2D`](https://ref.rerun.io/docs/python/stable/common/components#rerun.components.Range2D) + * 🦀 [Rust API docs for `Range2D`](https://docs.rs/rerun/latest/rerun/components/struct.Range2D.html) + + diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index d47defada3ff..1c659f9ea3e5 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -8,7 +8,6 @@ order: 3 Data types are the lowest layer of the data model hierarchy. They are re-usable types used by the components. -* [`AABB2D`](datatypes/aabb2d.md): An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. * [`Angle`](datatypes/angle.md): Angle in either radians or degrees. * [`AnnotationInfo`](datatypes/annotation_info.md): Annotation info annotating a class id or key-point id. * [`Bool`](datatypes/bool.md): A single boolean. @@ -25,6 +24,7 @@ Data types are the lowest layer of the data model hierarchy. They are re-usable * [`MeshProperties`](datatypes/mesh_properties.md): Optional triangle indices for a mesh. * [`Quaternion`](datatypes/quaternion.md): A Quaternion represented by 4 real numbers. * [`Range1D`](datatypes/range1d.md): A 1D range, specifying a lower and upper bound. +* [`Range2D`](datatypes/range2d.md): An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. * [`Rgba32`](datatypes/rgba32.md): An RGBA color with unmultiplied/separate alpha, in sRGB gamma space with linear alpha. * [`Rotation3D`](datatypes/rotation3d.md): A 3D rotation. * [`RotationAxisAngle`](datatypes/rotation_axis_angle.md): 3D rotation represented by a rotation around a given axis. diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index cd80d78a173b..1a82697fda80 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -1,7 +1,6 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -aabb2d.md linguist-generated=true angle.md linguist-generated=true annotation_info.md linguist-generated=true bool.md linguist-generated=true @@ -18,6 +17,7 @@ material.md linguist-generated=true mesh_properties.md linguist-generated=true quaternion.md linguist-generated=true range1d.md linguist-generated=true +range2d.md linguist-generated=true rgba32.md linguist-generated=true rotation3d.md linguist-generated=true rotation_axis_angle.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/aabb2d.md b/docs/content/reference/types/datatypes/aabb2d.md deleted file mode 100644 index dec7dbd29400..000000000000 --- a/docs/content/reference/types/datatypes/aabb2d.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "AABB2D" ---- - -An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. - -## Fields - -* min: [`Vec2D`](../datatypes/vec2d.md) -* max: [`Vec2D`](../datatypes/vec2d.md) - -## Links - * 🌊 [C++ API docs for `AABB2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1AABB2D.html) - * 🐍 [Python API docs for `AABB2D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.AABB2D) - * 🦀 [Rust API docs for `AABB2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.AABB2D.html) - - -## Used by - -* [`AABB2D`](../components/aabb2d.md) diff --git a/docs/content/reference/types/datatypes/range1d.md b/docs/content/reference/types/datatypes/range1d.md index 5360463b53bd..b60a94d78200 100644 --- a/docs/content/reference/types/datatypes/range1d.md +++ b/docs/content/reference/types/datatypes/range1d.md @@ -17,3 +17,4 @@ A 1D range, specifying a lower and upper bound. ## Used by * [`Range1D`](../components/range1d.md) +* [`Range2D`](../datatypes/range2d.md) diff --git a/docs/content/reference/types/datatypes/range2d.md b/docs/content/reference/types/datatypes/range2d.md new file mode 100644 index 000000000000..60d3c19d2e72 --- /dev/null +++ b/docs/content/reference/types/datatypes/range2d.md @@ -0,0 +1,20 @@ +--- +title: "Range2D" +--- + +An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. + +## Fields + +* x_range: [`Range1D`](../datatypes/range1d.md) +* y_range: [`Range1D`](../datatypes/range1d.md) + +## Links + * 🌊 [C++ API docs for `Range2D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1Range2D.html) + * 🐍 [Python API docs for `Range2D`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.Range2D) + * 🦀 [Rust API docs for `Range2D`](https://docs.rs/rerun/latest/rerun/datatypes/struct.Range2D.html) + + +## Used by + +* [`Range2D`](../components/range2d.md) diff --git a/docs/content/reference/types/datatypes/vec2d.md b/docs/content/reference/types/datatypes/vec2d.md index d9055170734a..68aa0b665805 100644 --- a/docs/content/reference/types/datatypes/vec2d.md +++ b/docs/content/reference/types/datatypes/vec2d.md @@ -16,7 +16,6 @@ A vector in 2D space. ## Used by -* [`AABB2D`](../datatypes/aabb2d.md) * [`HalfSizes2D`](../components/half_sizes2d.md) * [`LineStrip2D`](../components/line_strip2d.md) * [`Position2D`](../components/position2d.md) diff --git a/docs/content/reference/types/views/spatial2d_view.md b/docs/content/reference/types/views/spatial2d_view.md index c55daa1e93a8..5d5b1ad3c7e2 100644 --- a/docs/content/reference/types/views/spatial2d_view.md +++ b/docs/content/reference/types/views/spatial2d_view.md @@ -14,7 +14,7 @@ Configuration for the background of a view. ### `VisualBounds` Controls the visual bounds of a 2D space view. -* visual_bounds: The visible parts of a 2D space view, in the coordinate space of the scene. +* range2d: The visible parts of a 2D space view, in the coordinate space of the scene. ### `VisibleTimeRange` Configures what range of the timeline is shown on a view. diff --git a/docs/snippets/all/extra_values.py b/docs/snippets/all/extra_values.py index 0f4ee366ab1b..103b2de5c6f4 100644 --- a/docs/snippets/all/extra_values.py +++ b/docs/snippets/all/extra_values.py @@ -14,4 +14,4 @@ ) # Set view bounds: -rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1.5, -1.5], max=[1.5, 1.5]))) +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(x_range=[-1.5, 1.5], y_range=[-1.5, 1.5]))) diff --git a/docs/snippets/all/line_segments2d_simple.py b/docs/snippets/all/line_segments2d_simple.py index 6676dda3be00..50c6d009d042 100644 --- a/docs/snippets/all/line_segments2d_simple.py +++ b/docs/snippets/all/line_segments2d_simple.py @@ -12,4 +12,4 @@ ) # Set view bounds: -rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 3]))) +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(x_range=[-1, 7], y_range=[-3, 3]))) diff --git a/docs/snippets/all/line_strip2d_batch.py b/docs/snippets/all/line_strip2d_batch.py index 7e72f53e105c..3aec7afa695d 100644 --- a/docs/snippets/all/line_strip2d_batch.py +++ b/docs/snippets/all/line_strip2d_batch.py @@ -19,4 +19,4 @@ ) # Set view bounds: -rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 6]))) +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(x_range=[-1, 7], y_range=[-3, 6]))) diff --git a/docs/snippets/all/line_strip2d_simple.py b/docs/snippets/all/line_strip2d_simple.py index 368e50662b5a..60135bd37ed2 100644 --- a/docs/snippets/all/line_strip2d_simple.py +++ b/docs/snippets/all/line_strip2d_simple.py @@ -11,4 +11,4 @@ ) # Set view bounds: -rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 3]))) +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(x_range=[-1, 7], y_range=[-3, 3]))) diff --git a/docs/snippets/all/point2d_random.py b/docs/snippets/all/point2d_random.py index fe100265e81a..ecd6f2d937b1 100644 --- a/docs/snippets/all/point2d_random.py +++ b/docs/snippets/all/point2d_random.py @@ -14,4 +14,4 @@ rr.log("random", rr.Points2D(positions, colors=colors, radii=radii)) # Set view bounds: -rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-4, -4], max=[4, 4]))) +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(x_range=[-4, 4], y_range=[-4, 4]))) diff --git a/docs/snippets/all/point2d_simple.py b/docs/snippets/all/point2d_simple.py index 569e4ab72271..a1e729198ec6 100644 --- a/docs/snippets/all/point2d_simple.py +++ b/docs/snippets/all/point2d_simple.py @@ -8,4 +8,4 @@ rr.log("points", rr.Points2D([[0, 0], [1, 1]])) # Set view bounds: -rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -1], max=[2, 2]))) +rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(x_range=[-1, 2], y_range=[-1, 2]))) diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp index 575ab5c11190..5cfa2d5ed8e0 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.cpp @@ -16,8 +16,8 @@ namespace rerun { std::vector cells; cells.reserve(2); - if (archetype.visual_bounds.has_value()) { - auto result = DataCell::from_loggable(archetype.visual_bounds.value()); + if (archetype.range2d.has_value()) { + auto result = DataCell::from_loggable(archetype.range2d.value()); RR_RETURN_NOT_OK(result.error); cells.push_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp index c9c88725f054..fd844c98eb65 100644 --- a/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp +++ b/rerun_cpp/src/rerun/blueprint/archetypes/visual_bounds.hpp @@ -5,7 +5,7 @@ #include "../../collection.hpp" #include "../../compiler_utils.hpp" -#include "../../components/aabb2d.hpp" +#include "../../components/range2d.hpp" #include "../../data_cell.hpp" #include "../../indicator_component.hpp" #include "../../result.hpp" @@ -22,7 +22,7 @@ namespace rerun::blueprint::archetypes { /// /// Everything within these bounds are guaranteed to be visible. /// Somethings outside of these bounds may also be visible due to letterboxing. - std::optional visual_bounds; + std::optional range2d; public: static constexpr const char IndicatorComponentName[] = @@ -39,8 +39,8 @@ namespace rerun::blueprint::archetypes { /// /// Everything within these bounds are guaranteed to be visible. /// Somethings outside of these bounds may also be visible due to letterboxing. - VisualBounds with_visual_bounds(rerun::components::AABB2D _visual_bounds) && { - visual_bounds = std::move(_visual_bounds); + VisualBounds with_range2d(rerun::components::Range2D _range2d) && { + range2d = std::move(_range2d); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/components.hpp b/rerun_cpp/src/rerun/components.hpp index 4e818c0b9b78..ff62cba0d864 100644 --- a/rerun_cpp/src/rerun/components.hpp +++ b/rerun_cpp/src/rerun/components.hpp @@ -2,7 +2,6 @@ #pragma once -#include "components/aabb2d.hpp" #include "components/annotation_context.hpp" #include "components/blob.hpp" #include "components/class_id.hpp" @@ -28,6 +27,7 @@ #include "components/position3d.hpp" #include "components/radius.hpp" #include "components/range1d.hpp" +#include "components/range2d.hpp" #include "components/resolution.hpp" #include "components/rotation3d.hpp" #include "components/scalar.hpp" diff --git a/rerun_cpp/src/rerun/components/.gitattributes b/rerun_cpp/src/rerun/components/.gitattributes index 1bfb2e511343..5902b7444eff 100644 --- a/rerun_cpp/src/rerun/components/.gitattributes +++ b/rerun_cpp/src/rerun/components/.gitattributes @@ -1,7 +1,6 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -aabb2d.hpp linguist-generated=true annotation_context.cpp linguist-generated=true annotation_context.hpp linguist-generated=true blob.cpp linguist-generated=true @@ -38,6 +37,7 @@ position3d.hpp linguist-generated=true radius.cpp linguist-generated=true radius.hpp linguist-generated=true range1d.hpp linguist-generated=true +range2d.hpp linguist-generated=true resolution.hpp linguist-generated=true rotation3d.hpp linguist-generated=true scalar.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/aabb2d.hpp b/rerun_cpp/src/rerun/components/aabb2d.hpp deleted file mode 100644 index 07d00176a8b2..000000000000 --- a/rerun_cpp/src/rerun/components/aabb2d.hpp +++ /dev/null @@ -1,54 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". - -#pragma once - -#include "../datatypes/aabb2d.hpp" -#include "../result.hpp" - -#include -#include - -namespace rerun::components { - /// **Component**: An Axis-Aligned Bounding Box in 2D space. - struct AABB2D { - rerun::datatypes::AABB2D aabb; - - public: - AABB2D() = default; - - AABB2D(rerun::datatypes::AABB2D aabb_) : aabb(aabb_) {} - - AABB2D& operator=(rerun::datatypes::AABB2D aabb_) { - aabb = aabb_; - return *this; - } - - /// Cast to the underlying AABB2D datatype - operator rerun::datatypes::AABB2D() const { - return aabb; - } - }; -} // namespace rerun::components - -namespace rerun { - static_assert(sizeof(rerun::datatypes::AABB2D) == sizeof(components::AABB2D)); - - /// \private - template <> - struct Loggable { - static constexpr const char Name[] = "rerun.components.AABB2D"; - - /// Returns the arrow data type this type corresponds to. - static const std::shared_ptr& arrow_datatype() { - return Loggable::arrow_datatype(); - } - - /// Serializes an array of `rerun::components::AABB2D` into an arrow array. - static Result> to_arrow( - const components::AABB2D* instances, size_t num_instances - ) { - return Loggable::to_arrow(&instances->aabb, num_instances); - } - }; -} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/range2d.hpp b/rerun_cpp/src/rerun/components/range2d.hpp new file mode 100644 index 000000000000..bf38a2736c63 --- /dev/null +++ b/rerun_cpp/src/rerun/components/range2d.hpp @@ -0,0 +1,57 @@ +// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/re_types/definitions/rerun/components/range2d.fbs". + +#pragma once + +#include "../datatypes/range2d.hpp" +#include "../result.hpp" + +#include +#include + +namespace rerun::components { + /// **Component**: An Axis-Aligned Bounding Box in 2D space. + struct Range2D { + rerun::datatypes::Range2D range2d; + + public: + Range2D() = default; + + Range2D(rerun::datatypes::Range2D range2d_) : range2d(range2d_) {} + + Range2D& operator=(rerun::datatypes::Range2D range2d_) { + range2d = range2d_; + return *this; + } + + /// Cast to the underlying Range2D datatype + operator rerun::datatypes::Range2D() const { + return range2d; + } + }; +} // namespace rerun::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::Range2D) == sizeof(components::Range2D)); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.components.Range2D"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::components::Range2D` into an arrow array. + static Result> to_arrow( + const components::Range2D* instances, size_t num_instances + ) { + return Loggable::to_arrow( + &instances->range2d, + num_instances + ); + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index 7b47facd6c3e..cc2784d3fc5c 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -2,7 +2,6 @@ #pragma once -#include "datatypes/aabb2d.hpp" #include "datatypes/angle.hpp" #include "datatypes/annotation_info.hpp" #include "datatypes/bool.hpp" @@ -19,6 +18,7 @@ #include "datatypes/mesh_properties.hpp" #include "datatypes/quaternion.hpp" #include "datatypes/range1d.hpp" +#include "datatypes/range2d.hpp" #include "datatypes/rgba32.hpp" #include "datatypes/rotation3d.hpp" #include "datatypes/rotation_axis_angle.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 34f722d5efa0..4170301018d2 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -1,8 +1,6 @@ # DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs .gitattributes linguist-generated=true -aabb2d.cpp linguist-generated=true -aabb2d.hpp linguist-generated=true angle.cpp linguist-generated=true angle.hpp linguist-generated=true annotation_info.cpp linguist-generated=true @@ -35,6 +33,8 @@ quaternion.cpp linguist-generated=true quaternion.hpp linguist-generated=true range1d.cpp linguist-generated=true range1d.hpp linguist-generated=true +range2d.cpp linguist-generated=true +range2d.hpp linguist-generated=true rgba32.cpp linguist-generated=true rgba32.hpp linguist-generated=true rotation3d.cpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.cpp b/rerun_cpp/src/rerun/datatypes/range2d.cpp similarity index 68% rename from rerun_cpp/src/rerun/datatypes/aabb2d.cpp rename to rerun_cpp/src/rerun/datatypes/range2d.cpp index d960e1a1516d..ab5be43f96f4 100644 --- a/rerun_cpp/src/rerun/datatypes/aabb2d.cpp +++ b/rerun_cpp/src/rerun/datatypes/range2d.cpp @@ -1,9 +1,9 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/range2d.fbs". -#include "aabb2d.hpp" +#include "range2d.hpp" -#include "vec2d.hpp" +#include "range1d.hpp" #include #include @@ -11,16 +11,16 @@ namespace rerun::datatypes {} namespace rerun { - const std::shared_ptr& Loggable::arrow_datatype() { + const std::shared_ptr& Loggable::arrow_datatype() { static const auto datatype = arrow::struct_({ - arrow::field("min", Loggable::arrow_datatype(), false), - arrow::field("max", Loggable::arrow_datatype(), false), + arrow::field("x_range", Loggable::arrow_datatype(), false), + arrow::field("y_range", Loggable::arrow_datatype(), false), }); return datatype; } - Result> Loggable::to_arrow( - const datatypes::AABB2D* instances, size_t num_instances + Result> Loggable::to_arrow( + const datatypes::Range2D* instances, size_t num_instances ) { // TODO(andreas): Allow configuring the memory pool. arrow::MemoryPool* pool = arrow::default_memory_pool(); @@ -28,7 +28,7 @@ namespace rerun { ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( static_cast(builder.get()), instances, num_instances @@ -39,8 +39,8 @@ namespace rerun { return array; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const datatypes::AABB2D* elements, size_t num_elements + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const datatypes::Range2D* elements, size_t num_elements ) { if (builder == nullptr) { return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); @@ -57,9 +57,9 @@ namespace rerun { static_cast(builder->field_builder(0)); ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( field_builder, - &elements[elem_idx].min, + &elements[elem_idx].x_range, 1 )); } @@ -69,9 +69,9 @@ namespace rerun { static_cast(builder->field_builder(1)); ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { - RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( field_builder, - &elements[elem_idx].max, + &elements[elem_idx].y_range, 1 )); } diff --git a/rerun_cpp/src/rerun/datatypes/aabb2d.hpp b/rerun_cpp/src/rerun/datatypes/range2d.hpp similarity index 56% rename from rerun_cpp/src/rerun/datatypes/aabb2d.hpp rename to rerun_cpp/src/rerun/datatypes/range2d.hpp index 41a751bfed12..1c5e2f7ed159 100644 --- a/rerun_cpp/src/rerun/datatypes/aabb2d.hpp +++ b/rerun_cpp/src/rerun/datatypes/range2d.hpp @@ -1,10 +1,10 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/range2d.fbs". #pragma once #include "../result.hpp" -#include "vec2d.hpp" +#include "range1d.hpp" #include #include @@ -17,15 +17,15 @@ namespace arrow { namespace rerun::datatypes { /// **Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners. - struct AABB2D { - /// The minimum bounds; usually left-top corner. - rerun::datatypes::Vec2D min; + struct Range2D { + /// The range of the X-axis (usually left and right bounds). + rerun::datatypes::Range1D x_range; - /// The maximum bounds; usually right-bottom corner. - rerun::datatypes::Vec2D max; + /// The range of the Y-axis (usually top and bottom bounds). + rerun::datatypes::Range1D y_range; public: - AABB2D() = default; + Range2D() = default; }; } // namespace rerun::datatypes @@ -35,20 +35,20 @@ namespace rerun { /// \private template <> - struct Loggable { - static constexpr const char Name[] = "rerun.datatypes.AABB2D"; + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.Range2D"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Serializes an array of `rerun::datatypes::AABB2D` into an arrow array. + /// Serializes an array of `rerun::datatypes::Range2D` into an arrow array. static Result> to_arrow( - const datatypes::AABB2D* instances, size_t num_instances + const datatypes::Range2D* instances, size_t num_instances ); /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const datatypes::AABB2D* elements, size_t num_elements + arrow::StructBuilder* builder, const datatypes::Range2D* elements, size_t num_elements ); }; } // namespace rerun diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py index f1995404a11a..6e9a828abc49 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py @@ -44,7 +44,7 @@ class LineStrips2D(Archetype): ) # Set view bounds: - rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-1, -3], max=[7, 6]))) + rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(x_range=[-1, 7], y_range=[-3, 6]))) ```
diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py index 25bcaaaef58c..756e96f7c548 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py @@ -37,7 +37,7 @@ class Points2D(Points2DExt, Archetype): rr.log("random", rr.Points2D(positions, colors=colors, radii=radii)) # Set view bounds: - rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(min=[-4, -4], max=[4, 4]))) + rr.send_blueprint(rrb.Spatial2DView(visual_bounds=rrb.VisualBounds(x_range=[-4, 4], y_range=[-4, 4]))) ```
diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py index c611cd889a5e..2e8f1f5fcde0 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds.py @@ -23,7 +23,7 @@ class VisualBounds(VisualBoundsExt, Archetype): def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( - visual_bounds=None, # type: ignore[arg-type] + range2d=None, # type: ignore[arg-type] ) @classmethod @@ -33,10 +33,10 @@ def _clear(cls) -> VisualBounds: inst.__attrs_clear__() return inst - visual_bounds: components.AABB2DBatch | None = field( + range2d: components.Range2DBatch | None = field( metadata={"component": "optional"}, default=None, - converter=components.AABB2DBatch._optional, # type: ignore[misc] + converter=components.Range2DBatch._optional, # type: ignore[misc] ) # The visible parts of a 2D space view, in the coordinate space of the scene. # diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py index 9124871c0612..04088d2a3d00 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visual_bounds_ext.py @@ -12,24 +12,22 @@ class VisualBoundsExt: def __init__( self: Any, *, - min: datatypes.Vec2DLike, - max: datatypes.Vec2DLike, + x_range: datatypes.Range1DLike, + y_range: datatypes.Range1DLike, ): """ Create a new instance of the VisualBounds archetype. Parameters ---------- - min: - The minimum point of the visible parts of a 2D space view, in the coordinate space of the scene. - Usually the left-top corner. - max: - The maximum point of the visible parts of a 2D space view, in the coordinate space of the scene. - Usually the right-bottom corner. + x_range: + The minimum visible range of the X-axis (usually left and right bounds). + y_range: + The minimum visible range of the Y-axis (usually left and right bounds). """ with catch_and_log_exceptions(context=self.__class__.__name__): - self.__attrs_init__(visual_bounds=components.AABB2D(min=min, max=max)) + self.__attrs_init__(range2d=components.Range2D(x_range=x_range, y_range=y_range)) return self.__attrs_clear__() diff --git a/rerun_py/rerun_sdk/rerun/components/.gitattributes b/rerun_py/rerun_sdk/rerun/components/.gitattributes index f7f22c699975..6806534cc37a 100644 --- a/rerun_py/rerun_sdk/rerun/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/components/.gitattributes @@ -2,7 +2,6 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true -aabb2d.py linguist-generated=true annotation_context.py linguist-generated=true blob.py linguist-generated=true class_id.py linguist-generated=true @@ -28,6 +27,7 @@ position2d.py linguist-generated=true position3d.py linguist-generated=true radius.py linguist-generated=true range1d.py linguist-generated=true +range2d.py linguist-generated=true resolution.py linguist-generated=true rotation3d.py linguist-generated=true scalar.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/components/__init__.py b/rerun_py/rerun_sdk/rerun/components/__init__.py index 0c7615bd6e34..a7c6965e1a1a 100644 --- a/rerun_py/rerun_sdk/rerun/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/components/__init__.py @@ -2,7 +2,6 @@ from __future__ import annotations -from .aabb2d import AABB2D, AABB2DBatch, AABB2DType from .annotation_context import ( AnnotationContext, AnnotationContextArrayLike, @@ -46,6 +45,7 @@ from .position3d import Position3D, Position3DBatch, Position3DType from .radius import Radius, RadiusArrayLike, RadiusBatch, RadiusLike, RadiusType from .range1d import Range1D, Range1DBatch, Range1DType +from .range2d import Range2D, Range2DBatch, Range2DType from .resolution import Resolution, ResolutionBatch, ResolutionType from .rotation3d import Rotation3D, Rotation3DBatch, Rotation3DType from .scalar import Scalar, ScalarArrayLike, ScalarBatch, ScalarLike, ScalarType @@ -80,9 +80,6 @@ ) __all__ = [ - "AABB2D", - "AABB2DBatch", - "AABB2DType", "AnnotationContext", "AnnotationContextArrayLike", "AnnotationContextBatch", @@ -180,6 +177,9 @@ "Range1D", "Range1DBatch", "Range1DType", + "Range2D", + "Range2DBatch", + "Range2DType", "Resolution", "ResolutionBatch", "ResolutionType", diff --git a/rerun_py/rerun_sdk/rerun/components/aabb2d.py b/rerun_py/rerun_sdk/rerun/components/aabb2d.py deleted file mode 100644 index 16419767704c..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/aabb2d.py +++ /dev/null @@ -1,29 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/components/aabb2d.fbs". - -# You can extend this class by creating a "AABB2DExt" class in "aabb2d_ext.py". - -from __future__ import annotations - -from .. import datatypes -from .._baseclasses import ComponentBatchMixin -from .aabb2d_ext import AABB2DExt - -__all__ = ["AABB2D", "AABB2DBatch", "AABB2DType"] - - -class AABB2D(AABB2DExt, datatypes.AABB2D): - """**Component**: An Axis-Aligned Bounding Box in 2D space.""" - - # __init__ can be found in aabb2d_ext.py - - # Note: there are no fields here because AABB2D delegates to datatypes.AABB2D - pass - - -class AABB2DType(datatypes.AABB2DType): - _TYPE_NAME: str = "rerun.components.AABB2D" - - -class AABB2DBatch(datatypes.AABB2DBatch, ComponentBatchMixin): - _ARROW_TYPE = AABB2DType() diff --git a/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py b/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py deleted file mode 100644 index 0248277a3262..000000000000 --- a/rerun_py/rerun_sdk/rerun/components/aabb2d_ext.py +++ /dev/null @@ -1,31 +0,0 @@ -from __future__ import annotations - -from typing import Any - -from ..datatypes import Vec2DLike - - -class AABB2DExt: - """Extension for [AABB2D][rerun.components.AABB2D].""" - - def __init__( - self: Any, - *, - min: Vec2DLike, - max: Vec2DLike, - ): - """ - Create a new instance of the AABB2D component. - - Parameters - ---------- - min: - The minimum point of the visible parts of a 2D space view, in the coordinate space of the scene. - Usually the left-top corner. - max: - The maximum point of the visible parts of a 2D space view, in the coordinate space of the scene. - Usually the right-bottom corner. - - """ - - self.__attrs_init__(min=min, max=max) diff --git a/rerun_py/rerun_sdk/rerun/components/range2d.py b/rerun_py/rerun_sdk/rerun/components/range2d.py new file mode 100644 index 000000000000..e58da57c4bb7 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/range2d.py @@ -0,0 +1,29 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/components/range2d.fbs". + +# You can extend this class by creating a "Range2DExt" class in "range2d_ext.py". + +from __future__ import annotations + +from .. import datatypes +from .._baseclasses import ComponentBatchMixin +from .range2d_ext import Range2DExt + +__all__ = ["Range2D", "Range2DBatch", "Range2DType"] + + +class Range2D(Range2DExt, datatypes.Range2D): + """**Component**: An Axis-Aligned Bounding Box in 2D space.""" + + # __init__ can be found in range2d_ext.py + + # Note: there are no fields here because Range2D delegates to datatypes.Range2D + pass + + +class Range2DType(datatypes.Range2DType): + _TYPE_NAME: str = "rerun.components.Range2D" + + +class Range2DBatch(datatypes.Range2DBatch, ComponentBatchMixin): + _ARROW_TYPE = Range2DType() diff --git a/rerun_py/rerun_sdk/rerun/components/range2d_ext.py b/rerun_py/rerun_sdk/rerun/components/range2d_ext.py new file mode 100644 index 000000000000..e6a0d3902484 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/range2d_ext.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +from typing import Any + +from ..datatypes import Range1DLike + + +class Range2DExt: + """Extension for [Range2D][rerun.components.Range2D].""" + + def __init__( + self: Any, + *, + x_range: Range1DLike, + y_range: Range1DLike, + ): + """ + Create a new instance of the Range2D component. + + Parameters + ---------- + x_range: + The minimum visible range of the X-axis (usually left and right bounds). + y_range: + The minimum visible range of the Y-axis (usually left and right bounds). + + """ + + self.__attrs_init__(x_range=x_range, y_range=y_range) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index 9a04afcec6f7..1cab4659e6a6 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -2,7 +2,6 @@ .gitattributes linguist-generated=true __init__.py linguist-generated=true -aabb2d.py linguist-generated=true angle.py linguist-generated=true annotation_info.py linguist-generated=true bool.py linguist-generated=true @@ -19,6 +18,7 @@ material.py linguist-generated=true mesh_properties.py linguist-generated=true quaternion.py linguist-generated=true range1d.py linguist-generated=true +range2d.py linguist-generated=true rgba32.py linguist-generated=true rotation3d.py linguist-generated=true rotation_axis_angle.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index 717aac102f48..bf33b417cbaf 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -2,7 +2,6 @@ from __future__ import annotations -from .aabb2d import AABB2D, AABB2DArrayLike, AABB2DBatch, AABB2DLike, AABB2DType from .angle import Angle, AngleArrayLike, AngleBatch, AngleLike, AngleType from .annotation_info import ( AnnotationInfo, @@ -43,6 +42,7 @@ ) from .quaternion import Quaternion, QuaternionArrayLike, QuaternionBatch, QuaternionLike, QuaternionType from .range1d import Range1D, Range1DArrayLike, Range1DBatch, Range1DLike, Range1DType +from .range2d import Range2D, Range2DArrayLike, Range2DBatch, Range2DLike, Range2DType from .rgba32 import Rgba32, Rgba32ArrayLike, Rgba32Batch, Rgba32Like, Rgba32Type from .rotation3d import Rotation3D, Rotation3DArrayLike, Rotation3DBatch, Rotation3DLike, Rotation3DType from .rotation_axis_angle import ( @@ -90,11 +90,6 @@ from .vec4d import Vec4D, Vec4DArrayLike, Vec4DBatch, Vec4DLike, Vec4DType __all__ = [ - "AABB2D", - "AABB2DArrayLike", - "AABB2DBatch", - "AABB2DLike", - "AABB2DType", "Angle", "AngleArrayLike", "AngleBatch", @@ -175,6 +170,11 @@ "Range1DBatch", "Range1DLike", "Range1DType", + "Range2D", + "Range2DArrayLike", + "Range2DBatch", + "Range2DLike", + "Range2DType", "Rgba32", "Rgba32ArrayLike", "Rgba32Batch", diff --git a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py b/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py deleted file mode 100644 index 60d0923f214f..000000000000 --- a/rerun_py/rerun_sdk/rerun/datatypes/aabb2d.py +++ /dev/null @@ -1,111 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/datatypes/aabb2d.fbs". - -# You can extend this class by creating a "AABB2DExt" class in "aabb2d_ext.py". - -from __future__ import annotations - -from typing import Any, Sequence, Union - -import pyarrow as pa -from attrs import define, field - -from .. import datatypes -from .._baseclasses import BaseBatch, BaseExtensionType - -__all__ = ["AABB2D", "AABB2DArrayLike", "AABB2DBatch", "AABB2DLike", "AABB2DType"] - - -def _aabb2d__min__special_field_converter_override(x: datatypes.Vec2DLike) -> datatypes.Vec2D: - if isinstance(x, datatypes.Vec2D): - return x - else: - return datatypes.Vec2D(x) - - -def _aabb2d__max__special_field_converter_override(x: datatypes.Vec2DLike) -> datatypes.Vec2D: - if isinstance(x, datatypes.Vec2D): - return x - else: - return datatypes.Vec2D(x) - - -@define(init=False) -class AABB2D: - """**Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners.""" - - def __init__(self: Any, min: datatypes.Vec2DLike, max: datatypes.Vec2DLike): - """ - Create a new instance of the AABB2D datatype. - - Parameters - ---------- - min: - The minimum bounds; usually left-top corner. - max: - The maximum bounds; usually right-bottom corner. - - """ - - # You can define your own __init__ function as a member of AABB2DExt in aabb2d_ext.py - self.__attrs_init__(min=min, max=max) - - min: datatypes.Vec2D = field(converter=_aabb2d__min__special_field_converter_override) - # The minimum bounds; usually left-top corner. - # - # (Docstring intentionally commented out to hide this field from the docs) - - max: datatypes.Vec2D = field(converter=_aabb2d__max__special_field_converter_override) - # The maximum bounds; usually right-bottom corner. - # - # (Docstring intentionally commented out to hide this field from the docs) - - -AABB2DLike = AABB2D -AABB2DArrayLike = Union[ - AABB2D, - Sequence[AABB2DLike], -] - - -class AABB2DType(BaseExtensionType): - _TYPE_NAME: str = "rerun.datatypes.AABB2D" - - def __init__(self) -> None: - pa.ExtensionType.__init__( - self, - pa.struct([ - pa.field( - "min", - pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 2), - nullable=False, - metadata={}, - ), - pa.field( - "max", - pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 2), - nullable=False, - metadata={}, - ), - ]), - self._TYPE_NAME, - ) - - -class AABB2DBatch(BaseBatch[AABB2DArrayLike]): - _ARROW_TYPE = AABB2DType() - - @staticmethod - def _native_to_pa_array(data: AABB2DArrayLike, data_type: pa.DataType) -> pa.Array: - from rerun.datatypes import Vec2DBatch - - if isinstance(data, AABB2D): - data = [data] - - return pa.StructArray.from_arrays( - [ - Vec2DBatch([x.min for x in data]).as_arrow_array().storage, - Vec2DBatch([x.max for x in data]).as_arrow_array().storage, - ], - fields=list(data_type), - ) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/range2d.py b/rerun_py/rerun_sdk/rerun/datatypes/range2d.py new file mode 100644 index 000000000000..d94190ed1068 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/datatypes/range2d.py @@ -0,0 +1,111 @@ +# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/re_types/definitions/rerun/datatypes/range2d.fbs". + +# You can extend this class by creating a "Range2DExt" class in "range2d_ext.py". + +from __future__ import annotations + +from typing import Any, Sequence, Union + +import pyarrow as pa +from attrs import define, field + +from .. import datatypes +from .._baseclasses import BaseBatch, BaseExtensionType + +__all__ = ["Range2D", "Range2DArrayLike", "Range2DBatch", "Range2DLike", "Range2DType"] + + +def _range2d__x_range__special_field_converter_override(x: datatypes.Range1DLike) -> datatypes.Range1D: + if isinstance(x, datatypes.Range1D): + return x + else: + return datatypes.Range1D(x) + + +def _range2d__y_range__special_field_converter_override(x: datatypes.Range1DLike) -> datatypes.Range1D: + if isinstance(x, datatypes.Range1D): + return x + else: + return datatypes.Range1D(x) + + +@define(init=False) +class Range2D: + """**Datatype**: An Axis-Aligned Bounding Box in 2D space, implemented as the minimum and maximum corners.""" + + def __init__(self: Any, x_range: datatypes.Range1DLike, y_range: datatypes.Range1DLike): + """ + Create a new instance of the Range2D datatype. + + Parameters + ---------- + x_range: + The range of the X-axis (usually left and right bounds). + y_range: + The range of the Y-axis (usually top and bottom bounds). + + """ + + # You can define your own __init__ function as a member of Range2DExt in range2d_ext.py + self.__attrs_init__(x_range=x_range, y_range=y_range) + + x_range: datatypes.Range1D = field(converter=_range2d__x_range__special_field_converter_override) + # The range of the X-axis (usually left and right bounds). + # + # (Docstring intentionally commented out to hide this field from the docs) + + y_range: datatypes.Range1D = field(converter=_range2d__y_range__special_field_converter_override) + # The range of the Y-axis (usually top and bottom bounds). + # + # (Docstring intentionally commented out to hide this field from the docs) + + +Range2DLike = Range2D +Range2DArrayLike = Union[ + Range2D, + Sequence[Range2DLike], +] + + +class Range2DType(BaseExtensionType): + _TYPE_NAME: str = "rerun.datatypes.Range2D" + + def __init__(self) -> None: + pa.ExtensionType.__init__( + self, + pa.struct([ + pa.field( + "x_range", + pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), + nullable=False, + metadata={}, + ), + pa.field( + "y_range", + pa.list_(pa.field("item", pa.float64(), nullable=False, metadata={}), 2), + nullable=False, + metadata={}, + ), + ]), + self._TYPE_NAME, + ) + + +class Range2DBatch(BaseBatch[Range2DArrayLike]): + _ARROW_TYPE = Range2DType() + + @staticmethod + def _native_to_pa_array(data: Range2DArrayLike, data_type: pa.DataType) -> pa.Array: + from rerun.datatypes import Range1DBatch + + if isinstance(data, Range2D): + data = [data] + + return pa.StructArray.from_arrays( + [ + Range1DBatch([x.x_range for x in data]).as_arrow_array().storage, + Range1DBatch([x.y_range for x in data]).as_arrow_array().storage, + ], + fields=list(data_type), + ) From 9c42ba7f0040869bb3df261fc6d509335cc32486 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 30 Apr 2024 13:58:53 +0200 Subject: [PATCH 397/508] Add script to upload an .rrd file (#6111) ### What * Closes #6052 Example: ``` pixi run upload-rrd ../rgbd.rrd --version 0.15.1 ``` Result: https://www.rerun.io/viewer/version/0.15.1?url=https%3A%2F%2Fstatic.rerun.io%2Frrd%2F0.15.1%2Frgbd_3f2ebd882270ce75cec25022152f468194c8c4ef.rrd ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6111?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6111?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6111) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Clement Rey --- pixi.toml | 3 + scripts/upload_image.py | 4 +- scripts/upload_rrd.py | 147 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 2 deletions(-) create mode 100755 scripts/upload_rrd.py diff --git a/pixi.toml b/pixi.toml index da7d411af7be..68c482a6b799 100644 --- a/pixi.toml +++ b/pixi.toml @@ -183,6 +183,9 @@ rs-update-insta-tests = "cargo test ; cargo insta review" # Upload image to gcloud storage. upload-image = "python scripts/upload_image.py" +# Upload .rrd to gcloud storage. +upload-rrd = "python scripts/upload_rrd.py" + # Check whether there's too large files in the repository. check-large-files = "python scripts/ci/check_large_files.py" diff --git a/scripts/upload_image.py b/scripts/upload_image.py index 001c6d1256a1..a1aa472be7fb 100755 --- a/scripts/upload_image.py +++ b/scripts/upload_image.py @@ -29,7 +29,7 @@ python3 scripts/upload_image.py --help -or the just command: +or the pixi command: pixi run upload-image --help @@ -305,7 +305,7 @@ def upload_data( destination.content_encoding = content_encoding if destination.exists(): - logging.warn(f"blob {path} already exists in GCS, skipping upload") + logging.warning(f"blob {path} already exists in GCS, skipping upload") return stream = BytesIO(data) diff --git a/scripts/upload_rrd.py b/scripts/upload_rrd.py new file mode 100755 index 000000000000..dffb02991037 --- /dev/null +++ b/scripts/upload_rrd.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +""" +Upload an .rrd to Google Cloud. + +Installation +------------ + +Requires the following packages: + pip install google-cloud-storage + +Before running, you have to authenticate via the Google Cloud CLI: +- Install it (https://cloud.google.com/storage/docs/gsutil_install) +- Set up credentials (https://cloud.google.com/storage/docs/gsutil_install#authenticate) + +If you get this error: + + File "…/site-packages/cryptography/hazmat/primitives/asymmetric/utils.py", line 6, in + from cryptography.hazmat.bindings._rust import asn1 + pyo3_runtime.PanicException: Python API call failed + +Then run `python3 -m pip install cryptography==38.0.4` +(https://levelup.gitconnected.com/fix-attributeerror-module-lib-has-no-attribute-openssl-521a35d83769) + +Usage +----- + +Use the script: + + python3 scripts/upload_rrd.py --help + +or the pixi command: + + pixi run upload-rrd --help +""" + +from __future__ import annotations + +import argparse +import hashlib +import logging +import re +import sys +from io import BytesIO +from pathlib import Path + +from google.cloud import storage + + +class Uploader: + def __init__(self): + gcs = storage.Client("rerun-open") + self.bucket = gcs.bucket("rerun-rrd") + + def upload_data( + self, data: bytes, gcs_path: str, content_type: str | None = None, content_encoding: str | None = None + ) -> None: + """ + Low-level upload of data. + + Parameters + ---------- + data: + The data to upload. + gcs_path: + The path of the object. + content_type: + The content type of the object. + content_encoding: + The content encoding of the object. + + """ + + logging.info(f"Uploading {gcs_path} (size: {len(data)}, type: {content_type}, encoding: {content_encoding})") + destination = self.bucket.blob(gcs_path) + destination.content_type = content_type + destination.content_encoding = content_encoding + + if destination.exists(): + logging.warning(f"blob {gcs_path} already exists in GCS, skipping upload") + return + + stream = BytesIO(data) + destination.upload_from_file(stream) + + +def data_hash(data: bytes) -> str: + """Compute a sha1 hash digest of some data.""" + return hashlib.sha1(data).hexdigest() + + +DESCRIPTION = """Upload an .rrd to static.rerun.io. + + pixi run upload-rrd --version 0.15.0 path/to/recording.rrd + + The version is used for two things: + A) used as a folder name in the GCS bucket. + B) used to generate a link to the correct version of the Rerun web viewer. +""" + + +def main() -> None: + parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument("path", type=str, help="Recording .rrd to upload") + parser.add_argument( + "--name", type=str, required=False, help="Name of the recording. If not supplied, the file name is used." + ) + parser.add_argument("--version", type=str, required=True, help="The Rerun version, e.g. '0.15.0'.") + parser.add_argument("--debug", action="store_true", help="Enable debug logging.") + args = parser.parse_args() + + if args.debug: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + + try: + if not args.path.endswith(".rrd"): + raise RuntimeError("File path expected to have .rrd extension") + + file_path = Path(args.path) + name = args.name or file_path.stem + version = args.version + + # Check if user put `v0.15.0` instead of `0.15.0`: + if m := re.match(r"v(\d+\.\d+\..*)", version): + version = m.group(1) + raise RuntimeError("Version should be in the format '{version}', without a leading 'v'") + + file_data = file_path.read_bytes() + digest = data_hash(file_data) + gcp_path = f"{version}/{name}_{digest}.rrd" + + uploader = Uploader() + uploader.upload_data(file_data, gcp_path, content_type="application/octet-stream") + + recording_url = f"https://static.rerun.io/rrd/{gcp_path}" + print(f"Recording at: {recording_url}") + print(f"View it at: https://rerun.io/viewer/version/{version}/?url={recording_url}") + + except RuntimeError as e: + print(f"Error: {e.args[0]}", file=sys.stderr) + return + + +if __name__ == "__main__": + main() From aa60aab4d747cbe40471a3eea723888f9c9b8d3f Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:46:03 +0200 Subject: [PATCH 398/508] Minor removal of dead code and cleanup of component related code (#6173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What ☝🏻 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6173?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6173?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6173) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_data_ui/src/instance_path.rs | 5 +---- crates/re_data_ui/src/lib.rs | 17 +++-------------- crates/re_time_panel/src/lib.rs | 2 +- crates/re_viewer/src/ui/override_ui.rs | 3 +-- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/crates/re_data_ui/src/instance_path.rs b/crates/re_data_ui/src/instance_path.rs index 1970c4acc227..c7ddfd03e158 100644 --- a/crates/re_data_ui/src/instance_path.rs +++ b/crates/re_data_ui/src/instance_path.rs @@ -40,10 +40,7 @@ impl DataUi for InstancePath { return; }; - let mut components = crate::ui_visible_components(&components); - - // Put indicator components first: - components.sort_by_key(|c| !c.is_indicator_component()); + let mut components = crate::component_list_for_ui(&components); let split = components.partition_point(|c| c.is_indicator_component()); let normal_components = components.split_off(split); diff --git a/crates/re_data_ui/src/lib.rs b/crates/re_data_ui/src/lib.rs index 6e6b696d4e36..4317586a24e8 100644 --- a/crates/re_data_ui/src/lib.rs +++ b/crates/re_data_ui/src/lib.rs @@ -40,16 +40,11 @@ pub use component::EntityLatestAtResults; pub use component_ui_registry::{add_to_registry, create_component_ui_registry}; pub use image_meaning::image_meaning_for_entity; -/// Filter out components that should not be shown in the UI, -/// and order the other components in a cosnsiten way. -pub fn ui_visible_components<'a>( +/// Sort components for display in the UI. +pub fn component_list_for_ui<'a>( iter: impl IntoIterator + 'a, ) -> Vec { - let mut components: Vec = iter - .into_iter() - .copied() - .filter(is_component_visible_in_ui) - .collect(); + let mut components: Vec = iter.into_iter().copied().collect(); // Put indicator components first: components.sort_by_key(|c| (!c.is_indicator_component(), c.full_name())); @@ -57,12 +52,6 @@ pub fn ui_visible_components<'a>( components } -/// Show this component in the UI. -pub fn is_component_visible_in_ui(component_name: &ComponentName) -> bool { - const HIDDEN_COMPONENTS: &[&str] = &[]; - !HIDDEN_COMPONENTS.contains(&component_name.as_ref()) -} - /// Types implementing [`DataUi`] can display themselves in an [`egui::Ui`]. pub trait DataUi { /// If you need to lookup something in the data store, use the given query to do so. diff --git a/crates/re_time_panel/src/lib.rs b/crates/re_time_panel/src/lib.rs index 8e07405f3298..02371e67c300 100644 --- a/crates/re_time_panel/src/lib.rs +++ b/crates/re_time_panel/src/lib.rs @@ -741,7 +741,7 @@ impl TimePanel { if !tree.entity.components.is_empty() { let clip_rect_save = ui.clip_rect(); - for component_name in re_data_ui::ui_visible_components(tree.entity.components.keys()) { + for component_name in re_data_ui::component_list_for_ui(tree.entity.components.keys()) { let data = &tree.entity.components[&component_name]; let is_static = data.is_static(); diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index b0779fa7c4c0..0092235b6831 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -3,7 +3,6 @@ use std::collections::{BTreeMap, BTreeSet}; use itertools::Itertools; use re_data_store::LatestAtQuery; -use re_data_ui::is_component_visible_in_ui; use re_entity_db::{EntityDb, InstancePath}; use re_log_types::{DataRow, RowId, StoreKind}; use re_space_view::{determine_visualizable_entities, SpaceViewBlueprint}; @@ -93,7 +92,7 @@ pub fn override_ui( .resolved_component_overrides .into_iter() .sorted_by_key(|(c, _)| *c) - .filter(|(c, _)| component_to_vis.contains_key(c) && is_component_visible_in_ui(c)) + .filter(|(c, _)| component_to_vis.contains_key(c)) .collect(); egui_extras::TableBuilder::new(ui) From e39a8cf8446478df0df3e763b8d279dea228915b Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Tue, 30 Apr 2024 18:39:12 +0200 Subject: [PATCH 399/508] Fix silently interpreting zero time range as latest-at query (#6172) ### What * Fixes #6135 plus (and that's the bigger part of this PR) refactor time range handling to remove old `VisibleHistory` rust types. Commit by commit review recommended. Still need to fix the ui to better communicate when latest-at is used. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6172?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6172?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6172) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- Cargo.lock | 1 + crates/re_entity_db/src/lib.rs | 2 - crates/re_log_types/src/time_point/mod.rs | 7 +- crates/re_log_types/src/time_range.rs | 16 + crates/re_query/src/lib.rs | 2 - crates/re_query/src/visible_history.rs | 126 - crates/re_space_view/src/lib.rs | 6 - crates/re_space_view/src/visual_time_range.rs | 107 - .../src/visualizers/entity_iterator.rs | 66 +- .../src/space_view_class.rs | 3 +- crates/re_space_view_time_series/src/util.rs | 8 +- .../re_types/definitions/rerun/blueprint.fbs | 2 - .../visible_time_range_sequence.fbs | 2 +- .../components/visible_time_range_time.fbs | 2 +- .../re_types/definitions/rerun/datatypes.fbs | 1 + .../datatypes/visible_time_range.fbs | 19 +- .../components/visible_time_range_sequence.rs | 24 +- .../components/visible_time_range_time.rs | 22 +- .../src/blueprint/datatypes/.gitattributes | 7 - .../re_types/src/blueprint/datatypes/mod.rs | 11 - crates/re_types/src/blueprint/mod.rs | 3 - crates/re_types_core/Cargo.toml | 1 + .../src/datatypes/.gitattributes | 3 + crates/re_types_core/src/datatypes/mod.rs | 8 + .../src/datatypes/time_int_ext.rs | 18 + .../src}/datatypes/visible_time_range.rs | 76 +- .../datatypes/visible_time_range_boundary.rs | 66 +- .../visible_time_range_boundary_ext.rs | 19 +- .../visible_time_range_boundary_kind.rs | 32 +- .../src}/datatypes/visible_time_range_ext.rs | 0 crates/re_viewer/src/ui/visual_time_range.rs | 208 +- crates/re_viewer_context/src/query_range.rs | 2 +- docs/content/reference/types/datatypes.md | 3 + .../reference/types/datatypes/.gitattributes | 3 + .../reference/types/datatypes/time_int.md | 3 + .../types/datatypes/visible_time_range.md | 19 + .../datatypes/visible_time_range_boundary.md | 20 + .../visible_time_range_boundary_kind.md | 21 + pixi.lock | 4997 ++++++++--------- pixi.toml | 1 + rerun_cpp/src/rerun/blueprint/.gitattributes | 1 - .../visible_time_range_sequence.hpp | 17 +- .../components/visible_time_range_time.hpp | 17 +- rerun_cpp/src/rerun/blueprint/datatypes.hpp | 7 - .../rerun/blueprint/datatypes/.gitattributes | 9 - rerun_cpp/src/rerun/datatypes.hpp | 3 + rerun_cpp/src/rerun/datatypes/.gitattributes | 6 + .../datatypes/visible_time_range.cpp | 49 +- .../datatypes/visible_time_range.hpp | 22 +- .../datatypes/visible_time_range_boundary.cpp | 28 +- .../datatypes/visible_time_range_boundary.hpp | 24 +- .../visible_time_range_boundary_kind.cpp | 31 +- .../visible_time_range_boundary_kind.hpp | 20 +- rerun_py/docs/gen_common_index.py | 6 - rerun_py/rerun_sdk/rerun/__init__.py | 2 + .../rerun_sdk/rerun/blueprint/__init__.py | 3 +- .../archetypes/visible_time_range.py | 6 +- .../components/visible_time_range_sequence.py | 8 +- .../components/visible_time_range_time.py | 8 +- .../rerun/blueprint/datatypes/.gitattributes | 7 - .../rerun/blueprint/datatypes/__init__.py | 43 - .../rerun_sdk/rerun/datatypes/.gitattributes | 3 + .../rerun_sdk/rerun/datatypes/__init__.py | 36 + .../datatypes/visible_time_range.py | 20 +- .../datatypes/visible_time_range_boundary.py | 16 +- .../visible_time_range_boundary_kind.py | 6 +- 66 files changed, 2855 insertions(+), 3480 deletions(-) delete mode 100644 crates/re_query/src/visible_history.rs delete mode 100644 crates/re_space_view/src/visual_time_range.rs rename crates/re_types/definitions/rerun/{blueprint => }/datatypes/visible_time_range.fbs (68%) delete mode 100644 crates/re_types/src/blueprint/datatypes/.gitattributes delete mode 100644 crates/re_types/src/blueprint/datatypes/mod.rs rename crates/{re_types/src/blueprint => re_types_core/src}/datatypes/visible_time_range.rs (71%) rename crates/{re_types/src/blueprint => re_types_core/src}/datatypes/visible_time_range_boundary.rs (77%) rename crates/{re_types/src/blueprint => re_types_core/src}/datatypes/visible_time_range_boundary_ext.rs (78%) rename crates/{re_types/src/blueprint => re_types_core/src}/datatypes/visible_time_range_boundary_kind.rs (82%) rename crates/{re_types/src/blueprint => re_types_core/src}/datatypes/visible_time_range_ext.rs (100%) create mode 100644 docs/content/reference/types/datatypes/visible_time_range.md create mode 100644 docs/content/reference/types/datatypes/visible_time_range_boundary.md create mode 100644 docs/content/reference/types/datatypes/visible_time_range_boundary_kind.md delete mode 100644 rerun_cpp/src/rerun/blueprint/datatypes.hpp delete mode 100644 rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes rename rerun_cpp/src/rerun/{blueprint => }/datatypes/visible_time_range.cpp (59%) rename rerun_cpp/src/rerun/{blueprint => }/datatypes/visible_time_range.hpp (59%) rename rerun_cpp/src/rerun/{blueprint => }/datatypes/visible_time_range_boundary.cpp (72%) rename rerun_cpp/src/rerun/{blueprint => }/datatypes/visible_time_range_boundary.hpp (56%) rename rerun_cpp/src/rerun/{blueprint => }/datatypes/visible_time_range_boundary_kind.cpp (63%) rename rerun_cpp/src/rerun/{blueprint => }/datatypes/visible_time_range_boundary_kind.hpp (61%) delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes delete mode 100644 rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py rename rerun_py/rerun_sdk/rerun/{blueprint => }/datatypes/visible_time_range.py (86%) rename rerun_py/rerun_sdk/rerun/{blueprint => }/datatypes/visible_time_range_boundary.py (84%) rename rerun_py/rerun_sdk/rerun/{blueprint => }/datatypes/visible_time_range_boundary_kind.py (93%) diff --git a/Cargo.lock b/Cargo.lock index 2ce174593648..3bfdd42d9cbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4937,6 +4937,7 @@ dependencies = [ "bytemuck", "criterion", "document-features", + "itertools 0.12.0", "once_cell", "re_arrow2", "re_error", diff --git a/crates/re_entity_db/src/lib.rs b/crates/re_entity_db/src/lib.rs index 1d981b4a4d3f..6295ba7181d5 100644 --- a/crates/re_entity_db/src/lib.rs +++ b/crates/re_entity_db/src/lib.rs @@ -34,8 +34,6 @@ pub(crate) use self::entity_tree::{ClearCascade, CompactedStoreEvents}; use re_log_types::DataTableError; pub use re_log_types::{EntityPath, EntityPathPart, TimeInt, Timeline}; -pub use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; - #[cfg(feature = "serde")] pub use blueprint::components::EntityPropertiesComponent; #[cfg(feature = "serde")] diff --git a/crates/re_log_types/src/time_point/mod.rs b/crates/re_log_types/src/time_point/mod.rs index 0bb1ef0cd1da..452652cd1ed4 100644 --- a/crates/re_log_types/src/time_point/mod.rs +++ b/crates/re_log_types/src/time_point/mod.rs @@ -128,7 +128,12 @@ impl TimeType { } #[inline] - pub fn format(&self, time_int: TimeInt, time_zone_for_timestamps: TimeZone) -> String { + pub fn format( + &self, + time_int: impl Into, + time_zone_for_timestamps: TimeZone, + ) -> String { + let time_int = time_int.into(); match time_int { TimeInt::STATIC => "".into(), // TODO(#5264): remove time panel hack once we migrate to the new static UI diff --git a/crates/re_log_types/src/time_range.rs b/crates/re_log_types/src/time_range.rs index 86e041db26b2..18b5f5d48a87 100644 --- a/crates/re_log_types/src/time_range.rs +++ b/crates/re_log_types/src/time_range.rs @@ -101,6 +101,22 @@ impl TimeRange { max: self.max.max(other.max), } } + + pub fn from_visible_time_range( + range: &re_types_core::datatypes::VisibleTimeRange, + cursor: impl Into, + ) -> Self { + let cursor = cursor.into(); + + let mut min = range.start.start_boundary_time(cursor); + let mut max = range.end.end_boundary_time(cursor); + + if min > max { + std::mem::swap(&mut min, &mut max); + } + + Self::new(min, max) + } } impl re_types_core::SizeBytes for TimeRange { diff --git a/crates/re_query/src/lib.rs b/crates/re_query/src/lib.rs index a4dd0a7f188e..cfb6d29b8e45 100644 --- a/crates/re_query/src/lib.rs +++ b/crates/re_query/src/lib.rs @@ -6,7 +6,6 @@ mod flat_vec_deque; mod latest_at; mod promise; mod range; -mod visible_history; pub mod clamped_zip; pub mod range_zip; @@ -19,7 +18,6 @@ pub use self::latest_at::{LatestAtComponentResults, LatestAtMonoResult, LatestAt pub use self::promise::{Promise, PromiseId, PromiseResolver, PromiseResult}; pub use self::range::{RangeComponentResults, RangeData, RangeResults}; pub use self::range_zip::*; -pub use self::visible_history::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; pub(crate) use self::latest_at::LatestAtCache; pub(crate) use self::range::{RangeCache, RangeComponentResultsInner}; diff --git a/crates/re_query/src/visible_history.rs b/crates/re_query/src/visible_history.rs deleted file mode 100644 index f11b29f96baa..000000000000 --- a/crates/re_query/src/visible_history.rs +++ /dev/null @@ -1,126 +0,0 @@ -use re_data_store::{TimeInt, TimeRange}; - -// --- - -/// One of the boundaries of the visible history. -/// -/// For [`VisibleHistoryBoundary::RelativeToTimeCursor`] and [`VisibleHistoryBoundary::Absolute`], -/// the value are either nanos or frames, depending on the type of timeline. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -pub enum VisibleHistoryBoundary { - /// Boundary is a value relative to the time cursor - RelativeToTimeCursor(i64), - - /// Boundary is an absolute value - Absolute(i64), - - /// The boundary extends to infinity. - Infinite, -} - -impl VisibleHistoryBoundary { - /// Value when the boundary is set to the current time cursor. - pub const AT_CURSOR: Self = Self::RelativeToTimeCursor(0); -} - -impl Default for VisibleHistoryBoundary { - fn default() -> Self { - Self::AT_CURSOR - } -} - -/// Visible history bounds. -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -pub struct VisibleHistory { - /// Low time boundary. - pub from: VisibleHistoryBoundary, - - /// High time boundary. - pub to: VisibleHistoryBoundary, -} - -impl VisibleHistory { - /// Value with the visible history feature is disabled. - pub const OFF: Self = Self { - from: VisibleHistoryBoundary::AT_CURSOR, - to: VisibleHistoryBoundary::AT_CURSOR, - }; - - pub const ALL: Self = Self { - from: VisibleHistoryBoundary::Infinite, - to: VisibleHistoryBoundary::Infinite, - }; - - /// Returns the start boundary of the time range given an input cursor position. - /// - /// This is not guaranteed to be lesser than or equal to [`Self::to`]. - /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. - #[doc(hidden)] - pub fn range_start_from_cursor(&self, cursor: TimeInt) -> TimeInt { - match self.from { - VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { - cursor + TimeInt::new_temporal(value) - } - VisibleHistoryBoundary::Infinite => TimeInt::MIN, - } - } - - /// Returns the end boundary of the time range given an input cursor position. - /// - /// This is not guaranteed to be greater than [`Self::from`]. - /// Do not use this to build a [`TimeRange`], use [`Self::time_range`]. - #[doc(hidden)] - pub fn range_end_from_cursor(&self, cursor: TimeInt) -> TimeInt { - match self.to { - VisibleHistoryBoundary::Absolute(value) => TimeInt::new_temporal(value), - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { - cursor + TimeInt::new_temporal(value) - } - VisibleHistoryBoundary::Infinite => TimeInt::MAX, - } - } - - /// Returns a _sanitized_ [`TimeRange`], i.e. guaranteed to be monotonically increasing. - pub fn time_range(&self, cursor: TimeInt) -> TimeRange { - let mut from = self.range_start_from_cursor(cursor); - let mut to = self.range_end_from_cursor(cursor); - - // TODO(#4993): visible time range UI can yield inverted ranges - if from > to { - std::mem::swap(&mut from, &mut to); - } - - TimeRange::new(from, to) - } -} - -/// When showing an entity in the history view, add this much history to it. -#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(default))] -pub struct ExtraQueryHistory { - /// Is the feature enabled? - pub enabled: bool, - - /// Visible history settings for time timelines - pub nanos: VisibleHistory, - - /// Visible history settings for frame timelines - pub sequences: VisibleHistory, -} - -impl ExtraQueryHistory { - /// Multiply/and these together. - pub fn with_child(&self, child: &Self) -> Self { - if child.enabled { - *child - } else if self.enabled { - *self - } else { - Self::default() - } - } -} diff --git a/crates/re_space_view/src/lib.rs b/crates/re_space_view/src/lib.rs index 2de1e10273ea..104230a3b2a6 100644 --- a/crates/re_space_view/src/lib.rs +++ b/crates/re_space_view/src/lib.rs @@ -9,7 +9,6 @@ mod screenshot; mod space_view; mod space_view_contents; mod sub_archetypes; // TODO(andreas): better name before `sub_archetype` sticks around? -mod visual_time_range; mod visualizable; pub use data_query::{DataQuery, EntityOverrideContext, PropertyResolver}; @@ -21,11 +20,6 @@ pub use sub_archetypes::{ edit_blueprint_component, entity_path_for_view_property, get_blueprint_component, query_view_property, query_view_property_or_default, view_property, }; -pub use visual_time_range::{ - query_visual_history, time_range_from_visible_time_range, - visible_history_boundary_from_time_range_boundary, - visible_history_boundary_to_time_range_boundary, -}; pub use visualizable::determine_visualizable_entities; pub mod external { diff --git a/crates/re_space_view/src/visual_time_range.rs b/crates/re_space_view/src/visual_time_range.rs deleted file mode 100644 index 71754e259e8d..000000000000 --- a/crates/re_space_view/src/visual_time_range.rs +++ /dev/null @@ -1,107 +0,0 @@ -//! For the most part this module bridges older visual history types to the newer -//! visual range types that are defined in the `re_types` crate. -//! -//! Historically there was a special `EntityProperty` bag that was used to store the visual history. -//! Now, visual history makes use of the component override system (components stored at special paths in the blueprint store). -//! -//! The intent is to eventually remove the old types, but this bridge here is there in order -//! to reduce the amount of changes in code that is likely to be refactored soon anyways. - -use re_log_types::TimeRange; -use re_query::{ExtraQueryHistory, VisibleHistory, VisibleHistoryBoundary}; -use re_types::blueprint::datatypes::{ - VisibleTimeRange, VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind, -}; -use re_viewer_context::ViewerContext; - -pub fn visible_history_boundary_from_time_range_boundary( - boundary: &VisibleTimeRangeBoundary, -) -> VisibleHistoryBoundary { - match boundary.kind { - VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => { - VisibleHistoryBoundary::RelativeToTimeCursor(boundary.time.0) - } - VisibleTimeRangeBoundaryKind::Absolute => VisibleHistoryBoundary::Absolute(boundary.time.0), - VisibleTimeRangeBoundaryKind::Infinite => VisibleHistoryBoundary::Infinite, - } -} - -pub fn visible_history_boundary_to_time_range_boundary( - boundary: &VisibleHistoryBoundary, -) -> VisibleTimeRangeBoundary { - match boundary { - VisibleHistoryBoundary::RelativeToTimeCursor(v) => VisibleTimeRangeBoundary { - kind: VisibleTimeRangeBoundaryKind::RelativeToTimeCursor, - time: (*v).into(), - }, - VisibleHistoryBoundary::Absolute(v) => VisibleTimeRangeBoundary { - kind: VisibleTimeRangeBoundaryKind::Absolute, - time: (*v).into(), - }, - VisibleHistoryBoundary::Infinite => VisibleTimeRangeBoundary { - kind: VisibleTimeRangeBoundaryKind::Infinite, - time: 0.into(), - }, - } -} - -pub fn time_range_from_visible_time_range( - range: &VisibleTimeRange, - cursor: re_log_types::TimeInt, -) -> re_log_types::TimeRange { - let cursor = cursor.as_i64().into(); - - let mut min = range.start.start_boundary_time(cursor); - let mut max = range.end.end_boundary_time(cursor); - - if min > max { - std::mem::swap(&mut min, &mut max); - } - - let min: re_log_types::TimeInt = min.into(); - let max: re_log_types::TimeInt = max.into(); - - TimeRange::new(min, max) -} - -pub fn query_visual_history( - ctx: &ViewerContext<'_>, - data_result: &re_viewer_context::DataResult, -) -> ExtraQueryHistory { - let Some(overrides) = data_result.property_overrides.as_ref() else { - re_log::error!("No overrides found for visual history"); - return ExtraQueryHistory { - enabled: false, - nanos: Default::default(), - sequences: Default::default(), - }; - }; - - match &overrides.query_range { - re_viewer_context::QueryRange::TimeRange(time_range) => { - match ctx.rec_cfg.time_ctrl.read().time_type() { - re_log_types::TimeType::Time => ExtraQueryHistory { - enabled: true, - nanos: VisibleHistory { - from: visible_history_boundary_from_time_range_boundary(&time_range.start), - to: visible_history_boundary_from_time_range_boundary(&time_range.end), - }, - sequences: Default::default(), - }, - re_log_types::TimeType::Sequence => ExtraQueryHistory { - enabled: true, - nanos: Default::default(), - sequences: VisibleHistory { - from: visible_history_boundary_from_time_range_boundary(&time_range.start), - to: visible_history_boundary_from_time_range_boundary(&time_range.end), - }, - }, - } - } - re_viewer_context::QueryRange::LatestAt => ExtraQueryHistory { - enabled: false, - nanos: Default::default(), - sequences: Default::default(), - }, - } -} diff --git a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs index a5a6b7d68347..d667cb5a27cb 100644 --- a/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs +++ b/crates/re_space_view_spatial/src/visualizers/entity_iterator.rs @@ -2,13 +2,12 @@ use itertools::Either; use re_data_store::{LatestAtQuery, RangeQuery}; use re_entity_db::{EntityDb, EntityProperties}; use re_log_types::{EntityPath, TimeInt, Timeline}; -use re_query::{ExtraQueryHistory, Results}; +use re_query::Results; use re_renderer::DepthOffset; -use re_space_view::query_visual_history; use re_types::Archetype; use re_viewer_context::{ - IdentifiedViewSystem, SpaceViewClass, SpaceViewSystemExecutionError, ViewContextCollection, - ViewQuery, ViewerContext, + IdentifiedViewSystem, QueryRange, SpaceViewClass, SpaceViewSystemExecutionError, + ViewContextCollection, ViewQuery, ViewerContext, }; use crate::{ @@ -43,38 +42,37 @@ pub fn clamped(values: &[T], clamped_len: usize) -> impl Iterator pub fn query_archetype_with_history( entity_db: &EntityDb, timeline: &Timeline, - time: &TimeInt, - history: &ExtraQueryHistory, // TODO(andreas): don't take extra history, take something like `re_viewer_context::QueryRange` so we don't need to convert. + timeline_cursor: TimeInt, + query_range: &QueryRange, entity_path: &EntityPath, ) -> Results { - let visible_history = match timeline.typ() { - re_log_types::TimeType::Time => history.nanos, - re_log_types::TimeType::Sequence => history.sequences, - }; - - let time_range = visible_history.time_range(*time); - let store = entity_db.store(); let caches = entity_db.query_caches(); - if !history.enabled || time_range.min() == time_range.max() { - let latest_query = LatestAtQuery::new(*timeline, time_range.min()); - let results = caches.latest_at( - store, - &latest_query, - entity_path, - A::all_components().iter().copied(), - ); - (latest_query, results).into() - } else { - let range_query = RangeQuery::new(*timeline, time_range); - let results = caches.range( - store, - &range_query, - entity_path, - A::all_components().iter().copied(), - ); - (range_query, results).into() + match query_range { + QueryRange::TimeRange(time_range) => { + let range_query = RangeQuery::new( + *timeline, + re_log_types::TimeRange::from_visible_time_range(time_range, timeline_cursor), + ); + let results = caches.range( + store, + &range_query, + entity_path, + A::all_components().iter().copied(), + ); + (range_query, results).into() + } + QueryRange::LatestAt => { + let latest_query = LatestAtQuery::new(*timeline, timeline_cursor); + let results = caches.latest_at( + store, + &latest_query, + entity_path, + A::all_components().iter().copied(), + ); + (latest_query, results).into() + } } } @@ -133,13 +131,11 @@ where space_view_class_identifier: view_ctx.space_view_class_identifier(), }; - let extra_history = query_visual_history(ctx, data_result); - let results = query_archetype_with_history::( ctx.recording(), &query.timeline, - &query.latest_at, - &extra_history, + query.latest_at, + data_result.query_range(), &data_result.entity_path, ); diff --git a/crates/re_space_view_time_series/src/space_view_class.rs b/crates/re_space_view_time_series/src/space_view_class.rs index 479239f9239d..bf5fe56d4d7e 100644 --- a/crates/re_space_view_time_series/src/space_view_class.rs +++ b/crates/re_space_view_time_series/src/space_view_class.rs @@ -7,8 +7,7 @@ use re_format::next_grid_tick_magnitude_ns; use re_log_types::{EntityPath, TimeInt, TimeZone}; use re_space_view::{controls, query_view_property_or_default}; use re_types::{ - blueprint::{components::Corner2D, datatypes::VisibleTimeRange}, - components::Range1D, + blueprint::components::Corner2D, components::Range1D, datatypes::VisibleTimeRange, SpaceViewClassIdentifier, View, }; use re_viewer_context::external::re_entity_db::{ diff --git a/crates/re_space_view_time_series/src/util.rs b/crates/re_space_view_time_series/src/util.rs index 89cfd4560123..8c9eff66702e 100644 --- a/crates/re_space_view_time_series/src/util.rs +++ b/crates/re_space_view_time_series/src/util.rs @@ -1,9 +1,5 @@ use re_log_types::{EntityPath, TimeRange}; -use re_space_view::time_range_from_visible_time_range; -use re_types::{ - blueprint::datatypes::{VisibleTimeRange, VisibleTimeRangeBoundary}, - datatypes::Utf8, -}; +use re_types::datatypes::{Utf8, VisibleTimeRange, VisibleTimeRangeBoundary}; use re_viewer_context::{external::re_entity_db::TimeSeriesAggregator, ViewQuery, ViewerContext}; use crate::{ @@ -54,7 +50,7 @@ pub fn determine_time_range( } }; - let mut time_range = time_range_from_visible_time_range(&visible_time_range, time_cursor); + let mut time_range = TimeRange::from_visible_time_range(&visible_time_range, time_cursor); // TODO(cmc): We would love to reduce the query to match the actual plot bounds, but because // the plot widget handles zoom after we provide it with data for the current frame, diff --git a/crates/re_types/definitions/rerun/blueprint.fbs b/crates/re_types/definitions/rerun/blueprint.fbs index 7eeb9a27feba..28e39855655c 100644 --- a/crates/re_types/definitions/rerun/blueprint.fbs +++ b/crates/re_types/definitions/rerun/blueprint.fbs @@ -1,5 +1,3 @@ -include "./blueprint/datatypes/visible_time_range.fbs"; - include "./blueprint/components/active_tab.fbs"; include "./blueprint/components/auto_layout.fbs"; include "./blueprint/components/auto_space_views.fbs"; diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs index 0e09bea6761e..82678b83fb47 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_sequence.fbs @@ -16,5 +16,5 @@ table VisibleTimeRangeSequence ( "attr.rust.repr": "transparent", "attr.rust.derive": "PartialEq, Eq" ) { - value: rerun.blueprint.datatypes.VisibleTimeRange (order: 100); + value: rerun.datatypes.VisibleTimeRange (order: 100); } diff --git a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs index 8feab929d0a8..d4f0f1ba73e2 100644 --- a/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs +++ b/crates/re_types/definitions/rerun/blueprint/components/visible_time_range_time.fbs @@ -16,5 +16,5 @@ table VisibleTimeRangeTime ( "attr.rust.repr": "transparent", "attr.rust.derive": "PartialEq, Eq" ) { - value: rerun.blueprint.datatypes.VisibleTimeRange (order: 100); + value: rerun.datatypes.VisibleTimeRange (order: 100); } diff --git a/crates/re_types/definitions/rerun/datatypes.fbs b/crates/re_types/definitions/rerun/datatypes.fbs index ebe1ef3c634c..9476e1060f73 100644 --- a/crates/re_types/definitions/rerun/datatypes.fbs +++ b/crates/re_types/definitions/rerun/datatypes.fbs @@ -36,5 +36,6 @@ include "./datatypes/uvec4d.fbs"; include "./datatypes/vec2d.fbs"; include "./datatypes/vec3d.fbs"; include "./datatypes/vec4d.fbs"; +include "./datatypes/visible_time_range.fbs"; namespace rerun.datatypes; diff --git a/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs b/crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs similarity index 68% rename from crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs rename to crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs index db49efad0b78..a5112fafba39 100644 --- a/crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs +++ b/crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs @@ -5,13 +5,13 @@ include "rust/attributes.fbs"; include "rerun/attributes.fbs"; -include "../../datatypes/time_int.fbs"; +include "time_int.fbs"; -namespace rerun.blueprint.datatypes; +namespace rerun.datatypes; /// Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. enum VisibleTimeRangeBoundaryKind: byte ( - "attr.rerun.scope": "blueprint" + "attr.rust.override_crate": "re_types_core" ) { /// Boundary is a value relative to the time cursor. RelativeToTimeCursor, @@ -25,10 +25,11 @@ enum VisibleTimeRangeBoundaryKind: byte ( /// Type of boundary for visible history. struct VisibleTimeRangeBoundary ( - "attr.rerun.scope": "blueprint" + "attr.rust.derive": "Copy", + "attr.rust.override_crate": "re_types_core" ) { /// Type of the boundary. - kind: rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind (order: 100); + kind: rerun.datatypes.VisibleTimeRangeBoundaryKind (order: 100); /// Value of the boundary (ignored for `Infinite` type). time: rerun.datatypes.TimeInt (order: 200); @@ -38,13 +39,13 @@ struct VisibleTimeRangeBoundary ( /// /// This datatype does not specify whether it's a time or sequence based timeline. struct VisibleTimeRange ( - "attr.rerun.scope": "blueprint", - "attr.rust.derive": "PartialEq, Eq" + "attr.rust.derive": "PartialEq, Eq", + "attr.rust.override_crate": "re_types_core" ) { /// Low time boundary for sequence timeline. // Can't call it `from` because it's a reserved keyword in Python. - start: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 100); + start: rerun.datatypes.VisibleTimeRangeBoundary (order: 100); /// High time boundary for sequence timeline. - end: rerun.blueprint.datatypes.VisibleTimeRangeBoundary (order: 200); + end: rerun.datatypes.VisibleTimeRangeBoundary (order: 200); } diff --git a/crates/re_types/src/blueprint/components/visible_time_range_sequence.rs b/crates/re_types/src/blueprint/components/visible_time_range_sequence.rs index e923ce32eaf6..3a00cadb54e0 100644 --- a/crates/re_types/src/blueprint/components/visible_time_range_sequence.rs +++ b/crates/re_types/src/blueprint/components/visible_time_range_sequence.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: The range of values on time timelines that will be included in a space view query. #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] -pub struct VisibleTimeRangeSequence(pub crate::blueprint::datatypes::VisibleTimeRange); +pub struct VisibleTimeRangeSequence(pub crate::datatypes::VisibleTimeRange); impl ::re_types_core::SizeBytes for VisibleTimeRangeSequence { #[inline] @@ -35,30 +35,28 @@ impl ::re_types_core::SizeBytes for VisibleTimeRangeSequence { #[inline] fn is_pod() -> bool { - ::is_pod() + ::is_pod() } } -impl> From for VisibleTimeRangeSequence { +impl> From for VisibleTimeRangeSequence { fn from(v: T) -> Self { Self(v.into()) } } -impl std::borrow::Borrow - for VisibleTimeRangeSequence -{ +impl std::borrow::Borrow for VisibleTimeRangeSequence { #[inline] - fn borrow(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + fn borrow(&self) -> &crate::datatypes::VisibleTimeRange { &self.0 } } impl std::ops::Deref for VisibleTimeRangeSequence { - type Target = crate::blueprint::datatypes::VisibleTimeRange; + type Target = crate::datatypes::VisibleTimeRange; #[inline] - fn deref(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + fn deref(&self) -> &crate::datatypes::VisibleTimeRange { &self.0 } } @@ -80,12 +78,12 @@ impl ::re_types_core::Loggable for VisibleTimeRangeSequence { DataType::Struct(std::sync::Arc::new(vec![ Field::new( "start", - ::arrow_datatype(), + ::arrow_datatype(), false, ), Field::new( "end", - ::arrow_datatype(), + ::arrow_datatype(), false, ), ])) @@ -118,7 +116,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeSequence { }; { _ = data0_bitmap; - crate::blueprint::datatypes::VisibleTimeRange::to_arrow_opt(data0)? + crate::datatypes::VisibleTimeRange::to_arrow_opt(data0)? } }) } @@ -133,7 +131,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeSequence { use ::re_types_core::{Loggable as _, ResultExt as _}; use arrow2::{array::*, buffer::*, datatypes::*}; Ok( - crate::blueprint::datatypes::VisibleTimeRange::from_arrow_opt(arrow_data) + crate::datatypes::VisibleTimeRange::from_arrow_opt(arrow_data) .with_context("rerun.blueprint.components.VisibleTimeRangeSequence#value")? .into_iter() .map(|v| v.ok_or_else(DeserializationError::missing_data)) diff --git a/crates/re_types/src/blueprint/components/visible_time_range_time.rs b/crates/re_types/src/blueprint/components/visible_time_range_time.rs index a3ac1fc08402..f37504c83705 100644 --- a/crates/re_types/src/blueprint/components/visible_time_range_time.rs +++ b/crates/re_types/src/blueprint/components/visible_time_range_time.rs @@ -25,7 +25,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: The range of values on sequence timelines that will be included in a space view query. #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] -pub struct VisibleTimeRangeTime(pub crate::blueprint::datatypes::VisibleTimeRange); +pub struct VisibleTimeRangeTime(pub crate::datatypes::VisibleTimeRange); impl ::re_types_core::SizeBytes for VisibleTimeRangeTime { #[inline] @@ -35,28 +35,28 @@ impl ::re_types_core::SizeBytes for VisibleTimeRangeTime { #[inline] fn is_pod() -> bool { - ::is_pod() + ::is_pod() } } -impl> From for VisibleTimeRangeTime { +impl> From for VisibleTimeRangeTime { fn from(v: T) -> Self { Self(v.into()) } } -impl std::borrow::Borrow for VisibleTimeRangeTime { +impl std::borrow::Borrow for VisibleTimeRangeTime { #[inline] - fn borrow(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + fn borrow(&self) -> &crate::datatypes::VisibleTimeRange { &self.0 } } impl std::ops::Deref for VisibleTimeRangeTime { - type Target = crate::blueprint::datatypes::VisibleTimeRange; + type Target = crate::datatypes::VisibleTimeRange; #[inline] - fn deref(&self) -> &crate::blueprint::datatypes::VisibleTimeRange { + fn deref(&self) -> &crate::datatypes::VisibleTimeRange { &self.0 } } @@ -78,12 +78,12 @@ impl ::re_types_core::Loggable for VisibleTimeRangeTime { DataType::Struct(std::sync::Arc::new(vec![ Field::new( "start", - ::arrow_datatype(), + ::arrow_datatype(), false, ), Field::new( "end", - ::arrow_datatype(), + ::arrow_datatype(), false, ), ])) @@ -116,7 +116,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeTime { }; { _ = data0_bitmap; - crate::blueprint::datatypes::VisibleTimeRange::to_arrow_opt(data0)? + crate::datatypes::VisibleTimeRange::to_arrow_opt(data0)? } }) } @@ -131,7 +131,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeTime { use ::re_types_core::{Loggable as _, ResultExt as _}; use arrow2::{array::*, buffer::*, datatypes::*}; Ok( - crate::blueprint::datatypes::VisibleTimeRange::from_arrow_opt(arrow_data) + crate::datatypes::VisibleTimeRange::from_arrow_opt(arrow_data) .with_context("rerun.blueprint.components.VisibleTimeRangeTime#value")? .into_iter() .map(|v| v.ok_or_else(DeserializationError::missing_data)) diff --git a/crates/re_types/src/blueprint/datatypes/.gitattributes b/crates/re_types/src/blueprint/datatypes/.gitattributes deleted file mode 100644 index 788b8f6860a3..000000000000 --- a/crates/re_types/src/blueprint/datatypes/.gitattributes +++ /dev/null @@ -1,7 +0,0 @@ -# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs - -.gitattributes linguist-generated=true -mod.rs linguist-generated=true -visible_time_range.rs linguist-generated=true -visible_time_range_boundary.rs linguist-generated=true -visible_time_range_boundary_kind.rs linguist-generated=true diff --git a/crates/re_types/src/blueprint/datatypes/mod.rs b/crates/re_types/src/blueprint/datatypes/mod.rs deleted file mode 100644 index c843412e734b..000000000000 --- a/crates/re_types/src/blueprint/datatypes/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs - -mod visible_time_range; -mod visible_time_range_boundary; -mod visible_time_range_boundary_ext; -mod visible_time_range_boundary_kind; -mod visible_time_range_ext; - -pub use self::visible_time_range::VisibleTimeRange; -pub use self::visible_time_range_boundary::VisibleTimeRangeBoundary; -pub use self::visible_time_range_boundary_kind::VisibleTimeRangeBoundaryKind; diff --git a/crates/re_types/src/blueprint/mod.rs b/crates/re_types/src/blueprint/mod.rs index 6dbc2b84ebd7..765990b52c30 100644 --- a/crates/re_types/src/blueprint/mod.rs +++ b/crates/re_types/src/blueprint/mod.rs @@ -4,8 +4,5 @@ pub mod archetypes; /// The blueprint-specific components. pub mod components; -/// The blueprint-specific datatypes. -pub mod datatypes; - /// The blueprint-specific views. pub mod views; diff --git a/crates/re_types_core/Cargo.toml b/crates/re_types_core/Cargo.toml index 97cceda54a6b..6c3de666a0d5 100644 --- a/crates/re_types_core/Cargo.toml +++ b/crates/re_types_core/Cargo.toml @@ -44,6 +44,7 @@ arrow2 = { workspace = true, features = [ backtrace.workspace = true bytemuck.workspace = true document-features.workspace = true +itertools.workspace = true once_cell.workspace = true smallvec.workspace = true thiserror.workspace = true diff --git a/crates/re_types_core/src/datatypes/.gitattributes b/crates/re_types_core/src/datatypes/.gitattributes index 8d8025b30391..af7ae477ab6d 100644 --- a/crates/re_types_core/src/datatypes/.gitattributes +++ b/crates/re_types_core/src/datatypes/.gitattributes @@ -8,3 +8,6 @@ time_int.rs linguist-generated=true uint32.rs linguist-generated=true uint64.rs linguist-generated=true utf8.rs linguist-generated=true +visible_time_range.rs linguist-generated=true +visible_time_range_boundary.rs linguist-generated=true +visible_time_range_boundary_kind.rs linguist-generated=true diff --git a/crates/re_types_core/src/datatypes/mod.rs b/crates/re_types_core/src/datatypes/mod.rs index b3afd8508146..bd7e3853d41e 100644 --- a/crates/re_types_core/src/datatypes/mod.rs +++ b/crates/re_types_core/src/datatypes/mod.rs @@ -8,6 +8,11 @@ mod uint32; mod uint64; mod utf8; mod utf8_ext; +mod visible_time_range; +mod visible_time_range_boundary; +mod visible_time_range_boundary_ext; +mod visible_time_range_boundary_kind; +mod visible_time_range_ext; pub use self::entity_path::EntityPath; pub use self::float32::Float32; @@ -15,3 +20,6 @@ pub use self::time_int::TimeInt; pub use self::uint32::UInt32; pub use self::uint64::UInt64; pub use self::utf8::Utf8; +pub use self::visible_time_range::VisibleTimeRange; +pub use self::visible_time_range_boundary::VisibleTimeRangeBoundary; +pub use self::visible_time_range_boundary_kind::VisibleTimeRangeBoundaryKind; diff --git a/crates/re_types_core/src/datatypes/time_int_ext.rs b/crates/re_types_core/src/datatypes/time_int_ext.rs index 511f0efc2676..6d46ec4f3f64 100644 --- a/crates/re_types_core/src/datatypes/time_int_ext.rs +++ b/crates/re_types_core/src/datatypes/time_int_ext.rs @@ -4,3 +4,21 @@ impl TimeInt { pub const MIN: Self = Self(i64::MIN); pub const MAX: Self = Self(i64::MAX); } + +impl std::ops::Add for TimeInt { + type Output = Self; + + #[inline] + fn add(self, rhs: Self) -> Self::Output { + Self(self.0.saturating_add(rhs.0)) + } +} + +impl std::ops::Sub for TimeInt { + type Output = Self; + + #[inline] + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0.saturating_sub(rhs.0)) + } +} diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range.rs b/crates/re_types_core/src/datatypes/visible_time_range.rs similarity index 71% rename from crates/re_types/src/blueprint/datatypes/visible_time_range.rs rename to crates/re_types_core/src/datatypes/visible_time_range.rs index cafb80d1fbdd..56fe77f0881c 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range.rs +++ b/crates/re_types_core/src/datatypes/visible_time_range.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -16,11 +16,11 @@ #![allow(clippy::too_many_lines)] #![allow(clippy::unnecessary_cast)] -use ::re_types_core::external::arrow2; -use ::re_types_core::ComponentName; -use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; -use ::re_types_core::{DeserializationError, DeserializationResult}; +use crate::external::arrow2; +use crate::ComponentName; +use crate::SerializationResult; +use crate::{ComponentBatch, MaybeOwnedComponentBatch}; +use crate::{DeserializationError, DeserializationResult}; /// **Datatype**: Visible time range bounds for a timelines. /// @@ -28,13 +28,13 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct VisibleTimeRange { /// Low time boundary for sequence timeline. - pub start: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + pub start: crate::datatypes::VisibleTimeRangeBoundary, /// High time boundary for sequence timeline. - pub end: crate::blueprint::datatypes::VisibleTimeRangeBoundary, + pub end: crate::datatypes::VisibleTimeRangeBoundary, } -impl ::re_types_core::SizeBytes for VisibleTimeRange { +impl crate::SizeBytes for VisibleTimeRange { #[inline] fn heap_size_bytes(&self) -> u64 { self.start.heap_size_bytes() + self.end.heap_size_bytes() @@ -42,19 +42,19 @@ impl ::re_types_core::SizeBytes for VisibleTimeRange { #[inline] fn is_pod() -> bool { - ::is_pod() - && ::is_pod() + ::is_pod() + && ::is_pod() } } -::re_types_core::macros::impl_into_cow!(VisibleTimeRange); +crate::macros::impl_into_cow!(VisibleTimeRange); -impl ::re_types_core::Loggable for VisibleTimeRange { - type Name = ::re_types_core::DatatypeName; +impl crate::Loggable for VisibleTimeRange { + type Name = crate::DatatypeName; #[inline] fn name() -> Self::Name { - "rerun.blueprint.datatypes.VisibleTimeRange".into() + "rerun.datatypes.VisibleTimeRange".into() } #[allow(clippy::wildcard_imports)] @@ -64,12 +64,12 @@ impl ::re_types_core::Loggable for VisibleTimeRange { DataType::Struct(std::sync::Arc::new(vec![ Field::new( "start", - ::arrow_datatype(), + ::arrow_datatype(), false, ), Field::new( "end", - ::arrow_datatype(), + ::arrow_datatype(), false, ), ])) @@ -82,7 +82,7 @@ impl ::re_types_core::Loggable for VisibleTimeRange { where Self: Clone + 'a, { - use ::re_types_core::{Loggable as _, ResultExt as _}; + use crate::{Loggable as _, ResultExt as _}; use arrow2::{array::*, datatypes::*}; Ok({ let (somes, data): (Vec<_>, Vec<_>) = data @@ -97,7 +97,7 @@ impl ::re_types_core::Loggable for VisibleTimeRange { any_nones.then(|| somes.into()) }; StructArray::new( - ::arrow_datatype(), + ::arrow_datatype(), vec![ { let (somes, start): (Vec<_>, Vec<_>) = data @@ -116,9 +116,7 @@ impl ::re_types_core::Loggable for VisibleTimeRange { }; { _ = start_bitmap; - crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( - start, - )? + crate::datatypes::VisibleTimeRangeBoundary::to_arrow_opt(start)? } }, { @@ -138,9 +136,7 @@ impl ::re_types_core::Loggable for VisibleTimeRange { }; { _ = end_bitmap; - crate::blueprint::datatypes::VisibleTimeRangeBoundary::to_arrow_opt( - end, - )? + crate::datatypes::VisibleTimeRangeBoundary::to_arrow_opt(end)? } }, ], @@ -157,7 +153,7 @@ impl ::re_types_core::Loggable for VisibleTimeRange { where Self: Sized, { - use ::re_types_core::{Loggable as _, ResultExt as _}; + use crate::{Loggable as _, ResultExt as _}; use arrow2::{array::*, buffer::*, datatypes::*}; Ok({ let arrow_data = arrow_data @@ -168,7 +164,7 @@ impl ::re_types_core::Loggable for VisibleTimeRange { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange")?; + .with_context("rerun.datatypes.VisibleTimeRange")?; if arrow_data.is_empty() { Vec::new() } else { @@ -185,14 +181,12 @@ impl ::re_types_core::Loggable for VisibleTimeRange { Self::arrow_datatype(), "start", )) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + .with_context("rerun.datatypes.VisibleTimeRange"); } let arrow_data = &**arrays_by_name["start"]; - crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( - arrow_data, - ) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange#start")? - .into_iter() + crate::datatypes::VisibleTimeRangeBoundary::from_arrow_opt(arrow_data) + .with_context("rerun.datatypes.VisibleTimeRange#start")? + .into_iter() }; let end = { if !arrays_by_name.contains_key("end") { @@ -200,14 +194,12 @@ impl ::re_types_core::Loggable for VisibleTimeRange { Self::arrow_datatype(), "end", )) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange"); + .with_context("rerun.datatypes.VisibleTimeRange"); } let arrow_data = &**arrays_by_name["end"]; - crate::blueprint::datatypes::VisibleTimeRangeBoundary::from_arrow_opt( - arrow_data, - ) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange#end")? - .into_iter() + crate::datatypes::VisibleTimeRangeBoundary::from_arrow_opt(arrow_data) + .with_context("rerun.datatypes.VisibleTimeRange#end")? + .into_iter() }; arrow2::bitmap::utils::ZipValidity::new_with_validity( ::itertools::izip!(start, end), @@ -218,16 +210,16 @@ impl ::re_types_core::Loggable for VisibleTimeRange { Ok(Self { start: start .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange#start")?, + .with_context("rerun.datatypes.VisibleTimeRange#start")?, end: end .ok_or_else(DeserializationError::missing_data) - .with_context("rerun.blueprint.datatypes.VisibleTimeRange#end")?, + .with_context("rerun.datatypes.VisibleTimeRange#end")?, }) }) .transpose() }) .collect::>>() - .with_context("rerun.blueprint.datatypes.VisibleTimeRange")? + .with_context("rerun.datatypes.VisibleTimeRange")? } }) } diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs b/crates/re_types_core/src/datatypes/visible_time_range_boundary.rs similarity index 77% rename from crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs rename to crates/re_types_core/src/datatypes/visible_time_range_boundary.rs index 67cf73938af7..f9c1dd1917c9 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary.rs +++ b/crates/re_types_core/src/datatypes/visible_time_range_boundary.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -16,23 +16,23 @@ #![allow(clippy::too_many_lines)] #![allow(clippy::unnecessary_cast)] -use ::re_types_core::external::arrow2; -use ::re_types_core::ComponentName; -use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; -use ::re_types_core::{DeserializationError, DeserializationResult}; +use crate::external::arrow2; +use crate::ComponentName; +use crate::SerializationResult; +use crate::{ComponentBatch, MaybeOwnedComponentBatch}; +use crate::{DeserializationError, DeserializationResult}; /// **Datatype**: Type of boundary for visible history. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Copy)] pub struct VisibleTimeRangeBoundary { /// Type of the boundary. - pub kind: crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind, + pub kind: crate::datatypes::VisibleTimeRangeBoundaryKind, /// Value of the boundary (ignored for `Infinite` type). pub time: crate::datatypes::TimeInt, } -impl ::re_types_core::SizeBytes for VisibleTimeRangeBoundary { +impl crate::SizeBytes for VisibleTimeRangeBoundary { #[inline] fn heap_size_bytes(&self) -> u64 { self.kind.heap_size_bytes() + self.time.heap_size_bytes() @@ -40,19 +40,19 @@ impl ::re_types_core::SizeBytes for VisibleTimeRangeBoundary { #[inline] fn is_pod() -> bool { - ::is_pod() + ::is_pod() && ::is_pod() } } -::re_types_core::macros::impl_into_cow!(VisibleTimeRangeBoundary); +crate::macros::impl_into_cow!(VisibleTimeRangeBoundary); -impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { - type Name = ::re_types_core::DatatypeName; +impl crate::Loggable for VisibleTimeRangeBoundary { + type Name = crate::DatatypeName; #[inline] fn name() -> Self::Name { - "rerun.blueprint.datatypes.VisibleTimeRangeBoundary".into() + "rerun.datatypes.VisibleTimeRangeBoundary".into() } #[allow(clippy::wildcard_imports)] @@ -62,7 +62,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { DataType::Struct(std::sync::Arc::new(vec![ Field::new( "kind", - ::arrow_datatype(), + ::arrow_datatype(), false, ), Field::new("time", ::arrow_datatype(), false), @@ -76,7 +76,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { where Self: Clone + 'a, { - use ::re_types_core::{Loggable as _, ResultExt as _}; + use crate::{Loggable as _, ResultExt as _}; use arrow2::{array::*, datatypes::*}; Ok({ let (somes, data): (Vec<_>, Vec<_>) = data @@ -91,7 +91,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { any_nones.then(|| somes.into()) }; StructArray::new( - ::arrow_datatype(), + ::arrow_datatype(), vec![ { let (somes, kind): (Vec<_>, Vec<_>) = data @@ -110,9 +110,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { }; { _ = kind_bitmap; - crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind::to_arrow_opt( - kind, - )? + crate::datatypes::VisibleTimeRangeBoundaryKind::to_arrow_opt(kind)? } }, { @@ -160,7 +158,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { where Self: Sized, { - use ::re_types_core::{Loggable as _, ResultExt as _}; + use crate::{Loggable as _, ResultExt as _}; use arrow2::{array::*, buffer::*, datatypes::*}; Ok({ let arrow_data = arrow_data @@ -171,7 +169,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary")?; + .with_context("rerun.datatypes.VisibleTimeRangeBoundary")?; if arrow_data.is_empty() { Vec::new() } else { @@ -188,14 +186,12 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { Self::arrow_datatype(), "kind", )) - .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary"); + .with_context("rerun.datatypes.VisibleTimeRangeBoundary"); } let arrow_data = &**arrays_by_name["kind"]; - crate::blueprint::datatypes::VisibleTimeRangeBoundaryKind::from_arrow_opt( - arrow_data, - ) - .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary#kind")? - .into_iter() + crate::datatypes::VisibleTimeRangeBoundaryKind::from_arrow_opt(arrow_data) + .with_context("rerun.datatypes.VisibleTimeRangeBoundary#kind")? + .into_iter() }; let time = { if !arrays_by_name.contains_key("time") { @@ -203,7 +199,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { Self::arrow_datatype(), "time", )) - .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary"); + .with_context("rerun.datatypes.VisibleTimeRangeBoundary"); } let arrow_data = &**arrays_by_name["time"]; arrow_data @@ -214,7 +210,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary#time")? + .with_context("rerun.datatypes.VisibleTimeRangeBoundary#time")? .into_iter() .map(|opt| opt.copied()) .map(|res_or_opt| res_or_opt.map(|v| crate::datatypes::TimeInt(v))) @@ -228,20 +224,16 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundary { Ok(Self { kind: kind .ok_or_else(DeserializationError::missing_data) - .with_context( - "rerun.blueprint.datatypes.VisibleTimeRangeBoundary#kind", - )?, + .with_context("rerun.datatypes.VisibleTimeRangeBoundary#kind")?, time: time .ok_or_else(DeserializationError::missing_data) - .with_context( - "rerun.blueprint.datatypes.VisibleTimeRangeBoundary#time", - )?, + .with_context("rerun.datatypes.VisibleTimeRangeBoundary#time")?, }) }) .transpose() }) .collect::>>() - .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundary")? + .with_context("rerun.datatypes.VisibleTimeRangeBoundary")? } }) } diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs b/crates/re_types_core/src/datatypes/visible_time_range_boundary_ext.rs similarity index 78% rename from crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs rename to crates/re_types_core/src/datatypes/visible_time_range_boundary_ext.rs index d4ce92441b81..84ed070b67be 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_ext.rs +++ b/crates/re_types_core/src/datatypes/visible_time_range_boundary_ext.rs @@ -1,5 +1,4 @@ -use super::{VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}; -use re_types_core::datatypes::TimeInt; +use super::{TimeInt, VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind}; impl VisibleTimeRangeBoundary { /// Put the boundary at the current time cursor. @@ -34,6 +33,22 @@ impl VisibleTimeRangeBoundary { VisibleTimeRangeBoundaryKind::Infinite => TimeInt::MAX, } } + + /// Creates a new absolute boundary. + pub fn absolute(time: TimeInt) -> Self { + Self { + kind: VisibleTimeRangeBoundaryKind::Absolute, + time, + } + } + + /// Creates a new cursor relative boundary. + pub fn relative_to_time_cursor(time: TimeInt) -> Self { + Self { + kind: VisibleTimeRangeBoundaryKind::RelativeToTimeCursor, + time, + } + } } impl PartialEq for VisibleTimeRangeBoundary { diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs b/crates/re_types_core/src/datatypes/visible_time_range_boundary_kind.rs similarity index 82% rename from crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs rename to crates/re_types_core/src/datatypes/visible_time_range_boundary_kind.rs index 68b20a39af00..fb5ee7e5d11a 100644 --- a/crates/re_types/src/blueprint/datatypes/visible_time_range_boundary_kind.rs +++ b/crates/re_types_core/src/datatypes/visible_time_range_boundary_kind.rs @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/rust/api.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #![allow(trivial_numeric_casts)] #![allow(unused_imports)] @@ -16,11 +16,11 @@ #![allow(clippy::too_many_lines)] #![allow(clippy::unnecessary_cast)] -use ::re_types_core::external::arrow2; -use ::re_types_core::ComponentName; -use ::re_types_core::SerializationResult; -use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; -use ::re_types_core::{DeserializationError, DeserializationResult}; +use crate::external::arrow2; +use crate::ComponentName; +use crate::SerializationResult; +use crate::{ComponentBatch, MaybeOwnedComponentBatch}; +use crate::{DeserializationError, DeserializationResult}; /// **Datatype**: Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -40,7 +40,7 @@ impl VisibleTimeRangeBoundaryKind { pub const ALL: [Self; 3] = [Self::RelativeToTimeCursor, Self::Absolute, Self::Infinite]; } -impl ::re_types_core::SizeBytes for VisibleTimeRangeBoundaryKind { +impl crate::SizeBytes for VisibleTimeRangeBoundaryKind { #[inline] fn heap_size_bytes(&self) -> u64 { 0 @@ -62,14 +62,14 @@ impl std::fmt::Display for VisibleTimeRangeBoundaryKind { } } -::re_types_core::macros::impl_into_cow!(VisibleTimeRangeBoundaryKind); +crate::macros::impl_into_cow!(VisibleTimeRangeBoundaryKind); -impl ::re_types_core::Loggable for VisibleTimeRangeBoundaryKind { - type Name = ::re_types_core::DatatypeName; +impl crate::Loggable for VisibleTimeRangeBoundaryKind { + type Name = crate::DatatypeName; #[inline] fn name() -> Self::Name { - "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind".into() + "rerun.datatypes.VisibleTimeRangeBoundaryKind".into() } #[allow(clippy::wildcard_imports)] @@ -95,7 +95,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundaryKind { where Self: Clone + 'a, { - use ::re_types_core::{Loggable as _, ResultExt as _}; + use crate::{Loggable as _, ResultExt as _}; use arrow2::{array::*, datatypes::*}; Ok({ let data: Vec<_> = data @@ -118,7 +118,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundaryKind { .take(1 + num_variants) .collect(); UnionArray::new( - ::arrow_datatype(), + ::arrow_datatype(), types, fields, None, @@ -134,7 +134,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundaryKind { where Self: Sized, { - use ::re_types_core::{Loggable as _, ResultExt as _}; + use crate::{Loggable as _, ResultExt as _}; use arrow2::{array::*, buffer::*, datatypes::*}; Ok({ let arrow_data = arrow_data @@ -145,7 +145,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundaryKind { let actual = arrow_data.data_type().clone(); DeserializationError::datatype_mismatch(expected, actual) }) - .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind")?; + .with_context("rerun.datatypes.VisibleTimeRangeBoundaryKind")?; let arrow_data_types = arrow_data.types(); arrow_data_types .iter() @@ -161,7 +161,7 @@ impl ::re_types_core::Loggable for VisibleTimeRangeBoundaryKind { )), }) .collect::>>() - .with_context("rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind")? + .with_context("rerun.datatypes.VisibleTimeRangeBoundaryKind")? }) } } diff --git a/crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs b/crates/re_types_core/src/datatypes/visible_time_range_ext.rs similarity index 100% rename from crates/re_types/src/blueprint/datatypes/visible_time_range_ext.rs rename to crates/re_types_core/src/datatypes/visible_time_range_ext.rs diff --git a/crates/re_viewer/src/ui/visual_time_range.rs b/crates/re_viewer/src/ui/visual_time_range.rs index beb69d6f4b1b..67449aaea0cf 100644 --- a/crates/re_viewer/src/ui/visual_time_range.rs +++ b/crates/re_viewer/src/ui/visual_time_range.rs @@ -3,20 +3,15 @@ use std::ops::RangeInclusive; use egui::{NumExt as _, Response, Ui}; -use re_entity_db::{TimeHistogram, VisibleHistory, VisibleHistoryBoundary}; -use re_log_types::{EntityPath, TimeInt, TimeType, TimeZone}; -use re_space_view::{ - query_view_property, time_range_from_visible_time_range, - visible_history_boundary_from_time_range_boundary, - visible_history_boundary_to_time_range_boundary, SpaceViewBlueprint, -}; +use re_entity_db::TimeHistogram; +use re_log_types::{EntityPath, TimeRange, TimeType, TimeZone}; +use re_space_view::{query_view_property, SpaceViewBlueprint}; use re_space_view_spatial::{SpatialSpaceView2D, SpatialSpaceView3D}; use re_space_view_time_series::TimeSeriesSpaceView; use re_types::{ - blueprint::{ - archetypes::VisibleTimeRange, - components::{VisibleTimeRangeSequence, VisibleTimeRangeTime}, - datatypes::VisibleTimeRangeBoundary, + blueprint::components::{VisibleTimeRangeSequence, VisibleTimeRangeTime}, + datatypes::{ + TimeInt, VisibleTimeRange, VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind, }, SpaceViewClassIdentifier, }; @@ -55,11 +50,12 @@ pub fn visual_time_range_ui_space_view( let time_ctrl = ctx.rec_cfg.time_ctrl.read().clone(); let time_type = time_ctrl.timeline().typ(); - let (property, property_path) = query_view_property::( - space_view.id, - ctx.store_context.blueprint, - ctx.blueprint_query, - ); + let (property, property_path) = + query_view_property::( + space_view.id, + ctx.store_context.blueprint, + ctx.blueprint_query, + ); let has_individual_range = match time_type { TimeType::Time => property.ok().flatten().map_or(false, |v| v.time.is_some()), @@ -145,7 +141,7 @@ fn visual_time_range_ui( re_log::error_once!("Visible time range is set but no time range is provided"); } // TODO(andreas): Should print a string that we're using the latest time. - re_types::blueprint::datatypes::VisibleTimeRange { + re_types::datatypes::VisibleTimeRange { start: VisibleTimeRangeBoundary::AT_CURSOR, end: VisibleTimeRangeBoundary::AT_CURSOR, } @@ -183,79 +179,65 @@ fn visual_time_range_ui( TimelineSpec::from_time_range(0..=0) }; - let current_time = time_ctrl - .time_i64() - .unwrap_or_default() - .at_least(*timeline_spec.range.start()); // accounts for timeless time (TimeInt::MIN) - - let from = &mut resolved_range.start; - let to = &mut resolved_range.end; - - // Convert to legacy visual history type. - let mut visible_history = VisibleHistory { - from: visible_history_boundary_from_time_range_boundary(from), - to: visible_history_boundary_from_time_range_boundary(to), - }; + let current_time = TimeInt( + time_ctrl + .time_i64() + .unwrap_or_default() + .at_least(*timeline_spec.range.start()), + ); // accounts for timeless time (TimeInt::MIN) if has_individual_range { - let current_from = visible_history - .range_start_from_cursor(TimeInt::new_temporal(current_time)) - .as_i64(); - let current_to = visible_history - .range_end_from_cursor(TimeInt::new_temporal(current_time)) - .as_i64(); + let current_start = resolved_range.start.start_boundary_time(current_time); + let current_end = resolved_range.end.end_boundary_time(current_time); egui::Grid::new("from_to_editable").show(ui, |ui| { - re_ui.grid_left_hand_label(ui, "From"); + re_ui.grid_left_hand_label(ui, "Start"); interacting_with_controls |= ui .horizontal(|ui| { visible_history_boundary_ui( ctx, ui, - &mut visible_history.from, + &mut resolved_range.start, time_type, current_time, &timeline_spec, true, - current_to, + current_end, ) }) .inner; ui.end_row(); - re_ui.grid_left_hand_label(ui, "To"); + re_ui.grid_left_hand_label(ui, "End"); interacting_with_controls |= ui .horizontal(|ui| { visible_history_boundary_ui( ctx, ui, - &mut visible_history.to, + &mut resolved_range.end, time_type, current_time, &timeline_spec, false, - current_from, + current_start, ) }) .inner; ui.end_row(); }); - current_range_ui(ctx, ui, current_time, time_type, &visible_history); + current_range_ui(ctx, ui, current_time, time_type, &resolved_range); } else { // Show the resolved visible range as labels (user can't edit them): - if visible_history.from == VisibleHistoryBoundary::Infinite - && visible_history.to == VisibleHistoryBoundary::Infinite + if resolved_range.start.kind == VisibleTimeRangeBoundaryKind::Infinite + && resolved_range.end.kind == VisibleTimeRangeBoundaryKind::Infinite { ui.label("Entire timeline"); - } else if visible_history.from == VisibleHistoryBoundary::AT_CURSOR - && visible_history.to == VisibleHistoryBoundary::AT_CURSOR + } else if resolved_range.start == VisibleTimeRangeBoundary::AT_CURSOR + && resolved_range.end == VisibleTimeRangeBoundary::AT_CURSOR { - let current_time = time_type.format( - TimeInt::new_temporal(current_time), - ctx.app_options.time_zone, - ); + let current_time = time_type.format(current_time, ctx.app_options.time_zone); match time_type { TimeType::Time => { ui.label(format!("At current time: {current_time}")); @@ -270,7 +252,7 @@ fn visual_time_range_ui( resolved_visible_history_boundary_ui( ctx, ui, - &visible_history.from, + &resolved_range.start, time_type, true, ); @@ -280,21 +262,17 @@ fn visual_time_range_ui( resolved_visible_history_boundary_ui( ctx, ui, - &visible_history.to, + &resolved_range.end, time_type, false, ); ui.end_row(); }); - current_range_ui(ctx, ui, current_time, time_type, &visible_history); + current_range_ui(ctx, ui, current_time, time_type, &resolved_range); } } - // Convert back from visual history type. - *from = visible_history_boundary_to_time_range_boundary(&visible_history.from); - *to = visible_history_boundary_to_time_range_boundary(&visible_history.to); - // Save to blueprint store if anything has changed. if has_individual_range != has_individual_range_before || resolved_range != resolved_range_before @@ -355,7 +333,7 @@ fn visual_time_range_ui( if should_display_visible_history { if let Some(current_time) = time_ctrl.time_int() { - let range = time_range_from_visible_time_range(&resolved_range, current_time); + let range = TimeRange::from_visible_time_range(&resolved_range, current_time); ctx.rec_cfg.time_ctrl.write().highlighted_range = Some(range); } } @@ -383,11 +361,11 @@ Notes that the data current as of the time range starting time is included.", fn current_range_ui( ctx: &ViewerContext<'_>, ui: &mut Ui, - current_time: i64, + current_time: TimeInt, time_type: TimeType, - visible_history: &VisibleHistory, + visible_range: &VisibleTimeRange, ) { - let time_range = visible_history.time_range(TimeInt::new_temporal(current_time)); + let time_range = TimeRange::from_visible_time_range(visible_range, current_time); let from_formatted = time_type.format(time_range.min(), ctx.app_options.time_zone); let to_formatted = time_type.format(time_range.max(), ctx.app_options.time_zone); @@ -399,20 +377,20 @@ fn current_range_ui( fn resolved_visible_history_boundary_ui( ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - visible_history_boundary: &VisibleHistoryBoundary, + visible_history_boundary: &VisibleTimeRangeBoundary, time_type: TimeType, low_bound: bool, ) { - let boundary_type = match visible_history_boundary { - VisibleHistoryBoundary::RelativeToTimeCursor(_) => match time_type { + let boundary_type = match visible_history_boundary.kind { + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => match time_type { TimeType::Time => "current time", TimeType::Sequence => "current frame", }, - VisibleHistoryBoundary::Absolute(_) => match time_type { + VisibleTimeRangeBoundaryKind::Absolute => match time_type { TimeType::Time => "absolute time", TimeType::Sequence => "frame", }, - VisibleHistoryBoundary::Infinite => { + VisibleTimeRangeBoundaryKind::Infinite => { if low_bound { "beginning of timeline" } else { @@ -423,9 +401,10 @@ fn resolved_visible_history_boundary_ui( let mut label = boundary_type.to_owned(); - match visible_history_boundary { - VisibleHistoryBoundary::RelativeToTimeCursor(offset) => { - if *offset != 0 { + match visible_history_boundary.kind { + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => { + let offset = visible_history_boundary.time.0; + if offset != 0 { match time_type { TimeType::Time => { // This looks like it should be generically handled somewhere like re_format, @@ -442,7 +421,7 @@ fn resolved_visible_history_boundary_ui( ("ns", 1.) }; - label += &format!(" with {} {} offset", *offset as f64 / factor, unit); + label += &format!(" with {} {} offset", offset as f64 / factor, unit); } TimeType::Sequence => { label += &format!( @@ -453,33 +432,31 @@ fn resolved_visible_history_boundary_ui( } } } - VisibleHistoryBoundary::Absolute(time) => { - label += &format!( - " {}", - time_type.format(TimeInt::new_temporal(*time), ctx.app_options.time_zone) - ); + VisibleTimeRangeBoundaryKind::Absolute => { + let time = visible_history_boundary.time; + label += &format!(" {}", time_type.format(time, ctx.app_options.time_zone)); } - VisibleHistoryBoundary::Infinite => {} + VisibleTimeRangeBoundaryKind::Infinite => {} } ui.label(label); } fn visible_history_boundary_combo_label( - boundary: &VisibleHistoryBoundary, + boundary: VisibleTimeRangeBoundaryKind, time_type: TimeType, low_bound: bool, ) -> &'static str { match boundary { - VisibleHistoryBoundary::RelativeToTimeCursor(_) => match time_type { + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => match time_type { TimeType::Time => "current time with offset", TimeType::Sequence => "current frame with offset", }, - VisibleHistoryBoundary::Absolute(_) => match time_type { + VisibleTimeRangeBoundaryKind::Absolute => match time_type { TimeType::Time => "absolute time", TimeType::Sequence => "absolute frame", }, - VisibleHistoryBoundary::Infinite => { + VisibleTimeRangeBoundaryKind::Infinite => { if low_bound { "beginning of timeline" } else { @@ -493,20 +470,26 @@ fn visible_history_boundary_combo_label( fn visible_history_boundary_ui( ctx: &ViewerContext<'_>, ui: &mut egui::Ui, - visible_history_boundary: &mut VisibleHistoryBoundary, + visible_history_boundary: &mut VisibleTimeRangeBoundary, time_type: TimeType, - current_time: i64, + current_time: TimeInt, timeline_spec: &TimelineSpec, low_bound: bool, - other_boundary_absolute: i64, + other_boundary_absolute: TimeInt, ) -> bool { - let (abs_time, rel_time) = match visible_history_boundary { - VisibleHistoryBoundary::RelativeToTimeCursor(value) => (*value + current_time, *value), - VisibleHistoryBoundary::Absolute(value) => (*value, *value - current_time), - VisibleHistoryBoundary::Infinite => (current_time, 0), + let (abs_time, rel_time) = match visible_history_boundary.kind { + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => ( + visible_history_boundary.time + current_time, + visible_history_boundary.time, + ), + VisibleTimeRangeBoundaryKind::Absolute => ( + visible_history_boundary.time, + visible_history_boundary.time - current_time, + ), + VisibleTimeRangeBoundaryKind::Infinite => (current_time, TimeInt(0)), }; - let abs_time = VisibleHistoryBoundary::Absolute(abs_time); - let rel_time = VisibleHistoryBoundary::RelativeToTimeCursor(rel_time); + let abs_time = VisibleTimeRangeBoundary::absolute(abs_time); + let rel_time = VisibleTimeRangeBoundary::relative_to_time_cursor(rel_time); egui::ComboBox::from_id_source(if low_bound { "time_history_low_bound" @@ -514,7 +497,7 @@ fn visible_history_boundary_ui( "time_history_high_bound" }) .selected_text(visible_history_boundary_combo_label( - visible_history_boundary, + visible_history_boundary.kind, time_type, low_bound, )) @@ -524,7 +507,7 @@ fn visible_history_boundary_ui( ui.selectable_value( visible_history_boundary, rel_time, - visible_history_boundary_combo_label(&rel_time, time_type, low_bound), + visible_history_boundary_combo_label(rel_time.kind, time_type, low_bound), ) .on_hover_text(if low_bound { "Show data from a time point relative to the current time." @@ -534,7 +517,7 @@ fn visible_history_boundary_ui( ui.selectable_value( visible_history_boundary, abs_time, - visible_history_boundary_combo_label(&abs_time, time_type, low_bound), + visible_history_boundary_combo_label(abs_time.kind, time_type, low_bound), ) .on_hover_text(if low_bound { "Show data from an absolute time point." @@ -542,10 +525,10 @@ fn visible_history_boundary_ui( "Show data until an absolute time point." }); ui.selectable_value( - visible_history_boundary, - VisibleHistoryBoundary::Infinite, + &mut visible_history_boundary.kind, + VisibleTimeRangeBoundaryKind::Infinite, visible_history_boundary_combo_label( - &VisibleHistoryBoundary::Infinite, + VisibleTimeRangeBoundaryKind::Infinite, time_type, low_bound, ), @@ -564,14 +547,15 @@ fn visible_history_boundary_ui( // both boundaries fighting each other in some corner cases (when the user interacts with the // current time cursor) - let response = match visible_history_boundary { - VisibleHistoryBoundary::RelativeToTimeCursor(value) => { + let response = match visible_history_boundary.kind { + VisibleTimeRangeBoundaryKind::RelativeToTimeCursor => { // see note above let low_bound_override = if low_bound { None } else { - Some(other_boundary_absolute.saturating_sub(current_time)) + Some(other_boundary_absolute - current_time) }; + let value = &mut visible_history_boundary.time; match time_type { TimeType::Time => Some( @@ -599,13 +583,14 @@ fn visible_history_boundary_ui( ), } } - VisibleHistoryBoundary::Absolute(value) => { + VisibleTimeRangeBoundaryKind::Absolute => { // see note above let low_bound_override = if low_bound { None } else { Some(other_boundary_absolute) }; + let value = &mut visible_history_boundary.time; match time_type { TimeType::Time => { @@ -630,7 +615,7 @@ fn visible_history_boundary_ui( ), } } - VisibleHistoryBoundary::Infinite => None, + VisibleTimeRangeBoundaryKind::Infinite => None, }; response.map_or(false, |r| r.dragged() || r.has_focus()) @@ -698,9 +683,9 @@ impl TimelineSpec { fn sequence_drag_value( &self, ui: &mut egui::Ui, - value: &mut i64, + value: &mut TimeInt, absolute: bool, - low_bound_override: Option, + low_bound_override: Option, ) -> Response { let mut time_range = if absolute { self.abs_range.clone() @@ -713,11 +698,11 @@ impl TimelineSpec { let speed = (span as f32 * 0.005).at_least(1.0); if let Some(low_bound_override) = low_bound_override { - time_range = low_bound_override.at_least(*time_range.start())..=*time_range.end(); + time_range = low_bound_override.0.at_least(*time_range.start())..=*time_range.end(); } ui.add( - egui::DragValue::new(value) + egui::DragValue::new(&mut value.0) .clamp_range(time_range) .speed(speed), ) @@ -735,9 +720,9 @@ impl TimelineSpec { fn temporal_drag_value( &self, ui: &mut egui::Ui, - value: &mut i64, + value: &mut TimeInt, absolute: bool, - low_bound_override: Option, + low_bound_override: Option, time_zone_for_timestamps: TimeZone, ) -> (Response, Option) { let mut time_range = if absolute { @@ -757,10 +742,10 @@ impl TimelineSpec { let speed = (time_range.end() - time_range.start()) as f32 / factor * 0.005; if let Some(low_bound_override) = low_bound_override { - time_range = low_bound_override.at_least(*time_range.start())..=*time_range.end(); + time_range = low_bound_override.0.at_least(*time_range.start())..=*time_range.end(); } - let mut time_unit = (*value - offset) as f32 / factor; + let mut time_unit = (value.0 - offset) as f32 / factor; let time_range = (*time_range.start() - offset) as f32 / factor ..=(*time_range.end() - offset) as f32 / factor; @@ -769,8 +754,7 @@ impl TimelineSpec { self.base_time.map(|base_time| { ui.label(format!( "{} + ", - TimeType::Time - .format(TimeInt::new_temporal(base_time), time_zone_for_timestamps) + TimeType::Time.format(TimeInt(base_time), time_zone_for_timestamps) )) }) } else { @@ -784,7 +768,7 @@ impl TimelineSpec { .suffix(self.unit_symbol), ); - *value = (time_unit * factor).round() as i64 + offset; + *value = TimeInt((time_unit * factor).round() as i64 + offset); (drag_value_response, base_time_response) } diff --git a/crates/re_viewer_context/src/query_range.rs b/crates/re_viewer_context/src/query_range.rs index e0415a6749f7..f1ff8de53192 100644 --- a/crates/re_viewer_context/src/query_range.rs +++ b/crates/re_viewer_context/src/query_range.rs @@ -2,7 +2,7 @@ #[derive(Debug, Clone, PartialEq, Eq, Default)] pub enum QueryRange { /// Use a time range on the currently active timeline. - TimeRange(re_types::blueprint::datatypes::VisibleTimeRange), + TimeRange(re_types::datatypes::VisibleTimeRange), /// Use latest-at semantics. #[default] diff --git a/docs/content/reference/types/datatypes.md b/docs/content/reference/types/datatypes.md index 1c659f9ea3e5..cf967a4c6cf5 100644 --- a/docs/content/reference/types/datatypes.md +++ b/docs/content/reference/types/datatypes.md @@ -46,4 +46,7 @@ Data types are the lowest layer of the data model hierarchy. They are re-usable * [`Vec2D`](datatypes/vec2d.md): A vector in 2D space. * [`Vec3D`](datatypes/vec3d.md): A vector in 3D space. * [`Vec4D`](datatypes/vec4d.md): A vector in 4D space. +* [`VisibleTimeRange`](datatypes/visible_time_range.md): Visible time range bounds for a timelines. +* [`VisibleTimeRangeBoundary`](datatypes/visible_time_range_boundary.md): Type of boundary for visible history. +* [`VisibleTimeRangeBoundaryKind`](datatypes/visible_time_range_boundary_kind.md): Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. diff --git a/docs/content/reference/types/datatypes/.gitattributes b/docs/content/reference/types/datatypes/.gitattributes index 1a82697fda80..978f61efb039 100644 --- a/docs/content/reference/types/datatypes/.gitattributes +++ b/docs/content/reference/types/datatypes/.gitattributes @@ -39,3 +39,6 @@ uvec4d.md linguist-generated=true vec2d.md linguist-generated=true vec3d.md linguist-generated=true vec4d.md linguist-generated=true +visible_time_range.md linguist-generated=true +visible_time_range_boundary.md linguist-generated=true +visible_time_range_boundary_kind.md linguist-generated=true diff --git a/docs/content/reference/types/datatypes/time_int.md b/docs/content/reference/types/datatypes/time_int.md index 83a601840e60..be5d2651b2b7 100644 --- a/docs/content/reference/types/datatypes/time_int.md +++ b/docs/content/reference/types/datatypes/time_int.md @@ -14,3 +14,6 @@ A 64-bit number describing either nanoseconds OR sequence numbers. * 🦀 [Rust API docs for `TimeInt`](https://docs.rs/rerun/latest/rerun/datatypes/struct.TimeInt.html) +## Used by + +* [`VisibleTimeRangeBoundary`](../datatypes/visible_time_range_boundary.md) diff --git a/docs/content/reference/types/datatypes/visible_time_range.md b/docs/content/reference/types/datatypes/visible_time_range.md new file mode 100644 index 000000000000..32881f7eb435 --- /dev/null +++ b/docs/content/reference/types/datatypes/visible_time_range.md @@ -0,0 +1,19 @@ +--- +title: "VisibleTimeRange" +--- + +Visible time range bounds for a timelines. + +This datatype does not specify whether it's a time or sequence based timeline. + +## Fields + +* start: [`VisibleTimeRangeBoundary`](../datatypes/visible_time_range_boundary.md) +* end: [`VisibleTimeRangeBoundary`](../datatypes/visible_time_range_boundary.md) + +## Links + * 🌊 [C++ API docs for `VisibleTimeRange`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1VisibleTimeRange.html) + * 🐍 [Python API docs for `VisibleTimeRange`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.VisibleTimeRange) + * 🦀 [Rust API docs for `VisibleTimeRange`](https://docs.rs/rerun/latest/rerun/datatypes/struct.VisibleTimeRange.html) + + diff --git a/docs/content/reference/types/datatypes/visible_time_range_boundary.md b/docs/content/reference/types/datatypes/visible_time_range_boundary.md new file mode 100644 index 000000000000..9ed050778391 --- /dev/null +++ b/docs/content/reference/types/datatypes/visible_time_range_boundary.md @@ -0,0 +1,20 @@ +--- +title: "VisibleTimeRangeBoundary" +--- + +Type of boundary for visible history. + +## Fields + +* kind: [`VisibleTimeRangeBoundaryKind`](../datatypes/visible_time_range_boundary_kind.md) +* time: [`TimeInt`](../datatypes/time_int.md) + +## Links + * 🌊 [C++ API docs for `VisibleTimeRangeBoundary`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1datatypes_1_1VisibleTimeRangeBoundary.html) + * 🐍 [Python API docs for `VisibleTimeRangeBoundary`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.VisibleTimeRangeBoundary) + * 🦀 [Rust API docs for `VisibleTimeRangeBoundary`](https://docs.rs/rerun/latest/rerun/datatypes/struct.VisibleTimeRangeBoundary.html) + + +## Used by + +* [`VisibleTimeRange`](../datatypes/visible_time_range.md) diff --git a/docs/content/reference/types/datatypes/visible_time_range_boundary_kind.md b/docs/content/reference/types/datatypes/visible_time_range_boundary_kind.md new file mode 100644 index 000000000000..82627c2ecc00 --- /dev/null +++ b/docs/content/reference/types/datatypes/visible_time_range_boundary_kind.md @@ -0,0 +1,21 @@ +--- +title: "VisibleTimeRangeBoundaryKind" +--- + +Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. + +## Variants + +* RelativeToTimeCursor +* Absolute +* Infinite + +## Links + * 🌊 [C++ API docs for `VisibleTimeRangeBoundaryKind`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1datatypes.html) + * 🐍 [Python API docs for `VisibleTimeRangeBoundaryKind`](https://ref.rerun.io/docs/python/stable/common/datatypes#rerun.datatypes.VisibleTimeRangeBoundaryKind) + * 🦀 [Rust API docs for `VisibleTimeRangeBoundaryKind`](https://docs.rs/rerun/latest/rerun/datatypes/enum.VisibleTimeRangeBoundaryKind.html) + + +## Used by + +* [`VisibleTimeRangeBoundary`](../datatypes/visible_time_range_boundary.md) diff --git a/pixi.lock b/pixi.lock index 970f1a779c51..5a281e838699 100644 --- a/pixi.lock +++ b/pixi.lock @@ -174,7 +174,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -185,7 +185,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -199,7 +199,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 @@ -368,7 +368,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -379,7 +379,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -393,7 +393,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda @@ -550,7 +550,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -561,7 +561,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/35/69/b657974ddcbba54d59d7d62b01e60a8b815e35f415b996e4d355be0ac7b4/opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -575,7 +575,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda @@ -732,7 +732,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -743,7 +743,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -757,7 +757,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda @@ -893,7 +893,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -904,7 +904,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -918,7 +918,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl default: channels: @@ -944,12 +944,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-crt-cpp-0.26.0-h3b5eec7_3.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aws-sdk-cpp-1.11.210-hac0d6e5_8.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/binaryen-117-h59595ed_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h7f98852_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/c-ares-1.24.0-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2023.7.22-hbcca054_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-format-16.0.6-default_hb11cfb5_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/clang-tools-16.0.6-default_hb11cfb5_4.conda @@ -1042,7 +1039,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/psutil-5.9.8-py311h459d7ec_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/pyarrow-14.0.2-py311h39c9aba_3_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.8-hab00c5b_0_cpython.conda @@ -1050,7 +1046,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/rdma-core-28.9-h59595ed_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/re2-2023.06.02-h2873b5e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/rhash-1.4.4-hd590300_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ruff-0.3.5-py311h7145743_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/s2n-1.4.1-h06160fa_0.conda @@ -1067,7 +1062,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/typos-1.16.20-he8a937b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ucx-1.15.0-h64cca9d_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.9.4-py311h459d7ec_0.conda @@ -1075,12 +1069,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.5-hfc55251_0.conda - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -1090,8 +1086,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -1100,10 +1096,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 @@ -1124,12 +1122,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-crt-cpp-0.26.2-h07bb24a_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/aws-sdk-cpp-1.11.267-hfce6cab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/binaryen-117-h2f0025b_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.1.0-py311h8715677_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/bzip2-1.0.8-h31becfc_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/c-ares-1.27.0-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ca-certificates-2024.2.2-hcefe29a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-format-16.0.6-default_hb368394_5.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/clang-tools-16.0.6-default_hb368394_5.conda @@ -1221,7 +1216,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/psutil-5.9.8-py311hcd402e7_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/pyarrow-14.0.2-py311h1eb6f34_12_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-8.1.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/python-3.11.8-h43d1f9e_0_cpython.conda @@ -1229,7 +1223,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rdma-core-50.0-h0425590_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/re2-2023.09.01-h9caee61_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/readline-8.2-h8fc344f_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/rhash-1.4.4-h31becfc_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ruff-0.3.5-py311he69e3a7_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/s2n-1.4.5-h5a25046_0.conda @@ -1246,7 +1239,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/typos-1.19.0-h1d8f897_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/ucx-1.15.0-hcf8619e_7.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/xz-5.2.6-h9cdd2b7_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/yarl-1.9.4-py311hcd402e7_0.conda @@ -1254,12 +1246,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/zstd-1.5.5-h4c53e97_0.conda - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -1269,8 +1263,8 @@ environments: - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -1279,10 +1273,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda @@ -1302,12 +1298,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-crt-cpp-0.26.0-h88f2ebf_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/aws-sdk-cpp-1.11.210-heeba50e_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/binaryen-117-h73e2aa4_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/bzip2-1.0.8-h0d85af4_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/c-ares-1.24.0-h10d778d_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2023.7.22-h8857fd0_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-format-16.0.6-default_h7151d67_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/clang-tools-16.0.6-default_h7151d67_5.conda @@ -1391,14 +1384,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/psutil-5.9.8-py311he705e18_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/pyarrow-14.0.2-py311h54e7ce8_3_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.8-h9f0c242_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/re2-2023.06.02-hd34609a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/readline-8.2-h9e318b2_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/rhash-1.4.4-h0dc2134_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/ruff-0.3.5-py311hfff7943_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -1413,7 +1404,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-64/typos-1.16.20-h63b85fc_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.9.4-py311he705e18_0.conda @@ -1421,12 +1411,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-64/zstd-1.5.5-h829000d_0.conda - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -1435,9 +1427,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz + - pypi: https://files.pythonhosted.org/packages/35/69/b657974ddcbba54d59d7d62b01e60a8b815e35f415b996e4d355be0ac7b4/opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -1446,10 +1438,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda @@ -1469,12 +1463,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-crt-cpp-0.26.0-hcc526ff_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aws-sdk-cpp-1.11.210-ha042220_8.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/binaryen-117-hebf3989_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/bzip2-1.0.8-h3422bc3_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/c-ares-1.24.0-h93a5062_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ca-certificates-2023.7.22-hf0a4a13_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-format-16.0.6-default_he012953_5.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/clang-tools-16.0.6-default_he012953_5.conda @@ -1558,14 +1549,12 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/psutil-5.9.8-py311h05b510d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pyarrow-14.0.2-py311hd7bc329_3_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-3.11.8-hdf0ec26_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/re2-2023.06.02-h6135d0a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/readline-8.2-h92ec313_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/rhash-1.4.4-hb547adb_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ruff-0.3.5-py311h8c97afb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 @@ -1580,7 +1569,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.8.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/typos-1.16.20-h5ef7bb8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/xz-5.2.6-h57fd34a_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/yarl-1.9.4-py311h05b510d_0.conda @@ -1588,12 +1576,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.5-h4f39d0f_0.conda - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -1604,7 +1594,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -1613,10 +1603,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda @@ -1636,12 +1628,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/aws-crt-cpp-0.26.2-h8492d2a_7.conda - conda: https://conda.anaconda.org/conda-forge/win-64/aws-sdk-cpp-1.11.267-h93f5800_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/binaryen-117-h63175ca_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py311h12c1d0e_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/bzip2-1.0.8-h8ffe710_4.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/c-ares-1.27.0-hcfcfb64_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ca-certificates-2023.7.22-h56e8100_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-format-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/clang-tools-16.0.6-default_h3a3e6c3_5.conda - conda: https://conda.anaconda.org/conda-forge/win-64/cmake-3.27.6-hf0feee3_0.conda @@ -1719,13 +1708,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/pthreads-win32-2.9.1-hfa6e2cd_3.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/py-cpuinfo-9.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/pyarrow-14.0.2-py311h6a6099b_10_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-7.4.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pytest-benchmark-4.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/python-3.11.8-h2628c8c_0_cpython.conda - conda: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-4_cp311.conda - conda: https://conda.anaconda.org/conda-forge/win-64/re2-2023.09.01-hd3b24a8_2.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ruff-0.3.5-py311hc14472d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/semver-2.13.0-pyh9f0ad1d_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/setuptools-68.2.2-pyhd8ed1ab_0.conda @@ -1741,23 +1728,23 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/typos-1.16.20-h7f3b576_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/ucrt-10.0.22621.0-h57928b3_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h64f974e_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vc14_runtime-14.36.32532-hdcecf7f_17.conda - conda: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.36.32532-h05e6639_17.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.38.4-pyhd8ed1ab_0.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/win-64/yarl-1.9.4-py311ha68e1ae_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstd-1.5.5-h12be248_0.conda - pypi: https://files.pythonhosted.org/packages/db/fb/feb8456bef211621ed410909df4a3ab66d688be821dfcb1080956158d0cb/argcomplete-3.3.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fb/2b/a64c2d25a37aeb921fddb929111413049fc5f8b9a4c1aefaffaafe768d54/cachetools-5.3.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/f3/18/3e867ab37a24fdf073c1617b9c7830e06ec270b1ea4694a624038fc40a03/colorlog-6.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl @@ -1768,7 +1755,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -1777,10 +1764,12 @@ environments: - pypi: https://files.pythonhosted.org/packages/81/99/df45c40bf862817354b06bb25b45cd01b98a6e2849969926943ecf8ffb20/PyGithub-1.59.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/2b/4f/e04a8067c7c96c364cef7ef73906504e2f40d690811c021e1a1901473a19/PyJWT-2.8.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl examples: channels: @@ -1831,11 +1820,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ee/c0/9bd123d676eb61750e116a2cd915b06483fc406143cfc36c7f263f0f5368/contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/ca/7219b838086086972e662c19e908694bdc6744537fb41b70392501b8b5e4/dataclasses_json-0.6.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/41/fa9dcf51071202eb3e1f00daf91f39bec91231e06b1e2630068effa99432/dataclasses_json-0.6.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/d2/6d475e8925fa3f46f676263bfc6bdcf1e20273a433b296b1d63abecd2426/dicom_numpy-0.6.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/c5/3b84fd731dd93c549a0c25657e4ce5a957aeccd32d60dba2958cd3cdac23/diffusers-0.27.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/f0/7e988a019bc54b2dbd0ad4182ef2d53488bb02e58694cd79d61369e85900/flatbuffers-24.3.25-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c6/b5/dc17e93f60567fa1b0fa3720c2f28e0df5293927e2356e066e87af9adaba/fonttools-4.51.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/5f/34/76cfe866e482745ea8c9956b0be6198fd72d08d2be77b71596afdb8cd89f/freetype_py-2.4.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl @@ -1900,14 +1889,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9c/3d/a121f284241f08268b21359bd425f7d4825cffc5ac5cd0e1b3d82ffd2b10/pytz-2024.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/8b/9e/05bc55a3295d469ae658e15c7f6edc0f54d39745ad3bd268351ac31be73d/regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/52/21/22e993e8151c94e9adc9fc5f09848bad538d12c6390cec91f0fb1f6c8ba3/regex-2024.4.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d5/85/1e7d2804cbf82204cde462d16f1cb0ff5814b03f559fb46ceaa6b7020db4/safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/0a/40/2c57864acd77c168b96cb6e4e62651b9c98733962793293991ef55e2982c/scikit_image-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl @@ -1920,7 +1909,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/4c/f3/038b302fdfbe3be7da016777069f26ceefe11a681055ea1f7817546508e3/soupsieve-2.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl @@ -2005,11 +1994,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/ca/7219b838086086972e662c19e908694bdc6744537fb41b70392501b8b5e4/dataclasses_json-0.6.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/41/fa9dcf51071202eb3e1f00daf91f39bec91231e06b1e2630068effa99432/dataclasses_json-0.6.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/d2/6d475e8925fa3f46f676263bfc6bdcf1e20273a433b296b1d63abecd2426/dicom_numpy-0.6.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/c5/3b84fd731dd93c549a0c25657e4ce5a957aeccd32d60dba2958cd3cdac23/diffusers-0.27.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/f0/7e988a019bc54b2dbd0ad4182ef2d53488bb02e58694cd79d61369e85900/flatbuffers-24.3.25-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/84/51/8203a3e6e475e6766ac950638d42f45470f36c6a4f0615ff0a1c1f2ed0d6/fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/7c/77/faec42d1ffac2b970f606860a5bb083d606f1c673a5c57ab26382c8efec1/freetype_py-2.4.0-py3-none-macosx_10_9_universal2.whl @@ -2058,14 +2047,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9c/3d/a121f284241f08268b21359bd425f7d4825cffc5ac5cd0e1b3d82ffd2b10/pytz-2024.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/fd/b2/8069e8940bc3224d2cef6418aa6de4f2119d59709b841ecab012e3fc1d65/regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/9e/4b/950828d604c44c17468a992940c68c40a92dd5dc85e4415dc30f82535b2c/regex-2024.4.28-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl - pypi: https://files.pythonhosted.org/packages/78/2b/5f985cf4cf59378f80dc212004a7692b7b49b2a3910c3584d70284db5b89/scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl @@ -2078,7 +2067,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/4c/f3/038b302fdfbe3be7da016777069f26ceefe11a681055ea1f7817546508e3/soupsieve-2.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl @@ -2162,11 +2151,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/ca/7219b838086086972e662c19e908694bdc6744537fb41b70392501b8b5e4/dataclasses_json-0.6.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/41/fa9dcf51071202eb3e1f00daf91f39bec91231e06b1e2630068effa99432/dataclasses_json-0.6.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/d2/6d475e8925fa3f46f676263bfc6bdcf1e20273a433b296b1d63abecd2426/dicom_numpy-0.6.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/c5/3b84fd731dd93c549a0c25657e4ce5a957aeccd32d60dba2958cd3cdac23/diffusers-0.27.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/f0/7e988a019bc54b2dbd0ad4182ef2d53488bb02e58694cd79d61369e85900/flatbuffers-24.3.25-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/33/47/f2ca671af61757eaaac608963dda5b76ec9100621e45d0fd63a153fd8cd7/fonttools-4.51.0-cp311-cp311-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/7c/77/faec42d1ffac2b970f606860a5bb083d606f1c673a5c57ab26382c8efec1/freetype_py-2.4.0-py3-none-macosx_10_9_universal2.whl @@ -2215,14 +2204,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9c/3d/a121f284241f08268b21359bd425f7d4825cffc5ac5cd0e1b3d82ffd2b10/pytz-2024.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/aa/f1/de801945e6a18c9b7d7ea9ffe01d2433b40d1609426c3581f7d60acd1416/regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/ac/86/8a1f52664cc21effdd7a0d6a142ffce39f5533be418e5b26d75137f2921b/regex-2024.4.28-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b9/cf/9e5828fa29791bf7ac5c3fad3637ebb02f237a1c3de8233bd6a33c2c4aac/scikit_image-0.23.2-cp311-cp311-macosx_12_0_arm64.whl @@ -2235,7 +2224,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/4c/f3/038b302fdfbe3be7da016777069f26ceefe11a681055ea1f7817546508e3/soupsieve-2.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl @@ -2328,11 +2317,11 @@ environments: - pypi: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/91/ca/7219b838086086972e662c19e908694bdc6744537fb41b70392501b8b5e4/dataclasses_json-0.6.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/87/41/fa9dcf51071202eb3e1f00daf91f39bec91231e06b1e2630068effa99432/dataclasses_json-0.6.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a4/d2/6d475e8925fa3f46f676263bfc6bdcf1e20273a433b296b1d63abecd2426/dicom_numpy-0.6.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/75/c5/3b84fd731dd93c549a0c25657e4ce5a957aeccd32d60dba2958cd3cdac23/diffusers-0.27.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/f0/7e988a019bc54b2dbd0ad4182ef2d53488bb02e58694cd79d61369e85900/flatbuffers-24.3.25-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c5/d4/f426fa1ca42e47bcfff0c878fa9d49d9c03379d00903a7c178f95b97867a/fonttools-4.51.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b4/f5/4b8bb492464247236bd3dabd7734b3ea49adc63cf2e53160e830ebccb39d/freetype_py-2.4.0-py3-none-win_amd64.whl @@ -2384,14 +2373,14 @@ environments: - pypi: https://files.pythonhosted.org/packages/30/93/4d02ac696f16a2ad8fff0e78be28ab4ec0b990d2b3569fe07e27a258cb02/pyglet-2.0.15-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - pypi: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip + - pypi: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz - pypi: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9d/ea/6d76df31432a0e6fdf81681a895f009a4bb47b3c39036db3e1b528191d52/pyparsing-3.1.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/28/88/174c28b9d3d03cf6d8edb6f637458f30f1cf1a2bd7a617cbd9dadb1740f6/pyrender-0.1.45-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9c/3d/a121f284241f08268b21359bd425f7d4825cffc5ac5cd0e1b3d82ffd2b10/pytz-2024.1-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/b3/d0/1a054b685849b018cff594ccd4859fc6a3132f67698da805ed06d5b6974a/regex-2024.4.16-cp311-cp311-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/bd/ad/33a844d35d3be70e01743f27960cf3646da1dbdea050e67dbdae6b843582/regex-2024.4.28-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/eb/ab/8791ce3063e6d4ac7f8efe3c993fd2e911c9e08f4c7dd05b603eaa2493b2/scikit_image-0.23.2-cp311-cp311-win_amd64.whl @@ -2404,7 +2393,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/4c/f3/038b302fdfbe3be7da016777069f26ceefe11a681055ea1f7817546508e3/soupsieve-2.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/1f/1241aa3d66e8dc1612427b17885f5fcd9c9ee3079fc0d28e9a3aeeb36fa3/stringcase-1.2.0.tar.gz - pypi: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/88/23/6398b7bca8967c853b90ba2f8da5e3ad1e9b2ca5b9f869a8c26ea41543e2/tifffile-2024.4.24-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl @@ -2609,7 +2598,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl @@ -2636,7 +2625,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -2653,7 +2642,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl linux-aarch64: - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/_openmp_mutex-4.5-2_gnu.tar.bz2 @@ -2803,7 +2792,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl @@ -2818,7 +2807,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -2834,7 +2823,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl osx-64: - conda: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.9.3-py311he705e18_1.conda @@ -2973,7 +2962,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl @@ -2988,7 +2977,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/35/69/b657974ddcbba54d59d7d62b01e60a8b815e35f415b996e4d355be0ac7b4/opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl - pypi: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - pypi: https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -3004,7 +2993,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl osx-arm64: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/aiohttp-3.9.3-py311h05b510d_1.conda @@ -3143,7 +3132,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl @@ -3158,7 +3147,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -3174,7 +3163,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl win-64: - conda: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.9.3-py311ha68e1ae_1.conda @@ -3308,7 +3297,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/93/6d/66d48b03460768f523da62a57a7e14e5e95fdf339d79e996ce3cecda2cdb/fsspec-2024.3.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl @@ -3323,7 +3312,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ad/6e/1bed3b7c904cc178cb8ee8dbaf72934964452b3de95b7a63412591edb93c/protobuf-4.25.3-cp310-abi3-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/23/7e/5f50d07d5e70a2addbccd90ac2950f81d1edd0783630651d9268d7f1db49/pyasn1-0.6.0-py2.py3-none-any.whl @@ -3339,7 +3328,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/fc/3a/4950e3701e27f2157814f7ddb41553513ebd9f4864cca78f47e2a68c897c/types_Deprecated-1.2.9.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl packages: - kind: conda @@ -3414,23 +3403,23 @@ packages: url: https://files.pythonhosted.org/packages/53/fe/0251ccd9e0015c705e772da0fb2c96cdafd87b1d7dd45dc13dca7ced0eb7/accelerate-0.29.3-py3-none-any.whl sha256: 99d633d4b6126817c5e554487406748be95c8d1d1e659dd2fd60657e35f532dd requires_dist: - - numpy >=1.17 - - packaging >=20.0 + - numpy>=1.17 + - packaging>=20.0 - psutil - pyyaml - - torch >=1.10.0 + - torch>=1.10.0 - huggingface-hub - - safetensors >=0.3.1 - - black ~=23.1 ; extra == 'dev' - - hf-doc-builder >=0.3.0 ; extra == 'dev' - - ruff ~=0.2.1 ; extra == 'dev' - - pytest <=8.0.0, >=7.2.0 ; extra == 'dev' + - safetensors>=0.3.1 + - black~=23.1 ; extra == 'dev' + - hf-doc-builder>=0.3.0 ; extra == 'dev' + - ruff~=0.2.1 ; extra == 'dev' + - pytest<=8.0.0,>=7.2.0 ; extra == 'dev' - pytest-xdist ; extra == 'dev' - pytest-subtests ; extra == 'dev' - parameterized ; extra == 'dev' - datasets ; extra == 'dev' - evaluate ; extra == 'dev' - - torchpippy >=0.2.0 ; extra == 'dev' + - torchpippy>=0.2.0 ; extra == 'dev' - transformers ; extra == 'dev' - scipy ; extra == 'dev' - scikit-learn ; extra == 'dev' @@ -3439,14 +3428,14 @@ packages: - bitsandbytes ; extra == 'dev' - timm ; extra == 'dev' - rich ; extra == 'dev' - - black ~=23.1 ; extra == 'quality' - - hf-doc-builder >=0.3.0 ; extra == 'quality' - - ruff ~=0.2.1 ; extra == 'quality' + - black~=23.1 ; extra == 'quality' + - hf-doc-builder>=0.3.0 ; extra == 'quality' + - ruff~=0.2.1 ; extra == 'quality' - rich ; extra == 'rich' - sagemaker ; extra == 'sagemaker' - datasets ; extra == 'test_dev' - evaluate ; extra == 'test_dev' - - torchpippy >=0.2.0 ; extra == 'test_dev' + - torchpippy>=0.2.0 ; extra == 'test_dev' - transformers ; extra == 'test_dev' - scipy ; extra == 'test_dev' - scikit-learn ; extra == 'test_dev' @@ -3454,7 +3443,7 @@ packages: - tqdm ; extra == 'test_dev' - bitsandbytes ; extra == 'test_dev' - timm ; extra == 'test_dev' - - pytest <=8.0.0, >=7.2.0 ; extra == 'test_prod' + - pytest<=8.0.0,>=7.2.0 ; extra == 'test_prod' - pytest-xdist ; extra == 'test_prod' - pytest-subtests ; extra == 'test_prod' - parameterized ; extra == 'test_prod' @@ -3462,13 +3451,13 @@ packages: - comet-ml ; extra == 'test_trackers' - tensorboard ; extra == 'test_trackers' - dvclive ; extra == 'test_trackers' - - pytest <=8.0.0, >=7.2.0 ; extra == 'testing' + - pytest<=8.0.0,>=7.2.0 ; extra == 'testing' - pytest-xdist ; extra == 'testing' - pytest-subtests ; extra == 'testing' - parameterized ; extra == 'testing' - datasets ; extra == 'testing' - evaluate ; extra == 'testing' - - torchpippy >=0.2.0 ; extra == 'testing' + - torchpippy>=0.2.0 ; extra == 'testing' - transformers ; extra == 'testing' - scipy ; extra == 'testing' - scikit-learn ; extra == 'testing' @@ -3662,7 +3651,7 @@ packages: requires_dist: - importlib-metadata ; python_version < '3.8' - attrs[tests] ; extra == 'cov' - - coverage[toml] >=5.3 ; extra == 'cov' + - coverage[toml]>=5.3 ; extra == 'cov' - attrs[tests] ; extra == 'dev' - pre-commit ; extra == 'dev' - furo ; extra == 'docs' @@ -3674,14 +3663,14 @@ packages: - zope-interface ; extra == 'docs' - attrs[tests-no-zope] ; extra == 'tests' - zope-interface ; extra == 'tests' - - mypy >=1.6 ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' + - mypy>=1.6 ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' - pytest-mypy-plugins ; (platform_python_implementation == 'CPython' and python_version >= '3.8') and extra == 'tests-mypy' - attrs[tests-mypy] ; extra == 'tests-no-zope' - cloudpickle ; platform_python_implementation == 'CPython' and extra == 'tests-no-zope' - hypothesis ; extra == 'tests-no-zope' - pympler ; extra == 'tests-no-zope' - pytest-xdist[psutil] ; extra == 'tests-no-zope' - - pytest >=4.3.0 ; extra == 'tests-no-zope' + - pytest>=4.3.0 ; extra == 'tests-no-zope' requires_python: '>=3.7' - kind: conda name: attrs @@ -6898,7 +6887,7 @@ packages: url: https://files.pythonhosted.org/packages/b1/fe/e8c672695b37eecc5cbf43e1d0638d88d66ba3a44c4d321c796f4e59167f/beautifulsoup4-4.12.3-py3-none-any.whl sha256: b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed requires_dist: - - soupsieve >1.2 + - soupsieve>1.2 - cchardet ; extra == 'cchardet' - chardet ; extra == 'chardet' - charset-normalizer ; extra == 'charset-normalizer' @@ -7086,82 +7075,82 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/9b/f7/591d601c3046ceb65b97291dfe87fa25124cffac3d97aaaba89d0f0d7bdf/black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 + url: https://files.pythonhosted.org/packages/c5/48/34176b522e8cff4620a5d96c2e323ff2413f574870eb25efa8025885e028/black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb requires_dist: - - click >=8.0.0 - - mypy-extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9.0 - - platformdirs >=2 - - tomli >=1.1.0 ; python_version < '3.11' - - typing-extensions >=4.0.1 ; python_version < '3.11' - - colorama >=0.4.3 ; extra == 'colorama' - - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython >=7.8.0 ; extra == 'jupyter' - - tokenize-rt >=3.2.0 ; extra == 'jupyter' - - uvloop >=0.15.2 ; extra == 'uvloop' + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - tomli>=1.1.0 ; python_version < '3.11' + - typing-extensions>=4.0.1 ; python_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/c9/17/5e0036b265bbf6bc44970d93d48febcbc03701b671db3c9603fd43ebc616/black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c + url: https://files.pythonhosted.org/packages/9b/f7/591d601c3046ceb65b97291dfe87fa25124cffac3d97aaaba89d0f0d7bdf/black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 requires_dist: - - click >=8.0.0 - - mypy-extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9.0 - - platformdirs >=2 - - tomli >=1.1.0 ; python_version < '3.11' - - typing-extensions >=4.0.1 ; python_version < '3.11' - - colorama >=0.4.3 ; extra == 'colorama' - - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython >=7.8.0 ; extra == 'jupyter' - - tokenize-rt >=3.2.0 ; extra == 'jupyter' - - uvloop >=0.15.2 ; extra == 'uvloop' + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - tomli>=1.1.0 ; python_version < '3.11' + - typing-extensions>=4.0.1 ; python_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/c5/48/34176b522e8cff4620a5d96c2e323ff2413f574870eb25efa8025885e028/black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb + url: https://files.pythonhosted.org/packages/74/ce/e8eec1a77edbfa982bee3b5460dcdd4fe0e4e3165fc15d8ec44d04da7776/black-24.4.2-cp311-cp311-win_amd64.whl + sha256: 7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 requires_dist: - - click >=8.0.0 - - mypy-extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9.0 - - platformdirs >=2 - - tomli >=1.1.0 ; python_version < '3.11' - - typing-extensions >=4.0.1 ; python_version < '3.11' - - colorama >=0.4.3 ; extra == 'colorama' - - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython >=7.8.0 ; extra == 'jupyter' - - tokenize-rt >=3.2.0 ; extra == 'jupyter' - - uvloop >=0.15.2 ; extra == 'uvloop' + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - tomli>=1.1.0 ; python_version < '3.11' + - typing-extensions>=4.0.1 ; python_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/74/ce/e8eec1a77edbfa982bee3b5460dcdd4fe0e4e3165fc15d8ec44d04da7776/black-24.4.2-cp311-cp311-win_amd64.whl - sha256: 7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 + url: https://files.pythonhosted.org/packages/c9/17/5e0036b265bbf6bc44970d93d48febcbc03701b671db3c9603fd43ebc616/black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c requires_dist: - - click >=8.0.0 - - mypy-extensions >=0.4.3 - - packaging >=22.0 - - pathspec >=0.9.0 - - platformdirs >=2 - - tomli >=1.1.0 ; python_version < '3.11' - - typing-extensions >=4.0.1 ; python_version < '3.11' - - colorama >=0.4.3 ; extra == 'colorama' - - aiohttp !=3.9.0, >=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' - - aiohttp >=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' - - ipython >=7.8.0 ; extra == 'jupyter' - - tokenize-rt >=3.2.0 ; extra == 'jupyter' - - uvloop >=0.15.2 ; extra == 'uvloop' + - click>=8.0.0 + - mypy-extensions>=0.4.3 + - packaging>=22.0 + - pathspec>=0.9.0 + - platformdirs>=2 + - tomli>=1.1.0 ; python_version < '3.11' + - typing-extensions>=4.0.1 ; python_version < '3.11' + - colorama>=0.4.3 ; extra == 'colorama' + - aiohttp!=3.9.0,>=3.7.4 ; (sys_platform == 'win32' and implementation_name == 'pypy') and extra == 'd' + - aiohttp>=3.7.4 ; (sys_platform != 'win32' or implementation_name != 'pypy') and extra == 'd' + - ipython>=7.8.0 ; extra == 'jupyter' + - tokenize-rt>=3.2.0 ; extra == 'jupyter' + - uvloop>=0.15.2 ; extra == 'uvloop' requires_python: '>=3.8' - kind: pypi name: blueprint @@ -7183,117 +7172,6 @@ packages: - yfinance requires_python: '>=3.8' editable: true -- kind: conda - name: brotli-python - version: 1.1.0 - build: py311h12c1d0e_1 - build_number: 1 - subdir: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/brotli-python-1.1.0-py311h12c1d0e_1.conda - sha256: 5390e1e5e8e159d4893ecbfd2c08ca75ef51bdce1a4a44ff4ee9e2d596004aac - md5: 42fbf4e947c17ea605e6a4d7f526669a - depends: - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - - ucrt >=10.0.20348.0 - - vc >=14.2,<15 - - vc14_runtime >=14.29.30139 - constrains: - - libbrotlicommon 1.1.0 hcfcfb64_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli - size: 322086 - timestamp: 1695990976742 -- kind: conda - name: brotli-python - version: 1.1.0 - build: py311h8715677_1 - build_number: 1 - subdir: linux-aarch64 - url: https://conda.anaconda.org/conda-forge/linux-aarch64/brotli-python-1.1.0-py311h8715677_1.conda - sha256: f108fced985f7aa4457564c1e8f49cc5166d2e82bfdc120657c61888cd1f3a53 - md5: 22c060f41b1407ed9f40ce6468bdc338 - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - libbrotlicommon 1.1.0 h31becfc_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli - size: 355054 - timestamp: 1695990590279 -- kind: conda - name: brotli-python - version: 1.1.0 - build: py311ha891d26_1 - build_number: 1 - subdir: osx-arm64 - url: https://conda.anaconda.org/conda-forge/osx-arm64/brotli-python-1.1.0-py311ha891d26_1.conda - sha256: 2d78c79ccf2c17236c52ef217a4c34b762eb7908a6903d94439f787aac1c8f4b - md5: 5e802b015e33447d1283d599d21f052b - depends: - - libcxx >=15.0.7 - - python >=3.11,<3.12.0a0 - - python >=3.11,<3.12.0a0 *_cpython - - python_abi 3.11.* *_cp311 - constrains: - - libbrotlicommon 1.1.0 hb547adb_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli - size: 343332 - timestamp: 1695991223439 -- kind: conda - name: brotli-python - version: 1.1.0 - build: py311hb755f60_1 - build_number: 1 - subdir: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/brotli-python-1.1.0-py311hb755f60_1.conda - sha256: 559093679e9fdb6061b7b80ca0f9a31fe6ffc213f1dae65bc5c82e2cd1a94107 - md5: cce9e7c3f1c307f2a5fb08a2922d6164 - depends: - - libgcc-ng >=12 - - libstdcxx-ng >=12 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - libbrotlicommon 1.1.0 hd590300_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli - size: 351340 - timestamp: 1695990160360 -- kind: conda - name: brotli-python - version: 1.1.0 - build: py311hdf8f085_1 - build_number: 1 - subdir: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/brotli-python-1.1.0-py311hdf8f085_1.conda - sha256: 0f5e0a7de58006f349220365e32db521a1fe494c37ee455e5ecf05b8fe567dcc - md5: 546fdccabb90492fbaf2da4ffb78f352 - depends: - - libcxx >=15.0.7 - - python >=3.11,<3.12.0a0 - - python_abi 3.11.* *_cp311 - constrains: - - libbrotlicommon 1.1.0 h0dc2134_1 - license: MIT - license_family: MIT - purls: - - pkg:pypi/brotli - size: 366864 - timestamp: 1695990449997 - kind: conda name: bzip2 version: 1.0.8 @@ -7873,73 +7751,57 @@ packages: url: https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl sha256: dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1 requires_python: '>=3.6' -- kind: conda - name: certifi - version: 2024.2.2 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/certifi-2024.2.2-pyhd8ed1ab_0.conda - sha256: f1faca020f988696e6b6ee47c82524c7806380b37cfdd1def32f92c326caca54 - md5: 0876280e409658fc6f9e75d035960333 - depends: - - python >=3.7 - license: ISC - purls: - - pkg:pypi/certifi - size: 160559 - timestamp: 1707022289175 - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 + url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer @@ -7950,8 +7812,8 @@ packages: - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer @@ -7959,23 +7821,6 @@ packages: url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 requires_python: '>=3.7.0' -- kind: conda - name: charset-normalizer - version: 3.3.2 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/charset-normalizer-3.3.2-pyhd8ed1ab_0.conda - sha256: 20cae47d31fdd58d99c4d2e65fbdcefa0b0de0c84e455ba9d6356a4bdbc4b5b9 - md5: 7f4a9e3fcff3f6356ae99244a014da6a - depends: - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/charset-normalizer - size: 46597 - timestamp: 1698833765762 - kind: conda name: clang version: 16.0.6 @@ -9147,18 +8992,18 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 + url: https://files.pythonhosted.org/packages/ee/c0/9bd123d676eb61750e116a2cd915b06483fc406143cfc36c7f263f0f5368/contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df requires_dist: - - numpy >=1.20 + - numpy>=1.20 - furo ; extra == 'docs' - - sphinx >=7.2 ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy ==1.8.0 ; extra == 'mypy' + - mypy==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9171,18 +9016,18 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 + url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 requires_dist: - - numpy >=1.20 + - numpy>=1.20 - furo ; extra == 'docs' - - sphinx >=7.2 ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy ==1.8.0 ; extra == 'mypy' + - mypy==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9195,18 +9040,18 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/ee/c0/9bd123d676eb61750e116a2cd915b06483fc406143cfc36c7f263f0f5368/contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df + url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl + sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 requires_dist: - - numpy >=1.20 + - numpy>=1.20 - furo ; extra == 'docs' - - sphinx >=7.2 ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy ==1.8.0 ; extra == 'mypy' + - mypy==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9219,18 +9064,18 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl - sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 + url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 requires_dist: - - numpy >=1.20 + - numpy>=1.20 - furo ; extra == 'docs' - - sphinx >=7.2 ; extra == 'docs' + - sphinx>=7.2 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - bokeh ; extra == 'bokeh' - selenium ; extra == 'bokeh' - contourpy[bokeh,docs] ; extra == 'mypy' - docutils-stubs ; extra == 'mypy' - - mypy ==1.8.0 ; extra == 'mypy' + - mypy==1.8.0 ; extra == 'mypy' - types-pillow ; extra == 'mypy' - contourpy[test-no-images] ; extra == 'test' - matplotlib ; extra == 'test' @@ -9247,62 +9092,34 @@ packages: sha256: 8ae055c0b8b0dd7757e4e666f6163172859044d4090830aecbec3460cdb318ee requires_dist: - accelerate - - diffusers ==0.27.2 - - numpy - opencv-python - pillow - - rerun-sdk - - torch ==2.2.2 + - diffusers==0.27.2 + - numpy + - torch==2.2.2 - transformers + - rerun-sdk requires_python: '>=3.10' editable: true - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 - requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - - black ; extra == 'pep8test' - - flake8 ; extra == 'pep8test' - - flake8-import-order ; extra == 'pep8test' - - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' - - pytest-benchmark ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest-subtests ; extra == 'test' - - pytest-xdist ; extra == 'test' - - pretend ; extra == 'test' - - iso8601 ; extra == 'test' - - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' - requires_python: '>=3.6' -- kind: pypi - name: cryptography - version: 38.0.4 - url: https://files.pythonhosted.org/packages/6d/47/929f07e12ebbcfedddb95397c49677dd82bb5a0bb648582b10d5f65e321c/cryptography-38.0.4-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d + url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl + sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9310,27 +9127,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9338,7 +9155,7 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography @@ -9346,47 +9163,19 @@ packages: url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' - - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' - - black ; extra == 'pep8test' - - flake8 ; extra == 'pep8test' - - flake8-import-order ; extra == 'pep8test' - - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' - - pytest-benchmark ; extra == 'test' - - pytest-cov ; extra == 'test' - - pytest-subtests ; extra == 'test' - - pytest-xdist ; extra == 'test' - - pretend ; extra == 'test' - - iso8601 ; extra == 'test' - - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' - requires_python: '>=3.6' -- kind: pypi - name: cryptography - version: 38.0.4 - url: https://files.pythonhosted.org/packages/63/d4/66b3b4ffe51b47a065b5a5a00e6a4c8aa6cdfa4f2453adfa0aac77fd3511/cryptography-38.0.4-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8 - requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9394,7 +9183,7 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography @@ -9402,19 +9191,19 @@ packages: url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9422,27 +9211,27 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl - sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c + url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb requires_dist: - - cffi >=1.12 - - sphinx !=1.8.0, !=3.1.0, !=3.1.1, >=1.6.5 ; extra == 'docs' + - cffi>=1.12 + - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pyenchant >=1.6.11 ; extra == 'docstest' - - twine >=1.12.0 ; extra == 'docstest' - - sphinxcontrib-spelling >=4.0.1 ; extra == 'docstest' + - pyenchant>=1.6.11 ; extra == 'docstest' + - twine>=1.12.0 ; extra == 'docstest' + - sphinxcontrib-spelling>=4.0.1 ; extra == 'docstest' - black ; extra == 'pep8test' - flake8 ; extra == 'pep8test' - flake8-import-order ; extra == 'pep8test' - pep8-naming ; extra == 'pep8test' - - setuptools-rust >=0.11.4 ; extra == 'sdist' - - bcrypt >=3.1.5 ; extra == 'ssh' - - pytest >=6.2.0 ; extra == 'test' + - setuptools-rust>=0.11.4 ; extra == 'sdist' + - bcrypt>=3.1.5 ; extra == 'ssh' + - pytest>=6.2.0 ; extra == 'test' - pytest-benchmark ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-subtests ; extra == 'test' @@ -9450,7 +9239,7 @@ packages: - pretend ; extra == 'test' - iso8601 ; extra == 'test' - pytz ; extra == 'test' - - hypothesis !=3.79.2, >=1.11.4 ; extra == 'test' + - hypothesis!=3.79.2,>=1.11.4 ; extra == 'test' requires_python: '>=3.6' - kind: conda name: cxx-compiler @@ -9526,12 +9315,12 @@ packages: requires_python: '>=3.8' - kind: pypi name: dataclasses-json - version: 0.6.4 - url: https://files.pythonhosted.org/packages/91/ca/7219b838086086972e662c19e908694bdc6744537fb41b70392501b8b5e4/dataclasses_json-0.6.4-py3-none-any.whl - sha256: f90578b8a3177f7552f4e1a6e535e84293cd5da421fcce0642d49c0d7bdf8df2 + version: 0.6.5 + url: https://files.pythonhosted.org/packages/87/41/fa9dcf51071202eb3e1f00daf91f39bec91231e06b1e2630068effa99432/dataclasses_json-0.6.5-py3-none-any.whl + sha256: f49c77aa3a85cac5bf5b7f65f4790ca0d2be8ef4d92c75e91ba0103072788a39 requires_dist: - - marshmallow >=3.18.0, <4.0.0 - - typing-inspect >=0.4.0, <1 + - marshmallow>=3.18.0,<4.0.0 + - typing-inspect>=0.4.0,<1 requires_python: '>=3.7,<4.0' - kind: pypi name: deprecated @@ -9539,12 +9328,12 @@ packages: url: https://files.pythonhosted.org/packages/20/8d/778b7d51b981a96554f29136cd59ca7880bf58094338085bcf2a979a0e6a/Deprecated-1.2.14-py2.py3-none-any.whl sha256: 6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c requires_dist: - - wrapt <2, >=1.10 + - wrapt<2,>=1.10 - tox ; extra == 'dev' - pytest ; extra == 'dev' - pytest-cov ; extra == 'dev' - - bump2version <1 ; extra == 'dev' - - sphinx <2 ; extra == 'dev' + - bump2version<1 ; extra == 'dev' + - sphinx<2 ; extra == 'dev' requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*' - kind: pypi name: detect-and-track-objects @@ -9553,13 +9342,13 @@ packages: sha256: 6c88082f8ff9c5949f5786584edf771078e3f1be6202f7225ad02268f96d9292 requires_dist: - numpy - - opencv-contrib-python >4.6 - - opencv-python >4.6 + - opencv-contrib-python>4.6 + - opencv-python>4.6 - pillow - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - - timm ==0.9.11 - - torch ==2.2.2 + - timm==0.9.11 + - torch==2.2.2 - transformers editable: true - kind: pypi @@ -9568,12 +9357,12 @@ packages: path: examples/python/dicom_mri sha256: 98cb91dc5758ae59e3cd0fb797f86f40fcf627f63e659365806f59feed4618d8 requires_dist: - - dicom-numpy ==0.6.2 + - dicom-numpy==0.6.2 - numpy - - pydicom ==2.3.0 - - requests <3, >=2.31 + - pydicom==2.3.0 + - requests>=2.31,<3 - rerun-sdk - - types-requests <3, >=2.31 + - types-requests>=2.31,<3 editable: true - kind: pypi name: dicom-numpy @@ -9581,7 +9370,7 @@ packages: url: https://files.pythonhosted.org/packages/a4/d2/6d475e8925fa3f46f676263bfc6bdcf1e20273a433b296b1d63abecd2426/dicom_numpy-0.6.2-py2.py3-none-any.whl sha256: 361c8dfc52d625bf3344e5c2745e9c928d263999a4c094fe285d9fe461895ea9 requires_dist: - - pydicom >=1.0 + - pydicom>=1.0 - numpy - check-manifest ; extra == 'dev' - sphinx ; extra == 'dev' @@ -9597,74 +9386,74 @@ packages: requires_dist: - importlib-metadata - filelock - - huggingface-hub >=0.20.2 + - huggingface-hub>=0.20.2 - numpy - - regex !=2019.12.17 + - regex!=2019.12.17 - requests - - safetensors >=0.3.1 + - safetensors>=0.3.1 - pillow - - urllib3 <=2.0.0 ; extra == 'dev' - - isort >=5.5.4 ; extra == 'dev' - - ruff ==0.1.5 ; extra == 'dev' - - hf-doc-builder >=0.3.0 ; extra == 'dev' - - compel ==0.1.8 ; extra == 'dev' - - gitpython <3.1.19 ; extra == 'dev' + - urllib3<=2.0.0 ; extra == 'dev' + - isort>=5.5.4 ; extra == 'dev' + - ruff==0.1.5 ; extra == 'dev' + - hf-doc-builder>=0.3.0 ; extra == 'dev' + - compel==0.1.8 ; extra == 'dev' + - gitpython<3.1.19 ; extra == 'dev' - datasets ; extra == 'dev' - jinja2 ; extra == 'dev' - - invisible-watermark >=0.2.0 ; extra == 'dev' - - k-diffusion >=0.0.12 ; extra == 'dev' + - invisible-watermark>=0.2.0 ; extra == 'dev' + - k-diffusion>=0.0.12 ; extra == 'dev' - librosa ; extra == 'dev' - parameterized ; extra == 'dev' - pytest ; extra == 'dev' - pytest-timeout ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - requests-mock ==1.10.0 ; extra == 'dev' - - safetensors >=0.3.1 ; extra == 'dev' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev' + - requests-mock==1.10.0 ; extra == 'dev' + - safetensors>=0.3.1 ; extra == 'dev' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev' - scipy ; extra == 'dev' - torchvision ; extra == 'dev' - - transformers >=4.25.1 ; extra == 'dev' - - accelerate >=0.11.0 ; extra == 'dev' - - protobuf <4, >=3.20.3 ; extra == 'dev' + - transformers>=4.25.1 ; extra == 'dev' + - accelerate>=0.11.0 ; extra == 'dev' + - protobuf<4,>=3.20.3 ; extra == 'dev' - tensorboard ; extra == 'dev' - - peft >=0.6.0 ; extra == 'dev' - - torch >=1.4 ; extra == 'dev' - - jax >=0.4.1 ; extra == 'dev' - - jaxlib >=0.4.1 ; extra == 'dev' - - flax >=0.4.1 ; extra == 'dev' - - hf-doc-builder >=0.3.0 ; extra == 'docs' - - jax >=0.4.1 ; extra == 'flax' - - jaxlib >=0.4.1 ; extra == 'flax' - - flax >=0.4.1 ; extra == 'flax' - - urllib3 <=2.0.0 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - ruff ==0.1.5 ; extra == 'quality' - - hf-doc-builder >=0.3.0 ; extra == 'quality' - - compel ==0.1.8 ; extra == 'test' - - gitpython <3.1.19 ; extra == 'test' + - peft>=0.6.0 ; extra == 'dev' + - torch>=1.4 ; extra == 'dev' + - jax>=0.4.1 ; extra == 'dev' + - jaxlib>=0.4.1 ; extra == 'dev' + - flax>=0.4.1 ; extra == 'dev' + - hf-doc-builder>=0.3.0 ; extra == 'docs' + - jax>=0.4.1 ; extra == 'flax' + - jaxlib>=0.4.1 ; extra == 'flax' + - flax>=0.4.1 ; extra == 'flax' + - urllib3<=2.0.0 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - ruff==0.1.5 ; extra == 'quality' + - hf-doc-builder>=0.3.0 ; extra == 'quality' + - compel==0.1.8 ; extra == 'test' + - gitpython<3.1.19 ; extra == 'test' - datasets ; extra == 'test' - jinja2 ; extra == 'test' - - invisible-watermark >=0.2.0 ; extra == 'test' - - k-diffusion >=0.0.12 ; extra == 'test' + - invisible-watermark>=0.2.0 ; extra == 'test' + - k-diffusion>=0.0.12 ; extra == 'test' - librosa ; extra == 'test' - parameterized ; extra == 'test' - pytest ; extra == 'test' - pytest-timeout ; extra == 'test' - pytest-xdist ; extra == 'test' - - requests-mock ==1.10.0 ; extra == 'test' - - safetensors >=0.3.1 ; extra == 'test' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'test' + - requests-mock==1.10.0 ; extra == 'test' + - safetensors>=0.3.1 ; extra == 'test' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'test' - scipy ; extra == 'test' - torchvision ; extra == 'test' - - transformers >=4.25.1 ; extra == 'test' - - torch >=1.4 ; extra == 'torch' - - accelerate >=0.11.0 ; extra == 'torch' - - accelerate >=0.11.0 ; extra == 'training' + - transformers>=4.25.1 ; extra == 'test' + - torch>=1.4 ; extra == 'torch' + - accelerate>=0.11.0 ; extra == 'torch' + - accelerate>=0.11.0 ; extra == 'training' - datasets ; extra == 'training' - - protobuf <4, >=3.20.3 ; extra == 'training' + - protobuf<4,>=3.20.3 ; extra == 'training' - tensorboard ; extra == 'training' - jinja2 ; extra == 'training' - - peft >=0.6.0 ; extra == 'training' + - peft>=0.6.0 ; extra == 'training' requires_python: '>=3.8.0' - kind: pypi name: distlib @@ -9807,10 +9596,10 @@ packages: path: examples/python/face_tracking sha256: b8725fe4d36c11aad2c6c936ba2b57c7f65a856aa179badca5d041db63119d55 requires_dist: - - mediapipe ==0.10.11 ; sys_platform != 'darwin' - - mediapipe ==0.10.9 ; sys_platform == 'darwin' + - mediapipe==0.10.11 ; sys_platform != 'darwin' + - mediapipe==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python >4.6 + - opencv-python>4.6 - requests - rerun-sdk - tqdm @@ -9818,21 +9607,21 @@ packages: editable: true - kind: pypi name: filelock - version: 3.13.4 - url: https://files.pythonhosted.org/packages/6e/b5/15b3b36f298bcbc0be82a371ac744f4f5a10309ade0b8bbde286598dd612/filelock-3.13.4-py3-none-any.whl - sha256: 404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f + version: 3.14.0 + url: https://files.pythonhosted.org/packages/41/24/0b023b6537dfc9bae2c779353998e3e99ac7dfff4222fc6126650e93c3f3/filelock-3.14.0-py3-none-any.whl + sha256: 43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f requires_dist: - - furo >=2023.9.10 ; extra == 'docs' - - sphinx-autodoc-typehints !=1.23.4, >=1.25.2 ; extra == 'docs' - - sphinx >=7.2.6 ; extra == 'docs' - - covdefaults >=2.3 ; extra == 'testing' - - coverage >=7.3.2 ; extra == 'testing' - - diff-cover >=8.0.1 ; extra == 'testing' - - pytest-cov >=4.1 ; extra == 'testing' - - pytest-mock >=3.12 ; extra == 'testing' - - pytest-timeout >=2.2 ; extra == 'testing' - - pytest >=7.4.3 ; extra == 'testing' - - typing-extensions >=4.8 ; python_version < '3.11' and extra == 'typing' + - furo>=2023.9.10 ; extra == 'docs' + - sphinx-autodoc-typehints!=1.23.4,>=1.25.2 ; extra == 'docs' + - sphinx>=7.2.6 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'testing' + - coverage>=7.3.2 ; extra == 'testing' + - diff-cover>=8.0.1 ; extra == 'testing' + - pytest-cov>=4.1 ; extra == 'testing' + - pytest-mock>=3.12 ; extra == 'testing' + - pytest-timeout>=2.2 ; extra == 'testing' + - pytest>=7.4.3 ; extra == 'testing' + - typing-extensions>=4.8 ; python_version < '3.11' and extra == 'typing' requires_python: '>=3.8' - kind: pypi name: flatbuffers @@ -9994,162 +9783,162 @@ packages: - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/84/51/8203a3e6e475e6766ac950638d42f45470f36c6a4f0615ff0a1c1f2ed0d6/fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8ac27f436e8af7779f0bb4d5425aa3535270494d3bc5459ed27de3f03151e4c2 + url: https://files.pythonhosted.org/packages/c6/b5/dc17e93f60567fa1b0fa3720c2f28e0df5293927e2356e066e87af9adaba/fonttools-4.51.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b2b92381f37b39ba2fc98c3a45a9d6383bfc9916a87d66ccb6553f7bdd129097 requires_dist: - - fs <3, >=2.2.0 ; extra == 'all' - - lxml >=4.0 ; extra == 'all' - - zopfli >=0.1.4 ; extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'all' + - fs<3,>=2.2.0 ; extra == 'all' + - lxml>=4.0 ; extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops >=0.5.0 ; extra == 'all' - - uharfbuzz >=0.23.0 ; extra == 'all' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.23.0 ; extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'graphite' + - lz4>=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml >=4.0 ; extra == 'lxml' - - skia-pathops >=0.5.0 ; extra == 'pathops' + - lxml>=4.0 ; extra == 'lxml' + - skia-pathops>=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz >=0.23.0 ; extra == 'repacker' + - uharfbuzz>=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs <3, >=2.2.0 ; extra == 'ufo' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli >=0.1.4 ; extra == 'woff' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs<3,>=2.2.0 ; extra == 'ufo' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli>=0.1.4 ; extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/33/47/f2ca671af61757eaaac608963dda5b76ec9100621e45d0fd63a153fd8cd7/fonttools-4.51.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: a8feca65bab31479d795b0d16c9a9852902e3a3c0630678efb0b2b7941ea9c74 + url: https://files.pythonhosted.org/packages/84/51/8203a3e6e475e6766ac950638d42f45470f36c6a4f0615ff0a1c1f2ed0d6/fonttools-4.51.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 8ac27f436e8af7779f0bb4d5425aa3535270494d3bc5459ed27de3f03151e4c2 requires_dist: - - fs <3, >=2.2.0 ; extra == 'all' - - lxml >=4.0 ; extra == 'all' - - zopfli >=0.1.4 ; extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'all' + - fs<3,>=2.2.0 ; extra == 'all' + - lxml>=4.0 ; extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops >=0.5.0 ; extra == 'all' - - uharfbuzz >=0.23.0 ; extra == 'all' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.23.0 ; extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'graphite' + - lz4>=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml >=4.0 ; extra == 'lxml' - - skia-pathops >=0.5.0 ; extra == 'pathops' + - lxml>=4.0 ; extra == 'lxml' + - skia-pathops>=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz >=0.23.0 ; extra == 'repacker' + - uharfbuzz>=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs <3, >=2.2.0 ; extra == 'ufo' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli >=0.1.4 ; extra == 'woff' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs<3,>=2.2.0 ; extra == 'ufo' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli>=0.1.4 ; extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/c6/b5/dc17e93f60567fa1b0fa3720c2f28e0df5293927e2356e066e87af9adaba/fonttools-4.51.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b2b92381f37b39ba2fc98c3a45a9d6383bfc9916a87d66ccb6553f7bdd129097 + url: https://files.pythonhosted.org/packages/c5/d4/f426fa1ca42e47bcfff0c878fa9d49d9c03379d00903a7c178f95b97867a/fonttools-4.51.0-cp311-cp311-win_amd64.whl + sha256: 0f08c901d3866a8905363619e3741c33f0a83a680d92a9f0e575985c2634fcc1 requires_dist: - - fs <3, >=2.2.0 ; extra == 'all' - - lxml >=4.0 ; extra == 'all' - - zopfli >=0.1.4 ; extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'all' + - fs<3,>=2.2.0 ; extra == 'all' + - lxml>=4.0 ; extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops >=0.5.0 ; extra == 'all' - - uharfbuzz >=0.23.0 ; extra == 'all' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.23.0 ; extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'graphite' + - lz4>=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml >=4.0 ; extra == 'lxml' - - skia-pathops >=0.5.0 ; extra == 'pathops' + - lxml>=4.0 ; extra == 'lxml' + - skia-pathops>=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz >=0.23.0 ; extra == 'repacker' + - uharfbuzz>=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs <3, >=2.2.0 ; extra == 'ufo' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli >=0.1.4 ; extra == 'woff' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs<3,>=2.2.0 ; extra == 'ufo' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli>=0.1.4 ; extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: fonttools version: 4.51.0 - url: https://files.pythonhosted.org/packages/c5/d4/f426fa1ca42e47bcfff0c878fa9d49d9c03379d00903a7c178f95b97867a/fonttools-4.51.0-cp311-cp311-win_amd64.whl - sha256: 0f08c901d3866a8905363619e3741c33f0a83a680d92a9f0e575985c2634fcc1 + url: https://files.pythonhosted.org/packages/33/47/f2ca671af61757eaaac608963dda5b76ec9100621e45d0fd63a153fd8cd7/fonttools-4.51.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: a8feca65bab31479d795b0d16c9a9852902e3a3c0630678efb0b2b7941ea9c74 requires_dist: - - fs <3, >=2.2.0 ; extra == 'all' - - lxml >=4.0 ; extra == 'all' - - zopfli >=0.1.4 ; extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'all' + - fs<3,>=2.2.0 ; extra == 'all' + - lxml>=4.0 ; extra == 'all' + - zopfli>=0.1.4 ; extra == 'all' + - lz4>=1.7.4.2 ; extra == 'all' - pycairo ; extra == 'all' - matplotlib ; extra == 'all' - sympy ; extra == 'all' - - skia-pathops >=0.5.0 ; extra == 'all' - - uharfbuzz >=0.23.0 ; extra == 'all' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' + - skia-pathops>=0.5.0 ; extra == 'all' + - uharfbuzz>=0.23.0 ; extra == 'all' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'all' - scipy ; platform_python_implementation != 'PyPy' and extra == 'all' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'all' - munkres ; platform_python_implementation == 'PyPy' and extra == 'all' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'all' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'all' - xattr ; sys_platform == 'darwin' and extra == 'all' - - lz4 >=1.7.4.2 ; extra == 'graphite' + - lz4>=1.7.4.2 ; extra == 'graphite' - pycairo ; extra == 'interpolatable' - scipy ; platform_python_implementation != 'PyPy' and extra == 'interpolatable' - munkres ; platform_python_implementation == 'PyPy' and extra == 'interpolatable' - - lxml >=4.0 ; extra == 'lxml' - - skia-pathops >=0.5.0 ; extra == 'pathops' + - lxml>=4.0 ; extra == 'lxml' + - skia-pathops>=0.5.0 ; extra == 'pathops' - matplotlib ; extra == 'plot' - - uharfbuzz >=0.23.0 ; extra == 'repacker' + - uharfbuzz>=0.23.0 ; extra == 'repacker' - sympy ; extra == 'symfont' - xattr ; sys_platform == 'darwin' and extra == 'type1' - - fs <3, >=2.2.0 ; extra == 'ufo' - - unicodedata2 >=15.1.0 ; python_version <= '3.12' and extra == 'unicode' - - zopfli >=0.1.4 ; extra == 'woff' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' - - brotli >=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' + - fs<3,>=2.2.0 ; extra == 'ufo' + - unicodedata2>=15.1.0 ; python_version <= '3.12' and extra == 'unicode' + - zopfli>=0.1.4 ; extra == 'woff' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'woff' + - brotli>=1.0.1 ; platform_python_implementation == 'CPython' and extra == 'woff' requires_python: '>=3.8' - kind: pypi name: freetype-py version: 2.4.0 - url: https://files.pythonhosted.org/packages/7c/77/faec42d1ffac2b970f606860a5bb083d606f1c673a5c57ab26382c8efec1/freetype_py-2.4.0-py3-none-macosx_10_9_universal2.whl - sha256: 3e0f5a91bc812f42d98a92137e86bac4ed037a29e43dafdb76d716d5732189e8 + url: https://files.pythonhosted.org/packages/5f/34/76cfe866e482745ea8c9956b0be6198fd72d08d2be77b71596afdb8cd89f/freetype_py-2.4.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl + sha256: ce931f581d5038c4fea1f3d314254e0264e92441a5fdaef6817fe77b7bb888d3 requires_python: '>=3.7' - kind: pypi name: freetype-py version: 2.4.0 - url: https://files.pythonhosted.org/packages/5f/34/76cfe866e482745ea8c9956b0be6198fd72d08d2be77b71596afdb8cd89f/freetype_py-2.4.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl - sha256: ce931f581d5038c4fea1f3d314254e0264e92441a5fdaef6817fe77b7bb888d3 + url: https://files.pythonhosted.org/packages/7c/77/faec42d1ffac2b970f606860a5bb083d606f1c673a5c57ab26382c8efec1/freetype_py-2.4.0-py3-none-macosx_10_9_universal2.whl + sha256: 3e0f5a91bc812f42d98a92137e86bac4ed037a29e43dafdb76d716d5732189e8 requires_python: '>=3.7' - kind: pypi name: freetype-py @@ -10263,7 +10052,7 @@ packages: requires_dist: - adlfs ; extra == 'abfs' - adlfs ; extra == 'adl' - - pyarrow >=1 ; extra == 'arrow' + - pyarrow>=1 ; extra == 'arrow' - dask ; extra == 'dask' - distributed ; extra == 'dask' - pytest ; extra == 'devel' @@ -10272,7 +10061,7 @@ packages: - requests ; extra == 'dropbox' - dropbox ; extra == 'dropbox' - adlfs ; extra == 'full' - - aiohttp !=4.0.0a0, !=4.0.0a1 ; extra == 'full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' - dask ; extra == 'full' - distributed ; extra == 'full' - dropbox ; extra == 'full' @@ -10283,7 +10072,7 @@ packages: - ocifs ; extra == 'full' - panel ; extra == 'full' - paramiko ; extra == 'full' - - pyarrow >=1 ; extra == 'full' + - pyarrow>=1 ; extra == 'full' - pygit2 ; extra == 'full' - requests ; extra == 'full' - s3fs ; extra == 'full' @@ -10295,8 +10084,8 @@ packages: - requests ; extra == 'github' - gcsfs ; extra == 'gs' - panel ; extra == 'gui' - - pyarrow >=1 ; extra == 'hdfs' - - aiohttp !=4.0.0a0, !=4.0.0a1 ; extra == 'http' + - pyarrow>=1 ; extra == 'hdfs' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' - libarchive-c ; extra == 'libarchive' - ocifs ; extra == 'oci' - s3fs ; extra == 's3' @@ -10417,11 +10206,11 @@ packages: path: examples/python/gesture_detection sha256: 36dfc4cc822ee47f7aa29ba951bab8a94e96b9fd737daa324a441e6962a620bd requires_dist: - - mediapipe ==0.10.11 ; sys_platform != 'darwin' - - mediapipe ==0.10.9 ; sys_platform == 'darwin' + - mediapipe==0.10.11 ; sys_platform != 'darwin' + - mediapipe==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python >4.9 - - requests <3, >=2.31 + - opencv-python>4.9 + - requests>=2.31,<3 - rerun-sdk - tqdm requires_python: <3.12 @@ -10737,17 +10526,17 @@ packages: url: https://files.pythonhosted.org/packages/86/75/59a3ad90d9b4ff5b3e0537611dbe885aeb96124521c9d35aa079f1e0f2c9/google_api_core-2.18.0-py3-none-any.whl sha256: 5a63aa102e0049abe85b5b88cb9409234c1f70afcda21ce1e40b285b9629c1d6 requires_dist: - - googleapis-common-protos <2.0.dev0, >=1.56.2 - - protobuf !=3.20.0, !=3.20.1, !=4.21.0, !=4.21.1, !=4.21.2, !=4.21.3, !=4.21.4, !=4.21.5, <5.0.0.dev0, >=3.19.5 - - proto-plus <2.0.0.dev0, >=1.22.3 - - google-auth <3.0.dev0, >=2.14.1 - - requests <3.0.0.dev0, >=2.18.0 - - grpcio <2.0.dev0, >=1.33.2 ; extra == 'grpc' - - grpcio-status <2.0.dev0, >=1.33.2 ; extra == 'grpc' - - grpcio <2.0.dev0, >=1.49.1 ; python_version >= '3.11' and extra == 'grpc' - - grpcio-status <2.0.dev0, >=1.49.1 ; python_version >= '3.11' and extra == 'grpc' - - grpcio-gcp <1.0.dev0, >=0.2.2 ; extra == 'grpcgcp' - - grpcio-gcp <1.0.dev0, >=0.2.2 ; extra == 'grpcio-gcp' + - googleapis-common-protos<2.0.dev0,>=1.56.2 + - protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0,>=3.19.5 + - proto-plus<2.0.0.dev0,>=1.22.3 + - google-auth<3.0.dev0,>=2.14.1 + - requests<3.0.0.dev0,>=2.18.0 + - grpcio<2.0.dev0,>=1.33.2 ; extra == 'grpc' + - grpcio-status<2.0.dev0,>=1.33.2 ; extra == 'grpc' + - grpcio<2.0.dev0,>=1.49.1 ; python_version >= '3.11' and extra == 'grpc' + - grpcio-status<2.0.dev0,>=1.49.1 ; python_version >= '3.11' and extra == 'grpc' + - grpcio-gcp<1.0.dev0,>=0.2.2 ; extra == 'grpcgcp' + - grpcio-gcp<1.0.dev0,>=0.2.2 ; extra == 'grpcio-gcp' requires_python: '>=3.7' - kind: pypi name: google-auth @@ -10755,17 +10544,17 @@ packages: url: https://files.pythonhosted.org/packages/9e/8d/ddbcf81ec751d8ee5fd18ac11ff38a0e110f39dfbf105e6d9db69d556dd0/google_auth-2.29.0-py2.py3-none-any.whl sha256: d452ad095688cd52bae0ad6fafe027f6a6d6f560e810fec20914e17a09526415 requires_dist: - - cachetools <6.0, >=2.0.0 - - pyasn1-modules >=0.2.1 - - rsa <5, >=3.1.4 - - aiohttp <4.0.0.dev0, >=3.6.2 ; extra == 'aiohttp' - - requests <3.0.0.dev0, >=2.20.0 ; extra == 'aiohttp' - - cryptography ==36.0.2 ; extra == 'enterprise_cert' - - pyopenssl ==22.0.0 ; extra == 'enterprise_cert' - - pyopenssl >=20.0.0 ; extra == 'pyopenssl' - - cryptography >=38.0.3 ; extra == 'pyopenssl' - - pyu2f >=0.1.5 ; extra == 'reauth' - - requests <3.0.0.dev0, >=2.20.0 ; extra == 'requests' + - cachetools<6.0,>=2.0.0 + - pyasn1-modules>=0.2.1 + - rsa<5,>=3.1.4 + - aiohttp<4.0.0.dev0,>=3.6.2 ; extra == 'aiohttp' + - requests<3.0.0.dev0,>=2.20.0 ; extra == 'aiohttp' + - cryptography==36.0.2 ; extra == 'enterprise_cert' + - pyopenssl==22.0.0 ; extra == 'enterprise_cert' + - pyopenssl>=20.0.0 ; extra == 'pyopenssl' + - cryptography>=38.0.3 ; extra == 'pyopenssl' + - pyu2f>=0.1.5 ; extra == 'reauth' + - requests<3.0.0.dev0,>=2.20.0 ; extra == 'requests' requires_python: '>=3.7' - kind: pypi name: google-cloud-core @@ -10773,11 +10562,11 @@ packages: url: https://files.pythonhosted.org/packages/5e/0f/2e2061e3fbcb9d535d5da3f58cc8de4947df1786fe6a1355960feb05a681/google_cloud_core-2.4.1-py2.py3-none-any.whl sha256: a9e6a4422b9ac5c29f79a0ede9485473338e2ce78d91f2370c01e730eab22e61 requires_dist: - - google-api-core !=2.0.*, !=2.1.*, !=2.2.*, !=2.3.0, <3.0.0.dev0, >=1.31.6 - - google-auth <3.0.dev0, >=1.25.0 - - importlib-metadata >1.0.0 ; python_version < '3.8' - - grpcio <2.0.dev0, >=1.38.0 ; extra == 'grpc' - - grpcio-status <2.0.dev0, >=1.38.0 ; extra == 'grpc' + - google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0.dev0,>=1.31.6 + - google-auth<3.0.dev0,>=1.25.0 + - importlib-metadata>1.0.0 ; python_version < '3.8' + - grpcio<2.0.dev0,>=1.38.0 ; extra == 'grpc' + - grpcio-status<2.0.dev0,>=1.38.0 ; extra == 'grpc' requires_python: '>=3.7' - kind: pypi name: google-cloud-storage @@ -10785,50 +10574,50 @@ packages: url: https://files.pythonhosted.org/packages/74/fb/3770e7f44cf6133f502e1b8503b6739351b53272cf8313b47f1de6cf4960/google_cloud_storage-2.9.0-py2.py3-none-any.whl sha256: 83a90447f23d5edd045e0037982c270302e3aeb45fc1288d2c2ca713d27bad94 requires_dist: - - google-auth <3.0.dev0, >=1.25.0 - - google-api-core !=2.0.*, !=2.1.*, !=2.2.*, !=2.3.0, <3.0.0.dev0, >=1.31.5 - - google-cloud-core <3.0.dev0, >=2.3.0 - - google-resumable-media >=2.3.2 - - requests <3.0.0.dev0, >=2.18.0 - - protobuf <5.0.0.dev0 ; extra == 'protobuf' + - google-auth<3.0.dev0,>=1.25.0 + - google-api-core!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0,<3.0.0.dev0,>=1.31.5 + - google-cloud-core<3.0.dev0,>=2.3.0 + - google-resumable-media>=2.3.2 + - requests<3.0.0.dev0,>=2.18.0 + - protobuf<5.0.0.dev0 ; extra == 'protobuf' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 + url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 + url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -10838,10 +10627,10 @@ packages: url: https://files.pythonhosted.org/packages/b2/c6/1202ef64a9336d846f713107dac1c7a0b016cb3840ca3d5615c7005a23d1/google_resumable_media-2.7.0-py2.py3-none-any.whl sha256: 79543cfe433b63fd81c0844b7803aba1bb8950b47bedf7d980c38fa123937e08 requires_dist: - - google-crc32c <2.0.dev0, >=1.0 - - aiohttp <4.0.0.dev0, >=3.6.2 ; extra == 'aiohttp' - - google-auth <2.0.dev0, >=1.22.0 ; extra == 'aiohttp' - - requests <3.0.0.dev0, >=2.18.0 ; extra == 'requests' + - google-crc32c<2.0.dev0,>=1.0 + - aiohttp<4.0.0.dev0,>=3.6.2 ; extra == 'aiohttp' + - google-auth<2.0.dev0,>=1.22.0 ; extra == 'aiohttp' + - requests<3.0.0.dev0,>=2.18.0 ; extra == 'requests' requires_python: '>=3.7' - kind: pypi name: googleapis-common-protos @@ -10849,8 +10638,8 @@ packages: url: https://files.pythonhosted.org/packages/dc/a6/12a0c976140511d8bc8a16ad15793b2aef29ac927baa0786ccb7ddbb6e1c/googleapis_common_protos-1.63.0-py2.py3-none-any.whl sha256: ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632 requires_dist: - - protobuf !=3.20.0, !=3.20.1, !=4.21.1, !=4.21.2, !=4.21.3, !=4.21.4, !=4.21.5, <5.0.0.dev0, >=3.19.5 - - grpcio <2.0.0.dev0, >=1.44.0 ; extra == 'grpc' + - protobuf!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0.dev0,>=3.19.5 + - grpcio<2.0.0.dev0,>=1.44.0 ; extra == 'grpc' requires_python: '>=3.7' - kind: pypi name: grpclib @@ -10858,9 +10647,9 @@ packages: url: https://files.pythonhosted.org/packages/79/b9/55936e462a5925190d7427e880b3033601d1effd13809b483d13a926061a/grpclib-0.4.7.tar.gz sha256: 2988ef57c02b22b7a2e8e961792c41ccf97efc2ace91ae7a5b0de03c363823c3 requires_dist: - - h2 <5, >=3.1.0 + - h2<5,>=3.1.0 - multidict - - protobuf >=3.20.0 ; extra == 'protobuf' + - protobuf>=3.20.0 ; extra == 'protobuf' requires_python: '>=3.7' - kind: conda name: gxx @@ -10970,8 +10759,8 @@ packages: url: https://files.pythonhosted.org/packages/2a/e5/db6d438da759efbb488c4f3fbdab7764492ff3c3f953132efa6b9f0e9e53/h2-4.1.0-py3-none-any.whl sha256: 03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d requires_dist: - - hyperframe <7, >=6.0 - - hpack <5, >=4.0 + - hyperframe<7,>=6.0 + - hpack<5,>=4.0 requires_python: '>=3.6.1' - kind: pypi name: hpack @@ -10985,12 +10774,12 @@ packages: url: https://files.pythonhosted.org/packages/6c/dd/a834df6482147d48e225a49515aabc28974ad5a4ca3215c18a882565b028/html5lib-1.1-py2.py3-none-any.whl sha256: 0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d requires_dist: - - six >=1.9 + - six>=1.9 - webencodings - genshi ; extra == 'all' - - chardet >=2.2 ; extra == 'all' + - chardet>=2.2 ; extra == 'all' - lxml ; platform_python_implementation == 'CPython' and extra == 'all' - - chardet >=2.2 ; extra == 'chardet' + - chardet>=2.2 ; extra == 'chardet' - genshi ; extra == 'genshi' - lxml ; platform_python_implementation == 'CPython' and extra == 'lxml' requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*' @@ -11001,15 +10790,15 @@ packages: sha256: 3429e25f38ccb834d310804a3b711e7e4953db5a9e420cc147a5e194ca90fd17 requires_dist: - filelock - - fsspec >=2023.5.0 - - packaging >=20.9 - - pyyaml >=5.1 + - fsspec>=2023.5.0 + - packaging>=20.9 + - pyyaml>=5.1 - requests - - tqdm >=4.42.1 - - typing-extensions >=3.7.4.3 - - inquirerpy ==0.3.4 ; extra == 'all' + - tqdm>=4.42.1 + - typing-extensions>=3.7.4.3 + - inquirerpy==0.3.4 ; extra == 'all' - aiohttp ; extra == 'all' - - minijinja >=1.0 ; extra == 'all' + - minijinja>=1.0 ; extra == 'all' - jedi ; extra == 'all' - jinja2 ; extra == 'all' - pytest ; extra == 'all' @@ -11019,24 +10808,24 @@ packages: - pytest-vcr ; extra == 'all' - pytest-asyncio ; extra == 'all' - pytest-rerunfailures ; extra == 'all' - - urllib3 <2.0 ; extra == 'all' + - urllib3<2.0 ; extra == 'all' - soundfile ; extra == 'all' - pillow ; extra == 'all' - gradio ; extra == 'all' - numpy ; extra == 'all' - - ruff >=0.3.0 ; extra == 'all' - - mypy ==1.5.1 ; extra == 'all' - - typing-extensions >=4.8.0 ; extra == 'all' + - ruff>=0.3.0 ; extra == 'all' + - mypy==1.5.1 ; extra == 'all' + - typing-extensions>=4.8.0 ; extra == 'all' - types-pyyaml ; extra == 'all' - types-requests ; extra == 'all' - types-simplejson ; extra == 'all' - types-toml ; extra == 'all' - types-tqdm ; extra == 'all' - types-urllib3 ; extra == 'all' - - inquirerpy ==0.3.4 ; extra == 'cli' - - inquirerpy ==0.3.4 ; extra == 'dev' + - inquirerpy==0.3.4 ; extra == 'cli' + - inquirerpy==0.3.4 ; extra == 'dev' - aiohttp ; extra == 'dev' - - minijinja >=1.0 ; extra == 'dev' + - minijinja>=1.0 ; extra == 'dev' - jedi ; extra == 'dev' - jinja2 ; extra == 'dev' - pytest ; extra == 'dev' @@ -11046,14 +10835,14 @@ packages: - pytest-vcr ; extra == 'dev' - pytest-asyncio ; extra == 'dev' - pytest-rerunfailures ; extra == 'dev' - - urllib3 <2.0 ; extra == 'dev' + - urllib3<2.0 ; extra == 'dev' - soundfile ; extra == 'dev' - pillow ; extra == 'dev' - gradio ; extra == 'dev' - numpy ; extra == 'dev' - - ruff >=0.3.0 ; extra == 'dev' - - mypy ==1.5.1 ; extra == 'dev' - - typing-extensions >=4.8.0 ; extra == 'dev' + - ruff>=0.3.0 ; extra == 'dev' + - mypy==1.5.1 ; extra == 'dev' + - typing-extensions>=4.8.0 ; extra == 'dev' - types-pyyaml ; extra == 'dev' - types-requests ; extra == 'dev' - types-simplejson ; extra == 'dev' @@ -11061,21 +10850,21 @@ packages: - types-tqdm ; extra == 'dev' - types-urllib3 ; extra == 'dev' - toml ; extra == 'fastai' - - fastai >=2.4 ; extra == 'fastai' - - fastcore >=1.3.27 ; extra == 'fastai' - - hf-transfer >=0.1.4 ; extra == 'hf_transfer' + - fastai>=2.4 ; extra == 'fastai' + - fastcore>=1.3.27 ; extra == 'fastai' + - hf-transfer>=0.1.4 ; extra == 'hf_transfer' - aiohttp ; extra == 'inference' - - minijinja >=1.0 ; extra == 'inference' - - ruff >=0.3.0 ; extra == 'quality' - - mypy ==1.5.1 ; extra == 'quality' + - minijinja>=1.0 ; extra == 'inference' + - ruff>=0.3.0 ; extra == 'quality' + - mypy==1.5.1 ; extra == 'quality' - tensorflow ; extra == 'tensorflow' - pydot ; extra == 'tensorflow' - graphviz ; extra == 'tensorflow' - tensorflow ; extra == 'tensorflow-testing' - - keras <3.0 ; extra == 'tensorflow-testing' - - inquirerpy ==0.3.4 ; extra == 'testing' + - keras<3.0 ; extra == 'tensorflow-testing' + - inquirerpy==0.3.4 ; extra == 'testing' - aiohttp ; extra == 'testing' - - minijinja >=1.0 ; extra == 'testing' + - minijinja>=1.0 ; extra == 'testing' - jedi ; extra == 'testing' - jinja2 ; extra == 'testing' - pytest ; extra == 'testing' @@ -11085,14 +10874,14 @@ packages: - pytest-vcr ; extra == 'testing' - pytest-asyncio ; extra == 'testing' - pytest-rerunfailures ; extra == 'testing' - - urllib3 <2.0 ; extra == 'testing' + - urllib3<2.0 ; extra == 'testing' - soundfile ; extra == 'testing' - pillow ; extra == 'testing' - gradio ; extra == 'testing' - numpy ; extra == 'testing' - torch ; extra == 'torch' - safetensors ; extra == 'torch' - - typing-extensions >=4.8.0 ; extra == 'typing' + - typing-extensions>=4.8.0 ; extra == 'typing' - types-pyyaml ; extra == 'typing' - types-requests ; extra == 'typing' - types-simplejson ; extra == 'typing' @@ -11106,11 +10895,11 @@ packages: path: examples/python/human_pose_tracking sha256: 8a80b67528d3f6d0c82671dc5c36cf551faa4b879f4434f0d386d8ef85666e86 requires_dist: - - mediapipe ==0.10.11 ; sys_platform != 'darwin' - - mediapipe ==0.10.9 ; sys_platform == 'darwin' + - mediapipe==0.10.11 ; sys_platform != 'darwin' + - mediapipe==0.10.9 ; sys_platform == 'darwin' - numpy - - opencv-python >4.6 - - requests <3, >=2.31 + - opencv-python>4.6 + - requests>=2.31,<3 - rerun-sdk requires_python: <3.12 editable: true @@ -11214,7 +11003,7 @@ packages: sha256: 408c1d4d62f72c9e8347e7d1ca9bc11d8673328af3913868db3b828e28b40a4c requires_dist: - numpy - - pillow >=8.3.2 + - pillow>=8.3.2 - astropy ; extra == 'all-plugins' - av ; extra == 'all-plugins' - imageio-ffmpeg ; extra == 'all-plugins' @@ -11232,7 +11021,7 @@ packages: - fsspec[github] ; extra == 'dev' - black ; extra == 'dev' - flake8 ; extra == 'dev' - - sphinx <6 ; extra == 'docs' + - sphinx<6 ; extra == 'docs' - numpydoc ; extra == 'docs' - pydata-sphinx-theme ; extra == 'docs' - imageio-ffmpeg ; extra == 'ffmpeg' @@ -11252,7 +11041,7 @@ packages: - pydata-sphinx-theme ; extra == 'full' - pytest ; extra == 'full' - pytest-cov ; extra == 'full' - - sphinx <6 ; extra == 'full' + - sphinx<6 ; extra == 'full' - tifffile ; extra == 'full' - wheel ; extra == 'full' - gdal ; extra == 'gdal' @@ -11272,27 +11061,27 @@ packages: url: https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl sha256: 30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570 requires_dist: - - zipp >=0.5 - - typing-extensions >=3.6.4 ; python_version < '3.8' - - sphinx >=3.5 ; extra == 'docs' - - jaraco-packaging >=9.3 ; extra == 'docs' - - rst-linker >=1.9 ; extra == 'docs' + - zipp>=0.5 + - typing-extensions>=3.6.4 ; python_version < '3.8' + - sphinx>=3.5 ; extra == 'docs' + - jaraco-packaging>=9.3 ; extra == 'docs' + - rst-linker>=1.9 ; extra == 'docs' - furo ; extra == 'docs' - sphinx-lint ; extra == 'docs' - - jaraco-tidelift >=1.4 ; extra == 'docs' + - jaraco-tidelift>=1.4 ; extra == 'docs' - ipython ; extra == 'perf' - - pytest >=6 ; extra == 'testing' - - pytest-checkdocs >=2.4 ; extra == 'testing' + - pytest>=6 ; extra == 'testing' + - pytest-checkdocs>=2.4 ; extra == 'testing' - pytest-cov ; extra == 'testing' - - pytest-enabler >=2.2 ; extra == 'testing' - - pytest-ruff >=0.2.1 ; extra == 'testing' + - pytest-enabler>=2.2 ; extra == 'testing' + - pytest-ruff>=0.2.1 ; extra == 'testing' - packaging ; extra == 'testing' - pyfakefs ; extra == 'testing' - flufl-flake8 ; extra == 'testing' - - pytest-perf >=0.9.2 ; extra == 'testing' - - jaraco-test >=5.4 ; extra == 'testing' + - pytest-perf>=0.9.2 ; extra == 'testing' + - jaraco-test>=5.4 ; extra == 'testing' - pytest-mypy ; platform_python_implementation != 'PyPy' and extra == 'testing' - - importlib-resources >=1.3 ; python_version < '3.9' and extra == 'testing' + - importlib-resources>=1.3 ; python_version < '3.9' and extra == 'testing' requires_python: '>=3.8' - kind: pypi name: incremental-logging @@ -11369,46 +11158,46 @@ packages: url: https://files.pythonhosted.org/packages/dc/d9/f387d9dfb2cf00f814b24e0f8bf6f4c68ae01870994dc436993fadd73563/jax-0.4.26-py3-none-any.whl sha256: 50dc795148ee6b0735b48b477e5abc556aa3a4c7af5d6940dad08024a908b02f requires_dist: - - ml-dtypes >=0.2.0 - - numpy >=1.22 + - ml-dtypes>=0.2.0 + - numpy>=1.22 - opt-einsum - - scipy >=1.9 - - importlib-metadata >=4.6 ; python_version < '3.10' - - numpy >=1.23.2 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - scipy >=1.11.1 ; python_version >= '3.12' - - protobuf <4, >=3.13 ; extra == 'australis' - - jaxlib ==0.4.25 ; extra == 'ci' - - jaxlib ==0.4.26 ; extra == 'cpu' - - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda' - - jaxlib ==0.4.26 ; extra == 'cuda12' - - jax-cuda12-plugin ==0.4.26 ; extra == 'cuda12' - - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12' - - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12' - - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12' - - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12' - - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12' - - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12' - - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12' - - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12' - - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12' - - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12' - - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_cudnn89' - - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_local' - - jaxlib ==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_pip' - - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12_pip' - - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12_pip' - - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12_pip' - - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12_pip' - - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12_pip' - - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12_pip' - - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - jaxlib ==0.4.20 ; extra == 'minimum-jaxlib' - - jaxlib ==0.4.26 ; extra == 'tpu' - - libtpu-nightly ==0.1.dev20240403 ; extra == 'tpu' + - scipy>=1.9 + - importlib-metadata>=4.6 ; python_version < '3.10' + - numpy>=1.23.2 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - scipy>=1.11.1 ; python_version >= '3.12' + - protobuf<4,>=3.13 ; extra == 'australis' + - jaxlib==0.4.25 ; extra == 'ci' + - jaxlib==0.4.26 ; extra == 'cpu' + - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda' + - jaxlib==0.4.26 ; extra == 'cuda12' + - jax-cuda12-plugin==0.4.26 ; extra == 'cuda12' + - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12' + - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12' + - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12' + - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12' + - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12' + - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12' + - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12' + - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12' + - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12' + - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12' + - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_cudnn89' + - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_local' + - jaxlib==0.4.26+cuda12.cudnn89 ; extra == 'cuda12_pip' + - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12_pip' + - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12_pip' + - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12_pip' + - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12_pip' + - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12_pip' + - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12_pip' + - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12_pip' + - jaxlib==0.4.20 ; extra == 'minimum-jaxlib' + - jaxlib==0.4.26 ; extra == 'tpu' + - libtpu-nightly==0.1.dev20240403 ; extra == 'tpu' - requests ; extra == 'tpu' requires_python: '>=3.9' - kind: pypi @@ -11417,20 +11206,20 @@ packages: url: https://files.pythonhosted.org/packages/a9/41/6bbe0a55e4df1c5d30da02dc3d26be2aea6333af9c35c6d846d431b86c74/jaxlib-0.4.26-cp311-cp311-manylinux2014_x86_64.whl sha256: 3069da7d75f5b4dd15350fffe6e6b86ca09c4b9fde60b10515edb09cef653335 requires_dist: - - scipy >=1.9 - - numpy >=1.22 - - ml-dtypes >=0.2.0 - - scipy >=1.11.1 ; python_version >= '3.12' - - nvidia-cublas-cu12 >=12.1.3.1 ; extra == 'cuda12_pip' - - nvidia-cuda-cupti-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-nvcc-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cuda-runtime-cu12 >=12.1.105 ; extra == 'cuda12_pip' - - nvidia-cudnn-cu12 <9.0, >=8.9.2.26 ; extra == 'cuda12_pip' - - nvidia-cufft-cu12 >=11.0.2.54 ; extra == 'cuda12_pip' - - nvidia-cusolver-cu12 >=11.4.5.107 ; extra == 'cuda12_pip' - - nvidia-cusparse-cu12 >=12.1.0.106 ; extra == 'cuda12_pip' - - nvidia-nccl-cu12 >=2.18.1 ; extra == 'cuda12_pip' - - nvidia-nvjitlink-cu12 >=12.1.105 ; extra == 'cuda12_pip' + - scipy>=1.9 + - numpy>=1.22 + - ml-dtypes>=0.2.0 + - scipy>=1.11.1 ; python_version >= '3.12' + - nvidia-cublas-cu12>=12.1.3.1 ; extra == 'cuda12_pip' + - nvidia-cuda-cupti-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-nvcc-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cuda-runtime-cu12>=12.1.105 ; extra == 'cuda12_pip' + - nvidia-cudnn-cu12<9.0,>=8.9.2.26 ; extra == 'cuda12_pip' + - nvidia-cufft-cu12>=11.0.2.54 ; extra == 'cuda12_pip' + - nvidia-cusolver-cu12>=11.4.5.107 ; extra == 'cuda12_pip' + - nvidia-cusparse-cu12>=12.1.0.106 ; extra == 'cuda12_pip' + - nvidia-nccl-cu12>=2.18.1 ; extra == 'cuda12_pip' + - nvidia-nvjitlink-cu12>=12.1.105 ; extra == 'cuda12_pip' requires_python: '>=3.9' - kind: pypi name: jinja2 @@ -11438,8 +11227,8 @@ packages: url: https://files.pythonhosted.org/packages/30/6d/6de6be2d02603ab56e72997708809e8a5b0fbfee080735109b40a3564843/Jinja2-3.1.3-py3-none-any.whl sha256: 7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa requires_dist: - - markupsafe >=2.0 - - babel >=2.7 ; extra == 'i18n' + - markupsafe>=2.0 + - babel>=2.7 ; extra == 'i18n' requires_python: '>=3.7' - kind: conda name: jinja2 @@ -11528,32 +11317,32 @@ packages: - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90 + url: https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797 + url: https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e + url: https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl + sha256: 6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl - sha256: 6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355 + url: https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' @@ -11654,10 +11443,10 @@ packages: requires_dist: - packaging - importlib-metadata ; python_version < '3.8' - - changelist ==0.5 ; extra == 'dev' - - pre-commit ==3.7.0 ; extra == 'lint' - - pytest >=7.4 ; extra == 'test' - - pytest-cov >=4.1 ; extra == 'test' + - changelist==0.5 ; extra == 'dev' + - pre-commit==3.7.0 ; extra == 'lint' + - pytest>=7.4 ; extra == 'test' + - pytest-cov>=4.1 ; extra == 'test' requires_python: '>=3.7' - kind: conda name: ld64 @@ -20089,26 +19878,26 @@ packages: - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/13/97/4aac09bdfc1bc35f8eb64e21ff5897224a788170e5e8cab3e62c9eb78efb/llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf + url: https://files.pythonhosted.org/packages/a4/1f/300788b5eab99aec872ed2f3647386d7d7f7bbf4f99c91e9e023b404ff7f/llvmlite-0.42.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: c5bece0cdf77f22379f19b1959ccd7aee518afa4afbd3656c6365865f84903f9 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/ba/3a/286d01191e62ddbe645d4a3f1e0d96106a98d3fd7f82441d20ffe93ab669/llvmlite-0.42.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 81e674c2fe85576e6c4474e8c7e7aba7901ac0196e864fe7985492b737dbab65 + url: https://files.pythonhosted.org/packages/13/97/4aac09bdfc1bc35f8eb64e21ff5897224a788170e5e8cab3e62c9eb78efb/llvmlite-0.42.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: ae511caed28beaf1252dbaf5f40e663f533b79ceb408c874c01754cafabb9cbf requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/a4/1f/300788b5eab99aec872ed2f3647386d7d7f7bbf4f99c91e9e023b404ff7f/llvmlite-0.42.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: c5bece0cdf77f22379f19b1959ccd7aee518afa4afbd3656c6365865f84903f9 + url: https://files.pythonhosted.org/packages/f3/bd/3b27a1c8bbbe01b053f5e0c9ca9a37dbc3e39282dfcf596d143ad389f156/llvmlite-0.42.0-cp311-cp311-win_amd64.whl + sha256: 7e0c4c11c8c2aa9b0701f91b799cb9134a6a6de51444eff5a9087fc7c1384275 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.42.0 - url: https://files.pythonhosted.org/packages/f3/bd/3b27a1c8bbbe01b053f5e0c9ca9a37dbc3e39282dfcf596d143ad389f156/llvmlite-0.42.0-cp311-cp311-win_amd64.whl - sha256: 7e0c4c11c8c2aa9b0701f91b799cb9134a6a6de51444eff5a9087fc7c1384275 + url: https://files.pythonhosted.org/packages/ba/3a/286d01191e62ddbe645d4a3f1e0d96106a98d3fd7f82441d20ffe93ab669/llvmlite-0.42.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 81e674c2fe85576e6c4474e8c7e7aba7901ac0196e864fe7985492b737dbab65 requires_python: '>=3.9' - kind: pypi name: log-file @@ -20121,50 +19910,50 @@ packages: - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/95/4c/fc5e63fb41e867f530a70519e1bcab0c14e84a95aa659f697bc97531be96/lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe + url: https://files.pythonhosted.org/packages/be/c3/1765e019344d3f042dfe750eb9a424c0ea2fd43deb6b2ac176b5603a436e/lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: 200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095 requires_dist: - - cssselect >=0.7 ; extra == 'cssselect' + - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython >=3.0.10 ; extra == 'source' + - cython>=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/43/43/66a84c2a034f5df2782240cb2f68696a72ad6734d7a91f824e0360cde08b/lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl - sha256: 70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867 + url: https://files.pythonhosted.org/packages/95/4c/fc5e63fb41e867f530a70519e1bcab0c14e84a95aa659f697bc97531be96/lxml-5.2.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1ae67b4e737cddc96c99461d2f75d218bdf7a0c3d3ad5604d1f5e7464a2f9ffe requires_dist: - - cssselect >=0.7 ; extra == 'cssselect' + - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython >=3.0.10 ; extra == 'source' + - cython>=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/be/c3/1765e019344d3f042dfe750eb9a424c0ea2fd43deb6b2ac176b5603a436e/lxml-5.2.1-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: 200e63525948e325d6a13a76ba2911f927ad399ef64f57898cf7c74e69b71095 + url: https://files.pythonhosted.org/packages/df/c5/8b05e69685b48cf11b596fbdd466f76cb3c1e3efe0361d8be0edb9df0325/lxml-5.2.1-cp311-cp311-win_amd64.whl + sha256: 5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102 requires_dist: - - cssselect >=0.7 ; extra == 'cssselect' + - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython >=3.0.10 ; extra == 'source' + - cython>=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: pypi name: lxml version: 5.2.1 - url: https://files.pythonhosted.org/packages/df/c5/8b05e69685b48cf11b596fbdd466f76cb3c1e3efe0361d8be0edb9df0325/lxml-5.2.1-cp311-cp311-win_amd64.whl - sha256: 5c670c0406bdc845b474b680b9a5456c561c65cf366f8db5a60154088c92d102 + url: https://files.pythonhosted.org/packages/43/43/66a84c2a034f5df2782240cb2f68696a72ad6734d7a91f824e0360cde08b/lxml-5.2.1-cp311-cp311-macosx_10_9_universal2.whl + sha256: 70ac664a48aa64e5e635ae5566f5227f2ab7f66a3990d67566d9907edcbbf867 requires_dist: - - cssselect >=0.7 ; extra == 'cssselect' + - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' - lxml-html-clean ; extra == 'html_clean' - beautifulsoup4 ; extra == 'htmlsoup' - - cython >=3.0.10 ; extra == 'source' + - cython>=3.0.10 ; extra == 'source' requires_python: '>=3.6' - kind: conda name: lz4-c @@ -20320,26 +20109,26 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 + url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f + url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 + url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl + sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl - sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 + url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f requires_python: '>=3.7' - kind: conda name: markupsafe @@ -20448,15 +20237,15 @@ packages: url: https://files.pythonhosted.org/packages/38/04/37055b7013dfaaf66e3a9a51e46857cc9be151476a891b995fa70da7e139/marshmallow-3.21.1-py3-none-any.whl sha256: f085493f79efb0644f270a9bf2892843142d80d7174bbbd2f3713f2a589dc633 requires_dist: - - packaging >=17.0 + - packaging>=17.0 - marshmallow[tests] ; extra == 'dev' - tox ; extra == 'dev' - - pre-commit ~=3.5 ; extra == 'dev' - - sphinx ==7.2.6 ; extra == 'docs' - - sphinx-issues ==4.0.0 ; extra == 'docs' - - alabaster ==0.7.16 ; extra == 'docs' - - sphinx-version-warning ==1.1.2 ; extra == 'docs' - - autodocsumm ==0.2.12 ; extra == 'docs' + - pre-commit~=3.5 ; extra == 'dev' + - sphinx==7.2.6 ; extra == 'docs' + - sphinx-issues==4.0.0 ; extra == 'docs' + - alabaster==0.7.16 ; extra == 'docs' + - sphinx-version-warning==1.1.2 ; extra == 'docs' + - autodocsumm==0.2.12 ; extra == 'docs' - pytest ; extra == 'tests' - pytz ; extra == 'tests' - simplejson ; extra == 'tests' @@ -20464,70 +20253,70 @@ packages: - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/36/11/62250ea25780d4b59c2c6044ec161235c47cc05a18d0ec0a05657de75b7d/matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661 + url: https://files.pythonhosted.org/packages/80/3b/e363612ac1a514abfb5505aa209dd5b724b3232a6de98710d7759559706a/matplotlib-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: cc4ccdc64e3039fc303defd119658148f2349239871db72cd74e2eeaa9b80b71 requires_dist: - - contourpy >=1.0.1 - - cycler >=0.10 - - fonttools >=4.22.0 - - kiwisolver >=1.3.1 - - numpy >=1.21 - - packaging >=20.0 - - pillow >=8 - - pyparsing >=2.3.1 - - python-dateutil >=2.7 - - importlib-resources >=3.2.0 ; python_version < '3.10' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.21 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/14/60/12d4f27b859a74359306662da69c2d08826a2b05cfe7f96e66b490f41573/matplotlib-3.8.4-cp311-cp311-macosx_11_0_arm64.whl - sha256: 232ce322bfd020a434caaffbd9a95333f7c2491e59cfc014041d95e38ab90d1c + url: https://files.pythonhosted.org/packages/36/11/62250ea25780d4b59c2c6044ec161235c47cc05a18d0ec0a05657de75b7d/matplotlib-3.8.4-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 72f9322712e4562e792b2961971891b9fbbb0e525011e09ea0d1f416c4645661 requires_dist: - - contourpy >=1.0.1 - - cycler >=0.10 - - fonttools >=4.22.0 - - kiwisolver >=1.3.1 - - numpy >=1.21 - - packaging >=20.0 - - pillow >=8 - - pyparsing >=2.3.1 - - python-dateutil >=2.7 - - importlib-resources >=3.2.0 ; python_version < '3.10' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.21 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/80/3b/e363612ac1a514abfb5505aa209dd5b724b3232a6de98710d7759559706a/matplotlib-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: cc4ccdc64e3039fc303defd119658148f2349239871db72cd74e2eeaa9b80b71 + url: https://files.pythonhosted.org/packages/2d/d5/6227732ecab9165586966ccb54301e3164f61b470c954c4cf6940654fbe1/matplotlib-3.8.4-cp311-cp311-win_amd64.whl + sha256: 8080d5081a86e690d7688ffa542532e87f224c38a6ed71f8fbed34dd1d9fedae requires_dist: - - contourpy >=1.0.1 - - cycler >=0.10 - - fonttools >=4.22.0 - - kiwisolver >=1.3.1 - - numpy >=1.21 - - packaging >=20.0 - - pillow >=8 - - pyparsing >=2.3.1 - - python-dateutil >=2.7 - - importlib-resources >=3.2.0 ; python_version < '3.10' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.21 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: pypi name: matplotlib version: 3.8.4 - url: https://files.pythonhosted.org/packages/2d/d5/6227732ecab9165586966ccb54301e3164f61b470c954c4cf6940654fbe1/matplotlib-3.8.4-cp311-cp311-win_amd64.whl - sha256: 8080d5081a86e690d7688ffa542532e87f224c38a6ed71f8fbed34dd1d9fedae + url: https://files.pythonhosted.org/packages/14/60/12d4f27b859a74359306662da69c2d08826a2b05cfe7f96e66b490f41573/matplotlib-3.8.4-cp311-cp311-macosx_11_0_arm64.whl + sha256: 232ce322bfd020a434caaffbd9a95333f7c2491e59cfc014041d95e38ab90d1c requires_dist: - - contourpy >=1.0.1 - - cycler >=0.10 - - fonttools >=4.22.0 - - kiwisolver >=1.3.1 - - numpy >=1.21 - - packaging >=20.0 - - pillow >=8 - - pyparsing >=2.3.1 - - python-dateutil >=2.7 - - importlib-resources >=3.2.0 ; python_version < '3.10' + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.21 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' requires_python: '>=3.9' - kind: conda name: maturin @@ -20639,13 +20428,13 @@ packages: sha256: b7dde54b82732479b9b856c9230b9f7b3da55b0913dde5254a7489e20c2e3c6e requires_dist: - absl-py - - attrs >=19.1.0 - - flatbuffers >=2.0 + - attrs>=19.1.0 + - flatbuffers>=2.0 - matplotlib - numpy - opencv-contrib-python - - protobuf <4, >=3.11 - - sounddevice >=0.4.4 + - protobuf<4,>=3.11 + - sounddevice>=0.4.4 - kind: pypi name: mediapipe version: 0.10.9 @@ -20653,13 +20442,13 @@ packages: sha256: 8733735f582e6e6a05bf9b15c48b03a6387a0795793a2530aa1189eecfd33780 requires_dist: - absl-py - - attrs >=19.1.0 - - flatbuffers >=2.0 + - attrs>=19.1.0 + - flatbuffers>=2.0 - matplotlib - numpy - opencv-contrib-python - - protobuf <4, >=3.11 - - sounddevice >=0.4.4 + - protobuf<4,>=3.11 + - sounddevice>=0.4.4 - kind: pypi name: mediapipe version: 0.10.11 @@ -20667,16 +20456,16 @@ packages: sha256: ea751e043909ba7bbe27e7afdbcdafd79723d50ef4165afcaae431ab428eea13 requires_dist: - absl-py - - attrs >=19.1.0 - - flatbuffers >=2.0 + - attrs>=19.1.0 + - flatbuffers>=2.0 - jax - jaxlib - matplotlib - numpy - torch - opencv-contrib-python - - protobuf <4, >=3.11 - - sounddevice >=0.4.4 + - protobuf<4,>=3.11 + - sounddevice>=0.4.4 - kind: pypi name: mediapipe version: 0.10.11 @@ -20684,14 +20473,14 @@ packages: sha256: 36231eaf23cd795a923a8b015d36bd6e410a8e997c36dd9432db0157b822b181 requires_dist: - absl-py - - attrs >=19.1.0 - - flatbuffers >=2.0 + - attrs>=19.1.0 + - flatbuffers>=2.0 - jax - matplotlib - numpy - opencv-contrib-python - - protobuf <4, >=3.11 - - sounddevice >=0.4.4 + - protobuf<4,>=3.11 + - sounddevice>=0.4.4 - kind: conda name: meilisearch version: 1.5.1 @@ -20790,14 +20579,14 @@ packages: url: https://files.pythonhosted.org/packages/84/17/a936d3dfad84d028ba8539a93167274b7dcd7985e0d9df487e94a62f9428/ml_dtypes-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: e1e2f4237b459a63c97c2c9f449baa637d7e4c20addff6a9bac486f22432f3b6 requires_dist: - - numpy >1.20 - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.23.3 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' + - numpy>1.20 + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.23.3 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' - absl-py ; extra == 'dev' - pytest ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - pylint >=2.6.0 ; extra == 'dev' + - pylint>=2.6.0 ; extra == 'dev' - pyink ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -20806,14 +20595,14 @@ packages: url: https://files.pythonhosted.org/packages/f0/36/290745178e5776f7416818abc1334c1b19afb93c7c87fd1bef3cc99f84ca/ml_dtypes-0.4.0-cp311-cp311-win_amd64.whl sha256: 75b4faf99d0711b81f393db36d210b4255fd419f6f790bc6c1b461f95ffb7a9e requires_dist: - - numpy >1.20 - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.23.3 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' + - numpy>1.20 + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.23.3 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' - absl-py ; extra == 'dev' - pytest ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - pylint >=2.6.0 ; extra == 'dev' + - pylint>=2.6.0 ; extra == 'dev' - pyink ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -20822,14 +20611,14 @@ packages: url: https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl sha256: a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c requires_dist: - - pytest >=4.6 ; extra == 'develop' + - pytest>=4.6 ; extra == 'develop' - pycodestyle ; extra == 'develop' - pytest-cov ; extra == 'develop' - codecov ; extra == 'develop' - wheel ; extra == 'develop' - sphinx ; extra == 'docs' - - gmpy2 >=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' - - pytest >=4.6 ; extra == 'tests' + - gmpy2>=2.1.0a4 ; platform_python_implementation != 'PyPy' and extra == 'gmpy' + - pytest>=4.6 ; extra == 'tests' - kind: conda name: msys2-conda-epoch version: '20160418' @@ -20844,26 +20633,26 @@ packages: - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e + url: https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: 612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd + url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed + url: https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl + sha256: 2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl - sha256: 2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea + url: https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: 612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd requires_python: '>=3.7' - kind: conda name: multidict @@ -21262,27 +21051,27 @@ packages: url: https://files.pythonhosted.org/packages/38/e9/5f72929373e1a0e8d142a130f3f97e6ff920070f87f91c4e13e40e0fba5a/networkx-3.3-py3-none-any.whl sha256: 28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2 requires_dist: - - numpy >=1.23 ; extra == 'default' - - scipy !=1.11.0, !=1.11.1, >=1.9 ; extra == 'default' - - matplotlib >=3.6 ; extra == 'default' - - pandas >=1.4 ; extra == 'default' - - changelist ==0.5 ; extra == 'developer' - - pre-commit >=3.2 ; extra == 'developer' - - mypy >=1.1 ; extra == 'developer' + - numpy>=1.23 ; extra == 'default' + - scipy!=1.11.0,!=1.11.1,>=1.9 ; extra == 'default' + - matplotlib>=3.6 ; extra == 'default' + - pandas>=1.4 ; extra == 'default' + - changelist==0.5 ; extra == 'developer' + - pre-commit>=3.2 ; extra == 'developer' + - mypy>=1.1 ; extra == 'developer' - rtoml ; extra == 'developer' - - sphinx >=7 ; extra == 'doc' - - pydata-sphinx-theme >=0.14 ; extra == 'doc' - - sphinx-gallery >=0.14 ; extra == 'doc' - - numpydoc >=1.7 ; extra == 'doc' - - pillow >=9.4 ; extra == 'doc' - - texext >=0.6.7 ; extra == 'doc' - - myst-nb >=1.0 ; extra == 'doc' - - lxml >=4.6 ; extra == 'extra' - - pygraphviz >=1.12 ; extra == 'extra' - - pydot >=2.0 ; extra == 'extra' - - sympy >=1.10 ; extra == 'extra' - - pytest >=7.2 ; extra == 'test' - - pytest-cov >=4.0 ; extra == 'test' + - sphinx>=7 ; extra == 'doc' + - pydata-sphinx-theme>=0.14 ; extra == 'doc' + - sphinx-gallery>=0.14 ; extra == 'doc' + - numpydoc>=1.7 ; extra == 'doc' + - pillow>=9.4 ; extra == 'doc' + - texext>=0.6.7 ; extra == 'doc' + - myst-nb>=1.0 ; extra == 'doc' + - lxml>=4.6 ; extra == 'extra' + - pygraphviz>=1.12 ; extra == 'extra' + - pydot>=2.0 ; extra == 'extra' + - sympy>=1.10 ; extra == 'extra' + - pytest>=7.2 ; extra == 'test' + - pytest-cov>=4.0 ; extra == 'test' requires_python: '>=3.10' - kind: conda name: ninja @@ -21536,76 +21325,76 @@ packages: url: https://files.pythonhosted.org/packages/a4/28/2897c06b54cd99f41ca9e5cc7433211a085903a71aaed1cb1a1dc138d53c/nox-2024.4.15-py3-none-any.whl sha256: 6492236efa15a460ecb98e7b67562a28b70da006ab0be164e8821177577c0565 requires_dist: - - argcomplete <4.0, >=1.9.4 - - colorlog <7.0.0, >=2.6.1 + - argcomplete<4.0,>=1.9.4 + - colorlog<7.0.0,>=2.6.1 - importlib-metadata ; python_version < '3.8' - - packaging >=20.9 - - tomli >=1 ; python_version < '3.11' - - typing-extensions >=3.7.4 ; python_version < '3.8' - - virtualenv >=20.14.1 + - packaging>=20.9 + - tomli>=1 ; python_version < '3.11' + - typing-extensions>=3.7.4 ; python_version < '3.8' + - virtualenv>=20.14.1 - jinja2 ; extra == 'tox_to_nox' - tox ; extra == 'tox_to_nox' - - uv >=0.1.6 ; extra == 'uv' + - uv>=0.1.6 ; extra == 'uv' requires_python: '>=3.7' - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/5f/2d/085c21f3086eff0b830e5d03d084a1b4b10dfde0c65feeac6be8c361265c/numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051 + url: https://files.pythonhosted.org/packages/54/f2/7d1579037643c874fa73516ea84c07e8d30ea347fb1a88c03b198447655d/numba-0.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + sha256: dd2842fac03be4e5324ebbbd4d2d0c8c0fc6e0df75c09477dd45b288a0777389 requires_dist: - - llvmlite <0.43, >=0.42.0.dev0 - - numpy <1.27, >=1.22 + - llvmlite<0.43,>=0.42.0.dev0 + - numpy<1.27,>=1.22 requires_python: '>=3.9' - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/70/7d/0d1419479997319ca72ef735791c2ee50819f9c200adea96142ee7499fae/numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: 411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966 + url: https://files.pythonhosted.org/packages/5f/2d/085c21f3086eff0b830e5d03d084a1b4b10dfde0c65feeac6be8c361265c/numba-0.59.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 43727e7ad20b3ec23ee4fc642f5b61845c71f75dd2825b3c234390c6d8d64051 requires_dist: - - llvmlite <0.43, >=0.42.0.dev0 - - numpy <1.27, >=1.22 + - llvmlite<0.43,>=0.42.0.dev0 + - numpy<1.27,>=1.22 requires_python: '>=3.9' - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/54/f2/7d1579037643c874fa73516ea84c07e8d30ea347fb1a88c03b198447655d/numba-0.59.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - sha256: dd2842fac03be4e5324ebbbd4d2d0c8c0fc6e0df75c09477dd45b288a0777389 + url: https://files.pythonhosted.org/packages/38/f0/ad848815b0adafcf5f238e728933950034355a8d59969772be1cd57606d8/numba-0.59.1-cp311-cp311-win_amd64.whl + sha256: 0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450 requires_dist: - - llvmlite <0.43, >=0.42.0.dev0 - - numpy <1.27, >=1.22 + - llvmlite<0.43,>=0.42.0.dev0 + - numpy<1.27,>=1.22 requires_python: '>=3.9' - kind: pypi name: numba version: 0.59.1 - url: https://files.pythonhosted.org/packages/38/f0/ad848815b0adafcf5f238e728933950034355a8d59969772be1cd57606d8/numba-0.59.1-cp311-cp311-win_amd64.whl - sha256: 0594b3dfb369fada1f8bb2e3045cd6c61a564c62e50cf1f86b4666bc721b3450 + url: https://files.pythonhosted.org/packages/70/7d/0d1419479997319ca72ef735791c2ee50819f9c200adea96142ee7499fae/numba-0.59.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: 411df625372c77959570050e861981e9d196cc1da9aa62c3d6a836b5cc338966 requires_dist: - - llvmlite <0.43, >=0.42.0.dev0 - - numpy <1.27, >=1.22 + - llvmlite<0.43,>=0.42.0.dev0 + - numpy<1.27,>=1.22 requires_python: '>=3.9' - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71 + url: https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5 requires_python: '>=3.9' - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl - sha256: edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef + url: https://files.pythonhosted.org/packages/11/57/baae43d14fe163fa0e4c47f307b6b2511ab8d7d30177c491960504252053/numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71 requires_python: '>=3.9' - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/3a/d0/edc009c27b406c4f9cbc79274d6e46d634d139075492ad055e3d68445925/numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5 + url: https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl + sha256: cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2 requires_python: '>=3.9' - kind: pypi name: numpy version: 1.26.4 - url: https://files.pythonhosted.org/packages/3f/6b/5610004206cf7f8e7ad91c5a85a8c71b2f2f8051a0c0c4d5916b76d6cbb2/numpy-1.26.4-cp311-cp311-win_amd64.whl - sha256: cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2 + url: https://files.pythonhosted.org/packages/1a/2e/151484f49fd03944c4a3ad9c418ed193cfd02724e138ac8a9505d056c582/numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl + sha256: edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef requires_python: '>=3.9' - kind: conda name: numpy @@ -21734,9 +21523,9 @@ packages: path: examples/python/nv12 sha256: c8ca97c5d8c04037cd5eb9a65be7b1e7d667c11d4dba3ee9aad5956ccf926dc4 requires_dist: - - numpy + - rerun-sdk>=0.10 - opencv-python - - rerun-sdk >=0.10 + - numpy editable: true - kind: pypi name: nvidia-cublas-cu12 @@ -21826,8 +21615,8 @@ packages: requires_dist: - betterproto[compiler] - numpy - - opencv-python >4.6 - - requests <3, >=2.31 + - opencv-python>4.6 + - requests>=2.31,<3 - rerun-sdk - scipy editable: true @@ -21848,53 +21637,36 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/16/07/bf25df600eeaedddf8fece3f1ff837bf72865b93a03651cf7375ce8172be/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl - sha256: 86078d3653ec3107877536c9178622b1f98b51acf59e554ddbc552785cba55fa - requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' - requires_python: '>=3.6' -- kind: pypi - name: opencv-contrib-python - version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/4c/c3/ccff2e1bfe2bb47a7eaebc4280e93bd2f97ebbe5b3573d48bcfcc0c32387/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - sha256: b52e381144f774b486729ccee69911bdc7d16b5ced4830502e906ad803373ab0 + url: https://files.pythonhosted.org/packages/8a/ea/aea6289058480b93157ad698ecd7f13cae4892ae0a4750abf33b3ac12f91/opencv_contrib_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 89ca1508dd895ae42176640bdd503cac82772f6efa25120738a469a6a69de321 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-contrib-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/8a/ea/aea6289058480b93157ad698ecd7f13cae4892ae0a4750abf33b3ac12f91/opencv_contrib_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 89ca1508dd895ae42176640bdd503cac82772f6efa25120738a469a6a69de321 + url: https://files.pythonhosted.org/packages/16/07/bf25df600eeaedddf8fece3f1ff837bf72865b93a03651cf7375ce8172be/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl + sha256: 86078d3653ec3107877536c9178622b1f98b51acf59e554ddbc552785cba55fa requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-contrib-python @@ -21902,67 +21674,67 @@ packages: url: https://files.pythonhosted.org/packages/aa/2e/576ac47f21d555b459ca837bb3fb937e50339b8fbfd294945ea2f5290416/opencv_contrib_python-4.9.0.80-cp37-abi3-win_amd64.whl sha256: fdd9b14028f74af8dbb69f90e6e4a956ce2eb5b59947df28ba0b79d337431477 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi - name: opencv-python + name: opencv-contrib-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl - sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3 + url: https://files.pythonhosted.org/packages/4c/c3/ccff2e1bfe2bb47a7eaebc4280e93bd2f97ebbe5b3573d48bcfcc0c32387/opencv_contrib_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl + sha256: b52e381144f774b486729ccee69911bdc7d16b5ced4830502e906ad803373ab0 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a + url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/25/72/da7c69a3542071bf1e8f65336721b8b2659194425438d988f79bc14ed9cc/opencv-python-4.9.0.80.tar.gz - sha256: 1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1 + url: https://files.pythonhosted.org/packages/77/df/b56175c3fb5bc058774bdcf35f5a71cf9c3c5b909f98a1c688eb71cd3b1f/opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl + sha256: 71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python @@ -21970,33 +21742,33 @@ packages: url: https://files.pythonhosted.org/packages/c7/ec/9dabb6a9abfdebb3c45b0cc52dec901caafef2b2c7e7d6a839ed86d81e91/opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl sha256: 3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0 requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python version: 4.9.0.80 - url: https://files.pythonhosted.org/packages/d9/64/7fdfb9386511cd6805451e012c537073a79a958a58795c4e602e538c388c/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57 + url: https://files.pythonhosted.org/packages/52/00/2adf376707c7965bb4569f28f73fafe303c404d01047b10e3b52761be086/opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: pypi name: opencv-python @@ -22004,16 +21776,16 @@ packages: url: https://files.pythonhosted.org/packages/35/69/b657974ddcbba54d59d7d62b01e60a8b815e35f415b996e4d355be0ac7b4/opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl sha256: 7e5f7aa4486651a6ebfa8ed4b594b65bd2d2f41beeb4241a3e4b1b85acbbbadb requires_dist: - - numpy >=1.13.3 ; python_version < '3.7' - - numpy >=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' - - numpy >=1.21.2 ; python_version >= '3.10' - - numpy >=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' - - numpy >=1.23.5 ; python_version >= '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - numpy >=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' - - numpy >=1.17.0 ; python_version >= '3.7' - - numpy >=1.17.3 ; python_version >= '3.8' - - numpy >=1.19.3 ; python_version >= '3.9' + - numpy>=1.13.3 ; python_version < '3.7' + - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' + - numpy>=1.21.2 ; python_version >= '3.10' + - numpy>=1.21.4 ; python_version >= '3.10' and platform_system == 'Darwin' + - numpy>=1.23.5 ; python_version >= '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - numpy>=1.19.3 ; python_version >= '3.6' and platform_system == 'Linux' and platform_machine == 'aarch64' + - numpy>=1.17.0 ; python_version >= '3.7' + - numpy>=1.17.3 ; python_version >= '3.8' + - numpy>=1.19.3 ; python_version >= '3.9' requires_python: '>=3.6' - kind: conda name: openssl @@ -22196,8 +21968,8 @@ packages: url: https://files.pythonhosted.org/packages/bc/19/404708a7e54ad2798907210462fd950c3442ea51acc8790f3da48d2bee8b/opt_einsum-3.3.0-py3-none-any.whl sha256: 2455e59e3947d3c275477df7f5205b30635e266fe6dc300e3d9f9646bfcea147 requires_dist: - - numpy >=1.7 - - sphinx ==1.2.3 ; extra == 'docs' + - numpy>=1.7 + - sphinx==1.2.3 ; extra == 'docs' - sphinxcontrib-napoleon ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - numpydoc ; extra == 'docs' @@ -22504,376 +22276,376 @@ packages: license: Apache-2.0 license_family: APACHE purls: - - pkg:pypi/packaging@24.0 + - pkg:pypi/packaging size: 49832 timestamp: 1710076089469 - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 + url: https://files.pythonhosted.org/packages/fc/a5/4d82be566f069d7a9a702dcdf6f9106df0e0b042e738043c0cc7ddd7e3f6/pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee requires_dist: - - numpy >=1.22.4 ; python_version < '3.11' - - numpy >=1.23.2 ; python_version == '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - python-dateutil >=2.8.2 - - pytz >=2020.1 - - tzdata >=2022.7 - - hypothesis >=6.46.1 ; extra == 'test' - - pytest >=7.3.2 ; extra == 'test' - - pytest-xdist >=2.2.0 ; extra == 'test' - - pyarrow >=10.0.1 ; extra == 'pyarrow' - - bottleneck >=1.3.6 ; extra == 'performance' - - numba >=0.56.4 ; extra == 'performance' - - numexpr >=2.8.4 ; extra == 'performance' - - scipy >=1.10.0 ; extra == 'computation' - - xarray >=2022.12.0 ; extra == 'computation' - - fsspec >=2022.11.0 ; extra == 'fss' - - s3fs >=2022.11.0 ; extra == 'aws' - - gcsfs >=2022.11.0 ; extra == 'gcp' - - pandas-gbq >=0.19.0 ; extra == 'gcp' - - odfpy >=1.4.1 ; extra == 'excel' - - openpyxl >=3.1.0 ; extra == 'excel' - - python-calamine >=0.1.7 ; extra == 'excel' - - pyxlsb >=1.0.10 ; extra == 'excel' - - xlrd >=2.0.1 ; extra == 'excel' - - xlsxwriter >=3.0.5 ; extra == 'excel' - - pyarrow >=10.0.1 ; extra == 'parquet' - - pyarrow >=10.0.1 ; extra == 'feather' - - tables >=3.8.0 ; extra == 'hdf5' - - pyreadstat >=1.2.0 ; extra == 'spss' - - sqlalchemy >=2.0.0 ; extra == 'postgresql' - - psycopg2 >=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' - - sqlalchemy >=2.0.0 ; extra == 'mysql' - - pymysql >=1.0.2 ; extra == 'mysql' - - sqlalchemy >=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' - - beautifulsoup4 >=4.11.2 ; extra == 'html' - - html5lib >=1.1 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'xml' - - matplotlib >=3.6.3 ; extra == 'plot' - - jinja2 >=3.1.2 ; extra == 'output-formatting' - - tabulate >=0.9.0 ; extra == 'output-formatting' - - pyqt5 >=5.15.9 ; extra == 'clipboard' - - qtpy >=2.3.0 ; extra == 'clipboard' - - zstandard >=0.19.0 ; extra == 'compression' - - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql >=0.8.0 ; extra == 'all' - - adbc-driver-sqlite >=0.8.0 ; extra == 'all' - - beautifulsoup4 >=4.11.2 ; extra == 'all' - - bottleneck >=1.3.6 ; extra == 'all' - - dataframe-api-compat >=0.1.7 ; extra == 'all' - - fastparquet >=2022.12.0 ; extra == 'all' - - fsspec >=2022.11.0 ; extra == 'all' - - gcsfs >=2022.11.0 ; extra == 'all' - - html5lib >=1.1 ; extra == 'all' - - hypothesis >=6.46.1 ; extra == 'all' - - jinja2 >=3.1.2 ; extra == 'all' - - lxml >=4.9.2 ; extra == 'all' - - matplotlib >=3.6.3 ; extra == 'all' - - numba >=0.56.4 ; extra == 'all' - - numexpr >=2.8.4 ; extra == 'all' - - odfpy >=1.4.1 ; extra == 'all' - - openpyxl >=3.1.0 ; extra == 'all' - - pandas-gbq >=0.19.0 ; extra == 'all' - - psycopg2 >=2.9.6 ; extra == 'all' - - pyarrow >=10.0.1 ; extra == 'all' - - pymysql >=1.0.2 ; extra == 'all' - - pyqt5 >=5.15.9 ; extra == 'all' - - pyreadstat >=1.2.0 ; extra == 'all' - - pytest >=7.3.2 ; extra == 'all' - - pytest-xdist >=2.2.0 ; extra == 'all' - - python-calamine >=0.1.7 ; extra == 'all' - - pyxlsb >=1.0.10 ; extra == 'all' - - qtpy >=2.3.0 ; extra == 'all' - - scipy >=1.10.0 ; extra == 'all' - - s3fs >=2022.11.0 ; extra == 'all' - - sqlalchemy >=2.0.0 ; extra == 'all' - - tables >=3.8.0 ; extra == 'all' - - tabulate >=0.9.0 ; extra == 'all' - - xarray >=2022.12.0 ; extra == 'all' - - xlrd >=2.0.1 ; extra == 'all' - - xlsxwriter >=3.0.5 ; extra == 'all' - - zstandard >=0.19.0 ; extra == 'all' + - numpy>=1.22.4 ; python_version < '3.11' + - numpy>=1.23.2 ; python_version == '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 + url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 requires_dist: - - numpy >=1.22.4 ; python_version < '3.11' - - numpy >=1.23.2 ; python_version == '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - python-dateutil >=2.8.2 - - pytz >=2020.1 - - tzdata >=2022.7 - - hypothesis >=6.46.1 ; extra == 'test' - - pytest >=7.3.2 ; extra == 'test' - - pytest-xdist >=2.2.0 ; extra == 'test' - - pyarrow >=10.0.1 ; extra == 'pyarrow' - - bottleneck >=1.3.6 ; extra == 'performance' - - numba >=0.56.4 ; extra == 'performance' - - numexpr >=2.8.4 ; extra == 'performance' - - scipy >=1.10.0 ; extra == 'computation' - - xarray >=2022.12.0 ; extra == 'computation' - - fsspec >=2022.11.0 ; extra == 'fss' - - s3fs >=2022.11.0 ; extra == 'aws' - - gcsfs >=2022.11.0 ; extra == 'gcp' - - pandas-gbq >=0.19.0 ; extra == 'gcp' - - odfpy >=1.4.1 ; extra == 'excel' - - openpyxl >=3.1.0 ; extra == 'excel' - - python-calamine >=0.1.7 ; extra == 'excel' - - pyxlsb >=1.0.10 ; extra == 'excel' - - xlrd >=2.0.1 ; extra == 'excel' - - xlsxwriter >=3.0.5 ; extra == 'excel' - - pyarrow >=10.0.1 ; extra == 'parquet' - - pyarrow >=10.0.1 ; extra == 'feather' - - tables >=3.8.0 ; extra == 'hdf5' - - pyreadstat >=1.2.0 ; extra == 'spss' - - sqlalchemy >=2.0.0 ; extra == 'postgresql' - - psycopg2 >=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' - - sqlalchemy >=2.0.0 ; extra == 'mysql' - - pymysql >=1.0.2 ; extra == 'mysql' - - sqlalchemy >=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' - - beautifulsoup4 >=4.11.2 ; extra == 'html' - - html5lib >=1.1 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'xml' - - matplotlib >=3.6.3 ; extra == 'plot' - - jinja2 >=3.1.2 ; extra == 'output-formatting' - - tabulate >=0.9.0 ; extra == 'output-formatting' - - pyqt5 >=5.15.9 ; extra == 'clipboard' - - qtpy >=2.3.0 ; extra == 'clipboard' - - zstandard >=0.19.0 ; extra == 'compression' - - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql >=0.8.0 ; extra == 'all' - - adbc-driver-sqlite >=0.8.0 ; extra == 'all' - - beautifulsoup4 >=4.11.2 ; extra == 'all' - - bottleneck >=1.3.6 ; extra == 'all' - - dataframe-api-compat >=0.1.7 ; extra == 'all' - - fastparquet >=2022.12.0 ; extra == 'all' - - fsspec >=2022.11.0 ; extra == 'all' - - gcsfs >=2022.11.0 ; extra == 'all' - - html5lib >=1.1 ; extra == 'all' - - hypothesis >=6.46.1 ; extra == 'all' - - jinja2 >=3.1.2 ; extra == 'all' - - lxml >=4.9.2 ; extra == 'all' - - matplotlib >=3.6.3 ; extra == 'all' - - numba >=0.56.4 ; extra == 'all' - - numexpr >=2.8.4 ; extra == 'all' - - odfpy >=1.4.1 ; extra == 'all' - - openpyxl >=3.1.0 ; extra == 'all' - - pandas-gbq >=0.19.0 ; extra == 'all' - - psycopg2 >=2.9.6 ; extra == 'all' - - pyarrow >=10.0.1 ; extra == 'all' - - pymysql >=1.0.2 ; extra == 'all' - - pyqt5 >=5.15.9 ; extra == 'all' - - pyreadstat >=1.2.0 ; extra == 'all' - - pytest >=7.3.2 ; extra == 'all' - - pytest-xdist >=2.2.0 ; extra == 'all' - - python-calamine >=0.1.7 ; extra == 'all' - - pyxlsb >=1.0.10 ; extra == 'all' - - qtpy >=2.3.0 ; extra == 'all' - - scipy >=1.10.0 ; extra == 'all' - - s3fs >=2022.11.0 ; extra == 'all' - - sqlalchemy >=2.0.0 ; extra == 'all' - - tables >=3.8.0 ; extra == 'all' - - tabulate >=0.9.0 ; extra == 'all' - - xarray >=2022.12.0 ; extra == 'all' - - xlrd >=2.0.1 ; extra == 'all' - - xlsxwriter >=3.0.5 ; extra == 'all' - - zstandard >=0.19.0 ; extra == 'all' + - numpy>=1.22.4 ; python_version < '3.11' + - numpy>=1.23.2 ; python_version == '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/fc/a5/4d82be566f069d7a9a702dcdf6f9106df0e0b042e738043c0cc7ddd7e3f6/pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee + url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl + sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 requires_dist: - - numpy >=1.22.4 ; python_version < '3.11' - - numpy >=1.23.2 ; python_version == '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - python-dateutil >=2.8.2 - - pytz >=2020.1 - - tzdata >=2022.7 - - hypothesis >=6.46.1 ; extra == 'test' - - pytest >=7.3.2 ; extra == 'test' - - pytest-xdist >=2.2.0 ; extra == 'test' - - pyarrow >=10.0.1 ; extra == 'pyarrow' - - bottleneck >=1.3.6 ; extra == 'performance' - - numba >=0.56.4 ; extra == 'performance' - - numexpr >=2.8.4 ; extra == 'performance' - - scipy >=1.10.0 ; extra == 'computation' - - xarray >=2022.12.0 ; extra == 'computation' - - fsspec >=2022.11.0 ; extra == 'fss' - - s3fs >=2022.11.0 ; extra == 'aws' - - gcsfs >=2022.11.0 ; extra == 'gcp' - - pandas-gbq >=0.19.0 ; extra == 'gcp' - - odfpy >=1.4.1 ; extra == 'excel' - - openpyxl >=3.1.0 ; extra == 'excel' - - python-calamine >=0.1.7 ; extra == 'excel' - - pyxlsb >=1.0.10 ; extra == 'excel' - - xlrd >=2.0.1 ; extra == 'excel' - - xlsxwriter >=3.0.5 ; extra == 'excel' - - pyarrow >=10.0.1 ; extra == 'parquet' - - pyarrow >=10.0.1 ; extra == 'feather' - - tables >=3.8.0 ; extra == 'hdf5' - - pyreadstat >=1.2.0 ; extra == 'spss' - - sqlalchemy >=2.0.0 ; extra == 'postgresql' - - psycopg2 >=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' - - sqlalchemy >=2.0.0 ; extra == 'mysql' - - pymysql >=1.0.2 ; extra == 'mysql' - - sqlalchemy >=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' - - beautifulsoup4 >=4.11.2 ; extra == 'html' - - html5lib >=1.1 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'xml' - - matplotlib >=3.6.3 ; extra == 'plot' - - jinja2 >=3.1.2 ; extra == 'output-formatting' - - tabulate >=0.9.0 ; extra == 'output-formatting' - - pyqt5 >=5.15.9 ; extra == 'clipboard' - - qtpy >=2.3.0 ; extra == 'clipboard' - - zstandard >=0.19.0 ; extra == 'compression' - - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql >=0.8.0 ; extra == 'all' - - adbc-driver-sqlite >=0.8.0 ; extra == 'all' - - beautifulsoup4 >=4.11.2 ; extra == 'all' - - bottleneck >=1.3.6 ; extra == 'all' - - dataframe-api-compat >=0.1.7 ; extra == 'all' - - fastparquet >=2022.12.0 ; extra == 'all' - - fsspec >=2022.11.0 ; extra == 'all' - - gcsfs >=2022.11.0 ; extra == 'all' - - html5lib >=1.1 ; extra == 'all' - - hypothesis >=6.46.1 ; extra == 'all' - - jinja2 >=3.1.2 ; extra == 'all' - - lxml >=4.9.2 ; extra == 'all' - - matplotlib >=3.6.3 ; extra == 'all' - - numba >=0.56.4 ; extra == 'all' - - numexpr >=2.8.4 ; extra == 'all' - - odfpy >=1.4.1 ; extra == 'all' - - openpyxl >=3.1.0 ; extra == 'all' - - pandas-gbq >=0.19.0 ; extra == 'all' - - psycopg2 >=2.9.6 ; extra == 'all' - - pyarrow >=10.0.1 ; extra == 'all' - - pymysql >=1.0.2 ; extra == 'all' - - pyqt5 >=5.15.9 ; extra == 'all' - - pyreadstat >=1.2.0 ; extra == 'all' - - pytest >=7.3.2 ; extra == 'all' - - pytest-xdist >=2.2.0 ; extra == 'all' - - python-calamine >=0.1.7 ; extra == 'all' - - pyxlsb >=1.0.10 ; extra == 'all' - - qtpy >=2.3.0 ; extra == 'all' - - scipy >=1.10.0 ; extra == 'all' - - s3fs >=2022.11.0 ; extra == 'all' - - sqlalchemy >=2.0.0 ; extra == 'all' - - tables >=3.8.0 ; extra == 'all' - - tabulate >=0.9.0 ; extra == 'all' - - xarray >=2022.12.0 ; extra == 'all' - - xlrd >=2.0.1 ; extra == 'all' - - xlsxwriter >=3.0.5 ; extra == 'all' - - zstandard >=0.19.0 ; extra == 'all' + - numpy>=1.22.4 ; python_version < '3.11' + - numpy>=1.23.2 ; python_version == '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl - sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 + url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 requires_dist: - - numpy >=1.22.4 ; python_version < '3.11' - - numpy >=1.23.2 ; python_version == '3.11' - - numpy >=1.26.0 ; python_version >= '3.12' - - python-dateutil >=2.8.2 - - pytz >=2020.1 - - tzdata >=2022.7 - - hypothesis >=6.46.1 ; extra == 'test' - - pytest >=7.3.2 ; extra == 'test' - - pytest-xdist >=2.2.0 ; extra == 'test' - - pyarrow >=10.0.1 ; extra == 'pyarrow' - - bottleneck >=1.3.6 ; extra == 'performance' - - numba >=0.56.4 ; extra == 'performance' - - numexpr >=2.8.4 ; extra == 'performance' - - scipy >=1.10.0 ; extra == 'computation' - - xarray >=2022.12.0 ; extra == 'computation' - - fsspec >=2022.11.0 ; extra == 'fss' - - s3fs >=2022.11.0 ; extra == 'aws' - - gcsfs >=2022.11.0 ; extra == 'gcp' - - pandas-gbq >=0.19.0 ; extra == 'gcp' - - odfpy >=1.4.1 ; extra == 'excel' - - openpyxl >=3.1.0 ; extra == 'excel' - - python-calamine >=0.1.7 ; extra == 'excel' - - pyxlsb >=1.0.10 ; extra == 'excel' - - xlrd >=2.0.1 ; extra == 'excel' - - xlsxwriter >=3.0.5 ; extra == 'excel' - - pyarrow >=10.0.1 ; extra == 'parquet' - - pyarrow >=10.0.1 ; extra == 'feather' - - tables >=3.8.0 ; extra == 'hdf5' - - pyreadstat >=1.2.0 ; extra == 'spss' - - sqlalchemy >=2.0.0 ; extra == 'postgresql' - - psycopg2 >=2.9.6 ; extra == 'postgresql' - - adbc-driver-postgresql >=0.8.0 ; extra == 'postgresql' - - sqlalchemy >=2.0.0 ; extra == 'mysql' - - pymysql >=1.0.2 ; extra == 'mysql' - - sqlalchemy >=2.0.0 ; extra == 'sql-other' - - adbc-driver-postgresql >=0.8.0 ; extra == 'sql-other' - - adbc-driver-sqlite >=0.8.0 ; extra == 'sql-other' - - beautifulsoup4 >=4.11.2 ; extra == 'html' - - html5lib >=1.1 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'html' - - lxml >=4.9.2 ; extra == 'xml' - - matplotlib >=3.6.3 ; extra == 'plot' - - jinja2 >=3.1.2 ; extra == 'output-formatting' - - tabulate >=0.9.0 ; extra == 'output-formatting' - - pyqt5 >=5.15.9 ; extra == 'clipboard' - - qtpy >=2.3.0 ; extra == 'clipboard' - - zstandard >=0.19.0 ; extra == 'compression' - - dataframe-api-compat >=0.1.7 ; extra == 'consortium-standard' - - adbc-driver-postgresql >=0.8.0 ; extra == 'all' - - adbc-driver-sqlite >=0.8.0 ; extra == 'all' - - beautifulsoup4 >=4.11.2 ; extra == 'all' - - bottleneck >=1.3.6 ; extra == 'all' - - dataframe-api-compat >=0.1.7 ; extra == 'all' - - fastparquet >=2022.12.0 ; extra == 'all' - - fsspec >=2022.11.0 ; extra == 'all' - - gcsfs >=2022.11.0 ; extra == 'all' - - html5lib >=1.1 ; extra == 'all' - - hypothesis >=6.46.1 ; extra == 'all' - - jinja2 >=3.1.2 ; extra == 'all' - - lxml >=4.9.2 ; extra == 'all' - - matplotlib >=3.6.3 ; extra == 'all' - - numba >=0.56.4 ; extra == 'all' - - numexpr >=2.8.4 ; extra == 'all' - - odfpy >=1.4.1 ; extra == 'all' - - openpyxl >=3.1.0 ; extra == 'all' - - pandas-gbq >=0.19.0 ; extra == 'all' - - psycopg2 >=2.9.6 ; extra == 'all' - - pyarrow >=10.0.1 ; extra == 'all' - - pymysql >=1.0.2 ; extra == 'all' - - pyqt5 >=5.15.9 ; extra == 'all' - - pyreadstat >=1.2.0 ; extra == 'all' - - pytest >=7.3.2 ; extra == 'all' - - pytest-xdist >=2.2.0 ; extra == 'all' - - python-calamine >=0.1.7 ; extra == 'all' - - pyxlsb >=1.0.10 ; extra == 'all' - - qtpy >=2.3.0 ; extra == 'all' - - scipy >=1.10.0 ; extra == 'all' - - s3fs >=2022.11.0 ; extra == 'all' - - sqlalchemy >=2.0.0 ; extra == 'all' - - tables >=3.8.0 ; extra == 'all' - - tabulate >=0.9.0 ; extra == 'all' - - xarray >=2022.12.0 ; extra == 'all' - - xlrd >=2.0.1 ; extra == 'all' - - xlsxwriter >=3.0.5 ; extra == 'all' - - zstandard >=0.19.0 ; extra == 'all' + - numpy>=1.22.4 ; python_version < '3.11' + - numpy>=1.23.2 ; python_version == '3.11' + - numpy>=1.26.0 ; python_version >= '3.12' + - python-dateutil>=2.8.2 + - pytz>=2020.1 + - tzdata>=2022.7 + - hypothesis>=6.46.1 ; extra == 'test' + - pytest>=7.3.2 ; extra == 'test' + - pytest-xdist>=2.2.0 ; extra == 'test' + - pyarrow>=10.0.1 ; extra == 'pyarrow' + - bottleneck>=1.3.6 ; extra == 'performance' + - numba>=0.56.4 ; extra == 'performance' + - numexpr>=2.8.4 ; extra == 'performance' + - scipy>=1.10.0 ; extra == 'computation' + - xarray>=2022.12.0 ; extra == 'computation' + - fsspec>=2022.11.0 ; extra == 'fss' + - s3fs>=2022.11.0 ; extra == 'aws' + - gcsfs>=2022.11.0 ; extra == 'gcp' + - pandas-gbq>=0.19.0 ; extra == 'gcp' + - odfpy>=1.4.1 ; extra == 'excel' + - openpyxl>=3.1.0 ; extra == 'excel' + - python-calamine>=0.1.7 ; extra == 'excel' + - pyxlsb>=1.0.10 ; extra == 'excel' + - xlrd>=2.0.1 ; extra == 'excel' + - xlsxwriter>=3.0.5 ; extra == 'excel' + - pyarrow>=10.0.1 ; extra == 'parquet' + - pyarrow>=10.0.1 ; extra == 'feather' + - tables>=3.8.0 ; extra == 'hdf5' + - pyreadstat>=1.2.0 ; extra == 'spss' + - sqlalchemy>=2.0.0 ; extra == 'postgresql' + - psycopg2>=2.9.6 ; extra == 'postgresql' + - adbc-driver-postgresql>=0.8.0 ; extra == 'postgresql' + - sqlalchemy>=2.0.0 ; extra == 'mysql' + - pymysql>=1.0.2 ; extra == 'mysql' + - sqlalchemy>=2.0.0 ; extra == 'sql-other' + - adbc-driver-postgresql>=0.8.0 ; extra == 'sql-other' + - adbc-driver-sqlite>=0.8.0 ; extra == 'sql-other' + - beautifulsoup4>=4.11.2 ; extra == 'html' + - html5lib>=1.1 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'html' + - lxml>=4.9.2 ; extra == 'xml' + - matplotlib>=3.6.3 ; extra == 'plot' + - jinja2>=3.1.2 ; extra == 'output-formatting' + - tabulate>=0.9.0 ; extra == 'output-formatting' + - pyqt5>=5.15.9 ; extra == 'clipboard' + - qtpy>=2.3.0 ; extra == 'clipboard' + - zstandard>=0.19.0 ; extra == 'compression' + - dataframe-api-compat>=0.1.7 ; extra == 'consortium-standard' + - adbc-driver-postgresql>=0.8.0 ; extra == 'all' + - adbc-driver-sqlite>=0.8.0 ; extra == 'all' + - beautifulsoup4>=4.11.2 ; extra == 'all' + - bottleneck>=1.3.6 ; extra == 'all' + - dataframe-api-compat>=0.1.7 ; extra == 'all' + - fastparquet>=2022.12.0 ; extra == 'all' + - fsspec>=2022.11.0 ; extra == 'all' + - gcsfs>=2022.11.0 ; extra == 'all' + - html5lib>=1.1 ; extra == 'all' + - hypothesis>=6.46.1 ; extra == 'all' + - jinja2>=3.1.2 ; extra == 'all' + - lxml>=4.9.2 ; extra == 'all' + - matplotlib>=3.6.3 ; extra == 'all' + - numba>=0.56.4 ; extra == 'all' + - numexpr>=2.8.4 ; extra == 'all' + - odfpy>=1.4.1 ; extra == 'all' + - openpyxl>=3.1.0 ; extra == 'all' + - pandas-gbq>=0.19.0 ; extra == 'all' + - psycopg2>=2.9.6 ; extra == 'all' + - pyarrow>=10.0.1 ; extra == 'all' + - pymysql>=1.0.2 ; extra == 'all' + - pyqt5>=5.15.9 ; extra == 'all' + - pyreadstat>=1.2.0 ; extra == 'all' + - pytest>=7.3.2 ; extra == 'all' + - pytest-xdist>=2.2.0 ; extra == 'all' + - python-calamine>=0.1.7 ; extra == 'all' + - pyxlsb>=1.0.10 ; extra == 'all' + - qtpy>=2.3.0 ; extra == 'all' + - scipy>=1.10.0 ; extra == 'all' + - s3fs>=2022.11.0 ; extra == 'all' + - sqlalchemy>=2.0.0 ; extra == 'all' + - tables>=3.8.0 ; extra == 'all' + - tabulate>=0.9.0 ; extra == 'all' + - xarray>=2022.12.0 ; extra == 'all' + - xlrd>=2.0.1 ; extra == 'all' + - xlsxwriter>=3.0.5 ; extra == 'all' + - zstandard>=0.19.0 ; extra == 'all' requires_python: '>=3.9' - kind: conda name: patchelf @@ -22904,12 +22676,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22928,12 +22700,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/5c/04224bf1a8247d6bbba375248d74668724a5a9879b4c42c23dfadd0c28ae/Pillow-10.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 3ed64f9ca2f0a95411e88a4efbd7a29e5ce2cea36072c53dd9d26d9c76f753b3 + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22952,12 +22724,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -22976,12 +22748,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23000,12 +22772,12 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/45/de/b07418f00cd78af292ceb4e2855c158ef8477dc1cbcdac3e1f32eb4e53b6/Pillow-10.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0b6eb5502f45a60a3f411c63187db83a3d3107887ad0d036c13ce836f8a36f1d + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23023,17 +22795,19 @@ packages: requires_python: '>=3.8' - kind: pypi name: pillow - version: 10.0.0 - url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd + version: 10.3.0 + url: https://files.pythonhosted.org/packages/81/ff/ad3c942d865f9e45ce84eeb31795e6d4d94e1f1eea51026d5154028510d7/pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: 1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' - check-manifest ; extra == 'tests' - coverage ; extra == 'tests' - defusedxml ; extra == 'tests' @@ -23044,20 +22818,24 @@ packages: - pytest ; extra == 'tests' - pytest-cov ; extra == 'tests' - pytest-timeout ; extra == 'tests' + - typing-extensions ; python_version < '3.10' and extra == 'typing' + - defusedxml ; extra == 'xmp' requires_python: '>=3.8' - kind: pypi name: pillow - version: 10.0.0 - url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 + version: 10.3.0 + url: https://files.pythonhosted.org/packages/e5/51/e4b35e394b4e5ca24983e50361a1db3d7da05b1758074f9c4f5b4be4b22a/pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' - sphinxext-opengraph ; extra == 'docs' + - olefile ; extra == 'fpx' + - olefile ; extra == 'mic' - check-manifest ; extra == 'tests' - coverage ; extra == 'tests' - defusedxml ; extra == 'tests' @@ -23068,16 +22846,18 @@ packages: - pytest ; extra == 'tests' - pytest-cov ; extra == 'tests' - pytest-timeout ; extra == 'tests' + - typing-extensions ; python_version < '3.10' and extra == 'typing' + - defusedxml ; extra == 'xmp' requires_python: '>=3.8' - kind: pypi name: pillow version: 10.3.0 - url: https://files.pythonhosted.org/packages/e5/51/e4b35e394b4e5ca24983e50361a1db3d7da05b1758074f9c4f5b4be4b22a/pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795 + url: https://files.pythonhosted.org/packages/0a/16/c83877524c47976f16703d2e05c363244bc1e60ab439e078b3cd046d07db/pillow-10.3.0-cp311-cp311-win_amd64.whl + sha256: 8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23105,63 +22885,7 @@ packages: requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-inline-tabs ; extra == 'docs' - - sphinx-removed-in ; extra == 'docs' - - sphinxext-opengraph ; extra == 'docs' - - olefile ; extra == 'fpx' - - olefile ; extra == 'mic' - - check-manifest ; extra == 'tests' - - coverage ; extra == 'tests' - - defusedxml ; extra == 'tests' - - markdown2 ; extra == 'tests' - - olefile ; extra == 'tests' - - packaging ; extra == 'tests' - - pyroma ; extra == 'tests' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-timeout ; extra == 'tests' - - typing-extensions ; python_version < '3.10' and extra == 'typing' - - defusedxml ; extra == 'xmp' - requires_python: '>=3.8' -- kind: pypi - name: pillow - version: 10.3.0 - url: https://files.pythonhosted.org/packages/81/ff/ad3c942d865f9e45ce84eeb31795e6d4d94e1f1eea51026d5154028510d7/pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: 1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd - requires_dist: - - furo ; extra == 'docs' - - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' - - sphinx-copybutton ; extra == 'docs' - - sphinx-inline-tabs ; extra == 'docs' - - sphinx-removed-in ; extra == 'docs' - - sphinxext-opengraph ; extra == 'docs' - - olefile ; extra == 'fpx' - - olefile ; extra == 'mic' - - check-manifest ; extra == 'tests' - - coverage ; extra == 'tests' - - defusedxml ; extra == 'tests' - - markdown2 ; extra == 'tests' - - olefile ; extra == 'tests' - - packaging ; extra == 'tests' - - pyroma ; extra == 'tests' - - pytest ; extra == 'tests' - - pytest-cov ; extra == 'tests' - - pytest-timeout ; extra == 'tests' - - typing-extensions ; python_version < '3.10' and extra == 'typing' - - defusedxml ; extra == 'xmp' - requires_python: '>=3.8' -- kind: pypi - name: pillow - version: 10.3.0 - url: https://files.pythonhosted.org/packages/0a/16/c83877524c47976f16703d2e05c363244bc1e60ab439e078b3cd046d07db/pillow-10.3.0-cp311-cp311-win_amd64.whl - sha256: 8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d - requires_dist: - - furo ; extra == 'docs' - - olefile ; extra == 'docs' - - sphinx >=2.4 ; extra == 'docs' + - sphinx>=2.4 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - sphinx-inline-tabs ; extra == 'docs' - sphinx-removed-in ; extra == 'docs' @@ -23227,38 +22951,22 @@ packages: - pkg:pypi/pip size: 1398245 timestamp: 1706960660581 -- kind: pypi - name: platformdirs - version: 4.2.0 - url: https://files.pythonhosted.org/packages/55/72/4898c44ee9ea6f43396fbc23d9bfaf3d06e01b83698bdf2e4c919deceb7c/platformdirs-4.2.0-py3-none-any.whl - sha256: 0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068 - requires_dist: - - furo >=2023.9.10 ; extra == 'docs' - - proselint >=0.13 ; extra == 'docs' - - sphinx-autodoc-typehints >=1.25.2 ; extra == 'docs' - - sphinx >=7.2.6 ; extra == 'docs' - - appdirs ==1.4.4 ; extra == 'test' - - covdefaults >=2.3 ; extra == 'test' - - pytest-cov >=4.1 ; extra == 'test' - - pytest-mock >=3.12 ; extra == 'test' - - pytest >=7.4.3 ; extra == 'test' - requires_python: '>=3.8' - kind: pypi name: platformdirs version: 4.2.1 url: https://files.pythonhosted.org/packages/b0/15/1691fa5aaddc0c4ea4901c26f6137c29d5f6673596fe960a0340e8c308e1/platformdirs-4.2.1-py3-none-any.whl sha256: 17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1 requires_dist: - - furo >=2023.9.10 ; extra == 'docs' - - proselint >=0.13 ; extra == 'docs' - - sphinx-autodoc-typehints >=1.25.2 ; extra == 'docs' - - sphinx >=7.2.6 ; extra == 'docs' - - appdirs ==1.4.4 ; extra == 'test' - - covdefaults >=2.3 ; extra == 'test' - - pytest-cov >=4.1 ; extra == 'test' - - pytest-mock >=3.12 ; extra == 'test' - - pytest >=7.4.3 ; extra == 'test' - - mypy >=1.8 ; extra == 'type' + - furo>=2023.9.10 ; extra == 'docs' + - proselint>=0.13 ; extra == 'docs' + - sphinx-autodoc-typehints>=1.25.2 ; extra == 'docs' + - sphinx>=7.2.6 ; extra == 'docs' + - appdirs==1.4.4 ; extra == 'test' + - covdefaults>=2.3 ; extra == 'test' + - pytest-cov>=4.1 ; extra == 'test' + - pytest-mock>=3.12 ; extra == 'test' + - pytest>=7.4.3 ; extra == 'test' + - mypy>=1.8 ; extra == 'type' requires_python: '>=3.8' - kind: pypi name: plots @@ -23387,8 +23095,8 @@ packages: url: https://files.pythonhosted.org/packages/ad/41/7361075f3a31dcd05a6a38cfd807a6eecbfb6dbfe420d922cd400fc03ac1/proto_plus-1.23.0-py3-none-any.whl sha256: a829c79e619e1cf632de091013a4173deed13a55f326ef84f05af6f50ff4c82c requires_dist: - - protobuf <5.0.0.dev0, >=3.19.0 - - google-api-core[grpc] >=1.31.5 ; extra == 'testing' + - protobuf<5.0.0.dev0,>=3.19.0 + - google-api-core[grpc]>=1.31.5 ; extra == 'testing' requires_python: '>=3.6' - kind: pypi name: protobuf @@ -23399,14 +23107,14 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl - sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c + url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl + sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d requires_python: '>=3.8' - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl - sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 + url: https://files.pythonhosted.org/packages/f3/bf/26deba06a4c910a85f78245cac7698f67cedd7efe00d04f6b3e1b3506a59/protobuf-4.25.3-cp37-abi3-macosx_10_9_universal2.whl + sha256: f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c requires_python: '>=3.8' - kind: pypi name: protobuf @@ -23417,14 +23125,14 @@ packages: - kind: pypi name: protobuf version: 4.25.3 - url: https://files.pythonhosted.org/packages/15/db/7f731524fe0e56c6b2eb57d05b55d3badd80ef7d1f1ed59db191b2fdd8ab/protobuf-4.25.3-cp37-abi3-manylinux2014_x86_64.whl - sha256: 7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d + url: https://files.pythonhosted.org/packages/d8/82/aefe901174b5a618daee511ddd00342193c1b545e3cd6a2cd6df9ba452b5/protobuf-4.25.3-cp37-abi3-manylinux2014_aarch64.whl + sha256: e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019 requires_python: '>=3.8' - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl - sha256: aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81 + url: https://files.pythonhosted.org/packages/c5/4f/0e22aaa246f96d6ac87fe5ebb9c5a693fbe8877f537a1022527c47ca43c5/psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -23435,8 +23143,8 @@ packages: - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl - sha256: d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8 + url: https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl + sha256: aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -23447,8 +23155,8 @@ packages: - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/c5/4f/0e22aaa246f96d6ac87fe5ebb9c5a693fbe8877f537a1022527c47ca43c5/psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4 + url: https://files.pythonhosted.org/packages/93/52/3e39d26feae7df0aa0fd510b14012c3678b36ed068f7d78b8d8784d61f0e/psutil-5.9.8-cp37-abi3-win_amd64.whl + sha256: 8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -23459,8 +23167,8 @@ packages: - kind: pypi name: psutil version: 5.9.8 - url: https://files.pythonhosted.org/packages/93/52/3e39d26feae7df0aa0fd510b14012c3678b36ed068f7d78b8d8784d61f0e/psutil-5.9.8-cp37-abi3-win_amd64.whl - sha256: 8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf + url: https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl + sha256: d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -24006,7 +23714,7 @@ packages: url: https://files.pythonhosted.org/packages/13/68/8906226b15ef38e71dc926c321d2fe99de8048e9098b5dfd38343011c886/pyasn1_modules-0.4.0-py3-none-any.whl sha256: be04f15b66c206eed667e0bb5ab27e2b1855ea54a842e5037738099e8ca4ae0b requires_dist: - - pyasn1 <0.7.0, >=0.4.6 + - pyasn1<0.7.0,>=0.4.6 requires_python: '>=3.8' - kind: pypi name: pycparser @@ -24037,9 +23745,9 @@ packages: sha256: 126bdbae72087d8d038b113aab6b059b4553cb59348e3024bb1a1cae406ace9e requires_dist: - deprecated - - pyjwt[crypto] >=2.4.0 - - pynacl >=1.4.0 - - requests >=2.14.0 + - pyjwt[crypto]>=2.4.0 + - pynacl>=1.4.0 + - requests>=2.14.0 requires_python: '>=3.7' - kind: pypi name: pyglet @@ -24053,7 +23761,7 @@ packages: url: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz sha256: 4f9481f5841b0b8fb7b271b0414b394b503405260a6ee0cf2c330a5420d19b64 requires_dist: - - dataclasses-json >=0.0.25 + - dataclasses-json>=0.0.25 - deprecated - dataclasses ; python_version >= '3.6' and python_version < '3.7' requires_python: '>=3.6' @@ -24064,43 +23772,43 @@ packages: sha256: 59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320 requires_dist: - typing-extensions ; python_version <= '3.7' - - cryptography >=3.4.0 ; extra == 'crypto' - - sphinx <5.0.0, >=4.5.0 ; extra == 'dev' + - cryptography>=3.4.0 ; extra == 'crypto' + - sphinx<5.0.0,>=4.5.0 ; extra == 'dev' - sphinx-rtd-theme ; extra == 'dev' - zope-interface ; extra == 'dev' - - cryptography >=3.4.0 ; extra == 'dev' - - pytest <7.0.0, >=6.0.0 ; extra == 'dev' - - coverage[toml] ==5.0.4 ; extra == 'dev' + - cryptography>=3.4.0 ; extra == 'dev' + - pytest<7.0.0,>=6.0.0 ; extra == 'dev' + - coverage[toml]==5.0.4 ; extra == 'dev' - pre-commit ; extra == 'dev' - - sphinx <5.0.0, >=4.5.0 ; extra == 'docs' + - sphinx<5.0.0,>=4.5.0 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - zope-interface ; extra == 'docs' - - pytest <7.0.0, >=6.0.0 ; extra == 'tests' - - coverage[toml] ==5.0.4 ; extra == 'tests' + - pytest<7.0.0,>=6.0.0 ; extra == 'tests' + - coverage[toml]==5.0.4 ; extra == 'tests' requires_python: '>=3.7' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 + url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl + sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d requires_dist: - - cffi >=1.4.1 - - sphinx >=1.6.5 ; extra == 'docs' + - cffi>=1.4.1 + - sphinx>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - - hypothesis >=3.27.0 ; extra == 'tests' + - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' + - hypothesis>=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 + url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl + sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 requires_dist: - - cffi >=1.4.1 - - sphinx >=1.6.5 ; extra == 'docs' + - cffi>=1.4.1 + - sphinx>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - - hypothesis >=3.27.0 ; extra == 'tests' + - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' + - hypothesis>=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl @@ -24108,23 +23816,23 @@ packages: url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 requires_dist: - - cffi >=1.4.1 - - sphinx >=1.6.5 ; extra == 'docs' + - cffi>=1.4.1 + - sphinx>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - - hypothesis >=3.27.0 ; extra == 'tests' + - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' + - hypothesis>=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d + url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 requires_dist: - - cffi >=1.4.1 - - sphinx >=1.6.5 ; extra == 'docs' + - cffi>=1.4.1 + - sphinx>=1.6.5 ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - - pytest !=3.3.0, >=3.2.1 ; extra == 'tests' - - hypothesis >=3.27.0 ; extra == 'tests' + - pytest!=3.3.0,>=3.2.1 ; extra == 'tests' + - hypothesis>=3.27.0 ; extra == 'tests' requires_python: '>=3.6' - kind: pypi name: pynndescent @@ -24132,31 +23840,31 @@ packages: url: https://files.pythonhosted.org/packages/bf/06/18c0e17eb245b7caeb861f2ff747adb0575500183b6ec4282d5350d29e9f/pynndescent-0.5.12-py3-none-any.whl sha256: 9023dc5fea520a4e84d0633ae735db97d2509da927bfa86c897e61f3315473c7 requires_dist: - - scikit-learn >=0.18 - - scipy >=1.0 - - numba >=0.51.2 - - llvmlite >=0.30 - - joblib >=0.11 - - importlib-metadata >=4.8.1 ; python_version < '3.8' + - scikit-learn>=0.18 + - scipy>=1.0 + - numba>=0.51.2 + - llvmlite>=0.30 + - joblib>=0.11 + - importlib-metadata>=4.8.1 ; python_version < '3.8' - kind: pypi name: pyopengl version: 3.1.0 - url: https://files.pythonhosted.org/packages/ce/33/ef0e3b40a3f4cbfcfb93511652673fb19d07bafac0611f01f6237d1978ed/PyOpenGL-3.1.0.zip - sha256: efa4e39a49b906ccbe66758812ca81ced13a6f26931ab2ba2dba2750c016c0d0 + url: https://files.pythonhosted.org/packages/9c/1d/4544708aaa89f26c97cc09450bb333a23724a320923e74d73e028b3560f9/PyOpenGL-3.1.0.tar.gz + sha256: 9b47c5c3a094fa518ca88aeed35ae75834d53e4285512c61879f67a48c94ddaf - kind: pypi name: pyopf version: 1.1.1 url: https://files.pythonhosted.org/packages/a8/26/b67fe94cb53c489c5ccaed118f257a5100e7775071515942c9f45d8cd40f/pyopf-1.1.1-py3-none-any.whl sha256: 10971881afcb7ed0dd373f7e88862fa8ad0f70fe4329f2ef5093c152e923831f requires_dist: - - argparse >=1.4.0 - - numpy >=1.24.1 - - pillow >=9.5.0 - - pygltflib >=1.15.3 - - python-dateutil >=2.8.2 - - shapely >=2.0.1 - - tqdm >=4.65.0 - - simplejson >=18.3 ; extra == 'tests' + - argparse>=1.4.0 + - numpy>=1.24.1 + - pillow>=9.5.0 + - pygltflib>=1.15.3 + - python-dateutil>=2.8.2 + - shapely>=2.0.1 + - tqdm>=4.65.0 + - simplejson>=18.3 ; extra == 'tests' requires_python: '>=3.10' - kind: pypi name: pyparsing @@ -24178,8 +23886,8 @@ packages: - networkx - numpy - pillow - - pyglet >=1.4.10 - - pyopengl ==3.1.0 + - pyglet>=1.4.10 + - pyopengl==3.1.0 - scipy - six - trimesh @@ -24191,45 +23899,6 @@ packages: - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' - sphinx-automodapi ; extra == 'docs' -- kind: conda - name: pysocks - version: 1.7.1 - build: pyh0701188_6 - build_number: 6 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyh0701188_6.tar.bz2 - sha256: b3a612bc887f3dd0fb7c4199ad8e342bd148cf69a9b74fd9468a18cf2bef07b7 - md5: 56cd9fe388baac0e90c7149cfac95b60 - depends: - - __win - - python >=3.8 - - win_inet_pton - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pysocks - size: 19348 - timestamp: 1661605138291 -- kind: conda - name: pysocks - version: 1.7.1 - build: pyha2e5f31_6 - build_number: 6 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/pysocks-1.7.1-pyha2e5f31_6.tar.bz2 - sha256: a42f826e958a8d22e65b3394f437af7332610e43ee313393d1cf143f0a2d274b - md5: 2a7de29fb590ca14b5243c4c812c8025 - depends: - - __unix - - python >=3.8 - license: BSD-3-Clause - license_family: BSD - purls: - - pkg:pypi/pysocks - size: 18981 - timestamp: 1661604969727 - kind: conda name: pytest version: 7.4.2 @@ -24576,7 +24245,7 @@ packages: url: https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl sha256: a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 requires_dist: - - six >=1.5 + - six>=1.5 requires_python: '!=3.0.*,!=3.1.*,!=3.2.*,>=2.7' - kind: conda name: python_abi @@ -24661,26 +24330,26 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 + url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab + url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 + url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl + sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl - sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 + url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab requires_python: '>=3.6' - kind: pypi name: raw-mesh @@ -24689,10 +24358,10 @@ packages: sha256: 29d7482ea0dae8ceb7b95c4adeff04bd362cab0842f3f0a9572b2c42013c7656 requires_dist: - numpy - - pillow - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - - trimesh ==3.15.2 + - trimesh==3.15.2 + - pillow editable: true - kind: conda name: rdma-core @@ -24961,64 +24630,41 @@ packages: timestamp: 1679532707590 - kind: pypi name: regex - version: 2024.4.16 - url: https://files.pythonhosted.org/packages/fd/b2/8069e8940bc3224d2cef6418aa6de4f2119d59709b841ecab012e3fc1d65/regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd - requires_python: '>=3.7' + version: 2024.4.28 + url: https://files.pythonhosted.org/packages/52/21/22e993e8151c94e9adc9fc5f09848bad538d12c6390cec91f0fb1f6c8ba3/regex-2024.4.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fe00f4fe11c8a521b173e6324d862ee7ee3412bf7107570c9b564fe1119b56fb + requires_python: '>=3.8' - kind: pypi name: regex - version: 2024.4.16 - url: https://files.pythonhosted.org/packages/aa/f1/de801945e6a18c9b7d7ea9ffe01d2433b40d1609426c3581f7d60acd1416/regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl - sha256: fd80d1280d473500d8086d104962a82d77bfbf2b118053824b7be28cd5a79ea5 - requires_python: '>=3.7' + version: 2024.4.28 + url: https://files.pythonhosted.org/packages/9e/4b/950828d604c44c17468a992940c68c40a92dd5dc85e4415dc30f82535b2c/regex-2024.4.28-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b45d4503de8f4f3dc02f1d28a9b039e5504a02cc18906cfe744c11def942e9eb + requires_python: '>=3.8' - kind: pypi name: regex - version: 2024.4.16 - url: https://files.pythonhosted.org/packages/8b/9e/05bc55a3295d469ae658e15c7f6edc0f54d39745ad3bd268351ac31be73d/regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0c8290b44d8b0af4e77048646c10c6e3aa583c1ca67f3b5ffb6e06cf0c6f0f89 - requires_python: '>=3.7' + version: 2024.4.28 + url: https://files.pythonhosted.org/packages/bd/ad/33a844d35d3be70e01743f27960cf3646da1dbdea050e67dbdae6b843582/regex-2024.4.28-cp311-cp311-win_amd64.whl + sha256: fc0916c4295c64d6890a46e02d4482bb5ccf33bf1a824c0eaa9e83b148291f90 + requires_python: '>=3.8' - kind: pypi name: regex - version: 2024.4.16 - url: https://files.pythonhosted.org/packages/b3/d0/1a054b685849b018cff594ccd4859fc6a3132f67698da805ed06d5b6974a/regex-2024.4.16-cp311-cp311-win_amd64.whl - sha256: 8f83b6fd3dc3ba94d2b22717f9c8b8512354fd95221ac661784df2769ea9bba9 - requires_python: '>=3.7' + version: 2024.4.28 + url: https://files.pythonhosted.org/packages/ac/86/8a1f52664cc21effdd7a0d6a142ffce39f5533be418e5b26d75137f2921b/regex-2024.4.28-cp311-cp311-macosx_11_0_arm64.whl + sha256: 457c2cd5a646dd4ed536c92b535d73548fb8e216ebee602aa9f48e068fc393f3 + requires_python: '>=3.8' - kind: pypi name: requests version: 2.31.0 url: https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl sha256: 58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f requires_dist: - - charset-normalizer <4, >=2 - - idna <4, >=2.5 - - urllib3 <3, >=1.21.1 - - certifi >=2017.4.17 - - pysocks !=1.5.7, >=1.5.6 ; extra == 'socks' - - chardet <6, >=3.0.2 ; extra == 'use_chardet_on_py3' + - charset-normalizer<4,>=2 + - idna<4,>=2.5 + - urllib3<3,>=1.21.1 + - certifi>=2017.4.17 + - pysocks!=1.5.7,>=1.5.6 ; extra == 'socks' + - chardet<6,>=3.0.2 ; extra == 'use_chardet_on_py3' requires_python: '>=3.7' -- kind: conda - name: requests - version: 2.31.0 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/requests-2.31.0-pyhd8ed1ab_0.conda - sha256: 9f629d6fd3c8ac5f2a198639fe7af87c4db2ac9235279164bfe0fcb49d8c4bad - md5: a30144e4156cdbb236f99ebb49828f8b - depends: - - certifi >=2017.4.17 - - charset-normalizer >=2,<4 - - idna >=2.5,<4 - - python >=3.7 - - urllib3 >=1.21.1,<3 - constrains: - - chardet >=3.0.2,<6 - license: Apache-2.0 - license_family: APACHE - purls: - - pkg:pypi/requests - size: 56690 - timestamp: 1684774408600 - kind: pypi name: rerun-sdk version: 0.10.0 @@ -25031,8 +24677,8 @@ packages: sha256: b2ef153b0bedd672c3e0ce89b7be1f64f4344b2b75d71748899faea270383fa2 requires_dist: - numpy - - opencv-python >4.6 - - requests <3, >=2.31 + - opencv-python>4.6 + - requests>=2.31,<3 - rerun-sdk - tqdm editable: true @@ -25103,7 +24749,7 @@ packages: url: https://files.pythonhosted.org/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl sha256: 90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7 requires_dist: - - pyasn1 >=0.1.3 + - pyasn1>=0.1.3 requires_python: '>=3.6,<4' - kind: conda name: ruff @@ -25285,34 +24931,34 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a + url: https://files.pythonhosted.org/packages/d5/85/1e7d2804cbf82204cde462d16f1cb0ff5814b03f559fb46ceaa6b7020db4/safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b requires_dist: - - numpy >=1.21.6 ; extra == 'numpy' + - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch >=1.10 ; extra == 'torch' + - torch>=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow >=2.11.0 ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow ==2.11.0 ; extra == 'pinned-tf' + - tensorflow==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax >=0.6.3 ; extra == 'jax' - - jax >=0.3.25 ; extra == 'jax' - - jaxlib >=0.3.25 ; extra == 'jax' - - mlx >=0.0.9 ; extra == 'mlx' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' - - black ==22.3 ; extra == 'quality' - - click ==8.0.4 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - flake8 >=3.8.3 ; extra == 'quality' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - black==22.3 ; extra == 'quality' + - click==8.0.4 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - flake8>=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py >=3.7.0 ; extra == 'testing' - - huggingface-hub >=0.12.1 ; extra == 'testing' - - setuptools-rust >=1.5.2 ; extra == 'testing' - - pytest >=7.2.0 ; extra == 'testing' - - pytest-benchmark >=4.0.0 ; extra == 'testing' - - hypothesis >=6.70.2 ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - huggingface-hub>=0.12.1 ; extra == 'testing' + - setuptools-rust>=1.5.2 ; extra == 'testing' + - pytest>=7.2.0 ; extra == 'testing' + - pytest-benchmark>=4.0.0 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25325,34 +24971,34 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl - sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe + url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a requires_dist: - - numpy >=1.21.6 ; extra == 'numpy' + - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch >=1.10 ; extra == 'torch' + - torch>=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow >=2.11.0 ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow ==2.11.0 ; extra == 'pinned-tf' + - tensorflow==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax >=0.6.3 ; extra == 'jax' - - jax >=0.3.25 ; extra == 'jax' - - jaxlib >=0.3.25 ; extra == 'jax' - - mlx >=0.0.9 ; extra == 'mlx' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' - - black ==22.3 ; extra == 'quality' - - click ==8.0.4 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - flake8 >=3.8.3 ; extra == 'quality' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - black==22.3 ; extra == 'quality' + - click==8.0.4 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - flake8>=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py >=3.7.0 ; extra == 'testing' - - huggingface-hub >=0.12.1 ; extra == 'testing' - - setuptools-rust >=1.5.2 ; extra == 'testing' - - pytest >=7.2.0 ; extra == 'testing' - - pytest-benchmark >=4.0.0 ; extra == 'testing' - - hypothesis >=6.70.2 ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - huggingface-hub>=0.12.1 ; extra == 'testing' + - setuptools-rust>=1.5.2 ; extra == 'testing' + - pytest>=7.2.0 ; extra == 'testing' + - pytest-benchmark>=4.0.0 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25365,34 +25011,34 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/d5/85/1e7d2804cbf82204cde462d16f1cb0ff5814b03f559fb46ceaa6b7020db4/safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b + url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl + sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 requires_dist: - - numpy >=1.21.6 ; extra == 'numpy' + - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch >=1.10 ; extra == 'torch' + - torch>=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow >=2.11.0 ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow ==2.11.0 ; extra == 'pinned-tf' + - tensorflow==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax >=0.6.3 ; extra == 'jax' - - jax >=0.3.25 ; extra == 'jax' - - jaxlib >=0.3.25 ; extra == 'jax' - - mlx >=0.0.9 ; extra == 'mlx' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' - - black ==22.3 ; extra == 'quality' - - click ==8.0.4 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - flake8 >=3.8.3 ; extra == 'quality' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - black==22.3 ; extra == 'quality' + - click==8.0.4 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - flake8>=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py >=3.7.0 ; extra == 'testing' - - huggingface-hub >=0.12.1 ; extra == 'testing' - - setuptools-rust >=1.5.2 ; extra == 'testing' - - pytest >=7.2.0 ; extra == 'testing' - - pytest-benchmark >=4.0.0 ; extra == 'testing' - - hypothesis >=6.70.2 ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - huggingface-hub>=0.12.1 ; extra == 'testing' + - setuptools-rust>=1.5.2 ; extra == 'testing' + - pytest>=7.2.0 ; extra == 'testing' + - pytest-benchmark>=4.0.0 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25405,34 +25051,34 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl - sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 + url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl + sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe requires_dist: - - numpy >=1.21.6 ; extra == 'numpy' + - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' - - torch >=1.10 ; extra == 'torch' + - torch>=1.10 ; extra == 'torch' - safetensors[numpy] ; extra == 'tensorflow' - - tensorflow >=2.11.0 ; extra == 'tensorflow' + - tensorflow>=2.11.0 ; extra == 'tensorflow' - safetensors[numpy] ; extra == 'pinned-tf' - - tensorflow ==2.11.0 ; extra == 'pinned-tf' + - tensorflow==2.11.0 ; extra == 'pinned-tf' - safetensors[numpy] ; extra == 'jax' - - flax >=0.6.3 ; extra == 'jax' - - jax >=0.3.25 ; extra == 'jax' - - jaxlib >=0.3.25 ; extra == 'jax' - - mlx >=0.0.9 ; extra == 'mlx' + - flax>=0.6.3 ; extra == 'jax' + - jax>=0.3.25 ; extra == 'jax' + - jaxlib>=0.3.25 ; extra == 'jax' + - mlx>=0.0.9 ; extra == 'mlx' - safetensors[numpy] ; extra == 'paddlepaddle' - - paddlepaddle >=2.4.1 ; extra == 'paddlepaddle' - - black ==22.3 ; extra == 'quality' - - click ==8.0.4 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - flake8 >=3.8.3 ; extra == 'quality' + - paddlepaddle>=2.4.1 ; extra == 'paddlepaddle' + - black==22.3 ; extra == 'quality' + - click==8.0.4 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - flake8>=3.8.3 ; extra == 'quality' - safetensors[numpy] ; extra == 'testing' - - h5py >=3.7.0 ; extra == 'testing' - - huggingface-hub >=0.12.1 ; extra == 'testing' - - setuptools-rust >=1.5.2 ; extra == 'testing' - - pytest >=7.2.0 ; extra == 'testing' - - pytest-benchmark >=4.0.0 ; extra == 'testing' - - hypothesis >=6.70.2 ; extra == 'testing' + - h5py>=3.7.0 ; extra == 'testing' + - huggingface-hub>=0.12.1 ; extra == 'testing' + - setuptools-rust>=1.5.2 ; extra == 'testing' + - pytest>=7.2.0 ; extra == 'testing' + - pytest-benchmark>=4.0.0 ; extra == 'testing' + - hypothesis>=6.70.2 ; extra == 'testing' - safetensors[torch] ; extra == 'all' - safetensors[numpy] ; extra == 'all' - safetensors[pinned-tf] ; extra == 'all' @@ -25445,66 +25091,66 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/78/2b/5f985cf4cf59378f80dc212004a7692b7b49b2a3910c3584d70284db5b89/scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: ee83fdb1843ee938eabdfeb9498623282935ea30aa20dffc5d5d16698efb4b2a + url: https://files.pythonhosted.org/packages/0a/40/2c57864acd77c168b96cb6e4e62651b9c98733962793293991ef55e2982c/scikit_image-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fce619a6d84fe40c1208fa579b646e93ce13ef0afc3652a23e9782b2c183291a requires_dist: - - numpy >=1.23 - - scipy >=1.9 - - networkx >=2.8 - - pillow >=9.1 - - imageio >=2.33 - - tifffile >=2022.8.12 - - packaging >=21 - - lazy-loader >=0.4 - - meson-python >=0.15 ; extra == 'build' + - numpy>=1.23 + - scipy>=1.9 + - networkx>=2.8 + - pillow>=9.1 + - imageio>=2.33 + - tifffile>=2022.8.12 + - packaging>=21 + - lazy-loader>=0.4 + - meson-python>=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools >=67 ; extra == 'build' - - packaging >=21 ; extra == 'build' + - setuptools>=67 ; extra == 'build' + - packaging>=21 ; extra == 'build' - ninja ; extra == 'build' - - cython >=3.0.4 ; extra == 'build' + - cython>=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy >=2.0.0rc1 ; extra == 'build' - - spin ==0.8 ; extra == 'build' + - numpy>=2.0.0rc1 ; extra == 'build' + - spin==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch >=1.6.0 ; extra == 'data' + - pooch>=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx >=7.3 ; extra == 'docs' - - sphinx-gallery >=0.14 ; extra == 'docs' - - numpydoc >=1.7 ; extra == 'docs' + - sphinx>=7.3 ; extra == 'docs' + - sphinx-gallery>=0.14 ; extra == 'docs' + - numpydoc>=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib >=3.6 ; extra == 'docs' - - dask[array] >=2022.9.2 ; extra == 'docs' - - pandas >=1.5 ; extra == 'docs' - - seaborn >=0.11 ; extra == 'docs' - - pooch >=1.6 ; extra == 'docs' - - tifffile >=2022.8.12 ; extra == 'docs' + - matplotlib>=3.6 ; extra == 'docs' + - dask[array]>=2022.9.2 ; extra == 'docs' + - pandas>=1.5 ; extra == 'docs' + - seaborn>=0.11 ; extra == 'docs' + - pooch>=1.6 ; extra == 'docs' + - tifffile>=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly >=5.10 ; extra == 'docs' + - plotly>=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn >=1.1 ; extra == 'docs' - - sphinx-design >=0.5 ; extra == 'docs' - - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' - - pywavelets >=1.1.1 ; extra == 'docs' + - scikit-learn>=1.1 ; extra == 'docs' + - sphinx-design>=0.5 ; extra == 'docs' + - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' + - pywavelets>=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy >=5.0 ; extra == 'optional' - - cloudpickle >=0.2.1 ; extra == 'optional' - - dask[array] >=2021.1.0 ; extra == 'optional' - - matplotlib >=3.6 ; extra == 'optional' - - pooch >=1.6.0 ; extra == 'optional' + - astropy>=5.0 ; extra == 'optional' + - cloudpickle>=0.2.1 ; extra == 'optional' + - dask[array]>=2021.1.0 ; extra == 'optional' + - matplotlib>=3.6 ; extra == 'optional' + - pooch>=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets >=1.1.1 ; extra == 'optional' - - scikit-learn >=1.1 ; extra == 'optional' + - pywavelets>=1.1.1 ; extra == 'optional' + - scikit-learn>=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc >=1.7 ; extra == 'test' - - pooch >=1.6.0 ; extra == 'test' - - pytest >=7.0 ; extra == 'test' - - pytest-cov >=2.11.0 ; extra == 'test' + - numpydoc>=1.7 ; extra == 'test' + - pooch>=1.6.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-cov>=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25512,66 +25158,66 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/b9/cf/9e5828fa29791bf7ac5c3fad3637ebb02f237a1c3de8233bd6a33c2c4aac/scikit_image-0.23.2-cp311-cp311-macosx_12_0_arm64.whl - sha256: a158f50d3df4867bbd1c698520ede8bc493e430ad83f54ac1f0d8f57b328779b + url: https://files.pythonhosted.org/packages/78/2b/5f985cf4cf59378f80dc212004a7692b7b49b2a3910c3584d70284db5b89/scikit_image-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: ee83fdb1843ee938eabdfeb9498623282935ea30aa20dffc5d5d16698efb4b2a requires_dist: - - numpy >=1.23 - - scipy >=1.9 - - networkx >=2.8 - - pillow >=9.1 - - imageio >=2.33 - - tifffile >=2022.8.12 - - packaging >=21 - - lazy-loader >=0.4 - - meson-python >=0.15 ; extra == 'build' + - numpy>=1.23 + - scipy>=1.9 + - networkx>=2.8 + - pillow>=9.1 + - imageio>=2.33 + - tifffile>=2022.8.12 + - packaging>=21 + - lazy-loader>=0.4 + - meson-python>=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools >=67 ; extra == 'build' - - packaging >=21 ; extra == 'build' + - setuptools>=67 ; extra == 'build' + - packaging>=21 ; extra == 'build' - ninja ; extra == 'build' - - cython >=3.0.4 ; extra == 'build' + - cython>=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy >=2.0.0rc1 ; extra == 'build' - - spin ==0.8 ; extra == 'build' + - numpy>=2.0.0rc1 ; extra == 'build' + - spin==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch >=1.6.0 ; extra == 'data' + - pooch>=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx >=7.3 ; extra == 'docs' - - sphinx-gallery >=0.14 ; extra == 'docs' - - numpydoc >=1.7 ; extra == 'docs' + - sphinx>=7.3 ; extra == 'docs' + - sphinx-gallery>=0.14 ; extra == 'docs' + - numpydoc>=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib >=3.6 ; extra == 'docs' - - dask[array] >=2022.9.2 ; extra == 'docs' - - pandas >=1.5 ; extra == 'docs' - - seaborn >=0.11 ; extra == 'docs' - - pooch >=1.6 ; extra == 'docs' - - tifffile >=2022.8.12 ; extra == 'docs' + - matplotlib>=3.6 ; extra == 'docs' + - dask[array]>=2022.9.2 ; extra == 'docs' + - pandas>=1.5 ; extra == 'docs' + - seaborn>=0.11 ; extra == 'docs' + - pooch>=1.6 ; extra == 'docs' + - tifffile>=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly >=5.10 ; extra == 'docs' + - plotly>=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn >=1.1 ; extra == 'docs' - - sphinx-design >=0.5 ; extra == 'docs' - - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' - - pywavelets >=1.1.1 ; extra == 'docs' + - scikit-learn>=1.1 ; extra == 'docs' + - sphinx-design>=0.5 ; extra == 'docs' + - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' + - pywavelets>=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy >=5.0 ; extra == 'optional' - - cloudpickle >=0.2.1 ; extra == 'optional' - - dask[array] >=2021.1.0 ; extra == 'optional' - - matplotlib >=3.6 ; extra == 'optional' - - pooch >=1.6.0 ; extra == 'optional' + - astropy>=5.0 ; extra == 'optional' + - cloudpickle>=0.2.1 ; extra == 'optional' + - dask[array]>=2021.1.0 ; extra == 'optional' + - matplotlib>=3.6 ; extra == 'optional' + - pooch>=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets >=1.1.1 ; extra == 'optional' - - scikit-learn >=1.1 ; extra == 'optional' + - pywavelets>=1.1.1 ; extra == 'optional' + - scikit-learn>=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc >=1.7 ; extra == 'test' - - pooch >=1.6.0 ; extra == 'test' - - pytest >=7.0 ; extra == 'test' - - pytest-cov >=2.11.0 ; extra == 'test' + - numpydoc>=1.7 ; extra == 'test' + - pooch>=1.6.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-cov>=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25579,66 +25225,66 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/0a/40/2c57864acd77c168b96cb6e4e62651b9c98733962793293991ef55e2982c/scikit_image-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fce619a6d84fe40c1208fa579b646e93ce13ef0afc3652a23e9782b2c183291a + url: https://files.pythonhosted.org/packages/eb/ab/8791ce3063e6d4ac7f8efe3c993fd2e911c9e08f4c7dd05b603eaa2493b2/scikit_image-0.23.2-cp311-cp311-win_amd64.whl + sha256: ee65669aa586e110346f567ed5c92d1bd63799a19e951cb83da3f54b0caf7c52 requires_dist: - - numpy >=1.23 - - scipy >=1.9 - - networkx >=2.8 - - pillow >=9.1 - - imageio >=2.33 - - tifffile >=2022.8.12 - - packaging >=21 - - lazy-loader >=0.4 - - meson-python >=0.15 ; extra == 'build' + - numpy>=1.23 + - scipy>=1.9 + - networkx>=2.8 + - pillow>=9.1 + - imageio>=2.33 + - tifffile>=2022.8.12 + - packaging>=21 + - lazy-loader>=0.4 + - meson-python>=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools >=67 ; extra == 'build' - - packaging >=21 ; extra == 'build' + - setuptools>=67 ; extra == 'build' + - packaging>=21 ; extra == 'build' - ninja ; extra == 'build' - - cython >=3.0.4 ; extra == 'build' + - cython>=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy >=2.0.0rc1 ; extra == 'build' - - spin ==0.8 ; extra == 'build' + - numpy>=2.0.0rc1 ; extra == 'build' + - spin==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch >=1.6.0 ; extra == 'data' + - pooch>=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx >=7.3 ; extra == 'docs' - - sphinx-gallery >=0.14 ; extra == 'docs' - - numpydoc >=1.7 ; extra == 'docs' + - sphinx>=7.3 ; extra == 'docs' + - sphinx-gallery>=0.14 ; extra == 'docs' + - numpydoc>=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib >=3.6 ; extra == 'docs' - - dask[array] >=2022.9.2 ; extra == 'docs' - - pandas >=1.5 ; extra == 'docs' - - seaborn >=0.11 ; extra == 'docs' - - pooch >=1.6 ; extra == 'docs' - - tifffile >=2022.8.12 ; extra == 'docs' + - matplotlib>=3.6 ; extra == 'docs' + - dask[array]>=2022.9.2 ; extra == 'docs' + - pandas>=1.5 ; extra == 'docs' + - seaborn>=0.11 ; extra == 'docs' + - pooch>=1.6 ; extra == 'docs' + - tifffile>=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly >=5.10 ; extra == 'docs' + - plotly>=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn >=1.1 ; extra == 'docs' - - sphinx-design >=0.5 ; extra == 'docs' - - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' - - pywavelets >=1.1.1 ; extra == 'docs' + - scikit-learn>=1.1 ; extra == 'docs' + - sphinx-design>=0.5 ; extra == 'docs' + - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' + - pywavelets>=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy >=5.0 ; extra == 'optional' - - cloudpickle >=0.2.1 ; extra == 'optional' - - dask[array] >=2021.1.0 ; extra == 'optional' - - matplotlib >=3.6 ; extra == 'optional' - - pooch >=1.6.0 ; extra == 'optional' + - astropy>=5.0 ; extra == 'optional' + - cloudpickle>=0.2.1 ; extra == 'optional' + - dask[array]>=2021.1.0 ; extra == 'optional' + - matplotlib>=3.6 ; extra == 'optional' + - pooch>=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets >=1.1.1 ; extra == 'optional' - - scikit-learn >=1.1 ; extra == 'optional' + - pywavelets>=1.1.1 ; extra == 'optional' + - scikit-learn>=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc >=1.7 ; extra == 'test' - - pooch >=1.6.0 ; extra == 'test' - - pytest >=7.0 ; extra == 'test' - - pytest-cov >=2.11.0 ; extra == 'test' + - numpydoc>=1.7 ; extra == 'test' + - pooch>=1.6.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-cov>=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25646,66 +25292,66 @@ packages: - kind: pypi name: scikit-image version: 0.23.2 - url: https://files.pythonhosted.org/packages/eb/ab/8791ce3063e6d4ac7f8efe3c993fd2e911c9e08f4c7dd05b603eaa2493b2/scikit_image-0.23.2-cp311-cp311-win_amd64.whl - sha256: ee65669aa586e110346f567ed5c92d1bd63799a19e951cb83da3f54b0caf7c52 + url: https://files.pythonhosted.org/packages/b9/cf/9e5828fa29791bf7ac5c3fad3637ebb02f237a1c3de8233bd6a33c2c4aac/scikit_image-0.23.2-cp311-cp311-macosx_12_0_arm64.whl + sha256: a158f50d3df4867bbd1c698520ede8bc493e430ad83f54ac1f0d8f57b328779b requires_dist: - - numpy >=1.23 - - scipy >=1.9 - - networkx >=2.8 - - pillow >=9.1 - - imageio >=2.33 - - tifffile >=2022.8.12 - - packaging >=21 - - lazy-loader >=0.4 - - meson-python >=0.15 ; extra == 'build' + - numpy>=1.23 + - scipy>=1.9 + - networkx>=2.8 + - pillow>=9.1 + - imageio>=2.33 + - tifffile>=2022.8.12 + - packaging>=21 + - lazy-loader>=0.4 + - meson-python>=0.15 ; extra == 'build' - wheel ; extra == 'build' - - setuptools >=67 ; extra == 'build' - - packaging >=21 ; extra == 'build' + - setuptools>=67 ; extra == 'build' + - packaging>=21 ; extra == 'build' - ninja ; extra == 'build' - - cython >=3.0.4 ; extra == 'build' + - cython>=3.0.4 ; extra == 'build' - pythran ; extra == 'build' - - numpy >=2.0.0rc1 ; extra == 'build' - - spin ==0.8 ; extra == 'build' + - numpy>=2.0.0rc1 ; extra == 'build' + - spin==0.8 ; extra == 'build' - build ; extra == 'build' - - pooch >=1.6.0 ; extra == 'data' + - pooch>=1.6.0 ; extra == 'data' - pre-commit ; extra == 'developer' - ipython ; extra == 'developer' - tomli ; python_version < '3.11' and extra == 'developer' - - sphinx >=7.3 ; extra == 'docs' - - sphinx-gallery >=0.14 ; extra == 'docs' - - numpydoc >=1.7 ; extra == 'docs' + - sphinx>=7.3 ; extra == 'docs' + - sphinx-gallery>=0.14 ; extra == 'docs' + - numpydoc>=1.7 ; extra == 'docs' - sphinx-copybutton ; extra == 'docs' - pytest-runner ; extra == 'docs' - - matplotlib >=3.6 ; extra == 'docs' - - dask[array] >=2022.9.2 ; extra == 'docs' - - pandas >=1.5 ; extra == 'docs' - - seaborn >=0.11 ; extra == 'docs' - - pooch >=1.6 ; extra == 'docs' - - tifffile >=2022.8.12 ; extra == 'docs' + - matplotlib>=3.6 ; extra == 'docs' + - dask[array]>=2022.9.2 ; extra == 'docs' + - pandas>=1.5 ; extra == 'docs' + - seaborn>=0.11 ; extra == 'docs' + - pooch>=1.6 ; extra == 'docs' + - tifffile>=2022.8.12 ; extra == 'docs' - myst-parser ; extra == 'docs' - ipywidgets ; extra == 'docs' - ipykernel ; extra == 'docs' - - plotly >=5.10 ; extra == 'docs' + - plotly>=5.10 ; extra == 'docs' - kaleido ; extra == 'docs' - - scikit-learn >=1.1 ; extra == 'docs' - - sphinx-design >=0.5 ; extra == 'docs' - - pydata-sphinx-theme >=0.15.2 ; extra == 'docs' - - pywavelets >=1.1.1 ; extra == 'docs' + - scikit-learn>=1.1 ; extra == 'docs' + - sphinx-design>=0.5 ; extra == 'docs' + - pydata-sphinx-theme>=0.15.2 ; extra == 'docs' + - pywavelets>=1.1.1 ; extra == 'docs' - pytest-doctestplus ; extra == 'docs' - simpleitk ; extra == 'optional' - - astropy >=5.0 ; extra == 'optional' - - cloudpickle >=0.2.1 ; extra == 'optional' - - dask[array] >=2021.1.0 ; extra == 'optional' - - matplotlib >=3.6 ; extra == 'optional' - - pooch >=1.6.0 ; extra == 'optional' + - astropy>=5.0 ; extra == 'optional' + - cloudpickle>=0.2.1 ; extra == 'optional' + - dask[array]>=2021.1.0 ; extra == 'optional' + - matplotlib>=3.6 ; extra == 'optional' + - pooch>=1.6.0 ; extra == 'optional' - pyamg ; extra == 'optional' - - pywavelets >=1.1.1 ; extra == 'optional' - - scikit-learn >=1.1 ; extra == 'optional' + - pywavelets>=1.1.1 ; extra == 'optional' + - scikit-learn>=1.1 ; extra == 'optional' - asv ; extra == 'test' - - numpydoc >=1.7 ; extra == 'test' - - pooch >=1.6.0 ; extra == 'test' - - pytest >=7.0 ; extra == 'test' - - pytest-cov >=2.11.0 ; extra == 'test' + - numpydoc>=1.7 ; extra == 'test' + - pooch>=1.6.0 ; extra == 'test' + - pytest>=7.0 ; extra == 'test' + - pytest-cov>=2.11.0 ; extra == 'test' - pytest-localserver ; extra == 'test' - pytest-faulthandler ; extra == 'test' - pytest-doctestplus ; extra == 'test' @@ -25713,198 +25359,198 @@ packages: - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/59/11/63de36e6933b03490fdfe5cbc9b5a68870a1281d8e705a23b33076dc82fb/scikit_learn-1.4.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 45dee87ac5309bb82e3ea633955030df9bbcb8d2cdb30383c6cd483691c546cc + url: https://files.pythonhosted.org/packages/4e/53/14405a47292b59235d811a2af8634aba188ccfd1a38ef4b8042f3447d79a/scikit_learn-1.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 44c62f2b124848a28fd695db5bc4da019287abf390bfce602ddc8aa1ec186aae requires_dist: - - numpy >=1.19.5 - - scipy >=1.6.0 - - joblib >=1.2.0 - - threadpoolctl >=2.0.0 - - matplotlib >=3.3.4 ; extra == 'benchmark' - - pandas >=1.1.5 ; extra == 'benchmark' - - memory-profiler >=0.57.0 ; extra == 'benchmark' - - matplotlib >=3.3.4 ; extra == 'docs' - - scikit-image >=0.17.2 ; extra == 'docs' - - pandas >=1.1.5 ; extra == 'docs' - - seaborn >=0.9.0 ; extra == 'docs' - - memory-profiler >=0.57.0 ; extra == 'docs' - - sphinx >=6.0.0 ; extra == 'docs' - - sphinx-copybutton >=0.5.2 ; extra == 'docs' - - sphinx-gallery >=0.15.0 ; extra == 'docs' - - numpydoc >=1.2.0 ; extra == 'docs' - - pillow >=7.1.2 ; extra == 'docs' - - pooch >=1.6.0 ; extra == 'docs' - - sphinx-prompt >=1.3.0 ; extra == 'docs' - - sphinxext-opengraph >=0.4.2 ; extra == 'docs' - - plotly >=5.14.0 ; extra == 'docs' - - matplotlib >=3.3.4 ; extra == 'examples' - - scikit-image >=0.17.2 ; extra == 'examples' - - pandas >=1.1.5 ; extra == 'examples' - - seaborn >=0.9.0 ; extra == 'examples' - - pooch >=1.6.0 ; extra == 'examples' - - plotly >=5.14.0 ; extra == 'examples' - - matplotlib >=3.3.4 ; extra == 'tests' - - scikit-image >=0.17.2 ; extra == 'tests' - - pandas >=1.1.5 ; extra == 'tests' - - pytest >=7.1.2 ; extra == 'tests' - - pytest-cov >=2.9.0 ; extra == 'tests' - - ruff >=0.0.272 ; extra == 'tests' - - black >=23.3.0 ; extra == 'tests' - - mypy >=1.3 ; extra == 'tests' - - pyamg >=4.0.0 ; extra == 'tests' - - polars >=0.19.12 ; extra == 'tests' - - pyarrow >=12.0.0 ; extra == 'tests' - - numpydoc >=1.2.0 ; extra == 'tests' - - pooch >=1.6.0 ; extra == 'tests' + - numpy>=1.19.5 + - scipy>=1.6.0 + - joblib>=1.2.0 + - threadpoolctl>=2.0.0 + - matplotlib>=3.3.4 ; extra == 'benchmark' + - pandas>=1.1.5 ; extra == 'benchmark' + - memory-profiler>=0.57.0 ; extra == 'benchmark' + - matplotlib>=3.3.4 ; extra == 'docs' + - scikit-image>=0.17.2 ; extra == 'docs' + - pandas>=1.1.5 ; extra == 'docs' + - seaborn>=0.9.0 ; extra == 'docs' + - memory-profiler>=0.57.0 ; extra == 'docs' + - sphinx>=6.0.0 ; extra == 'docs' + - sphinx-copybutton>=0.5.2 ; extra == 'docs' + - sphinx-gallery>=0.15.0 ; extra == 'docs' + - numpydoc>=1.2.0 ; extra == 'docs' + - pillow>=7.1.2 ; extra == 'docs' + - pooch>=1.6.0 ; extra == 'docs' + - sphinx-prompt>=1.3.0 ; extra == 'docs' + - sphinxext-opengraph>=0.4.2 ; extra == 'docs' + - plotly>=5.14.0 ; extra == 'docs' + - matplotlib>=3.3.4 ; extra == 'examples' + - scikit-image>=0.17.2 ; extra == 'examples' + - pandas>=1.1.5 ; extra == 'examples' + - seaborn>=0.9.0 ; extra == 'examples' + - pooch>=1.6.0 ; extra == 'examples' + - plotly>=5.14.0 ; extra == 'examples' + - matplotlib>=3.3.4 ; extra == 'tests' + - scikit-image>=0.17.2 ; extra == 'tests' + - pandas>=1.1.5 ; extra == 'tests' + - pytest>=7.1.2 ; extra == 'tests' + - pytest-cov>=2.9.0 ; extra == 'tests' + - ruff>=0.0.272 ; extra == 'tests' + - black>=23.3.0 ; extra == 'tests' + - mypy>=1.3 ; extra == 'tests' + - pyamg>=4.0.0 ; extra == 'tests' + - polars>=0.19.12 ; extra == 'tests' + - pyarrow>=12.0.0 ; extra == 'tests' + - numpydoc>=1.2.0 ; extra == 'tests' + - pooch>=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/f2/30/1299e84d2ba3bc735baf17cebbf5b9d55144243c41b3ec6559ce3cf61e23/scikit_learn-1.4.2-cp311-cp311-macosx_12_0_arm64.whl - sha256: 1d0b25d9c651fd050555aadd57431b53d4cf664e749069da77f3d52c5ad14b3b + url: https://files.pythonhosted.org/packages/59/11/63de36e6933b03490fdfe5cbc9b5a68870a1281d8e705a23b33076dc82fb/scikit_learn-1.4.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 45dee87ac5309bb82e3ea633955030df9bbcb8d2cdb30383c6cd483691c546cc requires_dist: - - numpy >=1.19.5 - - scipy >=1.6.0 - - joblib >=1.2.0 - - threadpoolctl >=2.0.0 - - matplotlib >=3.3.4 ; extra == 'benchmark' - - pandas >=1.1.5 ; extra == 'benchmark' - - memory-profiler >=0.57.0 ; extra == 'benchmark' - - matplotlib >=3.3.4 ; extra == 'docs' - - scikit-image >=0.17.2 ; extra == 'docs' - - pandas >=1.1.5 ; extra == 'docs' - - seaborn >=0.9.0 ; extra == 'docs' - - memory-profiler >=0.57.0 ; extra == 'docs' - - sphinx >=6.0.0 ; extra == 'docs' - - sphinx-copybutton >=0.5.2 ; extra == 'docs' - - sphinx-gallery >=0.15.0 ; extra == 'docs' - - numpydoc >=1.2.0 ; extra == 'docs' - - pillow >=7.1.2 ; extra == 'docs' - - pooch >=1.6.0 ; extra == 'docs' - - sphinx-prompt >=1.3.0 ; extra == 'docs' - - sphinxext-opengraph >=0.4.2 ; extra == 'docs' - - plotly >=5.14.0 ; extra == 'docs' - - matplotlib >=3.3.4 ; extra == 'examples' - - scikit-image >=0.17.2 ; extra == 'examples' - - pandas >=1.1.5 ; extra == 'examples' - - seaborn >=0.9.0 ; extra == 'examples' - - pooch >=1.6.0 ; extra == 'examples' - - plotly >=5.14.0 ; extra == 'examples' - - matplotlib >=3.3.4 ; extra == 'tests' - - scikit-image >=0.17.2 ; extra == 'tests' - - pandas >=1.1.5 ; extra == 'tests' - - pytest >=7.1.2 ; extra == 'tests' - - pytest-cov >=2.9.0 ; extra == 'tests' - - ruff >=0.0.272 ; extra == 'tests' - - black >=23.3.0 ; extra == 'tests' - - mypy >=1.3 ; extra == 'tests' - - pyamg >=4.0.0 ; extra == 'tests' - - polars >=0.19.12 ; extra == 'tests' - - pyarrow >=12.0.0 ; extra == 'tests' - - numpydoc >=1.2.0 ; extra == 'tests' - - pooch >=1.6.0 ; extra == 'tests' + - numpy>=1.19.5 + - scipy>=1.6.0 + - joblib>=1.2.0 + - threadpoolctl>=2.0.0 + - matplotlib>=3.3.4 ; extra == 'benchmark' + - pandas>=1.1.5 ; extra == 'benchmark' + - memory-profiler>=0.57.0 ; extra == 'benchmark' + - matplotlib>=3.3.4 ; extra == 'docs' + - scikit-image>=0.17.2 ; extra == 'docs' + - pandas>=1.1.5 ; extra == 'docs' + - seaborn>=0.9.0 ; extra == 'docs' + - memory-profiler>=0.57.0 ; extra == 'docs' + - sphinx>=6.0.0 ; extra == 'docs' + - sphinx-copybutton>=0.5.2 ; extra == 'docs' + - sphinx-gallery>=0.15.0 ; extra == 'docs' + - numpydoc>=1.2.0 ; extra == 'docs' + - pillow>=7.1.2 ; extra == 'docs' + - pooch>=1.6.0 ; extra == 'docs' + - sphinx-prompt>=1.3.0 ; extra == 'docs' + - sphinxext-opengraph>=0.4.2 ; extra == 'docs' + - plotly>=5.14.0 ; extra == 'docs' + - matplotlib>=3.3.4 ; extra == 'examples' + - scikit-image>=0.17.2 ; extra == 'examples' + - pandas>=1.1.5 ; extra == 'examples' + - seaborn>=0.9.0 ; extra == 'examples' + - pooch>=1.6.0 ; extra == 'examples' + - plotly>=5.14.0 ; extra == 'examples' + - matplotlib>=3.3.4 ; extra == 'tests' + - scikit-image>=0.17.2 ; extra == 'tests' + - pandas>=1.1.5 ; extra == 'tests' + - pytest>=7.1.2 ; extra == 'tests' + - pytest-cov>=2.9.0 ; extra == 'tests' + - ruff>=0.0.272 ; extra == 'tests' + - black>=23.3.0 ; extra == 'tests' + - mypy>=1.3 ; extra == 'tests' + - pyamg>=4.0.0 ; extra == 'tests' + - polars>=0.19.12 ; extra == 'tests' + - pyarrow>=12.0.0 ; extra == 'tests' + - numpydoc>=1.2.0 ; extra == 'tests' + - pooch>=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/4e/53/14405a47292b59235d811a2af8634aba188ccfd1a38ef4b8042f3447d79a/scikit_learn-1.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 44c62f2b124848a28fd695db5bc4da019287abf390bfce602ddc8aa1ec186aae + url: https://files.pythonhosted.org/packages/79/3d/02d5d3ed359498fec3abdf65407d3c07e3b8765af17464969055aaec5171/scikit_learn-1.4.2-cp311-cp311-win_amd64.whl + sha256: 5cd7b524115499b18b63f0c96f4224eb885564937a0b3477531b2b63ce331904 requires_dist: - - numpy >=1.19.5 - - scipy >=1.6.0 - - joblib >=1.2.0 - - threadpoolctl >=2.0.0 - - matplotlib >=3.3.4 ; extra == 'benchmark' - - pandas >=1.1.5 ; extra == 'benchmark' - - memory-profiler >=0.57.0 ; extra == 'benchmark' - - matplotlib >=3.3.4 ; extra == 'docs' - - scikit-image >=0.17.2 ; extra == 'docs' - - pandas >=1.1.5 ; extra == 'docs' - - seaborn >=0.9.0 ; extra == 'docs' - - memory-profiler >=0.57.0 ; extra == 'docs' - - sphinx >=6.0.0 ; extra == 'docs' - - sphinx-copybutton >=0.5.2 ; extra == 'docs' - - sphinx-gallery >=0.15.0 ; extra == 'docs' - - numpydoc >=1.2.0 ; extra == 'docs' - - pillow >=7.1.2 ; extra == 'docs' - - pooch >=1.6.0 ; extra == 'docs' - - sphinx-prompt >=1.3.0 ; extra == 'docs' - - sphinxext-opengraph >=0.4.2 ; extra == 'docs' - - plotly >=5.14.0 ; extra == 'docs' - - matplotlib >=3.3.4 ; extra == 'examples' - - scikit-image >=0.17.2 ; extra == 'examples' - - pandas >=1.1.5 ; extra == 'examples' - - seaborn >=0.9.0 ; extra == 'examples' - - pooch >=1.6.0 ; extra == 'examples' - - plotly >=5.14.0 ; extra == 'examples' - - matplotlib >=3.3.4 ; extra == 'tests' - - scikit-image >=0.17.2 ; extra == 'tests' - - pandas >=1.1.5 ; extra == 'tests' - - pytest >=7.1.2 ; extra == 'tests' - - pytest-cov >=2.9.0 ; extra == 'tests' - - ruff >=0.0.272 ; extra == 'tests' - - black >=23.3.0 ; extra == 'tests' - - mypy >=1.3 ; extra == 'tests' - - pyamg >=4.0.0 ; extra == 'tests' - - polars >=0.19.12 ; extra == 'tests' - - pyarrow >=12.0.0 ; extra == 'tests' - - numpydoc >=1.2.0 ; extra == 'tests' - - pooch >=1.6.0 ; extra == 'tests' + - numpy>=1.19.5 + - scipy>=1.6.0 + - joblib>=1.2.0 + - threadpoolctl>=2.0.0 + - matplotlib>=3.3.4 ; extra == 'benchmark' + - pandas>=1.1.5 ; extra == 'benchmark' + - memory-profiler>=0.57.0 ; extra == 'benchmark' + - matplotlib>=3.3.4 ; extra == 'docs' + - scikit-image>=0.17.2 ; extra == 'docs' + - pandas>=1.1.5 ; extra == 'docs' + - seaborn>=0.9.0 ; extra == 'docs' + - memory-profiler>=0.57.0 ; extra == 'docs' + - sphinx>=6.0.0 ; extra == 'docs' + - sphinx-copybutton>=0.5.2 ; extra == 'docs' + - sphinx-gallery>=0.15.0 ; extra == 'docs' + - numpydoc>=1.2.0 ; extra == 'docs' + - pillow>=7.1.2 ; extra == 'docs' + - pooch>=1.6.0 ; extra == 'docs' + - sphinx-prompt>=1.3.0 ; extra == 'docs' + - sphinxext-opengraph>=0.4.2 ; extra == 'docs' + - plotly>=5.14.0 ; extra == 'docs' + - matplotlib>=3.3.4 ; extra == 'examples' + - scikit-image>=0.17.2 ; extra == 'examples' + - pandas>=1.1.5 ; extra == 'examples' + - seaborn>=0.9.0 ; extra == 'examples' + - pooch>=1.6.0 ; extra == 'examples' + - plotly>=5.14.0 ; extra == 'examples' + - matplotlib>=3.3.4 ; extra == 'tests' + - scikit-image>=0.17.2 ; extra == 'tests' + - pandas>=1.1.5 ; extra == 'tests' + - pytest>=7.1.2 ; extra == 'tests' + - pytest-cov>=2.9.0 ; extra == 'tests' + - ruff>=0.0.272 ; extra == 'tests' + - black>=23.3.0 ; extra == 'tests' + - mypy>=1.3 ; extra == 'tests' + - pyamg>=4.0.0 ; extra == 'tests' + - polars>=0.19.12 ; extra == 'tests' + - pyarrow>=12.0.0 ; extra == 'tests' + - numpydoc>=1.2.0 ; extra == 'tests' + - pooch>=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scikit-learn version: 1.4.2 - url: https://files.pythonhosted.org/packages/79/3d/02d5d3ed359498fec3abdf65407d3c07e3b8765af17464969055aaec5171/scikit_learn-1.4.2-cp311-cp311-win_amd64.whl - sha256: 5cd7b524115499b18b63f0c96f4224eb885564937a0b3477531b2b63ce331904 + url: https://files.pythonhosted.org/packages/f2/30/1299e84d2ba3bc735baf17cebbf5b9d55144243c41b3ec6559ce3cf61e23/scikit_learn-1.4.2-cp311-cp311-macosx_12_0_arm64.whl + sha256: 1d0b25d9c651fd050555aadd57431b53d4cf664e749069da77f3d52c5ad14b3b requires_dist: - - numpy >=1.19.5 - - scipy >=1.6.0 - - joblib >=1.2.0 - - threadpoolctl >=2.0.0 - - matplotlib >=3.3.4 ; extra == 'benchmark' - - pandas >=1.1.5 ; extra == 'benchmark' - - memory-profiler >=0.57.0 ; extra == 'benchmark' - - matplotlib >=3.3.4 ; extra == 'docs' - - scikit-image >=0.17.2 ; extra == 'docs' - - pandas >=1.1.5 ; extra == 'docs' - - seaborn >=0.9.0 ; extra == 'docs' - - memory-profiler >=0.57.0 ; extra == 'docs' - - sphinx >=6.0.0 ; extra == 'docs' - - sphinx-copybutton >=0.5.2 ; extra == 'docs' - - sphinx-gallery >=0.15.0 ; extra == 'docs' - - numpydoc >=1.2.0 ; extra == 'docs' - - pillow >=7.1.2 ; extra == 'docs' - - pooch >=1.6.0 ; extra == 'docs' - - sphinx-prompt >=1.3.0 ; extra == 'docs' - - sphinxext-opengraph >=0.4.2 ; extra == 'docs' - - plotly >=5.14.0 ; extra == 'docs' - - matplotlib >=3.3.4 ; extra == 'examples' - - scikit-image >=0.17.2 ; extra == 'examples' - - pandas >=1.1.5 ; extra == 'examples' - - seaborn >=0.9.0 ; extra == 'examples' - - pooch >=1.6.0 ; extra == 'examples' - - plotly >=5.14.0 ; extra == 'examples' - - matplotlib >=3.3.4 ; extra == 'tests' - - scikit-image >=0.17.2 ; extra == 'tests' - - pandas >=1.1.5 ; extra == 'tests' - - pytest >=7.1.2 ; extra == 'tests' - - pytest-cov >=2.9.0 ; extra == 'tests' - - ruff >=0.0.272 ; extra == 'tests' - - black >=23.3.0 ; extra == 'tests' - - mypy >=1.3 ; extra == 'tests' - - pyamg >=4.0.0 ; extra == 'tests' - - polars >=0.19.12 ; extra == 'tests' - - pyarrow >=12.0.0 ; extra == 'tests' - - numpydoc >=1.2.0 ; extra == 'tests' - - pooch >=1.6.0 ; extra == 'tests' + - numpy>=1.19.5 + - scipy>=1.6.0 + - joblib>=1.2.0 + - threadpoolctl>=2.0.0 + - matplotlib>=3.3.4 ; extra == 'benchmark' + - pandas>=1.1.5 ; extra == 'benchmark' + - memory-profiler>=0.57.0 ; extra == 'benchmark' + - matplotlib>=3.3.4 ; extra == 'docs' + - scikit-image>=0.17.2 ; extra == 'docs' + - pandas>=1.1.5 ; extra == 'docs' + - seaborn>=0.9.0 ; extra == 'docs' + - memory-profiler>=0.57.0 ; extra == 'docs' + - sphinx>=6.0.0 ; extra == 'docs' + - sphinx-copybutton>=0.5.2 ; extra == 'docs' + - sphinx-gallery>=0.15.0 ; extra == 'docs' + - numpydoc>=1.2.0 ; extra == 'docs' + - pillow>=7.1.2 ; extra == 'docs' + - pooch>=1.6.0 ; extra == 'docs' + - sphinx-prompt>=1.3.0 ; extra == 'docs' + - sphinxext-opengraph>=0.4.2 ; extra == 'docs' + - plotly>=5.14.0 ; extra == 'docs' + - matplotlib>=3.3.4 ; extra == 'examples' + - scikit-image>=0.17.2 ; extra == 'examples' + - pandas>=1.1.5 ; extra == 'examples' + - seaborn>=0.9.0 ; extra == 'examples' + - pooch>=1.6.0 ; extra == 'examples' + - plotly>=5.14.0 ; extra == 'examples' + - matplotlib>=3.3.4 ; extra == 'tests' + - scikit-image>=0.17.2 ; extra == 'tests' + - pandas>=1.1.5 ; extra == 'tests' + - pytest>=7.1.2 ; extra == 'tests' + - pytest-cov>=2.9.0 ; extra == 'tests' + - ruff>=0.0.272 ; extra == 'tests' + - black>=23.3.0 ; extra == 'tests' + - mypy>=1.3 ; extra == 'tests' + - pyamg>=4.0.0 ; extra == 'tests' + - polars>=0.19.12 ; extra == 'tests' + - pyarrow>=12.0.0 ; extra == 'tests' + - numpydoc>=1.2.0 ; extra == 'tests' + - pooch>=1.6.0 ; extra == 'tests' requires_python: '>=3.9' - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/be/e3/236639c51636ec7e678f2aa608fe89acb9d02ef64e1fe1d8eb40373bc62b/scipy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 0fbcf8abaf5aa2dc8d6400566c1a727aed338b5fe880cde64907596a89d576fa + url: https://files.pythonhosted.org/packages/e8/fb/e5955e2ddbdf2baee461eb53ec8d0adedd20a6dfc5510ef8d5e7e44ba461/scipy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 9ff7dad5d24a8045d836671e082a490848e8639cabb3dbdacb29f943a678683d requires_dist: - - numpy <2.3, >=1.22.4 + - numpy<2.3,>=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25915,35 +25561,35 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis >=6.30 ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx >=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' - - sphinx-design >=0.4.0 ; extra == 'doc' - - matplotlib >=3.5 ; extra == 'doc' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint >=0.12.2 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit >=0.36.0 ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/51/b6/188c8974d747b2998d672040c5b62a635a72240c515dc4577a28e1dedc80/scipy-1.13.0-cp311-cp311-macosx_12_0_arm64.whl - sha256: 5e4a756355522eb60fcd61f8372ac2549073c8788f6114449b37e9e8104f15a5 + url: https://files.pythonhosted.org/packages/be/e3/236639c51636ec7e678f2aa608fe89acb9d02ef64e1fe1d8eb40373bc62b/scipy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 0fbcf8abaf5aa2dc8d6400566c1a727aed338b5fe880cde64907596a89d576fa requires_dist: - - numpy <2.3, >=1.22.4 + - numpy<2.3,>=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25954,35 +25600,35 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis >=6.30 ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx >=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' - - sphinx-design >=0.4.0 ; extra == 'doc' - - matplotlib >=3.5 ; extra == 'doc' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint >=0.12.2 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit >=0.36.0 ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/e8/fb/e5955e2ddbdf2baee461eb53ec8d0adedd20a6dfc5510ef8d5e7e44ba461/scipy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 9ff7dad5d24a8045d836671e082a490848e8639cabb3dbdacb29f943a678683d + url: https://files.pythonhosted.org/packages/d4/a1/d4adf25b6d2bef8d0ad1682829dcfcba97f3f96bb5b6f137bc3e41003cc7/scipy-1.13.0-cp311-cp311-win_amd64.whl + sha256: a2f471de4d01200718b2b8927f7d76b5d9bde18047ea0fa8bd15c5ba3f26a1d6 requires_dist: - - numpy <2.3, >=1.22.4 + - numpy<2.3,>=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -25993,35 +25639,35 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis >=6.30 ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx >=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' - - sphinx-design >=0.4.0 ; extra == 'doc' - - matplotlib >=3.5 ; extra == 'doc' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint >=0.12.2 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit >=0.36.0 ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi name: scipy version: 1.13.0 - url: https://files.pythonhosted.org/packages/d4/a1/d4adf25b6d2bef8d0ad1682829dcfcba97f3f96bb5b6f137bc3e41003cc7/scipy-1.13.0-cp311-cp311-win_amd64.whl - sha256: a2f471de4d01200718b2b8927f7d76b5d9bde18047ea0fa8bd15c5ba3f26a1d6 + url: https://files.pythonhosted.org/packages/51/b6/188c8974d747b2998d672040c5b62a635a72240c515dc4577a28e1dedc80/scipy-1.13.0-cp311-cp311-macosx_12_0_arm64.whl + sha256: 5e4a756355522eb60fcd61f8372ac2549073c8788f6114449b37e9e8104f15a5 requires_dist: - - numpy <2.3, >=1.22.4 + - numpy<2.3,>=1.22.4 - pytest ; extra == 'test' - pytest-cov ; extra == 'test' - pytest-timeout ; extra == 'test' @@ -26032,26 +25678,26 @@ packages: - threadpoolctl ; extra == 'test' - scikit-umfpack ; extra == 'test' - pooch ; extra == 'test' - - hypothesis >=6.30 ; extra == 'test' + - hypothesis>=6.30 ; extra == 'test' - array-api-strict ; extra == 'test' - - sphinx >=5.0.0 ; extra == 'doc' - - pydata-sphinx-theme >=0.15.2 ; extra == 'doc' - - sphinx-design >=0.4.0 ; extra == 'doc' - - matplotlib >=3.5 ; extra == 'doc' + - sphinx>=5.0.0 ; extra == 'doc' + - pydata-sphinx-theme>=0.15.2 ; extra == 'doc' + - sphinx-design>=0.4.0 ; extra == 'doc' + - matplotlib>=3.5 ; extra == 'doc' - numpydoc ; extra == 'doc' - jupytext ; extra == 'doc' - myst-nb ; extra == 'doc' - pooch ; extra == 'doc' - - jupyterlite-sphinx >=0.12.0 ; extra == 'doc' + - jupyterlite-sphinx>=0.12.0 ; extra == 'doc' - jupyterlite-pyodide-kernel ; extra == 'doc' - mypy ; extra == 'dev' - typing-extensions ; extra == 'dev' - types-psutil ; extra == 'dev' - pycodestyle ; extra == 'dev' - ruff ; extra == 'dev' - - cython-lint >=0.12.2 ; extra == 'dev' + - cython-lint>=0.12.2 ; extra == 'dev' - rich-click ; extra == 'dev' - - doit >=0.36.0 ; extra == 'dev' + - doit>=0.36.0 ; extra == 'dev' - pydevtool ; extra == 'dev' requires_python: '>=3.9' - kind: pypi @@ -26074,12 +25720,12 @@ packages: path: examples/python/segment_anything_model sha256: 85bc241bedf212c63a39d0251a9dcc0fb3a435087a024d4eafd7f49342a75926 requires_dist: + - segment-anything @ git+https://github.com/facebookresearch/segment-anything.git - numpy - opencv-python - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - - segment-anything @ git+https://github.com/facebookresearch/segment-anything.git - - torch ==2.2.2 + - torch==2.2.2 - torchvision - tqdm editable: true @@ -26158,11 +25804,11 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/93/fd/b205661ed60294a344406fb04227042fcede9501e81ee1e7018e9159455a/shapely-2.0.4-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7 + url: https://files.pythonhosted.org/packages/d5/fb/bcf6a8164ed307c99f1a8fabe5acd86ac99a33f52530a3ca84b0936f95bd/shapely-2.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 4310b5494271e18580d61022c0857eb85d30510d88606fa3b8314790df7f367d requires_dist: - - numpy <3, >=1.14 - - numpydoc ==1.1.* ; extra == 'docs' + - numpy<3,>=1.14 + - numpydoc==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26173,11 +25819,11 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/2a/fb/e3f72b10a90e26bb1a92a38b3f30f3074ebac6d532f87848ac09c3e8a73b/shapely-2.0.4-cp311-cp311-macosx_11_0_arm64.whl - sha256: 58b0ecc505bbe49a99551eea3f2e8a9b3b24b3edd2a4de1ac0dc17bc75c9ec07 + url: https://files.pythonhosted.org/packages/93/fd/b205661ed60294a344406fb04227042fcede9501e81ee1e7018e9159455a/shapely-2.0.4-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 7d56ce3e2a6a556b59a288771cf9d091470116867e578bebced8bfc4147fbfd7 requires_dist: - - numpy <3, >=1.14 - - numpydoc ==1.1.* ; extra == 'docs' + - numpy<3,>=1.14 + - numpydoc==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26188,11 +25834,11 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/d5/fb/bcf6a8164ed307c99f1a8fabe5acd86ac99a33f52530a3ca84b0936f95bd/shapely-2.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 4310b5494271e18580d61022c0857eb85d30510d88606fa3b8314790df7f367d + url: https://files.pythonhosted.org/packages/6a/5c/3330f499ca860f0b92db4ceaebd7090096a83c1ea3ae7d8d4c6111761b82/shapely-2.0.4-cp311-cp311-win_amd64.whl + sha256: c52ed79f683f721b69a10fb9e3d940a468203f5054927215586c5d49a072de8d requires_dist: - - numpy <3, >=1.14 - - numpydoc ==1.1.* ; extra == 'docs' + - numpy<3,>=1.14 + - numpydoc==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26203,11 +25849,11 @@ packages: - kind: pypi name: shapely version: 2.0.4 - url: https://files.pythonhosted.org/packages/6a/5c/3330f499ca860f0b92db4ceaebd7090096a83c1ea3ae7d8d4c6111761b82/shapely-2.0.4-cp311-cp311-win_amd64.whl - sha256: c52ed79f683f721b69a10fb9e3d940a468203f5054927215586c5d49a072de8d + url: https://files.pythonhosted.org/packages/2a/fb/e3f72b10a90e26bb1a92a38b3f30f3074ebac6d532f87848ac09c3e8a73b/shapely-2.0.4-cp311-cp311-macosx_11_0_arm64.whl + sha256: 58b0ecc505bbe49a99551eea3f2e8a9b3b24b3edd2a4de1ac0dc17bc75c9ec07 requires_dist: - - numpy <3, >=1.14 - - numpydoc ==1.1.* ; extra == 'docs' + - numpy<3,>=1.14 + - numpydoc==1.1.* ; extra == 'docs' - matplotlib ; extra == 'docs' - sphinx ; extra == 'docs' - sphinx-book-theme ; extra == 'docs' @@ -26231,10 +25877,10 @@ packages: requires_dist: - mesh-to-sdf @ git+https://github.com/marian42/mesh_to_sdf.git - numpy - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - - scikit-learn >=1.1.3 - - trimesh ==3.15.2 + - scikit-learn>=1.1.3 + - trimesh==3.15.2 editable: true - kind: conda name: sigtool @@ -26445,19 +26091,19 @@ packages: - kind: pypi name: sounddevice version: 0.4.6 - url: https://files.pythonhosted.org/packages/24/5a/c0b9066fcaf783054b3f35254938dcba2d8cf02576ebdc56b6b4e85661f2/sounddevice-0.4.6-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl - sha256: 8b0b806c205dd3e3cd5a97262b2482624fd21db7d47083b887090148a08051c8 + url: https://files.pythonhosted.org/packages/d7/d5/f0a0aba169f23657c7af3f0c878db7413a9a3b113026fc759862a697c611/sounddevice-0.4.6-py3-none-any.whl + sha256: 5de768ba6fe56ad2b5aaa2eea794b76b73e427961c95acad2ee2ed7f866a4b20 requires_dist: - - cffi >=1.0 + - cffi>=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi name: sounddevice version: 0.4.6 - url: https://files.pythonhosted.org/packages/d7/d5/f0a0aba169f23657c7af3f0c878db7413a9a3b113026fc759862a697c611/sounddevice-0.4.6-py3-none-any.whl - sha256: 5de768ba6fe56ad2b5aaa2eea794b76b73e427961c95acad2ee2ed7f866a4b20 + url: https://files.pythonhosted.org/packages/24/5a/c0b9066fcaf783054b3f35254938dcba2d8cf02576ebdc56b6b4e85661f2/sounddevice-0.4.6-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl + sha256: 8b0b806c205dd3e3cd5a97262b2482624fd21db7d47083b887090148a08051c8 requires_dist: - - cffi >=1.0 + - cffi>=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi @@ -26466,7 +26112,7 @@ packages: url: https://files.pythonhosted.org/packages/39/ae/5e84220bfca4256e4ca2a62a174636089ab6ff671b5f9ddd7e8238587acd/sounddevice-0.4.6-py3-none-win_amd64.whl sha256: 7830d4f8f8570f2e5552942f81d96999c5fcd9a0b682d6fc5d5c5529df23be2c requires_dist: - - cffi >=1.0 + - cffi>=1.0 - numpy ; extra == 'numpy' requires_python: '>=3.7' - kind: pypi @@ -26494,9 +26140,9 @@ packages: path: examples/python/structure_from_motion sha256: b20b79aa7bb2b4225b37d3cb28872a70dc7e9ab2ca9ab138b90d60fc8d7b4c15 requires_dist: + - opencv-python>4.6 - numpy - - opencv-python >4.6 - - requests <3, >=2.31 + - requests>=2.31,<3 - rerun-sdk - tqdm editable: true @@ -26506,7 +26152,7 @@ packages: url: https://files.pythonhosted.org/packages/d2/05/e6600db80270777c4a64238a98d442f0fd07cc8915be2a1c16da7f2b9e74/sympy-1.12-py3-none-any.whl sha256: c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5 requires_dist: - - mpmath >=0.19 + - mpmath>=0.19 requires_python: '>=3.8' - kind: conda name: sysroot_linux-64 @@ -26686,9 +26332,9 @@ packages: timestamp: 1706164225098 - kind: pypi name: threadpoolctl - version: 3.4.0 - url: https://files.pythonhosted.org/packages/1e/84/ccd9b08653022b7785b6e3ee070ffb2825841e0dc119be22f0840b2b35cb/threadpoolctl-3.4.0-py3-none-any.whl - sha256: 8f4c689a65b23e5ed825c8436a92b818aac005e0f3715f6a1664d7c7ee29d262 + version: 3.5.0 + url: https://files.pythonhosted.org/packages/4b/2c/ffbf7a134b9ab11a67b0cf0726453cedd9c5043a4fe7a35d1cefa9a1bcfb/threadpoolctl-3.5.0-py3-none-any.whl + sha256: 56c1e26c150397e58c4926da8eeee87533b1e32bef131bd4bf6a2f45f3185467 requires_python: '>=3.8' - kind: pypi name: tifffile @@ -26697,7 +26343,7 @@ packages: sha256: 8d0b982f4b01ace358835ae6c2beb5a70cb7287f5d3a2e96c318bd5befa97b1f requires_dist: - numpy - - imagecodecs >=2023.8.12 ; extra == 'all' + - imagecodecs>=2023.8.12 ; extra == 'all' - matplotlib ; extra == 'all' - defusedxml ; extra == 'all' - lxml ; extra == 'all' @@ -26710,7 +26356,7 @@ packages: url: https://files.pythonhosted.org/packages/76/aa/4b54f6047c442883243f68f6f9e3a0ab77aaae4b3e6e51a98b371e73dd77/timm-0.9.11-py3-none-any.whl sha256: 02bba56786633ff46b55ee0ce3b991fa85375556844e500ad18e6b12921dc3da requires_dist: - - torch >=1.7 + - torch>=1.7 - torchvision - pyyaml - huggingface-hub @@ -26864,15 +26510,15 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 + url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa requires_dist: - - huggingface-hub >=0.16.4, <1.0 + - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black ==22.3 ; extra == 'testing' + - black==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26882,15 +26528,15 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 + url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 requires_dist: - - huggingface-hub >=0.16.4, <1.0 + - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black ==22.3 ; extra == 'testing' + - black==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26900,15 +26546,15 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa + url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl + sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 requires_dist: - - huggingface-hub >=0.16.4, <1.0 + - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black ==22.3 ; extra == 'testing' + - black==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26918,15 +26564,15 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl - sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 + url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 requires_dist: - - huggingface-hub >=0.16.4, <1.0 + - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' - requests ; extra == 'testing' - numpy ; extra == 'testing' - datasets ; extra == 'testing' - - black ==22.3 ; extra == 'testing' + - black==22.3 ; extra == 'testing' - ruff ; extra == 'testing' - sphinx ; extra == 'docs' - sphinx-rtd-theme ; extra == 'docs' @@ -26974,56 +26620,56 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl - sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch @@ -27032,25 +26678,25 @@ packages: sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch @@ -27059,95 +26705,95 @@ packages: sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf requires_dist: - filelock - - typing-extensions >=4.8.0 + - typing-extensions>=4.8.0 - sympy - networkx - jinja2 - fsspec - - nvidia-cuda-nvrtc-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-runtime-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cuda-cupti-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cudnn-cu12 ==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cublas-cu12 ==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cufft-cu12 ==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-curand-cu12 ==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusolver-cu12 ==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-cusparse-cu12 ==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nccl-cu12 ==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - nvidia-nvtx-cu12 ==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' - - triton ==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' - - opt-einsum >=3.3 ; extra == 'opt-einsum' - - optree >=0.9.1 ; extra == 'optree' + - nvidia-cuda-nvrtc-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-runtime-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cuda-cupti-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cudnn-cu12==8.9.2.26 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cublas-cu12==12.1.3.1 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cufft-cu12==11.0.2.54 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-curand-cu12==10.3.2.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusolver-cu12==11.4.5.107 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-cusparse-cu12==12.1.0.106 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nccl-cu12==2.19.3 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - nvidia-nvtx-cu12==12.1.105 ; platform_system == 'Linux' and platform_machine == 'x86_64' + - triton==2.2.0 ; platform_system == 'Linux' and platform_machine == 'x86_64' and python_version < '3.12' + - opt-einsum>=3.3 ; extra == 'opt-einsum' + - optree>=0.9.1 ; extra == 'optree' requires_python: '>=3.8.0' - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl - sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 + url: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl + sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 requires_dist: - numpy - - torch ==2.2.2 - - pillow !=8.3.*, >=5.3.0 + - torch==2.2.2 + - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d + url: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl + sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 requires_dist: - numpy - - torch ==2.2.2 - - pillow !=8.3.*, >=5.3.0 + - torch==2.2.2 + - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl - sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 + url: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl + sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 requires_dist: - numpy - - torch ==2.2.2 - - pillow !=8.3.*, >=5.3.0 + - torch==2.2.2 + - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl - sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 + url: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d requires_dist: - numpy - - torch ==2.2.2 - - pillow !=8.3.*, >=5.3.0 + - torch==2.2.2 + - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' - kind: pypi @@ -27157,11 +26803,11 @@ packages: sha256: 1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9 requires_dist: - colorama ; platform_system == 'Windows' - - pytest >=6 ; extra == 'dev' + - pytest>=6 ; extra == 'dev' - pytest-cov ; extra == 'dev' - pytest-timeout ; extra == 'dev' - pytest-xdist ; extra == 'dev' - - ipywidgets >=6 ; extra == 'notebook' + - ipywidgets>=6 ; extra == 'notebook' - slack-sdk ; extra == 'slack' - requests ; extra == 'telegram' requires_python: '>=3.7' @@ -27189,308 +26835,308 @@ packages: sha256: 9d5ee0c8142a60501faf9e49a0b42f8e9cb8611823bce4f195a9325a6816337e requires_dist: - filelock - - huggingface-hub <1.0, >=0.19.3 - - numpy >=1.17 - - packaging >=20.0 - - pyyaml >=5.1 - - regex !=2019.12.17 + - huggingface-hub<1.0,>=0.19.3 + - numpy>=1.17 + - packaging>=20.0 + - pyyaml>=5.1 + - regex!=2019.12.17 - requests - - tokenizers <0.20, >=0.19 - - safetensors >=0.4.1 - - tqdm >=4.27 - - accelerate >=0.21.0 ; extra == 'accelerate' + - tokenizers<0.20,>=0.19 + - safetensors>=0.4.1 + - tqdm>=4.27 + - accelerate>=0.21.0 ; extra == 'accelerate' - diffusers ; extra == 'agents' - - accelerate >=0.21.0 ; extra == 'agents' - - datasets !=2.5.0 ; extra == 'agents' + - accelerate>=0.21.0 ; extra == 'agents' + - datasets!=2.5.0 ; extra == 'agents' - torch ; extra == 'agents' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'agents' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'agents' - opencv-python ; extra == 'agents' - - pillow <=15.0, >=10.0.1 ; extra == 'agents' - - tensorflow <2.16, >=2.6 ; extra == 'all' + - pillow<=15.0,>=10.0.1 ; extra == 'agents' + - tensorflow<2.16,>=2.6 ; extra == 'all' - onnxconverter-common ; extra == 'all' - tf2onnx ; extra == 'all' - - tensorflow-text <2.16 ; extra == 'all' - - keras-nlp >=0.3.1 ; extra == 'all' + - tensorflow-text<2.16 ; extra == 'all' + - keras-nlp>=0.3.1 ; extra == 'all' - torch ; extra == 'all' - - accelerate >=0.21.0 ; extra == 'all' - - jax <=0.4.13, >=0.4.1 ; extra == 'all' - - jaxlib <=0.4.13, >=0.4.1 ; extra == 'all' - - flax <=0.7.0, >=0.4.1 ; extra == 'all' - - optax <=0.1.4, >=0.0.8 ; extra == 'all' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'all' + - accelerate>=0.21.0 ; extra == 'all' + - jax<=0.4.13,>=0.4.1 ; extra == 'all' + - jaxlib<=0.4.13,>=0.4.1 ; extra == 'all' + - flax<=0.7.0,>=0.4.1 ; extra == 'all' + - optax<=0.1.4,>=0.0.8 ; extra == 'all' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'all' - protobuf ; extra == 'all' - - tokenizers <0.20, >=0.19 ; extra == 'all' + - tokenizers<0.20,>=0.19 ; extra == 'all' - torchaudio ; extra == 'all' - librosa ; extra == 'all' - - pyctcdecode >=0.4.0 ; extra == 'all' + - pyctcdecode>=0.4.0 ; extra == 'all' - phonemizer ; extra == 'all' - kenlm ; extra == 'all' - - pillow <=15.0, >=10.0.1 ; extra == 'all' + - pillow<=15.0,>=10.0.1 ; extra == 'all' - optuna ; extra == 'all' - - ray[tune] >=2.7.0 ; extra == 'all' + - ray[tune]>=2.7.0 ; extra == 'all' - sigopt ; extra == 'all' - timm ; extra == 'all' - torchvision ; extra == 'all' - - codecarbon ==1.2.0 ; extra == 'all' - - decord ==0.6.0 ; extra == 'all' - - av ==9.2.0 ; extra == 'all' + - codecarbon==1.2.0 ; extra == 'all' + - decord==0.6.0 ; extra == 'all' + - av==9.2.0 ; extra == 'all' - librosa ; extra == 'audio' - - pyctcdecode >=0.4.0 ; extra == 'audio' + - pyctcdecode>=0.4.0 ; extra == 'audio' - phonemizer ; extra == 'audio' - kenlm ; extra == 'audio' - - codecarbon ==1.2.0 ; extra == 'codecarbon' - - deepspeed >=0.9.3 ; extra == 'deepspeed' - - accelerate >=0.21.0 ; extra == 'deepspeed' - - deepspeed >=0.9.3 ; extra == 'deepspeed-testing' - - accelerate >=0.21.0 ; extra == 'deepspeed-testing' - - pytest <8.0.0, >=7.2.0 ; extra == 'deepspeed-testing' + - codecarbon==1.2.0 ; extra == 'codecarbon' + - deepspeed>=0.9.3 ; extra == 'deepspeed' + - accelerate>=0.21.0 ; extra == 'deepspeed' + - deepspeed>=0.9.3 ; extra == 'deepspeed-testing' + - accelerate>=0.21.0 ; extra == 'deepspeed-testing' + - pytest<8.0.0,>=7.2.0 ; extra == 'deepspeed-testing' - pytest-xdist ; extra == 'deepspeed-testing' - timeout-decorator ; extra == 'deepspeed-testing' - parameterized ; extra == 'deepspeed-testing' - psutil ; extra == 'deepspeed-testing' - - datasets !=2.5.0 ; extra == 'deepspeed-testing' - - dill <0.3.5 ; extra == 'deepspeed-testing' - - evaluate >=0.2.0 ; extra == 'deepspeed-testing' + - datasets!=2.5.0 ; extra == 'deepspeed-testing' + - dill<0.3.5 ; extra == 'deepspeed-testing' + - evaluate>=0.2.0 ; extra == 'deepspeed-testing' - pytest-timeout ; extra == 'deepspeed-testing' - - ruff ==0.1.5 ; extra == 'deepspeed-testing' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'deepspeed-testing' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'deepspeed-testing' + - ruff==0.1.5 ; extra == 'deepspeed-testing' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'deepspeed-testing' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'deepspeed-testing' - nltk ; extra == 'deepspeed-testing' - - gitpython <3.1.19 ; extra == 'deepspeed-testing' - - hf-doc-builder >=0.3.0 ; extra == 'deepspeed-testing' + - gitpython<3.1.19 ; extra == 'deepspeed-testing' + - hf-doc-builder>=0.3.0 ; extra == 'deepspeed-testing' - protobuf ; extra == 'deepspeed-testing' - sacremoses ; extra == 'deepspeed-testing' - rjieba ; extra == 'deepspeed-testing' - beautifulsoup4 ; extra == 'deepspeed-testing' - tensorboard ; extra == 'deepspeed-testing' - pydantic ; extra == 'deepspeed-testing' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'deepspeed-testing' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'deepspeed-testing' - faiss-cpu ; extra == 'deepspeed-testing' - - cookiecutter ==1.7.3 ; extra == 'deepspeed-testing' + - cookiecutter==1.7.3 ; extra == 'deepspeed-testing' - optuna ; extra == 'deepspeed-testing' - - tensorflow <2.16, >=2.6 ; extra == 'dev' + - tensorflow<2.16,>=2.6 ; extra == 'dev' - onnxconverter-common ; extra == 'dev' - tf2onnx ; extra == 'dev' - - tensorflow-text <2.16 ; extra == 'dev' - - keras-nlp >=0.3.1 ; extra == 'dev' + - tensorflow-text<2.16 ; extra == 'dev' + - keras-nlp>=0.3.1 ; extra == 'dev' - torch ; extra == 'dev' - - accelerate >=0.21.0 ; extra == 'dev' - - jax <=0.4.13, >=0.4.1 ; extra == 'dev' - - jaxlib <=0.4.13, >=0.4.1 ; extra == 'dev' - - flax <=0.7.0, >=0.4.1 ; extra == 'dev' - - optax <=0.1.4, >=0.0.8 ; extra == 'dev' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev' + - accelerate>=0.21.0 ; extra == 'dev' + - jax<=0.4.13,>=0.4.1 ; extra == 'dev' + - jaxlib<=0.4.13,>=0.4.1 ; extra == 'dev' + - flax<=0.7.0,>=0.4.1 ; extra == 'dev' + - optax<=0.1.4,>=0.0.8 ; extra == 'dev' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev' - protobuf ; extra == 'dev' - - tokenizers <0.20, >=0.19 ; extra == 'dev' + - tokenizers<0.20,>=0.19 ; extra == 'dev' - torchaudio ; extra == 'dev' - librosa ; extra == 'dev' - - pyctcdecode >=0.4.0 ; extra == 'dev' + - pyctcdecode>=0.4.0 ; extra == 'dev' - phonemizer ; extra == 'dev' - kenlm ; extra == 'dev' - - pillow <=15.0, >=10.0.1 ; extra == 'dev' + - pillow<=15.0,>=10.0.1 ; extra == 'dev' - optuna ; extra == 'dev' - - ray[tune] >=2.7.0 ; extra == 'dev' + - ray[tune]>=2.7.0 ; extra == 'dev' - sigopt ; extra == 'dev' - timm ; extra == 'dev' - torchvision ; extra == 'dev' - - codecarbon ==1.2.0 ; extra == 'dev' - - decord ==0.6.0 ; extra == 'dev' - - av ==9.2.0 ; extra == 'dev' - - pytest <8.0.0, >=7.2.0 ; extra == 'dev' + - codecarbon==1.2.0 ; extra == 'dev' + - decord==0.6.0 ; extra == 'dev' + - av==9.2.0 ; extra == 'dev' + - pytest<8.0.0,>=7.2.0 ; extra == 'dev' - pytest-xdist ; extra == 'dev' - timeout-decorator ; extra == 'dev' - parameterized ; extra == 'dev' - psutil ; extra == 'dev' - - datasets !=2.5.0 ; extra == 'dev' - - dill <0.3.5 ; extra == 'dev' - - evaluate >=0.2.0 ; extra == 'dev' + - datasets!=2.5.0 ; extra == 'dev' + - dill<0.3.5 ; extra == 'dev' + - evaluate>=0.2.0 ; extra == 'dev' - pytest-timeout ; extra == 'dev' - - ruff ==0.1.5 ; extra == 'dev' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev' + - ruff==0.1.5 ; extra == 'dev' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev' - nltk ; extra == 'dev' - - gitpython <3.1.19 ; extra == 'dev' - - hf-doc-builder >=0.3.0 ; extra == 'dev' + - gitpython<3.1.19 ; extra == 'dev' + - hf-doc-builder>=0.3.0 ; extra == 'dev' - sacremoses ; extra == 'dev' - rjieba ; extra == 'dev' - beautifulsoup4 ; extra == 'dev' - tensorboard ; extra == 'dev' - pydantic ; extra == 'dev' - faiss-cpu ; extra == 'dev' - - cookiecutter ==1.7.3 ; extra == 'dev' - - isort >=5.5.4 ; extra == 'dev' - - urllib3 <2.0.0 ; extra == 'dev' - - fugashi >=1.0 ; extra == 'dev' - - ipadic <2.0, >=1.0.0 ; extra == 'dev' - - unidic-lite >=1.0.7 ; extra == 'dev' - - unidic >=1.0.2 ; extra == 'dev' - - sudachipy >=0.6.6 ; extra == 'dev' - - sudachidict-core >=20220729 ; extra == 'dev' - - rhoknp <1.3.1, >=1.1.0 ; extra == 'dev' + - cookiecutter==1.7.3 ; extra == 'dev' + - isort>=5.5.4 ; extra == 'dev' + - urllib3<2.0.0 ; extra == 'dev' + - fugashi>=1.0 ; extra == 'dev' + - ipadic<2.0,>=1.0.0 ; extra == 'dev' + - unidic-lite>=1.0.7 ; extra == 'dev' + - unidic>=1.0.2 ; extra == 'dev' + - sudachipy>=0.6.6 ; extra == 'dev' + - sudachidict-core>=20220729 ; extra == 'dev' + - rhoknp<1.3.1,>=1.1.0 ; extra == 'dev' - hf-doc-builder ; extra == 'dev' - scikit-learn ; extra == 'dev' - - pytest <8.0.0, >=7.2.0 ; extra == 'dev-tensorflow' + - pytest<8.0.0,>=7.2.0 ; extra == 'dev-tensorflow' - pytest-xdist ; extra == 'dev-tensorflow' - timeout-decorator ; extra == 'dev-tensorflow' - parameterized ; extra == 'dev-tensorflow' - psutil ; extra == 'dev-tensorflow' - - datasets !=2.5.0 ; extra == 'dev-tensorflow' - - dill <0.3.5 ; extra == 'dev-tensorflow' - - evaluate >=0.2.0 ; extra == 'dev-tensorflow' + - datasets!=2.5.0 ; extra == 'dev-tensorflow' + - dill<0.3.5 ; extra == 'dev-tensorflow' + - evaluate>=0.2.0 ; extra == 'dev-tensorflow' - pytest-timeout ; extra == 'dev-tensorflow' - - ruff ==0.1.5 ; extra == 'dev-tensorflow' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev-tensorflow' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev-tensorflow' + - ruff==0.1.5 ; extra == 'dev-tensorflow' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev-tensorflow' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev-tensorflow' - nltk ; extra == 'dev-tensorflow' - - gitpython <3.1.19 ; extra == 'dev-tensorflow' - - hf-doc-builder >=0.3.0 ; extra == 'dev-tensorflow' + - gitpython<3.1.19 ; extra == 'dev-tensorflow' + - hf-doc-builder>=0.3.0 ; extra == 'dev-tensorflow' - protobuf ; extra == 'dev-tensorflow' - sacremoses ; extra == 'dev-tensorflow' - rjieba ; extra == 'dev-tensorflow' - beautifulsoup4 ; extra == 'dev-tensorflow' - tensorboard ; extra == 'dev-tensorflow' - pydantic ; extra == 'dev-tensorflow' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev-tensorflow' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev-tensorflow' - faiss-cpu ; extra == 'dev-tensorflow' - - cookiecutter ==1.7.3 ; extra == 'dev-tensorflow' - - tensorflow <2.16, >=2.6 ; extra == 'dev-tensorflow' + - cookiecutter==1.7.3 ; extra == 'dev-tensorflow' + - tensorflow<2.16,>=2.6 ; extra == 'dev-tensorflow' - onnxconverter-common ; extra == 'dev-tensorflow' - tf2onnx ; extra == 'dev-tensorflow' - - tensorflow-text <2.16 ; extra == 'dev-tensorflow' - - keras-nlp >=0.3.1 ; extra == 'dev-tensorflow' - - tokenizers <0.20, >=0.19 ; extra == 'dev-tensorflow' - - pillow <=15.0, >=10.0.1 ; extra == 'dev-tensorflow' - - isort >=5.5.4 ; extra == 'dev-tensorflow' - - urllib3 <2.0.0 ; extra == 'dev-tensorflow' + - tensorflow-text<2.16 ; extra == 'dev-tensorflow' + - keras-nlp>=0.3.1 ; extra == 'dev-tensorflow' + - tokenizers<0.20,>=0.19 ; extra == 'dev-tensorflow' + - pillow<=15.0,>=10.0.1 ; extra == 'dev-tensorflow' + - isort>=5.5.4 ; extra == 'dev-tensorflow' + - urllib3<2.0.0 ; extra == 'dev-tensorflow' - hf-doc-builder ; extra == 'dev-tensorflow' - scikit-learn ; extra == 'dev-tensorflow' - - onnxruntime >=1.4.0 ; extra == 'dev-tensorflow' - - onnxruntime-tools >=1.4.2 ; extra == 'dev-tensorflow' + - onnxruntime>=1.4.0 ; extra == 'dev-tensorflow' + - onnxruntime-tools>=1.4.2 ; extra == 'dev-tensorflow' - librosa ; extra == 'dev-tensorflow' - - pyctcdecode >=0.4.0 ; extra == 'dev-tensorflow' + - pyctcdecode>=0.4.0 ; extra == 'dev-tensorflow' - phonemizer ; extra == 'dev-tensorflow' - kenlm ; extra == 'dev-tensorflow' - - pytest <8.0.0, >=7.2.0 ; extra == 'dev-torch' + - pytest<8.0.0,>=7.2.0 ; extra == 'dev-torch' - pytest-xdist ; extra == 'dev-torch' - timeout-decorator ; extra == 'dev-torch' - parameterized ; extra == 'dev-torch' - psutil ; extra == 'dev-torch' - - datasets !=2.5.0 ; extra == 'dev-torch' - - dill <0.3.5 ; extra == 'dev-torch' - - evaluate >=0.2.0 ; extra == 'dev-torch' + - datasets!=2.5.0 ; extra == 'dev-torch' + - dill<0.3.5 ; extra == 'dev-torch' + - evaluate>=0.2.0 ; extra == 'dev-torch' - pytest-timeout ; extra == 'dev-torch' - - ruff ==0.1.5 ; extra == 'dev-torch' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'dev-torch' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'dev-torch' + - ruff==0.1.5 ; extra == 'dev-torch' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'dev-torch' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'dev-torch' - nltk ; extra == 'dev-torch' - - gitpython <3.1.19 ; extra == 'dev-torch' - - hf-doc-builder >=0.3.0 ; extra == 'dev-torch' + - gitpython<3.1.19 ; extra == 'dev-torch' + - hf-doc-builder>=0.3.0 ; extra == 'dev-torch' - protobuf ; extra == 'dev-torch' - sacremoses ; extra == 'dev-torch' - rjieba ; extra == 'dev-torch' - beautifulsoup4 ; extra == 'dev-torch' - tensorboard ; extra == 'dev-torch' - pydantic ; extra == 'dev-torch' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'dev-torch' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'dev-torch' - faiss-cpu ; extra == 'dev-torch' - - cookiecutter ==1.7.3 ; extra == 'dev-torch' + - cookiecutter==1.7.3 ; extra == 'dev-torch' - torch ; extra == 'dev-torch' - - accelerate >=0.21.0 ; extra == 'dev-torch' - - tokenizers <0.20, >=0.19 ; extra == 'dev-torch' + - accelerate>=0.21.0 ; extra == 'dev-torch' + - tokenizers<0.20,>=0.19 ; extra == 'dev-torch' - torchaudio ; extra == 'dev-torch' - librosa ; extra == 'dev-torch' - - pyctcdecode >=0.4.0 ; extra == 'dev-torch' + - pyctcdecode>=0.4.0 ; extra == 'dev-torch' - phonemizer ; extra == 'dev-torch' - kenlm ; extra == 'dev-torch' - - pillow <=15.0, >=10.0.1 ; extra == 'dev-torch' + - pillow<=15.0,>=10.0.1 ; extra == 'dev-torch' - optuna ; extra == 'dev-torch' - - ray[tune] >=2.7.0 ; extra == 'dev-torch' + - ray[tune]>=2.7.0 ; extra == 'dev-torch' - sigopt ; extra == 'dev-torch' - timm ; extra == 'dev-torch' - torchvision ; extra == 'dev-torch' - - codecarbon ==1.2.0 ; extra == 'dev-torch' - - isort >=5.5.4 ; extra == 'dev-torch' - - urllib3 <2.0.0 ; extra == 'dev-torch' - - fugashi >=1.0 ; extra == 'dev-torch' - - ipadic <2.0, >=1.0.0 ; extra == 'dev-torch' - - unidic-lite >=1.0.7 ; extra == 'dev-torch' - - unidic >=1.0.2 ; extra == 'dev-torch' - - sudachipy >=0.6.6 ; extra == 'dev-torch' - - sudachidict-core >=20220729 ; extra == 'dev-torch' - - rhoknp <1.3.1, >=1.1.0 ; extra == 'dev-torch' + - codecarbon==1.2.0 ; extra == 'dev-torch' + - isort>=5.5.4 ; extra == 'dev-torch' + - urllib3<2.0.0 ; extra == 'dev-torch' + - fugashi>=1.0 ; extra == 'dev-torch' + - ipadic<2.0,>=1.0.0 ; extra == 'dev-torch' + - unidic-lite>=1.0.7 ; extra == 'dev-torch' + - unidic>=1.0.2 ; extra == 'dev-torch' + - sudachipy>=0.6.6 ; extra == 'dev-torch' + - sudachidict-core>=20220729 ; extra == 'dev-torch' + - rhoknp<1.3.1,>=1.1.0 ; extra == 'dev-torch' - hf-doc-builder ; extra == 'dev-torch' - scikit-learn ; extra == 'dev-torch' - - onnxruntime >=1.4.0 ; extra == 'dev-torch' - - onnxruntime-tools >=1.4.2 ; extra == 'dev-torch' - - tensorflow <2.16, >=2.6 ; extra == 'docs' + - onnxruntime>=1.4.0 ; extra == 'dev-torch' + - onnxruntime-tools>=1.4.2 ; extra == 'dev-torch' + - tensorflow<2.16,>=2.6 ; extra == 'docs' - onnxconverter-common ; extra == 'docs' - tf2onnx ; extra == 'docs' - - tensorflow-text <2.16 ; extra == 'docs' - - keras-nlp >=0.3.1 ; extra == 'docs' + - tensorflow-text<2.16 ; extra == 'docs' + - keras-nlp>=0.3.1 ; extra == 'docs' - torch ; extra == 'docs' - - accelerate >=0.21.0 ; extra == 'docs' - - jax <=0.4.13, >=0.4.1 ; extra == 'docs' - - jaxlib <=0.4.13, >=0.4.1 ; extra == 'docs' - - flax <=0.7.0, >=0.4.1 ; extra == 'docs' - - optax <=0.1.4, >=0.0.8 ; extra == 'docs' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'docs' + - accelerate>=0.21.0 ; extra == 'docs' + - jax<=0.4.13,>=0.4.1 ; extra == 'docs' + - jaxlib<=0.4.13,>=0.4.1 ; extra == 'docs' + - flax<=0.7.0,>=0.4.1 ; extra == 'docs' + - optax<=0.1.4,>=0.0.8 ; extra == 'docs' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'docs' - protobuf ; extra == 'docs' - - tokenizers <0.20, >=0.19 ; extra == 'docs' + - tokenizers<0.20,>=0.19 ; extra == 'docs' - torchaudio ; extra == 'docs' - librosa ; extra == 'docs' - - pyctcdecode >=0.4.0 ; extra == 'docs' + - pyctcdecode>=0.4.0 ; extra == 'docs' - phonemizer ; extra == 'docs' - kenlm ; extra == 'docs' - - pillow <=15.0, >=10.0.1 ; extra == 'docs' + - pillow<=15.0,>=10.0.1 ; extra == 'docs' - optuna ; extra == 'docs' - - ray[tune] >=2.7.0 ; extra == 'docs' + - ray[tune]>=2.7.0 ; extra == 'docs' - sigopt ; extra == 'docs' - timm ; extra == 'docs' - torchvision ; extra == 'docs' - - codecarbon ==1.2.0 ; extra == 'docs' - - decord ==0.6.0 ; extra == 'docs' - - av ==9.2.0 ; extra == 'docs' + - codecarbon==1.2.0 ; extra == 'docs' + - decord==0.6.0 ; extra == 'docs' + - av==9.2.0 ; extra == 'docs' - hf-doc-builder ; extra == 'docs' - hf-doc-builder ; extra == 'docs_specific' - - jax <=0.4.13, >=0.4.1 ; extra == 'flax' - - jaxlib <=0.4.13, >=0.4.1 ; extra == 'flax' - - flax <=0.7.0, >=0.4.1 ; extra == 'flax' - - optax <=0.1.4, >=0.0.8 ; extra == 'flax' + - jax<=0.4.13,>=0.4.1 ; extra == 'flax' + - jaxlib<=0.4.13,>=0.4.1 ; extra == 'flax' + - flax<=0.7.0,>=0.4.1 ; extra == 'flax' + - optax<=0.1.4,>=0.0.8 ; extra == 'flax' - librosa ; extra == 'flax-speech' - - pyctcdecode >=0.4.0 ; extra == 'flax-speech' + - pyctcdecode>=0.4.0 ; extra == 'flax-speech' - phonemizer ; extra == 'flax-speech' - kenlm ; extra == 'flax-speech' - ftfy ; extra == 'ftfy' - optuna ; extra == 'integrations' - - ray[tune] >=2.7.0 ; extra == 'integrations' + - ray[tune]>=2.7.0 ; extra == 'integrations' - sigopt ; extra == 'integrations' - - fugashi >=1.0 ; extra == 'ja' - - ipadic <2.0, >=1.0.0 ; extra == 'ja' - - unidic-lite >=1.0.7 ; extra == 'ja' - - unidic >=1.0.2 ; extra == 'ja' - - sudachipy >=0.6.6 ; extra == 'ja' - - sudachidict-core >=20220729 ; extra == 'ja' - - rhoknp <1.3.1, >=1.1.0 ; extra == 'ja' - - cookiecutter ==1.7.3 ; extra == 'modelcreation' - - natten <0.15.0, >=0.14.6 ; extra == 'natten' + - fugashi>=1.0 ; extra == 'ja' + - ipadic<2.0,>=1.0.0 ; extra == 'ja' + - unidic-lite>=1.0.7 ; extra == 'ja' + - unidic>=1.0.2 ; extra == 'ja' + - sudachipy>=0.6.6 ; extra == 'ja' + - sudachidict-core>=20220729 ; extra == 'ja' + - rhoknp<1.3.1,>=1.1.0 ; extra == 'ja' + - cookiecutter==1.7.3 ; extra == 'modelcreation' + - natten<0.15.0,>=0.14.6 ; extra == 'natten' - onnxconverter-common ; extra == 'onnx' - tf2onnx ; extra == 'onnx' - - onnxruntime >=1.4.0 ; extra == 'onnx' - - onnxruntime-tools >=1.4.2 ; extra == 'onnx' - - onnxruntime >=1.4.0 ; extra == 'onnxruntime' - - onnxruntime-tools >=1.4.2 ; extra == 'onnxruntime' + - onnxruntime>=1.4.0 ; extra == 'onnx' + - onnxruntime-tools>=1.4.2 ; extra == 'onnx' + - onnxruntime>=1.4.0 ; extra == 'onnxruntime' + - onnxruntime-tools>=1.4.2 ; extra == 'onnxruntime' - optuna ; extra == 'optuna' - - datasets !=2.5.0 ; extra == 'quality' - - isort >=5.5.4 ; extra == 'quality' - - ruff ==0.1.5 ; extra == 'quality' - - gitpython <3.1.19 ; extra == 'quality' - - hf-doc-builder >=0.3.0 ; extra == 'quality' - - urllib3 <2.0.0 ; extra == 'quality' - - ray[tune] >=2.7.0 ; extra == 'ray' + - datasets!=2.5.0 ; extra == 'quality' + - isort>=5.5.4 ; extra == 'quality' + - ruff==0.1.5 ; extra == 'quality' + - gitpython<3.1.19 ; extra == 'quality' + - hf-doc-builder>=0.3.0 ; extra == 'quality' + - urllib3<2.0.0 ; extra == 'quality' + - ray[tune]>=2.7.0 ; extra == 'ray' - faiss-cpu ; extra == 'retrieval' - - datasets !=2.5.0 ; extra == 'retrieval' - - sagemaker >=2.31.0 ; extra == 'sagemaker' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'sentencepiece' + - datasets!=2.5.0 ; extra == 'retrieval' + - sagemaker>=2.31.0 ; extra == 'sagemaker' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'sentencepiece' - protobuf ; extra == 'sentencepiece' - pydantic ; extra == 'serving' - uvicorn ; extra == 'serving' @@ -27500,73 +27146,73 @@ packages: - scikit-learn ; extra == 'sklearn' - torchaudio ; extra == 'speech' - librosa ; extra == 'speech' - - pyctcdecode >=0.4.0 ; extra == 'speech' + - pyctcdecode>=0.4.0 ; extra == 'speech' - phonemizer ; extra == 'speech' - kenlm ; extra == 'speech' - - pytest <8.0.0, >=7.2.0 ; extra == 'testing' + - pytest<8.0.0,>=7.2.0 ; extra == 'testing' - pytest-xdist ; extra == 'testing' - timeout-decorator ; extra == 'testing' - parameterized ; extra == 'testing' - psutil ; extra == 'testing' - - datasets !=2.5.0 ; extra == 'testing' - - dill <0.3.5 ; extra == 'testing' - - evaluate >=0.2.0 ; extra == 'testing' + - datasets!=2.5.0 ; extra == 'testing' + - dill<0.3.5 ; extra == 'testing' + - evaluate>=0.2.0 ; extra == 'testing' - pytest-timeout ; extra == 'testing' - - ruff ==0.1.5 ; extra == 'testing' - - sacrebleu <2.0.0, >=1.4.12 ; extra == 'testing' - - rouge-score !=0.0.7, !=0.0.8, !=0.1, !=0.1.1 ; extra == 'testing' + - ruff==0.1.5 ; extra == 'testing' + - sacrebleu<2.0.0,>=1.4.12 ; extra == 'testing' + - rouge-score!=0.0.7,!=0.0.8,!=0.1,!=0.1.1 ; extra == 'testing' - nltk ; extra == 'testing' - - gitpython <3.1.19 ; extra == 'testing' - - hf-doc-builder >=0.3.0 ; extra == 'testing' + - gitpython<3.1.19 ; extra == 'testing' + - hf-doc-builder>=0.3.0 ; extra == 'testing' - protobuf ; extra == 'testing' - sacremoses ; extra == 'testing' - rjieba ; extra == 'testing' - beautifulsoup4 ; extra == 'testing' - tensorboard ; extra == 'testing' - pydantic ; extra == 'testing' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'testing' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'testing' - faiss-cpu ; extra == 'testing' - - cookiecutter ==1.7.3 ; extra == 'testing' - - tensorflow <2.16, >=2.6 ; extra == 'tf' + - cookiecutter==1.7.3 ; extra == 'testing' + - tensorflow<2.16,>=2.6 ; extra == 'tf' - onnxconverter-common ; extra == 'tf' - tf2onnx ; extra == 'tf' - - tensorflow-text <2.16 ; extra == 'tf' - - keras-nlp >=0.3.1 ; extra == 'tf' - - tensorflow-cpu <2.16, >=2.6 ; extra == 'tf-cpu' + - tensorflow-text<2.16 ; extra == 'tf' + - keras-nlp>=0.3.1 ; extra == 'tf' + - tensorflow-cpu<2.16,>=2.6 ; extra == 'tf-cpu' - onnxconverter-common ; extra == 'tf-cpu' - tf2onnx ; extra == 'tf-cpu' - - tensorflow-text <2.16 ; extra == 'tf-cpu' - - keras-nlp >=0.3.1 ; extra == 'tf-cpu' + - tensorflow-text<2.16 ; extra == 'tf-cpu' + - keras-nlp>=0.3.1 ; extra == 'tf-cpu' - librosa ; extra == 'tf-speech' - - pyctcdecode >=0.4.0 ; extra == 'tf-speech' + - pyctcdecode>=0.4.0 ; extra == 'tf-speech' - phonemizer ; extra == 'tf-speech' - kenlm ; extra == 'tf-speech' - timm ; extra == 'timm' - - tokenizers <0.20, >=0.19 ; extra == 'tokenizers' + - tokenizers<0.20,>=0.19 ; extra == 'tokenizers' - torch ; extra == 'torch' - - accelerate >=0.21.0 ; extra == 'torch' + - accelerate>=0.21.0 ; extra == 'torch' - torchaudio ; extra == 'torch-speech' - librosa ; extra == 'torch-speech' - - pyctcdecode >=0.4.0 ; extra == 'torch-speech' + - pyctcdecode>=0.4.0 ; extra == 'torch-speech' - phonemizer ; extra == 'torch-speech' - kenlm ; extra == 'torch-speech' - torchvision ; extra == 'torch-vision' - - pillow <=15.0, >=10.0.1 ; extra == 'torch-vision' + - pillow<=15.0,>=10.0.1 ; extra == 'torch-vision' - filelock ; extra == 'torchhub' - - huggingface-hub <1.0, >=0.19.3 ; extra == 'torchhub' + - huggingface-hub<1.0,>=0.19.3 ; extra == 'torchhub' - importlib-metadata ; extra == 'torchhub' - - numpy >=1.17 ; extra == 'torchhub' - - packaging >=20.0 ; extra == 'torchhub' + - numpy>=1.17 ; extra == 'torchhub' + - packaging>=20.0 ; extra == 'torchhub' - protobuf ; extra == 'torchhub' - - regex !=2019.12.17 ; extra == 'torchhub' + - regex!=2019.12.17 ; extra == 'torchhub' - requests ; extra == 'torchhub' - - sentencepiece !=0.1.92, >=0.1.91 ; extra == 'torchhub' + - sentencepiece!=0.1.92,>=0.1.91 ; extra == 'torchhub' - torch ; extra == 'torchhub' - - tokenizers <0.20, >=0.19 ; extra == 'torchhub' - - tqdm >=4.27 ; extra == 'torchhub' - - decord ==0.6.0 ; extra == 'video' - - av ==9.2.0 ; extra == 'video' - - pillow <=15.0, >=10.0.1 ; extra == 'vision' + - tokenizers<0.20,>=0.19 ; extra == 'torchhub' + - tqdm>=4.27 ; extra == 'torchhub' + - decord==0.6.0 ; extra == 'video' + - av==9.2.0 ; extra == 'video' + - pillow<=15.0,>=10.0.1 ; extra == 'vision' requires_python: '>=3.8.0' - kind: pypi name: trimesh @@ -27629,14 +27275,14 @@ packages: sha256: da58a152bddb62cafa9a857dd2bc1f886dbf9f9c90a2b5da82157cd2b34392b0 requires_dist: - filelock - - cmake >=3.20 ; extra == 'build' + - cmake>=3.20 ; extra == 'build' - lit ; extra == 'build' - autopep8 ; extra == 'tests' - flake8 ; extra == 'tests' - isort ; extra == 'tests' - numpy ; extra == 'tests' - pytest ; extra == 'tests' - - scipy >=1.7.1 ; extra == 'tests' + - scipy>=1.7.1 ; extra == 'tests' - torch ; extra == 'tests' - matplotlib ; extra == 'tutorials' - pandas ; extra == 'tutorials' @@ -27653,7 +27299,7 @@ packages: url: https://files.pythonhosted.org/packages/8b/ea/91b718b8c0b88e4f61cdd61357cc4a1f8767b32be691fb388299003a3ae3/types_requests-2.31.0.20240406-py3-none-any.whl sha256: 6216cdac377c6b9a040ac1c0404f7284bd13199c0e1bb235f4324627e8898cf5 requires_dist: - - urllib3 >=2 + - urllib3>=2 requires_python: '>=3.8' - kind: pypi name: typing-extensions @@ -27667,9 +27313,9 @@ packages: url: https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl sha256: 9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f requires_dist: - - mypy-extensions >=0.3.0 - - typing-extensions >=3.7.4 - - typing >=3.7.4 ; python_version < '3.5' + - mypy-extensions>=0.3.0 + - typing-extensions>=3.7.4 + - typing>=3.7.4 ; python_version < '3.5' - kind: conda name: typing_extensions version: 4.8.0 @@ -28073,13 +27719,13 @@ packages: url: https://files.pythonhosted.org/packages/d1/1b/46802a050b1c55d10c4f59fc6afd2b45ac9b4f62b2e12092d3f599286f14/umap_learn-0.5.6-py3-none-any.whl sha256: 881cc0c2ee845b790bf0455aa1664f9f68b838d9d0fe12a1291b85c5a559c913 requires_dist: - - numpy >=1.17 - - scipy >=1.3.1 - - scikit-learn >=0.22 - - numba >=0.51.2 - - pynndescent >=0.5 + - numpy>=1.17 + - scipy>=1.3.1 + - scikit-learn>=0.22 + - numba>=0.51.2 + - pynndescent>=0.5 - tqdm - - tensorflow >=2.1 ; extra == 'parametric_umap' + - tensorflow>=2.1 ; extra == 'parametric_umap' - pandas ; extra == 'plot' - matplotlib ; extra == 'plot' - datashader ; extra == 'plot' @@ -28088,38 +27734,19 @@ packages: - colorcet ; extra == 'plot' - seaborn ; extra == 'plot' - scikit-image ; extra == 'plot' - - tbb >=2019.0 ; extra == 'tbb' + - tbb>=2019.0 ; extra == 'tbb' - kind: pypi name: urllib3 version: 2.2.1 url: https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl sha256: 450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d requires_dist: - - brotli >=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' - - brotlicffi >=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' - - h2 <5, >=4 ; extra == 'h2' - - pysocks !=1.5.7, <2.0, >=1.5.6 ; extra == 'socks' - - zstandard >=0.18.0 ; extra == 'zstd' + - brotli>=1.0.9 ; platform_python_implementation == 'CPython' and extra == 'brotli' + - brotlicffi>=0.8.0 ; platform_python_implementation != 'CPython' and extra == 'brotli' + - h2<5,>=4 ; extra == 'h2' + - pysocks!=1.5.7,<2.0,>=1.5.6 ; extra == 'socks' + - zstandard>=0.18.0 ; extra == 'zstd' requires_python: '>=3.8' -- kind: conda - name: urllib3 - version: 2.2.1 - build: pyhd8ed1ab_0 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/urllib3-2.2.1-pyhd8ed1ab_0.conda - sha256: d4009dcc9327684d6409706ce17656afbeae690d8522d3c9bc4df57649a352cd - md5: 08807a87fa7af10754d46f63b368e016 - depends: - - brotli-python >=1.0.9 - - pysocks >=1.5.6,<2.0,!=1.5.7 - - python >=3.7 - license: MIT - license_family: MIT - purls: - - pkg:pypi/urllib3 - size: 94669 - timestamp: 1708239595549 - kind: conda name: vc version: '14.3' @@ -28194,63 +27821,33 @@ packages: timestamp: 1702511239004 - kind: pypi name: virtualenv - version: 20.25.2 - url: https://files.pythonhosted.org/packages/b7/d0/ee2496ac979bbb3fd7ed2edba0da3f1f415a6559721b9d51b7efe99d15ea/virtualenv-20.25.2-py3-none-any.whl - sha256: 6e1281a57849c8a54da89ba82e5eb7c8937b9d057ff01aaf5bc9afaa3552e90f - requires_dist: - - distlib <1, >=0.3.7 - - filelock <4, >=3.12.2 - - importlib-metadata >=6.6 ; python_version < '3.8' - - platformdirs <5, >=3.9.1 - - furo >=2023.7.26 ; extra == 'docs' - - proselint >=0.13 ; extra == 'docs' - - sphinx !=7.3, >=7.1.2 ; extra == 'docs' - - sphinx-argparse >=0.4 ; extra == 'docs' - - sphinxcontrib-towncrier >=0.2.1a0 ; extra == 'docs' - - towncrier >=23.6 ; extra == 'docs' - - covdefaults >=2.3 ; extra == 'test' - - coverage-enable-subprocess >=1 ; extra == 'test' - - coverage >=7.2.7 ; extra == 'test' - - flaky >=3.7 ; extra == 'test' - - packaging >=23.1 ; extra == 'test' - - pytest-env >=0.8.2 ; extra == 'test' - - pytest-freezer >=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' - - pytest-mock >=3.11.1 ; extra == 'test' - - pytest-randomly >=3.12 ; extra == 'test' - - pytest-timeout >=2.1 ; extra == 'test' - - pytest >=7.4 ; extra == 'test' - - setuptools >=68 ; extra == 'test' - - time-machine >=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' - requires_python: '>=3.7' -- kind: pypi - name: virtualenv - version: 20.25.3 - url: https://files.pythonhosted.org/packages/cd/8a/709e9994dc2f9705d1127c63b64151582655e02c953e163b317803864fc0/virtualenv-20.25.3-py3-none-any.whl - sha256: 8aac4332f2ea6ef519c648d0bc48a5b1d324994753519919bddbb1aff25a104e + version: 20.26.1 + url: https://files.pythonhosted.org/packages/ca/28/19728b052c52b588fa117e80561d4b6e872664f4df73628d58593218becd/virtualenv-20.26.1-py3-none-any.whl + sha256: 7aa9982a728ae5892558bff6a2839c00b9ed145523ece2274fad6f414690ae75 requires_dist: - - distlib <1, >=0.3.7 - - filelock <4, >=3.12.2 - - importlib-metadata >=6.6 ; python_version < '3.8' - - platformdirs <5, >=3.9.1 - - furo >=2023.7.26 ; extra == 'docs' - - proselint >=0.13 ; extra == 'docs' - - sphinx !=7.3, >=7.1.2 ; extra == 'docs' - - sphinx-argparse >=0.4 ; extra == 'docs' - - sphinxcontrib-towncrier >=0.2.1a0 ; extra == 'docs' - - towncrier >=23.6 ; extra == 'docs' - - covdefaults >=2.3 ; extra == 'test' - - coverage-enable-subprocess >=1 ; extra == 'test' - - coverage >=7.2.7 ; extra == 'test' - - flaky >=3.7 ; extra == 'test' - - packaging >=23.1 ; extra == 'test' - - pytest-env >=0.8.2 ; extra == 'test' - - pytest-freezer >=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' - - pytest-mock >=3.11.1 ; extra == 'test' - - pytest-randomly >=3.12 ; extra == 'test' - - pytest-timeout >=2.1 ; extra == 'test' - - pytest >=7.4 ; extra == 'test' - - setuptools >=68 ; extra == 'test' - - time-machine >=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' + - distlib<1,>=0.3.7 + - filelock<4,>=3.12.2 + - importlib-metadata>=6.6 ; python_version < '3.8' + - platformdirs<5,>=3.9.1 + - furo>=2023.7.26 ; extra == 'docs' + - proselint>=0.13 ; extra == 'docs' + - sphinx!=7.3,>=7.1.2 ; extra == 'docs' + - sphinx-argparse>=0.4 ; extra == 'docs' + - sphinxcontrib-towncrier>=0.2.1a0 ; extra == 'docs' + - towncrier>=23.6 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'test' + - coverage-enable-subprocess>=1 ; extra == 'test' + - coverage>=7.2.7 ; extra == 'test' + - flaky>=3.7 ; extra == 'test' + - packaging>=23.1 ; extra == 'test' + - pytest-env>=0.8.2 ; extra == 'test' + - pytest-freezer>=0.4.8 ; platform_python_implementation == 'PyPy' and extra == 'test' + - pytest-mock>=3.11.1 ; extra == 'test' + - pytest-randomly>=3.12 ; extra == 'test' + - pytest-timeout>=2.1 ; extra == 'test' + - pytest>=7.4 ; extra == 'test' + - setuptools>=68 ; extra == 'test' + - time-machine>=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' requires_python: '>=3.7' - kind: conda name: vs2015_runtime @@ -28355,53 +27952,35 @@ packages: - pkg:pypi/wheel size: 57963 timestamp: 1711546009410 -- kind: conda - name: win_inet_pton - version: 1.1.0 - build: pyhd8ed1ab_6 - build_number: 6 - subdir: noarch - noarch: python - url: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyhd8ed1ab_6.tar.bz2 - sha256: a11ae693a0645bf6c7b8a47bac030be9c0967d0b1924537b9ff7458e832c0511 - md5: 30878ecc4bd36e8deeea1e3c151b2e0b - depends: - - __win - - python >=3.6 - license: PUBLIC-DOMAIN - purls: - - pkg:pypi/win-inet-pton - size: 8191 - timestamp: 1667051294134 - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d + url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 + url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 + url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl + sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl - sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 + url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 + url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 requires_python: '>=3.6' - kind: conda name: xz @@ -28573,37 +28152,37 @@ packages: url: https://files.pythonhosted.org/packages/d5/b5/70bb98ee38ce532ee29fab76fb668382291fe6e1aa69a8c1ac7e6bc108e7/yfinance-0.2.38-py2.py3-none-any.whl sha256: 07525cf84414272723a3e2b9d4c0a2898ddb60cc0828aa190de26664fac6f676 requires_dist: - - pandas >=1.3.0 - - numpy >=1.16.5 - - requests >=2.31 - - multitasking >=0.0.7 - - lxml >=4.9.1 - - appdirs >=1.4.4 - - pytz >=2022.5 - - frozendict >=2.3.4 - - peewee >=3.16.2 - - beautifulsoup4 >=4.11.1 - - html5lib >=1.1 - - requests-cache >=1.0 ; extra == 'nospam' - - requests-ratelimiter >=0.3.1 ; extra == 'nospam' - - scipy >=1.6.3 ; extra == 'repair' + - pandas>=1.3.0 + - numpy>=1.16.5 + - requests>=2.31 + - multitasking>=0.0.7 + - lxml>=4.9.1 + - appdirs>=1.4.4 + - pytz>=2022.5 + - frozendict>=2.3.4 + - peewee>=3.16.2 + - beautifulsoup4>=4.11.1 + - html5lib>=1.1 + - requests-cache>=1.0 ; extra == 'nospam' + - requests-ratelimiter>=0.3.1 ; extra == 'nospam' + - scipy>=1.6.3 ; extra == 'repair' - kind: pypi name: zipp version: 3.18.1 url: https://files.pythonhosted.org/packages/c2/0a/ba9d0ee9536d3ef73a3448e931776e658b36f128d344e175bc32b092a8bf/zipp-3.18.1-py3-none-any.whl sha256: 206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b requires_dist: - - sphinx >=3.5 ; extra == 'docs' - - jaraco-packaging >=9.3 ; extra == 'docs' - - rst-linker >=1.9 ; extra == 'docs' + - sphinx>=3.5 ; extra == 'docs' + - jaraco-packaging>=9.3 ; extra == 'docs' + - rst-linker>=1.9 ; extra == 'docs' - furo ; extra == 'docs' - sphinx-lint ; extra == 'docs' - - jaraco-tidelift >=1.4 ; extra == 'docs' - - pytest >=6 ; extra == 'testing' - - pytest-checkdocs >=2.4 ; extra == 'testing' + - jaraco-tidelift>=1.4 ; extra == 'docs' + - pytest>=6 ; extra == 'testing' + - pytest-checkdocs>=2.4 ; extra == 'testing' - pytest-cov ; extra == 'testing' - - pytest-enabler >=2.2 ; extra == 'testing' - - pytest-ruff >=0.2.1 ; extra == 'testing' + - pytest-enabler>=2.2 ; extra == 'testing' + - pytest-ruff>=0.2.1 ; extra == 'testing' - jaraco-itertools ; extra == 'testing' - jaraco-functools ; extra == 'testing' - more-itertools ; extra == 'testing' diff --git a/pixi.toml b/pixi.toml index 68c482a6b799..096297a9e612 100644 --- a/pixi.toml +++ b/pixi.toml @@ -201,6 +201,7 @@ fetch-artifact = "python scripts/ci/fetch_artifact.py" search-index = "cargo run --locked -p re_dev_tools -- search-index" # Serve python docs locally +# TODO(#6060): Put this in an environment and remove the requirements file. py-docs-serve = "mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py" [feature.cpp.tasks] diff --git a/rerun_cpp/src/rerun/blueprint/.gitattributes b/rerun_cpp/src/rerun/blueprint/.gitattributes index 435e1f8fe40d..0661cd67c5ea 100644 --- a/rerun_cpp/src/rerun/blueprint/.gitattributes +++ b/rerun_cpp/src/rerun/blueprint/.gitattributes @@ -3,4 +3,3 @@ .gitattributes linguist-generated=true archetypes.hpp linguist-generated=true components.hpp linguist-generated=true -datatypes.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/components/visible_time_range_sequence.hpp b/rerun_cpp/src/rerun/blueprint/components/visible_time_range_sequence.hpp index dee892ace385..38fbe05a3b68 100644 --- a/rerun_cpp/src/rerun/blueprint/components/visible_time_range_sequence.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/visible_time_range_sequence.hpp @@ -3,7 +3,7 @@ #pragma once -#include "../../blueprint/datatypes/visible_time_range.hpp" +#include "../../datatypes/visible_time_range.hpp" #include "../../result.hpp" #include @@ -12,21 +12,20 @@ namespace rerun::blueprint::components { /// **Component**: The range of values on time timelines that will be included in a space view query. struct VisibleTimeRangeSequence { - rerun::blueprint::datatypes::VisibleTimeRange value; + rerun::datatypes::VisibleTimeRange value; public: VisibleTimeRangeSequence() = default; - VisibleTimeRangeSequence(rerun::blueprint::datatypes::VisibleTimeRange value_) - : value(value_) {} + VisibleTimeRangeSequence(rerun::datatypes::VisibleTimeRange value_) : value(value_) {} - VisibleTimeRangeSequence& operator=(rerun::blueprint::datatypes::VisibleTimeRange value_) { + VisibleTimeRangeSequence& operator=(rerun::datatypes::VisibleTimeRange value_) { value = value_; return *this; } /// Cast to the underlying VisibleTimeRange datatype - operator rerun::blueprint::datatypes::VisibleTimeRange() const { + operator rerun::datatypes::VisibleTimeRange() const { return value; } }; @@ -34,7 +33,7 @@ namespace rerun::blueprint::components { namespace rerun { static_assert( - sizeof(rerun::blueprint::datatypes::VisibleTimeRange) == + sizeof(rerun::datatypes::VisibleTimeRange) == sizeof(blueprint::components::VisibleTimeRangeSequence) ); @@ -45,14 +44,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype() { - return Loggable::arrow_datatype(); + return Loggable::arrow_datatype(); } /// Serializes an array of `rerun::blueprint:: components::VisibleTimeRangeSequence` into an arrow array. static Result> to_arrow( const blueprint::components::VisibleTimeRangeSequence* instances, size_t num_instances ) { - return Loggable::to_arrow( + return Loggable::to_arrow( &instances->value, num_instances ); diff --git a/rerun_cpp/src/rerun/blueprint/components/visible_time_range_time.hpp b/rerun_cpp/src/rerun/blueprint/components/visible_time_range_time.hpp index 478cabff5272..719cb01b3967 100644 --- a/rerun_cpp/src/rerun/blueprint/components/visible_time_range_time.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/visible_time_range_time.hpp @@ -3,7 +3,7 @@ #pragma once -#include "../../blueprint/datatypes/visible_time_range.hpp" +#include "../../datatypes/visible_time_range.hpp" #include "../../result.hpp" #include @@ -12,21 +12,20 @@ namespace rerun::blueprint::components { /// **Component**: The range of values on sequence timelines that will be included in a space view query. struct VisibleTimeRangeTime { - rerun::blueprint::datatypes::VisibleTimeRange value; + rerun::datatypes::VisibleTimeRange value; public: VisibleTimeRangeTime() = default; - VisibleTimeRangeTime(rerun::blueprint::datatypes::VisibleTimeRange value_) - : value(value_) {} + VisibleTimeRangeTime(rerun::datatypes::VisibleTimeRange value_) : value(value_) {} - VisibleTimeRangeTime& operator=(rerun::blueprint::datatypes::VisibleTimeRange value_) { + VisibleTimeRangeTime& operator=(rerun::datatypes::VisibleTimeRange value_) { value = value_; return *this; } /// Cast to the underlying VisibleTimeRange datatype - operator rerun::blueprint::datatypes::VisibleTimeRange() const { + operator rerun::datatypes::VisibleTimeRange() const { return value; } }; @@ -34,7 +33,7 @@ namespace rerun::blueprint::components { namespace rerun { static_assert( - sizeof(rerun::blueprint::datatypes::VisibleTimeRange) == + sizeof(rerun::datatypes::VisibleTimeRange) == sizeof(blueprint::components::VisibleTimeRangeTime) ); @@ -45,14 +44,14 @@ namespace rerun { /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype() { - return Loggable::arrow_datatype(); + return Loggable::arrow_datatype(); } /// Serializes an array of `rerun::blueprint:: components::VisibleTimeRangeTime` into an arrow array. static Result> to_arrow( const blueprint::components::VisibleTimeRangeTime* instances, size_t num_instances ) { - return Loggable::to_arrow( + return Loggable::to_arrow( &instances->value, num_instances ); diff --git a/rerun_cpp/src/rerun/blueprint/datatypes.hpp b/rerun_cpp/src/rerun/blueprint/datatypes.hpp deleted file mode 100644 index 361e00061d0e..000000000000 --- a/rerun_cpp/src/rerun/blueprint/datatypes.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs - -#pragma once - -#include "blueprint/datatypes/visible_time_range.hpp" -#include "blueprint/datatypes/visible_time_range_boundary.hpp" -#include "blueprint/datatypes/visible_time_range_boundary_kind.hpp" diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes b/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes deleted file mode 100644 index 06328369afaa..000000000000 --- a/rerun_cpp/src/rerun/blueprint/datatypes/.gitattributes +++ /dev/null @@ -1,9 +0,0 @@ -# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs - -.gitattributes linguist-generated=true -visible_time_range.cpp linguist-generated=true -visible_time_range.hpp linguist-generated=true -visible_time_range_boundary.cpp linguist-generated=true -visible_time_range_boundary.hpp linguist-generated=true -visible_time_range_boundary_kind.cpp linguist-generated=true -visible_time_range_boundary_kind.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/datatypes.hpp b/rerun_cpp/src/rerun/datatypes.hpp index cc2784d3fc5c..df46efde30ee 100644 --- a/rerun_cpp/src/rerun/datatypes.hpp +++ b/rerun_cpp/src/rerun/datatypes.hpp @@ -40,3 +40,6 @@ #include "datatypes/vec2d.hpp" #include "datatypes/vec3d.hpp" #include "datatypes/vec4d.hpp" +#include "datatypes/visible_time_range.hpp" +#include "datatypes/visible_time_range_boundary.hpp" +#include "datatypes/visible_time_range_boundary_kind.hpp" diff --git a/rerun_cpp/src/rerun/datatypes/.gitattributes b/rerun_cpp/src/rerun/datatypes/.gitattributes index 4170301018d2..2aaeef55cca7 100644 --- a/rerun_cpp/src/rerun/datatypes/.gitattributes +++ b/rerun_cpp/src/rerun/datatypes/.gitattributes @@ -77,3 +77,9 @@ vec3d.cpp linguist-generated=true vec3d.hpp linguist-generated=true vec4d.cpp linguist-generated=true vec4d.hpp linguist-generated=true +visible_time_range.cpp linguist-generated=true +visible_time_range.hpp linguist-generated=true +visible_time_range_boundary.cpp linguist-generated=true +visible_time_range_boundary.hpp linguist-generated=true +visible_time_range_boundary_kind.cpp linguist-generated=true +visible_time_range_boundary_kind.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp b/rerun_cpp/src/rerun/datatypes/visible_time_range.cpp similarity index 59% rename from rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp rename to rerun_cpp/src/rerun/datatypes/visible_time_range.cpp index d4a26678aa7b..a67c84d05339 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.cpp +++ b/rerun_cpp/src/rerun/datatypes/visible_time_range.cpp @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #include "visible_time_range.hpp" @@ -8,51 +8,48 @@ #include #include -namespace rerun::blueprint::datatypes {} +namespace rerun::datatypes {} namespace rerun { - const std::shared_ptr& - Loggable::arrow_datatype() { + const std::shared_ptr& Loggable::arrow_datatype( + ) { static const auto datatype = arrow::struct_({ arrow::field( "start", - Loggable::arrow_datatype(), + Loggable::arrow_datatype(), false ), arrow::field( "end", - Loggable::arrow_datatype(), + Loggable::arrow_datatype(), false ), }); return datatype; } - Result> - Loggable::to_arrow( - const blueprint::datatypes::VisibleTimeRange* instances, size_t num_instances - ) { + Result> Loggable::to_arrow( + const datatypes::VisibleTimeRange* instances, size_t num_instances + ) { // TODO(andreas): Allow configuring the memory pool. arrow::MemoryPool* pool = arrow::default_memory_pool(); auto datatype = arrow_datatype(); ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) if (instances && num_instances > 0) { - RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - ) - ); + RR_RETURN_NOT_OK(Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + )); } std::shared_ptr array; ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, const blueprint::datatypes::VisibleTimeRange* elements, + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const datatypes::VisibleTimeRange* elements, size_t num_elements ) { if (builder == nullptr) { @@ -70,8 +67,11 @@ namespace rerun { ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { RR_RETURN_NOT_OK( - Loggable:: - fill_arrow_array_builder(field_builder, &elements[elem_idx].start, 1) + Loggable::fill_arrow_array_builder( + field_builder, + &elements[elem_idx].start, + 1 + ) ); } } @@ -80,8 +80,11 @@ namespace rerun { ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { RR_RETURN_NOT_OK( - Loggable:: - fill_arrow_array_builder(field_builder, &elements[elem_idx].end, 1) + Loggable::fill_arrow_array_builder( + field_builder, + &elements[elem_idx].end, + 1 + ) ); } } diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp b/rerun_cpp/src/rerun/datatypes/visible_time_range.hpp similarity index 59% rename from rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp rename to rerun_cpp/src/rerun/datatypes/visible_time_range.hpp index 8befacc65f8b..caf87a5dd866 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range.hpp +++ b/rerun_cpp/src/rerun/datatypes/visible_time_range.hpp @@ -1,9 +1,9 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #pragma once -#include "../../result.hpp" +#include "../result.hpp" #include "visible_time_range_boundary.hpp" #include @@ -15,21 +15,21 @@ namespace arrow { class StructBuilder; } // namespace arrow -namespace rerun::blueprint::datatypes { +namespace rerun::datatypes { /// **Datatype**: Visible time range bounds for a timelines. /// /// This datatype does not specify whether it's a time or sequence based timeline. struct VisibleTimeRange { /// Low time boundary for sequence timeline. - rerun::blueprint::datatypes::VisibleTimeRangeBoundary start; + rerun::datatypes::VisibleTimeRangeBoundary start; /// High time boundary for sequence timeline. - rerun::blueprint::datatypes::VisibleTimeRangeBoundary end; + rerun::datatypes::VisibleTimeRangeBoundary end; public: VisibleTimeRange() = default; }; -} // namespace rerun::blueprint::datatypes +} // namespace rerun::datatypes namespace rerun { template @@ -37,20 +37,20 @@ namespace rerun { /// \private template <> - struct Loggable { - static constexpr const char Name[] = "rerun.blueprint.datatypes.VisibleTimeRange"; + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.VisibleTimeRange"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRange` into an arrow array. + /// Serializes an array of `rerun::datatypes::VisibleTimeRange` into an arrow array. static Result> to_arrow( - const blueprint::datatypes::VisibleTimeRange* instances, size_t num_instances + const datatypes::VisibleTimeRange* instances, size_t num_instances ); /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, const blueprint::datatypes::VisibleTimeRange* elements, + arrow::StructBuilder* builder, const datatypes::VisibleTimeRange* elements, size_t num_elements ); }; diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp b/rerun_cpp/src/rerun/datatypes/visible_time_range_boundary.cpp similarity index 72% rename from rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp rename to rerun_cpp/src/rerun/datatypes/visible_time_range_boundary.cpp index 6e4820a69c1f..86f31c06edcf 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.cpp +++ b/rerun_cpp/src/rerun/datatypes/visible_time_range_boundary.cpp @@ -1,24 +1,23 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #include "visible_time_range_boundary.hpp" -#include "../../datatypes/time_int.hpp" +#include "time_int.hpp" #include "visible_time_range_boundary_kind.hpp" #include #include -namespace rerun::blueprint::datatypes {} +namespace rerun::datatypes {} namespace rerun { const std::shared_ptr& - Loggable::arrow_datatype() { + Loggable::arrow_datatype() { static const auto datatype = arrow::struct_({ arrow::field( "kind", - Loggable::arrow_datatype( - ), + Loggable::arrow_datatype(), false ), arrow::field("time", Loggable::arrow_datatype(), false), @@ -26,10 +25,9 @@ namespace rerun { return datatype; } - Result> - Loggable::to_arrow( - const blueprint::datatypes::VisibleTimeRangeBoundary* instances, size_t num_instances - ) { + Result> Loggable::to_arrow( + const datatypes::VisibleTimeRangeBoundary* instances, size_t num_instances + ) { // TODO(andreas): Allow configuring the memory pool. arrow::MemoryPool* pool = arrow::default_memory_pool(); auto datatype = arrow_datatype(); @@ -37,7 +35,7 @@ namespace rerun { ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) if (instances && num_instances > 0) { RR_RETURN_NOT_OK( - Loggable::fill_arrow_array_builder( + Loggable::fill_arrow_array_builder( static_cast(builder.get()), instances, num_instances @@ -49,9 +47,9 @@ namespace rerun { return array; } - rerun::Error Loggable::fill_arrow_array_builder( - arrow::StructBuilder* builder, - const blueprint::datatypes::VisibleTimeRangeBoundary* elements, size_t num_elements + rerun::Error Loggable::fill_arrow_array_builder( + arrow::StructBuilder* builder, const datatypes::VisibleTimeRangeBoundary* elements, + size_t num_elements ) { if (builder == nullptr) { return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); @@ -68,7 +66,7 @@ namespace rerun { ARROW_RETURN_NOT_OK(field_builder->Reserve(static_cast(num_elements))); for (size_t elem_idx = 0; elem_idx < num_elements; elem_idx += 1) { RR_RETURN_NOT_OK( - Loggable:: + Loggable:: fill_arrow_array_builder(field_builder, &elements[elem_idx].kind, 1) ); } diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp b/rerun_cpp/src/rerun/datatypes/visible_time_range_boundary.hpp similarity index 56% rename from rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp rename to rerun_cpp/src/rerun/datatypes/visible_time_range_boundary.hpp index 317bf804ec91..14a9893cc02e 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary.hpp +++ b/rerun_cpp/src/rerun/datatypes/visible_time_range_boundary.hpp @@ -1,10 +1,10 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #pragma once -#include "../../datatypes/time_int.hpp" -#include "../../result.hpp" +#include "../result.hpp" +#include "time_int.hpp" #include "visible_time_range_boundary_kind.hpp" #include @@ -16,11 +16,11 @@ namespace arrow { class StructBuilder; } // namespace arrow -namespace rerun::blueprint::datatypes { +namespace rerun::datatypes { /// **Datatype**: Type of boundary for visible history. struct VisibleTimeRangeBoundary { /// Type of the boundary. - rerun::blueprint::datatypes::VisibleTimeRangeBoundaryKind kind; + rerun::datatypes::VisibleTimeRangeBoundaryKind kind; /// Value of the boundary (ignored for `Infinite` type). rerun::datatypes::TimeInt time; @@ -28,7 +28,7 @@ namespace rerun::blueprint::datatypes { public: VisibleTimeRangeBoundary() = default; }; -} // namespace rerun::blueprint::datatypes +} // namespace rerun::datatypes namespace rerun { template @@ -36,21 +36,21 @@ namespace rerun { /// \private template <> - struct Loggable { - static constexpr const char Name[] = "rerun.blueprint.datatypes.VisibleTimeRangeBoundary"; + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.VisibleTimeRangeBoundary"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRangeBoundary` into an arrow array. + /// Serializes an array of `rerun::datatypes::VisibleTimeRangeBoundary` into an arrow array. static Result> to_arrow( - const blueprint::datatypes::VisibleTimeRangeBoundary* instances, size_t num_instances + const datatypes::VisibleTimeRangeBoundary* instances, size_t num_instances ); /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( - arrow::StructBuilder* builder, - const blueprint::datatypes::VisibleTimeRangeBoundary* elements, size_t num_elements + arrow::StructBuilder* builder, const datatypes::VisibleTimeRangeBoundary* elements, + size_t num_elements ); }; } // namespace rerun diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp b/rerun_cpp/src/rerun/datatypes/visible_time_range_boundary_kind.cpp similarity index 63% rename from rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp rename to rerun_cpp/src/rerun/datatypes/visible_time_range_boundary_kind.cpp index 08a67a5061bf..6ba9eb85e5ce 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.cpp +++ b/rerun_cpp/src/rerun/datatypes/visible_time_range_boundary_kind.cpp @@ -1,5 +1,5 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #include "visible_time_range_boundary_kind.hpp" @@ -8,7 +8,7 @@ namespace rerun { const std::shared_ptr& - Loggable::arrow_datatype() { + Loggable::arrow_datatype() { static const auto datatype = arrow::sparse_union({ arrow::field("_null_markers", arrow::null(), true, nullptr), arrow::field("RelativeToTimeCursor", arrow::null(), true), @@ -19,9 +19,8 @@ namespace rerun { } Result> - Loggable::to_arrow( - const blueprint::datatypes::VisibleTimeRangeBoundaryKind* instances, - size_t num_instances + Loggable::to_arrow( + const datatypes::VisibleTimeRangeBoundaryKind* instances, size_t num_instances ) { // TODO(andreas): Allow configuring the memory pool. arrow::MemoryPool* pool = arrow::default_memory_pool(); @@ -29,23 +28,23 @@ namespace rerun { ARROW_ASSIGN_OR_RAISE(auto builder, arrow::MakeBuilder(datatype, pool)) if (instances && num_instances > 0) { - RR_RETURN_NOT_OK(Loggable:: - fill_arrow_array_builder( - static_cast(builder.get()), - instances, - num_instances - )); + RR_RETURN_NOT_OK( + Loggable::fill_arrow_array_builder( + static_cast(builder.get()), + instances, + num_instances + ) + ); } std::shared_ptr array; ARROW_RETURN_NOT_OK(builder->Finish(&array)); return array; } - rerun::Error - Loggable::fill_arrow_array_builder( - arrow::SparseUnionBuilder* builder, - const blueprint::datatypes::VisibleTimeRangeBoundaryKind* elements, size_t num_elements - ) { + rerun::Error Loggable::fill_arrow_array_builder( + arrow::SparseUnionBuilder* builder, const datatypes::VisibleTimeRangeBoundaryKind* elements, + size_t num_elements + ) { if (builder == nullptr) { return rerun::Error(ErrorCode::UnexpectedNullArgument, "Passed array builder is null."); } diff --git a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp b/rerun_cpp/src/rerun/datatypes/visible_time_range_boundary_kind.hpp similarity index 61% rename from rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp rename to rerun_cpp/src/rerun/datatypes/visible_time_range_boundary_kind.hpp index 59025d01da86..3a97f7d1a1cc 100644 --- a/rerun_cpp/src/rerun/blueprint/datatypes/visible_time_range_boundary_kind.hpp +++ b/rerun_cpp/src/rerun/datatypes/visible_time_range_boundary_kind.hpp @@ -1,9 +1,9 @@ // DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/cpp/mod.rs -// Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +// Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". #pragma once -#include "../../result.hpp" +#include "../result.hpp" #include #include @@ -14,7 +14,7 @@ namespace arrow { class SparseUnionBuilder; } // namespace arrow -namespace rerun::blueprint::datatypes { +namespace rerun::datatypes { /// **Datatype**: Kind of boundary for visible history, see `VisibleTimeRangeBoundary`. enum class VisibleTimeRangeBoundaryKind : uint8_t { @@ -27,7 +27,7 @@ namespace rerun::blueprint::datatypes { /// The boundary extends to infinity. Infinite = 3, }; -} // namespace rerun::blueprint::datatypes +} // namespace rerun::datatypes namespace rerun { template @@ -35,23 +35,21 @@ namespace rerun { /// \private template <> - struct Loggable { - static constexpr const char Name[] = - "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind"; + struct Loggable { + static constexpr const char Name[] = "rerun.datatypes.VisibleTimeRangeBoundaryKind"; /// Returns the arrow data type this type corresponds to. static const std::shared_ptr& arrow_datatype(); - /// Serializes an array of `rerun::blueprint:: datatypes::VisibleTimeRangeBoundaryKind` into an arrow array. + /// Serializes an array of `rerun::datatypes::VisibleTimeRangeBoundaryKind` into an arrow array. static Result> to_arrow( - const blueprint::datatypes::VisibleTimeRangeBoundaryKind* instances, - size_t num_instances + const datatypes::VisibleTimeRangeBoundaryKind* instances, size_t num_instances ); /// Fills an arrow array builder with an array of this type. static rerun::Error fill_arrow_array_builder( arrow::SparseUnionBuilder* builder, - const blueprint::datatypes::VisibleTimeRangeBoundaryKind* elements, size_t num_elements + const datatypes::VisibleTimeRangeBoundaryKind* elements, size_t num_elements ); }; } // namespace rerun diff --git a/rerun_py/docs/gen_common_index.py b/rerun_py/docs/gen_common_index.py index b1a152ef47cd..5a8d7fd66aa8 100755 --- a/rerun_py/docs/gen_common_index.py +++ b/rerun_py/docs/gen_common_index.py @@ -271,12 +271,6 @@ class Section: Section( title="Blueprint", sub_title="Components", - mod_path="rerun.blueprint.datatypes", - show_tables=False, - ), - Section( - title="Blueprint", - sub_title="Datatypes", mod_path="rerun.blueprint.components", show_tables=False, ), diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 4ffdc2a1de2d..5d901d926788 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -71,6 +71,8 @@ TensorData, TranslationAndMat3x3, TranslationRotationScale3D, + VisibleTimeRangeBoundary, + VisibleTimeRangeBoundaryKind, ) from .error_utils import set_strict_mode from .logging_handler import LoggingHandler diff --git a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py index d769547b059f..41a04bfabf02 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/__init__.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/__init__.py @@ -1,6 +1,6 @@ from __future__ import annotations -from . import archetypes, components, datatypes +from . import archetypes, components from .api import ( Blueprint, BlueprintLike, @@ -25,7 +25,6 @@ LockRangeDuringZoom, ) from .containers import Grid, Horizontal, Tabs, Vertical -from .datatypes import VisibleTimeRangeBoundary, VisibleTimeRangeBoundaryKind from .views import ( BarChartView, Spatial2DView, diff --git a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_range.py index 4a09cf0aaf36..af17597efdcb 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_range.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/archetypes/visible_time_range.py @@ -9,9 +9,9 @@ from attrs import define, field +from ... import datatypes from ..._baseclasses import Archetype from ...blueprint import components as blueprint_components -from ...blueprint import datatypes as blueprint_datatypes from ...error_utils import catch_and_log_exceptions __all__ = ["VisibleTimeRange"] @@ -36,8 +36,8 @@ class VisibleTimeRange(Archetype): def __init__( self: Any, *, - sequence: blueprint_datatypes.VisibleTimeRangeLike | None = None, - time: blueprint_datatypes.VisibleTimeRangeLike | None = None, + sequence: datatypes.VisibleTimeRangeLike | None = None, + time: datatypes.VisibleTimeRangeLike | None = None, ): """ Create a new instance of the VisibleTimeRange archetype. diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_sequence.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_sequence.py index b1b743a16b6f..3e295c72153b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_sequence.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_sequence.py @@ -5,13 +5,13 @@ from __future__ import annotations +from ... import datatypes from ..._baseclasses import ComponentBatchMixin -from ...blueprint import datatypes as blueprint_datatypes __all__ = ["VisibleTimeRangeSequence", "VisibleTimeRangeSequenceBatch", "VisibleTimeRangeSequenceType"] -class VisibleTimeRangeSequence(blueprint_datatypes.VisibleTimeRange): +class VisibleTimeRangeSequence(datatypes.VisibleTimeRange): """**Component**: The range of values on time timelines that will be included in a space view query.""" # You can define your own __init__ function as a member of VisibleTimeRangeSequenceExt in visible_time_range_sequence_ext.py @@ -20,9 +20,9 @@ class VisibleTimeRangeSequence(blueprint_datatypes.VisibleTimeRange): pass -class VisibleTimeRangeSequenceType(blueprint_datatypes.VisibleTimeRangeType): +class VisibleTimeRangeSequenceType(datatypes.VisibleTimeRangeType): _TYPE_NAME: str = "rerun.blueprint.components.VisibleTimeRangeSequence" -class VisibleTimeRangeSequenceBatch(blueprint_datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): +class VisibleTimeRangeSequenceBatch(datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): _ARROW_TYPE = VisibleTimeRangeSequenceType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_time.py b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_time.py index b83c8a2e642a..ac93cab2e3ea 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_time.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/visible_time_range_time.py @@ -5,13 +5,13 @@ from __future__ import annotations +from ... import datatypes from ..._baseclasses import ComponentBatchMixin -from ...blueprint import datatypes as blueprint_datatypes __all__ = ["VisibleTimeRangeTime", "VisibleTimeRangeTimeBatch", "VisibleTimeRangeTimeType"] -class VisibleTimeRangeTime(blueprint_datatypes.VisibleTimeRange): +class VisibleTimeRangeTime(datatypes.VisibleTimeRange): """**Component**: The range of values on sequence timelines that will be included in a space view query.""" # You can define your own __init__ function as a member of VisibleTimeRangeTimeExt in visible_time_range_time_ext.py @@ -20,9 +20,9 @@ class VisibleTimeRangeTime(blueprint_datatypes.VisibleTimeRange): pass -class VisibleTimeRangeTimeType(blueprint_datatypes.VisibleTimeRangeType): +class VisibleTimeRangeTimeType(datatypes.VisibleTimeRangeType): _TYPE_NAME: str = "rerun.blueprint.components.VisibleTimeRangeTime" -class VisibleTimeRangeTimeBatch(blueprint_datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): +class VisibleTimeRangeTimeBatch(datatypes.VisibleTimeRangeBatch, ComponentBatchMixin): _ARROW_TYPE = VisibleTimeRangeTimeType() diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes deleted file mode 100644 index 5f25eb77dacd..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/.gitattributes +++ /dev/null @@ -1,7 +0,0 @@ -# DO NOT EDIT! This file is generated by crates/re_types_builder/src/lib.rs - -.gitattributes linguist-generated=true -__init__.py linguist-generated=true -visible_time_range.py linguist-generated=true -visible_time_range_boundary.py linguist-generated=true -visible_time_range_boundary_kind.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py deleted file mode 100644 index cfcebd2abc65..000000000000 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/__init__.py +++ /dev/null @@ -1,43 +0,0 @@ -# DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs - -from __future__ import annotations - -from .visible_time_range import ( - VisibleTimeRange, - VisibleTimeRangeArrayLike, - VisibleTimeRangeBatch, - VisibleTimeRangeLike, - VisibleTimeRangeType, -) -from .visible_time_range_boundary import ( - VisibleTimeRangeBoundary, - VisibleTimeRangeBoundaryArrayLike, - VisibleTimeRangeBoundaryBatch, - VisibleTimeRangeBoundaryLike, - VisibleTimeRangeBoundaryType, -) -from .visible_time_range_boundary_kind import ( - VisibleTimeRangeBoundaryKind, - VisibleTimeRangeBoundaryKindArrayLike, - VisibleTimeRangeBoundaryKindBatch, - VisibleTimeRangeBoundaryKindLike, - VisibleTimeRangeBoundaryKindType, -) - -__all__ = [ - "VisibleTimeRange", - "VisibleTimeRangeArrayLike", - "VisibleTimeRangeBatch", - "VisibleTimeRangeBoundary", - "VisibleTimeRangeBoundaryArrayLike", - "VisibleTimeRangeBoundaryBatch", - "VisibleTimeRangeBoundaryKind", - "VisibleTimeRangeBoundaryKindArrayLike", - "VisibleTimeRangeBoundaryKindBatch", - "VisibleTimeRangeBoundaryKindLike", - "VisibleTimeRangeBoundaryKindType", - "VisibleTimeRangeBoundaryLike", - "VisibleTimeRangeBoundaryType", - "VisibleTimeRangeLike", - "VisibleTimeRangeType", -] diff --git a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes index 1cab4659e6a6..06cab7b213d5 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/datatypes/.gitattributes @@ -40,3 +40,6 @@ uvec4d.py linguist-generated=true vec2d.py linguist-generated=true vec3d.py linguist-generated=true vec4d.py linguist-generated=true +visible_time_range.py linguist-generated=true +visible_time_range_boundary.py linguist-generated=true +visible_time_range_boundary_kind.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py index bf33b417cbaf..4a0a726dd196 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/__init__.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/__init__.py @@ -88,6 +88,27 @@ from .vec2d import Vec2D, Vec2DArrayLike, Vec2DBatch, Vec2DLike, Vec2DType from .vec3d import Vec3D, Vec3DArrayLike, Vec3DBatch, Vec3DLike, Vec3DType from .vec4d import Vec4D, Vec4DArrayLike, Vec4DBatch, Vec4DLike, Vec4DType +from .visible_time_range import ( + VisibleTimeRange, + VisibleTimeRangeArrayLike, + VisibleTimeRangeBatch, + VisibleTimeRangeLike, + VisibleTimeRangeType, +) +from .visible_time_range_boundary import ( + VisibleTimeRangeBoundary, + VisibleTimeRangeBoundaryArrayLike, + VisibleTimeRangeBoundaryBatch, + VisibleTimeRangeBoundaryLike, + VisibleTimeRangeBoundaryType, +) +from .visible_time_range_boundary_kind import ( + VisibleTimeRangeBoundaryKind, + VisibleTimeRangeBoundaryKindArrayLike, + VisibleTimeRangeBoundaryKindBatch, + VisibleTimeRangeBoundaryKindLike, + VisibleTimeRangeBoundaryKindType, +) __all__ = [ "Angle", @@ -280,4 +301,19 @@ "Vec4DBatch", "Vec4DLike", "Vec4DType", + "VisibleTimeRange", + "VisibleTimeRangeArrayLike", + "VisibleTimeRangeBatch", + "VisibleTimeRangeBoundary", + "VisibleTimeRangeBoundaryArrayLike", + "VisibleTimeRangeBoundaryBatch", + "VisibleTimeRangeBoundaryKind", + "VisibleTimeRangeBoundaryKindArrayLike", + "VisibleTimeRangeBoundaryKindBatch", + "VisibleTimeRangeBoundaryKindLike", + "VisibleTimeRangeBoundaryKindType", + "VisibleTimeRangeBoundaryLike", + "VisibleTimeRangeBoundaryType", + "VisibleTimeRangeLike", + "VisibleTimeRangeType", ] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py b/rerun_py/rerun_sdk/rerun/datatypes/visible_time_range.py similarity index 86% rename from rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py rename to rerun_py/rerun_sdk/rerun/datatypes/visible_time_range.py index 6b1eae02178c..e11d04eef17b 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/visible_time_range.py @@ -1,5 +1,5 @@ # DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +# Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". # You can extend this class by creating a "VisibleTimeRangeExt" class in "visible_time_range_ext.py". @@ -10,8 +10,8 @@ import pyarrow as pa from attrs import define, field -from ..._baseclasses import BaseBatch, BaseExtensionType -from ...blueprint import datatypes as blueprint_datatypes +from .. import datatypes +from .._baseclasses import BaseBatch, BaseExtensionType __all__ = [ "VisibleTimeRange", @@ -30,11 +30,7 @@ class VisibleTimeRange: This datatype does not specify whether it's a time or sequence based timeline. """ - def __init__( - self: Any, - start: blueprint_datatypes.VisibleTimeRangeBoundaryLike, - end: blueprint_datatypes.VisibleTimeRangeBoundaryLike, - ): + def __init__(self: Any, start: datatypes.VisibleTimeRangeBoundaryLike, end: datatypes.VisibleTimeRangeBoundaryLike): """ Create a new instance of the VisibleTimeRange datatype. @@ -50,12 +46,12 @@ def __init__( # You can define your own __init__ function as a member of VisibleTimeRangeExt in visible_time_range_ext.py self.__attrs_init__(start=start, end=end) - start: blueprint_datatypes.VisibleTimeRangeBoundary = field() + start: datatypes.VisibleTimeRangeBoundary = field() # Low time boundary for sequence timeline. # # (Docstring intentionally commented out to hide this field from the docs) - end: blueprint_datatypes.VisibleTimeRangeBoundary = field() + end: datatypes.VisibleTimeRangeBoundary = field() # High time boundary for sequence timeline. # # (Docstring intentionally commented out to hide this field from the docs) @@ -69,7 +65,7 @@ def __init__( class VisibleTimeRangeType(BaseExtensionType): - _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRange" + _TYPE_NAME: str = "rerun.datatypes.VisibleTimeRange" def __init__(self) -> None: pa.ExtensionType.__init__( @@ -123,7 +119,7 @@ class VisibleTimeRangeBatch(BaseBatch[VisibleTimeRangeArrayLike]): @staticmethod def _native_to_pa_array(data: VisibleTimeRangeArrayLike, data_type: pa.DataType) -> pa.Array: - from rerun.blueprint.datatypes import VisibleTimeRangeBoundaryBatch + from rerun.datatypes import VisibleTimeRangeBoundaryBatch if isinstance(data, VisibleTimeRange): data = [data] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py b/rerun_py/rerun_sdk/rerun/datatypes/visible_time_range_boundary.py similarity index 84% rename from rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py rename to rerun_py/rerun_sdk/rerun/datatypes/visible_time_range_boundary.py index c0813717e445..cd174d514d6c 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/visible_time_range_boundary.py @@ -1,5 +1,5 @@ # DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +# Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". # You can extend this class by creating a "VisibleTimeRangeBoundaryExt" class in "visible_time_range_boundary_ext.py". @@ -10,9 +10,8 @@ import pyarrow as pa from attrs import define, field -from ... import datatypes -from ..._baseclasses import BaseBatch, BaseExtensionType -from ...blueprint import datatypes as blueprint_datatypes +from .. import datatypes +from .._baseclasses import BaseBatch, BaseExtensionType __all__ = [ "VisibleTimeRangeBoundary", @@ -34,7 +33,7 @@ def _visible_time_range_boundary__time__special_field_converter_override(x: data class VisibleTimeRangeBoundary: """**Datatype**: Type of boundary for visible history.""" - def __init__(self: Any, kind: blueprint_datatypes.VisibleTimeRangeBoundaryKindLike, time: datatypes.TimeIntLike): + def __init__(self: Any, kind: datatypes.VisibleTimeRangeBoundaryKindLike, time: datatypes.TimeIntLike): """ Create a new instance of the VisibleTimeRangeBoundary datatype. @@ -50,7 +49,7 @@ def __init__(self: Any, kind: blueprint_datatypes.VisibleTimeRangeBoundaryKindLi # You can define your own __init__ function as a member of VisibleTimeRangeBoundaryExt in visible_time_range_boundary_ext.py self.__attrs_init__(kind=kind, time=time) - kind: blueprint_datatypes.VisibleTimeRangeBoundaryKind = field() + kind: datatypes.VisibleTimeRangeBoundaryKind = field() # Type of the boundary. # # (Docstring intentionally commented out to hide this field from the docs) @@ -69,7 +68,7 @@ def __init__(self: Any, kind: blueprint_datatypes.VisibleTimeRangeBoundaryKindLi class VisibleTimeRangeBoundaryType(BaseExtensionType): - _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRangeBoundary" + _TYPE_NAME: str = "rerun.datatypes.VisibleTimeRangeBoundary" def __init__(self) -> None: pa.ExtensionType.__init__( @@ -97,8 +96,7 @@ class VisibleTimeRangeBoundaryBatch(BaseBatch[VisibleTimeRangeBoundaryArrayLike] @staticmethod def _native_to_pa_array(data: VisibleTimeRangeBoundaryArrayLike, data_type: pa.DataType) -> pa.Array: - from rerun.blueprint.datatypes import VisibleTimeRangeBoundaryKindBatch - from rerun.datatypes import TimeIntBatch + from rerun.datatypes import TimeIntBatch, VisibleTimeRangeBoundaryKindBatch if isinstance(data, VisibleTimeRangeBoundary): data = [data] diff --git a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py b/rerun_py/rerun_sdk/rerun/datatypes/visible_time_range_boundary_kind.py similarity index 93% rename from rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py rename to rerun_py/rerun_sdk/rerun/datatypes/visible_time_range_boundary_kind.py index 72a218b1b3fd..1a326c22814c 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/datatypes/visible_time_range_boundary_kind.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/visible_time_range_boundary_kind.py @@ -1,5 +1,5 @@ # DO NOT EDIT! This file was auto-generated by crates/re_types_builder/src/codegen/python/mod.rs -# Based on "crates/re_types/definitions/rerun/blueprint/datatypes/visible_time_range.fbs". +# Based on "crates/re_types/definitions/rerun/datatypes/visible_time_range.fbs". # You can extend this class by creating a "VisibleTimeRangeBoundaryKindExt" class in "visible_time_range_boundary_kind_ext.py". @@ -9,7 +9,7 @@ import pyarrow as pa -from ..._baseclasses import BaseBatch, BaseExtensionType +from .._baseclasses import BaseBatch, BaseExtensionType __all__ = [ "VisibleTimeRangeBoundaryKind", @@ -43,7 +43,7 @@ class VisibleTimeRangeBoundaryKind(Enum): class VisibleTimeRangeBoundaryKindType(BaseExtensionType): - _TYPE_NAME: str = "rerun.blueprint.datatypes.VisibleTimeRangeBoundaryKind" + _TYPE_NAME: str = "rerun.datatypes.VisibleTimeRangeBoundaryKind" def __init__(self) -> None: pa.ExtensionType.__init__( From 3f56408ab6b9ede58e7792c8eca6255899c5724d Mon Sep 17 00:00:00 2001 From: Alexander Berntsson Date: Tue, 30 Apr 2024 23:17:31 +0200 Subject: [PATCH 400/508] Add DROID dataset example (#6149) --- examples/manifest.toml | 1 + examples/python/droid_dataset/README.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 examples/python/droid_dataset/README.md diff --git a/examples/manifest.toml b/examples/manifest.toml index e07bf505659c..8aa52e47c122 100644 --- a/examples/manifest.toml +++ b/examples/manifest.toml @@ -32,6 +32,7 @@ Examples related to robotics, autonomous systems, and interfacing with sensor ha """ examples = [ # display order, most interesting first + "droid_dataset", "ros_node", "nuscenes_dataset", "ros2_bridge", diff --git a/examples/python/droid_dataset/README.md b/examples/python/droid_dataset/README.md new file mode 100644 index 000000000000..82bb2738064b --- /dev/null +++ b/examples/python/droid_dataset/README.md @@ -0,0 +1,19 @@ + + +This example visualizes the [DROID dataset](https://droid-dataset.github.io/). + +https://vimeo.com/940717540?autoplay=1&loop=1&autopause=0&background=1&muted=1&ratio=1920:1080 + +## Background + +DROID is a robot manipulation dataset collected over a diverse set of environments that can be used to train robotic manipulation policies. The dataset contains sensor data from each joint of the robot as well as video footage from 3 stereo cameras located on wrist and on either side of the arm. In each frame it also stores the action taken which is the target position and velocity given by the teleoperator. + +## Run the code + +You can find the build instructions here: [python-example-droid-dataset](https://github.com/rerun-io/python-example-droid-dataset) From f7a1808050b9bfc9b86505b9073c707c1c4e5467 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Thu, 2 May 2024 09:42:31 +0200 Subject: [PATCH 401/508] Remove `datagen` (#6152) **_finally_** - Fixes #1810 --- Cargo.lock | 1 - crates/re_data_store/Cargo.toml | 2 +- crates/re_data_store/benches/arrow2.rs | 18 +- crates/re_data_store/tests/correctness.rs | 7 +- crates/re_data_store/tests/data_store.rs | 163 +++++++++--------- crates/re_data_store/tests/dump.rs | 20 +-- crates/re_entity_db/Cargo.toml | 2 +- crates/re_entity_db/examples/memory_usage.rs | 7 +- crates/re_log_encoding/Cargo.toml | 2 +- .../benches/msg_encode_benchmark.rs | 14 +- crates/re_log_types/src/example_components.rs | 18 ++ crates/re_query/Cargo.toml | 2 - crates/re_types/Cargo.toml | 5 - crates/re_types/src/datagen.rs | 38 ---- crates/re_types/src/lib.rs | 3 - 15 files changed, 131 insertions(+), 171 deletions(-) delete mode 100644 crates/re_types/src/datagen.rs diff --git a/Cargo.lock b/Cargo.lock index 3bfdd42d9cbd..2e105d003189 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4871,7 +4871,6 @@ dependencies = [ "nohash-hasher", "once_cell", "ply-rs", - "rand", "rayon", "re_arrow2", "re_build_tools", diff --git a/crates/re_data_store/Cargo.toml b/crates/re_data_store/Cargo.toml index a81e47ecf21d..4176edb5bea1 100644 --- a/crates/re_data_store/Cargo.toml +++ b/crates/re_data_store/Cargo.toml @@ -51,7 +51,7 @@ web-time.workspace = true [dev-dependencies] re_format.workspace = true -re_types = { workspace = true, features = ["datagen", "testing"] } +re_types = { workspace = true, features = ["testing"] } anyhow.workspace = true criterion.workspace = true diff --git a/crates/re_data_store/benches/arrow2.rs b/crates/re_data_store/benches/arrow2.rs index 236e3db60c3f..256c83983bfc 100644 --- a/crates/re_data_store/benches/arrow2.rs +++ b/crates/re_data_store/benches/arrow2.rs @@ -9,13 +9,9 @@ use arrow2::array::{Array, FixedSizeListArray, PrimitiveArray, StructArray}; use criterion::Criterion; use itertools::Itertools; -use re_log_types::example_components::MyIndex; +use re_log_types::example_components::{MyIndex, MyPoint}; use re_log_types::DataCell; -use re_types::datagen::build_some_positions2d; -use re_types::{ - components::Position2D, - testing::{build_some_large_structs, LargeStruct}, -}; +use re_types::testing::{build_some_large_structs, LargeStruct}; use re_types_core::{Component, SizeBytes}; // --- @@ -85,7 +81,7 @@ fn erased_clone(c: &mut Criterion) { bench_native(&mut group, &data); } ArrayKind::Struct => { - let data = build_some_positions2d(NUM_INSTANCES); + let data = MyPoint::from_iter(0..NUM_INSTANCES as u32); bench_arrow(&mut group, &data); bench_native(&mut group, &data); } @@ -205,7 +201,9 @@ fn estimated_size_bytes(c: &mut Criterion) { .collect(), ArrayKind::Struct => (0..NUM_ROWS) .map(|_| { - DataCell::from_native(build_some_positions2d(NUM_INSTANCES).as_slice()) + DataCell::from_native( + MyPoint::from_iter(0..NUM_INSTANCES as u32).as_slice(), + ) }) .collect(), ArrayKind::StructLarge => (0..NUM_ROWS) @@ -309,9 +307,9 @@ fn estimated_size_bytes(c: &mut Criterion) { } { - fn generate_positions() -> Vec> { + fn generate_positions() -> Vec> { (0..NUM_ROWS) - .map(|_| build_some_positions2d(NUM_INSTANCES)) + .map(|_| MyPoint::from_iter(0..NUM_INSTANCES as u32)) .collect() } diff --git a/crates/re_data_store/tests/correctness.rs b/crates/re_data_store/tests/correctness.rs index 89119b663c15..50d4245e8d29 100644 --- a/crates/re_data_store/tests/correctness.rs +++ b/crates/re_data_store/tests/correctness.rs @@ -8,12 +8,11 @@ use re_data_store::{ test_row, test_util::sanity_unwrap, DataStore, DataStoreConfig, DataStoreStats, GarbageCollectionOptions, LatestAtQuery, WriteError, }; -use re_log_types::example_components::{MyIndex, MyPoint}; +use re_log_types::example_components::{MyColor, MyIndex, MyPoint}; use re_log_types::{ build_frame_nr, build_log_time, DataRow, Duration, EntityPath, RowId, Time, TimeInt, TimePoint, TimeType, Timeline, }; -use re_types::datagen::{build_some_colors, build_some_positions2d}; use re_types_core::Loggable as _; // --- @@ -206,7 +205,7 @@ fn write_errors() { let mut row = test_row!(entity_path @ [ build_frame_nr(1), build_log_time(Time::now()), - ] => [ build_some_positions2d(1) ]); + ] => [ MyPoint::from_iter(0..1) ]); row.row_id = re_log_types::RowId::new(); store.insert_row(&row).unwrap(); @@ -368,7 +367,7 @@ fn gc_correct() { let row = test_row!(entity_path @ [ build_frame_nr(frame_nr), ] => [ - build_some_colors(num_instances as _), + MyColor::from_iter(0..num_instances), ]); store.insert_row(&row).unwrap(); } diff --git a/crates/re_data_store/tests/data_store.rs b/crates/re_data_store/tests/data_store.rs index 2099b69d46c4..76b8a4db8bcf 100644 --- a/crates/re_data_store/tests/data_store.rs +++ b/crates/re_data_store/tests/data_store.rs @@ -11,17 +11,12 @@ use re_data_store::{ LatestAtQuery, RangeQuery, TimeInt, TimeRange, }; use re_log_types::{ - build_frame_nr, example_components::MyIndex, DataRow, DataTable, EntityPath, TableId, TimeType, - Timeline, -}; -use re_types::{ - components::{Color, Position2D}, - testing::{build_some_large_structs, LargeStruct}, -}; -use re_types::{ - datagen::{build_some_colors, build_some_positions2d}, - ComponentNameSet, + build_frame_nr, + example_components::{MyColor, MyIndex, MyPoint}, + DataRow, DataTable, EntityPath, TableId, TimeType, Timeline, }; +use re_types::testing::{build_some_large_structs, LargeStruct}; +use re_types::ComponentNameSet; use re_types_core::{ComponentName, Loggable as _}; // --- LatestComponentsAt --- @@ -82,17 +77,17 @@ fn all_components() { ); let components_a = &[ - Color::name(), // added by test, static + MyColor::name(), // added by test, static LargeStruct::name(), // added by test ]; let components_b = &[ - Color::name(), // added by test, static - Position2D::name(), // added by test + MyColor::name(), // added by test, static + MyPoint::name(), // added by test LargeStruct::name(), // added by test ]; - let row = test_row!(entity_path => [build_some_colors(2)]); + let row = test_row!(entity_path => [MyColor::from_iter(0..2)]); store.insert_row(&row).unwrap(); let row = @@ -103,7 +98,7 @@ fn all_components() { let row = test_row!(entity_path @ [ build_frame_nr(frame2), - ] => [build_some_large_structs(2), build_some_positions2d(2)]); + ] => [build_some_large_structs(2), MyPoint::from_iter(0..2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_b)); @@ -135,17 +130,17 @@ fn all_components() { // └──────────┴─────────────┴─────────┴────────┴───────────┴──────────┘ let components_a = &[ - Color::name(), // added by test, static + MyColor::name(), // added by test, static LargeStruct::name(), // added by test ]; let components_b = &[ - Color::name(), // added by test, static + MyColor::name(), // added by test, static LargeStruct::name(), // ⚠ inherited before the buckets got split apart! - Position2D::name(), // added by test + MyPoint::name(), // added by test ]; - let row = test_row!(entity_path => [build_some_colors(2)]); + let row = test_row!(entity_path => [MyColor::from_iter(0..2)]); store.insert_row(&row).unwrap(); let row = @@ -154,7 +149,7 @@ fn all_components() { assert_latest_components_at(&mut store, &entity_path, Some(components_a)); - let row = test_row!(entity_path @ [build_frame_nr(frame3)] => [build_some_positions2d(2)]); + let row = test_row!(entity_path @ [build_frame_nr(frame3)] => [MyPoint::from_iter(0..2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_b)); @@ -189,17 +184,17 @@ fn all_components() { // └──────────┴─────────────┴────────┴───────────┴──────────┘ let components_a = &[ - Color::name(), // added by test, static + MyColor::name(), // added by test, static LargeStruct::name(), // added by test ]; let components_b = &[ - Color::name(), // added by test, static - Position2D::name(), // added by test but not contained in the second bucket + MyColor::name(), // added by test, static + MyPoint::name(), // added by test but not contained in the second bucket LargeStruct::name(), // added by test ]; - let row = test_row!(entity_path => [build_some_colors(2)]); + let row = test_row!(entity_path => [MyColor::from_iter(0..2)]); store.insert_row(&row).unwrap(); let row = @@ -220,7 +215,7 @@ fn all_components() { assert_latest_components_at(&mut store, &entity_path, Some(components_a)); - let row = test_row!(entity_path @ [build_frame_nr(frame1)] => [build_some_positions2d(2)]); + let row = test_row!(entity_path @ [build_frame_nr(frame1)] => [MyPoint::from_iter(0..2)]); store.insert_row(&row).unwrap(); assert_latest_components_at(&mut store, &entity_path, Some(components_b)); @@ -255,20 +250,20 @@ fn latest_at_impl(store: &mut DataStore) { let frame3 = TimeInt::new_temporal(3); let frame4 = TimeInt::new_temporal(4); - let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let (instances1, colors1) = (MyIndex::from_iter(0..3), MyColor::from_iter(0..3)); let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => [instances1.clone(), colors1]); - let positions2 = build_some_positions2d(3); + let positions2 = MyPoint::from_iter(0..3); let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => [instances1, positions2]); - let points3 = build_some_positions2d(10); + let points3 = MyPoint::from_iter(0..10); let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => [points3]); - let colors4 = build_some_colors(5); + let colors4 = MyColor::from_iter(0..5); let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => [colors4]); // injecting some static colors - let colors5 = build_some_colors(3); + let colors5 = MyColor::from_iter(0..3); let row5 = test_row!(entity_path => [colors5]); insert_table_with_retries( @@ -328,26 +323,26 @@ fn latest_at_impl(store: &mut DataStore) { assert_latest_components( frame0, &[ - (Color::name(), &row5), // static + (MyColor::name(), &row5), // static ], ); assert_latest_components( frame1, &[ - (Color::name(), &row5), // static + (MyColor::name(), &row5), // static ], ); assert_latest_components( frame2, - &[(Color::name(), &row5), (Position2D::name(), &row2)], + &[(MyColor::name(), &row5), (MyPoint::name(), &row2)], ); assert_latest_components( frame3, - &[(Color::name(), &row5), (Position2D::name(), &row3)], + &[(MyColor::name(), &row5), (MyPoint::name(), &row3)], ); assert_latest_components( frame4, - &[(Color::name(), &row5), (Position2D::name(), &row3)], + &[(MyColor::name(), &row5), (MyPoint::name(), &row3)], ); } @@ -378,35 +373,35 @@ fn range_impl(store: &mut DataStore) { let frame5 = TimeInt::new_temporal(5); let insts1 = MyIndex::from_iter(0..3); - let colors1 = build_some_colors(3); + let colors1 = MyColor::from_iter(0..3); let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => [insts1.clone(), colors1]); - let positions2 = build_some_positions2d(3); + let positions2 = MyPoint::from_iter(0..3); let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => [insts1, positions2]); - let points3 = build_some_positions2d(10); + let points3 = MyPoint::from_iter(0..10); let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => [points3]); let insts4_1 = MyIndex::from_iter(20..25); - let colors4_1 = build_some_colors(5); + let colors4_1 = MyColor::from_iter(0..5); let row4_1 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_1, colors4_1]); let insts4_2 = MyIndex::from_iter(25..30); - let colors4_2 = build_some_colors(5); + let colors4_2 = MyColor::from_iter(0..5); let row4_2 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_2.clone(), colors4_2]); - let points4_25 = build_some_positions2d(5); + let points4_25 = MyPoint::from_iter(0..5); let row4_25 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_2, points4_25]); let insts4_3 = MyIndex::from_iter(30..35); - let colors4_3 = build_some_colors(5); + let colors4_3 = MyColor::from_iter(0..5); let row4_3 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_3.clone(), colors4_3]); - let points4_4 = build_some_positions2d(5); + let points4_4 = MyPoint::from_iter(0..5); let row4_4 = test_row!(entity_path @ [build_frame_nr(frame4)] => [insts4_3, points4_4]); // injecting some static colors - let colors5 = build_some_colors(8); + let colors5 = MyColor::from_iter(0..8); let row5 = test_row!(entity_path => [colors5]); insert_table_with_retries( @@ -488,41 +483,41 @@ fn range_impl(store: &mut DataStore) { assert_range_components( TimeRange::new(frame1, frame1), - [Color::name(), Position2D::name()], + [MyColor::name(), MyPoint::name()], &[ - (TimeInt::STATIC, &[(Color::name(), &row5)]), // + (TimeInt::STATIC, &[(MyColor::name(), &row5)]), // ], ); assert_range_components( TimeRange::new(frame2, frame2), - [Color::name(), Position2D::name()], + [MyColor::name(), MyPoint::name()], &[ - (TimeInt::STATIC, &[(Color::name(), &row5)]), // - (frame2, &[(Position2D::name(), &row2)]), // + (TimeInt::STATIC, &[(MyColor::name(), &row5)]), // + (frame2, &[(MyPoint::name(), &row2)]), // ], ); assert_range_components( TimeRange::new(frame3, frame3), - [Color::name(), Position2D::name()], + [MyColor::name(), MyPoint::name()], &[ - (TimeInt::STATIC, &[(Color::name(), &row5)]), // - (frame3, &[(Position2D::name(), &row3)]), // + (TimeInt::STATIC, &[(MyColor::name(), &row5)]), // + (frame3, &[(MyPoint::name(), &row3)]), // ], ); assert_range_components( TimeRange::new(frame4, frame4), - [Color::name(), Position2D::name()], + [MyColor::name(), MyPoint::name()], &[ - (TimeInt::STATIC, &[(Color::name(), &row5)]), // - (frame4, &[(Position2D::name(), &row4_25)]), - (frame4, &[(Position2D::name(), &row4_4)]), + (TimeInt::STATIC, &[(MyColor::name(), &row5)]), // + (frame4, &[(MyPoint::name(), &row4_25)]), + (frame4, &[(MyPoint::name(), &row4_4)]), ], ); assert_range_components( TimeRange::new(frame5, frame5), - [Color::name(), Position2D::name()], + [MyColor::name(), MyPoint::name()], &[ - (TimeInt::STATIC, &[(Color::name(), &row5)]), // + (TimeInt::STATIC, &[(MyColor::name(), &row5)]), // ], ); @@ -530,13 +525,13 @@ fn range_impl(store: &mut DataStore) { assert_range_components( TimeRange::new(frame1, frame5), - [Color::name(), Position2D::name()], + [MyColor::name(), MyPoint::name()], &[ - (TimeInt::STATIC, &[(Color::name(), &row5)]), // - (frame2, &[(Position2D::name(), &row2)]), // - (frame3, &[(Position2D::name(), &row3)]), // - (frame4, &[(Position2D::name(), &row4_25)]), - (frame4, &[(Position2D::name(), &row4_4)]), + (TimeInt::STATIC, &[(MyColor::name(), &row5)]), // + (frame2, &[(MyPoint::name(), &row2)]), // + (frame3, &[(MyPoint::name(), &row3)]), // + (frame4, &[(MyPoint::name(), &row4_25)]), + (frame4, &[(MyPoint::name(), &row4_4)]), ], ); @@ -544,13 +539,13 @@ fn range_impl(store: &mut DataStore) { assert_range_components( TimeRange::new(TimeInt::MIN, TimeInt::MAX), - [Color::name(), Position2D::name()], + [MyColor::name(), MyPoint::name()], &[ - (TimeInt::STATIC, &[(Color::name(), &row5)]), // - (frame2, &[(Position2D::name(), &row2)]), // - (frame3, &[(Position2D::name(), &row3)]), // - (frame4, &[(Position2D::name(), &row4_25)]), - (frame4, &[(Position2D::name(), &row4_4)]), + (TimeInt::STATIC, &[(MyColor::name(), &row5)]), // + (frame2, &[(MyPoint::name(), &row2)]), // + (frame3, &[(MyPoint::name(), &row3)]), // + (frame4, &[(MyPoint::name(), &row4_25)]), + (frame4, &[(MyPoint::name(), &row4_4)]), ], ); } @@ -649,16 +644,16 @@ fn protected_gc_impl(store: &mut DataStore) { let frame3 = TimeInt::new_temporal(3); let frame4 = TimeInt::new_temporal(4); - let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let (instances1, colors1) = (MyIndex::from_iter(0..3), MyColor::from_iter(0..3)); let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => [instances1.clone(), colors1]); - let positions2 = build_some_positions2d(3); + let positions2 = MyPoint::from_iter(0..3); let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => [instances1, positions2]); - let points3 = build_some_positions2d(10); + let points3 = MyPoint::from_iter(0..10); let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => [points3]); - let colors4 = build_some_colors(5); + let colors4 = MyColor::from_iter(0..5); let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => [colors4]); store.insert_row(&row1).unwrap(); @@ -707,22 +702,22 @@ fn protected_gc_impl(store: &mut DataStore) { // The static data was preserved assert_latest_components( TimeInt::STATIC, - &[(Color::name(), &row1), (Position2D::name(), &row2)], // static + &[(MyColor::name(), &row1), (MyPoint::name(), &row2)], // static ); assert_latest_components( frame3, &[ - (Color::name(), &row1), // static - (Position2D::name(), &row2), // static + (MyColor::name(), &row1), // static + (MyPoint::name(), &row2), // static ], ); assert_latest_components( frame4, &[ - (Color::name(), &row1), // static - (Position2D::name(), &row2), // static + (MyColor::name(), &row1), // static + (MyPoint::name(), &row2), // static ], ); } @@ -751,16 +746,16 @@ fn protected_gc_clear_impl(store: &mut DataStore) { let frame3 = TimeInt::new_temporal(3); let frame4 = TimeInt::new_temporal(4); - let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let (instances1, colors1) = (MyIndex::from_iter(0..3), MyColor::from_iter(0..3)); let row1 = test_row!(entity_path @ [build_frame_nr(frame1)] => [instances1.clone(), colors1]); - let positions2 = build_some_positions2d(3); + let positions2 = MyPoint::from_iter(0..3); let row2 = test_row!(entity_path @ [build_frame_nr(frame2)] => [instances1, positions2]); - let colors2 = build_some_colors(0); + let colors2 = MyColor::from_iter(0..0); let row3 = test_row!(entity_path @ [build_frame_nr(frame3)] => [colors2]); - let points4 = build_some_positions2d(0); + let points4 = MyPoint::from_iter(0..0); let row4 = test_row!(entity_path @ [build_frame_nr(frame4)] => [points4]); // Insert the 3 rows as static @@ -803,7 +798,7 @@ fn protected_gc_clear_impl(store: &mut DataStore) { assert_latest_components( frame0, - &[(Color::name(), &row3), (Position2D::name(), &row2)], + &[(MyColor::name(), &row3), (MyPoint::name(), &row2)], ); // The 3 static cells should still be around. diff --git a/crates/re_data_store/tests/dump.rs b/crates/re_data_store/tests/dump.rs index 2db97deda2d8..570c0208a249 100644 --- a/crates/re_data_store/tests/dump.rs +++ b/crates/re_data_store/tests/dump.rs @@ -7,10 +7,10 @@ use re_data_store::{ DataStore, DataStoreStats, GarbageCollectionOptions, TimeInt, TimeRange, Timeline, }; use re_log_types::{ - build_frame_nr, build_log_time, example_components::MyIndex, DataRow, DataTable, EntityPath, - RowId, TableId, TimePoint, + build_frame_nr, build_log_time, + example_components::{MyColor, MyIndex, MyPoint}, + DataRow, DataTable, EntityPath, RowId, TableId, TimePoint, }; -use re_types::datagen::{build_some_colors, build_some_positions2d}; // --- @@ -275,22 +275,22 @@ fn create_insert_table(entity_path: impl Into) -> DataTable { let frame3 = TimeInt::new_temporal(3); let frame4 = TimeInt::new_temporal(4); - let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let (instances1, colors1) = (MyIndex::from_iter(0..3), MyColor::from_iter(0..3)); let row1 = test_row!(entity_path @ [ build_frame_nr(frame1), ] => [instances1.clone(), colors1]); - let positions2 = build_some_positions2d(3); + let positions2 = MyPoint::from_iter(0..2); let row2 = test_row!(entity_path @ [ build_frame_nr(frame2), ] => [instances1, positions2.clone()]); - let positions3 = build_some_positions2d(10); + let positions3 = MyPoint::from_iter(0..10); let row3 = test_row!(entity_path @ [ build_log_time(frame3.into()) /* ! */, build_frame_nr(frame3), ] => [positions3]); - let colors4 = build_some_colors(5); + let colors4 = MyColor::from_iter(0..5); let row4 = test_row!(entity_path @ [ build_frame_nr(frame4), ] => [colors4.clone()]); @@ -331,12 +331,12 @@ fn data_store_dump_empty_column_impl(store: &mut DataStore) { // Start by inserting a table with 2 rows, one with colors, and one with points. { - let (instances1, colors1) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let (instances1, colors1) = (MyIndex::from_iter(0..3), MyColor::from_iter(0..3)); let row1 = test_row!(entity_path @ [ build_frame_nr(frame1), ] => [instances1, colors1]); - let (instances2, positions2) = (MyIndex::from_iter(0..3), build_some_positions2d(3)); + let (instances2, positions2) = (MyIndex::from_iter(0..3), MyPoint::from_iter(0..2)); let row2 = test_row!(entity_path @ [ build_frame_nr(frame2), ] => [instances2, positions2]); @@ -347,7 +347,7 @@ fn data_store_dump_empty_column_impl(store: &mut DataStore) { // Now insert another table with points only. { - let (instances3, positions3) = (MyIndex::from_iter(0..3), build_some_colors(3)); + let (instances3, positions3) = (MyIndex::from_iter(0..3), MyColor::from_iter(0..3)); let row3 = test_row!(entity_path @ [ build_frame_nr(frame3), ] => [instances3, positions3]); diff --git a/crates/re_entity_db/Cargo.toml b/crates/re_entity_db/Cargo.toml index 178cc0f8e3ee..d5ed52af6722 100644 --- a/crates/re_entity_db/Cargo.toml +++ b/crates/re_entity_db/Cargo.toml @@ -52,7 +52,7 @@ web-time.workspace = true [dev-dependencies] re_log_encoding = { workspace = true, features = ["decoder", "encoder"] } -re_types = { workspace = true, features = ["datagen"] } +re_types.workspace = true anyhow.workspace = true criterion.workspace = true diff --git a/crates/re_entity_db/examples/memory_usage.rs b/crates/re_entity_db/examples/memory_usage.rs index f8431a681d89..3d1e4626bb80 100644 --- a/crates/re_entity_db/examples/memory_usage.rs +++ b/crates/re_entity_db/examples/memory_usage.rs @@ -48,7 +48,7 @@ fn live_bytes() -> usize { // ---------------------------------------------------------------------------- -use re_log_types::{entity_path, DataRow, RowId, StoreId, StoreKind}; +use re_log_types::{entity_path, example_components::MyPoint, DataRow, RowId, StoreId, StoreKind}; fn main() { log_messages(); @@ -56,7 +56,6 @@ fn main() { fn log_messages() { use re_log_types::{build_frame_nr, LogMsg, TimeInt, TimePoint, Timeline}; - use re_types::datagen::build_some_positions2d; // Note: we use Box in this function so that we also count the "static" // part of all the data, i.e. its `std::mem::size_of`. @@ -112,7 +111,7 @@ fn log_messages() { RowId::new(), entity_path!("points"), [build_frame_nr(TimeInt::ZERO)], - build_some_positions2d(1), + MyPoint::from_iter(0..1), ) .unwrap() .into_table(), @@ -138,7 +137,7 @@ fn log_messages() { RowId::new(), entity_path!("points"), [build_frame_nr(TimeInt::ZERO)], - build_some_positions2d(NUM_POINTS), + MyPoint::from_iter(0..NUM_POINTS as u32), ) .unwrap() .into_table(), diff --git a/crates/re_log_encoding/Cargo.toml b/crates/re_log_encoding/Cargo.toml index 207b13785689..efc277f18535 100644 --- a/crates/re_log_encoding/Cargo.toml +++ b/crates/re_log_encoding/Cargo.toml @@ -66,7 +66,7 @@ wasm-bindgen-futures = { workspace = true, optional = true } web-sys = { workspace = true, optional = true, features = ["Window"] } [dev-dependencies] -re_types = { workspace = true, features = ["datagen", "serde"] } +re_types = { workspace = true, features = ["serde"] } criterion.workspace = true mimalloc.workspace = true diff --git a/crates/re_log_encoding/benches/msg_encode_benchmark.rs b/crates/re_log_encoding/benches/msg_encode_benchmark.rs index c02bc4cec8e5..5e609657ed7d 100644 --- a/crates/re_log_encoding/benches/msg_encode_benchmark.rs +++ b/crates/re_log_encoding/benches/msg_encode_benchmark.rs @@ -5,10 +5,10 @@ compile_error!("msg_encode_benchmark requires 'decoder' and 'encoder' features." static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; use re_log_types::{ - entity_path, DataRow, DataTable, LogMsg, RowId, StoreId, StoreKind, TableId, TimeInt, TimeType, - Timeline, + entity_path, + example_components::{MyColor, MyPoint}, + DataRow, DataTable, LogMsg, RowId, StoreId, StoreKind, TableId, TimeInt, TimeType, Timeline, }; -use re_types::datagen::{build_some_colors, build_some_positions2d}; use criterion::{criterion_group, criterion_main, Criterion}; @@ -75,7 +75,7 @@ fn mono_points_arrow(c: &mut Criterion) { RowId::ZERO, entity_path!("points", i.to_string()), [build_frame_nr(TimeInt::ZERO)], - (build_some_positions2d(1), build_some_colors(1)), + (MyPoint::from_iter(0..1), MyColor::from_iter(0..1)), ) .unwrap()], ) @@ -132,7 +132,7 @@ fn mono_points_arrow_batched(c: &mut Criterion) { RowId::ZERO, entity_path!("points", i.to_string()), [build_frame_nr(TimeInt::ZERO)], - (build_some_positions2d(1), build_some_colors(1)), + (MyPoint::from_iter(0..1), MyColor::from_iter(0..1)), ) .unwrap() }), @@ -188,8 +188,8 @@ fn batch_points_arrow(c: &mut Criterion) { entity_path!("points"), [build_frame_nr(TimeInt::ZERO)], ( - build_some_positions2d(NUM_POINTS), - build_some_colors(NUM_POINTS), + MyPoint::from_iter(0..NUM_POINTS as u32), + MyColor::from_iter(0..NUM_POINTS as u32), ), ) .unwrap()], diff --git a/crates/re_log_types/src/example_components.rs b/crates/re_log_types/src/example_components.rs index 2cc5b2ac3cf5..ab2151989d6a 100644 --- a/crates/re_log_types/src/example_components.rs +++ b/crates/re_log_types/src/example_components.rs @@ -42,6 +42,16 @@ pub struct MyPoint { pub y: f32, } +impl MyPoint { + #[allow(clippy::should_implement_trait)] + #[inline] + pub fn from_iter(it: impl IntoIterator) -> Vec { + it.into_iter() + .map(|i| MyPoint::new(i as f32, i as f32)) + .collect() + } +} + impl MyPoint { #[inline] pub fn new(x: f32, y: f32) -> Self { @@ -133,6 +143,14 @@ impl Loggable for MyPoint { #[repr(transparent)] pub struct MyColor(pub u32); +impl MyColor { + #[allow(clippy::should_implement_trait)] + #[inline] + pub fn from_iter(it: impl IntoIterator) -> Vec { + it.into_iter().map(Self).collect() + } +} + impl MyColor { #[inline] pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { diff --git a/crates/re_query/Cargo.toml b/crates/re_query/Cargo.toml index f30c9c4e7dc1..3d5b67932ce1 100644 --- a/crates/re_query/Cargo.toml +++ b/crates/re_query/Cargo.toml @@ -65,8 +65,6 @@ unindent = { workspace = true, optional = true } [dev-dependencies] -re_types = { workspace = true, features = ["datagen"] } - criterion.workspace = true mimalloc.workspace = true rand = { workspace = true, features = ["std", "std_rng"] } diff --git a/crates/re_types/Cargo.toml b/crates/re_types/Cargo.toml index ab360bae3b00..aa5a454500f0 100644 --- a/crates/re_types/Cargo.toml +++ b/crates/re_types/Cargo.toml @@ -28,10 +28,6 @@ default = [] ## All features except `testing`. all = ["ecolor", "egui_plot", "glam", "image", "mint", "serde"] -## Enables the `datagen` module, which exposes a number of tools for generating random data for -## tests and benchmarks. -datagen = ["dep:rand"] - ## Enable color conversions. ecolor = ["dep:ecolor"] @@ -88,7 +84,6 @@ egui_plot = { workspace = true, optional = true } glam = { workspace = true, optional = true } image = { workspace = true, optional = true, default-features = false } mint = { workspace = true, optional = true } -rand = { workspace = true, optional = true, features = ["std", "std_rng"] } serde = { workspace = true, optional = true, features = ["derive", "rc"] } zune-core = { workspace = true, optional = true } zune-jpeg = { workspace = true, optional = true } diff --git a/crates/re_types/src/datagen.rs b/crates/re_types/src/datagen.rs deleted file mode 100644 index d276d78837de..000000000000 --- a/crates/re_types/src/datagen.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! Generate random data for tests and benchmarks. - -// TODO(#1810): It really is time for whole module to disappear. - -/// Create `len` dummy colors -pub fn build_some_colors(len: usize) -> Vec { - (0..len) - .map(|i| crate::components::Color::from(i as u32)) - .collect() -} - -/// Create `len` dummy `Position2D` -pub fn build_some_positions2d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - crate::components::Position2D::new(rng.gen_range(0.0..10.0), rng.gen_range(0.0..10.0)) - }) - .collect() -} - -/// Create `len` dummy `Vec3D` -pub fn build_some_vec3d(len: usize) -> Vec { - use rand::Rng as _; - let mut rng = rand::thread_rng(); - - (0..len) - .map(|_| { - crate::datatypes::Vec3D::new( - rng.gen_range(0.0..10.0), - rng.gen_range(0.0..10.0), - rng.gen_range(0.0..10.0), - ) - }) - .collect() -} diff --git a/crates/re_types/src/lib.rs b/crates/re_types/src/lib.rs index 345fcd9a7c25..655d42b0a3ff 100644 --- a/crates/re_types/src/lib.rs +++ b/crates/re_types/src/lib.rs @@ -246,9 +246,6 @@ pub mod datatypes { /// The blueprint-specific components. pub mod blueprint; -#[cfg(feature = "datagen")] -pub mod datagen; - // --- // One almost never uses `re_types` without `re_types_core`, so we reexport these core types From 27a4e54b29ee9dda08b22aa1a0aa5c1edef49a26 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 2 May 2024 11:40:32 +0200 Subject: [PATCH 402/508] Make visible time range ui aware of latest-at & `QueryRange` (#6176) ### What Under the hood this is now actually a "query range" ui since it operates directly on `QueryRange`, but I opted to not call it that in the viewer yet. The user facing changes are rather subtle Before: Defaulting to latest-at: ![image](https://github.com/rerun-io/rerun/assets/1220815/d8d0bfe2-a797-4abf-8a2b-7aaaa3721610) Defaulting to single timestamp: ![image](https://github.com/rerun-io/rerun/assets/1220815/20637666-e5b8-4f72-b938-00049a9bbd7d) After: Defaulting to latest-at: ![image](https://github.com/rerun-io/rerun/assets/1220815/d5a0e77f-ddcb-4207-9e22-35830555534a) Defaulting to single timestamp: ![image](https://github.com/rerun-io/rerun/assets/1220815/f26517b9-b6fe-460e-b3f9-79dee3bb846a) Note that today latest-at can only be inherited (via default). You can't actually set it as an override yet (we decided to delay that a bit since it needs even more restructuring and imho we may want to constrain that depending on the view type). ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6176?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6176?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6176) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../src/datatypes/visible_time_range_ext.rs | 9 + crates/re_viewer/src/ui/mod.rs | 2 +- ...visual_time_range.rs => query_range_ui.rs} | 272 ++++++++++-------- crates/re_viewer/src/ui/selection_panel.rs | 8 +- 4 files changed, 165 insertions(+), 126 deletions(-) rename crates/re_viewer/src/ui/{visual_time_range.rs => query_range_ui.rs} (79%) diff --git a/crates/re_types_core/src/datatypes/visible_time_range_ext.rs b/crates/re_types_core/src/datatypes/visible_time_range_ext.rs index 218dc2797777..a1a0a37c135a 100644 --- a/crates/re_types_core/src/datatypes/visible_time_range_ext.rs +++ b/crates/re_types_core/src/datatypes/visible_time_range_ext.rs @@ -9,4 +9,13 @@ impl VisibleTimeRange { // This means +∞ end: VisibleTimeRangeBoundary::INFINITE, }; + + /// A range of zero length exactly at the time cursor. + /// + /// This is *not* the same as latest-at queries and queries the state that was logged exactly at the cursor. + /// In contrast, latest-at queries each component's latest known state. + pub const AT_CURSOR: Self = Self { + start: VisibleTimeRangeBoundary::AT_CURSOR, + end: VisibleTimeRangeBoundary::AT_CURSOR, + }; } diff --git a/crates/re_viewer/src/ui/mod.rs b/crates/re_viewer/src/ui/mod.rs index 4afbd2cc5900..4865f62983d8 100644 --- a/crates/re_viewer/src/ui/mod.rs +++ b/crates/re_viewer/src/ui/mod.rs @@ -8,9 +8,9 @@ mod top_panel; mod welcome_screen; pub(crate) mod memory_panel; +pub(crate) mod query_range_ui; pub(crate) mod selection_panel; pub(crate) mod space_view_space_origin_ui; -pub(crate) mod visual_time_range; pub use blueprint_panel::blueprint_panel_ui; pub use recordings_panel::recordings_panel_ui; diff --git a/crates/re_viewer/src/ui/visual_time_range.rs b/crates/re_viewer/src/ui/query_range_ui.rs similarity index 79% rename from crates/re_viewer/src/ui/visual_time_range.rs rename to crates/re_viewer/src/ui/query_range_ui.rs index 67449aaea0cf..ffa765911cb8 100644 --- a/crates/re_viewer/src/ui/visual_time_range.rs +++ b/crates/re_viewer/src/ui/query_range_ui.rs @@ -38,7 +38,7 @@ fn space_view_with_visible_history(space_view_class: SpaceViewClassIdentifier) - VISIBLE_HISTORY_SUPPORTED_SPACE_VIEWS.contains(&space_view_class) } -pub fn visual_time_range_ui_space_view( +pub fn query_range_ui_space_view( ctx: &ViewerContext<'_>, ui: &mut Ui, space_view: &SpaceViewBlueprint, @@ -73,17 +73,17 @@ pub fn visual_time_range_ui_space_view( ); let is_space_view = true; - visual_time_range_ui( + query_range_ui( ctx, ui, - &query_range, + query_range.clone(), has_individual_range, is_space_view, &property_path, ); } -pub fn visual_time_range_ui_data_result( +pub fn query_range_ui_data_result( ctx: &ViewerContext<'_>, ui: &mut Ui, data_result_tree: &re_viewer_context::DataResultTree, @@ -110,21 +110,21 @@ pub fn visual_time_range_ui_data_result( }; let is_space_view = false; - visual_time_range_ui( + query_range_ui( ctx, ui, - &overrides.query_range, + overrides.query_range.clone(), has_individual_range, is_space_view, override_path, ); } -fn visual_time_range_ui( +fn query_range_ui( ctx: &ViewerContext<'_>, ui: &mut Ui, - resolved_range: &QueryRange, - mut has_individual_range: bool, + mut query_range: QueryRange, + mut has_individual_time_range: bool, is_space_view: bool, property_override_path: &EntityPath, ) { @@ -134,44 +134,29 @@ fn visual_time_range_ui( let mut interacting_with_controls = false; - let mut resolved_range = match resolved_range { - QueryRange::TimeRange(range) => range.clone(), - QueryRange::LatestAt => { - if has_individual_range { - re_log::error_once!("Visible time range is set but no time range is provided"); - } - // TODO(andreas): Should print a string that we're using the latest time. - re_types::datatypes::VisibleTimeRange { - start: VisibleTimeRangeBoundary::AT_CURSOR, - end: VisibleTimeRangeBoundary::AT_CURSOR, - } - } - }; - let collapsing_response = ctx .re_ui .collapsing_header(ui, "Visible time range", false, |ui| { - let has_individual_range_before = has_individual_range; - let resolved_range_before = resolved_range.clone(); + let has_individual_time_range_before = has_individual_time_range; + let query_range_before = query_range.clone(); ui.horizontal(|ui| { re_ui - .radio_value(ui, &mut has_individual_range, false, "Default") + .radio_value(ui, &mut has_individual_time_range, false, "Default") .on_hover_text(if is_space_view { - "Default visible time range settings for this kind of space view" + "Default query range settings for this kind of space view" } else { - "Visible time range settings inherited from parent Entity or enclosing \ + "Query range settings inherited from parent Entity or enclosing \ space view" }); re_ui - .radio_value(ui, &mut has_individual_range, true, "Override") + .radio_value(ui, &mut has_individual_time_range, true, "Override") .on_hover_text(if is_space_view { - "Set visible time range settings for the contents of this space view" + "Set query range settings for the contents of this space view" } else { - "Set visible time range settings for this entity" + "Set query range settings for this entity" }); }); - let timeline_spec = if let Some(times) = ctx.recording().time_histogram(time_ctrl.timeline()) { TimelineSpec::from_time_histogram(times) @@ -186,99 +171,52 @@ fn visual_time_range_ui( .at_least(*timeline_spec.range.start()), ); // accounts for timeless time (TimeInt::MIN) - if has_individual_range { - let current_start = resolved_range.start.start_boundary_time(current_time); - let current_end = resolved_range.end.end_boundary_time(current_time); - - egui::Grid::new("from_to_editable").show(ui, |ui| { - re_ui.grid_left_hand_label(ui, "Start"); - interacting_with_controls |= ui - .horizontal(|ui| { - visible_history_boundary_ui( - ctx, - ui, - &mut resolved_range.start, - time_type, - current_time, - &timeline_spec, - true, - current_end, - ) - }) - .inner; - ui.end_row(); - - re_ui.grid_left_hand_label(ui, "End"); - interacting_with_controls |= ui - .horizontal(|ui| { - visible_history_boundary_ui( - ctx, - ui, - &mut resolved_range.end, - time_type, - current_time, - &timeline_spec, - false, - current_start, - ) - }) - .inner; - ui.end_row(); - }); - - current_range_ui(ctx, ui, current_time, time_type, &resolved_range); - } else { - // Show the resolved visible range as labels (user can't edit them): - - if resolved_range.start.kind == VisibleTimeRangeBoundaryKind::Infinite - && resolved_range.end.kind == VisibleTimeRangeBoundaryKind::Infinite - { - ui.label("Entire timeline"); - } else if resolved_range.start == VisibleTimeRangeBoundary::AT_CURSOR - && resolved_range.end == VisibleTimeRangeBoundary::AT_CURSOR - { - let current_time = time_type.format(current_time, ctx.app_options.time_zone); - match time_type { - TimeType::Time => { - ui.label(format!("At current time: {current_time}")); - } - TimeType::Sequence => { - ui.label(format!("At current frame: {current_time}")); + if has_individual_time_range { + let time_range = match &mut query_range { + QueryRange::TimeRange(time_range) => time_range, + QueryRange::LatestAt => { + // This should only happen if we just flipped to an individual range and the parent used latest-at queries. + query_range = QueryRange::TimeRange(VisibleTimeRange::AT_CURSOR); + match &mut query_range { + QueryRange::TimeRange(range) => range, + QueryRange::LatestAt => unreachable!(), } } - } else { - egui::Grid::new("from_to_labels").show(ui, |ui| { - re_ui.grid_left_hand_label(ui, "From"); - resolved_visible_history_boundary_ui( - ctx, - ui, - &resolved_range.start, - time_type, - true, - ); - ui.end_row(); - - re_ui.grid_left_hand_label(ui, "To"); - resolved_visible_history_boundary_ui( - ctx, - ui, - &resolved_range.end, - time_type, - false, - ); - ui.end_row(); - }); + }; - current_range_ui(ctx, ui, current_time, time_type, &resolved_range); + time_range_editor( + ctx, + ui, + time_range, + current_time, + &mut interacting_with_controls, + time_type, + &timeline_spec, + ); + } else { + match &query_range { + QueryRange::TimeRange(range) => { + show_visual_time_range(ctx, ui, range, time_type, current_time); + } + QueryRange::LatestAt => { + let current_time = + time_type.format(current_time, ctx.app_options.time_zone); + ui.label(format!("Latest-at query at: {current_time}")) + .on_hover_text("Uses the latest known value for each component."); + } } } // Save to blueprint store if anything has changed. - if has_individual_range != has_individual_range_before - || resolved_range != resolved_range_before + if has_individual_time_range != has_individual_time_range_before + || query_range != query_range_before { - if has_individual_range { - let resolved_range = resolved_range.clone(); + if has_individual_time_range { + let resolved_range = match &query_range { + QueryRange::TimeRange(ref range) => range.clone(), + QueryRange::LatestAt => VisibleTimeRange::AT_CURSOR, + }; + match time_type { TimeType::Time => { ctx.save_blueprint_component( @@ -325,16 +263,18 @@ fn visual_time_range_ui( // so we must track these interactions specifically. // Note: visible history highlight is always reset at the beginning of the Selection Panel UI. - let should_display_visible_history = interacting_with_controls + let should_display_visible_time_range = interacting_with_controls || collapsing_response.header_response.hovered() || collapsing_response .body_response .map_or(false, |r| r.hovered()); - if should_display_visible_history { + if should_display_visible_time_range { if let Some(current_time) = time_ctrl.time_int() { - let range = TimeRange::from_visible_time_range(&resolved_range, current_time); - ctx.rec_cfg.time_ctrl.write().highlighted_range = Some(range); + if let QueryRange::TimeRange(ref time_range) = &query_range { + let range = TimeRange::from_visible_time_range(time_range, current_time); + ctx.rec_cfg.time_ctrl.write().highlighted_range = Some(range); + } } } @@ -358,6 +298,96 @@ Notes that the data current as of the time range starting time is included.", }); } +fn time_range_editor( + ctx: &ViewerContext<'_>, + ui: &mut Ui, + resolved_range: &mut VisibleTimeRange, + current_time: TimeInt, + interacting_with_controls: &mut bool, + time_type: TimeType, + timeline_spec: &TimelineSpec, +) { + let current_start = resolved_range.start.start_boundary_time(current_time); + let current_end = resolved_range.end.end_boundary_time(current_time); + + egui::Grid::new("from_to_editable").show(ui, |ui| { + ctx.re_ui.grid_left_hand_label(ui, "Start"); + *interacting_with_controls |= ui + .horizontal(|ui| { + visible_history_boundary_ui( + ctx, + ui, + &mut resolved_range.start, + time_type, + current_time, + timeline_spec, + true, + current_end, + ) + }) + .inner; + ui.end_row(); + + ctx.re_ui.grid_left_hand_label(ui, "End"); + *interacting_with_controls |= ui + .horizontal(|ui| { + visible_history_boundary_ui( + ctx, + ui, + &mut resolved_range.end, + time_type, + current_time, + timeline_spec, + false, + current_start, + ) + }) + .inner; + ui.end_row(); + }); + + current_range_ui(ctx, ui, current_time, time_type, resolved_range); +} + +fn show_visual_time_range( + ctx: &ViewerContext<'_>, + ui: &mut Ui, + resolved_range: &VisibleTimeRange, + time_type: TimeType, + current_time: TimeInt, +) { + // Show the resolved visible range as labels (user can't edit them): + if resolved_range.start.kind == VisibleTimeRangeBoundaryKind::Infinite + && resolved_range.end.kind == VisibleTimeRangeBoundaryKind::Infinite + { + ui.label("Entire timeline"); + } else if resolved_range.start == VisibleTimeRangeBoundary::AT_CURSOR + && resolved_range.end == VisibleTimeRangeBoundary::AT_CURSOR + { + let current_time = time_type.format(current_time, ctx.app_options.time_zone); + match time_type { + TimeType::Time => { + ui.label(format!("At current time: {current_time}")) + } + TimeType::Sequence => { + ui.label(format!("At current frame: {current_time}")) + } + }.on_hover_text("Does not perform a latest-at query, shows only data logged at exactly the current time cursor position."); + } else { + egui::Grid::new("from_to_labels").show(ui, |ui| { + ctx.re_ui.grid_left_hand_label(ui, "From"); + resolved_visible_history_boundary_ui(ctx, ui, &resolved_range.start, time_type, true); + ui.end_row(); + + ctx.re_ui.grid_left_hand_label(ui, "To"); + resolved_visible_history_boundary_ui(ctx, ui, &resolved_range.end, time_type, false); + ui.end_row(); + }); + + current_range_ui(ctx, ui, current_time, time_type, resolved_range); + } +} + fn current_range_ui( ctx: &ViewerContext<'_>, ui: &mut Ui, diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index d1eb4de03bbf..4e1034d995b9 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -29,8 +29,8 @@ use crate::ui::override_ui::override_visualizer_ui; use crate::{app_state::default_selection_panel_width, ui::override_ui::override_ui}; use super::{ - selection_history_ui::SelectionHistoryUi, visual_time_range::visual_time_range_ui_data_result, - visual_time_range::visual_time_range_ui_space_view, + query_range_ui::query_range_ui_data_result, query_range_ui::query_range_ui_space_view, + selection_history_ui::SelectionHistoryUi, }; // --- @@ -904,7 +904,7 @@ fn blueprint_ui_for_space_view( &class_identifier, ); - visual_time_range_ui_space_view(ctx, ui, space_view); + query_range_ui_space_view(ctx, ui, space_view); // Space View don't inherit (legacy) properties. let mut props = @@ -1174,7 +1174,7 @@ fn entity_props_ui( .checkbox(ui, &mut entity_props.interactive, "Interactive") .on_hover_text("If disabled, the entity will not react to any mouse interaction"); - visual_time_range_ui_data_result(ctx, ui, &query_result.tree, data_result); + query_range_ui_data_result(ctx, ui, &query_result.tree, data_result); egui::Grid::new("entity_properties") .num_columns(2) From 2641a5937ca973d7d14b19c60aa83a749ff1a99e Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Thu, 2 May 2024 11:44:23 +0200 Subject: [PATCH 403/508] Fix mesh flicker (#6157) Funnily enough, the reason this was flickering on `0.15` was completely unrelated to the reason why it flickers on `main`. Long story short: it had to with how explicit client-side splats were splitting the data across different timestamps and in some cases this was incorrectly handled. In the new APIs it's just an issue in the entity_iterator machinery which lowers everything to range semantics, which leads to problems when the query expects latest-at semantics. - Fixes #6072 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6157?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6157?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6157) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/re_query/src/range/results.rs | 6 +++++- .../src/visualizers/results_ext.rs | 10 ++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/crates/re_query/src/range/results.rs b/crates/re_query/src/range/results.rs index cff3abcceabc..73254a2adc1f 100644 --- a/crates/re_query/src/range/results.rs +++ b/crates/re_query/src/range/results.rs @@ -226,10 +226,13 @@ pub struct RangeData<'a, T> { impl<'a, C: Component> RangeData<'a, C> { /// Useful to abstract over latest-at and ranged results. + /// + /// Use `reindexed` override the index of the data, if needed. #[inline] pub fn from_latest_at( resolver: &PromiseResolver, results: &'a LatestAtComponentResults, + reindexed: Option<(TimeInt, RowId)>, ) -> Self { let LatestAtComponentResults { index, @@ -238,9 +241,10 @@ impl<'a, C: Component> RangeData<'a, C> { } = results; let status = results.to_dense::(resolver).map(|_| ()); + let index = reindexed.unwrap_or(*index); Self { - indices: Some(Indices::Owned(vec![*index].into())), + indices: Some(Indices::Owned(vec![index].into())), data: cached_dense.get().map(|data| Data::Owned(Arc::clone(data))), time_range: TimeRange::new(index.0, index.0), front_status: status.clone(), diff --git a/crates/re_space_view_spatial/src/visualizers/results_ext.rs b/crates/re_space_view_spatial/src/visualizers/results_ext.rs index 1b03697315b6..63c77109527c 100644 --- a/crates/re_space_view_spatial/src/visualizers/results_ext.rs +++ b/crates/re_space_view_spatial/src/visualizers/results_ext.rs @@ -1,3 +1,4 @@ +use re_log_types::{RowId, TimeInt}; use re_query::{LatestAtResults, PromiseResolver, PromiseResult, RangeData, RangeResults, Results}; use re_types::Component; @@ -92,7 +93,7 @@ impl RangeResultsExt for LatestAtResults { resolver: &PromiseResolver, ) -> Option>> { let results = self.get(C::name())?; - let data = RangeData::from_latest_at(resolver, results); + let data = RangeData::from_latest_at(resolver, results, None); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); @@ -114,7 +115,12 @@ impl RangeResultsExt for LatestAtResults { resolver: &PromiseResolver, ) -> re_query::Result> { let results = self.get_or_empty(C::name()); - let data = RangeData::from_latest_at(resolver, results); + // With latest-at semantics, we just want to join the secondary components onto the primary + // ones, irrelevant of their indices. + // In particular, it is pretty common to have a secondary component be more recent than the + // associated primary component in latest-at contexts, e.g. colors in an otherwise fixed + // point cloud being changed each frame. + let data = RangeData::from_latest_at(resolver, results, Some((TimeInt::MIN, RowId::ZERO))); // TODO(#5607): what should happen if the promise is still pending? let (front_status, back_status) = data.status(); From 5b0dbb5a3ffe24991bc19794c96cab73fa20dfa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Proch=C3=A1zka?= Date: Thu, 2 May 2024 12:15:26 +0200 Subject: [PATCH 404/508] Markdown linter (#6181) ### What - Closes https://github.com/rerun-io/rerun/issues/4007 Adding a very basic markdown linter. Currently covers only a few issues. Running `pixi run mdlint` will check all markdown files in the current directory. Every error has an error code, which can be used to explain the error via `pixi run mdlint --explain {code}`. ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6181?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/6181?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! - [PR Build Summary](https://build.rerun.io/pr/6181) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .github/workflows/reusable_checks.yml | 20 + .../through-code-tutorial.md | 28 +- docs/content/getting-started/data-in/cpp.md | 5 +- .../content/getting-started/data-in/python.md | 1 + docs/content/getting-started/data-in/rust.md | 1 + docs/content/getting-started/what-is-rerun.md | 1 + docs/content/reference/entity-queries.md | 3 +- pixi.toml | 3 + scripts/ci/mdlint.py | 376 ++++++++++++++++++ 9 files changed, 420 insertions(+), 18 deletions(-) create mode 100755 scripts/ci/mdlint.py diff --git a/.github/workflows/reusable_checks.yml b/.github/workflows/reusable_checks.yml index ceb4af0d9e66..905f17d07cf5 100644 --- a/.github/workflows/reusable_checks.yml +++ b/.github/workflows/reusable_checks.yml @@ -132,6 +132,26 @@ jobs: - name: Check example manifest coverage run: pixi run ./scripts/check_example_manifest_coverage.py + lint-md: + name: Lint markdown + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.ref || '' }} + + - uses: prefix-dev/setup-pixi@v0.6.0 + with: + pixi-version: v0.20.0 + + - name: Run linter + run: | + # double quoting because pixi does its own glob expansion + pixi run mdlint --glob "'docs/content/**/*.md'" + pixi run mdlint --glob "'examples/python/*/README.md'" + pixi run mdlint --glob "'examples/cpp/*/README.md'" + pixi run mdlint --glob "'examples/rust/*/README.md'" + # --------------------------------------------------------------------------- spell-check: diff --git a/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md index 0102a7ee4fd4..dcd6ce83518f 100644 --- a/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md +++ b/docs/content/getting-started/configure-the-viewer/through-code-tutorial.md @@ -173,9 +173,9 @@ python stocks.py You should see the application launch and display the stock data, but you will also notice the layout is far from ideal: - - + + @@ -209,9 +209,9 @@ Replace these lines with the following: This blueprint uses the `origin` parameter to scope the view to just a portion of the entity tree. If you run the script again, you should see a single chart for the AAPL data: - - + + @@ -238,9 +238,9 @@ Let's modify the code again to include additional blueprint specifications for t This time when you run the script, you will now see the panels start off collapsed, giving you a more focused view of your data: - - + + @@ -271,9 +271,9 @@ Let's modify the code to include the info card as well. We will use the `Vertica ``` Running the script now produces two views stacked vertically: - - + + @@ -306,9 +306,9 @@ the same chart. Using `origin` alone there is no way we could have expressed thi ``` Running the script now produces a chart that combines data from multiple sources: - - + + @@ -345,9 +345,9 @@ Going back to our single stock example, we can filter out the peaks data by excl ``` When you run the script you will see that the data from the peaks subtree is no longer part of the view: - - + + @@ -393,9 +393,9 @@ Setting this up by hand would be extremely tedious. ``` Running the script again this final chart is a significant improvement over the original heuristic-based layout: - - + + diff --git a/docs/content/getting-started/data-in/cpp.md b/docs/content/getting-started/data-in/cpp.md index a0d1bbd2fb20..127f8a4a6ea7 100644 --- a/docs/content/getting-started/data-in/cpp.md +++ b/docs/content/getting-started/data-in/cpp.md @@ -6,6 +6,7 @@ order: 1 In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: + @@ -117,9 +118,9 @@ cmake --build build -j ``` When everything finishes compiling, an empty Rerun viewer should be spawned: - - + + diff --git a/docs/content/getting-started/data-in/python.md b/docs/content/getting-started/data-in/python.md index 55d289b48069..a1c537128b18 100644 --- a/docs/content/getting-started/data-in/python.md +++ b/docs/content/getting-started/data-in/python.md @@ -6,6 +6,7 @@ order: 2 In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: + diff --git a/docs/content/getting-started/data-in/rust.md b/docs/content/getting-started/data-in/rust.md index ae6c9e9c9986..222e5183bbc4 100644 --- a/docs/content/getting-started/data-in/rust.md +++ b/docs/content/getting-started/data-in/rust.md @@ -6,6 +6,7 @@ order: 3 In this section we'll log and visualize our first non-trivial dataset, putting many of Rerun's core concepts and features to use. In a few lines of code, we'll go from a blank sheet to something you don't see every day: an animated, interactive, DNA-shaped abacus: + diff --git a/docs/content/getting-started/what-is-rerun.md b/docs/content/getting-started/what-is-rerun.md index 26d8fa87b848..bf6eac4e8aa5 100644 --- a/docs/content/getting-started/what-is-rerun.md +++ b/docs/content/getting-started/what-is-rerun.md @@ -20,6 +20,7 @@ Rerun is used by engineers and researchers in fields like robotics, spatial computing, 2D/3D simulation, and finance to verify, debug, and demo. ## How do you use it? + diff --git a/docs/content/reference/entity-queries.md b/docs/content/reference/entity-queries.md index 925d7721e4cf..4a86288f256e 100644 --- a/docs/content/reference/entity-queries.md +++ b/docs/content/reference/entity-queries.md @@ -51,8 +51,7 @@ edit box, with each query expression shown on its own line. You can find the query editor in the right-hand selection panel when selecting a space view. - - + diff --git a/pixi.toml b/pixi.toml index 096297a9e612..f3985a05701d 100644 --- a/pixi.toml +++ b/pixi.toml @@ -204,6 +204,9 @@ search-index = "cargo run --locked -p re_dev_tools -- search-index" # TODO(#6060): Put this in an environment and remove the requirements file. py-docs-serve = "mkdocs serve -f rerun_py/mkdocs.yml -w rerun_py" +# Lint markdown +mdlint = "python scripts/ci/mdlint.py" + [feature.cpp.tasks] # All the cpp-* tasks can be configured with environment variables, e.g.: RERUN_WERROR=ON CXX=clang++ cpp-prepare-release = "cmake -G 'Ninja' -B build/release -S . -DCMAKE_BUILD_TYPE=Release" diff --git a/scripts/ci/mdlint.py b/scripts/ci/mdlint.py new file mode 100755 index 000000000000..36eef75f99c9 --- /dev/null +++ b/scripts/ci/mdlint.py @@ -0,0 +1,376 @@ +#!/usr/bin/env python3 + +""" +Checks that no `.md` files contain invalid syntax. + +Usage: + python mdlint.py + python mdlint.py explain e001 + python mdlint.py lint docs/content/**/*.md +""" + +from __future__ import annotations + +import argparse +import re +import textwrap +from concurrent.futures import ThreadPoolExecutor +from dataclasses import dataclass +from glob import glob +from pathlib import Path + + +@dataclass +class Span: + start: int + end: int + + def offset(self, by: int): + self.start += by + self.end += by + return self + + def slice(self, content: str) -> str: + return content[self.start : self.end] + + +def extend_span(content: str, span: Span) -> Span: + """ + Extends the span (start, end) to contain all lines it inhabits. + + For example (with `|` denoting span bounds): + ``` + + + ``` + + Turns into: + ``` + | + | + ``` + """ + + if content[span.start] == "\n": + actual_start = span.start + 1 + else: + actual_start = content.rfind("\n", 0, span.start) + if actual_start == -1: + actual_start = 0 + + if content[span.end] == "\n": + actual_end = span.end + else: + actual_end = content.find("\n", span.end) + if actual_end == -1: + actual_end = len(content) + + return Span(start=actual_start, end=actual_end) + + +def get_line_num(content: str, start: int) -> int: + return 1 + content[:start].count("\n") + + +@dataclass +class Error: + code: str + message: str + span: Span + + def render(self, filepath: str, content: str) -> str: + span = extend_span(content, self.span) + + line_num = get_line_num(content, span.end) + lines = span.slice(content).splitlines() + line_num_align = len(f"{line_num + len(lines)}") + + out: list[str] = [ + f"error[{self.code}]: {self.message}", + f"{' '.rjust(line_num_align)}--> {filepath}:{line_num}", + ] + for line in lines: + num = f"{line_num}".ljust(line_num_align) + out.append(f"{num} | {line}") + line_num += 1 + + return "\n".join(out) + "\n" + + +class NoClosingTagError(Error): + CODE = "E001" + + def __init__(self, tagname: str, span: Span): + super().__init__(type(self).CODE, f"<{tagname}> has no closing tag", span) + + @staticmethod + def explain(): + return textwrap.dedent( + """ + If a block element such as `